mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
feat: transcribe bios search orders into priority
This commit is contained in:
1 parent
d862de9a2e
commit
4b8d7baac5
3 files changed
+54
-8
No files matched your search
+11
-6
@@ -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
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in new issue
Block a user