diff --git a/scripts/region_check.py b/scripts/region_check.py index 3ba28643b..76f509b6c 100644 --- a/scripts/region_check.py +++ b/scripts/region_check.py @@ -144,7 +144,8 @@ def outcome(records: dict[str, dict], entries: list[dict], region: str) -> dict: continue loaded = all(rep.get("loaded") for v in record["variants"] for rep in v["repetitions"]) item = {"record": record["id"], "verdict": verdict(record), "loaded": loaded, - "staged": sorted(record["variants"][0]["system_files"])} + "staged": sorted(record["variants"][0]["system_files"]), + "bios_used": record["variants"][0].get("bios_used", "unknown")} if full and label != "full": item["as_full"] = loaded and frames(record) == frames(full) results[label] = item @@ -173,22 +174,48 @@ def outcome(records: dict[str, dict], entries: list[dict], region: str) -> dict: "own_boots": boots("own"), "others_boot": boots("others"), "pack_boots": boots("pack"), + # The BIOS each ran, from its log: a boot is not the staged file's + # until the log names it (core_probe.bios_used). + "own_on": (results.get("own") or {}).get("bios_used", "unknown"), + "others_on": (results.get("others") or {}).get("bios_used", "unknown"), "judged_by": "verdict" if full_verdict not in (None, "unknown") else "full_run_frames", } +BUILTIN = "builtin" + + +def staged_name(used: str | None) -> str | None: + """The file a bios_used names, or None.""" + return used.removeprefix("staged:") if used and used.startswith("staged:") else None + + def sentence(game_region: str, result: dict) -> str: - """The outcome in words, for the site.""" + """The outcome in words, for the site. A boot is said to be another + region's BIOS only when the core's log names that file: a core that + refuses the staged files and runs its own BIOS (OpenBIOS, HLE) boots + too, on that built-in BIOS.""" word = REGION_WORDS.get(game_region, game_region) own, others = result.get("own_boots"), result.get("others_boot") if own is None: return f"The {word} game has no run with its own BIOS yet." - first = f"The {word} BIOS {'boots' if own else 'does not boot'} the {word} game" + if own and result.get("own_on") == BUILTIN: + first = f"The {word} game boots on the core's built-in BIOS, its own BIOS file was refused" + else: + first = f"The {word} BIOS {'boots' if own else 'does not boot'} the {word} game" if others is None: return first + ". The other regions' BIOS have no verdict yet." - if others: - return first + ", and so do the other regions' BIOS." - return first + ", the other regions' BIOS do not." + if not others: + return first + ", the other regions' BIOS do not." + used = result.get("others_on") + if used == BUILTIN: + return (first + ". With only the other regions' files it boots on its built-in BIOS, " + "the other regions' files were refused.") + name = staged_name(used) + if name: + return first + f", and so does {name}, another region's BIOS." + return (first + ". With only the other regions' files staged it boots too, on a BIOS " + "its log does not name.") # -------------------------------------------------------------------------- diff --git a/scripts/sitemeasurements.py b/scripts/sitemeasurements.py index 8e53f0276..b0b3f90c1 100644 --- a/scripts/sitemeasurements.py +++ b/scripts/sitemeasurements.py @@ -75,9 +75,21 @@ def permalink(repo: str, commit: str, path: str, line: int | None = None) -> str return f"{repo}/blob/{commit}/{path}" + (f"#L{line}" if line else "") +BOOTS_BUILTIN = "boots on built-in BIOS" + + +def shown_verdict(variant: dict) -> str: + """A variant's verdict as the pages say it: a boot on the core's + built-in BIOS is named so, never taken for the staged file's.""" + if variant["verdict"] == "boots" and variant.get("bios_used") == "builtin": + return BOOTS_BUILTIN + return variant["verdict"] + + def verdicts_of(record: dict) -> list[dict]: - """Each variant's boot verdict, from record version 4 on.""" - return [{"variant": v["label"], "verdict": v["verdict"], + """Each variant's boot verdict, from record version 4 on, and the BIOS + it ran from version 5 on.""" + return [{"variant": v["label"], "verdict": shown_verdict(v), "bios_used": v.get("bios_used", "unknown"), "detail": (v.get("verdict_evidence") or {}).get("detail", "")} for v in record["variants"] if "verdict" in v] @@ -537,17 +549,33 @@ REGION_SHORT = {"japan": "Japanese", "north-america": "US", "europe": "European" OUTCOME_WORDS = {True: "boots", False: "does not boot", None: "no verdict"} +def others_words(result: dict) -> str: + """What the run with only the other regions' files did, never calling a + boot the other region's BIOS unless the core's log names that file.""" + boots = result.get("others_boot") + if boots is not True: + return f"{OUTCOME_WORDS[boots]} with only the others" + used = result.get("others_on") + if used == "builtin": + return "boots on its built-in BIOS with only the others, which were refused" + if used and used.startswith("staged:"): + return f"boots on {used.removeprefix('staged:')} with only the others" + return "boots with only the others, on a BIOS its log does not name" + + def core_region_line(results: list[dict]) -> str: """One core's outcome over its region games, in a sentence: each game - on its own BIOS, then on the other regions' BIOS.""" + on its own BIOS, then with only the other regions' files.""" own = {r["own_boots"] for r in results} others = {r["others_boot"] for r in results} - if own == {True} and others == {True}: - return "Each region's game boots on its own BIOS and on the other regions' BIOS." + builtin = {r.get("others_on") for r in results} == {"builtin"} + if own == {True} and others == {True} and builtin: + return ("Each region's game boots on its own BIOS. With only the other regions' files it " + "boots on its built-in BIOS: those files were refused.") if own == {True} and others == {False}: return "Each region's game boots on its own BIOS only." parts = [f"{REGION_SHORT.get(r['region'], r['region'])} game: {OUTCOME_WORDS[r['own_boots']]} " - f"on its BIOS, {OUTCOME_WORDS[r['others_boot']]} on the others" for r in results] + f"on its BIOS, {others_words(r)}" for r in results] return ", ".join(parts) + "." @@ -854,6 +882,7 @@ def _short(commit: str | None) -> str: # A verdict or a comparison, as the block says it: words and a chip kind. RESULT_WORDS = { "boots": ("works", "success"), + BOOTS_BUILTIN: ("works on its built-in BIOS", "success"), "bios_error": ("BIOS error", "danger"), "crash": ("crash", "danger"), "hang": ("hang", "warning"), @@ -1023,9 +1052,9 @@ def variant_groups(record: dict) -> list[dict]: if all("verdict" in v for v in record["variants"]) and ( record["kind"] == "run" or check.get("observable") == "frame_hashes"): for variant in record["variants"]: - position.setdefault(variant["verdict"], len(position)) - result[variant["label"]] = RESULT_WORDS[variant["verdict"]][0] - groups = {v["label"]: position[v["verdict"]] for v in record["variants"]} + position.setdefault(shown_verdict(variant), len(position)) + result[variant["label"]] = RESULT_WORDS[shown_verdict(variant)][0] + groups = {v["label"]: position[shown_verdict(v)] for v in record["variants"]} else: groups = {} for number, group in enumerate((check.get("result") or {}).get("groups") or ()): diff --git a/tests/test_measurements.py b/tests/test_measurements.py index 4bf2f34f5..6e30f4fe2 100644 --- a/tests/test_measurements.py +++ b/tests/test_measurements.py @@ -252,6 +252,29 @@ class ReadAndIndex(Workspace): self.assertEqual([(g["variant"], g["result"], g["group"]) for g in groups], [("v0", "works", 0), ("v1", "hang", 1)]) + def test_a_boot_on_the_built_in_bios_is_named_so(self) -> None: + import core_probe # noqa: PLC0415 + + record = full_record("alpha", "region-x-game-others", "2026-10-28T10:00:00+00:00", + kind="run", observable="frame_hashes") + oracle = {"references": [{"sha1": "1" * 40, "stage": "game", "shows": "the title"}], + "error_patterns": [], "error_screens": [], "bios_patterns": [], + "fallback_patterns": [r"^Firmware is missing: "], "load_patterns": []} + for variant in record["variants"]: + for rep in variant["repetitions"]: + rep["logs"] = [{"frame": 0, "level": "info", "text": "Firmware is missing: scph5501.bin"}] + core_probe.judge_repetition(rep, oracle) + core_probe.judge_variant(variant) + self.assertEqual(record["variants"][0]["bios_used"], "builtin") + status, statement = sm.result_of(record) + self.assertEqual(status, sm.BOOTS_BUILTIN) + self.assertIn("built-in BIOS", statement) + item = {**SitePages.ITEM, "host_short": "h", "kind": "run", "status": status, "statement": statement, + "groups": sm.variant_groups(record), "verdicts": sm.verdicts_of(record)} + text = "\n".join(sm.tested_section("alpha", [item])) + self.assertIn("works on its built-in BIOS", text) + self.assertNotIn("other region", text) + def test_links_name_the_last_commit_that_touched_the_records(self) -> None: first = self.repository() (self.tree / "other.txt").write_text("x") diff --git a/tests/test_region_check.py b/tests/test_region_check.py index f39cf5aee..efcc3aea3 100644 --- a/tests/test_region_check.py +++ b/tests/test_region_check.py @@ -27,9 +27,10 @@ PROFILE = { def record(rid: str, staged: list[str], opened: list[str], hashes: list, verdict: str = "unknown", - loaded: bool = True) -> dict: + loaded: bool = True, bios_used: str = "unknown") -> dict: return {"id": rid, "variants": [{ - "label": "default", "verdict": verdict, "system_files": {name: "0" * 40 for name in staged}, + "label": "default", "verdict": verdict, "bios_used": bios_used, + "system_files": {name: "0" * 40 for name in staged}, "repetitions": [{"loaded": loaded, "files_opened": [{"path": p} for p in opened], "observables": {"frame_hashes": hashes}}]}]} @@ -145,8 +146,34 @@ class Outcome(unittest.TestCase): "own": record("o", ["scph5502.bin"], [], [[0, "a"]], "boots"), "others": record("x", ["scph5501.bin"], ["scph5501.bin"], [[0, "a"]], "boots")} result = rc.outcome(records, self.ENTRIES, "europe") + # The log names no BIOS: the boot is not said to be the other region's. self.assertEqual(rc.sentence("europe", result), - "The European BIOS boots the European game, and so do the other regions' BIOS.") + "The European BIOS boots the European game. With only the other regions' files " + "staged it boots too, on a BIOS its log does not name.") + records["others"] = record("x", ["scph5501.bin"], ["scph5501.bin"], [[0, "a"]], "boots", + bios_used="staged:scph5501.bin") + self.assertEqual(rc.sentence("europe", rc.outcome(records, self.ENTRIES, "europe")), + "The European BIOS boots the European game, and so does scph5501.bin, " + "another region's BIOS.") + + def test_a_boot_on_the_built_in_bios_is_never_another_regions(self) -> None: + """Beetle PSX logs "Firmware is missing" and maps OpenBIOS: the other + regions' files were opened, hashed and refused.""" + records = {"full": record("f", self.ALL, self.ALL, [[0, "a"]], "boots", + bios_used="staged:scph5501.bin"), + "own": record("o", ["scph5501.bin"], ["scph5501.bin"], [[0, "a"]], "boots", + bios_used="staged:scph5501.bin"), + "others": record("x", ["scph5500.bin", "scph5502.bin"], ["scph5500.bin", "scph5502.bin"], + [[0, "a"]], "boots", bios_used="builtin")} + result = rc.outcome(records, self.ENTRIES, "north-america") + text = rc.sentence("north-america", result) + self.assertEqual(text, "The US BIOS boots the US game. With only the other regions' files it " + "boots on its built-in BIOS, the other regions' files were refused.") + self.assertNotIn("so do the other regions", text) + import sitemeasurements as sm + line = sm.core_region_line([result]) + self.assertIn("built-in BIOS", line) + self.assertNotIn("on the other regions' BIOS", line) def test_no_own_run(self) -> None: self.assertEqual(rc.sentence("japan", rc.outcome({}, self.ENTRIES, "japan")),