Chain (every hop verified live): FootStep pulse (SetBodyAnimation, decay in
PerformAndWatch) -> AudioMatchOf match=1 -> Start(2.0) on the FootFall
DirectPatchSource... which the renderer DROPS because its volume is 0:
an AudioControlMixer (outCtl=3/Volume + a second outCtl=5 mixer) feeds the
source, and BOTH mixer inputs are 0 -- nothing ever sends them.
Eliminated as senders (all traced): AudioScaleOf scales (29 total, none target
the mixer), AudioControlMultiplier (one instance, other target), Random/
AudioSampleAndHold (RNG verified WORKING -- varied samples; RANDOM.cpp is in
the build, the self-init ctor runs).
HYPOTHESIS [T4, next session]: the mixer inputs are fed by AudioStateTriggers
on AnimationState keyed to the AUTHORED gait-clip ids (walk 2/3, run 8/9 =
per-gait footstep volume). Our runtime body SM walks in states 12<->13 --
which the recovered MechAnimationState enum names RightStandToReverse/
LeftStandToReverse. If the authored audio expects 2/3 for forward walk, the
runtime clip NUMBERING in the reconstructed gait SM is offset from the
authentic ids -- a locomotion-layer mismatch with implications beyond audio
(the audio config is an independent witness to the true clip numbering).
Verify via the AudioStateTrigger configs on the AnimationState watcher
(trigcfg dump exists) and cross-check the SetBodyAnimation clip table.
New diagnostics: [snh] SampleAndHold sends, [mix] mixer forwards with input
index + sum, [scalecfg] authored scale bindings/boundaries, [volset].
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Footstep chain progress (each step empirically verified):
- The FootStep watcher is an AudioMatchOf<Logical> (AudioLogicalTrigger extends
AudioMatchOf, NOT AudioTriggerOf): authored config match=1 -> Start(2.0) on a
DirectPatchSource. [trigcfg]/[matchcfg] ctor dumps added.
- The pulse was pinned at 1: the decay lived in IntegrateMotion, which the
current gait path NEVER CALLS. Moved to Mech::PerformAndWatch (provably
per-frame) with a time-based 150ms window sized to the ~10Hz watcher poll.
The matcher now fires per stride (14/run, was 1).
- Every footstep Start is DROPPED at the renderer: the source's volumeScale is
0 (five VolumeAudioHandler sends of exactly 0 = inert/one-shot primes). The
volume arrives through the authored control chain (AudioControlMultiplier
inputs ctl 100+; one 0 input pins the product). Chain scales identified on
this entity: LocalVelocity (live), LocalAcceleration (live), Myomers.
SpeedEffect (=1.0 healthy; one authored scale maps [0,1]->[1,0] INVERTED),
UnstablePercentage (INERT PAD -- always 0!), HeatSink.CurrentTemperature.
PRIME SUSPECT: an UnstablePercentage-fed multiplier input primes 0 once and
never updates (the pad never changes), pinning footstep volume at 0.
- SF2 numbering fact recorded: 38 presets in AUDIO1 / 5 in AUDIO2 have
wPreset != file index (gap at preset 77); my table keys by wPreset. The
184x ProgramButton01 (bank1 patch83) storm at ~7/s needs an identity check
against index-numbering (it may be the wrong sample for that patch id).
Diagnostics added (BT_AUDIO_SPATIAL/BT_ATTRBIND_LOG): [trigcfg]/[matchcfg]
ctor dumps, [matchfire] with component ptr+class, [volset] VolumeAudioHandler,
[mult0] multiplier zero-products, scale sends with authored boundaries,
[fswatch] dedicated footstep watcher tracer (g_btFootStepAddr), SetupPatch
ENTRY with bank/patch/state, Simulation::DebugAudioWatcherCount.
NEXT: back UnstablePercentage with a real (live) member -- it is the mech's
stability 0..1 (the stabilityAlarm/gyro family) -- or confirm via a one-run
chain dump which multiplier input pins the FS source; then the footstep
transient should clear the 0.3 drop gate at walking speed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>