def apply(self, apply: Callable[[], None], rom: NintendoDSRom, config: Pmd2Data): if not self.is_applied(rom, config): path_len = len(LIST_PATH%0)+1 if path_len%4!=0: path_len += 4-(path_len%4) if config.game_version == GAME_VERSION_EOS: if config.game_region == GAME_REGION_US: table = ITEM_LISTS_TABLE_US if config.game_region == GAME_REGION_EU: table = ITEM_LISTS_TABLE_EU ranges = [] for i in range(ITEM_LISTS_NB): start = read_uintle(rom.arm9, table+i*4, 4)-ARM9_START end = start size = 0 while size<ITEM_LISTS_SIZE: val = read_uintle(rom.arm9, end, 2) if val>=30000: size += (val-30000)*2 else: size += 2 end += 2 data = rom.arm9[start:end] if end%4!=0: end += 4-(end%4) path = LIST_PATH%i if path not in rom.filenames: create_file_in_rom(rom, path, data) else: rom.setFileByName(path, data) rom.arm9 = rom.arm9[:start]+bytes([0xCC]*(end-start))+rom.arm9[end:] ranges.append([start, end]) ranges.sort() i = 0 while i<len(ranges)-1: if ranges[i][1]==ranges[i+1][0]: ranges[i][1] = ranges[i+1][1] del ranges[i+1] i-=1 i+=1 buffer = bytearray(4*ITEM_LISTS_NB) for i in range(ITEM_LISTS_NB): path = LIST_PATH%i while ranges[0][1]-ranges[0][0]<path_len: del ranges[0] if len(ranges)==0: raise RuntimeError("Don't have enough space to put filenames! ") rom.arm9 = rom.arm9[:ranges[0][0]]+path.encode(encoding="ascii")+bytes(path_len-len(path))+rom.arm9[ranges[0][0]+path_len:] write_uintle(buffer, ARM9_START+ranges[0][0], i*4, 4) ranges[0][0] += path_len rom.arm9 = rom.arm9[:table]+buffer+rom.arm9[table+len(buffer):] try: apply() except RuntimeError as ex: raise ex
def set_binary_in_rom_ppmdu(rom: NintendoDSRom, binary: 'Pmd2Binary', data: bytes): """Sets the correct binary in the rom, using the binary block specifications.""" parts = binary.filepath.split('/') if parts[0] == 'arm9.bin': rom.arm9 = bytes(data) return if parts[0] == 'arm7.bin': rom.arm7 = bytes(data) return if parts[0] == 'overlay': if len(parts) > 1: r = re.compile(r'overlay_(\d+).bin', re.IGNORECASE) match = r.match(parts[1]) if match is not None: ov_id = int(match.group(1)) overlays = rom.loadArm9Overlays([ov_id]) if len(overlays) > 0: rom.files[overlays[ov_id].fileID] = data return raise ValueError(f"Binary {binary.filepath} not found.")
def apply(self, apply: Callable[[], None], rom: NintendoDSRom, config: Pmd2Data): if not self.is_applied(rom, config): if config.game_version == GAME_VERSION_EOS: if config.game_region == GAME_REGION_US: rank_table = FLOOR_RANKS_TABLE_US item_table = ITEM_AVAILABLE_TABLE_US forbid_table = FLOOR_FORBID_TABLE_US if config.game_region == GAME_REGION_EU: rank_table = FLOOR_RANKS_TABLE_EU item_table = ITEM_AVAILABLE_TABLE_EU forbid_table = FLOOR_FORBID_TABLE_EU header = bytearray(NB_ITEMS_TABLE*4) rank_data = bytearray(0) forbid_data = bytearray(0) current_ptr = len(header) for i in range(NB_ITEMS_TABLE): start = read_uintle(rom.arm9, rank_table+i*4, 4)-ARM9_START end = start+1+FLOORS_NB[i] if end%4!=0: end += 4-(end%4) rdata = rom.arm9[start:end] fdata = bytearray(len(rdata)) x = forbid_table while rom.arm9[x]!=0x64: if rom.arm9[x]==i: fdata[rom.arm9[x+1]] = 1 x += 2 rom.arm9 = rom.arm9[:start]+bytes([0xCC]*(end-start))+rom.arm9[end:] write_uintle(header, current_ptr, i*4, 4) rank_data += bytearray(rdata) forbid_data += bytearray(fdata) current_ptr += end-start file_data = header + rank_data if FLOOR_RANKS_PATH not in rom.filenames: create_file_in_rom(rom, FLOOR_RANKS_PATH, file_data) else: rom.setFileByName(FLOOR_RANKS_PATH, file_data) file_data = header + forbid_data if FLOOR_FORBID_PATH not in rom.filenames: create_file_in_rom(rom, FLOOR_FORBID_PATH, file_data) else: rom.setFileByName(FLOOR_FORBID_PATH, file_data) dungeon_list = HardcodedDungeons.get_dungeon_list(rom.arm9, config) groups = [d.mappa_index for d in dungeon_list] print(hex(len(groups))) list_available = [] for x in range(AVAILABLE_ITEMS_NB): list_available.append(bytearray(0x100//8)) for i, g in enumerate(groups): off = item_table + g * (AVAILABLE_ITEMS_NB//8) + (x//8) if rom.arm9[off]&(1<<(x%8)): list_available[-1][i//8] |= 1<<(i%8) file_data = bytearray().join(list_available) if AVAILABLE_ITEMS_PATH not in rom.filenames: create_file_in_rom(rom, AVAILABLE_ITEMS_PATH, file_data) else: rom.setFileByName(AVAILABLE_ITEMS_PATH, file_data) try: apply() except RuntimeError as ex: raise ex