home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Audio Version 4.94
/
audioversion4.94knowledgemediaresourcelibraryoctober1994.iso
/
msdos
/
midi
/
midiex
/
midiex.c
next >
Wrap
Text File
|
1989-01-10
|
14KB
|
592 lines
/****************************************************************************
* 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 );
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */