Follow-up to the gos-displays.txt enumeration trace. The expanded log arrived from the Intel tester and settled the failure - and disproved the hypothesis it was written to test. What the log showed ------------------- The consistency check printed "No duplicate device assignments", so the suspected -tmon clash was NOT the cause. The actual evidence was that HSH_EnterFullScreen2 runs TWICE: the first entry brings every panel up DD_OK, the second fails on the same device with DDERR_EXCLUSIVEMODEALREADYSET and then DDERR_NOCOOPERATIVELEVELSET. Two independent causes, one operational and one a real defect. Cause 1 - Windows Display Settings numbers are not DirectDraw indices -------------------------------------------------------------------- The operator set -tmon by reading the numbers off the Display Settings arrangement diagram. On that machine all three numbering systems differ: Settings 3 -> \\.\DISPLAY1 -> device 0 (primary, 800x600, main) Settings 4 -> \\.\DISPLAY4 -> device 3 (USB adapter, radar) Settings 2 -> \\.\DISPLAY2 -> device 1 (mfd1) Settings 1 -> \\.\DISPLAY3 -> device 2 (mfd2) A permutation with two accidental fixed points - no derivable rule, and the Settings ordinal is not exposed by any documented API, so it cannot be translated in code. -tmon 1,4,2,3 worked first try (user-confirmed). This is why Windows ships an Identify button rather than publishing the mapping. Cause 2 - panels re-opened without being released (REAL BUG, all machines) ------------------------------------------------------------------------- EnterFullScreenMode() calls HSH_EnterFullScreen2() on every mode change and every lost-front-buffer recovery, but the teardown HSH_DirectDrawRelease2() was only wired to DirectDrawRelease(), i.e. full shutdown. CHSH_Device::InitFirst() therefore overwrote pDD with a fresh IDirectDraw7 while the previous one still held exclusive fullscreen, leaking it and its exclusive claim for the life of the process. It only bites when a panel sits on the Windows primary: secondary outputs grant exclusive mode again, the primary does not. Every working pod happens to have the main display on the primary, so no panel is ever there - which is the whole reason this looked hardware-specific. FIX: HSH_EnterFullScreen2() now releases first when hsh_initialized || hsh_mrdev_initialized. Tagged [panelreinit]. Reuses the existing teardown, which already restores the display mode, drops the coop level and clears the flags for both the MFD/radar and cameraship paths. New: -tident, the game's own Identify ------------------------------------- MW4.exe -tident [3..120, default 20] fills every display with a distinct colour and prints, huge, the number to type into -tmon, plus its device index and the role currently assigned to it. Then exits. Deliberately uses DDSCL_NORMAL and paints via GDI on the primary surface: no exclusive mode, no display mode change. Taking exclusive fullscreen on several devices at once is the very failure being diagnosed, and a diagnostic that trips over that fault is worthless - this works even on a pod where the MFD modes are broken. It opens the real DirectDraw devices rather than positioning GDI windows by HMONITOR, so it proves the device-index -> physical-output association through the same path the panels use. Positioning by DirectDraw's own reported HMONITOR would be circular. Implemented as IdentifyDisplays() in VideoCard.cpp, called at the end of FindVideoCards() followed by ExitProcess(0). Everything it paints is also written to gos-displays.txt, so the mapping survives even if a monitor is dead. Also added: desktop-order block ------------------------------- gos-displays.txt now prints the monitors sorted left-to-right by desktop position with their device indices, which maps directly onto the picture in Display Settings. For the reporting machine it reads out as -tmon 1,4,2,3 with no derivation required. Documentation ------------- * -help: new -tident entry. The -tmon text now states outright that these are NOT Display Settings numbers and points at -tident. Its old "-tmon 1,2,3,4" example was actively inviting the mistake that caused this report, so that section was rewritten rather than appended to. * Release notes (md + html, both hand-maintained): -tident section with sample output and the reason it has to exist; -tmon warning; new sections for the CLASH report and the re-entry fix in operator terms; switch-table row; expanded log description with the copy-before-relaunch warning; upgrade-checklist step to run -tident once after upgrading. * CLAUDE.md: STEP 12 with the full engineering record, including the three-way numbering table and both causes. * OPTIONS-INI.md: videodriverindex note now points at -tident. Cost ---- -tident is opt-in and exits immediately after. The desktop-order block is a handful of extra startup writes. Nothing added is reachable from the frame loop. Testing ------- -tmon 1,4,2,3 confirmed working on the reporting machine, which validates the diagnosis. The -tident and re-entry changes are NOT yet built or run; both need a rebuild of MW4.exe (Release + Profile) as they touch CoreTech GameOS. Worth checking on the W4100 bench first that CreateSurface(PRIMARYSURFACE) under DDSCL_NORMAL succeeds on secondary devices through dgVoodoo2 - if a panel comes up blank the log names the failing call. Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com> Co-authored-by: GitHub Copilot <copilot@github.com>
BattleTech: FireStorm
Source code, game data, and build toolchain for BattleTech: FireStorm — the MechWarrior 4-based simulator software for Virtual World Entertainment Tesla II cockpit pods. This is the community-maintained continuation of the original 2002–2009 GameLeap / FASA Interactive codebase, currently at V5.1.x.
⚠️ Setting up a new machine? Read
RECOVERY.mdBEFORE cloning this repo. The clone only comes out byte-exact if long paths,core.autocrlf=false, and Git LFS are configured first — cloning without them silently corrupts line endings, truncates deep VC98/MFC paths, and leaves LFS placeholders instead of the real binaries.
Background
What BattleTech: FireStorm is
BattleTech: FireStorm is the game software that runs inside the Virtual World Entertainment Tesla II cockpit pods — the walk-in BattleMech simulator pods found at arcades, conventions, and private venues. Each pod is a fully enclosed cockpit with joysticks, throttle, rudder pedals, a primary infinity-optics display, five monochrome auxiliary instrument monitors, and a color map display. Up to 16 players battle simultaneously in networked sessions over a LAN, with a dedicated console pod managing the match, printing scoresheets, and running a post-game mission review.
History
Origins (1988–1990). The concept for networked BattleMech cockpit simulators originated with Jordan Weisman and L. Ross Babcock — co-founders of FASA Corporation — who developed it under the code name ESP ("Environmental Simulations Project"). In 1988 they partnered with Incredible Technologies to build a prototype: networked cockpits with joysticks, throttle, foot pedals, and dual monitors, rendered on custom Amiga and Texas Instruments hardware. The first public BattleTech Center opened in North Pier Mall, Chicago, in 1990.
Virtual World Entertainment and four hardware generations (1991–2001). The organization rebranded as Virtual World Entertainment (VWE) in 1991 and produced four generations of cockpit hardware over the following decade: System 1 (custom Amiga/TI graphics, 6 players); System 2 (TI TMS 34010 real-time 3D polygons, 8 players, launched in Yokohama and Chicago in 1992); System 2.5/3 (redesigned "Virtual World Centers" exterior, Red Planet added as a second game title, SiteLink ISDN networking connecting centers across the US and internationally — over 300 cockpits deployed worldwide at peak); and System 4 / Tesla (1996 — entirely PC-based, Division Pixel Planes texture-mapped 3D at locked 30 FPS, infinity-optics curved primary display surrounded by five monochrome auxiliary monitors and a color map display).
In 1996 VWE and FASA Interactive Technologies merged under Virtual World Entertainment Group. Microsoft purchased the group in 1999, sold VWE to former CFO James Garbarini, and integrated FASA Interactive into Microsoft Game Studios. In 2005 all remaining VWE interests were sold to Nickolas "PropWash" Smith, with the principal offices moving to Kalamazoo, Michigan.
Tesla II: FireStorm (2002–2016). Beginning in 2002, VWE partnered with Microsoft, Alienware, and GameLeap to upgrade the Tesla cockpits. The Division Pixel Planes cards — no longer in production — were replaced with Alienware PCs, and the Macintosh-based console became PC-based for the first time in over a decade. The new game software, BattleTech: FireStorm, was built on the MechWarrior 4: Mercenaries engine (GameLeap v5.03) developed by Microsoft / FASA Interactive. Software versions progressed through 5.04, 5.07, and finally 5.07D (the last official release, 2016, for LAN-center deployments).
Community continuation (2005–present). As the original Virtual World Center locations closed through the 2000s, pods passed into the hands of private operators, enthusiast venues, and convention touring groups. The most prominent continuing venue is MechCorps Entertainment in Houston, TX (opened November 2005), which operates publicly year-round and tours gaming conventions across the US. VWE itself continues to bring pods to conventions from Kalamazoo.
The pod-operator community has continued developing the FireStorm software beyond the last official release, producing the V5.1.x series maintained in this repository.
What's new in V5.1.x (community additions since 5.07D)
- Modern Windows compatibility — DirectDraw 16-bit shim automation, DirectInput joystick enumeration fix, windowed-mode DirectDraw fix for the mission editor (via DDrawCompat)
- Multi-monitor MFD support — four-display mode (
-tmfds 4) for pods using two separate 640×480 MFD monitors, plus stutter fix for split-MFD rendering - RIO cockpit hardware —
-tbaudswitch for replica RIO boards with high-speed UARTs - Automated match configuration — Load File system for setting up full matches from an
.inifile (game type, map, all 16 pilot slots) without manual console lobby input - Multiplayer fixes — 16-pilot + cameraship launch fixed; expanded time-limit list (up to 30 min)
- Expanded mech roster and loadout corrections — additional chassis with accurate IS/Clan loadouts
- Console lobby — V5.1.x Super6 rookie rotation, configurable Rookie Mission defaults, correct MFD time-limit and radar dropdowns
- mw4print v2.0 — MySQL match-data export, configurable banner text
- Source cleanup — all EUC-KR/CP949 Korean developer comments translated to English; Language DLL rebuilt from source as the English version (fixes Korean button labels in the GameOS crash dialog)
- Full build reconstruction — the complete toolchain (VC6, DX 7.0a, DX Media 6) is
self-contained in
build-env\; the game and editor build from source with 0 errors
See RELEASE-NOTES-5.1.0b_RC1.md for pod-owner change details, and CLAUDE.md for the full
engineering history.
Repository layout
Only three source trees feed the build; everything else is output (regenerable), design reference, or archived clutter.
Folder map
C:\VWE\firestorm\
├─ Gameleap\ The MW4/Gameleap 5.03 engine + game (the two live trees)
│ ├─ code\ ⭐ SOURCE CODE — build mw4\Code\MechWarrior4.dsw in VC6
│ │ ├─ CoreTech\ Reusable engine layer: GameOS, MLR renderer, gosFX,
│ │ │ GOSScript, Stuff, Network, blade + engine tools
│ │ ├─ mw4\Code\ The game itself: MW4 lib (AI, mechlab, HUD, shell),
│ │ │ MW4Application (→MW4.exe), MW4GameEd2 (mission editor),
│ │ │ scriptstrings/MissionLang (string DLLs), dedicated UI
│ │ ├─ mw4\Libraries\ mw4-local libs: Adept, stlport (build first), MLR,
│ │ │ Compost, ImageLib, gosfx, server, stuff …
│ │ ├─ mw4\Binaries\ 3DS Max export plug-ins (mech/prop .erf pipeline)
│ │ └─ rel.bin\ pro.bin\ Build OUTPUT: Release (MW4.exe, MW4pro.exe) / Profile
│ │ arm.bin\ dbg.bin\ (editor MW4Ed2.exe) / Armor / Debug — regenerable
│ └─ mw4\ ⭐ GAME DATA source tree (editor also runs here in place
│ │ via run-editor.bat; tool exes MapCreator/Tctd/NFOEditor…)
│ ├─ Content\ All content sources: Mechs\, Maps\, Missions\, Skies\,
│ │ Weapons\, WeaponSubsystems\, Subsystems\, Buildings\,
│ │ Vehicles\, Effects\, textures\, Campaigns\, Tables\,
│ │ Defines\, ABLScripts\ (mission/AI language),
│ │ ShellScripts\ (menu/mechlab UI), *.build manifests
│ ├─ Resource\ Packed .mw4 packages (output of `MW4pro -build`) +
│ │ Missions\*.nfo (MP registration) + UserMissions\
│ ├─ hsh\ Loose 2D art loaded at runtime: mech portraits, MFD
│ │ target images, HUD/radar bitmaps, decals, fonts
│ ├─ Assets\ Stats\ Runtime support data (cursors, world stats)
│ └─ Movies\ fonts\ Notes\ Cinematics / font sources / dev notes (not deployed)
├─ build-env\ ⭐ TOOLCHAIN — self-contained VC6 (VisualStudio6\),
│ │ DX 7.0a + DX Media 6 SDKs, stlnative\ headers,
│ │ ddrawcompat\ (editor viewport fix), .reg env files,
│ │ build/deploy scripts (see below), build logs
├─ MW4\ Runnable game deploy (output of deploy-mw4.ps1) —
│ regenerable; copy this to production
├─ BTFrstrm\ FireStorm design data: MechInfo_5.04.xls (stat source
│ of truth), scriptaddmech.xls (add-mech row generator)
├─ Finished HUDS from J&J\ Per-mech HUD source art (MFD + Radar) awaiting
│ integration, ~13 chassis
├─ _UNUSED\ Archived clutter — nothing read by the build (EXCEPT
│ worth knowing: Gameleap\EditorDocs\ = original map/
│ terrain/NFO/ABL tutorials)
├─ CLAUDE.md Full build/runtime reconstruction notes (the history)
├─ README.md This file — orientation + fresh-machine restore
├─ RECOVERY.md Disaster-recovery notes
├─ ADDING-A-MECH.md Workflow: add a new 'Mech chassis
└─ ADDING-A-MAP.md Workflow: add a new map/mission
The folders that matter (build inputs)
| Folder | Role | Notes |
|---|---|---|
Gameleap\code\ |
Source code + compiled binaries | C++ engine/game source (mw4\Code, CoreTech, mw4\Libraries). Build mw4\Code\MechWarrior4.dsw in VC6. Outputs land in rel.bin\ (Release MW4.exe, MW4pro.exe), pro.bin\ (editor MW4Ed2.exe), arm.bin\/dbg.bin\. |
Gameleap\mw4\ |
Game data source | The content tree the resource packer reads (Content\, and the generated resource\*.mw4, plus hsh\, Assets\, Stats\, runtime DLLs). This is the live data set — not GameleapCode5_03\Content (that was an old 2005 duplicate, now in _UNUSED). |
build-env\ |
Toolchain + scripts | Self-contained VC6 (VisualStudio6\), DirectX 7.0a + DX Media 6 SDKs, stlnative\, the .reg env files, and the deploy scripts. |
Build / deploy scripts (in build-env\)
deploy-mw4.ps1— packs resources from source (build-resources.ps1) then assembles the runnable game intoc:\VWE\firestorm\MW4. Trims dev bloat, ships only the canonical game packages, optimizes mech BMPs to 256-color, applies the DirectDraw compat shim.build-resources.ps1— (re)packsresource\*.mw4fromGameleap\mw4\Contentusing the in-exe compiler (MW4pro.exe -build). Called by the deploy; can be run standalone.deploy-editor.ps1— installs the mission editor in place intoGameleap\mw4(the data tree it edits): dropsMW4Ed2.exe+ DDrawCompat there, neutralizes the DDraw-breaking DLLs, sets the shim, writesrun-editor.bat. No separate editor directory. (build-resources.ps1moves DDrawCompat aside while the builder runs, since it's fatal toMW4pro.exe.)RESOURCE-BUILD.md— how the.mw4packaging works.
Outputs (regenerable — safe to delete and rebuild)
MW4\— runnable game deploy (fromdeploy-mw4.ps1). Move/copy this to production.- The editor has no separate output dir — it runs in place from
Gameleap\mw4viaGameleap\mw4\run-editor.bat(installed bydeploy-editor.ps1).
Design and reference (not build inputs)
BTFrstrm\— FireStorm design data: mech stat workbooks (MechInfo_*.xls,scriptaddmech.xls), mech loadout reference (mech_loadouts.md), autoconfig file spec, and test match files.Finished HUDS from J&J\— per-mech HUD source art (MFD + Radar) for ~13 chassis awaiting integration.
_UNUSED\ — archived clutter (nothing here is read by the build)
Moved here to reduce confusion. Safe to delete once comfortable. Contents:
Gameleap\{Archive, Drivers, EditorDocs, Notes, batch, utilities}— historical utility data (the build only ever usedGameleap\mw4). Note:EditorDocs\= original map/terrain/NFO/ABL tutorials.GameleapCode5_03\{Content, hsh}— stale 2005 duplicate data trees, superseded byGameleap\mw4.resource_fullbak\— one-off backup from the from-scratch rebuild; redundant now.
Building from source
Quick build flow
- Compile code: VC6 build
Gameleap\code\mw4\Code\MechWarrior4.dsw→rel.bin\/pro.bin\. - Deploy game:
build-env\deploy-mw4.ps1→MW4\(packs resources, assembles, optimizes BMPs, applies shim). - (Optional) Install editor:
build-env\deploy-editor.ps1→ runs in place fromGameleap\mw4\run-editor.bat.
On a fresh Windows machine
- Install Git for Windows (includes Git LFS) — or Git +
git-lfsseparately. - Enable long paths before cloning (this tree has deep VC98/MFC paths > 260 chars):
Also enable the OS setting:
git config --global core.longpaths true git config --global core.autocrlf false git lfs installHKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled = 1. - Clone to
C:\VWE\firestorm— the toolchain config has this path baked in:git clone https://gitea.mysticmachines.com/VWE/firestorm.git C:\VWE\firestormgit clonepulls LFS objects automatically. If any are missing:cd C:\VWE\firestorm && git lfs pull.
After cloning — make it buildable and runnable
- Build toolchain (VC6): import the registry config (elevated), per
build-env\README.md:Then buildreg import C:\VWE\firestorm\build-env\vc6-hklm-registration.reg reg import C:\VWE\firestorm\build-env\vc6-directories.regGameleap\code\mw4\Code\MechWarrior4.dswin VC6 (seeCLAUDE.mdSTEPs 1 and 3), or use the already-mirroredrel.bin\/pro.bin\binaries directly. - Deploy the game: run
build-env\deploy-mw4.ps1to assembleC:\VWE\firestorm\MW4and apply the Windows 10/11 DirectDraw compat shim. AppCompat is keyed on the exe path — the deploy script applies it automatically, but if you copyMW4\to a different location you must re-runset-appcompat.batfrom inside that new location. - Editor:
Gameleap\mw4\run-editor.bat(installed in place bydeploy-editor.ps1; seeCLAUDE.mdSTEP 9).
Important notes
core.autocrlf=false— line endings are preserved byte-for-byte. Do not change this.- The repo includes machine-specific bits (registry exports, AppCompat). These restore the files; registry state must be re-imported and the AppCompat shim re-applied on each new machine (steps above).
- See
CLAUDE.mdfor the full engineering and build reconstruction history. - See
RECOVERY.mdfor disaster-recovery procedures.