def run(self, status: Status): if not self.config['improvements']['download_portraits']: return status.done() status.step("Apply 'ActorAndLevelLoader' patch...") patcher = Patcher(self.rom, self.static_data) if not patcher.is_applied('ActorAndLevelLoader'): patcher.apply('ActorAndLevelLoader') overlay13 = get_binary_from_rom_ppmdu( self.rom, self.static_data.binaries['overlay/overlay_0013.bin']) actor_list: ActorListBin = FileType.SIR0.unwrap_obj( FileType.SIR0.deserialize( self.rom.getFileByName('BALANCE/actor_list.bin')), ActorListBin) starters = HardcodedPersonalityTestStarters.get_partner_md_ids( overlay13, self.static_data) partners = HardcodedPersonalityTestStarters.get_player_md_ids( overlay13, self.static_data) md = FileType.MD.deserialize( self.rom.getFileByName('BALANCE/monster.md')) with urllib.request.urlopen( "http://sprites.pmdcollab.org/resources/pokemons.json") as url: config = json.loads(url.read().decode()) kao = FileType.KAO.deserialize( self.rom.getFileByName('FONT/kaomado.kao')) if fun.is_fun_allowed(): status.step("Downloading portraits...") fun.replace_portraits(self.rom, self.static_data) return status.done() status.step("Downloading portraits for NPCs...") for actor in actor_list.list: if actor.entid > 0: self._import_portrait(kao, config, actor.entid, md.entries[actor.entid]) status.step("Downloading portraits for starters...") for starter in starters: self._import_portrait(kao, config, starter, md.entries[starter]) status.step("Downloading portraits for partners...") for partner in partners: self._import_portrait(kao, config, partner, md.entries[partner]) self.rom.setFileByName('FONT/kaomado.kao', FileType.KAO.serialize(kao)) def add_rows(): if Global.main_builder: o = Global.main_builder.get_object('store_debug_portraits') o.clear() for row in self._debugs: o.append(row) self.frontend.idle_add(add_rows) status.done()
def run(self, status: Status): if not self.config['starters_npcs']['npcs']: return status.done() status.step("Apply 'ActorAndLevelLoader' patch...") patcher = Patcher(self.rom, self.static_data) if not patcher.is_applied('ActorAndLevelLoader'): patcher.apply('ActorAndLevelLoader') status.step("Updating special recruitment table...") actor_list: ActorListBin = FileType.SIR0.unwrap_obj( FileType.SIR0.deserialize( self.rom.getFileByName('BALANCE/actor_list.bin')), ActorListBin) binary = get_binary_from_rom_ppmdu( self.rom, self.static_data.binaries['overlay/overlay_0011.bin']) sp_list = HardcodedRecruitmentTables.get_monster_species_list( binary, self.static_data) for i, actor in enumerate(actor_list.list): if i in ACTOR_TO_RECRUIT_MAPPING: for bi in ACTOR_TO_RECRUIT_MAPPING[i]: sp_list[bi] = actor.entid HardcodedRecruitmentTables.set_monster_species_list( sp_list, binary, self.static_data) set_binary_in_rom_ppmdu( self.rom, self.static_data.binaries['overlay/overlay_0011.bin'], binary) status.done()
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 run(self, status: Status): if not self.config['starters_npcs']['npcs']: return status.done() lang, string_file = get_main_string_file(self.rom, self.static_data) pokemon_string_data = self.static_data.string_index_data.string_blocks[ "Pokemon Names"] status.step("Apply 'ActorAndLevelLoader' patch...") patcher = Patcher(self.rom, self.static_data) if not patcher.is_applied('ActorAndLevelLoader'): patcher.apply('ActorAndLevelLoader') status.step("Randomizing NPC actor list...") mapped_actors = self._randomize_actors(string_file, pokemon_string_data) status.step("Replacing main text that mentions NPCs...") names_mapped_all = {} for lang, string_file in get_all_string_files(self.rom, self.static_data): names_mapped = {} names_mapped_all[lang] = names_mapped for old, new in mapped_actors.items(): old_base = old % 600 new_base = new % 600 old_name = self._get_name(string_file, old_base, pokemon_string_data) new_name = self._get_name(string_file, new_base, pokemon_string_data) names_mapped[old_name] = new_name replace_text_main(string_file, names_mapped, pokemon_string_data.begin, pokemon_string_data.end) self.rom.setFileByName(f'MESSAGE/{lang.filename}', FileType.STR.serialize(string_file)) status.step("Replacing script text that mentions NPCs...") replace_text_script(self.rom, self.static_data, names_mapped_all) status.step("Cloning missing NPC portraits...") kao = FileType.KAO.deserialize( self.rom.getFileByName('FONT/kaomado.kao')) for new in mapped_actors.values(): new_base = new % 600 clone_missing_portraits(kao, new_base - 1) self.rom.setFileByName('FONT/kaomado.kao', FileType.KAO.serialize(kao)) status.done()
def _patch_credits(self): credits = "" for patch in Patcher(self.rom, self.static_data).list(): try: if patch.is_applied(self.rom, self.static_data): desc = patch.description.replace('\n', '\\n') credits += f""" case menu("{patch.name}"): message_Mail("[CS:A]{escape(patch.name)}[CR]\\nby [CS:A]{escape(patch.author)}[CR]\\n\\n{escape(desc)}"); jump @l_patches; """ except NotImplementedError: pass return credits
def run(self, status: Status): if not self.config['starters_npcs']['npcs']: return status.done() status.step("Apply 'ActorAndLevelLoader' patch...") patcher = Patcher(self.rom, self.static_data) if not patcher.is_applied('ActorAndLevelLoader'): patcher.apply('ActorAndLevelLoader') status.step("Updating bosses...") actor_list: ActorListBin = FileType.SIR0.unwrap_obj( FileType.SIR0.deserialize( self.rom.getFileByName('BALANCE/actor_list.bin')), ActorListBin) binary = get_binary_from_rom_ppmdu( self.rom, self.static_data.binaries['overlay/overlay_0029.bin']) boss_list = HardcodedFixedFloorTables.get_monster_spawn_list( binary, self.static_data) for i, actor in enumerate(actor_list.list): if i in ACTOR_TO_BOSS_MAPPING: for bi in ACTOR_TO_BOSS_MAPPING[i]: boss_list[bi].md_idx = actor.entid for extra_id in EXTRA_FF_MONSTER_RANDOMIZE: boss_list[extra_id].md_idx = choice( get_allowed_md_ids(self.config, False)) HardcodedFixedFloorTables.set_monster_spawn_list( binary, boss_list, self.static_data) set_binary_in_rom_ppmdu( self.rom, self.static_data.binaries['overlay/overlay_0029.bin'], binary) status.done()
def run(self, status: Status): if not self.config['starters_npcs']['global_items']: return status.step("Apply patches...") patcher = Patcher(self.rom, self.static_data) if not patcher.is_applied('ActorAndLevelLoader'): patcher.apply('ActorAndLevelLoader') if not patcher.is_applied('ExtractHardcodedItemLists'): patcher.apply('ExtractHardcodedItemLists') status.step("Randomizing global item lists...") for i in range(0, ITEM_LIST_COUNT): self.rom.setFileByName( f'TABLEDAT/list_{i:02}.bin', ItemListHandler.serialize(self._randomize_items())) status.done()
# 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 create_patcher(self): if self._patcher is None: self._patcher = Patcher(self._rom, self.get_rom_module().get_static_data()) return self._patcher
def create_patcher(self): return Patcher(self._rom, self.get_rom_module().get_static_data())
from skytemple_files.patch.errors import PatchNotConfiguredError 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__), 'parameters_test') os.makedirs(out_dir, exist_ok=True) os.environ['SKYTEMPLE_DEBUG_ARMIPS_OUTPUT'] = 'YES' in_rom = NintendoDSRom.fromFile(os.path.join(base_dir, 'skyworkcopy.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, False) assert not patcher.is_applied('ParametersTest') # Missing params try: patcher.apply('ParametersTest') except PatchNotConfiguredError: pass else: assert False, "Must throw PatchNotConfiguredError" # Invalid params try:
def run(self, status: Status): patcher = Patcher(self.rom, self.static_data) status.step("Apply base patches by psy_commando, irdkwia and End45...") sleep(5) # gotta give some spotlight to them. if not patcher.is_applied('ActorAndLevelLoader'): patcher.apply('ActorAndLevelLoader') if not patcher.is_applied('ProvideATUPXSupport'): patcher.apply('ProvideATUPXSupport') if not patcher.is_applied('ExtraSpace'): patcher.apply('ExtraSpace') if self.config['improvements']['patch_moveshortcuts']: status.step("Apply 'MoveShortcuts' patch...") if not patcher.is_applied('MoveShortcuts'): patcher.apply('MoveShortcuts') if self.config['improvements']['patch_unuseddungeonchance']: status.step("Apply 'UnusedDungeonChancePatch' patch...") if not patcher.is_applied('UnusedDungeonChancePatch'): patcher.apply('UnusedDungeonChancePatch') if self.config['improvements']['patch_totalteamcontrol']: status.step("Apply 'Complete Team Control' patches...") if not patcher.is_applied('CompleteTeamControl'): patcher.apply('CompleteTeamControl') if not patcher.is_applied('FarOffPalOverdrive'): patcher.apply('FarOffPalOverdrive') if not patcher.is_applied('PartnersTriggerHiddenTraps'): patcher.apply('PartnersTriggerHiddenTraps') if not patcher.is_applied('ReduceJumpcutPauseTime'): patcher.apply('ReduceJumpcutPauseTime') status.done()
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'])) assert patcher.is_applied('ExamplePatch') in_rom.saveToFile(os.path.join(out_dir, 'patched.nds')) # Check if really patched