m4b_frames.py fuses the two proven halves: battle_frames.py's live per-draw program capture (from running-firmware C memory) + render_final.py's verified M5 texel render (perspective divide + real-texture decode). Result: the whole renderer chain runs offline from a real fifodump -- production VREND.MNG on the C i860 core -> per-draw coefficient program -> faithful frame -> PNG sequence. Verified over netdeath-20260708.fifodump: 12 frames, scene assembles draw by draw (26->48->78->87->127 quads), frame 11 = coherent perspective-correct arena interior (tiled floor to vanishing point, ceiling, side structures). This is the dress rehearsal for the live DOSBox seam -- identical pipeline, wire from a file instead of the C012 device. FINDING: firmware is real-time-capable (3.7s), the CPU numpy per-poly render is the bottleneck (69.9s/12 frames, ~5.8s/frame). The fix already exists: the conformant GPU tile path (igc_gpu). Moving the per-draw raster onto it is the M4b->M4c bridge to real-time. Full writeup in M4B-RESULTS.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.5 KiB
M4b — offline end-to-end seam: RESULTS (2026-07-20)
emu860c/m4b_frames.py — the whole renderer chain, offline, no DOSBox:
fifodump (VPXM wire) -> production VREND.MNG on the C i860 core (351x)
-> per-draw coefficient program captured LIVE from C memory (0x08158000..)
-> M5 faithful render (verified perspective divide + real-texture texel decode)
-> frame_NNNN.png sequence + timing
Run (netdeath-20260708.fifodump, 12 frames)
queued 53088 records
13 textures decoded from the wire
frame 0: 26 quads (cmd 4584)
frame 2: 48 quads (cmd 5155)
frame 4: 78 quads (cmd 6234)
frame 6: 87 quads (cmd 8046)
frame 10: 127 quads (cmd 10273)
frame 11: 127 quads (cmd 10478)
done: 12 faithful frames in 73.6s (3.7s firmware, 69.9s render), cmd 10479
The chain works end-to-end. Frames show the scene assembling draw by draw (26 -> 48 -> 78 -> 87 -> 127 quads): frame 0 is ceiling + horizon before the floor lands; frame 11 is a coherent, perspective-correct arena interior — tiled floor receding to a vanishing point, paneled ceiling, side structures, with green/blue detail where distinctive textures (emblems/labels) land.
The one finding: render is the bottleneck, not the firmware
- Firmware: 3.7 s for 10,479 wire commands producing 12 frames — real-time-capable.
- Render: 69.9 s — the CPU numpy per-poly path (O(quads x 832 x 512) float ops per draw). ~5.8 s/frame. This is the gap to close for the live seam.
The fix already exists: the GPU tile path (igc_gpu / igc_gpu_frame,
M1/M2-conformant) does the raster on the RTX in the compute shader. Moving the
per-draw raster onto it — reading the full pixel fields (texz/texu/texv/texid)
from the tile output and running the same verified texel decode as a vectorized
post-pass — is the M4b->M4c bridge to real-time.
Honest scope
- Verified: geometry, winding, perspective divide, texel decode, live per-draw program capture, full-mission drive, frame sequencing.
- Best-effort (documented M5-B limit): exact per-surface texid->texture handle. Palette shifts with the mapping (grayscale here vs teal on the static pkl); both are real decoded textures, best-effort placement.
Next (M4c)
- GPU raster in the per-draw loop (real-time render to match the real-time firmware).
- The C012 link device in DOSBox-X + socket bridge (wire from the live game instead of a file — identical pipeline downstream).
- Present path (render-bridge window / vr_readpixels).