mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-11 20:43:50 -06:00
feat: read ES-DE MAME search paths
ES-DE starts standalone MAME with -rompath %GAMEDIR%\;%ROMPATH%/<system> in 78 live commands across 54 systems (resources/systems/linux/ es_systems.xml at retrodeck-main-20261103-162710, 15e1b236; two more are commented out). The command line outranks mame.ini, so RetroDECK's MAME reads its sets in the roms folder each command names and in no BIOS folder. The ES-DE rom folders parser now records, per folder, the folders a standalone command passes as its ROM search path and the machines it starts, or that the game is the machine (%BASENAME%). Rescraped at the pinned revisions: retrodeck, emudeck and emudeck-windows gain these records and nothing else. A command reads the sets its machines load: the machine's own set, the BIOS sets on its romof chain and the device sets with ROMs it instantiates, from games/arcade/mame.json (mame0289 -listxml). That index now also lists the game and device sets of each driver source file, so a %BASENAME% folder reads for its board: neogeo and stv by their BIOS root, cps1-3 and model2 by source file, daphne and laserdisc by the laserdisc player devices, gameandwatch and lcdgames by the handheld sources, any other (arcade, mame, consolearcade) for every machine. The published installer copy of the index leaves the sources out. Manifests: RetroDECK gains 1399 files, 378.2 MB, below roms/. Of the 219 sets named as read outside the BIOS folder, 58 reach 146 files (25.9 MB), 161 stay named, no command's machine reading them. 441 sets RetroDECK's list also declares at bios/ reach 1253 files (352.3 MB), 429 each in arcade and mame and 480 in consolearcade. No other platform changes.
This commit is contained in:
1 parent
a8cfd20f49
commit
7a3d91585d
14 files changed
+1452
-10
No files matched your search
@@ -222,6 +222,13 @@ def build_index(
|
||||
for device in set(entry.devices) & device_roms:
|
||||
devices.setdefault(device, set()).add(name)
|
||||
with_bios = {g for members in bios.values() for g in members}
|
||||
# The source file of each game and device set: what a launcher that
|
||||
# starts whatever set a folder holds selects a folder's machines by
|
||||
# (ES-DE runs MAME on any CPS-2 set of roms/cps2).
|
||||
sources: dict[str, set[str]] = {}
|
||||
for name, entry in sets.items():
|
||||
if entry.source and (name in games or name in device_roms):
|
||||
sources.setdefault(entry.source, set()).add(archive(name, name))
|
||||
return {
|
||||
"bios": {k: sorted(v) for k, v in sorted(bios.items())},
|
||||
"devices": {k: sorted(v) for k, v in sorted(devices.items())},
|
||||
@@ -229,6 +236,7 @@ def build_index(
|
||||
"missing_parents": dict(sorted(missing.items())),
|
||||
"no_bios": sorted(set(games) - with_bios - set(missing)),
|
||||
"bios_sets": sorted(bios_names),
|
||||
**({"sources": {k: sorted(v) for k, v in sorted(sources.items())}} if sources else {}),
|
||||
"counts": {
|
||||
"sets": len(sets),
|
||||
"games": len(games),
|
||||
|
||||
@@ -36,7 +36,7 @@ SETUP_KEYS = (
|
||||
)
|
||||
ROW_KEYS = (
|
||||
"folder", "name", "aliases", "extensions", "files", "core", "emulator", "source_ref",
|
||||
"board_defaults", "arcade", "note",
|
||||
"board_defaults", "arcade", "searched_by", "note",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ Formats, by the shape of the source:
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import html
|
||||
import json
|
||||
import re
|
||||
import shlex
|
||||
@@ -167,7 +168,7 @@ def _all_lines(text: str, pattern: str) -> dict[str, list[int]]:
|
||||
for number, line in enumerate(text.splitlines(), 1):
|
||||
match = re.search(pattern, line)
|
||||
if match:
|
||||
out.setdefault(match.group(1).strip(), []).append(number)
|
||||
out.setdefault(html.unescape(match.group(1)).strip(), []).append(number)
|
||||
return out
|
||||
|
||||
|
||||
@@ -522,6 +523,64 @@ def _alternative_emulators(text: str, function: str) -> dict[str, tuple[str, int
|
||||
return out
|
||||
|
||||
|
||||
_ROMPATH_OPTIONS = ("-rompath", "-rp")
|
||||
|
||||
|
||||
def _searched_by(commands: list[tuple[str, str, int | None]], key: str, path: str) -> list[dict]:
|
||||
"""The ROM folders each standalone emulator's commands pass it, by emulator.
|
||||
|
||||
ES-DE starts standalone MAME with `-rompath %GAMEDIR%\\;%ROMPATH%/<system>`
|
||||
and a machine, or %BASENAME% where the game is the machine. The command
|
||||
line outranks mame.ini. %GAMEDIR% is the game's own folder, no folder a
|
||||
pack fills.
|
||||
"""
|
||||
found: dict[str, dict] = {}
|
||||
for _label, command, line in commands:
|
||||
emulator = _EMULATOR.search(command)
|
||||
if emulator is None or _RA_CORE.search(command):
|
||||
continue
|
||||
words = command.replace("\\;", ";").split()
|
||||
at = next((i for i, w in enumerate(words) if w in _ROMPATH_OPTIONS), None)
|
||||
if at is None or at + 1 >= len(words):
|
||||
continue
|
||||
reads = [
|
||||
folder for part in words[at + 1].split(";")
|
||||
if (folder := _strip_prefix(part, ["%ROMPATH%/", "%ROMPATH%\\"]))
|
||||
]
|
||||
if not reads:
|
||||
continue
|
||||
name = emulator.group(1).lower()
|
||||
record = found.setdefault(name, {"emulator": name, "reads": [], "machines": [],
|
||||
"any_machine": False, "lines": []})
|
||||
record["reads"] += [r for r in reads if r not in record["reads"]]
|
||||
machine = words[at + 2] if at + 2 < len(words) else ""
|
||||
if not machine or machine.startswith("%"):
|
||||
record["any_machine"] = True
|
||||
elif machine not in record["machines"]:
|
||||
record["machines"].append(machine)
|
||||
record["lines"].append(line)
|
||||
rows = []
|
||||
for record in found.values():
|
||||
row = {"emulator": record["emulator"], "reads": record["reads"]}
|
||||
if record["machines"]:
|
||||
row["machines"] = record["machines"]
|
||||
if record["any_machine"]:
|
||||
row["any_machine"] = True
|
||||
row["source_ref"] = _ref(key, path, *record["lines"])
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
def _command_lines(text: str) -> dict[str, list[int]]:
|
||||
"""Command text -> the lines it is written on, in file order."""
|
||||
out: dict[str, list[int]] = {}
|
||||
for number, line in enumerate(text.splitlines(), 1):
|
||||
match = re.search(r"<command\b[^>]*>([^<]*)</command>", line)
|
||||
if match:
|
||||
out.setdefault(match.group(1).strip(), []).append(number)
|
||||
return out
|
||||
|
||||
|
||||
@register("esde")
|
||||
def esde(spec: dict, fetcher: Fetcher) -> list[dict]:
|
||||
"""Each system of ES-DE's list whose path is %ROMPATH%/<folder>.
|
||||
@@ -537,13 +596,21 @@ def esde(spec: dict, fetcher: Fetcher) -> list[dict]:
|
||||
key, path = item["source"], item["path"]
|
||||
text = _lenient_xml(fetcher.text(key, path))
|
||||
lines = _first_lines(text, r"<name>([^<]+)</name>")
|
||||
command_lines = _command_lines(text)
|
||||
for name, rom_path, extensions, commands in _esde_systems(text, path):
|
||||
folder = _strip_prefix(rom_path, ["%ROMPATH%/", "%ROMPATH%\\"])
|
||||
if not name or not folder:
|
||||
continue
|
||||
start = lines.get(name) or 0
|
||||
placed = [
|
||||
(label, command, next(
|
||||
(n for n in command_lines.get(command, []) if n >= start), None))
|
||||
for label, command in commands
|
||||
]
|
||||
systems[name] = {
|
||||
"folder": folder, "extensions": extensions, "commands": commands,
|
||||
"ref": _ref(key, path, lines.get(name)),
|
||||
"searched_by": _searched_by(placed, key, path),
|
||||
}
|
||||
alternatives: dict[str, tuple[str, int]] = {}
|
||||
alt = params.get("alternatives")
|
||||
@@ -580,6 +647,7 @@ def esde(spec: dict, fetcher: Fetcher) -> list[dict]:
|
||||
"emulator": emulator,
|
||||
"source_ref": "; ".join(refs),
|
||||
"note": note,
|
||||
"searched_by": system["searched_by"] or None,
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
Reference in new issue
Block a user