Glass input audit: RIO mapper id fix (panel banks live), keyboard reconciliation

Root cause of the dead on-screen panel: MechRIOMapper's message-id enum
chained off L4MechControlsMapper::NextMessageID (=0x19), registering all 18
RIO override handlers at 0x19-0x2a while the streamed .CTL EventMapping
records carry the binary's ids -- the binary RIO table @0051dd30 re-registers
the BASE aux/zoom ids 3..0x13 (Hotbox 0x1a @0051de98).  Every MFD-bank/zoom
press hit the base ConfigureMappableMessageHandler FAIL trap (26/72 buttons
dead; an abort() on a trap-armed pod).  Ids now pinned to the binary
numbering + static_assert-locked (btl4mppr.hpp) -- panel goes 26 -> 52
working buttons (8 await handler reconstruction, filed on Gitea; 12 have no
streamed mapping authored = authentically inert).

Keyboard reconciliation (glass-only): the merged map -- keyboard hosts the
~20 core gameplay actions on the CONTROLS.MAP keys, the panel covers every
pod address by click (right-click = hold latch):
- W/S throttle lever, A/D pedals, Q/E twist, R/F elevation, X all-stop,
  arrows drive; numpad flight cluster kept (Cyd)
- 1/2/3/4/Space/LCTRL/RCTRL fire, LALT reverse, B look-behind (0x41)
- M=0x18 mode cycle, N=0x15 display cycle, H=0x2C coolant flush (hold),
  C=0x2F Condenser1 valve, G=0x0E weapon-1 configure (Mfd1-Quad-gated)
- F5-F9 = Mfd2 bank 0x27-0x24 + 0x22 (page-gated gen A-D / gen mode)
- hardcoded: ` or V = view toggle, J/K/L = Mfd1/2/3 preset-page cycle
  (PadRIO edges -> gBTPresetCycle; no pod "cycle" button exists)
- PadRIO::SuppressKey: bound keys are swallowed from the typed 1995 channel
  (the btinput suppression pattern, glass side) -- ends the glass double
  dispatch ('w'=pilot select 0, 'a'..'g'=MFD2 presets, NUMPAD/F-key key-up
  VK aliases like VK_F5=0x74='t').  Unbound keys keep their authentic
  meanings (5/z presets, t-o pilot select, +/- zoom, F1/F2 align).

DISPLACED from Cyd's default bindings (each reachable on the panel or by a
bindings.txt edit -- flagging for Cyd's veto): number row -> secondary panel
(1-4 now fire), QWERTY row -> pilot keypad (dropped), arrows -> hat looks
(now drive), V/C/B -> fire 0x47/0x46/0x45 (now view/valve/look-behind),
LCTRL -> throttle-down (now fire).  XInput pad section untouched.

Audit by-products (KB updated): the always-active msg-4 records identified
(0x2C = Reservoir flush, 0x29-0x2F = condenser valves, 0x1A-0x1D =
GeneratorA-D ToggleGeneratorOnOff @004b1ed0 unreconstructed); 0x13 = Mech
DuckRequest (crouch), 0x28 = BalanceCoolant; Searchlight/ThermalSight
ToggleLamp handler-sets are default-constructed EMPTY; weapon Eng-page msgs
0x3/0xb = ToggleCooling / ToggleSeekVoltage / EjectAmmo, all unwired;
unhandled messages are SILENT (no [FAIL] -- census = BT_CTRLMAP_LOG dump x
handler tables).

Verified live (build-glass2, ARENA1): panel presets/zoom/display/flush;
W drive (speedDemand 61.5, gait advances), Q turn (BAS), M -> MID, A turn
(MID), Space fires, N display, J/K/L presets, H flush drain, C valve 1->5;
suppression ('w' swallowed, 't' flows, F5-keyup swallowed); BT_SHOT frame.
Un-regression: pod build (gates OFF) compiles 0 errors, forced-walk drives,
streamed ids unchanged; CONTROLS.MAP/btinput untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-20 08:35:55 -05:00
co-authored by Claude Fable 5
parent cb190aa00a
commit 5dd35365c7
11 changed files with 422 additions and 48 deletions
+23
View File
@@ -239,6 +239,29 @@ From the weapon `.SUB` records + the charge-curve `.data` constants (PE-parsed a
- MechWeapon handler table @0x511860: {9,"ConfigureMappables"→@004b9550}, {10,"ChooseButton"→@004b95b8} - MechWeapon handler table @0x511860: {9,"ConfigureMappables"→@004b9550}, {10,"ChooseButton"→@004b95b8}
(strings @0x511994/@0x5119A7). PoweredSubsystem table @0x50F4EC: ids 4-8 = SelectGeneratorA-D / (strings @0x511994/@0x5119A7). PoweredSubsystem table @0x50F4EC: ids 4-8 = SelectGeneratorA-D /
ToggleGeneratorMode → @004b099c/@004b09e4/@004b0a2c/@004b0a74/@004b0abc. ToggleGeneratorMode → @004b099c/@004b09e4/@004b0a2c/@004b0a74/@004b0abc.
### Binary message tables decoded 2026-07-20 (glass input audit) [T1]
16-byte HandlerEntry {id, namePtr, fnPtr, 0} rows in section_dump. Per-receiver-class id spaces.
- **Mech (entity)** @0x50BDF8..: 0x12 TakeDamage@004a0230, 0x14 PlayerLink@0049f624, 0x15
RealMaxSpeed@0049f604, **0x16 BalanceCoolant@0049f728**, 0x17 SetBurningState@0049f674, 0x18
ClearBurningState@0049f700, **0x19 EjectPilot@0049f854**, **0x1a DuckRequest@0049fa00** (the
manual's CROUCH; streamed button 0x13 sends it — unreconstructed).
- **HeatableSubsystem** @0x50E41C: {3, "ToggleCooling"→@004ad6f8} (the Eng-page msg-3 button on
every weapon/avionics — unwired in the reconstruction).
- **Generator** @0x50FB90: {4, "ToggleGeneratorOnOff"→@004b1ed0} (streamed buttons 0x1A-0x1D →
GeneratorA-D — unreconstructed).
- **Searchlight** @0x51120C: {3, "ToggleLamp"→@004b860c}; PowerWatcher/ThermalSight-side variant
@0x51117C: {3, "ToggleLamp"→@004b838c}. (Reconstruction has Searchlight::ToggleLamp but the
MessageHandlers set is default-constructed EMPTY — unwired.)
- **Myomers-class** @0x51158C: {9, "ToggleSeekVoltage"→@004b8a48}; **energy-weapon** variant
@0x511DB8: {0xb, "ToggleSeekVoltage"→@004ba478}; **ammo-weapon** @0x512210: {0xb,
"EjectAmmo"→@004bb9b8}.
- **MechRIOMapper** @0x51DD30: RE-REGISTERS the base ids 3..0x13 (Aux1Quad..ZoomOut) with the
RIO override handlers @004d22fc..@004d24f8, + {0x19, Keypress→@004d2514} (RIO's OWN keypress,
unreconstructed — we use the shared L4 0x17 @004d1bf0) + {0x1a, Hotbox→@004d2574} @0x51DE98.
The reconstruction's enum chained these ids to 0x19-0x2a until 2026-07-20 — every streamed
MFD-bank/zoom press hit the base FAIL trap; now pinned + static_assert-locked (btl4mppr.hpp).
- Unhandled ids are SILENT: `Receiver::Receive` Find() returns NullHandler and does nothing.
- MechWeapon ATTRIBUTE table @0x511890: ELEVEN entries — 0x12 PercentDone@0x320, 0x13 TriggerState@0x31C, - MechWeapon ATTRIBUTE table @0x511890: ELEVEN entries — 0x12 PercentDone@0x320, 0x13 TriggerState@0x31C,
0x14 DistanceToTarget@0x324, 0x15 TargetWithinRange@0x34C, 0x16 WeaponRange@0x328, 0x17 PipPosition, 0x14 DistanceToTarget@0x324, 0x15 TargetWithinRange@0x34C, 0x16 WeaponRange@0x328, 0x17 PipPosition,
0x18 PipColor, 0x19 PipExtendedRange, 0x1A EstimatedReadyTime@0x330, 0x1B RearFiring@0x334, 0x18 PipColor, 0x19 PipExtendedRange, 0x1A EstimatedReadyTime@0x330, 0x1B RearFiring@0x334,
+2 -1
View File
@@ -10,7 +10,8 @@ open_questions:
- "HUD attr table RESOLVED 2026-07-19 (Gitea #10 audit): re-dumped @5110b8 -- the table starts one record earlier (id 3 FlickerRate@0x1D8), every hud.hpp offset was shifted one slot; hud.hpp/CLASSMAP corrected, no behavioral impact (the reticle feeds via port globals). See GAUGE_COMPOSITE.md AUDIT finding B" - "HUD attr table RESOLVED 2026-07-19 (Gitea #10 audit): re-dumped @5110b8 -- the table starts one record earlier (id 3 FlickerRate@0x1D8), every hud.hpp offset was shifted one slot; hud.hpp/CLASSMAP corrected, no behavioral impact (the reticle feeds via port globals). See GAUGE_COMPOSITE.md AUDIT finding B"
- "SeekVoltageGraph RECONSTRUCTED 2026-07-19 (Gitea #11, was #10 finding A): full widget landed (see §SeekVoltageGraph below) -- ghosts gone steady-state (BT_PRESET_HOLD verification); remaining polish: a 1-frame transition artifact when a BT_SHOT lands on the exact page-switch frame (label BecameActive vs the graph's next rated Execute -- same lag class as the binary; self-heals next frame)" - "SeekVoltageGraph RECONSTRUCTED 2026-07-19 (Gitea #11, was #10 finding A): full widget landed (see §SeekVoltageGraph below) -- ghosts gone steady-state (BT_PRESET_HOLD verification); remaining polish: a 1-frame transition artifact when a BT_SHOT lands on the exact page-switch frame (label BecameActive vs the graph's next rated Execute -- same lag class as the binary; self-heals next frame)"
- "Secondary-view cycling RESOLVED 2026-07-19 (Gitea #6): the selector is the DISPLAY mode (CycleDisplayMode -> vtbl+0x4C override @4d1ae4), NOT CycleControlMode; desktop 'N' / pad RightThumb wired; pixel-verified dama->crit->heat" - "Secondary-view cycling RESOLVED 2026-07-19 (Gitea #6): the selector is the DISPLAY mode (CycleDisplayMode -> vtbl+0x4C override @4d1ae4), NOT CycleControlMode; desktop 'N' / pad RightThumb wired; pixel-verified dama->crit->heat"
- "Upper-MFD PRESET pages RESOLVED 2026-07-19 (Gitea #9): SetPresetMode table @0051dbf0 re-decoded (little-endian -> ModeMFD bits 0-14), per-MFD pod button banks identified from the .CTL dump, desktop J/K/L cycle wired; remaining: the always-active 0x28-0x2F / 0x1A-0x1D per-subsystem msg-4 records (subs 3-13 -- likely the condenser-valve/coolant buttons) unidentified" - "Upper-MFD PRESET pages RESOLVED 2026-07-19 (Gitea #9): SetPresetMode table @0051dbf0 re-decoded (little-endian -> ModeMFD bits 0-14), per-MFD pod button banks identified from the .CTL dump, desktop J/K/L cycle wired"
- "Always-active msg-4 records IDENTIFIED 2026-07-20 (glass input audit): 0x2C = Reservoir InjectCoolant (the flush button), 0x2F/0x2E/0x2D/0x2B/0x2A/0x29 = Condenser1-6 MoveValve, 0x1A-0x1D = GeneratorA-D ToggleGeneratorOnOff (@0050fb90, unreconstructed); plus 0x13 = Mech DuckRequest (crouch), 0x28 = Mech BalanceCoolant, 0x12/0x14 = ThermalSight/Searchlight toggles -- see pod-hardware.md + docs/GLASS_COCKPIT.md 2026-07-20"
- "MP DEATHS resolved 2026-07-12 (observed-death tally + display clamp); remaining: verify multi-death tallies stay in sync across a long session (GAUGE_COMPOSITE.md)" - "MP DEATHS resolved 2026-07-12 (observed-death tally + display clamp); remaining: verify multi-death tallies stay in sync across a long session (GAUGE_COMPOSITE.md)"
--- ---
+15
View File
@@ -70,6 +70,21 @@ copied from them.
- **Step 4 (Steam): CODE COMPLETE 2026-07-18 [T2 single-machine].** See [[steam-networking]] — - **Step 4 (Steam): CODE COMPLETE 2026-07-18 [T2 single-machine].** See [[steam-networking]] —
the wire seam + `L4STEAMNET` identity-token transport + `btl4lobby`. Live 2-account the wire seam + `L4STEAMNET` identity-token transport + `btl4lobby`. Live 2-account
cross-machine session pending (`docs/STEAM_TEST.md`). cross-machine session pending (`docs/STEAM_TEST.md`).
- **Input-coverage audit + keyboard reconciliation: DONE 2026-07-20 [T2].** Root cause of the
dead panel: `MechRIOMapper`'s message ids were chained one enum too high (0x19-0x2a) — the
binary RIO table @0051dd30 re-registers the BASE aux/zoom ids 3..0x13 (Hotbox 0x1a); fixed
ungated + static_assert-locked (`btl4mppr.hpp`) → all 24 MFD-bank + 2 zoom buttons live
(52/72 panel buttons now work; 8 dead await handler reconstruction — Gitea backlog issue;
12 have no streamed mapping authored, authentically inert). **Keyboard = the ~20 core
gameplay actions on the CONTROLS.MAP keys; the PANEL covers every pod address by click**
(right-click = hold latch) — the merged default profile lives in `L4PADBINDINGS.cpp`
(auto-writes `content\bindings.txt`; W/S/A/D/Q/E/R/F/X drive, 1-4/Space/Ctrl fire, M/N/H/C =
pod buttons 0x18/0x15/0x2C/0x2F, `/V view toggle + J/K/L preset cycles hardcoded in PadRIO).
Bound keys are SUPPRESSED from the typed 1995 channel (`PadRIO::SuppressKey`, the btinput
pattern — ended the glass double-dispatch: 'w'=pilot-select, numpad/F-key key-up aliases);
unbound keys keep their authentic meanings (5/z presets, t-o pilot select, +/- zoom).
In BAS control mode the pod turns with the STICK (Q/E) and pedals are inactive — authentic;
A/D turn in MID/ADV. Full audit + census: `docs/GLASS_COCKPIT.md` §2026-07-20.
## Key Relationships ## Key Relationships
- Extends: [[pod-hardware]] (RIO input path) · Uses: [[gauges-hud]] dev-gauge modes · - Extends: [[pod-hardware]] (RIO input path) · Uses: [[gauges-hud]] dev-gauge modes ·
+11
View File
@@ -137,6 +137,17 @@ register. ⚠ The audit also flags the damage-economy item as SELF-CONTRADICTOR
(task #8 "landed" vs the kShotDamage=12 bring-up residue) — audit before reworking. (task #8 "landed" vs the kShotDamage=12 bring-up residue) — audit before reworking.
## Deferred subsystems / feeds (authentic path scoped, marked in code) ## Deferred subsystems / feeds (authentic path scoped, marked in code)
- **Glass panel dead-button backlog (input-coverage audit 2026-07-20) [T1 census].** 8 of the 72
panel buttons dispatch a streamed message with NO reconstructed handler (silently ignored):
0x13 → Mech `DuckRequest` @0049fa00 (CROUCH — `duckState` attr + SQUAT clips exist!), 0x28 →
Mech `BalanceCoolant` @0049f728, 0x1A-0x1D → Generator A-D `ToggleGeneratorOnOff` @004b1ed0,
0x12 → ThermalSight toggle (pvision unported), 0x14 → Searchlight `ToggleLamp` (body
reconstructed, handler-set unwired — note the 1995 latent bug below: even wired, the light
never turns on in the original). Plus page-gated Eng-page meanings: `ToggleCooling` @004ad6f8
(msg 3), `ToggleSeekVoltage` @004ba478/@004b8a48 (msg 0xb energy / 9 Myomers), `EjectAmmo`
@004bb9b8 (msg 0xb ammo weapons), and MechRIOMapper's own Keypress @004d2514 (id 0x19).
Filed as the Gitea "glass panel: unreconstructed button handlers backlog" issue; tables in
[[decomp-reference]] §2026-07-20; census in `docs/GLASS_COCKPIT.md`.
- **Searchlight-driven fog swap — DEFERRED, and it is an ORIGINAL 1995 LATENT BUG (task #63, - **Searchlight-driven fog swap — DEFERRED, and it is an ORIGINAL 1995 LATENT BUG (task #63,
2026-07-13) [T1 decomp].** The arcade swaps fog between `fog=` (lights on) and `nosearchlightfog=` 2026-07-13) [T1 decomp].** The arcade swaps fog between `fog=` (lights on) and `nosearchlightfog=`
(off) via `PullFogRenderable` watching the Searchlight's `lightState`. It never fires — in the PORT (off) via `PullFogRenderable` watching the Searchlight's `lightState`. It never fires — in the PORT
+17 -5
View File
@@ -42,11 +42,23 @@ preset-able MFD owns the 8-button bank AROUND it, mode-mask-gated per page — *
left) = 0x08-0x0F (AuxLowerLeft), Mfd2 (upper center) = 0x20-0x27 (AuxUpperCenter), Mfd3 left) = 0x08-0x0F (AuxLowerLeft), Mfd2 (upper center) = 0x20-0x27 (AuxUpperCenter), Mfd3
(lower right) = 0x00-0x07 (AuxLowerRight)**: Quad page → the outer buttons direct-select the (lower right) = 0x00-0x07 (AuxLowerRight)**: Quad page → the outer buttons direct-select the
populated Eng pages; Eng page → one button back to Quad, the rest drive the shown subsystem populated Eng pages; Eng page → one button back to Quad, the rest drive the shown subsystem
(generator select A-D, gen mode, weapon config/unjam). Always-active: **0x28-0x2F (generator select A-D msg 4-7, gen mode msg 8, weapon configure msg 9; also msg 0x3 =
(AuxUpperLeft) → per-subsystem msg 0x4 to roster subs 3-9** and secondary-panel 0x1A-0x1D → ToggleCooling and msg 0xb = ToggleSeekVoltage (energy) / EjectAmmo (ammo weapons) —
subs 10-13 msg 0x4 (identities unverified — likely the condenser-valve / coolant buttons unreconstructed, silently dead). **Always-active records IDENTIFIED 2026-07-20 [T1]** (roster:
[T4]); 0x10/0x11 = map ZoomIn/Out, 0x15 = CycleDisplayMode, 0x18 = CycleControlMode (#6). sub 3 = Reservoir, 4-9 = Condenser1-6, 10-13 = GeneratorA-D): **0x2C = the COOLANT FLUSH
Full decode: [[gauges-hud]] §preset pages. button** (Reservoir InjectCoolant, hold-to-flush — works), **0x2F/0x2E/0x2D/0x2B/0x2A/0x29 =
the per-condenser VALVE buttons** (MoveValve, Cond1-6 — work), **0x1A-0x1D = Generator A-D
ON/OFF** (`ToggleGeneratorOnOff` id 4, binary table @0050fb90 fn @004b1ed0 — DEAD until
reconstructed). Newly decoded from the binary message tables: **0x13 → Mech `DuckRequest`
(0x1a @0049fa00 — the manual's CROUCH button)**, **0x28 → Mech `BalanceCoolant` (0x16
@0049f728)**, 0x12 → ThermalSight toggle (id 3), **0x14 → Searchlight + Searchlight2
`ToggleLamp` (id 3 @004b860c; body reconstructed but the handler-set is default-constructed
EMPTY — unwired)** — all currently dead; an unhandled message is SILENTLY ignored
(Receiver::Receive finds no handler and does nothing — dead buttons produce NO log).
0x10/0x11 = map ZoomIn/Out, 0x15 = CycleDisplayMode, 0x18 = CycleControlMode (#6). Buttons
with NO streamed mapping authored (authentically inert): 0x16/0x17/0x19/0x1E/0x1F/0x38-0x3E.
Full decode: [[gauges-hud]] §preset pages; the complete 72-button census + verification:
`docs/GLASS_COCKPIT.md` §2026-07-20.
### Desktop input remap — CONTROLS.MAP + XInput (2026-07-18) [T2 live] ### Desktop input remap — CONTROLS.MAP + XInput (2026-07-18) [T2 live]
`game/reconstructed/btinput.cpp` + `content/CONTROLS.MAP` (WASD-classic default, compiled-in twin; `game/reconstructed/btinput.cpp` + `content/CONTROLS.MAP` (WASD-classic default, compiled-in twin;
+81
View File
@@ -162,6 +162,87 @@ map `169.254.77.1=<steamID64>` → egg roster carries the token → mission proc
mission RUNS (46 ticks). 3-config build matrix green throughout. **Remaining (user hardware):** mission RUNS (46 ticks). 3-config build matrix green throughout. **Remaining (user hardware):**
the live 2-account cross-machine session — procedure in `docs/STEAM_TEST.md`. the live 2-account cross-machine session — procedure in `docs/STEAM_TEST.md`.
## 2026-07-20 — Glass input-coverage audit + keyboard reconciliation
**Trigger:** making BT_GLASS the permanent player experience — familiar desktop keys dead, "most
panel buttons do nothing". Full audit of every input surface (bindings.txt keys, the 72-button
panel, the streamed .CTL EventMapping records, the typed 1995 channel), then the fix set.
### Finding 1 — THE panel-dead-buttons root cause: MechRIOMapper message ids shifted [T1→T2 fixed]
`MechRIOMapper`'s enum chained `Aux1QuadMessageID = L4MechControlsMapper::NextMessageID` (=0x19),
registering all 18 RIO handlers at ids 0x19-0x2a. The binary RIO table @0051dd30 RE-REGISTERS the
base aux/zoom ids **3..0x13** with the override handlers (Hotbox = 0x1a @0051de98) — that
re-registration over the base FAIL-trap ids is the whole point of the derived table. Streamed
`.CTL` events carry the binary ids, so every MFD-bank/zoom press found only the base
`ConfigureMappableMessageHandler``[FAIL]` (26 of 72 panel buttons dead; on a real pod with the
hard trap, an abort()). Hotbox worked by accident (sender + entry both used the same wrong 0x2a).
Fixed: ids pinned to the binary numbering + static_assert locks (`btl4mppr.hpp`). Verified live:
panel 0x0F/0x08/0x27/0x20 → `[mode] preset` lines, 0x10/0x11 zoom no longer FAIL. (Residual
fidelity gap: the binary RIO table also carries its OWN Keypress id 0x19 → @004d2514,
unreconstructed; we still register the shared L4 Keypress 0x17 — works, logged in the backlog.)
### Finding 2 — the always-active msg-4 records IDENTIFIED [T1] (closes the #9 open question)
Binary message tables decoded from section_dump (16-byte {id,name,fn,0} entries): per-receiver-
class id spaces. Roster (ARENA1 MadCat): subs 3=Reservoir, 4-9=Condenser1-6, 10-13=GeneratorA-D.
So: **0x2C = the COOLANT FLUSH button** (Reservoir InjectCoolant, WORKS), **0x2F/0x2E/0x2D/0x2B/
0x2A/0x29 = per-condenser VALVE buttons** (MoveValve, WORK), **0x1A-0x1D = Generator A-D ON/OFF**
(`ToggleGeneratorOnOff` id 4, table @0050fb90 fn @004b1ed0 — DEAD, unreconstructed). Also new:
0x13 → Mech **DuckRequest** (0x1a @0049fa00 — the manual's CROUCH button!), 0x28 → Mech
**BalanceCoolant** (0x16 @0049f728), 0x12 → ThermalSight toggle (id 3), 0x14 → Searchlight +
Searchlight2 **ToggleLamp** (id 3 @004b860c — body reconstructed but `Searchlight::
MessageHandlers` is default-constructed EMPTY, so it never fires: the quick win). Weapon
Eng-page extras: msg 0x3 = **ToggleCooling** (HeatableSubsystem @0050e41c fn @004ad6f8, unwired),
msg 0xb = **ToggleSeekVoltage** (energy @004ba478) / **EjectAmmo** (ammo weapons @004bb9b8),
Myomers msg 9 = ToggleSeekVoltage (@004b8a48; body exists, unwired). Unhandled messages are
SILENT (Receiver::Receive ignores an unfound id) — the dead-button census cannot come from
[FAIL] logs alone; it comes from the BT_CTRLMAP_LOG record dump × the handler tables.
### Finding 3 — glass keyboard: stand-down + double dispatch [T2]
ALL btinput actions (drive keys, M/N/J/K/L/H/C/V/B/G/F5-F9) stand down when PadRIO owns the path
— nothing on the game side polls keys directly (BTInputPoll is the only GetAsyncKeyState
consumer). Meanwhile the typed 1995 channel stays LIVE (glass preset = `PAD,KEYBOARD`) with NO
suppression — so Cyd's old bindings double-dispatched: W (keypad row) also typed 'w' = pilot
select 0; C (fire middle) also typed 'c' = MFD3 Eng3; NUMPAD key-UPS alias to letter hotkeys
(VK_NUMPAD2=0x62='b' = MFD3 Quad, VK_F5=0x74='t' = pilot select 3). This is the historic
pre-btinput double-dispatch, back on the glass side.
### The fix set (landed)
1. `btl4mppr.hpp` — RIO id pinning (ungated, pod-correctness; the step-2a idiom).
2. `L4PADRIO.*` — typed-channel suppression tables built from the loaded bindings (+hardcoded
keys), `PadRIO::SuppressKey` consumed by a `#ifdef BT_GLASS` arm next to the btinput hook in
`L4CTRL.cpp:1506` block; V joins backtick on the view-toggle edge; J/K/L fire
`gBTPresetCycle[3]` (the same seam the dev poll feeds — no binary analog exists for a "cycle"
button; the body is the authentic SetPresetMode).
3. `L4PADBINDINGS.cpp` + `content\bindings.txt` — the MERGED default map (user decision:
keyboard = the ~20 core gameplay actions on the CONTROLS.MAP keys; the PANEL covers all 72
pod buttons by click/latch). W/S throttle, A/D pedals, Q/E twist, R/F elevation, X all-stop,
1-4/Space/Ctrl fire + LALT reverse + B look-behind, M=0x18, N=0x15, H=0x2C (flush hold),
C=0x2F (Condenser1 valve), G=0x0E (weapon-1 configure, Mfd1-Quad-gated), F5-F9=Mfd2 bank
0x27-0x24+0x22 (page-gated gen A-D/mode), numpad flight cluster kept. DISPLACED from Cyd's
map (each reachable on the panel or by editing bindings.txt): number row→secondary panel,
QWERTY row→pilot keypad (dropped), arrows→hat looks (arrows now drive), V/C/B→fire
0x47/0x46/0x45, LCTRL→throttle-down. XInput pad section untouched.
NOTE (control modes, authentic): in BAS mode the pod turns with the STICK (Q/E here) and the
pedals are inactive; A/D turn in MID/ADV — exactly the manual's behavior, unlike the desktop
bridge which re-routes A/D per mode.
4. Un-touched: CONTROLS.MAP, btinput defaults, pod serial path. `bindings.txt` is read only by
`PadBindingProfile` inside the gated PadRIO TU — the pod build never opens it.
### Verification (2026-07-20, build-glass2, ARENA1 solo, all logs in-session)
- Panel: 0x0F→preset(0,1), 0x08→(0,0), 0x27→(1,1), 0x20→(1,0), zoom no-FAIL; 0x15 display
1→2→0; 0x2C hold → `[flush] Reservoir level 6→0`; dead-class buttons (0x13/0x1A/0x12/0x14)
silent as predicted. ZERO [FAIL] lines in the whole session (was 2 per bank press).
- Keyboard: W hold → thr 0→1, speedDemand 61.501, gait advances; Q → turnDemand 0.94 (BAS);
M → `control mode -> 1`; A hold → turnDemand 1.0 (MID); Space → `[emitter] FIRED`; N →
`display notify 1`; J/K/L → presets (0,1)/(1,1)/(2,1); H → reservoir drain; C → condenser#1
valveState 1→5. BT_SHOT frame confirms visually: MID lit on the control-mode column, CRITICAL
DAMAGE schematic up, MFDs on Eng pages, heading moved. V not re-injected (user took
foreground mid-run) — code-identical to the verified backtick edge [T3].
- Suppression: typed 'w' swallowed (no [keych]), typed 't' flows ([keych] 0x74), WM_KEYUP
VK_F5 swallowed (the 't'-alias hazard).
- Un-regression: build-pod (gates OFF) compiles 0 errors; forced-walk run drives
(speedDemand=61.501, 32 subsystems, streamed ids 3→+0xdc / 4→+0xe4 unchanged).
## 2026-07-18 — Merge origin/master (commit f889e24): btinput meets PadRIO ## 2026-07-18 — Merge origin/master (commit f889e24): btinput meets PadRIO
Master's 33-commit run landed (D1 relay/operator-console line, CONTROLS.MAP+XInput binding Master's 33-commit run landed (D1 relay/operator-console line, CONTROLS.MAP+XInput binding
+9
View File
@@ -1605,6 +1605,15 @@ void
{ {
// swallowed: remapped by CONTROLS.MAP // swallowed: remapped by CONTROLS.MAP
} }
#ifdef BT_GLASS
else if (PadRIO::SuppressKey((unsigned int)keyValue,
msg.message == WM_CHAR))
{
// swallowed: claimed by a bindings.txt row (PadRIO) --
// the glass-side analog of the CONTROLS.MAP suppression
// above (btinput stands down when PadRIO owns the path)
}
#endif
else else
{ {
keyboardGroup[KeyboardPC].ForceUpdate(&keyValue, mode_mask); keyboardGroup[KeyboardPC].ForceUpdate(&keyValue, mode_mask);
+58 -36
View File
@@ -139,6 +139,21 @@ static int
// right/left), 0x45-0x47 pinky/thumb-low/thumb-high, 0x10-0x15 + 0x18-0x1D // right/left), 0x45-0x47 pinky/thumb-low/thumb-high, 0x10-0x15 + 0x18-0x1D
// the 12 secondary-panel buttons, 0x00-0x0F the lower aux banks, 0x20-0x37 // the 12 secondary-panel buttons, 0x00-0x0F the lower aux banks, 0x20-0x37
// the upper aux banks. Keypad unit 0 = the pilot's MFD keypad. // the upper aux banks. Keypad unit 0 = the pilot's MFD keypad.
//
// KEYBOARD RECONCILIATION (2026-07-20, input-coverage audit): the keyboard
// carries the ~20 core gameplay actions on the SAME keys the desktop
// CONTROLS.MAP uses (W/S/A/D drive, Q/E twist, R/F elevation, X all-stop,
// 1-4/Space/Ctrl fire, M/N mode/display cycle, H flush, C valve, B look
// behind, G configure, V view); FULL pod-address coverage lives on the
// on-screen panel (every one of the 72 buttons is one click away,
// right-click = hold latch). Keys DISPLACED from the previous default
// (each still reachable by editing bindings.txt or on the panel):
// - number row 1-0/-/= -> secondary-panel 0x10-0x1D (1-4 now fire)
// - QWERTY row Q..P -> pilot MFD keypad unit 0 (dropped)
// - arrow keys -> hat looks 0x41-0x44 (arrows now drive)
// - V/C/B -> fire 0x47/0x46/0x45 (now view/valve/behind)
// - LCTRL -> throttle slew down (now fire 0x47)
// The XInput pad section is unchanged.
//########################################################################### //###########################################################################
static const char *defaultProfileText = static const char *defaultProfileText =
@@ -153,8 +168,33 @@ static const char *defaultProfileText =
"# padaxis <PADAXIS> axis <channel> [invert] [slew <rate>]\n" "# padaxis <PADAXIS> axis <channel> [invert] [slew <rate>]\n"
"# Channels: Throttle JoystickX JoystickY LeftPedal RightPedal\n" "# Channels: Throttle JoystickX JoystickY LeftPedal RightPedal\n"
"# Pad buttons: A B X Y LB RB BACK START LS RS DPAD_* Axes: LX LY RX RY LT RT\n" "# Pad buttons: A B X Y LB RB BACK START LS RS DPAD_* Axes: LX LY RX RY LT RT\n"
"#\n"
"# LAYOUT: the keyboard hosts the core gameplay actions on the desktop\n"
"# CONTROLS.MAP keys; the on-screen cockpit panel covers EVERY pod button\n"
"# by click (right-click = press-and-hold latch). A key bound here is\n"
"# REMOVED from the authentic 1995 typed-hotkey channel (no double\n"
"# dispatch); unbound keys keep their 1995 meaning -- 5 = MFD1 Quad page,\n"
"# z = MFD3 Eng1 page, t/y/u/i/o = pilot select 3-7, + / - = target zoom.\n"
"# Hardcoded (not rebindable here): ` or V = view toggle, J/K/L = cycle\n"
"# the Mfd1/Mfd2/Mfd3 preset page.\n"
"\n" "\n"
"# --- flight: numpad spring stick, pedals, throttle lever ---\n" "# --- drive: W/S sweep the throttle lever (sticks; X = all-stop detent),\n"
"# --- A/D spring the turn pedals, Q/E twist the torso, R/F aim it up/down\n"
"key W axis Throttle slew + 0.7\n"
"key S axis Throttle slew - 0.7\n"
"key UP axis Throttle slew + 0.7\n"
"key DOWN axis Throttle slew - 0.7\n"
"key A axis LeftPedal deflect + 2.5\n"
"key D axis RightPedal deflect + 2.5\n"
"key LEFT axis LeftPedal deflect + 2.5\n"
"key RIGHT axis RightPedal deflect + 2.5\n"
"key Q axis JoystickX deflect - 2.5\n"
"key E axis JoystickX deflect + 2.5\n"
"key R axis JoystickY deflect + 2.5\n"
"key F axis JoystickY deflect - 2.5\n"
"key X axis Throttle set 0\n"
"\n"
"# --- numpad flight cluster (alternative stick/pedals/lever) ---\n"
"key NUMPAD8 axis JoystickY deflect + 2.5\n" "key NUMPAD8 axis JoystickY deflect + 2.5\n"
"key NUMPAD2 axis JoystickY deflect - 2.5\n" "key NUMPAD2 axis JoystickY deflect - 2.5\n"
"key NUMPAD4 axis JoystickX deflect - 2.5\n" "key NUMPAD4 axis JoystickX deflect - 2.5\n"
@@ -162,51 +202,33 @@ static const char *defaultProfileText =
"key NUMPAD7 axis LeftPedal deflect + 2.5\n" "key NUMPAD7 axis LeftPedal deflect + 2.5\n"
"key NUMPAD9 axis RightPedal deflect + 2.5\n" "key NUMPAD9 axis RightPedal deflect + 2.5\n"
"key LSHIFT axis Throttle slew + 0.7\n" "key LSHIFT axis Throttle slew + 0.7\n"
"key LCTRL axis Throttle slew - 0.7\n"
"key NUMPAD5 axis Throttle set 0\n" "key NUMPAD5 axis Throttle set 0\n"
"\n" "\n"
"# --- weapons / hat / handle buttons ---\n" "# --- fire groups (the joystick's four mappable buttons) + reverse + look\n"
"key 1 button 0x40\n"
"key SPACE button 0x40\n" "key SPACE button 0x40\n"
"key 2 button 0x46\n"
"key 3 button 0x47\n"
"key LCTRL button 0x47\n"
"key RCTRL button 0x47\n"
"key 4 button 0x45\n"
"key LALT button 0x3F\n" "key LALT button 0x3F\n"
"key V button 0x47\n" "key B button 0x41\n"
"key C button 0x46\n"
"key B button 0x45\n"
"key UP button 0x42\n"
"key DOWN button 0x41\n"
"key LEFT button 0x44\n"
"key RIGHT button 0x43\n"
"\n" "\n"
"# --- secondary panel (12) on the number row ---\n" "# --- systems (pod console buttons) ---\n"
"key 1 button 0x10\n" "key M button 0x18 # cycle control mode (BAS/MID/ADV)\n"
"key 2 button 0x11\n" "key N button 0x15 # cycle secondary schematic (Damage/Critical/Heat)\n"
"key 3 button 0x12\n" "key H button 0x2C # HOLD = coolant flush (Reservoir InjectCoolant)\n"
"key 4 button 0x13\n" "key C button 0x2F # cycle Condenser1 coolant valve (MoveValve)\n"
"key 5 button 0x14\n" "key G button 0x0E # HOLD + fire key = regroup weapon 1 (Mfd1 Quad page)\n"
"key 6 button 0x15\n"
"key 7 button 0x18\n"
"key 8 button 0x19\n"
"key 9 button 0x1A\n"
"key 0 button 0x1B\n"
"key MINUS button 0x1C\n"
"key EQUALS button 0x1D\n"
"\n" "\n"
"# --- aux banks on F5-F8 (upper center 1-4) ---\n" "# --- Mfd2 bank on F5-F8 + F9 (page-gated: Quad page = select the Eng\n"
"# --- pages, Eng page = generator A-D select / F9 gen-mode toggle) ---\n"
"key F5 button 0x27\n" "key F5 button 0x27\n"
"key F6 button 0x26\n" "key F6 button 0x26\n"
"key F7 button 0x25\n" "key F7 button 0x25\n"
"key F8 button 0x24\n" "key F8 button 0x24\n"
"\n" "key F9 button 0x22\n"
"# --- pilot MFD keypad on QWERTY row (unit 0, keys 0-9) ---\n"
"key Q keypad 0 1\n"
"key W keypad 0 2\n"
"key E keypad 0 3\n"
"key R keypad 0 4\n"
"key T keypad 0 5\n"
"key Y keypad 0 6\n"
"key U keypad 0 7\n"
"key I keypad 0 8\n"
"key O keypad 0 9\n"
"key P keypad 0 0\n"
"\n" "\n"
"# --- XInput pad ---\n" "# --- XInput pad ---\n"
"padaxis LX axis JoystickX\n" "padaxis LX axis JoystickX\n"
+152 -4
View File
@@ -21,11 +21,23 @@
PadRIO *PadRIO::activeInstance = NULL; PadRIO *PadRIO::activeInstance = NULL;
// //
// Pending backtick view-toggle edges (set in Poll, consumed by the game's // Pending backtick/V view-toggle edges (set in Poll, consumed by the game's
// view-toggle block through BTPadViewToggleEdge). // view-toggle block through BTPadViewToggleEdge).
// //
int gBTPadViewToggleEdges = 0; int gBTPadViewToggleEdges = 0;
//
// The desktop per-MFD preset-page cycle edges (J/K/L -> Mfd1/2/3), consumed
// by L4MechControlsMapper::InterpretControls (btl4mppr.cpp step 3b -- the
// same seam the dev-build mech4 poll feeds). Defined in mech4.cpp (always
// compiled), so the glass TU externs it -- keyboard reconciliation
// 2026-07-20: J/K/L are the CONTROLS.MAP muscle-memory keys and there is no
// single pod button that "cycles" an MFD (the pod's bank buttons are
// mode-mask-gated direct selects), so the cycle stays a port-side sender
// with the authentic SetPresetMode body.
//
extern int gBTPresetCycle[3];
int int
BTPadViewToggleEdge(void) BTPadViewToggleEdge(void)
{ {
@@ -118,6 +130,7 @@ PadRIO::PadRIO():
memset(lampState, 0, sizeof(lampState)); memset(lampState, 0, sizeof(lampState));
bindings.Load(); bindings.Load();
BuildKeySuppression();
// //
// Per-channel spring return rate = the fastest deflect rate bound to // Per-channel spring return rate = the fastest deflect rate bound to
@@ -173,6 +186,118 @@ PadRIO::~PadRIO()
} }
} }
//###########################################################################
// Typed-channel suppression (the btinput sSuppressChar/sSuppressKeyUp
// pattern -- btinput.cpp AddSuppression -- rebuilt here because btinput
// stands down whenever a cockpit device owns the input path). A bound key
// must NOT also reach the 1995 in-cockpit keyboard dispatcher: 'w' selects
// pilot 0, 'a'/'s'/'d'/'f'/'g' flip MFD2 preset pages, letter/numpad
// KEY-UP VK values alias onto lowercase hotkeys (VK_F5==0x74=='t' = pilot
// select 3, VK_NUMPAD2==0x62=='b' = MFD3 Quad, ...). Unbound keys keep
// their authentic 1995 typed meaning.
//###########################################################################
void
PadRIO::AddKeySuppression(int virtual_key)
{
//
// WM_KEYUP delivers the raw VK; every consumer downstream compares
// typed CHARACTERS, so the VK value itself is the alias to swallow.
//
if (virtual_key >= 0 && virtual_key < 256)
{
suppressKeyUp[virtual_key] = 1;
}
//
// WM_CHAR delivers typed characters: both cases of a letter, the digit
// itself (main row AND numpad -- VK_NUMPAD0..9 type '0'..'9'), space,
// and the base punctuation of the Oem keys.
//
if (virtual_key >= 'A' && virtual_key <= 'Z')
{
suppressChar[virtual_key + ('a' - 'A')] = 1;
suppressChar[virtual_key] = 1;
}
else if (virtual_key >= '0' && virtual_key <= '9')
{
suppressChar[virtual_key] = 1;
}
else if (virtual_key >= VK_NUMPAD0 && virtual_key <= VK_NUMPAD9)
{
suppressChar['0' + (virtual_key - VK_NUMPAD0)] = 1;
}
else if (virtual_key == VK_SPACE)
{
suppressChar[' '] = 1;
suppressKeyUp[VK_SPACE] = 1;
}
else
{
static const struct { int vk; char ch; } oem[] =
{
{ VK_OEM_MINUS, '-' }, { VK_OEM_PLUS, '=' },
{ VK_OEM_COMMA, ',' }, { VK_OEM_PERIOD, '.' },
{ VK_OEM_2, '/' }, { VK_OEM_3, '`' },
{ VK_OEM_4, '[' }, { VK_OEM_5, '\\' },
{ VK_OEM_6, ']' }, { VK_OEM_1, ';' },
{ VK_OEM_7, '\'' }, { VK_RETURN, '\r' },
{ VK_TAB, '\t' }, { VK_BACK, '\b' },
};
for (int i = 0; i < (int)(sizeof(oem) / sizeof(oem[0])); ++i)
{
if (oem[i].vk == virtual_key)
{
suppressChar[(unsigned char)oem[i].ch] = 1;
}
}
}
//
// The generic modifier VK is what WM_KEYUP reports for L/R variants.
//
if (virtual_key == VK_LSHIFT || virtual_key == VK_RSHIFT)
{
suppressKeyUp[VK_SHIFT] = 1;
}
if (virtual_key == VK_LCONTROL || virtual_key == VK_RCONTROL)
{
suppressKeyUp[VK_CONTROL] = 1;
}
}
void
PadRIO::BuildKeySuppression()
{
memset(suppressChar, 0, sizeof(suppressChar));
memset(suppressKeyUp, 0, sizeof(suppressKeyUp));
for (int k = 0; k < bindings.keyBindingCount; ++k)
{
AddKeySuppression(bindings.keyBindings[k].virtualKey);
}
//
// The hardcoded keys (Poll): backtick + V = view toggle, J/K/L = the
// per-MFD preset-page cycle.
//
AddKeySuppression(VK_OEM_3);
AddKeySuppression('V');
AddKeySuppression('J');
AddKeySuppression('K');
AddKeySuppression('L');
}
int
PadRIO::SuppressKey(unsigned int key_value, int is_char)
{
if (activeInstance == NULL || key_value > 255)
{
return 0; // no glass device / ALT_BIT-tagged value
}
return is_char
? activeInstance->suppressChar[key_value]
: activeInstance->suppressKeyUp[key_value];
}
//########################################################################### //###########################################################################
// Event queue // Event queue
//########################################################################### //###########################################################################
@@ -278,13 +403,16 @@ void
// //
// The backtick view toggle (per Cyd: ` = 1st/3rd person in the glass // The backtick view toggle (per Cyd: ` = 1st/3rd person in the glass
// cockpit). Edge-detected here (async poll, message-path-free) and // cockpit) + V (the CONTROLS.MAP ViewToggle key -- keyboard
// consumed by the game's view-toggle block via BTPadViewToggleEdge. // reconciliation 2026-07-20). Edge-detected here (async poll,
// message-path-free) and consumed by the game's view-toggle block via
// BTPadViewToggleEdge.
// //
{ {
static int s_backtickWas = 0; static int s_backtickWas = 0;
int backtick_held = focused && int backtick_held = focused &&
(GetAsyncKeyState(VK_OEM_3) & 0x8000) != 0; (((GetAsyncKeyState(VK_OEM_3) & 0x8000) != 0) ||
((GetAsyncKeyState('V') & 0x8000) != 0));
if (backtick_held && !s_backtickWas) if (backtick_held && !s_backtickWas)
{ {
extern int gBTPadViewToggleEdges; extern int gBTPadViewToggleEdges;
@@ -293,6 +421,26 @@ void
s_backtickWas = backtick_held; s_backtickWas = backtick_held;
} }
//
// J/K/L: cycle the Mfd1/Mfd2/Mfd3 preset page (the CONTROLS.MAP keys;
// the L4 mapper consumes gBTPresetCycle and runs the authentic
// SetPresetMode body -- btl4mppr.cpp CyclePresetModeNow).
//
{
static int s_presetWas[3] = { 0, 0, 0 };
static const int s_presetKey[3] = { 'J', 'K', 'L' };
for (int g = 0; g < 3; ++g)
{
int held = focused &&
(GetAsyncKeyState(s_presetKey[g]) & 0x8000) != 0;
if (held && !s_presetWas[g])
{
gBTPresetCycle[g] = 1;
}
s_presetWas[g] = held;
}
}
float slewDelta[PadBindingProfile::ChannelCount]; float slewDelta[PadBindingProfile::ChannelCount];
int deflectHeld[PadBindingProfile::ChannelCount]; int deflectHeld[PadBindingProfile::ChannelCount];
memset(slewDelta, 0, sizeof(slewDelta)); memset(slewDelta, 0, sizeof(slewDelta));
+27
View File
@@ -58,6 +58,20 @@ public:
static int static int
GetLampState(int unit); GetLampState(int unit);
//
// Legacy typed-channel suppression (the btinput BTInputSuppressKey
// pattern, glass-side). A key CLAIMED by a bindings.txt row (or by the
// hardcoded `/V view-toggle and J/K/L preset-cycle keys) is swallowed
// from the engine's WM_CHAR/WM_KEYUP key-command feed (L4CTRL.cpp:1506
// block) -- otherwise every bound letter double-dispatches into the 1995
// in-cockpit dispatcher ('w' = pilot select 0, 'a'/'s'/'d'/'f' = MFD2
// preset pages, NUMPAD key-up VKs alias to 'b'/'d'/'e' hotkeys, ...).
// Unbound keys keep their authentic 1995 typed meaning. Returns 0 when
// no PadRIO is active (the feed flows untouched on dev/pod builds).
//
static int
SuppressKey(unsigned int key_value, int is_char);
enum { LampCount = 128 }; enum { LampCount = 128 };
protected: protected:
@@ -105,6 +119,19 @@ protected:
int int
lampState[LampCount]; lampState[LampCount];
//
// Typed-channel suppression tables (built from the loaded bindings +
// the hardcoded view/preset keys; see SuppressKey).
//
unsigned char
suppressChar[256]; // WM_CHAR values
unsigned char
suppressKeyUp[256]; // WM_KEYUP values (VK aliases)
void
AddKeySuppression(int virtual_key);
void
BuildKeySuppression();
static PadRIO static PadRIO
*activeInstance; *activeInstance;
}; };
+27 -2
View File
@@ -288,16 +288,41 @@
// Messaging Support // Messaging Support
// //
public: public:
//
// GLASS INPUT-AUDIT FIX (2026-07-20): these ids are PINNED to the
// binary numbering. The old chain started at
// L4MechControlsMapper::NextMessageID (=0x19), which registered every
// RIO handler at 0x19..0x2a -- but the streamed "L4" .CTL EventMapping
// records carry the BINARY's ids, and the binary RIO table @0051dd30
// (section_dump) RE-REGISTERS the MechControlsMapper aux/zoom ids
// 3..0x13 with the RIO override handlers (that is the whole point of
// the derived table: same message, real body instead of the base FAIL
// trap). With the shifted ids every streamed MFD-bank/zoom button
// press found only the base ConfigureMappableMessageHandler ("[FAIL]
// Unhandled button mapping") -- ~38 of the 72 pod panel buttons dead
// (and, on a real pod with BT_BUTTON_TRAP, an abort()). Hotbox is
// 0x1a in the binary (table entry @0051de98); the ctor/handler pair
// was previously self-consistent at the wrong value (0x2a), so it
// worked by accident -- now it matches the binary.
// (Faithful-fidelity note: the binary RIO table also carries its OWN
// Keypress id 0x19 -> @004d2514; our ctor still registers the shared
// L4 Keypress (0x17, @004d1bf0) -- see the Gitea backlog issue.)
//
enum { enum {
Aux1QuadMessageID = L4MechControlsMapper::NextMessageID, // 3 Aux1QuadMessageID = MechControlsMapper::Aux1QuadMessageID, // 3
Aux1Eng1MessageID, Aux1Eng2MessageID, Aux1Eng3MessageID, Aux1Eng4MessageID, Aux1Eng1MessageID, Aux1Eng2MessageID, Aux1Eng3MessageID, Aux1Eng4MessageID,
Aux2QuadMessageID, Aux2Eng1MessageID, Aux2Eng2MessageID, Aux2Eng3MessageID, Aux2Eng4MessageID, Aux2QuadMessageID, Aux2Eng1MessageID, Aux2Eng2MessageID, Aux2Eng3MessageID, Aux2Eng4MessageID,
Aux3QuadMessageID, Aux3Eng1MessageID, Aux3Eng2MessageID, Aux3Eng3MessageID, Aux3Eng4MessageID, Aux3QuadMessageID, Aux3Eng1MessageID, Aux3Eng2MessageID, Aux3Eng3MessageID, Aux3Eng4MessageID,
ZoomInMessageID, // 0x12 ZoomInMessageID, // 0x12
ZoomOutMessageID, // 0x13 ZoomOutMessageID, // 0x13
HotboxMessageID, // pilot-target select HotboxMessageID = 0x1a, // pilot-target select (@0051de98)
NextMessageID NextMessageID
}; };
static_assert(Aux1QuadMessageID == 0x03, "RIO Aux1Quad must be the binary id 3 (table @0051dd30)");
static_assert(Aux3Eng4MessageID == 0x11, "RIO Aux3Eng4 must be the binary id 0x11");
static_assert(ZoomInMessageID == 0x12 && ZoomOutMessageID == 0x13,
"RIO ZoomIn/ZoomOut must be the binary ids 0x12/0x13");
static_assert(HotboxMessageID == 0x1a, "RIO Hotbox must be the binary id 0x1a (@0051de98)");
void void
Aux1QuadMessageHandler(ReceiverDataMessageOf<ControlsButton> *message), // @004d22fc Aux1QuadMessageHandler(ReceiverDataMessageOf<ControlsButton> *message), // @004d22fc