diff options
Diffstat (limited to 'utils/midiplay/adlmidiplay.cpp')
-rw-r--r-- | utils/midiplay/adlmidiplay.cpp | 183 |
1 files changed, 179 insertions, 4 deletions
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); |