#!/usr/bin/env python3 """ analyze_scene.py -- decode the live scene graph FLYK streams to the board. Parses the framed region of capture.raw.bin (skipping the raw .BTL boot), tracks create/flush per handle, and dumps the DPL node structs (VIEW camera, DCS matrices, INSTANCE placements, MATERIAL colours) plus the mystery 0x1c/0x1d ops -- so we can feed the dpl3-revive renderer. python analyze_scene.py [capture.raw.bin] """ import sys, struct from vrboard import Assembler, A TYPE = {2:'zone',3:'view',4:'instance',5:'dcs',6:'lmodel',7:'light',8:'object', 9:'lod',10:'geogroup',11:'geometry',12:'material',13:'texmap',14:'texture',15:'ramp'} def floats(b, n=None): n = n if n else len(b)//4 return list(struct.unpack_from('<%df' % n, b, 0)) def main(): path = sys.argv[1] if len(sys.argv) > 1 else "capture.raw.bin" data = open(path, "rb").read() # find framed start: first 0x40ff00NN length word past the BTL start = None for i in range(80000, len(data)-8): w = struct.unpack_from(' {'type':.., 'body':..} creates = [] op1c, op1d = [], [] for m in asm: if m.iserver: continue a, p = m.action, m.payload if a == A.create: typ = struct.unpack_from('= 8 else 0 nodes.setdefault(h, {})['type'] = typ creates.append((h, typ)) elif a == A.flush: h = struct.unpack_from('= 8: rem, tc = struct.unpack_from('= 68: # node(4) + matrix(64) mat = floats(rest[4:68], 16) for r in range(4): print(" [" + " ".join(f"{mat[r*4+c]:8.3f}" for c in range(4)) + "]") elif t == 'view' and len(rest) >= 64: mat = floats(rest[0:64], 16) print(" camera matrix:") for r in range(4): print(" [" + " ".join(f"{mat[r*4+c]:8.3f}" for c in range(4)) + "]") tail = floats(rest[64:64+13*4]) if len(rest) >= 64+52 else [] print(" view params (enable,x0,y0,x1,y1,zeye,xs,ys,hither,yon,bg3...):") print(" ", [round(v,3) for v in tail]) else: print(" floats:", [round(v,3) for v in floats(rest[:min(64,len(rest))])]) for t in ('view', 'dcs', 'instance', 'material'): hs = by_type.get(t, []) if hs: show(hs[0]) if op1c: print(f"\n0x1c sample ({len(op1c[0])}B):", op1c[0].hex()) if op1d: p = op1d[0]; print(f"\n0x1d sample ({len(p)}B) as floats:", [round(v,3) for v in floats(p)]) if __name__ == '__main__': main()