mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-23 12:19:13 -05:00
fix: count alias readers in a file's requirers
Ymir reads sega_101.bin or saturn_bios.bin, so the sega_101.bin entry carries saturn_bios.bin as an alias. kronos, yabause and yabasanshiro open saturn_bios.bin and fall back to sega_101.bin: they were in that entry's _cores but not its _required_by, while their saturn_bios.bin entry had them requiring it. A reader that requires one of an entry's aliases now requires the entry. No reader is added, and same-name entries kept apart by path are left alone. No export changes.
This commit is contained in:
1 parent
f19a8f99d3
commit
566d36275f
2 files changed
+78
No files matched your search
@@ -200,6 +200,36 @@ def _same_file(files: list[dict], file_entry: dict, emu_name: str) -> dict | Non
|
||||
)
|
||||
|
||||
|
||||
def _require_by_slot(files: list[dict]) -> None:
|
||||
"""A core that requires a name an entry answers for requires the entry.
|
||||
|
||||
Merged by name, one core's alternatives land in several entries. Ymir
|
||||
reads sega_101.bin, mpr-17933.bin or saturn_bios.bin, so the sega_101.bin
|
||||
entry carries those aliases. kronos, yabause and yabasanshiro open
|
||||
saturn_bios.bin first and sega_101.bin as a fallback: they sat in that
|
||||
entry's _cores, out of its _required_by, while their saturn_bios.bin entry
|
||||
had them requiring it, and a platform line paired through the alias read
|
||||
them as optional. A core already among the entry's readers that requires
|
||||
one of its aliases, as another entry of the system, is one of its
|
||||
requirers. No reader is added.
|
||||
"""
|
||||
required_by_name: dict[str, set[str]] = {}
|
||||
for entry in files:
|
||||
required_by_name.setdefault(entry["name"].lower(), set()).update(
|
||||
entry.get("_required_by", ())
|
||||
)
|
||||
for entry in files:
|
||||
# Only the aliases: entries sharing the entry's own name are other
|
||||
# files that name already kept apart (pak0.pak under each game).
|
||||
names = {str(alias).lower() for alias in entry.get("aliases") or ()}
|
||||
names.discard(entry["name"].lower())
|
||||
requirers = set().union(*(required_by_name.get(n, set()) for n in names))
|
||||
added = (requirers & entry.get("_cores", set())) - entry.get("_required_by", set())
|
||||
if added:
|
||||
entry["_required_by"] = entry.get("_required_by", set()) | added
|
||||
entry["required"] = True
|
||||
|
||||
|
||||
def _brought(file_entry: dict, emu_name: str) -> set[str]:
|
||||
"""The core and build that need the file brought, empty when the
|
||||
emulator installs it. An entry read without layer (a test, a caller of
|
||||
@@ -666,6 +696,9 @@ def generate_platform_truth(
|
||||
)
|
||||
sys_cov["unprofiled"].add(emu_name)
|
||||
|
||||
for sys_data in systems.values():
|
||||
_require_by_slot(sys_data.get("files", []))
|
||||
|
||||
# Drop files with no exploitable data AFTER all cores have contributed.
|
||||
# A file declared by one core without hash/size/path may be enriched by
|
||||
# another core that has the same entry with data, so the filter must run
|
||||
|
||||
@@ -246,6 +246,51 @@ class ACompositeZipMd5IsNoContainerMd5(unittest.TestCase):
|
||||
self.assertEqual([m["name"] for m in result["hash_mismatch"]], ["neocdz.zip"])
|
||||
|
||||
|
||||
class OneSlotUnderSeveralNames(unittest.TestCase):
|
||||
"""kronos opens saturn_bios.bin, then sega_101.bin as a fallback. Ymir
|
||||
reads either name, so the sega_101.bin entry answers for saturn_bios.bin
|
||||
too. kronos sat in that entry's _cores and out of its _required_by while
|
||||
its saturn_bios.bin entry had it requiring the file."""
|
||||
|
||||
PROFILES = {
|
||||
"kronos": {
|
||||
"emulator": "Kronos", "type": "libretro", "systems": ["sega-saturn"],
|
||||
"files": [
|
||||
{"name": "saturn_bios.bin", "path": "kronos/saturn_bios.bin",
|
||||
"required": True, "size": 524288},
|
||||
{"name": "sega_101.bin", "required": False, "size": 524288},
|
||||
],
|
||||
},
|
||||
"ymir": {
|
||||
"emulator": "Ymir", "type": "libretro", "systems": ["sega-saturn"],
|
||||
"files": [
|
||||
{"name": "sega_101.bin", "required": True, "size": 524288,
|
||||
"aliases": ["saturn_bios.bin"]},
|
||||
],
|
||||
},
|
||||
"other": {
|
||||
"emulator": "Other", "type": "libretro", "systems": ["sega-saturn"],
|
||||
"files": [{"name": "saturn_bios.bin", "required": True, "size": 524288}],
|
||||
},
|
||||
}
|
||||
|
||||
def _files(self) -> dict[str, dict]:
|
||||
cores = ["kronos", "ymir", "other"]
|
||||
model = generate_platform_truth("p", {"cores": cores}, {}, self.PROFILES)
|
||||
return {f["name"]: f for f in model["systems"]["sega-saturn"]["files"]}
|
||||
|
||||
def test_a_reader_requiring_an_alias_requires_the_entry(self):
|
||||
sega = self._files()["sega_101.bin"]
|
||||
self.assertEqual(sega["_cores"], ["kronos", "ymir"])
|
||||
self.assertEqual(sega["_required_by"], ["kronos", "ymir"])
|
||||
|
||||
def test_no_reader_is_added(self):
|
||||
"""other requires saturn_bios.bin but never opens sega_101.bin."""
|
||||
sega = self._files()["sega_101.bin"]
|
||||
self.assertNotIn("other", sega["_required_by"])
|
||||
self.assertTrue(set(sega["_required_by"]) <= set(sega["_cores"]))
|
||||
|
||||
|
||||
class OnlySystemDirectoryEntries(unittest.TestCase):
|
||||
"""The truth kept files read from the save, content or working directory:
|
||||
diff_truth listed Cemu's mlc01 certificates, panda3ds's seeddb.bin and
|
||||
|
||||
Reference in new issue
Block a user