Emulate the cockpit RIO board natively inside the DOSBox-X fork, driven by
an SDL game controller + host keyboard -- no external vRIO process and no
named pipe. The game<->board round trip runs in-process at the emulated
UART's own cadence, so the serial round-trip dropouts (livelock, TXMAXIDLE,
rxburst, 15s retry) can't occur.
- serialrio.{cpp,h}: RIO 9600-8N1 device state machine + protocol codec +
input mapping, transcribed from the vRIO app (VRioDevice + Protocol +
InputRouter/BindingProfileFormat), minus transport/pacer/UI/locks.
B0 = gamepad (5 axes + joystick column). B1 = keyboard field: MFD banks on
the letter rows, F-keys = Secondary/Screen, numpad = flight controls,
LShift/LCtrl throttle slew; PAUSE/ScrollLock toggle panel<->DOS; vRIO-
grammar bindings file via bindings:/VWE_RIO_BINDINGS.
- vpx-device/README.md: device notes + apply steps (the DOSBox-X src tree is
git-ignored, so this dir is the tracked source of truth; the three sdlmain
keyboard-hook edits are documented there).
- net_{loop,rp}_rio.conf + deploy templates; render-bridge/
gauge_arena_rio_sound.conf (standalone -egg trim); pod-launch --rio
(mutually exclusive with --pipe).
Additive: real pods keep directserial realport:COM1; vRIO-over-pipe keeps
namedpipe pipe:vrio. Validated live 2026-07-22 (pad + keyboard field +
console networking) on the dist install.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dev-rig policy (2026-07-17): everything on the dev machine runs named pipes
to vRIO until Real-RIO testing -- no com0com. pod-launch --pipe selects the
<mode>_pipe conf (serial1=namedpipe pipe:vrio, serial2=namedpipe
pipe:vplasma); pipe variants of all three deploy templates (auto-staged/
rendered) + a dev-tree net_loop_pipe.conf beside the existing RP one.
Requires the vRIO dist >= 20260716-68e3d1f (VRioPipeService/
VPlasmaPipeService landed there). Arcade cockpits with the physical RIO
keep the plain COM-port confs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
VGL_LABS cockpit test suite as pod-launch 'test' mode
The WC hang, root-caused in three layers (each necessary):
1. WC was rendered-samples + 100ms-capped interpolation; AWEUTIL's poll
storm (~550k port-ops/s) starved the render thread of awe_lock, so the
clock crawled ~90x slow. Fixed: free-running host-clock derivation +
a fairness gate so the render thread can always take the lock.
2. Free-running at true 44.1kHz still failed: trapped port reads cost
~30us -- MORE than one 22.7us tick -- so consecutive reads skipped
counter values, and AWEUTIL's WaitUntilWC (decoded at COM offset
0x5F42) exits only on EQUALITY with a target tick: skipped value =
missed target = 1.49s wrap penalty, or forever.
3. Advancing +1 per read still failed: WaitUntilWC reads WC TWICE per
iteration, so its equality sample saw only every 2nd value -- wrong
parity = infinite loop. Final semantics: during a poll storm the
counter advances once per FOUR reads (every value observable by all
of AWEUTIL's loop shapes; its 8192-unchanged-reads dead-clock bailout
never trips), and resyncs to true wall time after any 50ms idle gap.
Result: the full stock TEST.BAT (DIAGNOSE + AWEUTIL /S on both cards)
completes in seconds.
Also: pod-launch 'test' mode -> vwetest.conf (stock TEST.BAT -> TSTALL),
DOSBox window defaults to 900,600 in test mode (the DOS screen is the
suite's UI), VWE_AWE_LOG gains storm bursts with guest cs:ip + caller and
rare-read tracing (the instrumentation that cracked this).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
--no-sound strips VWE_AWE32, the FAST (28Hz SOS) clock never ticks, and
BTL4OPT hangs forever in the RIO-reset busy-wait (L4RIO.cpp SetDTR loop on
a frozen Now()) -- looks exactly like a vRIO/serial failure but isn't.
Root-caused during the 2026-07-10 dist smoke test. Only safe with a
SLOW-clock conf (setenv arg2=s). Warn at launch + document in usage/README.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Complete arg surface of the single installed entry-point -- mode selector
(bt/rp + recognized-unsupported), feature toggles, window placement, path
overrides, diagnostics, and the exit codes the console reads back (game
ExitCodeID passed through; 2=bad args; 3=mode not yet wired).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Network-agnostic, air-gapped pod install for the two DOSBox titles (BT/RP 4.10),
fitting the existing TeslaConsole/TeslaLauncher pod-bay architecture.
emulator/DEPLOYMENT-PLAN.md
Full design: bridge on the one NIC (pods form a source-proven P2P TCP mesh, so
NAT/slirp is out); launcher keeps the bay IP, the DOSBox guest bridges at
bayIP+100 (egg/mesh/game endpoint); two-edit +100 convention (postinstall +
console DOSBox flag); static, air-gapped, <=32 pods.
emulator/pod-launch/ (C# net8 supervising entry-point)
Creates a Job Object (KILL_ON_JOB_CLOSE), launches DOSBox-X + the render bridge
into it and blocks -- kill this process and both die (kernel-enforced, even on
a hard TerminateProcess of a hung session; verified). Mode dispatch: bt/rp
wired (also serve camera + live mission-review via egg hostType); review +
diagnostics recognized but fail clean until their DOS launch args are known.
emulator/deploy/ (install side)
postinstall.bat (thin elevated wrapper) + configure.ps1 (NIC detect, realnic
bind as a contiguous letter-leading GUID fragment, game IP = bayIP+100, stable
MAC, render net_*.conf templates, stamp WATTCP.CFG my_ip) + tokenized conf
templates + package.ps1 (assemble the zip). Render/bind/stamp + packaging
verified against a scratch tree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>