Automatically fast-forward through entire replays during testing by
posting WM_KEYDOWN/WM_KEYUP spacebar messages with 50ms gaps. Subclasses
the game's WndProc to intercept WM_ACTIVATE/WM_ACTIVATEAPP, making WA
think it always has focus so input works even when the window is in the
background.
- Add input.rs with PostMessage loop + WndProc subclass
- Update validation auto-capture: dump at 8s, 120s safety timeout
- Update replay-test.ps1 with 150s timeout
- Add DDKeyboard::PollKeyboardState address
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design for launching WA.exe with replay files for automated
validation and RE discovery. Validator DLL detects automated mode
via OPENWA_REPLAY_TEST env var and self-terminates after capture.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docs: add configuration system design and implementation plan
Design doc and implementation plan for porting WA's configuration
subsystem (Theme I/O, Registry, GameInfo, CrashReportURL) to Rust.
These were used to guide the config.rs implementation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add offline test harness that loads WA.exe and calls its functions
Loads WA.exe into a 32-bit test process via LoadLibraryExA with
DONT_RESOLVE_DLL_REFERENCES, patches the IAT (445 imports), initializes
the statically-linked MSVC CRT heap, and successfully calls WA.exe
functions including malloc and CTask::Constructor.
9 tests: PE loading, vtable validation, prologue checks, IAT patching,
malloc wrapper call, and CTask constructor call with SEH support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ASLR rebasing (GetModuleHandleA) — WA.exe loads at 0x90000, not 0x400000
- Replace retour constructor hooks with global pointer polling (10s delay)
Hooks crashed due to retour trampoline splitting SEH prologues
- Fix DDGameWrapper constructor: __stdcall with 7 params, not __thiscall
Confirmed via RET 0x1c and stack parameter access patterns
- Fix CTask constructor: __stdcall with 3 params, not __thiscall
Confirmed via RET 0xc
- Add G_GAME_SESSION (0x7A0884) global for polling DDGameWrapper at runtime
- Fix DDGameWrapper struct: +0x4C0 is not GfxHandler, +0x4D4 is sound ptr
- Remove retour dependency (no longer needed, builds on stable Rust)
- Add missing prologue bytes: 0x64 (FS: SEH), 0x85 (test), 0x8D (lea)
Results: 78/78 static + 6/6 deferred = 84/84 all passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Initial openwa-types crate: enums, structs, and RE addresses
Bootstrap the Rust type foundation for WA 3.8.1 reverse engineering:
- Cargo workspace with openwa-types crate
- Enums translated from wkJellyWorm: ClassType (34), TaskMessage (83+),
Weapon (71), SoundId (126), SpriteId (696)
- Fixed-point math newtype (16.16 format, 0x10000 = 1.0)
- CTask and CGameTask struct stubs with compile-time size assertions
- 80+ known addresses: vtables, constructors, gameplay, rendering, sound
- RE documentation: task hierarchy, vtable layouts, memory map
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>