Reticle Execute @004cdcf0 RECOVERED: every HUD instrument now live (task #37)

The one un-exported gap in the reticle chain, read via capstone
(tools/disas2.py; the annotated disasm preserved at
reference/decomp/reticle_execute_004cdcf0.disasm.txt). Draw() is now a
transcription of the real per-frame logic, and the HUD attr-table names
(hud.hpp ids 4/5/6/8/A/B/C/D) are CONFIRMED by their Execute usage:

- Range ladder: BAR from ladder-top to the caret + caret translate.
- The bottom 21-tick tape is the TORSO-TWIST indicator (NOT heading):
  deflection = -/+(span/2) x (RotationOfTorsoHorizontal / twist limit),
  attrs 4/5/6. Fixed-torso BLH reads centred -- authentic static.
- The circle-with-stem is the COMPASS (attr 0xD, rad->deg rotation) at
  (botX, botY - 3*tickMajor - 0.03), with the THREAT trail (attr 0xC)
  in its rotated frame: 0.05-unit attack-direction marks, fresh < 2s
  red, expiring at 6s. Port feed: player TakeDamage pushes the impact
  direction (dormant vs the passive test dummy).
- Pips (composed into subB6): hidden when destroyed (attr 1 == 1), LIT
  when the fire cycle is LOADED (attr 0x1c == 2; port source
  rechargeLevel >= 1) else the dark charging ring; filtered by the
  weapon-GROUP bits (weaponMode & elementMask&0xF). Range plays NO part
  (the stored TargetWithinRange slots are never read by Execute).
- Lock ring: subB9 at frame centre SPINNING 4 deg/frame while locked
  ([0x9d] is the spin matrix, not a heading list).
- Target HOTBOX: a rectangle hugging the projected extents (x+-4 around
  the top-centre hotbox point, +1/-11.5 vertical; baked K=2.8145 -- the
  port projects through the live per-axis projection), switching to the
  edge arrows past +-1.6 or behind (BTProjectHotBox, L4VIDEO).
- Reticle state Off/On + PrimaryHudOn full-HUD/simple-X switch, aim
  translate on slew move, 3D marker + PNAME player-name mesh identified
  (chain still deferred).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-08 22:38:50 -05:00
co-authored by Claude Fable 5
parent cf9f56044e
commit 18d49491b7
10 changed files with 1677 additions and 108 deletions
+31 -7
View File
@@ -93,13 +93,37 @@ ladder 0..1200 m, bottom heading tape, center cross + dot; tick ladders via FUN_
range caret binds to the live target range (`BTSetHudTargetRange`, fed by mech4's targeting step).
**Weapon pips:** the build loop (part_014.c:5386) registers EVERY subsystem
`IsDerivedFrom(0x511830 = MechWeapon)` — lasers, PPCs AND missile launchers (BLH = 7 pips) — via
`AddWeapon` @004cdac0 (verified store map in btl4vid.hpp), reading WeaponRange/PipPosition/
PipColor/PipExtendedRange/TargetWithinRange/SimulationState(attrs 1+0x1c)/RearFiring. Pip A (lit,
authored PipColor) when TargetWithinRange, else the dark ring B. [T2 geometry+wiring]
The binary's per-frame `Execute` @004cdcf0 sits in an UN-EXPORTED decomp gap — the Draw dynamics
(caret slide, pip lit/dark; lock rings/turn arrows built but static) are best-effort [T3].
Deferred: PNAME1-8.bgf 3D pip meshes + the 3D marker chain; the `blx_cop` canopy shell renders
black and is hidden by name filter (`BT_INSIDE_COCKPIT=1` shows it) — see [[open-questions]].
`AddWeapon` @004cdac0 (verified store map in btl4vid.hpp).
**The per-frame `Execute` @004cdcf0 is RECOVERED (task #37, capstone disasm via
`tools/disas2.py` — the full annotated read: the task-37 commit + btl4vid.cpp comments) [T1],
and every instrument is now live [T2]:**
- **Right ladder** = range 01200 m: a BAR from ladder-top to the caret + the yellow caret
translate (`-scaleY·frac`); pegs at 1200 with no target.
- **Bottom 21-tick tape = the TORSO-TWIST indicator** (NOT a heading tape): deflection line +
carets at `∓(span/2)·(RotationOfTorsoHorizontal / HorizontalTorsoLimit)` (HUD attrs 4/5/6).
Fixed-torso BLH: centred (authentic static).
- **Circle-with-stem = the COMPASS** (HUD attr 0xD CompassHeading, rad→deg rotation) at
`(botX, botY3·tickMajor0.03)`; the **THREAT trail** (attr 0xC ThreatVector) draws inside its
rotated frame: 0.05-unit attack-direction marks, fresh <2 s red, expiring at 6 s, 1 s blink tick.
Port feed: the player's TakeDamage handler pushes the impact direction.
- **Pips** (composed into subB6, master-called): hidden when the weapon's DAMAGE state == 1
(destroyed, attr 1); LIT (A) when the FIRE-CYCLE state == 2 (loaded, attr 0x1c; port source
rechargeLevel ≥ 1) else dark ring (B, charging); filtered by `weaponMode & elementMask&0xF`
(the weapon-GROUP bits Front/Rear/Left/Right). **Range plays NO part** — Execute never reads
the stored TargetWithinRange slots.
- **Lock ring** = subB9 (ring+cross) at frame centre, **SPINNING 4°/frame** while the Lock attr
(0xA) is up (port: while a target is locked); the binary also hangs the PNAMEx.bgf player-name
mesh on the 3D marker here (3D chain still deferred).
- **Target HOTBOX** (attr 0xB HotBoxVector) = a rectangle hugging the projected extents — x±4
around the hotbox point, +1/11.5 vertical (K=2.8145 baked projection; the port uses the live
per-axis projection) — switching to the left/right edge ARROW past ±1.6 or behind.
- Reticle state Off/On + `PrimaryHudOn` (mask 0x20) picks full HUD vs the "simple X" list;
the aim group translates by `reticlePosition` (SetMatrix, rebuilt on slew move).
This recovery also CONFIRMS the HUD attr-table ids 4/5/6/8/0xA/0xB/0xC/0xD name↔use pairings
(hud.hpp had flagged them uncertain). Deferred: PNAME1-8.bgf 3D marker chain; the `blx_cop`
canopy shell renders black and is hidden by name filter (`BT_INSIDE_COCKPIT=1` shows it) — see
[[open-questions]].
## Key Relationships
- Full history: `docs/GAUGE_COMPOSITE.md`; reticle recovery: `phases/phase-02-dpl2d-reticle.md`.
+8 -7
View File
@@ -60,15 +60,16 @@ authentic path scoped.
by the mouse — wire the real channel when pod hardware lands; (c) pre-burial, the pick still
tests the sinking wreck's collision box at its parked position (pre-existing wreck-targeting
behavior).
- **Cockpit HUD leftovers (task #35 residue, 2026-07-08)** — the reticle + 7 weapon pips are LIVE
(see [[gauges-hud]] + `phases/phase-02-dpl2d-reticle.md`), but three pieces remain: (a) the
- **Cockpit HUD leftovers (tasks #35-#37 residue, 2026-07-08)** — the reticle + 7 weapon pips +
ALL the instrument dynamics are LIVE (the Execute @004cdcf0 gap was RECOVERED via capstone
disasm, task #37 — see [[gauges-hud]] for the full instrument map). Remaining: (a) the
**blx_cop canopy shell** renders BLACK (untextured/unlit in our inside view) so it's hidden by a
name filter — `BT_INSIDE_COCKPIT=1` shows it; the authentic look needs its material/lighting
path; (b) the **PNAME1-8.bgf 3D pip meshes** + the 3D target-designator marker chain (the ctor's
15-arg form binds 8 HUD-subsystem attrs we bypass); (c) the binary per-frame **Execute
@004cdcf0** is in an un-exported decomp gap — the Draw dynamics (lock rings, off-screen turn
arrows, blink states, the 3 cached "SimulationState" constants 2/3/1) are best-effort [T3];
a Ghidra re-export of the 0x4cdcf0 region would let us transcribe it properly.
path; (b) the **3D marker chain** ([0x31c]/[0x320] dpl objects + the PNAME1-8.bgf player-name
meshes the Execute hangs over the locked target); (c) the "simple X" list [0x264]
(PrimaryHudOn off — the minimal reticle mode) is built empty in the port; (d) the HUD Lock
attr's (0xA) own HudSimulation producer (port analog: locked == designated) and the compass
rotation SIGN are [T3].
- **StatusMessagePool (NULL stub, btstubs.cpp:62)** — the per-player status-message queue.
BTPlayer+0x1dc is never populated → MessageBoard is empty (authentic for bring-up). What
resolves it: wire the pool + decode `AddStatusMessage @0042e580` + the `Player__StatusMessage`