diff --git a/README.md b/README.md index 0fc29cce..bcc2d57d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Complete BIOS and firmware packs for Batocera, BizHawk, EmuDeck, Lakka, Recalbox, RetroArch, RetroBat, RetroDECK, RetroPie, and RomM. -**7,529** verified files across **352** systems, ready to extract into your emulator's BIOS directory. +**7,532** verified files across **352** systems, ready to extract into your emulator's BIOS directory. ## Download BIOS packs @@ -29,8 +29,8 @@ Each file is checked against the emulator's source code to match what the code a - **10 platforms** supported with platform-specific verification - **328 emulators** profiled from source (RetroArch cores + standalone) - **352 systems** covered (NES, SNES, PlayStation, Saturn, Dreamcast, ...) -- **7,529 files** verified with MD5, SHA1, CRC32 checksums -- **8108 MB** total collection size +- **7,532 files** verified with MD5, SHA1, CRC32 checksums +- **8112 MB** total collection size ## Supported systems @@ -49,7 +49,7 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/ | Recalbox | 346/346 (100.0%) | 346 | 0 | 0 | | RetroArch | 448/448 (100.0%) | 448 | 0 | 0 | | RetroBat | 331/331 (100.0%) | 330 | 1 | 0 | -| RetroDECK | 2007/2007 (100.0%) | 2000 | 7 | 0 | +| RetroDECK | 2007/2007 (100.0%) | 1999 | 8 | 0 | | RetroPie | 448/448 (100.0%) | 448 | 0 | 0 | | RomM | 374/374 (100.0%) | 372 | 2 | 0 | @@ -113,4 +113,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. This repository provides BIOS files for personal backup and archival purposes. -*Auto-generated on 2026-03-28T14:47:06Z* +*Auto-generated on 2026-03-28T16:30:00Z* diff --git a/database.json b/database.json index fff8038e..6a7ebf71 100644 --- a/database.json +++ b/database.json @@ -1,7 +1,7 @@ { - "generated_at": "2026-03-28T15:49:38Z", - "total_files": 7529, - "total_size": 8501557419, + "generated_at": "2026-03-28T16:29:37Z", + "total_files": 7532, + "total_size": 8505965231, "files": { "520d3d1b5897800af47f92efd2444a26b7a7dead": { "path": "bios/3DO Company/3DO/3do_arcade_saot.bin", @@ -27243,6 +27243,16 @@ "crc32": "4a1f42af", "adler32": "5b3adbba" }, + "5bcabba35bb8fbfe5a65b85efccf5ed657388308": { + "path": "bios/Atari/ST/hatari/BOOT.ST", + "name": "BOOT.ST", + "size": 737280, + "sha1": "5bcabba35bb8fbfe5a65b85efccf5ed657388308", + "md5": "cd6408638f9dbef45cbbd5d0b6060c60", + "sha256": "e2a0f8ce40fabd275f485eb4c1f59c5213ba0202d1b1c44ca8fdae60f112a8d5", + "crc32": "ca5e7999", + "adler32": "0b2b27eb" + }, "ee58768bdfc602c9b14942ce5481e97dd24e7c83": { "path": "bios/Atari/ST/megaste.img", "name": "megaste.img", @@ -70553,15 +70563,15 @@ "crc32": "f90f0089", "adler32": "3d4fc9b3" }, - "ae5557ed313b6708bb7c2aee0944e39335a8f814": { + "bebbc4db8ee3c97a9fe02c879ce149bac2c4a498": { "path": "bios/Sega/Saturn/stvbios.zip", "name": "stvbios.zip", - "size": 2699371, - "sha1": "ae5557ed313b6708bb7c2aee0944e39335a8f814", - "md5": "14c3c8f5cdc4dc0531228bd344afcf89", - "sha256": "2387d5a84527b0e083f177e60ba21311c964fa420dd1c3317e4976bf6d388b76", - "crc32": "ad4ed8d9", - "adler32": "9743d9ce" + "size": 5321327, + "sha1": "bebbc4db8ee3c97a9fe02c879ce149bac2c4a498", + "md5": "ea4d0ffe1feb88f53f675ac6d0cd9685", + "sha256": "a450943c69a10fd72509cfd211eea323104f966158838b865b59bbaa627094cd", + "crc32": "a8a8860f", + "adler32": "922c0afb" }, "4154e11959f3d5639b11d7902b3a393a99fb5776": { "path": "bios/Sega/Saturn/vsaturn.bin", @@ -71823,6 +71833,26 @@ "crc32": "0dcce9d7", "adler32": "41fe280a" }, + "91cb6e3f9871454a0127ecb928ed7f1237742ea1": { + "path": "bios/Sony/PlayStation/ps2_scph30003.bin", + "name": "ps2_scph30003.bin", + "size": 524288, + "sha1": "91cb6e3f9871454a0127ecb928ed7f1237742ea1", + "md5": "71f50ef4f4e17c163c78908e16244f7d", + "sha256": "a42c16a9be754f8f665c56611bd3a83eabb231c818b8de64744d0ea1a1d0e74d", + "crc32": "b6f00238", + "adler32": "1537f711" + }, + "3bbf6335b226932ee5a83d516acb0fafc62ac3ce": { + "path": "bios/Sony/PlayStation/ps2_scph70002_alt.bin", + "name": "ps2_scph70002_alt.bin", + "size": 524288, + "sha1": "3bbf6335b226932ee5a83d516acb0fafc62ac3ce", + "md5": "7ebb4fc5eab6f79a27d76ac9aad392b2", + "sha256": "7f7dd27cbddba7067fca250ef02b81dc5fe50083e8c20b83017343df6a34d411", + "crc32": "0c1a95f9", + "adler32": "c15c34af" + }, "96880d1ca92a016ff054be5159bb06fe03cb4e14": { "path": "bios/Sony/PlayStation/psxonpsp660.bin", "name": "psxonpsp660.bin", @@ -78020,6 +78050,7 @@ "fcd403db69f54290b51035d82f835e7b": "e4ed47fae31693e016b081c6bda48da5b70d7ccb", "e2c861c588fca2d0cf6be3df3aaf05f2": "bfcc01ae105fa4cee47890c09ebad9e3775395a4", "b338bacb2fc453bab61bcc1e2cf5076b": "7157f6a8aff275cfbb5ea6aa8e788dda8a977e56", + "cd6408638f9dbef45cbbd5d0b6060c60": "5bcabba35bb8fbfe5a65b85efccf5ed657388308", "c9093f27159e7d13ac0d1501a95e53d4": "ee58768bdfc602c9b14942ce5481e97dd24e7c83", "c87a52c277f7952b41c639fc7bf0a43b": "9a6e4c88533a9eaa4d55cdc040e47443e0226eb2", "992bac38e01633a529121a2a65f0779e": "3b8cf5ffa41b252eb67f8824f94608fa4005d6dd", @@ -82351,7 +82382,7 @@ "74570fed4d44b2682b560c8cd44b8b6a": "7b23b53d62de0f29a23e423d0fe751dfb469c2fa", "af5828fdff51384f99b3c4926be27762": "2b8cb4f87580683eb4d760e4ed210813d667f0a2", "f273555d7d91e8a5a6bfd9bcf066331c": "3bb41feb82838ab9a35601ac666de5aacfd17a58", - "14c3c8f5cdc4dc0531228bd344afcf89": "ae5557ed313b6708bb7c2aee0944e39335a8f814", + "ea4d0ffe1feb88f53f675ac6d0cd9685": "bebbc4db8ee3c97a9fe02c879ce149bac2c4a498", "ac4e4b6522e200c0d23d371a8cecbfd3": "4154e11959f3d5639b11d7902b3a393a99fb5776", "d063803adcced52217989bd825d69eb8": "c3cb7227e4dbc2af861e76d00cb59726105a2e4c", "2ef01c0e93f7ee3a0a4b139aa14728b9": "7297a11be143011ceb75a0720f96855003415a5d", @@ -82478,6 +82509,8 @@ "57a06303dfa9cf9351222dfcbb4a29d9": "ffa7f9a7fb19d773a0c3985a541c8e5623d2c30d", "81bbe60ba7a3d1cea1d48c14cbcc647b": "c40146361eb8cf670b19fdc9759190257803cab7", "d8f485717a5237285e4d7c5f881b7f32": "d7d6be084f51354bc951d8fa2d8d912aa70abc5e", + "71f50ef4f4e17c163c78908e16244f7d": "91cb6e3f9871454a0127ecb928ed7f1237742ea1", + "7ebb4fc5eab6f79a27d76ac9aad392b2": "3bbf6335b226932ee5a83d516acb0fafc62ac3ce", "c53ca5908936d412331790f4426c6c33": "96880d1ca92a016ff054be5159bb06fe03cb4e14", "8abc1b549a4a80954addc48ef02c4521": "339a48f4fcf63e10b5b867b8c93cfd40945faf6c", "239665b1a3dade1b5a52c06338011044": "343883a7b555646da8cee54aadd2795b6e7dd070", @@ -85239,7 +85272,7 @@ "7783ab663bb1a8d62ff60d583674355c2af556b1", "999ed28cfbf18103a4963b0d3797af3dcf67db05", "106cc72e61b11f4ae492fedc64be1dafe277a626", - "ae5557ed313b6708bb7c2aee0944e39335a8f814" + "bebbc4db8ee3c97a9fe02c879ce149bac2c4a498" ], "su2000.zip": [ "2e50b96a1d37e9407209e291d5f549233287ac77", @@ -90534,6 +90567,9 @@ "falcon.img": [ "7157f6a8aff275cfbb5ea6aa8e788dda8a977e56" ], + "BOOT.ST": [ + "5bcabba35bb8fbfe5a65b85efccf5ed657388308" + ], "megaste.img": [ "ee58768bdfc602c9b14942ce5481e97dd24e7c83" ], @@ -102438,6 +102474,12 @@ "ps2-50j.bin": [ "d7d6be084f51354bc951d8fa2d8d912aa70abc5e" ], + "ps2_scph30003.bin": [ + "91cb6e3f9871454a0127ecb928ed7f1237742ea1" + ], + "ps2_scph70002_alt.bin": [ + "3bbf6335b226932ee5a83d516acb0fafc62ac3ce" + ], "psxonpsp660.bin": [ "96880d1ca92a016ff054be5159bb06fe03cb4e14" ], @@ -105364,6 +105406,9 @@ "VT-DOS12-DISK.ROM": [ "072c6160d4e7d406f5d8f5b1b66066c797d35561" ], + "custom0.sf2": [ + "286b2e1fb21cc79851da01666db6c0b0e88f25e3" + ], "tos106de.img": [ "3b8cf5ffa41b252eb67f8824f94608fa4005d6dd" ], @@ -105382,9 +105427,6 @@ "Kickstart v3.0 rev 39.106 (1992)(Commodore)(A1200)[!].rom": [ "70033828182fffc7ed106e5373a8b89dda76faa5" ], - "custom0.sf2": [ - "286b2e1fb21cc79851da01666db6c0b0e88f25e3" - ], "basic11.rom": [ "9451a1a09d8f75944dbd6f91193fc360f1de80ac" ], @@ -109453,6 +109495,7 @@ "0d973c9d": "e4ed47fae31693e016b081c6bda48da5b70d7ccb", "dbfa7ceb": "bfcc01ae105fa4cee47890c09ebad9e3775395a4", "4a1f42af": "7157f6a8aff275cfbb5ea6aa8e788dda8a977e56", + "ca5e7999": "5bcabba35bb8fbfe5a65b85efccf5ed657388308", "3f2f840f": "ee58768bdfc602c9b14942ce5481e97dd24e7c83", "1a586c64": "9a6e4c88533a9eaa4d55cdc040e47443e0226eb2", "7c67c5c9": "3b8cf5ffa41b252eb67f8824f94608fa4005d6dd", @@ -113784,7 +113827,7 @@ "b3c63c25": "7b23b53d62de0f29a23e423d0fe751dfb469c2fa", "2aba43c2": "2b8cb4f87580683eb4d760e4ed210813d667f0a2", "f90f0089": "3bb41feb82838ab9a35601ac666de5aacfd17a58", - "ad4ed8d9": "ae5557ed313b6708bb7c2aee0944e39335a8f814", + "a8a8860f": "bebbc4db8ee3c97a9fe02c879ce149bac2c4a498", "e4d61811": "4154e11959f3d5639b11d7902b3a393a99fb5776", "d1883221": "c3cb7227e4dbc2af861e76d00cb59726105a2e4c", "0dd4c0d5": "7297a11be143011ceb75a0720f96855003415a5d", @@ -113911,6 +113954,8 @@ "24fc7e17": "ffa7f9a7fb19d773a0c3985a541c8e5623d2c30d", "2f53b852": "c40146361eb8cf670b19fdc9759190257803cab7", "0dcce9d7": "d7d6be084f51354bc951d8fa2d8d912aa70abc5e", + "b6f00238": "91cb6e3f9871454a0127ecb928ed7f1237742ea1", + "0c1a95f9": "3bbf6335b226932ee5a83d516acb0fafc62ac3ce", "5660f34f": "96880d1ca92a016ff054be5159bb06fe03cb4e14", "f2af798b": "339a48f4fcf63e10b5b867b8c93cfd40945faf6c", "3b601fc8": "343883a7b555646da8cee54aadd2795b6e7dd070", @@ -117428,6 +117473,9 @@ ".variants/ATARIOSB.ROM.0e86d61d": [ "db1031585968cfc6ec2ecda5c9a5a52f61444a3b" ], + "hatari/BOOT.ST": [ + "5bcabba35bb8fbfe5a65b85efccf5ed657388308" + ], "tos/emutos.img": [ "7f22e9b1de07d2466d17cf23187775c246ce9566" ], @@ -128717,12 +128765,12 @@ "abf119cf947ea32defd08b29a8a25d75f6bd4987", "f2572ee83d09fc08f4de4a62f101c8bb301a9505", "072c6160d4e7d406f5d8f5b1b66066c797d35561", + "286b2e1fb21cc79851da01666db6c0b0e88f25e3", "3b8cf5ffa41b252eb67f8824f94608fa4005d6dd", "ee58768bdfc602c9b14942ce5481e97dd24e7c83", "2b8cb4f87580683eb4d760e4ed210813d667f0a2", "70033828182fffc7ed106e5373a8b89dda76faa5", "44620f57a25f0bcac2b57ca2b0f1ebad3bf305d3", - "286b2e1fb21cc79851da01666db6c0b0e88f25e3", "bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4", "9451a1a09d8f75944dbd6f91193fc360f1de80ac", "03bbb386cf530e804363acdfc1d13e64cf28af2e", @@ -131429,6 +131477,12 @@ ], ".variants/scph101.bin.9a09ab7e": [ "7771d6e90980408f753891648685def6dd42ef6d" + ], + "zc210/sf2/custom0.sf2": [ + "286b2e1fb21cc79851da01666db6c0b0e88f25e3" + ], + "zc210/zcdata.dat": [ + "33b50cec88bc1569431a7885c0cc2692fddb004b" ] } } diff --git a/scripts/cross_reference.py b/scripts/cross_reference.py index 3f5bd2f5..e332dcaa 100644 --- a/scripts/cross_reference.py +++ b/scripts/cross_reference.py @@ -50,7 +50,21 @@ def load_platform_files(platforms_dir: str) -> tuple[dict[str, set[str]], dict[s return declared, platform_data_dirs -def _find_in_repo(fname: str, by_name: dict[str, list], by_name_lower: dict[str, str]) -> bool: +def _build_data_dir_index(data_root: str = "data") -> set[str]: + """Build a set of filenames available in data/ directories.""" + names: set[str] = set() + root_path = Path(data_root) + if not root_path.is_dir(): + return names + for fpath in root_path.rglob("*"): + if fpath.is_file() and not fpath.name.startswith("."): + names.add(fpath.name) + names.add(fpath.name.lower()) + return names + + +def _find_in_repo(fname: str, by_name: dict[str, list], by_name_lower: dict[str, str], + data_names: set[str] | None = None) -> bool: if fname in by_name: return True basename = fname.rsplit("/", 1)[-1] if "/" in fname else None @@ -63,6 +77,11 @@ def _find_in_repo(fname: str, by_name: dict[str, list], by_name_lower: dict[str, key = basename.lower() if key in by_name_lower: return True + if data_names: + if fname in data_names or key in data_names: + return True + if basename and (basename in data_names or basename.lower() in data_names): + return True return False @@ -71,12 +90,14 @@ def cross_reference( declared: dict[str, set[str]], db: dict, platform_data_dirs: dict[str, set[str]] | None = None, + data_names: set[str] | None = None, ) -> dict: """Compare emulator profiles against platform declarations. Returns a report with gaps (files emulators need but platforms don't list) and coverage stats. Files covered by matching data_directories between emulator profile and platform config are not reported as gaps. + Checks both bios/ (via database) and data/ (via data_names index). """ platform_data_dirs = platform_data_dirs or {} by_name = db.get("indexes", {}).get("by_name", {}) @@ -106,7 +127,7 @@ def cross_reference( continue in_platform = fname in platform_names - in_repo = _find_in_repo(fname, by_name, by_name_lower) + in_repo = _find_in_repo(fname, by_name, by_name_lower, data_names) entry = { "name": fname, @@ -205,7 +226,8 @@ def main(): declared, plat_data_dirs = load_platform_files(args.platforms_dir) db = load_database(args.db) - report = cross_reference(profiles, declared, db, plat_data_dirs) + data_names = _build_data_dir_index() + report = cross_reference(profiles, declared, db, plat_data_dirs, data_names) if args.json: print(json.dumps(report, indent=2)) diff --git a/scripts/verify.py b/scripts/verify.py index 316a0fc9..a16c27f4 100644 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -246,8 +246,9 @@ def _build_expected(file_entry: dict, checks: list[str]) -> dict: expected["adler32"] = adler_val return expected -def _name_in_index(name: str, by_name: dict, by_path_suffix: dict | None = None) -> bool: - """Check if a name is resolvable in the database indexes.""" +def _name_in_index(name: str, by_name: dict, by_path_suffix: dict | None = None, + data_names: set[str] | None = None) -> bool: + """Check if a name is resolvable in the database indexes or data directories.""" if name in by_name: return True basename = name.rsplit("/", 1)[-1] @@ -255,6 +256,11 @@ def _name_in_index(name: str, by_name: dict, by_path_suffix: dict | None = None) return True if by_path_suffix and name in by_path_suffix: return True + if data_names: + if name in data_names or name.lower() in data_names: + return True + if basename != name and (basename in data_names or basename.lower() in data_names): + return True return False @@ -264,6 +270,7 @@ def find_undeclared_files( db: dict, emu_profiles: dict | None = None, target_cores: set[str] | None = None, + data_names: set[str] | None = None, ) -> list[dict]: """Find files needed by cores but not declared in platform config.""" # Collect all filenames declared by this platform @@ -333,7 +340,7 @@ def find_undeclared_files( # Archived files are grouped by archive if archive: if archive not in archive_entries: - in_repo = _name_in_index(archive, by_name, by_path_suffix) + in_repo = _name_in_index(archive, by_name, by_path_suffix, data_names) archive_entries[archive] = { "emulator": profile.get("emulator", emu_name), "name": archive, @@ -364,10 +371,10 @@ def find_undeclared_files( dest = f.get("path") or fname # Resolution: try name, then path basename, then path_suffix - in_repo = _name_in_index(fname, by_name, by_path_suffix) + in_repo = _name_in_index(fname, by_name, by_path_suffix, data_names) if not in_repo and dest != fname: path_base = dest.rsplit("/", 1)[-1] - in_repo = _name_in_index(path_base, by_name, by_path_suffix) + in_repo = _name_in_index(path_base, by_name, by_path_suffix, data_names) checks = _parse_validation(f.get("validation")) undeclared.append({ @@ -587,7 +594,10 @@ def verify_platform( status_counts[s] = status_counts.get(s, 0) + 1 # Cross-reference undeclared files - undeclared = find_undeclared_files(config, emulators_dir, db, emu_profiles, target_cores=target_cores) + from cross_reference import _build_data_dir_index + data_names = _build_data_dir_index() + undeclared = find_undeclared_files(config, emulators_dir, db, emu_profiles, + target_cores=target_cores, data_names=data_names) exclusions = find_exclusion_notes(config, emulators_dir, emu_profiles, target_cores=target_cores) # Ground truth coverage