@@ -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// ---------------------------------------------------------------------------------------
0 commit comments