/* (C) Copyright 1988 Jack Deckard Helicon Software */ /* */ /* SYS-EX Filer Program Load and Save SYS-EX dumps */ #include #include #include #include #include #include #include #include #include #include #include /* Standard ARP header file */ #include /* Predeclared functions */ extern struct NewWindow NewWindowStructure1; extern struct Menu Menu1; extern struct Gadget Gadget1; extern struct IntuiText IText1; extern struct MenuItem MenuItem1; extern struct MenuItem MenuItem2; extern struct MenuItem MenuItem3; extern struct MenuItem MenuItem4; extern struct MenuItem MenuItem5; extern struct Border Border3; #define VERSION 33L /* 1.2 Library Version */ #define OTHER 0 #define DX 1 #define FB 2 #define TX81Z 3 #define MATRX6 10 /* Define all global variables, pointers, structures, etc */ struct Window *window; struct IntuiMessage *message; void *MidiBase; UBYTE datasaved[] = " Data Saved "; UBYTE ioerror[] = "I/O ERROR File not saved "; UBYTE ioerror2[] = "I/O ERROR Can't Read File"; UBYTE ioerror3[] = "I/O ERROR Can't Open File"; UBYTE ioerror4[] = "I/O ERROR File Not Found "; UBYTE dataerror[] = "Data Error in SYS-EX File "; UBYTE loadaborted[] = " Load Aborted "; UBYTE saveaborted[] = " Save Aborted "; UBYTE yamtext[] = " File ID is Yamaha "; UBYTE seqtext[] = "File ID is Seq Circuits "; UBYTE mootext[] = " File ID is Moog "; UBYTE obetext[] = " File ID is Oberheim "; UBYTE emutext[] = " File ID is E-mu "; UBYTE roltext[] = " File ID is Roland "; UBYTE kortext[] = " File ID is Korg "; UBYTE castext[] = " File ID is Casio "; UBYTE unktext[] = " File ID is Unknown "; struct IntuiText Mess1 = { 1,0,JAM2, /* front and back text pens, drawmode and fill byte */ 36,35, /* XY origin relative to container TopLeft */ NULL, /* font pointer or NULL for default */ datasaved, /* pointer to text */ NULL /* next IntuiText structure */ }; struct IntuiText Mess2 = { 1,0,JAM2, /* front and back text pens, drawmode and fill byte */ 60,47, /* XY origin relative to container TopLeft */ NULL, /* font pointer or NULL for default */ (UBYTE *)"Transmit Complete", /* pointer to text */ NULL /* next IntuiText structure */ }; struct Image cleartext = { 0,0, 260,28,0, NULL, 0,0, NULL }; struct MDest *dest=0; struct MRoute *routei=0; struct MRouteInfo routeiinfo = { MMF_SYSEX }; /* receive only sys/ex msg's */ struct MSource *source=0; struct MRoute *routeo=0; struct MRouteInfo routeoinfo = { -1, -1 }; /* support all msg's */ char def_dir[96] = "MIDI_Tools:sysexfiles"; char def_name[32]; char pathname[128]; BYTE LFR[] = "Load SysEx File"; BYTE SFR[] = "Save SysEx File"; struct FileRequester FR = { LFR, def_name, def_dir, NULL, NULL, NULL, NULL, }; /************/ UBYTE fbreq[] = {0xf0,0x43,0x75,0x00,0x20,0x00,0x00,0xf7}; UBYTE dxreq[] = {0xf0,0x43,0x20,0x04,0xf7}; UBYTE m6req[] = {0xf0,0x10,0x06,0x04,0x01,0x00,0xf7}; UBYTE ttxv1[] = "Which Voice Bank (1 - 2)?"; UBYTE ttxv2[] = "Which Voice Bank (1 - 7)?"; UBYTE ttxv3[] = " Which Voice (0 - 99)?"; UBYTE ttxc1[] = "Which Config Bank (1-16)?"; UBYTE ttxs1[] = " Splits Number (0 - 49)?"; struct IntuiText Title = { 1,0,JAM2, /* front and back text pens, drawmode and fill byte */ 4,5, /* XY origin relative to container TopLeft */ NULL, /* font pointer or NULL for default */ ttxv1, /* pointer to text */ NULL /* next IntuiText structure */ }; UBYTE undo[4]; UBYTE SNum[4]; struct StringInfo RSfo = { SNum, undo, 0,3,0,0,0,0,0, NULL, 0, NULL }; struct Gadget RGadget = { NULL, /* next gadget */ 218,4, /* origin XY of hit box relative to window TopLeft */ 24,11, /* hit box width and height */ NULL, /* gadget flags */ RELVERIFY+LONGINT+ENDGADGET, /* activation flags */ STRGADGET+REQGADGET, /* gadget type flags */ (APTR)&Border3, /* gadget border or image to be rendered */ NULL, /* alternate imagery for selection */ NULL, /* first IntuiText structure */ NULL, /* gadget mutual-exclude long word */ (APTR)&RSfo, /* SpecialInfo structure */ 1, /* user-definable data */ NULL /* pointer to user-definable data */ }; SHORT BRV1[] = { 0,0, 258,0, 258,60, 0,60, 0,0 }; struct Border BRs1 = { -2,-1, /* XY origin relative to container TopLeft */ 1,0,JAM1, /* front pen, back pen and drawmode */ 5, /* number of XY vectors */ BRV1, /* pointer to XY vectors */ NULL /* next border in list */ }; struct Requester Rqstr1 = { NULL, 4,11,256,58, /* Left, Top, Width, Height */ 0,0, &RGadget, /* first gadget in gadget list */ &BRs1, /* Requester Border */ &Title, /* window title */ NULL, /* Flags */ 0, NULL, {NULL}, {NULL}, NULL, {NULL} }; /************************************************************************/ main() { SHORT GetReqNum(); SHORT savefile(); struct FileLock *lock; struct FileHandle *filehandle; /* Load voice file */ struct FileInfoBlock *fib; struct Gadget *igad; UBYTE *midimsg, *buffer; LONG len, gadgid; ULONG class; USHORT i, j, code, menunum, itemnum, subnum, checksum; SHORT keepgoing = 1, errorcheck = OTHER; char lastchar; register LONG error; register UBYTE id, sysexch; error = 1; sysexch = 15; /* Open libraries. If error, exit immediatly */ if(!(MidiBase = OpenLibrary (MIDINAME,MIDIVERSION))) goto clean; if(!(dest = CreateMDest (NULL,NULL))) goto clean; /* create our source node (private) */ if(!(source = CreateMSource (NULL,NULL))) goto clean; /* create our routes to MidiIn and MidiOut */ if(!(routei = MRouteDest ("MidiIn", dest, &routeiinfo))) goto clean; if(!(routeo = MRouteSource (source,"MidiOut",&routeoinfo))) goto clean; /* Initialize window struct, then call OpenWindow. Exit if error */ if((window = (struct Window *)OpenWindow(&NewWindowStructure1)) == NULL) goto clean; /* Initialize Menu items, then submit them to Intuition */ SetMenuStrip(window,&Menu1); /* Wait for message at IDCMP port */ while(keepgoing) { /* wait for window message or midi message */ Wait((1L<DestPort->mp_SigBit)|(1L<UserPort->mp_SigBit)); while((midimsg = GetMidiMsg(dest))!=NULL) { len = MidiMsgLength(midimsg); error = 0; if(len>5) { DrawImage(window->RPort,&cleartext,2L,28L); if(errorcheck) /* check file for errors if possible */ { checksum = 0; switch(errorcheck) { case DX: if(*(midimsg+3)==9) { error = 1; for (i = 6; i < 4102; ++i) checksum += *(midimsg+i); checksum = 127 & ((~checksum)+1); if (checksum == *(midimsg+4102)) error = 0; } else if(*(midimsg+3)==1) { error = 1; for (i = 6; i < 161; ++i) checksum += *(midimsg+i); checksum = 127 & ((~checksum)+1); if (checksum == *(midimsg+161)) error = 0; } break; case FB: if(*(midimsg+5)==0) /* check sum voice data to validate */ { for(i=0;i<48;i++) { buffer = i * 131 + 74; checksum = 0; for (j=2;j<128;++j) checksum += *(midimsg+buffer+j); if(*(midimsg+buffer+130) != (UBYTE)(127 & ((~checksum)+1))) { error = 1; i = 48; } } } else if((*(midimsg+5)==1)||(*(midimsg+5)==2)) /* check sum config data to validate */ { for(i=9;i<169;i++) checksum += *(midimsg+i); if(*(midimsg+169) != (UBYTE)(127&((~checksum)+1))) error = 1; } else if(*(midimsg+5)==3) /* check sum all configs */ { for(i=0;i<16;i++) { buffer = i*169+7; for(j=2;j<169;j++) checksum += *(midimsg+buffer+j); if(*(midimsg+buffer+169)!=(UBYTE)(127&((~checksum)+1))) error = 1; } } break; case TX81Z: if(*(midimsg+3)==4) { error = 1; for (i = 6; i < 4102; ++i) checksum += *(midimsg+i); checksum = 127 & ((~checksum)+1); if (checksum == *(midimsg+4102)) error = 0; } break; case MATRX6: error = 1; if(*(midimsg+3) == 1) { if(*(midimsg+274)==0xf7) error = 0; } else if(*(midimsg+3)==2) { for(i=5;i<39;i++); checksum +=*(midimsg+i); checksum = 127 & checksum; if(checksum == *(midimsg+39)) error = 0; } else if(*(midimsg+3)==3) { for(i=5;i<475;i++); checksum +=*(midimsg+i); checksum = 127 & checksum; if(checksum == *(midimsg+475)) error = 0; } break; } } if(error==0) { /* save voicedata to disk */ error = savefile(midimsg,len); FreeMidiMsg(midimsg); if(error == 1) { Mess1.IText = datasaved; PrintIText(window->RPort,&Mess1,0L,0L); } else if(error == 0) { Mess1.IText = ioerror; PrintIText(window->RPort,&Mess1,0L,0L); } else if(error == -1) { Mess1.IText = saveaborted; PrintIText(window->RPort,&Mess1,0L,0L); } } else { FreeMidiMsg(midimsg); Mess1.IText = dataerror; PrintIText(window->RPort,&Mess1,0L,0L); } } else FreeMidiMsg(midimsg); } while((message=(struct IntuiMessage *)GetMsg(window->UserPort))!=NULL) { class = message->Class; code = message->Code; igad = (struct Gadget *) message->IAddress; /* Ptr to a gadget */ ReplyMsg(message); DrawImage(window->RPort,&cleartext,2L,28L); switch(class) { case CLOSEWINDOW: /* User is ready to quit, so indicate that execution should terminate with next iteration of the loop. */ keepgoing = 0; break; case GADGETUP: gadgid = igad->GadgetID; /* Get GadgetID */ switch(gadgid) { case 0: sysexch = (++sysexch) & 15; sprintf(IText1.IText,"%2d",(SHORT)sysexch + 1); RefreshGList(&Gadget1,window,NULL,1L); break; } break; case MENUPICK: if(code!=MENUNULL) { menunum = MENUNUM(code); itemnum = ITEMNUM(code); subnum = SUBNUM(code); switch(menunum) { case 0: /* Amiga send SYSEX */ /* Load the file on disk into array voicefile */ FR.fr_Hail = LFR; if(FileRequest(&FR)) { /* copy path and file name to pathname */ strcpy(pathname,def_dir); if(strlen(pathname)) { lastchar = pathname[strlen(pathname)-1]; if((lastchar!='/')||(lastchar!=':')) strcpy(pathname+strlen(pathname),"/"); } strcpy(pathname+strlen(pathname),def_name); if(lock = (struct FileLock *)Lock(pathname,ACCESS_READ)) { fib=(struct FileInfoBlock *)AllocMem((LONG)sizeof(struct FileInfoBlock),MEMF_CLEAR); if(Examine(lock,fib)) { len = (LONG)fib->fib_Size; FreeMem(fib,(LONG)sizeof(struct FileInfoBlock)); buffer = (UBYTE *)AllocMem((LONG)len,0L); filehandle = (struct FileHandle *)Open(pathname,MODE_OLDFILE); if(filehandle) { if(Read(filehandle,buffer,(LONG)len) != -1) { Close(filehandle); UnLock(lock); if(*(buffer+1)==0x43) /* if yamaha file */ { if(*(buffer+2)==0x75) /* if FB-01 file, get bank number to load to */ { if(*(buffer+5)==0x00) /* Voice bank */ { Title.IText = ttxv1; *(buffer+6) = GetReqNum(); *(buffer+3) = sysexch; } else if((*(buffer+5)==0x01)||(*(buffer+5)==0x02)) /* Config Bank */ { *(buffer+5) = 0x02; Title.IText = ttxc1; *(buffer+6) = GetReqNum(); *(buffer+3) = sysexch; } } else *(buffer+2) = (*(buffer+2) & 0xf0)|sysexch; } else if(*(buffer+1)==0x10) /* Oberheim ID? */ { if(*(buffer+2)==0x06) /* Matrix 6? */ { if(*(buffer+3)==0x01) /* Single Voice? */ { *(buffer+4)=(UBYTE)GetReqNum(); } } } id = *(buffer+1); /* Print file ID */ switch(id) { case 0x01: Mess1.IText = seqtext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x04: Mess1.IText = mootext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x10: Mess1.IText = obetext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x18: Mess1.IText = emutext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x41: Mess1.IText = roltext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x42: Mess1.IText = kortext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x43: Mess1.IText = yamtext; PrintIText(window->RPort,&Mess1,0L,0L); break; case 0x44: Mess1.IText = castext; PrintIText(window->RPort,&Mess1,0L,0L); break; Default: Mess1.IText = unktext; PrintIText(window->RPort,&Mess1,0L,0L); break; } /* transmit file */ PutMidiMsg(source,buffer); FreeMem(buffer,len); PrintIText(window->RPort,&Mess1,0L,0L); PrintIText(window->RPort,&Mess2,0L,0L); } else /* Can't READ file */ { FreeMem(buffer,len); Close(filehandle); /* error */ UnLock(lock); Mess1.IText = ioerror2; PrintIText(window->RPort,&Mess1,0L,0L); } } else /* Can't Open file */ { FreeMem(buffer,len); UnLock(lock); Mess1.IText = ioerror3; PrintIText(window->RPort,&Mess1,0L,0L); } } else /* Can't Examine file */ { FreeMem(fib,(LONG)sizeof(struct FileInfoBlock)); UnLock(lock); } } else /* Can't Lock file */ { Mess1.IText = ioerror4; PrintIText(window->RPort,&Mess1,0L,0L); } } else { Mess1.IText = loadaborted; PrintIText(window->RPort,&Mess1,0L,0L); } break; case 1: /* Dump Request */ switch(itemnum) { case 0: /* TX */ errorcheck = DX; MenuItem1.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP+CHECKED; /* DX, TX */ MenuItem2.Flags = MenuItem3.Flags = MenuItem4.Flags = MenuItem5.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP; /* Other */ dxreq[2] = 0x20 | sysexch; dxreq[3] = 9; PutMidiMsg(source,dxreq); break; break; case 1: /* FB-01 */ errorcheck = FB; MenuItem2.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP+CHECKED; /* FB-01 */ MenuItem1.Flags = MenuItem3.Flags = MenuItem4.Flags = MenuItem5.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP; /* Other */ fbreq[3] = sysexch; switch(subnum) { case 0: /* Voice Bank X */ Title.IText = ttxv2; i = GetReqNum(); fbreq[5] = 0; fbreq[6] = i; PutMidiMsg(source,fbreq); break; case 1: /* Config Bank X */ Title.IText = ttxc1; i = GetReqNum(); fbreq[5] = 2; fbreq[6] = i; PutMidiMsg(source,fbreq); break; } break; case 2: /* DX27 DX100 */ errorcheck = DX; MenuItem1.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP+CHECKED; /* DX, TX */ MenuItem2.Flags = MenuItem3.Flags = MenuItem4.Flags = MenuItem5.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP; /* Other */ dxreq[2] = 0x20 | sysexch; dxreq[3] = 4; PutMidiMsg(source,dxreq); break; case 3: /* Matrix 6 */ errorcheck = MATRX6; MenuItem1.Flags = MenuItem2.Flags = MenuItem3.Flags = MenuItem5.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP; /* TX81Z */ MenuItem4.Flags = CHECKIT+ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP+CHECKED; /* Matrix 6 */ switch(subnum) { case 0: /* Voice file */ Title.IText = ttxv3; m6req[4] = 0x01; m6req[5] = (UBYTE)GetReqNum(); PutMidiMsg(source,m6req); break; case 1: /* Splits */ Title.IText = ttxs1; m6req[4] = 2; m6req[5] = (UBYTE)GetReqNum(); PutMidiMsg(source,m6req); break; case 2: m6req[4] = 3; PutMidiMsg(source,m6req); break; } break; } break; case 2: /* Error Checking and identification */ switch(itemnum) { case 0: /* DX type */ errorcheck = DX; break; case 1: /* FB type */ errorcheck = FB; break; case 2: /* TX81Z */ errorcheck = TX81Z; break; case 3: /* Oberheim Matrix 6 */ errorcheck = MATRX6; break; case 4: /* None */ errorcheck = OTHER; break; } break; } /* end of switch(menunum) */ } /* end of if(menunum not null) */ break; } /* end of switch (class) */ } /* end of while(intuimessage)*/ } /* end while (keepgoing) */ /* Time to quit, so clean up and exit. */ clean: if(window) { ClearMenuStrip(window); CloseWindow(window); } if(routei) DeleteMRoute(routei); if(routeo) DeleteMRoute(routeo); if(dest) DeleteMDest(dest); if(source) DeleteMSource(source); if(MidiBase) CloseLibrary(MidiBase); exit(); } /* end of main */ /************************************************************************/ /* Create a file on disk using buffered I/O. Open the disk file, */ /* write the array to it, and close the file. */ SHORT savefile(buffer,len) UBYTE *buffer; /* pointer to voice file */ long len; { struct FileHandle *filehandle; /* Save voice file */ char lastchar; FR.fr_Hail = SFR; if(FileRequest(&FR)) { strcpy(pathname,def_dir); if(strlen(pathname)) { lastchar = pathname[strlen(pathname)-1]; if((lastchar!='/')||(lastchar!=':')) strcpy(pathname+strlen(pathname),"/"); } strcpy(pathname+strlen(pathname),def_name); if(!(filehandle = Open(&pathname,MODE_NEWFILE))) return(0); if(Write(filehandle,buffer,len) == -1L) { Close(filehandle); /* error */ return(0); } Close(filehandle); return(1); } else return(-1); /* aborted save */ } SHORT GetReqNum() { SHORT returncode; LONG class; RGadget.LongInt = 0; RSfo.BufferPos = 0; RSfo.DispPos = 0; for(returncode=0;returncode<4;returncode++) SNum[returncode] = 0; Request(&Rqstr1,window); for(class = 0;class != REQSET;) { Wait(1L<UserPort->mp_SigBit); message=(struct IntuiMessage *)GetMsg(window->UserPort); class = message->Class; ReplyMsg(message); } ActivateGadget(&RGadget,window,&Rqstr1); for(;class!=GADGETUP;) { Wait(1L<UserPort->mp_SigBit); message=(struct IntuiMessage *)GetMsg(window->UserPort); class = message->Class; ReplyMsg(message); } returncode = RSfo.LongInt; return(returncode); }