Files
riojoy/docs/INPUT-INTEGRATION.md
T
CydandClaude Fable 5 80222c5ea7 docs: input integration guide (cockpit -> RIOJoy -> game)
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>
2026-07-31 20:49:23 -05:00

8.2 KiB
Raw Blame History

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 0x000x47, grouped into five MFD clusters and four columns — the physical map is in OUTPUT-INTEGRATION.md.
  • Two 4×4 keypads: internal 0x500x5F, external 0x600x6F (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..32766 with center 16383.

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 111 (or 196 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 ((value16383)×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

  1. 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.
  2. 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.
  3. Triggers: comma-separated executable names that auto-activate the profile when their window is foreground (d1x-rebirth, descent). Matching is basename, case-insensitive, .exe optional. 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 in NativeGameExecutables instead — RIOJoy releases the ports for them.
  4. RIO port: leave (app default), or a COM name, or pipe:vrio for the emulator.
  5. JSON-only settings (edit %APPDATA%\RIOJoy\config.json): AxisRouting, Calibration fine points, PlasmaComPort/PlasmaGreeting, and the Feedback section (see FEEDBACK.md).
  6. Legacy import: RioJoy.Tray.exe --import-profile <file> merges a single-profile JSON document; the Import .ini menu converts an original RIO.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

  1. Find the game's real executable name (foreground window process) → Triggers.
  2. 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).
  3. Map the few primary actions to pad buttons 111, everything else to keyboard; mark cockpit-lit buttons Lit.
  4. Set EnableZR if the game wants one rudder axis rather than two pedals.
  5. Live-check in the editor, then in-game; bind a spare cockpit button to RIO command → recalibrate for the cabinet.
  6. Add the Feedback section if the game will drive lamps/plasma back (OUTPUT-INTEGRATION.md).