def write_brk(self, f): f.write(BRKFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size write_uint32(f, 1) # Always a section count of 1 f.write(b"SVR1" + b"\xFF"*12) trk1_start = f.tell() f.write(b"TRK1") trk1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for trk1 size write_uint8(f, self.loop_mode) write_uint8(f, 0xFF) write_uint16(f, self.duration) write_uint16(f, len(self.register_animations)) write_uint16(f, len(self.constant_animations)) count_offset = f.tell() f.write(b"AB"*8) # Placeholder for register and constant rgba counts data_offsets = f.tell() f.write(b"ABCD"*6) # Placeholder for data offsets f.write(b"ABCD"*8) # Placeholder for rgba data offsets write_padding(f, multiple=32) assert f.tell() == 0x80 register_anim_start = f.tell() f.write(b"\x00"*(0x1C*len(self.register_animations))) write_padding(f, multiple=4) constant_anim_start = f.tell() f.write(b"\x00"*(0x1C*len(self.constant_animations))) write_padding(f, multiple=4) all_values = {} for animtype, animations in ( ("register", self.register_animations), ("constant", self.constant_animations)): all_values[animtype] = {} for colorcomp in ("R", "G", "B", "A"): all_values[animtype][colorcomp] = [] for anim in animations: animation_components = anim.component[colorcomp] """ use_tantype_1 = False for comp in animation_components: if comp.tangentIn != comp.tangentOut: use_tantype_1 = True break if not use_tantype_1: anim._set_tangent_type(colorcomp, 0)""" # Set up offset for scale if len(animation_components) == 1: sequence = [ int(animation_components[0].value) ] else: sequence = [] for comp in animation_components: sequence.append(comp.time) sequence.append(comp.value) sequence.append( int(comp.tangentIn) ) if self.tan_type == 1 : sequence.append( int(comp.tangentOut) ) offset = j3d.find_sequence(all_values[animtype][colorcomp],sequence) if offset == -1: offset = len(all_values[animtype][colorcomp]) all_values[animtype][colorcomp].extend(sequence) anim._set_component_offsets(colorcomp, offset) data_starts = [] for animtype in ("register", "constant"): for comp in ("R", "G", "B", "A"): data_starts.append(f.tell()) for val in all_values[animtype][comp]: write_sint16(f, val) write_padding(f, 4) # Write the indices for each animation register_index_start = f.tell() for i in range(len(self.register_animations)): write_uint16(f, i) write_padding(f, multiple=4) constant_index_start = f.tell() for i in range(len(self.constant_animations)): write_uint16(f, i) write_padding(f, multiple=4) # Create string table of material names for register color animations register_stringtable = j3d.StringTable() for anim in self.register_animations: register_stringtable.strings.append(anim.name) # Create string table of material names for constant color animations constant_stringtable = j3d.StringTable() for anim in self.constant_animations: constant_stringtable.strings.append(anim.name) register_stringtable_start = f.tell() register_stringtable.write(f, register_stringtable.strings) write_padding(f, multiple=4) constant_stringtable_start = f.tell() constant_stringtable.write(f, constant_stringtable.strings) write_padding(f, multiple=4) write_padding(f, multiple=32) total_size = f.tell() f.seek(register_anim_start) for anim in self.register_animations: for comp in ("R", "G", "B", "A"): write_uint16(f, len(anim.component[comp])) # Scale count for this animation write_uint16(f, anim._component_offsets[comp]) # Offset into scales write_uint16(f, self.tan_type) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut write_uint8(f, anim.unknown) f.write(b"\xFF\xFF\xFF") f.seek(constant_anim_start) for anim in self.constant_animations: for comp in ("R", "G", "B", "A"): write_uint16(f, len(anim.component[comp])) # Scale count for this animation write_uint16(f, anim._component_offsets[comp]) # Offset into scales write_uint16(f, self.tan_type) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut write_uint8(f, anim.unknown) f.write(b"\xFF\xFF\xFF") # Fill in all the placeholder values f.seek(filesize_offset) write_uint32(f, total_size) f.seek(trk1_size_offset) write_uint32(f, total_size - trk1_start) f.seek(count_offset) for animtype in ("register", "constant"): for comp in ("R", "G", "B", "A"): write_uint16(f, len(all_values[animtype][comp])) # Next come the section offsets write_uint32(f, register_anim_start - trk1_start) write_uint32(f, constant_anim_start - trk1_start) write_uint32(f, register_index_start - trk1_start) write_uint32(f, constant_index_start - trk1_start) write_uint32(f, register_stringtable_start - trk1_start) write_uint32(f, constant_stringtable_start - trk1_start) # RGBA data starts for data_start in data_starts: write_uint32(f, data_start - trk1_start)
def write_bva(self, f): f.write(BVAFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size write_uint32(f, 1) # Always a section count of 1 f.write(b"\xFF" * 16) vaf1_start = f.tell() f.write(b"VAF1") vaf1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for vaf1 size write_uint8(f, self.loop_mode) write_uint8(f, 0xFF) write_uint16(f, self.duration) write_uint16(f, len(self.animations)) count_offset = f.tell() f.write(b"AB" * 1) # Placeholder for table count data_offsets = f.tell() f.write(b"ABCD" * 2) # Placeholder for data offsets write_padding(f, multiple=32) assert f.tell() == 0x40 # now, time for the visiblity animations to be written as placeholders anim_start = f.tell() f.write(b"\x00" * (0x4 * len(self.animations))) write_padding(f, multiple=4) table_offset = f.tell() # write the table all_frames = [] for anim in self.animations: print(anim.frames) offset = j3d.find_sequence(all_frames, anim.frames) if offset == -1: offset = len(all_frames) all_frames.extend(anim.frames) anim._set_offset(offset) for val in all_frames: j3d.write_uint8(f, int(val)) j3d.write_padding(f, 4) write_padding(f, multiple=32) total_size = f.tell() f.seek(anim_start) for anim in self.animations: write_uint16(f, len(anim.frames)) write_uint16(f, anim._offset) # Fill in all the placeholder values f.seek(count_offset) write_uint16(f, len(all_frames)) f.seek(filesize_offset) write_uint32(f, total_size) f.seek(vaf1_size_offset) write_uint32(f, total_size - vaf1_start) f.seek(data_offsets) write_uint32(f, anim_start - vaf1_start) write_uint32(f, table_offset - vaf1_start)
def write_bpk(self, f): f.write(BPKFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size write_uint32(f, 1) # Always a section count of 1 f.write(b"SVR1" + b"\xFF" * 12) pak1_start = f.tell() f.write(b"PAK1") pak1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for pak1 size write_uint8(f, self.loop_mode) write_uint8(f, 0xFF) write_uint8(f, 0xFF) write_uint8(f, 0xFF) write_uint16(f, self.duration) write_uint16(f, len(self.animations)) count_offset = f.tell() f.write(b"AB" * 4) # Placeholder for register and constant rgba counts data_offsets = f.tell() f.write(b"ABCD" * 3) # Placeholder for data offsets f.write(b"ABCD" * 4) # Placeholder for rgba data offsets write_padding(f, multiple=32) assert f.tell() == 0x60 anim_start = f.tell() f.write(b"\x00" * (0x18 * len(self.animations))) write_padding(f, multiple=4) all_values = {} for colorcomp in ("R", "G", "B", "A"): all_values[colorcomp] = [] for anim in self.animations: animation_components = anim.component[colorcomp] # Set up offset for scale if len(animation_components) == 1: sequence = [int(animation_components[0].value)] else: sequence = [] for comp in animation_components: sequence.append(comp.time) sequence.append(comp.value) sequence.append(int(comp.tangentIn)) if self.tan_type == 1: sequence.append(int(comp.tangentOut)) offset = j3d.find_sequence(all_values[colorcomp], sequence) if offset == -1: offset = len(all_values[colorcomp]) all_values[colorcomp].extend(sequence) anim._set_component_offsets(colorcomp, offset) data_starts = [] for comp in ("R", "G", "B", "A"): data_starts.append(f.tell()) for val in all_values[comp]: write_sint16(f, val) write_padding(f, 4) # Write the indices for each animation index_start = f.tell() for i in range(len(self.animations)): write_uint16(f, i) write_padding(f, multiple=4) # Create string table of material names for register color animations stringtable = j3d.StringTable() for anim in self.animations: stringtable.strings.append(anim.name) stringtable_start = f.tell() stringtable.write(f, stringtable.strings) write_padding(f, multiple=4) write_padding(f, multiple=32) total_size = f.tell() f.seek(anim_start) for anim in self.animations: for comp in ("R", "G", "B", "A"): write_uint16(f, len( anim.component[comp])) # Scale count for this animation write_uint16( f, anim._component_offsets[comp]) # Offset into scales write_uint16( f, self.tan_type ) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut # Fill in all the placeholder values f.seek(filesize_offset) write_uint32(f, total_size) f.seek(pak1_size_offset) write_uint32(f, total_size - pak1_start) f.seek(count_offset) for comp in ("R", "G", "B", "A"): write_uint16(f, len(all_values[comp])) # Next come the section offsets write_uint32(f, anim_start - pak1_start) write_uint32(f, index_start - pak1_start) write_uint32(f, stringtable_start - pak1_start) # RGBA data starts for data_start in data_starts: write_uint32(f, data_start - pak1_start)
def write_bla(self, f): f.write(BLAFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size j3d.write_uint32(f, 1) # Always a section count of 1 f.write(b"\xFF" * 16) clf1_start = f.tell() f.write(b"CLF1") clf1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for clf1 size j3d.write_uint8(f, self.loop_mode) j3d.write_sint8(f, self.anglescale) j3d.write_uint16(f, self.duration) #0x30 count_offset = f.tell() f.write(b"toad") # Placeholder for cluster and scale counts data_offsets = f.tell() f.write(b"toadette") #placeholder for offsets write_padding(f, multiple=32) cluster_anim_start = f.tell() f.write(b"\x00" * (0x4 * len(self.animations))) #placeholder for stuff write_padding(f, multiple=32) all_scales = [] for anim in self.animations: if len(anim.seq) == 1: sequence = [anim.seq[0].value] else: sequence = [] for comp in anim.seq: sequence.append(comp.value) offset = j3d.find_sequence(all_scales, sequence) if offset == -1: offset = len(all_scales) all_scales.extend(sequence) anim.scale_offset = offset scale_start = f.tell() for val in all_scales: write_float(f, val) j3d.write_padding(f, 32) total_size = f.tell() f.seek(cluster_anim_start) for anim in self.animations: j3d.write_uint16(f, len(anim.seq)) # Scale count for this animation j3d.write_uint16(f, anim.scale_offset) # Fill in all the placeholder values f.seek(filesize_offset) j3d.write_uint32(f, total_size) f.seek(clf1_size_offset) j3d.write_uint32(f, total_size - clf1_start) f.seek(count_offset) j3d.write_uint16(f, 1) j3d.write_uint16(f, len(all_scales)) # Next come the section offsets j3d.write_uint32(f, cluster_anim_start - clf1_start) j3d.write_uint32(f, scale_start - clf1_start)
def write_bck(self, f): f.write(BCKFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size j3d.write_uint32(f, 1) # Always a section count of 1 f.write(b"\xFF"*16) ank1_start = f.tell() f.write(b"ANK1") ttk1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for ttk1 size j3d.write_uint8(f, self.loop_mode) j3d.write_sint8(f, self.anglescale) rotscale = (2.0**self.anglescale)*(180.0 / 32768.0) j3d.write_uint16(f, self.duration) j3d.write_uint16(f, len( self.animations )) #0x30 count_offset = f.tell() f.write(b"1+1=11") # Placeholder for scale, rotation and translation count data_offsets = f.tell() f.write(b"toadettebestgirl") #placeholder for offsets write_padding(f, multiple=32) bone_anim_start = f.tell() f.write(b"\x00"*(0x36*len(self.animations))) #placeholder for stuff write_padding(f, multiple=32) all_scales = [] all_rotations = [] all_translations = [] for anim in self.animations: for axis in "XYZ": # Set up offset for scale if len(anim.scale[axis]) == 1: sequence = [anim.scale[axis][0].value] else: sequence = [] for comp in anim.scale[axis]: sequence.append(comp.time) sequence.append(comp.value) sequence.append(comp.tangentIn) if self.tan_type == 1 : sequence.append(comp.tangentOut) offset = j3d.find_sequence(all_scales,sequence) if offset == -1: offset = len(all_scales) all_scales.extend(sequence) anim._set_scale_offsets(axis, offset) # Set up offset for rotation if len(anim.rotation[axis]) == 1: comp = anim.rotation[axis][0] #angle = ((comp.value+180) % 360) - 180 sequence = [comp.value/rotscale] #print("seq", sequence) else: sequence = [] for comp in anim.rotation[axis]: #angle = ((comp.value+180) % 360) - 180 sequence.append(comp.time) sequence.append(comp.value/rotscale) sequence.append(comp.tangentIn/rotscale) if self.tan_type == 1 : sequence.append(comp.tangentOut/rotscale) #print("seq", sequence) offset = j3d.find_sequence(all_rotations, sequence) if offset == -1: offset = len(all_rotations) all_rotations.extend(sequence) anim._set_rot_offsets(axis, offset) # Set up offset for translation if len(anim.translation[axis]) == 1: sequence = [anim.translation[axis][0].value] else: sequence = [] for comp in anim.translation[axis]: sequence.append(comp.time) sequence.append(comp.value) sequence.append(comp.tangentIn) if self.tan_type == 1 : sequence.append(comp.tangentOut) offset = j3d.find_sequence(all_translations, sequence) if offset == -1: offset = len(all_translations) all_translations.extend(sequence) anim._set_translation_offsets(axis, offset) scale_start = f.tell() for val in all_scales: write_float(f, val) j3d.write_padding(f, 32) rotations_start = f.tell() for val in all_rotations: val = int(val) if val <= -32767: val = -32767 elif val > 32767: val = 32767 #try: j3d.write_sint16(f, val ) """except: print(val)""" j3d.write_padding(f, 32) translations_start = f.tell() for val in all_translations: #print(val) write_float(f, val) j3d.write_padding(f, 32) total_size = f.tell() f.seek(bone_anim_start) for anim in self.animations: for axis in "XYZ": j3d.write_uint16(f, len(anim.scale[axis])) # Scale count for this animation j3d.write_uint16(f, anim._scale_offsets[axis]) # Offset into scales j3d.write_uint16(f, self.tan_type) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut j3d.write_uint16(f, len(anim.rotation[axis])) # Rotation count for this animation j3d.write_uint16(f, anim._rot_offsets[axis]) # Offset into rotations j3d.write_uint16(f, self.tan_type) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut j3d.write_uint16(f, len(anim.translation[axis])) # Translation count for this animation j3d.write_uint16(f, anim._translation_offsets[axis])# offset into translations j3d.write_uint16(f, self.tan_type) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut # Fill in all the placeholder values f.seek(filesize_offset) j3d.write_uint32(f, total_size) f.seek(ttk1_size_offset) j3d.write_uint32(f, total_size - ank1_start) f.seek(count_offset) j3d.write_uint16(f, len(all_scales)) j3d.write_uint16(f, len(all_rotations)) j3d.write_uint16(f, len(all_translations)) # Next come the section offsets j3d.write_uint32(f, bone_anim_start - ank1_start) j3d.write_uint32(f, scale_start - ank1_start) j3d.write_uint32(f, rotations_start - ank1_start) j3d.write_uint32(f, translations_start - ank1_start)
def write_btk(self, f): f.write(BTKFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size j3d.write_uint32(f, 1) # Always a section count of 1 f.write(b"SVR1" + b"\xFF" * 12) ttk1_start = f.tell() f.write(b"TTK1") ttk1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for ttk1 size j3d.write_uint8(f, self.loop_mode) j3d.write_sint8(f, self.anglescale) rotscale = (2.0**self.anglescale) * (180.0 / 32768.0) j3d.write_uint16(f, self.duration) j3d.write_uint16(f, len(self.animations) * 3) # Three times the matrix animations count_offset = f.tell() f.write( b"1+1=11") # Placeholder for scale, rotation and translation count data_offsets = f.tell() f.write(b"--OnceUponATimeInALandFarAway---") f.write(b"\x00" * (0x7C - f.tell())) j3d.write_uint32(f, self.unknown_address) matrix_anim_start = f.tell() f.write(b"\x00" * (0x36 * len(self.animations))) write_padding(f, multiple=4) index_start = f.tell() for i in range(len(self.animations)): j3d.write_uint16(f, i) j3d.write_padding(f, multiple=4) stringtable = j3d.StringTable() for anim in self.animations: stringtable.strings.append(anim.name) stringtable_start = f.tell() stringtable.write(f, stringtable.strings) j3d.write_padding(f, multiple=4) matindex_start = f.tell() for anim in self.animations: j3d.write_uint8(f, anim.matindex) j3d.write_padding(f, multiple=4) center_start = f.tell() for anim in self.animations: for val in anim.center: write_float(f, val) j3d.write_padding(f, multiple=4) all_scales = [] all_rotations = [] all_translations = [] for anim in self.animations: for axis in "UVW": # Set up offset for scale if len(anim.scale[axis]) == 1: sequence = [anim.scale[axis][0].value] else: sequence = [] for comp in anim.scale[axis]: sequence.append(comp.time) sequence.append(comp.value) sequence.append(comp.tangentIn) if self.tan_type == 1: sequence.append(comp.tangentOut) offset = j3d.find_sequence(all_scales, sequence) if offset == -1: offset = len(all_scales) all_scales.extend(sequence) anim._set_scale_offsets(axis, offset) # Set up offset for rotation if len(anim.rotation[axis]) == 1: comp = anim.rotation[axis][0] #angle = ((comp.value+180) % 360) - 180 sequence = [comp.value / rotscale] #print("seq", sequence) else: sequence = [] for comp in anim.rotation[axis]: #angle = ((comp.value+180) % 360) - 180 sequence.append(comp.time) sequence.append(comp.value / rotscale) sequence.append(comp.tangentIn / rotscale) if self.tan_type == 1: sequence.append(comp.tangentOut / rotscale) #print("seq", sequence) offset = j3d.find_sequence(all_rotations, sequence) if offset == -1: offset = len(all_rotations) all_rotations.extend(sequence) anim._set_rot_offsets(axis, offset) """for comp in anim.rotation[axis]: all_rotations.append(comp.frame) all_rotations.append(comp.value/rotscale) all_rotations.append(comp.tangentIn/rotscale) all_rotations.append(comp.tangentOut/rotscale) """ # Set up offset for translation if len(anim.translation[axis]) == 1: sequence = [anim.translation[axis][0].value] else: sequence = [] for comp in anim.translation[axis]: sequence.append(comp.time) sequence.append(comp.value) sequence.append(comp.tangentIn) if self.tan_type == 1: sequence.append(comp.tangentOut) offset = j3d.find_sequence(all_translations, sequence) if offset == -1: offset = len(all_translations) all_translations.extend(sequence) anim._set_translation_offsets(axis, offset) """offset = len(all_translations) for comp in anim.translation[axis]: all_translations.append(comp.frame) all_translations.append(comp.value) all_translations.append(comp.tangentIn) all_translations.append(comp.tangentOut)""" scale_start = f.tell() for val in all_scales: write_float(f, val) j3d.write_padding(f, 4) rotations_start = f.tell() for val in all_rotations: val = int(val) if val <= -32767: val = -32767 elif val > 32767: val = 32767 """angle = ((val+180) % 360) - 180 # Force the angle between -180 and 180 degrees print(val, "becomes", angle) if angle >= 0: angle = (angle/180.0)*(2**15-1) else: angle = (angle/180.0)*(2**15)""" j3d.write_sint16(f, int(val)) j3d.write_padding(f, 4) translations_start = f.tell() for val in all_translations: #print(val) write_float(f, val) j3d.write_padding(f, 32) total_size = f.tell() f.seek(matrix_anim_start) for anim in self.animations: for axis in "UVW": j3d.write_uint16(f, len( anim.scale[axis])) # Scale count for this animation j3d.write_uint16( f, anim._scale_offsets[axis]) # Offset into scales j3d.write_uint16( f, self.tan_type ) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut j3d.write_uint16(f, len( anim.rotation[axis])) # Rotation count for this animation j3d.write_uint16( f, anim._rot_offsets[axis]) # Offset into rotations j3d.write_uint16( f, self.tan_type ) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut j3d.write_uint16(f, len(anim.translation[axis]) ) # Translation count for this animation j3d.write_uint16(f, anim._translation_offsets[axis] ) # offset into translations j3d.write_uint16( f, self.tan_type ) # Tangent type, 0 = only TangentIn; 1 = TangentIn and TangentOut # Fill in all the placeholder values f.seek(filesize_offset) j3d.write_uint32(f, total_size) f.seek(ttk1_size_offset) j3d.write_uint32(f, total_size - ttk1_start) f.seek(count_offset) j3d.write_uint16(f, len(all_scales)) j3d.write_uint16(f, len(all_rotations)) j3d.write_uint16(f, len(all_translations)) # Next come the section offsets j3d.write_uint32(f, matrix_anim_start - ttk1_start) j3d.write_uint32(f, index_start - ttk1_start) j3d.write_uint32(f, stringtable_start - ttk1_start) j3d.write_uint32(f, matindex_start - ttk1_start) j3d.write_uint32(f, center_start - ttk1_start) j3d.write_uint32(f, scale_start - ttk1_start) j3d.write_uint32(f, rotations_start - ttk1_start) j3d.write_uint32(f, translations_start - ttk1_start)
def write_btp(self, f): #header info f.write(j3d.BTPFILEMAGIC) filesize_offset = f.tell() f.write(b"ABCD") # Placeholder for file size j3d.write_uint32(f, 1) # Always a section count of 1 f.write(b"\xFF"*16) tpt1_start = f.tell() f.write(b"TPT1") tpt1_size_offset = f.tell() f.write(b"EFGH") # Placeholder for tpt1 size j3d.write_uint8(f, self.flag) j3d.write_uint8(f, self.anglescale) j3d.write_uint16(f, self.largest_duration) j3d.write_uint16(f, len(self.animations) ) j3d.write_uint16(f, self.unknown_address) tables_offset = f.tell(); f.write(b"toadettebestgril") facial_animation_entries_os = f.tell() f.write(b"\x00"*(0x8*len(self.animations))) #placeholder for stuff """ total_frames = 0; for i in range( len (btp.animations) ): j3d.write_uint16(f, len ( btp.animations[i].frames )) j3d.write_uint16(f, total_frames) total_frames += len (btp.animations[i].frames ) j3d.write_uint16(f, 0x00FF) j3d.write_uint16(f, 0xFFFF) """ j3d.write_padding(f, 4) texture_index_bank_os = f.tell() all_frames = [] for anim in self.animations: offset = j3d.find_sequence( all_frames, anim.frames ) if offset == -1: offset = len(all_frames) all_frames.extend(anim.frames) anim._set_offset(offset) for val in all_frames: j3d.write_uint16(f, int(val) ) j3d.write_padding(f, 4) """ for i in range( len (btp.animations) ): for j in btp.animations[i].frames: j = int(j) j3d.write_uint16(f, j) """ remap_table_os = f.tell() j3d.write_uint32(f, 0x00000001) stringtable_os = f.tell() strings = self.get_children_names() j3d.StringTable.write(f, strings) j3d.write_padding(f, 32) total_size = f.tell() f.seek(filesize_offset) j3d.write_uint32(f, total_size) f.seek(tpt1_size_offset) j3d.write_uint32(f, total_size - tpt1_start) f.seek(facial_animation_entries_os); for anim in self.animations: j3d.write_uint16(f, len ( anim.frames )) j3d.write_uint16(f, anim._offset) j3d.write_uint16(f, 0x00FF) j3d.write_uint16(f, 0xFFFF) f.seek(tables_offset) j3d.write_uint32(f, facial_animation_entries_os - tpt1_start) j3d.write_uint32(f, texture_index_bank_os - tpt1_start) j3d.write_uint32(f, remap_table_os - tpt1_start) j3d.write_uint32(f, stringtable_os - tpt1_start)