			NEWUNIT.EXE and NEWUNIT.C

	The newunit.exe file is a DOS program for converting the Unit Number
to a desired value in a bank of .SYX format messages for the Roland JV-80
family (JV-80, JV-880, JV-90, and JV-1000).  It won't work for a JV-1080 since
it has a different Model designation, but if there is demand, I think I could
make it general enough to work with that as well.  I don't know how necessary
that would be though, since we don't seem to have any banks or other resources
for the 1080, and it is so comprehensive a synth that it is probably a rare
setup that needs more than one of these.

	Usage is as follows (improper usage results in similar information
being displayed on the screen):

	newunit Unit# curfile newfile

The Unit# must be between 17 and 32 (the valid unit numbers for the JVs),
and the curfile and newfile names must be different.  It expects that the
curfile contains one or more properly formatted .SYX messages for a JV and
it produces the newfile containing the same messages but with the specified
unit number.  The curfile may contain a single patch, a bank of patches,
a dump of performances, patches, and drumkit, or literally any any file
of valid JV-80 family SYSEX messages.

	Error checking is rather strict (all the heading bytes are checked
for appropriate values, and the value of the checksum is verified).  If an
improper message is detected the program prints an error message and skips
the offending message, continuing with the next message it finds.  I chose
this error handling as opposed to just bailing out at the first errant
message, but if an error message is printed I'd suspect the entire contents
of the newfile (and probably the curfile as well).

	When an error is detected the program will print out a hexidecimal
error value.  The following defines indicate the meanings of the various
bits that may be set in this error value: 

#define E_NOT_ROLAND	0x01	/*  Not a Roland SYSEX message		*/
#define E_BAD_DEVICE	0x02	/*  Device ID (Unit# -1) out of range	*/
#define E_WRONG_MODEL	0x04	/*  Not JV-80 family synth		*/
#define E_BAD_COMMAND	0x08	/*  Not a DT1 command byte		*/
#define E_BAD_CHECKSUM	0x10	/*  Improper Checksum value		*/
#define E_EOF		0x20	/*  EOF encountered before 0xF7 found	*/
#define E_SHORT_MSG	0x40	/*  0xF7 found without complete header	*/
#define E_LONG_MSG	0x80	/*  Message longer than internal buffer	*/


	The newunit.c is the source code for this application.  I have
compiled it with both my MSC/C++ 7.0 compiler, and on my UNIX system (the
newunit.exe is the output of the MS compiler).  The one area of concern
in compiling it for other environments is to be sure the fopen() calls have
the necessary options strings to treat the files as binary files.  For my
MS compiler this requires adding a 'b' to the string (as "rb" for reading
a binary file, and "wb" for writing).  The UNIX system I use only needs the
"r" or "w" option string to work properly.  I tried to use the __STDC__
macro (using #ifndef __STDC__ to bracket affected code), but I'm not sure
that this is a proper approach to this (ie there may be some STDC compilers
that don't need the 'b', and some non-STDC compilers that do).  To get the
MS compiler to define the __STDC__ macro you need to specify the /Za command
line option (cl /Za newunit.c), but the code compiles cleanly without this
option.  However without the option the __STDC__ macro isn't defined and
thus the files are not treated as binary files, which results in errors
reading and/or writing the files.  All I can say is Beware!!!

	There are two routines that may be of interest to hackers.  These
are the get_syx_message() and put_syx_message() routines.  They work with
a data structure called syx_msg which is also defined in the file.  This
structure maintains the information about an individual SYSEX message,
including the unit number, address, size and data bytes of the message.  The
get_syx_message() function takes a message from a data file, error checking
it along the way, and storing the important data in the syx_msg structure.
It also verifies the checksum it finds in the message.  Bits are set in the
error field of the structure reflecting errors that are detected in the
message.  The meaning of the bits in this field are described by #define
statements found in the file (which are reproduced above).

	The syx_msg structure is malloc()'d by this function and a pointer
to it is returned by the function.  The buffer for the data bytes is also
malloc()'d here.  It is the responsability of the programmer to be sure and
free() these areas as necessary.  The routine will return a NULL pointer if
there were no more messages in the file, or if there was no memory available
for allocating the structure.  The msg_bytes pointer in the structure will
be NULL if an empty message was detected, or if no memory was available for
the message buffer.  Of course if either of these are NULL there is no need
to free() the associated memory.

	Once the message has been extracted the program can modify the
unit number, addressing, or data bytes as desired.  Then the put_syx_message()
function can be used to re-create the complete message into a file with
the necessary heading bytes, newly calculated checksum (in case the address
or data were modified), and terminating 0xF7 End_Of_SYSEX byte.


	These routines are released into the public domain for any and all
use.  You use them at your own risk.  I can be contacted via internet email
at:  greg@ihlpm.att.com  with any questions or comments.
