# VPX + AWE32 devices — DOSBox-X integration Our original source for the emulated pod hardware. Kept here under version control because the DOSBox-X source tree itself (`emulator/src/`, ~490 MB) is git-ignored. - **`vpxlog.cpp`** — the Division VPX link adapter (INMOS C012 at I/O base `0x150`), grown through Phase 3: iserver handshake responder, FIFO scene decode, GL Division renderer (gallery shading model), VDB video-head splitter windows. **RIO lamp/button bezel (B2, 2026-07-24, explode layout):** `pal_draw` rings each mono-MFD head with its 8 RIO buttons (red, 4 top / 4 bottom, tucked under a 640x500 display so a 10px lip shows) and the radar with the amber Secondary/Screen side columns + a centered bottom indicator strip, lit from `serialrio`'s `RIO_GetPanelState` (off/dim/bright + white-hot press; flashing lamps blink at the RioLampState rate). No labels -- the display shows each button's function. **Click-to-press:** `rt_wndproc` hit-tests a click against the bezel and presses that RIO address (thread-safe via serialrio's queued `RIO_HostButton`); head windows are `WS_EX_NOACTIVATE` so a click never pulls foreground off DOSBox (which would demote the emu thread and stop the SDL pad poll). No-op when no `serial=rio` port is present. - **`vweawe.cpp`** — the dual-AWE32 sound device: two vendored EMU8000 cores at 0x620/0x640 (+0x400/+0x800 triplets), rear-card DSP/mixer stub at 0x240, autonomous render thread with direct winmm output. Needs the GM ROM (`emulator/roms/awe32.raw`) via `VWE_AWE_ROM` or SoundFont uploads are refused (banks declare `irom=1MGM`). See `emulator/SOUND-NOTES.md`. - **`emu8k.cpp` / `emu8k.h` / `emu8k_shim.h`** — EMU8000 wavetable core vendored from 86Box (GPL-2.0-or-later, same license as DOSBox-X), with a minimal shim; local changes are listed in the emu8k.cpp header. - **`serialnamedpipe.cpp` / `serialnamedpipe.h`** — `serial=namedpipe pipe:` backend (2026-07-12): serial-over-named-pipe for vRIO/vPLASMA, replacing com0com. DOSBox is the pipe CLIENT with 500ms background retry; typed frames carry data (`0x00 len bytes`) and DTR/RTS line state (`0x01 bits`); the full wire contract is in the header comment (pinned with the vRIO session). Supports the directserial `rxpollus`/`rxburst`/`rxdelay` low-latency knobs. Smoke-tested end-to-end 2026-07-12. - **`serialrio.cpp` / `serialrio.h`** — `serial=rio` backend (2026-07-21, keyboard field 2026-07-22): the cockpit RIO board emulated **in-fork**. It speaks the device side of the RIO 9600-8N1 protocol straight to the game's UART (no external process, no pipe) and sources pilot input from an **SDL game controller + the host keyboard** inside the emulator. Because the game↔board round trip is in-process at the emulated UART's own cadence — like the real ISA UART on a pod — the serial round-trip dropouts (livelock, `TXMAXIDLE`, `rxburst`, 15s retry) can't occur. The protocol state machine + input mapping are transcribed from the validated vRIO app (`C:\VWE\vrio` VRio.Core: `VRioDevice`, the `Protocol` codec, `Input/InputRouter` + `BindingProfileFormat`); the transport, wire pacer, panel UI and thread locks are dropped (single emulator thread). RX byte pacing reuses directserial's state machine (same `rxpollus`/`rxburst` knobs), draining a queue the board itself fills. **Keyboard field (B1):** sdlmain offers every SDL key to `RIO_HostKeyEvent()` first; while capture is ON (default) bound keys press RIO addresses or drive axes and are swallowed; unbound keys and Ctrl/Alt/Gui chords pass through (host hotkeys keep working; modifier keys BOUND as inputs are exempt from the chord rule). Default field: number/QWERTY rows = upper MFD bank, home/bottom rows = lower bank, F1–F12 = Secondary/Screen, arrows+Space = hat+main, and keyboard FLIGHT controls (operator 2026-07-22): numpad 8/2/4/6 = stick, 7/9 = pedals, LShift/LCtrl = throttle slew ±0.7/s, numpad-5 = throttle zero; the internal keypad is unbound (mission-review plumbing only). **PAUSE or SCROLL LOCK toggles capture** panel↔DOS (toggling off releases everything; needed at the netnub loop / DOS prompts); `togglekey:` adds a third toggle key for keyboards lacking both. Focus loss releases held keys (`RIO_HostFocusLost` in `GFX_LosingFocus`). A bindings file in vRIO's grammar REPLACES the default profile (conf `bindings:`, else env `VWE_RIO_BINDINGS`; key-axis modes `deflect|slew|rate|set`, sign may be a separate token; vRIO's .NET key names are aliased so a vRIO `bindings.txt` ports over). Conf: `serial1=rio [pad:] [inverty] [bindings:] [togglekey:] [rxpollus:] [rxburst:]`. **Additive** — real pods keep `directserial realport:COM1`; vRIO-over-pipe keeps `namedpipe pipe:vrio`. Confs: `net_loop_rio.conf` / `net_rp_rio.conf`; `pod-launch --rio`. B0 (pad) LIVE-CONFIRMED 2026-07-22 from the repacked dist; keyboard-field live test pending. ## Applying to a DOSBox-X source checkout Tested against DOSBox-X `v2026.06.02`, MSYS2 mingw64. 1. Copy the devices in: ``` cp emulator/vpx-device/vpxlog.cpp emulator/src/src/hardware/ cp emulator/vpx-device/emu8k.cpp emulator/src/src/hardware/ cp emulator/vpx-device/emu8k.h emulator/src/src/hardware/ cp emulator/vpx-device/emu8k_shim.h emulator/src/src/hardware/ cp emulator/vpx-device/vweawe.cpp emulator/src/src/hardware/ ``` 2. Add them to the hardware build — in `src/src/hardware/Makefile.am`, append `vpxlog.cpp emu8k.cpp vweawe.cpp` to `libhardware_a_SOURCES` (we inserted them after `glide.cpp`; if you edit the generated `Makefile`/`Makefile.in` by hand instead of re-running automake, also mirror the `$(OBJEXT)` list, the `.Po` depfile list, and the depfile include markers — grep for how `vpxlog` appears and copy the pattern). 3. Call the inits — in `src/src/gui/sdlmain.cpp`, declare `void VPXLOG_Init();` and `void VWEAWE_Init();` next to the other `*_Init()` prototypes; call `VPXLOG_Init();` right after `GLIDE_Init();` and `VWEAWE_Init();` right after `SBLASTER_Init();` (it needs the mixer initialized). 3b. The namedpipe serial backend: ``` cp emulator/vpx-device/serialnamedpipe.cpp emulator/src/src/hardware/serialport/ cp emulator/vpx-device/serialnamedpipe.h emulator/src/src/hardware/serialport/ ``` plus four small stock edits: - `src/src/hardware/serialport/Makefile.am`: append `serialnamedpipe.cpp serialnamedpipe.h` to `libserial_a_SOURCES` (same generated-Makefile caveat as step 2). - `src/include/serialport.h`: add `SERIAL_TYPE_NAMED_PIPE` to `SerialTypesE` under `#if defined(WIN32)` (before `SERIAL_TYPE_DIRECT_SERIAL`). - `src/src/hardware/serialport/serialport.cpp`: `#include "serialnamedpipe.h"`; add the `type=="namedpipe"` case to BOTH dispatch switches (SERIALPORTS ctor + the SERIAL command) and `"namedpipe"` to the `serialTypes[]` string table — grep for how `"file"` appears and copy the pattern. - `src/src/dosbox.cpp`: add `"namedpipe"` to the `serials[]` allowed-values list (without this the config parser silently falls back to `dummy`). 3c. The in-fork RIO serial backend (needs SDL2 — the whole-program link already pulls SDL2 in, and the vendored SDL2 include dir is on the global compile flags, so no per-subdir cflag edits): ``` cp emulator/vpx-device/serialrio.cpp emulator/src/src/hardware/serialport/ cp emulator/vpx-device/serialrio.h emulator/src/src/hardware/serialport/ ``` plus the same four stock edits as the namedpipe backend: - `src/src/hardware/serialport/Makefile.am`: append `serialrio.cpp serialrio.h` to `libserial_a_SOURCES` (same generated- Makefile caveat as step 2). - `src/include/serialport.h`: add `SERIAL_TYPE_RIO` to `SerialTypesE` (UNguarded — SDL is cross-platform, unlike the WIN32-only namedpipe; placed right after `SERIAL_TYPE_MOUSE`). - `src/src/hardware/serialport/serialport.cpp`: `#include "serialrio.h"`; add the `type=="rio"` case to BOTH dispatch switches and `"rio"` to the `serialTypes[]` string table (copy the `namedpipe` pattern; keep it unguarded). - `src/src/dosbox.cpp`: add `"rio"` to the `serials[]` allowed-values list. - `src/src/gui/sdlmain.cpp` (the B1 keyboard field, three small edits): (a) declare the hooks above `GFX_LosingFocus`: `bool RIO_HostKeyEvent(int sdl_scancode, bool pressed, bool repeat, unsigned int sdl_mods); void RIO_HostFocusLost(void);` (b) call `RIO_HostFocusLost();` inside `GFX_LosingFocus` right after `MAPPER_LosingFocus();` (c) in GFX_Events' SDL2 `case SDL_KEYDOWN: case SDL_KEYUP:` block, right after the SCREEN_GAMELINK early-out, offer the event to `RIO_HostKeyEvent((int)event.key.keysym.scancode, event.type == SDL_KEYDOWN, event.key.repeat != 0, event.key.keysym.mod)` and `break;` when it returns true (consumed keys must never reach the mapper). 4. Build: ``` cd emulator/src ./build-mingw-sdl2 --enable-debug=heavy ``` Output: `src/src/dosbox-x.exe`. ## Running ``` set VPXLOG=C:\VWE\TeslaRel410\emulator\vpxlog.txt emulator\src\src\dosbox-x.exe -conf emulator\capture.conf python emulator\analyze_capture.py ``` With `VPXLOG` unset the device is inert and the build behaves like stock DOSBox-X.