feat: read Recalbox launchers from configgen

The scraper now records, from configgen at the pinned tag, the names each Recalbox launcher tries and where it hands them: the Hatari TOS cascades (standalone, hatari and hatarib cores), GSplus, Amiberry kickstarts, the PCSX2 region choice, the Dolphin IPL presence test, xemu, the mupen64plus 64DD IPL, the Mini vMac boot disk and the o2em_bios option. The system_directory libretroRetroarch gives each core, and the per-system overrides after it, are passes_path records.
This commit is contained in:
Abdessamad Derraz committed 2026-10-20 20:59:51 +02:00
1 parent 4465edcd0a
commit fe9a081cfb
5 files changed
+2789 -4

No files matched your search

File diff suppressed because it is too large. Load diff
+22 -3
View File
@@ -18,6 +18,8 @@ from __future__ import annotations
from common import parse_untrusted_xml
from .base_scraper import BaseScraper, BiosRequirement, fetch_bytes, requirement_entry
from .recalbox_launchers import SOURCE_FILES as LAUNCHER_FILES
from .recalbox_launchers import LauncherShapeError, extract_launchers
PLATFORM_NAME = "recalbox"
@@ -218,9 +220,14 @@ class Scraper(BaseScraper):
def _system_inis(self, systems: list[str]) -> list[str]:
"""Every system's system.ini at the tag, read in batches."""
paths = [f"{SYSTEMS_DIR}/{system}/system.ini" for system in systems]
texts = self._blobs(paths)
return [texts[path] for path in paths]
def _blobs(self, paths: list[str]) -> dict[str, str]:
"""The files at `paths` at the tag, read in batches."""
import json
paths = [f"{SYSTEMS_DIR}/{system}/system.ini" for system in systems]
texts: dict[str, str] = {}
for start in range(0, len(paths), BLOBS_PER_QUERY):
batch = paths[start:start + BLOBS_PER_QUERY]
@@ -236,8 +243,19 @@ class Scraper(BaseScraper):
texts.update({n["path"]: n["rawBlob"] for n in nodes if n.get("rawBlob")})
missing = [path for path in paths if path not in texts]
if missing:
raise RuntimeError(f"no system.ini at {self.tag} for {', '.join(missing[:5])}")
return [texts[path] for path in paths]
raise RuntimeError(f"nothing at {self.tag} for {', '.join(missing[:5])}")
return texts
def _fetch_launchers(self) -> list[dict]:
"""Launcher records read from configgen at the scraped tag."""
texts = self._blobs(list(LAUNCHER_FILES))
def read(path: str) -> str:
if path not in texts:
raise LauncherShapeError(f"{path} is read but not in SOURCE_FILES")
return texts[path]
return extract_launchers(read)
def _fetch_cores(self) -> tuple[list[str], list[str], list[str]]:
"""Every core Recalbox's systems offer, those it runs standalone, and
@@ -379,6 +397,7 @@ class Scraper(BaseScraper):
# Launched both ways: each layout gets its files.
**({"dual_mode_cores": dual} if dual else {}),
"systems": systems,
"launchers": self._fetch_launchers(),
}