The `tools` definition — "one person installs and runs it for themselves" — stopped
describing the store engines: they are products other people can build on. So the
four store repositories left `tools` for a `stores` org of their own, and the org
map, the clone list, the wiki table and the ecosystem plan follow. `check-repos.sh`
is green at 49.
Worth writing down for the next org change: `tea` has no transfer subcommand, but
`tea api` makes authenticated calls with tea's own credentials, which is enough for
all of it — POST /orgs, POST /orgs/{org}/teams, PUT /teams/{id}/members/{user},
POST /repos/{owner}/{repo}/transfer. And the transfer keeps Gitea's redirect: the
old `tools/...` raw URLs answer 301, so the installers on already-configured boxes
did not break. That is why this was a transfer and not a migrate-and-delete.
`warpstore` stayed in `engines`: it is a library other repos depend on, which is
what that org is for. The launcher gap moved out of the tools chapter of
ECOSYSTEM_PLAN into the new stores one, where it belongs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
25 KiB
RetroArch store — kidolgozott terv
Készült 2026-08-17-én, a MORE_STORES.md 4. pontjának kifejtéseként. Minden
alább szereplő formátum- és útvonal-állítás egy valódi RetroArch-telepítésen
mérve (macOS, ~/Library/Application Support/RetroArch), a mag-elérhetőség
pedig a libretro buildbot indexéből.
Megvalósítva ugyanaznap. Három repó:
engines/warpstore(közös mag),stores/warp-engine-retroarch-store(motor),stores/ttg-retroarch-store(a mi store-unk). A 11. pont javaslatával szemben a közös rész azonnal kiemelve — lásd az „Amit a megvalósítás megváltoztatott" szakaszt a végén. Wiki: warpstore, motor, store.
1. Mit ad, és mit nem
Új asset-fajtát nem fogyaszt: a RetroArch magok emulátorok, tehát pontosan
azt eszik, amit a Batocera-store is — a cartridge-et. A nyereség nem a
katalógus szélessége, hanem a gazdagépek száma: asztali Linux/Windows/macOS,
Android, Steam Deck, konzolportok.
A mai katalógusból (released + archived, 2026-08-17-i mérés) ez 6 cím,
összesen 233 KB:
| Platform | Szoftver | Cím | Fájl | Méret | CRC32 |
|---|---|---|---|---|---|
| c64 | blessingofra | Blessing of Ra | blessingofra-2.0.0.prg |
10 561 | 4253CFC6 |
| c64 | rabbitc64 | Rabbit Scooter | rabbit-1.0.0.prg |
8 072 | 31BF558B |
| c64 | c64demo | C64 Demo for Arok Party 2026 | c64demo-1.0.prg |
4 641 | AF681FFC |
| tic80 | impostor | Definitely not an Impostor | impostor-1.0.tic |
163 497 | 8D9A45DA |
| tic80 | bombexpert | BombExpert | bombexpert-0.2.tic |
25 227 | A67DDF4A |
| tic80 | mranderson | Mr Anderson's Adventure | mranderson-0.1.tic |
21 657 | E98C7712 |
Egy egész store negyed megabájt — ez az, ami miatt a szinkron gyakorlatilag ingyen van, és amiért az Android-célpont zip-ként is elküldhető.
A két mag mindenhol van. A buildbot indexét végigkérdezve:
| Cél | vice_x64 |
tic80 |
Fájlnév-alak |
|---|---|---|---|
apple/osx/arm64, apple/osx/x86_64 |
✔ | ✔ | *_libretro.dylib |
linux/x86_64, linux/aarch64, linux/armhf, linux/armv7-neon-hf |
✔ | ✔ | *_libretro.so |
windows/x86_64 |
✔ | ✔ | *_libretro.dll |
android/arm64-v8a, android/armeabi-v7a |
✔ | ✔ | *_libretro_android.so |
Tehát nincs olyan RetroArch-gazdagép, amin a katalógusunk ne futna — az Androidon
viszont a mag fájlneve más (_android.so), és ez a tervben külön kezelendő.
Amire nem jó. A html és a natív zipek maradnak kiszolgálatlanul: nincs
böngésző-mag, és a LÖVE-hoz sincs valódi mag (a lutro nem LÖVE-kompatibilis).
Batocerán és a többi ES-frontendes gépen szintén nem ez a helyes út — ott a
RetroArch a háttérben fut, a könyvtár az ES-é, tehát a Batocera-store dolgozik.
2. A gazdaplatform, ahogy valóban kinéz
Négy dolgot érdemes tudni, mert mind a négy megcáfol egy kézenfekvő feltevést.
(a) A retroarch.cfg az egyetlen igazságforrás, és a könyvtárak szét vannak
szórva. A mért gépen:
libretro_directory = ~/Library/Application Support/RetroArch/cores
thumbnails_directory = ~/Library/Application Support/RetroArch/thumbnails
playlist_directory = ~/Documents/RetroArch/playlists ← más ág!
system_directory = ~/Documents/RetroArch/system
A playlist-könyvtár tehát nem a RetroArch alapkönyvtárában van. Aki a
<base>/playlists mintát égeti bele, az ezen a gépen csendben a semmibe ír.
A motor kötelezően a retroarch.cfg-ből olvassa a négy útvonalat, és csak
akkor tippel, ha nincs cfg. A ~ feloldandó, ahogy a Windows-os portable
telepítések : prefixe is (a RetroArch saját alapkönyvtárát jelenti).
(b) A .lpl sémája. Egy valódi playlist a gépről (rövidítve) — ez a
formátum, amit írunk, nem egy dokumentációból vett közelítés:
{
"version": "1.5",
"default_core_path": "",
"default_core_name": "",
"label_display_mode": 0,
"right_thumbnail_mode": 0,
"left_thumbnail_mode": 0,
"thumbnail_match_mode": 0,
"sort_mode": 0,
"items": [
{
"path": "/…/Altered Beast (USA).md",
"entry_slot": -1,
"label": "Altered Beast (USA)",
"core_path": "/…/cores/genesis_plus_gx_libretro.dylib",
"core_name": "Sega - MS/GG/MD/CD (Genesis Plus GX)",
"crc32": "00000000|crc",
"db_name": "Sega - Mega Drive - Genesis.lpl"
}
]
}
Két tanulság: a path absztolút út a célgépen (ez a 7. pont egész
problémája), a crc32 pedig "<8 hex>|crc" alakú — a RetroArch maga gyakran
csak nullákat ír bele, mi a valódit tudjuk beírni (zlib.crc32, ingyen).
(c) A borítókép útja a playlist nevéből jön. A mért gépen:
thumbnails/Sega - Mega Drive - Genesis/Named_Boxarts/*.png
Named_Titles/*.png
Named_Snaps/*.png
Vagyis thumbnails/<db_name a .lpl nélkül>/Named_*/<label>.png, és kizárólag
PNG — a RetroArch a fájlnevet .png-re képezi. Ez a 6. pont.
(d) A magok saját nevet és kiterjesztést hoznak. A .info fájlokból:
| Mag | corename |
supported_extensions |
database |
|---|---|---|---|
tic80_libretro |
TIC-80 |
tic |
TIC-80 |
vice_x64_libretro |
VICE x64 |
d64|…|prg|p00|crt|… |
Commodore - 64 |
A prg valóban ott van a VICE listájában, tehát a nyers .prg-ket a mag
közvetlenül indítja — nem kell .d64-be csomagolni.
Amit a formátum nem tud: leírást. A .lpl bejegyzésnek nincs desc vagy
developer mezője. A katalógus desc/author adata itt elveszik — a Batocera
gamelist.xml-hez képest ez visszalépés, és nem konfigurálható. (Elvileg egy
generált .rdb adná meg az Információ-panelt és az Explore nézetet, de az bináris
libretrodb-formátum, külső eszközlánccal — ez a terven kívül, külön feladat.)
3. A megoldás felépítése
A Batocera-store bevált kettéosztását követi, ugyanazokkal a nevekkel:
stores/warp-engine-retroarch-store a motor: retroarch_store.py, install.sh
▲
│ config.json
stores/ttg-retroarch-store a mi store-unk: config + wrapper installer
Amit telepít:
<content_root>/<subfolder>/<platform>/ blessingofra-2.0.0.prg, impostor-1.0.tic, …
<playlists_dir>/Teletype Games - Commodore 64.lpl
<playlists_dir>/Teletype Games - TIC-80.lpl
<thumbnails_dir>/Teletype Games - Commodore 64/Named_Boxarts/Blessing of Ra.png
/Named_Titles/… /Named_Snaps/…
<store_home>/config.json, state.json, catalog.json, store.log
content_root alapértéke <retroarch_dir>/content, a subfolder a store
azonosítója. A retroarch.cfg-hez soha nem nyúlunk — így a store nem tud
elrontani semmit, amit a felhasználó beállított.
Playlist platformonként, nem egyben. Nem esztétikai döntés: a
default_core_path/default_core_name a playlist fejlécében van, tehát csak
akkor tud minden bejegyzés magválasztás nélkül, egy kattintással indulni, ha egy
playlisten egy mag van. Egy összevont „Teletype Games" listánál minden elemnek
saját, gépspecifikus core_path-ot kellene adni — ami az exportnál (7. pont)
azonnal elromlik.
A név sablonból jön: {store} - {label} → Teletype Games - Commodore 64.
Ez egyben a db_name és a borítókép-könyvtár neve is, tehát a store nevével
elszigetelt névtérben vagyunk: nem írunk bele a hivatalos
Commodore - 64.lpl-be, és a hivatalos thumbnail-pakkokkal sem ütközünk.
Cserébe a saját playlist-nevünkhöz nincs ikon. A RetroArch a menü-ikont
assets/xmb/<téma>/png/<Playlist neve>.png alapján keresi (a mért gépen ott
vannak a Commodore - 64.png / Commodore - 64-content.png párok), tehát egy
TTG-ikont le tudnánk tenni — de az assets/ a RetroArch online updaterének
tulajdona, ami a következő frissítéskor felülírja. Opcionális, alapból ki
(branding.icons: false), és a README mondja ki, hogy nem tartós.
CLI, a Batocera-store-ral azonos alakban:
retroarch-store list # kompatibilis címek; * telepítve, ^ frissítés van
retroarch-store sync # letöltés + playlist + borító
retroarch-store sync impostor
retroarch-store -n sync # dry run
retroarch-store remove c64:blessingofra
retroarch-store export <dir> --target-prefix <út> # 7. pont
retroarch-store config
4. A playlist, amit írunk
Konkrétan, valódi adatokkal (a fenti CRC-k mértek):
{
"version": "1.5",
"default_core_path": "/Users/tasi/Library/Application Support/RetroArch/cores/vice_x64_libretro.dylib",
"default_core_name": "VICE x64",
"label_display_mode": 0,
"right_thumbnail_mode": 0,
"left_thumbnail_mode": 0,
"thumbnail_match_mode": 0,
"sort_mode": 0,
"items": [
{
"path": "/Users/tasi/Library/Application Support/RetroArch/content/teletypegames/c64/blessingofra-2.0.0.prg",
"entry_slot": -1,
"label": "Blessing of Ra",
"core_path": "DETECT",
"core_name": "DETECT",
"crc32": "4253CFC6|crc",
"db_name": "Teletype Games - Commodore 64.lpl"
}
]
}
label= a katalógustitle-je, mert ez a megjelenő név és a borítókép-fájlnév egyszerre.core_path/core_namea tételekbenDETECT: a fejléc alapmagja dönt. Így egy playlist-fájl akkor is használható marad, ha a magok máshol vannak — a legrosszabb eset egy magválasztó kérdés, nem egy halott bejegyzés.db_namea saját fájlnevünk, ezen keresztül találja meg a borítót.- A
*_thumbnail_modeéslabel_display_modemarad0= a felhasználó globális beállítása érvényes. Nem írjuk felül a preferenciáit (lásd 6. pont).
5. Mag-feloldás
A configban a mag fájlneve suffix nélkül és a megjelenő neve áll:
"core": { "file": "vice_x64_libretro", "name": "VICE x64" }
A motor a suffixet a célgépből teszi hozzá — darwin → .dylib, linux →
.so, windows → .dll, android → _android.so —, majd megnézi, hogy a
fájl létezik-e a libretro_directory-ban:
- létezik → a playlist fejlécébe absztolút útként bekerül, a
namemellé; - nem létezik →
default_core_pathüres marad,default_core_nameaname, a tételekDETECT-en. A playlist működik, a RetroArch az első indításnál kérdez. Alist/synckiírja:magot nem találtam: vice_x64_libretro (.dylib) — DETECT, és mellé az egy soros megoldást: Online Updater ▸ Core Downloader ▸ VICE x64.
Ez a legfontosabb ergonómiai döntés: a hiányzó mag nem hiba, hanem figyelmeztetés. Egy store, ami magtelepítést követel meg, nem fog lefutni senkinek elsőre.
6. Borítókép
Egy letöltés, három hely. A thumbnail_kinds alapból mindhárom Named_*
könyvtár, mert a felhasználó globális beállítása dönti el, melyiket kéri
(bal/jobb panel), és mi nem akarjuk átírni a beállítását. Három 100 KB-os fájl
6 játéknál semmi; ahol a fájlrendszer engedi, hardlink, egyébként másolat.
A PNG-kényszer valódi problémát is jelent. A katalógus képei ma:
| Formátum | Címek |
|---|---|
image/png |
bombexpert, mranderson, rabbitc64, c64demo, blessingofra (+ nem-cartridge: rabbitroller, trickster-tiles) |
image/gif |
impostor |
A RetroArch PNG-t (és JPEG/TGA/BMP-t) tud, GIF-et nem, a fájlnevet pedig .png-re
képezi. Az impostor borítója tehát ma nem jelenne meg. A /api/image/:id
send_file-lal az eredetit adja vissza, átkódolás nélkül — a szerver nem segít.
A motor sorrendje:
- magic bytes alapján PNG? → kiírjuk, kész.
- nem PNG, és van külső átkódoló? →
sips(macOS gyári),magick/convert(ImageMagick),ffmpeg— az első elérhető nyer. - semmi? → figyelmeztetés, a bejegyzés borító nélkül is jó.
Stdlib-only megkötéssel Pythonból nem kódolunk át (GIF-dekóder kellene) — és nem
is kellene. A helyes javítás felfelé van: a warp_engine imageUrl-je
adhatna PNG-változatot (vagy a feltöltés normalizálhatna). Egy sor a
MORE_STORES.md-be: ez a store az első fogyasztó, aminek a kép formátuma is
számít, nem csak a léte.
7. Út-átírás: a motor egyetlen valódi új képessége
A .lpl absztolút utakat tartalmaz a célgépen. Amíg a store ott fut, ahol a
RetroArch, ez nem kérdés. Csak épp a legérdekesebb célpont, az Android, nem tud
Pythont futtatni — ott a store nem tud „ott" futni.
A megoldás egy kettéválasztás, ami minden esetet lefed:
| hova írunk | mi kerül a playlistbe | |
|---|---|---|
stage_root |
valódi fájlműveletek helye | — |
target_prefix |
— | ezzel az előtaggal az útvonalak |
Alapból a kettő ugyanaz (helyi telepítés). Ha eltér, egy „idegen gépre szánt" RetroArch-alakú fát írunk:
# 1. Android, adb-vel
retroarch-store export /tmp/ra-ttg \
--target-prefix /storage/emulated/0/RetroArch \
--core-suffix _android.so
adb push /tmp/ra-ttg/. /storage/emulated/0/RetroArch/
# 2. SD-kártya: a Mac-en /Volumes/SDCARD, a kézikonzolon /mnt/sdcard
retroarch-store export /Volumes/SDCARD/RetroArch --target-prefix /mnt/sdcard/RetroArch
Ugyanez a mechanizmus adja a Steam Deck flatpak-elrendezését
(~/.var/app/org.libretro.RetroArch/config/retroarch) is, ott viszont
target_prefix nélkül, mert helyben fut.
Az Android útvonalait nem égetjük be: az export --android (2. fázis) az
adb shell cat /storage/emulated/0/RetroArch/retroarch.cfg-ből olvassa ki a
készülék saját könyvtárait, ugyanazzal a parserrel, amivel helyben. A fenti
/storage/emulated/0/RetroArch csak a tartalék tipp — és ez az egyik pont, amit
valódi készüléken meg kell mérni (12. pont).
8. Tulajdonlás, prune, állapot
Ez a store a három közül a legtisztább: minden, amit ír, a nevét viseli.
- Tartalom: csak
<content_root>/<subfolder>/alatt törlünk, soha kívül. - Playlist: a fájl a miénk, de a merge mégis megőrző — újraírás előtt
kiválogatjuk azokat a tételeket, amiknek a
path-ja nem a mi tartalmi könyvtárunkban van, és visszaírjuk őket (ha a felhasználó kézzel vett fel valamit a listánkba, nem tűnik el). Ha a végén nulla tétel marad, a fájlt töröljük, nem hagyunk üres listát a menüben. - Borító:
<thumbnails_dir>/<playlist neve>/Named_*/<label>.png, prune-nál mind a három példány megy. - Állapot:
state.json,<platform>:<name>kulccsal (itt nincs „system", a platform az). Külön store, külön fájl — a Batocera v2 állapotával nincs migrációs viszony. - A verzióváltás (
1.0→2.0.0) a régi fájlt előbb törli, mint ahogy az újat hozza, ahogy ma is.
A label fájlnévvé alakításánál a RetroArch a &*/: ` <>?\|
karaktereket _-ra cseréli; a sanitizert ugyanígy írjuk meg. A mai hat címben
egyik sem szerepel (az Mr Anderson's Adventure aposztrófja nincs a listán),
tehát ez ma elméleti — de egy jövőbeli Foo: Bar cím néma borítóhiba lenne.
9. Verseny a futó RetroArch-csal
Ugyanaz a csapda, mint az EmulationStation gamelistjeivel: a RetroArch a playlisteket memóriában tartja, és visszaírja őket, ha módosultak (kedvencek, utolsó játék, rendezés). Ha futás közben írunk, a kilépése eltörölheti a munkánkat.
Batocerán ezt a sync-from-es + apply-gamelists --wait-pid páros oldja meg, de
ott van egy Ports-menü, ami elindít minket. Itt nincs: a RetroArch nem tud
szkriptet futtatni, tehát a store gazdagépen belüli indítója nem létezik. Ezért
a döntés egyszerűbb és szigorúbb:
behavior.refuse_while_running: true(alapérték) — ha fut RetroArch process, asyncnem ír, hanem kiírja, hogy zárjuk be.--forcefelülbírálja.- A
syncután az új playlistek a RetroArch újraindítása után látszanak; a menü a listát indulásnál építi. Ezt a README első bekezdésében kell kimondani, különben „nem működik" lesz a tapasztalat. - Indítás: shell, illetve ütemezve (
cron,systemd --usertimer, launchd, Task Scheduler). Ez a store-nak nincs in-app belépője, és ezt nem érdemes szépíteni.
10. A store configja
ttg-retroarch-store/config.json teljes egészében:
{
"store": {
"id": "ttg",
"name": "Teletype Games",
"base_url": "https://teletypegames.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": "teletypegames",
"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
},
"branding": { "icons": false }
}
A null útvonalak mindenütt azt jelentik: derítsd ki — env (RETROARCH_DIR),
majd retroarch.cfg, majd OS-enkénti tipplista. A config alparancs kiírja,
mire jutott, ahogy a Batocera-store a detected_arch-ot:
detected: os=darwin arch=aarch64 core_suffix=.dylib
retroarch_dir ~/Library/Application Support/RetroArch (candidate)
playlists_dir ~/Documents/RetroArch/playlists (retroarch.cfg)
libretro_dir ~/Library/Application Support/RetroArch/cores (retroarch.cfg)
cores vice_x64_libretro ✗ tic80_libretro ✗ → DETECT
11. A közös rész: mit mikor emeljünk ki
A MORE_STORES.md helyesen mondja, hogy a katalógus-lekérés, kiadásválasztás,
state.json, borító és prune-védelem közös. A most kézenfekvő lépés mégis nem
az azonnali kiemelés.
1. fázis — a RetroArch-motor önálló, egyfájlos, és igen, duplikál.
A retroarch_store.py átveszi a HTTP/katalógus/állapot réteget (~250 sor). Ok:
egyetlen minta alapján kiemelt absztrakció rossz absztrakció, és a Batocera-store
élesben fut — nem az a pillanat, hogy alatta cseréljünk réteget, amikor még
azt sem tudjuk, mit tanul a második adapter. A telepítés is egyszerűbb marad:
egy curl egy fájlra.
2. fázis — kiemelés, amikor két adapter már megmondja, mi közös.
Amit ma is látok jelöltnek: http_get/http_download, fetch_catalog +
gyorsítótár, pick_release, a config-merge, a state.json séma és az
atomikus írás. Ezek egy warpstore_core.py-ba mennek, mindkét installer két
fájlt tölt le. Amit a RetroArch már most tanított, és a közös részbe tartozik:
- a
resolve_for_archáltalánosítása: a Batocerán csak az architektúra volt a változó, itt az operációs rendszer is (mag-suffix). Egyresolve_for_host, amix86_64/aarch64/linux/darwin/windows/android/*kulcsokat is fogad, mindkettőt kiszolgálja; - a
stage_root/target_prefixkettősség (7. pont). Ez nem RetroArch-specifikus: az asztali store (MORE_STORES.md2.) és a kézikonzolos ES-disztrók ugyanígy „innen írok, ott fog futni" helyzetben vannak.
12. Munka és ellenőrzés
Becslés, a Batocera-motor mérete alapján (store.py 1073 sor):
| Rész | Új sor (kb.) |
|---|---|
| átvett réteg (HTTP, katalógus, állapot, config) | 250 |
retroarch.cfg parser + útvonal-felderítés |
90 |
playlist írás/merge (.lpl) |
120 |
| mag-feloldás | 60 |
| borító 3 könyvtárba + átkódolás | 80 |
| export / út-átírás | 70 |
| CLI, logolás | 90 |
| összesen | ~760 |
Plusz install.sh (a Batocera-inak asztali változata: ~/.local/share-be, nem
/userdata-ba) és két README.
Amit valódi gépen meg kell mérni — ez a lista a terv gyenge pontjai, nem formalitás:
- A két mag valóban elindítja-e a fájljainkat. Ez a store létjogosultsága.
Nem drága ellenőrizni:
Külön kérdés a
# magok a scratchpadbe, nem a felhasználó RetroArch-jába curl -fsSLO https://buildbot.libretro.com/nightly/apple/osx/arm64/latest/vice_x64_libretro.dylib.zip curl -fsSLO https://buildbot.libretro.com/nightly/apple/osx/arm64/latest/tic80_libretro.dylib.zip unzip -o '*.zip' retroarch -L ./vice_x64_libretro.dylib ./blessingofra-2.0.0.prg retroarch -L ./tic80_libretro.dylib ./impostor-1.0.tic.prgautostartja: a VICE-mag betölti, de futtatja-e magától, vagyRUN-ra vár. Ha vár, kell egy magopció (vice_autostart) vagy.d64-be csomagolás — ez a terv legvalószínűbb sérülési pontja. - A generált playlist megjelenik-e, a saját nevével, és a borító előjön-e a
Named_*könyvtárakból, a felhasználó globális thumbnail-beállításával. - Az Android útvonalai (
playlist_directory,libretro_directorya készülék cfg-jében) és hogy azadb push-olt tartalom olvasható-e a RetroArch-nak scoped storage mellett. - A visszaírás-verseny valódi mérete: mennyit ír vissza a RetroArch a
playlistünkből kilépéskor, elég-e a
refuse_while_running. - A
label→ borító-fájlnév sanitizálás pontos karakterkészlete (a fenti lista következtetés, nem mérés) — egyFoo: Barcímmel kipróbálva kiderül.
Javasolt sorrend
- Az 1. ellenőrzési pont (magok + a két fájltípus indítása) — mielőtt kód íródna. Egy órányi munka, és megválaszolja, hogy a store egyáltalán működhet-e.
warp-engine-retroarch-store: cfg-parser +list+synca helyi telepítéssel, macOS-en és Linuxon.ttg-retroarch-storeconfig, a fenti tartalommal.- Export/út-átírás + Android próba valódi készüléken.
- Kiemelés
warpstore_core.py-ba (11. pont, 2. fázis), és azimageUrlPNG-normalizálása awarp_engine-ben (6. pont).
Amit a megvalósítás megváltoztatott
(2026-08-17, a fenti terv leírása után.)
A közös rész azonnal kiemelve. A 11. pont fázisolását felülírtuk: a
warpstore.py a saját repójában (engines/warpstore) született meg, és a
Batocera-motor ugyanabban a körben átült rá — 1073 sorból 426 eltűnt, 115
jött vissza. A tools/ alá nem került, mert az org-definíció szerint az
engines/ a „saját motor és könyvtár, amitől más repók függnek", és ez pontosan
az. Mindkét telepítő két fájlt tölt le, a warpstore.py-t a saját repójából;
egyik sem pin-el verziót, tehát egy magbeli javítás a következő telepítéssel
mindkét store-hoz megérkezik.
Az élesben futó Batocera-store miatt az átültetés visszamérve: a cartridge-út, a
Ports-út, a borító, a gamelist-merge, az idempotens újraszinkron, a prune és az
eltávolítás ugyanazt adja, mint előtte. A régi state.json (rekordokban system,
scope nélkül) ugyanúgy kulcsolódik, tehát a frissítés után az első szinkron
nem tölt le és nem prune-ol semmit — ezt szándékosan a record_scope()
tartaléka adja, nem migráció.
Két általánosítás, amit a második adapter kényszerített ki:
resolve_for_arch→resolve_for_host. A Batocerán csak az architektúra volt a változó; a RetroArch-nál az OS is (.dll/.dylib/_android.so). A kulcssorrendos-arch,arch,os,*.- Az állapot
scopeszerint kulcsolódik, nem ES-systemszerint. A RetroArch-nál a scope a platform, nem a playlist neve — így a store átnevezése nem kulcsolja újra a telepítést.
Amit a terven felül kapott a motor: paths alparancs. A négy útvonal
felderítése annyira nem magától értetődő (lásd az (a) pontot), hogy önmagában
megérdemel egy kimenetet, ami azt is megmutatja, melyik válasz honnan jött —
config, retroarch.cfg, vagy tartalék. Ezt írja ki a telepítő is.
Ami az 5. pontból pontosításra került: a hiányzó mag nem csak „figyelmeztetés", hanem konkrét lépés is a kimenetben (Online Updater ▸ Core Downloader ▸ VICE x64).
Amit végigmértünk: letöltés, playlist, borító (a GIF sips-szel PNG-vé
konvertálva), idegen playlist-bejegyzés megőrzése, mag-felismerés, prune,
eltávolítás, üres playlist törlése, Android-export _android.so-val és POSIX
célútvonalakkal, végül teljes telepítés a forge-ról curl | bash-sal. A CRC32-k
egyeznek a doksi 1. pontjában független módszerrel mért értékekkel.
Ami továbbra is nyitott, változatlanul: a VICE .prg-autostart és az Android
adb push scoped storage kérdése. Ezt kód nem tudja megválaszolni.