/*
 * GLIB - a Generic LIBrarian and editor for synths
 *
 * D10 User Rhythm Pattern Librarian
 *
 * Code started 31 JAN 89 --  Michael R. Kesti mrk@gvgspd.GVG.TEK.COM
 */

#include "glib.h"
#include "machdep.h"
#include "vis.h"

#define D10URPSIZE 588
#define URPBASEADDR 0x0a0000
#define RESERVESIZE 20

char *visnum(), *visonoff();


/* This array contains arbitrary screen labels */
struct labelinfo Ld10urp[] = {
#MENU












               No User Rhythm Pattern editing is supported.










 Press SPACE BAR to sound note %   at volume %   for duration %  on channel % .
#END
-1,-1,NULL
};

struct paraminfo  Pd10urp[] =  {
/*
NAME		TYPE		POS	MAX	OFFSET	MASK	SHIFT	ADHOC
 */
#O autopitch	num		%%	127	-60
#O autovol	num		%%	127	-63
#O autodur	num		%%	20	-5	*5
#O autochan	num		%%	16	-1	*5
NULL,NULL,-1,-1,-1,-1,visnum,0,0,0,0
};


/*
 * d10urpnum
 *
 * Convert a voice number (0 to 31) to the string displayed in the
 * librarian (ie. 51 to 88).
 */

char *
d10urpnum(n)
{
	static char v[3];

	if ( n < 0 || n > 31 )
		return("??");

	v[0] = n/8 + '5';
	v[1] = n%8 + '1';
	v[2] = '\0';
	return(v);
}

/*
 * d10numurp
 *
 * Convert a display-style voice number (55 to 88) to internal
 * format (0 to 31).
 */

d10numurp(n)
int n;
{
	int ld, rd;
	
	/* crack out the digits as octal codes */
	ld = (n / 10) - 1; /* middle digit */
	rd = (n % 10) - 1; /* right digit */

	if(ld < 4 || ld > 7 || rd < 0 || rd > 7) {
		return(-1);
	} else {
		return(((ld - 4) * 8) + rd); /* combine as octal */
	}
}

/*
 * d10urpdin
 *
 * Take library bank 'data' and stuff values in the P array, by using
 * the setval function.
 */

d10urpdin(data)
char *data;
{
	/* The first RESERVESIZE bytes are reserved (arbitrarily) for the voice name */
}

/*
 * d10urpdout
 *
 * Take (possibly changed) parameters values out of the P array and
 * put them back into the library bank 'data'.
 */

d10urpdout(data)
char *data;
{
}

/*
 * d10urpsedit
 *
 * Send a single voice to the edit buffer of the D10.  This will be whatever
 * voice is currently selected.
 */

d10urpsedit(data)
char *data;
{
}

/*
 * d10urpnof
 *
 * Return a pointer to the voice name buried in library bank data.
 */
char *
d10urpnof(data)
char *data;
{
	static char buf[10];
	int n, v;

	for(n = 0; n < D10URPSIZE; n++)
		if ( data[n + RESERVESIZE] != 0 ) break;
	if ( n != D10URPSIZE ) {
		v = data[RESERVESIZE + 2] + (16 * data[RESERVESIZE + 3]);
		sprintf(buf, "%2d events", v);
	}
	else
		strcpy(buf, "         ");
	return(buf);
}

/*
 * d10urpsnof
 *
 * Set the voice name buried in data to name.
 */
d10urpsnof(data,name)
char *data;
char *name;
{
}

/* d10urpsone - send a single voice to the D10 */
d10urpsone(iv, data)
int iv;
char *data;
{
	int n;
	int cksum;
	long curadd;
	int addbyte;

	curadd = URPBASEADDR;

	for(n = 0; n < iv; n++) {
		curadd += 0x44c;	/* D10URPSIZE */

		if((curadd & 0x80) != 0) {
			curadd &= 0x7fff7f;
			curadd += 0x100;
		}
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}
	}

	sendmidi(0xf0);
	sendmidi(0x41);
	sendmidi(0x10);
	sendmidi(0x16);
	sendmidi(0x12);		/* DT1 - Data set 1 command */

	addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
	sendmidi(addbyte);
	cksum = addbyte;
	addbyte = ((curadd >> 8) & 0x7f);
	sendmidi(addbyte);
	cksum += addbyte;
	addbyte = (curadd & 0x7f);		/* address lsb */
	sendmidi(addbyte);
	cksum += addbyte;

	for(n = 0; n < 256; n++) {
		sendmidi(data[n + RESERVESIZE] & 0x7f);
		cksum += data[n + RESERVESIZE] & 0x7f;
	}
	sendmidi((-cksum) & 0x7f);	/* checksum */
	sendmidi(EOX);

	curadd += 256;

	if((curadd & 0x8000) != 0) {
		curadd &= 0x7f7f7f;
		curadd += 0x10000;
	}
	sendmidi(0xf0);
	sendmidi(0x41);
	sendmidi(0x10);
	sendmidi(0x16);
	sendmidi(0x12);		/* DT1 - Data set 1 command */

	addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
	sendmidi(addbyte);
	cksum = addbyte;
	addbyte = ((curadd >> 8) & 0x7f);
	sendmidi(addbyte);
	cksum += addbyte;
	addbyte = (curadd & 0x7f);		/* address lsb */
	sendmidi(addbyte);
	cksum += addbyte;

	for(n = 256; n < 512; n++) {
		sendmidi(data[n + RESERVESIZE] & 0x7f);
		cksum += data[n + RESERVESIZE] & 0x7f;
	}
	sendmidi((-cksum) & 0x7f);	/* checksum */
	sendmidi(EOX);


	curadd += 256;

	if((curadd & 0x8000) != 0) {
		curadd &= 0x7f7f7f;
		curadd += 0x10000;
	}

	sendmidi(0xf0);
	sendmidi(0x41);
	sendmidi(0x10);
	sendmidi(0x16);
	sendmidi(0x12);		/* DT1 - Data set 1 command */

	addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
	sendmidi(addbyte);
	cksum = addbyte;
	addbyte = ((curadd >> 8) & 0x7f);
	sendmidi(addbyte);
	cksum += addbyte;
	addbyte = (curadd & 0x7f);		/* address lsb */
	sendmidi(addbyte);
	cksum += addbyte;

	for(n = 512; n < (D10URPSIZE - 512); n++) {
		sendmidi(data[n + RESERVESIZE] & 0x7f);
		cksum += data[n + RESERVESIZE] & 0x7f;
	}
	sendmidi((-cksum) & 0x7f);	/* checksum */
	sendmidi(EOX);

	return(0);
}

/* d10urpgbulk - Request and read a bulk dump from the D10 */
d10urpgbulk(data)
char *data;
{
	static	char Buff[BUFSIZ];
	int c, n, v, b2, ret = 1;
	long begin, toolong, wait;
	long curadd;
	int addbyte;
	int cksum;
	FILE *d;
	
	sprintf(Buff,"\n");
	windstr(Buff);
	
	curadd = URPBASEADDR;

	for(v = 0; v < Nvoices; v++) {

		flushmidi();

		if(v % 10 != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (v / 10));
		}
		windstr(Buff);

	/* request the voice */
		sendmidi(0xf0);
		sendmidi(0x41);
		sendmidi(0x10);
		sendmidi(0x16);
		sendmidi(0x11);		/* RQ1 - Data request 1 command */

		addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
		sendmidi(addbyte);
		cksum = addbyte;
		addbyte = ((curadd >> 8) & 0x7f);
		sendmidi(addbyte);
		cksum += addbyte;
		addbyte = (curadd & 0x7f);		/* address lsb */
		sendmidi(addbyte);
		cksum += addbyte;

		sendmidi(0x00);		/* length msb */
		cksum += 0x00;
		sendmidi(0x04);		/* should be D10URPSIZE */
		cksum += 0x04;
		sendmidi(0x4c);		/* length lsb */
		cksum += 0x4c;

		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);
	
	/* set up timeout */
		begin = milliclock();
		toolong = begin + (1000 * TIMEOUT);

	/* read header */
		for(n = 0; n < 8; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout waiting for header";
					goto getout;
				}
			}
		}

	/* read data */
		for(n = 0; n < 256; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8)) {
					VOICEBYTE(data,v,n + RESERVESIZE) = b2;
					n++;
				}
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading data";
					goto timeout0;
				}
			}
		}

	timeout0:
		if ( n != 256 ) {
			Reason = "Timeout reading data!";
			goto getout;
		}

	/* read checksum */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading checksum";
					goto getout;
				}
			}
		}

	/* read EOX */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					if ( b2 != EOX ) {
						sprintf(Buff,"EOX not received (%X)\n", b2);
						Reason = Buff;
						goto getout;
					}
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading EOX";
					goto getout;
				}
			}
		}

	/* read header */
		for(n = 0; n < 8; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout waiting for header";
					goto getout;
				}
			}
		}

	/* read data */
		for(n = 0; n < 256; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8)) {
					VOICEBYTE(data,v,n + RESERVESIZE + 256) = b2;
					n++;
				}
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading data";
					goto timeout1;
				}
			}
		}

	timeout1:
		if ( n != 256 ) {
			Reason = "Timeout reading data!";
			goto getout;
		}

	/* read checksum */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading checksum";
					goto getout;
				}
			}
		}

	/* read EOX */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					if ( b2 != EOX ) {
						sprintf(Buff,"EOX not received (%X)\n", b2);
						Reason = Buff;
						goto getout;
					}
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading EOX";
					goto getout;
				}
			}
		}

	/* read header */
		for(n = 0; n < 8; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout waiting for header";
					goto getout;
				}
			}
		}

	/* read data */
		for(n = 0; n < 76; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8)) {
					VOICEBYTE(data,v,n + RESERVESIZE + 512) = b2;
					n++;
				}
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading data";
					goto timeout2;
				}
			}
		}

	timeout2:
		if ( n != 76 ) {
			Reason = "Timeout reading data!";
			goto getout;
		}

	/* read checksum */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading checksum";
					goto getout;
				}
			}
		}

	/* read EOX */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					if ( b2 != EOX ) {
						sprintf(Buff,"EOX not received (%X)\n", b2);
						Reason = Buff;
						goto getout;
					}
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading EOX";
					goto getout;
				}
			}
		}

		curadd += 0x44c;		/* D10URPSIZE */

		if((curadd & 0x80) != 0) {
			curadd &= 0x7fff7f;
			curadd += 0x100;
		}
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}

	} /* go back for another voice */

	Reason = "";
	ret = 0;	/* all's well */

getout:
	return(ret);
}

/* d10urpsbulk - send a bulk dump to the D10 */
d10urpsbulk(data)
char *data;
{
	static char Buff[BUFSIZ];
	int v, n;
	int cksum;
	long curadd, intadd;
	int addbyte, databyte;
	int curoff;

	curadd = URPBASEADDR;
	curoff = 0;	
	sprintf(Buff,"\n");
	windstr(Buff);

	for(v = 0; v <Nvoices ; v++) {
		if((((v > 63) ? (v - 64) : v) % 10) != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (((v > 63) ? (v - 64) : v) / 10));
		}

		windstr(Buff);

		sendmidi(0xf0);
		sendmidi(0x41);
		sendmidi(0x10);
		sendmidi(0x16);
		sendmidi(0x12);		/* DT1 - Data set 1 command */
		addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
		sendmidi(addbyte);
		cksum = addbyte;
		addbyte = ((curadd >> 8) & 0x7f);
		sendmidi(addbyte);
		cksum += addbyte;
		addbyte = (curadd & 0x7f);		/* address lsb */
		sendmidi(addbyte);
		cksum += addbyte;

		for(n = 0; n < 256; n++) {
			databyte = data[curoff + n + RESERVESIZE] & 0x7f;
			sendmidi(databyte);
			cksum += databyte;
		}
		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);

		intadd = curadd + 256;

		if((intadd & 0x8000) != 0) {
			intadd &= 0x7f7f7f;
			intadd += 0x10000;
		}

		sendmidi(0xf0);
		sendmidi(0x41);
		sendmidi(0x10);
		sendmidi(0x16);
		sendmidi(0x12);		/* DT1 - Data set 1 command */
		addbyte = ((intadd >> 16) & 0x7f);	/* address msb */
		sendmidi(addbyte);
		cksum = addbyte;
		addbyte = ((intadd >> 8) & 0x7f);
		sendmidi(addbyte);
		cksum += addbyte;
		addbyte = (intadd & 0x7f);		/* address lsb */
		sendmidi(addbyte);
		cksum += addbyte;

		for(n = 256; n < 512; n++) {
			databyte = data[curoff + n + RESERVESIZE] & 0x7f;
			sendmidi(databyte);
			cksum += databyte;
		}
		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);

		intadd += 256;

		if((intadd & 0x8000) != 0) {
			intadd &= 0x7f7f7f;
			intadd += 0x10000;
		}

		sendmidi(0xf0);
		sendmidi(0x41);
		sendmidi(0x10);
		sendmidi(0x16);
		sendmidi(0x12);		/* DT1 - Data set 1 command */
		addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
		sendmidi(addbyte);
		cksum = addbyte;
		addbyte = ((curadd >> 8) & 0x7f);
		sendmidi(addbyte);
		cksum += addbyte;
		addbyte = (curadd & 0x7f);		/* address lsb */
		sendmidi(addbyte);
		cksum += addbyte;

		for(n = 512; n < (D10URPSIZE - 512); n++) {
			databyte = data[curoff + n + RESERVESIZE] & 0x7f;
			sendmidi(databyte);
			cksum += databyte;
		}
		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);

		curadd += 0x44c;		/* D10URPSIZE */

		if((curadd & 0x80) != 0) {
			curadd &= 0x7fff7f;
			curadd += 0x100;
		}
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}
		curoff += (D10URPSIZE + RESERVESIZE);
	}
	return(0);
}

/* end */
