paavohtl Claude Opus 4.6 (1M context) commited on
Commit
d6d409e
Β·
1 Parent(s): 305964e

fix: enable loading progress ticks, fix _field_4dc condition

Browse files

- Enable DDGameWrapper__LoadingProgressTick calls (4 total) that were
disabled β€” these update wrapper+0x4D8/4DC/4E0 progress fields
- Fix _field_4dc condition: check net_game null (original checks
display null, but our headless display is non-null)
- Add DDGameWrapper shadow dump for comparison

Headful replay completes. Headless still has frame-0 checksum mismatch.
Wrapper fields 0x4D8/4DC/4E0 now closer to original.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

crates/openwa-core/src/engine/ddgame.rs CHANGED
@@ -1237,7 +1237,9 @@ unsafe fn init_graphics_and_resources(
1237
 
1238
  // ── DDGameWrapper field inits ──
1239
  (*wrapper)._field_4d8 = 0;
1240
- if display.is_null() || net_game.is_null() {
 
 
1241
  (*wrapper)._field_4dc = 0x2AD;
1242
  } else {
1243
  let byte_val = *net_game.add(0x44C) as u32;
@@ -1273,9 +1275,9 @@ unsafe fn init_graphics_and_resources(
1273
 
1274
  let _ = crate::log::log_line("[DDGame] past ActiveSoundTable");
1275
 
1276
- // ── Loading tick: disabled (pumps message loop, causes crashes) ──
1277
- // call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1278
- // call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1279
 
1280
  // ── GfxResource: thiscall(ECX=gfx_handler) + EAX=name + 1 stack(output), RET 0x4 ──
1281
  // Test: call GfxResource with real params
@@ -1540,9 +1542,9 @@ unsafe fn init_graphics_and_resources(
1540
  // TODO: populate coord_list from landscape data (complex loop)
1541
  }
1542
 
1543
- // ── Loading tick: disabled (pumps message loop) ──
1544
- // call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1545
- // call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1546
 
1547
  // ── Sprite resource loading via DDGameWrapper vtable[0] ──
1548
  // DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
 
1237
 
1238
  // ── DDGameWrapper field inits ──
1239
  (*wrapper)._field_4d8 = 0;
1240
+ // Original checks `display == NULL`, but our headless display is non-null.
1241
+ // Use net_game null check as equivalent (net_game is null in headless/offline modes).
1242
+ if net_game.is_null() {
1243
  (*wrapper)._field_4dc = 0x2AD;
1244
  } else {
1245
  let byte_val = *net_game.add(0x44C) as u32;
 
1275
 
1276
  let _ = crate::log::log_line("[DDGame] past ActiveSoundTable");
1277
 
1278
+ // ── Loading progress ticks (original calls DDGameWrapper__LoadingProgressTick twice here) ──
1279
+ call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1280
+ call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1281
 
1282
  // ── GfxResource: thiscall(ECX=gfx_handler) + EAX=name + 1 stack(output), RET 0x4 ──
1283
  // Test: call GfxResource with real params
 
1542
  // TODO: populate coord_list from landscape data (complex loop)
1543
  }
1544
 
1545
+ // ── Loading progress ticks (second pair, before sprite resource loading) ──
1546
+ call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1547
+ call_usercall_ecx(wrapper, LOADING_PROGRESS_TICK_ADDR);
1548
 
1549
  // ── Sprite resource loading via DDGameWrapper vtable[0] ──
1550
  // DDNetGameWrapper__LoadResourceList: thiscall(ECX=wrapper) +
crates/openwa-wormkit/src/replacements/game_session.rs CHANGED
@@ -163,6 +163,29 @@ pub(crate) unsafe fn construct_ddgame_wrapper(
163
  ));
164
  }
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  // Initialize DDGame's game-state fields.
167
  let _ = log_line("[GameSession] calling InitGameState");
168
  let init_state: unsafe extern "stdcall" fn(*mut DDGameWrapper) =
 
163
  ));
164
  }
165
 
166
+ // Dump DDGameWrapper state
167
+ if std::env::var("OPENWA_VALIDATE").is_ok() {
168
+ let wrapper_dwords = this as *const u32;
169
+ // DDGameWrapper is ~0x6EF0 bytes (from DDGameWrapper__Constructor at 0x56DEF0)
170
+ let w_count = 0x6EF0 / 4;
171
+ let mut w_nonzero = 0u32;
172
+ let _ = log_line("[Shadow:Wrapper] === DDGameWrapper ===");
173
+ for i in 0..w_count {
174
+ let val = *wrapper_dwords.add(i);
175
+ if val != 0 {
176
+ w_nonzero += 1;
177
+ if w_nonzero <= 200 {
178
+ let _ = log_line(&format!(
179
+ "[Shadow:Wrapper] +0x{:04X} = 0x{:08X}", i * 4, val,
180
+ ));
181
+ }
182
+ }
183
+ }
184
+ let _ = log_line(&format!(
185
+ "[Shadow:Wrapper] Total non-zero: {} / {}", w_nonzero, w_count,
186
+ ));
187
+ }
188
+
189
  // Initialize DDGame's game-state fields.
190
  let _ = log_line("[GameSession] calling InitGameState");
191
  let init_state: unsafe extern "stdcall" fn(*mut DDGameWrapper) =