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>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
GitHub Copilot
parent
3256c103a2
commit
77e19a723c
@@ -0,0 +1,168 @@
|
||||
# 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:
|
||||
|
||||
```cpp
|
||||
#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:
|
||||
|
||||
```cpp
|
||||
// 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 `#include`d 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
|
||||
Reference in New Issue
Block a user