/* FMMOD FM MIDI Sound Module, plays the fm chip with MIDI messages from MIDI IN */
/* With Built-in editor */
/* Last revision: 941017 */
#include <stdio.h>
#include <sbc.h>
#include <sbcmusic.h>
#include <bios.h>
#include <conio.h>
#include <dos.h>
#include <dir.h>
#include <cursor.h>
#include <midi.h>
#include <mkbrk.h>
#define SbProID 100
#define KeyUp 0x80
int edpatch;
int opr;
int Loaded_before;
char curr_cmf[80];
char cmfname[80];
unsigned char out_cnvrt(int i,int param);
unsigned char in_runstatus,out_runstatus;
char channel_on[16];
char default_instr[16] =
{ 0x021,0x011,0x04C,0x000,0x0F1,0x0F2,0x063,0x072,
0x000,0x000,0x004,0x000,0x000,0x000,0x000,0x000 };
char InstrBuf[128][16];
int numinstr;
unsigned char old_note,velocity,octave,program;
int editmode;
int playmode;
main(int argc,char **argv)
{
unsigned char midibyte,note,velocity,channel,program;
long midiin;
int event_flags;
if(init(argc,argv[1]))
{
while(1)
{
if (midiin=sbmidi_get())
{
midibyte=(unsigned char)midiin;
if(midibyte >= NoteOff1)
{
if(midibyte == SysEx)
sysex_rcv();
else
if(midibyte <= EOX) /* Ignore System Realtime Msgs */
in_runstatus = midibyte;
}
else
{
channel = in_runstatus & 0xF;
if((in_runstatus >= NoteOn1) && (in_runstatus <= NoteOn16))
{
do
while(!(midiin=sbmidi_get()));
while((velocity=(unsigned char)midiin) > 127); /* Ignore Non-Data msgs */
if(channel_on[channel])
fmplay(channel,midibyte,velocity);
}
else
if((in_runstatus >= ProgramChange1) && (in_runstatus <= ProgramChange16))
{
program = midibyte;
sbfd_program_change(channel,program);
}
}
}
if(playmode)
process_playkey();
else
if(kbhit())
process_key();
}
}
}
int init(int argc,char *argstr)
{
int i,j;
FILE* f;
/*
if(argc > 0)
{
*/
if ( ! GetEnvSetting() )
{
if (sbc_check_card() & 4)
{
if (sbc_test_int())
{
sbfd_init();
sbfd_setmode(1);
sbfd_program_change(15,15);
sbmidi_init(ct_int_num);
velocity = 64;
octave = 5;
program = 0;
editmode = 0;
playmode = 0;
edpatch = 0;
for(i=0;i<16;i++)
channel_on[i] = 1;
for(i=0;i<128;i++)
for(j=0;j<16;j++)
InstrBuf[i][j]=default_instr[j];
if(f=fopen("fmmod.cfg","rb"))
get_config_settings(f);
if(f=fopen("default.set","rb"))
{
fclose(f);
loadpatches2("default.set");
}
sbfd_instrument((char far*)InstrBuf);
draw_screen();
}
else
{
printf("Error on interrupt.\n");
return(0);
}
}
else
{
printf("Sound Blaster Card not found or wrong I/O setting.\n") ;
return(0);
}
}
else
{
printf("BLASTER environment variable not set or incomplete or invalid.\n");
return(0);
}
return(1);
/*
}
else
{
printf("FMMOD FM MIDI Sound Module v1.0\n");
printf("usage: fmmod <irq>\n");
return(0);
}
*/
}
quit()
{
int k;
gotoxy(1,22);
printf("Do you really want to quit (Y\\n)?");
k = 0;
while(1)
if(kbhit()) break;
if(kbhit())
k = (bioskey(0) >> 8) & 0xff;
if( k == 28 || k == 21 )
{
sbmidi_exit();
sbfd_music_off();
sbfd_reset();
showcur();
clrscr();
exit(0);
}
draw_screen();
}
get_config_settings(FILE* cfgf)
{
fread(&channel_on[0],1,16,cfgf);
fread(&velocity,1,1,cfgf);
fclose(cfgf);
}
save_config_settings()
{
FILE* cfgf;
cfgf = fopen("fmmod.cfg","wb");
fwrite(&channel_on[0],1,16,cfgf);
fwrite(&velocity,1,1,cfgf);
fclose(cfgf);
}
draw_screen()
{
int i;
clrscr();
printf("*** FM MIDI Sound Module v1.0 *** Current Program: %-3u\n\n",program);
printf("Alt-V Set Velocity Alt-O All notes off Alt-Y FM Editor Alt-Z List Files\n\n");
printf("Alt-P Load Patch Alt-L Load 128-patch set Alt-S Save 128-patch set\n\n");
printf("Alt-W Save Settings Alt-U SysEx Xmit\n\n");
printf("P Play Keyboard <ESC> Quit\n\n\n");
printf("Channels enabled/disabled\n");
printf("-------------------------\n\n");
printf("0 1 2 3 4 5 6 7 8 9 A B C D E F\n\n");
for(i=0;i<16;i++)
printf("%X ",channel_on[i]);
}
process_key()
{
int scan,modifiers;
scan = (bioskey(0) >> 8) & 0xFF;
modifiers = bioskey(2);
if(modifiers & 8)
{
switch(scan) {
case 47 : setveloc();break; /* Alt-V */
case 24 : all_notes_off();break; /* Alt-O */
case 25 : loadpatch();break; /* Alt-P */
case 38 : loadpatches();break; /* Alt-L */
case 31 : savepatches();break; /* Alt-S */
case 44 : listfiles();break; /* Alt-Z */
case 17 : save_config_settings();break; /* Alt-W */
case 21 : fm_edit();break; /* Alt-Y */
case 22 : sysex_xmit();break; /* Alt-U */
case 120 : channel_on[1] = channel_on[1] ^ 1; break;
case 121 : channel_on[2] = channel_on[2] ^ 1; break;
case 122 : channel_on[3] = channel_on[3] ^ 1; break;
case 123 : channel_on[4] = channel_on[4] ^ 1; break;
case 124 : channel_on[5] = channel_on[5] ^ 1; break;
case 125 : channel_on[6] = channel_on[6] ^ 1; break;
case 126 : channel_on[7] = channel_on[7] ^ 1; break;
case 127 : channel_on[8] = channel_on[8] ^ 1; break;
case 128 : channel_on[9] = channel_on[9] ^ 1; break;
case 129 : channel_on[0] = channel_on[0] ^ 1; break;
case 30 : channel_on[10] = channel_on[10] ^ 1; break;
case 48 : channel_on[11] = channel_on[11] ^ 1; break;
case 46 : channel_on[12] = channel_on[12] ^ 1; break;
case 32 : channel_on[13] = channel_on[13] ^ 1; break;
case 18 : channel_on[14] = channel_on[14] ^ 1; break;
case 33 : channel_on[15] = channel_on[15] ^ 1; break;
}
draw_screen();
}
else
{
switch(scan){
case 25 : goto_playmode(); break;
case 1 : quit();
}
}
}
unsigned char old_key,old_release;
process_playkey()
{
unsigned char key;
key=get_mkbrk_code();
if(key != old_key)
{
if(key >= KeyUp)
{
if((key-0x80) == old_key)
{
stop_note();
old_key = key;
}
}
else
{
if(old_key < KeyUp)
stop_note();
switch(key) {
case 44 : playnote(0);break; /* z */
case 31 : playnote(1);break; /* s */
case 45 : playnote(2);break; /* x */
case 32 : playnote(3);break; /* d */
case 46 : playnote(4);break; /* c */
case 47 : playnote(5);break; /* v */
case 34 : playnote(6);break; /* g */
case 48 : playnote(7);break; /* b */
case 35 : playnote(8);break; /* h */
case 49 : playnote(9);break; /* n */
case 36 : playnote(10);break; /* j */
case 50 : playnote(11);break; /* m */
case 51 : playnote(12);break; /* , */
case 16 : playnote(12);break; /* q */
case 3 : playnote(13);break; /* 2 */
case 17 : playnote(14);break; /* w */
case 4 : playnote(15);break; /* 3 */
case 18 : playnote(16);break; /* e */
case 19 : playnote(17);break; /* f */
case 6 : playnote(18);break; /* 5 */
case 20 : playnote(19);break; /* t */
case 7 : playnote(20);break; /* 6 */
case 21 : playnote(21);break; /* y */
case 8 : playnote(22);break; /* 7 */
case 22 : playnote(23);break; /* u */
case 23 : playnote(24);break; /* i */
case 78 : if(octave < 7) octave++; break;
case 74 : if(octave > 2) octave--; break;
case 73 : change_program(key,0); break;
case 81 : change_program(key,0);break; /* PgDwn */
case 1 : exit_playmode();
}
old_key = key;
}
}
}
goto_playmode()
{
init_mkbrk();
playmode = 1;
gotoxy(1,22);
printf("Keyboard Play mode");
}
exit_playmode()
{
while(get_mkbrk_code() != 0x81);
exit_mkbrk();
playmode = 0;
gotoxy(1,22);
printf(" ");
}
loadpatch()
{
FILE* f;
char patchname[80],patchnumstr[10];
clrscr();
showcur();
printf("Name of single patch to load: ");
gets(patchname);
if (strlen(patchname) != 0)
{
printf("Patch number to load patch into (0-127): ");
gets(patchnumstr);
if(f=fopen(patchname,"rb"))
{
fread(&InstrBuf[atoi(patchnumstr)][0],16,1,f);
fclose(f);
sbfd_program_change(0,atoi(patchnumstr));
}
else
{
printf("Couldn't find %s!\n",patchname);
delay(1000);
}
}
if(editmode)
draw_editscreen();
else
draw_screen();
}
loadpatches()
{
char patchsetname[80];
clrscr();
showcur();
printf("Name of patch set to load: ");
gets(patchsetname);
loadpatches2(patchsetname);
if(editmode)
draw_editscreen();
else
draw_screen();
}
loadpatches2(char *patchfile)
{
FILE* f;
int i;
if(f = fopen(patchfile,"rb"))
{
for(i=0;i<128;i++) /* read instruments */
fread(&InstrBuf[i][0],1,16,f);
fclose(f);
}
else
{
printf("Couldn't find %s!\n",patchfile);
delay(1000);
}
}
savepatches()
{
FILE* f;
int i;
char patchsetname[80];
clrscr();
showcur();
printf("Save patch set as: ");
gets(patchsetname);
f = fopen(patchsetname,"wb");
for(i=0;i<128;i++)
fwrite(&InstrBuf[i][0],1,16,f);
fclose(f);
if(editmode)
draw_editscreen();
else
draw_screen();
}
listfiles()
{
struct ffblk ffblk;
int done;
clrscr();
system("dir /w /p /on");
printf("\nPress any key to return to FMMOD...\n");
getch();
if(editmode)
draw_editscreen();
else
draw_screen();
}
fmplay(unsigned char channel, unsigned char note, unsigned char velocity)
{
if(velocity != 0)
sbfd_note_on(channel,note,velocity);
else
sbfd_note_off(channel,note,velocity);
}
setveloc()
{
char velocstr[10];
showcur();
gotoxy(1,22);
printf("\nSet velocity (0-127): ");
gets(velocstr);
velocity = atoi(velocstr);
hidecur();
}
all_notes_off()
{
sbfd_music_off();
}
playnote(unsigned char offs)
{
unsigned char note;
note = (octave*12)+offs;
if(out_runstatus != 0x90)
{
out_runstatus = 0x90;
sbmidi_put(0x90); /* Note On channel 1 */
}
sbmidi_put(note);
sbmidi_put(velocity);
old_note = note;
}
stop_note()
{
if(out_runstatus != 0x90)
{
out_runstatus = 0x90;
sbmidi_put(0x90);
}
sbmidi_put(old_note);
sbmidi_put(0);
}
change_program(int scan,int button)
{
if(! button)
{
switch(scan){
case 73 : {
if(program < 127)
program++;
}break;
case 81 : {
if(program > 0)
program--;
}break;
}
gotoxy(65,1);printf("%-3u",program);
gotoxy(65,1);
}
else
{
/*
switch(button){
case 1 : chg_while_pressed(1,0,&program,65,1,"%-3u"); break;
case 2 : chg_while_pressed(2,127,&program,65,1,"%-3u");
}
*/
}
if(out_runstatus != ProgramChange1)
{
out_runstatus = ProgramChange1;
sbmidi_put(ProgramChange1);
}
sbmidi_put(program);
}
sysex_rcv()
{
unsigned char param,val;
int i,j,offs;
long midiin;
unsigned int size,segp;
unsigned char sysdata[6700],sysexbyte;
offs=0;
while(1)
{
if(midiin=sbmidi_get())
{
sysexbyte=(unsigned char)midiin;
sysdata[offs++]=sysexbyte;
}
if(sysexbyte == EOX) break;
}
offs=0;
gotoxy(1,22);
if(sysdata[offs++] == SbProID) /* Check for SBPro ID */
{
switch(sysdata[offs++]){ /* get mode */
case 0 : /* All patches */
{
for(i=0;i<128;i++)
{
for(j=0;j<26;j++)
{
param=sysdata[offs++];
val=sysdata[offs++];
setFMparam(i,param,val);
}
}
} break;
case 1 : /* single patch */
{
for(i=0;i<26;i++)
{
param=sysdata[offs++];
val=sysdata[offs++];
setFMparam(program,param,val);
}
sbfd_program_change(0,0);
} break;
case 2 : /* Single parameter */
{
param=sysdata[offs++];
val=sysdata[offs++];
setFMparam(program,param,val);
sbfd_program_change(0,0);
}
}
if(sysdata[offs] != EOX){
printf("\nError on SysEx receive!\n");
delay(1000);
draw_screen();
}
}
else
{
printf("\nError: not SbPro ID!\n");
delay(1000);
draw_screen();
}
}
sysex_xmit()
{
int scan,i,j;
char patchstr[20];
int patch;
clrscr();
showcur();
printf("Dump All or Single patch? (A/S)");
do
scan=(bioskey(0) >> 8) & 0xff;
while( (scan != 30) && (scan != 31) );
sbmidi_put(SysEx);
sbmidi_put(SbProID); /* SbPro ID */
switch(scan){
case 30 : /* All */
{
sbmidi_put(0);
for(i=0;i<128;i++)
for(j=0;j<26;j++)
{
sbmidi_put(j);
sbmidi_put(out_cnvrt(i,j));
}
}break;
case 31 : /* Single patch */
{
printf("\nSelect patch to dump (0-127): ");
gets(patchstr);
patch = atoi(patchstr);
sbmidi_put(1);
for(i=0;i<26;i++)
{
sbmidi_put(i);
sbmidi_put(out_cnvrt(patch,i));
}
}
}
sbmidi_put(EOX);
printf("\n\nTransmission completed.\n");
delay(1000);
draw_screen();
}
unsigned char out_cnvrt(int i,int param)
{
unsigned char temp,outval;
switch(param){
case 0 : outval = (InstrBuf[i][0] & 128) >> 7; break;
case 1 : outval = (InstrBuf[i][0] & 64) >> 6; break;
case 2 : outval = (InstrBuf[i][0] & 32) >> 5; break;
case 3 : outval = (InstrBuf[i][0] & 16) >> 4; break;
case 4 : outval = InstrBuf[i][0] & 0x0F; break;
case 5 : outval = (InstrBuf[i][1] & 128) >> 7; break;
case 6 : outval = (InstrBuf[i][1] & 64) >> 6; break;
case 7 : outval = (InstrBuf[i][1] & 32) >> 5; break;
case 8 : outval = (InstrBuf[i][1] & 16) >> 4; break;
case 9 : outval = InstrBuf[i][1] & 0x0F; break;
case 10 : {
temp = InstrBuf[i][2] & 0xC0;
switch(temp){
case 0 : temp = 0;break;
case 0x80 : temp = 1;break;
case 0x40 : temp = 2;break;
case 0xC0 : temp = 3;
}
outval = temp;
} break;
case 11 : outval = InstrBuf[i][2] & 0x3F; break;
case 12 : {
temp = InstrBuf[i][3] & 0xC0;
switch(temp){
case 0 : temp = 0;break;
case 0x80 : temp = 1;break;
case 0x40 : temp = 2;break;
case 0xC0 : temp = 3;
}
outval = temp;
}break;
case 13 : outval = InstrBuf[i][3] & 0x3F; break;
case 14 : outval = (InstrBuf[i][4] & 0xF0) >> 4; break;
case 15 : outval = (InstrBuf[i][4] & 0x0F); break;
case 16 : outval = (InstrBuf[i][5] & 0xF0) >> 4; break;
case 17 : outval = (InstrBuf[i][5] & 0x0F); break;
case 18 : outval = (InstrBuf[i][6] & 0xF0) >> 4; break;
case 19 : outval = InstrBuf[edpatch][6] & 0x0F; break;
case 20 : outval = (InstrBuf[i][7] & 0xF0) >> 4; break;
case 21 : outval = InstrBuf[edpatch][7] & 0x0F; break;
case 22 : outval = InstrBuf[i][8]; break;
case 23 : outval = InstrBuf[i][9]; break;
case 24 : outval = (InstrBuf[i][10] & 0xE) >> 1; break;
case 25 : outval = InstrBuf[i][10] & 1; break;
}
return(outval);
}
/*
chg_while_pressed(int button,unsigned char limit,unsigned char *chgvar,int x,int y,char *format)
{
if(button == 1)
{
if((*chgvar) > limit)
(*chgvar)--;
gotoxy(x,y);printf(format,*chgvar);
gotoxy(x,y);
delay(250);
while(get_button_status() == button)
{
if((*chgvar) > limit)
{
(*chgvar)--;
gotoxy(x,y);printf(format,*chgvar);
gotoxy(x,y);
delay(35);
}
}
}
else
{
if((*chgvar) < limit)
(*chgvar)++;
gotoxy(x,y);printf(format,*chgvar);
gotoxy(x,y);
delay(250);
while(get_button_status() == button)
{
if((*chgvar) < limit)
{
(*chgvar)++;
gotoxy(x,y);printf(format,*chgvar);
gotoxy(x,y);
delay(35);
}
}
}
}
*/
/*********************************************************************/
/************************* FM editor functions ********************/
/*********************************************************************/
unsigned char undo_buf[16],compare_buf[16];
int compare;
void ReadVal(int *v, int llim, int ulim, int len, int x, int y)
{
char str[80];
str[0] = len+1;
do{
while (! kbhit());
if((bioskey(1) & 0xFF) == 13) break;
gotoxy(x,y); printf(" ");
gotoxy(x,y);
*v = atoi(gets(str));
gotoxy(x,y); printf(" ");
gotoxy(x,y);
} while((*v < llim) || (*v > ulim));
}
Edit_Play()
{
unsigned char key;
init_mkbrk();
gotoxy(65,1); printf("PLAY MODE ");
do
{
key=get_mkbrk_code();
if(key != old_key)
{
if(key >= KeyUp)
{
if((key-0x80) == old_key)
{
edit_stopnote();
old_key = key;
}
}
else
{
if(old_key < KeyUp)
edit_stopnote();
switch(key) {
case 44 : edit_playnote(0);break; /* z */
case 31 : edit_playnote(1);break; /* s */
case 45 : edit_playnote(2);break; /* x */
case 32 : edit_playnote(3);break; /* d */
case 46 : edit_playnote(4);break; /* c */
case 47 : edit_playnote(5);break; /* v */
case 34 : edit_playnote(6);break; /* g */
case 48 : edit_playnote(7);break; /* b */
case 35 : edit_playnote(8);break; /* h */
case 49 : edit_playnote(9);break; /* n */
case 36 : edit_playnote(10);break; /* j */
case 50 : edit_playnote(11);break; /* m */
case 51 : edit_playnote(12);break; /* , */
case 16 : edit_playnote(12);break; /* q */
case 3 : edit_playnote(13);break; /* 2 */
case 17 : edit_playnote(14);break; /* w */
case 4 : edit_playnote(15);break; /* 3 */
case 18 : edit_playnote(16);break; /* e */
case 19 : edit_playnote(17);break; /* f */
case 6 : edit_playnote(18);break; /* 5 */
case 20 : edit_playnote(19);break; /* t */
case 7 : edit_playnote(20);break; /* 6 */
case 21 : edit_playnote(21);break; /* y */
case 8 : edit_playnote(22);break; /* 7 */
case 22 : edit_playnote(23);break; /* u */
case 23 : edit_playnote(24);break; /* i */
case 78 : if(octave < 7) octave++; break;
case 74 : if(octave > 2) octave--; break;
}
old_key = key;
}
}
} while( key != 1 );
while(get_mkbrk_code() != 0x81);
exit_mkbrk();
sbfd_note_off(0,old_note,0);
gotoxy(65,1);printf(" ");
}
edit_playnote(int offs)
{
unsigned char note;
note = (octave*12)+offs;
sbfd_note_on(0,note,127);
old_note = note;
}
edit_stopnote()
{
sbfd_note_off(0,old_note,0);
}
void modop_msg(int x, int y)
{
int k;
k = 0;
gotoxy(x,y); printf("1: Modulator 2: Carrier: ");
ReadVal(&k,1,2,1,x+25,y);
gotoxy(x,y); printf(" ");
opr = (char)k;
}
void AM()
{
int k;
showcur();
modop_msg(25,6);
k = 0;
gotoxy(25,6); printf("(1) On (0) Off: ");
printf("%d",(InstrBuf[edpatch][opr-1] & 128) >> 7);
ReadVal(&k,0,1,1,41,6);
gotoxy(25,6); printf(" ");
switch(opr){
case 1: setFMparam(edpatch,0,k);break;
case 2: setFMparam(edpatch,5,k);
}
sbfd_program_change(0,edpatch);
}
void Vib()
{
int k;
showcur();
modop_msg(25,7);
k = 0;
gotoxy(25,7); printf("(1) On (0) Off: ");
printf("%d",(InstrBuf[edpatch][opr-1] & 64) >> 6);
ReadVal(&k,0,1,1,41,7);
gotoxy(25,7); printf(" ");
switch(opr){
case 1: setFMparam(edpatch,1,k); break;
case 2: setFMparam(edpatch,6,k);
}
sbfd_program_change(0,edpatch);
}
void EG()
{
int k;
showcur();
modop_msg(25,8);
k = 0;
gotoxy(25,8); printf("(1) Continuing (0) Diminishing: ");
printf("%d",(InstrBuf[edpatch][opr-1] & 32) >> 5);
ReadVal(&k,0,1,1,57,8);
gotoxy(25,8); printf(" ");
switch(opr){
case 1: setFMparam(edpatch,2,k); break;
case 2: setFMparam(edpatch,7,k);
}
sbfd_program_change(0,edpatch);
}
void KSR()
{
int k;
showcur();
modop_msg(25,9);
k = 0;
gotoxy(25,9); printf("(1) On (0) Off: ");
printf("%d",(InstrBuf[edpatch][opr-1] & 16) >> 4);
ReadVal(&k,0,1,1,41,9);
gotoxy(25,9); printf(" ");
switch(opr){
case 1: setFMparam(edpatch,3,k); break;
case 2: setFMparam(edpatch,8,k);
}
sbfd_program_change(0,edpatch);
}
void Multiple()
{
int val;
showcur();
modop_msg(25,10);
showcur();
gotoxy(25,10); printf("Multiple (0-15): ");
printf("%d",InstrBuf[edpatch][opr-1] & 0x0F);
ReadVal(&val,0,15,2,42,10);
gotoxy(25,10); printf(" ");
switch(opr){
case 1 : setFMparam(edpatch,4,val); break;
case 2 : setFMparam(edpatch,9,val);
}
sbfd_program_change(0,edpatch);
}
void KSL()
{
int val;
int temp;
showcur();
modop_msg(25,11);
showcur();
gotoxy(25,11); printf("KSL value (0-3): ");
temp = InstrBuf[edpatch][2+(opr-1)] & 0xC0;
switch(temp){
case 0 : printf("%d",0);break;
case 0x80 : printf("%d",1);break;
case 0x40 : printf("%d",2);break;
case 0xC0 : printf("%d",3);
}
ReadVal(&val,0,3,1,42,11);
gotoxy(25,11); printf(" ");
switch(opr){
case 1: setFMparam(edpatch,10,val); break;
case 2: setFMparam(edpatch,12,val);
}
sbfd_program_change(0,edpatch);
}
void TotLev()
{
int val;
showcur();
modop_msg(25,12);
showcur();
gotoxy(25,12); printf("Total Level (0-63): ");
printf("%d", InstrBuf[edpatch][2+(opr-1)] & 0x3F);
ReadVal(&val,0,63,2,45,12);
gotoxy(25,12); printf(" ");
switch(opr){
case 1 : setFMparam(edpatch,11,val); break;
case 2 : setFMparam(edpatch,13,val);
}
sbfd_program_change(0,edpatch);
}
void Attack()
{
int val;
showcur();
modop_msg(25,13);
showcur();
gotoxy(25,13); printf("Attack (0-15): ");
printf("%d",(InstrBuf[edpatch][4+(opr-1)] & 0xF0) >> 4);
ReadVal(&val,0,15,2,40,13);
gotoxy(25,13); printf(" ");
switch(opr){
case 1 : setFMparam(edpatch,14,val); break;
case 2 : setFMparam(edpatch,16,val);
}
sbfd_program_change(0,edpatch);
}
void Decay()
{
int val;
showcur();
modop_msg(25,14);
showcur();
gotoxy(25,14); printf("Decay (0-15): ");
printf("%d", InstrBuf[edpatch][4+(opr-1)] & 0x0F);
ReadVal(&val,0,15,2,39,14);
gotoxy(25,14); printf(" ");
switch(opr){
case 1 : setFMparam(edpatch,15,val); break;
case 2 : setFMparam(edpatch,17,val);
}
sbfd_program_change(0,edpatch);
}
void Sustain()
{
int val;
showcur();
modop_msg(25,15);
showcur();
gotoxy(25,15); printf("Sustain Level (0-15): ");
printf("%d",(InstrBuf[edpatch][6+(opr-1)] & 0xF0) >> 4);
ReadVal(&val,0,15,2,47,15);
gotoxy(25,15); printf(" ");
switch(opr){
case 1 : setFMparam(edpatch,18,val); break;
case 2 : setFMparam(edpatch,20,val);
}
sbfd_program_change(0,edpatch);
}
void Release()
{
int val;
showcur();
modop_msg(25,16);
showcur();
gotoxy(25,16); printf("Release (0-15): ");
printf("%d", InstrBuf[edpatch][6+(opr-1)] & 0x0F);
ReadVal(&val,0,15,2,41,16);
gotoxy(25,16); printf(" ");
switch(opr){
case 1: setFMparam(edpatch,19,val); break;
case 2: setFMparam(edpatch,21,val);
}
sbfd_program_change(0,edpatch);
}
void Wave()
{
int val;
showcur();
modop_msg(25,17);
val = 0;
gotoxy(25,17); printf("Wave (0-4): ");
printf("%d", InstrBuf[edpatch][8+(opr-1)]);
ReadVal(&val,0,4,1,37,17);
gotoxy(25,17); printf(" ");
switch(opr){
case 1 : setFMparam(edpatch,22,val);break;
case 2 : setFMparam(edpatch,23,val);
}
sbfd_program_change(0,edpatch);
}
void Feedback()
{
int val;
val = 0;
showcur();
gotoxy(25,18); printf("Feedback (0-7): ");
printf("%d",(InstrBuf[edpatch][10] & 0xE) >> 1);
ReadVal(&val,0,7,1,41,18);
gotoxy(25,18); printf(" ");
setFMparam(edpatch,24,val);
sbfd_program_change(0,edpatch);
}
void Connection()
{
int val;
showcur();
val = 0;
gotoxy(25,19); printf("Connection (0,1): ");
printf("%d",InstrBuf[edpatch][10] & 1);
ReadVal(&val,0,1,1,43,19);
gotoxy(25,19); printf(" ");
setFMparam(edpatch,25,val);
sbfd_program_change(0,edpatch);
}
void savepatch()
{
FILE* f;
char scr_buf[4096];
char patchname[80];
int i,j;
gettext(1,1,80,25,scr_buf);
clrscr();
showcur();
printf("Patch file to save to: ");
gets(patchname);
if (f = fopen(patchname,"wb"))
{
fwrite(&InstrBuf[edpatch][0],1,16,f);
fclose(f);
}
else
{
printf("\nError opening file");
delay(2000);
}
puttext(1,1,80,25,scr_buf);
}
Select_Patch()
{
char str[20];
clrscr();
showcur();
printf("Patch to edit (0-127): ");
gets(str);
edpatch = atoi(str);
compare=0;
sbfd_program_change(0,edpatch);
save_undo_settings(edpatch);
draw_editscreen();
}
draw_editscreen()
{
hidecur();
clrscr();
printf("Patch currently selected: %d\n\n",edpatch);
printf("Parameters\n");
printf("----------\n\n");
printf("1: AM On/Off\n");
printf("2: Vib On/Off\n");
printf("3: EG\n");
printf("4: KSR\n");
printf("5: Multiple\n");
printf("6: KSL\n");
printf("7: Total Level\n");
printf("8: Attack\n");
printf("9: Decay\n");
printf("A: Sustain\n");
printf("B: Release\n");
printf("C: Wave\n");
printf("D: Feedback Alt-F: List Files\n");
printf("E: Connection L: Load Patch Set\n");
printf("N: Select Patch to edit S: Save Patch Set\n");
printf("P: Play Keyboard Alt-L: Load Patch\n");
printf("U: Undo changes to patch Alt-S: Save Patch\n");
printf("X: Compare\n");
}
fm_edit()
{
int k,mod;
editmode = 1;
compare=0;
sbfd_program_change(0,edpatch);
save_undo_settings();
textcolor(GREEN);
draw_editscreen();
while((k & 0xff) != 27)
{
hidecur();
while(! bioskey(1));
mod = bioskey(2);
k = bioskey(0);
switch((k >> 8) & 0xFF)
{
case 0x02: AM(); break;
case 0x03: Vib(); break;
case 0x04: EG(); break;
case 0x05: KSR(); break;
case 0x06: Multiple(); break;
case 0x07: KSL(); break;
case 0x08: TotLev(); break;
case 0x09: Attack(); break;
case 0x0A: Decay(); break;
case 0x1E: Sustain(); break;
case 0x30: Release(); break;
case 0x2e: Wave(); break;
case 0x20: Feedback(); break;
case 0x12: Connection(); break;
case 0x21: if(mod & 8)
listfiles();
break;
case 0x26: if(mod & 8)
loadpatch();
else loadpatches();
break;
case 0x1F: if(mod & 8)
savepatch();
else savepatches();
break;
case 0x31: Select_Patch(); break;
case 0x19: Edit_Play(); break;
case 0x16: Undo(); break;
case 0x2d: Compare(); break;
}
}
showcur();
editmode = 0;
textcolor(LIGHTGRAY);
draw_screen();
}
save_undo_settings()
{
int i;
for(i=0;i<16;i++)
undo_buf[i] = InstrBuf[edpatch][i];
}
Compare()
{
int i;
compare = compare ^ 1;
if(compare)
{
for(i=0;i<16;i++)
compare_buf[i]=InstrBuf[edpatch][i];
for(i=0;i<16;i++)
InstrBuf[edpatch][i]=undo_buf[i];
gotoxy(46,3);printf("Compare, now original patch");
}
else
{
for(i=0;i<16;i++)
InstrBuf[edpatch][i]=compare_buf[i];
gotoxy(46,3);printf(" ");
}
sbfd_program_change(0,edpatch);
}
Undo()
{
int i;
for(i=0;i<16;i++)
InstrBuf[edpatch][i] = undo_buf[i];
sbfd_program_change(0,edpatch);
}
setFMparam(int edpatch,int param,int val)
{
switch(param){
case 0 : /* AM Modulator */
{
switch(val){
case 1: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] | 0x80; break;
case 0: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] & 0x7F;
}
}break;
case 1 : /* VIB Modulator */
{
switch(val){
case 1: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] | 0x40; break;
case 0: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] & 0xBF;
}
}break;
case 2 : /* EG modulator */
{
switch(val){
case 1: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] | 0x20; break;
case 0: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] & 0xDF;
}
}break;
case 3 : /* KSR modulator */
{
switch(val){
case 1: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] | 0x10; break;
case 0: InstrBuf[edpatch][0] = InstrBuf[edpatch][0] & 0xEF;
}
} break;
case 4 : /* Multiple modulator */
{
InstrBuf[edpatch][0] = InstrBuf[edpatch][0] & 0xF0;
InstrBuf[edpatch][0] = InstrBuf[edpatch][0] | val;
} break;
case 5 : /* AM Carrier */
{
switch(val){
case 1: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] | 0x80; break;
case 0: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] & 0x7F;
}
} break;
case 6 : /* VIB Carrier */
{
switch(val){
case 1: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] | 0x40; break;
case 0: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] & 0xBF;
}
} break;
case 7 : /* EG Carrier */
{
switch(val){
case 1: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] | 0x20; break;
case 0: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] & 0xDF;
}
} break;
case 8 : /* KSR Carrier */
{
switch(val){
case 1: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] | 0x10; break;
case 0: InstrBuf[edpatch][1] = InstrBuf[edpatch][1] & 0xEF;
}
} break;
case 9 : /* Multiple Carrier */
{
InstrBuf[edpatch][1] = InstrBuf[edpatch][1] & 0xF0;
InstrBuf[edpatch][1] = InstrBuf[edpatch][1] | val;
} break;
case 10 : /* KSL Modulator */
{
switch(val){
case 0: val = 0; break;
case 1: val = 0x80; break;
case 2: val = 0x40; break;
case 3: val = 0xC0; break;
}
InstrBuf[edpatch][2] = InstrBuf[edpatch][2] & 0x3F;
InstrBuf[edpatch][2] = InstrBuf[edpatch][2] | val;
} break;
case 11 : /* TL Modulator */
{
InstrBuf[edpatch][2] = InstrBuf[edpatch][2] & 0xC0;
InstrBuf[edpatch][2] = InstrBuf[edpatch][2] | val;
} break;
case 12 : /* KSL Carrier */
{
switch(val){
case 0: val = 0; break;
case 1: val = 0x80; break;
case 2: val = 0x40; break;
case 3: val = 0xC0; break;
}
InstrBuf[edpatch][3] = InstrBuf[edpatch][3] & 0x3F;
InstrBuf[edpatch][3] = InstrBuf[edpatch][3] | val;
} break;
case 13 : /* TL Carrier */
{
InstrBuf[edpatch][3] = InstrBuf[edpatch][3] & 0xC0;
InstrBuf[edpatch][3] = InstrBuf[edpatch][3] | val;
} break;
case 14 : /* Attack Modulator */
{
InstrBuf[edpatch][4] = InstrBuf[edpatch][4] & 0x0F;
InstrBuf[edpatch][4] = InstrBuf[edpatch][4] | (val << 4);
} break;
case 15 : /* Decay Modulator */
{
InstrBuf[edpatch][4] = InstrBuf[edpatch][4] & 0xF0;
InstrBuf[edpatch][4] = InstrBuf[edpatch][4] | val;
} break;
case 16 : /* Attack Carrier */
{
InstrBuf[edpatch][5] = InstrBuf[edpatch][5] & 0x0F;
InstrBuf[edpatch][5] = InstrBuf[edpatch][5] | (val << 4);
} break;
case 17 : /* Decay Carrier */
{
InstrBuf[edpatch][5] = InstrBuf[edpatch][5] & 0xF0;
InstrBuf[edpatch][5] = InstrBuf[edpatch][5] | val;
} break;
case 18 : /* Sustain Level Modulator */
{
InstrBuf[edpatch][6] = InstrBuf[edpatch][6] & 0x0F;
InstrBuf[edpatch][6] = InstrBuf[edpatch][6] | (val << 4);
} break;
case 19 : /* Release rate Modulator */
{
InstrBuf[edpatch][6] = InstrBuf[edpatch][6] & 0xF0;
InstrBuf[edpatch][6] = InstrBuf[edpatch][6] | val;
} break;
case 20 : /* Sustain Level Carrier */
{
InstrBuf[edpatch][7] = InstrBuf[edpatch][7] & 0x0F;
InstrBuf[edpatch][7] = InstrBuf[edpatch][7] | (val << 4);
} break;
case 21 : /* Release rate Carrier */
{
InstrBuf[edpatch][7] = InstrBuf[edpatch][7] & 0xF0;
InstrBuf[edpatch][7] = InstrBuf[edpatch][7] | val;
} break;
case 22 : /* Wave Select Modulator */
{
InstrBuf[edpatch][8] = val;
} break;
case 23 : /* Wave Select Carrier */
{
InstrBuf[edpatch][9] = val;
} break;
case 24 : /* Feedback */
{
InstrBuf[edpatch][10] = InstrBuf[edpatch][10] & 0xF1;
InstrBuf[edpatch][10] = InstrBuf[edpatch][10] | ( ((char)val) << 1);
} break;
case 25 : /* Connection */
{
InstrBuf[edpatch][10] = InstrBuf[edpatch][10] & 0xFE;
InstrBuf[edpatch][10] = InstrBuf[edpatch][10] | val;
} break;
}
}