Fix 1 (Gitea #12): disasm-exact ProjectileWeaponSimulation @004bbd04 + the dirty-bit sweep

Replace the RivetGun-modeled ProjectileWeaponSimulation body with the fully
recovered binary machine (capstone disasm, every branch address-cited):

- gate 1 @4bbd36: simulationState@0x40==1 (destroyed) || heatAlarm==FailureHeat
  || owner disabled -> recoil=rechargeRate + alarm 7 (was: simulationFlags==1)
- gate 2 @4bbd71: bin alarm 2/3 or bin destroyed -> alarm 7 re-pinned per frame
- Loaded @4bbec2: DENIED shots (viewFireEnable off / no owner target) blip
  SetLevel(4);SetLevel(2) and STAY LOADED, no ammo pull (the old FireWeapon
  early-returns under an unconditionally-cycling caller faked a full firing
  pip cycle -- the "missiles cycle but never launch" incident mechanic);
  the ammo pull is bin->FeedAmmo @4bbee6 in the CALLER; both updateModel|=1
  marks (@4bbf05/@4bbf4c = ForceUpdate) bracket FireWeapon; recoil set @4bbf51
- Loading @4bbdd2: recoil bleeds ONLY here at electrical Ready and CLAMPS at 0
  (it ran to -114 before); bin Loaded -> weapon Loaded
- 7 @4bbe4d: binary-faithful roach motel (re-asserted unconditionally;
  recovery = ResetToInitialState only)
- slot 17 @004b9c9c reconstructed as MechWeapon::ComputeOutputVoltage
  (rechargeLevel=(rechargeRate-recoil)/rechargeRate, Emitter overrides with
  @4ba738) and called from Loading/7 -- the launcher recharge dial ANIMATES
  (the old "authentically static" claim was wrong)

FireWeapon bodies stripped to heat+spawn only per @004bcc60 (no view gate, no
ConsumeRound, no recoil); ConsumeRound retired (not a binary method).

Gotcha #20 sweep (all sites disasm-verified): simulationFlags|=0x1 == engine
DelayWatchersFlag (audio watchers muted forever) removed everywhere --
projweap/mislanch fire marks, ProjectileWeapon::ResetToInitialState (@4bbb47
= updateModel|=1); Emitter::SetDirty retired and split per binary site into
ForceUpdate() (@4bafaa/@4ba55d) vs ExecuteOnUpdate() (@4ba99a/@4ba943);
Emitter fault gate GetFlags()==1 -> simulationState==1 (@4baab9).

AmmoBin::GetAmmoState() accessor added (named-member read of ammoAlarm@0x1A8).
BT_LOOK_TEST=<frame> scripted verify added (mech4.cpp): holds the rear-view
button 300f on/300f off to drive viewFireEnable headlessly.

Verified solo ARENA1 (bhk1, autofire): 54-60 [projectile] PUSH + impact smoke;
look-back denial window = trigger pulses, state stays 2, zero launches,
resumes on release; enemy (disabled) mech launchers pinned 7 + full recoil;
STREAK-6 recharge dial sweeps across BT_SHOT frames; lasers fire throughout;
zero gauge faults.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-19 23:26:11 -05:00
co-authored by Claude Fable 5
parent 2215932016
commit 2edde29671
11 changed files with 292 additions and 165 deletions
+4 -1
View File
@@ -201,7 +201,9 @@ From the weapon `.SUB` records + the charge-curve `.data` constants (PE-parsed a
(own heatAlarm level) == 2 -> emitter @004baa88 resets firing + holds charge 0; ballistic
@004bbd36 pins `recoil=rechargeRate` + alarm 7.
- **@004bbd04 ProjectileWeaponSimulation FULLY RECOVERED (capstone disasm, Gitea #12,
2026-07-19) [T1]**the port's RivetGun-modeled body diverges; the authentic machine:
2026-07-19) [T1] — PORT NOW IMPLEMENTS IT (landed 2026-07-19, projweap.cpp; solo-verified:
missiles fly, denial blip stays Loaded, recoil clamped, slot-17 dial animates; MP re-verify
pending)** — the old RivetGun-modeled body diverged; the authentic machine:
PoweredSubsystemSimulation@4b0bd0; trigger=CheckFireEdge@4b9608; UpdateEject@4bbb50;
**gate 1 @4bbd36: `simulationState@0x40==1` (destroyed — NOT simulationFlags@0x28!) ||
heatAlarm@0x184==2 || FUN_49fb54(owner disabled) → recoil=rechargeRate + alarm 7**;
@@ -313,6 +315,7 @@ default-ON (`'0'` disables).
| `BT_VIEWCYCLE_TEST=<frame>` / `BT_MODECYCLE_TEST=<frame>` | scripted verify (mech4.cpp): pulse a secondary-schematic cycle / a control-mode cycle at the frame and every 300 after — pixel-verifiable with `BT_DEV_GAUGES_DOCK`+`BT_SHOT` |
| `BT_PRESET_TEST=<frame>` | scripted verify (mech4.cpp, Gitea #9): from the frame, pulse an upper-MFD preset-page cycle on all three MFDs every 120 frames (Quad → populated Eng pages → Quad) — pixel-verifiable with `BT_DEV_GAUGES_DOCK`+`BT_SHOT` |
| `BT_PRESET_HOLD=<n>` | (with BT_PRESET_TEST, Gitea #11) stop after n pulses so a page is HELD — steady-state pixel verification; the 120-frame cycle phase-locks with BT_SHOT's 90-frame cadence, so cycling shots periodically capture the 1-frame page-switch transition |
| `BT_LOOK_TEST=<frame>` | scripted verify (mech4.cpp, Gitea #12): from the frame, HOLD the rear-view button 300 frames / release 300, repeating — drives mapper→BTCommitLookState→viewFireEnable so the projectile denied-shot blip (stay-Loaded, no launch) is log-verifiable headless |
| `BT_SEEK_LOG` | `[seek] BecameActive/replot` — SeekVoltageGraph activation sentinel + clear/replot events with the response-at-12kV value (Gitea #11, btl4gau2.cpp) |
| `BT_CTRLMAP_LOG` | streamed `.CTL` record audit (L4CTRL.cpp CreateStreamedMappings): Direct records with the resolved member offset + EVENT records (button→subsystem message; found the pod's secondary-panel Cycle buttons 0x15/0x18) |
| `BT_CAM_LOG` | camera-seat/broadcast trace: streamed camera network count, director pick + Players-group census, ship follow state, PlayerLink dispatch/receive, ranking-window render ([[multiplayer]] camera seat) |
+8
View File
@@ -422,6 +422,14 @@ port transcribed as `simulationFlags == 1` — with the spurious `|=1` above, th
permanent alarm-7 kill-switch for any launcher whose other flag bits are 0. **Rule:** a binary
`[this+0x18] |= 1` = `ForceUpdate()`; `[this+0x28]` = simulationFlags (engine-defined bits —
never invent meanings); `[this+0x40]` = MechSubsystem::simulationState (1 = destroyed). [T1]
**FIXED 2026-07-19 (Gitea #12, all sites disasm-verified):** `Emitter::SetDirty` retired — it
conflated `or word [this+0x18],1` (= ForceUpdate; FireWeapon tail @4bafaa, Reset tail @4ba55d)
with `or dword [this+0x28],2` (= ExecuteOnUpdate; ServiceDischarge @4ba99a/@4ba943) — each call
site now uses the correct engine call; the emitter fault gate `GetFlags()==1``simulationState
== 1` (@4baab9); `mislanch.cpp` salvo mark and `projweap.cpp` AC mark / ResetToInitialState
(@4bbb47) likewise. ⚠ One un-audited sibling remains: `btplayer.cpp:426` `simulationFlags|=0x1`
("request a forced update" — likely the same mis-transcription; verify against the
VehicleDead handler's disasm before changing). [T2]
---