From 9ca14bb77e97c7ca1732501399dc99337d01eadf Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 6 Oct 2026 12:48:58 +0200 Subject: [PATCH] fix: keep save and content files out of the truth --- scripts/cross_reference.py | 5 ++--- scripts/packextras.py | 5 ++--- scripts/truth.py | 4 +++- scripts/validation.py | 11 +++++++++++ scripts/verify.py | 5 ++--- tests/test_truth_diff.py | 28 ++++++++++++++++++++++++++++ 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/scripts/cross_reference.py b/scripts/cross_reference.py index 0374b4e5..30385718 100644 --- a/scripts/cross_reference.py +++ b/scripts/cross_reference.py @@ -31,6 +31,7 @@ from common import ( require_yaml, runs_standalone, ) +from validation import read_from_system_dir yaml = require_yaml() @@ -332,9 +333,7 @@ def _cross_reference_profile( if file_mode == "libretro" and is_standalone: continue - # Skip files loaded from non-system directories (save_dir, content_dir) - load_from = f.get("load_from", "") - if load_from and load_from != "system_dir": + if not read_from_system_dir(f): continue # Skip filename-agnostic files (handled by agnostic scan) diff --git a/scripts/packextras.py b/scripts/packextras.py index 4c3d1c52..931fade1 100644 --- a/scripts/packextras.py +++ b/scripts/packextras.py @@ -14,6 +14,7 @@ from common import resolve_local_file from common import runs_standalone from common import sanitize_pack_path from common import size_fits +from validation import read_from_system_dir def _emulator_systems_index(emu_profiles: dict | None) -> dict[str, list[str]]: """Map both the profile key and its display name to the profile's systems. @@ -564,9 +565,7 @@ def _collect_emulator_extras( continue if file_mode == "libretro" and is_standalone: continue - # Skip files loaded from non-system directories (save_dir, content_dir) - load_from = f.get("load_from", "") - if load_from and load_from != "system_dir": + if not read_from_system_dir(f): continue if is_standalone: raw = f.get("standalone_path") or f.get("path") or fname diff --git a/scripts/truth.py b/scripts/truth.py index a435f717..52bf651a 100644 --- a/scripts/truth.py +++ b/scripts/truth.py @@ -9,7 +9,7 @@ from __future__ import annotations import sys from common import _norm_system_id, resolve_platform_cores, runs_standalone -from validation import filter_files_by_mode +from validation import filter_files_by_mode, read_from_system_dir def _serialize_source_ref(sr: object) -> str: @@ -378,6 +378,8 @@ def generate_platform_truth( ) for fe in filtered: + if not read_from_system_dir(fe): + continue profile_sid = fe.get("system", "") if not profile_sid: sys_ids = profile.get("systems", []) diff --git a/scripts/validation.py b/scripts/validation.py index 8661622f..a166a98d 100644 --- a/scripts/validation.py +++ b/scripts/validation.py @@ -313,6 +313,17 @@ def validate_cli_modes(args, mode_attrs: list[str]) -> None: raise SystemExit(f"Options are mutually exclusive: --{' --'.join(mode_attrs)}") +def read_from_system_dir(file_entry: dict) -> bool: + """Whether the emulator reads this entry from the system directory. + + A file loaded from the save, content or working directory is not a BIOS: + no platform lists it, no pack carries it, and the truth model must not + ask a platform to declare it. + """ + load_from = file_entry.get("load_from", "") + return not load_from or load_from == "system_dir" + + def filter_files_by_mode(files: list[dict], standalone: bool) -> list[dict]: """Filter file entries by libretro/standalone mode.""" result = [] diff --git a/scripts/verify.py b/scripts/verify.py index 8c4b2cdd..632a3e36 100644 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -79,6 +79,7 @@ from validation import ( check_file_validation, filter_files_by_mode, find_validated_variant, + read_from_system_dir, ) DEFAULT_DB = "database.json" @@ -404,9 +405,7 @@ def _candidate_verdict( return "skip" if file_mode == "libretro" and is_standalone: return "skip" - # Read from somewhere other than the system directory: not a BIOS gap. - load_from = file_entry.get("load_from", "") - if load_from and load_from != "system_dir": + if not read_from_system_dir(file_entry): return "skip" # Filename-agnostic entries are answered by the builder's own scan. if file_entry.get("agnostic"): diff --git a/tests/test_truth_diff.py b/tests/test_truth_diff.py index b10c04af..f8325895 100644 --- a/tests/test_truth_diff.py +++ b/tests/test_truth_diff.py @@ -197,5 +197,33 @@ class RenameMatching(unittest.TestCase): self.assertNotIn("lonely.bin", matched_truth) + +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 + neo-emu's neogeo.zip as missing from platform lists that the pack and + verify deliberately leave them out of.""" + + def test_a_file_read_elsewhere_is_not_asked_of_the_platform(self): + from truth import generate_platform_truth + + profiles = { + "core": { + "emulator": "Core", + "type": "libretro", + "systems": ["sys"], + "files": [ + {"name": "bios.bin", "sha1": "a" * 40}, + {"name": "explicit.bin", "sha1": "b" * 40, "load_from": "system_dir"}, + {"name": "cert.der", "sha1": "c" * 40, "load_from": "save_dir"}, + {"name": "game.zip", "sha1": "d" * 40, "load_from": "content_dir"}, + ], + } + } + result = generate_platform_truth("p", {"cores": ["core"]}, {}, profiles) + names = sorted(f["name"] for f in result["systems"]["sys"]["files"]) + self.assertEqual(names, ["bios.bin", "explicit.bin"]) + + if __name__ == "__main__": unittest.main()