diff options
-rw-r--r-- | CMakeLists.txt | 79 | ||||
-rwxr-xr-x | cmake/openwattcom-dos/ow-cmake.sh | 36 | ||||
-rw-r--r-- | cmake/openwattcom-dos/toolchain-ow.cmake | 43 | ||||
-rwxr-xr-x | cmake/openwattcom/ow-cmake.sh | 9 | ||||
-rw-r--r-- | cmake/openwattcom/toolchain-ow.cmake | 37 | ||||
-rw-r--r-- | src/adldata.hh | 20 | ||||
-rw-r--r-- | src/adlmidi.cpp | 2 | ||||
-rw-r--r-- | src/adlmidi_load.cpp | 4 | ||||
-rw-r--r-- | src/adlmidi_midiplay.cpp | 30 | ||||
-rw-r--r-- | src/adlmidi_opl3.cpp | 33 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 14 | ||||
-rw-r--r-- | src/adlmidi_xmi2mid.c | 4 | ||||
-rw-r--r-- | utils/dumpbank/dumpbank.cpp | 9 | ||||
-rw-r--r-- | utils/dumpmiles/dumpmiles.cpp | 5 | ||||
-rw-r--r-- | utils/midiplay/adlmidiplay.cpp | 183 |
15 files changed, 415 insertions, 93 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 266d0fa..db7b115 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,14 +5,14 @@ project (libADLMIDI) # Strip garbage if(APPLE) set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -dead_strip") -ELSEIF(NOT MSVC) +ELSEIF(NOT MSVC AND NOT MSDOS) set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os -s -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os -s -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s") set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -Wl,--gc-sections -Wl,-s") ENDIF() # Global optimization flags -IF(NOT MSVC) +IF(NOT MSVC AND NOT MSDOS) set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-omit-frame-pointer") ENDIF() @@ -27,7 +27,7 @@ if(MSVC) ENDIF() # -fPIC thing -IF(NOT WIN32 AND NOT DJGPP) +IF(NOT WIN32 AND NOT DJGPP AND NOT MSDOS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") ENDIF() @@ -38,6 +38,7 @@ option(WITH_ADLMIDI2 "Build also classic ADLMIDI player [EXPERIMENTAL]" O option(WITH_OLD_UTILS "Build also old utilities" OFF) option(WITH_EMBEDDED_BANKS "Use embedded banks" ON) option(WITH_GENADLDATA "Build and run full rebuild of embedded banks cache" OFF) +option(WITH_GENADLDATA_COMMENTS "Enable comments in generated ADLDATA cache file" OFF) option(USE_DOSBOX_EMULATOR "Use DosBox emulator" OFF) option(WITH_CPP_EXTRAS "Build with support for C++ extras (features are can be found in 'adlmidi.hpp' header)" OFF) @@ -91,6 +92,10 @@ if(WITH_EMBEDDED_BANKS) target_compile_options(gen_adldata PUBLIC "/std:c++latest") endif() + if(WITH_GENADLDATA_COMMENTS) + target_compile_options(gen_adldata PUBLIC "-DADLDATA_WITH_COMMENTS") + endif() + add_custom_target( gen-adldata-run COMMAND gen_adldata ${libADLMIDI_SOURCE_DIR}/src/adldata.cpp @@ -113,15 +118,17 @@ list(APPEND libADLMIDI_SOURCES ${libADLMIDI_SOURCE_DIR}/src/adlmidi_xmi2mid.c ) -if(USE_DOSBOX_EMULATOR) - add_definitions(-DADLMIDI_USE_DOSBOX_OPL) - list(APPEND libADLMIDI_SOURCES - ${libADLMIDI_SOURCE_DIR}/src/dbopl.cpp - ) -else() - list(APPEND libADLMIDI_SOURCES - ${libADLMIDI_SOURCE_DIR}/src/nukedopl3.c - ) +if(NOT DJGPP AND NOT MSDOS) + if(USE_DOSBOX_EMULATOR) + add_definitions(-DADLMIDI_USE_DOSBOX_OPL) + list(APPEND libADLMIDI_SOURCES + ${libADLMIDI_SOURCE_DIR}/src/dbopl.cpp + ) + else() + list(APPEND libADLMIDI_SOURCES + ${libADLMIDI_SOURCE_DIR}/src/nukedopl3.c + ) + endif() endif() if(WITH_EMBEDDED_BANKS) @@ -162,15 +169,22 @@ You must enable at least one of them!") endif() if(WITH_MIDIPLAY) - find_library(SDL2_LIBRARY SDL2 REQUIRED) - include_directories(${SDL2_INCLUDE_DIR}) - message("Found ${SDL2_LIBRARY}") + if(NOT MSDOS AND NOT DJGPP) + find_library(SDL2_LIBRARY SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIR}) + message("Found ${SDL2_LIBRARY}") + endif() add_executable(adlmidiplay ${libADLMIDI_SOURCE_DIR}/utils/midiplay/adlmidiplay.cpp ${libADLMIDI_SOURCE_DIR}/utils/midiplay/wave_writer.c ) + if(MSDOS OR DJGPP) + target_compile_options(adlmidiplay PUBLIC "-DHARDWARE_OPL3") + message("Turn on hardware OPL3 support on demo tool") + endif() + if(WIN32) if(MSVC) target_link_libraries(adlmidiplay ADLMIDI ${SDL2_LIBRARY}) @@ -178,7 +192,15 @@ if(WITH_MIDIPLAY) target_link_libraries(adlmidiplay ADLMIDI ${SDL2_LIBRARY} pthread) endif() else() - target_link_libraries(adlmidiplay ADLMIDI ${SDL2_LIBRARY} pthread dl m stdc++) + if(MSDOS OR DJGPP) + target_link_libraries(adlmidiplay ADLMIDI) + else() + target_link_libraries(adlmidiplay ADLMIDI ${SDL2_LIBRARY} pthread dl m stdc++) + endif() + endif() + + if(MSDOS OR DJGPP) + set_target_properties(adlmidiplay PROPERTIES OUTPUT_NAME adlmidi) endif() if(libADLMIDI_SHARED) @@ -196,13 +218,13 @@ if(WITH_MIDIPLAY) endif() if(WITH_ADLMIDI2) - if(NOT WIN32 AND NOT DJGPP) + if(NOT WIN32 AND NOT DJGPP AND NOT MSDOS) find_library(SDL2_LIBRARY SDL2 REQUIRED) include_directories(${SDL2_INCLUDE_DIR}) message("Found ${SDL2_LIBRARY}") endif() - if(NOT WIN32 AND NOT DJGPP) + if(NOT WIN32 AND NOT DJGPP AND NOT MSDOS) set(ADLMIDI2_HAS_PUZZLE_GAME "TRUE") set(ADLMIDI2_VIDEO_OUT_SUPPORT "TRUE") endif() @@ -228,7 +250,7 @@ if(WITH_ADLMIDI2) if(WIN32) target_link_libraries(adlmidi2 ADLMIDI winmm) - elseif(DJGPP) + elseif(DJGPP OR MSDOS) target_link_libraries(adlmidi2 ADLMIDI) else() target_link_libraries(adlmidi2 ADLMIDI ${SDL2_LIBRARY} pthread dl m stdc++) @@ -275,13 +297,14 @@ install(FILES DESTINATION include/) message("==== libADLMIDI options ====") -message("WITH_MIDIPLAY = ${WITH_MIDIPLAY}") -message("WITH_ADLMIDI2 = ${WITH_ADLMIDI2}") -message("WITH_OLD_UTILS = ${WITH_OLD_UTILS}") -message("WITH_EMBEDDED_BANKS = ${WITH_EMBEDDED_BANKS}") -message("WITH_GENADLDATA = ${WITH_GENADLDATA}") -message("USE_DOSBOX_EMULATOR = ${USE_DOSBOX_EMULATOR}") -message("WITH_CPP_EXTRAS = ${WITH_CPP_EXTRAS}") -message("libADLMIDI_STATIC = ${libADLMIDI_STATIC}") -message("libADLMIDI_SHARED = ${libADLMIDI_SHARED}") +message("WITH_MIDIPLAY = ${WITH_MIDIPLAY}") +message("WITH_ADLMIDI2 = ${WITH_ADLMIDI2}") +message("WITH_OLD_UTILS = ${WITH_OLD_UTILS}") +message("WITH_EMBEDDED_BANKS = ${WITH_EMBEDDED_BANKS}") +message("WITH_GENADLDATA = ${WITH_GENADLDATA}") +message("WITH_GENADLDATA_COMMENTS = ${WITH_GENADLDATA_COMMENTS}") +message("USE_DOSBOX_EMULATOR = ${USE_DOSBOX_EMULATOR}") +message("WITH_CPP_EXTRAS = ${WITH_CPP_EXTRAS}") +message("libADLMIDI_STATIC = ${libADLMIDI_STATIC}") +message("libADLMIDI_SHARED = ${libADLMIDI_SHARED}") diff --git a/cmake/openwattcom-dos/ow-cmake.sh b/cmake/openwattcom-dos/ow-cmake.sh new file mode 100755 index 0000000..921df11 --- /dev/null +++ b/cmake/openwattcom-dos/ow-cmake.sh @@ -0,0 +1,36 @@ +#!/bin/bash +export WATCOM=$HOME/Qt/Tools/ow-snapshot-2.0 +export EDPATH=$WATCOM/eddat +export WIPFC=$WATCOM/wipfc +export INCLUDE="$WATCOM/h" +WATCOM_FLAGS="-bdos4g -march=i386" +export CFLAGS="$WATCOM_FLAGS -xc -std=wc" +export CXXFLAGS="$WATCOM_FLAGS -xc++ -xs -feh -std=c++11" +export LFLAGS="$WATCOM_FLAGS" + +# export PKG_CONFIG_LIBDIR="${WATCOM}/lib/pkgconfig" +# djgpp_c_flags="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4" + +SCRIPT_PATH=$HOME/_git_repos/libADLMIDI/cmake/openwattcom-dos +CUSTOM_PATH=$SCRIPT_PATH:${WATCOM}/binl:$PATH + +if [[ "$1" != '--build' ]]; then + echo "KEK [${CUSTOM_PATH}]" + + PATH=${CUSTOM_PATH} cmake \ + -DCMAKE_INSTALL_PREFIX:PATH=${WATCOM} \ + -DCMAKE_INSTALL_LIBDIR:PATH=${WATCOM}/lib386 \ + -DINCLUDE_INSTALL_DIR:PATH=${WATCOM}/lib386 \ + -DLIB_INSTALL_DIR:PATH=${WATCOM}/lib \ + -DSYSCONF_INSTALL_DIR:PATH=${WATCOM}/etc \ + -DSHARE_INSTALL_DIR:PATH=${WATCOM}/share \ + -DBUILD_SHARED_LIBS:BOOL=OFF \ + -DCMAKE_TOOLCHAIN_FILE="${SCRIPT_PATH}/toolchain-ow.cmake" \ + "$@" + +else + PATH=${CUSTOM_PATH} cmake "$@" +fi + +#-DCMAKE_CROSSCOMPILING_EMULATOR=/usr/bin/i686-pc-msdosdjgpp-wine + diff --git a/cmake/openwattcom-dos/toolchain-ow.cmake b/cmake/openwattcom-dos/toolchain-ow.cmake new file mode 100644 index 0000000..17fbd22 --- /dev/null +++ b/cmake/openwattcom-dos/toolchain-ow.cmake @@ -0,0 +1,43 @@ +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_SYSTEM_NAME MSDOS) +SET(CMAKE_SYSTEM_VERSION 6) + +set (OPENWATTCOM TRUE) +set (MSDOS TRUE) + +set (WATCOM_PREFIX "$ENV{HOME}/Qt/Tools/ow-snapshot-2.0") + +set (ENV{PATH} ${WATCOM_PREFIX}/binl:$ENV{PATH}) +set (ENV{WATCOM} ${WATCOM_PREFIX}) +set (ENV{INCLUDE} "${WATCOM_PREFIX}/lh") +set (ENV{EDPATH} ${WATCOM_PREFIX}/eddat) +set (ENV{WIPFC} ${WATCOM_PREFIX}/wipfc) + +# specify the cross compiler +set (CMAKE_C_COMPILER ${WATCOM_PREFIX}/binl/owcc) +set (CMAKE_CXX_COMPILER ${WATCOM_PREFIX}/binl/owcc) + +# where is the target environment +set (CMAKE_FIND_ROOT_PATH ${WATCOM_PREFIX}) + +# search for programs in the build host directories +set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +include_directories(${WATCOM_PREFIX}/lh) + +# Make sure Qt can be detected by CMake +set (QT_BINARY_DIR ${WATCOM_PREFIX}/binl /usr/bin) +set (QT_INCLUDE_DIRS_NO_SYSTEM ON) + +# These are needed for compiling lapack (RHBZ #753906) +#set (CMAKE_Fortran_COMPILER /home/wohlstand/Qt/Tools/ow-snapshot-2.0/binl/wfc) +#set (CMAKE_AR:FILEPATH /usr/local/djgpp/bin/i586-pc-msdosdjgpp-ar) +#set (CMAKE_RANLIB:FILEPATH /usr/local/djgpp/bin/i586-pc-msdosdjgpp-ranlib) + +# include(Linux-OpenWatcom.cmake) + + diff --git a/cmake/openwattcom/ow-cmake.sh b/cmake/openwattcom/ow-cmake.sh index cbccba0..2e6dbe5 100755 --- a/cmake/openwattcom/ow-cmake.sh +++ b/cmake/openwattcom/ow-cmake.sh @@ -1,8 +1,8 @@ #!/bin/bash -export WATCOM=/home/wohlstand/Qt/Tools/ow-snapshot-2.0/ +export WATCOM=$HOME/Qt/Tools/ow-snapshot-2.0 export EDPATH=$WATCOM/eddat export WIPFC=$WATCOM/wipfc -export INCLUDE="$djgpp_prefix/lh" +export INCLUDE="$WATCOM/lh" WATCOM_FLAGS="-blinux" export CFLAGS="$WATCOM_FLAGS -xc -std=wc" export CXXFLAGS="$WATCOM_FLAGS -xc++ -xs -feh -std=c++11" @@ -11,7 +11,8 @@ export CXXFLAGS="$WATCOM_FLAGS -xc++ -xs -feh -std=c++11" # djgpp_c_flags="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4" -CUSTOM_PATH=/home/wohlstand/_git_repos/libADLMIDI/cmake/openwattcom:${WATCOM}/binl:$PATH +SCRIPT_PATH=$HOME/_git_repos/libADLMIDI/cmake/openwattcom +CUSTOM_PATH=$SCRIPT_PATH:${WATCOM}/binl:$PATH if [[ "$1" != '--build' ]]; then echo "KEK [${CUSTOM_PATH}]" @@ -24,7 +25,7 @@ if [[ "$1" != '--build' ]]; then -DSYSCONF_INSTALL_DIR:PATH=${WATCOM}/etc \ -DSHARE_INSTALL_DIR:PATH=${WATCOM}/share \ -DBUILD_SHARED_LIBS:BOOL=OFF \ - -DCMAKE_TOOLCHAIN_FILE=/home/wohlstand/_git_repos/libADLMIDI/cmake/openwattcom/toolchain-ow.cmake \ + -DCMAKE_TOOLCHAIN_FILE=$SCRIPT_PATH/toolchain-ow.cmake \ "$@" else diff --git a/cmake/openwattcom/toolchain-ow.cmake b/cmake/openwattcom/toolchain-ow.cmake index 4f8b8f6..2881cc4 100644 --- a/cmake/openwattcom/toolchain-ow.cmake +++ b/cmake/openwattcom/toolchain-ow.cmake @@ -1,34 +1,37 @@ -set (CMAKE_SYSTEM_NAME linux) +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_SYSTEM_NAME Linux) -set (OPENWATTCOM TRUE) +set(OPENWATTCOM TRUE) +set(LINUX TRUE) -set (WATCOM_PREFIX "/home/wohlstand/Qt/Tools/ow-snapshot-2.0") +set(WATCOM_PREFIX "$ENV{HOME}/Qt/Tools/ow-snapshot-2.0") -set (ENV{PATH} ${WATCOM_PREFIX}/binl:$ENV{PATH}) -set (ENV{WATCOM} ${WATCOM_PREFIX}) -set (ENV{INCLUDE} ${WATCOM_PREFIX}/lh) -set (ENV{EDPATH} ${WATCOM_PREFIX}/eddat) -set (ENV{WIPFC} ${WATCOM_PREFIX}/wipfc) +set(ENV{PATH} ${WATCOM_PREFIX}/binl:$ENV{PATH}) +set(ENV{WATCOM} ${WATCOM_PREFIX}) +set(ENV{INCLUDE} "${WATCOM_PREFIX}/lh") +set(ENV{LIB} "${WATCOM_PREFIX}/lib386") +set(ENV{EDPATH} ${WATCOM_PREFIX}/eddat) +set(ENV{WIPFC} ${WATCOM_PREFIX}/wipfc) # specify the cross compiler -set (CMAKE_C_COMPILER ${WATCOM_PREFIX}/binl/owcc) -set (CMAKE_CXX_COMPILER ${WATCOM_PREFIX}/binl/owcc) +set(CMAKE_C_COMPILER ${WATCOM_PREFIX}/binl/owcc) +set(CMAKE_CXX_COMPILER ${WATCOM_PREFIX}/binl/owcc) # where is the target environment -set (CMAKE_FIND_ROOT_PATH ${WATCOM_PREFIX}) +set(CMAKE_FIND_ROOT_PATH ${WATCOM_PREFIX}) # search for programs in the build host directories -set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories -set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set (CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) include_directories(${WATCOM_PREFIX}/lh) # Make sure Qt can be detected by CMake -set (QT_BINARY_DIR ${WATCOM_PREFIX}/binl /usr/bin) -set (QT_INCLUDE_DIRS_NO_SYSTEM ON) +set(QT_BINARY_DIR ${WATCOM_PREFIX}/binl /usr/bin) +set(QT_INCLUDE_DIRS_NO_SYSTEM ON) # These are needed for compiling lapack (RHBZ #753906) #set (CMAKE_Fortran_COMPILER /home/wohlstand/Qt/Tools/ow-snapshot-2.0/binl/wfc) diff --git a/src/adldata.hh b/src/adldata.hh index 8e15ff4..e9ff00b 100644 --- a/src/adldata.hh +++ b/src/adldata.hh @@ -24,24 +24,26 @@ #ifndef ADLDATA_H #define ADLDATA_H +#include <stdint.h> + extern const struct adldata { - unsigned int modulator_E862, carrier_E862; // See below - unsigned char modulator_40, carrier_40; // KSL/attenuation settings - unsigned char feedconn; // Feedback/connection bits for the channel + uint32_t modulator_E862, carrier_E862; // See below + uint8_t modulator_40, carrier_40; // KSL/attenuation settings + uint8_t feedconn; // Feedback/connection bits for the channel - signed char finetune; + int8_t finetune; } adl[]; extern const struct adlinsdata { enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02 }; - unsigned short adlno1, adlno2; - unsigned char tone; - unsigned char flags; - unsigned short ms_sound_kon; // Number of milliseconds it produces sound; - unsigned short ms_sound_koff; + uint16_t adlno1, adlno2; + uint8_t tone; + uint8_t flags; + uint16_t ms_sound_kon; // Number of milliseconds it produces sound; + uint16_t ms_sound_koff; double voice2_fine_tune; } adlins[]; int maxAdlBanks(); diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp index 50163ac..f620b5e 100644 --- a/src/adlmidi.cpp +++ b/src/adlmidi.cpp @@ -471,7 +471,7 @@ ADLMIDI_EXPORT const Adl_MarkerEntry adl_metaMarker(struct ADL_MIDIPlayer *devic MIDIplay::MIDI_MarkerEntry &mk = play->musMarkers[index]; marker.label = mk.label.c_str(); marker.pos_time = mk.pos_time; - marker.pos_ticks = mk.pos_ticks; + marker.pos_ticks = (unsigned long)mk.pos_ticks; } return marker; } diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp index afe0610..4df4b32 100644 --- a/src/adlmidi_load.cpp +++ b/src/adlmidi_load.cpp @@ -58,7 +58,7 @@ bool MIDIplay::LoadBank(const std::string &filename) bool MIDIplay::LoadBank(void *data, unsigned long size) { fileReader file; - file.openData(data, size); + file.openData(data, (size_t)size); return LoadBank(file); } @@ -339,7 +339,7 @@ bool MIDIplay::LoadMIDI(const std::string &filename) bool MIDIplay::LoadMIDI(void *data, unsigned long size) { fileReader file; - file.openData(data, size); + file.openData(data, (size_t)size); return LoadMIDI(file); } diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 7b9a086..51da17e 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -175,6 +175,11 @@ void MIDIplay::MidiTrackRow::sortEvents(bool *noteStates) EvtArr controllers; EvtArr anyOther; + metas.reserve(events.size()); + noteOffs.reserve(events.size()); + controllers.reserve(events.size()); + anyOther.reserve(events.size()); + for(size_t i = 0; i < events.size(); i++) { if(events[i].type == MidiEvent::T_NOTEOFF) @@ -340,6 +345,7 @@ bool MIDIplay::buildTrackData() errorString += std::string(error, (size_t)len); return false; } + evtPos.events.push_back(event); if(event.type == MidiEvent::T_SPECIAL) { @@ -433,7 +439,7 @@ bool MIDIplay::buildTrackData() { fraction<uint64_t> currentTempo = Tempo; double time = 0.0; - uint8_t abs_position = 0; + uint64_t abs_position = 0; size_t tempo_change_index = 0; MidiTrackQueue &track = trackDataNew[tk]; if(track.empty()) @@ -559,7 +565,6 @@ bool MIDIplay::buildTrackData() //Initial loop position will begin at begin of track until passing of the loop point LoopBeginPositionNew = CurrentPositionNew; - /********************************************************************************/ //Resolve "hell of all times" of too short drum notes: //move too short percussion note-offs far far away as possible @@ -655,7 +660,6 @@ bool MIDIplay::buildTrackData() } #endif - return true; } @@ -1049,7 +1053,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) int32_t c = -1; int32_t bs = -0x7FFFFFFFl; - for(uint32_t a = 0; a < opl.NumChannels; ++a) + for(size_t a = 0; a < (size_t)opl.NumChannels; ++a) { if(ccount == 1 && static_cast<int32_t>(a) == adlchannel[0]) continue; // ^ Don't use the same channel for primary&secondary @@ -1067,7 +1071,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) expected_mode = PercussionMap[midiins & 0xFF]; } - if(opl.four_op_category[a] != expected_mode) + if(opl.four_op_category[a] != (uint32_t)expected_mode) continue; } else @@ -1361,7 +1365,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, const int16_t tone = info.tone; const uint8_t vol = info.vol; const int midiins = info.midiins; - const uint32_t insmeta = info.insmeta; + const size_t insmeta = info.insmeta; const adlinsdata &ains = opl.GetAdlMetaIns(insmeta); AdlChannel::Location my_loc; my_loc.MidCh = MidCh; @@ -1461,7 +1465,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, else { // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) - volume = volume > 8725 ? static_cast<unsigned int>(std::log(volume) * 11.541561 + (0.5 - 104.22845)) : 0; + volume = volume > 8725 ? static_cast<unsigned int>(std::log((double)volume) * 11.541561 + (0.5 - 104.22845)) : 0; // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) //opl.Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); } @@ -2033,7 +2037,7 @@ void MIDIplay::HandleEvent(size_t tk, const MIDIplay::MidiEvent &evt, int &statu } } -long MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t) const +long MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t) { long s = -ch[c].koff_time_until_neglible; @@ -2453,12 +2457,12 @@ ADLMIDI_EXPORT void AdlInstrumentTester::FindAdlList() ADLMIDI_EXPORT void AdlInstrumentTester::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127 { - if(opl->LogarithmicVolumes)// !!!ADL PRIVATE!!! - opl->Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2);// !!!ADL PRIVATE!!! + if(opl->LogarithmicVolumes) + opl->Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2); else { // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) - opl->Touch_Real(c, volume > 8725 ? static_cast<unsigned int>(std::log(volume) * 11.541561 + (0.5 - 104.22845)) : 0);// !!!ADL PRIVATE!!! + opl->Touch_Real(c, volume > 8725 ? static_cast<unsigned int>(std::log((double)volume) * 11.541561 + (0.5 - 104.22845)) : 0); // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) //Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); } @@ -2468,7 +2472,7 @@ ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) { if(adl_ins_list.empty()) FindAdlList(); const unsigned meta = adl_ins_list[ins_idx]; - const adlinsdata &ains = opl->GetAdlMetaIns(meta);// !!!ADL PRIVATE!!! + const adlinsdata &ains = opl->GetAdlMetaIns(meta); int tone = (cur_gm & 128) ? (cur_gm & 127) : (note + 50); if(ains.tone) @@ -2602,7 +2606,7 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) #endif return false; default: - const char *p = strchr(notes, ch); + const char *p = std::strchr(notes, ch); if(p && *p) DoNote((int)(p - notes) - 12); } diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp index 9db3803..f46d0ca 100644 --- a/src/adlmidi_opl3.cpp +++ b/src/adlmidi_opl3.cpp @@ -165,30 +165,56 @@ OPL3::OPL3() : void OPL3::Poke(size_t card, uint32_t index, uint32_t value) { #ifdef ADLMIDI_HW_OPL + (void)card; unsigned o = index >> 8; unsigned port = OPLBase + o * 2; + + #ifdef __DJGPP__ outportb(port, index); for(unsigned c = 0; c < 6; ++c) inportb(port); outportb(port + 1, value); for(unsigned c = 0; c < 35; ++c) inportb(port); - #else + #endif//__DJGPP__ + + #ifdef __WATCOMC__ + outp(port, index); + for(uint16_t c = 0; c < 6; ++c) inp(port); + outp(port + 1, value); + for(uint16_t c = 0; c < 35; ++c) inp(port); + #endif//__WATCOMC__ + + #else//ADLMIDI_HW_OPL + #ifdef ADLMIDI_USE_DOSBOX_OPL cards[card].WriteReg(index, static_cast<uint8_t>(value)); #else OPL3_WriteReg(&cards[card], static_cast<Bit16u>(index), static_cast<Bit8u>(value)); #endif - #endif + + #endif//ADLMIDI_HW_OPL } void OPL3::PokeN(size_t card, uint16_t index, uint8_t value) { #ifdef ADLMIDI_HW_OPL + (void)card; unsigned o = index >> 8; unsigned port = OPLBase + o * 2; + + #ifdef __DJGPP__ outportb(port, index); for(unsigned c = 0; c < 6; ++c) inportb(port); outportb(port + 1, value); for(unsigned c = 0; c < 35; ++c) inportb(port); + #endif + + #ifdef __WATCOMC__ + outp(port, index); + for(uint16_t c = 0; c < 6; ++c) inp(port); + outp(port + 1, value); + for(uint16_t c = 0; c < 35; ++c) inp(port); + #endif//__WATCOMC__ + #else #ifdef ADLMIDI_USE_DOSBOX_OPL cards[card].WriteReg(static_cast<Bit32u>(index), value); @@ -452,15 +478,16 @@ void OPL3::ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel) void OPL3::Reset(unsigned long PCM_RATE) { + #ifndef ADLMIDI_HW_OPL #ifdef ADLMIDI_USE_DOSBOX_OPL DBOPL::Handler emptyChip; //Constructors inside are will initialize necessary fields #else _opl3_chip emptyChip; std::memset(&emptyChip, 0, sizeof(_opl3_chip)); #endif - #ifndef ADLMIDI_HW_OPL cards.clear(); #endif + (void)PCM_RATE; ins.clear(); pit.clear(); regBD.clear(); diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index c860a88..408fede 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -53,9 +53,10 @@ typedef __int32 ssize_t; # include <windows.h> #endif -#ifdef __DJGPP__ +#if defined(__DJGPP__) || (defined(__WATCOMC__) && (defined(__DOS__) || defined(__DOS4G__) || defined(__DOS4GNZ__))) #define ADLMIDI_HW_OPL #include <conio.h> +#ifdef __DJGPP__ #include <pc.h> #include <dpmi.h> #include <go32.h> @@ -63,6 +64,8 @@ typedef __int32 ssize_t; #include <dos.h> #endif +#endif + #include <vector> #include <list> #include <string> @@ -72,6 +75,7 @@ typedef __int32 ssize_t; #include <cstdlib> #include <cstring> #include <cmath> +#include <cstdarg> #include <cstdio> #include <vector> // vector #include <deque> // deque @@ -89,11 +93,13 @@ typedef __int32 ssize_t; #include "fraction.hpp" +#ifndef ADLMIDI_HW_OPL #ifdef ADLMIDI_USE_DOSBOX_OPL #include "dbopl.h" #else #include "nukedopl3.h" #endif +#endif #include "adldata.hh" #include "adlmidi.h" //Main API @@ -529,7 +535,7 @@ public: users_t users; // If the channel is keyoff'd - long koff_time_until_neglible; + int64_t koff_time_until_neglible; // For channel allocation: AdlChannel(): users(), koff_time_until_neglible(0) { } void AddAge(int64_t ms); @@ -695,7 +701,7 @@ public: { std::string label; double pos_time; - unsigned long pos_ticks; + uint64_t pos_ticks; }; std::vector<MIDIchannel> Ch; @@ -893,7 +899,7 @@ private: // Determine how good a candidate this adlchannel // would be for playing a note from this instrument. - long CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/) const; + long CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/); // A new note will be played on this channel using this instrument. // Kill existing notes on this channel (or don't, if we do arpeggio) diff --git a/src/adlmidi_xmi2mid.c b/src/adlmidi_xmi2mid.c index 4fae2a2..896b3d9 100644 --- a/src/adlmidi_xmi2mid.c +++ b/src/adlmidi_xmi2mid.c @@ -98,7 +98,7 @@ static uint32_t read2(struct xmi_ctx *ctx) uint8_t b0, b1; b0 = *ctx->src_ptr++; b1 = *ctx->src_ptr++; - return (b0 + (b1 << 8)); + return (b0 + ((uint32_t)b1 << 8)); } static uint32_t read4(struct xmi_ctx *ctx) @@ -108,7 +108,7 @@ static uint32_t read4(struct xmi_ctx *ctx) b2 = *ctx->src_ptr++; b1 = *ctx->src_ptr++; b0 = *ctx->src_ptr++; - return (b0 + (b1<<8) + (b2<<16) + (b3<<24)); + return (b0 + ((uint32_t)b1<<8) + ((uint32_t)b2<<16) + ((uint32_t)b3<<24)); } static void copy(struct xmi_ctx *ctx, char *b, uint32_t len) diff --git a/utils/dumpbank/dumpbank.cpp b/utils/dumpbank/dumpbank.cpp index aad3e7b..84283e7 100644 --- a/utils/dumpbank/dumpbank.cpp +++ b/utils/dumpbank/dumpbank.cpp @@ -4,14 +4,15 @@ #include <cstdio> #include <vector> #include <cstring> +#include <stdio.h> -#ifndef _MSC_VER +#if !defined(_MSC_VER) && !defined(__WATCOMC__) #define PACKED_STRUCT __attribute__((packed)) #else #define PACKED_STRUCT #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__WATCOMC__) #pragma pack(push,1) #endif @@ -83,7 +84,7 @@ struct BNK2_instrument unsigned char xxxxxxxx; } PACKED_STRUCT; // Ad Lib Gold instrument maker bankfile patch -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__WATCOMC__) #pragma pack(pop) #endif @@ -157,7 +158,7 @@ static void LoadBNK2(const std::vector<unsigned char>& data) static void LoadBNK(const char* fn) { - FILE* fp = fopen(fn, "rb"); + FILE* fp = std::fopen(fn, "rb"); if(!fp) { std::fprintf(stderr, "ERROR: Can't open %s file!", fn); diff --git a/utils/dumpmiles/dumpmiles.cpp b/utils/dumpmiles/dumpmiles.cpp index e946c5d..0c2d51b 100644 --- a/utils/dumpmiles/dumpmiles.cpp +++ b/utils/dumpmiles/dumpmiles.cpp @@ -3,10 +3,11 @@ //#endif #include <cstdio> #include <vector> +#include <stdio.h> static void LoadMiles(const char* fn) { - FILE* fp = fopen(fn, "rb"); + FILE* fp = std::fopen(fn, "rb"); if(!fp) { std::fprintf(stderr, "ERROR: Can't open %s file!", fn); @@ -39,7 +40,7 @@ static void LoadMiles(const char* fn) std::printf("%02X %02X ", gmnumber,gmnumber2); //, offset); for(unsigned b=0; b<length; ++b) { - if(b > 3 && (b-3)%11 == 0) printf("\n "); + if(b > 3 && (b-3)%11 == 0) std::printf("\n "); std::printf("%02X ", data[offset+b]); } std::printf("\n"); diff --git a/utils/midiplay/adlmidiplay.cpp b/utils/midiplay/adlmidiplay.cpp index a5ced08..e15950f 100644 --- a/utils/midiplay/adlmidiplay.cpp +++ b/utils/midiplay/adlmidiplay.cpp @@ -8,12 +8,72 @@ #include <cstring> #include <deque> #include <cstdarg> +#include <algorithm> #include <signal.h> -#define SDL_MAIN_HANDLED -#include <SDL2/SDL.h> + +#if defined(__DJGPP__) || (defined(__WATCOMC__) && (defined(__DOS__) || defined(__DOS4G__) || defined(__DOS4GNZ__))) +#define HW_OPL_MSDOS +#include <conio.h> +#include <dos.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#ifdef __DJGPP__ +#include <pc.h> +#include <dpmi.h> +#include <go32.h> +#include <sys/farptr.h> +#include <sys/exceptn.h> +#define BIOStimer _farpeekl(_dos_ds, 0x46C) +#endif//__DJGPP__ + +#ifdef __WATCOMC__ +//#include <wdpmi.h> +#include <i86.h> +#include <bios.h> +#include <time.h> + +unsigned long biostime(unsigned cmd, unsigned long lon) +{ + long tval = (long)lon; + _bios_timeofday(cmd, &tval); + return (unsigned long)tval; +} + +#define BIOStimer biostime(0, 0l) +#define BIOSTICK 55 /* biostime() increases one tick about + every 55 msec */ + +void mch_delay(int32_t msec) +{ + /* + * We busy-wait here. Unfortunately, delay() and usleep() have been + * reported to give problems with the original Windows 95. This is + * fixed in service pack 1, but not everybody installed that. + */ + long starttime = biostime(0, 0L); + while(biostime(0, 0L) < starttime + msec / BIOSTICK); +} + +//#define BIOStimer _farpeekl(_dos_ds, 0x46C) +//#define DOSMEM(s,o,t) *(t _far *)(SS_DOSMEM + (DWORD)((o)|(s)<<4)) +//#define BIOStimer DOSMEM(0x46, 0x6C, WORD); +//#define VSYNC_STATUS Ox3da +//#define VSYNC_MASK Ox08 +/* #define SYNC { while(inp(VSYNCSTATUS) & VSYNCMASK);\ + while (!(inp(VSYNCSTATUS) & VSYNCMASK)); } */ +#endif//__WATCOMC__ + +#endif #include <adlmidi.h> +#ifndef HARDWARE_OPL3 + +#define SDL_MAIN_HANDLED +#include <SDL2/SDL.h> + #include "wave_writer.h" class MutexType @@ -35,7 +95,6 @@ public: } }; - static std::deque<short> AudioBuffer; static MutexType AudioBuffer_lock; @@ -59,6 +118,8 @@ static void SDL_AudioCallbackX(void *, Uint8 *stream, int len) SDL_UnlockAudio(); } +#endif //HARDWARE_OPL3 + static bool is_number(const std::string &s) { std::string::const_iterator it = s.begin(); @@ -73,6 +134,7 @@ static void printError(const char *err) } static int stop = 0; +#ifndef HARDWARE_OPL3 static void sighandler(int dum) { if((dum == SIGINT) @@ -83,6 +145,7 @@ static void sighandler(int dum) ) stop = 1; } +#endif static void debugPrint(void * /*userdata*/, const char *fmt, ...) @@ -102,7 +165,7 @@ static void debugPrint(void * /*userdata*/, const char *fmt, ...) #ifdef DEBUG_TRACE_ALL_EVENTS static void debugPrintEvent(void * /*userdata*/, ADL_UInt8 type, ADL_UInt8 subtype, ADL_UInt8 channel, const ADL_UInt8 * /*data*/, size_t len) { - std::fprintf(stdout, " - E: 0x%02X 0x%02X %02d (%d)\n", type, subtype, channel, (int)len); + std::fprintf(stdout, " - E: 0x%02X 0x%02X %02d (%d)\r\n", type, subtype, channel, (int)len); std::fflush(stdout); } #endif @@ -110,7 +173,11 @@ static void debugPrintEvent(void * /*userdata*/, ADL_UInt8 type, ADL_UInt8 subty int main(int argc, char **argv) { std::fprintf(stdout, "==========================================\n" + #ifdef HARDWARE_OPL3 + " libADLMIDI demo utility (HW OPL)\n" + #else " libADLMIDI demo utility\n" + #endif "==========================================\n\n"); std::fflush(stdout); @@ -167,6 +234,7 @@ int main(int argc, char **argv) return 0; } + #ifndef HARDWARE_OPL3 //const unsigned MaxSamplesAtTime = 512; // 512=dbopl limitation // How long is SDL buffer, in seconds? // The smaller the value, the more often SDL_AudioCallBack() @@ -185,8 +253,10 @@ int main(int argc, char **argv) spec.channels = 2; spec.samples = Uint16((double)spec.freq * AudioBufferLength); spec.callback = SDL_AudioCallbackX; + #endif ADL_MIDIPlayer *myDevice; + //Initialize libADLMIDI and create the instance (you can initialize multiple of them!) myDevice = adl_init(44100); if(myDevice == NULL) @@ -235,8 +305,13 @@ int main(int argc, char **argv) adl_setRawEventHook(myDevice, debugPrintEvent, NULL); #endif + #ifdef HARDWARE_OPL3 + std::fprintf(stdout, " - Hardware OPL3 chip in use\n"); + #else std::fprintf(stdout, " - %s OPL3 Emulator in use\n", adl_emulatorName()); + #endif + #ifndef HARDWARE_OPL3 if(!recordWave) { // Set up SDL @@ -253,6 +328,7 @@ int main(int argc, char **argv) obtained.samples, obtained.freq, obtained.channels); } } + #endif if(argc >= 3) { @@ -284,6 +360,7 @@ int main(int argc, char **argv) } } + #ifndef HARDWARE_OPL3 int numOfChips = 4; if(argc >= 4) numOfChips = std::atoi(argv[3]); @@ -295,6 +372,10 @@ int main(int argc, char **argv) return 1; } std::fprintf(stdout, " - Number of chips %d\n", adl_getNumChips(myDevice)); + #else + int numOfChips = 1; + adl_setNumChips(myDevice, numOfChips); + #endif if(argc >= 5) { @@ -314,19 +395,50 @@ int main(int argc, char **argv) return 2; } + std::fprintf(stdout, "File opened!\n"); std::fflush(stdout); + #ifndef HARDWARE_OPL3 signal(SIGINT, sighandler); signal(SIGTERM, sighandler); #ifndef _WIN32 signal(SIGHUP, sighandler); #endif + #else//HARDWARE_OPL3 + static const unsigned NewTimerFreq = 209; + unsigned TimerPeriod = 0x1234DDul / NewTimerFreq; + + #ifdef __DJGPP__ + //disable(); + outportb(0x43, 0x34); + outportb(0x40, TimerPeriod & 0xFF); + outportb(0x40, TimerPeriod >> 8); + //enable(); + #endif//__DJGPP__ + + #ifdef __WATCOMC__ + std::fprintf(stdout, " - Initializing BIOS timer...\n"); + std::fflush(stdout); + //disable(); + outp(0x43, 0x34); + outp(0x40, TimerPeriod & 0xFF); + outp(0x40, TimerPeriod >> 8); + //enable(); + std::fprintf(stdout, " - Ok!\n"); + std::fflush(stdout); + #endif//__WATCOMC__ + + unsigned long BIOStimer_begin = BIOStimer; + double tick_delay = 0.0; + #endif//HARDWARE_OPL3 double total = adl_totalTimeLength(myDevice); double loopStart = adl_loopStartTime(myDevice); double loopEnd = adl_loopEndTime(myDevice); + #ifndef HARDWARE_OPL3 if(!recordWave) + #endif { std::fprintf(stdout, " - Loop is turned %s\n", loopEnabled ? "ON" : "OFF"); if(loopStart >= 0.0 && loopEnd >= 0.0) @@ -334,7 +446,9 @@ int main(int argc, char **argv) std::fprintf(stdout, "\n==========================================\n"); std::fflush(stdout); + #ifndef HARDWARE_OPL3 SDL_PauseAudio(0); + #endif #ifdef DEBUG_SEEKING_TEST int delayBeforeSeek = 50; @@ -344,10 +458,12 @@ int main(int argc, char **argv) while(!stop) { + #ifndef HARDWARE_OPL3 short buff[4096]; size_t got = (size_t)adl_play(myDevice, 4096, buff); if(got <= 0) break; + #endif #ifndef DEBUG_TRACE_ALL_EVENTS std::fprintf(stdout, " \r"); @@ -355,6 +471,7 @@ int main(int argc, char **argv) std::fflush(stdout); #endif + #ifndef HARDWARE_OPL3 AudioBuffer_lock.Lock(); size_t pos = AudioBuffer.size(); AudioBuffer.resize(pos + got); @@ -376,10 +493,42 @@ int main(int argc, char **argv) adl_positionSeek(myDevice, seekTo); } #endif + + #else//HARDWARE_OPL3 + const double mindelay = 1.0 / NewTimerFreq; + + //__asm__ volatile("sti\nhlt"); + //usleep(10000); + #ifdef __DJGPP__ + __dpmi_yield(); + #endif + #ifdef __WATCOMC__ + //dpmi_dos_yield(); + mch_delay((unsigned int)(tick_delay * 1000.0)); + #endif + static unsigned long PrevTimer = BIOStimer; + const unsigned long CurTimer = BIOStimer; + const double eat_delay = (CurTimer - PrevTimer) / (double)NewTimerFreq; + PrevTimer = CurTimer; + tick_delay = adl_tickEvents(myDevice, eat_delay, mindelay); + if(adl_atEnd(myDevice) && tick_delay <= 0) + stop = true; + + if(kbhit()) + { // Quit on ESC key! + int c = getch(); + if(c == 27) + stop = true; + } + + #endif//HARDWARE_OPL3 } std::fprintf(stdout, " \n\n"); + #ifndef HARDWARE_OPL3 SDL_CloseAudio(); + #endif } + #ifndef HARDWARE_OPL3 else { std::string wave_out = std::string(argv[1]) + ".wav"; @@ -418,6 +567,32 @@ int main(int argc, char **argv) return 1; } } + #endif + + #ifdef HARDWARE_OPL3 + + #ifdef __DJGPP__ + // Fix the skewed clock and reset BIOS tick rate + _farpokel(_dos_ds, 0x46C, BIOStimer_begin + + (BIOStimer - BIOStimer_begin) + * (0x1234DD / 65536.0) / NewTimerFreq); + + //disable(); + outportb(0x43, 0x34); + outportb(0x40, 0); + outportb(0x40, 0); + //enable(); + #endif + + #ifdef __WATCOMC__ + outp(0x43, 0x34); + outp(0x40, 0); + outp(0x40, 0); + #endif + + adl_panic(myDevice); //Shut up all sustaining notes + + #endif adl_close(myDevice); |