/*
 *	For the second time, pack.c
 *
 *	Pack and unpack DX7 voice data blocks from and into our
 *	infernal structures
 *	
 *	char *pack155(struct dx7voice *)
 *		construct data block to transmit from voice structure
 *	struct dx7voice *unpack155(char *)
 *		construct voice structure from data block
 */
#include "dx7.h"

pack155(v, buf)
struct dx7voice *v;
char *buf;		/* pointer to 155-byte buf of char */
{
	char *p = buf;		/* Write pointer into buf */
	int i, j;		/* for various loops */
	char sum;		/* checksum */

	/*
	 * Check structure padding of operator structures.
	 * Distance from first to last should be size - 1
	 */
	if ((char *)&(v->op[0].detune) - (char *)&(v->op[0]) != 21 - 1) {
		error("Internal error in pack(): Padding of operator structure is wrong on this machine");
	}

	/* operators 6 .. 1 in that order */
	for (i=0; i<6; i++) {
		bcopy(p, (char *) &(v->op[i]), 21);
		p += 21;
	}	

	if ((char *) &(v->name[10]) - (char *) &(v->peg_rate[0]) != 155-126) {
		error("Internal error in pack(): Padding of voice structure is wrong on this machine");
		exit(1);
	}

	bcopy(p, (char *) &(v->peg_rate[0]), 155-126);	
	p += 155-126;
	
	if (p - buf != 155) {
		error("Internal error in pack()");
	}
}

unpack155(buf, v)
char *buf;		/* pointer to 155-byte buf of char */
struct dx7voice *v;
{
	char *p = buf;			/* read pointer into buf */
	int i, j;			/* control variables for various loops */

	/*
	 * Check size of operator structures.
	 * Distance from first to last should be size - 1
	 */
	if ((char *)&(v->op[0].detune) - (char *)&(v->op[0]) != 20) {
		error("Internal error in unpack: Padding of operator structure is wrong on this machine");
		exit(1);
	}

	/* copy operators 6 .. 1 in that order */
	for (i=0; i<6; i++) {
		bcopy((char *) &(v->op[i]), p, 21);
		p += 21;
	}	

	/* and the rest of the structure */
	if ((char *) &(v->name[10]) - (char *) &(v->peg_rate[0]) != 155-126) {
		error("Internal error in unpack(): Padding of voice structure is wrong on this machine");
		exit(1);
	}

	/* copy the rest of the params. 21 * 6 = 126. */
	bcopy((char *) &(v->peg_rate[0]), p, 155-126);	
	p += 155-126;

	if (p - buf != 155) {
		error("Internal error in unpack155()");
	}
}

pack128(v, buf)
struct dx7voice *v;
char *buf;		/* pointer to 128-byte buffer of char */
{
	register char *cp = buf;	/* where to put next item into buf */
	register int i;

	for (i=0; i<6; i++) {
		register struct dx7operator *op = &v->op[i];

		/* items 0-10 can be copied straight */
		bcopy(cp, (char *)op, 11);
		cp += 11;

		*cp++ = (op->kls_rcurve << 2) | op->kls_lcurve;
		*cp++ = (op->detune << 3) | op->k_rate_scale;
		*cp++ = (op->vel_sens << 2) | op->mod_sens;
		*cp++ = op->out_level;
		*cp++ = (op->freq_coarse << 1) | op->osc_mode;
		*cp++ = op->freq_fine;
	}

	/* Pitch eg stuff + algorithm select */
	bcopy(cp, (char *) &v->peg_rate[0], 9);
	cp += 9;

	*cp++ = (v->osc_sync << 3) | v->feedback;

	/* lfo speed, delay, pmd, amd */
	bcopy(cp, (char *) &v->lfo_speed, 4);
	cp += 4;

	*cp++ = (v->lfo_pms << 4) | (v->lfo_wave << 1) | v->lfo_sync;

	/* transpose and voice name */
	bcopy(cp, &v->transpose, 11);
	cp += 11;

	if (cp - buf != 128) {
		error("Internal error in pack128");
	}
}
