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:
co-authored by
Claude Fable 5
parent
6783619069
commit
904c75aff9
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user