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>
The binaries directory is where your plugins get put when you compile them. This is not the directory to use if you want to check in a binary of your plugin. This directory is in sourcesafe to assist in setup of 3DSMax2 development. Standard debug levels for 3DSMax2 are : rel - no debug - no debug memory hybrid - debug - no debug memory debug - debug - debug memory The now 3 levels for Stuff Armor and there corrilation between max are : Release - - rel max - Fully optimized, no debug, not LAB_ONLY Profile - - rel max - Fully optimized, some debug, LAB_ONLY Debug - - debug max - Varying level of armor, full debug, LAB_ONLY, When you compile the 3ds project the plugin will go into either the debug or rel directory, whichever is apporpriote to the copy of 3DSMax you must run it under. When you compile a plugin if it has been built in the directory it will be overwritten by the new dll. (IE: if you compile a Release and then a Profile only your Profile will exist since they share directories) Plugins must not be mixed. If the plugin is for the Release version of 3DSMax2 you must not run it under the debug version of 3DSMax2. -------------------------------- Setup For Existing Workspaces: -------------------------------- 3DSMax2 setup: I recommend installing max *without* the sdk ( all the sdk is included in the MW4 source control ). I also recomend installing the debug version *next* to the regular verson of max off of your root drive. example: c:\3DSMax2 c:\Maxdbg20 Under your release copy of max: File|Configure Paths|Plugins Tab|Add.. {driveletter}:\mw4\Code\3DSPlugins\Binaries\Rel Under your debug copy of max: File|Configure Paths|Plugins Tab|Add.. {driveletter}:\mw4\Code\3DSPlugins\Binaries\Debug Setup For project: Project|Settings|Debug Tab Choose the version from the "settings for" combo box for release and profile set the "Executable For Debug Session" to: {driveletter}:\3DSMAX2\3dsmax.exe for debug set: {driveletter}:\Maxdbg20\3dsmax.exe Once this is done everything should work as usual for compiling and debuging. --------------------- Adding a project --------------------- When adding a project make sure to copy the debug levels from other projects. Make sure to *NOT* specify any libries by adding them to the resource tree. Instead type the names into the : Project:Settings:Link Tab:General Object/Library Modules Just type the library names in with spaces seperating them and no paths. This way it will use the appropriate libraries ( debug, release ). Here is all the info needed for creating a new project. These are 3DSMax2, MFC, Stuff Defines Project|Settings|C/C++|General|Processor Definitions release WIN32,NDEBUG,_WINDOWS,_USRDLL,_WINDLL,MULTI_PLAYER,USE_PROTOTYPES,STRICT,TEST_CLASS=50 Profile WIN32,NDEBUG,_WINDOWS,_USRDLL,_WINDLL,LAB_ONLY,MULTI_PLAYER,USE_PROTOTYPES,STRICT,TEST_CLASS=50 Debug WIN32,_DEBUG,_WINDOWS,_USRDLL,_WINDLL,LAB_ONLY,MULTI_PLAYER,USE_PROTOTYPES,STRICT,TEST_CLASS=50 Project|Settings|Link|General|Object/Library Modules debug build must have NAFXCWD.LIB Project|Settings|C/C++|General|Warning level is 3 for all 3dstudio compiled programs. Project|Settings|C/C++|General|Optimizations is maximize speed for release and profile, disabled for Debug. Project|Settings|C/C++|Code Generation is PentiumPro for all configurations. Project|Settings|C/C++|Code Generation Runtime Lib is Multithreaded for rel & prof and multithreaded debug for debug. Project|Settings|C/C++|C++ Language|Enable Run-Time Type Information is set for all configurations. Project|Settings|C/C++|Optimizations|Inline Function is set to Any Suitable for rel & prof and disabled for debug. Project|Settings|Link|General|Generate Debug information is set for profile and debug and disabled for profile Project|Settings|Resource|PreProcessor Definitions NDEBUG for rel and profile and _DEBUG for debug