commit e6a55f56a25018c49935077104c02c018dadc84a Author: Zsolt Tasnadi Date: Mon Aug 17 18:00:19 2026 +0200 A RetroArch store engine for WarpEngine catalogs The Batocera store reaches one kind of machine. RetroArch reads the same cartridges on desktop Linux, Windows and macOS, on Android, on the Steam Deck and on the console ports — the same seven titles, a far larger audience — so this writes RetroArch's own library format instead: one .lpl playlist per platform, with box art in the thumbnail folders that playlist's name points at. Three things it does differently, each because RetroArch is not one machine: - It reads retroarch.cfg for its directories. On the macOS install this was developed against, playlist_directory is ~/Documents/RetroArch/ playlists while cores and thumbnails are under ~/Library/Application Support/RetroArch — an engine assuming /playlists writes into the void. The leading ':' of a portable install is expanded too. - It can write for a machine it is not running on (`export`). Android runs RetroArch but cannot run Python, so the only way to serve it is to render the tree here and copy it over; the same mechanism handles an SD card that will be mounted elsewhere. - It refuses to write while RetroArch is running, because RetroArch holds its playlists in memory and writes them back on exit. The Batocera engine defers the write instead; here there is no Ports menu launching us, so refusing is both simpler and safer. Decisions worth recording. One playlist per platform, because default_core_path is a header field — that is what makes every entry start without a core prompt; the entries themselves stay on DETECT so the file survives being moved to a machine whose cores live elsewhere. A missing core is a note, not an error, or the store would never run for anyone the first time. The playlist name carries the store's name, so we never write into RetroArch's own Commodore - 64.lpl and never collide with the official thumbnail packs — and an entry the user added to our playlist survives a rewrite. Thumbnails must be PNG and one of our covers is a GIF, so the engine shells out to sips/magick/convert/ffmpeg, and simply goes without the image if the machine has none of them. Co-Authored-By: Claude Opus 5 (1M context) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a60b85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.pyc diff --git a/README.md b/README.md new file mode 100644 index 0000000..69f1564 --- /dev/null +++ b/README.md @@ -0,0 +1,331 @@ +# warp-engine-retroarch-store — a RetroArch store engine for WarpEngine sites + +Pulls games from a [WarpEngine](https://git.teletypegames.org/engines/warp_engine) +catalog into RetroArch's own library: one `.lpl` playlist per platform, with box +art in the thumbnail folders that playlist's name points at. + +This repository is the engine only. It knows the WarpEngine API but nothing about +any particular site: the host, the store's name and where its games land all come +from a `config.json` that lives in a separate **store repository**. The shared +part — catalog, releases, state, HTTP — is +[`warpstore`](https://git.teletypegames.org/engines/warpstore), which this engine +has in common with the [Batocera engine](https://git.teletypegames.org/tools/warp-engine-batocera-store). + +``` +warpstore the shared core + ▲ +warp-engine-retroarch-store this engine — retroarch_store.py, install.sh + ▲ + │ config.json +ttg-retroarch-store store repositories + ▼ +teletypegames.org +``` + +The reference store is +[`ttg-retroarch-store`](https://git.teletypegames.org/tools/ttg-retroarch-store). + +``` +-retroarch-store sync + │ + ├─ GET /api/software the whole catalog + ├─ keep platforms a libretro core boots c64 → VICE, tic80 → TIC-80 + ├─ pick the newest non-dev release that carries the cartridge + ├─ GET /api/download?path= .prg / .tic into the content folder + ├─ GET box art, converted to PNG + └─ write -