3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
10 * By Shawn Hargreaves,
16 * Adlib/FM driver for the MIDI player.
18 * See readme.txt for copyright information.
23 #error This file should only be used by the djgpp version of Allegro
34 /* external interface to the Adlib driver */
35 static int fm_detect();
36 static int fm_init(int voices);
37 static void fm_exit();
38 static int fm_mixer_volume(int volume);
39 static int fm_load_patches(char *patches, char *drums);
40 static void fm_key_on(int inst, int note, int bend, int vol, int pan);
41 static void fm_key_off(int voice);
42 static void fm_set_volume(int voice, int vol);
43 static void fm_set_pitch(int voice, int note, int bend);
45 static char adlib_desc[80] = "not initialised";
48 MIDI_DRIVER midi_adlib =
59 _dummy_adjust_patches,
69 typedef struct FM_INSTRUMENT
71 unsigned char characteristic1;
72 unsigned char characteristic2;
75 unsigned char attackdecay1;
76 unsigned char attackdecay2;
77 unsigned char sustainrelease1;
78 unsigned char sustainrelease2;
81 unsigned char feedback;
95 /* include the GM patch set (static data) */
99 /* is the OPL in percussion mode? */
100 static int fm_drum_mode = FALSE;
102 /* delays when writing to OPL registers */
103 static int fm_delay_1 = 6;
104 static int fm_delay_2 = 35;
106 /* register offsets for each voice */
107 static int fm_offset[18] = {
108 0x000, 0x001, 0x002, 0x008, 0x009, 0x00A, 0x010, 0x011, 0x012,
109 0x100, 0x101, 0x102, 0x108, 0x109, 0x10A, 0x110, 0x111, 0x112
112 /* for converting midi note numbers to FM frequencies */
113 static int fm_freq[13] = {
114 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA,
115 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE
118 /* logarithmic relationship between midi and FM volumes */
119 static int fm_vol_table[128] = {
120 0, 11, 16, 19, 22, 25, 27, 29, 32, 33, 35, 37, 39, 40, 42, 43,
121 45, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
122 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77,
123 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89,
124 90, 91, 91, 92, 93, 93, 94, 95, 96, 96, 97, 97, 98, 99, 99, 100,
125 101, 101, 102, 103, 103, 104, 104, 105, 106, 106, 107, 107, 108,
126 109, 109, 110, 110, 111, 112, 112, 113, 113, 114, 114, 115, 115,
127 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122,
128 123, 123, 124, 124, 125, 125, 126, 126, 127
131 /* drum channel tables: BD SD TT CY HH */
132 static int fm_drum_channel[] = { 6, 7, 8, 8, 7 };
133 static int fm_drum_op1[] = { TRUE, FALSE, TRUE, FALSE, TRUE };
134 static int fm_drum_op2[] = { TRUE, TRUE, FALSE, TRUE, FALSE };
135 static int fm_drum_pitch[] = { TRUE, TRUE, TRUE, FALSE, FALSE };
137 /* cached information about the state of the drum channels */
138 static FM_INSTRUMENT *fm_drum_cached_inst1[5];
139 static FM_INSTRUMENT *fm_drum_cached_inst2[5];
140 static int fm_drum_cached_vol1[5];
141 static int fm_drum_cached_vol2[5];
142 static long fm_drum_cached_time[5];
144 /* various bits of information about the current state of the FM chip */
145 static unsigned char fm_drum_mask;
146 static unsigned char fm_key[18];
147 static unsigned char fm_keyscale[18];
148 static unsigned char fm_feedback[18];
149 static int fm_level[18];
150 static int fm_patch[18];
152 #define VOICE_OFFSET(x) ((x < 9) ? x : 0x100+x-9)
157 * Writes a byte to the specified register on the FM chip.
159 static void fm_write(int reg, unsigned char data)
162 int port = (reg & 0x100) ? _fm_port+2 : _fm_port;
164 outportb(port, reg & 0xFF); /* write the register */
166 for (i=0; i<fm_delay_1; i++) /* delay */
169 outportb(port+1, data); /* write the data */
171 for (i=0; i<fm_delay_2; i++) /* delay */
175 static END_OF_FUNCTION(fm_write);
180 * Resets the FM chip. If enable is set, puts OPL3 cards into OPL3 mode,
181 * otherwise puts them into OPL2 emulation mode.
183 static void fm_reset(int enable)
187 for (i=0xF5; i>0; i--)
190 if (midi_card == MIDI_OPL3) { /* if we have an OPL3... */
194 fm_write(0x105, 1); /* enable OPL3 mode */
196 for (i=0x1F5; i>0x105; i--)
199 for (i=0x104; i>0x100; i--)
203 fm_write(0x105, 0); /* turn OPL3 mode off again */
209 if (midi_card == MIDI_2XOPL2) { /* if we have a second OPL2... */
210 for (i=0x1F5; i>0x100; i--)
213 fm_write(0x101, 0x20);
214 fm_write(0x1BD, 0xC0);
218 for (i=0; i<midi_adlib.voices; i++) {
224 fm_write(0x40+fm_offset[i], 63);
225 fm_write(0x43+fm_offset[i], 63);
228 for (i=0; i<5; i++) {
229 fm_drum_cached_inst1[i] = NULL;
230 fm_drum_cached_inst2[i] = NULL;
231 fm_drum_cached_vol1[i] = -1;
232 fm_drum_cached_vol2[i] = -1;
233 fm_drum_cached_time[i] = 0;
236 fm_write(0x01, 0x20); /* turn on wave form control */
238 fm_drum_mode = FALSE;
240 fm_write(0xBD, fm_drum_mask); /* set AM and vibrato to high */
242 midi_adlib.xmin = -1;
243 midi_adlib.xmax = -1;
246 static END_OF_FUNCTION(fm_reset);
251 * Switches the OPL synth between normal and percussion modes.
253 static void fm_set_drum_mode(int usedrums)
257 fm_drum_mode = usedrums;
258 fm_drum_mask = usedrums ? 0xE0 : 0xC0;
260 midi_adlib.xmin = usedrums ? 6 : -1;
261 midi_adlib.xmax = usedrums ? 8 : -1;
264 if (midi_card == MIDI_OPL3)
265 fm_write(0xC0+VOICE_OFFSET(i), 0x30);
267 fm_write(0xC0+VOICE_OFFSET(i), 0);
269 fm_write(0xBD, fm_drum_mask);
272 static END_OF_FUNCTION(fm_set_drum_mode);
277 * Sets the sound to be used for the specified voice, from a structure
278 * containing eleven bytes of FM operator data. Note that it doesn't
279 * actually set the volume: it just stores volume data in the fm_level
280 * arrays for fm_set_volume() to use.
282 static inline void fm_set_voice(int voice, FM_INSTRUMENT *inst)
284 /* store some info */
285 fm_keyscale[voice] = inst->level2 & 0xC0;
286 fm_level[voice] = 63 - (inst->level2 & 63);
287 fm_feedback[voice] = inst->feedback;
289 /* write the new data */
290 fm_write(0x20+fm_offset[voice], inst->characteristic1);
291 fm_write(0x23+fm_offset[voice], inst->characteristic2);
292 fm_write(0x60+fm_offset[voice], inst->attackdecay1);
293 fm_write(0x63+fm_offset[voice], inst->attackdecay2);
294 fm_write(0x80+fm_offset[voice], inst->sustainrelease1);
295 fm_write(0x83+fm_offset[voice], inst->sustainrelease2);
296 fm_write(0xE0+fm_offset[voice], inst->wave1);
297 fm_write(0xE3+fm_offset[voice], inst->wave2);
299 /* don't set operator1 level for additive synthesis sounds */
300 if (!(inst->feedback & 1))
301 fm_write(0x40+fm_offset[voice], inst->level1);
303 /* on OPL3, 0xC0 contains pan info, so don't set it until fm_key_on() */
304 if (midi_card != MIDI_OPL3)
305 fm_write(0xC0+VOICE_OFFSET(voice), inst->feedback);
311 * Sets the sound for operator #1 of a drum channel.
313 static inline void fm_set_drum_op1(int voice, FM_INSTRUMENT *inst)
315 fm_write(0x20+fm_offset[voice], inst->characteristic1);
316 fm_write(0x60+fm_offset[voice], inst->attackdecay1);
317 fm_write(0x80+fm_offset[voice], inst->sustainrelease1);
318 fm_write(0xE0+fm_offset[voice], inst->wave1);
324 * Sets the sound for operator #2 of a drum channel.
326 static inline void fm_set_drum_op2(int voice, FM_INSTRUMENT *inst)
328 fm_write(0x23+fm_offset[voice], inst->characteristic2);
329 fm_write(0x63+fm_offset[voice], inst->attackdecay2);
330 fm_write(0x83+fm_offset[voice], inst->sustainrelease2);
331 fm_write(0xE3+fm_offset[voice], inst->wave2);
336 /* fm_set_drum_vol_op1:
337 * Sets the volume for operator #1 of a drum channel.
339 static inline void fm_set_drum_vol_op1(int voice, int vol)
341 vol = 63 * fm_vol_table[vol] / 128;
342 fm_write(0x40+fm_offset[voice], (63-vol));
347 /* fm_set_drum_vol_op2:
348 * Sets the volume for operator #2 of a drum channel.
350 static inline void fm_set_drum_vol_op2(int voice, int vol)
352 vol = 63 * fm_vol_table[vol] / 128;
353 fm_write(0x43+fm_offset[voice], (63-vol));
358 /* fm_set_drum_pitch:
359 * Sets the pitch of a drum channel.
361 static inline void fm_set_drum_pitch(int voice, FM_INSTRUMENT *drum)
363 fm_write(0xA0+VOICE_OFFSET(voice), drum->freq);
364 fm_write(0xB0+VOICE_OFFSET(voice), drum->key & 0x1F);
370 * Triggers a note on a drum channel.
372 static inline void fm_trigger_drum(int inst, int vol)
374 FM_INSTRUMENT *drum = fm_drum+inst;
378 fm_set_drum_mode(TRUE);
380 if (drum->type == FM_BD)
382 else if (drum->type == FM_SD)
384 else if (drum->type == FM_TT)
386 else if (drum->type == FM_CY)
391 /* don't let drum sounds come too close together */
392 if (fm_drum_cached_time[d] == _midi_tick)
395 fm_drum_cached_time[d] = _midi_tick;
397 fm_drum_mask &= (~drum->type);
398 fm_write(0xBD, fm_drum_mask);
402 if (fm_drum_op1[d]) {
403 if (fm_drum_cached_inst1[d] != drum) {
404 fm_drum_cached_inst1[d] = drum;
405 fm_set_drum_op1(fm_drum_channel[d], drum);
408 if (fm_drum_cached_vol1[d] != vol) {
409 fm_drum_cached_vol1[d] = vol;
410 fm_set_drum_vol_op1(fm_drum_channel[d], vol);
414 if (fm_drum_op2[d]) {
415 if (fm_drum_cached_inst2[d] != drum) {
416 fm_drum_cached_inst2[d] = drum;
417 fm_set_drum_op2(fm_drum_channel[d], drum);
420 if (fm_drum_cached_vol2[d] != vol) {
421 fm_drum_cached_vol2[d] = vol;
422 fm_set_drum_vol_op2(fm_drum_channel[d], vol);
426 fm_set_drum_pitch(fm_drum_channel[d], drum);
428 fm_drum_mask |= drum->type;
429 fm_write(0xBD, fm_drum_mask);
435 * Triggers the specified voice. The instrument is specified as a GM
436 * patch number, pitch as a midi note number, and volume from 0-127.
437 * The bend parameter is _not_ expressed as a midi pitch bend value.
438 * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp).
439 * Drum sounds are indicated by passing an instrument number greater than
440 * 128, in which case the sound is GM percussion key #(inst-128).
442 static void fm_key_on(int inst, int note, int bend, int vol, int pan)
446 if (inst > 127) { /* drum sound? */
453 fm_trigger_drum(inst, vol);
455 else { /* regular instrument */
456 if (midi_card == MIDI_2XOPL2) {
457 /* the SB Pro-1 has fixed pan positions per voice... */
459 voice = _midi_allocate_voice(0, 5);
461 voice = _midi_allocate_voice(9, midi_driver->voices-1);
464 /* on other cards we can use any voices */
465 voice = _midi_allocate_voice(-1, -1);
470 /* make sure the voice isn't sounding */
471 fm_write(0x43+fm_offset[voice], 63);
472 if (fm_feedback[voice] & 1)
473 fm_write(0x40+fm_offset[voice], 63);
475 /* make sure the voice is set up with the right sound */
476 if (inst != fm_patch[voice]) {
477 fm_set_voice(voice, fm_instrument+inst);
478 fm_patch[voice] = inst;
481 /* set pan position */
482 if (midi_card == MIDI_OPL3) {
490 fm_write(0xC0+VOICE_OFFSET(voice), pan | fm_feedback[voice]);
493 /* and play the note */
494 fm_set_pitch(voice, note, bend);
495 fm_set_volume(voice, vol);
499 static END_OF_FUNCTION(fm_key_on);
504 * Hey, guess what this does :-)
506 static void fm_key_off(int voice)
508 fm_write(0xB0+VOICE_OFFSET(voice), fm_key[voice] & 0xDF);
511 static END_OF_FUNCTION(fm_key_off);
516 * Sets the volume of the specified voice (vol range 0-127).
518 static void fm_set_volume(int voice, int vol)
520 vol = fm_level[voice] * fm_vol_table[vol] / 128;
521 fm_write(0x43+fm_offset[voice], (63-vol) | fm_keyscale[voice]);
522 if (fm_feedback[voice] & 1)
523 fm_write(0x40+fm_offset[voice], (63-vol) | fm_keyscale[voice]);
526 static END_OF_FUNCTION(fm_set_volume);
531 * Sets the pitch of the specified voice.
533 static void fm_set_pitch(int voice, int note, int bend)
544 freq = fm_freq[note];
546 freq += (fm_freq[note+1] - fm_freq[note]) * bend / 0x1000;
548 fm_key[voice] = (oct<<2) | (freq >> 8);
550 fm_write(0xA0+VOICE_OFFSET(voice), freq & 0xFF);
551 fm_write(0xB0+VOICE_OFFSET(voice), fm_key[voice] | 0x20);
554 static END_OF_FUNCTION(fm_set_pitch);
559 * Called before starting to play a MIDI file, to check if we need to be
560 * in rhythm mode or not.
562 static int fm_load_patches(char *patches, char *drums)
565 int usedrums = FALSE;
567 for (i=6; i<9; i++) {
573 fm_write(0x40+fm_offset[i], 63);
574 fm_write(0x43+fm_offset[i], 63);
577 for (i=0; i<5; i++) {
578 fm_drum_cached_inst1[i] = NULL;
579 fm_drum_cached_inst2[i] = NULL;
580 fm_drum_cached_vol1[i] = -1;
581 fm_drum_cached_vol2[i] = -1;
582 fm_drum_cached_time[i] = 0;
585 for (i=0; i<128; i++) {
592 fm_set_drum_mode(usedrums);
597 static END_OF_FUNCTION(fm_load_patches);
602 * For SB-Pro cards, sets the mixer volume for FM output.
604 static int fm_mixer_volume(int volume)
606 return _sb_set_mixer(-1, volume);
612 * Checks for the presence of an OPL synth at the current port.
614 static int fm_is_there()
616 fm_write(1, 0); /* init test register */
618 fm_write(4, 0x60); /* reset both timers */
619 fm_write(4, 0x80); /* enable interrupts */
621 if (inportb(_fm_port) & 0xE0)
624 fm_write(2, 0xFF); /* write 0xFF to timer 1 */
625 fm_write(4, 0x21); /* start timer 1 */
629 if ((inportb(_fm_port) & 0xE0) != 0xC0)
632 fm_write(4, 0x60); /* reset both timers */
633 fm_write(4, 0x80); /* enable interrupts */
641 * Adlib detection routine.
643 static int fm_detect()
646 { 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x388, 0 };
652 if (midi_card == MIDI_OPL2) {
658 for (i=0; ports[i]; i++) { /* find the card */
665 if (!fm_is_there()) {
666 strcpy(allegro_error, "OPL synth not found");
672 if ((inportb(_fm_port) & 6) == 0) { /* check for OPL3 */
673 opl_type = MIDI_OPL3;
674 _sb_read_dsp_version();
676 else { /* check for second OPL2 */
677 if (_sb_read_dsp_version() >= 0x300)
678 opl_type = MIDI_2XOPL2;
680 opl_type = MIDI_OPL2;
683 if (midi_card == MIDI_OPL3) {
684 if (opl_type != MIDI_OPL3) {
685 strcpy(allegro_error, "OPL3 synth not found");
689 else if (midi_card == MIDI_2XOPL2) {
690 if (opl_type != MIDI_2XOPL2) {
691 strcpy(allegro_error, "Second OPL2 synth not found");
695 else if (midi_card != MIDI_OPL2)
696 midi_card = opl_type;
698 if (midi_card == MIDI_OPL2)
700 else if (midi_card == MIDI_2XOPL2)
701 s = "Dual OPL2 synths";
705 sprintf(adlib_desc, "%s on port %X", s, _fm_port);
707 midi_adlib.voices = (midi_card == MIDI_OPL2) ? 9 : 18;
708 midi_adlib.def_voices = midi_adlib.max_voices = midi_adlib.voices;
716 * Reads in a .IBK patch set file, for use by the Adlib driver.
718 int load_ibk(char *filename, int drums)
722 int c, note, oct, skip, count;
724 PACKFILE *f = pack_fopen(filename, F_READ);
728 pack_fread(sig, 4, f);
729 if (memcmp(sig, "IBK\x1A", 4) != 0) {
740 inst = fm_instrument;
745 for (c=0; c<skip*16; c++)
748 for (c=0; c<count; c++) {
749 inst->characteristic1 = pack_getc(f);
750 inst->characteristic2 = pack_getc(f);
751 inst->level1 = pack_getc(f);
752 inst->level2 = pack_getc(f);
753 inst->attackdecay1 = pack_getc(f);
754 inst->attackdecay2 = pack_getc(f);
755 inst->sustainrelease1 = pack_getc(f);
756 inst->sustainrelease2 = pack_getc(f);
757 inst->wave1 = pack_getc(f);
758 inst->wave2 = pack_getc(f);
759 inst->feedback = pack_getc(f);
762 switch (pack_getc(f)) {
763 case 6: inst->type = FM_BD; break;
764 case 7: inst->type = FM_HH; break;
765 case 8: inst->type = FM_TT; break;
766 case 9: inst->type = FM_SD; break;
767 case 10: inst->type = FM_CY; break;
768 default: inst->type = 0; break;
773 note = pack_getc(f) - 24;
781 inst->freq = fm_freq[note];
782 inst->key = (oct<<2) | (fm_freq[note] >> 8);
807 * Setup the adlib driver.
809 static int fm_init(int voices)
816 for (i=0; i<2; i++) {
817 s = get_config_string("sound", ((i == 0) ? "ibk_file" : "ibk_drum_file"), NULL);
819 if (load_ibk(s, (i > 0)) != 0) {
820 sprintf(allegro_error, "Error reading .IBK file '%s'", s);
826 LOCK_VARIABLE(midi_adlib);
827 LOCK_VARIABLE(fm_instrument);
828 LOCK_VARIABLE(fm_drum);
829 LOCK_VARIABLE(_fm_port);
830 LOCK_VARIABLE(fm_offset);
831 LOCK_VARIABLE(fm_freq);
832 LOCK_VARIABLE(fm_vol_table);
833 LOCK_VARIABLE(fm_drum_channel);
834 LOCK_VARIABLE(fm_drum_op1);
835 LOCK_VARIABLE(fm_drum_op2);
836 LOCK_VARIABLE(fm_drum_pitch);
837 LOCK_VARIABLE(fm_drum_cached_inst1);
838 LOCK_VARIABLE(fm_drum_cached_inst2);
839 LOCK_VARIABLE(fm_drum_cached_vol1);
840 LOCK_VARIABLE(fm_drum_cached_vol2);
841 LOCK_VARIABLE(fm_drum_cached_time);
842 LOCK_VARIABLE(fm_drum_mask);
843 LOCK_VARIABLE(fm_drum_mode);
844 LOCK_VARIABLE(fm_key);
845 LOCK_VARIABLE(fm_keyscale);
846 LOCK_VARIABLE(fm_feedback);
847 LOCK_VARIABLE(fm_level);
848 LOCK_VARIABLE(fm_patch);
849 LOCK_VARIABLE(fm_delay_1);
850 LOCK_VARIABLE(fm_delay_2);
851 LOCK_FUNCTION(fm_write);
852 LOCK_FUNCTION(fm_reset);
853 LOCK_FUNCTION(fm_set_drum_mode);
854 LOCK_FUNCTION(fm_key_on);
855 LOCK_FUNCTION(fm_key_off);
856 LOCK_FUNCTION(fm_set_volume);
857 LOCK_FUNCTION(fm_set_pitch);
858 LOCK_FUNCTION(fm_load_patches);
866 * Cleanup when we are finished.
868 static void fm_exit()