diff --git a/emulators/mame0258.yml b/emulators/mame0258.yml index 0d6149de..32f0409e 100644 --- a/emulators/mame0258.yml +++ b/emulators/mame0258.yml @@ -10,6 +10,8 @@ core_version: '0.258' display_name: Arcade (MAME 0.258) cores: - mame0258 +built_by: +- recalbox systems: - snk-neogeo-mvs - snk-neogeo-aes diff --git a/emulators/mame0278.yml b/emulators/mame0278.yml index b0bfa74b..e65a87b7 100644 --- a/emulators/mame0278.yml +++ b/emulators/mame0278.yml @@ -10,6 +10,8 @@ core_version: '0.278' display_name: Arcade (MAME 0.278) cores: - mame0278 +built_by: +- recalbox systems: - snk-neogeo-mvs - snk-neogeo-aes diff --git a/schemas/emulator.schema.json b/schemas/emulator.schema.json index 2eeeca7d..e9baf222 100644 --- a/schemas/emulator.schema.json +++ b/schemas/emulator.schema.json @@ -101,6 +101,16 @@ "other" ] }, + "built_by": { + "description": "The platforms that compile this libretro build themselves (Recalbox's mame0278). It is reached by a platform naming it in its cores list, never by all_libretro: the libretro buildbot does not publish it.", + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 1, + "uniqueItems": true + }, "source": { "type": [ "string", diff --git a/scripts/common.py b/scripts/common.py index a2ba4cb4..25d9d766 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -1694,12 +1694,18 @@ def resolve_platform_cores( """ cores_config = config.get("cores") - if cores_config == "all_libretro": - result = { + def every_libretro() -> set[str]: + # A build only some platforms compile (built_by) is reached by name: + # the buildbot RetroArch installs from does not publish it. + return { name for name, p in profiles.items() if "libretro" in p.get("type", "") and p.get("type") != "alias" + and not p.get("built_by") } + + if cores_config == "all_libretro": + result = every_libretro() elif isinstance(cores_config, list): core_set = {str(c) for c in cores_config} index = upstream_profile_index(profiles) @@ -1712,11 +1718,7 @@ def resolve_platform_cores( # profiles with explicitly listed standalone cores (e.g. RetroDECK # ships RetroArch + standalone emulators) if "all_libretro" in core_set or "retroarch" in core_set: - result |= { - name - for name, p in profiles.items() - if "libretro" in p.get("type", "") and p.get("type") != "alias" - } + result |= every_libretro() else: # Fallback: system ID intersection with normalization norm_plat_systems = {_norm_system_id(s) for s in config.get("systems", {})} @@ -1725,6 +1727,7 @@ def resolve_platform_cores( for name, p in profiles.items() if {_norm_system_id(s) for s in p.get("systems", [])} & norm_plat_systems and p.get("type") != "alias" + and not p.get("built_by") } if target_cores is not None: diff --git a/scripts/scraper/mame_hash_scraper.py b/scripts/scraper/mame_hash_scraper.py index 3653ae40..3274007f 100644 --- a/scripts/scraper/mame_hash_scraper.py +++ b/scripts/scraper/mame_hash_scraper.py @@ -336,6 +336,7 @@ def release_profile( source_commit: str, cores: list[str], reference: dict[str, Any], + built_by: list[str], ) -> dict[str, Any]: """A profile for one MAME release a platform builds, from its own source. @@ -376,6 +377,7 @@ def release_profile( "core_version": version, "display_name": f"Arcade (MAME {version})", "cores": cores, + "built_by": built_by, "systems": list(reference.get("systems") or []), "notes": ( f"libretro/mame built at the {version} release. BIOS root sets " @@ -398,7 +400,8 @@ def _write_release(args: argparse.Namespace) -> None: 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 + args.release, bios_sets, commit, args.source_commit, args.core, reference, + args.built_by, ) text = yaml.safe_dump(profile, sort_keys=False, allow_unicode=True, width=100) write_text_atomic(str(args.profile), text) @@ -429,12 +432,16 @@ def build_parser() -> argparse.ArgumentParser: "release profile", "write the profile of one MAME release a platform builds " "(e.g. --release mame0278 --profile emulators/mame0278.yml " - "--source-commit --core mame0278)", + "--source-commit --core mame0278 --built-by recalbox)", ) 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") + release.add_argument( + "--built-by", action="append", default=[], + help="platform that compiles this build, repeatable", + ) return parser @@ -450,6 +457,7 @@ def main() -> None: flag for flag, value in ( ("--release", args.release), ("--profile", args.profile), ("--source-commit", args.source_commit), ("--core", args.core), + ("--built-by", args.built_by), ) if not value ] if missing: diff --git a/tests/test_e2e.py b/tests/test_e2e.py index 3a99e0f0..a1b7d4d5 100644 --- a/tests/test_e2e.py +++ b/tests/test_e2e.py @@ -1128,6 +1128,22 @@ class TestE2E(unittest.TestCase): result = resolve_platform_cores(config, profiles) self.assertEqual(result, {"fceumm", "gambatte"}) + def test_a_build_a_platform_compiles_is_reached_by_name(self): + """Recalbox compiles libretro/mame at 0.258 and 0.278; the buildbot + RetroArch installs from does not, so all_libretro must not reach + them while a platform naming them does.""" + profiles = { + "mame": {"type": "standalone + libretro", "systems": ["arcade"], "files": []}, + "mame0278": {"type": "libretro", "built_by": ["recalbox"], + "cores": ["mame0278"], "systems": ["arcade"], "files": []}, + } + everyone = {"cores": "all_libretro", "systems": {}} + self.assertEqual(resolve_platform_cores(everyone, profiles), {"mame"}) + retroarch_plus = {"cores": ["retroarch"], "systems": {}} + self.assertEqual(resolve_platform_cores(retroarch_plus, profiles), {"mame"}) + recalbox = {"cores": ["mame0278"], "systems": {}} + self.assertEqual(resolve_platform_cores(recalbox, profiles), {"mame0278"}) + def test_resolve_cores_explicit_list(self): """Explicit cores list matches against profile dict keys.""" config = {"cores": ["fbneo", "opera"], "systems": {"arcade": {"files": []}}} diff --git a/tests/test_hash_merge.py b/tests/test_hash_merge.py index cce52fe3..9336bbb6 100644 --- a/tests/test_hash_merge.py +++ b/tests/test_hash_merge.py @@ -389,13 +389,15 @@ class AReleaseProfileDescribesItsOwnRelease(unittest.TestCase): {"name": "gone.zip", "category": "bios_zip", "system": "x"}, ]} profile = release_profile( - "mame0278", bios_sets, "a" * 40, "b" * 40, ["mame0278"], reference + "mame0278", bios_sets, "a" * 40, "b" * 40, ["mame0278"], reference, + ["recalbox"], ) 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"]) + self.assertEqual(profile["built_by"], ["recalbox"]) 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")