diff --git a/CLAUDE.md b/CLAUDE.md index f28e365..ede7e2e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -85,7 +85,7 @@ precise than anything you can infer. | Term / acronym definitions | `reference/glossary.yaml` | | The ORIGINAL 1995 player manual (controls, per-mech stats, coolant loops) | `reference/manual/Tesla40_BT_manual.pdf` (+ alignment audit in `context/pod-hardware.md` §Manual) | | The complete verbatim detail (fallback) | `docs/PROGRESS_LOG.md` (the old 2236-line CLAUDE.md) | -| Detailed running ledgers | `docs/RECONCILE.md`, `docs/GAUGE_COMPOSITE.md`, `docs/HARD_PROBLEMS.md`, `docs/SUBSYS_PLAN.md`, `docs/P3_LOCOMOTION.md`, `docs/RESOURCE_AUDIT.md`, `docs/VEHICLE_SUBSYSTEMS.md`, `docs/BGF_FORMAT.md`, `docs/ASSET_PIPELINE.md`, `docs/BT_SOURCE_STATUS.md`, `docs/WAVE_PLAN.md`, `docs/GLASS_COCKPIT.md`, `docs/REVOLVING_DOOR_PLAN.md`, `docs/INPUT_PATH_AUDIT.md`, `docs/RESPAWN_REARM_PLAN.md`, `docs/KD_SCOREBOARD_PLAN.md` | +| Detailed running ledgers | `docs/RECONCILE.md`, `docs/GAUGE_COMPOSITE.md`, `docs/HARD_PROBLEMS.md`, `docs/SUBSYS_PLAN.md`, `docs/P3_LOCOMOTION.md`, `docs/RESOURCE_AUDIT.md`, `docs/VEHICLE_SUBSYSTEMS.md`, `docs/BGF_FORMAT.md`, `docs/ASSET_PIPELINE.md`, `docs/BT_SOURCE_STATUS.md`, `docs/WAVE_PLAN.md`, `docs/GLASS_COCKPIT.md`, `docs/REVOLVING_DOOR_PLAN.md`, `docs/INPUT_PATH_AUDIT.md`, `docs/RESPAWN_REARM_PLAN.md`, `docs/KD_SCOREBOARD_PLAN.md`, `docs/DIST_LAYOUT_PLAN.md` | --- diff --git a/context/build-and-run.md b/context/build-and-run.md index ac4d686..e02d1ab 100644 --- a/context/build-and-run.md +++ b/context/build-and-run.md @@ -55,7 +55,10 @@ run\run.cmd [EGG] # default DEV.EGG; cd's to content\ and runs btl4.exe -eg two-folder split (`build\Release\btl4.exe` + `content\`) is not a design decision: `mkdist.py` zips TRACKED REPO PATHS verbatim, so the dist inherited the repo's developer layout. In the authentic single-folder shape cwd is right by construction and a double-click just works, which - is why the other games never hit this. + is why the other games never hit this. **A proposal to ship the authentic shape is written up + in `docs/DIST_LAYOUT_PLAN.md` — PROPOSED, not implemented, awaiting a decision between the + authors.** The cwd guard stays either way (it protects the developer tree, where the split is + real and permanent). - Interactive: **WASD** drive; weapon groups (keyboard, task #43) **1/Space** = lasers, **2** = PPCs, **3/Ctrl** = missiles; **X** all-stop; **V** cockpit/chase view. Default egg = `DEV.EGG` (map=grass, time=day). Swap mech via the egg's `vehicle=` — **ALL 18 ModelList names diff --git a/docs/DIST_LAYOUT_PLAN.md b/docs/DIST_LAYOUT_PLAN.md new file mode 100644 index 0000000..f60c9d4 --- /dev/null +++ b/docs/DIST_LAYOUT_PLAN.md @@ -0,0 +1,162 @@ +# DIST_LAYOUT_PLAN — proposal: ship the authentic single-folder layout + +**Status: PROPOSED, NOT IMPLEMENTED.** Written 2026-07-26 for discussion between the authors. +Nothing in this document has been built. The seatbelt described in §7 *has* shipped (4.11.560); +this proposal is about removing the need for it. + +--- + +## 1. What prompted this + +Field report, 4.11.559: + +``` +PS C:\Games\BT411_4.11.559\build\Release> .\btl4.exe -fit +``` + +→ the mission console opens, then the game **crashes on Launch**, and the player's +`environ.ini` / `bindings.txt` appear to have never been created. + +Root cause: the engine resolves `BTL4.RES`, `VIDEO\`, `BTDPL.INI`, the eggs **and** both player +config files relative to **cwd**. Launched from `build\Release`, it found no resources +(`Resource file btl4.res v1.0.0.0 is obsolete!`), wrote stray copies of `bindings.txt` / +`environ.ini` / `btl4.log` next to the exe, and killed the mission generation the menu launched +(the child inherits the parent's cwd). + +The observation that matters more than the bug: **RP411, RP412 and the 1995 pod cannot hit this, +because they ship one folder.** + +## 2. Evidence that one folder is the authentic shape + +- **The 1995 pod.** `content\` in this repo *is* an original pod game directory: + `BTL4OPT.EXE`, `BTL4.RES`, `SETENV.BAT`, `32RTM.EXE`, `DPMI32VM.OVL`, `VIDEO\`, `GAUGE\`, + `AUDIO\` all sit together. The exe lived beside its resources. [T1] +- **RP411 / RP412.** `pack-dist.ps1` copies `rpl4opt.exe`, `AUDIO/`, `GAUGE/`, `VIDEO/`, + `RPL4.RES`, `RPDPL.INI`, the eggs, the DLLs, `environ.ini` and `bindings.txt` into ONE dist + root. A dist listing confirms it. [T1] +- **BT411.** `mkdist.py` zips **tracked repo paths verbatim** (`git ls-files content/` written as + `/content/...`, the exe as `/build/Release/btl4.exe`). The player therefore receives + the *developer tree*. [T1] + +So the split is not a decision anyone made about how the game should be installed — it is an +artifact of how the packer was written. In the authentic shape cwd is correct by construction and +a double-click just works. + +## 3. Proposed dist tree + +``` +BT411_4.11.NNN/ + btl4.exe <- was build/Release/btl4.exe + OpenAL32.dll d3dx9_43.dll msvcp140.dll vcruntime140.dll steam_api.dll + BTL4.RES BTDPL.INI CONTROLS.MAP *.EGG ... <- was content/* + AUDIO/ GAUGE/ VIDEO/ <- was content/*/ + play_solo.bat join.bat join_lan.bat joyconfig.bat play_steam.bat + README.txt CONTROLS.txt + (bindings.txt, environ.ini, volume.cfg, *.log appear here on first run) +``` + +Identical in shape to the pod's own directory and to RP's dist. + +## 4. What changes + +| File | Change | Size | +|---|---|---| +| `tools/mkdist.py` | rewrite archive paths: `content/X` → `X`, `build/Release/btl4.exe` → `btl4.exe`, DLLs → root. The redist/PDB/steam logic is unaffected. | ~15 lines | +| `players/*.bat` (5) | drop `cd content`; drop the `build\Release\` prefix; the `badpath` guard tests `BTL4.RES` instead of `content\OPERATOR.EGG` | ~4 lines each | +| `players/README.txt` | "next to the content and build folders" → "in the game folder"; upgrade section (see §6) | ~10 lines | +| `docs/CONTROLS.md` | `content\bindings.txt` → `bindings.txt` (3 mentions) | trivial | +| game code | **none required.** `BTEnsureContentDirectory` already probes the exe's own directory, so a single-folder install satisfies it on the first candidate. Log strings that say `content\environ.ini` become slightly wrong — cosmetic, worth a sweep. | ~5 strings | + +**The repo layout does NOT change.** `build/` is generated and `content/` stays where it is; only +the packer's output shape moves. Developers keep running `run\run.cmd` exactly as now. + +## 5. What it buys + +- The reported crash class disappears at the source rather than being caught by a guard. +- A double-clicked `btl4.exe` works — which is what a player tries first, and what the menu + front end was built to support. +- `bindings.txt` / `environ.ini` / `volume.cfg` / `btl4.log` land where the player can see them, + next to the game, instead of one folder down. +- One fewer way to run a **stale exe**: today `build\Release\btl4.exe` can survive an upgrade and + be launched by an old shortcut. (That has already cost us one debugging session — see + `docs/GLASS_COCKPIT.md` §2026-07-20 "STALE EXE, not code".) +- We stop shipping a directory named `build\` to players, which invites exactly the "run the exe + directly" instinct that caused this. + +## 6. The hard part — upgrades ⚠ + +The README tells players to extract the new zip **over** the existing folder and overwrite, so +their `bindings.txt` and `volume.cfg` survive. A layout change collides with that: + +| Hazard | Effect | +|---|---| +| Player's `content\bindings.txt` stays in the now-unused `content\` | Their key/joystick setup is silently ignored — and still visible on disk, so it looks like the game lost it | +| Old `build\Release\btl4.exe` remains | A shortcut or habit runs a **stale build** | +| Old `content\` tree remains | ~130 MB duplicated, and two copies of every asset | + +**But note the wrinkle worth checking first:** the zip root is *versioned* +(`BT411_4.11.560/…`), so extracting into `C:\Games\` produces a **new sibling folder**, not an +overlay — the reporter's own install is `C:\Games\BT411_4.11.559\`. The documented +extract-over-top only works if the player extracts the *inner folder's contents* onto the old +install, which is a fiddly manual step. **If in practice every version already lands in its own +folder, then bindings.txt already does not carry over today**, and the migration cost of this +change is close to zero. That should be confirmed before weighing the options below. + +### Migration options + +- **A. Versioned folder, no migration.** Rely on each version extracting fresh; README tells + players to copy `bindings.txt` (+ `volume.cfg`, `environ.ini`) from the old folder's `content\` + into the new folder's root. Simple, honest, one paragraph of README — but a manual step, and + wrong if anyone really is overlaying. +- **B. One-shot in-game migration.** On boot, if `\content\bindings.txt` exists and + `\bindings.txt` does not, copy the player files up and log it loudly. ~30 lines, + covers the overlay case invisibly. Does not solve the stale exe or the duplicated tree. +- **C. B + a loud stale-install warning.** Additionally, if `\build\Release\btl4.exe` + exists, log a warning and show it once in the front end ("an old copy of the game is still in + this folder — delete build\ and content\"). Most protective, most code. +- **D. Stable zip root** (`BT411/` instead of `BT411_/`) so extract-over-top genuinely + works, combined with B. Fixes the upgrade story properly but changes how testers file reports + (the folder no longer names the version — though the title bar and log head still do). + +**Recommendation: A if §6's wrinkle confirms versioned folders are the reality, else B+C.** +Either way the change is small; the risk is entirely in the migration, not in the layout. + +## 7. Relationship to the shipped seatbelt (4.11.560) + +`BTEnsureContentDirectory` (btl4main.cpp) already makes both layouts work: if cwd has no +`BTL4.RES` it probes `..\..\content`, `..\content`, `content`, and the exe dir itself. **It stays +either way** — it costs nothing, it protects the developer tree (where the split is real and +permanent), and it means this proposal can be adopted or rejected without any risk of regression. +If the layout changes, the first probe candidate simply becomes the hit. + +## 8. Verification plan (if adopted) + +1. `mkdist.py` → extract clean → **double-click `btl4.exe`** (no bat, no cwd help): menu opens, + Launch runs a mission, `bindings.txt`/`environ.ini`/`btl4.log` appear at the root. +2. Each of the five bats from a clean extract. +3. `btl4.exe -fit` bare, and from a shell sitting anywhere else on disk. +4. 2-node LAN via `join_lan.bat` (path assumptions in the join path are the least exercised). +5. Migration path per the chosen option: install 4.11.559 old-shape, customize `bindings.txt`, + upgrade, confirm the setup survives or that the README's step recovers it. +6. Pod profile boot (`SETENV.BAT` now sits at the root — confirm the cabinet contract in + `context/glass-cockpit.md` §ONE unified build still reads correctly). + +## 9. Open questions for the other author + +1. Do we actually have players *overlaying* installs, or does everyone get a fresh folder per + version? This decides §6 entirely. +2. Do the `.bat` launchers survive at all in a single-folder world? They still earn their keep + (launch forensics `#41`, the handoff wait, `BT_FE_SOLO`, `BT_LOG` naming) — but a player who + can now just double-click the exe may never touch them. +3. Should `environ.ini` / `bindings.txt` be **shipped** in the zip rather than written on first + run? RP ships both. We deliberately do not, so extract-over-top cannot clobber a player's + settings — but that reasoning weakens under option A/D. +4. Does the real pod cabinet care? Its `SETENV.BAT` + `BT_PLATFORM=pod` contract is + path-independent, but the pod's own install shape should be confirmed against Nick's notes + before we call the single folder "authentic" for the cabinet as well as the 1995 build. + +## Key Relationships + +- Caused by: `context/build-and-run.md` §cwd guard (the landmine + why BT411 differs) +- Touches: `tools/mkdist.py`, `players/*.bat`, `players/README.txt`, `docs/CONTROLS.md` +- Prior art: `C:\VWE\RP412\pack-dist.ps1` (single-folder dist), `content\BTL4OPT.EXE` (the pod's own)