IOS LLE: checkpoint NAND conformance and diagnostic tooling
Preserve formatted NAND boot and Wii Remote pairing, add DMA/SRAM conformance tests and a Wii comparison probe. Keep P1 profiling tools and native update A/B evidence; reject the unhelpful targeted SRAM shortcut.
This commit is contained in:
1 parent
b931671fde
commit
c230971f07
64 files changed
+6488
-238
No files matched your search
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compare two runs of the identical Wii conformance DOL."""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
METADATA = ("schema", "rounds", "observations", "ios_version", "ios_revision")
|
||||
HEADER = ["seq", "test", "round", "value", "extra"]
|
||||
|
||||
|
||||
def read_capture(path: Path):
|
||||
with path.open(newline="", encoding="utf-8") as stream:
|
||||
rows = csv.reader(stream)
|
||||
metadata = {}
|
||||
for key in METADATA:
|
||||
row = next(rows, None)
|
||||
if row is None or len(row) != 2 or row[0] != key:
|
||||
raise ValueError(f"{path}: expected metadata row {key!r}")
|
||||
metadata[key] = int(row[1])
|
||||
if next(rows, None) != HEADER:
|
||||
raise ValueError(f"{path}: invalid observation header")
|
||||
observations = []
|
||||
for line, row in enumerate(rows, start=7):
|
||||
if len(row) != 5:
|
||||
raise ValueError(f"{path}:{line}: expected 5 columns")
|
||||
seq, test, round_number, value, extra = row
|
||||
if int(seq) != len(observations):
|
||||
raise ValueError(f"{path}:{line}: sequence is not contiguous")
|
||||
observations.append((test, int(round_number), int(value), int(extra)))
|
||||
if len(observations) != metadata["observations"]:
|
||||
raise ValueError(
|
||||
f"{path}: expected {metadata['observations']} observations, "
|
||||
f"found {len(observations)}"
|
||||
)
|
||||
return metadata, observations
|
||||
|
||||
|
||||
def compare(reference, candidate, limit=20):
|
||||
reference_meta, reference_rows = reference
|
||||
candidate_meta, candidate_rows = candidate
|
||||
for key in METADATA:
|
||||
if reference_meta[key] != candidate_meta[key]:
|
||||
print(f"Incomparable runs: {key}: Wii={reference_meta[key]}, Dolphin={candidate_meta[key]}")
|
||||
return 2
|
||||
|
||||
differences = 0
|
||||
for index in range(max(len(reference_rows), len(candidate_rows))):
|
||||
expected = reference_rows[index] if index < len(reference_rows) else None
|
||||
actual = candidate_rows[index] if index < len(candidate_rows) else None
|
||||
if expected == actual:
|
||||
continue
|
||||
differences += 1
|
||||
if differences <= limit:
|
||||
print(f"#{index} Wii={expected} Dolphin={actual}")
|
||||
|
||||
if differences:
|
||||
print(f"{differences} differences across {max(len(reference_rows), len(candidate_rows))} observations")
|
||||
return 1
|
||||
print(f"Identical: {len(reference_rows)} observations")
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("wii", type=Path, help="CSV from the real Wii")
|
||||
parser.add_argument("dolphin", type=Path, help="CSV from Dolphin")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
return compare(read_capture(args.wii), read_capture(args.dolphin))
|
||||
except (OSError, ValueError) as error:
|
||||
print(error, file=sys.stderr)
|
||||
return 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user