File size: 3,716 Bytes
a8f286b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | # Frontend__MainNavigationLoop (0x4E6700)
Ghidra address: `0x004E6700`
Calling convention: `__fastcall` (ECX = CWinApp*)
Size: ~3500 lines of decompiled C
This is the main entry point / event loop of WA.exe. It handles:
- Command-line argument parsing
- Crash handling (`/handlecrash`, `/silentcrash`, `/disablecrashhandler`)
- Replay playback (`/play`, `/playat`, `/getlog`, `/getmap`, `/getscheme`, `/getvideo`, `/getlogs`)
- Sanitize/repair modes (`/sanitise`, `/repair`)
- Network hosting (`/host`, `wa:` protocol)
- WormKit module loading (`/wk`, `/nowk`, `/wkargs`)
- Frontend screen navigation loop (main menu, multiplayer, campaigns, etc.)
- Renderer selection (DirectDraw, OpenGL, D3D9, etc.)
## Crash Handler Mechanism
WA.exe's crash handler works by **relaunching itself** with `/handlecrash`:
1. Original WA.exe crashes (C++ exception via `__CxxThrowException`)
2. The crash handler (likely SEH-based) writes `ERRORLOG.TXT` and relaunches WA.exe with `/handlecrash`
3. The new WA.exe instance processes `/handlecrash` in this function
4. It checks `Options__GetCrashReportURL()` β if crash reporting is available, shows a dialog offering to send the report
5. It checks `DAT_0088e410` (WormKit modules loaded flag) β if set, shows the "Fatal error" dialog with Yes/No asking to disable WormKit modules
### Key flags:
- `/silentcrash` β sets `DAT_007a0f10+1 = 1` β suppresses the crash dialog
- `/disablecrashhandler` β sets `DAT_007a0f10+0 = 1` β disables the crash handler entirely
- `/crash` β intentionally crashes via `__CxxThrowException("Goodbye, cruel world!")`
### Crash dialog code (at ~0x4E6730):
```c
// Check for crash report URL
iVar11 = Options__GetCrashReportURL();
if (iVar11 != 0) {
// Show "send bug report?" dialog (MB_YESNO | MB_ICONQUESTION = 0x14)
iVar10 = MessageBoxA(NULL,
"Worms Armageddon has encountered an error...\nWould you like to send the bug report?",
"Fatal error", 0x14);
if (iVar10 == IDYES) FUN_005a6470(); // send crash report
}
// Check if WormKit modules were loaded
if (DAT_0088e410 == 0) {
// No WormKit β just show error (MB_ICONERROR = 0x10)
MessageBoxA(NULL, error_msg, "Fatal error", 0x10);
} else {
// WormKit loaded β ask to disable (MB_YESNO | MB_ICONQUESTION = 0x14)
FUN_00444d30(); // builds error message mentioning WormKit
iVar11 = MessageBoxA(NULL, error_msg, "Fatal error", 0x14);
if (iVar11 == IDYES) {
DAT_0088e410 = 0;
FUN_004c8c70(); // disable WormKit in registry
MessageBoxA(NULL, "WormKit modules have been disabled.", "Worms Armageddon", 0x40);
}
}
```
## ERRORLOG.TXT
String at `0x00677FE0`: `"ERRORLOG.TXT"`
String at `0x00678484`: `"Can't open ERRORLOG.TXT"`
Written by the crash handler before relaunching (separate from this function).
## `/getlog` Mode
The `/getlog` flag sets:
- `DAT_0088cd4c = 1` (headless replay mode)
- `local_31 = 1` (getlog flag)
- Copies replay path to `DAT_0088af58`
Later in the function, `/getlog` mode opens the replay for writing the game log output.
## WormKit Module Loading
Around line 1200 of decompilation:
- Searches for `wk*.dll` files in the game directory
- Loads each via `LoadLibraryA`
- If loading fails, shows a MessageBox with the error
- Flag at `DAT_0088e410` tracks whether WormKit modules are loaded
## Key Addresses
| Address | Purpose |
|---------|---------|
| `0x007A0F10+0` | `/disablecrashhandler` flag |
| `0x007A0F10+1` | `/silentcrash` flag |
| `0x0088E410` | WormKit modules loaded flag |
| `0x0088AF58` | Replay path buffer |
| `0x0088CD4C` | Headless replay mode flag |
| `0x0088E17D` | Current directory buffer |
| `0x006B1FEC` | argc |
| `0x006B1FF0` | argv |
|