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>