mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-11 20:43:50 -06:00
dsi_bios7.bin and dsi_bios9.bin hold the DSi Panda devkit boot ROMs, eMMC key-Y zeroed. Every md5 and crc32 declared under those names designates a retail dump in the same directory, yet hashless entries (RetroBat, dsperate) got the devkit ROMs by name. by_proven_name maps such a name to the proven primaries beside it. kick13.rom, dsi_firmware.bin and spectrum.zip follow the same rule.
126 lines
4.5 KiB
Python
126 lines
4.5 KiB
Python
"""A name means the dump its declarations prove, not whatever is filed under it.
|
|
|
|
The collection files the DSi Panda (Japan) (Intense) devkit boot ROMs as
|
|
dsi_bios7.bin and dsi_bios9.bin. Their eMMC key-Y at 0x8308 is zeroed, so a
|
|
retail NAND cannot be opened with them. Every hash declared under those names
|
|
(Batocera's md5, melonDS's crc32) designates a retail dump in the same
|
|
directory, yet RetroBat and dsperate, which declare no hash, were served the
|
|
devkit ROMs by the name step.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
import zlib
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
|
|
import generate_db # noqa: E402
|
|
from common import resolve_local_file # noqa: E402
|
|
|
|
DEVKIT = b"D" * 64
|
|
RETAIL = b"R" * 64
|
|
OTHER = b"O" * 64
|
|
|
|
|
|
def record(path: str, data: bytes) -> dict:
|
|
return {
|
|
"path": path,
|
|
"name": path.rsplit("/", 1)[-1],
|
|
"size": len(data),
|
|
"md5": hashlib.md5(data).hexdigest(),
|
|
"crc32": f"{zlib.crc32(data):08x}",
|
|
"sha256": hashlib.sha256(data).hexdigest(),
|
|
}
|
|
|
|
|
|
class ProvenNameIndex(unittest.TestCase):
|
|
def setUp(self):
|
|
self.files = {
|
|
hashlib.sha1(DEVKIT).hexdigest(): record("bios/N/DSi/dsi_bios7.bin", DEVKIT),
|
|
hashlib.sha1(RETAIL).hexdigest(): record("bios/N/DSi/biosdsi7.bin", RETAIL),
|
|
hashlib.sha1(OTHER).hexdigest(): record("bios/X/Y/other.bin", OTHER),
|
|
}
|
|
self.indexes = generate_db.build_indexes(self.files, {})
|
|
|
|
def index(self, declarations: list[dict]) -> dict:
|
|
return generate_db.proven_name_index(self.files, self.indexes, declarations)
|
|
|
|
def test_name_points_at_the_proven_dump_beside_it(self):
|
|
declared = [{"name": "dsi_bios7.bin", "md5": hashlib.md5(RETAIL).hexdigest()}]
|
|
self.assertEqual(
|
|
self.index(declared),
|
|
{"dsi_bios7.bin": [hashlib.sha1(RETAIL).hexdigest()]},
|
|
)
|
|
|
|
def test_a_proven_holder_keeps_its_name(self):
|
|
declared = [
|
|
{"name": "dsi_bios7.bin", "md5": hashlib.md5(RETAIL).hexdigest()},
|
|
{"name": "dsi_bios7.bin", "crc32": f"{zlib.crc32(DEVKIT):08x}"},
|
|
]
|
|
self.assertEqual(self.index(declared), {})
|
|
|
|
def test_a_dump_filed_elsewhere_proves_nothing(self):
|
|
declared = [{"name": "dsi_bios7.bin", "md5": hashlib.md5(OTHER).hexdigest()}]
|
|
self.assertEqual(self.index(declared), {})
|
|
|
|
def test_a_member_hash_proves_nothing(self):
|
|
declared = [{
|
|
"name": "dsi_bios7.bin",
|
|
"md5": hashlib.md5(RETAIL).hexdigest(),
|
|
"zipped_file": "x.bin",
|
|
}]
|
|
self.assertEqual(self.index(declared), {})
|
|
|
|
|
|
class HashlessEntryTakesTheProvenDump(unittest.TestCase):
|
|
def test_resolver_reads_the_index(self):
|
|
(REPO_ROOT / "tmp").mkdir(exist_ok=True)
|
|
root = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp"))
|
|
self.addCleanup(shutil.rmtree, root, True)
|
|
previous = os.getcwd()
|
|
os.chdir(root)
|
|
self.addCleanup(os.chdir, previous)
|
|
Path("bios/N/DSi").mkdir(parents=True)
|
|
Path("bios/N/DSi/dsi_bios7.bin").write_bytes(DEVKIT)
|
|
Path("bios/N/DSi/biosdsi7.bin").write_bytes(RETAIL)
|
|
files = {
|
|
hashlib.sha1(DEVKIT).hexdigest(): record("bios/N/DSi/dsi_bios7.bin", DEVKIT),
|
|
hashlib.sha1(RETAIL).hexdigest(): record("bios/N/DSi/biosdsi7.bin", RETAIL),
|
|
}
|
|
indexes = generate_db.build_indexes(files, {})
|
|
db = {"files": files, "indexes": indexes}
|
|
entry = {"name": "dsi_bios7.bin", "size": 64}
|
|
self.assertEqual(
|
|
resolve_local_file(entry, db)[0], "bios/N/DSi/dsi_bios7.bin"
|
|
)
|
|
indexes["by_proven_name"] = generate_db.proven_name_index(
|
|
files, indexes,
|
|
[{"name": "dsi_bios7.bin", "md5": hashlib.md5(RETAIL).hexdigest()}],
|
|
)
|
|
self.assertEqual(
|
|
resolve_local_file(entry, db), ("bios/N/DSi/biosdsi7.bin", "name_exact")
|
|
)
|
|
|
|
|
|
class TheCollectionServesRetailRoms(unittest.TestCase):
|
|
def test_dsi_boot_roms(self):
|
|
db = json.loads((REPO_ROOT / "database.json").read_text())
|
|
index = db["indexes"].get("by_proven_name", {})
|
|
for name in ("dsi_bios7.bin", "dsi_bios9.bin"):
|
|
held = [db["files"][sha1]["path"] for sha1 in index.get(name, [])]
|
|
self.assertTrue(held, name)
|
|
self.assertFalse(any(path.endswith(f"/{name}") for path in held), held)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|