# 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:`** (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:`** (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/` subdir). That is content/mission configuration, separate from the VPX protocol, the renderer, and the RIO — all of which now work.