aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWohlstand <admin@wohlnet.ru>2025-03-25 19:52:51 +0300
committerWohlstand <admin@wohlnet.ru>2025-03-25 19:52:51 +0300
commit55d2eab229b563aa0e0f5f9319570876c525ccb8 (patch)
tree72da417f1dd7845675413e7c4dce189e7912fcd7 /src
parent06fb33d4641cbb0d136d069edbf6d8687267166b (diff)
downloadlibADLMIDI-55d2eab229b563aa0e0f5f9319570876c525ccb8.tar.gz
libADLMIDI-55d2eab229b563aa0e0f5f9319570876c525ccb8.tar.bz2
libADLMIDI-55d2eab229b563aa0e0f5f9319570876c525ccb8.zip
Implemented support of YMFM emulators and OPL2
Diffstat (limited to 'src')
-rw-r--r--src/adlmidi_opl3.cpp109
-rw-r--r--src/adlmidi_opl3.hpp11
2 files changed, 87 insertions, 33 deletions
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index 4d54e8a..72f2bbb 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -66,6 +66,12 @@ static const unsigned OPLBase = 0x388;
# include "chips/esfmu_opl3.h"
# endif
+// YMFM emulators
+# ifndef ADLMIDI_DISABLE_YMFM_EMULATOR
+# include "chips/ymfm_opl2.h"
+# include "chips/ymfm_opl3.h"
+# endif
+
// HW OPL Serial
# ifdef ADLMIDI_ENABLE_HW_SERIAL
# include "chips/opl_serial_port.h"
@@ -93,6 +99,11 @@ static const unsigned adl_emulatorSupport = 0
# ifndef ADLMIDI_DISABLE_JAVA_EMULATOR
| (1u << ADLMIDI_EMU_JAVA)
# endif
+
+# ifndef ADLMIDI_DISABLE_YMFM_EMULATOR
+ | (1u << ADLMIDI_EMU_YMFM_OPL2)
+ | (1u << ADLMIDI_EMU_YMFM_OPL3)
+# endif
#endif
;
@@ -879,6 +890,9 @@ OPL3::OPL3() :
m_serialBaud(0),
m_serialProtocol(0),
#endif
+ m_softPanningSup(false),
+ m_currentChipType((int)OPLChipBase::CHIPTYPE_OPL3),
+ m_perChipChannels(OPL3_CHANNELS_RHYTHM_BASE),
m_numChips(1),
m_numFourOps(0),
m_deepTremoloMode(false),
@@ -1516,10 +1530,14 @@ void OPL3::setPatch(size_t c, const OplTimbre &instrument)
void OPL3::setPan(size_t c, uint8_t value)
{
size_t chip = c / NUM_OF_CHANNELS, cc = c % NUM_OF_CHANNELS;
+
+ if(m_currentChipType == OPLChipBase::CHIPTYPE_OPL2)
+ return; // OPL2 chip doesn't support panning at all
+
if(g_channelsMapPan[cc] != 0xFFF)
{
#ifndef ADLMIDI_HW_OPL
- if (m_softPanning)
+ if (m_softPanningSup && m_softPanning)
{
writePan(chip, g_channelsMapPan[cc], value);
writeRegI(chip, 0xC0 + g_channelsMapPan[cc], m_insCache[c].feedconn | OPL_PANNING_BOTH);
@@ -1560,27 +1578,28 @@ void OPL3::updateChannelCategories()
fours_left -= fours_this_chip;
}
- if(!m_rhythmMode)
+ for(size_t p = 0, a = 0, n = m_numChips; a < n; ++a)
{
- for(size_t a = 0, n = m_numChips; a < n; ++a)
+ for(size_t b = 0; b < OPL3_CHANNELS_RHYTHM_BASE; ++b, ++p)
{
- for(size_t b = 0; b < NUM_OF_CHANNELS; ++b)
- {
- m_channelCategory[a * NUM_OF_CHANNELS + b] =
- (b >= OPL3_CHANNELS_RHYTHM_BASE) ? ChanCat_Rhythm_Secondary : ChanCat_Regular;
- }
+ if(m_currentChipType == OPLChipBase::CHIPTYPE_OPL2 && b >= NUM_OF_OPL2_CHANNELS)
+ m_channelCategory[p] = ChanCat_None;
+ else
+ m_channelCategory[p] = ChanCat_Regular;
+
+ if(m_rhythmMode && b >= 6 && b < 9)
+ m_channelCategory[p] = ChanCat_Rhythm_Secondary;
}
- }
- else
- {
- for(size_t a = 0, n = m_numChips; a < n; ++a)
+
+ if(!m_rhythmMode)
{
- for(size_t b = 0; b < NUM_OF_CHANNELS; ++b)
- {
- m_channelCategory[a * NUM_OF_CHANNELS + b] =
- (b >= OPL3_CHANNELS_RHYTHM_BASE) ? static_cast<ChanCat>(ChanCat_Rhythm_Bass + (b - OPL3_CHANNELS_RHYTHM_BASE)) :
- (b >= 6 && b < 9) ? ChanCat_Rhythm_Secondary : ChanCat_Regular;
- }
+ for(size_t b = 0; b < NUM_OF_RM_CHANNELS; ++b)
+ m_channelCategory[p++] = ChanCat_Rhythm_Secondary;
+ }
+ else
+ {
+ for(size_t b = 0; b < NUM_OF_RM_CHANNELS; ++b)
+ m_channelCategory[p++] = (ChanCat_Rhythm_Bass + b);
}
}
@@ -1770,16 +1789,6 @@ void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
m_regBD.resize(m_numChips, 0);
m_channelCategory.resize(m_numChannels, 0);
- for(size_t p = 0, a = 0; a < m_numChips; ++a)
- {
- for(size_t b = 0; b < OPL3_CHANNELS_RHYTHM_BASE; ++b)
- m_channelCategory[p++] = ChanCat_Regular;
- for(size_t b = 0; b < NUM_OF_RM_CHANNELS; ++b)
- m_channelCategory[p++] = ChanCat_Rhythm_Secondary;
- }
-
-// size_t fours = m_numFourOps;
-
for(size_t i = 0; i < m_numChips; ++i)
{
#ifdef ADLMIDI_ENABLE_HW_SERIAL
@@ -1828,6 +1837,14 @@ void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
chip = new ESFMuOPL3;
break;
#endif
+#ifndef ADLMIDI_DISABLE_YMFM_EMULATOR
+ case ADLMIDI_EMU_YMFM_OPL2:
+ chip = new YmFmOPL2;
+ break;
+ case ADLMIDI_EMU_YMFM_OPL3:
+ chip = new YmFmOPL3;
+ break;
+#endif
}
m_chips[i].reset(chip);
@@ -1851,7 +1868,7 @@ void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
void OPL3::initChip(size_t chip)
{
- static const uint16_t data[] =
+ static const uint16_t data_opl3[] =
{
0x004, 96, 0x004, 128, // Pulse timer
0x105, 0, 0x105, 1, 0x105, 0, // Pulse OPL3 enable
@@ -1859,8 +1876,28 @@ void OPL3::initChip(size_t chip)
0x08, 0 // CSW/Note Sel
};
+ static const uint16_t data_opl2[] =
+ {
+ 0x004, 96, 0x004, 128, // Pulse timer
+ 0x001, 32 // Enable wave
+ };
+
+ // Report does emulator/interface supports full-panning stereo or not
+ if(chip == 0)
+ {
+ m_softPanningSup = m_chips[chip]->hasFullPanning();
+ m_currentChipType = (int)m_chips[chip]->chipType();
+ m_perChipChannels = OPL3_CHANNELS_RHYTHM_BASE;
+
+ if(m_currentChipType == OPLChipBase::CHIPTYPE_OPL2)
+ {
+ m_perChipChannels = NUM_OF_OPL2_CHANNELS;
+ m_numFourOps = 0; // Can't have 4ops on OPL2 chip
+ }
+ }
+
/* Clean-up channels from any playing junk sounds */
- for(size_t a = 0; a < OPL3_CHANNELS_RHYTHM_BASE; ++a)
+ for(size_t a = 0; a < m_perChipChannels; ++a)
{
writeRegI(chip, 0x20 + g_operatorsMap[a * 2], 0x00);
writeRegI(chip, 0x20 + g_operatorsMap[(a * 2) + 1], 0x00);
@@ -1868,8 +1905,16 @@ void OPL3::initChip(size_t chip)
writeRegI(chip, 0xB0 + g_channelsMap[a], 0x00);
}
- for(size_t a = 0; a < sizeof(data) / sizeof(*data); a += 2)
- writeRegI(chip, data[a], (data[a + 1]));
+ if(m_currentChipType == OPLChipBase::CHIPTYPE_OPL2)
+ {
+ for(size_t a = 0; a < sizeof(data_opl2) / sizeof(*data_opl2); a += 2)
+ writeRegI(chip, data_opl2[a], (data_opl2[a + 1]));
+ }
+ else
+ {
+ for(size_t a = 0; a < sizeof(data_opl3) / sizeof(*data_opl3); a += 2)
+ writeRegI(chip, data_opl3[a], (data_opl3[a + 1]));
+ }
}
#ifdef ADLMIDI_ENABLE_HW_SERIAL
diff --git a/src/adlmidi_opl3.hpp b/src/adlmidi_opl3.hpp
index 7ae0f59..5b472f7 100644
--- a/src/adlmidi_opl3.hpp
+++ b/src/adlmidi_opl3.hpp
@@ -38,6 +38,7 @@
#define NUM_OF_4OP_CHANNELS 6
#define NUM_OF_2OP_CHANNELS 18
#define NUM_OF_2x2_CHANNELS 9
+#define NUM_OF_OPL2_CHANNELS 9
#define NUM_OF_RM_CHANNELS 5
/**
@@ -80,6 +81,12 @@ private:
unsigned m_serialBaud;
unsigned m_serialProtocol;
#endif
+ //! Does loaded emulator supports soft panning?
+ bool m_softPanningSup;
+ //! Current type of chip
+ int m_currentChipType;
+ //! Number channels per chip
+ size_t m_perChipChannels;
public:
/**
@@ -197,7 +204,9 @@ public:
//! Rhythm-mode Hi-Hat
ChanCat_Rhythm_HiHat = 7,
//! Rhythm-mode Secondary channel
- ChanCat_Rhythm_Secondary = 8
+ ChanCat_Rhythm_Secondary = 8,
+ //! Here is no channel used (OPL2 only)
+ ChanCat_None = 9
};
//! Category of the channel