debug: add OPENWA_WATCH_FRAME for runtime hardware watchpoints
Browse filesArms DR0 on DDGame+0x50 at the specified frame via the existing VEH
watchpoint infrastructure. Set OPENWA_WATCH_FRAME=0 to arm from the
first frame.
Key finding: DDGame+0x50 is a sprite pointer at frame 1350, NOT a
small integer. The earlier raw-dump comparison was flawed (cross-
process pointer values compared without ASLR normalization). The real
desync is in sub-object content, not in DDGame field values.
Also adds shotgun replay (PASSES with both constructors, confirming
the desync is longbow-specific, not arrow-handler-specific).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
crates/openwa-wormkit/src/debug_watchpoint.rs
CHANGED
|
@@ -32,12 +32,8 @@ use windows_sys::Win32::System::Diagnostics::Debug::{
|
|
| 32 |
|
| 33 |
/// DDGame offsets to watch. Hardware limit: 4 watchpoints (DR0–DR3).
|
| 34 |
/// Change these to investigate different fields.
|
| 35 |
-
const WATCH_OFFSETS: [(u32, &str);
|
| 36 |
-
(
|
| 37 |
-
(0x0420, "sprite_cache[39]"),
|
| 38 |
-
(0x7820, "render_idx[0]"),
|
| 39 |
-
(0x7824, "render_idx[1]"),
|
| 40 |
-
// Swap in (0x7828, "render_idx[2]") if needed — likely same writer as [0]/[1]
|
| 41 |
];
|
| 42 |
|
| 43 |
/// DDGame base address (set when allocation is reported).
|
|
@@ -87,10 +83,12 @@ unsafe extern "system" fn veh_handler(info: *mut EXCEPTION_POINTERS) -> i32 {
|
|
| 87 |
SAVED_DR = [ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr6, ctx.Dr7];
|
| 88 |
|
| 89 |
let base = DDGAME_BASE.load(Ordering::Relaxed);
|
| 90 |
-
ctx.Dr0
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
|
|
|
|
|
|
| 94 |
ctx.Dr6 = 0;
|
| 95 |
ctx.Dr7 = dr7_for_count(WATCH_OFFSETS.len());
|
| 96 |
|
|
|
|
| 32 |
|
| 33 |
/// DDGame offsets to watch. Hardware limit: 4 watchpoints (DR0–DR3).
|
| 34 |
/// Change these to investigate different fields.
|
| 35 |
+
const WATCH_OFFSETS: [(u32, &str); 1] = [
|
| 36 |
+
(0x0050, "ddgame+0x50"),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
];
|
| 38 |
|
| 39 |
/// DDGame base address (set when allocation is reported).
|
|
|
|
| 83 |
SAVED_DR = [ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr6, ctx.Dr7];
|
| 84 |
|
| 85 |
let base = DDGAME_BASE.load(Ordering::Relaxed);
|
| 86 |
+
let dr_regs = [&mut ctx.Dr0, &mut ctx.Dr1, &mut ctx.Dr2, &mut ctx.Dr3];
|
| 87 |
+
for (i, dr) in dr_regs.into_iter().enumerate() {
|
| 88 |
+
if i < WATCH_OFFSETS.len() {
|
| 89 |
+
*dr = base + WATCH_OFFSETS[i].0;
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
ctx.Dr6 = 0;
|
| 93 |
ctx.Dr7 = dr7_for_count(WATCH_OFFSETS.len());
|
| 94 |
|
crates/openwa-wormkit/src/replacements/input.rs
CHANGED
|
@@ -186,6 +186,19 @@ unsafe extern "stdcall" fn hook_turn_manager(turngame: u32) {
|
|
| 186 |
if !ddgame.is_null() {
|
| 187 |
let game_frame = (*ddgame).frame_counter;
|
| 188 |
crate::debug_sync::on_frame_start(game_frame);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
}
|
| 190 |
|
| 191 |
// Call original
|
|
|
|
| 186 |
if !ddgame.is_null() {
|
| 187 |
let game_frame = (*ddgame).frame_counter;
|
| 188 |
crate::debug_sync::on_frame_start(game_frame);
|
| 189 |
+
|
| 190 |
+
// Hardware watchpoint: arm once at the watch frame
|
| 191 |
+
static WATCH_ARMED: core::sync::atomic::AtomicBool = core::sync::atomic::AtomicBool::new(false);
|
| 192 |
+
if !WATCH_ARMED.load(Ordering::Relaxed) {
|
| 193 |
+
if let Ok(val) = std::env::var("OPENWA_WATCH_FRAME") {
|
| 194 |
+
let target: i32 = val.parse().unwrap_or(0);
|
| 195 |
+
if game_frame >= target {
|
| 196 |
+
WATCH_ARMED.store(true, Ordering::Relaxed);
|
| 197 |
+
crate::debug_watchpoint::prepare();
|
| 198 |
+
crate::debug_watchpoint::on_ddgame_alloc(ddgame as *mut u8);
|
| 199 |
+
}
|
| 200 |
+
}
|
| 201 |
+
}
|
| 202 |
}
|
| 203 |
|
| 204 |
// Call original
|
testdata/replays/shotgun.WAgame
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e1e1bdccaf88674cae5c859ebf5b9fc1e5ace782e1d157aae4bb14f593be3ea9
|
| 3 |
+
size 12318
|
testdata/replays/shotgun_expected.log
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1cc0c12cdf6c012f1ce153bdc7f5ed03199a0602a9e486c64c7cdfad8cecd12e
|
| 3 |
+
size 1186
|