Files
TeslaRel410/emulator/vpx-device/README.md
T
CydandClaude Opus 4.8 9dd0aa8702 emulator: RIO panel click-to-press + lamp flash blink
Make the in-fork glass cockpit fully interactive and finish the lamp model.

- Click-to-press: clicking a button's region in a VDB head window presses that
  RIO address into the game (lights white-hot while held, releases on mouse-up).
  vpxlog rt_wndproc hit-tests the click against the bezel geometry (MFD 4 top /
  4 bottom, radar 6 left / 6 right; the radar bottom indicators are display-only,
  not clickable); head windows are tagged via GWLP_USERDATA. Clicks arrive on the
  VPX render thread, so the seam serialrio RIO_HostButton() queues them under a
  mutex and pollInput() drains them on the emu tick through the same incHold/
  decHold path as the keyboard/pad -- so a click also lights the bezel.
- Flash blink: decode the lamp byte's flash bits (RioLampState 1 slow / 2 med /
  3 fast) -- an unpressed flashing lamp now toggles between its brightness level
  and off (half-periods 500/250/125ms); solid lamps unchanged, a press still wins.
- Focus: head windows are WS_EX_NOACTIVATE so a button click never pulls
  foreground off DOSBox (which would demote the emu thread and stop SDL polling
  the pad); a click uses MA_NOACTIVATE too. Do NOT enable SDL background joystick
  events -- that raced the emu-thread controller poll against SDL's main-thread
  pump and crashed the process.

Explode layout only, and only when a serial=rio port is present.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 11:50:53 -05:00

162 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<n>=namedpipe
pipe:<name>` 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<n>=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, F1F12 = 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:<sdl-name>` 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:<path>`, 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:<n>] [inverty] [bindings:<path>]
[togglekey:<key>] [rxpollus:<us>] [rxburst:<n>]`. **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.