diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/adlmidi_opl3.cpp | 15 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 21 | ||||
-rw-r--r-- | utils/midiplay/adlmidiplay.cpp | 183 |
4 files changed, 143 insertions, 77 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0396be2..05458ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") if(DJGPP OR MSDOS) set(ADLMIDI_DOS 1) + add_definitions(-DADLMIDI_HW_OPL) endif() #=========================================================================================== diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp index 59773d3..7ba4a13 100644 --- a/src/adlmidi_opl3.cpp +++ b/src/adlmidi_opl3.cpp @@ -232,6 +232,13 @@ OPL3::OPL3() : OPL3::~OPL3() { +#ifdef ADLMIDI_HW_OPL + silenceAll(); + writeRegI(0, 0x0BD, 0); + writeRegI(0, 0x104, 0); + writeRegI(0, 0x105, 0); + silenceAll(); +#endif } bool OPL3::setupLocked() @@ -275,19 +282,19 @@ void OPL3::writeReg(size_t chip, uint16_t address, uint8_t value) unsigned o = address >> 8; unsigned port = OPLBase + o * 2; - #ifdef __DJGPP__ +# ifdef __DJGPP__ outportb(port, address); for(unsigned c = 0; c < 6; ++c) inportb(port); outportb(port + 1, value); for(unsigned c = 0; c < 35; ++c) inportb(port); - #endif +# endif - #ifdef __WATCOMC__ +# ifdef __WATCOMC__ outp(port, address); 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__ +# endif//__WATCOMC__ #else//ADLMIDI_HW_OPL m_chips[chip]->writeReg(address, value); diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 06f8a9e..152ac33 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -60,16 +60,17 @@ typedef int32_t ssize_t; #endif #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> -#include <sys/farptr.h> -#include <dos.h> -#endif - +# ifndef ADLMIDI_HW_OPL +# define ADLMIDI_HW_OPL +# endif +# include <conio.h> +# ifdef __DJGPP__ +# include <pc.h> +# include <dpmi.h> +# include <go32.h> +# include <sys/farptr.h> +# include <dos.h> +# endif #endif #include <vector> diff --git a/utils/midiplay/adlmidiplay.cpp b/utils/midiplay/adlmidiplay.cpp index 0cb314e..9cfe4c4 100644 --- a/utils/midiplay/adlmidiplay.cpp +++ b/utils/midiplay/adlmidiplay.cpp @@ -243,6 +243,42 @@ static void debugPrint(void * /*userdata*/, const char *fmt, ...) } } +static void printBanks() +{ + // Get count of embedded banks (no initialization needed) + int banksCount = adl_getBanksCount(); + //Get pointer to list of embedded bank names + const char *const *banknames = adl_getBankNames(); + + if(banksCount > 0) + { + std::printf(" Available embedded banks by number:\n\n"); + + for(int a = 0; a < banksCount; ++a) + std::printf("%10s%2u = %s\n", a ? "" : "Banks:", a, banknames[a]); + + std::printf( + "\n" + " Use banks 2-5 to play Descent \"q\" soundtracks.\n" + " Look up the relevant bank number from descent.sng.\n" + "\n" + " The fourth parameter can be used to specify the number\n" + " of four-op channels to use. Each four-op channel eats\n" + " the room of two regular channels. Use as many as required.\n" + " The Doom & Hexen sets require one or two, while\n" + " Miles four-op set requires the maximum of numcards*6.\n" + "\n" + ); + } + else + { + std::printf(" This build of libADLMIDI has no embedded banks!\n\n"); + } + + flushout(stdout); +} + + #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) { @@ -277,10 +313,17 @@ int main(int argc, char **argv) "==========================================\n\n"); flushout(stdout); + if(argc >= 2 && std::string(argv[1]) == "--list-banks") + { + printBanks(); + return 0; + } + if(argc < 2 || std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h") { std::printf( - "Usage: adlmidi <midifilename> [ <options> ] [ <bank> [ <numchips> [ <numfourops>] ] ]\n" + "Usage: adlmidi <midifilename> [ <options> ] \n" + " [ <bank> [ <numchips> [ <numfourops>] ] ]\n" // " -p Enables adlib percussion instrument mode\n" " -t Enables tremolo amplification mode\n" " -v Enables vibrato amplification mode\n" @@ -288,17 +331,23 @@ int main(int argc, char **argv) " -frb Enables full-ranged CC74 XG Brightness controller\n" " -nl Quit without looping\n" " -w Write WAV file rather than playing\n" - " -mb Run the test of multibank over embedded. 62, 14, 68, and 74'th banks will be combined into one\n" + " -mb Run the test of multibank over embedded. 62, 14, 68, and 74'th banks\n" + " will be combined into one\n" " --solo <track> Selects a solo track to play\n" " --only <track1,...,trackN> Selects a subset of tracks to play\n" - #ifndef HARDWARE_OPL3 +#ifndef HARDWARE_OPL3 " -fp Enables full-panning stereo support\n" " --emu-nuked Uses Nuked OPL3 v 1.8 emulator\n" " --emu-nuked7 Uses Nuked OPL3 v 1.7.4 emulator\n" " --emu-dosbox Uses DosBox 0.74 OPL3 emulator\n" " --emu-opal Uses Opal OPL3 emulator\n" " --emu-java Uses Java OPL3 emulator\n" - #endif +#endif +#ifdef HARDWARE_OPL3 + "\n" + " --time-freq <hz> Uses a different time value, DEFAULT 209\n" + " --list-banks Print a lost of all built-in FM banks\n" +#endif "\n" "Where <bank> - number of embeeded bank or filepath to custom WOPL bank file\n" "\n" @@ -307,38 +356,9 @@ int main(int argc, char **argv) "\n" ); - // Get count of embedded banks (no initialization needed) - int banksCount = adl_getBanksCount(); - //Get pointer to list of embedded bank names - const char *const *banknames = adl_getBankNames(); - - if(banksCount > 0) - { - std::printf(" Available embedded banks by number:\n\n"); - - for(int a = 0; a < banksCount; ++a) - std::printf("%10s%2u = %s\n", a ? "" : "Banks:", a, banknames[a]); - - std::printf( - "\n" - " Use banks 2-5 to play Descent \"q\" soundtracks.\n" - " Look up the relevant bank number from descent.sng.\n" - "\n" - " The fourth parameter can be used to specify the number\n" - " of four-op channels to use. Each four-op channel eats\n" - " the room of two regular channels. Use as many as required.\n" - " The Doom & Hexen sets require one or two, while\n" - " Miles four-op set requires the maximum of numcards*6.\n" - "\n" - ); - } - else - { - std::printf(" This build of libADLMIDI has no embedded banks!\n\n"); - } - - flushout(stdout); - +#ifndef HARDWARE_OPL3 + printBanks(); +#endif return 0; } @@ -365,9 +385,14 @@ int main(int argc, char **argv) spec.channels = 2; spec.samples = uint16_t((double)spec.freq * AudioBufferLength); # endif //OUTPUT_WAVE_ONLY - #endif //HARDWARE_OPL3 +#ifdef HARDWARE_OPL3 + static unsigned newTimerFreq = 209; + unsigned timerPeriod = 0x1234DDul / newTimerFreq; +#endif + + ADL_MIDIPlayer *myDevice; //Initialize libADLMIDI and create the instance (you can initialize multiple of them!) @@ -466,6 +491,27 @@ int main(int argc, char **argv) else if(!std::strcmp("-s", argv[2])) adl_setScaleModulators(myDevice, 1);//Turn on modulators scaling by volume +#ifdef HARDWARE_OPL3 + else if(!std::strcmp("--time-freq", argv[2])) + { + if(argc <= 3) + { + printError("The option --time-freq requires an argument!\n"); + return 1; + } + newTimerFreq = std::strtoul(argv[3], NULL, 0); + if(newTimerFreq == 0) + { + printError("The option --time-freq requires a non-zero integer argument!\n"); + return 1; + } + + timerPeriod = 0x1234DDul / newTimerFreq; + + had_option = true; + } +#endif + else if(!std::strcmp("--solo", argv[2])) { if(argc <= 3) @@ -724,19 +770,17 @@ int main(int argc, char **argv) signal(SIGHUP, sighandler); # endif -#else//HARDWARE_OPL3 - static const unsigned NewTimerFreq = 209; - unsigned TimerPeriod = 0x1234DDul / NewTimerFreq; +#else // HARDWARE_OPL3 - #ifdef __DJGPP__ +# ifdef __DJGPP__ //disable(); outportb(0x43, 0x34); - outportb(0x40, TimerPeriod & 0xFF); - outportb(0x40, TimerPeriod >> 8); + outportb(0x40, timerPeriod & 0xFF); + outportb(0x40, timerPeriod >> 8); //enable(); - #endif//__DJGPP__ +# endif//__DJGPP__ - #ifdef __WATCOMC__ +# ifdef __WATCOMC__ std::fprintf(stdout, " - Initializing BIOS timer...\n"); flushout(stdout); //disable(); @@ -746,7 +790,7 @@ int main(int argc, char **argv) //enable(); std::fprintf(stdout, " - Ok!\n"); flushout(stdout); - #endif//__WATCOMC__ +# endif//__WATCOMC__ unsigned long BIOStimer_begin = BIOStimer; double tick_delay = 0.0; @@ -792,6 +836,14 @@ int main(int argc, char **argv) # endif char posHMS[25]; uint64_t milliseconds_prev = ~0u; + int printsCounter = 0; + int printsCounterPeriod = 100; +# ifdef HARDWARE_OPL3 + printsCounterPeriod = 1000; +# endif + + std::fprintf(stdout, " \r"); + while(!stop) { # ifndef HARDWARE_OPL3 @@ -814,15 +866,20 @@ int main(int argc, char **argv) # ifndef DEBUG_TRACE_ALL_EVENTS double time_pos = adl_positionTell(myDevice); - std::fprintf(stdout, " \r"); uint64_t milliseconds = static_cast<uint64_t>(time_pos * 1000.0); + if(milliseconds != milliseconds_prev) { - secondsToHMSM(time_pos, posHMS, 25); - std::fprintf(stdout, " \r"); - std::fprintf(stdout, "Time position: %s / %s\r", posHMS, totalHMS); - flushout(stdout); - milliseconds_prev = milliseconds; + if(printsCounter >= printsCounterPeriod) + { + printsCounter = -1; + secondsToHMSM(time_pos, posHMS, 25); + std::fprintf(stdout, " \r"); + std::fprintf(stdout, "Time position: %s / %s\r", posHMS, totalHMS); + flushout(stdout); + milliseconds_prev = milliseconds; + } + printsCounter++; } # endif @@ -850,20 +907,20 @@ int main(int argc, char **argv) # endif # else//HARDWARE_OPL3 - const double mindelay = 1.0 / NewTimerFreq; + const double mindelay = 1.0 / newTimerFreq; //__asm__ volatile("sti\nhlt"); //usleep(10000); - #ifdef __DJGPP__ +# ifdef __DJGPP__ __dpmi_yield(); - #endif - #ifdef __WATCOMC__ +# endif +# ifdef __WATCOMC__ //dpmi_dos_yield(); mch_delay((unsigned int)(tick_delay * 1000.0)); - #endif +# endif static unsigned long PrevTimer = BIOStimer; const unsigned long CurTimer = BIOStimer; - const double eat_delay = (CurTimer - PrevTimer) / (double)NewTimerFreq; + 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) @@ -938,24 +995,24 @@ int main(int argc, char **argv) #ifdef HARDWARE_OPL3 - #ifdef __DJGPP__ +# ifdef __DJGPP__ // Fix the skewed clock and reset BIOS tick rate _farpokel(_dos_ds, 0x46C, BIOStimer_begin + (BIOStimer - BIOStimer_begin) - * (0x1234DD / 65536.0) / NewTimerFreq); + * (0x1234DD / 65536.0) / newTimerFreq); //disable(); outportb(0x43, 0x34); outportb(0x40, 0); outportb(0x40, 0); //enable(); - #endif +# endif - #ifdef __WATCOMC__ +# ifdef __WATCOMC__ outp(0x43, 0x34); outp(0x40, 0); outp(0x40, 0); - #endif +# endif adl_panic(myDevice); //Shut up all sustaining notes |