diff --git a/CLAUDE.md b/CLAUDE.md index b6d2585..700a488 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,14 +5,18 @@ > detail is preserved verbatim in **`docs/PROGRESS_LOG.md`** (the old monolithic CLAUDE.md) — the > ultimate fallback if a topic digest is thin. Migration history: `phases/phase-01-context-restructure.md`. -**Project:** Port VWE's 1995 arcade **BattleTech** (BT) pod game (MUNGA engine, Tesla platform -4.10) to modern Windows + the pod hardware, by reconstructing the missing BT game logic from the -`BTL4OPT.EXE` binary on top of the working WinTesla engine. +**Project:** **BT412 — the Steamification of the BattleTech pod port.** The upstream work +(BT411) ports VWE's 1995 arcade **BattleTech** (BT) pod game (MUNGA engine, Tesla platform 4.10) +to modern Windows by reconstructing the missing BT game logic from the `BTL4OPT.EXE` binary on +top of the working WinTesla engine. This repo carries that forward to a consumer Steam title: +virtual cockpit controls (no pod hardware), single-window cockpit, in-game session front end +replacing the operator console, Steam internet multiplayer, distributable packaging. **Repo of record:** the top-level `CMakeLists.txt` + `README.md` build `btl4.exe`. Layout: -`engine/ game/ content/ docs/ reference/ tools/ context/`. -**Current front:** `btl4.exe` runs a full single-player loop; the gauge system is complete; the -active work is reconstructing each subsystem's authentic behavior from the binary. Details + -what's-next: `context/project-overview.md`, `context/open-questions.md`, recent git log. +`engine/ game/ content/ docs/ reference/ tools/ context/`. Remote: `origin` = +`VWE/BT412.git` ONLY — this repo must never touch the BT411 remote (no cross-pull remote). +**Current front:** the steamification — plan and phase order in `docs/BT412-ROADMAP.md`, running +status in `context/steamification.md`. Subsystem-fidelity reconstruction continues alongside. +Details + what's-next: `context/project-overview.md`, `context/open-questions.md`, recent git log. --- @@ -57,6 +61,7 @@ precise than anything you can infer. | User asks about... | Read this file | |---|---| | What the project is, engine, platform, goal | `context/project-overview.md` | +| The Steamification (BT412): plan, phases, PadRIO, Steam net, front end | `context/steamification.md` + `docs/BT412-ROADMAP.md` | | Missing BT source, decompilation strategy | `context/source-completeness.md` | | The WinTesla Windows port (renderer/audio/HAL) | `context/wintesla-port.md` | | Build / run / debug / repo layout / env gates | `context/build-and-run.md` + `context/decomp-reference.md` §6 | diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c6dfee..ab7277e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,11 @@ cmake_minimum_required(VERSION 3.20) -project(bt411 CXX) +project(bt412 CXX) set(CMAKE_CXX_STANDARD 14) -# BattleTech 4.11 -- Virtual World Entertainment pod BattleTech (Tesla rel 4.10) -# reconstructed on the shared RP411 Windows engine. Build 32-bit (Win32) with -# the VS2019 BuildTools instance -- see README.md for the exact configure line. +# BattleTech 4.12 -- the Steamification of the BT411 pod port (Virtual World +# Entertainment pod BattleTech, Tesla rel 4.10, reconstructed on the shared +# RP411 Windows engine). Build 32-bit (Win32) -- see README.md for the exact +# configure line, docs/BT412-ROADMAP.md for the plan. # Run from the content dir: cd content && ../build/Debug/btl4.exe -egg DEV.EGG # --- external dependency: legacy DirectX SDK (June 2010); override with -DDXSDK=... --- diff --git a/README.md b/README.md index b6fc055..11c33d8 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ -# BattleTech 4.11 (bt411) +# BattleTech 4.12 (bt412) — the Steamification -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. +**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: -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. +| 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** | **This repo: 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 | + +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. diff --git a/context/steamification.md b/context/steamification.md new file mode 100644 index 0000000..6dec628 --- /dev/null +++ b/context/steamification.md @@ -0,0 +1,83 @@ +--- +id: steamification +title: "BT412 Steamification — status, seams, and merge notes" +status: living +source_sections: "docs/BT412-ROADMAP.md; RP412 repo (C:\\vwe\\RP412) git history + docs" +related_topics: [pod-hardware, multiplayer, gauges-hud, build-and-run, wintesla-port] +key_terms: [egg, RIO, console] +open_questions: + - "BT cockpit button-bank geometry source (no vRIO CockpitLayout exists for BT): l4gauge.cfg / pod photos / Nick" + - "Does BT's rebuilt L4D3D still have RP's NULL-texture AddRef crash pattern?" + - "Does L4CONTROLS=PAD set primaryControlType=PrimaryRIO so MechRIOMapper engages unchanged?" +--- +# BT412 Steamification — status, seams, and merge notes + +BT412 = BT411 made distributable on Steam and playable over the internet with no pod +hardware, following the recipe RP412 proved end-to-end (RP411 → RP412). The full plan +and phase order: `docs/BT412-ROADMAP.md`. RP412 (`C:\vwe\RP412`) is the reference +implementation — its git history from commit `467934c` onward is the steamification, +grouped roughly: toolchain → PadRIO input → MFD-split cockpit → front end/LocalConsole +→ NetTransport/Steam sockets → lobby → bindings/KeyLight → packaging. + +**Repo rule [T0]:** `origin` = `VWE/BT412.git` only. This repo must never touch the +BT411 remote (no cross-pull remote — deliberate difference from RP412's `rp411` +pattern). Forked at BT411 `4e72f0c` (2026-07-14). + +## Status ledger + +- **Phase 0 bootstrap — DONE 2026-07-14.** Tree copied (working tree + full history, + `build/` excluded), origin re-pointed, fast-forwarded to `4e72f0c`, dev-state + `run/run.cmd` working-tree edit discarded (committed version is the documented solo + launcher), identity pass (README/CLAUDE.md/CMake `project(bt412)`), this topic + + roadmap authored. +- Phase 1 (VS2022 v143): not started. +- Phases 2–7: not started — see the roadmap. + +## The seams (what plugs in where) [T0 unless noted] + +- **Input**: `LBE4ControlsManager` PUSH model; `L4CTRL.cpp` parses `L4CONTROLS` tokens; + RP412 adds token `PAD` → `new PadRIO()` (a `RIOBase` implementation from + XInput+keyboard), and the stock RIO mapper runs against it unchanged. BT's mapper + selection: `btl4app.cpp MakeViewpointEntity` switch on + `controls->primaryControlType` (+0xc98) → `MechRIOMapper` for PrimaryRIO(4). +- **Plasma**: BT's plasma is identical hardware to RP's (128×32, `L4PLASMA.h`); + RP412's `PlasmaScreen` renders the same `Video8BitBuffered` surface into a desktop + window, selected in `L4GREND.cpp` on `L4PLASMA=SCREEN`. +- **Displays**: BT pod = main 800×600 3D view + 640×480 radar + five mono MFDs on one + spanned 1280×480 surface (+ plasma). All cockpit surfaces are bit-plane masks over + one shared `SVGA16` pixelBuffer (see [[gauges-hud]], [[pod-hardware]]). RP412's + `MFDSplitView` (`L4MFDVIEW.*` + `L4VB16.cpp` split mode, `L4MFDSPLIT=1`) composes + child panes on a fixed 1920×1080 canvas; 3D presents into the viewscreen pane via + `Present(hDestWindowOverride)`. +- **Networking**: arcade stack unchanged (see [[multiplayer]]); RP412 moved the wire + behind `NetTransport` (`L4NETTRANSPORT.*`), default `WinsockNetTransport`, Steam + implementation `L4STEAMTRANSPORT.*` (`ISteamNetworkingSockets`, FakeIP + SDR, + degrade-to-TCP on any failure). Addresses stay SOCKADDR_IN-shaped so the egg + `[pilots] ip[:port]` roster works over both wires. +- **Session**: console protocol (egg msgID 3, 1040-byte chunks + ACK; RunMission + msgID 5 ×2; console must stay connected) — `tools/btconsole.py` is the working + feeder and the spec for the in-process LocalConsole marshal (Phase 5). + +## Known merge risks (from the 3-way BT411 / RP411-baseline / RP412 comparison) + +- **`L4VB16.cpp` — HIGH.** RP412 rebuilt ~3846–4046 (splitViews/canvas/present); BT + rebuilt the same window-management region for dev-gauge docking (`BT_DEV_GAUGES`, + `BT_DEV_GAUGES_WINDOW`, `BT_DEV_GAUGES_DOCK`, `BT_GAUGE_SCALE`, `BT_GAUGE_SEC_ROT`, + `BT_ALL` — 15 sites). Hand-merge; write the 3-way diff notes HERE before editing. +- **`L4NET.CPP` — MEDIUM.** RP412 rerouted all ~22–26 Winsock call sites through + `NetTransport_Get()`; BT's 5 `BT_NET_TRACE` diagnostic blocks sit exactly on those + send/receive sites and must be re-sited onto the seam calls. +- **`L4RIO.*`, `L4CTRL.cpp`, `L4GREND.cpp` — LOW.** BT never customized these + (verified: zero BT_ hits); take RP412's versions after the 3-way check. +- **CMake**: engine sources are explicit per-file lines (no globs) — every ported + `.cpp` needs its own `add_library` line or it silently doesn't compile. New deps: + `xinput9_1_0.lib` (PadRIO), C++/WinRT (KeyLight, per-file C++17), Steamworks SDK + + `steam_api.lib` behind `option(BT412_STEAM)`. +- **No `/Zp1` in BT's build** (RP's engine builds `/Zp1`): RP412's packing-mismatch + workarounds (`WINDOWS_IGNORE_PACKING_MISMATCH`, KeyLight default-packing carve-out, + `pack(push,8)` around Steam headers) are no-ops here — keep them for verbatim-ness, + but eyeball any copied code for /Zp1-layout assumptions. + +## Key Relationships +- Uses: [[pod-hardware]] · [[multiplayer]] · [[gauges-hud]] · [[build-and-run]] +- Feeds: [[open-questions]] (steamification investigate items) diff --git a/docs/BT412-ROADMAP.md b/docs/BT412-ROADMAP.md new file mode 100644 index 0000000..a64f70c --- /dev/null +++ b/docs/BT412-ROADMAP.md @@ -0,0 +1,178 @@ +# BT 4.12 Roadmap — Steam + Internet Multiplayer + +Working plan for turning the 4.11 pod port into a consumer Steam title, following the +recipe proven end-to-end by **RP412** (Red Planet 4.11 → 4.12; see +`C:\vwe\RP412\docs\RP412-ROADMAP.md` and its git history — the reference implementation +for every workstream here). Status: plan authored 2026-07-14. Items marked +**[investigate]** need archaeology before they become concrete tasks. + +## Where 4.11 stands + +- **Game**: `btl4.exe`, 32-bit Win32, DirectX 9, CMake + VS2019 BuildTools (v142), + DXSDK June 2010, `/FORCE:MULTIPLE`. Full single-player combat loop + (drive → animate → target → fire → damage → destroy → respawn) on all 8 maps. +- **Engine**: the same WinTesla MUNGA/MUNGA_L4 engine as Red Planet — the MUNGA core is + file-identical to RP's; BT's L4 layer adds bgfload/image + BT render work + (L4D3D/L4VIDEO) and dev-gauge docking in L4VB16. +- **Networking**: same arcade stack — `MUNGA/NETWORK|HOSTMGR|INTEREST`, WinSock2 TCP in + `MUNGA_L4/L4NET.CPP`. Two-instance loopback MP verified including cross-pod combat, + kills, respawn, gait, and weapon visuals. Console feeder: `tools/btconsole.py` + (egg msgID 3 in 1040-byte chunks, RunMission msgID 5 ×2, must stay connected). +- **Input/output**: pod hardware is a serial **RIO** board (stick X/Y, throttle, pedals, + fire/config buttons 0x40/0x45/0x46/0x47 + MFD aux buttons) — `L4RIO`/`L4SERIAL`. Dev + box uses keyboard debug controls (WASD etc.). Displays: **7 monitors** (main 800×600 + 3D view, radar 640×480, five mono MFDs as one spanned 1280×480 surface) + the + **128×32 plasma** (identical hardware to RP's; `L4PLASMA`). `BT_DEV_GAUGES` docks the + gauge strip into the main window (dev mode). +- **Session control**: missions are **egg** files (NotationFile); the operator console + configures and launches over TCP 1501. No in-game menu; no mission-end flow (mission + review msgID 0x18 is a stub, `scoreAward=0`); live kill/death tally exists on the + Comm MFD `pilotList`. + +## Defaults (decided at planning, change only deliberately) + +- Gates mirror RP412 with a BT412 prefix: `BT412_STEAM`, `BT412KEYLIGHT`, env + `BT412STEAM=1`. Exe stays `btl4.exe`; CMake project is `bt412`. +- AppID: Spacewar **480** via hand-created `steam_appid.txt` (gitignored, never packed) + until a real AppID exists. +- Mech catalog: base 8 (`avatar bhk1 loki madcat owens sunder thor vulture`) + variants + (`ava1 lok1 lok2 mad1 mad2 own1 snd1 thr1 vul1 blkhawk`); trim any that fail to load. +- Results v1: read the live Comm-MFD `pilotList` tally (kills + observed deaths) at + stop; EndMission wire scores when remote-pod marshaling needs them. +- `L4VB16.cpp` end-state: `MFDSplitView` is the successor to the dev-gauge dock; keep + `BT_DEV_GAUGES` gated until parity, then retire. +- **This repo never touches the BT411 remote.** `origin` = `VWE/BT412.git` only. + +## Phase 1 — Toolchain: VS2022 (v143) + +RP412's step 1: unblocks everything, no design risk. + +- Configure `-G "Visual Studio 17 2022" -A Win32` (drop the 2019 + `CMAKE_GENERATOR_INSTANCE`). **Stay Win32** — DXSDK June 2010 x86 libs are the hard + constraint. BT's CMake has no `/Zp1`, so RP's packing-mismatch defines don't apply. +- Apply RP412 BUILD.md §3 source fixes as v143 errors demand: `MUNGA/TIME.h` Time + copy-ctor; `MUNGA/NETWORK.h` inline `operator==`; `L4DINPUT.cpp` DIEnum callback + renames; `CAMMGR.cpp` `std::ios::in`; `legacy_stdio_definitions.lib` for dxerr. +- [investigate] RP412's `L4D3D.cpp` NULL-texture AddRef guard — BT's L4D3D is heavily + rebuilt; port the guard if the crash pattern survives. +- **Verify**: v143 build boots DEV.EGG; two-instance loopback + btconsole.py — drive, + fire, cross-pod kill, respawn. + +## Phase 2 — Input layer: RIOBase / PadRIO (Workstream A.1) + +Rule for every touched engine file: 3-way check (BT copy vs RP411 baseline vs RP412); +identical-to-baseline → take RP412's file verbatim, diverged → hand-apply the diff. + +- Port `L4RIO.h/.cpp` (RIOBase split), new `L4PADRIO.*`, `L4PADBINDINGS.*`; the + `L4CTRL.cpp` hook (`new PadRIO()` for token `PAD`). BT never customized these — + expected clean. +- CMake: explicit source lines (no globs); link `xinput9_1_0.lib`. +- Confirm `L4CONTROLS=PAD` yields `primaryControlType=PrimaryRIO` so the stock + `MechRIOMapper` engages unchanged (`btl4app.cpp MakeViewpointEntity`) — RP precedent: + stock VTVRIOMapper ran against PadRIO unmodified. +- Author the default BT `bindings.txt` (vRIO grammar): stick/throttle/pedal axes, fire + buttons, MFD aux banks. +- Fix desktop-unreachable controls: secondary-MFD view cycling (mapper cases + 0x13d/0x13e are dead DOS F3/F4 codes). Weapon regrouping comes alive via the RIO + path for free. +- **Verify**: full mech drive+fight from pad+keyboard, no COM ports; pad hot-plug; + `L4CONTROLS=RIO` pod regression still initializes. + +## Phase 3 — Cockpit on the desktop (Workstream A.2) + +- **3a PlasmaScreen** (low risk, land first): `L4PLASMASCREEN.*` verbatim + the + `L4GREND.cpp` selector diff. `L4PLASMA=SCREEN`. +- **3b Single-window MFD split** (`L4MFDSPLIT=1`) — **the HIGH-risk hand-merge**: + RP412 rebuilt `L4VB16.cpp` ~3846–4046 (splitViews, fixed 1920×1080 canvas, + 3D Present into the viewscreen pane via `hDestWindowOverride`); BT rebuilt the same + region for dev-gauge docking (`BT_DEV_GAUGES*`, `BT_GAUGE_*`, `BT_ALL` — 15 sites). + Write 3-way diff notes into `context/steamification.md` **before** editing. + `L4MFDVIEW.*` copied as skeleton; replace RP's pod tables with BT's display set + (viewscreen, radar, five mono MFDs sliced from the 1280×480 span, plasma glass). +- **[investigate]** BT cockpit button-bank geometry: no vRIO `CockpitLayout` exists for + the BT pod. Sources: `content/GAUGE/l4gauge.cfg`, pod photos, ask Nick. Land + panes-without-buttons first; clicks inject `PadRIO::SetScreenButton`, lamps light + from `GetLampState` once geometry lands. +- **Verify**: one cockpit window, 3D presents into its pane (smoke BT's rebuilt L4D3D + present path EARLY), live MFDs/radar/plasma; pod multi-surface path (`L4GAUGE`) + unbroken. + +## Phase 4 — NetTransport seam + Steam transport (Workstream C.1) + +- `L4NETTRANSPORT.*` verbatim (abstract seam + `WinsockNetTransport` default; + SOCKADDR_IN-shaped addresses keep egg `[pilots] ip[:port]` working in both worlds). +- `L4NET.CPP`: apply RP412's refactor (~22–26 Winsock sites → `NetTransport_Get()`); + **re-site the 5 `BT_NET_TRACE` blocks** onto the seam calls. +- `L4STEAMTRANSPORT.*` near-verbatim, gate `BT412_STEAM`; vendor + `extern/steamworks_sdk_164/` (copy from RP412). +- CMake: seam always compiled; `option(BT412_STEAM)` gates the transport TU + define + + SDK include + `steam_api.lib` + post-build dll copy. +- **Verify**: (1) loopback + btconsole.py full MP parity through the seam (TCP); + (2) Steam smoke — transport installs, FakeIP allocated, graceful TCP degrade when + Steam is absent; (3) real Steam-sockets session (may defer to Phase 6). + +## Phase 5 — Front end + LocalConsole marshal (Workstream B — bulk of new code) + +- **5a `game/reconstructed/btl4fe.cpp`** (skeleton: RP412 `RP_L4/RPL4FE.cpp`): no + `-egg`/`-net` → setup menu. Catalog: 8 maps + (`cavern grass rav polar3 polar4 arena1 arena2 dbase`), mechs per defaults, + scenario=freeforall, time/weather/temperature/length, pilot name. + `BTMission::ToEggString` against the verified egg format (`content/MP.EGG`, + `DEV.EGG`) incl. GDI-rendered 128×32 `[ordinals]`/name plasma bitmaps → the standard + egg-load path. +- **5b `game/reconstructed/btl4console.cpp`** (skeleton: `RPL4CONSOLE.cpp`): in-process + console on its own thread over NetTransport — egg chunks + ACK, RunMission ×2 + (mirror btconsole.py), stays connected (fixes the console-loss listener bug for + solo), owns the mission clock, StopMission at `length=` expiry, launcher-role loop, + `InstallNetworkRace` marshal for remote pods. +- **5c Score intake — genuinely new for BT** (no mission-end flow exists): a + `gConsoleScoreSink` equivalent through `BTPlayer`; v1 results screen = kills/deaths + per pilot from the Comm-MFD `pilotList` tally at stop. +- **5d `game/btl4main.cpp` WinMain wiring** (skeleton: RP412 `RPL4.CPP` diff): + front-end-mode detection, single-binary `for(;;)` loop (results → menu → launch), + host/member branch, self-documenting `environ.ini` parsing, minidump crash filter, + `SC_KEYMENU` swallow, `BT412STEAM` env → `SteamNetTransport_Install()`. +- **Verify**: no-args boot → menu → LAUNCH → mission → stop at set length → results → + fresh menu; `-egg DEV.EGG` stays unmarshaled (dev shortcut); btconsole.py external + feed still works; marshaled 2-instance loopback collects both score lines. + +## Phase 6 — Steam lobby (Workstream C.2) + +- **`game/reconstructed/btl4lobby.cpp`** (skeleton: `RPL4LOBBY.cpp` — mechanics + generic): lobby owner = console; member data = FakeIP + fake console/game ports + + persona + loadout (**mech**/color/badge); nonced launch roster → `RegisterPeer` all → + owner hosts via egg+marshal, members join as network pods; Push/PullRaceResults + distribute the score sheet. FE gains HOST/JOIN screens. +- Author `docs/STEAM-3-MACHINE-TEST.md` for BT (adapt RP412's; keep its gotchas: + disable Steam Input on 480, one Steam account per machine, abort key). +- **Verify**: 3-machine Steam test — lobby → mesh → marshaled timed mission → + kills/deaths → stop → results everywhere → rematch. Known MP fidelity gaps (peer + warp spheres, missile clusters, PNAME/PLACE billboards) do not block. + +## Phase 7 — Polish, packaging, release + +- KeyLight RGB mirror: `L4KEYLIGHT.*` verbatim (C++/WinRT TU — per-file C++17 props), + gate `BT412KEYLIGHT`. +- `pack-dist.ps1` adapted: `btl4.exe`+pdb, `BTL4.RES`, `BTDPL.INI`, + `VIDEO/ GAUGE/ AUDIO/`, eggs, `steam_api.dll`, OpenAL runtime, generated commented + `environ.ini`, `start-windowed.bat`, README.txt, refuse-while-running. +- `tools/two-pod-test.ps1` adapted (feeder = btconsole.py). Version banner `4.12.x`; + tag the release on gitea. +- **Verify**: dist zip runs on a clean machine (no DXSDK); solo loop; packaged + 2-machine Steam session. + +## Copy matrix (from RP412) + +| Treatment | Files | +|-----------|-------| +| **Verbatim** (after 3-way check) | `L4PADRIO.*`, `L4PADBINDINGS.*`, `L4PLASMASCREEN.*`, `L4NETTRANSPORT.*`, `L4STEAMTRANSPORT.*` (gate rename), `L4KEYLIGHT.*` (gate rename), `extern/steamworks_sdk_164/` | +| **Diff-apply / hand-merge** | `L4RIO.*`, `L4CTRL.cpp`, `L4GREND.cpp` (expected clean); `L4NET.CPP` (medium — BT_NET_TRACE); `L4VB16.cpp` (**high** — dev-gauge collision); `L4VIDEO.*`; v143 source fixes | +| **Adapt** (RP skeleton, BT tables/fields) | `L4MFDVIEW.*`, `btl4lobby`, `pack-dist.ps1`, `two-pod-test.ps1`, `environ.ini` template, STEAM-3-MACHINE-TEST doc | +| **New** | `btl4fe`, `btl4console`, score sink + results screen, BT `bindings.txt`, CMake Steam gating, `context/steamification.md` | + +## Standing regressions (after every engine-file merge) + +1. Solo: `run\run.cmd` boots DEV.EGG; drive → fire → kill → respawn works. +2. Loopback MP via btconsole.py keeps entity/combat replication. +3. Pod paths (`L4CONTROLS=RIO`, `L4GAUGE`, `L4PLASMA=com2`) still compile and + initialize.