|
|
|
@@ -30,6 +30,26 @@ namespace sfall
|
|
|
|
|
|
|
|
|
|
#define SAFERELEASE(a) { if (a) { a->Release(); } }
|
|
|
|
|
|
|
|
|
|
enum SoundType : unsigned long {
|
|
|
|
|
sfx_loop = 0, // sfall
|
|
|
|
|
sfx_single = 1, // sfall
|
|
|
|
|
game_sfx = 2,
|
|
|
|
|
game_master = 3
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum SoundMode : long {
|
|
|
|
|
single_play = 0, // uses sfx volume
|
|
|
|
|
loop_play = 1, // uses sfx volume
|
|
|
|
|
music_play = 2, // uses background volume
|
|
|
|
|
engine_music_play = -1 // used when playing game music in an alternative format (not used from scripts)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum SoundFlags : unsigned long {
|
|
|
|
|
looping = 0x10000000,
|
|
|
|
|
restore = 0x40000000, // restore background game music on stop play
|
|
|
|
|
engine = 0x80000000
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct sDSSound {
|
|
|
|
|
DWORD id; // should be first
|
|
|
|
|
IGraphBuilder *pGraph;
|
|
|
|
@@ -46,7 +66,7 @@ DWORD playID = 0;
|
|
|
|
|
DWORD loopID = 0;
|
|
|
|
|
|
|
|
|
|
static HWND soundwindow = 0;
|
|
|
|
|
static sDSSound* musicLoopPtr = nullptr;
|
|
|
|
|
static sDSSound* backgroundMusic = nullptr; // currently playing sfall background music
|
|
|
|
|
//static char playingMusicFile[256];
|
|
|
|
|
|
|
|
|
|
static void FreeSound(sDSSound* sound) {
|
|
|
|
@@ -64,7 +84,7 @@ static void WipeSounds() {
|
|
|
|
|
for (size_t i = 0; i < loopingSounds.size(); i++) FreeSound(loopingSounds[i]);
|
|
|
|
|
playingSounds.clear();
|
|
|
|
|
loopingSounds.clear();
|
|
|
|
|
musicLoopPtr = nullptr;
|
|
|
|
|
backgroundMusic = nullptr;
|
|
|
|
|
playID = 0;
|
|
|
|
|
loopID = 0;
|
|
|
|
|
}
|
|
|
|
@@ -73,7 +93,8 @@ LRESULT CALLBACK SoundWndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l) {
|
|
|
|
|
if (msg == WM_APP) {
|
|
|
|
|
DWORD id = l;
|
|
|
|
|
sDSSound* sound = nullptr;
|
|
|
|
|
if (id & 0x80000000) {
|
|
|
|
|
long index = -1;
|
|
|
|
|
if (id & SoundFlags::looping) {
|
|
|
|
|
for (size_t i = 0; i < loopingSounds.size(); i++) {
|
|
|
|
|
if (loopingSounds[i]->id == id) {
|
|
|
|
|
sound = loopingSounds[i];
|
|
|
|
@@ -84,28 +105,24 @@ LRESULT CALLBACK SoundWndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l) {
|
|
|
|
|
for (size_t i = 0; i < playingSounds.size(); i++) {
|
|
|
|
|
if (playingSounds[i]->id == id) {
|
|
|
|
|
sound = playingSounds[i];
|
|
|
|
|
index = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!sound) return 0;
|
|
|
|
|
|
|
|
|
|
LONG e = 0;
|
|
|
|
|
LONG_PTR p1 = 0, p2 = 0;
|
|
|
|
|
while (!FAILED(sound->pEvent->GetEvent(&e, &p1, &p2, 0))) {
|
|
|
|
|
if (sound && !FAILED(sound->pEvent->GetEvent(&e, &p1, &p2, 0))) {
|
|
|
|
|
sound->pEvent->FreeEventParams(e, p1, p2);
|
|
|
|
|
if (e == EC_COMPLETE) {
|
|
|
|
|
if (id & 0x80000000) {
|
|
|
|
|
if (id & SoundFlags::looping) {
|
|
|
|
|
LONGLONG pos = 0;
|
|
|
|
|
sound->pSeek->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);
|
|
|
|
|
sound->pControl->Run();
|
|
|
|
|
} else {
|
|
|
|
|
for (size_t i = 0; i < playingSounds.size(); i++) {
|
|
|
|
|
if (playingSounds[i] == sound) {
|
|
|
|
|
FreeSound(sound);
|
|
|
|
|
playingSounds.erase(playingSounds.begin() + i);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FreeSound(sound);
|
|
|
|
|
playingSounds.erase(playingSounds.begin() + index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -119,7 +136,8 @@ static void CreateSndWnd() {
|
|
|
|
|
if (Graphics::mode == 0) CoInitialize(0);
|
|
|
|
|
|
|
|
|
|
WNDCLASSEX wcx;
|
|
|
|
|
memset(&wcx, 0, sizeof(wcx));
|
|
|
|
|
std::memset(&wcx, 0, sizeof(wcx));
|
|
|
|
|
|
|
|
|
|
wcx.cbSize = sizeof(wcx);
|
|
|
|
|
wcx.lpfnWndProc = SoundWndProc;
|
|
|
|
|
wcx.hInstance = GetModuleHandleA(0);
|
|
|
|
@@ -130,16 +148,28 @@ static void CreateSndWnd() {
|
|
|
|
|
dlogr(" Done", DL_INIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __stdcall PauseSfallSound(sDSSound* ptr) {
|
|
|
|
|
ptr->pControl->Pause();
|
|
|
|
|
void __stdcall PauseSfallSound(sDSSound* sound) {
|
|
|
|
|
sound->pControl->Pause();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __stdcall ResumeSfallSound(sDSSound* ptr) {
|
|
|
|
|
ptr->pControl->Run();
|
|
|
|
|
void __stdcall ResumeSfallSound(sDSSound* sound) {
|
|
|
|
|
sound->pControl->Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __stdcall PauseAllSfallSound() {
|
|
|
|
|
for (sDSSound* sound : loopingSounds) sound->pControl->Pause();
|
|
|
|
|
for (sDSSound* sound : playingSounds) sound->pControl->Pause();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __stdcall ResumeAllSfallSound() {
|
|
|
|
|
for (sDSSound* sound : loopingSounds) sound->pControl->Run();
|
|
|
|
|
for (sDSSound* sound : playingSounds) sound->pControl->Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static long CalculateVolumeDB(long masterVolume, long passVolume) {
|
|
|
|
|
const int volOffset = -100; // maximum volume
|
|
|
|
|
if (masterVolume <= 0 || passVolume <= 0) return -9999; // mute
|
|
|
|
|
|
|
|
|
|
const int volOffset = -100; // adjust the maximum volume
|
|
|
|
|
const int minVolume = -2048;
|
|
|
|
|
|
|
|
|
|
float multiply = (32767.0f / masterVolume);
|
|
|
|
@@ -148,32 +178,34 @@ static long CalculateVolumeDB(long masterVolume, long passVolume) {
|
|
|
|
|
return static_cast<long>(minVolume - volume) + volOffset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __cdecl SfallSoundVolume(sDSSound* sound, int type, long passVolume) {
|
|
|
|
|
long loopVolume, sfxVolume, masterVolume = *(DWORD*)FO_VAR_master_volume;
|
|
|
|
|
/*
|
|
|
|
|
master_volume: sound=0 type=game_master passVolume=background_volume
|
|
|
|
|
background_volume: sound=backgroundMusic type=background_loop passVolume=background_volume
|
|
|
|
|
sfx_volume: sound=0 type=game_sfx passVolume=sndfx_volume
|
|
|
|
|
*/
|
|
|
|
|
static void __cdecl SfallSoundVolume(sDSSound* sound, SoundType type, long passVolume) {
|
|
|
|
|
long volume, sfxVolume, masterVolume = fo::var::master_volume;
|
|
|
|
|
|
|
|
|
|
if (masterVolume > 0 && passVolume > 0) {
|
|
|
|
|
loopVolume = CalculateVolumeDB(masterVolume, passVolume);
|
|
|
|
|
if (type = 2) sfxVolume = CalculateVolumeDB(masterVolume, *(DWORD*)FO_VAR_sndfx_volume);
|
|
|
|
|
} else {
|
|
|
|
|
if (masterVolume == 0) {
|
|
|
|
|
loopVolume = sfxVolume = -9999; // mute
|
|
|
|
|
} else if (type = 0) { // for music
|
|
|
|
|
if (musicLoopPtr) {
|
|
|
|
|
Sound::StopSfallSound(musicLoopPtr->id);
|
|
|
|
|
musicLoopPtr = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
volume = CalculateVolumeDB(masterVolume, passVolume);
|
|
|
|
|
if (type == SoundType::game_master) sfxVolume = CalculateVolumeDB(masterVolume, fo::var::sndfx_volume);
|
|
|
|
|
|
|
|
|
|
if (sound) {
|
|
|
|
|
sound->pAudio->put_Volume(loopVolume);
|
|
|
|
|
sound->pAudio->put_Volume(volume);
|
|
|
|
|
} else {
|
|
|
|
|
for (DWORD i = 0; i < loopingSounds.size(); i++) {
|
|
|
|
|
loopingSounds[i]->pAudio->put_Volume(loopVolume);
|
|
|
|
|
if (type == SoundType::game_sfx) sfxVolume = volume;
|
|
|
|
|
bool sfx_or_master = (type == SoundType::game_sfx || type == SoundType::game_master);
|
|
|
|
|
for (size_t i = 0; i < loopingSounds.size(); i++) {
|
|
|
|
|
if (sfx_or_master) {
|
|
|
|
|
if ((loopingSounds[i]->id & 0xF0000000) == SoundFlags::looping) { // only for sfx loop mode
|
|
|
|
|
loopingSounds[i]->pAudio->put_Volume(sfxVolume);
|
|
|
|
|
continue;
|
|
|
|
|
} else
|
|
|
|
|
if (type == SoundType::game_sfx) continue;
|
|
|
|
|
}
|
|
|
|
|
loopingSounds[i]->pAudio->put_Volume(volume);
|
|
|
|
|
}
|
|
|
|
|
if (type = 2) { // sfx
|
|
|
|
|
for (DWORD i = 0; i < playingSounds.size(); i++) {
|
|
|
|
|
if (sfx_or_master) {
|
|
|
|
|
for (size_t i = 0; i < playingSounds.size(); i++) {
|
|
|
|
|
playingSounds[i]->pAudio->put_Volume(sfxVolume);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -181,27 +213,29 @@ static void __cdecl SfallSoundVolume(sDSSound* sound, int type, long passVolume)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool IsMute(bool type) {
|
|
|
|
|
//if (*(DWORD*)FO_VAR_master_volume == 0) return true;
|
|
|
|
|
//if (fo::var::master_volume == 0) return true;
|
|
|
|
|
int value;
|
|
|
|
|
if (type) {
|
|
|
|
|
value = *(DWORD*)FO_VAR_background_volume;
|
|
|
|
|
value = fo::var::background_volume;
|
|
|
|
|
} else {
|
|
|
|
|
value = *(DWORD*)FO_VAR_sndfx_volume;
|
|
|
|
|
value = fo::var::sndfx_volume;
|
|
|
|
|
}
|
|
|
|
|
return (value == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static sDSSound* PlayingSound(wchar_t* path, bool loop) {
|
|
|
|
|
/*
|
|
|
|
|
single_play: mode 0 - single sound playback (with sound overlay)
|
|
|
|
|
loop_play: mode 1 - loop sound playback (with sound overlay)
|
|
|
|
|
music_play: mode 2 - loop sound playback with the background game music turned off
|
|
|
|
|
*/
|
|
|
|
|
static sDSSound* PlayingSound(wchar_t* path, SoundMode mode) {
|
|
|
|
|
if (!soundwindow) CreateSndWnd();
|
|
|
|
|
|
|
|
|
|
if (IsMute(loop)) return nullptr;
|
|
|
|
|
bool isLoop = (mode != SoundMode::single_play);
|
|
|
|
|
if (IsMute(isLoop)) return nullptr;
|
|
|
|
|
|
|
|
|
|
sDSSound* sound = new sDSSound();
|
|
|
|
|
|
|
|
|
|
DWORD id = (loop) ? ++loopID : ++playID;
|
|
|
|
|
if (loop) id |= 0x80000000;
|
|
|
|
|
sound->id = id;
|
|
|
|
|
|
|
|
|
|
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC, IID_IGraphBuilder, (void**)&sound->pGraph);
|
|
|
|
|
if (hr != S_OK) {
|
|
|
|
|
dlog_f("Error CoCreateInstance: %d", DL_INIT, hr);
|
|
|
|
@@ -209,24 +243,38 @@ static sDSSound* PlayingSound(wchar_t* path, bool loop) {
|
|
|
|
|
}
|
|
|
|
|
sound->pGraph->QueryInterface(IID_IMediaControl, (void**)&sound->pControl);
|
|
|
|
|
|
|
|
|
|
if (loop)
|
|
|
|
|
if (isLoop)
|
|
|
|
|
sound->pGraph->QueryInterface(IID_IMediaSeeking, (void**)&sound->pSeek);
|
|
|
|
|
else
|
|
|
|
|
sound->pSeek = nullptr;
|
|
|
|
|
|
|
|
|
|
sound->pGraph->QueryInterface(IID_IMediaEventEx, (void**)&sound->pEvent);
|
|
|
|
|
sound->pEvent->SetNotifyWindow((OAHWND)soundwindow, WM_APP, id);
|
|
|
|
|
sound->pGraph->QueryInterface(IID_IBasicAudio, (void**)&sound->pAudio);
|
|
|
|
|
|
|
|
|
|
sound->id = (isLoop) ? ++loopID : ++playID;
|
|
|
|
|
if (isLoop) sound->id |= SoundFlags::looping; // sfx loop sound
|
|
|
|
|
|
|
|
|
|
if (mode == SoundMode::music_play) {
|
|
|
|
|
sound->id |= SoundFlags::restore; // restore background game music on stop
|
|
|
|
|
if (backgroundMusic)
|
|
|
|
|
Sound::StopSfallSound(backgroundMusic->id);
|
|
|
|
|
else {
|
|
|
|
|
__asm call fo::funcoffs::gsound_background_stop_;
|
|
|
|
|
}
|
|
|
|
|
backgroundMusic = sound;
|
|
|
|
|
}
|
|
|
|
|
else if (mode == SoundMode::engine_music_play) sound->id |= SoundFlags::engine; // engine play
|
|
|
|
|
|
|
|
|
|
sound->pEvent->SetNotifyWindow((OAHWND)soundwindow, WM_APP, sound->id);
|
|
|
|
|
sound->pControl->RenderFile(path);
|
|
|
|
|
sound->pControl->Run();
|
|
|
|
|
|
|
|
|
|
if (loop) {
|
|
|
|
|
if (isLoop) {
|
|
|
|
|
loopingSounds.push_back(sound);
|
|
|
|
|
SfallSoundVolume(sound, 0, *(DWORD*)FO_VAR_background_volume); // music
|
|
|
|
|
SfallSoundVolume(sound, SoundType::sfx_loop, (mode == SoundMode::loop_play) ? fo::var::sndfx_volume : fo::var::background_volume);
|
|
|
|
|
} else {
|
|
|
|
|
playingSounds.push_back(sound);
|
|
|
|
|
SfallSoundVolume(sound, 1, *(DWORD*)FO_VAR_sndfx_volume);
|
|
|
|
|
SfallSoundVolume(sound, SoundType::sfx_single, fo::var::sndfx_volume);
|
|
|
|
|
}
|
|
|
|
|
return sound;
|
|
|
|
|
}
|
|
|
|
@@ -249,19 +297,19 @@ static bool __cdecl SoundFileLoad(DWORD called, const char* path) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool music = (called == 0x45092B); // from gsound_background_play_
|
|
|
|
|
if (music && musicLoopPtr != nullptr) {
|
|
|
|
|
if (music && backgroundMusic != nullptr) {
|
|
|
|
|
//if (found && strcmp(path, playingMusicFile) == 0) return true; // don't stop music
|
|
|
|
|
Sound::StopSfallSound(musicLoopPtr->id);
|
|
|
|
|
musicLoopPtr = nullptr;
|
|
|
|
|
Sound::StopSfallSound(backgroundMusic->id);
|
|
|
|
|
backgroundMusic = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (!isExist) return false;
|
|
|
|
|
|
|
|
|
|
if (music) {
|
|
|
|
|
//strcpy_s(playingMusicFile, path);
|
|
|
|
|
musicLoopPtr = PlayingSound(buf, true); // music loop
|
|
|
|
|
if (!musicLoopPtr) return false;
|
|
|
|
|
backgroundMusic = PlayingSound(buf, SoundMode::engine_music_play); // background music loop
|
|
|
|
|
if (!backgroundMusic) return false;
|
|
|
|
|
} else {
|
|
|
|
|
if (!PlayingSound(buf, false)) return false;
|
|
|
|
|
if (!PlayingSound(buf, SoundMode::single_play)) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -277,21 +325,24 @@ static void __fastcall MakeMusicPath(const char* file) {
|
|
|
|
|
SoundFileLoad(0x45092B, pathBuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD Sound::PlaySfallSound(const char* path, bool loop) {
|
|
|
|
|
DWORD Sound::PlaySfallSound(const char* path, long mode) {
|
|
|
|
|
wchar_t buf[256];
|
|
|
|
|
mbstowcs_s(0, buf, path, 256);
|
|
|
|
|
sDSSound* sound = PlayingSound(buf, loop);
|
|
|
|
|
return (loop && sound) ? sound->id : 0;
|
|
|
|
|
sDSSound* sound = PlayingSound(buf, (SoundMode)mode);
|
|
|
|
|
return (mode && sound) ? sound->id : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __stdcall Sound::StopSfallSound(DWORD id) {
|
|
|
|
|
if (!id) return;
|
|
|
|
|
if (!(id & 0xFFFFFF)) return;
|
|
|
|
|
for (size_t i = 0; i < loopingSounds.size(); i++) {
|
|
|
|
|
if (loopingSounds[i]->id == id) {
|
|
|
|
|
sDSSound* sound = loopingSounds[i];
|
|
|
|
|
sound->pControl->Stop();
|
|
|
|
|
FreeSound(sound);
|
|
|
|
|
loopingSounds.erase(loopingSounds.begin() + i);
|
|
|
|
|
if (!(id & SoundFlags::engine) && id & SoundFlags::restore) {
|
|
|
|
|
__asm call fo::funcoffs::gsound_background_restart_last_;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -333,16 +384,16 @@ static void __declspec(naked) gsound_background_play_hook() {
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) gmovie_play_hook_stop() {
|
|
|
|
|
__asm {
|
|
|
|
|
mov eax, musicLoopPtr;
|
|
|
|
|
mov eax, backgroundMusic;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz skip;
|
|
|
|
|
mov eax, [eax]; // musicLoopPtr->id
|
|
|
|
|
mov eax, [eax]; // backgroundMusic->id
|
|
|
|
|
push ecx;
|
|
|
|
|
push edx;
|
|
|
|
|
push eax;
|
|
|
|
|
call Sound::StopSfallSound;
|
|
|
|
|
xor eax, eax;
|
|
|
|
|
mov musicLoopPtr, eax;
|
|
|
|
|
mov backgroundMusic, eax;
|
|
|
|
|
pop edx;
|
|
|
|
|
pop ecx;
|
|
|
|
|
retn;
|
|
|
|
@@ -353,35 +404,31 @@ skip:
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) gmovie_play_hook_pause() {
|
|
|
|
|
__asm {
|
|
|
|
|
mov eax, musicLoopPtr;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz skip;
|
|
|
|
|
push ecx;
|
|
|
|
|
push edx;
|
|
|
|
|
push eax;
|
|
|
|
|
call PauseSfallSound;
|
|
|
|
|
call PauseAllSfallSound;
|
|
|
|
|
pop edx;
|
|
|
|
|
pop ecx;
|
|
|
|
|
retn;
|
|
|
|
|
skip:
|
|
|
|
|
cmp dword ptr backgroundMusic, 0;
|
|
|
|
|
jnz skip;
|
|
|
|
|
jmp fo::funcoffs::gsound_background_pause_;
|
|
|
|
|
skip:
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) gmovie_play_hook_unpause() {
|
|
|
|
|
__asm {
|
|
|
|
|
mov eax, musicLoopPtr;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz skip;
|
|
|
|
|
push ecx;
|
|
|
|
|
push edx;
|
|
|
|
|
push eax;
|
|
|
|
|
call ResumeSfallSound;
|
|
|
|
|
call ResumeAllSfallSound;
|
|
|
|
|
pop edx;
|
|
|
|
|
pop ecx;
|
|
|
|
|
retn;
|
|
|
|
|
skip:
|
|
|
|
|
cmp dword ptr backgroundMusic, 0;
|
|
|
|
|
jnz skip;
|
|
|
|
|
jmp fo::funcoffs::gsound_background_unpause_;
|
|
|
|
|
skip:
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -389,13 +436,13 @@ static void __declspec(naked) gsound_background_volume_set_hack() {
|
|
|
|
|
__asm {
|
|
|
|
|
mov dword ptr ds:[FO_VAR_background_volume], eax;
|
|
|
|
|
push ecx;
|
|
|
|
|
mov ecx, musicLoopPtr;
|
|
|
|
|
mov ecx, backgroundMusic;
|
|
|
|
|
test ecx, ecx;
|
|
|
|
|
jz skip;
|
|
|
|
|
push edx;
|
|
|
|
|
push eax;
|
|
|
|
|
push 0;
|
|
|
|
|
push ecx;
|
|
|
|
|
push 0; // SoundType::sfx_loop
|
|
|
|
|
push ecx; // set volume for background music
|
|
|
|
|
call SfallSoundVolume;
|
|
|
|
|
add esp, 8;
|
|
|
|
|
pop eax;
|
|
|
|
@@ -413,8 +460,8 @@ static void __declspec(naked) gsound_master_volume_set_hack() {
|
|
|
|
|
push ecx;
|
|
|
|
|
push edx;
|
|
|
|
|
push dword ptr ds:[FO_VAR_background_volume];
|
|
|
|
|
push 2;
|
|
|
|
|
push 0;
|
|
|
|
|
push 3; // SoundType::game_master
|
|
|
|
|
push 0; // set volume for all sounds
|
|
|
|
|
call SfallSoundVolume;
|
|
|
|
|
add esp, 12;
|
|
|
|
|
pop edx;
|
|
|
|
@@ -424,6 +471,33 @@ static void __declspec(naked) gsound_master_volume_set_hack() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) gsound_set_sfx_volume_hack() {
|
|
|
|
|
__asm {
|
|
|
|
|
push ecx;
|
|
|
|
|
push edx;
|
|
|
|
|
mov dword ptr ds:[FO_VAR_sndfx_volume], eax;
|
|
|
|
|
push eax;
|
|
|
|
|
push 2; // SoundType::game_sfx
|
|
|
|
|
push 0; // set volume for all sounds
|
|
|
|
|
call SfallSoundVolume;
|
|
|
|
|
add esp, 12;
|
|
|
|
|
pop edx;
|
|
|
|
|
pop ecx;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void SoundLostFocus() {
|
|
|
|
|
long isActive;
|
|
|
|
|
__asm mov isActive, eax;
|
|
|
|
|
|
|
|
|
|
if (isActive) {
|
|
|
|
|
ResumeAllSfallSound();
|
|
|
|
|
} else {
|
|
|
|
|
PauseAllSfallSound();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static char attackerSnd[9] = {0};
|
|
|
|
@@ -478,14 +552,18 @@ void Sound::init() {
|
|
|
|
|
LoadGameHook::OnGameReset() += WipeSounds;
|
|
|
|
|
LoadGameHook::OnBeforeGameClose() += WipeSounds;
|
|
|
|
|
|
|
|
|
|
int allowDShowSound = GetConfigInt("Sound", "AllowDShowSound", 0);
|
|
|
|
|
if (allowDShowSound > 0) {
|
|
|
|
|
HookCall(0x44E816, gmovie_play_hook_pause);
|
|
|
|
|
HookCall(0x44EA84, gmovie_play_hook_unpause);
|
|
|
|
|
MakeCall(0x450525, gsound_background_volume_set_hack);
|
|
|
|
|
MakeCall(0x4503CA, gsound_master_volume_set_hack, 1);
|
|
|
|
|
MakeCall(0x45042C, gsound_set_sfx_volume_hack);
|
|
|
|
|
|
|
|
|
|
// Pause and resume sound playback when the game loses focus
|
|
|
|
|
fo::func::set_focus_func(SoundLostFocus);
|
|
|
|
|
|
|
|
|
|
if (int allowDShowSound = GetConfigInt("Sound", "AllowDShowSound", 0) > 0) {
|
|
|
|
|
MakeJump(0x4AD499, soundLoad_hack);
|
|
|
|
|
HookCalls(gmovie_play_hook_stop, {0x44E80A, 0x445280}); // only play looping music
|
|
|
|
|
HookCalls(gmovie_play_hook_pause, {0x44E816});
|
|
|
|
|
HookCalls(gmovie_play_hook_unpause, {0x44EA84});
|
|
|
|
|
MakeCall(0x450525, gsound_background_volume_set_hack);
|
|
|
|
|
MakeCall(0x4503CA, gsound_master_volume_set_hack, 1);
|
|
|
|
|
if (allowDShowSound > 1) {
|
|
|
|
|
HookCall(0x450851, gsound_background_play_hook);
|
|
|
|
|
}
|
|
|
|
|