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_minimap(self, rom: LocalRom, addr): rom.write_sbyte(addr, self.icon) rom.write_byte(addr + 1, self.count) cur = 2 for p in self.points: p.write_to_minimap(rom, addr + cur) cur += 0x03
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 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
def patch_mesh(self, rom: LocalRom, mesh: CollisionMesh): start = self.file.start final_cams = [] # build final camera data for cam in self.coldelta.cams: data = cam['Data'] pos = cam['PositionIndex'] if pos < 0: final_cams.append((data, 0)) else: addr = start + (mesh.camera_data_addr & 0xFFFFFF) seg_off = rom.read_int32(addr + (pos * 8) + 4) final_cams.append((data, seg_off)) types_move_addr = 0 # if data can't fit within the old mesh space, append camera data if self.coldelta.is_larger: types_move_addr = mesh.camera_data_addr # append to end of file self.write_cam_data(rom, self.file.end, final_cams) mesh.camera_data_addr = get_segment_address( 2, self.file.end - self.file.start) self.file.end += len(final_cams) * 8 else: types_move_addr = mesh.camera_data_addr + (len(final_cams) * 8) # append in place addr = self.file.start + (mesh.camera_data_addr & 0xFFFFFF) self.write_cam_data(rom, addr, final_cams) # if polytypes needs to be moved, do so if (types_move_addr != mesh.polytypes_addr): a_start = self.file.start + (mesh.polytypes_addr & 0xFFFFFF) b_start = self.file.start + (types_move_addr & 0xFFFFFF) size = mesh.polytypes * 8 rom.buffer[b_start:b_start + size] = rom.buffer[a_start:a_start + size] mesh.polytypes_addr = types_move_addr # patch polytypes for item in self.coldelta.polytypes: id = item['Id'] high = item['High'] low = item['Low'] addr = self.file.start + (mesh.polytypes_addr & 0xFFFFFF) + (id * 8) rom.write_int32s(addr, [high, low]) # patch poly data for item in self.coldelta.polys: id = item['Id'] t = item['Type'] flags = item['Flags'] addr = self.file.start + (mesh.poly_addr & 0xFFFFFF) + (id * 0x10) vert_bit = rom.read_byte(addr + 0x02) & 0x1F # VertexA id data rom.write_int16(addr, t) rom.write_byte(addr + 0x02, (flags << 5) + vert_bit) # Write Mesh to Scene mesh.write_to_scene(rom, self.file.start)
def write_to_minimap(self, rom: LocalRom, addr): rom.write_sbyte(addr, self.flag) rom.write_byte(addr + 1, self.x) rom.write_byte(addr + 2, self.y)