Fixed crash at the end of DS sound playback

* revert to the previous implementation.

Made sure sfall only loads a localized resource file with valid name.
Some code edits.
This commit is contained in:
NovaRain
2021-10-05 13:36:58 +08:00
parent 5df3d7230f
commit c19137bd1a
6 changed files with 66 additions and 30 deletions
@@ -1046,6 +1046,7 @@ sfall_funcX metarule functions
- Overrides the name of the script object that was set from **scrname.msg** - Overrides the name of the script object that was set from **scrname.msg**
- The changed name will be reset each time the player leaves the map or reloads the game - The changed name will be reset each time the player leaves the map or reloads the game
- Passing an empty string ("") to the `name` argument or omitting it will allow the game to get the name for the object from pro_*.msg files - Passing an empty string ("") to the `name` argument or omitting it will allow the game to get the name for the object from pro_*.msg files
- The function can override the name only once for the same object until reset
- __NOTE:__ this function is intended for use in normal game scripts - __NOTE:__ this function is intended for use in normal game scripts
+7 -2
View File
@@ -472,11 +472,16 @@ static void SfallResourceFile() {
const char* sfallRes = "sfall.dat"; const char* sfallRes = "sfall.dat";
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile("sfall_??.dat", &findData); // example: sfall_ru.dat, sfall_zh.dat HANDLE hFind = FindFirstFileA("sfall_??.dat", &findData); // example: sfall_ru.dat, sfall_zh.dat
if (hFind != INVALID_HANDLE_VALUE) { if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind); do {
if (std::strlen(&findData.cFileName[6]) == 6) {
dlog_f("Found a localized sfall resource file: %s\n", DL_MAIN, findData.cFileName); dlog_f("Found a localized sfall resource file: %s\n", DL_MAIN, findData.cFileName);
sfallRes = findData.cFileName; sfallRes = findData.cFileName;
break;
}
} while (FindNextFileA(hFind, &findData));
FindClose(hFind);
} }
patchFiles.push_back(sfallRes); patchFiles.push_back(sfallRes);
} }
+1 -1
View File
@@ -174,7 +174,7 @@ static void ReadExtraGameMsgFiles() {
path += ".msg"; path += ".msg";
fo::MessageList* list = new fo::MessageList(); fo::MessageList* list = new fo::MessageList();
if (fo::func::message_load(list, path.c_str()) == 1) { if (fo::func::message_load(list, path.c_str()) == 1) {
Message::gExtraGameMsgLists.insert(std::make_pair(0x2000 + number, list)); Message::gExtraGameMsgLists.emplace(0x2000 + number, list);
} else { } else {
delete list; delete list;
} }
+1 -1
View File
@@ -561,7 +561,7 @@ static void PrepareGlobalScriptsListByMask() {
fo::func::debug_printf("\n[SFALL] Script: %s will not be executed. A script with the same name already exists in another directory.", fullPath); fo::func::debug_printf("\n[SFALL] Script: %s will not be executed. A script with the same name already exists in another directory.", fullPath);
continue; continue;
} }
globalScriptFilesList.insert(std::make_pair(baseName, fullPath)); // script files should be sorted in alphabetical order globalScriptFilesList.emplace(std::move(baseName), std::move(fullPath)); // script files should be sorted in alphabetical order
} }
} }
fo::func::db_free_file_list(&filenames, 0); fo::func::db_free_file_list(&filenames, 0);
+52 -22
View File
@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <unordered_map>
#include <algorithm> #include <algorithm>
#include <dsound.h> #include <dsound.h>
#include <dshow.h> #include <dshow.h>
@@ -31,6 +30,7 @@
namespace sfall namespace sfall
{ {
#define WM_APP_DS_NOTIFY 0xA000
#define SAFERELEASE(a) { if (a) { a->Release(); } } #define SAFERELEASE(a) { if (a) { a->Release(); } }
enum SoundType : DWORD { enum SoundType : DWORD {
@@ -83,7 +83,7 @@ static bool deathSceneSpeech = false;
static bool lipsPlaying = false; static bool lipsPlaying = false;
static void FreeSound(sDSSound* sound) { static void FreeSound(sDSSound* sound) {
sound->pEvent->SetNotifyWindow(0, WM_APP, 0); sound->pEvent->SetNotifyWindow(0, WM_APP_DS_NOTIFY, 0);
SAFERELEASE(sound->pAudio); SAFERELEASE(sound->pAudio);
SAFERELEASE(sound->pEvent); SAFERELEASE(sound->pEvent);
SAFERELEASE(sound->pSeek); SAFERELEASE(sound->pSeek);
@@ -93,8 +93,8 @@ static void FreeSound(sDSSound* sound) {
} }
static void WipeSounds() { static void WipeSounds() {
for (size_t i = 0; i < playingSounds.size(); i++) FreeSound(playingSounds[i]); for (auto &sound : playingSounds) FreeSound(sound);
for (size_t i = 0; i < loopingSounds.size(); i++) FreeSound(loopingSounds[i]); for (auto &sound : loopingSounds) FreeSound(sound);
playingSounds.clear(); playingSounds.clear();
loopingSounds.clear(); loopingSounds.clear();
backgroundMusic = nullptr; backgroundMusic = nullptr;
@@ -105,33 +105,51 @@ static void WipeSounds() {
} }
LRESULT CALLBACK SoundWndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l) { LRESULT CALLBACK SoundWndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l) {
if (msg == WM_APP) { if (msg == WM_APP_DS_NOTIFY) {
if (!(l & 0xA0000000)) return 0; long id = l;
sDSSound* sound = reinterpret_cast<sDSSound*>(l & ~0xA0000000); sDSSound* sound = nullptr;
size_t i;
if (id & SoundFlags::looping) {
for (i = 0; i < loopingSounds.size(); i++) {
if (loopingSounds[i]->id == id) {
sound = loopingSounds[i];
break;
}
}
} else {
for (i = 0; i < playingSounds.size(); i++) {
if (playingSounds[i]->id == id) {
sound = playingSounds[i];
break;
}
}
}
if (!sound || !sound->pEvent) return 0;
LONG e = 0; LONG e = 0;
LONG_PTR p1 = 0, p2 = 0; LONG_PTR p1 = 0, p2 = 0;
if (!FAILED(sound->pEvent->GetEvent(&e, &p1, &p2, 0))) { bool shouldFree = false;
while (!FAILED(sound->pEvent->GetEvent(&e, &p1, &p2, 0))) {
sound->pEvent->FreeEventParams(e, p1, p2);
if (e == EC_COMPLETE) { if (e == EC_COMPLETE) {
if (sound->id & SoundFlags::looping) { if (sound->id & SoundFlags::looping) {
LONGLONG pos = 0; LONGLONG pos = 0;
sound->pSeek->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); sound->pSeek->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);
sound->pControl->Run(); sound->pControl->Run();
sound->pEvent->FreeEventParams(e, p1, p2);
} else { } else {
sound->pEvent->FreeEventParams(e, p1, p2);
if (sound->id & SoundFlags::on_stop) { // speech sound playback is completed if (sound->id & SoundFlags::on_stop) { // speech sound playback is completed
fo::var::main_death_voiceover_done = 1; fo::var::main_death_voiceover_done = 1;
fo::var::endgame_subtitle_done = 1; fo::var::endgame_subtitle_done = 1;
lipsPlaying = false; lipsPlaying = false;
speechSound = nullptr; speechSound = nullptr;
} }
playingSounds.erase( playingSounds.erase(playingSounds.cbegin() + i);
std::find_if(playingSounds.cbegin(), playingSounds.cend(), [&](const sDSSound* snd) { return snd->id == sound->id; }) shouldFree = true;
);
FreeSound(sound);
} }
} }
} }
if (shouldFree) FreeSound(sound);
return 0; return 0;
} }
return DefWindowProc(wnd, msg, w, l); return DefWindowProc(wnd, msg, w, l);
@@ -170,22 +188,34 @@ static DWORD GetSpeechPlayingPosition() {
return static_cast<DWORD>(pos << 1); return static_cast<DWORD>(pos << 1);
} }
void __fastcall PauseSfallSound(sDSSound* sound) { //void __fastcall PauseSfallSound(sDSSound* sound) {
if (sound) sound->pControl->Pause(); // if (sound) sound->pControl->Pause();
} //}
void __fastcall ResumeSfallSound(sDSSound* sound) { void __fastcall ResumeSfallSound(sDSSound* sound) {
if (sound) sound->pControl->Run(); if (sound) sound->pControl->Run();
} }
void __stdcall PauseAllSfallSound() { void __stdcall PauseAllSfallSound() {
for (sDSSound* sound : loopingSounds) sound->pControl->Pause(); for (sDSSound* sound : loopingSounds) {
for (sDSSound* sound : playingSounds) sound->pControl->Pause(); sound->pEvent->SetNotifyFlags(AM_MEDIAEVENT_NONOTIFY);
sound->pControl->Pause();
}
for (sDSSound* sound : playingSounds) {
sound->pEvent->SetNotifyFlags(AM_MEDIAEVENT_NONOTIFY);
sound->pControl->Pause();
}
} }
void __stdcall ResumeAllSfallSound() { void __stdcall ResumeAllSfallSound() {
for (sDSSound* sound : loopingSounds) sound->pControl->Run(); for (sDSSound* sound : loopingSounds) {
for (sDSSound* sound : playingSounds) sound->pControl->Run(); sound->pEvent->SetNotifyFlags(0);
sound->pControl->Run();
}
for (sDSSound* sound : playingSounds) {
sound->pEvent->SetNotifyFlags(0);
sound->pControl->Run();
}
} }
long Sound::CalculateVolumeDB(long masterVolume, long passVolume) { long Sound::CalculateVolumeDB(long masterVolume, long passVolume) {
@@ -301,7 +331,7 @@ static sDSSound* PlayingSound(const wchar_t* pathFile, SoundMode mode, long adju
break; break;
} }
sound->pEvent->SetNotifyWindow((OAHWND)soundwindow, WM_APP, ((unsigned long)sound | 0xA0000000)); sound->pEvent->SetNotifyWindow((OAHWND)soundwindow, WM_APP_DS_NOTIFY, (LONG_PTR)sound->id);
sound->pControl->Run(); sound->pControl->Run();
if (isLoop) { if (isLoop) {
+2 -2
View File
@@ -562,7 +562,7 @@ bool Worldmap::LoadData(HANDLE file) {
ReadFile(file, &mID, 4, &sizeRead, 0); ReadFile(file, &mID, 4, &sizeRead, 0);
ReadFile(file, &elevData, sizeof(levelRest), &sizeRead, 0); ReadFile(file, &elevData, sizeof(levelRest), &sizeRead, 0);
if (sizeRead != sizeof(levelRest)) return true; if (sizeRead != sizeof(levelRest)) return true;
mapRestInfo.insert(std::make_pair(mID, elevData)); mapRestInfo.emplace(mID, elevData);
} }
if (count && !restMap) { if (count && !restMap) {
HookCall(0x42E57A, critter_can_obj_dude_rest_hook); HookCall(0x42E57A, critter_can_obj_dude_rest_hook);
@@ -637,7 +637,7 @@ void Worldmap::SetRestMapLevel(int mapId, long elev, bool canRest) {
elev++; elev++;
} }
elevData.level[elev] = canRest; elevData.level[elev] = canRest;
mapRestInfo.insert(std::make_pair(mapId, elevData)); mapRestInfo.emplace(mapId, elevData);
} }
} }