[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