Bring the graphics-dev collaborator's dpl3-revive into the repo as first-class
project code (they've handed it off; it's ours now). This is the proven
Division renderer that our in-process rt_draw has been trying to be.
What's here:
- parser/ B2Z/V2Z/SVT/SCN/SPL/BGF/BMF/BSL decoders (pure Python).
- spec/ reverse-engineered format + the definitive VelociRender wire
protocol (from the original DIVISION source, matches our live
VPX node/action tables exactly).
- source-ref/ read-only copies of the original DIVISION C (BIZREAD.C,
DPLTYPES.H, DPL.H) that define the formats.
- patha/ the "virtual VelociRender board": vrboard.py (24-action protocol
server), vrview.py (numpy software rasterizer, the reference),
vrview_gl.py (moderngl GPU backend, 832x512@60Hz), plus the
run/replay/regress tooling and evidence renders. Drives FLYK/BLADE/
Star Trek demos AND our btl4opt/rpl4opt game binaries.
- viewer/ WebGL archive generators (.py); prebuilt HTML/data regeneratable.
- samples/ small test models/textures.
- bt*.raw.bin real BTL4OPT arena wire captures (kept for offline renderer
testing/regression against OUR game).
.gitignore keeps the multi-hundred-MB demo capture dumps + debug logs +
regeneratable viewer bundles out of history (they stay on disk).
Phase 0 of the integration is validated: their board decodes our bt8 capture
with zero errors (3748 nodes, 507 instances, 4 mechs) and renders our arena
(terrain/dome/sky, correct Division DAC gamma). Plan + status in memory;
integration continues in emulator/RENDERER-COLLAB.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
2.9 KiB
Python
72 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
census.py -- full inventory of a staged-run capture: create types, list_add tree,
|
|
instance/geogroup/material flush refs. Establishes the shipped node-type ids and
|
|
the object->lod->geogroup->geometry linkage the renderer walks.
|
|
|
|
python census.py cap5.raw.bin
|
|
"""
|
|
import sys, struct
|
|
from collections import defaultdict
|
|
sys.path.insert(0, '.')
|
|
from vrboard import Assembler, A
|
|
from decode_anim import find_framed_start
|
|
|
|
# shipped type ids (established cap3-cap5; 1994 ids differed from 7 up)
|
|
TYPE = {2:'zone',3:'view',4:'instance',5:'dcs',6:'lmodel',7:'object',8:'lod',
|
|
9:'geogroup',0xa:'geometry',0xb:'material',0xc:'texmap',0xd:'texture',
|
|
0xe:'light',0xf:'ramp'}
|
|
|
|
def main():
|
|
path = sys.argv[1] if len(sys.argv) > 1 else 'cap5.raw.bin'
|
|
data = open(path, 'rb').read()
|
|
asm = Assembler(); asm.feed(data[find_framed_start(data):])
|
|
types, flushes, edges = {}, defaultdict(list), []
|
|
extra = defaultdict(int)
|
|
for m in asm:
|
|
if m.iserver: continue
|
|
a, p = m.action, m.payload
|
|
if a == A.create and len(p) >= 8:
|
|
t, h = struct.unpack_from('<II', p, 0); types[h] = t
|
|
elif a == A.flush:
|
|
h = struct.unpack_from('<I', p, 0)[0]; flushes[h].append(p)
|
|
elif a in (A.dcs_nest, A.dcs_link, A.dcs_prune, A.list_add, A.list_remove):
|
|
x, y = struct.unpack_from('<II', p, 0); edges.append((A(a).name, x, y))
|
|
elif a in (A.draw_scene,) or a in (0x1d, 0x17, 0x19, 0x2a, 0x1c):
|
|
if a not in (9,): extra[a] += 0
|
|
else:
|
|
try: A(a)
|
|
except ValueError: extra[a] += 1
|
|
|
|
tn = lambda h: TYPE.get(types.get(h), f'?{types.get(h)}') + f':{h:#x}'
|
|
print('type census:', {TYPE.get(t, hex(t)): sum(1 for x in types.values() if x == t)
|
|
for t in sorted(set(types.values()))})
|
|
print('unknown extra actions:', {hex(k): v for k, v in extra.items()})
|
|
|
|
print('\n=== list_add / dcs edges ===')
|
|
for op, x, y in edges:
|
|
lhs = 'scene:0x0' if x == 0 else tn(x)
|
|
print(f' {op:9} {lhs:16} <- {tn(y)}')
|
|
|
|
print('\n=== per-type last-flush word dump (refs annotated) ===')
|
|
for h in sorted(flushes):
|
|
t = TYPE.get(types.get(h))
|
|
if t not in ('instance', 'geogroup', 'material', 'lod', 'object', 'texmap',
|
|
'texture', 'geometry'):
|
|
continue
|
|
body = flushes[h][-1]
|
|
n = len(body) // 4
|
|
wi = struct.unpack_from('<%dI' % n, body, 0)
|
|
wf = struct.unpack_from('<%df' % n, body, 0)
|
|
out = []
|
|
for i in range(2, n):
|
|
w, f = wi[i], wf[i]
|
|
if w in types: out.append(f'[{i}]={tn(w)}')
|
|
elif w == 0xffffffff: out.append(f'[{i}]=-1')
|
|
elif w and (w < 0x1000): out.append(f'[{i}]={w}')
|
|
elif w and abs(f) > 1e-6 and abs(f) < 1e6: out.append(f'[{i}]={f:.3f}')
|
|
print(f' {t:9} {h:#04x} ({len(body)}B x{len(flushes[h])}): ' + ' '.join(out))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|