OSDN Git Service

imfplay works now~
[proj16/16.git] / src / imfplay.c
1 /* midi.c
2  *
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.
7  *
8  * This code is licensed under the LGPL.
9  * <insert LGPL legal text here>
10  *
11  * Compiles for intended target environments:
12  *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
13  */
14
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"
23
24 // #include <stdio.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>
30 // #include <ctype.h>
31 // #include <fcntl.h>
32 // #include <math.h>
33 // #include <dos.h>
34
35 extern struct glob_game_vars    *ggvv;
36
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;
40
41 #pragma pack(push,1)
42 struct imf_entry {
43         uint8_t         reg,data;
44         uint16_t        delay;
45 };
46 #pragma pack(pop)
47
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;
52
53 #define PRINTBB {\
54         printf("-------------------------------------------------------------------------------\n");\
55         printf("buffer:\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");\
65 }
66
67 void imf_free_music(global_game_variables_t *gvar) {
68         if (gvar->ca.sd.imf_music) free(gvar->ca.sd.imf_music);
69         MM_FreePtr(MEMPTRCONV gvar->ca.audiosegs[0], gvar);
70         gvar->ca.sd.imf_music = gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music_end = NULL;
71         gvar->ca.sd.imf_delay_countdown = 0;
72 }
73
74 int imf_load_music(const char *path, global_game_variables_t *gvar) {
75         unsigned long len;
76         unsigned char buf[8];
77         int fd;
78
79         imf_free_music(gvar);
80
81         fd = open(path,O_RDONLY|O_BINARY);
82         if (fd < 0) return 0;
83
84         len = lseek(fd,0,SEEK_END);
85         lseek(fd,0,SEEK_SET);
86         read(fd,buf,2);
87         if (buf[0] != 0 || buf[1] != 0) // type 1 IMF
88                 len = *((uint16_t*)buf);
89         else
90                 lseek(fd,0,SEEK_SET);
91
92         if (len == 0 || len > 65535UL) {
93                 close(fd);
94                 return 0;
95         }
96         len -= len & 3;
97
98 //      imf_music = malloc(len);
99         MM_GetPtr(MEMPTRCONV gvar->ca.audiosegs[0],len, gvar);
100         gvar->ca.sd.imf_music = (struct imf_entry *)gvar->ca.audiosegs[0];
101         if (gvar->ca.sd.imf_music == NULL) {
102                 close(fd);
103                 return 0;
104         }
105         read(fd,gvar->ca.sd.imf_music,len);
106         close(fd);
107
108         gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music;
109         gvar->ca.sd.imf_music_end = gvar->ca.sd.imf_music + (len >> 2UL);
110 //      PRINTBB;
111         return 1;
112 }*/
113
114 // WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models
115 void interrupt irq0()
116 {
117         ggvv->ca.sd.irq0_ticks++;
118         if ((ggvv->ca.sd.irq0_cnt += ggvv->ca.sd.irq0_add) >= ggvv->ca.sd.irq0_max) {
119                 ggvv->ca.sd.irq0_cnt -= ggvv->ca.sd.irq0_max;
120                 old_irq0();
121         }
122         else {
123                 p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);
124         }
125 }
126
127 /*void imf_tick() {
128         if (imf_delay_countdown == 0) {
129                 do {
130                         adlib_write(imf_play_ptr->reg,imf_play_ptr->data);
131                         imf_delay_countdown = imf_play_ptr->delay;
132                         imf_play_ptr++;
133                         if (imf_play_ptr == imf_music_end)
134                         {
135                                 printf("replay\n");
136                                 imf_play_ptr = imf_music;
137                         }
138                 } while (imf_delay_countdown == 0);
139         }
140         else {
141                 imf_delay_countdown--;
142         }
143 }
144
145 void adlib_shut_up() {
146         int i;
147
148         memset(adlib_fm,0,sizeof(adlib_fm));
149         memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));
150         for (i=0;i < adlib_fm_voices;i++) {
151                 struct adlib_fm_operator *f;
152                 f = &adlib_fm[i].mod;
153                 f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
154                 f = &adlib_fm[i].car;
155                 f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
156         }
157
158         for (i=0;i < adlib_fm_voices;i++) {
159                 struct adlib_fm_operator *f;
160
161                 f = &adlib_fm[i].mod;
162                 f->mod_multiple = 1;
163                 f->total_level = 63 - 16;
164                 f->attack_rate = 15;
165                 f->decay_rate = 4;
166                 f->sustain_level = 0;
167                 f->release_rate = 8;
168                 f->f_number = 400;
169                 f->sustain = 1;
170                 f->octave = 4;
171                 f->key_on = 0;
172
173                 f = &adlib_fm[i].car;
174                 f->mod_multiple = 1;
175                 f->total_level = 63 - 16;
176                 f->attack_rate = 15;
177                 f->decay_rate = 4;
178                 f->sustain_level = 0;
179                 f->release_rate = 8;
180                 f->f_number = 0;
181                 f->sustain = 1;
182                 f->octave = 0;
183                 f->key_on = 0;
184         }
185
186         adlib_apply_all();
187 }*/
188
189 void main(int argc,char **argv) {
190         static global_game_variables_t gvar;
191         unsigned long ptick, tickrate = 700;
192         int c;
193 #ifdef __DEBUG_CA__
194         dbg_debugca=1;
195 #endif
196 #ifdef __DEBUG_MM_
197         dbg_debugmm=1;
198 #endif
199         ggvv=&gvar;
200         StartupCAMMPM(&gvar);
201         printf("ADLIB FM test program IMFPLAY\n");
202         if (argc < 2) {
203                 printf("You must specify an IMF file to play\n"); ShutdownCAMMPM(&gvar);
204                 return;
205         }
206
207         SD_Initimf(&gvar);
208
209         if (!SD_imf_load_music(argv[1], &gvar)) {
210                 printf("Failed to load IMF Music\n"); ShutdownCAMMPM(&gvar);
211                 return;
212         }
213
214         write_8254_system_timer(T8254_REF_CLOCK_HZ / tickrate);
215         old_irq0 = _dos_getvect(8);     /*IRQ0*/
216         _dos_setvect(8,irq0);
217
218         _cli();
219         gvar.ca.sd.irq0_ticks = ptick = 0;
220         _sti();
221
222         printf("playing!\n");
223         while (1) {
224                 unsigned long adv;
225
226                 _cli();
227                 adv = gvar.ca.sd.irq0_ticks - ptick;
228                 if (adv >= 100UL) adv = 100UL;
229                 ptick = gvar.ca.sd.irq0_ticks;
230                 _sti();
231
232                 while (adv != 0) {
233                         SD_imf_tick(&gvar);
234                         adv--;
235                 }
236
237                 if (kbhit()) {
238                         c = getch();
239                         if (c == 0) c = getch() << 8;
240
241                         if (c == 27) {
242                                 break;
243                         }
244                 }
245         }
246         printf("contents of the imf_music\n[\n%s\n]\n", gvar.ca.sd.imf_music);
247
248         SD_imf_free_music(&gvar);
249         SD_adlib_shut_up();
250         shutdown_adlib();
251         _dos_setvect(8,old_irq0);
252         write_8254_system_timer(0);     /* back to normal 18.2Hz */
253         ShutdownCAMMPM(&gvar);
254 }