aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt57
-rw-r--r--README.md2
-rw-r--r--include/adlmidi.h4
-rw-r--r--src/adlmidi_opl3.cpp109
-rw-r--r--src/adlmidi_opl3.hpp11
-rw-r--r--utils/midiplay/adlmidiplay.cpp4
-rw-r--r--utils/vlc_codec/libadlmidi.c7
-rw-r--r--utils/winmm_drv/cpl/config_dialog.c4
8 files changed, 164 insertions, 34 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b88bb9..faaab65 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,12 +3,34 @@ project (libADLMIDI VERSION 1.5.1 LANGUAGES C CXX)
include(GNUInstallDirs)
include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
# Prefer C90 standard
set(CMAKE_C_STANDARD 90)
# Prefer C++98 standard
set(CMAKE_CXX_STANDARD 98)
+if(MSVC)
+ check_cxx_compiler_flag("/std:c++14" COMPILER_SUPPORTS_CXX14)
+ if(COMPILER_SUPPORTS_CXX14)
+ set(FLAG_CPP14 "/std:c++14")
+ endif()
+ if(MSVC_VERSION LESS 1910)
+ unset(COMPILER_SUPPORTS_CXX14) # MSVC older than 2017 fails to build YMFM
+ endif()
+else()
+ check_cxx_compiler_flag("-std=c++14" COMPILER_SUPPORTS_CXX14)
+ if(COMPILER_SUPPORTS_CXX14)
+ set(FLAG_CPP14 "-std=c++14")
+ endif()
+endif()
+
+if(COMPILER_SUPPORTS_CXX14)
+ message("== Your C++ compiler supports C++14, YMFM emulator will be ENABLED")
+else()
+ message("== Your C++ compiler does NOT supports C++14, YMFM emulator will be DISABLED")
+endif()
+
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
endif()
@@ -190,6 +212,9 @@ option(USE_NUKED_EMULATOR "Use Nuked OPL3 emulator (most accurate, powerful)"
option(USE_OPAL_EMULATOR "Use Opal emulator (inaccurate)" ${DEFAULT_HEAVY_EMULATORS})
option(USE_JAVA_EMULATOR "Use JavaOPL emulator" ${DEFAULT_HEAVY_EMULATORS})
option(USE_ESFMU_EMULATOR "Use ESFMu emulator (Based on Nuked OPL3, powerful)" ${DEFAULT_HEAVY_EMULATORS})
+if(COMPILER_SUPPORTS_CXX14)
+ option(USE_YMFM_EMULATOR "Use YMFM emulator (requires C++14 support)" ON)
+endif()
option(USE_HW_SERIAL "Use the hardware OPL3 chip via Serial on modern systems" OFF)
option(WITH_GENADLDATA "Build and run full rebuild of embedded banks cache" OFF)
@@ -307,6 +332,34 @@ function(handle_options targetLib)
target_compile_definitions(${targetLib} PUBLIC ADLMIDI_DISABLE_ESFMU_EMULATOR)
endif()
+ if(USE_YMFM_EMULATOR)
+ set(YMFM_SOURCES
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm_opl2.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm_opl2.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm_opl3.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm_opl3.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_adpcm.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_adpcm.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_fm.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_fm.ipp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_misc.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_misc.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_opl.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_opl.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_pcm.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_pcm.h
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_ssg.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/ymfm/ymfm_ssg.h
+ )
+ if(DEFINED FLAG_CPP14)
+ set_source_files_properties(${YMFM_SOURCES} COMPILE_FLAGS ${FLAG_CPP14})
+ endif()
+ target_sources(${targetLib} PRIVATE ${YMFM_SOURCES})
+ set(HAS_EMULATOR TRUE)
+ else()
+ target_compile_definitions(${targetLib} PUBLIC -DADLMIDI_DISABLE_YMFM_EMULATOR)
+ endif()
+
if(USE_HW_SERIAL)
set(HAS_EMULATOR TRUE)
target_sources(${targetLib} PRIVATE
@@ -578,6 +631,10 @@ message("USE_DOSBOX_EMULATOR = ${USE_DOSBOX_EMULATOR}")
message("USE_NUKED_EMULATOR = ${USE_NUKED_EMULATOR}")
message("USE_OPAL_EMULATOR = ${USE_OPAL_EMULATOR}")
message("USE_JAVA_EMULATOR = ${USE_JAVA_EMULATOR}")
+message("USE_ESFMU_EMULATOR = ${USE_ESFMU_EMULATOR}")
+if(COMPILER_SUPPORTS_CXX14)
+ message("USE_YMFM_EMULATOR = ${USE_YMFM_EMULATOR}")
+endif()
message("USE_HW_SERIAL = ${USE_HW_SERIAL}")
message("===== Utils and extras =====")
diff --git a/README.md b/README.md
index 8d61551..e88e20f 100644
--- a/README.md
+++ b/README.md
@@ -192,6 +192,8 @@ To build that example you will need to have installed SDL2 library.
* Added an ability to supply the custom list of embedded banks using `-DGENADLDATA_CUSTOM_BANKLIST=/path/to/ini/file.ini` argument
* Improved support of the CMF files: added support for previously missing transpose, depth control, and song marker controllers
* Added ESFMu emulator for the future ESFM support (Currently used as one another OPL3 emulator and without panned stereo support yet).
+ * Added YMFM emulator support (OPL3 and OPL2).
+ * Added support for OPL2 mode when some emulators enabled.
## 1.5.1 2022-10-31
* Added an ability to disable the automatical arpeggio
diff --git a/include/adlmidi.h b/include/adlmidi.h
index ffdde50..4b1dc24 100644
--- a/include/adlmidi.h
+++ b/include/adlmidi.h
@@ -707,6 +707,10 @@ enum ADL_Emulator
ADLMIDI_EMU_JAVA,
/*! ESFMu */
ADLMIDI_EMU_ESFMu,
+ /*! YMFM OPL2 */
+ ADLMIDI_EMU_YMFM_OPL2,
+ /*! YMFM OPL3 */
+ ADLMIDI_EMU_YMFM_OPL3,
/*! Count instrument on the level */
ADLMIDI_EMU_end
};
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
diff --git a/utils/midiplay/adlmidiplay.cpp b/utils/midiplay/adlmidiplay.cpp
index 4001378..e0bbdde 100644
--- a/utils/midiplay/adlmidiplay.cpp
+++ b/utils/midiplay/adlmidiplay.cpp
@@ -1430,6 +1430,10 @@ int main(int argc, char **argv)
emulator = ADLMIDI_EMU_JAVA;
else if(!std::strcmp("--emu-esfmu", argv[2]))
emulator = ADLMIDI_EMU_ESFMu;
+ else if(!std::strcmp("--emu-ymfm-opl2", argv[2]))
+ emulator = ADLMIDI_EMU_YMFM_OPL2;
+ else if(!std::strcmp("--emu-ymfm-opl3", argv[2]))
+ emulator = ADLMIDI_EMU_YMFM_OPL3;
#endif
#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
else if(!std::strcmp("--serial", argv[2]))
diff --git a/utils/vlc_codec/libadlmidi.c b/utils/vlc_codec/libadlmidi.c
index 61f132e..1ef1387 100644
--- a/utils/vlc_codec/libadlmidi.c
+++ b/utils/vlc_codec/libadlmidi.c
@@ -164,6 +164,11 @@ static const char * const emulator_type_descriptions[] =
N_("DOSBox"),
N_("Opal"),
N_("Java OPL3"),
+ N_("ESFMu"),
+#ifndef ADLMIDI_DISABLE_YMFM_EMULATOR
+ N_("YMFM OPL2"),
+ N_("YMFM OPL3"),
+#endif
NULL
};
@@ -299,7 +304,7 @@ static int Open (vlc_object_t *p_this)
}
adl_setVolumeRangeModel(p_sys->synth, var_InheritInteger(p_this, CONFIG_PREFIX "volume-model"));
- adl_setChannelAllocMode(p_sys->synth, var_InheritInteger(p_this, CONFIG_PREFIX "channel-allocation"));
+ adl_setChannelAllocMode(p_sys->synth, var_InheritInteger(p_this, CONFIG_PREFIX "channel-allocation"));
adl_setFullRangeBrightness(p_sys->synth, var_InheritBool(p_this, CONFIG_PREFIX "full-range-brightness"));
diff --git a/utils/winmm_drv/cpl/config_dialog.c b/utils/winmm_drv/cpl/config_dialog.c
index 8808e6d..abaa857 100644
--- a/utils/winmm_drv/cpl/config_dialog.c
+++ b/utils/winmm_drv/cpl/config_dialog.c
@@ -56,6 +56,10 @@ static const char * const emulator_type_descriptions[] =
"Opal",
"Java OPL3",
"ESFMu",
+#ifndef ADLMIDI_DISABLE_YMFM_EMULATOR
+ "YMFM OPL2",
+ "YMFM OPL3",
+#endif
NULL
};