From a461c2a942ae4da5bd241da41bbb15731192a091 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Fri, 25 Aug 2017 14:11:36 -0500 Subject: [PATCH] imfplay works now~ --- makefile | 3 + src/i0fplay.c | 231 ++++++++++++++++++++++++++++++++++++++++++ src/imfplay.c | 41 ++++---- src/lib/16_sd.c | 19 +++- src/lib/16_sd.h | 4 +- src/util/shbat/sd.bat | 1 + 6 files changed, 272 insertions(+), 27 deletions(-) create mode 100755 src/i0fplay.c create mode 100755 src/util/shbat/sd.bat diff --git a/makefile b/makefile index 354c451c..a655ce6c 100755 --- a/makefile +++ b/makefile @@ -211,6 +211,7 @@ TESTEXEC = & 0tesuto.exe & maptest.exe & imfplay.exe & + i0fplay.exe & vrldbg.exe #zcroll.exe & TESTEXEC2 = & @@ -290,6 +291,7 @@ fontgfx.exe: fontgfx.$(OBJ) gfx.lib $(DOSLIB) inputest.exe: inputest.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib sountest.exe: sountest.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib imfplay.exe: imfplay.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib +i0fplay.exe: i0fplay.$(OBJ) $(DOSLIB) vrldbg.exe: vrldbg.$(OBJ) #gfx.lib $(DOSLIB) pcxtest.exe: pcxtest.$(OBJ) gfx.lib $(DOSLIB) $(16LIB) vrstest.exe: vrstest.$(OBJ) $(16LIB) gfx.lib $(DOSLIB) @@ -340,6 +342,7 @@ inputest.$(OBJ):$(SRC)/inputest.c #inntest.$(OBJ):$(SRC)/inntest.c sountest.$(OBJ): $(SRC)/sountest.c imfplay.$(OBJ): $(SRC)/imfplay.c +i0fplay.$(OBJ): $(SRC)/i0fplay.c vrldbg.$(OBJ): $(SRC)/vrldbg.c #miditest.$(OBJ): $(SRC)/miditest.c #testemm.$(OBJ):$(SRC)/testemm.c diff --git a/src/i0fplay.c b/src/i0fplay.c new file mode 100755 index 00000000..0e67d2f1 --- /dev/null +++ b/src/i0fplay.c @@ -0,0 +1,231 @@ +/* midi.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* 8254 timer */ +#include +#include + +static void (interrupt *old_irq0)(); +static volatile unsigned long irq0_ticks=0; +static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; + +#pragma pack(push,1) +struct imf_entry { + uint8_t reg,data; + uint16_t delay; +}; +#pragma pack(pop) + +static struct imf_entry* imf_music=NULL; +static struct imf_entry* imf_play_ptr=NULL; +static struct imf_entry* imf_music_end=NULL; +static uint16_t imf_delay_countdown=0; + +void imf_free_music() { + if (imf_music) free(imf_music); + imf_music = imf_play_ptr = imf_music_end = NULL; + imf_delay_countdown = 0; +} + +int imf_load_music(const char *path) { + unsigned char buf[8]; + unsigned long len; + int fd; + + imf_free_music(); + + fd = open(path,O_RDONLY|O_BINARY); + if (fd < 0) return 0; + + len = lseek(fd,0,SEEK_END); + lseek(fd,0,SEEK_SET); + read(fd,buf,2); + if (buf[0] != 0 || buf[1] != 0) // type 1 IMF + len = *((uint16_t*)buf); + else + lseek(fd,0,SEEK_SET); + + if (len == 0 || len > 65535UL) { + close(fd); + return 0; + } + len -= len & 3; + + imf_music = malloc(len); + if (imf_music == NULL) { + close(fd); + return 0; + } + read(fd,imf_music,len); + close(fd); + + imf_play_ptr = imf_music; + imf_music_end = imf_music + (len >> 2UL); + return 1; +} + +/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ +void interrupt irq0() { + irq0_ticks++; + if ((irq0_cnt += irq0_add) >= irq0_max) { + irq0_cnt -= irq0_max; + old_irq0(); + } + else { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } +} + +void imf_tick() { + if (imf_delay_countdown == 0) { + do { + adlib_write(imf_play_ptr->reg,imf_play_ptr->data); + imf_delay_countdown = imf_play_ptr->delay; + imf_play_ptr++; + if (imf_play_ptr == imf_music_end) + imf_play_ptr = imf_music; + } while (imf_delay_countdown == 0); + } + else { + imf_delay_countdown--; + } +} + +void adlib_shut_up() { + int i; + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 400; + f->sustain = 1; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 0; + f->sustain = 1; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); +} + +int main(int argc,char **argv) { + unsigned long tickrate = 700; + unsigned long ptick; + int c; + + printf("ADLIB FM test program IMFPLAY\n"); + if (argc < 2) { + printf("You must specify an IMF file to play\n"); + return 1; + } + + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + if (!probe_8254()) { /* we need the timer to keep time with the music */ + printf("8254 timer not found\n"); + return 1; + } + + if (!imf_load_music(argv[1])) { + printf("Failed to load IMF Music\n"); + return 1; + } + + write_8254_system_timer(T8254_REF_CLOCK_HZ / tickrate); + irq0_cnt = 0; + irq0_add = 182; + irq0_max = 1000; /* about 18.2Hz */ + old_irq0 = _dos_getvect(8);/*IRQ0*/ + _dos_setvect(8,irq0); + + adlib_shut_up(); + shutdown_adlib_opl3(); // NTS: Apparently the music won't play otherwise + _cli(); + irq0_ticks = ptick = 0; + _sti(); + + while (1) { + unsigned long adv; + + _cli(); + adv = irq0_ticks - ptick; + if (adv >= 100UL) adv = 100UL; + ptick = irq0_ticks; + _sti(); + + while (adv != 0) { + imf_tick(); + adv--; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + } + } + + imf_free_music(); + adlib_shut_up(); + shutdown_adlib(); + _dos_setvect(8,old_irq0); + write_8254_system_timer(0); /* back to normal 18.2Hz */ + return 0; +} + diff --git a/src/imfplay.c b/src/imfplay.c index 697b6d36..35527524 100755 --- a/src/imfplay.c +++ b/src/imfplay.c @@ -34,8 +34,8 @@ extern struct glob_game_vars *ggvv; -/*static void (interrupt *old_irq0)(); -static volatile unsigned long irq0_ticks=0; +static void (interrupt *old_irq0)(); +/*static volatile unsigned long irq0_ticks=0; static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; #pragma pack(push,1) @@ -65,10 +65,10 @@ static uint16_t imf_delay_countdown=0; } void imf_free_music(global_game_variables_t *gvar) { - if (imf_music) free(imf_music); - MM_FreePtr(MEMPTR gvar->ca.audiosegs[0], gvar); - imf_music = imf_play_ptr = imf_music_end = NULL; - imf_delay_countdown = 0; + if (gvar->ca.sd.imf_music) free(gvar->ca.sd.imf_music); + MM_FreePtr(MEMPTRCONV gvar->ca.audiosegs[0], gvar); + gvar->ca.sd.imf_music = gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music_end = NULL; + gvar->ca.sd.imf_delay_countdown = 0; } int imf_load_music(const char *path, global_game_variables_t *gvar) { @@ -96,20 +96,20 @@ int imf_load_music(const char *path, global_game_variables_t *gvar) { len -= len & 3; // imf_music = malloc(len); - MM_GetPtr(MEMPTR gvar->ca.audiosegs[0],len, gvar); - imf_music = (struct imf_entry *)gvar->ca.audiosegs[0]; - if (imf_music == NULL) { + MM_GetPtr(MEMPTRCONV gvar->ca.audiosegs[0],len, gvar); + gvar->ca.sd.imf_music = (struct imf_entry *)gvar->ca.audiosegs[0]; + if (gvar->ca.sd.imf_music == NULL) { close(fd); return 0; } - read(fd,imf_music,len); + read(fd,gvar->ca.sd.imf_music,len); close(fd); - imf_play_ptr = imf_music; - imf_music_end = imf_music + (len >> 2UL); - PRINTBB; + gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music; + gvar->ca.sd.imf_music_end = gvar->ca.sd.imf_music + (len >> 2UL); +// PRINTBB; return 1; -} +}*/ // WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models void interrupt irq0() @@ -124,7 +124,7 @@ void interrupt irq0() } } -void imf_tick() { +/*void imf_tick() { if (imf_delay_countdown == 0) { do { adlib_write(imf_play_ptr->reg,imf_play_ptr->data); @@ -200,15 +200,15 @@ void main(int argc,char **argv) { StartupCAMMPM(&gvar); printf("ADLIB FM test program IMFPLAY\n"); if (argc < 2) { - printf("You must specify an IMF file to play\n"); -// return; + printf("You must specify an IMF file to play\n"); ShutdownCAMMPM(&gvar); + return; } SD_Initimf(&gvar); if (!SD_imf_load_music(argv[1], &gvar)) { - printf("Failed to load IMF Music\n"); -// return; + printf("Failed to load IMF Music\n"); ShutdownCAMMPM(&gvar); + return; } write_8254_system_timer(T8254_REF_CLOCK_HZ / tickrate); @@ -219,6 +219,7 @@ void main(int argc,char **argv) { gvar.ca.sd.irq0_ticks = ptick = 0; _sti(); + printf("playing!\n"); while (1) { unsigned long adv; @@ -242,7 +243,7 @@ void main(int argc,char **argv) { } } } -// printf("contents of the imf_music\n[\n%s\n]\n", imf_music); + printf("contents of the imf_music\n[\n%s\n]\n", gvar.ca.sd.imf_music); SD_imf_free_music(&gvar); SD_adlib_shut_up(); diff --git a/src/lib/16_sd.c b/src/lib/16_sd.c index 610f7ed0..f42f2019 100755 --- a/src/lib/16_sd.c +++ b/src/lib/16_sd.c @@ -22,8 +22,10 @@ #include "src/lib/16_sd.h" -//static void (interrupt *old_irq0)(); -void interrupt (*old_irq0)(void); +//#define SD_USESCAMMPM + +static void (interrupt *SD_old_irq0)(); +//void interrupt (*old_irq0)(void); void opl2out(word reg, word data) { @@ -225,8 +227,11 @@ void SD_Initimf(global_game_variables_t *gvar) void SD_imf_free_music(global_game_variables_t *gvar) { -// if (gvar->ca.sd.imf_music) free(gvar->ca.sd.imf_music); +#ifndef SD_USESCAMMPM + if (gvar->ca.sd.imf_music) free(gvar->ca.sd.imf_music); +#else MM_FreePtr(MEMPTRCONV gvar->ca.audiosegs[0], gvar); //TODO make behave like id engine +#endif gvar->ca.sd.imf_music = gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music_end = NULL; gvar->ca.sd.imf_delay_countdown = 0; } @@ -256,8 +261,12 @@ int SD_imf_load_music(const char *path, global_game_variables_t *gvar) } len -= len & 3; +#ifndef SD_USESCAMMPM + gvar->ca.sd.imf_music = malloc(len); +#else MM_GetPtr(MEMPTRCONV gvar->ca.audiosegs[0],len, gvar); gvar->ca.sd.imf_music = (struct imf_entry *)gvar->ca.audiosegs[0]; +#endif if (gvar->ca.sd.imf_music == NULL) { close(fd); return 0; @@ -272,12 +281,12 @@ int SD_imf_load_music(const char *path, global_game_variables_t *gvar) struct glob_game_vars *ggvv; // WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models -void interrupt irq0() +void interrupt SD_irq0() { ggvv->ca.sd.irq0_ticks++; if ((ggvv->ca.sd.irq0_cnt += ggvv->ca.sd.irq0_add) >= ggvv->ca.sd.irq0_max) { ggvv->ca.sd.irq0_cnt -= ggvv->ca.sd.irq0_max; - old_irq0(); + SD_old_irq0(); } else { p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); diff --git a/src/lib/16_sd.h b/src/lib/16_sd.h index f91ec991..7bae1648 100755 --- a/src/lib/16_sd.h +++ b/src/lib/16_sd.h @@ -52,7 +52,7 @@ typedef struct{ byte Feedback; /* feedback algorithm and strength */ } FMInstrument; -extern void interrupt (*old_irq0)(void); +//extern void interrupt (*old_irq0)(void); void opl2out(word reg, word data); void opl3out(word reg, word data); @@ -66,7 +66,7 @@ void FMSetVoice(int voiceNum, FMInstrument *ins); void SD_Initimf(global_game_variables_t *gvar); void SD_imf_free_music(global_game_variables_t *gvar); int SD_imf_load_music(const char *path, global_game_variables_t *gvar); -void interrupt irq0(void); +void interrupt SD_irq0(void); void SD_imf_tick(global_game_variables_t *gvar); void SD_adlib_shut_up(); diff --git a/src/util/shbat/sd.bat b/src/util/shbat/sd.bat new file mode 100755 index 00000000..e878d322 --- /dev/null +++ b/src/util/shbat/sd.bat @@ -0,0 +1 @@ +imfplay.exe data\02.imf -- 2.39.2