5a425320b760a7970204084c46d9f830120b8f3c
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1671b7d4b2 |
the REVERSE DISABLED voice (#78): SimulationState 3/4 IS the trigger -- mirror the gimp level into the engine cell
User + old-timers were right; the earlier "no voice exists" verdict was wrong. The authored mech audio has state watchers on Entity.SimulationState==3/4 (the binary's one-cell mech+0x40) that start sequence notes 29,16,40 -- two klaxon hits then Warnings01 zone 8 (key 40-41) = the "reverse disabled" voice line the testers remember. The port's cell split (graphicAlarm vs engine simulationState, gotcha #23) meant the trigger value never arrived. - mechdmg: mirror gimp 3/4 into SetSimulationState at the leg-half crossing (guarded: never stomps disabled/fall/dead states). Voice verified playing end-to-end on the bench: SetupPatch bank2 patch113 note=40 -> Warnings01_z7.wav. - mech.cpp: BT_GIMP_SAFE_BASE_READ on all seven Simulation::ReadUpdateRecord sites -- gimp is monotonic per life; a record captured pre-gimp must not stomp the cell (the loopback otherwise perpetuates the stale value and restarts the warning on every damage event). - diagnostics (all env-gated): [statefire]/[startreq]/[animind]/[gimp-sim]/ [simstomp]/[indstomp] + StateIndicator::DebugAudioWatcherCount + raised spatial-log caps. These traced the whole chain and PROVED no SetState path stomps the cell. OPEN (follow-up): a RAW writer (bypasses SetState entirely; invisible to the indicator-level trap) resets the cell between damage events -- under the bench's 1 Hz metronome harness it restarted the sequence before the 1.8 s voice note; sporadic real-play damage is unaffected (one edge -> full sequence). Needs a cdb write-watchpoint session; candidates: a recon raw +0x2c-equivalent write or a struct copy spanning it. Also decoded en route: the AnimationState triggers on the limp states play EngineShiftRev01 (the downshift foley) -- working, and NOT the voice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a11a697824 |
Audio: footsteps arrive on the FIRST stride -- the 10-20 s warm-up bug
User report: footfalls silent for the first 10-20 s of every mission (all
mechs), then solid. Root cause was three interlocking layers, each measured
with timestamped traces:
1. The authored footstep volume chain (LocalAcceleration [0,10]->ctl100 +
LocalVelocity [0,0.6]->ctl101 through authored N=30/N=15
AudioControlSmoothers, fill 0) hangs off the SOURCE's watcher chain
(scale watches smoother watches mixer watches source), and an idle
source's chain executes only at Start attempts -- one smoother sample
per stride.
2. Each hop is frame-gated (AudioComponent::ExecuteWatchers,
DefaultAudioFrameDelay), so any burst collapses to one execution.
3. The transient drop gate (vol < 0.3, AUDREND) rejected every Start while
the smoother average crawled up 1/30th per attempt -> ~25 dropped strides
before the first audible step, then per-frame execution while playing
kept it warm forever ("solid after that").
Fixes (engine-level, each documented in place):
- AudioScaleOf<T>::Execute now sends EVERY poll (scales are continuous
value-feeders; the base bitwise change-gate -- Motion::operator== is
memcmp -- froze on our deterministic gait math, where the original's
noisy physics floats never bit-repeated. Triggers/matchers keep the
change gate: their semantics are edge-based).
- Component/AudioComponent::PrimeWatchers(passes): recursive, GATE-FREE
watcher pump; AUDREND runs 30 passes on every transient Start request so
the authored smoothers evaluate at their true steady state before the
drop gate reads the volume.
- localAcceleration derives via the binary's exact structure: 15-sample
ring buffers of the raw position derivative + dt (ctor part_012.c:9836,
derive :15169-15195), in the PerformAndWatch tail so it runs every frame.
- AttributeWatcherOf::GrabCurrentValue private -> protected (the scale
override calls it).
Verified (30 s walk from cold start): drops 25 -> 3 (the survivors are
authentic quiet-stride gating: first gentle strides at vol ~0.28 vs the 0.3
gate), footfalls deliver from the first stride, 43 delivered with live
per-stride gain variation. Diag traces added: [accwatch]/[fsscale]/
[smooth]/[smoothcfg]/[motionscalecfg] + timestamps on DROP/volset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
90f99fe4b5 |
Audio: FOOTSTEPS WORK -- reconstruct the lost game-side step-intensity broadcast (task #50)
The final link: the footstep source's volume + brightness mix from two AudioControlMixer inputs (ctl 100 walk / 101 run) behind an entity-registered AudioControlSplitter. The object stream only ZERO-initializes those inputs (AudioControlSend one-shot initializers; mixer ctor inits 0.0) -- the runtime feed was BT game code (lost with the source), using the engine's game-facing Entity::AudioSocketIterator broadcast (the only path to those anonymous components; the splitter registers via entity->AddAudioComponent). Reconstruction [T3]: on each foot plant (the SetBodyAnimation locomotion-clip pulse), broadcast the step intensity (live ground speed on the authored 0..40 -> 0..1 velocity-curve family, floored at 0.35 to clear the 0.3 transient-drop gate) on the gait-appropriate input (run-family clips 0x0a..0x0f -> 101, walk family -> 100; the other input zeroed so gait changes don't stack). Patch-source components (VDATA 1001/1002/1005) are skipped -- AudioSource::ReceiveControl Fail()s on input-range ids. VERIFIED: FootFallInt01.wav (bank2 patch39) delivers + plays per stride; mixer sums nonzero (vol=1 at run speed); 30s drive+fire regression clean -- weapon charge/fire/sustain cycles, ready dings, buttons, engine loops, state audio (0 skips), gait advancing normally, no crashes, no stuck loops. Also this session: [seqcfg] sequence config dump (decoded the authored event streams: ctl 8=note/6=attack-vol/1=start/2=stop patterns), BT_AUDIO_NODROP diagnostic (force low-volume transient delivery at a 0.7 floor). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
744ef8cc16 |
Audio: restore the dropped ExecuteWatchers poll -- polled audio watchers were ALL dead (task #50)
User: "when I start moving all the sounds fade away, no footsteps." Diagnosis chain (all empirical, BT_AUDIO_SPATIAL/BT_ATTRBIND_LOG traces): - The audio head DOES track the mech (listener-relative positioning verified while driving) -- not a spatial bug. - The idle sounds correctly STOP on leaving the standing state; the MOVING sounds never started because every POLLED audio watcher was dead: the reconstructed Mech::PerformAndWatch replaced the engine performance but dropped the ExecuteWatchers() step from the engine tail (Simulation:: PerformAndWatch = Perform -> ExecuteWatchers -> WriteSimulationUpdate). Only PUSHED StateIndicator watchers (SetState->Execute) ever fired -- which is exactly why state sounds worked but footsteps/motion-scaled audio didn't. FIX: poll ExecuteWatchers() (AreWatchersDelayed-gated) before the update write. Immediately unlocks the polled family: MissileLoaded01/LaserLoaded01 ready dings, ProgramButton01, motion scales (PlayNote 15 -> 30 per run). - FootStep (0x1e) backed REAL: was the inert attrPad (an AudioLogicalTrigger polls it -- threshold-crossing pulse per foot plant). New footStep member, pulsed by SetBodyAnimation on entering any locomotion clip 1..0x17 (runtime stride alternation MEASURED as body states 12<->13 -- the enum-name numbering does not match runtime clip ids), decayed by IntegrateMotion (~1/3 s). - Footstep volume is speed-scaled (AudioMotionScale on LocalVelocity): at standstill the transient start computes volume 0 and the renderer drops it (LowAudioVolumeThreshold) -- so footfalls are audible at real walking speed. Diagnostics kept (BT_AUDIO_SPATIAL): spatial dist/vol per source, CLIPPED/DROP/ START at the request gate, vol=0 factor breakdown, scale->0 sends, trigger notifications, watcher poll-rate probe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
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>
|