/* (C) Copyright 1986 Jack Deckard Helicon Software */ /* */ /* DX7 Voice Librarian by Jack Deckard */ /* Simple program to send/recieve 32 voice data files */ /* from Yamaha DX synth and load/save them on disk. */ /* Special thanks to Michael Mounier, from who's ATERM */ /* program I learned to write C code. */ /* Use Aztec +l option (32 bit int) when compiling. */ #include #include #include #include #include #include #include #define VERSION 31L /* 1.1 Library Version */ /* Define all global variables, pointers, structures, etc */ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct MsgPort *MRport; struct MsgPort *MWport; struct MsgPort *CreatePort(); struct IORequest *CreateExtIO(); struct IOExtSer *IORser; /* Read serial request block */ struct IOExtSer *IOWser; /* Write serial request block */ struct Window *window; struct IntuiMessage *NewMessage; struct Menu menu[2]; struct MenuItem menuitem[6]; struct IntuiText menutext[6]; struct FileHandle *filehandle; /* Load and save voice files */ static char name[32]; /* Initialize NewWindow structure */ struct NewWindow newwindow = { 10, /* LeftEdge */ 20, /* TopEdge */ 300, /* Width */ 80, /* Height */ 0, /* DetailPen */ 1, /* BlockPen */ CLOSEWINDOW | MENUPICK | VANILLAKEY | ACTIVEWINDOW | INACTIVEWINDOW, /* IDCMPFlags */ WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH, /* Flags */ NULL, /* FirstGadget */ NULL, /* CheckMark */ (UBYTE *) "DX Voice Filer", /* Title */ NULL, /* Screen */ NULL, /* BitMap */ 300, /* MinWidth */ 80, /* MinHeight */ 300, /* MaxWidth */ 80, /* MaxHeight */ WBENCHSCREEN, /* Type */ }; SHORT linearray[] = { 0,20, 0,79, 299,79, 299,14 }; main() { VOID InitMenu(), ClearWindow(); LONG loadfile(), savefile(); LONG error; ULONG class; SHORT KeepGoing; static USHORT capture, chksum; USHORT i, code, menunum, itemnum; static UBYTE rs_in[2]; /* read data */ UBYTE c[2], voicedata[4104]; voicedata[0] = 0xf0; /* Status byte */ voicedata[1] = 0x43; /* ID (Yamaha) */ voicedata[2] = 0x00; /* Substatus & channel */ voicedata[3] = 0x09; /* Format # */ voicedata[4] = 0x20; /* MSB count */ voicedata[5] = 0x00; /* LSB count */ voicedata[6] = 0x00; /* 1st data byte */ voicedata[4101] = 0x00; /* 4096th data byte */ voicedata[4102] = 0x00; /* Check Sum */ voicedata[4103] = 0xf7; /* EOX */ /* * * * * * * * * */ /* Open Intuition and Graphics libraries. If error, exit immediatly */ IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",31L); if (IntuitionBase == NULL) exit(100L); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",VERSION); if (GfxBase == NULL) exit(100L); /* Initialize window struct, then call OpenWindow. Exit if error */ if ((window = (struct Window *)OpenWindow(&newwindow)) == NULL) exit(100L); /* Initialize Menu items, then submit them to Intuition */ InitMenu(); SetMenuStrip(window,&menu); /* * * * * * * * * */ /* Create the Read serial reply port, and request block */ MRport = CreatePort(SERIALNAME,0L); if(MRport == NULL) { puts("Error during read CreatePort\n"); ClearMenuStrip(window); CloseWindow(window); exit(100L); } /* Create request block for reading from serial port. IORser is */ /* pointer to that request block. */ IORser = (struct IOExtSer *)CreateExtIO(MRport,sizeof(struct IOExtSer)); if(IORser == NULL) { puts("Error during CreateExtIO (read)\n"); DeletePort(MRport); ClearMenuStrip(window); CloseWindow(window); exit(100L); } /* Set initial parms, then open the serial device */ IORser -> io_SerFlags = SERF_XDISABLED | SERF_SHARED; if((error = OpenDevice(SERIALNAME,0L,IORser,0L))!=0L) { puts("Read serial device did not open\n"); DeletePort(MRport); DeleteExtIO(MRport,sizeof(struct IOExtSer)); ClearMenuStrip(window); CloseWindow(window); exit(100L); } /* Now set all the other serial parms, ie MIDI baud rate, no parity, */ /* 8 data bits, 1 start bit, 1 stop bit, no break signal */ IORser -> IOSer.io_Length = 1; IORser -> IOSer.io_Data = (APTR) &rs_in[0]; IORser -> io_SerFlags = SERF_SHARED | SERF_RAD_BOOGIE; IORser -> io_Baud = 31250; IORser -> io_ReadLen = 8; IORser -> io_WriteLen = 8; IORser -> io_StopBits = 1; IORser -> io_RBufLen = 5120; IORser -> IOSer.io_Command = SDCMD_SETPARAMS; DoIO(IORser); IORser -> IOSer.io_Command = CMD_READ; /* * * * * * * * * */ /* Create the Write serial reply port, and request block */ MWport = CreatePort(SERIALNAME,0L); if(MWport == NULL) { puts("Error during CreatePort (write)\n"); CloseDevice(IORser); DeletePort(MRport); ClearMenuStrip(window); CloseWindow(window); exit(100L); } /* Create write request block (IOWser) for passing info. */ IOWser = (struct IOExtSer *)CreateExtIO(MWport,sizeof(struct IOExtSer)); if(IOWser == NULL) { puts("Error during CreateExtIO (write)\n"); DeletePort(MWport); CloseDevice(IORser); DeletePort(MRport); ClearMenuStrip(window); CloseWindow(window); exit(100L); } /* Set initial parms, then open the write serial device */ IOWser -> io_SerFlags = SERF_XDISABLED | SERF_SHARED; if((error = OpenDevice(SERIALNAME,0L,IOWser,0L))!=0L) { puts("Write serial device did not open\n"); DeletePort (MWport); DeleteExtIO(MWport,sizeof(struct IOExtSer)); CloseDevice(IORser); DeletePort(MRport); ClearMenuStrip(window); CloseWindow(window); exit(100L); } IOWser -> IOSer.io_Command = CMD_WRITE; IOWser -> IOSer.io_Length = 4104; IOWser -> IOSer.io_Data = (APTR) &voicedata[0]; /* Display initial screen message credits */ Move(window->RPort,20L,20L); Text(window->RPort,"DX Voice Filer by Jack Deckard",31L); Move(window->RPort,20L,28L); Text(window->RPort,"(C) 1986 Helicon Software",25L); /* Wait for message at IDCMP port */ KeepGoing = 1; capture = 0; SetAPen(window -> RPort,1L); BeginIO(IORser); while( KeepGoing ) { /* wait for window message or serial port message */ Wait((1L << IORser -> IOSer.io_Message.mn_ReplyPort -> mp_SigBit) | ( 1L << window -> UserPort -> mp_SigBit)); if(CheckIO(IORser)) /* another byte sent to Amiga? */ { WaitIO(IORser); c[0] = rs_in[0]; BeginIO(IORser); if(c[0] > 0x7f) /* MIDI status byte */ { capture = 0; chksum = 0; if(c[0] == 0xf0) ++capture; } else if(capture) /* MIDI data byte */ { if ((capture > 5) && (capture < 4102)) { voicedata[capture] = c[0]; chksum += c[0]; } else if (capture == 4102) { ClearWindow(); chksum = 127 & ((~chksum)+1); if (chksum == c[0]) { Move(window->RPort,20L,20L); Text(window->RPort,"Gotcha",6L); /* save voicedata to disk */ error = savefile(&voicedata[6]); if (error == 1L) { Move(window->RPort,20L,52L); Text(window->RPort,"Data Saved",10L); } else if (error == 0L) { Move(window->RPort,20L,52L); Text(window->RPort,"I/O ERROR File not saved",27L); } else if (error == -1L) { Move(window->RPort,20L,52L); Text(window->RPort,"Save Aborted",12L); } } else { Move(window->RPort,20L,52L); Text(window->RPort,"Data Error in Voice File",24L); } } ++capture; } } while(NewMessage=(struct IntuiMessage *)GetMsg(window->UserPort) ) { class = NewMessage->Class; code = NewMessage->Code; ReplyMsg( NewMessage ); switch( class ) { case VANILLAKEY: break; case ACTIVEWINDOW: break; case INACTIVEWINDOW: break; case CLOSEWINDOW: /* User is ready to quit, so indicate that execution should terminate with next iteration of the loop. */ KeepGoing = 0; break; case MENUPICK: if ( code != MENUNULL ) { menunum = MENUNUM( code ); itemnum = ITEMNUM( code ); switch(menunum) { case 0: switch( itemnum ) { case 0: /* DX to Amiga */ ClearWindow(); Move(window->RPort,20L,20L); Text(window->RPort,"Send DX data to Amiga ",23L); Move(window->RPort,20L,36L); Text(window->RPort,"Put DX in SYS INFO AVAIL",24L); Move(window->RPort,20L,44L); Text(window->RPort,"mode, select MIDI TRANSMIT?",27L); Move(window->RPort,20L,52L); Text(window->RPort,"and then press YES",18L); break; case 1: /* Amiga to DX */ ClearWindow(); Move(window->RPort,20L,20L); Text(window->RPort,"Send Amiga data to DX",21L); /* Load the file on disk into array voicefile */ error = loadfile(&voicedata[6]); if (error == 1L) { for (i = 6; i < 4102; ++i) { chksum += voicedata[i]; } /* get 2s complement of chksum */ voicedata[4102] = (UBYTE)(127 & ((~chksum)+1)); /* send all 4104 bytes to DX */ DoIO(IOWser); Move(window->RPort,20L,52L); Text(window->RPort,"Voice data to DX complete",25L); } else if (error == 0L) { Move(window->RPort,20L,52L); Text(window->RPort,"I/O ERROR File Not Found",25L); } else if (error == -1L) { Move(window->RPort,20L,52L); Text(window->RPort,"Load Aborted",12L); } break; case 2: /* RND to DX7 */ ClearWindow(); Move(window->RPort,20L,20L); Text(window->RPort,"Send random data to DX",22L); /* generate RND data into array voicefile */ for (i = 6; i < 4102; ++i) { voicedata[i] = RangeRand(127L); chksum += voicedata[i]; } /* get 2s complement of chksum */ voicedata[4102] = (UBYTE)(127 & ((~chksum)+1)); /* send all 4104 bytes to DX */ DoIO(IOWser); Move(window->RPort,20L,52L); Text(window->RPort,"Random data to DX complete",26L); break; } break; case 1: switch (itemnum) { case 0: /* DX7 */ voicedata[3] = 0x09; break; /* DX21 */ case 1: voicedata[3] = 0x04; break; case 2: /* DX100 */ voicedata[3] = 0x04; break; } break; } /* end of switch ( menunum ) */ } /* end of if ( not null ) */ break; } /* end of switch (class) */ } /* end of while ( newmessage )*/ } /* end while ( keepgoing ) */ /* * * * * * * * * */ /* It must be time to quit, so we have to clean */ /* up and exit. */ CloseDevice(IOWser); /* Close Write serial device */ DeletePort(MWport); DeleteExtIO(IOWser,sizeof(struct IOExtSer)); CloseDevice(IORser); /* Close Read serial device */ DeletePort(MRport); DeleteExtIO(IORser,sizeof(struct IOExtSer)); ClearMenuStrip(window); CloseWindow(window); exit(FALSE); } /* end of main */ VOID InitMenu() /* Set up Menu */ { /* Initialize Menu Header Voice Data Transfer */ menu[0].NextMenu = &menu[1]; menu[0].LeftEdge = 5; menu[0].TopEdge = 0; menu[0].Width = 165; menu[0].Height = 10; menu[0].Flags = MENUENABLED | MIDRAWN; menu[0].MenuName = "Voice Data Transfer"; menu[0].FirstItem = &menuitem[0]; /* Initialize menu item "DX to Amiga" */ menuitem[0].NextItem = &menuitem[1]; menuitem[0].LeftEdge = 0; menuitem[0].TopEdge = 0; menuitem[0].Width = 156; menuitem[0].Height = 11; menuitem[0].Flags = ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP; menuitem[0].MutualExclude = 0xffff; menuitem[0].ItemFill = (APTR)&menutext[0]; menuitem[0].SelectFill = NULL; menuitem[0].Command = 'c'; menuitem[0].SubItem = NULL; menuitem[0].NextSelect = NULL; menutext[0].FrontPen = 0; menutext[0].BackPen = 1; menutext[0].DrawMode = JAM2; menutext[0].LeftEdge = 0; menutext[0].TopEdge = 1; menutext[0].ITextFont = NULL; menutext[0].IText = (UBYTE *) "DX to Amiga"; menutext[0].NextText = NULL; /* Second Menu Item "Amiga to DX" */ menuitem[1].NextItem = &menuitem[2]; menuitem[1].LeftEdge = 0; menuitem[1].TopEdge = 11; menuitem[1].Width = 156; menuitem[1].Height = 11; menuitem[1].Flags = ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP; menuitem[1].MutualExclude = 0xffff; menuitem[1].ItemFill = (APTR) &menutext[1]; menuitem[1].SelectFill = NULL; menuitem[1].Command = 's'; menuitem[1].SubItem = NULL; menuitem[1].NextSelect = NULL; menutext[1].FrontPen = 0; menutext[1].BackPen = 1; menutext[1].DrawMode = JAM2; menutext[1].LeftEdge = 0; menutext[1].TopEdge = 1; menutext[1].ITextFont = NULL; menutext[1].IText = (UBYTE *) "Amiga to DX"; menutext[1].NextText = NULL; /* Third Menu Item "RND to DX" */ menuitem[2].NextItem = NULL; menuitem[2].LeftEdge = 0; menuitem[2].TopEdge = 22; menuitem[2].Width = 156; menuitem[2].Height = 11; menuitem[2].Flags = ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP; menuitem[2].MutualExclude = 0xffff; menuitem[2].ItemFill = (APTR) &menutext[2]; menuitem[2].SelectFill = NULL; menuitem[2].Command = 'r'; menuitem[2].SubItem = NULL; menuitem[2].NextSelect = NULL; menutext[2].FrontPen = 0; menutext[2].BackPen = 1; menutext[2].DrawMode = JAM2; menutext[2].LeftEdge = 0; menutext[2].TopEdge = 1; menutext[2].ITextFont = NULL; menutext[2].IText = (UBYTE *) "RND to DX"; menutext[2].NextText = NULL; /* Initialize Menu Header DX Synth */ menu[1].NextMenu = NULL; menu[1].LeftEdge = 175; menu[1].TopEdge = 0; menu[1].Width = 140; menu[1].Height = 10; menu[1].Flags = MENUENABLED | MIDRAWN; menu[1].MenuName = "DX Synthesizer"; menu[1].FirstItem = &menuitem[3]; /* Initialize menu item "DX7" */ menuitem[3].NextItem = &menuitem[4]; menuitem[3].LeftEdge = 0; menuitem[3].TopEdge = 0; menuitem[3].Width = 132; menuitem[3].Height = 11; menuitem[3].Flags = CHECKIT | CHECKED | ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP; menuitem[3].MutualExclude = 0xfffe; menuitem[3].ItemFill = (APTR)&menutext[3]; menuitem[3].SelectFill = NULL; menuitem[3].Command = '7'; menuitem[3].SubItem = NULL; menuitem[3].NextSelect = NULL; menutext[3].FrontPen = 0; menutext[3].BackPen = 1; menutext[3].DrawMode = JAM2; menutext[3].LeftEdge = CHECKWIDTH; menutext[3].TopEdge = 1; menutext[3].ITextFont = NULL; menutext[3].IText = (UBYTE *) "DX7"; menutext[3].NextText = NULL; /* Second Menu Item "DX21" */ menuitem[4].NextItem = &menuitem[5]; menuitem[4].LeftEdge = 0; menuitem[4].TopEdge = 11; menuitem[4].Width = 132; menuitem[4].Height = 11; menuitem[4].Flags = CHECKIT | ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP; menuitem[4].MutualExclude = 0xfffd; menuitem[4].ItemFill = (APTR) &menutext[4]; menuitem[4].SelectFill = NULL; menuitem[4].Command = '2'; menuitem[4].SubItem = NULL; menuitem[4].NextSelect = NULL; menutext[4].FrontPen = 0; menutext[4].BackPen = 1; menutext[4].DrawMode = JAM2; menutext[4].LeftEdge = CHECKWIDTH; menutext[4].TopEdge = 1; menutext[4].ITextFont = NULL; menutext[4].IText = (UBYTE *) "DX21"; menutext[4].NextText = NULL; /* Third Menu Item "DX100" */ menuitem[5].NextItem = NULL; menuitem[5].LeftEdge = 0; menuitem[5].TopEdge = 22; menuitem[5].Width = 132; menuitem[5].Height = 11; menuitem[5].Flags = CHECKIT | ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP; menuitem[5].MutualExclude = 0xfffb; menuitem[5].ItemFill = (APTR) &menutext[5]; menuitem[5].SelectFill = NULL; menuitem[5].Command = '1'; menuitem[5].SubItem = NULL; menuitem[5].NextSelect = NULL; menutext[5].FrontPen = 0; menutext[5].BackPen = 1; menutext[5].DrawMode = JAM2; menutext[5].LeftEdge = CHECKWIDTH; menutext[5].TopEdge = 1; menutext[5].ITextFont = NULL; menutext[5].IText = (UBYTE *) "DX100"; menutext[5].NextText = NULL; } VOID ClearWindow() /* Clear the window, */ { Move(window->RPort,10L,20L); ClearScreen(window->RPort); Move(window->RPort,1L,79L); Draw(window->RPort,1L,20L); Move(window->RPort,0L,20L); PolyDraw(window->RPort,4L,&linearray[0]); Move(window->RPort,298L,14L); Draw(window->RPort,298L,79L); } /* Load a file on disk using buffered I/O, 4096 bytes long. */ /* Open the disk file, read the array, and close the file */ LONG loadfile(buffer) UBYTE *buffer; /* pointer to byte array voice file */ { VOID filename(); filename(); if (name[0] == 0) return(-1L); /* aborted save */ filehandle = Open(name,MODE_OLDFILE); if (filehandle == 0L) return(0L); if(Read(filehandle,buffer,4096L) == -1L) { Close(filehandle); /* error */ return(0L); } Close(filehandle); return(1L); } /* Create a file on disk using buffered I/O, 4096 bytes long */ /* Open the disk file, write the array to it, and close the file. */ LONG savefile(buffer) UBYTE *buffer; /* pointer to voice file */ { VOID filename(); filename(); if (name[0] == 0) return(-1L); /* aborted save */ filehandle = Open(name,MODE_NEWFILE); if (filehandle == 0L) return(0L); if(Write(filehandle,buffer,4096L) == -1L) { Close(filehandle); /* error */ return(0L); } Close(filehandle); return(1L); } /* function to get file name */ VOID filename() { ULONG class; USHORT code, keepgoing = 1, i = 0; LONG x = 100; Move(window->RPort,20L,36L); Text(window->RPort,"File name? ",11L); while(keepgoing) { Wait( 1L << window -> UserPort -> mp_SigBit); while(NewMessage=(struct IntuiMessage *)GetMsg(window->UserPort)) { class = NewMessage->Class; code = NewMessage->Code; ReplyMsg(NewMessage); if(class = VANILLAKEY) { if(code) { if(code == 13) /* return */ { name[i]=0; keepgoing = 0; } if(code == 27) /* ESC */ { name[0]=0; keepgoing = 0; } else if((code == 8) && (i > 0)) /* backspace */ { i--; name[i] = 0; Move(window->RPort,x,36L); Text(window->RPort," ",1L); Move(window->RPort,x,36L); x=x-8L; } else if(code >= 32) { name[i]=code; Text(window->RPort,&name[i],1L); x=x+8L; i++; } } } } /* end of new message loop */ } /* end of while(keepgoing) */ } /* end of function */ /* end of file */