From d880783784391346de9a96df831d11bc76216093 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Apr 2015 12:25:10 +0200 Subject: [PATCH] - make OpenAL and the decoder libraries delay loaded so that ZDoom can still start without them being present. This required the addition of a few exception handlers so to avoid #ifdef overuse I also added some #defines for non-Windows systems that allow using __try and __except directly in the code without #ifdef'ing them out. --- src/CMakeLists.txt | 4 +- src/sound/except.h | 34 ++++++++++++++++ src/sound/fmodsound.cpp | 36 +++------------- src/sound/i_sound.cpp | 25 ++++++------ src/sound/mpg123_decoder.cpp | 21 ++++++++-- src/sound/oalsound.cpp | 77 ++++++++++++++++++++++------------- src/sound/oalsound.h | 2 + src/sound/sndfile_decoder.cpp | 35 +++++++++++----- 8 files changed, 148 insertions(+), 86 deletions(-) create mode 100644 src/sound/except.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ea29f012..b75b679c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1200,9 +1200,9 @@ endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) if( ZDOOM_GENERATE_MAPFILE ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\" /MAP") else( ZDOOM_GENERATE_MAPFILE ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"") endif( ZDOOM_GENERATE_MAPFILE ) add_custom_command(TARGET zdoom POST_BUILD diff --git a/src/sound/except.h b/src/sound/except.h new file mode 100644 index 000000000..10b484130 --- /dev/null +++ b/src/sound/except.h @@ -0,0 +1,34 @@ +#ifndef __EXCEPT_H +#define __EXCEPT_H + +#ifdef _MSC_VER +//========================================================================== +// +// CheckException +// +//========================================================================== + +#ifndef FACILITY_VISUALCPP +#define FACILITY_VISUALCPP ((LONG)0x6d) +#endif +#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err) + +inline int CheckException(DWORD code) +{ + if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) || + code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND)) + { + return EXCEPTION_EXECUTE_HANDLER; + } + return EXCEPTION_CONTINUE_SEARCH; +} + + +#else + +#define __try +#define __except(a) if (0) + +#endif + +#endif \ No newline at end of file diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index e54569e79..5c06f5301 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -52,6 +52,7 @@ extern HWND Window; #include #endif +#include "except.h" #include "templates.h" #include "fmodsound.h" #include "c_cvars.h" @@ -629,30 +630,6 @@ bool FMODSoundRenderer::IsValid() return InitSuccess; } -#ifdef _MSC_VER -//========================================================================== -// -// CheckException -// -//========================================================================== - -#ifndef FACILITY_VISUALCPP -#define FACILITY_VISUALCPP ((LONG)0x6d) -#endif -#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err) - -static int CheckException(DWORD code) -{ - if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) || - code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND)) - { - return EXCEPTION_EXECUTE_HANDLER; - } - return EXCEPTION_CONTINUE_SEARCH; -} - -#endif - //========================================================================== // // FMODSoundRenderer :: Init @@ -690,12 +667,12 @@ bool FMODSoundRenderer::Init() Printf("I_InitSound: Initializing FMOD\n"); + HMODULE a = GetModuleHandle("fmodex.dll"); + // Create a System object and initialize. -#ifdef _MSC_VER - __try { -#endif - result = FMOD::System_Create(&Sys); -#ifdef _MSC_VER + __try + { + result = FMOD::System_Create(&Sys); } __except(CheckException(GetExceptionCode())) { @@ -707,7 +684,6 @@ bool FMODSoundRenderer::Init() ".dll\n"); return false; } -#endif if (result != FMOD_OK) { Sys = NULL; diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index efac427b5..8904fc7c4 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -53,6 +53,7 @@ extern HINSTANCE g_hInst; #include "doomtype.h" #include +#include "except.h" #include "fmodsound.h" #include "oalsound.h" @@ -574,22 +575,22 @@ SoundDecoder *SoundRenderer::CreateDecoder(FileReader *reader) int pos = reader->Tell(); #ifdef HAVE_MPG123 - decoder = new MPG123Decoder; - if(decoder->open(reader)) - return decoder; - reader->Seek(pos, SEEK_SET); + decoder = new MPG123Decoder; + if (decoder->open(reader)) + return decoder; + reader->Seek(pos, SEEK_SET); - delete decoder; - decoder = NULL; + delete decoder; + decoder = NULL; #endif #ifdef HAVE_SNDFILE - decoder = new SndFileDecoder; - if(decoder->open(reader)) - return decoder; - reader->Seek(pos, SEEK_SET); + decoder = new SndFileDecoder; + if (decoder->open(reader)) + return decoder; + reader->Seek(pos, SEEK_SET); - delete decoder; - decoder = NULL; + delete decoder; + decoder = NULL; #endif return decoder; } diff --git a/src/sound/mpg123_decoder.cpp b/src/sound/mpg123_decoder.cpp index 969706a98..551fe8434 100644 --- a/src/sound/mpg123_decoder.cpp +++ b/src/sound/mpg123_decoder.cpp @@ -1,3 +1,10 @@ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#define USE_WINDOWS_DWORD +#endif +#include "except.h" + #include "mpg123_decoder.h" #include "files.h" @@ -49,9 +56,17 @@ bool MPG123Decoder::open(FileReader *reader) { if(!inited) { - if(mpg123_init() != MPG123_OK) - return false; - inited = true; + __try + { + if(mpg123_init() != MPG123_OK) + return false; + inited = true; + } + __except (CheckException(GetExceptionCode())) + { + // this means that the delay loaded decoder DLL was not found. + return false; + } } Reader = reader; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 6d5b05d1e..3f61578a8 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -38,6 +38,7 @@ #define USE_WINDOWS_DWORD #endif +#include "except.h" #include "doomstat.h" #include "templates.h" #include "oalsound.h" @@ -65,19 +66,25 @@ void I_BuildALDeviceList(FOptionValues *opt) opt->mValues[0].Text = "Default"; #ifndef NO_OPENAL - const ALCchar *names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? - alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : - alcGetString(NULL, ALC_DEVICE_SPECIFIER)); - if(!names) - Printf("Failed to get device list: %s\n", alcGetString(NULL, alcGetError(NULL))); - else while(*names) - { - unsigned int i = opt->mValues.Reserve(1); - opt->mValues[i].TextValue = names; - opt->mValues[i].Text = names; + __try + { + const ALCchar *names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? + alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : + alcGetString(NULL, ALC_DEVICE_SPECIFIER)); + if (!names) + Printf("Failed to get device list: %s\n", alcGetString(NULL, alcGetError(NULL))); + else while (*names) + { + unsigned int i = opt->mValues.Reserve(1); + opt->mValues[i].TextValue = names; + opt->mValues[i].Text = names; - names += strlen(names)+1; - } + names += strlen(names) + 1; + } + } + __except (CheckException(GetExceptionCode())) + { + } #endif } @@ -588,6 +595,34 @@ static float GetRolloff(const FRolloffInfo *rolloff, float distance) return (powf(10.f, volume) - 1.f) / 9.f; } +ALCdevice *OpenALSoundRenderer::InitDevice() +{ + ALCdevice *device = NULL; + __try + { + if(strcmp(snd_aldevice, "Default") != 0) + { + device = alcOpenDevice(*snd_aldevice); + if(!device) + Printf(TEXTCOLOR_BLUE" Failed to open device "TEXTCOLOR_BOLD"%s"TEXTCOLOR_BLUE". Trying default.\n", *snd_aldevice); + } + + if(!device) + { + device = alcOpenDevice(NULL); + if(!device) + { + Printf(TEXTCOLOR_RED" Could not open audio device\n"); + } + } + } + __except(CheckException(GetExceptionCode())) + { + Printf(TEXTCOLOR_ORANGE"Failed to load openal32.dll\n"); + } + return device; +} + template static void LoadALFunc(const char *name, T *x) @@ -601,22 +636,8 @@ OpenALSoundRenderer::OpenALSoundRenderer() Printf("I_InitSound: Initializing OpenAL\n"); - if(strcmp(snd_aldevice, "Default") != 0) - { - Device = alcOpenDevice(*snd_aldevice); - if(!Device) - Printf(TEXTCOLOR_BLUE" Failed to open device "TEXTCOLOR_BOLD"%s"TEXTCOLOR_BLUE". Trying default.\n", *snd_aldevice); - } - - if(!Device) - { - Device = alcOpenDevice(NULL); - if(!Device) - { - Printf(TEXTCOLOR_RED" Could not open audio device\n"); - return; - } - } + Device = InitDevice(); + if (Device == NULL) return; const ALCchar *current = NULL; if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 9ae2db7b2..e6de8ce6d 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -206,6 +206,8 @@ private: TArray Streams; friend class OpenALSoundStream; + + ALCdevice *InitDevice(); }; #endif // NO_OPENAL diff --git a/src/sound/sndfile_decoder.cpp b/src/sound/sndfile_decoder.cpp index 1eba863d4..4a477baf8 100644 --- a/src/sound/sndfile_decoder.cpp +++ b/src/sound/sndfile_decoder.cpp @@ -1,3 +1,10 @@ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#define USE_WINDOWS_DWORD +#endif +#include "except.h" + #include "sndfile_decoder.h" #include "files.h" @@ -47,19 +54,25 @@ SndFileDecoder::~SndFileDecoder() bool SndFileDecoder::open(FileReader *reader) { - SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell }; + __try + { + SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell }; - Reader = reader; - SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this); - if(SndFile) - { - if(SndInfo.channels == 1 || SndInfo.channels == 2) - return true; - - sf_close(SndFile); - SndFile = 0; - } + Reader = reader; + SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this); + if (SndFile) + { + if (SndInfo.channels == 1 || SndInfo.channels == 2) + return true; + sf_close(SndFile); + SndFile = 0; + } + } + __except (CheckException(GetExceptionCode())) + { + // this means that the delay loaded decoder DLL was not found. + } return false; }