mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-17 00:43:29 -05:00
feat: profile the MAME releases recalbox builds
Recalbox ships libretro/mame built at 0.258 and at 0.278, and no profile described either release. mame_hash_scraper gains --release, which reads the BIOS root sets at one mamedev tag and writes a profile pinned to it; mame0258 and mame0278 are generated from it, every source_ref anchored at its tag.
This commit is contained in:
1 parent
d0a4315427
commit
a4da6d205f
5 files changed
+5978
-4
No files matched your search
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -24,7 +24,7 @@ import yaml
|
||||
|
||||
from common import source_yaml_paths, write_text_atomic, yaml_load
|
||||
|
||||
from ._hash_merge import compute_diff, merge_mame_profile
|
||||
from ._hash_merge import _build_contents, _build_source_ref, compute_diff, merge_mame_profile
|
||||
from .mame_parser import parse_mame_source_tree
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -329,6 +329,82 @@ def _run(args: argparse.Namespace) -> None:
|
||||
print("(dry run, no files modified)")
|
||||
|
||||
|
||||
def release_profile(
|
||||
release: str,
|
||||
bios_sets: dict[str, Any],
|
||||
upstream_commit: str,
|
||||
source_commit: str,
|
||||
cores: list[str],
|
||||
reference: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""A profile for one MAME release a platform builds, from its own source.
|
||||
|
||||
Recalbox ships libretro/mame twice, built at 0.258 and at 0.278; the
|
||||
BIOS root sets and their ROMs change between releases, so the current
|
||||
MAME profile does not describe them. Each set keeps the system and the
|
||||
required flag the current profile gives it; the contents and the line
|
||||
are the release's own.
|
||||
"""
|
||||
version = release.removeprefix("mame")
|
||||
version = f"{version[0]}.{version[1:]}" if version.isdigit() else version
|
||||
known = {
|
||||
str(f.get("name")): f for f in reference.get("files") or []
|
||||
if f.get("category") == "bios_zip"
|
||||
}
|
||||
files = []
|
||||
for set_name, data in sorted(bios_sets.items()):
|
||||
name = f"{set_name}.zip"
|
||||
entry: dict[str, Any] = {
|
||||
"name": name,
|
||||
"required": known.get(name, {}).get("required", True),
|
||||
"category": "bios_zip",
|
||||
}
|
||||
if known.get(name, {}).get("system"):
|
||||
entry["system"] = known[name]["system"]
|
||||
entry["source_ref"] = _build_source_ref(data)
|
||||
entry["contents"] = _build_contents(data.get("roms", []))
|
||||
files.append(entry)
|
||||
return {
|
||||
"emulator": f"MAME {version}",
|
||||
"type": "libretro",
|
||||
"core_classification": "frozen_snapshot",
|
||||
"source": "https://github.com/libretro/mame",
|
||||
"upstream": f"https://github.com/mamedev/mame/tree/{release}",
|
||||
"profiled_date": datetime.now(timezone.utc).strftime("%Y-%m-%d"),
|
||||
"source_commit": source_commit,
|
||||
"upstream_commit": upstream_commit,
|
||||
"core_version": version,
|
||||
"display_name": f"Arcade (MAME {version})",
|
||||
"cores": cores,
|
||||
"systems": list(reference.get("systems") or []),
|
||||
"notes": (
|
||||
f"libretro/mame built at the {version} release. BIOS root sets "
|
||||
f"read from mamedev/mame at {release}: the sets and their ROMs "
|
||||
"are that release's, not the current one's."
|
||||
),
|
||||
"files": files,
|
||||
}
|
||||
|
||||
|
||||
def _write_release(args: argparse.Namespace) -> None:
|
||||
"""Write the profile of one MAME release, read from its own tag."""
|
||||
try:
|
||||
_sparse_clone(args.release)
|
||||
bios_sets = parse_mame_source_tree(str(_CLONE_DIR))
|
||||
commit = _get_commit()
|
||||
finally:
|
||||
_cleanup()
|
||||
if not bios_sets or not commit:
|
||||
raise RuntimeError(f"no BIOS root set read at {args.release}")
|
||||
reference = yaml_load((_EMULATORS_DIR / "mame.yml").read_text(encoding="utf-8"))
|
||||
profile = release_profile(
|
||||
args.release, bios_sets, commit, args.source_commit, args.core, reference
|
||||
)
|
||||
text = yaml.safe_dump(profile, sort_keys=False, allow_unicode=True, width=100)
|
||||
write_text_atomic(str(args.profile), text)
|
||||
print(f"{args.profile}: {len(profile['files'])} BIOS root sets at {args.release}")
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="mame_hash_scraper",
|
||||
@@ -349,6 +425,16 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
action="store_true",
|
||||
help="re-fetch even if cache is fresh",
|
||||
)
|
||||
release = parser.add_argument_group(
|
||||
"release profile",
|
||||
"write the profile of one MAME release a platform builds "
|
||||
"(e.g. --release mame0278 --profile emulators/mame0278.yml "
|
||||
"--source-commit <libretro/mame sha> --core mame0278)",
|
||||
)
|
||||
release.add_argument("--release", help="mamedev/mame tag, such as mame0278")
|
||||
release.add_argument("--profile", type=Path, help="profile file to write")
|
||||
release.add_argument("--source-commit", help="libretro/mame commit the platform builds")
|
||||
release.add_argument("--core", action="append", default=[], help="core name, repeatable")
|
||||
return parser
|
||||
|
||||
|
||||
@@ -359,6 +445,19 @@ def main() -> None:
|
||||
)
|
||||
parser = build_parser()
|
||||
args = parser.parse_args()
|
||||
if args.release or args.profile:
|
||||
missing = [
|
||||
flag for flag, value in (
|
||||
("--release", args.release), ("--profile", args.profile),
|
||||
("--source-commit", args.source_commit), ("--core", args.core),
|
||||
) if not value
|
||||
]
|
||||
if missing:
|
||||
parser.error(f"a release profile needs {', '.join(missing)}")
|
||||
if args.dry_run or args.json:
|
||||
parser.error("--release writes a profile; --dry-run and --json do not apply")
|
||||
_write_release(args)
|
||||
return
|
||||
_run(args)
|
||||
|
||||
|
||||
|
||||
@@ -369,6 +369,47 @@ class TheScraperClonesTheReleaseItLabels(unittest.TestCase):
|
||||
self.assertEqual(data["commit"], "c" * 40)
|
||||
|
||||
|
||||
class AReleaseProfileDescribesItsOwnRelease(unittest.TestCase):
|
||||
"""Recalbox builds libretro/mame at 0.258 and at 0.278; the current
|
||||
MAME profile described neither. A release profile carries that
|
||||
release's sets and pins, and keeps the system the current profile
|
||||
gives a set."""
|
||||
|
||||
def test_sets_pins_and_systems(self):
|
||||
from scripts.scraper.mame_hash_scraper import release_profile
|
||||
|
||||
bios_sets = {
|
||||
"neogeo": {"source_file": "src/mame/neogeo/neogeo.cpp", "source_line": 10,
|
||||
"roms": [{"name": "sp-s2.sp1", "size": 131072, "crc32": "9036d879"}]},
|
||||
"newset": {"source_file": "src/mame/x/x.cpp", "source_line": 5, "roms": []},
|
||||
}
|
||||
reference = {"systems": ["snk-neogeo-mvs"], "files": [
|
||||
{"name": "neogeo.zip", "category": "bios_zip", "system": "snk-neogeo-mvs",
|
||||
"required": True},
|
||||
{"name": "gone.zip", "category": "bios_zip", "system": "x"},
|
||||
]}
|
||||
profile = release_profile(
|
||||
"mame0278", bios_sets, "a" * 40, "b" * 40, ["mame0278"], reference
|
||||
)
|
||||
self.assertEqual(profile["core_version"], "0.278")
|
||||
self.assertEqual(profile["upstream"], "https://github.com/mamedev/mame/tree/mame0278")
|
||||
self.assertEqual((profile["upstream_commit"], profile["source_commit"]),
|
||||
("a" * 40, "b" * 40))
|
||||
self.assertEqual(profile["cores"], ["mame0278"])
|
||||
files = {f["name"]: f for f in profile["files"]}
|
||||
self.assertEqual(sorted(files), ["neogeo.zip", "newset.zip"])
|
||||
self.assertEqual(files["neogeo.zip"]["system"], "snk-neogeo-mvs")
|
||||
self.assertNotIn("system", files["newset.zip"])
|
||||
self.assertEqual(files["neogeo.zip"]["source_ref"], "src/mame/neogeo/neogeo.cpp:10")
|
||||
|
||||
def test_a_release_profile_is_left_out_of_the_current_refresh(self):
|
||||
from scripts.scraper.mame_hash_scraper import _find_mame_profiles
|
||||
|
||||
names = {path.name for path in _find_mame_profiles()}
|
||||
self.assertIn("mame.yml", names)
|
||||
self.assertFalse({"mame0258.yml", "mame0278.yml"} & names)
|
||||
|
||||
|
||||
class TestFbneoMerge(unittest.TestCase):
|
||||
"""Tests for merge_fbneo_profile."""
|
||||
|
||||
|
||||
+3
-3
@@ -658,8 +658,8 @@ Located in `scripts/scraper/`. Each inherits `BaseScraper` and implements `fetch
|
||||
| Scraper | Source | Format |
|
||||
|---------|--------|--------|
|
||||
| `libretro_scraper` | System.dat + core-info .info files | clrmamepro DAT |
|
||||
| `batocera_scraper` | batocera-systems script | Python dict |
|
||||
| `recalbox_scraper` | es_bios.xml | XML |
|
||||
| `batocera_scraper` | batocera-systems script, es_systems.yml (cores) | Python dict, YAML |
|
||||
| `recalbox_scraper` | es_bios.xml, recalbox-romfs2 system.ini files (cores) | XML, INI |
|
||||
| `retrobat_scraper` | batocera-systems.json | JSON |
|
||||
| `emudeck_scraper` | checkBIOS.sh | Bash + CSV |
|
||||
| `retrodeck_scraper` | component manifests | JSON per component |
|
||||
@@ -668,7 +668,7 @@ Located in `scripts/scraper/`. Each inherits `BaseScraper` and implements `fetch
|
||||
| `misterfpga_scraper` | BiosDB_MiSTer bios_db.json.zip | JSON in ZIP |
|
||||
| `coreinfo_scraper` | .info files from libretro-core-info | INI-like |
|
||||
| `bizhawk_scraper` | FirmwareDatabase.cs | C# source |
|
||||
| `mame_hash_scraper` | mamedev/mame source tree | C source (sparse clone) |
|
||||
| `mame_hash_scraper` | mamedev/mame source tree; `--release mameNNNN` writes the profile of one release a platform builds | C source (sparse clone) |
|
||||
| `fbneo_hash_scraper` | FBNeo source tree | C source (sparse clone) |
|
||||
|
||||
Internal modules: `base_scraper.py` (abstract base with `_fetch_raw()` caching
|
||||
|
||||
Reference in new issue
Block a user