[Scummvm-git-logs] scummvm master -> 221fa4c841e2ead1a629a5026ac61b6f209291d9
NMIError
noreply at scummvm.org
Sat Jan 29 16:33:32 UTC 2022
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
221fa4c841 AUDIO: Add support for RetroWave OPL3
Commit: 221fa4c841e2ead1a629a5026ac61b6f209291d9
https://github.com/scummvm/scummvm/commit/221fa4c841e2ead1a629a5026ac61b6f209291d9
Author: NMIError (60350957+NMIError at users.noreply.github.com)
Date: 2022-01-29T17:33:29+01:00
Commit Message:
AUDIO: Add support for RetroWave OPL3
This commit adds support for the SudoMaker RetroWave OPL3 sound card. Requires
the retrowave library.
Add the following settings to scummvm.ini:
retrowaveopl3_bus=serial
retrowaveopl3_port=<port> f.e. COM3 or ttyACM0
Changed paths:
A audio/rwopl3.cpp
A audio/rwopl3.h
audio/fmopl.cpp
audio/fmopl.h
audio/module.mk
base/version.cpp
configure
devtools/create_project/cmake.cpp
devtools/create_project/create_project.cpp
devtools/create_project/msvc.cpp
devtools/create_project/xcode.cpp
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 7911ed8cf1e..c1a0a75f091 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -22,6 +22,9 @@
#include "audio/fmopl.h"
#include "audio/mixer.h"
+#ifdef USE_RETROWAVE
+#include "audio/rwopl3.h"
+#endif
#include "audio/softsynth/opl/dosbox.h"
#include "audio/softsynth/opl/mame.h"
#include "audio/softsynth/opl/nuked.h"
@@ -48,6 +51,12 @@ namespace OPL2LPT {
} // End of namespace OPL2LPT
#endif // ENABLE_OPL2LPT
+#ifdef USE_RETROWAVE
+namespace RetroWaveOPL3 {
+ OPL *create(Config::OplType type);
+} // End of namespace RetroWaveOPL3
+#endif // ENABLE_RETROWAVE_OPL3
+
// Config implementation
enum OplEmulator {
@@ -57,7 +66,8 @@ enum OplEmulator {
kALSA = 3,
kNuked = 4,
kOPL2LPT = 5,
- kOPL3LPT = 6
+ kOPL3LPT = 6,
+ kRWOPL3 = 7
};
OPL::OPL() {
@@ -81,6 +91,9 @@ const Config::EmulatorDescription Config::_drivers[] = {
#ifdef ENABLE_OPL2LPT
{ "opl2lpt", _s("OPL2LPT"), kOPL2LPT, kFlagOpl2},
{ "opl3lpt", _s("OPL3LPT"), kOPL3LPT, kFlagOpl2 | kFlagOpl3 },
+#endif
+#ifdef USE_RETROWAVE
+ {"rwopl3", _s("RetroWave OPL3"), kRWOPL3, kFlagOpl2 | kFlagOpl3},
#endif
{ nullptr, nullptr, 0, 0 }
};
@@ -224,6 +237,15 @@ OPL *Config::create(DriverId driver, OplType type) {
return 0;
#endif
+#ifdef USE_RETROWAVE
+ case kRWOPL3:
+ if (type == kDualOpl2) {
+ warning("RetroWave OPL3 does not support dual OPL2");
+ return 0;
+ }
+ return RetroWaveOPL3::create(type);
+#endif
+
default:
warning("Unsupported OPL emulator %d", driver);
// TODO: Maybe we should add some dummy emulator too, which just outputs
diff --git a/audio/fmopl.h b/audio/fmopl.h
index d1f025c0fb9..4c556a8ade1 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -225,10 +225,10 @@ protected:
// OPL API
void startCallbacks(int timerFrequency);
void stopCallbacks();
+ virtual void onTimer();
private:
static void timerProc(void *refCon);
- void onTimer();
uint _baseFreq;
uint _remainingTicks;
diff --git a/audio/module.mk b/audio/module.mk
index 24212552d31..b2a413f6e44 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -100,5 +100,10 @@ MODULE_OBJS += \
opl2lpt.o
endif
+ifdef USE_RETROWAVE
+MODULE_OBJS += \
+ rwopl3.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk
diff --git a/audio/rwopl3.cpp b/audio/rwopl3.cpp
new file mode 100644
index 00000000000..13e06ae706d
--- /dev/null
+++ b/audio/rwopl3.cpp
@@ -0,0 +1,235 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * Based on RetroWave OPL3 integration code of DOSBox-X
+ */
+
+// Allow forbidden symbols for included library headers
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "rwopl3.h"
+
+#include <RetroWaveLib/Board/OPL3.h>
+#include <RetroWaveLib/Platform/Linux_SPI.h>
+#include <RetroWaveLib/Platform/POSIX_SerialPort.h>
+#include <RetroWaveLib/Platform/Win32_SerialPort.h>
+
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/tokenizer.h"
+
+namespace OPL {
+namespace RetroWaveOPL3 {
+
+OPL::OPL(Config::OplType type) : _type(type), _activeReg(0), _initialized(false), _connType(RWCONNTYPE_POSIX_SERIAL), _useBuffer(true) {
+ _rwMutex = new Common::Mutex();
+ _retrowaveGlobalContext = { nullptr, nullptr, nullptr, 0, 0, 0 };
+}
+
+OPL::~OPL() {
+ _rwMutex->lock();
+
+ if (_initialized) {
+ reset();
+ retrowave_deinit(&_retrowaveGlobalContext);
+
+ switch (_connType) {
+ case RWCONNTYPE_POSIX_SERIAL:
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+ retrowave_deinit_posix_serialport(&_retrowaveGlobalContext);
+#endif
+ break;
+ case RWCONNTYPE_WIN32_SERIAL:
+#ifdef WIN32
+ retrowave_deinit_win32_serialport(&_retrowaveGlobalContext);
+#endif
+ break;
+ case RWCONNTYPE_LINUX_SPI:
+#if defined(__linux__)
+ retrowave_deinit_linux_spi(&_retrowaveGlobalContext);
+#endif
+ break;
+ }
+
+ _initialized = false;
+ }
+
+ _rwMutex->unlock();
+}
+
+bool OPL::init() {
+ Common::String bus = ConfMan.get("retrowaveopl3_bus");
+ Common::String port = ConfMan.get("retrowaveopl3_port");
+ Common::String spiCs = ConfMan.get("retrowaveopl3_spi_cs");
+ _useBuffer = ConfMan.hasKey("retrowaveopl3_disable_buffer") ? !ConfMan.getBool("retrowaveopl3_disable_buffer") : true;
+
+ int rc = -1;
+
+ _rwMutex->lock();
+
+ if (bus == "serial") {
+ if (port.empty()) {
+ warning("RWOPL3: Missing port specification.");
+ } else {
+#if defined(__linux__) || defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+ char buf[128];
+ snprintf(buf, sizeof(buf) - 1, "/dev/%s", port.c_str());
+
+ rc = retrowave_init_posix_serialport(&_retrowaveGlobalContext, buf);
+ _connType = RWCONNTYPE_POSIX_SERIAL;
+#endif
+
+#ifdef WIN32
+ rc = retrowave_init_win32_serialport(&_retrowaveGlobalContext, port.c_str());
+ _connType = RWCONNTYPE_WIN32_SERIAL;
+#endif
+ }
+ } else if (bus == "spi") {
+#if defined(__linux__)
+ Common::StringTokenizer *st = new Common::StringTokenizer(spiCs, ",");
+ Common::String gpiochip = st->nextToken();
+ Common::String line = st->nextToken();
+ int scg[2] = {0};
+
+ if (gpiochip.empty() || line.empty()) {
+ warning("RWOPL3: Bad GPIO specification. Please use the 'gpiochip,line' format.");
+ } else {
+ scg[0] = strtol(gpiochip.c_str(), nullptr, 10);
+ scg[1] = strtol(line.c_str(), nullptr, 10);
+
+ debug("RWOPL3: SPI CS: chip=%d, line=%d\n", scg[0], scg[1]);
+
+ rc = retrowave_init_linux_spi(&_retrowaveGlobalContext, port.c_str(), scg[0], scg[1]);
+ _connType = RWCONNTYPE_LINUX_SPI;
+ }
+#else
+ warning("RWOPL3: SPI is not supported on your platform.");
+#endif
+ } else {
+ warning("RWOPL3: Bad bus specification. Valid values are \"serial\" and \"spi\".");
+ }
+
+ if (rc < 0) {
+ warning("RWOPL3: Failed to init board - init returned %d.", rc);
+ } else {
+ retrowave_io_init(&_retrowaveGlobalContext);
+ _initialized = true;
+ }
+
+ _rwMutex->unlock();
+
+ return rc >= 0;
+}
+
+void OPL::reset() {
+ _rwMutex->lock();
+
+ if (_initialized) {
+ retrowave_opl3_reset(&_retrowaveGlobalContext);
+
+ writeReg(0x01, 0, true);
+ writeReg(0x02, 0, true);
+ writeReg(0x03, 0, true);
+ writeReg(0x04, 0x60, true);
+ writeReg(0x04, 0x80, true);
+ writeReg(0x104, 0, true);
+ writeReg(0x105, 0, true);
+ writeReg(0x08, 0, true);
+
+ for (int offset = 0; offset <= 0x100; offset += 0x100) {
+ for (int reg = 0x20; reg <= 0xF5; reg++) {
+ writeReg(offset + reg, 0, true);
+ }
+ }
+ }
+
+ _rwMutex->unlock();
+}
+
+void OPL::write(int portAddress, int value) {
+ if (portAddress & 1) {
+ writeReg(_activeReg, value);
+ } else {
+ if (_type == Config::kOpl2) {
+ _activeReg = value & 0xFF;
+ } else {
+ _activeReg = ((portAddress & 2) << 7) | value;
+ }
+ }
+}
+
+byte OPL::read(int portAddress) {
+ // Reads are not supported by the RetroWave OPL3.
+ return 0;
+}
+
+void OPL::writeReg(int reg, int value) {
+ writeReg(reg, value, false);
+}
+
+void OPL::writeReg(int reg, int value, bool forcePort) {
+ int portReg = reg & 0xFF;
+ value &= 0xFF;
+
+ _rwMutex->lock();
+
+ if (_initialized) {
+ if (reg & 0x100 && (forcePort || _type != Config::kOpl2)) {
+ // Write to the second register set.
+ if (_useBuffer) {
+ retrowave_opl3_queue_port1(&_retrowaveGlobalContext, portReg, value);
+ } else {
+ retrowave_opl3_emit_port1(&_retrowaveGlobalContext, portReg, value);
+ }
+ } else {
+ // Write to the first register set.
+ if (_useBuffer) {
+ retrowave_opl3_queue_port0(&_retrowaveGlobalContext, portReg, value);
+ } else {
+ retrowave_opl3_emit_port0(&_retrowaveGlobalContext, portReg, value);
+ }
+ }
+ }
+
+ _rwMutex->unlock();
+}
+
+void OPL::onTimer() {
+ if (_useBuffer) {
+ _rwMutex->lock();
+
+ if (_initialized)
+ retrowave_flush(&_retrowaveGlobalContext);
+
+ _rwMutex->unlock();
+ }
+
+ RealOPL::onTimer();
+}
+
+OPL *create(Config::OplType type) {
+ return new OPL(type);
+}
+
+} // End of namespace RetroWaveOPL3
+} // End of namespace OPL
+
diff --git a/audio/rwopl3.h b/audio/rwopl3.h
new file mode 100644
index 00000000000..ca09d4d32fd
--- /dev/null
+++ b/audio/rwopl3.h
@@ -0,0 +1,75 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * Based on RetroWave OPL3 integration code of DOSBox-X
+ */
+
+#ifndef AUDIO_SOFTSYNTH_OPL_RWOPL3_H
+#define AUDIO_SOFTSYNTH_OPL_RWOPL3_H
+
+#include "audio/fmopl.h"
+#include "common/mutex.h"
+
+#include <RetroWaveLib/RetroWave.h>
+
+namespace OPL {
+namespace RetroWaveOPL3 {
+
+class OPL : public ::OPL::RealOPL {
+private:
+ enum RWConnType {
+ RWCONNTYPE_POSIX_SERIAL,
+ RWCONNTYPE_WIN32_SERIAL,
+ RWCONNTYPE_LINUX_SPI
+ };
+
+ Config::OplType _type;
+ int _activeReg;
+ bool _initialized;
+ RWConnType _connType;
+ bool _useBuffer;
+
+ RetroWaveContext _retrowaveGlobalContext;
+
+ Common::Mutex *_rwMutex;
+
+public:
+ explicit OPL(Config::OplType type);
+ ~OPL();
+
+ bool init() override;
+ void reset() override;
+
+ void write(int portAddress, int value) override;
+ byte read(int portAddress) override;
+
+ void writeReg(int reg, int value) override;
+
+protected:
+ void writeReg(int reg, int value, bool forcePort);
+ void onTimer() override;
+};
+
+} // End of namespace RetroWaveOPL3
+} // End of namespace OPL
+
+#endif
diff --git a/base/version.cpp b/base/version.cpp
index e8a0ff45214..1d54b4cfe05 100644
--- a/base/version.cpp
+++ b/base/version.cpp
@@ -207,5 +207,8 @@ const char gScummVMFeatures[] = ""
#elif USE_GLES_MODE == 2
"OpenGL ES 2 only "
#endif
+#endif
+#ifdef USE_RETROWAVE
+ "RetroWave "
#endif
;
diff --git a/configure b/configure
index dd48f5c89df..a0f66a21fbc 100755
--- a/configure
+++ b/configure
@@ -142,6 +142,7 @@ _tremolo=no
_flac=auto
_mad=auto
_opl2lpt=no
+_retrowave=no
_alsa=auto
_seq_midi=auto
_sndio=auto
@@ -976,6 +977,9 @@ Optional Libraries:
--with-ieee1284-prefix=DIR prefix where libieee1284 is installed (optional)
--enable-opl2lpt enable OPL2LPT support
+
+ --with-retrowave-prefix=DIR prefix where libretrowave is installed (optional)
+ --enable-retrowave enable RetroWave OPL3 support
--with-sparkle-prefix=DIR prefix where sparkle is installed
(macOS/Windows only - optional)
@@ -1103,6 +1107,8 @@ for ac_option in $@; do
--disable-tremor) _tremor=no ;;
--enable-opl2lpt) _opl2lpt=yes ;;
--disable-opl2lpt) _opl2lpt=no ;;
+ --enable-retrowave) _retrowave=yes ;;
+ --disable-retrowave) _retrowave=no ;;
--enable-flac) _flac=yes ;;
--disable-flac) _flac=no ;;
--enable-mad) _mad=yes ;;
@@ -1245,6 +1251,11 @@ for ac_option in $@; do
IEEE1284_CFLAGS="-I$arg/include"
IEEE1284_LIBS="-L$arg/lib"
;;
+ --with-retrowave-prefix=*)
+ arg=`echo $ac_option | cut -d '=' -f 2`
+ RETROWAVE_CFLAGS="-I$arg/include"
+ RETROWAVE_LIBS="-L$arg/lib"
+ ;;
--with-flac-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
FLAC_CFLAGS="-I$arg/include"
@@ -4461,6 +4472,27 @@ fi
define_in_config_if_yes "$_opl2lpt" 'ENABLE_OPL2LPT'
echo "$_opl2lpt"
+#
+# Check for retrowave for RetroWave OPL3
+#
+echocheck "RetroWave OPL3"
+if test "$_retrowave" = yes ; then
+ _retrowave=no
+ cat > $TMPC << EOF
+#include <RetroWaveLib/RetroWave.h>
+RetroWaveContext context;
+int main(void) { retrowave_init(&context); return 0; }
+EOF
+ cc_check $RETROWAVE_CFLAGS $RETROWAVE_LIBS -lretrowave && \
+ _retrowave=yes
+fi
+if test "$_retrowave" = yes; then
+ append_var LIBS "$RETROWAVE_LIBS -lretrowave"
+ append_var INCLUDES "$RETROWAVE_CFLAGS"
+fi
+define_in_config_if_yes "$_retrowave" 'USE_RETROWAVE'
+echo "$_retrowave"
+
#
# Check for FLAC
#
diff --git a/devtools/create_project/cmake.cpp b/devtools/create_project/cmake.cpp
index 35d91573920..cab4c51c6a6 100644
--- a/devtools/create_project/cmake.cpp
+++ b/devtools/create_project/cmake.cpp
@@ -55,7 +55,8 @@ const CMakeProvider::Library *CMakeProvider::getLibraryFromFeature(const char *f
{ "opengl", nullptr, kSDLVersionAny, "FindOpenGL", "OpenGL", "OPENGL_INCLUDE_DIR", "OPENGL_gl_LIBRARY", nullptr },
{ "libcurl", "libcurl", kSDLVersionAny, "FindCURL", "CURL", "CURL_INCLUDE_DIRS", "CURL_LIBRARIES", nullptr },
{ "sdlnet", nullptr, kSDLVersion1, "FindSDL_net", "SDL_net", "SDL_NET_INCLUDE_DIRS", "SDL_NET_LIBRARIES", nullptr },
- { "sdlnet", "SDL2_net", kSDLVersion2, nullptr, nullptr, nullptr, nullptr, "SDL2_net" }
+ { "sdlnet", "SDL2_net", kSDLVersion2, nullptr, nullptr, nullptr, nullptr, "SDL2_net" },
+ { "retrowave", "retrowave", kSDLVersionAny, nullptr, nullptr, nullptr, nullptr, "retrowave" }
};
for (unsigned int i = 0; i < sizeof(s_libraries) / sizeof(s_libraries[0]); i++) {
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 51edd256629..6905ffae521 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -1084,6 +1084,7 @@ const Feature s_features[] = {
{ "libcurl", "USE_LIBCURL", true, true, "libcurl support" },
{ "sdlnet", "USE_SDL_NET", true, true, "SDL_net support" },
{ "discord", "USE_DISCORD", true, false, "Discord support" },
+ { "retrowave", "USE_RETROWAVE", true, false, "RetroWave OPL3 support" },
// Feature flags
{ "bink", "USE_BINK", false, true, "Bink video support" },
diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp
index 81b149688b2..250773b48b2 100644
--- a/devtools/create_project/msvc.cpp
+++ b/devtools/create_project/msvc.cpp
@@ -75,6 +75,7 @@ std::string MSVCProvider::getLibraryFromFeature(const char *feature, const Build
{ "sdlnet", "SDL_net.lib", nullptr, "iphlpapi.lib", nullptr },
{ "sdl2net", "SDL2_net.lib", nullptr, "iphlpapi.lib", "SDL_net.lib" },
{ "discord", "discord-rpc.lib", nullptr, nullptr, nullptr },
+ { "retrowave", "retrowave.lib", nullptr, nullptr, nullptr },
// Feature flags with library dependencies
{ "updates", "winsparkle.lib", nullptr, nullptr, nullptr },
{ "tts", nullptr, nullptr, "sapi.lib", nullptr },
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index f7da3283c17..e7f1f1cb777 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -503,6 +503,9 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
DEF_LOCALLIB_STATIC("libtheoradec");
}
+ if (CONTAINS_DEFINE(setup.defines, "USE_RETROWAVE")) {
+ DEF_LOCALLIB_STATIC("libretrowave");
+ }
if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
DEF_SYSTBD("libz");
}
@@ -706,6 +709,9 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
frameworks_osx.push_back("libtheoradec.a");
}
+ if (CONTAINS_DEFINE(setup.defines, "USE_RETROWAVE")) {
+ frameworks_osx.push_back("libretrowave.a");
+ }
if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
frameworks_osx.push_back("libz.tbd");
}
More information about the Scummvm-git-logs
mailing list