Files
firestorm/mw4print-issues.md
T
77e19a723c mw4print: document known issues and research notes
Captures all findings from the 2026-08-07 debugging session:
print flow diagram, DoPrint error codes, which commits changed what,
hypotheses explored/ruled out, and next steps once the -debug log
is available.

Co-authored-by: Claude Sonnet 4.6 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-08-07 21:55:35 -05:00

5.9 KiB

mw4print ? Known Issues & Research (2026-08-07)

Symptom

Printing is broken in the current build (post-b98cb87e).

  • Without MySQL enabled: never prints, neither on mission-end (WM_COPYDATA) nor on manual File ¡æ Open.
  • With MySQL enabled: app locks up ~5 seconds, prints one mission, then never prints again until restart.

"Anymore" = it worked before the MySQL/banner commits.


Print Flow (how it works)

Game (MW4.exe)
  ¦¦¦¡ SendMessage(WM_COPYDATA, filename)
       ¦¦¦¡ CMainFrame::OnCopyData
            ¦¦¦¡ CChildView::DoCopyData  ¡ç adds CMyPrintInfo to m_lstMPIs queue

1-second WM_TIMER
  ¦¦¦¡ CChildView::OnTimer
       ¦¦¦¡ g_RSF.LoadPR(p->m_strFile)    ¡ç opens and parses .pr file
       ¦¦¦¡ g_RSF.DoPrint()               ¡ç if nErr==0: remove from queue
       ¦¦¦¡ g_RSF.Reset()

Manual path (File ¡æ Open) also adds to m_lstMPIs; the timer handles both cases identically.

DoPrint() internal flow

DoPrint()
  LoadPrintParams()               ¡ç reads options.ini / banner.txt
  count m_pScoreObjects ¡æ nPlayers
  if nPlayers == 0: return 0 silently (no print, item still removed!)
  PrintDlg(PD_RETURNDEFAULT | PD_RETURNDC)
    ¦§¦¡ fail ¡æ nErr = -1, CommDlgExtendedError() has the reason
    ¦¦¦¡ ok   ¡æ hDC set
  MakeInfoTable / params.LoadParameters
  [#ifdef MW4PRINT] if g_dbConfig.bEnabled: DB_ExportMatch()   ¡ç 5s timeout here
  SetupFonts(DPI)     fail ¡æ nErr = -2
  StartDoc            fail ¡æ nErr = -3
  per-player loop:
    StartPage / DoPrint(hDC, ...) / EndPage   fail ¡æ nErr = -4
  EndDoc (or AbortDoc on error)
  DeleteDC / delete pInfoTable
  return nErr

Key return codes

nErr Meaning
0 Success (or nPlayers==0 ? silent non-print)
-1 PrintDlg returned FALSE ? check CommDlgExtendedError()
-2 SetupFonts failed
-3 StartDoc failed
-4 EndPage failed mid-print

Commits that changed mw4print

Hash Description
b98cb87e MySQL export, configurable banner text ? first change
9f3a5044 / a45be804 Version bump to 2.0 (rc only)
515adc24 persist banner text via banner.txt ? second change
3256c103 -debug diagnostic logging (current)

What b98cb87e actually changed inside DoPrint

The ONLY addition inside DoPrint when MySQL is disabled:

#ifdef MW4PRINT
    if (g_dbConfig.bEnabled) {
        DB_ExportMatch(...);   // ¡ç gated; skipped when bEnabled=false
    }
#endif

So with MySQL disabled, DoPrint() is byte-for-byte identical to the pre-b98cb87e code. If it's failing, the failure is NOT in this block.

What 515adc24 changed in LoadPrintParams

Fixed a missing backslash in the options.ini path:

// before: strOI += "options.ini";   ¡æ "C:\MW4options.ini" (wrong)
strOI += "\\options.ini";            ¡æ "C:\MW4\options.ini" (correct)

Side-effect: before the fix, all layout params used their hardcoded defaults. After the fix, they read from the real options.ini. If that file has unusual values, print layout could differ ? but all params are clamped to sane min/max so they can't cause a crash.


Key facts established

  • MW4PRINT IS defined ? it's in mw4dummy.h (#define MW4PRINT), which is #included before everything in ChildView.cpp.
  • DB_ExportMatch is called after PrintDlg, not before. The 5-second "lockup" with MySQL = connection-timeout inside DB_ExportMatch, which is reached only after PrintDlg has already succeeded.
  • LoadPR always returns true if the file opens, even if the meta-header parse fails. If parse fails, m_pScoreObjects = NULL ¡æ nPlayers = 0 ¡æ DoPrint returns 0 silently.
  • AssetsDirectory1 has no trailing backslash (stripped in InitInstance).

Hypotheses explored (and ruled out)

Hypothesis Status
MySQL blocks before PrintDlg ? Wrong ? DB_ExportMatch is called after PrintDlg
MW4PRINT not defined ? Defined in mw4dummy.h
options.ini path fix breaks layout ? All params clamped; can't cause crash
Message-map corruption from new dialogs ? Maps look correct
LoadPR always fails ? Returns true if file exists, regardless of parse
Memory corruption from DB code Unconfirmed
PrintDlg returns FALSE (no default printer) Active hypothesis
nPlayers == 0 (parse failure / all bots) Active hypothesis

Current debugging approach

Commit 3256c103 adds a -debug flag. Run:

mw4print.exe -debug

Output goes to mw4print-debug.txt next to the exe (append, timestamped).

What the log tells us

DoPrint: nPlayers=0

¡æ File opened but no players found. Either the .pr file has an unrecognised meta header, or all players are bots and g_bPRTest=false (no "Include Bot" checkbox ticked).

DoPrint: PrintDlg FAILED nErr=-1, CommDlgExtendedError=0000100A

¡æ CDERR_NODEFAULTPRN ? no default printer is configured on this machine.

DoPrint: PrintDlg FAILED nErr=-1, CommDlgExtendedError=00000000

¡æ PrintDlg returned FALSE with no error. Unusual; may indicate a hidden dialog or modal conflict.

OnTimer: LoadPR FAILED for 'C:\...'

¡æ fopen failed ? file was deleted between WM_COPYDATA arriving and the timer firing.


Next steps

  1. Build from current source on Windows (quick ? only ChildView.cpp recompiles).
  2. Run mw4print.exe -debug, do File ¡æ Open on a known .pr file, wait 2 seconds.
  3. Read mw4print-debug.txt and look for the first failure line.
  4. Act on the specific error:
    • nPlayers=0 ¡æ check .pr file validity; check if "Include Bot" is needed
    • CommDlgExtendedError=0000100A ¡æ configure a default printer on the test machine
    • Other ¡æ investigate that specific failure path