3 * Adlib OPL2/OPL3 FM synthesizer chipset test program.
4 * Play MIDI file using the OPLx synthesizer (well, poorly anyway)
5 * (C) 2010-2012 Jonathan Campbell.
6 * Hackipedia DOS library.
8 * This code is licensed under the LGPL.
9 * <insert LGPL legal text here>
11 * Compiles for intended target environments:
12 * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
15 #include "src/lib/16_head.h"
16 #include "src/lib/16_tail.h"
17 #include "src/lib/16_pm.h"
18 #include "src/lib/16_ca.h"
19 #include "src/lib/16_mm.h"
20 #include "src/lib/16_hc.h"
21 #include "src/lib/16_dbg.h"
22 #include "src/lib/16_sd.h"
25 // #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
26 // #include <stdlib.h>
27 // #include <string.h>
28 // #include <unistd.h>
29 // #include <malloc.h>
35 extern struct glob_game_vars *ggvv;
37 /*static void (interrupt *old_irq0)();
38 static volatile unsigned long irq0_ticks=0;
39 static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0;
48 static struct imf_entry* imf_music=NULL;
49 static struct imf_entry* imf_play_ptr=NULL;
50 static struct imf_entry* imf_music_end=NULL;
51 static uint16_t imf_delay_countdown=0;
54 printf("-------------------------------------------------------------------------------\n");\
56 printf("bigbuffer %Fp\t", gvar->ca.audiosegs[0]);\
57 printf("&%Fp\n", MEMPTR gvar->ca.audiosegs[0]);\
58 printf("imf_music %Fp\t", imf_music);\
59 printf("&%Fp\n", imf_music);\
60 printf("imf_play_ptr %Fp\t", imf_play_ptr);\
61 printf("&%Fp\n", imf_play_ptr);\
62 printf("imf_music_end %Fp\t", imf_music_end);\
63 printf("&%Fp\n", imf_music_end);\
64 printf("-------------------------------------------------------------------------------\n");\
67 void imf_free_music(global_game_variables_t *gvar) {
68 if (imf_music) free(imf_music);
69 MM_FreePtr(MEMPTR gvar->ca.audiosegs[0], gvar);
70 imf_music = imf_play_ptr = imf_music_end = NULL;
71 imf_delay_countdown = 0;
74 int imf_load_music(const char *path, global_game_variables_t *gvar) {
81 fd = open(path,O_RDONLY|O_BINARY);
84 len = lseek(fd,0,SEEK_END);
87 if (buf[0] != 0 || buf[1] != 0) // type 1 IMF
88 len = *((uint16_t*)buf);
92 if (len == 0 || len > 65535UL) {
98 // imf_music = malloc(len);
99 MM_GetPtr(MEMPTR gvar->ca.audiosegs[0],len, gvar);
100 imf_music = (struct imf_entry *)gvar->ca.audiosegs[0];
101 if (imf_music == NULL) {
105 read(fd,imf_music,len);
108 imf_play_ptr = imf_music;
109 imf_music_end = imf_music + (len >> 2UL);
115 // WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models
116 void interrupt irq0()
118 ggvv->ca.sd.irq0_ticks++;
119 if ((ggvv->ca.sd.irq0_cnt += ggvv->ca.sd.irq0_add) >= ggvv->ca.sd.irq0_max) {
120 ggvv->ca.sd.irq0_cnt -= ggvv->ca.sd.irq0_max;
124 p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);
130 if (imf_delay_countdown == 0) {
132 adlib_write(imf_play_ptr->reg,imf_play_ptr->data);
133 imf_delay_countdown = imf_play_ptr->delay;
135 if (imf_play_ptr == imf_music_end)
138 imf_play_ptr = imf_music;
140 } while (imf_delay_countdown == 0);
143 imf_delay_countdown--;
147 void adlib_shut_up() {
150 memset(adlib_fm,0,sizeof(adlib_fm));
151 memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));
152 for (i=0;i < adlib_fm_voices;i++) {
153 struct adlib_fm_operator *f;
154 f = &adlib_fm[i].mod;
155 f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
156 f = &adlib_fm[i].car;
157 f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
160 for (i=0;i < adlib_fm_voices;i++) {
161 struct adlib_fm_operator *f;
163 f = &adlib_fm[i].mod;
165 f->total_level = 63 - 16;
168 f->sustain_level = 0;
175 f = &adlib_fm[i].car;
177 f->total_level = 63 - 16;
180 f->sustain_level = 0;
191 void main(int argc,char **argv) {
192 static global_game_variables_t gvar;
193 unsigned long tickrate = 700;
204 PM_Startup(&gvar); PM_CheckMainMem(&gvar); PM_UnlockMainMem(&gvar);
206 printf("ADLIB FM test program IMFPLAY\n");
208 printf("You must specify an IMF file to play\n");
214 if (!SD_imf_load_music(argv[1], &gvar)) {
215 printf("Failed to load IMF Music\n");
219 write_8254_system_timer(T8254_REF_CLOCK_HZ / tickrate);
220 old_irq0 = _dos_getvect(8);/*IRQ0*/
221 _dos_setvect(8,irq0);
224 gvar.ca.sd.irq0_ticks = ptick = 0;
231 adv = gvar.ca.sd.irq0_ticks - ptick;
232 if (adv >= 100UL) adv = 100UL;
233 ptick = gvar.ca.sd.irq0_ticks;
243 if (c == 0) c = getch() << 8;
250 // printf("contents of the imf_music\n[\n%s\n]\n", imf_music);
252 SD_imf_free_music(&gvar);
255 _dos_setvect(8,old_irq0);
256 write_8254_system_timer(0);/* back to normal 18.2Hz */