fix: keep ares labels off other dumps' names

ares finds firmware by sha256 (desktop-ui/settings/firmware.cpp:116-136) and names no file. Its FDS entry (RP2C33-01, crc32 1c7ae5d5) was labelled disksys.rom, the name nestopia, fceumm and four more cores read for RP2C33A-01A: ROCKNIX and EmuDeck got ares's revision at disksys.rom. It now carries MAME's member name rp2c33-01.bin.

The LaserActive v1.05 entry, the PAC-S10, PAC-N10, PAC-N1, PCE-LP1 and Neo Geo Pocket aliases are names RetroBat's launcher passes (Ares.Generator.cs:435-555): mega-ld.cpp:16-17 holds only the v1.04 US and v1.02 Japan hashes. RetroBat declares each name in its own list.

AHashScanLabelNamesNoOtherDump compares every found_by: content label with other profiles' entries of that name through the hash indexes.
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 10:02:30 +02:00
1 parent f4010bfd18
commit 62a4f19ce3
2 files changed
+75 -16

No files matched your search

+2 -16
View File
@@ -112,12 +112,12 @@ files:
source_ref: "desktop-ui/emulator/colecovision.cpp:12"
# --- Famicom Disk System ---
- name: disksys.rom
- name: rp2c33-01.bin
system: famicom-disk-system
required: true
sha256: "fdc1a76e654feea993fcb38366e05ee5f4eb641f86fe6bebaeefd412e112dd72"
validation: [sha256]
description: "Famicom Disk System BIOS"
description: "Famicom Disk System BIOS, RP2C33-01 revision"
source_ref: "desktop-ui/emulator/famicom-disk-system.cpp:19"
# --- Game Boy Advance ---
@@ -202,7 +202,6 @@ files:
# --- Mega LD (LaserActive SEGA PAC) ---
- name: mega_ld_bios_U.bin
aliases: ["[BIOS] LaserActive PAC-S10 (US) (v1.04).bin"]
system: mega-ld
region: [north-america]
required: true
@@ -220,14 +219,6 @@ files:
description: "LaserActive SEGA PAC BIOS (Japan), v1.02"
source_ref: "desktop-ui/emulator/mega-ld.cpp:17"
- name: "[BIOS] LaserActive PAC-S1 (Japan) (v1.05).bin"
system: mega-ld
region: [japan]
required: false
description: "LaserActive SEGA PAC BIOS (Japan), v1.05"
note: "Absent from the firmware table, so the scan by hash never assigns it. A path written into the Japanese BIOS slot of settings.bml is read as is, with no hash check. RetroBat writes this name there first and falls back to v1.02."
source_ref: "desktop-ui/emulator/mega-ld.cpp:17, desktop-ui/emulator/mega-ld.cpp:54, desktop-ui/settings/firmware.cpp:109, desktop-ui/emulator/emulator.cpp:188-197"
# --- MSX ---
- name: msx-japanese.rom
system: msx
@@ -270,7 +261,6 @@ files:
# --- Neo Geo Pocket ---
- name: ngp_bios.rom
aliases: ["[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp"]
system: neo-geo-pocket
required: true
sha256: "0293555b21c4fac516d25199df7809b26beeae150e1d4504a050db32264a6ad7"
@@ -280,7 +270,6 @@ files:
# --- Neo Geo Pocket Color ---
- name: ngpc_bios.rom
aliases: ["[BIOS] SNK Neo Geo Pocket (Japan, Europe) (En,Ja).ngp"]
system: neo-geo-pocket-color
required: true
sha256: "8fb845a2f71514cec20728e2f0fecfade69444f8d50898b92c2259f1ba63e10d"
@@ -350,7 +339,6 @@ files:
# --- PC Engine LD (LaserActive NEC PAC) ---
- name: pac-n10.pce
aliases: ["[BIOS] LaserActive PAC-N10 (US) (v1.02).bin"]
system: pc-engine-ld
required: true
sha256: "0e87a3385a27b3a4cac51934819b7eefa5b3d690768d2495633838488cd0e2e4"
@@ -359,7 +347,6 @@ files:
source_ref: "desktop-ui/emulator/pc-engine-ld.cpp:18"
- name: pac-n1.pce
aliases: ["[BIOS] LaserActive PAC-N1 (Japan) (v1.02).bin"]
system: pc-engine-ld
required: true
sha256: "459325690a458baebd77495c91e37c4dddfdd542ba13a821ce954e5bb245627f"
@@ -368,7 +355,6 @@ files:
source_ref: "desktop-ui/emulator/pc-engine-ld.cpp:19"
- name: pce-lp1.pce
aliases: ["[BIOS] LaserActive PCE-LP1 (Japan) (v1.02).bin"]
system: pc-engine-ld
required: true
sha256: "3f43b3b577117d84002e99cb0baeb97b0d65b1d70b4adadc68817185c6a687f0"
+73
View File
@@ -5438,6 +5438,79 @@ class AHashScanningCoreContradictsNoPlatform(unittest.TestCase):
self.assertEqual(claimed, [])
class AHashScanLabelNamesNoOtherDump(unittest.TestCase):
"""A core that finds its firmware by content names no file, so each
entry name is a label. ares labelled its Famicom Disk System revision
(RP2C33-01, crc32 1c7ae5d5) disksys.rom, the name six NES cores read for
the RP2C33A-01A dump: on ROCKNIX the manifest put ares's revision at
disksys.rom for all of them. A label that another profile gives a
different dump is refused, the two dumps compared through the
collection's hash indexes."""
# Names the core's own code gives the image, not labels.
CODE_NAMED = {
("bizhawk", "MSX.rom"):
"FirmwareDatabase.cs:362 names the image MSX.rom",
("swanstation", "ps1_rom.bin"):
"the whole PS3 image is the file the PS3 itself names ps1_rom.bin, "
"beetle_psx reads its first 512 KB under the same name",
}
@staticmethod
def _identity(entry: dict, db: dict) -> tuple[set, set]:
raw: set = set()
sha1s: set = set()
indexes = db["indexes"]
for field, index in (("sha1", None), ("md5", "by_md5"),
("crc32", "by_crc32"), ("sha256", "by_sha256")):
value = entry.get(field)
values = value if isinstance(value, list) else [value] if value else []
for item in values:
for digest in str(item).lower().split(","):
digest = digest.strip()
if not digest:
continue
raw.add((field, digest))
sha1 = digest if index is None else indexes[index].get(digest)
if sha1 in db["files"]:
sha1s.add(sha1)
return raw, sha1s
def test_labels_are_not_other_dumps_names(self):
import json
from scripts.common import load_emulator_profiles
if not (ROOT / "database.json").exists():
self.skipTest("database.json is not built")
db = json.loads((ROOT / "database.json").read_text(encoding="utf-8"))
profiles = load_emulator_profiles(str(ROOT / "emulators"))
by_name: dict[str, list[tuple[str, dict]]] = {}
for emulator, profile in profiles.items():
for entry in profile.get("files") or []:
for name in [entry.get("name"), *(entry.get("aliases") or [])]:
if name:
by_name.setdefault(str(name).casefold(), []).append((emulator, entry))
clashes = []
for emulator, profile in profiles.items():
if profile.get("found_by") != "content":
continue
for entry in profile.get("files") or []:
raw, sha1s = self._identity(entry, db)
if not sha1s:
continue
for name in [entry.get("name"), *(entry.get("aliases") or [])]:
if (emulator, name) in self.CODE_NAMED:
continue
for other, other_entry in by_name.get(str(name).casefold(), []):
if other == emulator:
continue
other_raw, other_sha1s = self._identity(other_entry, db)
if other_sha1s and not raw & other_raw and not sha1s & other_sha1s:
clashes.append(f"{emulator} {name} is {other}'s name for another dump")
self.assertEqual(sorted(set(clashes)), [])
class ReportsHoldTheDataTrees(unittest.TestCase):
"""Run on their own, the README, site and slot reports resolved against
data/ without the shared hold, so a concurrent refresh could swap a tree