2e85cd2066 GameOS: full display enumeration trace in gos-displays.txt
Motivation
----------
A tester's 3-display Intel integrated-graphics box (main + 2 MFDs on the
iGPU, radar on a USB adapter) failed MFD bring-up with the second MFD
panel returning DDERR_EXCLUSIVEMODEALREADYSET, while the same build works
on a W4100 and on a Quadro. The old report showed only the final device
list and role numbers, which was not enough to tell whether the cause was
device count, capability, index shifting, or a duplicate assignment.

The report now traces every stage of display discovery in the order the
game performs it, so the cause can be read off the file instead of
inferred.

What gets logged
----------------
* Header: executable path, full command line, and the requested -tmfds /
  -tmon values already converted from the 1-based command-line form to
  the 0-based DirectDraw indices the code uses. That conversion is an
  easy off-by-one to miss: "-tmon 1,..." means device 0.

* Windows desktop topology via EnumDisplayDevicesA + EnumDisplaySettingsA
  - every \\.\DISPLAYn adapter, its friendly name, attached/primary
  state and current mode. Stated explicitly so it can be compared
  against the DirectDraw order, which is NOT the same ordering.

* Stage 1, enumeration callbacks: each callback as it fires, with driver
  description, driver name, GUID, and the HMONITOR resolved through
  GetMonitorInfoA to \\.\DISPLAYn plus desktop rect and primary flag.
  Entries with no HMONITOR are named as the primary-display-driver alias,
  noting that NumMonitors is not incremented for them.

* Stage 2, capability check: per device ACCEPTED (with assigned index and
  whether a HAL was found) or REJECTED.

* Device table printed THREE times - before the NULL-device merge, after
  it, and final. Each entry shows description, driver, DeviceGUID,
  guidDeviceIdentifier, vendor/device IDs, hardware-rasterizer flag and
  its monitor. Followed by an adapter grouping listing which device
  indices belong to the same physical card, since guidDeviceIdentifier
  identifies the ADAPTER and not the output - which is precisely why a
  single card and a mixed iGPU + USB adapter setup enumerate differently.

* Stage 3, the NULL-device merge: whether the NumMonitors>=2 guard
  passed, which device matched the primary's adapter GUID, and every
  index shift printed individually. If nothing matches, it says so
  loudly - slot 0 then remains the alias and any role pointed at device 0
  lands on the Windows primary monitor.

* Stages 4-7, role selection: span / main / radar / MFD searches, each
  printing the device chosen AND the reason every skipped device was
  skipped. Then the -tmon overrides, each showing what auto-detection had
  chosen and what the override replaced it with, or why it was rejected.

* Final summary: role -> device -> physical monitor, plus a consistency
  check that reports two roles landing on one device as an explicit
  CLASH, with the explanation that the second panel will fail with
  DDERR_EXCLUSIVEMODEALREADYSET. That is the suspected failure on the
  Intel box and nothing in the old log pointed at it.

Fixes
-----
* Monitor/device desync: the NULL-device merge shifted DeviceArray but
  nothing tracked which monitor each slot drove. g_ahDevMonitor[] is now
  shifted in lockstep; without this every monitor attribution after a
  merge would be off by one, i.e. confidently wrong rather than absent.

* HMONITOR is now retained. The Ex enumeration callback is the only place
  the device-to-monitor association is available and it was being
  discarded, so videoDevices gained an hMonitor field and BufferDevice
  takes it.

Behaviour
---------
No functional change. Every condition, code path and assignment is
unchanged - only logging was added, plus the monitor-array shift above.
-tmon still applies each slot independently and still does not reject
duplicates; the duplicate is now merely visible. Whether to make it an
error is a separate decision, pending test results.

Cost
----
Startup only. Nothing added is reachable from the frame loop, so there is
no runtime cost of any kind. Roughly 255 writes for a 4-monitor pod, at
~25-130 ms total on a warm cache - inside the noise of FindVideoCards()
itself, which creates DirectDraw objects and enumerates every display
mode per device. Worst case is antivirus on-access scanning of each
CreateFile, which could reach ~1 s; a folder exclusion removes it.

Lines remain open-append-close so the report survives a hard crash during
panel init, which is exactly when it is most needed. gos-fps.txt is the
buffered log; this one deliberately is not.

Portability
-----------
GetMonitorInfoA and EnumDisplayDevicesA are resolved with GetProcAddress
and the MONITORINFOEXA / DISPLAY_DEVICEA layouts are declared locally, so
nothing depends on the 1998 SDK headers carrying multimon support. If the
APIs are unavailable the report degrades gracefully instead of failing to
build. ENUM_CURRENT_SETTINGS is defined defensively.

Testing
-------
Not yet built. Requires a rebuild of MW4.exe (Release + Profile) as this
is CoreTech GameOS. Note the report is truncated on every launch - a
failing run's log must be copied before relaunching.

Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-08-05 10:07:11 -05:00
2026-07-25 08:54:28 -05:00
2026-06-26 10:40:23 -05:00

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 20022009 GameLeap / FASA Interactive codebase, currently at V5.1.x.

⚠️ Setting up a new machine? Read RECOVERY.md BEFORE 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 (19881990). 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 (19912001). 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 (20022016). 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 (2005present). 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-tbaud switch for replica RIO boards with high-speed UARTs
  • Automated match configuration — Load File system for setting up full matches from an .ini file (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 into c:\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)packs resource\*.mw4 from Gameleap\mw4\Content using the in-exe compiler (MW4pro.exe -build). Called by the deploy; can be run standalone.
  • deploy-editor.ps1 — installs the mission editor in place into Gameleap\mw4 (the data tree it edits): drops MW4Ed2.exe + DDrawCompat there, neutralizes the DDraw-breaking DLLs, sets the shim, writes run-editor.bat. No separate editor directory. (build-resources.ps1 moves DDrawCompat aside while the builder runs, since it's fatal to MW4pro.exe.)
  • RESOURCE-BUILD.md — how the .mw4 packaging works.

Outputs (regenerable — safe to delete and rebuild)

  • MW4\ — runnable game deploy (from deploy-mw4.ps1). Move/copy this to production.
  • The editor has no separate output dir — it runs in place from Gameleap\mw4 via Gameleap\mw4\run-editor.bat (installed by deploy-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 used Gameleap\mw4). Note: EditorDocs\ = original map/terrain/NFO/ABL tutorials.
  • GameleapCode5_03\{Content, hsh} — stale 2005 duplicate data trees, superseded by Gameleap\mw4.
  • resource_fullbak\ — one-off backup from the from-scratch rebuild; redundant now.

Building from source

Quick build flow

  1. Compile code: VC6 build Gameleap\code\mw4\Code\MechWarrior4.dswrel.bin\ / pro.bin\.
  2. Deploy game: build-env\deploy-mw4.ps1MW4\ (packs resources, assembles, optimizes BMPs, applies shim).
  3. (Optional) Install editor: build-env\deploy-editor.ps1 → runs in place from Gameleap\mw4\run-editor.bat.

On a fresh Windows machine

  1. Install Git for Windows (includes Git LFS) — or Git + git-lfs separately.
  2. Enable long paths before cloning (this tree has deep VC98/MFC paths > 260 chars):
    git config --global core.longpaths true
    git config --global core.autocrlf false
    git lfs install
    
    Also enable the OS setting: HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled = 1.
  3. Clone to C:\VWE\firestorm — the toolchain config has this path baked in:
    git clone https://gitea.mysticmachines.com/VWE/firestorm.git C:\VWE\firestorm
    
    git clone pulls 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:
    reg import C:\VWE\firestorm\build-env\vc6-hklm-registration.reg
    reg import C:\VWE\firestorm\build-env\vc6-directories.reg
    
    Then build Gameleap\code\mw4\Code\MechWarrior4.dsw in VC6 (see CLAUDE.md STEPs 1 and 3), or use the already-mirrored rel.bin\ / pro.bin\ binaries directly.
  • Deploy the game: run build-env\deploy-mw4.ps1 to assemble C:\VWE\firestorm\MW4 and apply the Windows 10/11 DirectDraw compat shim. AppCompat is keyed on the exe path — the deploy script applies it automatically, but if you copy MW4\ to a different location you must re-run set-appcompat.bat from inside that new location.
  • Editor: Gameleap\mw4\run-editor.bat (installed in place by deploy-editor.ps1; see CLAUDE.md STEP 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.md for the full engineering and build reconstruction history.
  • See RECOVERY.md for disaster-recovery procedures.
S
Description
No description provided
Readme
9.5 GiB
Languages
C 48.8%
C++ 36.9%
Rich Text Format 12.2%
HTML 0.6%
Visual Basic 6.0 0.5%
Other 0.5%