Merge replay-test.ps1's headful mode into openwa-test as a new
`headful` subcommand. Runs with graphics+sound, checks for crashes,
panics, and [GAMEPLAY PASS/FAIL] markers. Supports filter by name
or direct .WAgame path, with configurable --timeout (default 150s).
replay-test.ps1 is now a thin wrapper like run-tests.ps1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix: use openwa-config registry lookup in replay-test.ps1
The script had a hardcoded fallback path (I:\games\...) that broke on
machines with WA installed elsewhere. Now resolves the WA directory
using the same OPENWA_WA_PATH env var / HKCU registry key priority
as the openwa-config crate, matching run-tests.ps1 behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
refactor: replace validation module with registry-driven startup checks
Delete the 2100-line validation/ module (stale checks, wrong vtable slot,
no-op hooks, sleep-based dumps) and replace with ~120-line startup_checks.rs
that auto-generates all checks from define_addresses! and #[vtable(...)]
metadata. Checks run unconditionally at DLL load — no OPENWA_VALIDATE env
var needed. Test runner scans OpenWA.log for [CHECK FAIL] and reports once.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add gameplay milestone checks to replay testing
Replace misleading "133 PASS" output (all static checks) with two
distinct categories:
- Static checks ([STATIC PASS/FAIL]): vtables, struct offsets, prologues
- Gameplay checks ([GAMEPLAY PASS/FAIL]): game init, match start, match end
Gameplay milestones are detected hook-based via TurnManager_ProcessFrame
(no timers): frame counter for init, health-based alive-team counting
for match start/completion. Report written from DLL_PROCESS_DETACH.
Key finding: team arena indices are 1-based (index 0 is unused preamble),
and sentinel header fields like worm_count are populated lazily — direct
worm health checks are more reliable for early-frame detection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: port 5 DDGame constructor sub-functions to Rust hooks
Port DDGame constructor sub-functions as individual MinHook replacements,
so each works in isolation regardless of whether the DDGame constructor
itself is Rust or original WA code. All 5 hooks verified with replay
test (133 PASS, 0 FAIL).
Ported functions:
- DDGame__InitFields (0x526120): zeroes scattered offsets + render indices
- DDGame__InitRenderIndices (0x526080): identity permutation tables at
ddgame+0x72D8 (team index maps, NOT base of DDGame)
- TaskStateMachine__Init (0x4F6370): bit-per-cell grid allocator
- GfxResource__Create_Maybe (0x4F6300): FindEntry → cached load → DisplayGfx
wrap, with LoadImage → IMG_Decode fallback
- FUN_570E20 / DDGame__InitDisplayLayerColors: 3 display vtable[4] calls
Key bugs found and fixed:
- InitRenderIndices base pointer: ESI = ddgame+0x72D8, not ddgame itself.
Original was writing render indices to team_index_map region.
- InitFields return value: caller stores EAX as DDGame pointer at
wrapper+0x488. Missing return caused null DDGame…
feat: integrate ERRORLOG.TXT into replay testing flow
Clear ERRORLOG.TXT before each test run, copy to testdata/logs/ when
present after a run, and report crash with first 5 lines before any
other summary output. Exit code 1 on crash detection.
Crash check runs before the log diff/validation summary to ensure it
is always visible even when the diff would also fail.
Update CLAUDE.md and replay-test skill docs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add -Headless flag to replay-test.ps1 that uses WA's /getlog mode for
pure-simulation replay testing. Compares output log byte-for-byte
against bots_expected.log to verify replay determinism.
Update replay-test skill docs to cover both modes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add CTaskFire and CTaskTurnGame structs with runtime validation
- CTaskFire (0xD8 bytes, class_type=0x18): spawn coords, timer, burn_rate,
spread_counter, lifetime, slot_index fields
- CTaskTurnGame (0x2E0 bytes): 15 named fields covering timers (turn_timer
+0x18C, idle_timer +0x184, retreat_timer +0x178), team tracking
(current_team, current_worm, arena_team, arena_worm), and frame counters
(active_worm_frames, retreat_frames, _timer_scale); all offsets runtime-
validated via offset_of! checks (15 PASS)
- dump_turngame(): finds TurnGame via vtable scan + SharedDataTable, dumps
known fields and full 0x2E0-byte raw region via dump_region
- dump_region refactored from DDGame-specific to generic *const u8 base
- replay-test.ps1: fix launcher invocation (pass $waExe explicitly so
replay file is forwarded as a WA.exe arg, not misinterpreted as exe path)
- Debug UI inspector sections for CTaskFire and CTaskTurnGame
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: replace WormKit injection with custom launcher (openwa-launcher)
New binary crate `openwa-launcher` creates WA.exe in a suspended state,
injects openwa_wormkit.dll via CreateRemoteThread(LoadLibraryA), waits for
DllMain to complete (all hooks installed), then resumes the main thread.
This guarantees hooks are in place before a single WA instruction runs and
requires zero modifications to the game folder.
- WA.exe location: CLI arg > OPENWA_WA_PATH env var > Steam registry
- DLL location: always next to the launcher executable
- Forwards all CLI args (replay file etc.) to WA.exe
- Supports --minimized flag (used by replay-test.ps1)
- Remove deploy.ps1 / deploy-debug.ps1 (no longer needed)
- Update replay-test.ps1 to build + run via launcher; removes DLL copy step
- Update start-debug.ps1 to invoke launcher directly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: replay fast-forward via PostMessage + WndProc subclass
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>
feat: unify validator into wormkit DLL, triggered via OPENWA_VALIDATE env var
Merge validation logic from openwa-validator into openwa-wormkit as a
conditional module. Set OPENWA_VALIDATE=1 to enable validation checks,
OPENWA_REPLAY_TEST=1 for auto-capture mode. Eliminates the need for a
separate wkOpenWAValidator.dll.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: launch WA.exe minimized in replay test to prevent focus steal