rpynx v0.1.0pre-release

Project

Changelog

What changed, day by day, from the rpynx git history and the hardware test runs. No version has been released yet.

On this page

Dates are commit dates. A “run” is a test on a real Switch, recorded in tests/hardware/results/ in the rpynx repo.

2026-10-22

Milestone 7: the graphical loader

  • Renamed to rpynx: Play Ren’Py games on Switch. The README header, the titles in the .nro files, the importer window and the log line changed. The SD card folder stays switch/renpy-loader/.
  • The loader’s UI is now LVGL 9.6.0, drawn on the CPU into the framebuffer: library in Row, Grid and Cinematic layouts, game details, the + menu, controller settings and test, diagnostics, and How to play on the first start.
  • First hardware test of the LVGL loader: first frame 80 ms after start, cores at 1 % idle, SoC 36–38 °C, frames 11–17 ms.
  • Second round from that test: fonts measured so nothing is cut off, centred icons, bigger covers, a controller-shaped test screen, one Layout page for layout, backgrounds and accent colour, an illustrated How to play, and touch everywhere. Waiting for its hardware test.
  • Covers and backgrounds: the importer makes them from the game’s menu art or a chosen picture (--cover, --backdrop, Change cover…, Change background…). On the Switch, Change picture turns an Album screenshot into either, and the cover’s frame can be dragged by touch. Host-tested only.
  • Cover corners are transparent, so a focused cover’s outline stays whole. B on the Layout page goes back to the library.
  • App icons for the loader and the importer.
  • Code: the runtime’s main.c split into rslnx.c, pyrun.c and threads.c; the Ren’Py bridge split into rsl_focus, rsl_keyboard, rsl_compat and rsl_diag. No behaviour change.

Milestone 6 done (run 27)

  • The emergency combo in a game saves the defaults to the game’s profile and to the loader’s global.json, keeping each old file as .bak.
  • Games are refused in applet mode, by the loader and the runtime. The loader’s status line holds 512 characters, so the refusal text is no longer cut.

2026-10-21

Runs 21–26: gameplay reliability

  • Starting a second game after quitting no longer crashes. The cause was a Ren’Py audio decode thread waiting forever at exit (runs 22–23); finished audio streams are now closed while Python still runs (run 24). Quitting waits 1 s instead of 3 s for leftover threads (run 25).
  • A game error shows the system error dialog, with a Details page naming the logs, and returns to the library. The old path crashed (runs 23–24); fixed in run 25.
  • Links and folder buttons show a notice with the address or path, instead of failing silently or stopping the game (runs 24–25).
  • The D-pad reaches buttons whose boxes overlap (Forbidden Fantasy’s menu, runs 24–25).
  • The game menu starts on its side menu; no cursor after a touch (desktop-tested).
  • The runtime ships the Ren’Py SDK’s two fonts: The Question’s preferences screen crashed without them (run 25).
  • Logs for hardware tests: the button behind each action, the emergency combo, the line a save or load is at, HOME and sleep.
  • Run 26: a remap used in a game, save and load back to the same line, HOME. Applet mode crashed the whole console a second time.
  • Diagnostics count this process’s threads, and report load per core.
  • Build folders moved under one ignored build/.

Importer

  • Uploads to the Switch over FTP, through a hidden folder and a rename, so a failed upload leaves nothing behind.
  • unrpyc as a second decompiler.
  • Files with non-ASCII names are packed into game/rsl-nonascii.rpa. Run 20 had found that the SD card parses names as Shift-JIS and lists none of them; run 21 confirmed images and sound load from the archive, and that audio plays.

2026-10-20

  • Importer window (pywebview): a Library of the games on the SD card, an Import page with option alerts, and a target. suggested_options in the manifest.
  • --decompile with rpycdec, for Ren’Py 7 games that ship only .rpyc.
  • Windows support in the importer: tool discovery, --tools, export progress.
  • Docs matched to hardware runs 1–19.

2026-10-19

Milestone 5: the importer (macOS, standard library only)

  • Folder, ZIP, 7z and RAR in; compatibility report, manifest.json and SD export out. Its export of The Question launched on a Switch (run 9).

Runs 9–19

  • The loader no longer crashes after a game: SDL’s timer thread outlived the runtime (run 9, fixed in run 10).
  • Every thread is tracked and closed at exit, so three games in a row and Exit to the Homebrew Menu work in one session (runs 11–12).
  • Ren’Py 7 support as an experiment: --recompile; Forbidden Fantasy compiled and ran on the console (run 13). A fix for Ren’Py 7 gui values across a language change.
  • The Switch’s own keyboard for text fields; the first button of a new screen is selected; B goes back in the game; the cursor hides until the stick moves, with new cursor art.
  • Importer: Switch performance checks, --optimize, media checks inside .rpa archives.
  • The project’s source is licensed under MIT. The runtime binary is GPL-2.0-or-later, because of devkitPro’s FFmpeg.

2026-10-18

Milestones 1–4

  • Milestones 1–2: the pinned Switch toolchain, the loader shell and the controller system (normaliser, mapping engine, remapping, profiles, emergency combo).
  • Milestone 3: static CPython 3.12.8 for the Switch.
  • Milestone 4: Ren’Py 8.5.3 builds into the runtime; a desktop integration test for the boot script and controller bridge.

Runs 1–8

  • Run 1: the loader and runtime start and chain-load each other. Python errors were invisible; now they are logged.
  • Runs 2–4: the self-test stalled on select.poll() and romfs:/ paths; both fixed, 66/66 required imports. scripts/switch-ftp.sh to fetch logs and push builds over Wi-Fi.
  • Run 5: Ren’Py 8.5.3 runs on the Switch. The Question starts, renders with OpenGL ES 3.2 on nouveau, and quits. Start-up and heat fixes followed.
  • Runs 6–7: the quit freeze fixed; heat telemetry; an opt-in 30 fps cap.
  • Run 8: a game in applet mode crashed the whole console in Mesa; applet launches guarded.

↑↓ move↵ openesc close