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
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)
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)
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)
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)
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
# 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!")
# 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)
# 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'))
def load_rom_data(self): return get_ppmdu_config_for_rom(self._rom)
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):
# 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)
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 = {}
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']))