fix: name RomM's size rule in every check label

This commit is contained in:
Abdessamad Derraz committed 2026-11-05 11:43:55 +01:00
1 parent e54d146954
commit ba150de469
5 files changed
+56 -42

No files matched your search

+19 -19
View File
@@ -99,24 +99,24 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/
| Platform | On its BIOS list | Files its emulators load | Checked by |
|----------|-----------------:|-------------------------:|------------|
| AmberELEC | 414/434 | 4,751/4,935 | MD5 hash |
| Batocera | 353/353 | 14,171/15,291 | MD5 hash |
| BizHawk | 118/118 | - | SHA1 hash |
| EmuDeck | 168/168 | 8,422/8,525 | MD5 hash |
| EmuELEC | 544/572 | 4,786/10,215 | MD5 hash |
| KNULLI | 290/290 | 9,126/15,349 | MD5 hash |
| Lakka | 532/532 | 7,910/7,996 | file presence |
| MiSTer FPGA | 81/81 | - | MD5 hash |
| MinUI | 0/0 | 78/79 | file presence |
| MyMinUI | 0/0 | 356/367 | file presence |
| NextUI | 0/0 | 343/350 | file presence |
| ROCKNIX | 38/38 | 7,421/9,134 | MD5 hash |
| Recalbox | 351/351 | 3,125/3,344 | MD5 hash |
| RetroArch | 526/526 | 7,919/7,987 | file presence |
| RetroBat | 348/348 | 5,133/9,658 | MD5 hash |
| RetroDECK | 2,007/2,008 | 6,703/6,991 | MD5 hash |
| RetroPie * | 532/532 | 8,120/12,775 | file presence |
| RomM | 383/383 | 83/873 | MD5 hash |
| AmberELEC | 414/434 | 4,751/4,935 | MD5 |
| Batocera | 353/353 | 14,171/15,291 | MD5 |
| BizHawk | 118/118 | - | SHA-1 |
| EmuDeck | 168/168 | 8,422/8,525 | MD5 |
| EmuELEC | 544/572 | 4,786/10,215 | MD5 |
| KNULLI | 290/290 | 9,126/15,349 | MD5 |
| Lakka | 532/532 | 7,910/7,996 | name only |
| MiSTer FPGA | 81/81 | - | MD5 |
| MinUI | 0/0 | 78/79 | name only |
| MyMinUI | 0/0 | 356/367 | name only |
| NextUI | 0/0 | 343/350 | name only |
| ROCKNIX | 38/38 | 7,421/9,134 | MD5 |
| Recalbox | 351/351 | 3,125/3,344 | MD5 |
| RetroArch | 526/526 | 7,919/7,987 | name only |
| RetroBat | 348/348 | 5,133/9,658 | MD5 |
| RetroDECK | 2,007/2,008 | 6,703/6,991 | MD5 |
| RetroPie * | 532/532 | 8,120/12,775 | name only |
| RomM | 383/383 | 83/873 | size, then any hash |
Each fraction is what the pack has over what is needed, counting required and optional files alike since both ship. The first column is the BIOS list the platform publishes. The second counts files its emulators load that this list never mentions, found by reading their source code, and it is routinely several times larger. A short fraction means files are still missing, and they are named in the [gap analysis](https://abdess.github.io/retrobios/gaps/).
That second number is a floor, not a ceiling: an emulator that accepts any file handed to it names none in its code, so nothing there can be counted.
@@ -203,4 +203,4 @@ The scripts and tooling are released under the [MIT License](LICENSE).
The BIOS and firmware files are not covered by that license: they are third-party system software, preserved and provided for personal backup, archival, and interoperability with emulation software. [NOTICE](NOTICE) sets out their status and how to ask for a file to be removed.
The reasoning, and where it is weakest, is in [the project's legal position](https://abdess.github.io/retrobios/wiki/legal/).
*Auto-generated on 2026-11-03T17:50:12Z*
*Auto-generated on 2026-11-05T10:43:18Z*
+2 -7
View File
@@ -34,6 +34,7 @@ from common import (
unique_emulator_profiles,
write_if_changed,
)
from nativemode import check_label
import release_record
from siteguides import install_command
from verify import verify_platform
@@ -737,15 +738,9 @@ def generate_readme(db: dict, platforms_dir: str, db_path: str = "database.json"
]
)
mode_labels = {
"md5": "MD5 hash",
"sha1": "SHA1 hash",
"existence": "file presence",
}
for name, cov in sorted(coverages.items(), key=lambda x: x[1]["platform"]):
display = f"{cov['platform']} *" if name in archived else cov["platform"]
checked = mode_labels.get(cov["mode"], cov["mode"])
checked = check_label(cov["mode"], cov["config"].get("hash_rule"))
core_total = (
cov["core_present"] + cov["core_missing"] + cov["core_unsourceable"]
)
+7 -16
View File
@@ -64,7 +64,7 @@ from common import (
from artifacts import ArtifactLockBusy, artifact_lock
from artifacts import json_text as _json_text
from cross_reference import FileConsumers, held_copy
from nativemode import digest_algorithm, reads_file_contents
from nativemode import check_label, digest_algorithm, reads_file_contents
@@ -3194,8 +3194,6 @@ def generate_platform_index(coverages: dict, registry: dict | None = None) -> st
SETUP_TABLE_PAGE = "wiki/verification-modes.md"
SETUP_TABLE_ANCHOR = "every-setup-at-a-glance"
SETUP_TABLE_LINK = f"{SETUP_TABLE_PAGE}#{SETUP_TABLE_ANCHOR}"
# How a setup checks a file, in the words of a reader.
_HOW_IT_CHECKS = {"existence": "name only", "md5": "MD5", "sha1": "SHA-1"}
def setup_table(coverages: dict, registry: dict | None = None) -> list[str]:
@@ -3220,7 +3218,7 @@ def setup_table(coverages: dict, registry: dict | None = None) -> list[str]:
lines.append(
f"| [{cov['platform']}](../platforms/{name}.md)"
f"{' (archived)' if status == 'archived' else ''} | {listed} | {zipped} | "
f"{_HOW_IT_CHECKS.get(cov['mode'], cov['mode'])} |"
f"{check_label(cov['mode'], cov['config'].get('hash_rule'))} |"
)
lines += [
"",
@@ -4292,9 +4290,8 @@ def _platform_guide(name: str, display: str, cov: dict, registry: dict, no_list:
return lines
# How a platform checks a file, in words.
_CHECK_WORDS = {"existence": "name only", "md5": "MD5", "sha1": "SHA-1", "sha256": "SHA-256",
"crc32": "CRC32"}
# A hash a platform's list writes, in words.
_HASH_WORDS = {"md5": "MD5", "sha1": "SHA-1", "sha256": "SHA-256", "crc32": "CRC32"}
def generate_platform_page(
@@ -4374,7 +4371,7 @@ def generate_platform_page(
*_stat(f"{cov['present']}/{cov['total']}", f"Coverage ({pct})"),
*_stat(str(cov["verified"]), "Verified"),
*_stat(str(cov["missing"]), "Missing"),
*_stat(f'<span class="rb-badge {mode_badge}">{_CHECK_WORDS.get(mode, mode)}</span>',
*_stat(f'<span class="rb-badge {mode_badge}">{check_label(mode, config.get("hash_rule"))}</span>',
"Checked by"),
"</div>",
"",
@@ -4384,7 +4381,7 @@ def generate_platform_page(
# The hash the list writes, when it is not the one the platform checks:
# RetroArch checks presence and its System.dat writes sha1.
if hash_type and hash_type != mode:
lines.append(f"| Hashes in the list | {_CHECK_WORDS.get(hash_type, hash_type)} |")
lines.append(f"| Hashes in the list | {_HASH_WORDS.get(hash_type, hash_type)} |")
if version:
lines.append(f"| Version | {version} |")
# base_destination is only the root the platform's own list writes its
@@ -10409,12 +10406,6 @@ def generate_gap_analysis(
"|----------|-----------------:|-------------------------:|------------|",
])
mode_labels = {
"md5": "MD5 hash",
"sha1": "SHA1 hash",
"existence": "file presence",
}
for pname, cov in sorted(coverages.items(), key=lambda x: x[1]["platform"]):
display = cov["platform"]
core_total = (
@@ -10424,7 +10415,7 @@ def generate_gap_analysis(
f"| [{display}](platforms/{pname}.md) "
f"| {_ratio_cell(cov['present'], cov['total'], _missing_required_firmware(cov))} "
f"| {_ratio_cell(cov['core_present'], core_total)} "
f"| {mode_labels.get(cov['mode'], cov['mode'])} |"
f"| {check_label(cov['mode'], cov['config'].get('hash_rule'))} |"
)
lines.extend([
"",
+12
View File
@@ -40,6 +40,18 @@ SIZE_AND_ANY_HASH = "size_and_any_hash"
HASH_RULES = (SIZE_AND_ANY_HASH,)
#: How a platform checks a file, in a reader's words. Every table and badge
#: that says it reads this, so a page cannot call RomM's rule an MD5 check.
_CHECK_LABELS = {"existence": "name only", "md5": "MD5", "sha1": "SHA-1"}
def check_label(mode: str | None, hash_rule: str | None = None) -> str:
"""The words for what a platform's own check compares."""
if hash_rule == SIZE_AND_ANY_HASH:
return "size, then any hash"
return _CHECK_LABELS[normalize(mode)]
def normalize(mode: str | None) -> str:
"""Return a declared mode, falling back to the schema default."""
return mode if mode in MODES else DEFAULT_MODE
+16
View File
@@ -201,6 +201,22 @@ class PlatformReferenceInWords(unittest.TestCase):
self.assertIn("[r repository at commit aaaaaaaaaaaa](https://github.com/o/r/tree/"
+ "a" * 40 + ")", page)
def test_every_check_label_reads_the_hash_rule(self):
"""RomM's badge and table rows said MD5 beside a sentence saying it
accepts the size and any one hash."""
details = [{"name": "f.bin", "status": "ok", "system": "sony-playstation"}]
cov = {"platform": "RomM", "details": details, "total": 1, "verified": 1,
"present": 1, "missing": 0, "untested": 0, "mode": "md5",
"core_present": 0, "core_missing": 0, "core_unsourceable": 0,
"config": {"hash_type": "md5", "hash_rule": "size_and_any_hash",
"systems": {"sony-playstation": {"files": [{"name": "f.bin"}]}},
"source": "https://github.com/o/r/tree/" + "a" * 40}}
page = generate_site.generate_platform_page("romm", cov, {})
self.assertIn(">size, then any hash</span>", page)
self.assertNotIn(">MD5</span>", page)
table = "\n".join(generate_site.setup_table({"romm": cov}, {}))
self.assertIn("| size, then any hash |", table)
def test_systems_by_name_with_the_id_in_small_text(self):
systems = {"sony-playstation": {"files": [{"name": "f.bin"}]}}
page = self._page("md5", "md5", systems)