option(BT412 ... ON) gates the steamification layer for the merge-back into BT411, so the unified repo serves both fronts: - Default (BT412=ON): pod/dev game + PadRIO / plasma / front end / lobby -- all runtime-gated, so a -egg/-net launch still behaves as 4.11. - Pod-minimal (-DBT412=OFF, build-pod/): compiles OUT L4PADRIO, L4PADBINDINGS, L4KEYLIGHT, L4PLASMASCREEN, L4STEAMTRANSPORT, btl4fe, btl4console, btl4lobby. Seam sites carry #ifdef BT412: L4CTRL.cpp PAD token (log + ignore), L4GREND.cpp L4PLASMA=SCREEN (log + ignore), L4VB16.cpp (inert PadRIO stub -- call sites identical in both flavors), btl4main.cpp (front-end/marshal/lobby blocks out; zero-arg launch = 4.11 behavior). - The NetTransport seam ALWAYS compiles -- it is the wire for both flavors (WinsockNetTransport, verified byte-identical to the pre-seam arcade path). - BT412_STEAM now requires BT412 (configure-time FATAL_ERROR; negative-tested). Verified: OFF -- clean v143 link, solo DEV.EGG mission runs (31 subsystems tick, gait, targeting). ON -- zero-arg launch engages the front-end menu. STEAM -- links clean, ships steam_api.dll. Also: README/context docs for the flavors + the merge-back; corrected the stale Phase 3b DEFERRED note (the single-window cockpit landed 07-16) and the README's leftover 0xBD3 valve-gate claim (it is a damage/explosion hub). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
142 lines
8.4 KiB
Markdown
142 lines
8.4 KiB
Markdown
# BattleTech 4.12 (bt412) — the Steamification
|
||
|
||
**BattleTech** is VWE's arcade mech-combat game (Tesla platform, release 4.10, ~1995–96),
|
||
originally played from inside Virtual World cockpit pods. This repo is the consumer line of
|
||
that reconstruction:
|
||
|
||
| Generation | What it was |
|
||
|------------|-------------|
|
||
| **BattleTech 4.10** | The original pod game — DOS-era MUNGA engine, serial RIO cockpit I/O, 7-monitor cockpit, operator console |
|
||
| **BattleTech 4.11** | The **Win32 port** — the BT game logic reconstructed from `BTL4OPT.EXE` on the shared RP411 Windows engine; DirectX 9, full single-player combat loop, two-instance LAN multiplayer |
|
||
| **BattleTech 4.12** | **The Steamification of 4.11** — the same engine, missions, and wire protocol, made distributable on Steam and playable over the internet with no pod hardware |
|
||
|
||
**One tree, both lines (2026-07-17):** the 4.12 steamification was merged back into BT411, so the
|
||
same repo builds the **pod game** and the **consumer/Steam game**. The steamification layer
|
||
(PadRIO virtual cockpit, desktop plasma, in-game front end, Steam lobby/transport) sits behind the
|
||
**`BT412` compile gate** (CMake option, default ON) — see *Build flavors* below. Everything under
|
||
the gate is also runtime-inert without its env/arg triggers, so a default build still behaves as a
|
||
pod/dev 4.11 binary when launched the pod way (`-egg` / `-net`).
|
||
|
||
The plan and workstreams live in [docs/BT412-ROADMAP.md](docs/BT412-ROADMAP.md). The sister
|
||
project **RP412** (Red Planet's steamification, shipped end-to-end: lobby → Steam-sockets mesh →
|
||
marshaled race → results on every machine) is the proven recipe this repo follows — each pod-era
|
||
dependency replaced by a consumer equivalent behind the engine's existing seams.
|
||
|
||
> **License:** the game content (`content/`) and the original binary are proprietary to Virtual
|
||
> World / the pod owner. This repository is **private**; do not redistribute.
|
||
|
||
---
|
||
|
||
## 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 2022 BuildTools** (MSVC v143, x86) — the BT412 toolchain of record (moved from
|
||
the 2019/v142 line at the 4.12 fork; v142 still builds if you swap the generator back). The
|
||
explicit BuildTools instance in the configure line below matches the dev box; 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 17 2022" -A Win32 ^
|
||
-DCMAKE_GENERATOR_INSTANCE="C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools"
|
||
cmake --build build --config Debug
|
||
```
|
||
|
||
### Build flavors (the `BT412` compile gate)
|
||
|
||
| Flavor | Configure | What you get |
|
||
|--------|-----------|--------------|
|
||
| **Default** (`BT412=ON`) | as above | Pod/dev game **plus** the steamification layer: PadRIO (`L4CONTROLS=PAD`), desktop plasma (`L4PLASMA=SCREEN`), single-window cockpit (`L4MFDSPLIT=1`), zero-arg front end + LocalConsole marshal. All runtime-gated — a `-egg`/`-net` launch behaves as 4.11. |
|
||
| **Pod-minimal** (`-DBT412=OFF`, dir `build-pod`) | `... -B build-pod -DBT412=OFF` | The 4.11 pod image: PadRIO/plasma/KeyLight/front end/lobby/Steam transport are **compiled out**. The NetTransport seam stays (it is the wire for both flavors; `WinsockNetTransport` is byte-identical to the pre-seam arcade behavior). Gated env/args are ignored with a log line. |
|
||
| **Steam** (`-DBT412_STEAM=ON`, dir `build-steam`) | `... -B build-steam -DBT412_STEAM=ON` | Default flavor + the `ISteamNetworkingSockets` transport and lobby (vendored SDK at `extern/steamworks_sdk_164`); ships `steam_api.dll`. Requires `BT412=ON` (enforced at configure). Packaged by `pack-dist.ps1`. |
|
||
|
||
Must be **Win32** — the DirectX SDK link libs are `Lib/x86`. The link uses `/FORCE:MULTIPLE`: the
|
||
1995 headers define free functions/globals without `inline`/`extern`, so identical symbols appear
|
||
in many translation units (~124 `LNK2005`); `MULTIPLE` keeps the first. `UNRESOLVED` is gone as of
|
||
4.12 — the v143 linker refuses to emit an image with unresolved externals even under `/FORCE`, so
|
||
the dead offline-tool factory in `mech3.cpp` is neutralized behind `BT412_OFFLINE_TOOLS` (default
|
||
off) and a genuinely unresolved symbol is now a hard link error instead of a hidden runtime AV.
|
||
(Remaining cleanup task: move the multiply-defined globals to single TUs, then drop `/FORCE`
|
||
entirely.)
|
||
|
||
## 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, **Space/Ctrl** fire, **X** all-stop. The complete env-gate table is in
|
||
`context/decomp-reference.md` §6 (routed from `CLAUDE.md`).
|
||
|
||
## Multiplayer (two instances, one box)
|
||
|
||
```
|
||
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; the console emulator delivers the mission egg and the launch
|
||
command. Entity + movement replication works; cross-pod combat is in progress.
|
||
|
||
## 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: the steamification (roadmap phases —
|
||
live multi-machine Steam test + packaging/release remain), per-subsystem polish, 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.
|