Gitea #10 audit fixes: HUD attr table re-based (@5110b8, one-record shift) + BT_SHOT dock capture

- hud.hpp/hud.cpp/CLASSMAP.md: the binary HUD AttributePointers table starts at
  @5110b8 with a FULL id-3 FlickerRate record (the old transcription read it as a
  label and shifted every offset one slot). Re-based member names/offsets:
  rotationOfTorsoHorizontal@0x1DC (<- Torso+0x1D8 twist), limits@0x1E0/0x1E4,
  speed@0x1E8, rangeToTarget@0x1EC, @0x1F0 unbound, Visible@0x1F4 (init 1),
  Lock@0x1F8 (init 0), HotBoxVector P3D@0x1FC, ThreatVector P3D@0x208,
  CompassHeading Scalar@0x214 (= yaw euler[0] + twist, HudSimulation :5676).
  Cross-checked vs ctor @004b7f94 + HudSimulation @004b7830 (Lock rule writes
  @0x1F8 :5622/:5633; range default 1200 + 500 m/s slide @0x1EC). SetCompassHeading
  renamed SetThreatVector (@004b7810 writes @0x208 = the threat vector; no port
  caller). No behavioral change: the reticle feeds via port globals and the CFG
  never binds HUD attrs. Resolves the gauges-hud open question (Gitea #10 entry b).
- L4VIDEO.cpp: BT_SHOT capture moved AFTER BTDrawGaugeInset -- the 2026-07-18
  reorder had left it before the dock blit, so BT_DEV_GAUGES_DOCK screenshots
  silently omitted the gauge panel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-19 18:33:44 -05:00
co-authored by Claude Fable 5
parent 6783619069
commit 904c75aff9
4 changed files with 100 additions and 62 deletions
+9 -7
View File
@@ -8585,12 +8585,19 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
if (mCamShipHUD)
mCamShipHUD->Render(0, &viewTransform);
// DEV-COMPOSITE: in DOCKED mode (BT_DEV_GAUGES_DOCK) blit the 6-surface gauge panel
// into this window as the LAST draw before EndScene (no-op otherwise / off pod).
extern void BTDrawGaugeInset(LPDIRECT3DDEVICE9 device);
BTDrawGaugeInset(mDevice);
// DIAG (off by default): BT_SHOT=<path> dumps this instance's backbuffer to a
// PNG every 90 frames -- non-disruptive per-instance frame capture without
// foregrounding the window. Built for the -net render glitch (task #53);
// moved AFTER the 2D pass (2026-07-18, camera-seat bring-up) so captures
// include the HUD overlays (reticle, camera-ship ranking window) the screen
// actually shows.
// include the HUD overlays (reticle, camera-ship ranking window), and AFTER
// the docked gauge inset (2026-07-19, Gitea #10 audit -- the 07-18 reorder
// had left the capture BEFORE BTDrawGaugeInset, so BT_DEV_GAUGES_DOCK shots
// were missing the gauge panel the screen actually shows).
{
const char *shotPath = getenv("BT_SHOT");
if (shotPath)
@@ -8613,11 +8620,6 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
}
}
// DEV-COMPOSITE: in DOCKED mode (BT_DEV_GAUGES_DOCK) blit the 6-surface gauge panel
// into this window as the LAST draw before EndScene (no-op otherwise / off pod).
extern void BTDrawGaugeInset(LPDIRECT3DDEVICE9 device);
BTDrawGaugeInset(mDevice);
hr = mDevice->EndScene();
// DEV-COMPOSITE: default mode -- render the 6 cockpit surfaces into a SEPARATE window
+10 -5
View File
@@ -31,13 +31,18 @@ Subsystem (MUNGA base — have source: RP/MUNGA/SUBSYSTM.HPP)
│ │ │ cockpit heads-up display (torso-horizon gimbal + reticle/threat/status read-outs). Confirms the
│ │ │ "Resolved conflict" note: @4b7f94 is the HUD, mislabeled "MechTech" by mech.cpp's 0xBD6 factory case.
│ │ │ DefaultData 00511078; resource +0xF4 FlickerRate, +0xF8 SegmentPageName(idx), +0xFC HorizontalMovementPerSecond, +0x100 HorizontalLimit.
│ │ │ members: flickerRate@0x1D8, torso/target read-outs@0x1DC-0x1EC, lockFlag@0x1F4, visible@0x1F8,
│ │ │ threatVector(Vec3)@0x1FC, compassHeading(Vec3)@0x208 (setter @4b7810), blink/slew accums@0x218-0x230,
│ │ │ members (re-based 2026-07-19, Gitea #10, per the re-dumped attr table @5110b8): flickerRate@0x1D8,
│ │ │ rotationOfTorsoHorizontal@0x1DC(<-Torso+0x1D8 twist), torsoLimits@0x1E0/0x1E4, torsoSpeed@0x1E8,
│ │ │ rangeToTarget@0x1EC, @0x1F0 unbound, visible@0x1F4(init 1), lockFlag@0x1F8(init 0),
│ │ │ hotBoxVector(Vec3)@0x1FC, threatVector(Vec3)@0x208 (setter @4b7810 = SetThreatVector, ex-"SetCompassHeading" mislabel),
│ │ │ compassHeading(Scalar)@0x214(=yaw+twist), blink/slew accums@0x218-0x230,
│ │ │ linkedEntity@0x234(=Mech+0x438), statusAlarm(2)@0x238, horizontalTorsoOffset@0x294, HMPS@0x298, HorizontalLimit@0x29C, flickerActive@0x2A0.
│ │ │ overrides: HandleMessage@4b7780(s9, body not captured), ResetToInitialState@4b77bc(s10). HudSimulation@4b7830 (Performance, PTR@511170).
│ │ │ attr table @5110c0 (ids 4-0xd: RotationOfTorsoHorizontal/HorizontalTorsoLimit{Right,Left}/SpeedOfTorsoHorizontal/
│ │ │ RangeToTarget/Visible/Lock/HotBoxVector/ThreatVector/CompassHeading) — NB attr name<->offset bindings only
│ │ │ partially agree with ctor/sim usage (UNCERTAIN). TestInstance@4b81b8 (deriv @511088 "HUD"). UpdateFlicker@4b7ed4.
│ │ │ attr table @5110b8 (16-byte records; ids 3-0xd: FlickerRate@0x1D8 + RotationOfTorsoHorizontal@0x1DC/
│ │ │ HorizontalTorsoLimit{Right@0x1E0,Left@0x1E4}/SpeedOfTorsoHorizontal@0x1E8/RangeToTarget@0x1EC/Visible@0x1F4/
│ │ │ Lock@0x1F8/HotBoxVector@0x1FC/ThreatVector@0x208/CompassHeading@0x214) — RESOLVED 2026-07-19: the old
│ │ │ "@5110c0, ids 4-0xd" transcription had dropped the leading id-3 FlickerRate record and shifted every offset
│ │ │ one slot; ctor+HudSimulation usage now agrees exactly. TestInstance@4b81b8 (deriv @511088 "HUD"). UpdateFlicker@4b7ed4.
│ │ ├─ Searchlight vtable 005114d4 classID 0xBD8 ctor @4b84dc dtor @4b8568 CSS @4b85a8 [searchlight.cpp DONE] model 0xF4
│ │ │ illumination subsystem (corroborated by btl4vid MakeMechRenderables "0xBD8 SearchLight"). DefaultData 00511198.
│ │ │ empty resource (CSS only stamps). members: lightState@0x1D8 ("LightState" attr id5),
+32 -22
View File
@@ -126,17 +126,21 @@ HUD::HUD(
Check(owner);
Check_Pointer(subsystem_resource);
flickerRate = 0.0f; // @0x1D8 (overwritten below from resource)
torsoLimitRight = 0.0f; // @0x1DC
torsoLimitLeft = 0.0f; // @0x1E0
torsoSpeed = 0.0f; // @0x1E4
rangeToTarget = 0.0f; // @0x1E8
targetRange = 0.0f; // @0x1EC
lockFlag = True; // @0x1F4 = 1
visible = False; // @0x1F8
threatVector = HudZeroVector; // @0x1FC
compassHeading = HudZeroVector; // @0x208
hotBoxScalar = 0.0f; // @0x214
// (member names re-based 2026-07-19 per the re-dumped attr table @005110b8;
// the ctor @004b7f94 zeroes [0x76..0x7b] then sets [0x7d]=1 / [0x7e]=0 --
// note [0x7c]=@0x1F0 is left uninitialized in the binary)
flickerRate = 0.0f; // @0x1D8 (overwritten below from resource)
rotationOfTorsoHorizontal = 0.0f; // @0x1DC
torsoLimitRight = 0.0f; // @0x1E0
torsoLimitLeft = 0.0f; // @0x1E4
torsoSpeed = 0.0f; // @0x1E8
rangeToTarget = 0.0f; // @0x1EC
scratch1F0 = 0; // @0x1F0 (binary leaves it uninitialized; zeroed here)
visible = True; // @0x1F4 = 1 ("Visible" starts shown)
lockFlag = False; // @0x1F8 = 0 ("Lock" starts un-locked)
hotBoxVector = HudZeroVector; // @0x1FC
threatVector = HudZeroVector; // @0x208
compassHeading = 0.0f; // @0x214
blinkTimer = 0.0f; // @0x218
flickerTimer = 0.0f; // @0x21C
blinkState = True; // @0x224 = 1
@@ -162,12 +166,14 @@ HUD::HUD(
// owner+0x438 is the torso-orientation source -- a Mech RAW OFFSET that does not
// hold a valid pointer in the reconstructed Mech layout (and isn't linked yet at
// subsystem-construction time), so dereferencing it crashes. Default the
// torso/range readouts to 0; HudSimulation refreshes them per-frame once the link
// torso/twist readouts to 0; HudSimulation refreshes them per-frame once the link
// is live. TODO: wire a real Mech torso-orientation-source accessor.
// (binary snapshot @004b7f94: [0x77]@0x1DC <- linked+0x1D8 twist, [0x78]@0x1E0
// <- +0x1DC limitR, [0x79]@0x1E4 <- +0x1E0 limitL, [0x7a]@0x1E8 <- +0x1E8 speed)
linkedEntity = 0; // @0x234
rotationOfTorsoHorizontal = 0.0f;
torsoLimitRight = 0.0f;
torsoLimitLeft = 0.0f;
rangeToTarget = 0.0f;
torsoSpeed = 0.0f;
Check_Fpu();
@@ -203,14 +209,17 @@ Logical
}
//###########################################################################
// SetCompassHeading -- @004b7810
// SetThreatVector -- @004b7810
//
// Copies a Point3D into compassHeading (@0x208).
// Copies a Point3D into threatVector (@0x208). Renamed 2026-07-19 (Gitea
// #10): the re-dumped attr table @005110b8 binds "ThreatVector" (attr 12) to
// @0x208 -- the old SetCompassHeading label was the one-slot transcription
// shift (the compass is the Scalar @0x214). No port caller.
//
void
HUD::SetCompassHeading(const Point3D &heading)
HUD::SetThreatVector(const Point3D &threat)
{
compassHeading = heading; // FUN_00408440(this+0x208, &heading)
threatVector = threat; // FUN_00408440(this+0x208, &threat)
}
//###########################################################################
@@ -299,11 +308,12 @@ Logical
// 0 -> set HUD flag bit 0x1 on the graphic, clear bit 0x2
// 3 -> set bit 0x2, clear bit 0x1 (and gate on mech +0x410)
// writes the resulting "active" flag to *(mech +0x374).
// 5. Target line-of-sight: if a target entity (mech +0x388) exists and is
// not over the heat limits, computes targetRange (@0x1EC) as the distance
// between the HUD anchor (mech +0x37C) and the target (+0x100); sets
// visible (@0x1F8); otherwise blanks. A default range 1200.0 is used
// when there is no target.
// 5. Target lock + range: if a target entity (mech +0x388) exists and the
// own/target zone-damage limits pass (:5619-5634, the Lock rule), sets
// lockFlag (@0x1F8, "Lock"); rangeToTarget (@0x1EC, "RangeToTarget") is
// the distance between the HUD anchor (mech +0x37C) and the target
// (+0x100), sliding at 500 m/s (:5652-5670), default 1200.0 with no
// target; the compass Scalar @0x214 = yaw euler[0] + torso twist (:5676).
// 6. Torso-horizon slew: horizontalTorsoOffset (@0x294) is moved toward the
// commanded torso heading at up to MaxTorsoSlew (500/sec), clamped to
// +/- horizontalLimit (@0x29C), then written to the graphic at
+49 -28
View File
@@ -96,18 +96,30 @@
//
// AttributePointers IndexEntry table @005110c0 (each record binds a name
// to an attribute id and an object offset, the offset encoded as
// byte_offset|1 -- the same scheme used by sensor.hpp). Recovered:
// id 4 "RotationOfTorsoHorizontal" -> @0x1D8
// id 5 "HorizontalTorsoLimitRight" -> @0x1DC
// id 6 "HorizontalTorsoLimitLeft" -> @0x1E0
// id 7 "SpeedOfTorsoHorizontal" -> @0x1E4
// id 8 "RangeToTarget" -> @0x1E8
// id 9 "Visible" -> @0x1EC
// id 10 "Lock" -> @0x1F4
// id 11 "HotBoxVector" -> @0x1F8
// id 12 "ThreatVector" -> @0x1FC (Vec3)
// id 13 "CompassHeading" -> @0x208 (Vec3)
// (FlickerRate name ptr @005110bc heads the table as the category label.)
// byte_offset|1 -- the same scheme used by sensor.hpp).
//
// RE-DUMPED 2026-07-19 (Gitea #10 audit; section_dump.txt @5110b8, 16-byte
// records {id, namePtr, offset|1, 0}, terminator @511160). The table
// actually STARTS at @005110b8 with a FULL id-3 FlickerRate record (the old
// transcription had misread it as a "category label" and shifted every
// subsequent offset down one slot):
// id 3 "FlickerRate" -> @0x1D8
// id 4 "RotationOfTorsoHorizontal" -> @0x1DC
// id 5 "HorizontalTorsoLimitRight" -> @0x1E0
// id 6 "HorizontalTorsoLimitLeft" -> @0x1E4
// id 7 "SpeedOfTorsoHorizontal" -> @0x1E8
// id 8 "RangeToTarget" -> @0x1EC
// id 9 "Visible" -> @0x1F4 (init 1; @0x1F0 is unbound)
// id 10 "Lock" -> @0x1F8 (init 0)
// id 11 "HotBoxVector" -> @0x1FC (Point3D)
// id 12 "ThreatVector" -> @0x208 (Point3D)
// id 13 "CompassHeading" -> @0x214 (Scalar: yaw + torso twist)
// CROSS-CHECKED against the ctor @004b7f94 (inits @0x1F4=1 Visible-on /
// @0x1F8=0 Lock-off; @0x1F0 uninitialized) and HudSimulation @004b7830
// (per-frame @0x1DC <- linkedTorso+0x1D8 = Torso::currentTwist; @0x1EC
// range default 1200.0 + the 500 m/s display slide; the Lock rule writes
// @0x1F8 at :5622/:5633; @0x214 = EulerAngles(mech)[0] + @0x1DC at :5676;
// the hotbox Point3D copy @0x1FC at :5680). All consistent.
//
// CONFIRMED (task #37): the recovered reticle Execute @004cdcf0 binds and
// USES ids 4/5/6/8/0xA/0xB/0xC/0xD exactly per these names --
@@ -115,8 +127,7 @@
// HorizontalTorsoLimit full-scales, RangeToTarget the range caret, Lock
// the spinning lock ring, HotBoxVector the target box (eye-space vec3),
// ThreatVector the compass threat trail, CompassHeading the rose
// rotation. (The earlier note about @0x1D8/@0x1EC/@0x1F8 usage remains
// for the ctor-side seeds only.)
// rotation.
//
public:
enum {
@@ -142,20 +153,25 @@
// Local data. Offsets are byte offsets into the shipped object; names are
// best-effort from the attribute pool + ctor/HudSimulation usage.
//
// Member names re-based 2026-07-19 (Gitea #10) against the RE-DUMPED attr
// table @005110b8 -- the old names were shifted one slot (see the table
// comment above).
protected:
Scalar flickerRate; // @0x1D8 resource +0xF4 (flicker / blink period threshold)
// Torso / target read-outs sampled each construction from the linked
// targeting entity (owner Mech +0x438 -> this->linkedEntity @0x234):
Scalar torsoLimitRight; // @0x1DC <- linkedEntity +0x1D8
Scalar torsoLimitLeft; // @0x1E0 <- linkedEntity +0x1DC
Scalar torsoSpeed; // @0x1E4 <- linkedEntity +0x1E0
Scalar rangeToTarget; // @0x1E8 <- linkedEntity +0x1E8 (and recomputed in sim @0x1EC)
Scalar targetRange; // @0x1EC computed line-of-sight distance to the target
int lockFlag; // @0x1F4 init 1
int visible; // @0x1F8 set 0/1 from heat + line-of-sight each frame
Point3D threatVector; // @0x1FC init (0,0,0) ("ThreatVector")
Point3D compassHeading; // @0x208 init (0,0,0) ("CompassHeading"); see SetCompassHeading
Scalar hotBoxScalar; // @0x214 init 0
Scalar flickerRate; // @0x1D8 resource +0xF4 ("FlickerRate", attr id 3)
// Torso / target read-outs sampled at construction AND per-frame in
// HudSimulation from the linked Torso subsystem (owner Mech +0x438 ->
// this->linkedEntity @0x234):
Scalar rotationOfTorsoHorizontal; // @0x1DC <- linkedEntity +0x1D8 (Torso::currentTwist; attr 4)
Scalar torsoLimitRight; // @0x1E0 <- linkedEntity +0x1DC (attr 5)
Scalar torsoLimitLeft; // @0x1E4 <- linkedEntity +0x1E0 (attr 6)
Scalar torsoSpeed; // @0x1E8 <- linkedEntity +0x1E8 (attr 7 "SpeedOfTorsoHorizontal")
Scalar rangeToTarget; // @0x1EC computed target distance; 1200.0 default; 500 m/s display slide (attr 8)
int scratch1F0; // @0x1F0 unbound / not ctor-initialized in the binary
int visible; // @0x1F4 init 1 ("Visible", attr 9; heat/page gating)
int lockFlag; // @0x1F8 init 0 ("Lock", attr 10; the :5619-5634 lock rule)
Point3D hotBoxVector; // @0x1FC init (0,0,0) ("HotBoxVector", attr 11)
Point3D threatVector; // @0x208 init (0,0,0) ("ThreatVector", attr 12); see SetThreatVector
Scalar compassHeading; // @0x214 init 0 ("CompassHeading", attr 13; yaw euler[0] + torso twist @:5676)
Scalar blinkTimer; // @0x218 accumulates time, reset against flickerRate
Scalar flickerTimer; // @0x21C
int blinkState; // @0x224 init 1 (visible phase of the blink)
@@ -193,8 +209,13 @@
void
HudSimulation(Scalar time_slice); // @004b7830 (Performance, PTR @00511170)
// @004b7810 writes the Point3D @0x208 -- which the RE-DUMPED attr table
// (2026-07-19) proves is the THREAT vector, not the compass (the compass
// is the Scalar @0x214). Renamed from the old mislabel SetCompassHeading;
// no port caller exists (the port threat-trail feed goes through the
// reticle globals, btl4vid.cpp).
void
SetCompassHeading(const Point3D &heading); // @004b7810 (writes compassHeading @0x208)
SetThreatVector(const Point3D &threat); // @004b7810 (writes threatVector @0x208)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Subsystem virtual overrides (vtable @00511510)