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
Example #2
0
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