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**
- 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
- 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
+8 -3
View File
@@ -472,11 +472,16 @@ static void SfallResourceFile() {
const char* sfallRes = "sfall.dat";
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) {
do {
if (std::strlen(&findData.cFileName[6]) == 6) {
dlog_f("Found a localized sfall resource file: %s\n", DL_MAIN, findData.cFileName);
sfallRes = findData.cFileName;
break;
}
} while (FindNextFileA(hFind, &findData));
FindClose(hFind);
dlog_f("Found a localized sfall resource file: %s\n", DL_MAIN, findData.cFileName);
sfallRes = findData.cFileName;
}
patchFiles.push_back(sfallRes);
}
+1 -1
View File
@@ -174,7 +174,7 @@ static void ReadExtraGameMsgFiles() {
path += ".msg";
fo::MessageList* list = new fo::MessageList();
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 {
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);
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);
+53 -23
View File
@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <unordered_map>
#include <algorithm>
#include <dsound.h>
#include <dshow.h>
@@ -31,7 +30,8 @@
namespace sfall
{
#define SAFERELEASE(a) { if (a) { a->Release(); } }
#define WM_APP_DS_NOTIFY 0xA000
#define SAFERELEASE(a) { if (a) { a->Release(); } }
enum SoundType : DWORD {
sfx_loop = 0, // sfall
@@ -83,7 +83,7 @@ static bool deathSceneSpeech = false;
static bool lipsPlaying = false;
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->pEvent);
SAFERELEASE(sound->pSeek);
@@ -93,8 +93,8 @@ static void FreeSound(sDSSound* sound) {
}
static void WipeSounds() {
for (size_t i = 0; i < playingSounds.size(); i++) FreeSound(playingSounds[i]);
for (size_t i = 0; i < loopingSounds.size(); i++) FreeSound(loopingSounds[i]);
for (auto &sound : playingSounds) FreeSound(sound);
for (auto &sound : loopingSounds) FreeSound(sound);
playingSounds.clear();
loopingSounds.clear();
backgroundMusic = nullptr;
@@ -105,33 +105,51 @@ static void WipeSounds() {
}
LRESULT CALLBACK SoundWndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l) {
if (msg == WM_APP) {
if (!(l & 0xA0000000)) return 0;
sDSSound* sound = reinterpret_cast<sDSSound*>(l & ~0xA0000000);
if (msg == WM_APP_DS_NOTIFY) {
long id = l;
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_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 (sound->id & SoundFlags::looping) {
LONGLONG pos = 0;
sound->pSeek->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);
sound->pControl->Run();
sound->pEvent->FreeEventParams(e, p1, p2);
} else {
sound->pEvent->FreeEventParams(e, p1, p2);
if (sound->id & SoundFlags::on_stop) { // speech sound playback is completed
fo::var::main_death_voiceover_done = 1;
fo::var::endgame_subtitle_done = 1;
lipsPlaying = false;
speechSound = nullptr;
}
playingSounds.erase(
std::find_if(playingSounds.cbegin(), playingSounds.cend(), [&](const sDSSound* snd) { return snd->id == sound->id; })
);
FreeSound(sound);
playingSounds.erase(playingSounds.cbegin() + i);
shouldFree = true;
}
}
}
if (shouldFree) FreeSound(sound);
return 0;
}
return DefWindowProc(wnd, msg, w, l);
@@ -170,22 +188,34 @@ static DWORD GetSpeechPlayingPosition() {
return static_cast<DWORD>(pos << 1);
}
void __fastcall PauseSfallSound(sDSSound* sound) {
if (sound) sound->pControl->Pause();
}
//void __fastcall PauseSfallSound(sDSSound* sound) {
// if (sound) sound->pControl->Pause();
//}
void __fastcall ResumeSfallSound(sDSSound* sound) {
if (sound) sound->pControl->Run();
}
void __stdcall PauseAllSfallSound() {
for (sDSSound* sound : loopingSounds) sound->pControl->Pause();
for (sDSSound* sound : playingSounds) sound->pControl->Pause();
for (sDSSound* sound : loopingSounds) {
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() {
for (sDSSound* sound : loopingSounds) sound->pControl->Run();
for (sDSSound* sound : playingSounds) sound->pControl->Run();
for (sDSSound* sound : loopingSounds) {
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) {
@@ -301,7 +331,7 @@ static sDSSound* PlayingSound(const wchar_t* pathFile, SoundMode mode, long adju
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();
if (isLoop) {
+2 -2
View File
@@ -562,7 +562,7 @@ bool Worldmap::LoadData(HANDLE file) {
ReadFile(file, &mID, 4, &sizeRead, 0);
ReadFile(file, &elevData, sizeof(levelRest), &sizeRead, 0);
if (sizeRead != sizeof(levelRest)) return true;
mapRestInfo.insert(std::make_pair(mID, elevData));
mapRestInfo.emplace(mID, elevData);
}
if (count && !restMap) {
HookCall(0x42E57A, critter_can_obj_dude_rest_hook);
@@ -637,7 +637,7 @@ void Worldmap::SetRestMapLevel(int mapId, long elev, bool canRest) {
elev++;
}
elevData.level[elev] = canRest;
mapRestInfo.insert(std::make_pair(mapId, elevData));
mapRestInfo.emplace(mapId, elevData);
}
}