Skip to content

Commit 6b43cab

Browse files
authored
Fix CTD when an interface sound is shared with a gameplay sound (#7488)
1 parent 14b0edc commit 6b43cab

5 files changed

Lines changed: 32 additions & 0 deletions

File tree

code/gamesnd/gamesnd.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ void gamesnd_unload_gameplay_sounds()
601601
}
602602
}
603603
}
604+
snd_unload_cleanup();
604605
}
605606

606607
/**
@@ -636,6 +637,7 @@ void gamesnd_unload_interface_sounds()
636637
}
637638
}
638639
}
640+
snd_unload_cleanup();
639641
}
640642

641643
void parse_gamesnd_old(game_snd* gs)

code/mission/missionmessage.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ void message_mission_shutdown()
10071007
snd_unload( Message_waves[i].num );
10081008
}
10091009
}
1010+
snd_unload_cleanup();
10101011

10111012
fsspeech_stop();
10121013

code/scripting/api/objs/sound.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ ADE_FUNC(unload, l_Soundfile, nullptr,
481481
return ade_set_error(L, "b", false);
482482

483483
auto result = snd_unload(handle->idx);
484+
snd_unload_cleanup();
484485

485486
if (result != 0) {
486487
// Invalidate this handle so that the script cannot do something bad with it

code/sound/sound.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@ sound_load_id snd_load(game_snd_entry* entry, int *flags, int /*allow_hardware_l
481481
return sound_load_id(static_cast<int>(n));
482482
}
483483

484+
static SCP_set<sound_load_id> Unloaded_sound_ids;
485+
484486
// ---------------------------------------------------------------------------------------
485487
// snd_unload()
486488
//
@@ -504,6 +506,8 @@ int snd_unload(sound_load_id n)
504506

505507
ds_unload_buffer(snd.sid);
506508

509+
Unloaded_sound_ids.emplace(n);
510+
507511
if (snd.sid != -1) {
508512
Snd_sram -= snd.uncompressed_size;
509513
}
@@ -530,6 +534,29 @@ void snd_unload_all()
530534
while ( !Sounds.empty() ) {
531535
snd_unload(sound_load_id((int)(Sounds.size() - 1)));
532536
}
537+
snd_unload_cleanup();
538+
}
539+
540+
// If two tabled sounds share a sound file, unloading one will not correctly invalidate the index of the other,
541+
// causing a CTD when trying to play the other sound.
542+
// To fix this, every time we unload ANY sound, we must iterate over all tabled sounds, and invalidate their indices
543+
// if the given sound ID has been unloaded.
544+
void snd_unload_cleanup() {
545+
for (auto& snd : Snds) {
546+
for (auto& entry : snd.sound_entries) {
547+
if (Unloaded_sound_ids.contains(entry.id)) {
548+
entry.id = sound_load_id::invalid();
549+
}
550+
}
551+
}
552+
for (auto& snd : Snds_iface) {
553+
for (auto& entry : snd.sound_entries) {
554+
if (Unloaded_sound_ids.contains(entry.id)) {
555+
entry.id = sound_load_id::invalid();
556+
}
557+
}
558+
}
559+
Unloaded_sound_ids.clear();
533560
}
534561

535562
// ---------------------------------------------------------------------------------------

code/sound/sound.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ sound_load_id snd_load(game_snd_entry* entry, int* flags, int allow_hardware_loa
136136

137137
int snd_unload(sound_load_id sndnum);
138138
void snd_unload_all();
139+
void snd_unload_cleanup();
139140

140141
// Plays a sound with volume between 0 and 1.0, where 0 is the
141142
// inaudible and 1.0 is the loudest sound in the game.

0 commit comments

Comments
 (0)