#include #include #include #define ADLIB_ADDR_PORT 0x388 #define ADLIB_DATA_PORT 0x389 #define BYTE char unsigned typedef struct { BYTE flags1; BYTE flags2; BYTE ksl_attn1; BYTE ksl_attn2; BYTE att_dec1; BYTE att_dec2; BYTE sus_rel1; BYTE sus_rel2; BYTE wave_sel1; BYTE wave_sel2; BYTE fdbk_alg; } PatchData; PatchData sample_patch = { (1<<5)|(15), (1<<5)|(7), 0, 0, 0xF0, 0xFF, 0xF8, 0xF8, 0, 3, (3<<1)|(1) }; PatchData drum_patch_6={0x00,0x00,0x0B,0x00,0xA8,0xD6,0x4C,0x4F,0,0,0}; PatchData drum_patch_7={0x01,0x0C,0x06,0x00,0xF9,0xF8,0x68,0xB5,0,0,1}; PatchData drum_patch_8={0x02,0x03,0x00,0x05,0xF7,0xF5,0xB5,0xA5,0,0,1}; static int op_offset[]={0,1,2,8,9,10,16,17,18}; static int fnumber[]={ 0x158, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287 }; static char shadow_0xBD; static char reg_shadow[9]; //void write_to_reg(char reg,char value) void write_to_reg(unsigned reg,int value) { int i; for (i=0;i<35;i++) inp(ADLIB_ADDR_PORT); _outp(ADLIB_ADDR_PORT,reg); for (i=0;i<7;i++) inp(ADLIB_ADDR_PORT); _outp(ADLIB_DATA_PORT,value); } void write_patch(PatchData *pd,int voice_no) { int addr; int volume; addr=op_offset[voice_no]; write_to_reg(0x20+addr,pd->flags1); write_to_reg(0x20+3+addr,pd->flags2); write_to_reg(0x40+addr,pd->ksl_attn1); write_to_reg(0x40+3+addr,pd->ksl_attn2); write_to_reg(0x60+addr,pd->att_dec1); write_to_reg(0x60+3+addr,pd->att_dec2); write_to_reg(0x80+addr,pd->sus_rel1); write_to_reg(0x80+3+addr,pd->sus_rel2); write_to_reg(0xE0+addr,pd->wave_sel1); write_to_reg(0xE0+3+addr,pd->wave_sel2); write_to_reg(0xC0+voice_no,pd->fdbk_alg); } void fm_reset(void) { int i; write_to_reg(0x01,0x20); write_to_reg(0x08,0x20); write_to_reg(0xBD,0xC0); for(i=0;i<9;i++) { write_to_reg(0xA0,0x00); write_to_reg(0xB0,0x00); } } void set_frequency(int voice_no,int octave,int note) { unsigned char key_oct_fn; int fnum=fnumber[note]; write_to_reg(0xA0+voice_no,fnum&0xFF); key_oct_fn=((octave&0x03)<<2)|((fnum>>8)&0x03); reg_shadow[voice_no]=key_oct_fn; write_to_reg(0xB0+voice_no,key_oct_fn); } void play_voice(int voice_no,int octave,int note) { unsigned char key_oct_fn; int fnum=fnumber[note]; write_to_reg(0xA0+voice_no,fnum&0xFF); key_oct_fn=0x20|((octave&0x03)<<2)|((fnum>>8)&0x03); reg_shadow[voice_no]=key_oct_fn; write_to_reg(0xB0+voice_no,key_oct_fn); } void stop_voice(int voice_no) { write_to_reg(0xB0+voice_no,reg_shadow[voice_no]&0x1F); } void init_drums(void) { int i; for (i=6;i<9;i++) stop_voice(i); write_to_reg(0xBD,0xE0); shadow_0xBD=0xE0; write_patch(&drum_patch_6,6); write_patch(&drum_patch_7,7); write_patch(&drum_patch_8,8); set_frequency(6,2,1); set_frequency(7,2,2); set_frequency(8,2,3); } void play_drum(int drumno) { char outbyte; if (drumno<5) { outbyte=1<='1')&&(key<='5')) { key-='1'; stop_drum(key); play_drum(key); } else { key-='a'; block=2+key/12; note=key%12; play_voice(0,block,note); stop_voice(0); } } fm_reset(); }