Commit Graph
4 Commits
Author SHA1 Message Date
arcattackandClaude Opus 4.8 99757a947d Audio: footstep chain traced to the END -- gait VINDICATED; audio clock 18x unit mismatch found (task #50)
MAJOR RESULT -- THE GAIT IS CORRECT, the enum was mislabeled:
LoadLocomotionClips (binary-verified slot map) proves namedClip==&animationClips[5]:
clips 6/7 = wwr/wwl (WALK cycle), 12/13 = rrr/rrl (RUN cycle -- what autodrive
uses at full throttle), 10/11 = wrr/wrl, 14/15 = rwr/rwl, 16-21 = reverse set.
The mech2.cpp "MechAnimationState" enum (0x3c-stride name table) does NOT match
the runtime clip ids -- it is the mislabel (12/13 are NOT StandToReverse).
The authored AudioStateTriggers on AnimationState (statecfg dump: states
1,2,5,8,9,10,11,14,15,16,17,20,21,22,23,26,27 -> Start) align EXACTLY with the
TRANSITION clips under the true map; the CYCLING strides (6/7, 12/13) have no
state triggers because the FootStep pulse attribute serves them -- our FootStep
reconstruction is the authentic design.  DO NOT renumber the gait.

Footstep chain, fully mapped (all empirtical):
pulse -> AudioMatchOf(match=1) -> Start on the FootFall DirectPatchSource ->
DROPPED at volume 0.  Volume path: an AudioControlMixer (2 inputs, never fed)
<- an AudioControlSplitter <- AudioControlSequence timeline events.  The
sequences DO fire -- but only value-0 events (the tick-0 initializers); the
later (real-volume) events never land.

NEW ROOT-CAUSE CANDIDATE [T3]: audio clock unit mismatch.  The renderer is
constructed with DefaultRendererRate=30 (calibrationRate: Seconds_To_Frames =
s*30) but AudioHead::Execute sets audioFrameCount = Now().ticks which advances
~550/s (measured via the [audioclock] probe) -- sequence event scheduling runs
~18x off the authored timing.  Fix candidate: calibrate the audio renderer to
the actual Now().ticks rate (or drive audioFrameCount at the calibrated 30/s).

Also corrected en route: FUN_004b9550/95b8 are MechWeapon ConfigureMappables/
ChooseButton (mapper EnterConfiguration +0x38), NOT Myomers::ConnectToMover;
+0x31c there is fireImpulse.  Myomers::speedEffect has NO binary writer found
beyond the ctor 1.0f (its 'mover coupling' stand-in is spurious).

Diagnostics added: [statecfg] AudioStateTrigger ctor dump, [split] splitter
forwards, [seqev] sequence timeline events, [audioclock] frame-rate probe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 00:25:18 -05:00
arcattackandClaude Opus 4.8 c4be8d3a07 Audio: footstep volume chain FULLY mapped -- blocked on gait-state id mismatch (task #50)
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>
2026-07-16 00:01:58 -05:00
arcattackandClaude Opus 4.8 1d019e8109 Audio: footstep pulse VERIFIED end-to-end to the matcher; volume chain traced (task #50)
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>
2026-07-15 23:52:06 -05:00
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
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>
2026-07-05 21:03:40 -05:00