ROM editing with Python and skytemple-files

Revision as of 16:51, 30 September 2025 by Frostbyte (talk | contribs) (Add skytemple-files tutorial)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This article is unfinished. You can help expanding it.


SkyTemple is internally powered by skytemple-files, a Python library. This library can be installed independently and used to modify the assets of Explorers of Sky by writing Python code. This can be helpful to make changes that are not directly supported by SkyTemple, such as mass editing data.

Installation

To install skytemple-files on any OS using Python 3.11 - 3.13 just run:

pip install skytemple-files

Note: This only works if binary third party libraries used by skytemple-files are also published on pypi for the platform and python version you use. Otherwise pip will try to build them from source, which means you will have to build the dependencies, like Rust.

Usage

The following script shows an example of how skytemple-files can be used to make a single change to dungeon floor data.

from ndspy.rom import NintendoDSRom
from range_typed_integers import u8

from skytemple_files.common.impl_cfg import (
    change_implementation_type,
    ImplementationType,
)
from skytemple_files.common.types.file_types import FileType
from skytemple_files.common.util import get_ppmdu_config_for_rom

# 1. First you probably always want to enable native file handlers to fast Rust-based implementations
#    for all file types, wherever possible.
change_implementation_type(ImplementationType.NATIVE)

# 2. Second you need to ROM
rom = NintendoDSRom.fromFile("/tmp/rom.nds")

# 3. You then almost always need the ppmdu static data for the ROM 
#    (the XML files in SkyTemple Files _resources/ppmdu_config)
static_data = get_ppmdu_config_for_rom(rom)
# 4. You then get the file you want as bytes from the ROM
file_raw = rom.getFileByName("BALANCE/mappa_s.bin")
# 5. Next you use FileType.<YOUR FILE TYPE> to get the file type handler and use deserialize to unpack
#    the bytes into a model representing the file. See `FileType` for a list of available file types.
#    Some file handlers need the PPMDU static data as parameter.
mappa = FileType.MAPPA_BIN.deserialize(file_raw)
# 6. You can then interact with the model. Here we change the tileset of the first floor in the dungeon floor list.
mappa.floor_lists[0][0].layout.tileset_id = u8(123)
# 7. You can then turn the model back into bytes with the handler:
mappa_bytes_after = FileType.MAPPA_BIN.serialize(mappa)
# 8. And then write that back to the ROM:
rom.setFileByName("BALANCE/mappa_s.bin", mappa_bytes_after)
# 9. Which you can then write to a file again:
rom.saveToFile("/tmp/rom_out.nds")