home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * midiex.c 2/20/86 Copyright (C) 1986 John Bailin, Cantus Corportion
- *
- * Patch exchange software for the IBM-PC using MPU-401 in dumb mode.
- *
- * Modified 08/24/86 Jim Bergsten to run under Microsoft "C"
- * Changes copyright (C) 1986 Jim Bergsten
- * "creat" call changed to "open" calls.
- * Symbol "string" defined in routine "edit_space"
- * Missing open bracket in first "for" stmt. in routine "edit_space"
- * Some logic changed; some extensions, for example, created files
- * are now only as long as the system exclusive data received.
- * Error recovery added so operation can be retried without
- * restarting the program.
- * Other minor editorial changes...
- *
- * Updated by Michael Geary, 11/14/86
- * These changes are not copyrighted!
- * (How many silly copyrights do you want to see on this thing?)
- * Fixed bugs:
- * Files were not closed on error.
- * You could ^C out and leave the IRQ2 (INT 0Ah) vector hooked -
- * now forces BREAK OFF and does all console I/O through BIOS.
- * Interrupt routine in .ASM file failed to chain to previous
- * interrupt handler when it wasn't ours.
- * Function templates and type checking added.
- * Streamlined the user interface
- * More and more editorial changes...
- *
- * Updated by Dave Hayes, 1/22/88
- * These changes aren't copyrighted either. I concur with Michael!
- * Added support for GMR bulk dumps from Yamaha E! modified DX7
- * so the banks can be FULLY backed up.
- *
- ***************************************************************************/
-
- /*
- * The external data and code declarations are all publics in the 8086
- * assembler module MIDIINT.ASM. This program was compiled with the Microsoft
- * C compiler.
- */
-
- /* Force library argument checking */
- #define LINT_ARGS
-
- #include <ctype.h>
- #include <fcntl.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <io.h>
- #include <dos.h>
- #include <process.h>
-
- /* Don't include stdio.h - so inadvertant printf's will be caught */
- int cdecl sprintf( char *, char *, ... );
-
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- typedef unsigned long DWORD;
- typedef int BOOL;
-
- #define TRUE 1
- #define FALSE 0
-
- /* Changing BUFMAX requires that you change the same value in MIDIINT.ASM! */
- #define BUFMAX 16834
- #define CR 13
- #define ESC 27
- #define LINE 80
-
- /*
- * MIDI equates
- */
-
- #define SYSEX 0xF0
- #define EOX 0xF7
-
-
- /*
- * MPU-401 equates
- */
-
- #define UART 0x3F
- #define RESET 0xFF
-
- /*
- * global declarations
- */
-
- extern int recv_data_count;
- extern BYTE recv_buf[ ];
- extern int recv_buf_ptr;
-
- extern BYTE wait_char;
-
- BYTE dump_buf[BUFMAX];
- BOOL breakstate;
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- /*
- * Functions in this C file
- */
-
- void check_keys( void );
- BOOL file_exists( char * );
- BOOL get_filename( char *, char * );
- char *getstring( char * );
- void getword( char * *, char * );
- BOOL initialize( void );
- void instruct( void );
- void main( void );
- void menu( void );
- void print( char * );
- void quit( int );
- int read_dump( char * );
- int receive_dump( void );
- int gmr_receive_dump( void );
- BOOL send_dump( int );
- BOOL setbreak( BOOL );
- BOOL write_dump( char *, int );
- BYTE get_a_digit( void );
-
- /*
- * Functions in MIDIINT.ASM
- */
-
- WORD fetch_mpu_data( void );
- int get_char( int );
- void int10( WORD, WORD, WORD, WORD );
- void reset_mpu_vector( void );
- BOOL set_mpu_vector( void );
- BOOL write_mpu_command( int );
- BOOL write_mpu_data( int );
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void main()
- {
- print( "\n\nMIDIEX patch exchange utility.\n" );
- print( "Copyright (C) 1986 by Cantus Corportaion.\n" );
- print( "Modifications (C) 1986 by Jim Bergsten.\n" );
- print( "Version 1.2, updated by Michael Geary.\n" );
- print( "Version 1.3, updated by Dave Hayes.\n" );
- if( ! initialize() ) {
- print( "\nYour MPU isn't responding within MIDIEX's timeout period.\n" );
- print( "Try rebooting your system and starting over.\n" );
- quit( 1 );
- }
- print( "\nThis program allows you to send and receive MIDI System Exclusive\n" );
- print( "data dumps between your PC and a synthesizer or other MIDI device.\n" );
- instruct();
-
- while( TRUE ) menu();
-
- quit( 0 );
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BOOL file_exists( name )
- char *name;
- {
- register int f;
-
- if( ( f = open( name, (int)(O_RDONLY|O_BINARY) ) ) < 0 ) return FALSE;
-
- close( f );
- return TRUE;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BOOL get_filename( prompt, name )
- char *prompt, *name;
- {
- char response[LINE];
- char *resp;
-
- if( name[0] ) return TRUE;
-
- print( "\nEnter filename to " );
- print( prompt );
- print( ": " );
- resp = getstring( response );
- getword( &resp, name );
-
- return name[0] != 0;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BOOL initialize()
- {
- breakstate = setbreak( 0 );
- if( ! set_mpu_vector() ) return FALSE;
- write_mpu_command( RESET );
- write_mpu_command( UART );
- return TRUE;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void instruct()
- {
- print( "\nCommands are:\n" );
- print( " S pathname to Send a data dump to your synthesizer.\n" );
- print( " R pathname to Receive a data dump from your synthesizer.\n" );
- print( " G pathname to Receive a GMR data dump from your Yamaha.\n\n" );
- print( "Press the Esc key at any time to exit.\n" );
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void menu()
- {
- char response[LINE];
- char *resp;
- char name[LINE];
- int size;
-
- prompt:
- print( "\nCommand (S, R, G, Esc): " );
- resp = getstring( response );
- getword( &resp, name );
-
- switch( name[0] ) {
-
- case 'S':
- getword( &resp, name );
- if( ! get_filename( "send", name ) ) break;
- if( size = read_dump( name ) ) send_dump( size );
- print( "\n" );
- break;
-
- case 'R':
- getword( &resp, name );
- if( ! get_filename( "receive", name ) ) break;
- if( file_exists( name ) ) {
- print( "File already exists, OK to overwrite (Y/N)? " );
- getstring( response );
- if( response[0] != 'Y' ) break;
- }
- if( size = receive_dump() ) write_dump( name, size );
- print( "\n" );
- break;
-
- case 'G':
- getword( &resp, name );
- if( ! get_filename( "receive", name ) ) break;
- if( file_exists( name ) ) {
- print( "File already exists, OK to overwrite (Y/N)? " );
- getstring( response );
- if( response[0] != 'Y' ) break;
- }
- if( size = gmr_receive_dump() ) write_dump( name, size );
- print( "\n" );
- break;
-
- default:
- instruct();
- goto prompt;
- }
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void quit( exitvalue )
- int exitvalue;
- {
- print( "\n\n" );
- write_mpu_command( RESET );
- reset_mpu_vector();
- setbreak( breakstate );
- _exit( exitvalue );
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- int read_dump( name )
- char *name;
- {
- register int f, size;
-
- if( ( f = open( name, (int)(O_RDONLY|O_BINARY) ) ) < 0 ) {
- print( "\nUnable to open input file " );
- print( name );
- return FALSE;
- }
-
- if( ( size = read( f, dump_buf, BUFMAX ) ) <= 0 ) {
- close( f );
- print( "\nTrouble reading input file " );
- print( name );
- return FALSE;
- }
-
- close( f );
- return size;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- int receive_dump()
- {
- register int i, j, k;
- char printbuf[40];
-
- /* Set character to wait for */
- wait_char = EOX;
-
- print( "\nSend the MIDI data now...\n" );
- while( wait_char ) check_keys();
-
- /* The following dumps the received data in hexadecimal.
- remove the comments around it if you want this display. */
-
- /* print( "MIDI data received...\n" );
- j = 0;
- for( i = 0; i < recv_buf_ptr; ++i ) {
- sprintf( printbuf, " %2.2X", recv_buf[i] );
- print( printbuf );
- if( j++ == 15 ) {
- print( "\n" );
- j = 0;
- }
- }
- if( j ) print( "\n" );
- */
-
- /* search backwards for start of dump */
- i = recv_buf_ptr;
-
- for( k = 1; k <= BUFMAX; k++ ) {
- if( --i < 0 ) i = BUFMAX;
- if ( recv_buf[i] == SYSEX ) break ;
- }
-
- if( k >= BUFMAX ) {
- print( "Start of MIDI dump not found\n" );
- return 0;
- }
-
- sprintf( printbuf, "Size of dump is %d\n", k );
- print( printbuf );
-
- for ( j = 0; j < k; j++ ) {
- if( i == BUFMAX ) i = 0;
- dump_buf[ j ] = recv_buf[ i++ ];
- }
-
- return k;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #define GMR_BANK 4
- int gmr_receive_dump()
- {
- register int i, j, k;
- char printbuf[40];
- static BYTE gmr_msg[] = { 0xF0, 0x12, 0x00, 0x00, 0x00,
- 0x00, 0x11, 0xF7, 0x00 };
- static int gmr_size = 8;
-
- /* Alright...get the frigging bank number*/
- print("\nWhich bank (0 thru 9): ");
- gmr_msg[GMR_BANK] = get_a_digit();
-
- /* Send the GMR dump request */
- print( "\nStrike any key when ready to get GMR MIDI data...\n" );
- get_char( 0 );
- print( "\nSending dump request...\n" );
- for (k = 0; k < gmr_size; k++) {
- if( ! write_mpu_data( gmr_msg[k] ) ) {
- print( "MIDI interface timed out\n" );
- return FALSE;
- }
- check_keys();
- if( gmr_msg[k] == EOX ) break;
- }
- print( "\nDone! Waiting for response..." );
-
- /* Set character to wait for */
- wait_char = EOX;
-
- while( wait_char ) check_keys();
-
- /* The following dumps the received data in hexadecimal.
- remove the comments around it if you want this display. */
-
- /* print( "MIDI data received...\n" );
- j = 0;
- for( i = 0; i < recv_buf_ptr; ++i ) {
- sprintf( printbuf, " %2.2X", recv_buf[i] );
- print( printbuf );
- if( j++ == 15 ) {
- print( "\n" );
- j = 0;
- }
- }
- if( j ) print( "\n" );
- */
-
- /* search backwards for start of dump */
- i = recv_buf_ptr;
-
- for( k = 1; k <= BUFMAX; k++ ) {
- if( --i < 0 ) i = BUFMAX;
- if ( recv_buf[i] == SYSEX ) break ;
- }
-
- if( k >= BUFMAX ) {
- print( "Start of MIDI dump not found\n" );
- return 0;
- }
-
- sprintf( printbuf, "Size of dump is %d\n", k );
- print( printbuf );
-
- for ( j = 0; j < k; j++ ) {
- if( i == BUFMAX ) i = 0;
- dump_buf[ j ] = recv_buf[ i++ ];
- }
-
- return k;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BOOL send_dump( size )
- int size;
- {
- register int i;
-
- print( "\nStrike any key when ready to send MIDI data...\n" );
- get_char( 0 );
- print( "\nSending MIDI data...\n" );
- for (i = 0; i <= size; i++) {
- if( ! write_mpu_data( dump_buf[i] ) ) {
- print( "MIDI interface timed out\n" );
- return FALSE;
- }
- check_keys();
- if( dump_buf[i] == EOX ) break;
- }
- print( "\nDone!" );
- return TRUE;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BOOL setbreak( newstate )
- BOOL newstate;
- /*
- * Sets DOS Ctrl-Break checking to newstate and returns previous state.
- */
- {
- BOOL oldstate;
- union REGS regs;
-
- regs.x.ax = 0x3300;
- intdos( ®s, ®s );
- oldstate = (BOOL)regs.h.dl;
-
- regs.x.ax = 0x3301;
- regs.h.dl = (unsigned char)newstate;
- intdos( ®s, ®s );
-
- return oldstate;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BOOL write_dump( name, size )
- register char *name;
- int size;
- {
- register int f;
-
- if( ( f = open( name, (int)(O_CREAT|O_TRUNC|O_WRONLY|O_BINARY), S_IWRITE ) ) < 0 ) {
- print( "\nUnable to open output file " );
- print( name );
- return FALSE;
- }
-
- if( write( f, dump_buf, size ) != size ) {
- close( f );
- print( "\nTrouble writing to output file " );
- print( name );
- return FALSE;
- }
-
- close( f );
- print( "\nDone!" );
- return TRUE;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- /*
- *
- * lower level editing routines
- *
- */
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- BYTE get_a_digit()
- {
- register char c;
- char pbuf[40];
-
- getdigit:
- while ( get_char( 1 ) != 1 ) ;
- c = (char)( get_char( 0 ) & 0xFF );
- if( c == ESC ) quit( 0 );
- if (c < '0' || c > '9') goto getdigit;
-
- sprintf(pbuf,"%c",c);
- print(pbuf);
- return ((BYTE) (c - '0'));
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void check_keys()
- {
- register char c;
-
- if( get_char( 1 ) == 1 ) {
- c = (char)( get_char( 0 ) & 0xFF );
- if( c == ESC ) quit( 0 );
- }
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- char *getstring( string )
- char *string;
- {
- register int x = 0;
- register char c;
-
- while( TRUE ) {
- c = (char)( get_char( 0 ) & 0xFF );
- if( c == ESC ) quit( 0 );
- if( c == CR ) {
- print( "\n" );
- string[x] = '\0';
- return string;
- }
- if( ( c >= 32 && c < 127 ) || c == CR ) {
- string[ x++ ] = toupper( c );
- int10( 0x0E00 | c, 0, 0, 0 );
- } else if( c == 8 && x > 0 ) {
- int10( 0x0E00 | c, 0, 0, 0 );
- int10( 0x0A00 | ' ', 7, 1, 0 );
- --x;
- }
- }
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void getword( strpp, word )
- char **strpp;
- char *word;
- {
- char *wordp;
-
- wordp = word;
- while( isspace( **strpp ) ) (*strpp)++;
- while( **strpp && ! isspace( **strpp ) ) *wordp++ = *(*strpp)++;
- *wordp = 0;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- void print( string )
- register char *string;
- {
- register char c;
-
- while( c = *string++ ) {
- if( c == '\n' ) int10( 0x0E00 | '\r', 0, 0, 0 );
- int10( 0x0E00 | c, 0, 0, 0 );
- }
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */