Fix CTD when an interface sound is shared with a gameplay sound (#7488)

This commit is contained in:
BMagnu authored and GitHub committed 2026-05-30 23:45:22 +02:00
1 parent 14b0edcb95
commit 6b43cabff6
5 files changed
+32

No files matched your search

+2
View File
@@ -601,6 +601,7 @@ void gamesnd_unload_gameplay_sounds()
}
}
}
snd_unload_cleanup();
}
/**
@@ -636,6 +637,7 @@ void gamesnd_unload_interface_sounds()
}
}
}
snd_unload_cleanup();
}
void parse_gamesnd_old(game_snd* gs)
+1
View File
@@ -1007,6 +1007,7 @@ void message_mission_shutdown()
snd_unload( Message_waves[i].num );
}
}
snd_unload_cleanup();
fsspeech_stop();
+1
View File
@@ -481,6 +481,7 @@ ADE_FUNC(unload, l_Soundfile, nullptr,
return ade_set_error(L, "b", false);
auto result = snd_unload(handle->idx);
snd_unload_cleanup();
if (result != 0) {
// Invalidate this handle so that the script cannot do something bad with it
+27
View File
@@ -481,6 +481,8 @@ sound_load_id snd_load(game_snd_entry* entry, int *flags, int /*allow_hardware_l
return sound_load_id(static_cast<int>(n));
}
static SCP_set<sound_load_id> Unloaded_sound_ids;
// ---------------------------------------------------------------------------------------
// snd_unload()
//
@@ -504,6 +506,8 @@ int snd_unload(sound_load_id n)
ds_unload_buffer(snd.sid);
Unloaded_sound_ids.emplace(n);
if (snd.sid != -1) {
Snd_sram -= snd.uncompressed_size;
}
@@ -530,6 +534,29 @@ void snd_unload_all()
while ( !Sounds.empty() ) {
snd_unload(sound_load_id((int)(Sounds.size() - 1)));
}
snd_unload_cleanup();
}
// If two tabled sounds share a sound file, unloading one will not correctly invalidate the index of the other,
// causing a CTD when trying to play the other sound.
// To fix this, every time we unload ANY sound, we must iterate over all tabled sounds, and invalidate their indices
// if the given sound ID has been unloaded.
void snd_unload_cleanup() {
for (auto& snd : Snds) {
for (auto& entry : snd.sound_entries) {
if (Unloaded_sound_ids.contains(entry.id)) {
entry.id = sound_load_id::invalid();
}
}
}
for (auto& snd : Snds_iface) {
for (auto& entry : snd.sound_entries) {
if (Unloaded_sound_ids.contains(entry.id)) {
entry.id = sound_load_id::invalid();
}
}
}
Unloaded_sound_ids.clear();
}
// ---------------------------------------------------------------------------------------
+1
View File
@@ -136,6 +136,7 @@ sound_load_id snd_load(game_snd_entry* entry, int* flags, int allow_hardware_loa
int snd_unload(sound_load_id sndnum);
void snd_unload_all();
void snd_unload_cleanup();
// Plays a sound with volume between 0 and 1.0, where 0 is the
// inaudible and 1.0 is the loudest sound in the game.