#!/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 <fb.mem> <out.png> [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())
