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
.nrofiles, the importer window and the log line changed. The SD card folder staysswitch/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.csplit intorslnx.c,pyrun.candthreads.c; the Ren’Py bridge split intorsl_focus,rsl_keyboard,rsl_compatandrsl_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_optionsin the manifest. --decompilewith 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.jsonand 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.rpaarchives. - 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()andromfs:/paths; both fixed, 66/66 required imports.scripts/switch-ftp.shto 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.