paavohtl Claude Opus 4.6 (1M context) commited on
Commit
5724790
Β·
1 Parent(s): f2fe683

fix: correct SpriteRegion params from hook data + pass gfx_resource

Browse files

SpriteRegion params 4-8 were completely wrong (guessed from asm,
not verified). Hooked SpriteRegion__Constructor with naked fastcall
trampoline to capture actual params from original:
- Entries 4-8: ECX/EDX values were wrong (0x21β†’0x0C, etc.)
- p6 (6th stack param): was 0, should be GfxResource pointer

2/5 runs now pass. Crash moved to GfxDir__FindEntry in arrow loop β€”
likely a calling convention issue in the arrow sprite loading section.

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

crates/openwa-core/src/engine/ddgame.rs CHANGED
@@ -818,16 +818,19 @@ unsafe fn init_graphics_and_resources(
818
  // ── 8Γ— SpriteRegion at DDGame+0x46C..0x488 ──
819
  // SpriteRegion__Constructor: fastcall(ECX, EDX) + 6 stack(this, p2, p3, p4, p5, p6), RET 0x18
820
  {
821
- // (ddgame_offset, ECX, EDX, stack2, stack3, stack4, stack5, stack6)
 
 
 
822
  let regions: [(u32, u32, u32, u32, u32, u32, u32, u32); 8] = [
823
- (0x474, 0x37, 0x36, 0x2E, 0x24, 0x41, 0x2D, 0),
824
- (0x46C, 0x30, 0x0C, 0x2D, 0x07, 0x34, 0x09, 0),
825
- (0x470, 0x11, 0x1A, 0x0D, 0x0A, 0x16, 0x13, 0),
826
- (0x478, 0x21, 0x01, 0x00, 0x20, 0x22, 0x01, 0),
827
- (0x47C, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0),
828
- (0x484, 0x0A, 0x01, 0x173, 0x09, 0x17C, 0x02, 0),
829
- (0x488, 0x08, 0x01, 0x1E5, 0x07, 0x1EC, 0x02, 0),
830
- (0x480, 0x08, 0x01, 0x2D, 0x07, 0x34, 0x02, 0),
831
  ];
832
 
833
  for &(offset, ecx, edx, p2, p3, p4, p5, p6) in &regions {
 
818
  // ── 8Γ— SpriteRegion at DDGame+0x46C..0x488 ──
819
  // SpriteRegion__Constructor: fastcall(ECX, EDX) + 6 stack(this, p2, p3, p4, p5, p6), RET 0x18
820
  {
821
+ // Params verified by hooking original (see SpriteRegion param logger).
822
+ // (ddgame_offset, ECX, EDX, p2, p3, p4, p5, p6=gfx_resource)
823
+ // p6 is the GfxResource pointer returned by GfxResource__Create_Maybe.
824
+ let gr = gfx_resource as u32;
825
  let regions: [(u32, u32, u32, u32, u32, u32, u32, u32); 8] = [
826
+ (0x474, 0x37, 0x36, 0x2E, 0x24, 0x41, 0x2D, gr),
827
+ (0x46C, 0x30, 0x0C, 0x2D, 0x07, 0x34, 0x09, gr),
828
+ (0x470, 0x11, 0x1A, 0x0D, 0x0A, 0x16, 0x13, gr),
829
+ (0x478, 0x0C, 0x3D, 0x00, 0x20, 0x18, 0x33, gr),
830
+ (0x47C, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, gr),
831
+ (0x484, 0x1A2,0x1B, 0x173,0x09, 0x1D8,0x03, gr),
832
+ (0x488, 0x1EF,0x26, 0x1E5,0x07, 0x1F9,0x16, gr),
833
+ (0x480, 0x2D, 0x08, 0x2D, 0x07, 0x2E, 0x07, gr),
834
  ];
835
 
836
  for &(offset, ecx, edx, p2, p3, p4, p5, p6) in &regions {
crates/openwa-wormkit/src/replacements/game_session.rs CHANGED
@@ -322,6 +322,51 @@ unsafe extern "stdcall" fn hook_pc_landscape_ctor(
322
  orig(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
323
  }
324
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  pub fn install() -> Result<(), String> {
326
  unsafe {
327
  INIT_REPLAY_ADDR = rb(va::DDGAMEWRAPPER_INIT_REPLAY);
@@ -338,6 +383,14 @@ pub fn install() -> Result<(), String> {
338
  hook_pc_landscape_ctor as *const (),
339
  )?;
340
  PC_LANDSCAPE_TRAMPOLINE = tramp as *const ();
 
 
 
 
 
 
 
 
341
  }
342
  Ok(())
343
  }
 
322
  orig(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
323
  }
324
 
325
+ // ── SpriteRegion__Constructor param logger ──────────────────────────
326
+ static mut SPRITE_REGION_TRAMPOLINE: *const () = core::ptr::null();
327
+
328
+ /// Log fastcall params. Called from naked trampoline with all params on stack.
329
+ unsafe extern "cdecl" fn log_sprite_region(
330
+ ecx: u32, edx: u32, p1: u32, p2: u32, p3: u32, p4: u32, p5: u32, p6: u32,
331
+ ) {
332
+ let _ = log_line(&format!(
333
+ "[SpriteRgn] ECX=0x{:X} EDX=0x{:X} p1=0x{:X} p2=0x{:X} p3=0x{:X} p4=0x{:X} p5=0x{:X} p6=0x{:X}",
334
+ ecx, edx, p1, p2, p3, p4, p5, p6));
335
+ }
336
+
337
+ /// Naked trampoline: captures ECX/EDX, logs, then calls original fastcall.
338
+ #[unsafe(naked)]
339
+ unsafe extern "C" fn hook_sprite_region_ctor() {
340
+ core::arch::naked_asm!(
341
+ // Save all regs
342
+ "pushl %eax",
343
+ "pushl %ecx",
344
+ "pushl %edx",
345
+ // Push all 8 params for logger: ECX, EDX, then 6 stack params
346
+ // Stack after 3 pushes: [edx][ecx][eax][ret][p1][p2][p3][p4][p5][p6]
347
+ // p1 at ESP+16, p2 at ESP+20, ...
348
+ "pushl 36(%esp)", // p6
349
+ "pushl 36(%esp)", // p5
350
+ "pushl 36(%esp)", // p4
351
+ "pushl 36(%esp)", // p3
352
+ "pushl 36(%esp)", // p2
353
+ "pushl 36(%esp)", // p1
354
+ "pushl %edx", // EDX
355
+ "pushl %ecx", // ECX
356
+ "calll {logger}",
357
+ "addl $32, %esp", // clean 8 cdecl params
358
+ // Restore regs
359
+ "popl %edx",
360
+ "popl %ecx",
361
+ "popl %eax",
362
+ // Jump to original (fastcall, same params on stack)
363
+ "jmpl *({tramp})",
364
+ logger = sym log_sprite_region,
365
+ tramp = sym SPRITE_REGION_TRAMPOLINE,
366
+ options(att_syntax),
367
+ );
368
+ }
369
+
370
  pub fn install() -> Result<(), String> {
371
  unsafe {
372
  INIT_REPLAY_ADDR = rb(va::DDGAMEWRAPPER_INIT_REPLAY);
 
383
  hook_pc_landscape_ctor as *const (),
384
  )?;
385
  PC_LANDSCAPE_TRAMPOLINE = tramp as *const ();
386
+
387
+ // Hook SpriteRegion__Constructor to log fastcall params
388
+ let tramp2 = hook::install(
389
+ "SpriteRegion__Constructor",
390
+ va::SPRITE_REGION_CONSTRUCTOR,
391
+ hook_sprite_region_ctor as *const (),
392
+ )?;
393
+ SPRITE_REGION_TRAMPOLINE = tramp2 as *const ();
394
  }
395
  Ok(())
396
  }