Uncommitted work from the speed-model + peer-motion investigation: - btl4mppr.cpp: the L4MechControlsMapper full-throttle detent used the unparenthesized Abs() macro (STYLE.H:118) on an expression -- Abs(throttlePos - 1.0f) mis-expands to -(throttlePos + 1.0f), always <= 0.05, so the detent snapped throttle to full EVERY frame. Diff into a temp first (same class as the7615ecdangular-resync Abs fix). - context/pod-hardware.md: document the decomp-verified analog-continuous pod throttle path (RIO Ranger 0-800 counts, 0.05 deadband, no notching; '5 speeds' is false) from workflow w0odszxro. - mech4.cpp: BT_SLIDE/[mslide] per-frame slide diagnostics (peer position moving while legs in stand; master decel profile) -- used to prove the stop-slide is a peer leg-SM-winds-down-early desync, not master momentum. Env-gated. The 'pretty good' coupled-motion gameplay state is already shipped (a9ab3db). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
5.3 KiB
Markdown
81 lines
5.3 KiB
Markdown
---
|
||
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 pod throttle is ANALOG-CONTINUOUS, not notched (verified end-to-end) [T1]
|
||
The authentic pod throttle path — traced 2026-07 (task #50 throttle-fidelity question):
|
||
1. **Hardware → RIO:** serial `AnalogReply` packet → `Ranger("Throttle", 0, 800, .05)` — raw counts
|
||
0–800, 5% deadband, auto-ranging offset, output a CONTINUOUS Scalar; the sign is inverted
|
||
("Throttle counts BACKWARDS", `engine/MUNGA_L4/L4RIO.cpp:1374-1377`, Ranger @L4RIO.cpp:461-701).
|
||
No quantization/notching anywhere in `Ranger::Update`.
|
||
2. **Manager:** `LBE4ControlsManager::Execute` → `scalarGroup[ScalarThrottle].Update(&rioPointer->
|
||
Throttle, mode_mask)` on every AnalogReply (`L4CTRL.cpp:1379-1382`). ScalarThrottle = index 0 →
|
||
manager+0x24 (scalarGroup base 0x24, 0x20/entry; buttonGroup base 0x1c0, keyboardGroup 0x160).
|
||
3. **Streamed `.CTL` mapping (the "handled elsewhere"):** `MechRIOMapper`'s ctor @004d266c binds NO
|
||
throttle — the bind comes from the type-19 `ControlMappingStream` resource named **"L4"** (child
|
||
of the per-mech type-6 `ControlMappingsList`; installed by `BTL4APP MakeViewpointEntity` via
|
||
`CreateStreamedMappings` @0047703c). BTL4.RES "L4" record [1]:
|
||
`Scalar Throttle → subsystemID 0 (ControlsMapper slot), DirectMapping, attr 4, mask 0xffffffff`.
|
||
Attr 4 = "ThrottlePosition" @ mapper+0x11c (binary IndexEntry table @0050efd8: id 4 → offset
|
||
0x11d-1 = 0x11c, name "ThrottlePosition" @0050f28f). Reverse = record [2]: `Button Throttle1
|
||
(0x3F, on the throttle handle) → attr 6 ReverseThrust@0x124`. Turn = pedals value-bound in the
|
||
ctor (manager+0x44/+0x64 → mapper+0x1b4/+0x1b8).
|
||
4. **Interpretation:** `L4MechControlsMapper::InterpretControls` @004d196c applies the ONLY software
|
||
detent — snap to 1.0 when |t−1.0| ≤ 0.05 — then `MechControlsMapper::InterpretControls` @004afd10
|
||
computes `speedDemand@0x128 = maxSpeed(mech+0x34c) × throttlePosition(0x11c) × scale(mech+0x5c0)`
|
||
(forward) or `−maxSpeed × throttlePosition` (reverse flag 0x124).
|
||
|
||
**Consequence:** the original pod produced a continuously varying speedDemand while the lever moved
|
||
(updated per serial AnalogReply, NOT per render frame). There are NO "5 throttle notches" anywhere
|
||
in the software path. (Keyboard keys '1'-'5' in @004d1bf0 set controls-manager MODE masks; the
|
||
'+'/'-' pair steps a [0,5] value that drives `pow(2,x)` into mech+0x404 = HUD zoom 1×–32× — neither
|
||
is a speed setting.) The mech's `throttleState@0x4a4` writer remains un-exported (likely in the
|
||
0x4a9b5a–0x4ab188 gap) — [[open-questions]].
|
||
|
||
## Multi-surface gauge path (intact, pod-only by default)
|
||
The pod multi-surface path EXISTS and is intact: `DPLRenderer::FindBestAdapterIndices` (multi-
|
||
adapter selector, honors PRIMGAUGE/SECGAUGE/MFDGAUGE/SPANDISABLE), `SVGA16::BuildWindows` (a
|
||
fullscreen D3D device + window per gauge/MFD surface, MFD span = width×2), `L4GaugeRenderer` (gated
|
||
on `L4GAUGE`). `content/SETENV.BAT` is the authentic pod env preset (L4CONTROLS=RIO,KEYBOARD;
|
||
L4GAUGE=640x480x16; L4PLASMA=com2). [T2]
|
||
|
||
## Platform profile switch
|
||
`-platform pod|dev` (or `BT_PLATFORM` env; default DEV) selects a runtime env preset WITHOUT forking
|
||
the codepath. **DEV** = keyboard + single 800×600 window. **POD** = RIO input (keyboard fallback off
|
||
serial) + multi-surface gauges (from SETENV.BAT/L4GAUGE on real hardware). `-platform pod` does NOT
|
||
auto-enable L4GAUGE (each surface needs its own fullscreen device on the pod's 2 cards). Off-pod, the
|
||
6 MFD surfaces render in a dev window via `BT_DEV_GAUGES` ([[gauges-hud]]). [T2]
|
||
|
||
## MFD surface model
|
||
All cockpit surfaces are bit-plane MASKS over ONE shared `SVGA16` pixelBuffer: `sec`=palette low
|
||
byte; `Heat`=0x4000, `Mfd2`=0x0400, `Comm`=0x8000, `Mfd1`=0x0100, `Mfd3`=0x1000; `Eng1-3` =
|
||
engineering-mode alt planes; `overlay`=0x00C0 (shares the sec surface). See [[gauges-hud]]. [T2]
|
||
|
||
## Key Relationships
|
||
- Renders: [[gauges-hud]] (the MFD surfaces), [[rendering]] (the main 3D view).
|
||
- Input: [[locomotion]] (the mapper).
|
||
- Bring-up: Phase 8 (get pod specifics from Nick — [[open-questions]]).
|