mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-20 18:59:07 -05:00
fix: look past another emulator's copy by name
xm6typeg took XM6 Utility's synthesized SCSIINROM.DAT while the X68000 dump sat under another casing; blueMSX took a 16 KB RS232.ROM once msx-emu's 8 KB copy was set aside, though data/bluemsx held its own.
This commit is contained in:
1 parent
d64129def8
commit
a3a735771b
2 files changed
+91
-8
No files matched your search
+13
-8
@@ -1364,11 +1364,14 @@ def resolve_local_file(
|
||||
and path not in candidates
|
||||
):
|
||||
candidates.append(path)
|
||||
if not candidates:
|
||||
owners = _owner_tokens(file_entry)
|
||||
if not candidates or all(_foreign_tree(p, owners) for p in candidates):
|
||||
# Case-insensitive fallback: upstream platforms disagree on
|
||||
# casing (VEC_MineStorm.vec vs VEC_Minestorm.vec). Two casings
|
||||
# can name two contents (FONT.ROM and font.rom), so this only
|
||||
# runs when no casing matches exactly.
|
||||
# runs when no casing matches exactly, or when only another
|
||||
# emulator's tree does: xm6typeg got XM6 Utility's synthesized
|
||||
# SCSIINROM.DAT while the X68000 dump sat as scsiinrom.dat.
|
||||
folded = _casefold_name_index(by_name)
|
||||
for try_name in names_to_try:
|
||||
for match_sha1 in folded.get(try_name.casefold(), []):
|
||||
@@ -1385,21 +1388,23 @@ def resolve_local_file(
|
||||
elif len(candidates) > 1 and name.casefold().endswith(".zip"):
|
||||
candidates = _covering_archives(candidates)
|
||||
candidates = _by_affinity(candidates, file_entry, dest_hint)
|
||||
best = candidates[0] if candidates else ""
|
||||
# A copy outside another emulator's tree comes first: the
|
||||
# affinity read pcsx2 in bios/Other/armsx2/pcsx2/ and served
|
||||
# upstream PCSX2 the patches.zip of ARMSX2.
|
||||
owners = _owner_tokens(file_entry)
|
||||
candidates = [
|
||||
p for p in candidates if not _foreign_tree(p, owners)
|
||||
] or candidates
|
||||
primary = [p for p in candidates if "/.variants/" not in p]
|
||||
if primary or candidates:
|
||||
chosen = primary[0] if primary else candidates[0]
|
||||
# Even the best of them is another emulator's own copy: the
|
||||
# name says nothing about this profile's file, and a data
|
||||
# directory it reads may hold it. Dolphin got Dolphin-MMJR's
|
||||
# codehandler.bin while data/dolphin-sys held its own.
|
||||
if data_dir_registry and _foreign_tree(chosen, _owner_tokens(file_entry)):
|
||||
# The best of them is another emulator's own copy, served or
|
||||
# set aside: the name says nothing about this profile's file,
|
||||
# and a data directory it reads may hold it. Dolphin got
|
||||
# Dolphin-MMJR's codehandler.bin while data/dolphin-sys held
|
||||
# its own; blueMSX got the 16 KB RS232.ROM once msx-emu's
|
||||
# 8 KB copy was set aside, while data/bluemsx held its own.
|
||||
if data_dir_registry and _foreign_tree(best, owners):
|
||||
hit, _mismatch = _resolve_in_data_dirs(
|
||||
names_to_try, data_dir_registry,
|
||||
functools.partial(
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
"""The name step does not settle on another emulator's copy.
|
||||
|
||||
xm6typeg asked for SCSIINROM.DAT: only XM6 Utility's synthesized image
|
||||
matched the casing, under bios/Other/xm6pro68k/, and the X68000 dump stored
|
||||
as scsiinrom.dat was never a candidate. blueMSX asked for RS232.ROM: its own
|
||||
8 KB copy was msx-emu's, set aside as foreign, and the 16 KB file left was
|
||||
served while data/bluemsx held the 8 KB one.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
||||
|
||||
from common import resolve_local_file # noqa: E402
|
||||
|
||||
|
||||
class ForeignTreeNames(unittest.TestCase):
|
||||
def setUp(self):
|
||||
(REPO_ROOT / "tmp").mkdir(exist_ok=True)
|
||||
self.root = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp"))
|
||||
self.addCleanup(shutil.rmtree, self.root, True)
|
||||
# The collection's paths are relative to the repository root.
|
||||
self.addCleanup(os.chdir, os.getcwd())
|
||||
os.chdir(self.root)
|
||||
self.db = {"files": {}, "indexes": {
|
||||
"by_md5": {}, "by_name": {}, "by_crc32": {}, "by_path_suffix": {},
|
||||
}}
|
||||
|
||||
def _hold(self, rel: str, data: bytes) -> str:
|
||||
target = self.root / rel
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_bytes(data)
|
||||
sha1 = hashlib.sha1(data).hexdigest()
|
||||
name = rel.rsplit("/", 1)[-1]
|
||||
if "/.variants/" in rel:
|
||||
name = name.rsplit(".", 1)[0]
|
||||
self.db["files"][sha1] = {
|
||||
"path": rel, "name": name, "size": len(data),
|
||||
"md5": hashlib.md5(data).hexdigest(), "crc32": "",
|
||||
}
|
||||
self.db["indexes"]["by_name"].setdefault(name, []).append(sha1)
|
||||
return rel
|
||||
|
||||
def test_a_casing_only_another_tree_holds(self):
|
||||
self._hold("bios/Other/xm6pro68k/.variants/SCSIINROM.DAT.47404fbb", b"X" * 64)
|
||||
own = self._hold("bios/Sharp/X68000/scsiinrom.dat", b"D" * 64)
|
||||
entry = {"name": "SCSIINROM.DAT", "source_emulator": "xm6typeg"}
|
||||
self.assertEqual(resolve_local_file(entry, self.db)[0], own)
|
||||
|
||||
def test_a_set_aside_copy_sends_the_name_to_the_data_directory(self):
|
||||
self._hold("bios/Microsoft/MSX/RS232.ROM", b"L" * 128)
|
||||
self._hold("bios/Other/msx-emu/Machines/Shared Roms/RS232.ROM", b"S" * 64)
|
||||
cache = self.root / "data" / "bluemsx"
|
||||
(cache / "Machines" / "Shared Roms").mkdir(parents=True)
|
||||
(cache / "Machines" / "Shared Roms" / "RS232.ROM").write_bytes(b"S" * 64)
|
||||
entry = {
|
||||
"name": "RS232.ROM", "path": "Machines/Shared Roms/RS232.ROM",
|
||||
"size": 64, "source_emulator": "bluemsx",
|
||||
}
|
||||
path, status = resolve_local_file(
|
||||
entry, self.db,
|
||||
data_dir_registry={"bluemsx": {"local_cache": str(cache)}},
|
||||
)
|
||||
self.assertEqual(status, "data_dir")
|
||||
self.assertEqual(Path(path).stat().st_size, 64)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user