Phase 3a: decode captured VPX render stream to pixels (SMPTE bars)
- vpxlog.cpp: VPX_FIFODUMP=<path> records every FIFO burst ('VPXM' records)
- decode_fifodump.py: action census + payload dumps of a capture
- render_capture.py: reconstruct the DPL scene graph from a capture and
software-render each draw_scene frame (camera, view, materials, geometry
all taken from the wire)
- divrgb.conf + divrgb.fifodump: flyk divrgb.scn capture fixture
- divrgb-decoded.png / divrgb-frame0.png: first images ever produced from
the Rel 4.10 VPX protocol without a real board -- the textbook SMPTE
color-bar pattern, validating verts/conns/materials/camera in one shot
- PHASE3-PROGRESS.md: the established Rel 4.10 wire protocol (action map,
node types, message layouts); RENDER-HARNESS.md updated
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# Phase 3 — Render Backend: Progress
|
||||
|
||||
**Status (2026-07-03): Phase 3a complete — the render command stream is fully
|
||||
captured and decoded, and a captured DIVRGB frame has been reconstructed to
|
||||
pixels. First image ever produced from the Rel 4.10 VPX protocol without a
|
||||
real board.**
|
||||
|
||||

|
||||
|
||||
That is `flyk divrgb.scn` — Division's SMPTE color-bar calibration scene —
|
||||
rendered *entirely from the FIFO command stream captured by the emulated VPX
|
||||
board*: geometry, connectivity, materials, camera, viewport and background all
|
||||
come from the wire, none from the scene files. `divrgb-frame0.png` is the same
|
||||
capture drawn with the actual frame-0 spline camera the app sent.
|
||||
|
||||
## 3a. Full FIFO capture
|
||||
|
||||
`vpxlog.cpp` now records every FIFO burst when `VPX_FIFODUMP=<path>` is set
|
||||
(records: `'VPXM'` magic, u32 length, raw bytes; one record per burst between
|
||||
`outputData` tag writes). The capture used here: `divrgb.fifodump`
|
||||
(1297 messages) from `divrgb.conf`.
|
||||
|
||||
Tools:
|
||||
|
||||
- `decode_fifodump.py <dump> [--hex N] [--action A]` — action census + payload
|
||||
hexdumps.
|
||||
- `render_capture.py <dump> [-o out.png] [--frame N] [--eye x,y,z]` —
|
||||
reconstructs the scene graph and software-renders the frame each
|
||||
`draw_scene` commits.
|
||||
|
||||
## The Rel 4.10 wire protocol (established from this capture)
|
||||
|
||||
One burst per message: `[action:4][payload]`, packetized at 508 bytes.
|
||||
The i860 image download itself rides the FIFO in this build (actions 18–20,
|
||||
`VREND.MNG`). The DPL3 `vr_action` enum holds for 0–23 but Rel 4.10 extends
|
||||
and re-purposes the tail:
|
||||
|
||||
| action | meaning | payload |
|
||||
|---|---|---|
|
||||
| 0 | init | args string (`/device~0x150~/video~svga~…`) |
|
||||
| 1 | create | `[type][name]` — **the host assigns node names** (1,2,3…); the board's create reply node value is ignored |
|
||||
| 3 | flush | `[name][type][node struct]` (see node types below) |
|
||||
| 7 | dcs_link | `[parent][child]` |
|
||||
| 9 | draw_scene | `[view?][0][0][1][1.0f]` — commits the frame |
|
||||
| 11 | list_add | `[parent][child]` |
|
||||
| 18–21 | 860code/data/bss/args | i860 download (FIFO in this build) |
|
||||
| 23 | **set_geom_verts** (Rel4.10; DPL3 had 22) | hdr `[name][0][n_verts][3][n_blocks][1][5][n_verts][1.0f]`, then float32 x,y,z per vertex |
|
||||
| 25 | **set_geom_conns** (new) | hdr `[name][n_polys][loop_len][0]`, then indices; each poly a closed loop (last=first) |
|
||||
| 31 | **camera** (new) | `[?][view][3×3 rotation, row-major][eye x,y,z]` per frame |
|
||||
| 45 (0x2D) | sync | token ping (see PHASE2) |
|
||||
|
||||
Node types (from create/flush pairs in this capture):
|
||||
|
||||
| type | node | flush payload highlights |
|
||||
|---|---|---|
|
||||
| 2 | texture/ramp? | one word, `0xFFFFFFFF` / `0x0FFFFFFF` |
|
||||
| 3 | view | window l,b,r,t (±1 × ±0.6154), window-plane distance 1.3, viewport 832×512, near 2, far 12000, background RGB |
|
||||
| 4 | light | |
|
||||
| 5 | dcs | 4×4 matrix |
|
||||
| 6 | material (old-style) | RGB floats |
|
||||
| 7 | object | |
|
||||
| 8 | lod | 2×4 bounds + lists |
|
||||
| 9 | geogroup | bounds; **payload int 14 = material node name** |
|
||||
| 10 | geometry | `[geo_type][n_polys][n_verts]…[radius]` |
|
||||
| 11 | material | **floats 10–12 (payload) = diffuse RGB** |
|
||||
|
||||
Graph: `list_add` links object→lod→geogroup→geometry (and zone-level nodes to
|
||||
node 0); geogroups bind materials by name. The 13 DIVRGB bars decode to the
|
||||
textbook SMPTE pattern — 7 color bars, the reverse strip, and the −I/white/+Q
|
||||
PLUGE row — which validates vertices, connectivity, materials, camera and
|
||||
window mapping in one image. (Division screen x runs opposite to a GL-style
|
||||
eye space; without negating x the pattern comes out mirrored.)
|
||||
|
||||
## Next: 3b — live OpenGL backend
|
||||
|
||||
Feed the same decode path a live stream inside DOSBox-X instead of a dump:
|
||||
maintain the node store in `vpxlog.cpp` (or a sibling `vpxrender.cpp`), upload
|
||||
geometry on set_geom_verts/conns, draw on draw_scene into an OpenGL window
|
||||
(or the DOSBox surface). The `divrgb.fifodump` fixture allows developing the
|
||||
backend offline; `flyk yip.scn` (CYCLE, Red Planet geometry) is the next
|
||||
fixture up once the DOS/4GW sync variant is handled, then the game itself
|
||||
(`buttee.bgf` etc. via the production content path).
|
||||
Reference in New Issue
Block a user