]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/adlib.h
going to work on this soon
[16.git] / src / lib / doslib / adlib.h
1 /* adlib.h
2  *
3  * Adlib OPL2/OPL3 FM synthesizer chipset controller library.
4  * (C) 2010-2012 Jonathan Campbell.
5  * Hackipedia DOS library.
6  *
7  * This code is licensed under the LGPL.
8  * <insert LGPL legal text here>
9  *
10  * Compiles for intended target environments:
11  *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */
12
13 //#include "src/lib/doslib/cpu.h"
14 #include "src/lib/doslib/8254.h"                /* 8254 timer */
15 #include <stdint.h>
16
17 #define ADLIB_FM_VOICES                 18
18
19 #define ADLIB_IO_INDEX                  0x388
20 #define ADLIB_IO_STATUS                 0x388
21 #define ADLIB_IO_DATA                   0x389
22
23 #define ADLIB_IO_INDEX2                 0x38A
24 #define ADLIB_IO_STATUS2                0x38A
25 #define ADLIB_IO_DATA2                  0x38B
26
27 /* Adlib status */
28 #define ADLIB_STATUS_TIMERS_EXPIRED     0x80
29 #define ADLIB_STATUS_TIMER1_EXPIRED     0x40
30 #define ADLIB_STATUS_TIMER2_EXPIRED     0x20
31
32 enum {
33         ADLIB_FM_DUAL_OPL2=0x01,
34         ADLIB_FM_OPL3=0x02
35 };
36
37 struct adlib_fm_operator {
38         /* 0x20-0x3F */
39         uint8_t                 am:1;                   /* bit 7: Apply amplitude modulation */
40         uint8_t                 vibrato:1;              /* bit 6: Apply vibrato */
41         uint8_t                 sustain:1;              /* bit 5: maintain sustain level */
42         uint8_t                 key_scaling_rate:1;     /* bit 4: increase ADSR enevelope speed as pitch increases */
43         uint8_t                 mod_multiple:4;         /* bits 0-3: modulator multiple (1=voice frequency, 2=one octave above) */
44         /* 0x40-0x5F */
45         uint8_t                 level_key_scale:2;      /* bits 7-6: decrease volume as frequency rises (0=none 1=1.5dB/8ve 2=3dB/8ve 3=6dB/8ve) */
46         uint8_t                 total_level:6;          /* bits 5-0: total output level (for sanity's sake, we maintain here as 0=silent 0x3F=full even though hardware is opposite) */
47         /* 0x60-0x7F */
48         uint8_t                 attack_rate:4;          /* bits 7-4: attack rate */
49         uint8_t                 decay_rate:4;           /* bits 3-0: decay rate */
50         /* 0x80-0x9F */
51         uint8_t                 sustain_level:4;        /* bits 7-4: sustain level */
52         uint8_t                 release_rate:4;         /* bits 3-0: release rate */
53         /* 0xA0-0xBF */
54         uint16_t                key_on:1;               /* bit 5: voice the channel */
55         uint16_t                octave:3;               /* bits 4-2: octave */
56         uint16_t                f_number:10;            /* bits 1-0, then bits 7-0: F-number (frequency) */
57         /* 0xC0-0xCF */
58         uint8_t                 ch_a:1;                 /* bit 4: OPL3: Channel A output */
59         uint8_t                 ch_b:1;                 /* bit 5: OPL3: Channel B output */
60         uint8_t                 ch_c:1;                 /* bit 6: OPL3: Channel C output */
61         uint8_t                 ch_d:1;                 /* bit 7: OPL3: Channel D output */
62         uint8_t                 feedback:3;             /* bits 3-1: feedback strength */
63         uint8_t                 connection:1;           /* bit 0: connection (operator 1 and 2 independent if set) */
64         /* 0xE0-0xFF */
65         uint8_t                 waveform:3;             /* bits 1-0: which waveform to use */
66 };
67
68 struct adlib_fm_channel {
69         struct adlib_fm_operator        mod,car;
70 };
71
72 struct adlib_reg_bd {
73         uint8_t                 am_depth:1;
74         uint8_t                 vibrato_depth:1;
75         uint8_t                 rythm_enable:1;
76         uint8_t                 bass_drum_on:1;
77         uint8_t                 snare_drum_on:1;
78         uint8_t                 tom_tom_on:1;
79         uint8_t                 cymbal_on:1;
80         uint8_t                 hi_hat_on:1;
81 };
82
83 int init_adlib();
84 void shutdown_adlib();
85 void shutdown_adlib_opl3();
86 int probe_adlib(unsigned char sec);
87 unsigned char adlib_read(unsigned short i);
88 void adlib_write(unsigned short i,unsigned char d);
89 void adlib_update_group20(unsigned int op,struct adlib_fm_operator *f);
90 void adlib_update_group40(unsigned int op,struct adlib_fm_operator *f);
91 void adlib_update_group60(unsigned int op,struct adlib_fm_operator *f);
92 void adlib_update_group80(unsigned int op,struct adlib_fm_operator *f);
93 void adlib_update_groupA0(unsigned int channel,struct adlib_fm_channel *ch);
94 void adlib_update_groupC0(unsigned int channel,struct adlib_fm_channel *ch);
95 void adlib_update_groupE0(unsigned int op,struct adlib_fm_operator *f);
96 void adlib_update_operator(unsigned int op,struct adlib_fm_operator *f);
97 void adlib_freq_to_fm_op(struct adlib_fm_operator *f,double freq);
98 double adlib_fm_op_to_freq(struct adlib_fm_operator *f);
99 void adlib_update_bd(struct adlib_reg_bd *b);
100 void adlib_apply_all();
101
102 extern unsigned short                   adlib_voice_to_op_opl2[9];
103 extern unsigned short                   adlib_voice_to_op_opl3[18];
104 extern unsigned short*                  adlib_voice_to_op;
105
106 extern struct adlib_reg_bd              adlib_reg_bd;
107 extern struct adlib_fm_channel          adlib_fm[ADLIB_FM_VOICES];
108 extern int                              adlib_fm_voices;
109 extern unsigned char                    adlib_flags;
110
111 extern struct adlib_fm_channel          adlib_fm_preset_deep_bass_drum;
112 extern struct adlib_fm_channel          adlib_fm_preset_violin_opl3;
113 extern struct adlib_fm_channel          adlib_fm_preset_violin_opl2;
114 extern struct adlib_fm_channel          adlib_fm_preset_harpsichord;
115 extern struct adlib_fm_channel          adlib_fm_preset_small_drum;
116 extern struct adlib_fm_channel          adlib_fm_preset_piano;
117 extern struct adlib_fm_channel          adlib_fm_preset_horn;
118
119 /* NTS: I have a Creative CT1350B card where we really do have to wait at least
120  *      33us per I/O access, because the OPL2 chip on it really is that slow.
121  *
122  *      Peior to this fix, the adlib code would often fail on a real CT1350B
123  *      (unless run just after the Sound Blaster test program) and even if it
124  *      did run, only about 1/3rd of the voices would work. Upping the delay
125  *      to 40us for OPL3 and 100us for OPL2 resolved these issues. */
126 static inline void adlib_wait() {
127         t8254_wait(t8254_us2ticks((adlib_flags & ADLIB_FM_OPL3) ? 40 : 100));
128 }
129
130 static inline unsigned char adlib_status(unsigned char which) {
131         adlib_wait();
132         return inp(ADLIB_IO_STATUS+(which*2));
133 }
134
135 static inline unsigned char adlib_status_imm(unsigned char which) {
136         return inp(ADLIB_IO_STATUS+(which*2));
137 }
138