--- id: pod-hardware title: "Pod Hardware — the fixed target (7 monitors, D3D9, RIO)" status: established source_sections: "PROGRESS_LOG.md §3; the PLATFORM PROFILE + GAUGE DEV-COMPOSITE notes" related_topics: [gauges-hud, rendering, project-overview] key_terms: [pod, RIO, MFD, IG-board, SVGA16] --- # Pod Hardware (the fixed target) The port must run on (a) a dev box and (b) the fixed arcade pod. The pod is a hard constraint that bounds the graphics API. Full detail: `docs/PROGRESS_LOG.md §3`. ## Displays - **2 video cards → 7 monitors:** main 3D view **800×600**; radar **640×480**; five monochrome MFDs driven as one **1280×480** horizontally-spanned surface. [T1] - Requires **old NVIDIA drivers** for the MFD horizontal spanning — a hard constraint that bounds the graphics API → **Target Direct3D 9** (lowest common denominator that runs on old-driver pods AND modern cards; one codepath). NOT Vulkan/D3D11+. CUDA is irrelevant (compute, not display). [T1] ## Cockpit I/O (RIO) Joystick X/Y, throttle, pedals, buttons over **serial COM** (`L4RIO`, `L4SERIAL`). Must be remapped to keyboard/gamepad on a dev box; real wiring is a pod bring-up task (Phase 8). The engine is a PUSH model — `LBE4ControlsManager` groups are fed by all devices (RIO on the pod, DirectInput on dev); the `MechControlsMapper` interprets them ([[locomotion]]). [T2] ### The button space + lamps [T0, L4CTRL.h enum] buttonGroup addresses 0x00-0x47: `AuxLowerRight/Left 1-8` (0x00-0x0F), `Secondary1-12` (0x10-0x1B), `AuxUpperCenter/Left/Right 1-8` (0x20-0x37; **0x30-0x37 = the target HOTBOX**, pilot select), icom/door 0x39-0x3C, `Panic` 0x3D (the config-mode lamp), `Throttle1` 0x3F (throttle-head = REVERSE THRUST), joystick cluster 0x40-0x47 (Main trigger 0x40, hat 0x41-0x44, Pinky/ThumbLow/ThumbHigh 0x45-0x47 — the four MAPPABLE fire buttons). "Lamp buttons" are literal: physical illuminated pushbuttons in panels around the screens; the RIO `LampRequest` protocol lights them (`MakeLinkedLamp`), reports burned-out bulbs (`RIODeadLamps` failure page, per-lamp names). A lit button = active. Keypads are NOT buttons: `keyboardGroup[KeyboardPilot/ KeyboardExternal]` carry key VALUES ('0'-'9','A'-'F', L4CTRL.cpp:2526). RIO event convention: press = `buttonGroup[a].Update(a+1, modeMask)` (mask saved), release = `Update(-a-1, savedMask)` (L4CTRL.cpp:2470-2520). **Bank→MFD assignment (Gitea #9, from the streamed "L4" .CTL EventMapping dump [T1]):** each preset-able MFD owns the 8-button bank AROUND it, mode-mask-gated per page — **Mfd1 (lower left) = 0x08-0x0F (AuxLowerLeft), Mfd2 (upper center) = 0x20-0x27 (AuxUpperCenter), Mfd3 (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 (generator select A-D msg 4-7, gen mode msg 8, weapon configure msg 9; also **msg 0x3 = ToggleCooling — WIRED 2026-07-20**: the button→msg-3 route was always authored (`BT_CTRLMAP_LOG` shows ~a dozen `EVENT msg 0x3` entries, e.g. Eng-page aux `elem 0x21` mask-gated per ModeMFD page to each weapon), but was "silently dead" only for lack of the id-3 handler. Reconstructed `HeatSink::ToggleCoolingMessageHandler` (@004ad6f8) + restored the `PoweredSubsystem→HeatSink` handler chain, so the Eng-page "Coolant" button now toggles the shown weapon's coolant flow. msg 0xb = ToggleSeekVoltage (energy) / EjectAmmo (ammo weapons) still unreconstructed). **Always-active records IDENTIFIED 2026-07-20 [T1]** (roster: sub 3 = Reservoir, 4-9 = Condenser1-6, 10-13 = GeneratorA-D): **0x2C = the COOLANT FLUSH 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] `game/reconstructed/btinput.cpp` + `content/CONTROLS.MAP` (WASD-classic default, compiled-in twin; `content/CONTROLS_NUMPAD.MAP` = the corrected community numpad profile). Grammar: `key button |axis deflect|rate |keypad pilot|external <0-15>|pckey |action `; `pad