mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user