/*
**	TXVMRG -- Combine single-voice TX dumps into a 32-voice dump.
**	psl 3/88
*/
#include	<stdio.h>
#include	<midi.h>

#define	DEFDEVN	0
#define	MAXDEVN	15

u_char	V32[DX732VTOTLEN];

main(argc, argv)
char	*argv[];
{
	char *lastfile = 0;
	int i, n, fh, devn = DEFDEVN;

	n = 0;
	for (i = 1; i < argc; i++) {
	    if (argv[i][0] == '-') {
		switch (argv[i][1]) {
		case 'd':
		    devn = atoi(&argv[i][2]);
		    if (devn < 0 || devn > MAXDEVN)
			goto syntax;
		    break;
		default:
		    goto syntax;
		}
	    } else if (n++ < 32) {
		if ((fh = open(argv[i], 0)) < 0) {
		    perror(argv[i]);
		    continue;
		}
		addvoice(n - 1, fh, lastfile = argv[i]);
		close(fh);
	    } else {
syntax:
		fprintf(stderr, "Usage: %s [-d#] [v1 [v2 [v3...[v32]]]]\n",
		 argv[0]);
		fprintf(stderr, "-d sets dev # (must 0..%d)\n", MAXDEVN);
		exit(2);
	    }
	}
	if (lastfile && n < 32) {
	    fh = open(lastfile, 0);
	    while (n++ < 32)
		addvoice(n - 1, fh, lastfile);
	}
	dump32(1, devn);
}

addvoice(n, fh, file)
char	*file;
{
	u_char buf[32], *cp;
	u_char v1[DX7VOXLEN];
	int lhi, llo;

	lseek(fh, 0L, 0);
	lhi = DX7VOXLEN / 128;
	llo = DX7VOXLEN % 128;
	for (cp = buf; read(fh, cp, 1) == 1 && *cp != SX_CMD; );
	if (read(fh, &cp[1], 5) != 5) {
	    sprintf(stderr, "%s: EOF in file header?\n", file);
	    return;
	}
	if (cp[1] != ID_YAMAHA
	 || cp[3] != DX7_SXF_1V
	 || cp[4] != lhi || cp[5] != llo) {
	    fprintf(stderr, "%s: naughty file header:", file);
	    fprintf(stderr, " %x %x %x %x %x %x\n",
	     cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
	    return;
	}
	if (read(fh, v1, DX7VOXLEN) != DX7VOXLEN) {
	    fprintf(stderr, "%s: EOF in file body?\n", file);
	    return;
	}
	if (read(fh, buf, 2) != 2) {
	    sprintf(stderr, "%s: EOF in file trailer?\n", file);
	    return;
	}
	if (buf[0] != check_sum(v1, DX7VOXLEN))
	    fprintf(stderr, "%s: bad check-sum; ignored.\n", file);
	if (buf[1] != SX_EOB)
	    fprintf(stderr, "%s: no SX_EOB; ignored.\n", file);
	tx1v32(v1, n, V32);
}

dump32(fh, devn)
{
	u_char buf[32], *cp;
	u_char v1[DX7VOXLEN];
	int lhi, llo;

	cp = buf;
	*cp++ = SX_CMD;
	*cp++ = ID_YAMAHA;
	*cp++ = DX7_SXSS_BD | devn;
	*cp++ = DX7_SXF_32V;
	*cp++ = DX732VTOTLEN / 128;
	*cp++ = DX732VTOTLEN % 128;
	write(fh, buf, cp - buf);
	write(fh, V32, DX732VTOTLEN);
	buf[0] = check_sum(V32, DX732VTOTLEN);
	buf[1] = SX_EOB;
	write(fh, buf, 2);
}

check_sum(buf, len)
u_char	*buf;
{
	register u_char *cp;
	register int s = 0;

	for (cp = &buf[len]; --cp >= buf; s -= *cp);
	return(s & 0x7F);
}
