Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/gamesnd/gamesnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ void gamesnd_unload_gameplay_sounds()
}
}
}
snd_unload_cleanup();
}

/**
Expand Down Expand Up @@ -636,6 +637,7 @@ void gamesnd_unload_interface_sounds()
}
}
}
snd_unload_cleanup();
}

void parse_gamesnd_old(game_snd* gs)
Expand Down
1 change: 1 addition & 0 deletions code/mission/missionmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,7 @@ void message_mission_shutdown()
snd_unload( Message_waves[i].num );
}
}
snd_unload_cleanup();

fsspeech_stop();

Expand Down
1 change: 1 addition & 0 deletions code/scripting/api/objs/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions code/sound/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
//
Expand All @@ -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;
}
Expand All @@ -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();
}

// ---------------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions code/sound/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading