aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/sfx/softseq/adlib.cpp2
-rw-r--r--gui/options.cpp31
-rw-r--r--gui/options.h1
-rw-r--r--gui/themes/default.inc6
-rw-r--r--gui/themes/scummclassic.zipbin45619 -> 45730 bytes
-rw-r--r--gui/themes/scummclassic/classic_layout.stx3
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx3
-rw-r--r--gui/themes/scummmodern.zipbin148830 -> 148944 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx3
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx3
-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
14 files changed, 223 insertions, 45 deletions
diff --git a/engines/sci/sfx/softseq/adlib.cpp b/engines/sci/sfx/softseq/adlib.cpp
index 3be0ed86f3..92a04f065e 100644
--- a/engines/sci/sfx/softseq/adlib.cpp
+++ b/engines/sci/sfx/softseq/adlib.cpp
@@ -82,7 +82,7 @@ int MidiDriver_Adlib::open(bool isSCI0) {
debug(3, "ADLIB: Starting driver in %s mode", (isSCI0 ? "SCI0" : "SCI1"));
_isSCI0 = isSCI0;
- _opl = OPL::OPL::create(isStereo() ? OPL::OPL::kDualOpl2 : OPL::OPL::kOpl2);
+ _opl = OPL::Config::create(isStereo() ? OPL::Config::kDualOpl2 : OPL::Config::kOpl2);
if (!_opl)
return -1;
diff --git a/gui/options.cpp b/gui/options.cpp
index 956c0d8cf6..c152a3a266 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -40,6 +40,7 @@
#include "sound/mididrv.h"
#include "sound/mixer.h"
+#include "sound/fmopl.h"
namespace GUI {
@@ -102,6 +103,7 @@ void OptionsDialog::init() {
_aspectCheckbox = 0;
_enableAudioSettings = false;
_midiPopUp = 0;
+ _oplPopUp = 0;
_outputRatePopUp = 0;
_enableMIDISettings = false;
_multiMidiCheckbox = 0;
@@ -181,6 +183,9 @@ void OptionsDialog::open() {
_midiPopUp->setSelectedTag(id);
}
+ if (_oplPopUp)
+ _oplPopUp->setSelectedTag(OPL::Config::parse(ConfMan.get("opl_driver", _domain)));
+
if (_outputRatePopUp) {
_outputRatePopUp->setSelected(1);
int value = ConfMan.getInt("output_rate", _domain);
@@ -315,6 +320,21 @@ void OptionsDialog::close() {
}
}
+ if (_oplPopUp) {
+ if (_enableAudioSettings) {
+ const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable();
+ while (ed->name && ed->id != (int)_oplPopUp->getSelectedTag())
+ ++ed;
+
+ if (ed->name)
+ ConfMan.set("opl_driver", ed->name, _domain);
+ else
+ ConfMan.removeKey("opl_driver", _domain);
+ } else {
+ ConfMan.removeKey("opl_driver", _domain);
+ }
+ }
+
if (_outputRatePopUp) {
if (_enableAudioSettings) {
if (_outputRatePopUp->getSelectedTag() != 0)
@@ -457,6 +477,7 @@ void OptionsDialog::setAudioSettingsState(bool enabled) {
_enableAudioSettings = enabled;
_midiPopUp->setEnabled(enabled);
+ _oplPopUp->setEnabled(enabled);
_outputRatePopUp->setEnabled(enabled);
}
@@ -545,6 +566,16 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) {
md++;
}
+ // The OPL emulator popup & a label
+ _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup", "AdLib emulator:");
+
+ // Populate it
+ const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable();
+ while (ed->name) {
+ _oplPopUp->appendEntry(ed->description, ed->id);
+ ++ed;
+ }
+
// Sample rate settings
_outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate:");
diff --git a/gui/options.h b/gui/options.h
index aca5db83cd..53fc5e2d01 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -101,6 +101,7 @@ private:
//
bool _enableAudioSettings;
PopUpWidget *_midiPopUp;
+ PopUpWidget *_oplPopUp;
PopUpWidget *_outputRatePopUp;
//
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index d5fcd8e6eb..ddb8127d77 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -475,6 +475,9 @@
"<widget name='auMidiPopup' "
"type='PopUp' "
"/> "
+"<widget name='auOPLPopup' "
+"type='PopUp' "
+"/> "
"<widget name='auSampleRatePopup' "
"type='PopUp' "
"/> "
@@ -1115,6 +1118,9 @@
"<widget name='auMidiPopup' "
"type='PopUp' "
"/> "
+"<widget name='auOPLPopup' "
+"type='PopUp' "
+"/> "
"<widget name='auSampleRatePopup' "
"type='PopUp' "
"/> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index ad886efd12..798f4d292f 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 4d7698f306..bb7fdc20a2 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -186,6 +186,9 @@
<widget name = 'auMidiPopup'
type = 'PopUp'
/>
+ <widget name = 'auOPLPopup'
+ type = 'PopUp'
+ />
<widget name = 'auSampleRatePopup'
type = 'PopUp'
/>
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 33401966c4..c144f0bad3 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -183,6 +183,9 @@
<widget name = 'auMidiPopup'
type = 'PopUp'
/>
+ <widget name = 'auOPLPopup'
+ type = 'PopUp'
+ />
<widget name = 'auSampleRatePopup'
type = 'PopUp'
/>
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index eb0f890f15..a67b11f244 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 6377cc48ae..736fce87f2 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -201,6 +201,9 @@
<widget name = 'auMidiPopup'
type = 'PopUp'
/>
+ <widget name = 'auOPLPopup'
+ type = 'PopUp'
+ />
<widget name = 'auSampleRatePopup'
type = 'PopUp'
/>
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 36ed3f25fa..bf19b48485 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -181,6 +181,9 @@
<widget name = 'auMidiPopup'
type = 'PopUp'
/>
+ <widget name = 'auOPLPopup'
+ type = 'PopUp'
+ />
<widget name = 'auSampleRatePopup'
type = 'PopUp'
/>
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