Files
TeslaRel410/dpl3-revive/patha/CAPTURE.md
T
CydandClaude Fable 5 afc3fd839e Vendor dpl3-revive: the Division/DPL3 renderer, now ours
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>
2026-07-05 22:06:25 -05:00

124 lines
5.9 KiB
Markdown

# Capturing real FLYK.EXE link traffic (Path A validation)
Goal: run the genuine `FLYK.EXE` under DOSBox-X, have it talk to our Python
`vrboard` in place of the dead i860 board, and log every byte — to validate the
message framing against the *shipped* binary and pin the two open items
(`vr_readpixels` reply layout, and the bit30 `0x40000000` receive-side meaning).
## Why a responder, not a passive log
`start_velocirender()` streams the transputer `.BTL`, then blocks in
`startup_handshake()` waiting for **3 iserver transactions from the board**
(`VR_COMMS.C`). No framed `vr_*` message is sent until that handshake completes. So a
passive port logger stalls at boot and never sees the interesting scene traffic. The
link must *respond*. We keep all protocol logic in the tested Python `vrboard` and make
the emulator side a dumb byte-pipe.
## Architecture — socket bridge
```
FLYK.EXE (unmodified, in DOSBox-X)
│ IN/OUT ports 0x150-0x161 (polled C012, LINKIO.C)
DOSBox-X I/O handler (host-level C++, ~40 lines) ── TCP 127.0.0.1:8620 ──► vrserver.py
▲ │
└─────────────────────── board→host reply bytes ◄─────────────────────────┘
(VirtualBoard + full logging → capture.log)
```
The I/O handler runs at **host** level (it's DOSBox-X code, not guest code), so it can
open a normal host socket. No guest-side driver, no changes to `FLYK.EXE`.
## Port map (mirror of LINKIO.C `setLA`)
| Port | Dir | Handler action |
|------|-----|----------------|
| 0x150 | R (Input Data) | return next board→host byte (from socket recv buffer) |
| 0x151 | W (Output Data) | send byte to socket (host→board) |
| 0x152 | R (Input Status) | pump socket; bit0=1 if a byte is available |
| 0x153 | R (Output Status)| bit0=1 (always ready to accept) |
| 0x160 | W reset / R fifo | on write send the RESET marker; on read return 1 |
| 0x161 | W (Analyse) | ignore |
## Drop-in DOSBox-X I/O handler (sketch)
Add to a new `src/hardware/vrlink.cpp` and call `VRLINK_Init()` from hardware init.
Adapt the handler signatures to your DOSBox-X version; init Winsock on Windows.
```cpp
// vrlink.cpp -- bridge the C012 link ports (0x150-0x161) to vrserver.py
#include "inout.h"
#include <winsock2.h> // Windows; use <sys/socket.h> on *nix
static SOCKET s = INVALID_SOCKET;
static unsigned char rxbuf[4096]; static int rxlen=0, rxpos=0;
static void connect_board() {
WSADATA w; WSAStartup(MAKEWORD(2,2), &w);
s = socket(AF_INET, SOCK_STREAM, 0);
int one=1; setsockopt(s, IPPROTO_TCP, TCP_NODELAY,(char*)&one,sizeof one);
sockaddr_in a{}; a.sin_family=AF_INET; a.sin_port=htons(8620);
a.sin_addr.s_addr=inet_addr("127.0.0.1");
connect(s,(sockaddr*)&a,sizeof a);
u_long nb=1; ioctlsocket(s, FIONBIO, &nb); // non-blocking reads
}
static void pump() { // fill rxbuf if empty
if (rxpos<rxlen) return;
int n=recv(s,(char*)rxbuf,sizeof rxbuf,0);
if (n>0){ rxlen=n; rxpos=0; } else { rxlen=rxpos=0; }
}
static Bitu rd(Bitu port, Bitu){
switch(port){
case 0x150: pump(); return rxpos<rxlen ? rxbuf[rxpos++] : 0xFF; // Input Data
case 0x152: pump(); return rxpos<rxlen ? 1 : 0; // Input Status
case 0x153: return 1; // Output Status
case 0x160: return 1; // fifo-ok
} return 0xFF;
}
static void wr(Bitu port, Bitu val, Bitu){
unsigned char b=(unsigned char)val;
switch(port){
case 0x151: send(s,(char*)&b,1,0); break; // Output Data
case 0x160: send(s,"\x00RSET",5,0); break; // reset marker
case 0x161: break; // analyse: ignore
}
}
void VRLINK_Init(){
connect_board();
for (Bitu p=0x150; p<=0x161; ++p){ IO_RegisterReadHandler(p,rd,IO_MB); IO_RegisterWriteHandler(p,wr,IO_MB); }
}
```
## Run
1. `python vrserver.py` (listens on 127.0.0.1:8620, writes `capture.log`)
2. Launch DOSBox-X (with the handler built in). Mount the HPDAVE tree, set `DOS4GPATH`
to `sda4/BIN`, run the app the way `SETSVGA.BAT` + `HLOOP.BAT` do:
```
set DOS4GPATH=C:\SDA4\BIN
call SETSVGA.BAT REM sets DPLARG=/tranny~...~/i860~...~/device~0x150~/video~svga~...
FLYK.EXE <scene args> REM (see HFLY/HLOOP for the scene/run pair)
```
3. Watch `capture.log` — it annotates every reassembled message and reply. Boot should
walk: RESET → 3 iserver txns → `hspcode`/`860code`/`860data`/`860bss`/`860args`
(discarded) → `init` → scene `create`/`flush`/`dcs_*`/`set_geom_verts`/
`set_texmap_texels` → `draw_scene` → `readpixels`.
## What the capture proves / pins
- **Assembler validation:** every message reassembles with the source-derived framing
(incl. the mirrored bit30). Any mismatch shows up immediately as a bad length/action.
- **`vr_readpixels` layout (open item):** the request args and the reply chunking/pixel
word order the shipped lib expects — the one payload the source snapshot stubs.
- **bit30 semantics (open item):** whether FLYK's receive path requires `0x40000000` on
replies (we already set it) or ignores it.
Once the capture is clean, swap the stub responder for the real render path
(`vrboard` → dpl3-revive pipeline) and `vr_readpixels` returns actual frames.
## No build environment?
If DOSBox-X + a C++ toolchain isn't set up, the alternative is to compile the original
host comms (`VR_COMMS.C` + `LINKIO.C` + `DPL_HOST.C`, port I/O teed to a file) natively
and drive it with a `STARTDPL.C`-style scene — same framed output, no emulator. Heavier
(needs the DPL types to build); the socket bridge above is the lighter path.