def read_field(self, reader: ByteIO): count = self.count if count == 0: count = 1 exit_point = 0 if self.indirection_bytes: if self.indirection_level > 1: raise NotImplementedError( 'More than one indirection, not yet handled') if self.count > 0: raise NotImplementedError( 'Indirection.Count > 0 && field.Count > 0') indir = self.indirection_bytes[0] entry = reader.tell() offset = reader.read_uint32() if indir == 0x03: pass if not offset: return None exit_point = reader.tell() # with reader.save_current_pos(): # reader.seek(entry+offset) # return self.read_field_data(reader) elif indir == 0x04: # data = [] count = reader.read_uint32() exit_point = reader.tell() # if count>0: # with reader.save_current_pos(): # reader.seek(entry + offset) # for _ in range(count): # data.append(self.read_field(reader)) # return data else: raise NotImplementedError("Unknown indirection. ({0})".format( hex(indir))) if self.count > 0 and self.indirection_level > 0: array = [] with reader.save_current_pos(): reader.seek(entry + offset) for _ in range(count): data = self.read_field_data(reader) array.append(data) if exit_point: reader.seek(exit_point) return array else: array = [] with reader.save_current_pos(): reader.seek(entry + offset) for _ in range(count): data = self.read_field_data(reader) array.append(data) if exit_point: reader.seek(exit_point) return array else: if exit_point: reader.seek(exit_point) return self.read_field_data(reader)
def read(self, reader: ByteIO): entry = reader.tell() self.name = reader.read_ascii_string() reader.seek(entry + 36) self.format = DXGI_FORMAT(reader.read_int32()) self.offset = reader.read_uint32() reader.skip(12)
def read(self, reader: ByteIO): entry = reader.tell() self.model_count, self.model_offset = reader.read_fmt('II') with reader.save_current_pos(): reader.seek(entry + self.model_offset) for _ in range(self.model_count): self.vtx_models.append(SourceVtxModel().read(reader)) return self
def read(self, reader: ByteIO): entry = reader.tell() self.scale = [reader.read_uint32() for _ in range(6)] self.offset = [reader.read_uint32() for _ in range(6)] for offset in self.offset: with reader.save_current_pos(): reader.seek(entry + offset) self.theAnimValues.append(SourceMdlAnimationValue(reader.read_uint16())) return self
def read(self, reader: ByteIO): entry = reader.tell() self.lodCount, self.lodOffset = reader.read_fmt('ii') with reader.save_current_pos(): if self.lodCount > 0 and self.lodOffset != 0: reader.seek(entry + self.lodOffset) for _ in range(self.lodCount): self.vtx_model_lods.append(SourceVtxModelLod().read(reader, self)) return self
def read(self, reader: ByteIO): entry = reader.tell() self.strip_group_count = reader.read_uint32() self.strip_group_offset = reader.read_uint32() self.flags = reader.read_uint8() with reader.save_current_pos(): if self.strip_group_offset > 0: reader.seek(entry + self.strip_group_offset) for _ in range(self.strip_group_count): self.vtx_strip_groups.append(SourceVtxStripGroup().read(reader)) return self
def read_struct(self, reader: ByteIO): # print('Reading struct {}'.format(self.name)) struct_data = {} entry = reader.tell() for field in self.fields: reader.seek(entry + field.on_disc_size) struct_data[field.name] = field.read_field(reader) # print(struct_data) reader.seek(entry + self.disc_size) # print(struct_data) return struct_data
def read(self, reader: ByteIO): entry = reader.tell() self.replacements_count = reader.read_int32() self.replacement_offset = reader.read_int32() with reader.save_current_pos(): reader.seek(entry + self.replacement_offset) for _ in range(self.replacements_count): mat = MaterialReplacement() mat.read(reader) self.replacements.append(mat) return self
def read(self, reader: ByteIO, block_info: InfoBlock = None): self.info_block = block_info self.entry = reader.tell() self.resource_entry_offset = reader.read_int32() self.resource_count = reader.read_int32() with reader.save_current_pos(): reader.seek(self.entry + self.resource_entry_offset) for n in range(self.resource_count): resource = RERLResource() resource.read(reader) self.resources.append(resource)
def read(self, reader: ByteIO, model: SourceVtxModel): entry = reader.tell() self.lod = len(model.vtx_model_lods) self.meshCount = reader.read_uint32() self.meshOffset = reader.read_uint32() self.switchPoint = reader.read_float() with reader.save_current_pos(): if self.meshOffset > 0: reader.seek(entry + self.meshOffset) for _ in range(self.meshCount): self.vtx_meshes.append(SourceVtxMesh().read(reader)) return self
class SourceMdlFile10: def __init__(self, filepath): self.reader = ByteIO(path=filepath + '.mdl', copy_data_from_handle=False, ) self.filename = os.path.basename(filepath + '.mdl')[:-4] self.file_data = SourceMdlFileDataV10() self.file_data.read(self.reader) self.read_bones() self.read_bone_controllers() self.read_skin_families() # self.read_attachments() # self.read_mouths() # self.read_bone_flex_drivers() # self.read_flex_controllers_ui() # self.read_body_parts() # self.read_textures() # self.read_texture_paths() # self.build_flex_frames() # self.prepare_models() # # self.read_local_animation_descs() # self.read_sequences() # # print(self.mdl) def read_bones(self): if self.file_data.bone_count > 0: pb = Progress_bar(desc='Reading bones', max_=self.file_data.bone_count, len_=20) self.reader.seek(self.file_data.bone_offset, 0) for i in range(self.file_data.bone_count): pb.draw() SourceMdlBone().read(self.reader, self.file_data) pb.increment(1) pb.draw() def read_bone_controllers(self): if self.file_data.bone_controller_count > 0: pb = Progress_bar(desc='Reading Bone Controllers', max_=self.file_data.bone_controller_count, len_=20) for _ in range(self.file_data.bone_controller_count): pb.draw() SourceMdlBoneController().read(self.reader, self.file_data) pb.increment(1) def read_skin_families(self): if self.file_data.skin_family_count and self.file_data.skin_reference_count: self.reader.seek(self.file_data.skin_family_offset) for _ in range(self.file_data.skin_family_count): skin_ref = [] for _ in range(self.file_data.skin_reference_count): skin_ref.append(self.reader.read_int16()) self.file_data.skin_families.append(skin_ref) def test(self): for bone in self.file_data.bones: print(bone)
def read(self, reader: ByteIO): entry = reader.tell() self.vertex_count = reader.read_uint32() self.vertex_offset = reader.read_uint32() self.index_count = reader.read_uint32() self.index_offset = reader.read_uint32() self.strip_count = reader.read_uint32() self.strip_offset = reader.read_uint32() self.flags = StripGroupFlags(reader.read_uint8()) global extra_8 if extra_8: self.topology_indices_count = reader.read_uint32() self.topology_offset = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.index_offset) for _ in range(self.index_count): self.vtx_indexes.append(reader.read_uint16()) reader.seek(entry + self.vertex_offset) for _ in range(self.vertex_count): SourceVtxVertex().read(reader, self) reader.seek(entry + self.strip_offset) for _ in range(self.strip_count): SourceVtxStrip().read(reader, self) if extra_8: reader.seek(entry + self.topology_offset) # for _ in range(self.topology_indices_count): self.topology = (reader.read_bytes(self.topology_indices_count * 2)) return self
def read(self, reader: ByteIO): self.count = reader.read_uint32() self.size = reader.read_uint32() self.unk1 = reader.read_uint32() self.unk2 = reader.read_uint32() entry = reader.tell() self.offset = reader.read_uint32() self.total_size = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.offset) assert self.total_size == self.size * self.count self.buffer = ByteIO(byte_object=reader.read_bytes(self.count * self.size)) self.read_buffer()
def read(self, reader: ByteIO): entry = reader.tell() self.boneIndex = reader.read_uint32() self.boneNewParentIndex = reader.read_uint32() self.startInfluence = reader.read_float() self.peakInfluence = reader.read_float() self.tailInfluence = reader.read_float() self.endInfluence = reader.read_float() self.startFrameIndex = reader.read_uint32() self.localAnimOffset = reader.read_uint32() if self.localAnimOffset != 0: with reader.save_current_pos(): reader.seek(entry + self.localAnimOffset) self.theLocalAnims.read(reader) self.unused = [reader.read_uint32() for _ in range(4)] return self
def read(self, reader: ByteIO, block_info: InfoBlock = None): self.info_block = block_info entry = reader.tell() self.name_offset = reader.read_int32() self.name = reader.read_from_offset(entry + self.name_offset, reader.read_ascii_string) self.count = reader.read_int16() self.on_disc_size = reader.read_int16() entry = reader.tell() self.indirection_bytes_offset = reader.read_int32() self.indirection_level = reader.read_int32() with reader.save_current_pos(): reader.seek(entry + self.indirection_bytes_offset) indir_level = self.indirection_level if self.indirection_level < 10 else 10 for _ in range(indir_level): self.indirection_bytes.append(reader.read_int8()) self.data_type = reader.read_int32() self.type = KeyValueDataType(reader.read_int16()) reader.skip(2)
def read(self, reader: ByteIO): self.introspection_version = reader.read_int32() self.s_id = reader.read_int32() entry = reader.tell() self.name_offset = reader.read_int32() self.name = reader.read_from_offset(entry + self.name_offset, reader.read_ascii_string) self.disc_crc = reader.read_int32() self.user_version = reader.read_uint32() entry = reader.tell() self.field_offset = reader.read_int32() self.field_count = reader.read_int32() with reader.save_current_pos(): if self.field_count > 0: reader.seek(entry + self.field_offset) for n in range(self.field_count): field = NTROEnumField(self) field.read(reader) self.fields.append(field)
def read(self, reader: ByteIO, block_info: InfoBlock = None): self.info_block = block_info entry = reader.tell() self.vertex_offset = reader.read_uint32() self.vertex_count = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.vertex_offset) for _ in range(self.vertex_count): v_buffer = VertexBuffer() v_buffer.read(reader) self.vertex_buffer.append(v_buffer) entry = reader.tell() self.index_offset = reader.read_uint32() self.index_count = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.index_offset) for _ in range(self.index_count): i_buffer = IndexBuffer() i_buffer.read(reader) self.index_buffer.append(i_buffer)
def read(self, reader: ByteIO): self.count = reader.read_uint32() self.size = reader.read_uint32() entry = reader.tell() self.attributes_offset = reader.read_uint32() self.attributes_count = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.attributes_offset) for _ in range(self.attributes_count): v_attrib = VertexAttribute() v_attrib.read(reader) self.attributes.append(v_attrib) entry = reader.tell() self.offset = reader.read_uint32() self.total_size = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.offset) assert self.total_size == self.size * self.count self.buffer = ByteIO(byte_object=reader.read_bytes(self.count * self.size)) self.read_buffer()
def read(self, reader: ByteIO, block_info: InfoBlock = None): self.info_block = block_info self.introspection_version = reader.read_int32() entry = reader.tell() self.struct_offset = reader.read_int32() self.struct_count = reader.read_int32() with reader.save_current_pos(): reader.seek(entry + self.struct_offset) for n in range(self.struct_count): struct = NTROStruct(self) struct.read(reader) self.structs.append(struct) entry = reader.tell() self.enum_offset = reader.read_int32() self.enum_count = reader.read_int32() with reader.save_current_pos(): reader.seek(entry + self.enum_offset) for n in range(self.enum_count): enum = NTROEnum(self) enum.read(reader) self.enums.append(enum)
def read(self, reader: ByteIO): self.id = reader.read_fourcc() if self.id != 'IDSV': if self.id[:-1] == 'DSV': reader.insert_begin(b'I') self.id = reader.read_fourcc() print('VVD FILE WAS "PROTECTED", but screew it :P') else: raise NotImplementedError('VVD format {} is not supported!'.format(self.id)) self.version = reader.read_uint32() self.checksum = reader.read_uint32() self.lod_count = reader.read_uint32() self.lod_vertex_count = [reader.read_uint32() for _ in range(8)] self.fixup_count = reader.read_uint32() self.fixup_table_offset = reader.read_uint32() self.vertex_data_offset = reader.read_uint32() self.tangent_data_offset = reader.read_uint32() self.fixed_vertexes_by_lod = [[]] * self.lod_count if self.lod_count <= 0: return reader.seek(self.vertex_data_offset) for _ in range(self.lod_vertex_count[0]): self.vertexes.append(SourceVertex().read(reader)) reader.seek(self.fixup_table_offset) if self.fixup_count > 0: for _ in range(self.fixup_count): self.fixups.append(SourceVvdFixup().read(reader)) if self.lod_count > 0: for lod_index in range(self.lod_count): for fixup_index in range(len(self.fixups)): fixup = self.fixups[fixup_index] if fixup.lod_index >= lod_index: for j in range(fixup.vertex_count): vertex = self.vertexes[fixup.vertex_index + j] self.fixed_vertexes_by_lod[lod_index].append(vertex)
def read(self, reader: ByteIO): self.version = reader.read_uint32() if self.version!=7: if self.version == 402653184: reader.insert_begin(b'\x07') self.version = reader.read_uint32() print('VTX FILE WAS "PROTECTED", but screew it :P') else: raise NotImplementedError('VTX version {} is not supported!'.format(self.version)) self.vertex_cache_size = reader.read_uint32() self.max_bones_per_strip = reader.read_uint16() self.max_bones_per_tri = reader.read_uint16() self.max_bones_per_vertex = reader.read_uint32() self.checksum = reader.read_uint32() self.lodCount = reader.read_uint32() self.material_replacement_list_offset = reader.read_uint32() self.bodyPartCount = reader.read_uint32() self.bodyPartOffset = reader.read_uint32() global max_bones_per_vertex max_bones_per_vertex = self.max_bones_per_vertex if self.bodyPartOffset > 0: reader.seek(self.bodyPartOffset) try: for _ in range(self.bodyPartCount): self.vtx_body_parts.append(SourceVtxBodyPart().read(reader)) except struct.error: global extra_8 extra_8 = False self.vtx_body_parts.clear() reader.seek(self.bodyPartOffset) for _ in range(self.bodyPartCount): self.vtx_body_parts.append(SourceVtxBodyPart().read(reader)) if self.material_replacement_list_offset > 0: reader.seek(self.material_replacement_list_offset) for _ in range(self.lodCount): self.material_replacement_lists.append(MaterialReplacementList().read(reader))
class BinaryKeyValue(Dummy): ENCODING = (0x46, 0x1A, 0x79, 0x95, 0xBC, 0x95, 0x6C, 0x4F, 0xA7, 0x0B, 0x05, 0xBC, 0xA1, 0xB7, 0xDF, 0xD2) FORMAT = (0x7C, 0x16, 0x12, 0x74, 0xE9, 0x06, 0x98, 0x46, 0xAF, 0xF2, 0xE6, 0x3E, 0xB5, 0x90, 0x37, 0xE7) SIG = (0x56, 0x4B, 0x56, 0x03) def __init__(self, block_info: InfoBlock = None): self.strings = [] self.info_block = block_info self.kv = [] self.flags = 0 self.buffer = ByteIO() # type: ByteIO def read(self, reader: ByteIO): fourcc = reader.read_bytes(4) assert tuple(fourcc) == self.SIG, 'Invalid KV Signature' encoding = reader.read_bytes(16) assert tuple(encoding) == self.ENCODING, 'Unrecognized KV3 Encoding' format = reader.read_bytes(16) assert tuple(format) == self.FORMAT, 'Unrecognised KV3 Format' self.flags = reader.read_bytes(4) if self.flags[3] & 0x80: self.buffer.write_bytes( reader.read_bytes(self.info_block.block_size - (reader.tell() - self.info_block.absolute_offset))) working = True while reader.tell() != reader.size() and working: block_mask = reader.read_uint16() for i in range(16): if block_mask & (1 << i) > 0: offset_and_size = reader.read_uint16() offset = ((offset_and_size & 0xFFF0) >> 4) + 1 size = (offset_and_size & 0x000F) + 3 lookup_size = offset if offset < size else size entry = self.buffer.tell() self.buffer.seek(entry - offset) data = self.buffer.read_bytes(lookup_size) self.buffer.seek(entry) while size > 0: self.buffer.write_bytes( data[:lookup_size if lookup_size < size else size]) size -= lookup_size else: data = reader.read_int8() self.buffer.write_int8(data) if self.buffer.size() == (self.flags[2] << 16) + ( self.flags[1] << 8) + self.flags[0]: working = False break self.buffer.seek(0) string_count = self.buffer.read_uint32() for i in range(string_count): self.strings.append(self.buffer.read_ascii_string()) self.parse(self.buffer, self.kv, True) self.buffer.close() del self.buffer def parse(self, reader: ByteIO, parent=None, in_array=False): name = None parent = parent if not in_array: string_id = reader.read_uint32() name = "ERROR" if string_id == -1 else self.strings[string_id] add = lambda v: parent.update({name: v} ) if not in_array else parent.append(v) data_type = reader.read_int8() flag_info = KVFlag.Nothing if data_type & 0x80: data_type &= 0x7F flag_info = KVFlag(reader.read_int8()) if data_type == KVType.NULL: add(None) return if data_type == KVType.BOOLEAN: add(reader.read_int8() > 0) return if data_type == KVType.INTEGER: add(reader.read_int64()) return if data_type == KVType.DOUBLE: add(reader.read_double()) return if data_type == KVType.STRING: string_id = reader.read_int32() if string_id == -1: add(None) return add(self.strings[string_id]) return if data_type == KVType.ARRAY: size = reader.read_uint32() arr = [] for _ in range(size): self.parse(reader, arr, True) add(arr) return if data_type == KVType.OBJECT: size = reader.read_uint32() tmp = {} for _ in range(size): self.parse(reader, tmp, False) add(tmp) if not parent: parent = tmp return parent
def read(self,reader:ByteIO,mdl:SourceMdlFileData): entry = reader.tell() self.baseHeaderOffset = reader.read_int32() self.nameOffset = reader.read_uint32() self.theName = reader.read_from_offset(entry+self.nameOffset,reader.read_ascii_string) self.activityNameOffset = reader.read_uint32() self.theActivityName = reader.read_from_offset(entry+self.activityNameOffset,reader.read_ascii_string) self.flags = reader.read_uint32() self.activity = reader.read_int32() self.activityWeight = reader.read_uint32() self.eventCount = reader.read_uint32() self.eventOffset = reader.read_uint32() self.bbMin.read(reader) self.bbMax.read(reader) self.blendCount = reader.read_uint32() self.animIndexOffset = reader.read_uint32() self.movementIndex = reader.read_uint32() self.groupSize = [reader.read_uint32() for _ in range(2)] self.paramIndex = [reader.read_int32() for _ in range(2)] self.paramStart = [reader.read_uint32() for _ in range(2)] self.paramEnd = [reader.read_uint32() for _ in range(2)] self.paramParent = reader.read_uint32() self.fadeInTime = reader.read_float() self.fadeOutTime = reader.read_float() self.localEntryNodeIndex = reader.read_uint32() self.localExitNodeIndex = reader.read_uint32() self.nodeFlags = reader.read_uint32() self.entryPhase = reader.read_float() self.exitPhase = reader.read_float() self.lastFrame = reader.read_float() self.nextSeq = reader.read_uint32() self.pose = reader.read_uint32() self.ikRuleCount = reader.read_uint32() self.autoLayerCount = reader.read_uint32() self.autoLayerOffset = reader.read_uint32() self.weightOffset = reader.read_uint32() self.poseKeyOffset = reader.read_uint32() self.ikLockCount = reader.read_uint32() self.ikLockOffset = reader.read_uint32() self.keyValueOffset = reader.read_uint32() self.keyValueSize = reader.read_uint32() self.cyclePoseIndex = reader.read_uint32() if mdl.version == 49: self.activityModifierOffset = reader.read_int32() self.activityModifierCount = reader.read_uint32() self.unused = [reader.read_uint32() for _ in range(5)] else: self.unused = [reader.read_uint32() for _ in range(7)] if self.groupSize[0] > 1 and self.groupSize[1] > 1 and self.poseKeyOffset !=0: with reader.save_current_pos(): reader.seek(entry+self.poseKeyOffset) for _ in range(self.groupSize[0]+self.groupSize[1]): self.thePoseKeys.append(reader.read_float()) if self.eventCount > 0 and self.eventOffset!=0: with reader.save_current_pos(): reader.seek(entry+self.eventOffset) for _ in range(self.eventCount): self.theEvents.append(SourceMdlEvent().read(reader)) return self
def read(self, frame_count, anim_section, mdl: SourceMdlFileData, reader: ByteIO): anim_entry = reader.tell() self.boneIndex = reader.read_uint8() print('BoneIndex:',self.boneIndex) try: self.bone_name = mdl.bones[self.boneIndex].name except: self.bone_name = "ERROR" print('BoneName:',self.bone_name) if self.boneIndex == 255: reader.skip(3) return self, 0 if self.boneIndex >= mdl.bone_count: print('Bone index out of range {} - {}'.format(self.boneIndex, mdl.bone_count)) return self, 0 self.flags = reader.read_uint8() self.sflags = self.STUDIO_ANIM.get_flags(self.flags) self.nextSourceMdlAnimationOffset = reader.read_int16() pdata = reader.tell() print('Seq flag',self.flags,self.sflags) if (self.flags & self.STUDIO_ANIM.RAWROT2) > 0: with reader.save_current_pos(): reader.seek(pdata) self.theRot64bits.read(reader) print('Rot 64',self.theRot64bits) if (self.flags & self.STUDIO_ANIM.RAWROT) > 0: with reader.save_current_pos(): reader.seek(pdata) self.theRot48bits.read(reader) print('Rot 48', self.theRot48bits) if (self.flags & self.STUDIO_ANIM.RAWPOS) > 0: with reader.save_current_pos(): reader.seek(pdata+(((self.flags & self.STUDIO_ANIM.RAWROT) != 0)*6) + ((self.flags & self.STUDIO_ANIM.RAWROT2) != 0)*8) self.thePos.read(reader) print('Pos', self.thePos) if (self.flags & self.STUDIO_ANIM.ANIMROT) > 0: with reader.save_current_pos(): rotV_entry = reader.tell() reader.seek(pdata) self.theRotV.read(reader) self.theRotV.read_values(rotV_entry, frame_count, reader) print('Rot V', self.theRotV) if (self.flags & self.STUDIO_ANIM.ANIMPOS) > 0: with reader.save_current_pos(): reader.seek(((self.flags & self.STUDIO_ANIM.ANIMPOS)!=0) + pdata) posV_entry = reader.tell() self.thePosV.read(reader) self.thePosV.read_values(posV_entry, frame_count, reader) print('Pos V', self.thePosV) print('\n') pprint(self.__dict__) print('\n') if self.nextSourceMdlAnimationOffset == 0: print('DONE WITH ANIMATIONS') reader.seek(pdata) return self, -1 else: nextAnimationInputFileStreamPosition = anim_entry + self.nextSourceMdlAnimationOffset if nextAnimationInputFileStreamPosition < reader.tell(): print('PROBLEM! Should not be going backwards in file.') # raise BufferError('PROBLEM! Should not be going backwards in file.') reader.seek(nextAnimationInputFileStreamPosition) anim_section.append(self) return self, 1
class ValveFile: def __init__(self, filepath): try: from Source2.Blocks.NTRO import NTRO from Source2.Blocks.REDI import REDI from Source2.Blocks.RERP import RERL from Source2.Blocks.VBIB import VBIB from Source2.Blocks.DATA import DATA except: from .Blocks.NTRO import NTRO from .Blocks.REDI import REDI from .Blocks.RERP import RERL from .Blocks.VBIB import VBIB from .Blocks.DATA import DATA print('Reading {}'.format(filepath)) self.reader = ByteIO( path=filepath, copy_data_from_handle=False, ) self.filepath = Path(filepath) self.filename = self.filepath.stem self.filepath = os.path.abspath(os.path.dirname(filepath)) self.header = CompiledHeader() self.header.read(self.reader) self.blocks_info = [] # type: List[InfoBlock] self.rerl = RERL(self) self.nrto = NTRO(self) self.redi = REDI(self) self.vbib = VBIB(self) self.data = DATA(self) self.available_resources = {} def read_block_info(self): for n in range(self.header.block_count): block_info = InfoBlock() block_info.read(self.reader) self.blocks_info.append(block_info) print(block_info) if block_info.block_name == 'RERL': with self.reader.save_current_pos(): self.reader.seek(block_info.entry + block_info.block_offset) self.rerl.read(self.reader, block_info) # print(self.rerl) if block_info.block_name == 'NTRO': with self.reader.save_current_pos(): self.reader.seek(block_info.entry + block_info.block_offset) self.nrto.read(self.reader, block_info) if block_info.block_name == 'REDI': with self.reader.save_current_pos(): self.reader.seek(block_info.entry + block_info.block_offset) self.redi.read(self.reader, block_info) # print(self.redi) if block_info.block_name == 'VBIB': with self.reader.save_current_pos(): self.reader.seek(block_info.entry + block_info.block_offset) self.vbib.read(self.reader, block_info) # print(self.vbib) if block_info.block_name == 'DATA': with self.reader.save_current_pos(): self.reader.seek(block_info.entry + block_info.block_offset) self.data.read(self.reader, block_info) # pprint(self.data.data) def dump_structs(self, file: TextIO): file.write('''struct vector2 { float x,y } struct vector3 { float x,y,z } struct vector4 { float x,y,z,w } struct quaternion { float x,y,z,w } struct RGB { byte r,g,b } ''') for struct in self.nrto.structs: # print(struct) # for mem in struct.fields: # print('\t', mem) file.write(struct.as_c_struct()) # print(struct.as_c_struct()) for enum in self.nrto.enums: # print(enum) # for mem in enum.fields: # print('\t', mem) file.write(enum.as_c_enum()) # print(struct.as_c_struct()) def dump_resources(self): for block in self.rerl.resources: pass # print(block) # for block in self.redi.blocks: # print(block) # for dep in block.container: # print('\t',dep) # print(block) # for block in self.vbib.vertex_buffer: # for vert in block.vertexes: # print(vert.boneWeight) # print(block) def check_external_resources(self): for block in self.rerl.resources: name = os.path.basename(block.resource_name) if os.path.exists(os.path.join(self.filepath, name + '_c')): self.available_resources[name] = os.path.abspath( os.path.join(self.filepath, name + '_c')) print('Found', name) else: print('Can\'t find', name)
class VertexBuffer(Dummy): def __init__(self): self.count = 0 self.size = 0 self.attributes_offset = 0 self.attributes_count = 0 self.offset = 0 self.total_size = 0 self.attributes = [] # type:List[VertexAttribute] self.buffer = None # type: ByteIO self.vertexes = [] # type: List[SourceVertex] def __repr__(self): buff = '' for attrib in self.attributes: buff += attrib.name + ' ' + attrib.format.name + '; ' return '<VertexBuffer vertexes:{} attributes:{} vertex size:{} vertex attributes: {} >'.format( self.count, self.attributes_count, self.size, buff, ) def read(self, reader: ByteIO): self.count = reader.read_uint32() self.size = reader.read_uint32() entry = reader.tell() self.attributes_offset = reader.read_uint32() self.attributes_count = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.attributes_offset) for _ in range(self.attributes_count): v_attrib = VertexAttribute() v_attrib.read(reader) self.attributes.append(v_attrib) entry = reader.tell() self.offset = reader.read_uint32() self.total_size = reader.read_uint32() with reader.save_current_pos(): reader.seek(entry + self.offset) assert self.total_size == self.size * self.count self.buffer = ByteIO(byte_object=reader.read_bytes(self.count * self.size)) self.read_buffer() def read_buffer(self): for n in range(self.count): entry = self.buffer.tell() vertex = SourceVertex() for attrib in self.attributes: if attrib.name == 'POSITION': vertex.position = SourceVector( *attrib.read_from_buffer(self.buffer)) elif attrib.name == 'TEXCOORD': vertex.texCoordX, vertex.texCoordY = attrib.read_from_buffer( self.buffer) elif attrib.name == 'NORMAL': vertex.normal = SourceVector( *attrib.read_from_buffer(self.buffer)) elif attrib.name == "BLENDINDICES": vertex.boneWeight.bone = attrib.read_from_buffer( self.buffer) vertex.boneWeight.boneCount = len(vertex.boneWeight.bone) elif attrib.name == "BLENDWEIGHT": vertex.boneWeight.weight = SourceVector4D( *attrib.read_from_buffer( self.buffer)).to_floats.as_list self.vertexes.append(vertex) self.buffer.seek(entry + self.size)