paavohtl Claude Opus 4.6 (1M context) commited on
Commit
b7c455f
Β·
1 Parent(s): 06e639d

feat: replace DSSound slot 0 (destructor) with Rust

Browse files

Releases all COM objects in correct order: 8 channel desc buffers
(Stop + Release), 500 channel slot buffers (Release), primary buffer
(Stop + Release), IDirectSound (Release). Sets secondary vtable at end.

Update Ghidra names for all converted DSSound vtable methods.

22/24 DSSound vtable slots now Rust. Only slots 3 (play_sound) and
4 (play_sound_pooled) remain.

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

crates/openwa-core/src/audio/dssound.rs CHANGED
@@ -396,6 +396,60 @@ pub unsafe extern "thiscall" fn set_channel_volume(
396
  1
397
  }
398
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  /// Slot 14: sub_destructor β€” sets secondary vtable (0x66AF58), optionally frees.
400
  /// This is a base-class destructor called by the primary destructor (slot 0).
401
  pub unsafe extern "thiscall" fn sub_destructor(
 
396
  1
397
  }
398
 
399
+ /// Slot 0: destructor β€” releases all COM objects and frees memory.
400
+ pub unsafe extern "thiscall" fn destructor(
401
+ this: *mut DSSound, flags: u8,
402
+ ) -> *mut DSSound {
403
+ let snd = &mut *this;
404
+
405
+ // Reset vtable to primary (destructor chain pattern).
406
+ use crate::address::va;
407
+ use crate::rebase::rb;
408
+ snd.vtable = rb(va::DS_SOUND_VTABLE) as *const DSSoundVtable;
409
+
410
+ // Release all 8 channel descriptor buffers (Stop + Release).
411
+ for desc in &mut snd.channel_descs {
412
+ if let Some(buf) = desc.take_buffer() {
413
+ let _ = buf.Stop();
414
+ // Release on drop
415
+ }
416
+ }
417
+
418
+ // Release all 500 channel slot buffers.
419
+ for slot in &mut snd.channel_slots {
420
+ if *slot != 0 {
421
+ let buf: IDirectSoundBuffer = core::mem::transmute_copy(slot);
422
+ // Release on drop (no Stop needed β€” these are template buffers)
423
+ drop(buf);
424
+ *slot = 0;
425
+ }
426
+ }
427
+
428
+ // Release primary buffer (Stop + Release).
429
+ if snd.primary_buffer != 0 {
430
+ let buf: IDirectSoundBuffer = core::mem::transmute_copy(&snd.primary_buffer);
431
+ let _ = buf.Stop();
432
+ drop(buf);
433
+ snd.primary_buffer = 0;
434
+ }
435
+
436
+ // Release IDirectSound.
437
+ if snd.direct_sound != 0 {
438
+ use windows::Win32::Media::Audio::DirectSound::IDirectSound;
439
+ let ds: IDirectSound = core::mem::transmute_copy(&snd.direct_sound);
440
+ drop(ds);
441
+ snd.direct_sound = 0;
442
+ }
443
+
444
+ // Set secondary vtable (base class destructor pattern).
445
+ snd.vtable = rb(0x0066_AF58) as *const DSSoundVtable;
446
+
447
+ if flags & 1 != 0 {
448
+ crate::wa_alloc::wa_free(this as *mut u8);
449
+ }
450
+ this
451
+ }
452
+
453
  /// Slot 14: sub_destructor β€” sets secondary vtable (0x66AF58), optionally frees.
454
  /// This is a base-class destructor called by the primary destructor (slot 0).
455
  pub unsafe extern "thiscall" fn sub_destructor(
crates/openwa-core/src/audio/mod.rs CHANGED
@@ -8,6 +8,7 @@ pub mod streaming;
8
  pub use active_sound::{ActiveSoundEntry, ActiveSoundTable};
9
  pub use dssound::{DSSound, DSSoundVtable, ChannelDescriptor};
10
  pub use dssound::{
 
11
  update_channels, release_finished,
12
  is_slot_loaded, is_channel_finished, stop_channel,
13
  set_volume_params, set_master_volume, set_channel_volume, set_pan,
 
8
  pub use active_sound::{ActiveSoundEntry, ActiveSoundTable};
9
  pub use dssound::{DSSound, DSSoundVtable, ChannelDescriptor};
10
  pub use dssound::{
11
+ destructor as dssound_destructor,
12
  update_channels, release_finished,
13
  is_slot_loaded, is_channel_finished, stop_channel,
14
  set_volume_params, set_master_volume, set_channel_volume, set_pan,
crates/openwa-wormkit/src/replacements/sound.rs CHANGED
@@ -170,6 +170,7 @@ unsafe fn patch_dssound_vtable() -> Result<(), String> {
170
  use openwa_core::audio::{
171
  update_channels, release_finished,
172
  is_slot_loaded, is_channel_finished, stop_channel,
 
173
  set_volume_params, set_master_volume, set_channel_volume, set_pan,
174
  dssound_sub_destructor,
175
  load_wav, dssound_noop, dssound_returns_0, dssound_returns_1,
@@ -181,6 +182,9 @@ unsafe fn patch_dssound_vtable() -> Result<(), String> {
181
  // Slot 12: load_wav β€” WAV file β†’ DirectSound secondary buffer (hound + windows crate)
182
  *vt.add(12) = load_wav as *const () as u32;
183
 
 
 
 
184
  // Slot 1: update_channels β€” release finished buffers each frame
185
  *vt.add(1) = update_channels as *const () as u32;
186
 
@@ -223,6 +227,6 @@ unsafe fn patch_dssound_vtable() -> Result<(), String> {
223
  // Trivial returns-1 (slot 23)
224
  *vt.add(23) = dssound_returns_1 as *const () as u32;
225
 
226
- let _ = log_line("[Sound] DSSound vtable: patched 21/24 slots with Rust");
227
  }).map_err(|e| e.to_string())
228
  }
 
170
  use openwa_core::audio::{
171
  update_channels, release_finished,
172
  is_slot_loaded, is_channel_finished, stop_channel,
173
+ dssound_destructor,
174
  set_volume_params, set_master_volume, set_channel_volume, set_pan,
175
  dssound_sub_destructor,
176
  load_wav, dssound_noop, dssound_returns_0, dssound_returns_1,
 
182
  // Slot 12: load_wav β€” WAV file β†’ DirectSound secondary buffer (hound + windows crate)
183
  *vt.add(12) = load_wav as *const () as u32;
184
 
185
+ // Slot 0: destructor β€” releases all COM objects
186
+ *vt.add(0) = dssound_destructor as *const () as u32;
187
+
188
  // Slot 1: update_channels β€” release finished buffers each frame
189
  *vt.add(1) = update_channels as *const () as u32;
190
 
 
227
  // Trivial returns-1 (slot 23)
228
  *vt.add(23) = dssound_returns_1 as *const () as u32;
229
 
230
+ let _ = log_line("[Sound] DSSound vtable: patched 22/24 slots with Rust");
231
  }).map_err(|e| e.to_string())
232
  }