feat: transcribe bios search orders into priority

This commit is contained in:
Abdessamad Derraz committed 2026-08-11 19:18:30 +02:00
1 parent d862de9a2e
commit 4b8d7baac5
3 files changed
+54 -8

No files matched your search

+11 -6
View File
@@ -19,8 +19,10 @@ exactly the file the core may load. Where the order is not declared the group
is reported undecidable and every candidate is kept: picking one would be the
arbitrary selection this exists to remove.
The scale is only meaningful inside one system's candidate set. Profiles that
cover the same system must rank on the same scale.
The scale is only meaningful inside one emulator's candidate set. When two
profiles rank the same file differently -- pcsx1 walks scph1001 first while
DuckStation prefers scph5501 -- the pack serves both cores, so neither order
may win: the file is marked conflicting and its group stays undecidable.
"""
from __future__ import annotations
@@ -43,12 +45,16 @@ def build_slot_index(profiles: dict) -> dict[str, dict]:
path = f.get("path") or ""
for key in {path, name} - {""}:
entry = index.setdefault(
key, {"rank": None, "regions": set(), "emulators": []}
key,
{"rank": None, "conflict": False, "regions": set(),
"emulators": []},
)
entry["regions"] |= {str(r) for r in (f.get("region") or [])}
rank = f.get("priority")
if rank is not None:
current = entry["rank"]
if current is not None and current != rank:
entry["conflict"] = True
entry["rank"] = (
rank if current is None else min(current, rank)
)
@@ -96,9 +102,8 @@ def resolve_slot_drops(
keep.add(destination)
continue
tier = tuple(sorted(entry["regions"]))
tiers.setdefault((group_id, tier), []).append(
(destination, entry["rank"])
)
rank = None if entry.get("conflict") else entry["rank"]
tiers.setdefault((group_id, tier), []).append((destination, rank))
for (group_id, tier), candidates in tiers.items():
if len(candidates) < 2:
+34 -2
View File
@@ -173,8 +173,12 @@ class TestRepoProfiles(unittest.TestCase):
def test_lowest_priority_picks_the_reference_playstation_bios(self):
"""DuckStation ranks scph5501 at 5 and de-prioritizes by raising the
number, so the US slot must resolve to it and not to a PS2 image."""
index = slot.build_slot_index(self.profiles)
number, so on its own scale the US slot resolves to it. The merged
index is a different story: pcsx1 disagrees, and the conflict test
below asserts that neither order wins there."""
index = slot.build_slot_index(
{"duckstation": self.profiles["duckstation"]}
)
ds = self.profiles.get("duckstation")
if not ds:
self.skipTest("duckstation profile not present")
@@ -192,6 +196,34 @@ class TestRepoProfiles(unittest.TestCase):
kept = {n for n, _ in members} - drops
self.assertEqual(kept, {"scph5501.bin"})
def test_conflicting_cross_profile_orders_decide_nothing(self):
"""pcsx1 walks scph1001 first; DuckStation prefers scph5501. The pack
serves both cores, so neither order may drop the other's first pick."""
index = slot.build_slot_index(self.profiles)
for name in ("scph1001.bin", "scph5501.bin"):
entry = index.get(name)
if entry is None:
self.skipTest(f"{name} not in any profile")
if not index["scph1001.bin"].get("conflict"):
self.skipTest("no conflicting ranks declared yet")
drops, _u = slot.resolve_slot_drops(
{"psx": _pairs("scph1001.bin", "scph5501.bin", "scph7001.bin")},
index,
)
self.assertEqual(drops & {"scph1001.bin", "scph5501.bin"}, set())
def test_numero_search_order_decides_its_slot(self):
"""numero is alone on ti-83 and ranks all three ROMs, so this is the
one slot the repo can currently decide end to end."""
index = slot.build_slot_index(self.profiles)
if "ti83se.rom" not in index:
self.skipTest("numero profile not present")
drops, undecidable = slot.resolve_slot_drops(
{"ti-83": _pairs("ti83se.rom", "ti83plus.rom", "ti83.rom")}, index
)
self.assertEqual(drops, {"ti83plus.rom", "ti83.rom"})
self.assertEqual(undecidable, [])
def test_ties_leave_the_group_untouched(self):
"""Japanese PlayStation ties at 5, so nothing may be dropped there."""
index = slot.build_slot_index(self.profiles)
+9
View File
@@ -136,6 +136,15 @@ Where no such list is declared, the group is left untouched and counted:
63 slot(s) with no declared order: every candidate kept
```
Two rules keep a declared order from overreaching:
- **Cores that disagree cancel out.** pcsx1 walks `scph1001` first while
DuckStation prefers `scph5501`; the pack serves both cores, so neither order
wins and both files stay.
- **A slot mixing unrelated roles stays open.** px68k's IPL ROMs are ranked,
but its character ROM shares the same system and carries no rank, so the
whole group is kept. Ordering an IPL against a font would be meaningless.
That number is the remaining work, not a failure. Picking a file without a
declared order would be the arbitrary selection this exists to remove, and it
could drop the one the core would have loaded.