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>
73 lines
3.0 KiB
Python
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'))
|