def set_defaults(self): self.name_count = 0 if self.context.version >= 32: self.knownff = 0 if self.context.version >= 32: self.zero_0 = 0 if self.context.version >= 32: self.unknown_0_c = 0 self.unk_count = 0 self.bind_matrix_count = 0 self.zeros = numpy.zeros((3), dtype='uint64') self.bone_count = 0 self.unknown_40 = 0 self.parents_count = 0 if (self.context.version == 13) or (((self.context.version == 48) or (self.context.version == 50)) or (self.context.version == 51)): self.extra_zero = 0 self.enum_count = 0 self.unknown_58 = 0 self.one = 0 self.zeros_count = 0 if self.context.version == 32: self.unk_pc_count = 0 self.count_7 = 0 self.joint_count = 0 self.unk_78_count = 0 if self.context.version <= 13: self.unk_extra = 0 if (self.context.version == 47) or (self.context.version == 39): self.unk_extra_jwe = 0 if not (self.context.version < 47): self.name_indices = numpy.zeros((self.name_count), dtype='uint') if self.context.version < 47: self.name_indices = numpy.zeros((self.name_count), dtype='ushort') if not (self.context.version < 47): self.name_padding = numpy.zeros( ((16 - ((self.name_count * 4) % 16)) % 16), dtype='byte') if self.context.version < 47: self.name_padding = numpy.zeros( ((16 - ((self.name_count * 2) % 16)) % 16), dtype='byte') self.inverse_bind_matrices = Array(self.context) self.bones = Array(self.context) self.parents = numpy.zeros((self.parents_count), dtype='ubyte') if not (self.context.version == 13): self.parents_padding = numpy.zeros( ((8 - (self.parents_count % 8)) % 8), dtype='byte') if not (self.context.version == 13) and self.one: self.enumeration = numpy.zeros((self.enum_count, 2), dtype='uint') if self.context.version == 13 and self.one: self.enumeration = numpy.zeros((self.enum_count), dtype='ubyte') if self.context.version == 13: self.zt_weirdness = numpy.zeros((10), dtype='short') if not (self.context.version < 47) and self.zeros_count: self.zeros_padding = ZerosPadding(self.context, self.zeros_count, None) if self.context.version < 47 and self.zeros_count: self.minus_padding = MinusPadding(self.context, self.zeros_count, None) if self.count_7: self.struct_7 = Struct7(self.context, None, None) if self.joint_count: self.joints = JointData(self.context, None, None)
class BKHDSection: """ First Section of a soundback aux """ def __init__(self, arg=None, template=None): self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # length of following data self.length = 0 self.version = 0 self.id_a = 0 self.id_b = 0 self.constant_a = 0 self.constant_b = 0 # filler zeroes self.zeroes = Array() def read(self, stream): self.io_start = stream.tell() self.length = stream.read_uint() self.version = stream.read_uint() stream.version = self.version self.id_a = stream.read_uint() self.id_b = stream.read_uint() self.constant_a = stream.read_uint() self.constant_b = stream.read_uint() self.zeroes.read(stream, 'Byte', self.length - 20, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_uint(self.length) stream.write_uint(self.version) stream.version = self.version stream.write_uint(self.id_a) stream.write_uint(self.id_b) stream.write_uint(self.constant_a) stream.write_uint(self.constant_b) self.zeroes.write(stream, 'Byte', self.length - 20, None) self.io_size = stream.tell() - self.io_start def __repr__(self): s = 'BKHDSection [Size: ' + str(self.io_size) + ', Address:' + str( self.io_start) + ']' s += '\n * length = ' + self.length.__repr__() s += '\n * version = ' + self.version.__repr__() s += '\n * id_a = ' + self.id_a.__repr__() s += '\n * id_b = ' + self.id_b.__repr__() s += '\n * constant_a = ' + self.constant_a.__repr__() s += '\n * constant_b = ' + self.constant_b.__repr__() s += '\n * zeroes = ' + self.zeroes.__repr__() s += '\n' return s
class BoneInfo: context = ContextReference() def __init__(self, context, arg=None, template=None): self.name = '' self._context = context self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # counts the names self.name_count = 0 # this is always FFFF for now self.knownff = 0 # this is always 0000 for now self.zero_0 = 0 self.unknown_0_c = 0 # almost always 4, 1 for male african lion self.unk_count = 0 # seems to match bone count self.bind_matrix_count = 0 self.zeros = numpy.zeros((3), dtype='uint64') self.bone_count = 0 self.unknown_40 = 0 self.parents_count = 0 # not PC, JWE1 self.extra_zero = 0 self.enum_count = 0 # usually zero self.unknown_58 = 0 # always 1 self.one = 0 # this counts the weird padding at the end, usually == bone count, 0 in PZ aardvark self.zeros_count = 0 # matches the other count on dino entertainer, but count7 is not present self.unk_pc_count = 0 # index count 7 self.count_7 = 0 # joint count self.joint_count = 0 # zero self.unk_78_count = 0 # zero self.unk_extra = 0 # zero self.unk_extra_jwe = 0 # index into ms2 string table for bones used here self.name_indices = numpy.zeros((self.name_count), dtype='uint') # index into ms2 string table for bones used here self.name_indices = numpy.zeros((self.name_count), dtype='ushort') # zeros. One index occupies 4 bytes; pad to multiples of 16 bytes. self.name_padding = numpy.zeros( ((16 - ((self.name_count * 4) % 16)) % 16), dtype='byte') # zeros. One index occupies 4 bytes; pad to multiples of 16 bytes. self.name_padding = numpy.zeros( ((16 - ((self.name_count * 2) % 16)) % 16), dtype='byte') # used for skinning self.inverse_bind_matrices = Array(self.context) self.bones = Array(self.context) # 255 = root, index in this list is the current bone index, value is the bone's parent index self.parents = numpy.zeros((self.parents_count), dtype='ubyte') # zeros self.parents_padding = numpy.zeros( ((8 - (self.parents_count % 8)) % 8), dtype='byte') # enumerates all bone indices, 4 may be flags self.enumeration = numpy.zeros((self.enum_count, 2), dtype='uint') # enumerates all bone indices, 4 may be flags self.enumeration = numpy.zeros((self.enum_count), dtype='ubyte') # zeros self.zt_weirdness = numpy.zeros((10), dtype='short') # weird zeros self.zeros_padding = ZerosPadding(self.context, self.zeros_count, None) # weird -1s self.minus_padding = MinusPadding(self.context, self.zeros_count, None) # ragdoll links? self.struct_7 = Struct7(self.context, None, None) # joints self.joints = JointData(self.context, None, None) self.set_defaults() def set_defaults(self): self.name_count = 0 if self.context.version >= 32: self.knownff = 0 if self.context.version >= 32: self.zero_0 = 0 if self.context.version >= 32: self.unknown_0_c = 0 self.unk_count = 0 self.bind_matrix_count = 0 self.zeros = numpy.zeros((3), dtype='uint64') self.bone_count = 0 self.unknown_40 = 0 self.parents_count = 0 if (self.context.version == 13) or (((self.context.version == 48) or (self.context.version == 50)) or (self.context.version == 51)): self.extra_zero = 0 self.enum_count = 0 self.unknown_58 = 0 self.one = 0 self.zeros_count = 0 if self.context.version == 32: self.unk_pc_count = 0 self.count_7 = 0 self.joint_count = 0 self.unk_78_count = 0 if self.context.version <= 13: self.unk_extra = 0 if (self.context.version == 47) or (self.context.version == 39): self.unk_extra_jwe = 0 if not (self.context.version < 47): self.name_indices = numpy.zeros((self.name_count), dtype='uint') if self.context.version < 47: self.name_indices = numpy.zeros((self.name_count), dtype='ushort') if not (self.context.version < 47): self.name_padding = numpy.zeros( ((16 - ((self.name_count * 4) % 16)) % 16), dtype='byte') if self.context.version < 47: self.name_padding = numpy.zeros( ((16 - ((self.name_count * 2) % 16)) % 16), dtype='byte') self.inverse_bind_matrices = Array(self.context) self.bones = Array(self.context) self.parents = numpy.zeros((self.parents_count), dtype='ubyte') if not (self.context.version == 13): self.parents_padding = numpy.zeros( ((8 - (self.parents_count % 8)) % 8), dtype='byte') if not (self.context.version == 13) and self.one: self.enumeration = numpy.zeros((self.enum_count, 2), dtype='uint') if self.context.version == 13 and self.one: self.enumeration = numpy.zeros((self.enum_count), dtype='ubyte') if self.context.version == 13: self.zt_weirdness = numpy.zeros((10), dtype='short') if not (self.context.version < 47) and self.zeros_count: self.zeros_padding = ZerosPadding(self.context, self.zeros_count, None) if self.context.version < 47 and self.zeros_count: self.minus_padding = MinusPadding(self.context, self.zeros_count, None) if self.count_7: self.struct_7 = Struct7(self.context, None, None) if self.joint_count: self.joints = JointData(self.context, None, None) def read(self, stream): self.io_start = stream.tell() self.name_count = stream.read_uint64() if self.context.version >= 32: self.knownff = stream.read_short() self.zero_0 = stream.read_short() if self.context.version >= 32: self.unknown_0_c = stream.read_uint() self.unk_count = stream.read_uint64() self.bind_matrix_count = stream.read_uint64() self.zeros = stream.read_uint64s((3)) self.bone_count = stream.read_uint64() self.unknown_40 = stream.read_uint64() self.parents_count = stream.read_uint64() if (self.context.version == 13) or (((self.context.version == 48) or (self.context.version == 50)) or (self.context.version == 51)): self.extra_zero = stream.read_uint64() self.enum_count = stream.read_uint64() self.unknown_58 = stream.read_uint64() self.one = stream.read_uint64() self.zeros_count = stream.read_uint64() if self.context.version == 32: self.unk_pc_count = stream.read_uint64() self.count_7 = stream.read_uint64() self.joint_count = stream.read_uint64() self.unk_78_count = stream.read_uint64() if self.context.version <= 13: self.unk_extra = stream.read_uint64() if (self.context.version == 47) or (self.context.version == 39): self.unk_extra_jwe = stream.read_uint64() if not (self.context.version < 47): self.name_indices = stream.read_uints((self.name_count)) if self.context.version < 47: self.name_indices = stream.read_ushorts((self.name_count)) if not (self.context.version < 47): self.name_padding = stream.read_bytes( ((16 - ((self.name_count * 4) % 16)) % 16)) if self.context.version < 47: self.name_padding = stream.read_bytes( ((16 - ((self.name_count * 2) % 16)) % 16)) self.inverse_bind_matrices.read(stream, Matrix44, self.bind_matrix_count, None) self.bones.read(stream, Bone, self.bone_count, None) self.parents = stream.read_ubytes((self.parents_count)) if not (self.context.version == 13): self.parents_padding = stream.read_bytes( ((8 - (self.parents_count % 8)) % 8)) if not (self.context.version == 13) and self.one: self.enumeration = stream.read_uints((self.enum_count, 2)) if self.context.version == 13 and self.one: self.enumeration = stream.read_ubytes((self.enum_count)) if self.context.version == 13: self.zt_weirdness = stream.read_shorts((10)) if not (self.context.version < 47) and self.zeros_count: self.zeros_padding = stream.read_type( ZerosPadding, (self.context, self.zeros_count, None)) if self.context.version < 47 and self.zeros_count: self.minus_padding = stream.read_type( MinusPadding, (self.context, self.zeros_count, None)) if self.count_7: self.struct_7 = stream.read_type(Struct7, (self.context, None, None)) if self.joint_count: self.joints = stream.read_type(JointData, (self.context, None, None)) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_uint64(self.name_count) if self.context.version >= 32: stream.write_short(self.knownff) stream.write_short(self.zero_0) if self.context.version >= 32: stream.write_uint(self.unknown_0_c) stream.write_uint64(self.unk_count) stream.write_uint64(self.bind_matrix_count) stream.write_uint64s(self.zeros) stream.write_uint64(self.bone_count) stream.write_uint64(self.unknown_40) stream.write_uint64(self.parents_count) if (self.context.version == 13) or (((self.context.version == 48) or (self.context.version == 50)) or (self.context.version == 51)): stream.write_uint64(self.extra_zero) stream.write_uint64(self.enum_count) stream.write_uint64(self.unknown_58) stream.write_uint64(self.one) stream.write_uint64(self.zeros_count) if self.context.version == 32: stream.write_uint64(self.unk_pc_count) stream.write_uint64(self.count_7) stream.write_uint64(self.joint_count) stream.write_uint64(self.unk_78_count) if self.context.version <= 13: stream.write_uint64(self.unk_extra) if (self.context.version == 47) or (self.context.version == 39): stream.write_uint64(self.unk_extra_jwe) if not (self.context.version < 47): stream.write_uints(self.name_indices) if self.context.version < 47: stream.write_ushorts(self.name_indices) if not (self.context.version < 47): self.name_padding.resize( ((16 - ((self.name_count * 4) % 16)) % 16)) stream.write_bytes(self.name_padding) if self.context.version < 47: self.name_padding.resize( ((16 - ((self.name_count * 2) % 16)) % 16)) stream.write_bytes(self.name_padding) self.inverse_bind_matrices.write(stream, Matrix44, self.bind_matrix_count, None) self.bones.write(stream, Bone, self.bone_count, None) stream.write_ubytes(self.parents) if not (self.context.version == 13): self.parents_padding.resize(((8 - (self.parents_count % 8)) % 8)) stream.write_bytes(self.parents_padding) if not (self.context.version == 13) and self.one: stream.write_uints(self.enumeration) if self.context.version == 13 and self.one: stream.write_ubytes(self.enumeration) if self.context.version == 13: stream.write_shorts(self.zt_weirdness) if not (self.context.version < 47) and self.zeros_count: stream.write_type(self.zeros_padding) if self.context.version < 47 and self.zeros_count: stream.write_type(self.minus_padding) if self.count_7: stream.write_type(self.struct_7) if self.joint_count: stream.write_type(self.joints) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'BoneInfo [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += f'\n * name_count = {self.name_count.__repr__()}' s += f'\n * knownff = {self.knownff.__repr__()}' s += f'\n * zero_0 = {self.zero_0.__repr__()}' s += f'\n * unknown_0_c = {self.unknown_0_c.__repr__()}' s += f'\n * unk_count = {self.unk_count.__repr__()}' s += f'\n * bind_matrix_count = {self.bind_matrix_count.__repr__()}' s += f'\n * zeros = {self.zeros.__repr__()}' s += f'\n * bone_count = {self.bone_count.__repr__()}' s += f'\n * unknown_40 = {self.unknown_40.__repr__()}' s += f'\n * parents_count = {self.parents_count.__repr__()}' s += f'\n * extra_zero = {self.extra_zero.__repr__()}' s += f'\n * enum_count = {self.enum_count.__repr__()}' s += f'\n * unknown_58 = {self.unknown_58.__repr__()}' s += f'\n * one = {self.one.__repr__()}' s += f'\n * zeros_count = {self.zeros_count.__repr__()}' s += f'\n * unk_pc_count = {self.unk_pc_count.__repr__()}' s += f'\n * count_7 = {self.count_7.__repr__()}' s += f'\n * joint_count = {self.joint_count.__repr__()}' s += f'\n * unk_78_count = {self.unk_78_count.__repr__()}' s += f'\n * unk_extra = {self.unk_extra.__repr__()}' s += f'\n * unk_extra_jwe = {self.unk_extra_jwe.__repr__()}' s += f'\n * name_indices = {self.name_indices.__repr__()}' s += f'\n * name_padding = {self.name_padding.__repr__()}' s += f'\n * inverse_bind_matrices = {self.inverse_bind_matrices.__repr__()}' s += f'\n * bones = {self.bones.__repr__()}' s += f'\n * parents = {self.parents.__repr__()}' s += f'\n * parents_padding = {self.parents_padding.__repr__()}' s += f'\n * enumeration = {self.enumeration.__repr__()}' s += f'\n * zt_weirdness = {self.zt_weirdness.__repr__()}' s += f'\n * zeros_padding = {self.zeros_padding.__repr__()}' s += f'\n * minus_padding = {self.minus_padding.__repr__()}' s += f'\n * struct_7 = {self.struct_7.__repr__()}' s += f'\n * joints = {self.joints.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s
class JointData: def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # 4 self.joint_count = 0 # 0 self.unknown_1 = 0 # 0 self.unknown_2 = 0 # 0 self.unknown_3 = 0 self.joint_compound = JointCompound() self.joint_list = Array() self.unknown_list = Array() self.unknown_10 = Array() self.unknown_11 = 0 self.joint_names = ZStringBuffer() self.joint_names_padding = Array() self.joint_info_list = Array() def read(self, stream): self.io_start = stream.tell() self.joint_count = stream.read_uint() self.unknown_1 = stream.read_uint() self.unknown_2 = stream.read_uint() self.unknown_3 = stream.read_uint() self.joint_compound = stream.read_type(JointCompound) self.joint_list.read(stream, JointEntry, self.joint_count, None) self.unknown_list.read(stream, UnknownJointEntry, self.joint_count, None) self.unknown_10.read(stream, FFCounter, self.joint_count, None) self.unknown_11 = stream.read_uint() self.joint_names = stream.read_type( ZStringBuffer, (self.joint_compound.namespace_length, )) self.joint_names_padding = stream.read_bytes( ((4 - (self.joint_compound.namespace_length % 8)) % 8)) self.joint_info_list.read(stream, JointInfo, self.joint_count, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_uint(self.joint_count) stream.write_uint(self.unknown_1) stream.write_uint(self.unknown_2) stream.write_uint(self.unknown_3) stream.write_type(self.joint_compound) self.joint_list.write(stream, JointEntry, self.joint_count, None) self.unknown_list.write(stream, UnknownJointEntry, self.joint_count, None) self.unknown_10.write(stream, FFCounter, self.joint_count, None) stream.write_uint(self.unknown_11) stream.write_type(self.joint_names) stream.write_bytes(self.joint_names_padding) self.joint_info_list.write(stream, JointInfo, self.joint_count, None) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'JointData [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += f'\n * joint_count = {self.joint_count.__repr__()}' s += f'\n * unknown_1 = {self.unknown_1.__repr__()}' s += f'\n * unknown_2 = {self.unknown_2.__repr__()}' s += f'\n * unknown_3 = {self.unknown_3.__repr__()}' s += f'\n * joint_compound = {self.joint_compound.__repr__()}' s += f'\n * joint_list = {self.joint_list.__repr__()}' s += f'\n * unknown_list = {self.unknown_list.__repr__()}' s += f'\n * unknown_10 = {self.unknown_10.__repr__()}' s += f'\n * unknown_11 = {self.unknown_11.__repr__()}' s += f'\n * joint_names = {self.joint_names.__repr__()}' s += f'\n * joint_names_padding = {self.joint_names_padding.__repr__()}' s += f'\n * joint_info_list = {self.joint_info_list.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s
def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.header_types = Array() self.header_entries = Array() self.data_entries = Array() self.buffer_entries = Array() self.sized_str_entries = Array() self.fragments = Array()
class Header: """ Found at the beginning of every OVL file """ def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # 'FRES' self.fres = FixedString() # if 0x08 then 64bit, differentiates between ED and JWE, 0x08 for ED and PC self.version_flag = 0 # 0x12 = PC, 0x13 = JWE, PZ self.version = 0 # endianness?, usually zero self.bitswap = 0 # always = 1 self.seventh_byte = 1 # determines compression format (none, zlib or oodle) and apparently type of data (additional fields) self.user_version = VersionInfo() # always = 0 self.zero = 0 # length of the Names block below, including 00 bytes self.len_names = 0 # always = 0 self.zero_2 = 0 # count of external aux files, ie audio banks self.num_aux_entries = 0 # count of directories self.num_dirs = 0 # count of file mime types, aka. extensions with metadata self.num_mimes = 0 # count of files self.num_files = 0 # repeat count of files ?? self.num_files_2 = 0 # count of parts self.num_textures = 0 # number of archives self.num_archives = 0 # number of header types across all archives self.num_header_types = 0 # number of headers of all types across all archives self.num_headers = 0 # number of DataEntries across all archives self.num_datas = 0 # number of BufferEntries across all archives self.num_buffers = 0 # number of files in external OVS archive self.num_files_ovs = 0 # used in ZTUAC elephants self.ztuac_unknowns = Array() # length of archive names self.len_archive_names = 0 # another Num Files self.num_files_3 = 0 # length of the type names portion insideNames block (usually at the start), not counting 00 bytes self.len_type_names = 0 # 52 bytes zeros self.zeros_2 = Array() # Name buffer for assets and file mime types. self.names = ZStringBuffer() # Array of MimeEntry objects that represent a mime type (file extension) each. self.mimes = Array() # Array of FileEntry objects. self.files = Array() # Name buffer for archives, usually will be STATIC followed by any OVS names self.archive_names = ZStringBuffer() # Array of ArchiveEntry objects. self.archives = Array() # Array of DirEntry objects. self.dirs = Array() # Array of TextureEntry objects. self.textures = Array() # Array of AuxEntry objects. self.aux_entries = Array() # Array of UnknownEntry objects. self.unknowns = Array() # repeats by archive count self.zlibs = Array() def read(self, stream): self.io_start = stream.tell() self.fres = stream.read_type(FixedString, (4, )) self.version_flag = stream.read_byte() stream.version_flag = self.version_flag self.version = stream.read_byte() stream.version = self.version self.bitswap = stream.read_byte() self.seventh_byte = stream.read_byte() self.user_version = stream.read_type(VersionInfo) stream.user_version = self.user_version self.zero = stream.read_uint() self.len_names = stream.read_uint() self.zero_2 = stream.read_uint() self.num_aux_entries = stream.read_uint() self.num_dirs = stream.read_ushort() self.num_mimes = stream.read_ushort() self.num_files = stream.read_uint() self.num_files_2 = stream.read_uint() self.num_textures = stream.read_uint() self.num_archives = stream.read_uint() self.num_header_types = stream.read_uint() self.num_headers = stream.read_uint() self.num_datas = stream.read_uint() self.num_buffers = stream.read_uint() self.num_files_ovs = stream.read_uint() self.ztuac_unknowns.read(stream, 'Uint', 3, None) self.len_archive_names = stream.read_uint() self.num_files_3 = stream.read_uint() self.len_type_names = stream.read_uint() self.zeros_2.read(stream, 'Byte', 52, None) self.names = stream.read_type(ZStringBuffer, (self.len_names, )) self.mimes.read(stream, MimeEntry, self.num_mimes, None) self.files.read(stream, FileEntry, self.num_files, None) self.archive_names = stream.read_type(ZStringBuffer, (self.len_archive_names, )) self.archives.read(stream, ArchiveEntry, self.num_archives, None) self.dirs.read(stream, DirEntry, self.num_dirs, None) self.textures.read(stream, TextureEntry, self.num_textures, None) self.aux_entries.read(stream, AuxEntry, self.num_aux_entries, None) self.unknowns.read(stream, UnknownEntry, self.num_files_ovs, None) self.zlibs.read(stream, ZlibInfo, self.num_archives, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_type(self.fres) stream.write_byte(self.version_flag) stream.version_flag = self.version_flag stream.write_byte(self.version) stream.version = self.version stream.write_byte(self.bitswap) stream.write_byte(self.seventh_byte) stream.write_type(self.user_version) stream.user_version = self.user_version stream.write_uint(self.zero) stream.write_uint(self.len_names) stream.write_uint(self.zero_2) stream.write_uint(self.num_aux_entries) stream.write_ushort(self.num_dirs) stream.write_ushort(self.num_mimes) stream.write_uint(self.num_files) stream.write_uint(self.num_files_2) stream.write_uint(self.num_textures) stream.write_uint(self.num_archives) stream.write_uint(self.num_header_types) stream.write_uint(self.num_headers) stream.write_uint(self.num_datas) stream.write_uint(self.num_buffers) stream.write_uint(self.num_files_ovs) self.ztuac_unknowns.write(stream, 'Uint', 3, None) stream.write_uint(self.len_archive_names) stream.write_uint(self.num_files_3) stream.write_uint(self.len_type_names) self.zeros_2.write(stream, 'Byte', 52, None) stream.write_type(self.names) self.mimes.write(stream, MimeEntry, self.num_mimes, None) self.files.write(stream, FileEntry, self.num_files, None) stream.write_type(self.archive_names) self.archives.write(stream, ArchiveEntry, self.num_archives, None) self.dirs.write(stream, DirEntry, self.num_dirs, None) self.textures.write(stream, TextureEntry, self.num_textures, None) self.aux_entries.write(stream, AuxEntry, self.num_aux_entries, None) self.unknowns.write(stream, UnknownEntry, self.num_files_ovs, None) self.zlibs.write(stream, ZlibInfo, self.num_archives, None) self.io_size = stream.tell() - self.io_start def __repr__(self): s = 'Header [Size: ' + str(self.io_size) + ', Address:' + str( self.io_start) + '] ' + self.name s += '\n * fres = ' + self.fres.__repr__() s += '\n * version_flag = ' + self.version_flag.__repr__() s += '\n * version = ' + self.version.__repr__() s += '\n * bitswap = ' + self.bitswap.__repr__() s += '\n * seventh_byte = ' + self.seventh_byte.__repr__() s += '\n * user_version = ' + self.user_version.__repr__() s += '\n * zero = ' + self.zero.__repr__() s += '\n * len_names = ' + self.len_names.__repr__() s += '\n * zero_2 = ' + self.zero_2.__repr__() s += '\n * num_aux_entries = ' + self.num_aux_entries.__repr__() s += '\n * num_dirs = ' + self.num_dirs.__repr__() s += '\n * num_mimes = ' + self.num_mimes.__repr__() s += '\n * num_files = ' + self.num_files.__repr__() s += '\n * num_files_2 = ' + self.num_files_2.__repr__() s += '\n * num_textures = ' + self.num_textures.__repr__() s += '\n * num_archives = ' + self.num_archives.__repr__() s += '\n * num_header_types = ' + self.num_header_types.__repr__() s += '\n * num_headers = ' + self.num_headers.__repr__() s += '\n * num_datas = ' + self.num_datas.__repr__() s += '\n * num_buffers = ' + self.num_buffers.__repr__() s += '\n * num_files_ovs = ' + self.num_files_ovs.__repr__() s += '\n * ztuac_unknowns = ' + self.ztuac_unknowns.__repr__() s += '\n * len_archive_names = ' + self.len_archive_names.__repr__() s += '\n * num_files_3 = ' + self.num_files_3.__repr__() s += '\n * len_type_names = ' + self.len_type_names.__repr__() s += '\n * zeros_2 = ' + self.zeros_2.__repr__() s += '\n * names = ' + self.names.__repr__() s += '\n * mimes = ' + self.mimes.__repr__() s += '\n * files = ' + self.files.__repr__() s += '\n * archive_names = ' + self.archive_names.__repr__() s += '\n * archives = ' + self.archives.__repr__() s += '\n * dirs = ' + self.dirs.__repr__() s += '\n * textures = ' + self.textures.__repr__() s += '\n * aux_entries = ' + self.aux_entries.__repr__() s += '\n * unknowns = ' + self.unknowns.__repr__() s += '\n * zlibs = ' + self.zlibs.__repr__() s += '\n' return s
class CoreModelInfo: """ Used by ms2 or in Mdl2ModelInfo In load order it always defines the variable fragments for the next mdl2 The mdl2's fragment informs the first mdl2 """ def __init__(self, arg=None, template=None): self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.unk_vec_a = Vector3() self.unk_float_a = 0 self.unk_vec_b = Vector3() # scale: pack_offset / 512, also added as offset self.pack_offset = 0 # always? self.zero_a = 0 self.unk_float_b = 0 self.unknownvectors = Array() self.unk_float_0 = 0 self.unk_float_1 = 0 # PZ only self.unk_vec_a_repeat = Vector3() # PZ only self.unk_vec_b_repeat = Vector3() self.mat_count = 0 self.lod_count = 0 self.mat_1_count = 0 # count of modeldata fragments for the mdl2 this struct refers to self.model_count = 0 self.last_count = 0 self.unk_0 = 0 self.unk_1 = 0 self.pad = Array() def read(self, stream): self.io_start = stream.tell() self.unk_vec_a = stream.read_type(Vector3) self.unk_float_a = stream.read_float() self.unk_vec_b = stream.read_type(Vector3) self.pack_offset = stream.read_float() self.zero_a = stream.read_float() self.unk_float_b = stream.read_float() self.unknownvectors.read(stream, Vector3, 2, None) if (stream.user_version == 24724) and (stream.version == 19): self.unk_float_0 = stream.read_float() self.unk_float_1 = stream.read_float() if (stream.user_version == 8340) and (stream.version == 19): self.unk_vec_a_repeat = stream.read_type(Vector3) self.unk_vec_b_repeat = stream.read_type(Vector3) self.mat_count = stream.read_ushort() self.lod_count = stream.read_ushort() self.mat_1_count = stream.read_ushort() self.model_count = stream.read_ushort() self.last_count = stream.read_ushort() self.unk_0 = stream.read_uint64() self.unk_1 = stream.read_uint64() self.pad.read(stream, 'Ubyte', 6, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_type(self.unk_vec_a) stream.write_float(self.unk_float_a) stream.write_type(self.unk_vec_b) stream.write_float(self.pack_offset) stream.write_float(self.zero_a) stream.write_float(self.unk_float_b) self.unknownvectors.write(stream, Vector3, 2, None) if (stream.user_version == 24724) and (stream.version == 19): stream.write_float(self.unk_float_0) stream.write_float(self.unk_float_1) if (stream.user_version == 8340) and (stream.version == 19): stream.write_type(self.unk_vec_a_repeat) stream.write_type(self.unk_vec_b_repeat) stream.write_ushort(self.mat_count) stream.write_ushort(self.lod_count) stream.write_ushort(self.mat_1_count) stream.write_ushort(self.model_count) stream.write_ushort(self.last_count) stream.write_uint64(self.unk_0) stream.write_uint64(self.unk_1) self.pad.write(stream, 'Ubyte', 6, None) self.io_size = stream.tell() - self.io_start def __repr__(self): s = 'CoreModelInfo [Size: ' + str(self.io_size) + ', Address:' + str( self.io_start) + ']' s += '\n * unk_vec_a = ' + self.unk_vec_a.__repr__() s += '\n * unk_float_a = ' + self.unk_float_a.__repr__() s += '\n * unk_vec_b = ' + self.unk_vec_b.__repr__() s += '\n * pack_offset = ' + self.pack_offset.__repr__() s += '\n * zero_a = ' + self.zero_a.__repr__() s += '\n * unk_float_b = ' + self.unk_float_b.__repr__() s += '\n * unknownvectors = ' + self.unknownvectors.__repr__() s += '\n * unk_float_0 = ' + self.unk_float_0.__repr__() s += '\n * unk_float_1 = ' + self.unk_float_1.__repr__() s += '\n * unk_vec_a_repeat = ' + self.unk_vec_a_repeat.__repr__() s += '\n * unk_vec_b_repeat = ' + self.unk_vec_b_repeat.__repr__() s += '\n * mat_count = ' + self.mat_count.__repr__() s += '\n * lod_count = ' + self.lod_count.__repr__() s += '\n * mat_1_count = ' + self.mat_1_count.__repr__() s += '\n * model_count = ' + self.model_count.__repr__() s += '\n * last_count = ' + self.last_count.__repr__() s += '\n * unk_0 = ' + self.unk_0.__repr__() s += '\n * unk_1 = ' + self.unk_1.__repr__() s += '\n * pad = ' + self.pad.__repr__() s += '\n' return s
class MeshCollision: context = ContextReference() def __init__(self, context, arg=None, template=None): self.name = '' self._context = context self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.rotation = Matrix33(self.context, None, None) # offset of mesh self.offset = Vector3(self.context, None, None) # not floats, maybe 6 ushorts, shared among (all?) redwoods self.unk_1 = numpy.zeros((3, 2), dtype='ushort') # vertices (3 float) self.vertex_count = 0 # tris?, counts the 25s at the end self.tri_count = 0 # the smallest coordinates across all axes self.bounds_min = Vector3(self.context, None, None) # the biggest coordinates across all axes self.bounds_max = Vector3(self.context, None, None) # seemingly fixed self.ones_or_zeros = numpy.zeros((7), dtype='uint64') # seemingly fixed self.ff_or_zero = numpy.zeros((10), dtype='int') # seemingly fixed self.ff_or_zero = numpy.zeros((8), dtype='int') # verbatim self.bounds_min_repeat = Vector3(self.context, None, None) # verbatim self.bounds_max_repeat = Vector3(self.context, None, None) # seems to repeat tri_count self.tri_flags_count = 0 # counts MeshCollisionBit self.count_bits = 0 # ? self.stuff = numpy.zeros((9), dtype='ushort') # ? self.collision_bits = Array(self.context) # always 25 self.zeros = numpy.zeros((4), dtype='uint') # array of vertices self.vertices = numpy.zeros((self.vertex_count, 3), dtype='float') # triangle indices into vertex list self.triangles = numpy.zeros((self.tri_count, 3), dtype='ushort') # ? self.const = 0 # always 25 self.triangle_flags = numpy.zeros((self.tri_flags_count), dtype='uint') # might be padding! self.zero_end = 0 self.set_defaults() def set_defaults(self): self.rotation = Matrix33(self.context, None, None) self.offset = Vector3(self.context, None, None) self.unk_1 = numpy.zeros((3, 2), dtype='ushort') self.vertex_count = 0 self.tri_count = 0 self.bounds_min = Vector3(self.context, None, None) self.bounds_max = Vector3(self.context, None, None) self.ones_or_zeros = numpy.zeros((7), dtype='uint64') if self.context.version <= 32: self.ff_or_zero = numpy.zeros((10), dtype='int') if self.context.version >= 47: self.ff_or_zero = numpy.zeros((8), dtype='int') if self.context.version <= 32: self.bounds_min_repeat = Vector3(self.context, None, None) if self.context.version <= 32: self.bounds_max_repeat = Vector3(self.context, None, None) if self.context.version <= 32: self.tri_flags_count = 0 if self.context.version <= 32: self.count_bits = 0 if self.context.version <= 32: self.stuff = numpy.zeros((9), dtype='ushort') if self.context.version <= 32: self.collision_bits = Array(self.context) if self.context.version <= 32: self.zeros = numpy.zeros((4), dtype='uint') self.vertices = numpy.zeros((self.vertex_count, 3), dtype='float') self.triangles = numpy.zeros((self.tri_count, 3), dtype='ushort') if self.context.version <= 32: self.const = 0 if self.context.version <= 32 and self.const: self.triangle_flags = numpy.zeros((self.tri_flags_count), dtype='uint') self.zero_end = 0 def read(self, stream): self.io_start = stream.tell() self.rotation = stream.read_type(Matrix33, (self.context, None, None)) self.offset = stream.read_type(Vector3, (self.context, None, None)) self.unk_1 = stream.read_ushorts((3, 2)) self.vertex_count = stream.read_uint64() self.tri_count = stream.read_uint64() self.bounds_min = stream.read_type(Vector3, (self.context, None, None)) self.bounds_max = stream.read_type(Vector3, (self.context, None, None)) self.ones_or_zeros = stream.read_uint64s((7)) if self.context.version <= 32: self.ff_or_zero = stream.read_ints((10)) if self.context.version >= 47: self.ff_or_zero = stream.read_ints((8)) if self.context.version <= 32: self.bounds_min_repeat = stream.read_type( Vector3, (self.context, None, None)) self.bounds_max_repeat = stream.read_type( Vector3, (self.context, None, None)) if self.context.version <= 32: self.tri_flags_count = stream.read_uint() self.count_bits = stream.read_ushort() if self.context.version <= 32: self.stuff = stream.read_ushorts((9)) self.collision_bits.read(stream, MeshCollisionBit, self.count_bits, None) if self.context.version <= 32: self.zeros = stream.read_uints((4)) self.vertices = stream.read_floats((self.vertex_count, 3)) self.triangles = stream.read_ushorts((self.tri_count, 3)) if self.context.version <= 32: self.const = stream.read_uint() if self.context.version <= 32 and self.const: self.triangle_flags = stream.read_uints((self.tri_flags_count)) self.zero_end = stream.read_uint() self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_type(self.rotation) stream.write_type(self.offset) stream.write_ushorts(self.unk_1) stream.write_uint64(self.vertex_count) stream.write_uint64(self.tri_count) stream.write_type(self.bounds_min) stream.write_type(self.bounds_max) stream.write_uint64s(self.ones_or_zeros) if self.context.version <= 32: stream.write_ints(self.ff_or_zero) if self.context.version >= 47: stream.write_ints(self.ff_or_zero) if self.context.version <= 32: stream.write_type(self.bounds_min_repeat) stream.write_type(self.bounds_max_repeat) if self.context.version <= 32: stream.write_uint(self.tri_flags_count) stream.write_ushort(self.count_bits) if self.context.version <= 32: stream.write_ushorts(self.stuff) self.collision_bits.write(stream, MeshCollisionBit, self.count_bits, None) if self.context.version <= 32: stream.write_uints(self.zeros) stream.write_floats(self.vertices) stream.write_ushorts(self.triangles) if self.context.version <= 32: stream.write_uint(self.const) if self.context.version <= 32 and self.const: stream.write_uints(self.triangle_flags) stream.write_uint(self.zero_end) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'MeshCollision [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += f'\n * rotation = {self.rotation.__repr__()}' s += f'\n * offset = {self.offset.__repr__()}' s += f'\n * unk_1 = {self.unk_1.__repr__()}' s += f'\n * vertex_count = {self.vertex_count.__repr__()}' s += f'\n * tri_count = {self.tri_count.__repr__()}' s += f'\n * bounds_min = {self.bounds_min.__repr__()}' s += f'\n * bounds_max = {self.bounds_max.__repr__()}' s += f'\n * ones_or_zeros = {self.ones_or_zeros.__repr__()}' s += f'\n * ff_or_zero = {self.ff_or_zero.__repr__()}' s += f'\n * bounds_min_repeat = {self.bounds_min_repeat.__repr__()}' s += f'\n * bounds_max_repeat = {self.bounds_max_repeat.__repr__()}' s += f'\n * tri_flags_count = {self.tri_flags_count.__repr__()}' s += f'\n * count_bits = {self.count_bits.__repr__()}' s += f'\n * stuff = {self.stuff.__repr__()}' s += f'\n * collision_bits = {self.collision_bits.__repr__()}' s += f'\n * zeros = {self.zeros.__repr__()}' s += f'\n * vertices = {self.vertices.__repr__()}' s += f'\n * triangles = {self.triangles.__repr__()}' s += f'\n * const = {self.const.__repr__()}' s += f'\n * triangle_flags = {self.triangle_flags.__repr__()}' s += f'\n * zero_end = {self.zero_end.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s
class JointDataNasuto: def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # variable self.joint_count = 0 # 0 self.unknown_1 = 0 # 0 self.unknown_2 = 0 # 0 self.unknown_3 = 0 # usually fairly big nr, 500ish self.unknown_4 = 0 self.unknown_list = Array() # 0 self.zero = 0 # small number self.count_0 = 0 # small number self.count_1 = 0 self.joint_compound = JointCompound() self.unknown_lista = Array() self.unknown_listb = Array() self.unknown_listc = Array() # 3 self.d = 0 # 2 self.e = 0 # velo01male self.undecoded_floats = Array() # index self.indices = Array() # index or -1 self.indices_2 = Array() self.joint_names = ZStringBuffer() self.joint_names_padding = Array() self.joint_info_list = Array() def read(self, stream): self.io_start = stream.tell() self.joint_count = stream.read_uint() self.unknown_1 = stream.read_uint() self.unknown_2 = stream.read_uint() self.unknown_3 = stream.read_uint() self.unknown_4 = stream.read_uint() self.unknown_list.read(stream, NasutoJointEntry, self.joint_count, None) self.zero = stream.read_uint() self.count_0 = stream.read_uint() self.count_1 = stream.read_uint() self.joint_compound = stream.read_type(JointCompound) self.unknown_lista.read(stream, JointEntry, self.arg, None) self.unknown_listb = stream.read_uint64s((self.arg)) self.unknown_listc.read(stream, ListCEntry, self.arg, None) self.d = stream.read_ushort() self.e = stream.read_ushort() self.undecoded_floats = stream.read_floats((917)) self.indices = stream.read_uints((self.arg)) self.indices_2 = stream.read_ints((self.joint_compound.unknown_8)) self.joint_names = stream.read_type(ZStringBuffer, (self.joint_compound.namespace_length,)) self.joint_names_padding = stream.read_bytes(((8 - (self.joint_compound.namespace_length % 8)) % 8)) self.joint_info_list.read(stream, JointInfo, self.arg, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_uint(self.joint_count) stream.write_uint(self.unknown_1) stream.write_uint(self.unknown_2) stream.write_uint(self.unknown_3) stream.write_uint(self.unknown_4) self.unknown_list.write(stream, NasutoJointEntry, self.joint_count, None) stream.write_uint(self.zero) stream.write_uint(self.count_0) stream.write_uint(self.count_1) stream.write_type(self.joint_compound) self.unknown_lista.write(stream, JointEntry, self.arg, None) stream.write_uint64s(self.unknown_listb) self.unknown_listc.write(stream, ListCEntry, self.arg, None) stream.write_ushort(self.d) stream.write_ushort(self.e) stream.write_floats(self.undecoded_floats) stream.write_uints(self.indices) stream.write_ints(self.indices_2) stream.write_type(self.joint_names) stream.write_bytes(self.joint_names_padding) self.joint_info_list.write(stream, JointInfo, self.arg, None) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'JointDataNasuto [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += f'\n * joint_count = {self.joint_count.__repr__()}' s += f'\n * unknown_1 = {self.unknown_1.__repr__()}' s += f'\n * unknown_2 = {self.unknown_2.__repr__()}' s += f'\n * unknown_3 = {self.unknown_3.__repr__()}' s += f'\n * unknown_4 = {self.unknown_4.__repr__()}' s += f'\n * unknown_list = {self.unknown_list.__repr__()}' s += f'\n * zero = {self.zero.__repr__()}' s += f'\n * count_0 = {self.count_0.__repr__()}' s += f'\n * count_1 = {self.count_1.__repr__()}' s += f'\n * joint_compound = {self.joint_compound.__repr__()}' s += f'\n * unknown_lista = {self.unknown_lista.__repr__()}' s += f'\n * unknown_listb = {self.unknown_listb.__repr__()}' s += f'\n * unknown_listc = {self.unknown_listc.__repr__()}' s += f'\n * d = {self.d.__repr__()}' s += f'\n * e = {self.e.__repr__()}' s += f'\n * undecoded_floats = {self.undecoded_floats.__repr__()}' s += f'\n * indices = {self.indices.__repr__()}' s += f'\n * indices_2 = {self.indices_2.__repr__()}' s += f'\n * joint_names = {self.joint_names.__repr__()}' s += f'\n * joint_names_padding = {self.joint_names_padding.__repr__()}' s += f'\n * joint_info_list = {self.joint_info_list.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s
class ManiBlock: context = ContextReference() def __init__(self, context, arg=None, template=None): self.name = '' self._context = context self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.ref = Empty(self.context, None, None) self.indices_c_0 = numpy.zeros((), dtype='ushort') self.indices_c_0 = numpy.zeros((), dtype='uint') self.indices_c_1 = numpy.zeros((), dtype='ushort') self.indices_c_1 = numpy.zeros((), dtype='uint') self.indices_1 = numpy.zeros((), dtype='ushort') self.indices_1 = numpy.zeros((), dtype='uint') self.indices_e_2 = numpy.zeros((), dtype='ushort') self.indices_e_2 = numpy.zeros((), dtype='uint') self.p_indices_c_0 = numpy.zeros((), dtype='ubyte') self.p_indices_c_0 = numpy.zeros((), dtype='ubyte') self.p_indices_c_1 = numpy.zeros((), dtype='ubyte') self.p_indices_c_1 = numpy.zeros((), dtype='ubyte') self.p_indices_0_b = numpy.zeros((), dtype='ubyte') self.p_indices_0_c = numpy.zeros((), dtype='ubyte') # ? self.pad = PadAlign(self.context, self.ref, 4) # these are likely a scale reference or factor self.floatsa = numpy.zeros((), dtype='float') # ? self.pad_2 = SmartPadding(self.context, None, None) # likely self.frame_count = 0 self.c_1 = 0 self.e = 0 # fixed self.zeros_19 = numpy.zeros((19), dtype='uint') self.count = 0 # usually / always 420 self.four_and_twenty = 0 self.ref_2 = Empty(self.context, None, None) self.zeros = numpy.zeros((self.c_1), dtype='ubyte') # ? self.anoth_pad = SmartPadding(self.context, None, None) # these are likely a scale reference or factor self.floatsb = numpy.zeros((6), dtype='float') # ? self.unk = 0 # this seems to be vaguely related, but not always there? self.unk_for_e_2 = 0 self.repeats = Array(self.context) self.set_defaults() def set_defaults(self): self.ref = Empty(self.context, None, None) if self.context.version == 18: self.indices_c_0 = numpy.zeros((), dtype='ushort') if not (self.context.version == 18): self.indices_c_0 = numpy.zeros((), dtype='uint') if self.context.version == 18: self.indices_c_1 = numpy.zeros((), dtype='ushort') if not (self.context.version == 18): self.indices_c_1 = numpy.zeros((), dtype='uint') if self.context.version == 18: self.indices_1 = numpy.zeros((), dtype='ushort') if not (self.context.version == 18): self.indices_1 = numpy.zeros((), dtype='uint') if self.context.version == 18: self.indices_e_2 = numpy.zeros((), dtype='ushort') if not (self.context.version == 18): self.indices_e_2 = numpy.zeros((), dtype='uint') self.p_indices_c_0 = numpy.zeros((), dtype='ubyte') if self.context.version == 18: self.p_indices_c_0 = numpy.zeros((), dtype='ubyte') self.p_indices_c_1 = numpy.zeros((), dtype='ubyte') if self.context.version == 18: self.p_indices_c_1 = numpy.zeros((), dtype='ubyte') self.p_indices_0_b = numpy.zeros((), dtype='ubyte') self.p_indices_0_c = numpy.zeros((), dtype='ubyte') self.pad = PadAlign(self.context, self.ref, 4) self.floatsa = numpy.zeros((), dtype='float') self.pad_2 = SmartPadding(self.context, None, None) self.frame_count = 0 self.c_1 = 0 self.e = 0 self.zeros_19 = numpy.zeros((19), dtype='uint') self.count = 0 self.four_and_twenty = 0 self.ref_2 = Empty(self.context, None, None) self.zeros = numpy.zeros((self.c_1), dtype='ubyte') self.anoth_pad = SmartPadding(self.context, None, None) self.floatsb = numpy.zeros((6), dtype='float') self.unk = 0 if self.arg.e_2: self.unk_for_e_2 = 0 self.repeats = Array(self.context) def read(self, stream): self.io_start = stream.tell() self.ref = stream.read_type(Empty, (self.context, None, None)) if self.context.version == 18: self.indices_c_0 = stream.read_ushorts((self.arg.c_0)) if not (self.context.version == 18): self.indices_c_0 = stream.read_uints((self.arg.c_0)) if self.context.version == 18: self.indices_c_1 = stream.read_ushorts((self.arg.c_1)) if not (self.context.version == 18): self.indices_c_1 = stream.read_uints((self.arg.c_1)) if self.context.version == 18: self.indices_1 = stream.read_ushorts((self.arg.name_count)) if not (self.context.version == 18): self.indices_1 = stream.read_uints((self.arg.name_count)) if self.context.version == 18: self.indices_e_2 = stream.read_ushorts((self.arg.e_2)) if not (self.context.version == 18): self.indices_e_2 = stream.read_uints((self.arg.e_2)) self.p_indices_c_0 = stream.read_ubytes((self.arg.c_0)) if self.context.version == 18: self.p_indices_c_0 = stream.read_ubytes((self.arg.c_0)) self.p_indices_c_1 = stream.read_ubytes((self.arg.c_1)) if self.context.version == 18: self.p_indices_c_1 = stream.read_ubytes((self.arg.c_1)) self.p_indices_0_b = stream.read_ubytes( ((self.arg.p_indices_c_0_max - self.arg.p_indices_c_0_min) + 1)) self.p_indices_0_c = stream.read_ubytes( ((self.arg.p_indices_c_1_max - self.arg.p_indices_c_1_min) + 1)) self.pad = stream.read_type(PadAlign, (self.context, self.ref, 4)) self.floatsa = stream.read_floats((self.arg.frame_count, self.arg.e_2)) self.pad_2 = stream.read_type(SmartPadding, (self.context, None, None)) self.frame_count = stream.read_uint() self.c_1 = stream.read_uint() self.e = stream.read_uint() self.zeros_19 = stream.read_uints((19)) self.count = stream.read_ushort() self.four_and_twenty = stream.read_ushort() self.ref_2 = stream.read_type(Empty, (self.context, None, None)) self.zeros = stream.read_ubytes((self.c_1)) self.anoth_pad = stream.read_type(SmartPadding, (self.context, None, None)) self.floatsb = stream.read_floats((6)) self.unk = stream.read_uint() if self.arg.e_2: self.unk_for_e_2 = stream.read_uint64() self.repeats.read(stream, Repeat, self.count, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_type(self.ref) if self.context.version == 18: stream.write_ushorts(self.indices_c_0) if not (self.context.version == 18): stream.write_uints(self.indices_c_0) if self.context.version == 18: stream.write_ushorts(self.indices_c_1) if not (self.context.version == 18): stream.write_uints(self.indices_c_1) if self.context.version == 18: stream.write_ushorts(self.indices_1) if not (self.context.version == 18): stream.write_uints(self.indices_1) if self.context.version == 18: stream.write_ushorts(self.indices_e_2) if not (self.context.version == 18): stream.write_uints(self.indices_e_2) stream.write_ubytes(self.p_indices_c_0) if self.context.version == 18: stream.write_ubytes(self.p_indices_c_0) stream.write_ubytes(self.p_indices_c_1) if self.context.version == 18: stream.write_ubytes(self.p_indices_c_1) stream.write_ubytes(self.p_indices_0_b) stream.write_ubytes(self.p_indices_0_c) stream.write_type(self.pad) stream.write_floats(self.floatsa) stream.write_type(self.pad_2) stream.write_uint(self.frame_count) stream.write_uint(self.c_1) stream.write_uint(self.e) stream.write_uints(self.zeros_19) stream.write_ushort(self.count) stream.write_ushort(self.four_and_twenty) stream.write_type(self.ref_2) stream.write_ubytes(self.zeros) stream.write_type(self.anoth_pad) stream.write_floats(self.floatsb) stream.write_uint(self.unk) if self.arg.e_2: stream.write_uint64(self.unk_for_e_2) self.repeats.write(stream, Repeat, self.count, None) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'ManiBlock [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += f'\n * ref = {self.ref.__repr__()}' s += f'\n * indices_c_0 = {self.indices_c_0.__repr__()}' s += f'\n * indices_c_1 = {self.indices_c_1.__repr__()}' s += f'\n * indices_1 = {self.indices_1.__repr__()}' s += f'\n * indices_e_2 = {self.indices_e_2.__repr__()}' s += f'\n * p_indices_c_0 = {self.p_indices_c_0.__repr__()}' s += f'\n * p_indices_c_1 = {self.p_indices_c_1.__repr__()}' s += f'\n * p_indices_0_b = {self.p_indices_0_b.__repr__()}' s += f'\n * p_indices_0_c = {self.p_indices_0_c.__repr__()}' s += f'\n * pad = {self.pad.__repr__()}' s += f'\n * floatsa = {self.floatsa.__repr__()}' s += f'\n * pad_2 = {self.pad_2.__repr__()}' s += f'\n * frame_count = {self.frame_count.__repr__()}' s += f'\n * c_1 = {self.c_1.__repr__()}' s += f'\n * e = {self.e.__repr__()}' s += f'\n * zeros_19 = {self.zeros_19.__repr__()}' s += f'\n * count = {self.count.__repr__()}' s += f'\n * four_and_twenty = {self.four_and_twenty.__repr__()}' s += f'\n * ref_2 = {self.ref_2.__repr__()}' s += f'\n * zeros = {self.zeros.__repr__()}' s += f'\n * anoth_pad = {self.anoth_pad.__repr__()}' s += f'\n * floatsb = {self.floatsb.__repr__()}' s += f'\n * unk = {self.unk.__repr__()}' s += f'\n * unk_for_e_2 = {self.unk_for_e_2.__repr__()}' s += f'\n * repeats = {self.repeats.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s
def __init__(self, context, arg=None, template=None): self.name = '' self._context = context self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.rotation = Matrix33(self.context, None, None) # offset of mesh self.offset = Vector3(self.context, None, None) # not floats, maybe 6 ushorts, shared among (all?) redwoods self.unk_1 = numpy.zeros((3, 2), dtype='ushort') # vertices (3 float) self.vertex_count = 0 # tris?, counts the 25s at the end self.tri_count = 0 # the smallest coordinates across all axes self.bounds_min = Vector3(self.context, None, None) # the biggest coordinates across all axes self.bounds_max = Vector3(self.context, None, None) # seemingly fixed self.ones_or_zeros = numpy.zeros((7), dtype='uint64') # seemingly fixed self.ff_or_zero = numpy.zeros((10), dtype='int') # seemingly fixed self.ff_or_zero = numpy.zeros((8), dtype='int') # verbatim self.bounds_min_repeat = Vector3(self.context, None, None) # verbatim self.bounds_max_repeat = Vector3(self.context, None, None) # seems to repeat tri_count self.tri_flags_count = 0 # counts MeshCollisionBit self.count_bits = 0 # ? self.stuff = numpy.zeros((9), dtype='ushort') # ? self.collision_bits = Array(self.context) # always 25 self.zeros = numpy.zeros((4), dtype='uint') # array of vertices self.vertices = numpy.zeros((self.vertex_count, 3), dtype='float') # triangle indices into vertex list self.triangles = numpy.zeros((self.tri_count, 3), dtype='ushort') # ? self.const = 0 # always 25 self.triangle_flags = numpy.zeros((self.tri_flags_count), dtype='uint') # might be padding! self.zero_end = 0 self.set_defaults()
class TexInfoHeader(GenericHeader): def __init__(self, context, arg=None, template=None): self.name = '' super().__init__(context, arg, template) self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.tex_info = TexHeader(self.context, None, None) self.frag_01 = Array(self.context) self.frag_01 = Array(self.context) self.frag_11 = Header7Data1(self.context, None, None) # pad whole frag_11 struct to 320 bytes self.padding = numpy.zeros((320 - self.frag_11.io_size), dtype='ubyte') # pad whole frag_11 struct to 320 bytes self.padding = numpy.zeros((384 - self.frag_11.io_size), dtype='ubyte') self.set_defaults() def set_defaults(self): self.tex_info = TexHeader(self.context, None, None) if 17 <= self.context.version <= 18: self.frag_01 = Array(self.context) if self.context.version >= 19: self.frag_01 = Array(self.context) if self.context.version >= 19: self.frag_11 = Header7Data1(self.context, None, None) if ((not self.context.user_version.is_jwe) and (self.context.version == 20)) or (((not self.context.user_version.is_jwe) and (self.context.version >= 19)) or (self.context.user_version.is_jwe and (self.context.version == 20))): self.padding = numpy.zeros((320 - self.frag_11.io_size), dtype='ubyte') if self.context.user_version.is_jwe and (self.context.version == 19): self.padding = numpy.zeros((384 - self.frag_11.io_size), dtype='ubyte') def read(self, stream): self.io_start = stream.tell() super().read(stream) self.tex_info = stream.read_type(TexHeader, (self.context, None, None)) if 17 <= self.context.version <= 18: self.frag_01.read(stream, TexBufferPc, self.tex_info.stream_count, None) if self.context.version >= 19: self.frag_01.read(stream, TexBuffer, self.tex_info.stream_count, None) self.frag_11 = stream.read_type(Header7Data1, (self.context, None, None)) if ((not self.context.user_version.is_jwe) and (self.context.version == 20)) or (((not self.context.user_version.is_jwe) and (self.context.version >= 19)) or (self.context.user_version.is_jwe and (self.context.version == 20))): self.padding = stream.read_ubytes((320 - self.frag_11.io_size)) if self.context.user_version.is_jwe and (self.context.version == 19): self.padding = stream.read_ubytes((384 - self.frag_11.io_size)) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() super().write(stream) stream.write_type(self.tex_info) if 17 <= self.context.version <= 18: self.frag_01.write(stream, TexBufferPc, self.tex_info.stream_count, None) if self.context.version >= 19: self.frag_01.write(stream, TexBuffer, self.tex_info.stream_count, None) stream.write_type(self.frag_11) if ((not self.context.user_version.is_jwe) and (self.context.version == 20)) or (((not self.context.user_version.is_jwe) and (self.context.version >= 19)) or (self.context.user_version.is_jwe and (self.context.version == 20))): stream.write_ubytes(self.padding) if self.context.user_version.is_jwe and (self.context.version == 19): stream.write_ubytes(self.padding) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'TexInfoHeader [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += super().get_fields_str() s += f'\n * tex_info = {self.tex_info.__repr__()}' s += f'\n * frag_01 = {self.frag_01.__repr__()}' s += f'\n * frag_11 = {self.frag_11.__repr__()}' s += f'\n * padding = {self.padding.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s
def set_defaults(self): self.weird_padding = SmartPadding(self.context, None, None) self.unks = Array(self.context)
def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # 'FRES' self.fres = FixedString() # if 0x08 then 64bit, differentiates between ED and JWE, 0x08 for ED and PC self.version_flag = 0 # 0x12 = PC, 0x13 = JWE, PZ self.version = 0 # endianness?, usually zero self.bitswap = 0 # always = 1 self.seventh_byte = 1 # determines compression format (none, zlib or oodle) and apparently type of data (additional fields) self.user_version = VersionInfo() # always = 0 self.zero = 0 # length of the Names block below, including 00 bytes self.len_names = 0 # always = 0 self.zero_2 = 0 # count of external aux files, ie audio banks self.num_aux_entries = 0 # count of directories self.num_dirs = 0 # count of file mime types, aka. extensions with metadata self.num_mimes = 0 # count of files self.num_files = 0 # repeat count of files ?? self.num_files_2 = 0 # count of parts self.num_textures = 0 # number of archives self.num_archives = 0 # number of header types across all archives self.num_header_types = 0 # number of headers of all types across all archives self.num_headers = 0 # number of DataEntries across all archives self.num_datas = 0 # number of BufferEntries across all archives self.num_buffers = 0 # number of files in external OVS archive self.num_files_ovs = 0 # used in ZTUAC elephants self.ztuac_unknowns = Array() # length of archive names self.len_archive_names = 0 # another Num Files self.num_files_3 = 0 # length of the type names portion insideNames block (usually at the start), not counting 00 bytes self.len_type_names = 0 # 52 bytes zeros self.zeros_2 = Array() # Name buffer for assets and file mime types. self.names = ZStringBuffer() # Array of MimeEntry objects that represent a mime type (file extension) each. self.mimes = Array() # Array of FileEntry objects. self.files = Array() # Name buffer for archives, usually will be STATIC followed by any OVS names self.archive_names = ZStringBuffer() # Array of ArchiveEntry objects. self.archives = Array() # Array of DirEntry objects. self.dirs = Array() # Array of TextureEntry objects. self.textures = Array() # Array of AuxEntry objects. self.aux_entries = Array() # Array of UnknownEntry objects. self.unknowns = Array() # repeats by archive count self.zlibs = Array()
def __init__(self, context, arg=None, template=None): self.name = '' self._context = context self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # counts the names self.name_count = 0 # this is always FFFF for now self.knownff = 0 # this is always 0000 for now self.zero_0 = 0 self.unknown_0_c = 0 # almost always 4, 1 for male african lion self.unk_count = 0 # seems to match bone count self.bind_matrix_count = 0 self.zeros = numpy.zeros((3), dtype='uint64') self.bone_count = 0 self.unknown_40 = 0 self.parents_count = 0 # not PC, JWE1 self.extra_zero = 0 self.enum_count = 0 # usually zero self.unknown_58 = 0 # always 1 self.one = 0 # this counts the weird padding at the end, usually == bone count, 0 in PZ aardvark self.zeros_count = 0 # matches the other count on dino entertainer, but count7 is not present self.unk_pc_count = 0 # index count 7 self.count_7 = 0 # joint count self.joint_count = 0 # zero self.unk_78_count = 0 # zero self.unk_extra = 0 # zero self.unk_extra_jwe = 0 # index into ms2 string table for bones used here self.name_indices = numpy.zeros((self.name_count), dtype='uint') # index into ms2 string table for bones used here self.name_indices = numpy.zeros((self.name_count), dtype='ushort') # zeros. One index occupies 4 bytes; pad to multiples of 16 bytes. self.name_padding = numpy.zeros( ((16 - ((self.name_count * 4) % 16)) % 16), dtype='byte') # zeros. One index occupies 4 bytes; pad to multiples of 16 bytes. self.name_padding = numpy.zeros( ((16 - ((self.name_count * 2) % 16)) % 16), dtype='byte') # used for skinning self.inverse_bind_matrices = Array(self.context) self.bones = Array(self.context) # 255 = root, index in this list is the current bone index, value is the bone's parent index self.parents = numpy.zeros((self.parents_count), dtype='ubyte') # zeros self.parents_padding = numpy.zeros( ((8 - (self.parents_count % 8)) % 8), dtype='byte') # enumerates all bone indices, 4 may be flags self.enumeration = numpy.zeros((self.enum_count, 2), dtype='uint') # enumerates all bone indices, 4 may be flags self.enumeration = numpy.zeros((self.enum_count), dtype='ubyte') # zeros self.zt_weirdness = numpy.zeros((10), dtype='short') # weird zeros self.zeros_padding = ZerosPadding(self.context, self.zeros_count, None) # weird -1s self.minus_padding = MinusPadding(self.context, self.zeros_count, None) # ragdoll links? self.struct_7 = Struct7(self.context, None, None) # joints self.joints = JointData(self.context, None, None) self.set_defaults()
def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 # variable self.joint_count = 0 # 0 self.unknown_1 = 0 # 0 self.unknown_2 = 0 # 0 self.unknown_3 = 0 # usually fairly big nr, 500ish self.unknown_4 = 0 self.unknown_list = Array() # 0 self.zero = 0 # small number self.count_0 = 0 # small number self.count_1 = 0 self.joint_compound = JointCompound() self.unknown_lista = Array() self.unknown_listb = Array() self.unknown_listc = Array() # 3 self.d = 0 # 2 self.e = 0 # velo01male self.undecoded_floats = Array() # index self.indices = Array() # index or -1 self.indices_2 = Array() self.joint_names = ZStringBuffer() self.joint_names_padding = Array() self.joint_info_list = Array()
class OvsHeader: """ Description of one archive's content """ def __init__(self, arg=None, template=None): self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.header_types = Array() self.header_entries = Array() self.data_entries = Array() self.buffer_entries = Array() self.sized_str_entries = Array() self.fragments = Array() def read(self, stream): self.io_start = stream.tell() self.header_types = [ stream.read_type(HeaderType) for _ in range(self.arg.num_header_types) ] num_headers = sum(header_type.num_headers for header_type in self.header_types) self.header_entries = [ stream.read_type(HeaderEntry) for _ in range(num_headers) ] self.data_entries = [ stream.read_type(DataEntry) for _ in range(self.arg.num_datas) ] self.buffer_entries = [ stream.read_type(BufferEntry) for _ in range(self.arg.num_buffers) ] self.sized_str_entries = [ stream.read_type(SizedStringEntry) for _ in range(self.arg.num_files) ] self.fragments = [ stream.read_type(Fragment) for _ in range(self.arg.num_fragments) ] self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() for item in self.header_types: stream.write_type(item) for item in self.header_entries: stream.write_type(item) for item in self.data_entries: stream.write_type(item) for item in self.buffer_entries: stream.write_type(item) for item in self.sized_str_entries: stream.write_type(item) for item in self.fragments: stream.write_type(item) self.io_size = stream.tell() - self.io_start def __repr__(self): s = 'OvsHeader [Size: ' + str(self.io_size) + ', Address:' + str( self.io_start) + ']' s += '\n * header_types = ' + self.header_types.__repr__() s += '\n * header_entries = ' + self.header_entries.__repr__() s += '\n * data_entries = ' + self.data_entries.__repr__() s += '\n * buffer_entries = ' + self.buffer_entries.__repr__() s += '\n * sized_str_entries = ' + self.sized_str_entries.__repr__() s += '\n * fragments = ' + self.fragments.__repr__() s += '\n' return s
class SetHeader: """ defines amount of sets and assets (not a struct in barbasol) """ def __init__(self, arg=None, template=None): self.name = '' self.arg = arg self.template = template self.io_size = 0 self.io_start = 0 self.set_count = 0 self.asset_count = 0 # must be 1065336831 self.sig_a = 1065336831 # must be 16909320 self.sig_b = 16909320 self.sets = Array() self.assets = Array() def read(self, stream): self.io_start = stream.tell() self.set_count = stream.read_uint() self.asset_count = stream.read_uint() self.sig_a = stream.read_uint() self.sig_b = stream.read_uint() self.sets.read(stream, SetEntry, self.set_count, None) self.assets.read(stream, AssetEntry, self.asset_count, None) self.io_size = stream.tell() - self.io_start def write(self, stream): self.io_start = stream.tell() stream.write_uint(self.set_count) stream.write_uint(self.asset_count) stream.write_uint(self.sig_a) stream.write_uint(self.sig_b) self.sets.write(stream, SetEntry, self.set_count, None) self.assets.write(stream, AssetEntry, self.asset_count, None) self.io_size = stream.tell() - self.io_start def get_info_str(self): return f'SetHeader [Size: {self.io_size}, Address: {self.io_start}] {self.name}' def get_fields_str(self): s = '' s += f'\n * set_count = {self.set_count.__repr__()}' s += f'\n * asset_count = {self.asset_count.__repr__()}' s += f'\n * sig_a = {self.sig_a.__repr__()}' s += f'\n * sig_b = {self.sig_b.__repr__()}' s += f'\n * sets = {self.sets.__repr__()}' s += f'\n * assets = {self.assets.__repr__()}' return s def __repr__(self): s = self.get_info_str() s += self.get_fields_str() s += '\n' return s