/*
 *	spew - pick up 4096-byte dx7 patch description files and fling them
 *	out of the midi port.
 *
 *	-v	display as hex values on the screen instead of sending to midi
 *	-n	display patch names
 *	-d	interpolate DX7 dum format, including leading garbage, status
 *		byte and header.
 */
#include <stdio.h>
#include <osbind.h>
#include "midi.h"

main(argc, argv)
char **argv;
{
	register int i;
	register unsigned char *cp;
	unsigned char buf[4096];
	register FILE *fp;
	int ch;
	register int csum;
	int cflag = 0, dflag = 0, nflag = 0, vflag = 0;

	while (argc >= 2 && argv[1][0] == '-') {
		switch(argv[1][1]) {
		case 'c':
			cflag = 1;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
		default:
			goto usage;
		}
		argv++; argc--;	/* ugh */
	}
	if (argc != 2) {
usage:		fputs("usage: spew [-n] [-v] file\n", stderr);
		fputs("-c\tgenerate dummy voice names to see char set\n", stderr);
		fputs("-d\tDecode full dump, with MIDI header\n", stderr);
		fputs("-n\tDisplay voice names on the screen\n", stderr);
		fputs("-v\tDisplay voice data on the screen\n", stderr);
		exit(1);
	}

	if (cflag) {
		for (i=0; i<128; i++) {
			buf[i/10*128 + 118 + i%10] = i;
		}
		goto afterload;
	}

	fp = fopen(argv[1], "br");
	if (fp == NULL) {
		fprintf(stderr, "Cannot open %s\n", argv[1]);
		exit(1);
	}

	if (dflag) {
		/* dispense with leading garbage */
		do {
			ch = getc(fp);
			if (ch == EOF) {
				fputs("Premature EOF before Status byte\n", stderr);
				exit(1);
			}
		} while (ch != 0xF0);

		/* gobble header */
		for (i=0; i<5; i++) {
			if (getc(fp) == EOF) {
				fputs("Premature EOF in header\n", stderr);
				exit(1);
			}
		}
		/* ready to go... */
	}

	if (fread(buf, 1, 4096, fp) != 4096) {
		fprintf(stderr, "wrong count from file\n");
		exit(1);
	}
	fclose(fp);

afterload:

	/* do they just want a voice listing? */
	if (nflag) {
		for (i=0; i<32; i++) {
			register int j;
			fputs("     ", stdout);
			for (j=0; j<10; j++) putchar(buf[128*i+118+j]);
			fputs("     ", stdout);
		}
		exit(0);
	}

	/* do they just want a hex dump? */
	if (vflag) {
		for (i=0; i<32; i++) {
			register int j;
			for (j=0; j<128; j++) printf(" %02x ", buf[i*128+j]);
			putchar('\n');
		}
		exit(0);
	}

	/* check for top bit set in data */
	for (i=0; i<4096; i++) {
		if (buf[i] & 0x80) {
			fprintf(stderr,	"Dirty file. cleaning...\n");
			for ( ; i<4096; i++) buf[i] = buf[i] & 0x7F;
		}
	}

	/* do header */	
	Bconout(MIDI, 0xF0);		/* status */
	Bconout(MIDI, 0x43);		/* ID = YAMAHA (67 decimal) */
	Bconout(MIDI, 0x00);		/* subst & channel number=1 */
	Bconout(MIDI, 0x09);		/* 32-voice bulk dump */
	Bconout(MIDI, 4096>>7);		/* MSB of byte count = 4096 */
	Bconout(MIDI, 0x00);		/* LSB (7 bits each) */
	csum = 0;
	for (i=0, cp=buf; i<4096; cp++, i++) {
		Bconout(MIDI, *cp);
		csum += *cp;
	}
	/* need to output "the 2's complement of the sum of 4096 bytes" */
	Bconout(MIDI, (-csum) & 0x7F);		/* checksum */
	Bconout(MIDI, EOX);
	
	exit(0);
}
