#!/usr/bin/env python3 # Convert a linear PSMCT32 framebuffer dump ($fwrite "%08x") to a PNG for visual triage. # Word layout = PS2 PSMCT32 0xAABBGGRR (low byte R). Usage: # gs_fb_to_png.py [width] [height] [scale] # Defaults to the SH3 real-draw FB (256x120). No-op (exit 0) if input missing or PIL absent, # so it can be chained after a sim without ever breaking the build. import sys def main(): a = sys.argv src = a[1] if len(a) > 1 else "sim/data/top_psmct32_raster_demo/sh3_real_fb_out.mem" dst = a[2] if len(a) > 2 else "sim/data/top_psmct32_raster_demo/sh3_real_fb_rtl.png" W = int(a[3]) if len(a) > 3 else 256 H = int(a[4]) if len(a) > 4 else 120 SC = int(a[5]) if len(a) > 5 else 3 try: from PIL import Image except Exception: print("[fb_to_png] PIL not available; skipping PNG"); return 0 try: words = [] with open(src) as f: for ln in f: s = ln.strip() if not s or s.startswith("/"): continue words.append(int(s, 16) & 0xFFFFFFFF) except FileNotFoundError: print(f"[fb_to_png] {src} not found; skipping"); return 0 img = Image.new("RGB", (W, H)) for i, w in enumerate(words[:W*H]): img.putpixel((i % W, i // W), (w & 0xFF, (w >> 8) & 0xFF, (w >> 16) & 0xFF)) img.resize((W*SC, H*SC), Image.NEAREST).save(dst) print(f"[fb_to_png] wrote {dst} ({W}x{H} x{SC})") return 0 if __name__ == "__main__": sys.exit(main())