diff options
Diffstat (limited to 'sound/fmopl.cpp')
-rw-r--r-- | sound/fmopl.cpp | 104 |
1 files changed, 89 insertions, 15 deletions
diff --git a/sound/fmopl.cpp b/sound/fmopl.cpp index eb84d37366..f0f7327fd4 100644 --- a/sound/fmopl.cpp +++ b/sound/fmopl.cpp @@ -27,27 +27,101 @@ #include "sound/softsynth/opl/dosbox.h" #include "sound/softsynth/opl/mame.h" +#include "common/config-manager.h" + namespace OPL { -bool OPL::_hasInstance = false; +// Config implementation -OPL *OPL::create(kOplType type) { - // Simple hack to assure we only create one instance, - // since the DOSBox OPL emulator does not allow more than - // one instance. - assert(!_hasInstance); - _hasInstance = true; +enum OplEmulator { + kMame = 0, + kDOSBox = 1 +}; -#ifdef DISABLE_DOSBOX_OPL - if (type != kOpl2) - return 0; - else - return new MAME::OPL(); -#else - return new DOSBox::OPL(type); +const Config::EmulatorDescription Config::_drivers[] = { + { "auto", "<default>", 0, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, + { "mame", "MAME OPL emulator", kMame, kFlagOpl2 }, +#ifndef DISABLE_DOSBOX_OPL + { "db", "DOSBox OPL emulator (experimental)", kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, #endif + { 0, 0, 0, 0 } +}; + +Config::DriverId Config::parse(const Common::String &name) { + for (int i = 0; _drivers[i].name; ++i) { + if (name.equalsIgnoreCase(_drivers[i].name)) + return _drivers[i].id; + } + + return 0; } +Config::DriverId Config::detect(OplType type) { + uint32 flags = 0; + switch (type) { + case kOpl2: + flags = kFlagOpl2; + break; + + case kDualOpl2: + flags = kFlagDualOpl2; + break; + + case kOpl3: + flags = kFlagOpl3; + break; + } + + DriverId drv = parse(ConfMan.get("opl_driver")); + + // When a valid driver is selected, check whether it supports + // the requested OPL chip. + if (validDriver(drv)) { + // If the chip is supported, just use the driver. + if ((flags & _drivers[drv].flags)) + return drv; + + // When it doesn't support the flags fall back to auto detection + } + + // Detect the first matching emulator + for (int i = 1; _drivers[i].name; ++i) { + if (_drivers[i].flags & flags) { + drv = _drivers[i].id; + break; + } + } + + return drv; +} + +OPL *Config::create(DriverId driver, OplType type) { + if (!validDriver(driver)) + driver = detect(type); + + switch (driver) { + case kMame: + if (type == kOpl2) + return new MAME::OPL(); + else + warning("MAME OPL emulator only supports OPL2 emulation."); + return 0; + +#ifndef DISABLE_DOSBOX_OPL + case kDOSBox: + return new DOSBox::OPL(type); +#endif + + default: + warning("Unsupported OPL emulator %d", driver); + // TODO: Maybe we should add some dummy emulator too, which just outputs + // silence as sound? + return 0; + } +} + +bool OPL::_hasInstance = false; + } // end of namespace OPL void OPLDestroy(FM_OPL *OPL) { @@ -75,7 +149,7 @@ void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length) { } FM_OPL *makeAdlibOPL(int rate) { - FM_OPL *opl = OPL::OPL::create(OPL::OPL::kOpl2); + FM_OPL *opl = OPL::Config::create(OPL::Config::kOpl2); if (opl) { if (!opl->init(rate)) { |