Texturing (validated live -- game-live-textured.png, the ravine's brown dirt terrain): the wire model is Division's intensity+ramp scheme. action 26 uploads 8-bit intensity texels ([node][nbytes][w][h] + rows; type 13 = texture); texmap (12) references the texture; material (11) references its texmap and a ramp (14: lo/hi RGB); texel color = lerp(lo, hi, i/255). The backend bakes RGBA per material, uploads to GL, maps with wire UVs (stride-5: floats 3-4; stride-8/9: floats 6-7). Serial (directserial fork options, tracked in vpx-device/serialport/): - rxpollus:<us> -- receive poll tick (stock 1ms); 100us discovers inbound bytes ~10x sooner. Validated: sim advanced, camera moved with real RIO. - rxburst:<n> -- stock DOSBox re-serializes received bytes at emulated wire speed (~1ms/byte at 9600) though they already paid wire time on the real cable; a 15-byte analog reply gained ~14ms, blowing the RIO's few-ms ACK window and dropping the game into its 15-second retry fallback (L4CTRL.CPP limit=15.0 //0.2). rxburst:16 delivers buffered bytes 16x faster. game_rio.conf: realport:COM1 rxpollus:100 rxburst:16. Crash-on-advance fixed: *_TSHD.BGF terrain shadows live only in arena subdirs the search path misses; null shadow renderable was dereferenced once the sim moved. All 11 copied into VIDEO/GEO in the working image; game now runs sustained (560+ frames, textured, no crash). Details in RIO-NOTES.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
102 lines
4.7 KiB
Markdown
102 lines
4.7 KiB
Markdown
# RIO cockpit controls — passthrough tuning (Phase 5+)
|
||
|
||
The RIO (Remote Input/Output) is the cockpit control board on **COM1** (the
|
||
plasma display is COM2, handled later). DOSBox-X talks to a real RIO through
|
||
`serial1=directserial realport:COM1` (`game_rio.conf`). On this host the RIO is
|
||
a **Prolific USB-to-Serial adapter enumerated as COM1**.
|
||
|
||
## The analog-poll latency problem (solved)
|
||
|
||
The initial RIO *check* request tolerates latency and passed easily. But the
|
||
runtime control loop ([L4CTRL.CPP:1145](../CODE/RP/MUNGA_L4/L4CTRL.CPP)) sends
|
||
an **analog request** every cycle and, if the reply doesn't return inside its
|
||
window, logs `LBE4ControlsManager::Execute, lost RIO analog request` and
|
||
re-requests. The board itself refuses/drops comms if the ACK is late by more
|
||
than a few milliseconds — a hard real-time deadline.
|
||
|
||
Empirical result (2026-07-03): a **slower** CPU made the RIO fail **sooner**.
|
||
So the dominant latency was how fast the game processes the RIO packet and
|
||
emits the ACK, not the serial wiring. The fix:
|
||
|
||
```
|
||
[cpu]
|
||
core=dynamic ; recompiler — many x faster than the 'normal' interpreter
|
||
cputype=pentium
|
||
cycles=max ; full host speed
|
||
```
|
||
|
||
With `core=dynamic + cycles=max` the RIO **stays in sync** (the user confirmed
|
||
"the rio behaved"). Notes:
|
||
- `cycles=fixed 20000` / `150000` and `core=normal` were all too slow — the RIO
|
||
dropped comms, faster at lower speeds.
|
||
- The DOSBox-X serial path is already low-latency on **transmit**
|
||
(`directserial.cpp` `transmitByte` calls `SERIAL_sendchar` immediately).
|
||
- Prolific PL2303 has no adjustable `LatencyTimer` registry value (unlike
|
||
FTDI); an FTDI adapter set to 1 ms latency would be the lowest-latency host
|
||
option if ever needed.
|
||
|
||
## Receive-latency fork options (2026-07-03)
|
||
|
||
Even with the fast CPU, intermittent timeouts remained and the game would
|
||
drop into its **15-second analog retry fallback** — the source shows
|
||
`limit = 15.0; // 0.2` in L4CTRL.CPP, so the shipped binary re-requests very
|
||
slowly once replies stop arriving ("the polling is really slow"). Two
|
||
emulator receive latencies were fixed with new `directserial` options:
|
||
|
||
- **`rxpollus:<us>`** (50–1000, stock 1000): host-port receive poll tick.
|
||
Stock DOSBox-X discovers inbound bytes on a 1 ms tick; 100 µs discovers
|
||
them ~10× sooner. First validated result: the sim advanced and the camera
|
||
moved in the render window.
|
||
- **`rxburst:<n>`** (1–64): stock DOSBox re-serializes each received byte at
|
||
emulated wire speed (~1 ms/byte at 9600) even though the bytes already
|
||
paid their wire time on the physical cable and sit in the host buffer — a
|
||
15-byte analog reply gained ~14 ms of artificial latency, single-handedly
|
||
blowing the RIO's few-ms ACK window. `rxburst:16` delivers buffered bytes
|
||
16× faster.
|
||
|
||
`game_rio.conf` uses `realport:COM1 rxpollus:100 rxburst:16`.
|
||
|
||
## Crash-on-advance fixed: arena terrain shadows
|
||
|
||
With the RIO in sync the sim advances and the game crashed dereferencing the
|
||
**mech terrain shadow** renderable: `*_TSHD.BGF` live only in
|
||
`VIDEO/GEO/ARENA/` + `…/POLAR/`, which the object search path misses, so
|
||
`thr_tshd.bgf` failed to load and left a null renderable that the moving sim
|
||
eventually touched. Fix: the 11 `*_TSHD.BGF` files are copied from `ARENA/`
|
||
into `VIDEO/GEO/` in the working image (reversible, one file each). After
|
||
the fix the game runs sustained (500+ frames, no crash).
|
||
|
||
## Next wall: mission content (a game-data issue, not protocol/RIO)
|
||
|
||
With the RIO feeding real input, the simulation advances — and then the game
|
||
faults:
|
||
|
||
```
|
||
32loader runtime error: Unhandled exception
|
||
Exception 0E at 00FF:0040223B
|
||
Module 'BTL4OPT.EXE' section 'CODE' offset 0000123B
|
||
[..] 8B 4D 0C (mov ecx,[ebp+0C]) 8B 11 (mov edx,[ecx]) ECX=2
|
||
The instruction referenced illegal address 00000002
|
||
```
|
||
|
||
A near-null pointer (`2`) dereference: a function got `2` where an object
|
||
pointer was expected. This is downstream of the failed content load logged
|
||
just before it:
|
||
|
||
```
|
||
Entity -1:63 class:42 couldn't figure out how to MakeEntityRenderables
|
||
L4VIDEO.cpp couldn't load object thr_tshd.bgf
|
||
```
|
||
|
||
`thr_tshd.bgf` exists in `VIDEO/GEO/ARENA/` and `VIDEO/GEO/POLAR/`, but not the
|
||
top `VIDEO/GEO/`. The game builds its object search path from **`objectpath`
|
||
entries in the mission notation file** ([L4VIDEO.CPP:1852](../CODE/RP/MUNGA_L4/L4VIDEO.CPP)),
|
||
i.e. from the `.egg`. The shipped `test.egg` is only mission parameters and
|
||
does not set up the arena object path, so arena-specific objects aren't found;
|
||
the entity gets a broken renderable and the sim eventually dereferences it.
|
||
|
||
**To progress past this needs a real mission/arena `.egg`** (or an object path
|
||
manually pointed at the selected arena's `VIDEO/GEO/<ARENA>` subdir). That is
|
||
content/mission configuration, separate from the VPX protocol, the renderer,
|
||
and the RIO — all of which now work.
|