Exemplo n.º 1
0
 def _set_generic(ov11: bytes, config: Pmd2Data, block_name: str,
                  bytelen: int, value: List[int]):
     block = config.binaries['overlay/overlay_0011.bin'].blocks[block_name]
     expected_length = int((block.end - block.begin) / bytelen)
     if len(value) != expected_length:
         raise ValueError(
             f"The list must have exactly the length of {expected_length} entries."
         )
     for i, entry in enumerate(value):
         write_uintle(ov11, entry, block.begin + i * bytelen, bytelen)
Exemplo n.º 2
0
 def to_mappa(self):
     data = bytearray(8)
     write_uintle(data, self.level * LEVEL_MULTIPLIER, 0x00, 2)
     write_uintle(data, self.weight, 0x02, 2)
     write_uintle(data, self.weight2, 0x04, 2)
     write_uintle(data, self.md_index, 0x06, 2)
     return data
Exemplo n.º 3
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(ENTRY_LEN)
     write_uintle(buffer, self.rank_name_str, 0x00, 4)
     write_uintle(buffer, self.points_needed_next, 0x04, 4)
     write_uintle(buffer, self.storage_capacity, 0x08, 4)
     write_uintle(buffer, self.item_awarded, 0x0C, 4)
     return buffer
Exemplo n.º 4
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(8)
     write_uintle(buffer, self.item_id, 0, 4)
     write_uintle(buffer, self.null1, 2, 2)
     write_uintle(buffer, self.null2, 4, 2)
     write_uintle(buffer, self.null3, 6, 2)
     return buffer
Exemplo n.º 5
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(4)
     write_uintle(buffer, self.trap_id, 0, 1)
     write_uintle(buffer, self.trap_data, 1, 1)
     write_uintle(buffer, self.room_id, 2, 1)
     write_uintle(buffer, self.flags, 3, 1)
     return buffer
 def set_player_md_ids(value: List[int], overlay13: bytearray,
                       config: Pmd2Data) -> None:
     """
     Sets the monster.md indices of the player partner choices (in place, total index, with gender form!)
     The length of the list must exactly match the original ROM's length (see get_player_md_ids).
     """
     block = config.binaries['overlay/overlay_0013.bin'].blocks[
         'StartersHeroIds']
     expected_length = int((block.end - block.begin) / 2)
     if len(value) != expected_length:
         raise ValueError(
             f"The ID list must have exactly the length of {expected_length} entries."
         )
     for i, v in enumerate(value):
         write_uintle(overlay13, v, block.begin + (i * 2), 2)
Exemplo n.º 7
0
def corrupt341():
    """Corrupt 341: Dungeon tiles Beach cave 2? -- No? Tiles -> Chunk mappings or similar?"""
    img341 = dungeon_bin[341].decompress()
    img341new = bytearray(img341)

    # Decode XOR
    #XOR_ROW_LEN = 7200#18 * 7
    #rows_decoded = []
    #row_before = bytes(XOR_ROW_LEN)
    #for chunk in iter_bytes(img341, XOR_ROW_LEN):
    #    xored = bytearray(a ^ b for (a, b) in zip(chunk, row_before))
    #    row_before = xored
    #    rows_decoded.append(xored)

    dummy_map = [
        TilemapEntry(10, False, False, 0),
        TilemapEntry(10, True, False, 0),
        TilemapEntry(10, False, True, 0),
        TilemapEntry(5, False, False, 0),
        TilemapEntry(5, True, False, 0),
        TilemapEntry(5, False, True, 0),
        TilemapEntry(10, False, False, 6),
        TilemapEntry(10, True, False, 6),
        TilemapEntry(10, False, True, 6)
    ]

    for j in range(1, 300):
        for i, m in enumerate(dummy_map):
            write_uintle(img341new, m.to_int(), (j * 18) + 2 * i, 2)

    all_tilemaps = []
    for bytes2 in iter_bytes(img341new, 2):
        all_tilemaps.append(TilemapEntry.from_int(read_uintle(bytes2, 0, 2)))

    # Encode XOR
    #rows_encoded = []
    #row_before = bytes(XOR_ROW_LEN)
    #for row in rows_decoded:
    #    xored = bytes(a ^ b for (a, b) in zip(row, row_before))
    #    row_before = row
    #    rows_encoded.append(xored)
    #img341new = bytes(itertools.chain.from_iterable(rows_encoded))
    #assert img341 == img341new

    with open('/tmp/corrupt.bin', 'wb') as f:
        f.write(img341new)
    dungeon_bin[341] = FileType.AT4PX.compress(img341new)
Exemplo n.º 8
0
    def _wrap_sir0(self, full_binary: bytes, table_data: bytes, entry_len: int,
                   string_offs_per_entry: List[int], write_subheader) -> bytes:
        table_data = bytearray(table_data)
        out_data = bytearray()
        pointer_offsets = []

        # 1. Write strings
        number_entries = 0
        for i in range(0, len(table_data), entry_len):
            for string_off in string_offs_per_entry:
                new_pointer = self._push_string(
                    full_binary, out_data,
                    read_uintle(table_data, i + string_off, 4) -
                    self._binary.loadaddress)
                pointer_offsets.append(i + string_off)
                write_uintle(table_data, new_pointer, i + string_off, 4)
            number_entries += 1
        # Padding
        self._pad(out_data)

        # 2. Correct string pointer offsets
        pointer_offsets = [off + len(out_data) for off in pointer_offsets]

        # 3. Append table
        pointer_data_block = len(out_data)
        out_data += table_data
        # Padding
        self._pad(out_data)

        # 4. Write sub-header
        if write_subheader:
            data_pointer = len(out_data)
            pointer_offsets.append(len(out_data))
            out_data += pointer_data_block.to_bytes(4,
                                                    byteorder='little',
                                                    signed=False)
            out_data += number_entries.to_bytes(4,
                                                byteorder='little',
                                                signed=False)
        else:
            data_pointer = pointer_data_block

        # 5. Convert into SIR0
        return FileType.SIR0.serialize(
            FileType.SIR0.wrap(out_data, pointer_offsets, data_pointer))
Exemplo n.º 9
0
    def sir0_serialize_parts(self) -> Tuple[bytes, List[int], Optional[int]]:
        string_codec.init()

        out_data = bytearray()
        # 1. Write strings
        pointer_offsets: List[int] = []
        for entry in self.list:
            pointer_offsets.append(len(out_data))
            out_data += bytes(entry.name,
                              string_codec.PMD2_STR_ENCODER) + b'\0'

        # Padding
        self._pad(out_data)

        # Write table
        sir0_pointer_offsets = []
        pointer_data_block = len(out_data)
        for i, entry in enumerate(self.list):
            entry_buffer = bytearray(LEN_ACTOR_ENTRY)
            write_uintle(entry_buffer, entry.type, 0, 2)
            write_uintle(entry_buffer, entry.entid, 2, 2)
            sir0_pointer_offsets.append(len(out_data) + 4)
            write_uintle(entry_buffer, pointer_offsets[i], 4, 4)
            write_uintle(entry_buffer, entry.unk3, 8, 2)
            write_uintle(entry_buffer, entry.unk4, 10, 2)
            out_data += entry_buffer

        # Padding
        self._pad(out_data)

        # 4. Write sub-header
        data_pointer = len(out_data)
        sir0_pointer_offsets.append(len(out_data))
        out_data += pointer_data_block.to_bytes(4,
                                                byteorder='little',
                                                signed=False)
        out_data += len(self.list).to_bytes(4,
                                            byteorder='little',
                                            signed=False)

        return out_data, sir0_pointer_offsets, data_pointer
Exemplo n.º 10
0
 def to_bytes(self) -> bytes:
     bitfield0 = generate_bitfield(
         (self.dont_save_before_entering, self.leader_can_be_changed,
          self.money_allowed, self.level_reset, self.recruiting_allowed,
          self.enemies_grant_exp, self.enemies_evolve_when_team_member_koed,
          bool(self.direction.value)))
     bitfield1 = generate_bitfield(
         (False, False, False, False, False, self.enemies_can_drop_chests,
          self.traps_remain_invisible_on_attack, self.iq_skills_disabled))
     bitfield2 = 0
     bitfield3 = 0
     buff = bytearray(DUNGEON_RESTRICTIONS_ENTRY_LEN)
     write_uintle(buff, bitfield0, 0, 1)
     write_uintle(buff, bitfield1, 1, 1)
     write_uintle(buff, bitfield2, 2, 1)
     write_uintle(buff, bitfield3, 3, 1)
     write_sintle(buff, self.max_rescue_attempts, 4, 1)
     write_sintle(buff, self.max_items_allowed, 5, 1)
     write_sintle(buff, self.max_party_members, 6, 1)
     write_sintle(buff, self.null7, 7, 1)
     write_sintle(buff, self.turn_limit, 8, 2)
     write_sintle(buff, self.nullA, 10, 1)
     write_sintle(buff, self.nullB, 11, 1)
     return buff
Exemplo n.º 11
0
 def set_player_md_id(value: int, arm9: bytearray, config: Pmd2Data):
     """
     Sets the monster.md index of the default player starter
     """
     block = config.binaries['arm9.bin'].blocks['DefaultHeroId']
     write_uintle(arm9, value, block.begin, 2)
Exemplo n.º 12
0
def main():
    os.makedirs(output_dir, exist_ok=True)

    rom = NintendoDSRom.fromFile(os.path.join(base_dir,
                                              'skyworkcopy_edit.nds'))

    bin_before = rom.getFileByName('SCRIPT/G01P01A/enter.sse')
    ssa_before = SsaHandler.deserialize(bin_before)
    data = Pmd2XmlReader.load_default()
    scriptdata = data.script_data

    ssa_before.layer_list[0].objects = [
        # TODO: 5=Width, 1=Height!
        SsaObject(
            scriptdata, 6, 5, 1,
            SsaPosition(scriptdata, 44, 24, 0, 0,
                        scriptdata.directions__by_name['Down'].id), 10, -1)
    ]

    # Write NPC types
    npc_table_start = data.binaries['arm9.bin'].blocks['Entities'].begin
    NPC_TABLE_ENTRY_LEN = 0x0c
    # uint16: type, uint16: entid, uint32: pointer to name, unk3, unk4

    # Shaymin NPC_SHEIMI 534 / V02P06A
    ent_id__shaymin = scriptdata.level_entities__by_name['NPC_SHEIMI'].id
    print(
        read_uintle(
            rom.arm9,
            npc_table_start + ent_id__shaymin * NPC_TABLE_ENTRY_LEN + 0x02, 2))
    write_uintle(
        rom.arm9, 534,
        npc_table_start + ent_id__shaymin * NPC_TABLE_ENTRY_LEN + 0x02, 2)
    # Elekid NPC_SHEIMI1 266 / V02P07A
    ent_id__elekid = scriptdata.level_entities__by_name['NPC_SHEIMI1'].id
    print(
        read_uintle(
            rom.arm9,
            npc_table_start + ent_id__elekid * NPC_TABLE_ENTRY_LEN + 0x02, 2))
    write_uintle(rom.arm9, 266,
                 npc_table_start + ent_id__elekid * NPC_TABLE_ENTRY_LEN + 0x02,
                 2)
    # Piplup NPC_SHEIMI2 428 / V03P01A
    ent_id__piplup = scriptdata.level_entities__by_name['NPC_SHEIMI2'].id
    print(
        read_uintle(
            rom.arm9,
            npc_table_start + ent_id__piplup * NPC_TABLE_ENTRY_LEN + 0x02, 2))
    write_uintle(rom.arm9, 428,
                 npc_table_start + ent_id__piplup * NPC_TABLE_ENTRY_LEN + 0x02,
                 2)
    # Meowth NPC_SHEIMI3 52 / V03P02A
    ent_id__meowth = scriptdata.level_entities__by_name['NPC_SHEIMI3'].id
    print(
        read_uintle(
            rom.arm9,
            npc_table_start + ent_id__meowth * NPC_TABLE_ENTRY_LEN + 0x02, 2))
    write_uintle(rom.arm9, 52,
                 npc_table_start + ent_id__meowth * NPC_TABLE_ENTRY_LEN + 0x02,
                 2)
    # Buneary NPC_SHEIMI4 469 / V03P03A
    ent_id__buneary = scriptdata.level_entities__by_name['NPC_SHEIMI4'].id
    print(
        read_uintle(
            rom.arm9,
            npc_table_start + ent_id__buneary * NPC_TABLE_ENTRY_LEN + 0x02, 2))
    write_uintle(
        rom.arm9, 469,
        npc_table_start + ent_id__buneary * NPC_TABLE_ENTRY_LEN + 0x02, 2)

    ssa_before.layer_list[0].actors = [
        SsaActor(
            scriptdata, ent_id__shaymin,
            SsaPosition(scriptdata, 14, 24, 2, 0,
                        scriptdata.directions__by_name['Down'].id), 5, -1),
        SsaActor(
            scriptdata, ent_id__elekid,
            SsaPosition(scriptdata, 20, 24, 2, 0,
                        scriptdata.directions__by_name['Down'].id), 6, -1),
        SsaActor(
            scriptdata, ent_id__piplup,
            SsaPosition(scriptdata, 26, 24, 2, 0,
                        scriptdata.directions__by_name['Down'].id), 7, -1),
        SsaActor(
            scriptdata, ent_id__meowth,
            SsaPosition(scriptdata, 32, 24, 2, 0,
                        scriptdata.directions__by_name['Down'].id), 8, -1),
        SsaActor(
            scriptdata, ent_id__buneary,
            SsaPosition(scriptdata, 38, 24, 2, 0,
                        scriptdata.directions__by_name['Down'].id), 9, -1),
        # Mimikyu NPC_PUKURIN 40 / V03P04A
        # Litten NPC_ZUBATTO 41 / V04P02A
        # Zorua NPC_DIGUDA 50  / V03P13A
    ]
    ssa_before.layer_list[0].events = [
        SsaEvent(6, 2, 1, 0, SsaPosition(scriptdata, 27, 0, 0, 0, None),
                 65535),
        SsaEvent(6, 2, 2, 0, SsaPosition(scriptdata, 27, 49, 0, 0, None),
                 65535),
    ]

    # Exit Guild
    ssa_before.layer_list[1].actors = [
        SsaActor(
            scriptdata, 0,
            SsaPosition(scriptdata, 29, 7, 2, 0,
                        scriptdata.directions__by_name['Down'].id), -1, -1),
        SsaActor(
            scriptdata, 10,
            SsaPosition(scriptdata, 29, 4, 2, 0,
                        scriptdata.directions__by_name['Down'].id), -1, -1)
    ]

    # Exit Town
    ssa_before.layer_list[2].actors = [
        SsaActor(
            scriptdata, 0,
            SsaPosition(scriptdata, 29, 44, 2, 0,
                        scriptdata.directions__by_name['Up'].id), -1, -1),
        SsaActor(
            scriptdata, 10,
            SsaPosition(scriptdata, 29, 47, 2, 0,
                        scriptdata.directions__by_name['Up'].id), -1, -1)
    ]

    # Create scripts, if don't exist
    tpl_ssb = rom.getFileByName('SCRIPT/G01P01A/enter01.ssb')
    try:
        rom.getFileByName('SCRIPT/G01P01A/enter05.ssb')
    except ValueError:
        create_file_in_rom(rom, 'SCRIPT/G01P01A/enter05.ssb', tpl_ssb)
    try:
        rom.getFileByName('SCRIPT/G01P01A/enter06.ssb')
    except ValueError:
        create_file_in_rom(rom, 'SCRIPT/G01P01A/enter06.ssb', tpl_ssb)
    try:
        rom.getFileByName('SCRIPT/G01P01A/enter07.ssb')
    except ValueError:
        create_file_in_rom(rom, 'SCRIPT/G01P01A/enter07.ssb', tpl_ssb)
    try:
        rom.getFileByName('SCRIPT/G01P01A/enter08.ssb')
    except ValueError:
        create_file_in_rom(rom, 'SCRIPT/G01P01A/enter08.ssb', tpl_ssb)
    try:
        rom.getFileByName('SCRIPT/G01P01A/enter09.ssb')
    except ValueError:
        create_file_in_rom(rom, 'SCRIPT/G01P01A/enter09.ssb', tpl_ssb)
    try:
        rom.getFileByName('SCRIPT/G01P01A/enter10.ssb')
    except ValueError:
        create_file_in_rom(rom, 'SCRIPT/G01P01A/enter10.ssb', tpl_ssb)

    bin_after = SsaHandler.serialize(ssa_before)
    rom.setFileByName('SCRIPT/G01P01A/enter.sse', bin_after)
    rom.saveToFile(os.path.join(base_dir, 'skyworkcopy_edit.nds'))

    draw_maps_main()
Exemplo n.º 13
0
 def to_bytes(self):
     buffer = bytearray(2 * len(self.mappings))
     for i, m in enumerate(self.mappings):
         write_uintle(buffer, m, i * 2, 2)
     return buffer
Exemplo n.º 14
0
 def to_mappa(self):
     data = bytearray(50)
     for i in range(0, 25):
         write_uintle(data, self.weights[MappaTrapType(i)], i * 2, 2)
     return data
Exemplo n.º 15
0
    def to_mappa(self) -> bytes:
        data = bytearray(32)
        write_uintle(data, self.structure.value, 0x00, 1)
        write_uintle(data, self.room_density, 0x01, 1)
        write_uintle(data, self.tileset_id, 0x02, 1)
        write_uintle(data, self.music_id, 0x03, 1)
        write_uintle(data, self.weather.value, 0x04, 1)
        write_uintle(data, self.floor_connectivity, 0x05, 1)
        write_uintle(data, self.initial_enemy_density, 0x06, 1)
        write_uintle(data, self.kecleon_shop_chance, 0x07, 1)
        write_uintle(data, self.monster_house_chance, 0x08, 1)
        write_uintle(data, self.unusued_chance, 0x09, 1)
        write_uintle(data, self.sticky_item_chance, 0x0A, 1)
        write_uintle(data, self.dead_ends, 0x0B, 1)
        write_uintle(data, self.secondary_terrain.value, 0x0C, 1)
        write_uintle(data, self.terrain_settings.to_mappa(), 0x0D, 1)
        write_uintle(data, self.unk_e, 0x0E, 1)
        write_uintle(data, self.item_density, 0x0F, 1)
        write_uintle(data, self.trap_density, 0x10, 1)
        write_uintle(data, self.floor_number, 0x11, 1)
        write_uintle(data, self.fixed_floor_id, 0x12, 1)
        write_uintle(data, self.extra_hallway_density, 0x13, 1)
        write_uintle(data, self.buried_item_density, 0x14, 1)
        write_uintle(data, self.water_density, 0x15, 1)
        write_uintle(data, self.darkness_level.value, 0x16, 1)
        write_uintle(data, int(self.max_coin_amount / 5), 0x17, 1)
        write_uintle(data, self.kecleon_shop_item_positions, 0x18, 1)
        write_uintle(data, self.empty_monster_house_chance, 0x19, 1)
        write_uintle(data, self.unk_hidden_stairs, 0x1A, 1)
        write_uintle(data, self.hidden_stairs_spawn_chance, 0x1B, 1)
        write_uintle(data, self.enemy_iq, 0x1C, 2)
        write_uintle(data, self.iq_booster_enabled, 0x1E, 1)

        return data
Exemplo n.º 16
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(4)
     write_uintle(buffer, self.md_idx, 0, 2)
     write_uintle(buffer, self.stats_entry, 2, 1)
     write_uintle(buffer, self.enemy_settings.value, 3, 1)
     return buffer
Exemplo n.º 17
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(12)
     write_uintle(buffer, self.item_id * 8 + self._overlay29bin.blocks['ItemSpawnTable'].begin_absolute, 0, 4)
     write_uintle(buffer, self.monster_id * 4 + self._overlay29bin.blocks['MonsterSpawnTable'].begin_absolute, 4, 4)
     write_uintle(buffer, self.tile_id * 4 + self._overlay29bin.blocks['TileSpawnTable'].begin_absolute, 8, 4)
     return buffer
Exemplo n.º 18
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(12)
     write_uintle(buffer, self.music_track, 0, 4)
     write_uintle(buffer, self.unk4, 4, 1)
     write_uintle(buffer, self.unk5, 5, 1)
     write_uintle(buffer, self.moves_enabled, 6, 1)
     write_uintle(buffer, self.orbs_enabled, 7, 1)
     write_uintle(buffer, self.unk8, 8, 1)
     write_uintle(buffer, self.unk9, 9, 1)
     write_uintle(buffer, self.exit_floor_when_defeating_enemies, 10, 1)
     write_uintle(buffer, self.null, 11, 1)
     return buffer
Exemplo n.º 19
0
 def to_bytes(self) -> bytes:
     buffer = bytearray(12)
     write_uintle(buffer, self.level, 0, 2)
     write_uintle(buffer, self.hp, 2, 2)
     write_uintle(buffer, self.exp_yield, 4, 2)
     write_uintle(buffer, self.attack, 6, 1)
     write_uintle(buffer, self.special_attack, 7, 1)
     write_uintle(buffer, self.defense, 8, 1)
     write_uintle(buffer, self.special_defense, 9, 1)
     write_uintle(buffer, self.unkA, 10, 2)
     return buffer
Exemplo n.º 20
0
 def set_player_level(value: int, arm9: bytearray, config: Pmd2Data):
     """
     Sets the level of the player starter
     """
     block = config.binaries['arm9.bin'].blocks['HeroStartLevel']
     write_uintle(arm9, value, block.begin, 1)