Files
retroDE_ps2/tools/gs_make_sh3_banded_diag.py
T
thejayman77 ba74bbd5aa Snapshot: fog implementation + fidelity tooling baseline (pre bilinear-clamp fix)
Per-vertex GS fog end-to-end (gs_stub emit incl. persp_emit5, gs_prim_list_feeder
XYZ2->XYZF2 on PRIM.FGE, gs_make_sh3_scheduler_fixture.py F/FGE packing), new fog
TBs, fidelity attribution tooling. Functional baseline before removing the dead
bilinear lerp8 clamps (Codex: 161-node comb loop -> -0.042ns setup fail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 19:56:46 -04:00

73 lines
3.4 KiB
Python

#!/usr/bin/env python3
# Ch352 diagnostic (Codex's test): replace the SH3 texture indices with a LARGE, UNMISTAKABLE
# 16x16-cell pattern using strongly-contrasting indices from the REAL SH3 CSM1 palette, and emit it
# through the EXACT same linear LPDDR texture file the uploader streams. Geometry / CLUT / feeder are
# untouched. If the cells render as clean flat colors -> the board photo is authentic high-frequency
# SH3 texture, NOT timing corruption. If the flat cells speckle -> real corruption.
#
# LOCAL/gitignored (palette is dump-derived). Backs up the real texture to *.REAL.bak first.
import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from gs_localmem import ct32_addr # CT32 grid de-swizzle (CSM1 palette layout)
DATA = os.path.join(os.path.dirname(__file__), "..", "sim", "data", "top_psmct32_raster_demo")
TEX = os.path.join(DATA, "sh3_real_tex_lpddr.mem")
CLUT = os.path.join(DATA, "sh3_real_clut.mem")
TW = TH = 512
CELL = 16
NCHOSEN = 8
def load_words(path):
out = []
with open(path) as f:
for ln in f:
s = ln.strip()
if not s or s.startswith("/"):
continue
out.append(int(s, 16) & 0xFFFFFFFF)
return out
# ---- 1) de-grid the CSM1 palette to index order, get each index's RGB ----
clut_words = load_words(CLUT)
clut_bytes = bytearray()
for w in clut_words:
clut_bytes += (w & 0xFFFFFFFF).to_bytes(4, "little")
pal = [0]*256
for i in range(256):
a = ct32_addr(0, 1, i & 15, i >> 4) # palette entry i sits at grid (i%16, i//16)
pal[i] = int.from_bytes(clut_bytes[a:a+4], "little") if a+4 <= len(clut_bytes) else 0
rgb = [(p & 0xFF, (p >> 8) & 0xFF, (p >> 16) & 0xFF) for p in pal] # PSMCT32 low byte = R
# ---- 2) greedy farthest-point pick of NCHOSEN maximally-contrasting indices ----
def d2(a, b): return sum((a[k]-b[k])**2 for k in range(3))
chosen = [max(range(256), key=lambda i: rgb[i][0]+rgb[i][1]+rgb[i][2])] # start brightest
while len(chosen) < NCHOSEN:
nxt = max(range(256), key=lambda i: min(d2(rgb[i], rgb[c]) for c in chosen))
chosen.append(nxt)
print("[banded] chosen indices + RGB:", [(c, rgb[c]) for c in chosen])
# ---- 3) build the 16x16-cell pattern as LINEAR raster indices (PSMT8_SWIZZLE=0) ----
idx = bytearray(TW*TH)
for y in range(TH):
cy = y // CELL
for x in range(TW):
cx = x // CELL
idx[y*TW + x] = chosen[(cx + cy) % NCHOSEN] # diagonal bands of contrasting flat cells
# ---- 4) pack 4 indices / LE word, write through the exact uploader format ----
if os.path.exists(TEX) and not os.path.exists(TEX + ".REAL.bak"):
os.rename(TEX, TEX + ".REAL.bak")
print("[banded] backed up real texture ->", os.path.basename(TEX) + ".REAL.bak")
nwords = (TW*TH)//4
with open(TEX, "w") as f:
f.write("// Ch352 DIAGNOSTIC banded 16x16-cell texture (contrasting SH3 palette indices). "
"LINEAR de-swizzled, PSMT8_SWIZZLE=0. Restore from sh3_real_tex_lpddr.mem.REAL.bak. gitignored.\n")
sm = 0
for w in range(nwords):
word = idx[4*w] | (idx[4*w+1] << 8) | (idx[4*w+2] << 16) | (idx[4*w+3] << 24)
sm = (sm + word) & 0xFFFFFFFF
f.write("%08x\n" % word)
print(f"[banded] wrote {nwords} words to {TEX} sum32=0x{sm:08x}")
print("[banded] upload as usual; on HDMI expect a perspective-warped grid of FLAT contrasting cells.")
print("[banded] CLEAN flat cells => authentic texture (not corruption). SPECKLED cells => real corruption.")