diff --git a/src/dosbox.cpp b/src/dosbox.cpp
index 7a9651b12..f71c66fe6 100644
--- a/src/dosbox.cpp
+++ b/src/dosbox.cpp
@@ -1316,7 +1316,7 @@ void DOSBOX_SetupConfigSections(void) {
const char* irqssb[] = { "7", "5", "3", "9", "10", "11", "12", 0 };
const char* dmasgus[] = { "3", "0", "1", "5", "6", "7", 0 };
const char* dmassb[] = { "1", "5", "0", "3", "6", "7", 0 };
- const char* oplemus[] = { "default", "compat", "fast", "nuked", "mame", "opl2board", 0 };
+ const char* oplemus[] = { "default", "compat", "fast", "nuked", "mame", "opl2board","opl3duoboard" ,0 };
const char *qualityno[] = { "0", "1", "2", "3", 0 };
const char* tandys[] = { "auto", "on", "off", 0};
const char* ps1opt[] = { "on", "off", 0};
diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am
index 247c1adbf..7c9501a9c 100644
--- a/src/hardware/Makefile.am
+++ b/src/hardware/Makefile.am
@@ -18,5 +18,5 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler
snd_pc98/common/parts.c snd_pc98/generic/keydisp.c snd_pc98/sound/adpcmc.c snd_pc98/sound/adpcmg.c \
snd_pc98/sound/rhythmc.c snd_pc98/sound/sound.c snd_pc98/sound/getsnd/getwave.c snd_pc98/sound/getsnd/getsmix.c \
snd_pc98/sound/getsnd/getsnd.c snd_pc98/x11/dosio.c snd_pc98/sound/fmboard.c snd_pc98/sound/soundrom.c \
- snd_pc98/cbus/board86.c snd_pc98/sound/fmtimer.c snd_pc98/cbus/board26k.c 8255.cpp opl2board/opl2board.cpp
+ snd_pc98/cbus/board86.c snd_pc98/sound/fmtimer.c snd_pc98/cbus/board26k.c 8255.cpp opl2board/opl2board.cpp opl3duoboard/opl3duoboard.cpp
diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp
index dc6277ee6..9b7315fd7 100644
--- a/src/hardware/adlib.cpp
+++ b/src/hardware/adlib.cpp
@@ -34,6 +34,7 @@
#include "mame/fmopl.h"
#include "mame/ymf262.h"
#include "opl2board/opl2board.h"
+#include "opl3duoboard/opl3duoboard.h"
#define OPL2_INTERNAL_FREQ 3600000 // The OPL2 operates at 3.6MHz
#define OPL3_INTERNAL_FREQ 14400000 // The OPL3 operates at 14.4MHz
@@ -384,6 +385,40 @@ namespace OPL2BOARD {
};
}
+namespace OPL3DUOBOARD {
+ Opl3DuoBoard opl3DuoBoard;
+
+ struct Handler : public Adlib::Handler {
+ Handler(const char* port) {
+ opl3DuoBoard.connect(port);
+ }
+ virtual void WriteReg(uint32_t reg, uint8_t val) {
+ opl3DuoBoard.write(reg, val);
+ }
+ virtual uint32_t WriteAddr(uint32_t port, uint8_t val) {
+ uint32_t reg = val;
+
+ if ((port&3)!=0) {
+ reg |= 0x100;
+ }
+ return reg;
+ }
+
+ virtual void Generate(MixerChannel* chan, Bitu samples) {
+ int16_t buf[1] = { 0 };
+ chan->AddSamples_m16(1, buf);
+ }
+ virtual void Init(Bitu rate) {
+ opl3DuoBoard.reset();
+ }
+ ~Handler() {
+ opl3DuoBoard.reset();
+ opl3DuoBoard.disconnect();
+ }
+ };
+}
+
+
#define RAW_SIZE 1024
@@ -1098,6 +1133,10 @@ Module::Module( Section* configuration ) : Module_base(configuration) {
oplmode = OPL_opl2;
handler = new OPL2BOARD::Handler(oplport.c_str());
}
+ else if (oplemu == "opl3duoboard") {
+ oplmode = OPL_opl3;
+ handler = new OPL3DUOBOARD::Handler(oplport.c_str());
+ }
else if (oplemu == "mame") {
if (oplmode == OPL_opl2) {
handler = new MAMEOPL2::Handler();
diff --git a/src/hardware/opl3duoboard/opl3duoboard.cpp b/src/hardware/opl3duoboard/opl3duoboard.cpp
new file mode 100644
index 000000000..9f10514bd
--- /dev/null
+++ b/src/hardware/opl3duoboard/opl3duoboard.cpp
@@ -0,0 +1,61 @@
+#include "../serialport/libserial.h"
+#include "setup.h"
+#include "opl3duoboard.h"
+
+Opl3DuoBoard::Opl3DuoBoard() {
+}
+
+void Opl3DuoBoard::connect(const char* port) {
+ printf("OPL3 Duo! Board: Connecting to port %s... \n", port);
+
+ comport = 0;
+ if (SERIAL_open(port, &comport)) {
+ SERIAL_setCommParameters(comport, 115200, 'n', SERIAL_1STOP, 8);
+ printf("OK\n");
+ } else {
+ printf("FAIL\n");
+ }
+}
+
+void Opl3DuoBoard::disconnect() {
+ #if OPL3_DUO_BOARD_DEBUG
+ printf("OPL3 Duo! Board: Disconnect\n");
+ #endif
+
+ if (comport) {
+ SERIAL_close(comport);
+ }
+}
+
+void Opl3DuoBoard::reset() {
+ #if OPL3_DUO_BOARD_DEBUG
+ printf("OPL3 Duo! Board: Reset\n");
+ #endif
+
+ for (uint8_t i = 0x00; i < 0xFF; i++) {
+ if (i >= 0x40 && i <= 0x55) {
+ // Set channel volumes to minimum.
+ write(i, 0x3F);
+ } else {
+ write(i, 0x00);
+ }
+ }
+}
+
+void Opl3DuoBoard::write(uint32_t reg, uint8_t val) {
+ if (comport) {
+ #if OPL3_DUO_BOARD_DEBUG
+ printf("OPL3 Duo! Board: Write %d --> %d\n", val, reg);
+ #endif
+
+ uint8_t sendBuffer[3];
+
+ sendBuffer[0] = (reg >> 6) | 0x80;
+ sendBuffer[1] = ((reg & 0x3f) << 1) | (val >> 7);
+ sendBuffer[2] = (val & 0x7f);
+
+ SERIAL_sendchar(comport, sendBuffer[0]);
+ SERIAL_sendchar(comport, sendBuffer[1]);
+ SERIAL_sendchar(comport, sendBuffer[2]);
+ }
+}
\ No newline at end of file
diff --git a/src/hardware/opl3duoboard/opl3duoboard.h b/src/hardware/opl3duoboard/opl3duoboard.h
new file mode 100644
index 000000000..23c014253
--- /dev/null
+++ b/src/hardware/opl3duoboard/opl3duoboard.h
@@ -0,0 +1,20 @@
+#include "../serialport/libserial.h"
+
+#ifndef OPL3_DUO_BOARD
+ #define OPL3_DUO_BOARD
+
+ // Output debug information to the DosBox console if set to 1
+ #define OPL3_DUO_BOARD_DEBUG 0
+
+ class Opl3DuoBoard {
+ public:
+ Opl3DuoBoard();
+ void connect(const char* port);
+ void disconnect();
+ void reset();
+ void write(uint32_t reg, uint8_t val);
+
+ private:
+ COMPORT comport;
+ };
+#endif
\ No newline at end of file
diff --git a/vs2015/dosbox-x.vcxproj b/vs2015/dosbox-x.vcxproj
index 9f4c2d100..a5cdd7523 100644
--- a/vs2015/dosbox-x.vcxproj
+++ b/vs2015/dosbox-x.vcxproj
@@ -1215,6 +1215,7 @@ copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"
+
diff --git a/vs2015/dosbox-x.vcxproj.filters b/vs2015/dosbox-x.vcxproj.filters
index 3af31d1d9..a0e93b9dc 100644
--- a/vs2015/dosbox-x.vcxproj.filters
+++ b/vs2015/dosbox-x.vcxproj.filters
@@ -1028,6 +1028,8 @@
Sources\hardware
+
+ Sources\hardware
Sources\libs\mt32
@@ -2317,6 +2319,8 @@
Sources\hardware
+
+ Sources\hardware
Sources\libs\mt32