Files
BT411/docs/DIST_LAYOUT_PLAN.md
T
CydandClaude Opus 5 a7bcf1cbab 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>
2026-07-26 02:49:30 -05:00

9.4 KiB

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/XX, build/Release/btl4.exebtl4.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.txtbindings.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)