aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorJohannes Schickel2009-05-12 18:42:44 +0000
committerJohannes Schickel2009-05-12 18:42:44 +0000
commit4f0768b9096aab65961d697ca60d6e939f36eae2 (patch)
treecdd956f755a04eb23c140913a0e681ad6094b79b /sound
parent938db170f3af6eaade05fec36edc8011e155422f (diff)
downloadscummvm-rg350-4f0768b9096aab65961d697ca60d6e939f36eae2.tar.gz
scummvm-rg350-4f0768b9096aab65961d697ca60d6e939f36eae2.tar.bz2
scummvm-rg350-4f0768b9096aab65961d697ca60d6e939f36eae2.zip
- Add support for selecting the OPL emulator being used (config entry: "opl_driver")
- Make MAME FM OPL the default emulator again - Add GUI support for selecting the active OPL emulator - Update themes svn-id: r40496
Diffstat (limited to 'sound')
-rw-r--r--sound/fmopl.cpp104
-rw-r--r--sound/fmopl.h70
-rw-r--r--sound/softsynth/opl/dosbox.cpp36
-rw-r--r--sound/softsynth/opl/dosbox.h6
4 files changed, 172 insertions, 44 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)) {
diff --git a/sound/fmopl.h b/sound/fmopl.h
index 7713f76e6a..d84b62f693 100644
--- a/sound/fmopl.h
+++ b/sound/fmopl.h
@@ -26,25 +26,81 @@
#define SOUND_FMOPL_H
#include "common/scummsys.h"
+#include "common/str.h"
namespace OPL {
-class OPL {
-private:
- // TODO: This is part of a temporary HACK to allow only 1 instance
- static bool _hasInstance;
+class OPL;
+
+class Config {
public:
- virtual ~OPL() { _hasInstance = false; }
+ enum OplFlags {
+ kFlagOpl2 = (1 << 0),
+ kFlagDualOpl2 = (1 << 1),
+ kFlagOpl3 = (1 << 2)
+ };
/**
* OPL type to emulate.
*/
- enum kOplType {
+ enum OplType {
kOpl2,
kDualOpl2,
kOpl3
};
+ typedef int8 DriverId;
+ struct EmulatorDescription {
+ const char *name;
+ const char *description;
+
+ DriverId id; // A unique ID for each driver
+ uint32 flags; // Capabilities of this driver
+ };
+
+ /**
+ * Get a list of all available OPL emulators.
+ * @return list of all available OPL emulators, terminated by a zero entry
+ */
+ static const EmulatorDescription *getAvailable() { return _drivers; }
+
+ /**
+ * Returns the driver id of a given name.
+ */
+ static DriverId parse(const Common::String &name);
+
+ /**
+ * Detects a driver for the specific type.
+ */
+ static DriverId detect(OplType type = kOpl2);
+
+ /**
+ * Checks whether the driver id is valid.
+ */
+ static bool validDriver(DriverId id) { return (id > 0); }
+
+ /**
+ * Creates the specific driver with a specific type setup.
+ */
+ static OPL *create(DriverId driver, OplType type);
+
+ /**
+ * Wrapper to easily init an OPL chip, without specifing an emulator.
+ */
+ static OPL *create(OplType type) { return create(detect(type), type); }
+
+private:
+ static const EmulatorDescription _drivers[];
+};
+
+class OPL {
+private:
+ // TODO: This is part of a temporary HACK to allow only 1 instance
+ static bool _hasInstance;
+public:
+ OPL() { _hasInstance = true; }
+ virtual ~OPL() { _hasInstance = false; }
+
/**
* Initializes the OPL emulator.
*
@@ -99,8 +155,6 @@ public:
* Returns whether the setup OPL mode is stereo or not
*/
virtual bool isStereo() const = 0;
-
- static OPL *create(kOplType type);
};
} // end of namespace OPL
diff --git a/sound/softsynth/opl/dosbox.cpp b/sound/softsynth/opl/dosbox.cpp
index db8f8109d7..cbb3090608 100644
--- a/sound/softsynth/opl/dosbox.cpp
+++ b/sound/softsynth/opl/dosbox.cpp
@@ -190,7 +190,7 @@ struct Handler : public DOSBox::Handler {
};
} // end of namespace OPL3
-OPL::OPL(kOplType type) : _type(type), _rate(0), _handler(0) {
+OPL::OPL(Config::OplType type) : _type(type), _rate(0), _handler(0) {
}
OPL::~OPL() {
@@ -209,12 +209,12 @@ bool OPL::init(int rate) {
memset(_chip, 0, sizeof(_chip));
switch (_type) {
- case kOpl2:
+ case Config::kOpl2:
_handler = new OPL2::Handler();
break;
- case kDualOpl2:
- case kOpl3:
+ case Config::kDualOpl2:
+ case Config::kOpl3:
_handler = new OPL3::Handler();
break;
@@ -224,7 +224,7 @@ bool OPL::init(int rate) {
_handler->init(rate);
- if (_type == kDualOpl2) {
+ if (_type == Config::kDualOpl2) {
// Setup opl3 mode in the hander
_handler->writeReg(0x105, 1);
}
@@ -240,12 +240,12 @@ void OPL::reset() {
void OPL::write(int port, int val) {
if (port&1) {
switch (_type) {
- case kOpl2:
- case kOpl3:
+ case Config::kOpl2:
+ case Config::kOpl3:
if (!_chip[0].write(_reg.normal, val))
_handler->writeReg(_reg.normal, val);
break;
- case kDualOpl2:
+ case Config::kDualOpl2:
// Not a 0x??8 port, then write to a specific port
if (!(port & 0x8)) {
byte index = (port & 2) >> 1;
@@ -261,13 +261,13 @@ void OPL::write(int port, int val) {
// Ask the handler to write the address
// Make sure to clip them in the right range
switch (_type) {
- case kOpl2:
+ case Config::kOpl2:
_reg.normal = _handler->writeAddr(port, val) & 0xff;
break;
- case kOpl3:
+ case Config::kOpl3:
_reg.normal = _handler->writeAddr(port, val) & 0x1ff;
break;
- case kDualOpl2:
+ case Config::kDualOpl2:
// Not a 0x?88 port, when write to a specific side
if (!(port & 0x8)) {
byte index = (port & 2) >> 1;
@@ -283,16 +283,16 @@ void OPL::write(int port, int val) {
byte OPL::read(int port) {
switch (_type) {
- case kOpl2:
+ case Config::kOpl2:
if (!(port & 1))
//Make sure the low bits are 6 on opl2
return _chip[0].read() | 0x6;
break;
- case kOpl3:
+ case Config::kOpl3:
if (!(port & 1))
return _chip[0].read();
break;
- case kDualOpl2:
+ case Config::kDualOpl2:
// Only return for the lower ports
if (port & 1)
return 0xff;
@@ -305,9 +305,9 @@ byte OPL::read(int port) {
void OPL::writeReg(int r, int v) {
byte tempReg = 0;
switch (_type) {
- case kOpl2:
- case kDualOpl2:
- case kOpl3:
+ case Config::kOpl2:
+ case Config::kDualOpl2:
+ case Config::kOpl3:
// We can't use _handler->writeReg here directly, since it would miss timer changes.
// Backup old setup register
@@ -350,7 +350,7 @@ void OPL::dualWrite(uint8 index, uint8 reg, uint8 val) {
void OPL::readBuffer(int16 *buffer, int length) {
// For stereo OPL cards, we divide the sample count by 2,
// to match stereo AudioStream behavior.
- if (_type != kOpl2)
+ if (_type != Config::kOpl2)
length >>= 1;
_handler->generate(buffer, length);
diff --git a/sound/softsynth/opl/dosbox.h b/sound/softsynth/opl/dosbox.h
index 68a53276f0..488cc3d82a 100644
--- a/sound/softsynth/opl/dosbox.h
+++ b/sound/softsynth/opl/dosbox.h
@@ -85,7 +85,7 @@ public:
class OPL : public ::OPL::OPL {
private:
- kOplType _type;
+ Config::OplType _type;
uint _rate;
Handler *_handler;
@@ -98,7 +98,7 @@ private:
void free();
void dualWrite(uint8 index, uint8 reg, uint8 val);
public:
- OPL(kOplType type);
+ OPL(Config::OplType type);
~OPL();
bool init(int rate);
@@ -110,7 +110,7 @@ public:
void writeReg(int r, int v);
void readBuffer(int16 *buffer, int length);
- bool isStereo() const { return _type != kOpl2; }
+ bool isStereo() const { return _type != Config::kOpl2; }
};
} // end of namespace DOSBox