CydandClaude Fable 5 a1b7dae3da vPLASMA: companion app emulating the cockpit plasma display
The cockpit's second serial device joins vRIO: the 128x32 dot-matrix
plasma on COM2 (9600 8N1) that the game draws mission text and status
graphics on. VPlasma.App opens the device end of a COM port, decodes
the display's command stream, and renders the matrix in plasma orange.

The command set is recovered from two Tesla 4.10 artifacts: the game's
driver (L4PLASMA.CPP — ESC P packed-bitmap row writes, ESC G 0 cursor
hide at boot) and the factory test tool PLASMA.EXE, whose data segment
pairs each command literal with its printf description (BS/HT/LF/VT/CR
motion, ESC @ clear, ESC L home, ESC G cursor, ESC K fonts, ESC H
attributes: intensity/underline/reverse/flash). Text renders through
the classic public-domain 5x7 set standing in for the lost ROM glyphs;
fonts 0-3 give 21x4 cells, fonts 4-7 the doubled 10x2. A Self test
cycles banner/charset/graphics pages through the same parser the wire
feeds, and the wire log shows every decoded command.

Verified end-to-end over the second com0com pair (host writing COM2,
vPLASMA listening on COM12). The verify skill gains the cross-process
combo-box lesson: string-carrying CB_* messages hang across processes,
so select ports by locally computed index via CB_SETCURSEL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:22:00 -05:00

vRIO — virtual RIO cockpit device

A software replica of the cockpit RIO (Remote Input/Output) board: it opens a COM port and speaks the device side of the RIO serial protocol, so any host that expects the real hardware — most importantly RIOJoy — can talk to it without a cockpit attached. (The cockpit's other serial device gets the same treatment: see vPLASMA below.)

The window is an interactive version of the cockpit control panel that RIOJoy's profile editor draws (the same functional layout from the original Win32 RIO design: five MFD clusters, four board columns, two keypads, encoder gauges). But where the editor edits bindings, vRIO's cells are the physical controls:

  • Left-click a cell — momentary button press (ButtonPressed/Released or KeyPressed/Released on the wire). Right-click — latch it down.
  • Drag the X/Y box and the Z / L / R gauges — the five analog axes, returned by the next AnalogReply (14-bit signed, 7-bit-pair packed). Gauges span each axis' realistic hardware travel, not the full 14-bit range: Z/L/R rest at raw 0 at the gauge bottom and travel to 800 (throttle — forward travel runs negative, matching RIOJoy's ratchet) or +500 (spring-loaded pedals), and the stick covers ±80 around center — the windows RIOJoy's calibrator expects.
  • Cells shade to the lamp state the host commands (LampRequest: off / dim / bright, with slow/med/fast flash), so RIOJoy's press-feedback lights the on-screen panel just like the real buttons.
  • Lamps can mirror onto an RGB keyboard (Mirror lamps on RGB keyboard, via Windows 11 Dynamic Lighting): keys bound to lamp-capable buttons glow with the panel's palette and blink in step with the on-screen flash modes; per-key keyboards get the full button field, zone-lit keyboards show the strongest current lamp board-wide, and a picker narrows the mirror to one keyboard when several are attached. For the LEDs to stay lit while the game has focus, vRIO needs package identity: run pkg\Register-vRIO.ps1 once (Developer Mode required; pass the exe folder for a deployed copy), launch vRIO from its Start menu entry (a direct exe launch runs without identity), then drag vRIO to the top of Settings → Personalization → Dynamic Lighting → Background light control.
  • Keyboard and Xbox (XInput) controller input drive the same controls through a bindings file (%APPDATA%\vRIO\bindings.txt, created with commented defaults on first run — Edit bindings… opens it, Reload bindings applies edits live). Keys and pad buttons press any RIO address; pad sticks/triggers and keys drive the axes in each axis' realistic travel window, with deflect (spring-back), rate (throttle-style, position holds), deadzone, and invert options. The default profile makes the controller mandatory: all five axes live on the pad (left stick / triggers / right stick = stick / pedals / throttle) and the keyboard covers the button field — number row + QWERTY row = the upper MFD bank, home + bottom rows = the lower MFD bank (4-key blocks split by an unbound gap key), F1F6 / F7F12 = the Secondary / Screen columns, numpad = internal keypad (hex keys on the operators), arrows + Space = hat + main, with ABXY / dpad / shoulders on the pad's named buttons.
  • Capture one keyboard in the background (Capture keyboard picker in the Input panel): by default keyboard input follows the focused window, so vRIO goes deaf the moment the sim takes focus. Selecting a specific keyboard instead taps it through the Windows Raw Input API (RIDEV_INPUTSINK), so its keys drive the panel while the game has focus — the input-side twin of the lamp mirror writing that keyboard's LEDs under the same condition. Raw Input observes without intercepting: the keystroke still reaches the focused app, so this is meant for a keyboard dedicated to the panel, not the one you also type on. Leaving the picker on All keyboards keeps the plain focus-only behavior. (No package identity needed — unlike the lamp side, this is a plain Win32 tap.)

Wire behavior

Protocol per riojoy/docs/PROTOCOL.md (9600 8N1, [cmd][payload…][7-bit checksum], ACK 0xFC / NAK 0xFD / RESTART 0xFE / IDLE 0xFF), with device behavior grounded in the real v4.2 firmware dump (riojoy/rio-firmware/RIOv4_2-ANALYSIS.md):

  • ACKs every well-formed packet; NAKs bad-checksum packets.
  • TX is paced at the wire rate — one byte per 10-bit frame (~1.04 ms at 9600 8N1), never closer. A virtual null-modem has no UART, so unpaced writes would land at the host in microsecond bursts no real board could produce; vRIO's writer thread schedules each byte against a monotonic slot deadline instead, so e.g. the 51-byte CheckRequest response takes the same ~53 ms it takes real hardware.
  • CheckRequest → the real board's init handshake: TestModeChange enter, one BoardOk CheckReply per board (the 11 boards from the legacy firmware's table), then TestModeChange exit. Hosts wait (≤5 s per step) on both test-mode packets and send nothing while test mode is active, so the exit is mandatory. VersionRequest → configurable version, default 4.2.
  • ResetRequest re-zeroes the targeted axis (or all).
  • A NAK re-sends the last event up to 4 times, then gives up with a RESTART byte — the real board's retry budget.
  • Optional v4.2 reply-wedge emulation (in VRio.Core; the UI toggles were removed): after retry exhaustion, analog requests are silently dropped — still ACK'd, RX path alive — until a host ResetRequest, reproducing the latch-leak fault the firmware analysis documents.

Using it with RIOJoy on one PC

The two apps need a crossed serial link. Install a com0com virtual null-modem pair (e.g. COM1 ⇄ COM11), then:

  1. Run VRio.App, pick COM11, Open.
  2. RIOJoy will always poit to COM1.

RIOJoy's DTR open-pulse shows up in the wire log (DSR handshake), its ~55 ms analog polling drives the "analog polls served" counter, and every click on the vRIO panel arrives at RIOJoy as real cockpit input. Two physical PCs with a null-modem cable work the same way.

vPLASMA — the companion plasma display

The cockpit's second serial device is the plasma display: a 128×32 dot-matrix panel on COM2 (9600 8N1, no flow control) that the game draws mission text and status graphics on. VPlasma.App is its software replica: it opens the device end of a COM port, decodes the display's command stream, and renders the dot matrix in plasma orange — text mode included.

The command set was recovered from two Tesla 4.10 artifacts: CODE\RP\MUNGA_L4\L4PLASMA.CPP (the game's driver — it renders everything into a local 1bpp buffer and streams changed rows as ESC P graphics writes, hiding the cursor with ESC G 0 at boot) and the factory test tool VWETEST\VGLTEST\PLASMA.EXE (the text mode: BS/HT/LF/VT/CR cursor motion, ESC @ clear, ESC L home, ESC G cursor visibility, ESC K font select, ESC H attributes — intensity/underline/reverse/flash). The full recovered grammar lives in src/VPlasma.Core/Protocol/PlasmaProtocol.cs.

  • GraphicsESC P screen y xbyte width rows + packed 1bpp row data, MSB = leftmost pixel. This is everything the game sends, so it is the wire path a pod's plasma actually sees.
  • Text — printable ASCII renders through a 5×7 font at a cursor: fonts 03 give a 21×4 cell grid, fonts 47 the same glyphs doubled to 10×2. Half-intensity draws dimmer, reverse/underline render in the cell, flashing text (and the flashing cursor) blink on the glass. The panel's own ROM glyphs are lost with the hardware, so the classic public-domain 5×7 set stands in.
  • Self test cycles three pages (banner, charset, graphics pattern) through the same parser the wire feeds — useful without a host.
  • Pair it with the game like vRIO ↔ RIOJoy: a second com0com null-modem pair (e.g. COM2 ⇄ COM12) — the game's plasma output writes COM2, vPLASMA listens on COM12. The plasma never talks back, so there is no transmit path to pace.

Repository layout

Path Contents
src/VRio.Core Protocol framing/builder/parser, the VRioDevice state machine, serial pump, panel layout data (class library)
src/VRio.App WinForms panel UI
src/VPlasma.Core Plasma command-stream parser, the VPlasmaDevice display state machine, 5×7 font, serial listener (class library)
src/VPlasma.App WinForms dot-matrix display UI
pkg Sparse-package manifest + registration script: grants VRio.App.exe the package identity Dynamic Lighting's background-control list requires
tests/VRio.Core.Tests xUnit tests for the protocol + device engine
tests/VPlasma.Core.Tests xUnit tests for the plasma parser + display engine

Building

Same toolchain as RIOJoy: .NET SDK (8.0+) with the .NET Framework 4.8 targeting pack; apps target net48 so deployed builds run in-box on Windows 10/11.

dotnet build VRio.sln -c Release
dotnet test VRio.sln

Interop is additionally verified against RIOJoy's real RioSerialLink (version/check/analog/lamp/button/keypad/reset round-trips over an in-memory transport) — see the RIOJoy repo for the host side.

S
Description
No description provided
Readme
4 MiB
Languages
C# 97.4%
PowerShell 1.8%
QMake 0.8%