Coverage audit of this session's ~30 commits against the docs found
gaps; fixed:
- README §Multiplayer was stale (only the old mesh flow, 'combat in
progress'): now leads with the relay + operator-console path
(internet play, join.bat/play_solo.bat, patient wait) and lists what
the mesh path has verified (4-pod, camera seat, callsigns, clock);
README controls line updated (turn/twist/pitch, pad, CONTROLS.MAP)
- decomp-reference env table: added BT_CAM_LOG, BT_SPEC_LOG (were in
code, not the hub); BT_INPUT_LOG note gains the twist/elev axis
- pod-hardware §input remap: the AXIS SIGN CONVENTION finding
(positive sim = CCW/left; bridge negates once per channel;
screenshot-forensics lesson) was only in commit cb82d8c -- now durable
- multiplayer.md: PATIENT WALK-UP + MISSION CLOCK sections (features
shipped in f9f230c/f57d25f, only incidentally referenced before)
checkctx CLEAN (20 topics, 68 glossary keys). All session features
now have topic-file coverage.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
151 lines
7.9 KiB
Markdown
151 lines
7.9 KiB
Markdown
# BattleTech 4.11 (bt411)
|
||
|
||
A standalone Windows port of **Virtual World Entertainment's arcade *BattleTech*** (Tesla
|
||
platform, release 4.10, ~1995–96), reconstructed on the shared **RP411 Windows engine**. The
|
||
game boots, renders, and runs a single-player **drive → animate → target → fire → damage →
|
||
destroy** loop across all 8 maps, with two-instance multiplayer entity replication working.
|
||
|
||
This repo is a clean, self-contained extraction of the BattleTech-specific work from the larger
|
||
reverse-engineering workspace — engine + game + content + build, with nothing from Red Planet or
|
||
the raw archive dumps. It builds and runs out of the box.
|
||
|
||
> **License:** the game content (`content/`) and the original binary are proprietary to Virtual
|
||
> World / the pod owner. This repository is **private**; do not redistribute.
|
||
|
||
## Versioning
|
||
|
||
`4.10` = the 1995 arcade release. `4.11` = this win32 reconstruction. Dev builds are
|
||
**`4.11.<build>` where `<build>` is the git commit count** — monotonic and zero-maintenance —
|
||
plus the short commit hash (`4.11.311 (980c9cd)`); a trailing `+` on the hash means the exe was
|
||
built from an uncommitted working tree. The stamp regenerates every build
|
||
(`tools/btversion.cmake` → `build/btversion.h`) and shows in the boot banner (`btl4.log` line 2)
|
||
and the window title. To identify any player's build, ask for the title bar or the top of their
|
||
`btl4.log`.
|
||
|
||
---
|
||
|
||
## Layout
|
||
|
||
```
|
||
CMakeLists.txt one build: munga_engine lib + bt410_l4 game lib + btl4.exe
|
||
engine/
|
||
MUNGA/ shared 2007 sim/render engine (149 .cpp + headers)
|
||
MUNGA_L4/ Win32/D3D9 HAL + renderer + asset loaders (44 .cpp), incl.
|
||
our BT work: bgfload / L4D3D / L4VIDEO + the image codec
|
||
shim/ minimal ATL shim (USES_CONVERSION/W2A)
|
||
lib/ OpenAL32 / libsndfile import libs + runtime DLLs
|
||
game/
|
||
reconstructed/ the reconstructed BT game logic (mech, subsystems, HUD, app; ~47 .cpp)
|
||
original/BT,BT_L4 surviving original BT source + all BT headers
|
||
fwd/ header shims forwarding <NAME.hpp> -> the engine's NAME.h
|
||
btl4main.cpp WinMain launcher / entry point
|
||
content/ runtime data: BTL4.RES, VIDEO/, GAUGE/, AUDIO/, *.EGG, BTDPL.INI
|
||
context/ progressive knowledge graph — 18 on-demand topic files (routed by CLAUDE.md)
|
||
docs/ format specs + reconstruction ledgers + PROGRESS_LOG.md (full history)
|
||
reference/
|
||
decomp/ raw Ghidra pseudocode — source-of-truth for ongoing recon
|
||
ghidra_scripts/ the headless decomp exporter
|
||
glossary.yaml term / acronym definitions
|
||
phases/ restructuring / investigation logs
|
||
tools/ btconsole.py (MP console emulator), map/resource scanners
|
||
run/ run.cmd helper
|
||
CLAUDE.md knowledge-base ROUTER — identity, protocols, quick-lookup, conventions
|
||
```
|
||
|
||
## Prerequisites
|
||
|
||
- **Visual Studio 2019 BuildTools** (MSVC v142, x86). The Community install on the original dev
|
||
box was broken, hence the explicit BuildTools instance in the configure line below; adjust to
|
||
your install.
|
||
- **CMake ≥ 3.20**.
|
||
- **Legacy DirectX SDK (June 2010)** — the engine uses `d3dx9`/`dinput`/`dxerr`, removed from the
|
||
modern Windows SDK. Default path `C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)`;
|
||
override with `-DDXSDK=<path>`. (The installer may throw a harmless **S1023** error — dismiss it;
|
||
the SDK headers/libs install before the failing redist step.)
|
||
|
||
OpenAL/libsndfile import libs + DLLs are vendored under `engine/lib/`; the DLLs are copied next to
|
||
the exe automatically at build time.
|
||
|
||
## Build (32-bit / Win32)
|
||
|
||
```
|
||
cmake -S . -B build -G "Visual Studio 16 2019" -A Win32 ^
|
||
-DCMAKE_GENERATOR_INSTANCE="C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools"
|
||
cmake --build build --config Debug
|
||
```
|
||
|
||
Must be **Win32** — the DirectX SDK link libs are `Lib/x86`. The link uses `/FORCE`: the 1995
|
||
headers define free functions/globals without `inline`/`extern`, so identical symbols appear in
|
||
many translation units (~124 `LNK2005`); `/FORCE:MULTIPLE` keeps the first. `UNRESOLVED` tolerates
|
||
a dead offline-tool factory in `mech3.cpp` that is never called at runtime. (Cleanup task: move
|
||
those definitions to single TUs + neutralize the dead factory, then drop `/FORCE`.)
|
||
|
||
## Run
|
||
|
||
```
|
||
run\run.cmd REM boots DEV.EGG (grass / day)
|
||
run\run.cmd DBASE.EGG REM any egg in content/
|
||
```
|
||
|
||
The working directory **must** be `content/` (the engine resolves `BTL4.RES`, `VIDEO\`,
|
||
`BTDPL.INI`, and eggs relative to cwd); `run.cmd` handles that. Maps available in `BTL4.RES`:
|
||
`cavern grass rav polar3 polar4 arena1 arena2 dbase` — switch via a copied egg's `map=` field.
|
||
|
||
### Useful env-var flags (default OFF unless noted)
|
||
|
||
The authentic stack (gait, collision, real controls) is **default-on**; set `=0` to fall back.
|
||
Debug/harness flags: `BT_FORCE_THROTTLE=1` (auto-walk), `BT_SPAWN_ENEMY=1` (spawn a target dummy),
|
||
`BT_FORCE_FIRE=1` (auto-fire), `BT_HEAPCHECK=1` (whole-heap validation — slow), `BT_BSL=0` (legacy
|
||
texture decode), `BT_DEV_GAUGES=1` (render the cockpit MFDs in a dev window), `BT_LOG=<file>`.
|
||
Interactive: **WASD** drive, **A/D** turn, **Q/E** torso twist, **R/F** torso pitch aim,
|
||
**Space / 1-4** fire, **X** all-stop, **V** view, **M** control mode. An Xbox-type controller
|
||
works out of the box. All bindings are user-editable in **`content/CONTROLS.MAP`** (delete it to
|
||
restore the compiled-in WASD default; `content/CONTROLS_NUMPAD.MAP` is an alternate profile). The
|
||
complete env-gate table is in `context/decomp-reference.md` §6 (routed from `CLAUDE.md`);
|
||
controls/pad details in `context/pod-hardware.md`.
|
||
|
||
## Multiplayer
|
||
|
||
**Modern path (relay + operator console).** Pods make ONE outbound connection to a relay/console,
|
||
so internet play needs no per-player port forwarding and CGNAT-safe LAN discovery just works. Run
|
||
the operator station:
|
||
|
||
```
|
||
python tools/btoperator.py # PySide6 GUI: build the mission egg (validated dropdowns),
|
||
# start the relay, watch pods arrive, assign seats, LAUNCH,
|
||
# end the timed mission, export player join.bat scripts
|
||
```
|
||
|
||
Players run one universal `join.bat` (internet, seat assigned by the relay) or `join_lan.bat`
|
||
(same LAN, auto-discovers the console) or `play_solo.bat` (offline practice) — see `players/`.
|
||
The pod waits patiently if the session isn't up yet. Full architecture, wire format, and the
|
||
D1 relay/UDP design: `context/multiplayer.md`.
|
||
|
||
**Legacy mesh (two instances, one box), still supported:**
|
||
|
||
```
|
||
instance A: btl4.exe -egg MP.EGG -net 1501 (BT_LOG=mp_a.log)
|
||
instance B: btl4.exe -net 1601 (BT_LOG=mp_b.log)
|
||
console: python tools/btconsole.py MP.EGG 127.0.0.1:1501 127.0.0.1:1601
|
||
```
|
||
|
||
`-net <port>` enables networked mode. Verified end-to-end: full entity/movement replication,
|
||
cross-pod combat + kills, per-pilot paint + callsigns, timed missions, 4-pod live sessions, and a
|
||
spectator/broadcast **camera seat** (`hostType=1 vehicle=camera`) with auto-directed coverage and
|
||
a live ranking window.
|
||
|
||
## Status & continuing the work
|
||
|
||
The engine, renderer, audio, HAL, build, locomotion, collision, damage, render fidelity, the full
|
||
cockpit **gauge / MFD system** (every config binding resolves + every widget builds), and the
|
||
projectile / missile weapon families are done. Active fronts: per-subsystem polish (the gyroscope
|
||
integrator; the `0xBD3` message manager that gates the valve / status-message control routes) and
|
||
cross-pod MP combat. `reference/decomp/` holds the raw pseudocode every reconstruction is verified
|
||
against.
|
||
|
||
**Start with `CLAUDE.md`** — it is the router into the progressive knowledge base: a quick-lookup
|
||
table pointing to the `context/*.md` topic files (loaded on demand), the evidence-tier and
|
||
convention rules, and `context/open-questions.md` for what's deferred / next. The complete
|
||
pre-restructure history is preserved verbatim in `docs/PROGRESS_LOG.md`; `docs/*.md` holds the
|
||
detailed running ledgers.
|