diff options
author | James Ye | 2019-08-22 14:43:50 +1000 |
---|---|---|
committer | Filippos Karapetis | 2019-08-23 14:34:44 +0300 |
commit | 8170166d36b622cafb12ffc8c215786996212e36 (patch) | |
tree | 6be2cdbb80fbc0589e7f7f08ab659a729c76dbd8 /audio/opl2lpt.cpp | |
parent | 98d68b3cea4a856193fd4c30f1326a75fb73be11 (diff) | |
download | scummvm-rg350-8170166d36b622cafb12ffc8c215786996212e36.tar.gz scummvm-rg350-8170166d36b622cafb12ffc8c215786996212e36.tar.bz2 scummvm-rg350-8170166d36b622cafb12ffc8c215786996212e36.zip |
AUDIO: (opl2lpt) add OPL3LPT support
The OPL3LPT is like the OPL2LPT with an OPL3 chip. Add OPL3 support to
the existing OPL2LPT driver.
There is no auto-detection of OPL3 capability. The user is required to
explicitly select OPL3LPT as their OPL device.
Tested with Sam & Max Hit the Road.
Diffstat (limited to 'audio/opl2lpt.cpp')
-rw-r--r-- | audio/opl2lpt.cpp | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/audio/opl2lpt.cpp b/audio/opl2lpt.cpp index fc5a4ef465..3b30b60501 100644 --- a/audio/opl2lpt.cpp +++ b/audio/opl2lpt.cpp @@ -20,7 +20,7 @@ * */ -/* OPL implementation for OPL2LPT through libieee1284. +/* OPL implementation for OPL2LPT and OPL3LPT through libieee1284. */ #define FORBIDDEN_SYMBOL_ALLOW_ALL @@ -35,17 +35,35 @@ #include <unistd.h> #include <ieee1284.h> +static const uint8 OPL2LPTRegisterSelect[] = { + (C1284_NSELECTIN | C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED, + (C1284_NSELECTIN | C1284_NSTROBE) ^ C1284_INVERTED, + (C1284_NSELECTIN | C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED +}; + +static const uint8 OPL3LPTRegisterSelect[] = { + (C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED, + C1284_NSTROBE ^ C1284_INVERTED, + (C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED +}; + +static const uint8 OPL2LPTRegisterWrite[] = { + (C1284_NSELECTIN | C1284_NINIT) ^ C1284_INVERTED, + C1284_NSELECTIN ^ C1284_INVERTED, + (C1284_NSELECTIN | C1284_NINIT) ^ C1284_INVERTED +}; + namespace OPL { namespace OPL2LPT { class OPL : public ::OPL::RealOPL { private: struct parport *_pport; + Config::OplType _type; int index; - static const uint8 ctrlBytes[]; public: - OPL(); + explicit OPL(Config::OplType type); ~OPL(); bool init(); @@ -57,17 +75,7 @@ public: void writeReg(int r, int v); }; -const uint8 OPL::ctrlBytes[] = { - (C1284_NSELECTIN | C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED, - (C1284_NSELECTIN | C1284_NSTROBE) ^ C1284_INVERTED, - (C1284_NSELECTIN | C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED, - - (C1284_NSELECTIN | C1284_NINIT) ^ C1284_INVERTED, - C1284_NSELECTIN ^ C1284_INVERTED, - (C1284_NSELECTIN | C1284_NINIT) ^ C1284_INVERTED -}; - -OPL::OPL() : _pport(nullptr) { +OPL::OPL(Config::OplType type) : _pport(nullptr), _type(type), index(0) { } OPL::~OPL() { @@ -114,6 +122,11 @@ void OPL::reset() { for(int i = 0; i < 256; i ++) { writeReg(i, 0); } + if (_type == Config::kOpl3) { + for (int i = 0; i < 256; i++) { + writeReg(i + 256, 0); + } + } index = 0; } @@ -121,7 +134,17 @@ void OPL::write(int port, int val) { if (port & 1) { writeReg(index, val); } else { - index = val; + switch (_type) { + case Config::kOpl2: + index = val & 0xff; + break; + case Config::kOpl3: + index = (val & 0xff) | ((port << 7) & 0x100); + break; + default: + warning("OPL2LPT: unsupported OPL mode %d", _type); + break; + } } } @@ -131,23 +154,34 @@ byte OPL::read(int port) { } void OPL::writeReg(int r, int v) { - r &= 0xff; + if (_type == Config::kOpl3) { + r &= 0x1ff; + } else { + r &= 0xff; + } v &= 0xff; - ieee1284_write_data(_pport, r); - ieee1284_write_control(_pport, ctrlBytes[0]); - ieee1284_write_control(_pport, ctrlBytes[1]); - ieee1284_write_control(_pport, ctrlBytes[2]); + + ieee1284_write_data(_pport, r & 0xff); + if (r < 0x100) { + ieee1284_write_control(_pport, OPL2LPTRegisterSelect[0]); + ieee1284_write_control(_pport, OPL2LPTRegisterSelect[1]); + ieee1284_write_control(_pport, OPL2LPTRegisterSelect[2]); + } else { + ieee1284_write_control(_pport, OPL3LPTRegisterSelect[0]); + ieee1284_write_control(_pport, OPL3LPTRegisterSelect[1]); + ieee1284_write_control(_pport, OPL3LPTRegisterSelect[2]); + } usleep(4); // 3.3 us ieee1284_write_data(_pport, v); - ieee1284_write_control(_pport, ctrlBytes[3]); - ieee1284_write_control(_pport, ctrlBytes[4]); - ieee1284_write_control(_pport, ctrlBytes[5]); + ieee1284_write_control(_pport, OPL2LPTRegisterWrite[0]); + ieee1284_write_control(_pport, OPL2LPTRegisterWrite[1]); + ieee1284_write_control(_pport, OPL2LPTRegisterWrite[2]); usleep(23); } -OPL *create() { - return new OPL(); +OPL *create(Config::OplType type) { + return new OPL(type); } } // End of namespace OPL2LPT |