rpynx v0.1.0pre-release

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.

Source docs/IMPORTER.md
On this page

Checks

CheckHowEffect
Game directoryRen’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 versionrenpy/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 generationThe 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 Pythongame/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.0Any other header: warning, a custom format that needs the game’s own loader
MediaAudio 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 namesAny exported path with non-ASCII charactersPacked into an archive; see Non-ASCII file names

Status

Detectedstatusruntime
Ren’Py 8.xexperimentalrenpy-8.5.3
Ren’Py 8.0–8.4experimental, plus a warning (loading their .rpyc in 8.5.3 is untested)renpy-8.5.3
Version unknown, Python 3 .rpycexperimental, plus a warningrenpy-8.5.3
Ren’Py 7.x or older, or Python 2unsupported (no Python 2 runtime yet)null
Ren’Py 7.x with --recompileexperimental, plus warningsrenpy-8.5.3
Ren’Py 9+, or nothing identifiableunsupportednull

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 !.

FindingWhy it mattersFixed by --optimize
Video above 30 fpsEvery extra frame costs CPU and heat; the screen gains littleYes
Video above 1920×1080Too heavy to decode smoothlyNo
Video above 1280×720About twice the decoding work of 720pNo
HEVC or AV1 videoThe most expensive codecs to decode in softwareNo
Image above 4096 px on a sideOver the GPU texture limit; may not displayNo
Locked archiveIts assets cannot be checkedNo

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 .7z or .rar with 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 .rpa are not inspected; only images and videos are. A game that ships only .rpa and no renpy/ folder may have an unknown Python generation, which makes it unsupported.
  • 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.

↑↓ move↵ openesc close