ec82764bef
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression (272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps, and all dump-derived textures/traces) is excluded via .gitignore and stays local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
71 lines
3.2 KiB
Python
71 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Ch340 byte-exact parser gate. Regenerates the synthetic fixture and asserts gs_parse decodes it
|
|
into the EXACT expected normalized event stream (container header + every GIF mode). No board, no
|
|
real dump needed. Exit non-zero on any mismatch."""
|
|
import os, sys, subprocess
|
|
HERE = os.path.dirname(__file__)
|
|
sys.path.insert(0, HERE)
|
|
import gs_parse
|
|
|
|
def main():
|
|
subprocess.run([sys.executable, os.path.join(HERE, "gs_make_synthetic.py")], check=True)
|
|
fix = os.path.join(HERE, "..", "captures", "gs", "synthetic", "mini.gs")
|
|
h, ev = gs_parse.parse_dump(fix)
|
|
fail = 0
|
|
def check(cond, msg):
|
|
nonlocal fail
|
|
print((" ok " if cond else " FAIL ") + msg)
|
|
if not cond: fail = 1
|
|
|
|
check(h.serial == "SYNTH001", f"serial == SYNTH001 (got {h.serial!r})")
|
|
check(h.crc == 0x12345678, f"crc == 0x12345678 (got 0x{h.crc:08x})")
|
|
check(h.state_size == 16, f"state_size == 16 (got {h.state_size})")
|
|
|
|
# The expected ordered (kind, reg, value) skeleton of the event stream.
|
|
got = [(e.kind, e.reg, e.value) for e in ev]
|
|
exp = [
|
|
("TRANSFER","",0),
|
|
("GIFTAG","",0),
|
|
("GSREG","FRAME_1",0x0000_0000_0C00_1807),
|
|
("TRANSFER","",0),
|
|
("GIFTAG","",0),
|
|
("GSREG","PRIM", 3 | (1<<4) | (1<<6)), # via PRE
|
|
("GSREG","RGBAQ", 0xFF | (0<<8) | (0<<16) | (0x80<<24)), # vtx0 red
|
|
("GSREG","XYZ2", (100<<4) | ((50<<4)<<16) | (0x5000<<32)),
|
|
("GSREG","RGBAQ", 0x00 | (0xFF<<8) | (0<<16) | (0x80<<24)),# vtx1 green
|
|
("GSREG","XYZ2", (200<<4) | ((50<<4)<<16) | (0x5000<<32)),
|
|
("GSREG","RGBAQ", 0x00 | (0<<8) | (0xFF<<16) | (0x80<<24)),# vtx2 blue
|
|
("GSREG","XYZ2", (100<<4) | ((150<<4)<<16) | (0x5000<<32)),
|
|
("TRANSFER","",0),
|
|
("GIFTAG","",0),
|
|
("IMAGE","",0),
|
|
("FRAME_BOUNDARY","",0),
|
|
]
|
|
check(len(got)==len(exp), f"event count == {len(exp)} (got {len(got)})")
|
|
for i,(g,e) in enumerate(zip(got,exp)):
|
|
# compare kind always; reg+value only where the expected has them
|
|
if e[0] in ("GSREG",):
|
|
check(g==e, f"event[{i}] {e} (got {g})")
|
|
else:
|
|
check(g[0]==e[0], f"event[{i}] kind {e[0]} (got {g[0]})")
|
|
# IMAGE qwc + no malformed
|
|
img=[e for e in ev if e.kind=="IMAGE"]
|
|
check(len(img)==1 and img[0].info.get("qwc")==2, f"one IMAGE qwc==2 (got {[e.info for e in img]})")
|
|
check(all(e.kind!="MALFORMED" for e in ev), "no MALFORMED events")
|
|
|
|
# Ch342 — PACKED ST must expose the STQ Q lane as info["q_stq"] (don't drop RGBAQ.Q).
|
|
h2, ev2 = gs_parse.parse_dump(os.path.join(HERE, "..", "captures", "gs", "synthetic", "mini_st.gs"))
|
|
sts = [e for e in ev2 if e.kind=="GSREG" and e.reg=="ST"]
|
|
check(len(sts)==1, f"mini_st: one ST event (got {len(sts)})")
|
|
if sts:
|
|
e=sts[0]
|
|
check((e.value & 0xFFFFFFFF)==0x11111111, "mini_st: ST.S == 0x11111111")
|
|
check(((e.value>>32)&0xFFFFFFFF)==0x22222222, "mini_st: ST.T == 0x22222222")
|
|
check(e.info.get("q_stq")==0x33333333, f"mini_st: q_stq == 0x33333333 (got {e.info.get('q_stq')})")
|
|
|
|
print("RESULT:", "PASS" if not fail else "FAIL")
|
|
return fail
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|