dfd1894fb948a002a739b6f32cd2840ce8a44fb2
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fad962bec8 |
Version stamping: 4.11.<git commit count> (<hash>[+])
4.10 = the 1995 arcade release; 4.11 = the win32 reconstruction; the
build number is the git commit count -- monotonic, zero-maintenance,
and every exe pins to exact source via the short hash ('+' = built
from an uncommitted tree). tools/btversion.cmake regenerates
build/btversion.h on every build (write-if-changed, no rebuild churn);
the stamp shows in the boot banner (btl4.log head, replacing the stale
'v4.10' line) and the window title (incl. the MP node tag).
Verified: build stamps 4.11.311 (980c9cd+), banner + title correct on
a live boot.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
980c9cd7e5 |
Input remap: CONTROLS.MAP binding engine + XInput gamepad support
The pod's controls reach the game through the RIO serial board; on a
desktop that hardware is a keyboard shim of hardcoded GetAsyncKeyState
reads. New binding engine (game/reconstructed/btinput.cpp) maps PC keys
and an XInput pad onto the authentic channels through a user-editable
file (content/CONTROLS.MAP, community-suggested grammar, corrected):
key/pad -> button <addr> real buttonGroup emissions, mirroring the
RIO convention exactly (press a+1 w/ mode
mask saved, release -a-1 w/ saved mask;
L4CTRL.cpp:2470-2520) -- aux/preset banks,
hotbox, panic, reverse thrust all reachable
key/pad -> axis Throttle rate (lever), pedals/JoystickX
deflect (turn/twist) into the existing
virtual-controls integrators (feel, gait
detent, spring-centering all unchanged)
keypad pilot|external <n> keyboardGroup key values ('0'-'F')
pckey <char> any authentic 1995 typed hotkey
action <name> port dev controls (view, all-stop, ...)
Keys claimed by a binding are SUPPRESSED from the legacy WM_CHAR/KEYUP
feed -- ends the historic double-dispatch ('w' drove AND selected pilot
0; F5's key-up value 0x74 aliased to the 't' hotkey; letter key-ups fed
the developer fake-event dispatcher). Unbound keys keep their authentic
meaning. The dual-use 'V' is split: V = view toggle, B = look behind.
Default profile = WASD classic (compiled-in twin; delete the file to
restore). CONTROLS_NUMPAD.MAP ships the corrected community layout
(keypads are NOT buttons 0x50-0x6F -- that space doesn't exist; no
clickable cockpit exists so everything needs a binding; keyboard fire
buttons added; 0x36/0x37 are hotbox not 'config'; missiles moved off
Ctrl). XInput loads dynamically (1_4 -> 9_1_0), disconnected-pad
probing rate-limited; pad sticks write the axes as absolute positions
(the spring is physical), triggers/buttons per the file.
Verified live: bindings load (43), W and NumPad8 drive (speedDemand 0 ->
61.5), X all-stop (spd -> 0), aux-bank emission (D1 -> [input] 0x2f
PRESS/release under the numpad profile), suppression both directions
(posted 'r' reaches [keych], posted 'w' swallowed), full-keyspace
WM_CHAR+WM_KEYUP fuzz x3 survived with sim advancing, XInput graceful
with no pad, 2-node relay session un-regressed (full ladder + UDP).
Pad-in-hand testing still needs a physical controller.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
0ca7d269d2 |
Audio Phase 3 (AUDIO_FIDELITY F9/F11/F12): EFX lowpass + reverb split + cockpit placement
New L4AUDEFX bridge (OpenAL Soft ALC_EXT_EFX): one EAXReverb aux slot at the authentic AUDIO.INI global_reverb_scale (0.3) + a scratch AL_FILTER_LOWPASS (params copied at attach). F9 filters (was: computed then thrown away -- everything full-bright at all distances): Dynamic3D ExecuteModel drives GAINHF from highFreqCutoffScale x brightnessScale x maxMIDIFilterCutoff, UNGATED (decomp part_008.c:7496, 7589-7604 -- every moving 3D sound dulls with distance per the AUDIO.INI knee-60/exp-2.0 model); Static3D from brightness x max (:7831-7884); Direct inside its existing gated NRPN-rate block. AWE 100-8000 Hz curve -> EFX 5 kHz-reference gainhf via a 2-pole approximation [T3 curve, endpoints exact]. F11 reverb (was: bone-dry everywhere): 3D patch sources attach an aux send at Start, exactly where the original sent CC91 = global_reverb_scale (part_008.c:7278-7394); Direct cockpit sources keep CC91=0 -- dry. The wet-exterior vs dry-cockpit contrast is back. F12 placement (was: every cockpit sound dead-center): DirectPatchSource Start places sources by the authored 6-value position enum (front/rear card + pan CC10, decomp @00463848/@004638a8) as listener-relative directions, composed with the zone L/C/R pan. New PatchResource GetBankID/GetPatchID pass-throughs (the LOD accessor is protected). Regression (35s drive+fire): EFX READY, stable, deliveries unregressed, no AL errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5b46655b82 |
Audio: ENABLE sound -- real OpenAL + in-tree WAV loader; both backend DLLs were no-op STUBS (task #50)
Root cause of "no sound, ever": the two audio backend DLLs shipped in the repo are fakes. libsndfile-1.dll exports 15 funcs BY ORDINAL ONLY (no names) and sf_open() always returns NULL; OpenAL32.dll (72KB) imports only KERNEL32 -- no dsound/wasapi/winmm -- so it is a pure no-op that returns fake handles (ctx=0x00000001, alGenSources->0) and never touches the hardware. The whole render->device->buffer->source->play chain ran clean and silent. Fixes: - OpenAL32.dll: replace the stub with the real OpenAL Soft 1.25.2 Win32 build (imports AVRT/ole32/WINMM, real WASAPI backend). The exe imports the 25 AL funcs by NAME so it is a drop-in; alGenSources now yields a live source and alSourcePlay reaches AL_PLAYING. - libsndfile: DROPPED entirely. It is replaced by LoadWavPCM() in L4AUDRES -- a tiny RIFF/WAVE fmt+data reader that loads our soundbank WAVs (16-bit PCM) straight into the AL buffer. Removed the .lib/.dll from the link + copy and git-rm'd the stub. (This also kills the "ordinal 50 could not be located in libsndfile-1.dll" load-failure popup: adding an sf_strerror import bound to an ordinal the 2..16-only stub could not satisfy.) - Soundbank: 241 samples cracked from AUDIO1/2.RES (SF2 v1.0) by tools/sf2extract.py into content/AUDIO/*.wav + the allPresets[2][128] table (audiopresets.cpp), replacing the zero-init btstubs stub. All 241 now load (alErr=0). BT_AUDIO_TEST plays buffer0 as proof-of-life; BT_AUDIO_LOG traces the chain. Remaining: in-game triggering (AudioEntities on fire/step/engine/explosion) so PlayNote fires during play -- next audio wave. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a3b735d5da |
MP: replicant motion chop ROOT-CAUSED + FIXED -- stale peer-mirror spammed re-base
records; also the 2007 call-counter clock stub + two crash fixes
User-reported: peer mechs turn/move choppy ("missing frames"). Measured per-frame
(BT_REPL_HDG): 13% of frames the replicant's heading STALLED, 11% it JUMPED 2-6x.
THREE layered defects found:
1) THE CLOCK STUB (engine substrate): TIMESTUB.cpp's GetRTC/GetHiRes were 2007
`return time++` call-counters -- the "clock" advanced per CALL, not per ms --
and TIMESTUB won the /FORCE duplicate-symbol race over the REAL QPC clock in
L4TIME.cpp (LNK4006). Every Now()-domain consumer (dead-reckon above all) ran
on call-count pseudo-time. Removed TIMESTUB from the build; L4TIME covers every
symbol. [The real clock alone did NOT cure the chop -- but it was objectively
broken and un-gated the two latent bugs below.]
2) TWO CRASH FIXES the real clock exposed:
- legAnimationState@0x3b0 never ctor-initialized (the task-#56 0xCDCDCDCD
family): the type-3 writer re-dispatches SetBodyAnimation(legAnimationState)
on the WRITER; a record emitted before the leg SM's first tick passed raw
0xCDCDCDCD as a clip index -> AV (cdb-pinned, mech2.cpp:233). Init 0.
- Replicants were SERIALIZING update records: the tail WriteSimulationUpdate ran
for every instance, and the port's replicant leg-SM accommodation (task #50)
calls ForceUpdate -> replicants emitted derived/uninitialized state into the
stream. Master-gated; replicant marks discarded (master-authoritative).
3) THE CHOP ITSELF: the master's resync send-gate compares localOrigin vs
projectedOrigin -- the PEER-ESTIMATE mirror -- but the port master never
maintained projectedOrigin (the bring-up drive replaced Mover::Perform; the
engine only updates the projection inside replicant-only DeadReckon). Stale
mirror -> |local-projected| > deadband EVERY frame -> a type-4 re-base record
EVERY frame -> the replicant hard-copied the master's deadband-quantized
heading each frame (the engine lerp never engaged; nextUpdate always behind
till) -> stall/snap beat = the chop. FIX: advance the mirror each frame by the
last-SENT angular velocity (what the peer is extrapolating) and re-base it in
the type-4 writer. Records now flow only on TRUE drift (~1 per 5 frames in a
steady spin), the replicant extrapolates smoothly between them, and the lerp
horizon finally engages. Measured: STALLS 13%->1%, JUMPS 11%->1% (residue: tiny
sub-degree backward corrections on record arrival -- inherent dead-reckon
overshoot the lerp absorbs).
Diag probes: BT_REPL_HDG (per-frame replicant heading + dead-reckon internals),
BT_REPL_TRN (replicant turn/leg state). scratchpad/clockcrash_bp.txt (cdb).
Co-Authored-By: Claude Fable 5 <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>
|