mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
fix: say what the core refuses in emulator mode
This commit is contained in:
1 parent
22cad6ee01
commit
31e2d4235a
3 files changed
+98
-9
No files matched your search
@@ -1349,6 +1349,8 @@ def generate_emulator_pack(
|
|||||||
|
|
||||||
total_files = 0
|
total_files = 0
|
||||||
missing_files = []
|
missing_files = []
|
||||||
|
rejected_files: list[str] = []
|
||||||
|
discrepancies: list[str] = []
|
||||||
seen_destinations: set[str] = set()
|
seen_destinations: set[str] = set()
|
||||||
seen_lower: set[str] = set()
|
seen_lower: set[str] = set()
|
||||||
seen_parents: set[str] = (
|
seen_parents: set[str] = (
|
||||||
@@ -1515,15 +1517,27 @@ def generate_emulator_pack(
|
|||||||
|
|
||||||
# The file verify --emulator credits is the one shipped: a
|
# The file verify --emulator credits is the one shipped: a
|
||||||
# dump the core's own check rejects gives way to a held one
|
# dump the core's own check rejects gives way to a held one
|
||||||
# it accepts (azahar's otp.bin, dolphin's dsp_rom.bin).
|
# it accepts (azahar's otp.bin, dolphin's dsp_rom.bin). With
|
||||||
if check_file_validation(
|
# none, the core would refuse what the pack ships: it is named
|
||||||
|
# and left out, as verify reports it.
|
||||||
|
refused = check_file_validation(
|
||||||
local_path, fe["name"], validation_index, bios_dir
|
local_path, fe["name"], validation_index, bios_dir
|
||||||
):
|
)
|
||||||
|
if refused:
|
||||||
better = find_validated_variant(
|
better = find_validated_variant(
|
||||||
fe, db, local_path, validation_index, bios_dir
|
fe, db, local_path, validation_index, bios_dir
|
||||||
)
|
)
|
||||||
if better:
|
if not better:
|
||||||
local_path = better
|
reason, _owners = refused
|
||||||
|
rejected_files.append(f"{fe['name']} -{reason}")
|
||||||
|
continue
|
||||||
|
local_path = better
|
||||||
|
elif status == "hash_mismatch":
|
||||||
|
# Not a check the core runs, so the file still serves;
|
||||||
|
# it is not the dump the profile documents, and says so.
|
||||||
|
discrepancies.append(
|
||||||
|
f"{fe['name']} -not the dump the {emu_name} profile declares"
|
||||||
|
)
|
||||||
|
|
||||||
# SHA1 dedup: skip if same physical file AND same destination
|
# SHA1 dedup: skip if same physical file AND same destination
|
||||||
# (but allow same file to be packed under different destinations,
|
# (but allow same file to be packed under different destinations,
|
||||||
@@ -1545,7 +1559,7 @@ def generate_emulator_pack(
|
|||||||
total_files += 1
|
total_files += 1
|
||||||
|
|
||||||
# Remove empty ZIP (no files packed and no missing = nothing to ship)
|
# Remove empty ZIP (no files packed and no missing = nothing to ship)
|
||||||
if total_files == 0 and not missing_files:
|
if total_files == 0 and not missing_files and not rejected_files:
|
||||||
os.unlink(zip_path)
|
os.unlink(zip_path)
|
||||||
|
|
||||||
# Report
|
# Report
|
||||||
@@ -1555,15 +1569,21 @@ def generate_emulator_pack(
|
|||||||
parts = [f"{ok_count} files packed"]
|
parts = [f"{ok_count} files packed"]
|
||||||
if missing_count:
|
if missing_count:
|
||||||
parts.append(f"{missing_count} missing")
|
parts.append(f"{missing_count} missing")
|
||||||
|
if rejected_files:
|
||||||
|
parts.append(f"{len(rejected_files)} refused by the core")
|
||||||
print(f" {zip_path}: {', '.join(parts)}")
|
print(f" {zip_path}: {', '.join(parts)}")
|
||||||
for name in missing_files:
|
for name in missing_files:
|
||||||
print(f" MISSING: {name}")
|
print(f" MISSING: {name}")
|
||||||
|
for line in rejected_files:
|
||||||
|
print(f" REFUSED: {line}")
|
||||||
|
for line in discrepancies:
|
||||||
|
print(f" DISCREPANCY: {line}")
|
||||||
for ref in sorted(set(data_dir_notices)):
|
for ref in sorted(set(data_dir_notices)):
|
||||||
print(
|
print(
|
||||||
f" Note: data directory '{ref}' required but not included (use refresh_data_dirs.py)"
|
f" Note: data directory '{ref}' required but not included (use refresh_data_dirs.py)"
|
||||||
)
|
)
|
||||||
|
|
||||||
return zip_path if total_files > 0 or missing_files else None
|
return zip_path if total_files > 0 or missing_files or rejected_files else None
|
||||||
|
|
||||||
|
|
||||||
def generate_system_pack(
|
def generate_system_pack(
|
||||||
|
|||||||
+15
-2
@@ -287,6 +287,19 @@ def verify_entry_sha1(
|
|||||||
# Severity mapping per platform
|
# Severity mapping per platform
|
||||||
|
|
||||||
|
|
||||||
|
def _emulator_severity(status: str, required: bool, hle_fallback: bool) -> str:
|
||||||
|
"""Severity when the emulator's own code is the check.
|
||||||
|
|
||||||
|
A file present but refused by the core's validation, or a different dump
|
||||||
|
than the one the profile declares, is not a file the core runs with:
|
||||||
|
read in existence mode it counted OK, and `verify --emulator` announced
|
||||||
|
1/1 OK above the line that said the core would refuse it.
|
||||||
|
"""
|
||||||
|
if status == Status.UNTESTED:
|
||||||
|
return Severity.WARNING
|
||||||
|
return compute_severity(status, required, "existence", hle_fallback)
|
||||||
|
|
||||||
|
|
||||||
def compute_severity(
|
def compute_severity(
|
||||||
status: str,
|
status: str,
|
||||||
required: bool,
|
required: bool,
|
||||||
@@ -1499,7 +1512,7 @@ def verify_emulator(
|
|||||||
prev, 0
|
prev, 0
|
||||||
):
|
):
|
||||||
file_status[dest] = cur
|
file_status[dest] = cur
|
||||||
sev = compute_severity(cur, required, "existence", False)
|
sev = _emulator_severity(cur, required, False)
|
||||||
prev_sev = file_severity.get(dest)
|
prev_sev = file_severity.get(dest)
|
||||||
if prev_sev is None or _SEVERITY_ORDER.get(
|
if prev_sev is None or _SEVERITY_ORDER.get(
|
||||||
sev, 0
|
sev, 0
|
||||||
@@ -1612,7 +1625,7 @@ def verify_emulator(
|
|||||||
prev, 0
|
prev, 0
|
||||||
):
|
):
|
||||||
file_status[dest] = cur
|
file_status[dest] = cur
|
||||||
sev = compute_severity(cur, required, "existence", hle)
|
sev = _emulator_severity(cur, required, hle)
|
||||||
prev_sev = file_severity.get(dest)
|
prev_sev = file_severity.get(dest)
|
||||||
if prev_sev is None or _SEVERITY_ORDER.get(
|
if prev_sev is None or _SEVERITY_ORDER.get(
|
||||||
sev, 0
|
sev, 0
|
||||||
|
|||||||
@@ -167,5 +167,61 @@ class AnExtraDoesNotPassAHashCheck(unittest.TestCase):
|
|||||||
self.assertEqual(int(packed.group(1)), 0, report.getvalue())
|
self.assertEqual(int(packed.group(1)), 0, report.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TheEmulatorPackShipsWhatTheCoreAccepts(unittest.TestCase):
|
||||||
|
"""BasiliskII wants a 512 KB to 1 MB ROM. The only ROM held was 128 KB:
|
||||||
|
the emulator pack shipped it silently and verify --emulator announced
|
||||||
|
1/1 OK above the line saying the core would refuse it."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._tmp = tempfile.TemporaryDirectory()
|
||||||
|
self.root = Path(self._tmp.name)
|
||||||
|
bios = self.root / "bios" / "Apple"
|
||||||
|
self.emulators = self.root / "emulators"
|
||||||
|
for directory in (bios, self.emulators):
|
||||||
|
directory.mkdir(parents=True)
|
||||||
|
payload = b"r" * 131072
|
||||||
|
(bios / "ROM").write_bytes(payload)
|
||||||
|
sha1 = hashlib.sha1(payload).hexdigest()
|
||||||
|
files = {sha1: {
|
||||||
|
"path": str(bios / "ROM"), "name": "ROM", "size": len(payload),
|
||||||
|
"sha1": sha1, "md5": hashlib.md5(payload).hexdigest(),
|
||||||
|
"sha256": hashlib.sha256(payload).hexdigest(), "crc32": "00000003",
|
||||||
|
}}
|
||||||
|
self.db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
|
||||||
|
profile = {
|
||||||
|
"emulator": "Mac", "type": "libretro", "cores": ["mac"],
|
||||||
|
"systems": ["apple-macintosh"],
|
||||||
|
"files": [{"name": "ROM", "required": True, "min_size": 524288,
|
||||||
|
"max_size": 1048576, "validation": ["size"]}],
|
||||||
|
}
|
||||||
|
(self.emulators / "mac.yml").write_text(yaml.dump(profile))
|
||||||
|
common._emulator_profiles_cache.clear()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
common._emulator_profiles_cache.clear()
|
||||||
|
self._tmp.cleanup()
|
||||||
|
|
||||||
|
def test_the_refused_rom_is_named_not_shipped(self):
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
out = self.root / "dist"
|
||||||
|
out.mkdir()
|
||||||
|
report = io.StringIO()
|
||||||
|
with contextlib.redirect_stdout(report):
|
||||||
|
zip_path = builder.generate_emulator_pack(
|
||||||
|
["mac"], str(self.emulators), self.db, str(self.root / "bios"),
|
||||||
|
str(out), offline=True,
|
||||||
|
)
|
||||||
|
self.assertIn("REFUSED: ROM", report.getvalue())
|
||||||
|
with zipfile.ZipFile(zip_path) as archive:
|
||||||
|
self.assertNotIn("ROM", archive.namelist())
|
||||||
|
|
||||||
|
def test_verify_does_not_call_it_ok(self):
|
||||||
|
from verify import Severity, verify_emulator
|
||||||
|
|
||||||
|
result = verify_emulator(["mac"], str(self.emulators), self.db)
|
||||||
|
self.assertEqual(result["severity_counts"][Severity.OK], 0)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
Reference in new issue
Block a user