TITLE=warpstore ROUTE=/engines/warpstore LOCALE=hu MODIFIED=1792417593 URL=https://wiki.teletypegames.org/hu/engines/warpstore L=1 #22 L=2 https://git.teletypegames.org/engines/warpstore L=3 #45 L=4 #47 L=5 #43 q│ Egy báruházmotorq beolvas egy 1WarpEngine-katalógust, és kiírja valamelyik q│ gazdaplatform saját játékkönyvtár-formátumát. Csak ez az utolsó lépés tér el q│ platformonként. Az API-val való beszélgetés, a kiadás kiválasztása, a gép q│ illesztése és annak nyilvántartása, hogy mi hova került, mindenhol ugyanaz a q│ munka — a cwarpstoreq pontosan ez a munka, egyetlen fájlban, minden q│ áruházmotor közösen használja. p ┌──────────────────────────────┐ p │ warpstore.py │ p │ catalog · releases · host │ p │ state · config · HTTP │ p └──────────────┬───────────────┘ p ┌──────────────┴───────────────┐ p ▼ ▼ p warp-engine-batocera-store warp-engine-retroarch-store p ROM-mappák + gamelist.xml .lpl lejátszási listák + bélyegképek p │ │ p ▼ ▼ p EmulationStation RetroArch bRepó:0 2https://git.teletypegames.org/engines/warpstore bKatalógusoldal: 1WarpEngine bHasználói:0 3Batocera áruházmotor · 4RetroArch áruházmotor 1Miért létezik 1═════════════ A Batocera-áruház 1073 sor volt, és ennek csak nagyjából a harmada szólt a Batoceráról. A RetroArch-áruháznak a másik kétharmadra volt szüksége, ezért a közös rész kiköltözött — már egy második fogyasztóval a kézben, hogy a vágás ott legyen, ahol a két motor valóban eltér. Egyetlen fájl, csak a Python 3 szabványkönyvtárával: a gazdagépek a Batocera-doboztól (cpython30, cpip0 nélkül) az asztali gépig terjednek, és egyiket sem szabad rávenni bármi telepítésére. Egy motor telepítője a cwarpstore.py fájlt az adapterszkript mellé teszi, az adapter pedig cimport warpstore0-t hív. 1Mit ad hozzá egy adapter 1════════════════════════ 1. cDEFAULT_CONFIG0 — hol vannak a dolgok ezen a gazdagépen, és melyik katalógusplatform mire képződik le. 2. caccept(spec, sw)0 — mely katalógusbejegyzéseket tudja futtatni ez a gazdagép, és hogyan csoportosulnak. 3. bA kód, amely kiírja a gazdagép könyvtárformátumát. p import warpstore as ws p p def accept(spec, sw): p """Return (scope, extras), or raise ws.Skip(reason) to reject the title.» p """ p if spec["system"] not in available_systems: p raise ws.Skip(f"no '{spec['system']}' ROM folder on this box") p return spec["system"], {"system": spec["system"]} p p cfg = ws.load_config(path, DEFAULT_CONFIG, required=("paths.subfolder",)) p ws.init(path) p games, skipped = ws.select_games(cfg, ws.fetch_catalog(cfg, use_cache=True),» p accept) A cscope0 az, ahogyan a gazdagép csoportosítja a könyvtárát — egy Batocera-rendszer, egy RetroArch-lejátszási lista. A cstate.json0 kulcsa c:0, így ugyanaz a szoftvernév két scope-ban két külön bejegyzés marad. 1Mi van benne 1════════════ t┌─────────────────┬──────────────────────────────────────────────────────────┐ t│h Terület t│h Függvények t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Naplózás t│0 cset_tag0, cset_verbose0, clog0, cdebug0, cdie0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Fájlok t│0 cload_json0, cwrite_json0, cwrite_atomic0, cwithin0, t│ t│0 t│0 cprune_empty_dirs0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Konfiguráció t│0 cdeep_merge0, cload_config0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Áruház-könyvtár t│0 cinit0, majd cHOME0, cCONFIG_PATH0, cSTATE_PATH0, cCATALOG_CACHE0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 HTTP t│0 chttp_get0, chttp_download0, capi_url0, cdownload_url0, t│ t│0 t│0 cuser_agent0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Gazdagép t│0 cmachine0, chost_os0, chost0, cresolve_for_host0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Katalógus t│0 cfetch_catalog0, cselect_games0, csurvey_catalog0, t│ t│0 t│0 cpick_release0, casset_basename0, cdownload_image0 t│ t├─────────────────┼──────────────────────────────────────────────────────────┤ t│0 Állapot t│0 cload_state0, csave_state0, cgame_key0, crecord_scope0, t│ t│0 t│0 crecords_by_scope0, cmatch_keys0, climit_to_names0 t│ t└─────────────────┴──────────────────────────────────────────────────────────┘ Öt közülük olyan döntést hordoz, amit érdemes ismerni. cselect_gamesb kontra csurvey_catalog0 — a cselect_games0 azt adja vissza, amit az áruház telepíteni tud. A csurvey_catalog0 ezen felül címenként egy rekordot ad azokról is, amelyeket ez a gép nem tud telepíteni, egy creason0 kóddal (cplatform_off0, chost_asset0, cno_asset0, cvetoed0, az 1.5.0-tól cgated0 is — olyan cím, amelyet a host árul, és amelyet egy névtelen áruház nem tud letölteni; ilyenkor a rekordban ott a cpurchase_url0) és egy mondattal. Egy kliens ezeket kiszürkítheti elrejtés helyett — a WarpEngine Client a saját portjában pontosan ezt teszi. Azok a címek, amelyeket az áruház imaga dönt úgy0, hogy nem kínál, egyik listában sincsenek benne — egy rossz státusz vagy egy kizárólista szerkesztői döntés, nem a gép korlátja. cfetch_catalog0 — a hostot kéri meg, hogy maga szűrjön cowner_id0-re és a ccatalog.statuses0-ra (cstatus=released,archived0), és ha a host mégis lapozva válaszol, követi a cnextPage0-et — így egy host oldali lapméret sosem vághatja meg csendben a szinkront. Mindkettő csak rövidebb letöltés: a csurvey_catalog ugyanezeket a szűrőket újra alkalmazza, így egy paramétert nem ismerő host semmin nem változtat. cdownload_url0 — a cGET /api/download0 végpontra mutat, nem a c/file/0-ra, így a host minden letöltést lát. Hogy beszámolja-e, az a host döntése: a teletypegames.org szándékosan kihagyja a letöltésszámból a cwarpstore/*0 user agentet (cuser_agent0, cignored_user_agents0), így az áruházak telepítései nem jelennek meg a statisztikában. cresolve_for_host(value, host)0 — olyan konfigurációs érték, amely függhet a géptől. Egy sima sztring mindenhol ugyanaz — ilyen a ccartridge0: adat egy emulátornak. Egyébként az érték egy mapping, és a legspecifikusabb kulcs nyer: p {"linux-aarch64": …, "aarch64": …, "linux": …, "*": …} Ha nincs illeszkedő kulcs és nincs c*0 sem, az eredmény cNone0, és a hívó kihagyottként jelenti a címet, ahelyett hogy olyasmit telepítene, ami nem tud futni. Ez a Batocera-motor cresolve_for_arch0 függvényének általánosítása: a Batocera mindig csak clinux0 volt, de egy RetroArch-gazdagép lehet Windows, macOS vagy Android — és ez dönti el, hogy hogyan hívják a libretro core fájlját (c.dll0, c.dylib0, c_android.so0). cwithin(path, root)0 — minden törlést ez őriz. Egy áruház csak abból a részfából távolíthat el fájlokat, amely az övé, soha nem a felhasználó könyvtárából és soha nem egy másik áruházéból. cprune_empty_dirs(dirs, root)0 — ugyanennek a szabálynak az eltávolítási oldala. Csak üres könyvtárak tűnnek el, és csak a croot0 belsejében: egyetlen kósza fájl megtartja a könyvtárat. Ez teszi lehetővé, hogy a cpurge0 (és így az cuninstall.sh0) úgy hagyja a gazdagépet, ahogy volt. cwrite_atomic0 — semmi nem íródik a helyén. Egy szinkron közben megszakított áruház különben félig megírt lejátszási listát vagy gamelistet hagyna maga után, ami rosszabb, mint egy régi. 1Minden áruház eltávolítása egy gépről 1═════════════════════════════════════ p curl -fsSL https://git.teletypegames.org/engines/warpstore/raw/branch/master» p /uninstall.sh | sh Ezzel az egész keretrendszer lehúzható anélkül, hogy fejben kellene tartani, mi van telepítve: megkeresi az összes áruház-könyvtárat az ismert gyökerek alatt, mindegyik áruház bsaját motorjával0 takaríttatja el, amit telepített, majd törli az áruházat, az indítóját és a motorfájlokat. Egyetlen áruházhoz inkább az adott motor saját cuninstall.sh0 szkriptjét használd — az ismeri a gazdagép extráit is, például egy Batocera Ports-bejegyzést. t┌─────────────────────────────────────┬──────────────────────────────────────┐ t│h Környezeti változó t│h Jelentés t│ t├─────────────────────────────────────┼──────────────────────────────────────┤ t│0 cDRY_RUN0 t│0 c10 esetén kiírja, mi tűnne el, és t│ t│0 t│0 semmit nem távolít el t│ t├─────────────────────────────────────┼──────────────────────────────────────┤ t│0 cKEEP_GAMES0 t│0 c10 esetén csak a szkripteket törli, a t│ t│0 t│0 játékokat megtartja t│ t├─────────────────────────────────────┼──────────────────────────────────────┤ t│0 cFORCE0 t│0 c10 esetén futó RetroArch mellett is t│ t│0 t│0 takarít t│ t├─────────────────────────────────────┼──────────────────────────────────────┤ t│0 cBATOCERA_STORE_ROOT0, t│0 hol keressen egy Batocera-dobozon t│ t│0 cBATOCERA_PORTS_DIR0 t│0 t│ t├─────────────────────────────────────┼──────────────────────────────────────┤ t│0 cSTORE_ROOT0, cBIN_DIR0 t│0 hol keressen egy asztali gépen t│ t└─────────────────────────────────────┴──────────────────────────────────────┘ Ha egy motor nem tud végezni (fut a RetroArch, nincs felcsatolva a ROM-gyökér), a futás ott megáll, ahelyett hogy törölné azt a motort, amely tudja, mit telepített. A szkript POSIX csh0, nem bash, így a c| sh0 ott is működik, ahol a c/bin/sh0 a dash. A motorok saját telepítői ugyanígy. 1Állapot 1═══════ cstate.json0, 2-es verzió, c:0 kulccsal: p { p "version": 2, p "installed": { p "c64:blessingofra": { "name": "blessingofra", "scope": "c64", "asset": "» p blessingofra-2.0.0.prg", "…": "…" } p } p } A crecord_scope()0 visszaesik a rekord csystem0 mezőjére, mert a Batocera-áruház ezt írta, mielőtt ez a modul létezett. Ott a kettő ugyanaz a sztring volt, így egy telepített doboz migráció nélkül működik tovább, és semmit nem tölt le újra. Egy cversion: 10 fájlt, amelynek a kulcsa a csupasz szoftvernév, az első futáskor újrakulcsoz. 1Verziózás 1═════════ A motorok onnan húzzák le a cwarpstore.py0 fájlt, ahová a telepítőjük cWARPSTORE_RAW_BASE0-e mutat — alapból a cmaster0-ről, így egy itteni változás a következő telepítéskor eljut az áruházhoz, és pont ezért kell a felületet kicsin tartani. Egy áruházrepó rögzítheti is: a 5TTG Batocera Store a motorját és a cwarpstore0-t is rögzített commitról húzza, és kiadás után átírja őket. A c--version0 mindkét motoron kiírja mindkét számot, például c3.1.0 (warpstore c1.2.0)0.