Proposal: ship the authentic single-folder dist layout (docs only, NOT implemented)

The bare-launch crash was a symptom; the cause is that BT411 hands players a
developer tree.  mkdist zips tracked repo paths verbatim, so the dist inherited
build\Release\btl4.exe + content\ -- while the 1995 pod (BTL4OPT.EXE sits
beside BTL4.RES to this day, in content\) and RP411/RP412 all ship ONE folder,
where cwd is right by construction and a double-click just works.

docs/DIST_LAYOUT_PLAN.md sets out the proposed tree, the file-by-file change
(~50 lines total, no game code), what it buys, and the part that actually needs
a decision: the upgrade story.  Four migration options with a recommendation,
plus the wrinkle that decides between them -- the zip root is VERSIONED, so
every version may already land in its own folder, in which case the documented
extract-over-top has never worked and the migration cost is near zero.

Four open questions listed for the other author, including whether the .bat
launchers still earn their keep and whether the pod cabinet's own install shape
should be confirmed against Nick's notes before we call one folder authentic
for the cabinet too.

Not implemented pending that discussion.  The 4.11.560 cwd guard stands either
way and makes both layouts work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-26 02:49:30 -05:00
co-authored by Claude Opus 5
parent 78a98dafc7
commit a7bcf1cbab
3 changed files with 167 additions and 2 deletions
+1 -1
View File
@@ -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` |
---
+4 -1
View File
@@ -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
+162
View File
@@ -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
`<name>/content/...`, the exe as `<name>/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 `<exe dir>\content\bindings.txt` exists and
`<exe dir>\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 `<exe dir>\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_<version>/`) 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)