def write_data(self, rom: LocalRom): # move file to remap address self.file.relocate(rom) headcur = self.file.start code = rom.read_byte(headcur) loop = 0x20 while loop != 0 and code != 0x14: #terminator loop -= 1 if code == 0x01: # actors offset = self.file.end - self.file.start write_actor_data(rom, self.file.end, self.actors) self.file.end += len(self.actors) * 0x10 rom.write_byte(headcur + 1, len(self.actors)) rom.write_int32(headcur + 4, get_segment_address(3, offset)) elif code == 0x0B: # objects offset = self.append_object_data(rom, self.objects) rom.write_byte(headcur + 1, len(self.objects)) rom.write_int32(headcur + 4, get_segment_address(3, offset)) headcur += 8 code = rom.read_byte(headcur) # update file reference self.file.end = align16(self.file.end) update_dmadata(rom, self.file)
def write_to_floormap(self, rom: LocalRom, addr): rom.write_int16(addr, self.icon) rom.write_int32(addr + 0x10, self.count) cur = 0x14 for p in self.points: p.write_to_floormap(rom, addr + cur) cur += 0x0C
def patch_spirit_temple_mq_room_6(rom: LocalRom, room_addr): cur = room_addr actor_list_addr = 0 cmd_actors_offset = 0 # scan for actor list and header end code = rom.read_byte(cur) while code != 0x14: #terminator if code == 0x01: # actors actor_list_addr = rom.read_int32(cur + 4) cmd_actors_offset = cur - room_addr cur += 8 code = rom.read_byte(cur) cur += 8 # original header size header_size = cur - room_addr # set alternate header data location alt_data_off = header_size + 8 # set new alternate header offset alt_header_off = align16(alt_data_off + (4 * 3)) # alt header record size * num records # write alternate header data # the first 3 words are mandatory. the last 3 are just to make the binary # cleaner to read rom.write_int32s(room_addr + alt_data_off, [0, get_segment_address(3, alt_header_off), 0, 0, 0, 0]) # clone header a_start = room_addr a_end = a_start + header_size b_start = room_addr + alt_header_off b_end = b_start + header_size rom.buffer[b_start:b_end] = rom.buffer[a_start:a_end] # make the child header skip the first actor, # which avoids the spawning of the block while in the hole cmd_addr = room_addr + cmd_actors_offset actor_list_addr += 0x10 actors = rom.read_byte(cmd_addr + 1) rom.write_byte(cmd_addr + 1, actors - 1) rom.write_int32(cmd_addr + 4, actor_list_addr) # move header rom.buffer[a_start + 8:a_end + 8] = rom.buffer[a_start:a_end] # write alternate header command seg = get_segment_address(3, alt_data_off) rom.write_int32s(room_addr, [0x18000000, seg])
def write_data(self, rom: LocalRom): # write floormap and minimap data self.write_map_data(rom) # move file to remap address self.file.relocate(rom) start = self.file.start headcur = self.file.start room_list_offset = 0 code = rom.read_byte(headcur) loop = 0x20 while loop > 0 and code != 0x14: #terminator loop -= 1 if code == 0x03: #collision col_mesh_offset = rom.read_int24(headcur + 5) col_mesh = CollisionMesh(rom, start, col_mesh_offset) self.patch_mesh(rom, col_mesh) elif code == 0x04: #rooms room_list_offset = rom.read_int24(headcur + 5) elif code == 0x0D: #paths path_offset = self.append_path_data(rom) rom.write_int32(headcur + 4, path_offset) elif code == 0x0E: #transition actors t_offset = rom.read_int24(headcur + 5) addr = self.file.start + t_offset write_actor_data(rom, addr, self.transition_actors) headcur += 8 code = rom.read_byte(headcur) # update file references self.file.end = align16(self.file.end) update_dmadata(rom, self.file) update_scene_table(rom, self.id, self.file.start, self.file.end) # write room file data for room in self.rooms: room.write_data(rom) if self.id == 6 and room.id == 6: patch_spirit_temple_mq_room_6(rom, room.file.start) cur = self.file.start + room_list_offset for room in self.rooms: rom.write_int32s(cur, [room.file.start, room.file.end]) cur += 0x08
def append_path_data(self, rom: LocalRom): start = self.file.start cur = self.file.end records = [] for path in self.paths: nodes = len(path) offset = get_segment_address(2, cur - start) records.append((nodes, offset)) #flatten points = [x for points in path for x in points] rom.write_int16s(cur, points) path_size = align4(len(path) * 6) cur += path_size records_offset = get_segment_address(2, cur - start) for node, offset in records: rom.write_byte(cur, node) rom.write_int32(cur + 4, offset) cur += 8 self.file.end = cur return records_offset