/* dxput.c -- program to send Yamaha exclusive messages from file */ /***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 13-Jun-86 | Created Change Log * 6-Aug-86 | Adapted to Lattice C V3.00 *****************************************************************************/ #include "cext.h" #include "stdio.h" #include "midicode.h" #include "mpu.h" #include "userio.h" #include "cmdline.h" #define buffsize 17000 byte midibuff[buffsize]; extern int miditrace; int xflag; /* for debugging */ int debptr; /**************************************************************************** * Data for command line parsing ****************************************************************************/ #define nswitches 8 private char *switches[nswitches] = { "-help", "-miditrace", "-m", "-trace", "-t", "-block", "-d", "-debug" }; #define noptions 1 private char *options[noptions] = { "-tune" }; /***************************************************************************** * Routines local to this module *****************************************************************************/ private void instruct(); private boolean isdangerous(); private boolean output(); private boolean readbuff(); /**************************************************************************** * instruct * Effect: prints instructions for this routine ****************************************************************************/ private void instruct() { printf("This program will let you send voice programs to a DX7 or TX816.\n"); printf("You must send a file previously created by the dxget program.\n"); printf("To send DX7 programs, you must connect\n"); printf(" MPU 401 MIDI OUT to DX7 MIDI IN.\n"); printf("For TX816 programs, connect MPU 401 MIDI OUT to TX816 MIDI IN.\n"); printf("For a DX7 voice: push the orange FUNCTION key, then the green 8.\n"); printf(" Push 8 repeatedly until the display says SYS INFO AVAIL\n"); printf(" or SYS INFO UNAVAIL. If the display says SYS INFO\n"); printf(" UNAVAIL, push YES to change to SYS INFO AVAIL.\n"); printf(" Next, push MEMORY PROTECT/INTERNAL, then NO, and then\n"); printf(" then MEMORY SELECT/INTERNAL. Now, type the name of a file\n"); printf(" created by dxget and then the space bar to send data.\n"); printf(" To store the voice program on the DX7, hold down STORE\n"); printf(" while you push a (green) number. The current voice at\n"); printf(" this number will be erased and replaced by the new voice.\n"); printf("For ALL DX7 voices: Same as for a single DX7 voice, but all 32\n"); printf(" voice programs on the DX7 will be replaced whey you type\n"); printf(" Y in response to `Are you sure?' on the computer.\n"); printf("For all TX816 voices: To store into one module, push NO until the\n"); printf(" MEMORY PROTECT light goes out. Make sure other MEMORY\n"); printf(" PROTECT lights are ON. Type Y in response to 'Are you\n"); printf(" sure?' on the computer.\n"); } /**************************************************************************** * isdangerous * Inputs: * byte *msg: pointer message to check * Outputs: * returns true if message can destroy lots of info (block data message) ****************************************************************************/ private boolean isdangerous(msg) byte *msg; { /* look for 32 voice and 64 performance data msgs */ return (msg[1] == 0x43 && (msg[3] == 2 || msg[3] == 9)); } /**************************************************************************** * main * Effect: main program -- prompt user for information and put data ****************************************************************************/ void main(argc, argv) int argc; char *argv[]; { FILE *fp; /* the input file */ int count; /* length of data in file */ byte *msg; /* message pointer */ int done = false; /* flag is true when user is done */ char filename[100]; /* the output file name */ char *s; /* the file name in the command line */ cl_init(switches, nswitches, options, noptions, argv, argc); if (cl_switch("-help")) instruct(); /* get input file name: */ filename[0] = NULL; /* empty string */ if ((s = cl_arg(1)) != NULL) strcpy(filename, s); while (!done) { if (askbool("Do you want instructions", true)) instruct(); fp = fileopen(filename, "dx7", "r", "file name"); if (!readbuff(fp, midibuff, &count)) { printf("Something is wrong with your data or you typed the\n"); printf("wrong file name. Please try again.\n"); exit(1); } printf("\nReady with your data. Type space when you are ready...\n"); while (true) { if (kbhit() && getch() == ' ') break; } musicinit(); exclusive(true); msg = midibuff; while (output(&msg, midibuff + count)) /* write messages */; musicterm(); fclose(fp); printf("DONE\n"); done = !askbool("Do you want to send another file", false); filename[0] = NULL; /* force prompt for new file name */ } } /**************************************************************************** * output * Inputs: * byte **msg: pointer to message to send * byte *msg_tail: pointer to byte after last message byte * Outputs: * *msg is set to byte after last byte of the message sent * returns true if there is more data to send * Effect: sends exclusive messages using recorded data * Assumes: msg_tail > *msg * Implementation: ****************************************************************************/ private boolean output(msg, msg_tail) byte **msg; byte *msg_tail; { byte *this_msg = *msg; int datalen; int cksum; int n; /* counts bytes printed on one line */ int OK; /* OK to send message */ /* printf("*msg %x, this_msg %x, msg_tail %x\n", *msg, this_msg, msg_tail); printf("%d bytes to go.\n", msg_tail - this_msg); */ excldesc(this_msg); this_msg = *msg; datalen = (this_msg[4] << 7) + this_msg[5]; /* printf("datalen %x\n", datalen);*/ cksum = 0; for (n = 6; n < datalen+6; n++) { cksum = (cksum + this_msg[n]) & 0x7f; } if (datalen == 0 || (cksum + this_msg[datalen+6]) & 0x7f != 0) { printf("Data in your file is garbled.\n"); return false; } if (isdangerous(this_msg)) { OK = askbool("Are you sure", false); } else OK = true; if (OK) midi_exclusive(this_msg); do { /* always skip first byte, */ /* then terminate after finding MIDI_EOX */ this_msg++; } while (this_msg < msg_tail && *(this_msg-1) != MIDI_EOX) ; *msg = this_msg; return this_msg < msg_tail; } /**************************************************************************** * readbuff * Inputs: * FILE *fp: file from which to read * Outputs: * byte *buff: where to put the data * int *count: count is set to the number of of bytes read * Effect: * read midi exclusive data from a file into buff * Assumes: * fp is open for reading ****************************************************************************/ private boolean readbuff(fp, buff, count) FILE *fp; byte *buff; int *count; /* result */ { int i; *count = 0; while (fscanf(fp, "%x", &i) > 0) { *buff = i; buff++; (*count)++; } return *count != 0; }