Importer
Checks and statuses
What the importer looks at, the status it gives a game, the Switch performance checks, and how archives are kept safe.
On this page
Checks
| Check | How | Effect |
|---|---|---|
| Game directory | Ren’Py’s own path_to_gamedir rule: launcher names, then game, then data, then the folder itself if it holds scripts. It descends through one wrapper folder or <Name>.app/Contents/Resources/autorun. | No .rpy, .rpyc or .rpa found: refused |
| Ren’Py version | renpy/vc_version.py (8.1+), then a compiled vc_version.pyc, then version_tuple in renpy/__init__.py. An SDK project uses its parent’s renpy/, with a warning. | Decides the status |
| Python generation | The version first (8 → 3, 7 or older → 2). Otherwise lib/py3-* against lib/py2-* and Python 2 file names. Otherwise the .rpyc header and pickle protocol; only 2 bytes are decompressed. | Conflicting hints: warning |
| Custom Python | game/python-packages/, *.py in game/ (not *_ren.py) | Warning: pure Python 3.12 only; no ctypes, ssl, sqlite3, mmap, subprocess or multiprocessing on the Switch |
| Native code | *.pyd, *.dll, *.so, *.dylib in game/ | Warning: cannot load on the Switch |
| Archive format | .rpa header is RPA-3.0 or RPA-2.0 | Any other header: warning, a custom format that needs the game’s own loader |
| Media | Audio and video files by extension | .mid warns (Ren’Py cannot play MIDI). Files of 2 GiB or more warn (FAT32 cannot hold files of 4 GiB or more) |
| Non-ASCII names | Any exported path with non-ASCII characters | Packed into an archive; see Non-ASCII file names |
Status
| Detected | status | runtime |
|---|---|---|
| Ren’Py 8.x | experimental | renpy-8.5.3 |
| Ren’Py 8.0–8.4 | experimental, plus a warning (loading their .rpyc in 8.5.3 is untested) | renpy-8.5.3 |
Version unknown, Python 3 .rpyc | experimental, plus a warning | renpy-8.5.3 |
| Ren’Py 7.x or older, or Python 2 | unsupported (no Python 2 runtime yet) | null |
Ren’Py 7.x with --recompile | experimental, plus warnings | renpy-8.5.3 |
| Ren’Py 9+, or nothing identifiable | unsupported | null |
The importer never writes verified: only a hardware test can do that. It does not export unsupported games, because no runtime could start them. The statuses are explained in Statuses and test runs.
Switch performance
The Switch decodes video in software on a ~1 GHz Cortex-A57. Its screen is 1280×720 handheld and 1920×1080 docked, and its GPU’s largest texture is 4096×4096. Findings go into performance.issues in the manifest, and the loader marks those games with an amber !.
| Finding | Why it matters | Fixed by --optimize |
|---|---|---|
| Video above 30 fps | Every extra frame costs CPU and heat; the screen gains little | Yes |
| Video above 1920×1080 | Too heavy to decode smoothly | No |
| Video above 1280×720 | About twice the decoding work of 720p | No |
| HEVC or AV1 video | The most expensive codecs to decode in software | No |
| Image above 4096 px on a side | Over the GPU texture limit; may not display | No |
| Locked archive | Its assets cannot be checked | No |
The checks cover loose files and the contents of standard .rpa archives. The archive index (a pickle) is read opcode by opcode with pickletools; only plain data is accepted, and nothing is unpickled or executed. Archives in any other format count as locked: their contents are not checked and the importer does not try to open them.
What --optimize does
- Re-encodes videos above 30 fps at 30 fps, at the same size. It keeps the codec family, because the game refers to the file by name: VP9 → libvpx-vp9 at CRF 31 with tiles, VP8 → libvpx, H.264 → libx264 at CRF 20.
- Constant quality, not a fixed bitrate. Audio is copied unchanged.
- Skips videos with an alpha channel, and codecs it has no encoder for, and says so.
- Changes only the export. A video from an archive is exported as a loose file, which Ren’Py loads before the archive.
Sizes are not shrunk automatically: Ren’Py draws a movie or image at the file’s own pixel size, so halving a 1080p splash would show it at two thirds of the screen.
Archive safety
Every archive is checked before anything is written, then unpacked into a fresh temp folder that is deleted afterwards. The importer refuses an archive that has:
- an absolute path, a drive letter, or a
..component; - on Windows, a name Windows cannot create as written;
- a password;
- a symlink pointing outside the archive (a
.7zor.rarwith any link is refused); - more than 200,000 entries, or more than 32 GiB uncompressed;
- an entry over 1 MiB that compresses better than 200:1.
After unpacking, the tree is walked again, and any link or limit breach found then refuses the import. The limits are constants at the top of importer/rsl/archives.py.
Limits
- No
.tar.bz2(Ren’Py’s Linux format) or.dmg. Unpack these first and import the folder. - Scripts inside
.rpaare not inspected; only images and videos are. A game that ships only.rpaand norenpy/folder may have an unknown Python generation, which makes itunsupported. - The Python modules in
game/are not scanned for imports of modules the Switch lacks. - The media check looks at file extensions. The runtime’s FFmpeg codec list is not confirmed on hardware.