Companion to OUTPUT-INTEGRATION.md: the three input surfaces (ViGEm x360 pad, SendInput scancode keyboard/mouse, RioGamepad HID), per-button routing kinds incl. the fixed 11-button pad order, axis calibration + routing with the triggers-are-buttons trap and the shipped Descent pattern, per-game strategy, profile building/triggers workflow, benchless testing, checklist. Cross-linked from README and the output guide. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8.2 KiB
Input integration guide (cockpit → RIOJoy → game)
How a game receives the cockpit's inputs — the 72 lighted buttons, two 16-key keypads, and 5 analog axes — and how to build the profile that maps them. This is the mirror of OUTPUT-INTEGRATION.md (game → cockpit); the wire protocol lives in PROTOCOL.md, the profile/auto-switch model in PLAN.md.
What a game sees
RIOJoy translates cockpit events into ordinary Windows input, per profile, through three surfaces (all can be active at once — each button picks its route):
| Surface | What the game sees | When |
|---|---|---|
| Virtual Xbox 360 pad (ViGEm) | a normal XInput controller: 11 buttons, D-pad, 2 sticks, 2 triggers | default on Windows 10/11 when ViGEmBus is installed |
Keyboard / mouse (SendInput) |
scancode keystrokes with modifiers; relative mouse moves + clicks | any button routed to a key/mouse action |
| RioGamepad HID | a native 6-axis, 96-button, 1-hat joystick | fallback when ViGEm is absent; the XP flavor |
The sink is chosen at activation: ViGEm → RioGamepad feeder → none (keyboard and mouse always work). Most games — XInput and DirectInput alike — see the Xbox 360 pad as a standard controller; the practical limit is its 11 mappable buttons, so keyboard routing carries everything beyond that.
The input inventory
- 72 lighted buttons, RIO addresses
0x00–0x47, grouped into five MFD clusters and four columns — the physical map is in OUTPUT-INTEGRATION.md. - Two 4×4 keypads: internal
0x50–0x5F, external0x60–0x6F(key label → address = base + hex digit; no lamps). - 5 analog inputs — joystick X/Y, throttle, left pedal, right pedal —
calibrated into 6 virtual axes (X, Y, Z, Rx, Ry, Rz), each
0..32766with center16383.
Per-button routing
Every mapped address carries one action (the iRIO word, PROTOCOL.md §5).
The editor exposes these as the Action kinds:
| Kind | What happens on press/release |
|---|---|
| Keyboard | key down/up by scancode (so DOS-era and raw-input games see it), with optional Shift/Ctrl/Alt held around it and the extended-key flag for nav keys |
| Joystick | virtual pad button 1–11 (or 1–96 on the RioGamepad HID) |
| Hat | the POV hat / D-pad direction (up/right/down/left; release = centered) |
| Mouse | relative move in clean 50-px steps (up/right/down/left) or left/right click — the legacy build's mixed-up move deltas are fixed in the port |
| RIO command | internal: axis recalibrations/resets, version/check request, diagnostic toggles — useful on a spare cockpit button so recalibration never needs the desktop |
| Lit flag | lamp follows the button (dim idle, bright pressed). Also marks the lamp as profile-owned, which shields it from the feedback endpoint (see OUTPUT-INTEGRATION.md) |
The Xbox 360 button map
RIO joystick buttons are assigned in this fixed order — pick low numbers for the game's most important actions:
| RIO joy button | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Pad button | A | B | X | Y | LB | RB | Back | Start | L3 | R3 | Guide |
The hat maps to the D-pad. Buttons past 11 are dropped by the pad — route those to the keyboard instead. (On the RioGamepad HID all 96 buttons exist natively and no mapping table applies.)
Axes
Calibration (per profile)
Calibration holds per-axis invert flags and EnableZR:
- Joystick X/Y auto-range from observed travel with a small deadzone.
- Throttle (Z) is the ratcheted lever; calibrated so the detent rest
position reads 0, full forward
32766— i.e. it is naturally unipolar. - Pedals feed Rx/Ry directly, or — with
EnableZR— mix into a single rudder axis:Rz = 16383 − left/2 + right/2(Rx/Ry then idle).
Routing onto the pad (AxisRouting, JSON-only)
Each of the six axes picks a Target and Mode
(src/RioJoy.Core/Output/AxisRoutingConfig.cs; null section = the legacy
default routing):
| Axis | Default target | Conversion |
|---|---|---|
| X | LeftThumbX | Centered |
| Y | LeftThumbY | Centered |
| Z | LeftTrigger | trigger byte value×255/32766 |
| Rx | RightThumbX | Centered |
| Ry | RightThumbY | Centered |
| Rz | RightTrigger | trigger byte |
Modes for thumb targets: Centered ((value−16383)×2 → stick range) for
axes that rest mid-travel, UnipolarPositive (rest 0 = stick center,
32766 = stick max — only the upper half is used) for the ratcheted throttle.
Target: "None" suppresses an axis entirely.
The triggers-are-buttons trap: many games hard-bind the pad triggers to
fire/actions. If the throttle rides LeftTrigger (the default), advancing the
throttle fires. The shipped Descent profile
(profiles/descent-d1x.json) is the worked
example: throttle → RightThumbY UnipolarPositive, rudder mix →
RightThumbX, pedals None, keeping both triggers free for the game.
Choosing a strategy per game
- Modern XInput game — pad buttons + axes for the flight controls, keyboard routing for the long tail (MFD pages, systems). Check the game's own binding UI to see the pad.
- DOS / emulated game (DOSBox, source ports) — mostly keyboard routing (it arrives as scancodes, which DOSBox maps cleanly); axes via the pad if the emulator supports a controller, else map coarse throttle steps to keys.
- Legacy DirectInput sim — the x360 pad appears as a DirectInput device too; if the game needs more than 11 buttons on the stick itself, prefer keyboard routing or run the RioGamepad HID (96 native buttons).
- Anything with a clickable cockpit — mouse routing gives you cursor nudges and clicks from cockpit buttons.
Building the profile
- Create/edit from the tray: Edit profile. The editor shows the cockpit panel in its functional groups; click a button, set its label, action, modifiers, and Lit, then Apply. Save writes the config.
- Live check: with the RIO (or vRIO) connected, physical presses light the panel and the axis gauges move — before any game is involved. The "Send button output to the PC" toggle turns real keystroke injection on when you want to test into an editor/notepad.
- Triggers: comma-separated executable names that auto-activate the
profile when their window is foreground (
d1x-rebirth, descent). Matching is basename, case-insensitive,.exeoptional. First matching profile wins; DOSBox-hosted games all share the DOSBox exe name (rename per game or switch manually); native games (Firestorm, Red Planet) go inNativeGameExecutablesinstead — RIOJoy releases the ports for them. - RIO port: leave
(app default), or a COM name, orpipe:vriofor the emulator. - JSON-only settings (edit
%APPDATA%\RIOJoy\config.json):AxisRouting,Calibrationfine points,PlasmaComPort/PlasmaGreeting, and theFeedbacksection (see FEEDBACK.md). - Legacy import:
RioJoy.Tray.exe --import-profile <file>merges a single-profile JSON document; theImport .inimenu converts an originalRIO.ini(buttons, inverts, greeting).
Testing without hardware or game
- vRIO (
pipe:vrio): click buttons on the emulator's panel and watch them arrive — the editor lights up, the pad reacts. - joy.cpl (Game Controllers): shows the virtual pad's axes/buttons moving.
- Keyboard routes: open Notepad, enable the editor's output toggle, press cockpit buttons.
Checklist for a new game
- Find the game's real executable name (foreground window process) → Triggers.
- Decide the axis story first: does the game hard-use triggers? If yes, route
the throttle to a thumb axis
UnipolarPositive(copy the Descent pattern). - Map the few primary actions to pad buttons 1–11, everything else to keyboard; mark cockpit-lit buttons Lit.
- Set
EnableZRif the game wants one rudder axis rather than two pedals. - Live-check in the editor, then in-game; bind a spare cockpit button to RIO command → recalibrate for the cabinet.
- Add the
Feedbacksection if the game will drive lamps/plasma back (OUTPUT-INTEGRATION.md).