From 833fe85d63d7ac268954db3f80841f4a82ad7a52 Mon Sep 17 00:00:00 2001 From: Cyd Date: Fri, 3 Jul 2026 15:08:39 -0500 Subject: [PATCH] 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 --- emulator/RIO-NOTES.md | 72 ++++++++++++++++++++++++++++++++++++++++++ emulator/game_rio.conf | 32 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 emulator/RIO-NOTES.md create mode 100644 emulator/game_rio.conf diff --git a/emulator/RIO-NOTES.md b/emulator/RIO-NOTES.md new file mode 100644 index 0000000..f237b74 --- /dev/null +++ b/emulator/RIO-NOTES.md @@ -0,0 +1,72 @@ +# 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). 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](../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. diff --git a/emulator/game_rio.conf b/emulator/game_rio.conf new file mode 100644 index 0000000..c237480 --- /dev/null +++ b/emulator/game_rio.conf @@ -0,0 +1,32 @@ +[sdl] +output=opengl +[dosbox] +memsize=32 +machine=svga_s3 +[cpu] +# The RIO drops comms if an ACK is late by more than a few ms. Empirically +# (2026-07-03) a SLOWER CPU makes it fail SOONER -> the ACK latency is +# dominated by how fast the game processes the RIO packet and replies, so we +# run the CPU as fast as possible: +# - core=dynamic: recompiler, many x faster than the 'normal' interpreter. +# - cycles=max: full host speed. +core=dynamic +cputype=pentium +cycles=max +# RIO cockpit controls on COM1 (Phase 5 passthrough), plasma COM2 later. +[serial] +serial1=directserial realport:COM1 +serial2=disabled +[autoexec] +mount c "C:\VWE\TeslaRel410\ALPHA_1" +c: +cd \REL410\BT +set VIDEOFORMAT=svga +set BLASTER=A220 I5 D1 H5 P330 T6 +set TEMP=c:\ +call setenv.bat r s n n +32rtm.exe -x +btl4opt.exe -egg test.egg +32rtm.exe -u +echo ALPHA1-RUN-DONE +pause