def unpack(self, mdl0, binfile): """ unpacks model data """ super().unpack(mdl0, binfile) offset = binfile.start() # Header ln = binfile.readLen() fh, mdl0.scaling_rule, mdl0.texture_matrix_mode, mdl0.facepoint_count, \ mdl0.faceCount, _, mdl0.boneCount, _ = binfile.read("i7I", 32) binfile.store() # bone table offset if binfile.offset - offset < ln: mdl0.minimum = binfile.read("3f", 12) mdl0.maximum = binfile.read("3f", 12) else: mdl0.find_min_max = True binfile.end() # end header binfile.recallOffset(offset) mdl0.boneTable = unpack_bonetable(binfile, 'I') # unpack sections self.definitions = self.unpackSection(binfile, self.UnpackDefinition, 'Definitions', return_nodes=False) # store bone unpackers to resolve references self.bone_unpackers = self.unpackSection(binfile, UnpackBone, 'Bones', return_nodes=False) mdl0.vertices = self.unpackSection(binfile, UnpackVertex, 'Vertices') mdl0.normals = self.unpackSection(binfile, UnpackNormal, 'Normals') mdl0.colors = self.unpackSection(binfile, UnpackColor, 'Colors') mdl0.uvs = self.unpackSection(binfile, UnpackUV, 'UVs') if mdl0.version >= 10: if binfile.recall() or binfile.recall(): raise UnpackingError(binfile, 'Furs are not supported!') # mdl0.fur_vectors = self.unpackSection(binfile, UnpackFurVectors, 'FurVectors') # mdl0.fur_layers = self.unpackSection(binfile, UnpackFurLayers, 'FurLayers') self.mat_unpackers = self.unpackSection(binfile, UnpackMaterial, 'Materials', return_nodes=False) self.shader_offsets_map = self.unpack_shaders(binfile) self.poly_unpackers = self.unpackSection(binfile, UnpackPolygon, 'Objects', return_nodes=False) # self.texture_links = self.unpackSection(binfile, self.UnpackTexLink, 'Textures', return_nodes=False) if binfile.recall() and binfile.recall(): raise UnpackingError(binfile, 'Palettes are not supported!') binfile.end() # end file self.post_unpack(mdl0)
def unpack(self, subfile, binfile): """ unpacks the sub file, subclass must use binfile.end() """ offset = binfile.start() magic = binfile.readMagic() if magic != subfile.MAGIC: raise UnpackingError(binfile, 'Magic {} does not match expected {}'.format(magic, subfile.MAGIC)) binfile.readLen() subfile.version, outerOffset = binfile.read("Ii", 8) try: subfile.numSections = subfile.get_num_sections() except KeyError: raise UnpackingError(binfile, "{} {} unsupported version {}".format(subfile.MAGIC, subfile.name, subfile.version)) binfile.store(subfile.numSections) # store section offsets subfile.name = binfile.unpack_name()
def unpack(self, brres, binfile): """ Unpacks the brres """ self.offset = binfile.start() magic = binfile.readMagic() if magic != 'bres': raise UnpackingError(brres, '"{}" not a brres file'.format(brres.name)) bom = binfile.read("H", 2) binfile.bom = "<" if bom == 0xfffe else ">" binfile.advance(2) l = binfile.readLen() rootoffset, numSections = binfile.read("2h", 4) binfile.offset = rootoffset root = binfile.readMagic() assert (root == 'root') section_length = binfile.read("I", 4) root = Folder(binfile, root) root.unpack(binfile) self.section_offsets = [] # open all the folders for i in range(len(root)): self.unpack_folder(root.recallEntryI()) self.section_offsets.append(binfile.names_offset) brres.unknown = self.unpack_unknown() binfile.end() self.post_unpacking(brres)
def get_index_decoder(self, index): if index == ply.INDEX_FORMAT_NONE: return None elif index == ply.INDEX_FORMAT_BYTE: return 'B' elif index == ply.INDEX_FORMAT_SHORT: return 'H' elif index == 1: raise UnpackingError( self.binfile, f'Polygon {self.node.name} has direct indices, which are not supported' ) else: raise UnpackingError( self.binfile, f'Polygon {self.node.name} index format {index} out of range')
def unpack_key_frame_list(self, anim, binfile): offset = binfile.offset binfile.offset = binfile.read('I', 0)[0] + offset anim.entries = [] # header size, uk, fs = binfile.read("2Hf", 8) # print('FrameScale: {} i v d'.format(fs)) # str = '' if size <= 0: raise UnpackingError(binfile, 'SRT0 Key frame list has no entries!') for i in range(size): index, value, delta = binfile.read("3f", 12) # str += '({},{},{}), '.format(index, value, delta) anim.entries.append(anim.SRTKeyFrame(value, index, delta)) binfile.offset = offset + 4 return anim
def get_next_offset(self, binfile, boundary_offsets): current_offset = binfile.offset next_offset = float('inf') for x in boundary_offsets: if current_offset < x < next_offset: next_offset = x if next_offset == float('inf'): raise UnpackingError( binfile, 'Failed to detect end offset after {}'.format(current_offset)) if not self.is_folder: for i in range(current_offset, len(binfile.file)): if binfile.file[i] == 0: i += 1 if next_offset < i: return next_offset return i return next_offset
def unpack(self, material, binfile): """ Unpacks material """ self.offset = binfile.start() # print('Material {} offset {}'.format(self.name, offset)) binfile.readLen() binfile.advance(8) material.index, xluFlags, ntexgens, nlights, \ material.shaderStages, material.indirectStages, \ material.cullmode, material.compareBeforeTexture, \ material.lightset, material.fogset, pad = binfile.read("2I2B2BI4b", 20) material.xlu = xluFlags >> 31 & 1 assert (xluFlags & 0x7fffffff) == 0 assert nlights <= 2 binfile.advance(8) self.shaderOffset, nlayers = binfile.read("2i", 8) self.shaderOffset += self.offset if nlayers != ntexgens: raise UnpackingError( 'Number of layers {} is different than number texgens {}'. format(nlayers, ntexgens)) binfile.store() # layer offset if material.parent.version >= 10: binfile.advance(8) # bo = binfile.offset # [dpo] = binfile.readOffset("I", binfile.offset) binfile.store() # store matgx offset else: binfile.advance(4) binfile.store() # store matgx offset # binfile.advance(4) # ignore precompiled code space binfile.advance(360) startlayerInfo = binfile.offset # [self.textureMatrixMode] = binfile.readOffset('I', binfile.offset + 4) self.unpack_layers(binfile, startlayerInfo, nlayers) binfile.offset = startlayerInfo + 584 self.unpack_light_channels(binfile, nlights) binfile.recall() binfile.start() # Mat wii graphics self.unpack_matgx(material, binfile) for layer in self.layers: layer.unpack_xf(binfile) binfile.end() binfile.end()
def unpack_folder(self, folder_name): self.folder_name = folder_name if folder_name == "3DModels(NW4R)": self.node.models = self.unpack_subfiles(Mdl0) elif folder_name == "Textures(NW4R)": self.node.textures = self.unpack_subfiles(Tex0) elif folder_name == "AnmTexPat(NW4R)": self.node.pat0 = self.unpack_subfiles(Pat0) elif folder_name == "AnmTexSrt(NW4R)": self.node.srt0 = self.unpack_subfiles(Srt0) elif folder_name == "AnmChr(NW4R)": self.node.chr0 = self.unpack_subfiles(Chr0) elif folder_name == "AnmScn(NW4R)": self.node.scn0 = self.unpack_subfiles(Scn0) elif folder_name == "AnmShp(NW4R)": self.node.shp0 = self.unpack_subfiles(Shp0) elif folder_name == "AnmClr(NW4R)": self.node.clr0 = self.unpack_subfiles(Clr0) else: raise UnpackingError(self.binfile, 'Unkown folder {}'.format(folder_name))
def post_unpack(self, mdl0): # set up mdl0 nodes left mdl0.bones = [x.node for x in self.bone_unpackers] mdl0.objects = [x.node for x in self.poly_unpackers] mdl0.materials = [x.node for x in self.mat_unpackers] # hook references for x in self.mat_unpackers: try: shader = self.shader_offsets_map[x.shaderOffset] except ValueError: raise UnpackingError( self.binfile, 'Material {} shader not found!'.format(x.node.name)) if shader.parent is not None: # only use one shader per material shader = deepcopy(shader) shader.parent = x.node x.node.shader = shader for x in self.bone_unpackers: x.post_unpack(self.bone_unpackers) for x in self.definitions: if x.definition is not None: self.parse_definition_list(x.definition.list) for x in self.poly_unpackers: x.post_unpack()
def unpack_key_frames(key_frame_list, binfile, from_in_place=True, format=None): offset = binfile.offset if from_in_place: binfile.offset = binfile.read('I', 0)[0] + offset else: binfile.store() binfile.recall() key_frame_list.entries = [] # header size, uk, fs = binfile.read("2Hf", 8) # print('FrameScale: {} i v d'.format(fs)) # str = '' if size <= 0: raise UnpackingError(binfile, 'Key frame list has no entries!') for i in range(size): index, value, delta = binfile.read("3f", 12) # str += '({},{},{}), '.format(index, value, delta) key_frame_list.entries.append( key_frame_list.KeyFrame(value, index, delta)) binfile.offset = offset + 4 return key_frame_list