def main():
    rom_path = sys.argv[1]
    rom = NintendoDSRom.fromFile(rom_path)
    config = get_ppmdu_config_for_rom(rom)
    arm9 = rom.arm9
    original_arm9 = arm9[0:len(arm9)]

    extra_dungeon_data = ExtraDungeonDataList.read(arm9, config)
    guest_pokemon_data = GuestPokemonList.read(arm9, config)

    ExtraDungeonDataList.write(extra_dungeon_data, arm9, config)
    GuestPokemonList.write(guest_pokemon_data, arm9, config)

    extra_dungeon_data2 = ExtraDungeonDataList.read(arm9, config)
    guest_pokemon_data2 = GuestPokemonList.read(arm9, config)

    assert extra_dungeon_data == extra_dungeon_data2
    assert guest_pokemon_data == guest_pokemon_data2

    guest_pokemon_data.append(
        GuestPokemon(0, 64, 0, [1, 2, 3, 4], 901, 50, 255, 100, 102, 77, 88, 0,
                     0))
    GuestPokemonList.write(guest_pokemon_data, arm9, config)
    guest_pokemon_data2 = GuestPokemonList.read(arm9, config)
    assert guest_pokemon_data == guest_pokemon_data2

    guest_pokemon_data2.pop(-1)
    GuestPokemonList.write(guest_pokemon_data2, arm9, config)
    assert original_arm9 == arm9
Ejemplo n.º 2
0
def run_main(rom_path, export_dir, actor_mapping_path=None, opt_draw_invisible_actors_objects=True):
    global monster_bin_pack_file, monster_md, draw_invisible_actors_objects, ground_dungeon_tilesets
    draw_invisible_actors_objects = opt_draw_invisible_actors_objects

    print("Loading ROM and core files...")
    os.makedirs(export_dir, exist_ok=True)
    rom = NintendoDSRom.fromFile(rom_path)
    config = get_ppmdu_config_for_rom(rom)

    scriptdata = config.script_data
    if actor_mapping_path:
        with open(actor_mapping_path, 'r') as f:
            actor_mapping = json.load(f)
            for name, entid in actor_mapping.items():
                scriptdata.level_entities__by_name[name].entid = entid

    monster_bin_pack_file = FileType.BIN_PACK.deserialize(rom.getFileByName('MONSTER/monster.bin'))
    monster_md = FileType.MD.deserialize(rom.getFileByName('BALANCE/monster.md'))

    map_bg_dir = os.path.join(export_dir, 'MAP_BG')
    dungeon_map_bg_dir = os.path.join(export_dir, 'MAP_BG_DUNGEON_TILESET')
    print("-- DRAWING BACKGROUNDS --")
    draw_map_bgs(rom, map_bg_dir)
    print("-- DRAWING REST ROOM AND BOSS ROOM BACKGROUNDS --")
    draw_dungeon_map_bgs(rom, dungeon_map_bg_dir, config)
    print("-- DRAWING MAP ENTITIES --")
    draw_maps(rom, os.path.join(export_dir, 'MAP'), scriptdata)
Ejemplo n.º 3
0
    def main_test():
        import os
        from skytemple_files.common.types.file_types import FileType
        from ndspy.rom import NintendoDSRom
        from skytemple_files.common.util import get_ppmdu_config_for_rom
        # Testing.
        base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
        rom = NintendoDSRom.fromFile(os.path.join(base_dir, 'skyworkcopy_us.nds'))
        config = get_ppmdu_config_for_rom(rom)
        out_dir = '/tmp/monster_graphs'
        os.makedirs(out_dir, exist_ok=True)
        monster_md = FileType.MD.deserialize(rom.getFileByName('BALANCE/monster.md'))
        level_bin = FileType.BIN_PACK.deserialize(rom.getFileByName('BALANCE/m_level.bin'))
        waza_p = FileType.WAZA_P.deserialize(rom.getFileByName('BALANCE/waza_p.bin'))
        move_string_block = config.string_index_data.string_blocks['Move Names']
        monster_name_block = config.string_index_data.string_blocks['Pokemon Names']
        strings = FileType.STR.deserialize(rom.getFileByName('MESSAGE/text_e.str'))
        move_strings = strings.strings[move_string_block.begin:move_string_block.end]
        monster_strings = strings.strings[monster_name_block.begin:monster_name_block.end]

        level_bin = level_bin

        # The level_bin has no entry for monster 0.
        for monster, lbinentry_bin, waza_entry in zip(monster_md.entries[1:], level_bin, waza_p.learnsets[1:]):
            level_bin_entry = FileType.LEVEL_BIN_ENTRY.deserialize(
                FileType.COMMON_AT.deserialize(FileType.SIR0.deserialize(lbinentry_bin).content).decompress()
            )
            graph_provider = LevelUpGraphProvider(monster, level_bin_entry, waza_entry, move_strings)
            g = graph_provider.provide(
                f'{monster_strings[monster.md_index]}',
                dark=True
            )
            g.render_to_file(os.path.join(out_dir, f'{monster.md_index}.svg'))
            g.render_to_png(os.path.join(out_dir, f'{monster.md_index}.png'), dpi=92)
Ejemplo n.º 4
0
    def _outer_wrapper(wrapped_function):
        import inspect
        import pytest
        from ndspy.rom import NintendoDSRom
        from unittest import SkipTest
        from parameterized import parameterized
        rom = None
        if 'SKYTEMPLE_TEST_ROM' in os.environ and os.environ[
                'SKYTEMPLE_TEST_ROM'] != '':
            rom = NintendoDSRom.fromFile(os.environ['SKYTEMPLE_TEST_ROM'])

        if rom:

            def dataset_name_func(testcase_func, _, param):
                return f'{testcase_func.__name__}/{param.args[0]}'

            files = [(x, rom.getFileByName(x))
                     for x in get_files_from_rom_with_extension(rom, file_ext)
                     if x.startswith(path)]

            if len(files) < 1:

                def no_files(*args, **kwargs):
                    raise SkipTest("No matching files were found in the ROM.")

                return pytest.mark.romtest(no_files)
            else:
                spec = inspect.getfullargspec(wrapped_function)
                if "pmd2_data" in spec.args or "pmd2_data" in spec.kwonlyargs:
                    pmd2_data = get_ppmdu_config_for_rom(rom)

                    def pmd2datawrapper(*args, **kwargs):
                        return wrapped_function(*args,
                                                **kwargs,
                                                pmd2_data=pmd2_data)

                    pmd2datawrapper.__name__ = wrapped_function.__name__

                    parameterized.expand(files, name_func=dataset_name_func)(
                        pytest.mark.romtest(pmd2datawrapper))
                else:
                    parameterized.expand(files, name_func=dataset_name_func)(
                        pytest.mark.romtest(wrapped_function))
                # since expands now adds the tests to our locals, we need to pass them back...
                # this isn't hacky at all wdym??????ßßß
                frame_locals = inspect.currentframe(
                ).f_back.f_locals  # type: ignore
                for local_name, local in inspect.currentframe().f_locals.items(
                ):  # type: ignore
                    if local_name.startswith('test_'):
                        frame_locals[local_name] = local

        else:

            def no_tests(*args, **kwargs):
                raise SkipTest("No ROM file provided or ROM not found.")

            return pytest.mark.romtest(no_tests)
Ejemplo n.º 5
0
def create_mapping():
    from ndspy.rom import NintendoDSRom
    rom = NintendoDSRom.fromFile(
        '/home/marco/dev/skytemple/skytemple/skyworkcopy_us_unpatched.nds')
    from skytemple_files.common.util import get_ppmdu_config_for_rom
    static_data = get_ppmdu_config_for_rom(rom)
    from skytemple_files.patch.patches import Patcher
    patcher = Patcher(rom, static_data)
    patcher.apply('ActorAndLevelLoader')

    from skytemple_files.common.types.file_types import FileType
    from skytemple_files.data.md.model import Md
    md: Md = FileType.MD.deserialize(rom.getFileByName('BALANCE/monster.md'))
    from skytemple_files.list.actor.model import ActorListBin
    actor_list: ActorListBin = FileType.SIR0.unwrap_obj(
        FileType.SIR0.deserialize(rom.getFileByName('BALANCE/actor_list.bin')),
        ActorListBin)
    from skytemple_files.hardcoded.fixed_floor import HardcodedFixedFloorTables
    from skytemple_files.common.util import get_binary_from_rom_ppmdu
    boss_list = HardcodedFixedFloorTables.get_monster_spawn_list(
        get_binary_from_rom_ppmdu(
            rom, static_data.binaries['overlay/overlay_0029.bin']),
        static_data)

    actor_list_pokedex_number_mapping = []
    for e in actor_list.list:
        monster = md.entries[e.entid]
        actor_list_pokedex_number_mapping.append(
            monster.national_pokedex_number)

    boss_list_pokedex_number_mapping = []
    for boss in boss_list:
        try:
            monster = md.entries[boss.md_idx]
            boss_list_pokedex_number_mapping.append(
                monster.national_pokedex_number)
        except IndexError:
            boss_list_pokedex_number_mapping.append(0)

    mapping = {}
    for idx, a in enumerate(actor_list_pokedex_number_mapping):
        if a == 0:
            continue
        indices = [
            i for i, x in enumerate(boss_list_pokedex_number_mapping) if x == a
        ]
        if len(indices) > 0:
            mapping[idx] = indices

    print(mapping)
Ejemplo n.º 6
0
def main():
    rom_path = sys.argv[1]
    rom = NintendoDSRom.fromFile(rom_path)
    config = get_ppmdu_config_for_rom(rom)
    block_compressed = config.binaries['arm9.bin'].symbols['CompressedIqGroupsSkills']
    arm9 = rom.arm9

    groups = IqGroupsSkills.read_uncompressed(arm9, config)
    IqGroupsSkills.write_compressed(arm9, groups, config)

    assert arm9[block_compressed.begin:block_compressed.end] == COMPRESSED_GROUPS

    groups2 = IqGroupsSkills.read_compressed(arm9, config)
    for i in range(len(groups)):
        assert sorted(groups[i]) == sorted(groups2[i])
    def __init__(self, status: Status, rom: NintendoDSRom, config: RandomizerConfig, seed: str):
        """
        Inits the thread. If it's started() access to rom and config MUST NOT be done until is_done().
        is_done is also signaled by the status object's done() event.
        The max number of steps can be retrieved with the attribute 'total_steps'.
        If there's an error, this is marked as done and the error attribute contains the exception.
        """
        super().__init__()
        self.status = status
        self.rom = rom
        self.config = config
        self.lock = Lock()
        self.done = False

        self.static_data = get_ppmdu_config_for_rom(rom)
        self.randomizers: List[AbstractRandomizer] = []
        for cls in RANDOMIZERS:
            self.randomizers.append(cls(config, rom, self.static_data, seed))

        self.total_steps = sum(x.step_count() for x in self.randomizers) + 1
        self.error = None
Ejemplo n.º 8
0
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with SkyTemple.  If not, see <https://www.gnu.org/licenses/>.
import os

from ndspy.rom import NintendoDSRom

from skytemple_files.common.util import get_ppmdu_config_for_rom
from skytemple_files.dungeon_data.fixed_bin.handler import FixedBinHandler

output_dir = os.path.join(os.path.dirname(__file__), 'dbg_output')
os.makedirs(output_dir, exist_ok=True)

rom = NintendoDSRom.fromFile(
    '/home/marco/dev/skytemple/skytemple/skyworkcopy.nds')
static_data = get_ppmdu_config_for_rom(rom)

fixed_bin = rom.getFileByName('BALANCE/fixed.bin')
fixed = FixedBinHandler.deserialize(fixed_bin, static_data=static_data)
fixed_bin_after = FixedBinHandler.serialize(fixed)

with open(os.path.join(output_dir, 'before.bin'), 'wb') as f:
    f.write(fixed_bin)

with open(os.path.join(output_dir, 'after.bin'), 'wb') as f:
    f.write(fixed_bin_after)

assert fixed_bin == fixed_bin_after
print("ok!")
Ejemplo n.º 9
0
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
# 
#  SkyTemple is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# 
#  You should have received a copy of the GNU General Public License
#  along with SkyTemple.  If not, see <https://www.gnu.org/licenses/>.
import os

from ndspy.rom import NintendoDSRom

from skytemple_files.common.util import get_ppmdu_config_for_rom, get_binary_from_rom_ppmdu
from skytemple_files.hardcoded.rank_up_table import HardcodedRankUpTable

base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
rom_us = NintendoDSRom.fromFile(os.path.join(base_dir, 'skyworkcopy_us.nds'))
ppmdu_us = get_ppmdu_config_for_rom(rom_us)
arm9_us = get_binary_from_rom_ppmdu(rom_us, ppmdu_us.binaries['arm9.bin'])

rank_up = HardcodedRankUpTable.get_rank_up_table(arm9_us, ppmdu_us)

for i, rank in enumerate(rank_up):
    print(i, rank)
    
# Try setting and see if still same.
HardcodedRankUpTable.set_rank_up_table(rank_up, arm9_us, ppmdu_us)
assert rank_up == HardcodedRankUpTable.get_rank_up_table(arm9_us, ppmdu_us)
Ejemplo n.º 10
0
#  along with SkyTemple.  If not, see <https://www.gnu.org/licenses/>.
import os

from ndspy.rom import NintendoDSRom

from skytemple_files.common.util import get_ppmdu_config_for_rom, create_file_in_rom, set_binary_in_rom_ppmdu
from skytemple_files.patch.patches import Patcher

if __name__ == '__main__':
    out_dir = os.path.join(os.path.dirname(__file__), 'dbg_output')
    base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
    os.makedirs(out_dir, exist_ok=True)

    in_rom = NintendoDSRom.fromFile(
        os.path.join(base_dir, 'skyworkcopy_us.nds'))
    patcher = Patcher(in_rom, get_ppmdu_config_for_rom(in_rom))
    assert not patcher.is_applied('ActorAndLevelLoader')

    patcher.apply('ActorAndLevelLoader')
    with open(os.path.join(out_dir, 'actor_list.bin'), 'wb') as f:
        f.write(in_rom.getFileByName('BALANCE/actor_list.bin'))
    with open(os.path.join(out_dir, 'level_list.bin'), 'wb') as f:
        f.write(in_rom.getFileByName('BALANCE/level_list.bin'))

    assert patcher.is_applied('ActorAndLevelLoader')
    in_rom.saveToFile(os.path.join(out_dir, 'patched.nds'))

    # Check if really patched
    out_rom = NintendoDSRom.fromFile(os.path.join(out_dir, 'patched.nds'))
    assert Patcher(
        out_rom,
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  SkyTemple is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with SkyTemple.  If not, see <https://www.gnu.org/licenses/>.
import os

from ndspy.rom import NintendoDSRom

from skytemple_files.common.util import get_ppmdu_config_for_rom, create_file_in_rom, set_binary_in_rom_ppmdu
from skytemple_files.patch.patches import Patcher

if __name__ == '__main__':
    out_dir = os.path.join(os.path.dirname(__file__), 'dbg_output')
    base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
    os.makedirs(out_dir, exist_ok=True)

    in_rom = NintendoDSRom.fromFile(os.path.join(base_dir, 'skyworkcopy.nds'))
    patcher = Patcher(in_rom, get_ppmdu_config_for_rom(in_rom))
    assert not patcher.is_applied('MoveShortcuts')

    patcher.apply('MoveShortcuts')

    assert patcher.is_applied('MoveShortcuts')
    in_rom.saveToFile(os.path.join(out_dir, 'patched.nds'))
Ejemplo n.º 12
0
 def load_rom_data(self):
     return get_ppmdu_config_for_rom(self._rom)
Ejemplo n.º 13
0
from ndspy.rom import NintendoDSRom

from skytemple_files.common.ppmdu_config.xml_reader import Pmd2XmlReader
from skytemple_files.common.util import get_ppmdu_config_for_rom
from skytemple_files.container.sir0.handler import Sir0Handler
from skytemple_files.list.actor.model import ActorListBin
from skytemple_files.patch.patches import Patcher

if __name__ == '__main__':
    base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
                            '..')

    rom = NintendoDSRom.fromFile(
        os.path.join(base_dir, 'skyworkcopy_us_unpatched.nds'))
    patcher = Patcher(rom, get_ppmdu_config_for_rom(rom))
    assert not patcher.is_applied('ActorAndLevelLoader')

    patcher.apply('ActorAndLevelLoader')

    bin_before = rom.getFileByName('BALANCE/actor_list.bin')
    # noinspection PyTypeChecker
    # - Bug in PyCharm with bound TypeVars
    actor_list_before: ActorListBin = Sir0Handler.unwrap_obj(
        Sir0Handler.deserialize(bin_before), ActorListBin)
    # This only works with unmodified ROMs!
    assert actor_list_before.list == Pmd2XmlReader.load_default(
        'EoS_NA').script_data.level_entities
    assert len(
        Sir0Handler.deserialize(bin_before).content_pointer_offsets) == len(
            Sir0Handler.wrap_obj(actor_list_before).content_pointer_offsets)
MAP_OUT_DIR = '/tmp/maps'
DUNGEON_TILEDATA__ENTRYLEN = 20
DUNGEON_TILEDATA__WIDTH = 56
DUNGEON_TILEDATA__HEIGHT = 32
DUNGEON_ENTITIES__ENTRYLEN = 184
DUNGEON_ENTITIES__LEN_MONSTER = 40
DUNGEON_ENTITIES__LEN_ITEMS = 64
DUNGEON_ENTITIES__LEN_TRAPS = 64
DUNGEON_ENTITIES__LEN_HIDDEN_STAIRS = 1
DUNGEON_ENTITIES__EXTRA_MONSTERS_ENTRYLEN = 576
DUNGEON_ENTITIES__EXTRA_ITEMS_ENTRYLEN = 6
DUNGEON_ENTITIES__EXTRA_TRAPS_ENTRYLEN = 4
CHUNK_DIM = 8 * 3

rom = NintendoDSRom.fromFile("../../../skyworkcopy_us.nds")
pmd2data = get_ppmdu_config_for_rom(rom)
blk_dungeon_current_id = pmd2data.binaries['arm9.bin'].symbols[
    "DungeonCurrentId"]
pnt_dungeon_data = pmd2data.binaries['arm9.bin'].symbols["DungeonData"]
addr_current_id = blk_dungeon_current_id.begin_absolute  # uin16

dungeon_bin = FileType.DUNGEON_BIN.deserialize(
    rom.getFileByName('DUNGEON/dungeon.bin'), pmd2data)
mappa_s = FileType.MAPPA_BIN.deserialize(
    rom.getFileByName('BALANCE/mappa_s.bin'))
monster_md = FileType.MD.deserialize(rom.getFileByName('BALANCE/monster.md'))
monster_bin = FileType.BIN_PACK.deserialize(
    rom.getFileByName('MONSTER/monster.bin'))


class DungeonRamEntityType(Enum):
Ejemplo n.º 15
0
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with SkyTemple.  If not, see <https://www.gnu.org/licenses/>.

import os

from ndspy.rom import NintendoDSRom

from skytemple_files.common.types.file_types import FileType
from skytemple_files.common.util import get_files_from_rom_with_extension, get_ppmdu_config_for_rom
from skytemple_files.graphics.chr.handler import ChrHandler
from skytemple_files.graphics.pal.handler import PalHandler

base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
                        '..')
out_dir = os.path.join(os.path.dirname(__file__), 'dbg_output')
os.makedirs(out_dir, exist_ok=True)

rom = NintendoDSRom.fromFile(os.path.join(base_dir, 'skyworkcopy_us.nds'))
config = get_ppmdu_config_for_rom(rom)

for fn in get_files_from_rom_with_extension(rom, 'chr'):
    font = ChrHandler.deserialize(rom.getFileByName(fn))
    pal = PalHandler.deserialize(rom.getFileByName(fn[:-4] + ".pal"))
    font.set_palette(pal)
    font.to_pil().save(os.path.join(out_dir, fn.replace('/', '_') + f'.png'))
    assert rom.getFileByName(fn) == ChrHandler.serialize(font)
Ejemplo n.º 16
0
 def open_rom(self, filename: str):
     self._rom = NintendoDSRom.fromFile(filename)
     self._rom_filename = filename
     self._project_fm = ProjectFileManager(filename)
     self._static_data = get_ppmdu_config_for_rom(self._rom)
     self._open_files = {}
Ejemplo n.º 17
0
from skytemple_files.common.util import get_ppmdu_config_for_rom, get_binary_from_rom_ppmdu
from skytemple_files.patch.patches import Patcher

if __name__ == '__main__':
    out_dir = os.path.join(os.path.dirname(__file__), 'dbg_output')
    base_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
    package = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'docs',
                           'patch_packages', 'example_patch.skypatch')
    os.makedirs(out_dir, exist_ok=True)

    in_rom = NintendoDSRom.fromFile(
        os.path.join(base_dir, 'skyworkcopy_us.nds'))

    # Load PPMDU config, but remove all data about Patches and LooseBinFiles.
    config = get_ppmdu_config_for_rom(in_rom)
    config.asm_patches_constants.patches = {}
    config.asm_patches_constants.loose_bin_files = {}

    patcher = Patcher(in_rom, config, skip_core_patches=True)

    # Load the package
    patcher.add_pkg(package)
    assert not patcher.is_applied('ExamplePatch')

    patcher.apply('ExamplePatch')
    with open(os.path.join(out_dir, 'example_patch_ov11.bin'), 'wb') as f:
        f.write(
            get_binary_from_rom_ppmdu(
                in_rom, config.binaries['overlay/overlay_0011.bin']))