"""EXACT scene recovery: payloads = triangles as 3 edge equations {scale,A,B,C} in stride-0x10 groups. Solve pairwise intersections -> true vertices; auto-detect tile-local vs global coords; fill triangles. Usage: tri_recover.py """ 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]; outb = sys.argv[2] mem = pickle.load(open(S + '\\' + dump, 'rb'))['mem'] def asf(w): return struct.unpack('> 23) & 0xff return 1 < e < 254 and 1e-7 < abs(asf(w)) < 1e7 # chains with tile ids regions = [] for page in sorted(set(a & ~0xfff for a in mem if 0x0801e000 <= a < 0x08030000)): sends = []; tile = None a = page while a < page + 0x800: w0 = mem.get(a); w1 = mem.get(a + 4) if w0 is None or w1 is None: a += 8; continue c = (w1 >> 28) & 0xf if c in (1, 9) and w0 >= 0x08030000: sends.append((w0, w1 & 0x7f)) elif c == 2: tile = w0 a += 8 if sends: regions.append((page, tile, sends)) def parse_edges(addr, size): """Find stride-0x10 groups {scale, A, B, C}: scale small (~1e-3..1e-1), A/B/C larger.""" edges = [] off = 0 while off + 0x10 <= size * 4 + 4: ws = [mem.get(addr + off + k) for k in (0, 4, 8, 12)] if all(w is not None and isf(w) for w in ws): s, A, B, C = (asf(w) for w in ws) if 1e-4 < abs(s) < 0.1 and (abs(A) > 0.5 or abs(B) > 0.5): edges.append((A, B, C)) off += 0x10 continue off += 4 return edges def isect(e1, e2): (a1, b1, c1), (a2, b2, c2) = e1, e2 d = a1 * b2 - a2 * b1 if abs(d) < 1e-9: return None return ((-c1 * b2 + c2 * b1) / d, (-a1 * c2 + a2 * c1) / d) tris = [] # (tile, [(x,y)x3]) for page, tile, sends in regions: for addr, size in sends: edges = parse_edges(addr, size) # group consecutive edge triples into triangles for k in range(0, len(edges) - 2, 3): e = edges[k:k+3] pts = [isect(e[0], e[1]), isect(e[1], e[2]), isect(e[2], e[0])] if all(p is not None for p in pts): tris.append((tile, pts)) xs = [p[0] for _, ps in tris for p in ps] ys = [p[1] for _, ps in tris for p in ps] if not xs: print("no triangles solved"); sys.exit() print("triangles: %d vertex range x[%.1f..%.1f] y[%.1f..%.1f]" % (len(tris), min(xs), max(xs), min(ys), max(ys))) # auto-detect: if 95% of coords within [−16, 160] treat as tile-local loc = sum(1 for v in xs + ys if -16 <= v <= 160) / len(xs + ys) tile_local = loc > 0.9 print("tile-local coords: %s (%.0f%% in range)" % (tile_local, loc * 100)) W, H = 832, 512 img = [[(6, 9, 14) for _ in range(W)] for _ in range(H)] PAL = [(65,255,142),(95,208,255),(255,176,32),(255,90,106),(234,255,239), (160,120,255),(200,200,90),(90,200,160),(255,140,110),(120,180,230)] def fill_tri(pts, col): xs_ = [p[0] for p in pts]; ys_ = [p[1] for p in pts] x0, x1 = max(0, int(min(xs_))), min(W - 1, int(max(xs_)) + 1) y0, y1 = max(0, int(min(ys_))), min(H - 1, int(max(ys_)) + 1) if x1 - x0 > 500 or y1 - y0 > 500: return # reject degenerate giants (ax, ay), (bx, by), (cx, cy) = pts den = (bx - ax) * (cy - ay) - (cx - ax) * (by - ay) if abs(den) < 1e-9: return for y in range(y0, y1 + 1): for x in range(x0, x1 + 1): w0 = ((bx - x) * (cy - y) - (cx - x) * (by - y)) / den w1 = ((cx - x) * (ay - y) - (ax - x) * (cy - y)) / den w2 = 1 - w0 - w1 if w0 >= -0.02 and w1 >= -0.02 and w2 >= -0.02: r0, g0, b0 = img[y][x] img[y][x] = (min(255, r0 + col[0] // 3), min(255, g0 + col[1] // 3), min(255, b0 + col[2] // 3)) drawn = 0 for i, (tile, pts) in enumerate(tris): if tile_local and tile is not None: ox = (tile & 0x1f) * 64; oy = ((tile >> 5) & 0x1f) * 128 pts = [(p[0] + ox, p[1] + oy) for p in pts] fill_tri(pts, PAL[i % len(PAL)]) drawn += 1 print("drawn:", drawn) 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)) from PIL import Image Image.open(S + '\\' + outb + '.ppm').save(S + '\\' + outb + '.png') print("wrote %s.png" % outb)