chore: merge games on card installer mode

This commit is contained in:
Abdessamad Derraz committed 2026-11-03 21:06:04 +01:00
commit af2e930d32
71 files changed
+4244 -89

No files matched your search

+4 -3
View File
@@ -43,11 +43,12 @@ KEY_TYPES: dict[str, dict] = {
"files", "files_done", "files_total", "bytes", "bytes_done", "bytes_total",
"bytes_local", "bytes_network", "size", "present", "missing", "wrong_hash",
"bytes_needed", "data_missing", "not_installable", "installed", "up_to_date",
"pending", "code",
"pending", "code", "games", "recognised", "not_games",
), _COUNT),
**dict.fromkeys(("truncated", "ok", "interrupted"), _FLAG),
**dict.fromkeys(("truncated", "ok", "interrupted", "required_only"), _FLAG),
**dict.fromkeys(("systems", "other_drives", "dests", "written"), _NAMES),
**dict.fromkeys(("platforms", "failed", "skipped", "left_out", "kept"), _RECORDS),
**dict.fromkeys(("platforms", "failed", "skipped", "left_out", "kept", "found",
"fallback"), _RECORDS),
}
+48 -11
View File
@@ -311,27 +311,42 @@ def build_setups(
counts["profile"] += 1
if resolution.systems:
counts["resolved"] += 1
def fallback_keys(chosen: str | None) -> list[str]:
"""The fallback sets of the folder's systems under one core,
computed once per platform."""
keys = []
table = fallbacks.setdefault(platform, {})
for system in resolution.systems:
key = f"{system}|{chosen or ''}"
if key not in table:
table[key] = fallback_set(manifest, required[platform], profiles, system, chosen)
keys.append(key)
return keys
sets_known = manifest is not None and bool(resolution.systems)
boards = {}
for board, spec in sorted((row.get("board_defaults") or {}).items()):
boards[board] = {"core": spec["core"]}
if cores.resolve(spec["core"]):
boards[board]["profile"] = cores.resolve(spec["core"])
board_profile = cores.resolve(spec["core"])
if board_profile:
boards[board]["profile"] = board_profile
if board_profile in arcade:
boards[board]["arcade"] = board_profile
if sets_known:
# A card moves between boards, and the installer reads
# it on a computer: each board's core has its set.
boards[board]["fallback"] = fallback_keys(board_profile)
if boards:
published["board_defaults"] = boards
if profile and profile in arcade:
published["arcade"] = profile
elif row.get("arcade"):
published["arcade"] = True
if manifest is not None and resolution.systems:
keys = []
table = fallbacks.setdefault(platform, {})
for system in resolution.systems:
key = f"{system}|{profile or ''}"
if key not in table:
table[key] = fallback_set(manifest, required[platform], profiles, system, profile)
keys.append(key)
if sets_known:
keys = fallback_keys(profile)
published["fallback"] = keys
if any(table[k]["files"] for k in keys):
if any(fallbacks[platform][k]["files"] for k in keys):
counts["fallback"] += 1
published["source_ref"] = row["source_ref"]
folders.append(published)
@@ -476,6 +491,27 @@ def _entry(text: str) -> dict:
}
def folder_systems(setups: dict[str, dict]) -> dict[str, list[str]]:
"""Every folder name a setup gives a system, casefolded, with the systems
any setup reads there, and each system id under its own name.
What a games folder on a computer is read with when its setup names no
folder of its own (RetroArch): a name two setups give two systems keeps
both.
"""
names: dict[str, set[str]] = {}
for doc in setups.values():
for row in doc["folders"]:
systems = row["systems"]
if not systems:
continue
for name in [row["folder"], *(row.get("aliases") or [])]:
names.setdefault(str(name).casefold(), set()).update(systems)
for system in systems:
names.setdefault(system.casefold(), set()).add(system)
return {name: sorted(systems) for name, systems in sorted(names.items())}
def render(output: Path = OUTPUT, inputs: Inputs = Inputs()) -> tuple[dict[Path, str], dict]:
"""Every published file's text, keyed by its path, and the coverage."""
resolver = SystemResolver.from_repo(inputs.emulators, inputs.platforms)
@@ -514,6 +550,7 @@ def render(output: Path = OUTPUT, inputs: Inputs = Inputs()) -> tuple[dict[Path,
containers = _load_yaml(inputs.games / "headers.yml").get("containers")
if containers:
index["containers"] = containers
index["folders"] = folder_systems(setups)
files[output / "index.json"] = dumps(index)
coverage = {"setups": setup_cov, "systems": system_cov, "arcade": sorted(arcade)}
return files, coverage
+7 -1
View File
@@ -28,7 +28,9 @@ and ``BIOS[].filename`` the archive when it differs from the name
Output: games/arcade/<profile>.json. CHD games are listed, not resolved: a
CHD is game content. A ``romof`` pointing outside the sets read is listed
with its target, never guessed.
with its target, never guessed. The games that load no BIOS set
(``no_bios``) and every BIOS set (``bios_sets``) are listed too: a set name
on a card that none of the lists holds is one the core does not know.
"""
from __future__ import annotations
@@ -224,6 +226,8 @@ def build_index(
"devices": {k: sorted(v) for k, v in sorted(devices.items())},
"chd": sorted(n for n, e in games.items() if e.disks),
"missing_parents": dict(sorted(missing.items())),
"no_bios": sorted(set(games) - with_bios - set(missing)),
"bios_sets": sorted(bios_names),
"counts": {
"sets": len(sets),
"games": len(games),
@@ -424,6 +428,8 @@ def flycast_index(source: str) -> dict:
"devices": {},
"chd": sorted(chd),
"missing_parents": dict(sorted(unknown.items())),
"no_bios": [],
"bios_sets": sorted(set(archive_of.values())),
"counts": {
"sets": len(games) + len(archive_of),
"games": len(games),
+3 -2
View File
@@ -882,8 +882,9 @@ GLANCE_HEADING = "## Options at a glance"
GLANCE_GROUPS: tuple[tuple[str, tuple[str, ...]], ...] = (
("Where and for what", ("--platform", "--dest", "--target", "--every-board", "--save-dir",
"--romm-firmware", "--standalone-copies", "--add-app")),
("Fewer files", ("--system", "--core", "--emulator", "--region", "--no-game-data",
"--declared-only", "--installed-cores", "--cores-dir")),
("Fewer files", ("--for-games", "--required-only", "--system", "--core", "--emulator",
"--region", "--no-game-data", "--declared-only", "--installed-cores",
"--cores-dir")),
("Look first", ("--check", "--dry-run", "--list-platforms", "--list-targets",
"--list-systems", "--list-cores", "--list-emulators")),
("From files you have", ("--from", "--from-pack", "--manifest", "--offline", "--restore")),