Files
TeslaRel410/emulator/firmware-decomp/recover_scene.py
T
CydandClaude Opus 4.8 24ddbd4970 Second scene recovered: the Klingon vessel (klngvid)
recover_scene.py generalizes the recovery (dual-window dump -> chain walk ->
position/segment parse -> render) for any capture. Applied to klngvid: 139
content payload programs, 96 positions + 62 edge segments = a sparse starfield
with a dense edge tangle right-of-center -- a vessel in space. Readout §06 now
shows both recovered scenes (warp field + Klingon) side by side.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:19:21 -05:00

73 lines
3.0 KiB
Python

"""Generalized scene recovery: given a dual-window dump pkl (bin pages + content
region), walk the DMA chains, parse every content payload's screen-space floats
(+0x14/+0x18, +0x24/+0x28), and render points+streaks to PNG.
Usage: recover_scene.py <dump.pkl> <out-base>"""
import sys, pickle, struct, collections
S = r'C:\Users\cyd\AppData\Local\Temp\claude\c--VWE-TeslaRel410\4e848c76-6e89-4034-8047-d8d491cb32d8\scratchpad'
dump = sys.argv[1] if len(sys.argv) > 1 else 'klng_wide30.pkl'
outb = sys.argv[2] if len(sys.argv) > 2 else 'klng_scene'
mem = pickle.load(open(S + '\\' + dump, 'rb'))['mem']
def asf(w):
return struct.unpack('<f', struct.pack('<I', w & 0xffffffff))[0]
def isf(w):
e = (w >> 23) & 0xff
return 1 < e < 254 and 1e-6 < abs(asf(w)) < 1e6
# chain walk: every SEND target from bin pages
sends = set()
for a in sorted(k for k in mem if 0x0801e000 <= k < 0x08030000):
w0 = mem.get(a); w1 = mem.get(a + 4)
if w0 is None or w1 is None: continue
if ((w1 >> 28) & 0xf) in (1, 9) and w0 >= 0x08030000:
sends.add((w0, w1 & 0x7f))
print("content sends:", len(sends))
pts = []; segs = []
for addr, size in sorted(sends):
def f(off):
w = mem.get(addr + off)
return asf(w) if w is not None and isf(w) else None
x1, y1, x2, y2 = f(0x14), f(0x18), f(0x24), f(0x28)
if x1 is not None and y1 is not None and -100 < x1 < 1000 and -100 < y1 < 600:
pts.append((x1, y1))
if x2 is not None and y2 is not None and -100 < x2 < 1000 and -100 < y2 < 600:
segs.append((x1, y1, x2, y2))
print("positions: %d segments: %d" % (len(pts), len(segs)))
if not pts:
print("no positions parsed -- content window may differ; check send addrs:")
for a, s in sorted(sends)[:10]:
print(" %08x size=%d present=%s" % (a, s, (a in mem)))
sys.exit()
W, H = 832, 512
img = [[(5, 8, 13) for _ in range(W)] for _ in range(H)]
def put(x, y, c, blend=1.0):
xi, yi = int(x), int(y)
if 0 <= xi < W and 0 <= yi < H:
r0, g0, b0 = img[yi][xi]
img[yi][xi] = (min(255, int(r0 + c[0] * blend)),
min(255, int(g0 + c[1] * blend)),
min(255, int(b0 + c[2] * blend)))
def line(x1, y1, x2, y2, c):
steps = max(1, int(max(abs(x2 - x1), abs(y2 - y1))))
for i in range(steps + 1):
t = i / steps
put(x1 + (x2 - x1) * t, y1 + (y2 - y1) * t, c, 0.5)
for x1, y1, x2, y2 in segs:
line(x1, y1, x2, y2, (200, 80, 70))
for x, y in pts:
put(x, y, (255, 240, 230)); put(x + 1, y, (170, 120, 110)); put(x, y + 1, (170, 120, 110))
buf = bytearray()
for row in img:
for r, g, b in row:
buf += bytes((r, g, b))
open(S + '\\' + outb + '.ppm', 'wb').write(b'P6\n%d %d\n255\n' % (W, H) + bytes(buf))
try:
from PIL import Image
Image.open(S + '\\' + outb + '.ppm').save(S + '\\' + outb + '.png')
print("wrote %s.png" % outb)
except Exception as e:
print("ppm only:", e)
pickle.dump({'pts': pts, 'segs': segs}, open(S + '\\' + outb + '_pos.pkl', 'wb'))