aboutsummaryrefslogtreecommitdiff
path: root/sound/fmopl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sound/fmopl.cpp')
-rw-r--r--sound/fmopl.cpp104
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)) {