- 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.
This commit is contained in:
Christoph Oelckers 2015-04-25 12:25:10 +02:00
parent 12118550d2
commit d880783784
8 changed files with 148 additions and 86 deletions

View file

@ -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

34
src/sound/except.h Normal file
View file

@ -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

View file

@ -52,6 +52,7 @@ extern HWND Window;
#include <malloc.h>
#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;

View file

@ -53,6 +53,7 @@ extern HINSTANCE g_hInst;
#include "doomtype.h"
#include <math.h>
#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;
}

View file

@ -1,3 +1,10 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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;

View file

@ -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<typename T>
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"))

View file

@ -206,6 +206,8 @@ private:
TArray<OpenALSoundStream*> Streams;
friend class OpenALSoundStream;
ALCdevice *InitDevice();
};
#endif // NO_OPENAL

View file

@ -1,3 +1,10 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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;
}