def load(self, filepath): # store file name for later self.file = filepath self.dir, self.basename = os.path.split(filepath) self.file_no_ext = os.path.splitext(self.file)[0] with self.reader(filepath) as stream: self.read(stream) print(self) # # read the first mani data mani_info = self.mani_infos[0] mani_block = stream.read_type(ManiBlock, (mani_info, )) print(mani_block) # is this correct?? zeros = stream.read(4) print(zeros, stream.tell()) sum_bytes = sum(mb.byte_size for mb in mani_block.repeats) print("sum_bytes", sum_bytes) sum_bytes2 = sum(mb.byte_size + get_padding_size(mb.byte_size) for mb in mani_block.repeats) print("sum_bytes + padding", sum_bytes2) for mb in mani_block.repeats: data = stream.read(mb.byte_size) pad_size = get_padding_size(mb.byte_size) padding = stream.read(pad_size) print(binascii.hexlify(data[:40])) stream.tell()
def read_all_bone_infos(self, stream, bone_info_cls): # functional for JWE detailobjects.ms2, if joint_data is read potential_start = stream.tell() print("mdl2 count", self.general_info.mdl_2_count) for i in range(self.general_info.mdl_2_count): print(f"BONE INFO {i} starts at {stream.tell()}") try: bone_info = bone_info_cls() bone_info.read(stream) # print(bone_info) print("end of bone info at", stream.tell()) # last one has no padding, so stop here if stream.tell() >= potential_start + self.bone_info_size: print(f"Exhausted bone info buffer at {stream.tell()}") break relative_offset = stream.tell() - potential_start # currently no other way to predict the padding, no correlation to joint count padding_len = get_padding_size(relative_offset) # k = None # if bone_info.joint_count: # k = bone_info.joint_datas.joint_count print("padding", padding_len, stream.read(padding_len), "joint count", bone_info.joint_count) except: print("Bone info failed") stream.seek(potential_start)
def get_padding(self, stream, alignment=16): abs_offset = stream.tell() relative_offset = abs_offset - self.bone_info_start # currently no other way to predict the padding, no correlation to joint count padding_len = get_padding_size(relative_offset, alignment=alignment) padding = stream.read(padding_len) if padding != b'\x00' * padding_len: logging.warning(f"Padding is nonzero {padding} at offset {abs_offset}") logging.debug(f"padding: {padding_len} aligned to {alignment}")
def read(self, stream): self.io_start = stream.tell() self.bone_infos = [] i = 0 if self.context.version < 47: # # start = self.io_start start = self.arg.io_start # meh, add it here even though it's really interleaved self.bone_info_start = stream.tell() for model_info in self.arg: # logging.debug(model_info) model_info.model = Model(self.context, model_info) if model_info.num_objects: # self.get_padding(stream, alignment=8) # 21346 # self.get_padding(stream) model_info.model.read(stream) # logging.debug(model_info.model) # alignment, not sure if really correct if model_info.increment_flag: model_info.model_padding = stream.read( get_padding_size(stream.tell() - start, alignment=16)) else: model_info.model_padding = stream.read( get_padding_size(stream.tell() - start, alignment=8)) # logging.debug(f"model padding {model_info.model_padding}") i = self.assign_bone_info(i, model_info, stream) else: for model_info in self.arg: # logging.debug(model_info) model_info.model = Model(self.context, model_info) if model_info.num_objects: model_info.model.read(stream) # logging.debug(model_info.model) self.bone_info_start = stream.tell() for model_info in self.arg: try: i = self.assign_bone_info(i, model_info, stream) except: raise AttributeError(f"Bone info {i} failed") self.io_size = stream.tell() - self.io_start
def read_all_bone_infos(self, stream): # functional for JWE detailobjects.ms2, if joint_data is read potential_start = stream.tell() self.buffer_1_bytes = stream.read(self.bone_info_size) stream.seek(potential_start) self.bone_infos = [] if self.bone_info_size: logging.debug(f"mdl2 count {self.general_info.mdl_2_count}") for i in range(self.general_info.mdl_2_count): logging.debug(f"BONE INFO {i} starts at {stream.tell()}") bone_info = Ms2BoneInfo() try: bone_info.read(stream) self.assign_bone_names(bone_info) try: self.read_joints(bone_info) except: logging.error("Joints failed...") traceback.print_exc() self.read_hitcheck_verts(bone_info, stream) self.bone_infos.append(bone_info) # print(bone_info) logging.debug(f"end of bone info at {stream.tell()}") # last one has no padding, so stop here if stream.tell() >= potential_start + self.bone_info_size: logging.debug( f"Exhausted bone info buffer at {stream.tell()}") break relative_offset = stream.tell() - potential_start # currently no other way to predict the padding, no correlation to joint count padding_len = get_padding_size(relative_offset) logging.debug( f"padding {padding_len} {stream.read(padding_len)} joint count {bone_info.joint_count}" ) except Exception as err: traceback.print_exc() logging.error(f"Bone info {i} failed:") logging.error(bone_info) if self.bone_infos: logging.error(f"Last bone info that worked:") logging.error(self.bone_infos[-1]) break stream.seek(potential_start)
def read_pc_buffer_1(self, stream): """Reads the model info buffer for PC / ZTUAC which includes MDL2s + bone infos interleaved""" self.bone_infos = [] self.pc_buffer1 = stream.read_type(PcBuffer1, (self, )) logging.debug(self.pc_buffer1) for i, model_info in enumerate(self.pc_buffer1.model_infos): logging.debug(f"\n\nMDL2 {i}") # print(model_info) model_info.pc_model = stream.read_type(PcModel, (model_info, )) logging.debug(model_info.pc_model) if is_pc(self): model_info.pc_model_padding = stream.read( get_padding_size(stream.tell() - self.buffer_1_offset)) # try: # self.bone_info = stream.read_type(Ms2BoneInfo) # except Exception as err: # print("BONE INFO FAILED", err) self.bone_infos.append( self.get_bone_info(0, stream, Ms2BoneInfo, hack=False))
def get_pad(self, stream): distance = stream.tell() - self.arg.io_start return get_padding_size(distance, alignment=self.template)