Merge branch experimental/adlmidi into master
Add experimental support for using ADL MIDI instead of SDL for music playback. Support for ADL MIDI contributed by Github user jpcima. This feature is minimally supported by the core Rebirth team, but is included as a courtesy so that users need not patch in support separately. Suggested-by: jpcima <https://github.com/dxx-rebirth/dxx-rebirth/pull/408>
This commit is contained in:
commit
931ea05f41
32
SConstruct
32
SConstruct
|
@ -1160,6 +1160,22 @@ struct d_screenshot
|
|||
successflags = self.pkgconfig.merge(context, self.msgprefix, self.user_settings, 'libpng', 'libpng', _guess_flags)
|
||||
return self._soft_check_system_library(context, header=_header, main=_main, lib='png', text=_text, successflags=successflags)
|
||||
|
||||
@_custom_test
|
||||
def _check_user_settings_adldmidi(self,context):
|
||||
user_settings = self.user_settings
|
||||
adlmidi = user_settings.adlmidi
|
||||
if adlmidi == 'none':
|
||||
adlmidi_load_type = 'disabled'
|
||||
elif adlmidi == 'runtime':
|
||||
adlmidi_load_type = 'load dynamically'
|
||||
else:
|
||||
return
|
||||
context.Result('%s: checking how to handle ADL MIDI...%s' % (self.msgprefix, adlmidi_load_type))
|
||||
Define = context.sconf.Define
|
||||
enable_adlmidi = int(adlmidi != 'none')
|
||||
user_settings._enable_adlmidi = enable_adlmidi
|
||||
Define('DXX_USE_ADLMIDI', enable_adlmidi)
|
||||
|
||||
@_custom_test
|
||||
def _check_user_settings_screenshot(self,context):
|
||||
user_settings = self.user_settings
|
||||
|
@ -3440,6 +3456,8 @@ class DXXCommon(LazyObjectConstructor):
|
|||
if self.raspberrypi == 'yes':
|
||||
return 'brcmEGL'
|
||||
return self.default_EGL_LIB
|
||||
def need_dynamic_library_load(self):
|
||||
return self.adlmidi == 'runtime'
|
||||
|
||||
def __default_DATA_DIR(self):
|
||||
platform_settings_type = self._program.get_platform_settings_type(self.host_platform)
|
||||
|
@ -3634,6 +3652,7 @@ class DXXCommon(LazyObjectConstructor):
|
|||
'variable': EnumVariable,
|
||||
'arguments': (
|
||||
('host_endian', None, 'endianness of host platform', {'allowed_values' : ('little', 'big')}),
|
||||
('adlmidi', 'none', 'include ADL MIDI support (none: disabled; runtime: dynamically load at runtime)', {'allowed_values' : ('none', 'runtime')}),
|
||||
('screenshot', 'png', 'screenshot file format', {'allowed_values' : ('none', 'legacy', 'png')}),
|
||||
),
|
||||
},
|
||||
|
@ -4276,13 +4295,19 @@ class DXXArchive(DXXCommon):
|
|||
'common/misc/vgrphys.cpp',
|
||||
'common/misc/vgwphys.cpp',
|
||||
)), \
|
||||
__get_objects_use_adlmidi=DXXCommon.create_lazy_object_getter((
|
||||
'common/music/adlmidi_dynamic.cpp',
|
||||
)),
|
||||
__get_objects_use_sdl1=DXXCommon.create_lazy_object_getter((
|
||||
'common/arch/sdl/rbaudio.cpp',
|
||||
))
|
||||
):
|
||||
value = list(__get_objects_common(self))
|
||||
extend = value.extend
|
||||
if not self.user_settings.sdl2:
|
||||
user_settings = self.user_settings
|
||||
if user_settings._enable_adlmidi:
|
||||
extend(__get_objects_use_adlmidi(self))
|
||||
if not user_settings.sdl2:
|
||||
extend(__get_objects_use_sdl1(self))
|
||||
extend(self.platform_settings.get_platform_objects())
|
||||
return value
|
||||
|
@ -4641,6 +4666,11 @@ class DXXProgram(DXXCommon):
|
|||
DXXCommon.LinuxPlatformSettings.__init__(self,program,user_settings)
|
||||
if user_settings.sharepath and user_settings.sharepath[-1] != '/':
|
||||
user_settings.sharepath += '/'
|
||||
def adjust_environment(self,program,env):
|
||||
DXXCommon.LinuxPlatformSettings.adjust_environment(self,program,env)
|
||||
user_settings = self.user_settings
|
||||
if user_settings.need_dynamic_library_load():
|
||||
env.Append(LIBS = ['dl'])
|
||||
|
||||
def get_objects_common(self,
|
||||
__get_objects_common=__get_objects_common,
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
|
||||
#include "args.h"
|
||||
#include "hmp.h"
|
||||
#include "adlmidi_dynamic.h"
|
||||
#include "digi_mixer_music.h"
|
||||
#include "strutil.h"
|
||||
#include "u_mem.h"
|
||||
#include "config.h"
|
||||
#include "console.h"
|
||||
|
||||
namespace dcx {
|
||||
|
@ -92,13 +94,53 @@ public:
|
|||
static current_music_t current_music;
|
||||
static std::vector<uint8_t> current_music_hndlbuf;
|
||||
|
||||
#if DXX_USE_ADLMIDI
|
||||
static ADL_MIDIPlayer_t current_adlmidi;
|
||||
static ADL_MIDIPlayer *get_adlmidi()
|
||||
{
|
||||
if (!CGameCfg.ADLMIDI_enabled)
|
||||
return nullptr;
|
||||
ADL_MIDIPlayer *adlmidi = current_adlmidi.get();
|
||||
if (!adlmidi)
|
||||
{
|
||||
int sample_rate;
|
||||
Mix_QuerySpec(&sample_rate, nullptr, nullptr);
|
||||
adlmidi = adl_init(sample_rate);
|
||||
if (adlmidi)
|
||||
{
|
||||
adl_switchEmulator(adlmidi, ADLMIDI_EMU_DOSBOX);
|
||||
adl_setNumChips(adlmidi, CGameCfg.ADLMIDI_num_chips);
|
||||
adl_setBank(adlmidi, CGameCfg.ADLMIDI_bank);
|
||||
adl_setSoftPanEnabled(adlmidi, 1);
|
||||
current_adlmidi.reset(adlmidi);
|
||||
}
|
||||
}
|
||||
return adlmidi;
|
||||
}
|
||||
|
||||
static void mix_adlmidi(void *udata, Uint8 *stream, int len);
|
||||
#endif
|
||||
|
||||
enum class CurrentMusicType
|
||||
{
|
||||
None,
|
||||
#if DXX_USE_ADLMIDI
|
||||
ADLMIDI,
|
||||
#endif
|
||||
SDLMixer,
|
||||
};
|
||||
|
||||
static CurrentMusicType current_music_type = CurrentMusicType::None;
|
||||
|
||||
static CurrentMusicType load_mus_data(const uint8_t *data, size_t size);
|
||||
static CurrentMusicType load_mus_file(const char *filename);
|
||||
|
||||
/*
|
||||
* Plays a music file from an absolute path or a relative path
|
||||
*/
|
||||
|
||||
int mix_play_file(const char *filename, int loop, void (*hook_finished_track)())
|
||||
{
|
||||
SDL_RWops *rw = NULL;
|
||||
array<char, PATH_MAX> full_path;
|
||||
const char *fptr;
|
||||
unsigned int bufsize = 0;
|
||||
|
@ -114,17 +156,16 @@ int mix_play_file(const char *filename, int loop, void (*hook_finished_track)())
|
|||
if (!d_stricmp(fptr, ".hmp"))
|
||||
{
|
||||
hmp2mid(filename, current_music_hndlbuf);
|
||||
rw = SDL_RWFromConstMem(¤t_music_hndlbuf[0], current_music_hndlbuf.size()*sizeof(char));
|
||||
current_music.reset(Mix_LoadMUS_RW(rw DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS) DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw));
|
||||
current_music_type = load_mus_data(current_music_hndlbuf.data(), current_music_hndlbuf.size());
|
||||
}
|
||||
|
||||
// try loading music via given filename
|
||||
if (!current_music)
|
||||
current_music.reset(Mix_LoadMUS(filename));
|
||||
if (current_music_type == CurrentMusicType::None)
|
||||
current_music_type = load_mus_file(filename);
|
||||
|
||||
// allow the shell convention tilde character to mean the user's home folder
|
||||
// chiefly used for default jukebox level song music referenced in 'descent.m3u' for Mac OS X
|
||||
if (!current_music && *filename == '~')
|
||||
if (current_music_type == CurrentMusicType::None && *filename == '~')
|
||||
{
|
||||
const auto sep = PHYSFS_getDirSeparator();
|
||||
const auto lensep = strlen(sep);
|
||||
|
@ -132,46 +173,61 @@ int mix_play_file(const char *filename, int loop, void (*hook_finished_track)())
|
|||
&filename[1 + (!strncmp(&filename[1], sep, lensep)
|
||||
? lensep
|
||||
: 0)]);
|
||||
current_music.reset(Mix_LoadMUS(full_path.data()));
|
||||
if (current_music)
|
||||
current_music_type = load_mus_file(full_path.data());
|
||||
if (current_music_type != CurrentMusicType::None)
|
||||
filename = full_path.data(); // used later for possible error reporting
|
||||
}
|
||||
|
||||
|
||||
// no luck. so it might be in Searchpath. So try to build absolute path
|
||||
if (!current_music)
|
||||
if (current_music_type == CurrentMusicType::None)
|
||||
{
|
||||
PHYSFSX_getRealPath(filename, full_path);
|
||||
current_music.reset(Mix_LoadMUS(full_path.data()));
|
||||
if (current_music)
|
||||
current_music_type = load_mus_file(full_path.data());
|
||||
if (current_music_type != CurrentMusicType::None)
|
||||
filename = full_path.data(); // used later for possible error reporting
|
||||
}
|
||||
|
||||
// still nothin'? Let's open via PhysFS in case it's located inside an archive
|
||||
if (!current_music)
|
||||
if (current_music_type == CurrentMusicType::None)
|
||||
{
|
||||
if (RAIIPHYSFS_File filehandle{PHYSFS_openRead(filename)})
|
||||
{
|
||||
unsigned len = PHYSFS_fileLength(filehandle);
|
||||
current_music_hndlbuf.resize(len);
|
||||
bufsize = PHYSFS_read(filehandle, ¤t_music_hndlbuf[0], sizeof(char), len);
|
||||
rw = SDL_RWFromConstMem(¤t_music_hndlbuf[0], bufsize*sizeof(char));
|
||||
current_music.reset(Mix_LoadMUS_RW(rw DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS) DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw));
|
||||
current_music_type = load_mus_data(current_music_hndlbuf.data(), bufsize*sizeof(char));
|
||||
}
|
||||
}
|
||||
|
||||
if (current_music)
|
||||
switch (current_music_type)
|
||||
{
|
||||
|
||||
#if DXX_USE_ADLMIDI
|
||||
case CurrentMusicType::ADLMIDI:
|
||||
{
|
||||
ADL_MIDIPlayer *adlmidi = get_adlmidi();
|
||||
adl_setLoopEnabled(adlmidi, loop);
|
||||
Mix_HookMusic(&mix_adlmidi, nullptr);
|
||||
Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
case CurrentMusicType::SDLMixer:
|
||||
{
|
||||
Mix_PlayMusic(current_music.get(), (loop ? -1 : 1));
|
||||
Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
||||
default:
|
||||
{
|
||||
con_printf(CON_CRITICAL,"Music %s could not be loaded: %s", filename, Mix_GetError());
|
||||
mix_stop_music();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -179,8 +235,18 @@ int mix_play_file(const char *filename, int loop, void (*hook_finished_track)())
|
|||
void mix_free_music()
|
||||
{
|
||||
Mix_HaltMusic();
|
||||
#if DXX_USE_ADLMIDI
|
||||
/* Only ADLMIDI can set a hook, so if ADLMIDI is compiled out, there is no
|
||||
* need to clear the hook.
|
||||
*
|
||||
* When ADLMIDI is supported, clear unconditionally, instead of checking
|
||||
* whether the music type requires it.
|
||||
*/
|
||||
Mix_HookMusic(nullptr, nullptr);
|
||||
#endif
|
||||
current_music.reset();
|
||||
current_music_hndlbuf.clear();
|
||||
current_music_type = CurrentMusicType::None;
|
||||
}
|
||||
|
||||
void mix_set_music_volume(int vol)
|
||||
|
@ -213,4 +279,66 @@ void mix_pause_resume_music()
|
|||
Mix_PauseMusic();
|
||||
}
|
||||
|
||||
static CurrentMusicType load_mus_data(const uint8_t *data, size_t size)
|
||||
{
|
||||
CurrentMusicType type = CurrentMusicType::None;
|
||||
#if DXX_USE_ADLMIDI
|
||||
const auto adlmidi = get_adlmidi();
|
||||
if (adlmidi && adl_openData(adlmidi, data, size) == 0)
|
||||
type = CurrentMusicType::ADLMIDI;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const auto rw = SDL_RWFromConstMem(data, size);
|
||||
current_music.reset(Mix_LoadMUS_RW(rw DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS) DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw));
|
||||
if (current_music)
|
||||
type = CurrentMusicType::SDLMixer;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static CurrentMusicType load_mus_file(const char *filename)
|
||||
{
|
||||
CurrentMusicType type = CurrentMusicType::None;
|
||||
#if DXX_USE_ADLMIDI
|
||||
const auto adlmidi = get_adlmidi();
|
||||
if (adlmidi && adl_openFile(adlmidi, filename) == 0)
|
||||
type = CurrentMusicType::ADLMIDI;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
current_music.reset(Mix_LoadMUS(filename));
|
||||
if (current_music)
|
||||
type = CurrentMusicType::SDLMixer;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
#if DXX_USE_ADLMIDI
|
||||
static int16_t sat16(int32_t x)
|
||||
{
|
||||
x = (x < INT16_MIN) ? INT16_MIN : x;
|
||||
x = (x > INT16_MAX) ? INT16_MAX : x;
|
||||
return x;
|
||||
}
|
||||
|
||||
static void mix_adlmidi(void *, Uint8 *stream, int len)
|
||||
{
|
||||
ADLMIDI_AudioFormat format;
|
||||
format.containerSize = sizeof(int16_t);
|
||||
format.sampleOffset = 2 * format.containerSize;
|
||||
format.type = ADLMIDI_SampleType_S16;
|
||||
|
||||
ADL_MIDIPlayer *adlmidi = get_adlmidi();
|
||||
int sampleCount = len / format.containerSize;
|
||||
adl_playFormat(adlmidi, sampleCount, stream, stream + format.containerSize, &format);
|
||||
|
||||
const auto samples = reinterpret_cast<int16_t *>(stream);
|
||||
const auto amplify = [](int16_t i) { return sat16(2 * i); };
|
||||
std::transform(samples, samples + sampleCount, samples, amplify);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
76
common/include/adlmidi_dynamic.h
Normal file
76
common/include/adlmidi_dynamic.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
/*
|
||||
* This is a dynamic interface to libADLMIDI, the OPL3 synthesizer library.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include "dxxsconf.h"
|
||||
|
||||
#if DXX_USE_ADLMIDI
|
||||
struct ADL_MIDIPlayer;
|
||||
|
||||
enum ADLMIDI_SampleType
|
||||
{
|
||||
ADLMIDI_SampleType_S16 = 0
|
||||
};
|
||||
|
||||
struct ADLMIDI_AudioFormat
|
||||
{
|
||||
enum ADLMIDI_SampleType type;
|
||||
unsigned containerSize;
|
||||
unsigned sampleOffset;
|
||||
};
|
||||
|
||||
enum ADL_Emulator
|
||||
{
|
||||
ADLMIDI_EMU_DOSBOX = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* A few embedded bank numbers.
|
||||
*/
|
||||
enum class ADL_EmbeddedBank
|
||||
{
|
||||
MILES_AIL = 0,
|
||||
BISQWIT = 1,
|
||||
DESCENT = 2,
|
||||
// DESCENT_INT = 3,
|
||||
// DESCENT_HAM = 4,
|
||||
// DESCENT_RICK = 5,
|
||||
// DESCENT2 = 6,
|
||||
LBA_4OP = 31,
|
||||
THE_FATMAN_2OP = 58,
|
||||
THE_FATMAN_4OP = 59,
|
||||
JAMIE_OCONNELL = 66,
|
||||
NGUYEN_WOHLSTAND_4OP = 68,
|
||||
DMXOPL3 = 72,
|
||||
APOGEE_IMF90 = 74,
|
||||
};
|
||||
|
||||
extern ADL_MIDIPlayer *(*adl_init)(long sample_rate);
|
||||
extern void (*adl_close)(ADL_MIDIPlayer *device);
|
||||
extern int (*adl_switchEmulator)(ADL_MIDIPlayer *device, int emulator);
|
||||
extern int (*adl_setNumChips)(ADL_MIDIPlayer *device, int numChips);
|
||||
extern int (*adl_setBank)(ADL_MIDIPlayer *device, int bank);
|
||||
extern void (*adl_setSoftPanEnabled)(ADL_MIDIPlayer *device, int softPanEn);
|
||||
extern void (*adl_setLoopEnabled)(ADL_MIDIPlayer *device, int loopEn);
|
||||
extern int (*adl_openData)(ADL_MIDIPlayer *device, const void *mem, unsigned long size);
|
||||
extern int (*adl_openFile)(ADL_MIDIPlayer *device, const char *filePath);
|
||||
extern int (*adl_playFormat)(ADL_MIDIPlayer *device, int sampleCount, uint8_t *left, uint8_t *right, const ADLMIDI_AudioFormat *format);
|
||||
|
||||
struct ADLMIDI_delete
|
||||
{
|
||||
void operator()(ADL_MIDIPlayer *x)
|
||||
{
|
||||
adl_close(x);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<ADL_MIDIPlayer, ADLMIDI_delete> ADL_MIDIPlayer_t;
|
||||
#endif
|
|
@ -38,6 +38,14 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
namespace dcx {
|
||||
struct CCfg : prohibit_void_ptr<CCfg>
|
||||
{
|
||||
#if DXX_USE_ADLMIDI
|
||||
int ADLMIDI_num_chips = 6;
|
||||
/* See common/include/adlmidi_dynamic.h for the symbolic name and for other
|
||||
* values.
|
||||
*/
|
||||
int ADLMIDI_bank = 31;
|
||||
bool ADLMIDI_enabled;
|
||||
#endif
|
||||
bool VSync;
|
||||
bool Grabinput;
|
||||
bool WindowMode;
|
||||
|
|
113
common/music/adlmidi_dynamic.cpp
Normal file
113
common/music/adlmidi_dynamic.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
/*
|
||||
* This is a dynamic interface to libADLMIDI, the OPL3 synthesizer library.
|
||||
*/
|
||||
|
||||
#include "adlmidi_dynamic.h"
|
||||
#include "console.h"
|
||||
#if !defined(_WIN32)
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(_WIN32)
|
||||
enum
|
||||
{
|
||||
RTLD_LAZY = 1, RTLD_NOW = 2
|
||||
};
|
||||
|
||||
HMODULE dlopen(const char *const filename, int)
|
||||
{
|
||||
return LoadLibraryA(filename);
|
||||
}
|
||||
|
||||
void dlclose(const HMODULE handle)
|
||||
{
|
||||
FreeLibrary(handle);
|
||||
}
|
||||
|
||||
void *dlsym(const HMODULE handle, const char *const symbol)
|
||||
{
|
||||
return reinterpret_cast<void *>(
|
||||
GetProcAddress(handle, symbol));
|
||||
}
|
||||
#else
|
||||
using HMODULE = void *;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static ADL_MIDIPlayer *adl_init_failure(long)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void reported_failed_load_function(const char *const name)
|
||||
{
|
||||
con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic function \"%s\"", name);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
static bool load_function(const HMODULE handle, const char *const name, F *&fptr)
|
||||
{
|
||||
const auto f = reinterpret_cast<F *>(dlsym(handle, name));
|
||||
fptr = f;
|
||||
if (!f)
|
||||
/* Use out of line report function to prevent redundant instantiations
|
||||
* on a per-type basis.
|
||||
*/
|
||||
reported_failed_load_function(name);
|
||||
return f;
|
||||
}
|
||||
|
||||
static ADL_MIDIPlayer *adl_init_first_call(long sample_rate)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
const char *library_name = "libADLMIDI.dll";
|
||||
#elif defined(__APPLE__)
|
||||
const char *library_name = "libADLMIDI.dylib";
|
||||
#else
|
||||
const char *library_name = "libADLMIDI.so";
|
||||
#endif
|
||||
const auto handle = dlopen(library_name, RTLD_NOW);
|
||||
if (!handle ||
|
||||
!load_function(handle, "adl_init", adl_init) ||
|
||||
!load_function(handle, "adl_close", adl_close) ||
|
||||
!load_function(handle, "adl_switchEmulator", adl_switchEmulator) ||
|
||||
!load_function(handle, "adl_setNumChips", adl_setNumChips) ||
|
||||
!load_function(handle, "adl_setBank", adl_setBank) ||
|
||||
!load_function(handle, "adl_setSoftPanEnabled", adl_setSoftPanEnabled) ||
|
||||
!load_function(handle, "adl_setLoopEnabled", adl_setLoopEnabled) ||
|
||||
!load_function(handle, "adl_openData", adl_openData) ||
|
||||
!load_function(handle, "adl_openFile", adl_openFile) ||
|
||||
!load_function(handle, "adl_playFormat", adl_playFormat))
|
||||
{
|
||||
adl_init = &adl_init_failure;
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
else
|
||||
con_printf(CON_NORMAL, "ADLMIDI: failed to load the dynamic library \"%s\"", library_name);
|
||||
}
|
||||
else
|
||||
con_printf(CON_NORMAL, "ADLMIDI: loaded the dynamic OPL3 synthesizer");
|
||||
return adl_init(sample_rate);
|
||||
}
|
||||
|
||||
ADL_MIDIPlayer *(*adl_init)(long sample_rate) = &adl_init_first_call;
|
||||
void (*adl_close)(ADL_MIDIPlayer *device);
|
||||
int (*adl_switchEmulator)(ADL_MIDIPlayer *device, int emulator);
|
||||
int (*adl_setNumChips)(ADL_MIDIPlayer *device, int numChips);
|
||||
int (*adl_setBank)(ADL_MIDIPlayer *device, int bank);
|
||||
void (*adl_setSoftPanEnabled)(ADL_MIDIPlayer *device, int softPanEn);
|
||||
void (*adl_setLoopEnabled)(ADL_MIDIPlayer *device, int loopEn);
|
||||
int (*adl_openData)(ADL_MIDIPlayer *device, const void *mem, unsigned long size);
|
||||
int (*adl_openFile)(ADL_MIDIPlayer *device, const char *filePath);
|
||||
int (*adl_playFormat)(ADL_MIDIPlayer *device, int sampleCount, uint8_t *left, uint8_t *right, const ADLMIDI_AudioFormat *format);
|
|
@ -69,6 +69,8 @@ What's new in 0.60
|
|||
* Fixed original game bug that prevented markers from spinning. Markers were given a spin rate, but their type did not use that field, so they did not spin. Markers now spin, and their spin varies based on an internal identifier, so different markers will spin in different directions and orientations.
|
||||
* New SP (Options->Gameplay) / MP (Host Game -> Game Setup -> Advanced) options to remove the thief during level load and to restore the thief energy weapon bug.
|
||||
* Command line option `-tmap` was specific to SDL-only builds and had no effect in OpenGL-enabled builds. It is no longer accepted by OpenGL builds.
|
||||
* Added experimental support for ADL MIDI [contributed by jpcima].
|
||||
- Users must separately install a compatible ADL MIDI library on the library search path.
|
||||
* ... and many, many more bugfixes and improvements.
|
||||
|
||||
|
||||
|
|
|
@ -81,6 +81,11 @@ Cfg GameCfg;
|
|||
#define MovieTexFiltStr "MovieTexFilt"
|
||||
#define MovieSubtitlesStr "MovieSubtitles"
|
||||
#endif
|
||||
#if DXX_USE_ADLMIDI
|
||||
#define ADLMIDINumChipsStr "ADLMIDI_NumberOfChips"
|
||||
#define ADLMIDIBankStr "ADLMIDI_Bank"
|
||||
#define ADLMIDIEnabledStr "ADLMIDI_Enabled"
|
||||
#endif
|
||||
#define VSyncStr "VSync"
|
||||
#define MultisampleStr "Multisample"
|
||||
#define FPSIndicatorStr "FPSIndicator"
|
||||
|
@ -212,6 +217,14 @@ int ReadConfigFile()
|
|||
convert_integer(GameCfg.MovieTexFilt, value);
|
||||
else if (cmp(lb, eq, MovieSubtitlesStr))
|
||||
convert_integer(GameCfg.MovieSubtitles, value);
|
||||
#endif
|
||||
#if DXX_USE_ADLMIDI
|
||||
else if (cmp(lb, eq, ADLMIDINumChipsStr))
|
||||
convert_integer(CGameCfg.ADLMIDI_num_chips, value);
|
||||
else if (cmp(lb, eq, ADLMIDIBankStr))
|
||||
convert_integer(CGameCfg.ADLMIDI_bank, value);
|
||||
else if (cmp(lb, eq, ADLMIDIEnabledStr))
|
||||
convert_integer(CGameCfg.ADLMIDI_enabled, value);
|
||||
#endif
|
||||
else if (cmp(lb, eq, VSyncStr))
|
||||
convert_integer(CGameCfg.VSync, value);
|
||||
|
@ -270,6 +283,11 @@ int WriteConfigFile()
|
|||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
PHYSFSX_printf(infile, "%s=%i\n", MovieTexFiltStr, GameCfg.MovieTexFilt);
|
||||
PHYSFSX_printf(infile, "%s=%i\n", MovieSubtitlesStr, GameCfg.MovieSubtitles);
|
||||
#endif
|
||||
#if DXX_USE_ADLMIDI
|
||||
PHYSFSX_printf(infile, "%s=%i\n", ADLMIDINumChipsStr, CGameCfg.ADLMIDI_num_chips);
|
||||
PHYSFSX_printf(infile, "%s=%i\n", ADLMIDIBankStr, CGameCfg.ADLMIDI_bank);
|
||||
PHYSFSX_printf(infile, "%s=%i\n", ADLMIDIEnabledStr, CGameCfg.ADLMIDI_enabled);
|
||||
#endif
|
||||
PHYSFSX_printf(infile, "%s=%i\n", VSyncStr, CGameCfg.VSync);
|
||||
PHYSFSX_printf(infile, "%s=%i\n", MultisampleStr, CGameCfg.Multisample);
|
||||
|
|
Loading…
Reference in a new issue