From 479ad7fd8cfd4bfb4a7a30c2d4159245164afa9c Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Fri, 16 Oct 2026 22:07:48 +0200 Subject: [PATCH] fix: arbitrate slots for the target and source --- scripts/generate_pack.py | 6 ++++-- scripts/slots.py | 10 ++++++++-- scripts/verify.py | 3 ++- tests/test_slots.py | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index 0291085a..363bbcbd 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -610,7 +610,8 @@ def generate_pack( validation_index = _build_validation_index(platform_profiles) validation_owners = destination_owners(platform_profiles) slot_overrides = slots.pack_overrides( - config, emu_profiles or {}, db, zip_contents, data_registry + config, emu_profiles or {}, db, zip_contents, data_registry, + target_cores=target_cores, source=source, ) # Filter systems by target if specified @@ -3437,7 +3438,8 @@ def generate_manifest( if data_registry is None: data_registry = load_data_dir_registry(platforms_dir) slot_overrides = slots.pack_overrides( - config, emu_profiles, db, zip_contents, data_registry + config, emu_profiles, db, zip_contents, data_registry, + target_cores=target_cores, source=source, ) def manifest_destination(full_destination: str) -> str: diff --git a/scripts/slots.py b/scripts/slots.py index 2eacb548..4e771559 100644 --- a/scripts/slots.py +++ b/scripts/slots.py @@ -416,6 +416,8 @@ def pack_overrides( db: dict, zip_contents: dict | None = None, data_dir_registry: dict | None = None, + target_cores: set[str] | None = None, + source: str = "full", ) -> dict[str, str]: """Full pack destination -> the file a platform pack serves there instead. @@ -428,10 +430,14 @@ def pack_overrides( """ from common import resolve_platform_cores - if not profiles: + # A baseline-only pack serves what the platform declares, and a target's + # pack answers to the cores that hardware builds: DuckStation does not + # exist on any RetroArch target and still replaced its scph5000.bin. + if not profiles or source == "platform": return {} platform_profiles = { - name: profiles[name] for name in resolve_platform_cores(config, profiles) + name: profiles[name] + for name in resolve_platform_cores(config, profiles, target_cores=target_cores) } mode = config.get("verification_mode", "existence") overrides: dict[str, str] = {} diff --git a/scripts/verify.py b/scripts/verify.py index d0864c38..135f8af7 100644 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -912,7 +912,8 @@ def verify_platform( slot_overrides = { (key[len(base_dest) + 1:] if base_dest and key.startswith(f"{base_dest}/") else key): path for key, path in slots.pack_overrides( - config, emu_profiles or {}, db, zip_contents, data_dir_registry + config, emu_profiles or {}, db, zip_contents, data_dir_registry, + target_cores=target_cores, ).items() } diff --git a/tests/test_slots.py b/tests/test_slots.py index e3d67bc0..d23b6d6d 100644 --- a/tests/test_slots.py +++ b/tests/test_slots.py @@ -715,6 +715,21 @@ class AnArchiveIsClaimedByItsMembers(unittest.TestCase): config["verification_mode"] = "md5" self.assertEqual(slots.find_conflicts(config, self.profiles, self.db, "system"), []) + def test_a_target_without_the_core_keeps_the_pin(self): + """DuckStation exists on no RetroArch target and still replaced the + scph5000.bin System.dat pins in every --target pack.""" + config = self._config("existence", "short") + self.assertTrue(slots.pack_overrides(config, self.profiles, self.db)) + self.assertEqual( + slots.pack_overrides(config, self.profiles, self.db, target_cores={"other"}), {} + ) + + def test_a_baseline_pack_serves_the_baseline(self): + config = self._config("existence", "short") + self.assertEqual( + slots.pack_overrides(config, self.profiles, self.db, source="platform"), {} + ) + def test_a_pin_holding_the_members_is_agreement(self): config = self._config("md5", "full") self.assertEqual(slots.find_conflicts(config, self.profiles, self.db, "system"), [])