Files
TeslaRel410/emulator/RIO-NOTES.md
T
CydandClaude Opus 4.8 833fe85d63 RIO passthrough: solve analog-poll latency (core=dynamic + cycles=max)
The RIO drops comms if the analog-reply ACK is late by more than a few ms.
Empirically a slower CPU failed sooner, so the latency was dominated by how
fast the game processes the RIO packet and ACKs -- core=dynamic (recompiler)
+ cycles=max keeps the board in sync (user-confirmed). game_rio.conf passes
the real RIO through serial1=directserial realport:COM1.

With real control input the sim advances and then faults (null-ptr deref at
BTL4OPT.EXE CODE+0x123B) -- downstream of the minimal test.egg not setting the
arena objectpath, so VIDEO/GEO/ARENA/thr_tshd.bgf isn't found. That is content
config, separate from the now-working VPX protocol / renderer / RIO. Details
in RIO-NOTES.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:08:39 -05:00

3.3 KiB

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) 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). The one remaining emulator-side latency is the 1 ms receive poll (directserial.cpp:68), reducible to ~0.25 ms if a future board needs it.
  • 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.

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), 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.