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 <base>/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) <noreply@anthropic.com>
67 lines
1.3 KiB
JSON
67 lines
1.3 KiB
JSON
{
|
|
"store": {
|
|
"id": "warp",
|
|
"name": "WarpEngine Store",
|
|
"base_url": "https://example.org",
|
|
"api": {
|
|
"catalog": "/api/software",
|
|
"download": "/api/download"
|
|
}
|
|
},
|
|
"paths": {
|
|
"retroarch_dir": null,
|
|
"playlists_dir": null,
|
|
"thumbnails_dir": null,
|
|
"libretro_dir": null,
|
|
"content_root": null,
|
|
"subfolder": "warp",
|
|
"target_prefix": null
|
|
},
|
|
"playlist": {
|
|
"name_template": "{store} - {label}",
|
|
"write_crc32": true,
|
|
"thumbnail_kinds": [
|
|
"Named_Boxarts",
|
|
"Named_Titles",
|
|
"Named_Snaps"
|
|
]
|
|
},
|
|
"catalog": {
|
|
"statuses": [
|
|
"released",
|
|
"archived"
|
|
],
|
|
"owner_id": null,
|
|
"only": [],
|
|
"exclude": []
|
|
},
|
|
"platforms": {
|
|
"c64": {
|
|
"label": "Commodore 64",
|
|
"kind": "cartridge",
|
|
"ext": ".prg",
|
|
"core": {
|
|
"file": "vice_x64_libretro",
|
|
"name": "VICE x64"
|
|
},
|
|
"enabled": true
|
|
},
|
|
"tic80": {
|
|
"label": "TIC-80",
|
|
"kind": "cartridge",
|
|
"ext": ".tic",
|
|
"core": {
|
|
"file": "tic80_libretro",
|
|
"name": "TIC-80"
|
|
},
|
|
"enabled": true
|
|
}
|
|
},
|
|
"behavior": {
|
|
"prune": true,
|
|
"timeout": 30,
|
|
"insecure": false,
|
|
"refuse_while_running": true,
|
|
"convert_images": true
|
|
}
|
|
} |