[comp.sources.misc] v06i109: glib part 8 of 15

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (05/15/89)

Posting-number: Volume 6, Issue 109
Submitted-by: lee@uhccux.uhcc.Hawaii.Edu (Greg Lee )
Archive-name: glib/part08

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 15)."
# Contents:  dep5.mnu mac-mdr.a tx81p.mnu
# Wrapped by lee@uhccux on Sun May  7 00:40:15 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dep5.mnu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dep5.mnu'\"
else
echo shar: Extracting \"'dep5.mnu'\" \(18882 characters\)
sed "s/^X//" >'dep5.mnu' <<'END_OF_FILE'
X/* $Id: dep5.mnu,v 1.6 89/05/06 17:13:20 lee Exp $
X * GLIB - a Generic LIBrarian and editor for synths
X *
X * DEP-5 routines.
X * Tim Thompson
X *
X * The DEP-5 is a mess, the code below is likewise.  There are only 12
X * parameters or so, but there are 11 algorithms, and different parameters
X * have different meanings and ranges in each algorithm.  Also, the displayed
X * values have NO regular relationship to the byte values of the parameters,
X * hence the need for all the huge tables.
X *
X * modifications: Greg Lee
X * $Log:	dep5.mnu,v $
X * Revision 1.6  89/05/06  17:13:20  lee
X * rel. to comp.sources.misc
X * 
X * 
X */
X
X#define OVERLAY2
X
X#include "glib.h"
X#include <ctype.h>
X
X#define DEP5VSIZE 42
X#define DEP5NSIZE 16
X#define DEP5NVOICES 99
X#define RESERVESIZE 0
X
Xchar D5buff[16];
Xint Alg;	/* current algorithm, 0-10 */
X
Xchar *visnum(), *visonoff(), *vism3num(), *viswave(), *vismono();
Xchar *visd5alg(), *visdcr(), *visdcd(), *visdcf(), *visdrs(), *visd5pd();
Xchar *visd5rt(), *visd5hf(), *visd5no(), *visd5q(), *visd5fm(), *visd5bc();
X
Xstruct numpair {
X	int np_byte;
X	int np_val;
X};
X
Xstruct hfpair {
X	short hf_byte;
X	short hf_val;
X};
X
X
X#define NUMHF 96
X#define NUMCD 223
X#define NUMFREQ 128
X#define NUMGATE 256
X#define NUMCF 256
X#define NUMCR 97
X#define NUMNLRT 151
X#define NUMRT 153
X#define NUMDT 256
X#define NUMPD 256
Xstruct numpair *Revtime;
Xstruct numpair *Nlrevtime;
Xstruct hfpair *Hf;
Xstruct numpair *Chdepth;
Xstruct numpair *Chrate;
Xint *Predly;
Xint *Chfeed;
Xint *Dtime;
Xint *Freqmid;
Xint *Gatetime;
X
X/* This array contains arbitrary screen labels */
Xstruct labelinfo Ldep5[] = {
X#MENU
X
X
X                 Algorithm %
X                 ===========
X
X<Equalizer>                       <Chorus>
X   Output Level        %                 Feedback of Chorus   %
X   Boost/Cut of Low    %                 Rate of Chorus       %
X   Boost/Cut of Mid    %                 Depth of Chorus      %
X   Boost/Cut of High   %          <Reverb>
X   Q of Mid            %                 Pre-Delay            %
X   Freq (KHz) of Mid   %                 Reverb Time          %
X                                         HF Damping           %
X-------------------------+               Reverb Selection     %
XN - set name  q - quit   |        <Non-Linear>
Xh - left      j - down   |
Xk - up        l - right  |
XJ - decr      K - incr   |
Xspace = play auto-note   |
X                         |        <Delay>
XAuto-Note:               |
X   Pitch %    Vol  %     |
X   Dur   %    Chan %     |
X                         |
X#END
X-1,-1,NULL
X};
X
Xstruct paraminfo  Pdep5[] =  {
X/*
XNAME		TYPE		POS	MAX	OFFSET	MASK	SHIFT	ADHOC
X */
X#O algorithm	d5alg	%%	10	0
X#O chorfeed	dcf	%%	255	0
X#O outlev	num	%%	99	1
X#O chorrate	dcr	%%	96	0
X#O lowfilt	d5bc	%%	24	0
X#O chordepth	dcd	%%	222	0
X#O midfilt	d5bc	%%	24	0
X#O highfilt	d5bc	%%	24	0
X#O predelay	d5pd	%%	255	0
X#O q		d5q	%%	90	2
X#O reverbtime	d5rt	%%	152	0
X#O freqmid	d5fm	%%	127	3
X#O hfdamp	d5hf	%%	95	0
X#O reverbsel	drs	%%	21	0
X#O autovol	num	%%	127	-63
X#O autopitch	num	%%	127	-60
X#O autochan	num	%%	16	-1	*5
X#O autodur	num	%%	20	-5	*5
XNULL,NULL,-1,-1,-1,-1,visnum,0,0,0,0
X};
X
X
X/*
X * dep5din
X *
X * Take info from 'data' and stuff values in the P array, by using
X * the setval functionms.
X */
X
Xdep5din(data)
Xchar *data;
X{
X	initdp5();
X
X	Alg = d5algin(data[16] | ((data[17]&0xf)<<4));
X	setval("algorithm", Alg);
X
X	setval("reverbsel",data[0]);
X	setval("outlev",data[1]);
X	setval("q",data[2]);
X	setval("freqmid",data[3]);
X	/* these parameters take up 2 bytes (4bits in each) */
X	setval("lowfilt", d5bcin(data[4] | ((data[5]&0xf)<<4)) );
X	setval("midfilt", d5bcin(data[6] | ((data[7]&0xf)<<4)) );
X	setval("highfilt", d5bcin(data[8] | ((data[9]&0xf)<<4)) );
X	setval("chorfeed", data[10] | ((data[11]&0xf)<<4) );
X	setval("chorrate",d5vin(Chrate,data[12] | ((data[13]&0xf)<<4)));
X	setval("chordepth",d5vin(Chdepth,data[14] | ((data[15]&0xf)<<4)));
X	setval("predelay", data[18] | ((data[19]&0xf)<<4) );
X	setval("reverbtime", d5rtin(data[20] | ((data[21]&0xf)<<4)) );
X	setval("hfdamp", d5hfin(data[22] | ((data[23]&0xf)<<4)) );
X
X	setval("autochan",Channel);
X
X}
X
X/*
X * dep5dout
X *
X * Take (possibly changed) parameters values out of the P array and
X * put them back into 'data'.
X */
X
Xdep5dout(data)
Xchar *data;
X{
X	int n, alg;
X
X	alg = d5algout(getval("algorithm"));
X	data[16] = alg & 0xf;
X	data[17] = (alg >> 4) & 0xf;
X
X	data[0] = getval("reverbsel");
X	data[1] = getval("outlev");
X	data[2] = getval("q");
X	data[3] = getval("freqmid");
X
X	/* these parameters take up 2 bytes (4bits in each) */
X	n = d5bcout(getval("lowfilt"));
X	data[4] = n & 0xf;
X	data[5] = (n >> 4) & 0xf;
X	n = d5bcout(getval("midfilt"));
X	data[6] = n & 0xf;
X	data[7] = (n >> 4) & 0xf;
X	n = d5bcout(getval("highfilt"));
X	data[8] = n & 0xf;
X	data[9] = (n >> 4) & 0xf;
X	n = getval("chorfeed");
X	data[10] = n & 0xf;
X	data[11] = (n >> 4) & 0xf;
X	n = d5crout(getval("chorrate"));
X	data[12] = n & 0xf;
X	data[13] = (n >> 4) & 0xf;
X	n = d5cdout(getval("chordepth"));
X	data[14] = n & 0xf;
X	data[15] = (n >> 4) & 0xf;
X	n = getval("predelay");
X	data[18] = n & 0xf;
X	data[19] = (n >> 4) & 0xf;
X	n = d5rtout(getval("reverbtime"));
X	data[20] = n & 0xf;
X	data[21] = (n >> 4) & 0xf;
X	n = d5hfout(getval("hfdamp"));
X	data[22] = n & 0xf;
X	data[23] = (n >> 4) & 0xf;
X
X	Channel = getval("autochan");
X}
X
X/*
X * dep5sedit
X *
X * Send a single voice to the edit buffer of the dep5.
X */
Xdep5sedit(data)
Xchar *data;
X{
X	dep5parms(data);
X}
X
Xdep5parms(data)
Xchar *data;
X{
X	int n;
X
X	sendmidi(0xf0);
X	sendmidi(0x41);		/* Roland */
X	sendmidi(0x35);		/* operation code = APR (all parameters) */
X	sendmidi(Channel-1);	/* MIDI channel */
X	sendmidi(0x52);		/* format type */
X	sendmidi(0x20);		/* level # = 1 */
X	sendmidi(0x01);		/* group # = 1 */
X	/* send 24 bytes of parameter info */
X	for ( n=0; n<24; n++ ) {
X		sendmidi((int)(data[n]));
X	}
X	sendmidi(EOX);
X}
X
X/* dep5nof - return a pointer to the voice name buried in data */
Xchar *
Xdep5nof(data)
Xchar *data;
X{
X	static char currbuff[DEP5NSIZE+1];
X	char *p;
X	int m;
X
X	p = currbuff;
X	for ( m=0; m<DEP5NSIZE; m++ )
X		*p++ = data[24+m];
X	*p = '\0';
X	return(currbuff);
X}
X
X/* setnameof - set the voice name buried in data to name */
Xdep5snof(data,name)
Xchar *data;
Xchar *name;
X{
X	char *p;
X	int m;
X
X	for ( p=name,m=0; *p!='\0' && m<DEP5NSIZE; p++,m++ )
X		data[24+m] = *p;
X	for ( ; m<DEP5NSIZE; m++ )
X		data[24+m] = '\0';
X}
X
X/* dep5sone - send and store one voice */
Xdep5sone(voicenum,data)
Xchar *data;
X{
X	/* Send the parameters for this voice. */
X	dep5parms(data);
X
X	/* now ask it to be stored into memory */
X	sendmidi(0xf0);
X	sendmidi(0x41);		/* Roland */
X	sendmidi(0x34);		/* operation code = PGR (program #) */
X	sendmidi(Channel-1);	/* MIDI channel */
X	sendmidi(0x52);		/* format type */
X	sendmidi(0x20);		/* level # = 1 */
X	sendmidi(0x00);		/* group # = 0 */
X	sendmidi(0x00);		/* extension = 0 */
X	sendmidi(voicenum & 0x7f);	/* memory number (minus 1) */
X	sendmidi(0x02);		/* writing data to memory */
X	sendmidi(EOX);
X	
X	Reason = "";
X	return(0);	/* can't fail */
X}
X
Xchar *D5alg[] = {
X"1    ---EQ---Chorus---<~u/----~d~d~l~l~l~l~l\\----",
X"2    ---EQ---Reverb---<~u/----~d~d~l~l~l~l~l\\----",
X"3    ---EQ---Reverb(Mod)---<~u/----~d~d~l~l~l~l~l\\----",
X"4    ---EQ---Reverb(Mod)---Chorus---<~u/----~d~d~l~l~l~l~l\\----",
X"5    ---EQ-+-Reverb--<   +-Chorus---<~u/~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l\
X/~u/--------------+---~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~d~d~d~\
Xl~l~l~l~l~l~l~l~l|__________\\__|~l~l~l~d\\--------------~l~u\\~d+---",
X"6    ---EQ---Reverb--<--Chorus---<~u/~l~l~l~l~l~l~l~l~l~l~l~l~l\
X/~u/-----------+---~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~d~d~d~\
Xl\\~d\\-----------~l~u\\~d+---",
X"7    ---EQ---NLR---<~u/----~d~d~l~l~l~l~l\\----",
X"8    ---EQ---NLR(Mod)---<~u/----~d~d~l~l~l~l~l\\----",
X"9    ---EQ---NLR--<--Chorus---<~u/~l~l~l~l~l~l~l~l~l~l~l~l~l\
X/~u/-----------+---~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~d~d~d~\
Xl\\~d\\-----------~l~u\\~d+---",
X"10   ---EQ---Delay--<--Chorus---<~u/~l~l~l~l~l~l~l~l~l~l~l~l~l\
X/~u/-----------+---~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~l~d~d~d~\
Xl\\~d\\-----------~l~u\\~d+---",
X"11   ---EQ---NLR(Mod)---<~u/----~d~d~l~l~l~l~l\\----",
X};
X
X#define NPARM 12
Xchar Algparms[][NPARM] = {
X1,1,1,0,0,0,0,1,1,1,1,1,	/* alg 1 */
X0,0,0,1,1,1,1,1,1,1,1,1,	/* alg 2 */
X0,1,1,1,1,1,1,1,1,1,1,1,	/* alg 3 */
X1,1,1,1,1,1,1,1,1,1,1,1,	/* alg 4 */
X1,1,1,1,1,1,1,1,1,1,1,1,	/* alg 5 */
X1,1,1,1,1,1,1,1,1,1,1,1,	/* alg 6 */
X0,0,0,1,1,1,1,1,1,1,1,1,	/* alg 7 */
X0,1,1,1,1,1,1,1,1,1,1,1,	/* alg 8 */
X1,1,1,1,1,1,1,1,1,1,1,1,	/* alg 9 */
X1,1,1,1,1,1,1,1,1,1,1,1,	/* alg 10 */
X0,1,1,1,1,1,1,1,1,1,1,1		/* alg 11 */
X};
X/* for the parameters in the array above, Algmap gives the index in P */
Xint Algmap[] = {1,2,3,4,5,6,7,8,9,10,11,12};
X
X/*
X * visd5alg
X *
X * Whenever the algorithm is changed, we have to change the
X * meanings/locations/ranges of various parameters.
X */
X
Xchar *
Xvisd5alg(v)
X{
X	static int rt = -1, pd, hf, rs;
X	int n;
X
X	if ( rt == -1 ) {
X		pd = parmindex("predelay");
X		hf = parmindex("hfdamp");
X		rt = parmindex("reverbtime");
X		rs = parmindex("reverbsel");
X	}
X	if ( v >= 0 && v <= 10 ){
X		Alg = v;
X		/* Enable the parameters that this algorithm uses */
X		for ( n=0; n<NPARM; n++ ) {
X			if ( Algparms[v][n] == 1 )
X				enableparm(Algmap[n]);
X			else
X				disableparm(Algmap[n]);
X		}
X		if ( v == 9 ) {
X			P[pd].p_vrow=P[pd].p_lrow=20;
X			P[pd].p_label = "Delay Time";
X
X			P[rt].p_vrow=P[rt].p_lrow=21;
X			P[rt].p_label = "Delay Feedback";
X			P[rt].p_max = 255;
X
X			P[hf].p_vrow=P[hf].p_lrow=22;
X			P[hf].p_label = "HF Damp";
X			P[hf].p_max = 95;
X
X			P[rs].p_vrow=P[rs].p_lrow=23;
X			P[rs].p_label = "Delay Output";
X			P[rs].p_max = 2;
X		}
X		else if ( v<6 ) {
X			P[pd].p_vrow=P[pd].p_lrow=10;
X			P[pd].p_label = "Pre-Delay";
X
X			P[rt].p_vrow=P[rt].p_lrow=11;
X			P[rt].p_label = "Reverb Time";
X			P[rt].p_max = 152;
X
X			P[hf].p_vrow=P[hf].p_lrow=12;
X			P[hf].p_label = "HF Damp";
X			P[hf].p_max = 95;
X
X			P[rs].p_vrow=P[rs].p_lrow=13;
X			P[rs].p_label = "Reverb Selection";
X			P[rs].p_max = 21;
X		}
X		else {
X			P[pd].p_vrow=P[pd].p_lrow=15;
X			P[pd].p_label = "NL Pre-Delay";
X
X			P[rt].p_vrow=P[rt].p_lrow=16;
X			P[rt].p_label = "NL Reverb Time";
X			P[rt].p_max = 150;
X
X			P[hf].p_vrow=P[hf].p_lrow=17;
X			P[hf].p_label = "NL Gate Time";
X			P[hf].p_max = 255;
X
X			P[rs].p_vrow=P[rs].p_lrow=18;
X			P[rs].p_label = "NL Output";
X			P[rs].p_max = 2;
X		}
X		Redraw = 1;
X		return(D5alg[v]);
X	}
X	else
X		return("????");
X}
X
Xint Algval[] = { 0, 3, 31, 59, 87, 115, 143, 171, 199, 227, 255 };
X
Xd5algin(d)
X{
X	int n = 0;
X
X	while ( d >= Algval[n] && n <= 10 )
X		n++;
X	return(n-1);
X}
X
Xd5algout(v)
X{
X	return(Algval[v]);
X}
X
Xd5vin(nparr,v)
Xstruct numpair *nparr;
X{
X	int n;
X
X	for ( n=0; nparr[n].np_val >= 0; n++ ) {
X		if ( v <= nparr[n].np_byte )
X			return(n);
X	}
X	return(0);
X}
X
Xchar *
Xvisdcr(v)
X{
X	if ( v >= 0 && v< NUMCR ) {
X		v = Chrate[v].np_val;
X		sprintf(D5buff,"%d.%d",v/10,v%10);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
X
Xd5crout(v)
X{
X	if ( v >= 0 && v< NUMCR )
X		return(Chrate[v].np_byte);
X	else
X		return(0);
X}
X
Xchar *
Xvisdcd(v)
X{
X	if ( v >= 0 && v< NUMCD ) {
X		v = Chdepth[v].np_val;
X		sprintf(D5buff,"%d.%d",v/10,v%10);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
Xd5cdout(v)
X{
X	if ( v >= 0 && v< NUMCD )
X		return(Chdepth[v].np_byte);
X	else
X		return(0);
X}
X
X
Xchar *
Xvisdcf(v)
X{
X	if ( v >= 0 && v< 256 ) {
X		v = Chfeed[v];
X		sprintf(D5buff,"%d.%d",v/10,v%10);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
X
Xchar *
Xvisd5no(v)
X{
X	char *p;
X	switch (v) {
X	case 0: p = "Normal"; break;
X	case 1: p = "Pan B to A"; break;
X	case 2: p = "Pan A to B"; break;
X	}
X	return(p);
X}
X
Xchar *
Xvisddo(v)
X{
X	char *p;
X	switch (v) {
X	case 0: p = "Normal"; break;
X	case 1: p = "Invert Phase"; break;
X	case 2: p = "Pan A to B"; break;
X	}
X	return(p);
X}
X
Xchar *Revsel[] = { "Special 1", "Special 2", "Plate 1", "Plate 2",
X  "Hall 14'","Hall 20'","Hall 27'","Hall 36'","Hall 48'","Hall 61'","Hall 76'",
X  "Room 0.3'","Room 1.4'","Room 3.1'","Room 8.2'","Room 14'","Room 20'",
X  "Room 27'","Room 36'","Room 48'","Room 61'","Room 76'"
X};
X
Xchar *
Xvisdrs(v)
X{
X	/* For algorithms 6,7,8,10, the reverb select parameter */
X	/* is the NL output */
X	if ( Alg==6 || Alg==7 || Alg==8 || Alg==10 )
X		return(visd5no(v));
X	if ( Alg == 9 )
X		return(visddo(v));
X	if ( v>=0 && v<22 ) {
X		rtclip();
X		return(Revsel[v]);
X	}
X	return("??");
X}
X
Xchar *
Xvisddt(v)
X{
X	int rem;
X
X	if ( v < 0 || v >= NUMDT )
X		return("??");
X	v = Dtime[v];
X	if ( v < 1000 )
X		sprintf(D5buff,"%d",v);
X	else {
X		rem = (v%1000)/10;
X		sprintf(D5buff,(rem<10)?"%d.0%d":"%d.%d",v/1000,rem);
X	}
X	return(D5buff);
X}
X
Xchar *
Xvisd5pd(v)
X{
X	if ( v < 0 || v >= NUMPD )
X		return("??");
X	/* For algorithm 9 (aka 10), the predelay parameter is the delay time*/
X	if ( Alg == 9 )
X		return(visddt(v));
X	else
X		sprintf(D5buff,"%d",(int)Predly[v]);
X	return(D5buff);
X}
X
Xd5rtin(v)
X{
X	register int n;
X
X	if ( Alg==9 )
X		return(v);
X	else if ( Alg==6 || Alg==7 || Alg==8 || Alg==10 ) {
X		for ( n=0; n<NUMNLRT; n++ ) {
X			if ( v < Nlrevtime[n].np_byte )
X				break;
X		}
X		return(n-1);
X	}
X	else {
X		for ( n=0; n<NUMRT; n++ ) {
X			if ( v < Revtime[n].np_byte )
X				break;
X		}
X		return(n-1);
X	}
X}
X
Xd5rtout(v)
X{
X	if ( Alg==9 )
X		return(v);
X	else if ( Alg==6 || Alg==7 || Alg==8 || Alg==10 )
X		return(Nlrevtime[v].np_byte);
X	else
X		return(Revtime[v].np_byte);
X}
X
Xchar *
Xvisd5rt(v)
X{
X	/* In algorithm 9 (aka 10), the reverb time parameter is */
X	/* the delay feedback. */
X	if ( Alg == 9 ) {
X		if ( v<0 || v>=NUMCF )
X			return("??");
X		else
X			return(visdcf(v));
X	}
X	else if ( Alg==6 || Alg==7 || Alg==8 || Alg == 10 ) {
X		if ( v<0 || v>=NUMNLRT )
X			return("??");
X		v = Nlrevtime[v].np_val;
X		if ( v < 0 )
X			sprintf(D5buff,"-0.%d",-v);
X		else if ( v < 10 )
X			sprintf(D5buff,"0.%d",v);
X		else if ( v < 100 )
X			sprintf(D5buff,"%d.%d",v/10,v%10);
X		else
X			sprintf(D5buff,"%d",v/10);
X		return(D5buff);
X	}
X	else if ( v >= 0 && v < NUMRT ) {
X		v = rtclip();
X		v = Revtime[v].np_val;
X		if ( v < 100 )
X			sprintf(D5buff,"%d.%d  ",v/10,v%10);
X		else
X			sprintf(D5buff,"%d  ",v/10);
X		return(D5buff);
X	}
X	else
X		return("??  ");
X}
X
Xchar *
Xvisd5gt(v)
X{
X	if ( v >=0 && v < NUMGATE ) {
X		sprintf(D5buff,"%d",Gatetime[v]);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
X
X
Xchar *
Xvisd5hf(v)
X{
X	if ( Alg==6 || Alg==7 || Alg==8 || Alg==10 ) {
X		return(visd5gt(v));
X	}
X	else if ( v >= 0 && v < NUMHF ) {
X		v = Hf[v].hf_val;
X		if ( v >= 10 )
X			sprintf(D5buff,"%d.%d",v/100,v%100);
X		else
X			sprintf(D5buff,"0.0%d",v%100);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
X
Xd5hfout(v)
X{
X	if ( Alg==6 || Alg==7 || Alg==8 || Alg==10 )
X		return(v);
X	else
X		return(Hf[v].hf_byte);
X}
X
Xd5hfin(d)
X{
X	register int n;
X
X	if ( Alg==6 || Alg==7 || Alg==8 || Alg==10 )
X		return(d);
X	for ( n=0; Hf[n].hf_byte >= 0 ; n++ ) {
X		if ( d < Hf[n].hf_byte )
X			break;
X	}
X	return(n-1);
X}
X
Xint Revmin[] = { 10,10,7,7,1,2,3,4,5,6,7,1,1,1,1,1,2,3,4,5,6,7 };
Xint Revmax[] = { 990,990,990,990,200,400,720,990,990,990,990,
X  5,15,35,75,200,400,720,990,990,990,990
X};
X
Xrtclip()
X{
X	int rtval, rtype, origrtval;
X
X	origrtval = rtval = getval("reverbtime");
X	rtype = getval("reverbsel");
X	while ( Revtime[rtval].np_val < Revmin[rtype] )
X		rtval++;
X	while ( Revtime[rtval].np_val > Revmax[rtype] )
X		rtval--;
X	if ( rtval != origrtval ) {
X		setval("reverbtime",rtval);
X		showparam(parmindex("reverbtime"),0);
X	}
X	return(rtval);
X}
X
X#define NUMBOOST 25
Xstruct numpair Boost[] = {
X0,-12, 11,-11, 21,-10, 31,-9, 41,-8,
X52,-7, 62,-6, 72,-5, 82,-4, 92,-3,
X103,-2, 113,-1, 123,0, 133,1, 143,2,
X153,3, 164,4, 174,5, 184,6, 194,7,
X204,8, 215,9, 225,10, 235,11, 245,12,
X-1, -1
X};
X
Xd5bcin(v)
X{
X	register int n;
X
X	for ( n=0; Boost[n].np_byte >= 0 ; n++ ) {
X		if ( v < Boost[n].np_byte )
X			break;
X	}
X	return(n-1);
X}
Xd5bcout(v)
X{
X	return(Boost[v].np_byte);
X}
X
Xchar *
Xvisd5bc(v)
X{
X	if ( v >= 0 && v < NUMBOOST ) {
X		sprintf(D5buff,"%d",Boost[v].np_val);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
X
Xchar *
Xvisd5q(v)
X{
X	if ( v==0 )
X		return("0.2");
X	else if ( v <= 3 )
X		return("0.3");
X	else if ( v <= 90 ) {
X		sprintf(D5buff,"%d.%d",v/10,v%10);
X		return(D5buff);
X	}
X	else
X		return("??");
X}
X
Xchar *
Xvisd5fm(v)
X{
X	int rem;
X
X	if ( v < 0 || v > 127 )
X		return("??");
X	v = Freqmid[v];
X	if ( v < 100 )
X		sprintf(D5buff,"0.%d",v);
X	else if ( v < 1000 ) {
X		rem = v%100;
X		sprintf(D5buff,(rem<10)?"%d.0%d":"%d.%d",v/100,rem);
X	}
X	else
X		sprintf(D5buff,"%d.%d",v/100,(v/10)%10);
X	return(D5buff);
X}
X
Xinitdp5()
X{
X	static int initdone = 0;
X	int n1, n2, n;
X	FILE *f;
X
X	if ( initdone )
X		return;
X	initdone = 1;
X	printf("Reading data from 'glibinit.dp5' ...\n");
X
X	Chdepth = (struct numpair *) alloc(NUMCD * sizeof(struct numpair));
X	Chrate = (struct numpair *) alloc(NUMCR * sizeof(struct numpair));
X	Chfeed = (int *) alloc(NUMCF * sizeof(int));
X	Nlrevtime = (struct numpair *) alloc(NUMNLRT * sizeof(struct numpair));
X	Revtime = (struct numpair *) alloc(NUMRT * sizeof(struct numpair));
X	Freqmid = (int *) alloc(NUMFREQ * sizeof(int));
X	Gatetime = (int *) alloc(NUMGATE * sizeof(int));
X	Hf = (struct hfpair *) alloc(NUMHF * sizeof(struct hfpair));
X	Dtime = (int *) alloc(NUMDT * sizeof(int));
X	Predly = (int *) alloc(NUMPD * sizeof(int));
X
X	OPENTEXTFILE(f,"glibinit.dp5","r");
X	if ( f == NULL ) {
X		fprintf(stderr,"Hey, 'initdata.dp5' can't be opened!\n");
X		millisleep(2000);
X		return;
X	}
X
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMCD; n++ ) {
X		if ( fscanf(f,"%d,%d",&n1,&n2) != 2 )
X			goto err;
X		Chdepth[n].np_byte = n1;
X		Chdepth[n].np_val = n2;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMFREQ; n++ ) {
X		if ( fscanf(f,"%d",&n1) != 1 )
X			goto err;
X		Freqmid[n] = n1;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMHF; n++ ) {
X		if ( fscanf(f,"%d,%d",&n1,&n2) != 2 )
X			goto err;
X		Hf[n].hf_byte = n1;
X		Hf[n].hf_val = n2;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMGATE; n++ ) {
X		if ( fscanf(f,"%d",&n1) != 1 )
X			goto err;
X		Gatetime[n] = n1;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMCR; n++ ) {
X		if ( fscanf(f,"%d,%d",&n1,&n2) != 2 )
X			goto err;
X		Chrate[n].np_byte = n1;
X		Chrate[n].np_val = n2;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMNLRT; n++ ) {
X		if ( fscanf(f,"%d,%d",&n1,&n2) != 2 )
X			goto err;
X		Nlrevtime[n].np_byte = n1;
X		Nlrevtime[n].np_val = n2;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMCF; n++ ) {
X		if ( fscanf(f,"%d",&n1) != 1 )
X			goto err;
X		Chfeed[n] = n1;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMRT; n++ ) {
X		if ( fscanf(f,"%d,%d",&n1,&n2) != 2 )
X			goto err;
X		Revtime[n].np_byte = n1;
X		Revtime[n].np_val = n2;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMDT; n++ ) {
X		if ( fscanf(f,"%d",&n1) != 1 )
X			goto err;
X		Dtime[n] = n1;
X	}
X	if ( getcomment(f) )
X		goto err;
X	for ( n=0; n<NUMPD; n++ ) {
X		if ( fscanf(f,"%d",&n1) != 1 )
X			goto err;
X		Predly[n] = n1;
X	}
X	if ( getcomment(f) )
X		goto err;
X
X	return;
X    err:
X	fprintf(stderr,"Hey, something's wrong with initdata.dp5!\n");
X	millisleep(2000);
X	return;
X}
Xgetcomment(f)
XFILE *f;
X{
X	char buff[BUFSIZ];
X
X	if ( fscanf(f,"%s",buff) != 1 || *buff != '#' )
X		return(1);
X	return(0);
X}
END_OF_FILE
if test 18882 -ne `wc -c <'dep5.mnu'`; then
    echo shar: \"'dep5.mnu'\" unpacked with wrong size!
fi
# end of 'dep5.mnu'
fi
if test -f 'mac-mdr.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mac-mdr.a'\"
else
echo shar: Extracting \"'mac-mdr.a'\" \(14436 characters\)
sed "s/^X//" >'mac-mdr.a' <<'END_OF_FILE'
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X; $Id: mac-mdr.a,v 1.6 89/05/06 17:13:33 lee Exp $
X;
X; midi driver
X;
X; also includes a millisecond relative-time counter with 5 mS resolution
X;
X; Steven A. Falco  - moss!saf
X; 3/6/87
X; $Log:	mac-mdr.a,v $
X; Revision 1.6  89/05/06  17:13:33  lee
X; rel. to comp.sources.misc
X; 
X;
X; portions taken from article in nov 85 mactutor by Kirk Austin
X;
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;
X		BRANCH	SHORT		; use short displacements
X		CASE	ON		; be case-sensitive
X		STRING	PASCAL		; use pascal-style strings
X;
X; timer constants
X;
XTIME_INC	EQU	5		; granularity of timer
XMS5		EQU	3917		; VIA tics per 5 ms (1.2766 uS each)
X;
XT1VEC		EQU	24		; lvl1 trap table offset
XMAX_BYTE	EQU	$FF		; like it says
XVIAT1EN		EQU	$C0		; enable timer 1 interrupts
XVIAT1DI		EQU	$40		; diable timer 1  interrupts
XVIARUN		EQU	$40		; make T1 free-run
XVIASTOP		EQU	$3F		; put T1 in single-shot mode
X;
X; queue lengths
X;
XTxQSize		EQU	$100		; transmit buffer length
XRxQSize		EQU	$100		; receive buffer length
X;
X; queue state flags
X;
Xmidi_em		EQU	$FF		; queue is empty
Xmidi_ne		EQU	$00		; queue is not empty
X;
X; The following are stack offsets given that an item is passed
X; by the MPW C compiler and LINK/UNLK is used. DANGER!!!  MPW C
X; always passes in a long value.
X;
X; Note that in Pascal, a byte is passed as a short rather than a long...
X; so Get_Byte would be $9.  Also, in C, the caller cleans up, while in
X; Pascal the callee cleans up.
X;
XGet_Byte	EQU	$000B
XGet_Short	EQU	$000A
XGet_Long	EQU	$0008
X;
X; select one based on oscillator frequency used in hardware
X;
X;C_baud		EQU	%01000100	; 500 KHz
XC_baud		EQU	%10000100	; 1 MHz
X;C_baud		EQU	%11000100	; 2 MHz
X;
X; misc controls in SCC chip
X;
XNo_W_Req	EQU	0
XRx_off		EQU	%11000000
XTx_off		EQU	%01100010
XTRxC		EQU	%00101000
XBrgen_off	EQU	0
XRx_on		EQU	%11000001
XTx_on		EQU	%01101010
XDCD_int		EQU	%00001000
XRstExtSt	EQU	%00010000
XEnInt		EQU	%00010011
XMIntEn		EQU	%00001010
XEnMoInt		EQU	%00000001
XNo_Vec		EQU	%00000010
XaReset		EQU	%10000000
XrstTBE		EQU	$28
XrstEERR		EQU	$30
XNoData		EQU	$FFFF
X;
X; misc offsets in trap table
X;
XarxIO		EQU	24
XatxIO		EQU	16
XaspRC		EQU	28
X;
X; SR masks for interrupt control
X;
Xspl3		EQU	$0300		;set interrupt level to 3
X;
X; SCC registers
X;
XSCC0		EQU	0
XSCC1		EQU	1
XSCC2		EQU	2
XSCC3		EQU	3
XSCC4		EQU	4
XSCC5		EQU	5
XSCC6		EQU	6
XSCC7		EQU	7
XSCC8		EQU	8
XSCC9		EQU	9
XSCC10		EQU	10
XSCC11		EQU	11
XSCC12		EQU	12
XSCC13		EQU	13
XSCC14		EQU	14
XSCC15		EQU	15
X;
X; macro to enqueue a byte to be transmitted (can't use a subroutine
X; 'cause we expect the stack to be in a certain state!)
X;
X		MACRO
X		TxEnqueue
X		MOVE	TxByteIn(A5),D0		; where to put it (offset)
X		LEA	TxQueue(A5),A2		; base of queue
X		MOVE.B	Get_Byte(A6),0(A2,D0)	; copy it from the stack to the queue
X		ADDQ	#1,D0			; bump offset
X		CMP	#TxQSize,D0		; did it wrap?
X		BNE	@1			; nope
X		MOVE	#0,D0			; you betcha'
X@1		MOVE	D0,TxByteIn(A5)		; replace it
X		ENDM
X;
X; macro for delay (SCC is slow compared to 68000)
X;
X		MACRO
X		Delay
X		MOVE.L	(SP),(SP)
X		ENDM
X;
X; macro to load an SCC register (double moves are on purpose - slow down)
X;
X		MACRO
X		Lscc	&sreg,&val
X		MOVE.B	&sreg,D0
X		MOVE.B	D0,(A0)
X		Delay
X		MOVE.B	&val,D0
X		MOVE.B	D0,(A0)
X		Delay
X		ENDM
X;
X; debug traps for Macsbug
X;
XDbgb		OPWORD	$A9FF		; breakpoint
XDbgs		OPWORD	$ABFF		; print string and breakpoint
X;
X; debug macro
X;
X		MACRO
X		Dbs	&string
X;		PEA	&string
X;		Dbgs
X		ENDM
X;
X; chip addresses and offsets
X;
X		PRINT	OFF
X		INCLUDE	'SysEqu.a'
X		PRINT	ON
X;
X; this code must always be resident so we load it in Main segment to
X; guarantee that.  (Ever call an interrupt handler that wasn't resident?)
X;
X		SEG	'Main'
X;
X; global area
X;
X		EXPORT (midi_txst, midi_rxst, midi_time):DATA
X;
XCtlOffset	DS.W	1			; channel control offset
XDataOffset	DS.W	1			; channel data offset
XChnReset	DS.B	1			; SCC channel reset select
XRxIntOffset	DS.W	1			; for dispatch table
XTxIntOffset	DS.W	1			; likewise
XSpecRecCond	DS.W	1			; and one more
X;
XTxQueue		DS.B	TxQSize			; Tx data queue
Xmidi_txst	DS.B	1			; the queue state
XTxByteIn	DS.W	1			; offset for enqueue
XTxByteOut	DS.W	1			; offset for dequeue
X;
XRxQueue		DS.B	RxQSize			; and the Rx queue
Xmidi_rxst	DS.B	1			; the queue state
XRxByteIn	DS.W	1			; offset for enqueue
XRxByteOut	DS.W	1			; offset for dequeue
X;
Xmidi_time	DS.L	1			; mS relative-time value
Xold_via_v	DS.L	1			; old VIA vector
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X; The following are interrupt handlers.  The system saves registers
X; D0-D3 and A0-A3 so we don't...
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X
X;
X; handler for time increment task
X;
Xup_it		PROC	ENTRY
X		MOVEM.L	A5,-(SP)		; we also use D0-D1/A0
X		MOVE.L	CurrentA5,A5		; we need the globals
X;		
X		Dbs	#'time interrupt'
X;	
X		MOVE.L	VIA,A0			; via base register
X		MOVE.L	#vT1C,D0		; low byte of counter
X		MOVE.B	0(A0,D0),D1		; reading clears the interrupt
X;		
X		MOVEQ	#TIME_INC,D0		; how much?
X		ADD.L	D0,midi_time(A5)	; kick it up
X;		
X		MOVEM.L (SP)+,A5
X		RTS
X		ENDP
X;
X; interrupt handler for received characters
X;
XRxIntHand	PROC	ENTRY
X		MOVEM.L	A5,-(SP)		; we also use D0-D1/A0-A2
X		MOVE.L	CurrentA5,A5		; we need the globals
X		MOVE.L	SCCRd,A0		; hardware addresses
X		MOVE.L	SCCWr,A1
X;
X		Dbs	#'rx interrupt'
X;
X		MOVE	DataOffset(A5),D0	; ... offset
X		MOVE.B	0(A0,D0),D1		; read the data - it's here given the interrupt
X		Delay
X		LEA	RxQueue(A5),A2		; base of destination queue
X		MOVE	RxByteIn(A5),D0		; ... offset
X		MOVE.B	D1,0(A2,D0)		; store it
X		MOVE.B	#midi_ne,midi_rxst(A5)	; guaranteed not empty
X		ADDQ	#1,D0			; we filled one
X		CMP	#RxQSize,D0		; wrapped it?
X		BNE	@1			; not yet
X		MOVE	#0,D0			; yes - reset to top
X;
X@1		MOVE	D0,RxByteIn(A5)		; replace the offset
X;
X		MOVEM.L	(SP)+,A5		; restore context
X		RTS				; back to user
X		ENDP
X;
X; interrupt handler for transmitted characters
X;
XTxIntHand	PROC	ENTRY
X		MOVEM.L	A5,-(SP)		; we also use D0-D1/A0-A2
X		MOVE.L	CurrentA5,A5
X		MOVE.L	SCCRd,A0		; read base
X		MOVE.L	SCCWr,A1		; write base
X;
X		Dbs	#'tx interrupt'
X;
X		TST.B	midi_txst(A5)		; is there something to write?
X		BEQ	@1			; no - pity
X		MOVE	CtlOffset(A5),D0	; offset to control
X		MOVE.B	#rstTBE,0(A1,D0)	; we saw the empty...
X		Delay
X		BRA	TxIExit			; nothing to be done
X;
X@1		MOVE	TxByteOut(A5),D0	; offset of something to send
X		LEA	TxQueue(A5),A2		; base of queue
X		MOVE	DataOffset(A5),D1	; offset to hardware
X		MOVE.B	0(A2,D0),0(A1,D1)	; move it out
X		Delay
X		ADDQ	#1,D0			; we used it up
X		CMP	#TxQSize,D0		; wrapped?
X		BNE	@2			; no...
X		MOVE	#0,D0			; 'fraid so
X;
X@2		MOVE	D0,TxByteOut(A5)	; remember position
X		MOVE	TxByteIn(A5),D1		; see about the input side
X		CMP	D0,D1			; now empty?
X		BNE	TxIExit			; no - just exit
X		MOVE.B	#midi_em,midi_txst(A5)	; it's empty
X;
XTxIExit
X		MOVEM.L	(SP)+,A5		; be polite
X		RTS
X		ENDP
X;
X; a stub for special conditions - we sort-of handle them
X;
XStub		PROC	ENTRY
X		MOVEM.L	A5,-(SP)		; we also use A0-A1
X		MOVE.L	CurrentA5,A5
X		MOVE.L	SCCRd,A0		; read base
X		MOVE.L	SCCWr,A1		; write base
X;
X		Dbs	#'stub interrupt'
X;
X		MOVE	CtlOffset(A5),D0	; offset to control
X		MOVE.B	#rstEERR,0(A1,D0)	; we saw the botch, clear it
X		Delay
X		MOVEM.L	(SP)+,A5
X		RTS
X		ENDP
X;
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X; The following routines interface to MPW C.  It considers D0-D1/A0-A1 as
X; scratch.  So do we.  Returned values are placed in D0 (32 bits always)
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;
X; init routine - must call this first to set up stuff!
X;
Xmidi_init	PROC	EXPORT
X		MOVE	#aCtl,CtlOffset(A5)
X		MOVE	#aData,DataOffset(A5)
X		MOVE.B	#aReset,ChnReset(A5)
X		MOVE	#arxIO,RxIntOffset(A5)
X		MOVE	#atxIO,TxIntOffset(A5)
X		MOVE	#aspRC,SpecRecCond(A5)
X;
X		MOVE	SR,-(SP)		; save interrupts
X						; we use D0-D1/A0-A1
X		ORI	#spl3,SR		; interrupts of 4 or better only		
X;
X		Dbs	#'init routine'
X;
X		MOVE.L	SCCRd,A1		; get base address
X		ADD	CtlOffset(A5),A1	; ... control
X		MOVE.B	(A1),D0			; dummy read to clear SCC WR0
X		Delay
X;
X; set up SCC channel A
X;
X		MOVE.L	SCCWr,A0		; another base address
X		ADD	CtlOffset(A5),A0	; ... control
X		Lscc	#SCC9,ChnReset(A5)	; reset channel
X		Lscc	#SCC4,#C_baud		; set clock rate
X		Lscc	#SCC1,#No_W_Req		; no write request
X		Lscc	#SCC3,#Rx_off		; turn it off
X		Lscc	#SCC5,#Tx_off		; him too
X		Lscc	#SCC9,#No_Vec		; not vectored interrupts
X		Lscc	#SCC11,#TRxC		; set clock source
X		Lscc	#SCC14,#Brgen_off	; no break gen
X		Lscc	#SCC3,#Rx_on		; now turn channel back on
X		Lscc	#SCC5,#Tx_on		; these on too
X		Lscc	#SCC15,#DCD_int		; Mr. Mousie on
X		Lscc	#SCC0,#RstExtSt		; reset ext status
X		Lscc	#SCC0,#RstExtSt		; reset ext status
X		Lscc	#SCC1,#EnInt		; enable interrupts
X		Lscc	#SCC9,#MIntEn		; master interrupt
X;
X; install trap vectors
X;
X		MOVE.L	#Lvl2DT,A0		; dispatch table
X		MOVE	RxIntOffset(A5),D0	; ... offset
X		LEA	RxIntHand,A1		; pointer to handler
X		MOVE.L	A1,0(A0,D0)		; load the pointer into the dispatch table
X		MOVE	TxIntOffset(A5),D0	; ... offset
X		LEA	TxIntHand,A1		; another pointer
X		MOVE.L	A1,0(A0,D0)		; load it
X		MOVE	SpecRecCond(A5),D0	; ... offset
X		LEA	Stub,A1			; dummy handler
X		MOVE.L	A1,0(A0,D0)		; load it
X;
X; clear queues
X;
X		CLR	RxByteIn(A5)		; clear circ. buffer pointers
X		CLR	RxByteOut(A5)
X		MOVE.B	#midi_em,midi_rxst(A5)	; mark it empty
X		CLR	TxByteIn(A5)
X		CLR	TxByteOut(A5)
X		MOVE.B	#midi_em,midi_txst(A5)	; mark it empty
X;
X; get the timer going
X;
X		CLR.L	midi_time(A5)		; start clean
X;
X;		save old interrupt vector - write ours
X		MOVE.L	#Lvl1DT,A0		; via trap table base
X		MOVEQ	#T1VEC,D0		; offset to t1 trap
X		MOVE.L	0(A0,D0),old_via_v(A5)	; save the old one
X		LEA	up_it,A1		; our trap handler
X		MOVE.L	A1,0(A0,D0)		; set our handler in place
X;
X		MOVE.L	VIA,A0			; via base register
X;
X;		set the mode of operation - free running
X		MOVE.L	#vACR,D0		; offset to ACR
X		MOVE.B	0(A0,D0),D1		; read old acr value
X		AND.B	#VIASTOP,D1		; drop any existing T1 bits
X		OR.B	#VIARUN,D1		; set the free-run bit
X		MOVE.B	D1,0(A0,D0)		; put it back
X;
X;		set the latches and counters
X		MOVE.L	#vT1C,D0		; low byte of timer
X		MOVE.B	#(MS5 ** MAX_BYTE),0(A0,D0) ; write low byte
X		MOVE.L	#vT1CH,D0		; high byte of timer
X		MOVE.B	#((MS5 >> 8) ** MAX_BYTE),0(A0,D0) ; write high byte
X;
X		MOVE.L	#vIER,D0		; enable/disable register
X		MOVE.B	#VIAT1EN,0(A0,D0)	; enable that interrupt!
X;
X		MOVE	(SP)+,SR		; interrupts on
X		RTS
X		ENDP
X;
X; midi_tx - send a byte to the midi port (we expect the stack to contain a long)
X;
Xmidi_tx		PROC	EXPORT
X		LINK	A6,#0			; remember where our argument is
X		MOVE	SR,-(SP)		; save interrupts
X		MOVEM.L	A2,-(SP)		; we also use D0/A0-A1
X		ORI	#spl3,SR		; interrupts of 4 or better only
X;
X		Dbs	#'transmit routine'
X;
X		TST.B	midi_txst(A5)		; check the flag
X		BNE	TxQE			; queue empty - send direct
X		; something here - just add to queue
X		TxEnqueue
X		BRA	TxExit			; go home	
X;
XTxQE		; must write directly to device (maybe)
X		MOVE.L	SCCRd,A0		; read base
X		MOVE.L	SCCWr,A1		; write base
X		MOVE	CtlOffset(A5),D0	; ... offset
X		BTST.B	#txBE,0(A0,D0)		; is the device ready
X		BNE	FirstByte		; yes - do direct write
X		; device busy - add to queue - interrupt will wake up
X		; handler and send it out when the device is free
X		TxEnqueue
X		MOVE.B	#midi_ne,midi_txst(A5)	; now it's not empty
X		BRA	TxExit			; done
X;
XFirstByte	; it really wants this byte...
X		MOVE	DataOffset(A5),D0	; ... offset
X		Delay
X		MOVE.B	Get_Byte(A6),0(A1,D0)	; copy it from the stack to the device
X		Delay
X;
XTxExit		; clean up the world
X		MOVEM.L	(SP)+,A2		; restore registers
X		MOVE	(SP)+,SR		; and interrupts
X		UNLK	A6
X		RTS				; in C, the caller cleans up
X		ENDP
X;
X; midi_rx - get a byte from the port (leave it in D0 as a long)
X; We return -1 if nothing is available
X;
Xmidi_rx		PROC	EXPORT
X		; don't need link 'cause nothing is passed in
X		MOVE	SR,-(SP)		; save the interrupts
X		MOVEM.L	D2/A2,-(SP)		; we also use D0-D1/A0-A1
X		ORI	#spl3,SR		; interrupts of 4 or better only
X;
X		Dbs	#'receive routine'
X;
X		TST.B	midi_rxst(A5)		; any data available?
X		BEQ	@1			; yes
X		MOVE.W	#NoData,D0		; no-data flag
X		EXT.L	D0			; sign-extend it
X		BRA	RxExit			; C returns stuff in D0
X;
X@1		MOVE	RxByteOut(A5),D2	; ... offset
X		LEA	RxQueue(A5),A2		; and base
X		CLR.L	D0			; start off empty
X		MOVE.B	0(A2,D2),D0		; get the byte
X		ADDQ	#1,D2			; up the offset
X		CMP	#RxQSize,D2		; wrapped around?
X		BNE	@2			; not yet
X		MOVE	#0,D2			; yes - reset it to the top
X;
X@2		MOVE	D2,RxByteOut(A5)	; and save it
X		MOVE	RxByteIn(A5),D1		; now look at the input side
X		CMP	D2,D1			; is the queue now empty?
X		BNE	RxExit			; no - don't worry about it
X		MOVE.B	#midi_em,midi_rxst(A5)	; yes - set the flag
X;
XRxExit
X		MOVEM.L	(SP)+,D2/A2		; restore registers
X		MOVE	(SP)+,SR		; and interrupts
X		RTS
X		ENDP
X;
X; reset the modem port - must call before quitting because the trap
X; vectors will be invalid once we exit!!!
X;
Xmidi_reset	PROC	EXPORT
X		MOVE	#aCtl,CtlOffset(A5)	; prepare globals
X		MOVE	#aData,DataOffset(A5)
X		MOVE.B	#aReset,ChnReset(A5)
X		MOVE	#arxIO,RxIntOffset(A5)
X		MOVE	#atxIO,TxIntOffset(A5)
X		MOVE	#aspRC,SpecRecCond(A5)
X;
X		MOVE	SR,-(SP)		; save interrupts
X						; we use A0
X		ORI	#spl3,SR		; interrupts of 4 or better only
X;
X		Dbs	#'reset routine'
X;
X		MOVE.L	SCCWr,A0		; base for writing
X		ADD	CtlOffset(A5),A0	; and the offset
X;
X		Lscc	#SCC9,ChnReset(A5)	; reset channel
X		Lscc	#SCC15,#DCD_int		; Mr. Mousie stays on
X		Lscc	#SCC0,#RstExtSt		; reset ext status
X		Lscc	#SCC0,#RstExtSt		; reset ext status
X		Lscc	#SCC1,#EnMoInt		; enable mouse interrupts
X		Lscc	#SCC9,#MIntEn		; master interrupt
X;
X; pull out the plug on the timer
X;
X;		first disable interrupts
X		MOVE.L	VIA,A0			; base of via
X		MOVE.L	#vIER,D0		; interrupt control reg.
X		MOVE.B	#VIAT1DI,0(A0,D0)	; kill the interrupts
X;
X;		next set back to single shot mode
X		MOVE.L	#vACR,D0		; offset to ACR
X		MOVE.B	0(A0,D0),D1		; read old acr value
X		AND.B	#VIASTOP,D1		; drop any existing T1 bits
X		MOVE.B	D1,0(A0,D0)		; put it back
X;
X;		set the latches to 0
X		MOVE.L	#vT1C,D0		; lower latch/counter
X		CLR.B	0(A0,D0)		; clear it too
X		MOVE.L	#vT1CH,D0		; offset to upper latch/counter
X		CLR.B	0(A0,D0)		; clear it
X;
X;		restore old trap vector
X		MOVE.L	#Lvl1DT,A0		; dispatch table
X		MOVEQ	#T1VEC,D0		; vector offset
X		MOVE.L	old_via_v(A5),0(A0,D0)	; reset the vector
X;
X; We don't turn the other vectors back to where they were...
X; We also don't leave any of our interrupts enabled so it's OK
X;
X		MOVE	(SP)+,SR		; interrupts on
X		RTS
X		ENDP
X;
X		END
X
END_OF_FILE
if test 14436 -ne `wc -c <'mac-mdr.a'`; then
    echo shar: \"'mac-mdr.a'\" unpacked with wrong size!
fi
# end of 'mac-mdr.a'
fi
if test -f 'tx81p.mnu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tx81p.mnu'\"
else
echo shar: Extracting \"'tx81p.mnu'\" \(14135 characters\)
sed "s/^X//" >'tx81p.mnu' <<'END_OF_FILE'
X/* $Id: tx81p.mnu,v 1.6 89/05/06 17:13:43 lee Exp $
X * GLIB - a Generic LIBrarian and editor for synths
X *
X * TX81Z routines for Performance parameters
X * Tim Thompson
X * modifications: Greg Lee
X * $Log:	tx81p.mnu,v $
X * Revision 1.6  89/05/06  17:13:43  lee
X * rel. to comp.sources.misc
X * 
X */
X
X#define OVERLAY1
X
X#include "glib.h"
X#include <ctype.h>
X
Xchar *visnum(), *viseffect(), *visass(), *viskey();
Xchar *vischan(), *visnote(), *vistdetune(), *vistout(), *vislfo();
Xchar *visponoff(), *vispvoice(), *vispshift();
X
Xstatic char Pbuff[17];
X
X#define PMEMSIZE 76
X#define PCEDSIZE 110
X
X#define RESERVESIZE 0
X
X/* This array contains arbitrary screen labels */
Xstruct labelinfo Ltx81p[] = {
X#MENU
X
X                  1      2      3      4      5      6      7      8
X                 ---    ---    ---    ---    ---    ---    ---    ---
X  Voice          %      %      %      %      %      %      %      %
X
X
X
X  Max Notes       %      %      %      %      %      %      %      %
X  Receive Ch.     %      %      %      %      %      %      %      %
X  Limit Low       %      %      %      %      %      %      %      %
X  Limit High      %      %      %      %      %      %      %      %
X  Detune          %      %      %      %      %      %      %      %
X  Note Shift      %      %      %      %      %      %      %      %
X  Volume          %      %      %      %      %      %      %      %
X  Out Assign      %      %      %      %      %      %      %      %
X  LFO Select      %      %      %      %      %      %      %      %
X  Micro Tune      %      %      %      %      %      %      %      %
X
X
X                                Micro Tune Table     %
X                                Micro Tune Key       %
X-------------------------+      Assign Mode          %
XAuto-Note: Pitch %       |      Effect Select        %
XVol %   Dur %   Chan %   |
X#END
X-1,-1,NULL
X};
X
Xstruct paraminfo  Ptx81p[] =  {
X/*
XNAME		TYPE	POS	MAX	OFFSET	MASK	SHIFT	ADHOC
X */
X#O op1voice	pvoice	%%	159	0
X#O op2voice	pvoice	%%	159	0
X#O op3voice	pvoice	%%	159	0
X#O op4voice	pvoice	%%	159	0
X#O op5voice	pvoice	%%	159	0
X#O op6voice	pvoice	%%	159	0
X#O op7voice	pvoice	%%	159	0
X#O op8voice	pvoice	%%	159	0
X#O op1max	num	%%	8	0
X#O op2max	num	%%	8	0
X#O op3max	num	%%	8	0
X#O op4max	num	%%	8	0
X#O op5max	num	%%	8	0
X#O op6max	num	%%	8	0
X#O op7max	num	%%	8	0
X#O op8max	num	%%	8	0
X#O op1rec	chan	%%	16	0
X#O op2rec	chan	%%	16	0
X#O op3rec	chan	%%	16	0
X#O op4rec	chan	%%	16	0
X#O op5rec	chan	%%	16	0
X#O op6rec	chan	%%	16	0
X#O op7rec	chan	%%	16	0
X#O op8rec	chan	%%	16	0
X#O op1liml	note	%%	127	0
X#O op2liml	note	%%	127	0
X#O op3liml	note	%%	127	0
X#O op4liml	note	%%	127	0
X#O op5liml	note	%%	127	0
X#O op6liml	note	%%	127	0
X#O op7liml	note	%%	127	0
X#O op8liml	note	%%	127	0
X#O op1limh	note	%%	127	0
X#O op2limh	note	%%	127	0
X#O op3limh	note	%%	127	0
X#O op4limh	note	%%	127	0
X#O op5limh	note	%%	127	0
X#O op6limh	note	%%	127	0
X#O op7limh	note	%%	127	0
X#O op8limh	note	%%	127	0
X#O op1detune	tdetune	%%	14	0
X#O op2detune	tdetune	%%	14	0
X#O op3detune	tdetune	%%	14	0
X#O op4detune	tdetune	%%	14	0
X#O op5detune	tdetune	%%	14	0
X#O op6detune	tdetune	%%	14	0
X#O op7detune	tdetune	%%	14	0
X#O op8detune	tdetune	%%	14	0
X#O op1shift	pshift	%%	48	0
X#O op2shift	pshift	%%	48	0
X#O op3shift	pshift	%%	48	0
X#O op4shift	pshift	%%	48	0
X#O op5shift	pshift	%%	48	0
X#O op6shift	pshift	%%	48	0
X#O op7shift	pshift	%%	48	0
X#O op8shift	pshift	%%	48	0
X#O op1vol	num	%%	99	0
X#O op2vol	num	%%	99	0
X#O op3vol	num	%%	99	0
X#O op4vol	num	%%	99	0
X#O op5vol	num	%%	99	0
X#O op6vol	num	%%	99	0
X#O op7vol	num	%%	99	0
X#O op8vol	num	%%	99	0
X#O op1out	tout	%%	3	0
X#O op2out	tout	%%	3	0
X#O op3out	tout	%%	3	0
X#O op4out	tout	%%	3	0
X#O op5out	tout	%%	3	0
X#O op6out	tout	%%	3	0
X#O op7out	tout	%%	3	0
X#O op8out	tout	%%	3	0
X#O op1lfo	lfo	%%	3	0
X#O op2lfo	lfo	%%	3	0
X#O op3lfo	lfo	%%	3	0
X#O op4lfo	lfo	%%	3	0
X#O op5lfo	lfo	%%	3	0
X#O op6lfo	lfo	%%	3	0
X#O op7lfo	lfo	%%	3	0
X#O op8lfo	lfo	%%	3	0
X#O op1micro	ponoff	%%	1	0
X#O op2micro	ponoff	%%	1	0
X#O op3micro	ponoff	%%	1	0
X#O op4micro	ponoff	%%	1	0
X#O op5micro	ponoff	%%	1	0
X#O op6micro	ponoff	%%	1	0
X#O op7micro	ponoff	%%	1	0
X#O op8micro	ponoff	%%	1	0
X#O microtune	num	%%	12	0
X#O microkey	key	%%	11	0
X#O assmode	ass	%%	1	0
X#O autopitch	num	%%	127	-60
X#O effect	effect	%%	3	0
X#O autochan	num	%%	16	-1	*5
X#O autodur	num	%%	20	-5	*5
X#O autovol	num	%%	127	-63
XNULL,NULL,-1,-1,-1,-1,visnum,0,0,0,0
X};
X
X
Xchar *tx81voices[] = {
X	"GrandPiano", "Uprt piano", "Deep Grd", "HonkeyTonk", "Elec Grand",
X	"Fuzz Piano", "SkoolPiano", "Thump Pno", "LoTine81Z", "HiTine81Z",
X	"ElectroPno", "NewElectro", "DynomiteEP", "DynoWurlie", "Wood Piano",
X	"Reed Piano", "PercOrgan", "16 8 4 2 F", "PumpOrgan", "<6 Tease>",
X	"Farcheeza", "Small Pipe", "Big Church", "AnalogOrgn", "Thin Clav",
X	"EZ Clav", "Fuzz Clavi", "LiteHarpsi", "RichHarpsi", "Celeste",
X	"BriteCelst", "Squeezebox",
X
X	"Trumpet81Z", "Full Brass", "Flugelhorn", "ChorusBras", "FrenchHorn",
X	"AtackBrass", "SpitBoneBC", "Horns BC", "MelloTenor", "RaspAlto",
X	"Flute", "Pan Floot", "Bassoon", "Oboe", "Clarinet",
X	"Harmonica", "DoubleBass", "BowCello", "BoxCello", "SoloViolin",
X	"HiString 1", "LowString", "Pizzicato", "Harp", "ReverbStrg",
X	"SynString", "Voices", "HarmoPad", "FanfarTpts", "HiString 2",
X	"PercFlute", "BreathOrgn",
X
X	"NylonGuit", "Guitar #1", "TwelveStrg", "Funky Pick", "AllThatJaz",
X	"HeavyMetal", "Old Banjo", "Zither", "ElecBass 1", "SqncrBass",
X	"SynFunkBas", "ElecBass 2", "AnalogBass", "Jaco Bass", "LatelyBass",
X	"MonophBass", "StadiumSol", "TrumptSolo", "BCSexyPhon", "Lyrisyn",
X	"WarmSquare", "Sync Lead", "MellowSqar", "Jazz Flute", "HeavyLead",
X	"Java Jive", "Xylophone", "GreatVibes	", "Sitar", "Bell Pad",
X	"PlasticHit", "DigiAnnie",
X
X	"BaadBreath", "VocalNuts", "KrstlChoir", "Metalimba", "WaterGlass",
X	"BowedBell", ">>WOW<<", "Fuzzy Koto", "Spc Midiot", "Gurgle",
X	"Hole in 1", "Birds", "MalibuNite", "Helicopter", "Flight Sim",
X	"Brthbells", "Storm Wind", "Alarm Call", "Racing Car", "Whistling",
X	"Space Talk", "Space Vibe", "Timpani", "FM Hi-Hats", "Bass Drum",
X	"Tube Bells", "Noise Shot", "Snare 1", "Snare 2", "Hand Drum",
X	"Synballs", "Efem Toms"
X};
X
X/*
X * tx8pdin
X *
X * Take info from 'data' and stuff values in the P array, by using
X * the setval (and setopval) functions.  The data is in PMEM format.
X */
X
Xtx8pdin(data)
Xchar *data;
X{
X	int dop, n, msb;
X
X	for ( n=1; n<=8; n++ ) {
X		dop = (n-1)*8;
X		setopval(n,"max",data[0+dop] & 017);
X		msb = (data[0+dop]>>4)&01;
X		setopval(n,"voice",128*msb + (data[1+dop]&0177));
X		setopval(n,"rec",data[2+dop] & 037);
X		setopval(n,"liml",data[3+dop] & 0177);
X		setopval(n,"limh",data[4+dop] & 0177);
X		setopval(n,"detune",data[5+dop] & 017);
X		setopval(n,"shift",data[6+dop] & 077);
X		setopval(n,"vol",data[7+dop] & 0177);
X		setopval(n,"out",(data[0+dop]>>5) & 03);
X		setopval(n,"lfo",(data[2+dop]>>5) & 03);
X		setopval(n,"micro",(data[6+dop]>>6) & 01);
X	}
X	setval("microtune",data[64] & 017);
X	setval("assmode",data[65] & 01);
X	setval("effect",(data[65]>>1) & 03);
X	setval("microkey",(data[65]>>3) & 017);
X
X	setval("autochan",Channel);
X}
X
X/*
X * tx8pdout
X *
X * Take (possibly changed) parameters values out of the P array and
X * put them back into 'data'.
X */
X
Xtx8pdout(data)
Xchar *data;
X{
X	int dop, n, voicenum, msb;
X
X	for ( n=1; n<=8; n++ ) {
X		dop = (n-1)*8;
X		voicenum = getopval(n,"voice");
X		msb = (voicenum>>7)&01;
X		data[0+dop] = getopval(n,"max") | (msb<<4)
X				| getopval(n,"out")<<5;
X		data[1+dop] = voicenum & 0177;
X		data[2+dop] = getopval(n,"lfo")<<5 | getopval(n,"rec");
X		data[3+dop] = getopval(n,"liml");
X		data[4+dop] = getopval(n,"limh");
X		data[5+dop] = getopval(n,"detune");
X		data[6+dop] = getopval(n,"micro")<<6 | getopval(n,"shift");
X		data[7+dop] = getopval(n,"vol");
X	}
X	data[64] = getval("microtune");
X	data[65] = getval("microkey")<<3 | getval("effect")<<1
X			| getval("assmode");
X	Channel = getval("autochan");
X}
X
Xtx8psedit(data)
Xchar *data;
X{
X	char pdata[PCEDSIZE];
X	int n, cksum, c;
X	char *p;
X
X	clrdata(pdata,PCEDSIZE);
X	pmemtopced(data,pdata);
X	sendmidi(0xf0);
X	sendmidi(0x43);
X	sendmidi(Channel-1);	/* channel # */
X	sendmidi(0x7e);		/* format type */
X	sendmidi(0x00);		/* byte count */
X	sendmidi(0x78);		/* byte count */
X	p = "LM  8976PE";
X	cksum = 0;
X	while ( (c=(int)(*p++)) != '\0' ) {
X		sendmidi(c);
X		cksum += c;
X	}
X	for ( n=0; n<PCEDSIZE; n++ ) {
X		c = (int)(pdata[n]);
X		sendmidi(c);
X		cksum += c;
X	}
X	sendmidi((-cksum) & 0x7f);
X	sendmidi(EOX);
X}
X
X/* Convert PMEM to PCED format */
Xpmemtopced(indata,outdata)
Xchar *indata, *outdata;
X{
X	int n, inop, outop;
X
X	for ( n=1; n<=8; n++ ) {
X		inop = (n-1)*8;
X		outop = (n-1)*12;
X
X		outdata[0+outop] = indata[0+inop] & 017;
X
X		outdata[1+outop] = (indata[0+inop]>>4)&01;
X		outdata[2+outop] = indata[1+inop] & 0177;
X		outdata[3+outop] = indata[2+inop] & 037;
X		outdata[4+outop] = indata[3+inop] & 0177;
X		outdata[5+outop] = indata[4+inop] & 0177;
X		outdata[6+outop] = indata[5+inop] & 017;
X		outdata[7+outop] = indata[6+inop] & 077;
X		outdata[8+outop] = indata[7+inop] & 0177;
X		outdata[9+outop] = (indata[0+inop]>>5) & 03;
X		outdata[10+outop] = (indata[2+inop]>>5) & 03;
X		outdata[11+outop] = (indata[6+inop]>>6) & 01;
X	}
X	outdata[96] = indata[64] & 017;
X	outdata[97] = indata[65] & 01;
X	outdata[98] = (indata[65]>>1) & 03;
X	outdata[99] = (indata[65]>>3) & 017;
X	for ( n=0; n<10; n++ )
X		outdata[100+n] = indata[66+n];
X}
X
X/* send a bulk performance dump to the tx81z */
Xtx8psbulk(data)
Xchar *data;
X{
X	int c, v, n, cksum;
X	char *p;
X
X	sendmidi(0xf0);
X	sendmidi(0x43);
X	sendmidi(Channel-1);	/* Channel # */
X	sendmidi(0x7e);
X	sendmidi(0x13);
X	sendmidi(0x0a);
X	p = "LM  8976PM";
X	cksum = 0;
X	while ( (c=(int)(*p++)) != '\0' ) {
X		sendmidi(c);
X		cksum += c;
X	}
X	/* send 32 PMEM's worth of data */
X	for ( v=0; v<32; v++ ) {
X		for ( n=0; n<PMEMSIZE; n++ ) {
X			/* 24 PMEM's are editable, but the bulk dump has 32 */
X			if ( v >= 24 )
X				c = 0;
X			else
X				c = VOICEBYTE(data,v,n);
X			sendmidi(c & 0xff);
X			cksum += c;
X		}
X	}
X	sendmidi((-cksum) & 0x7f);
X	sendmidi(0xf7);
X	return(0);
X}
X
X/* Request and read a bulk performance dump from the TX81Z */
Xtx8pgbulk(data)
Xchar *data;
X{
X	int c, n, v, b1, b2, cksum, ret = 1;
X	long begin, toolong;
X	char *p;
X
X	flushmidi();
X
X	sendmidi(0xf0);
X	sendmidi(0x43);
X	sendmidi(0x20 | (Channel-1));	/* Channel # */
X	sendmidi(0x7e);
X	p = "LM  8976PM";
X	while ( (c=(int)(*p++)) != '\0' )
X		sendmidi(c);
X	sendmidi(EOX);
X
X	begin = milliclock();
X	toolong = begin + 1000 * TIMEOUT;
X
X	if (synthinfileflag) getmidi();
X
X	/* wait for the x43 byte starting the dump */
X	while ( milliclock() < toolong ) {
X		if ( STATMIDI && (c=(getmidi() & 0xff)) == 0x43 )
X			break;
X	}
X	if ( c != 0x43 ) {
X		Reason = "Timeout waiting for 0x43";
X		goto getout;
X	}
X	/* get the 14 bytes preceeding the data */
X	for ( cksum=n=0; n<14; n++ ) {
X		/* twiddle your thumbs, but not forever */
X		while ( ! STATMIDI ) {
X			if ( milliclock() > toolong )
X				goto timeout;	/* the end of an era */
X		}
X		c = getmidi();
X		if(n >= 4)
X			cksum += c; /* start of LM... keyword */
X	}
X	/* 32 memories are dumped */
X	for ( v=0; v<32; v++ ) {
X		for ( n=0; n<PMEMSIZE; n++ ) {
X			/* twiddle your thumbs, but not forever */
X			while ( ! STATMIDI ) {
X				if ( milliclock() > toolong )
X					goto timeout;	/* the end of an era */
X			}
X			c = (getmidi() & 0xff);
X			/* Ignore non-data bytes ? */
X			if ( c & 0x80 )
X				continue;
X			/* compute checksum */
X			cksum += c;
X			/* Only 24 memories are used */
X			if ( v < 24 )
X				VOICEBYTE(data,v,n) = c;
X		}
X	}
Xtimeout:
X	if ( v < 32 ) {
X		Reason = "Timeout while reading!";
X		goto getout;
X	}
X	b1 = (getmidi() & 0xff);	/* Checksum */
X	b2 = (getmidi() & 0xff);	/* EOX */
X	cksum = (-cksum) & 0x7f;	/* convert to what we must match */
X	if ( b2 != EOX )
X		Reason = "EOX not received";
X	else if ( b1 != cksum ) {
X		static char ckbuff[80];
X		sprintf(ckbuff,"Checksum doesn't match (got %d expected %d)",b1,cksum);
X		/* Reason = "Checksum doesn't match"; */
X		Reason = ckbuff;
X	}
X	else {
X		Reason = "";
X		ret = 0;	/* all's well */
X	}
Xgetout:
X	return(ret);
X}
X
Xchar *
Xtx8pnof(data)
Xchar *data;
X{
X	int n;
X
X	for ( n=0; n<10; n++ )
X		Pbuff[n] = data[66+n];
X	Pbuff[10] = '\0';
X	return(Pbuff);
X} 
X
Xtx8psnof(data,name)
Xchar *data, *name;
X{
X	int n;
X
X	for ( n=0; name[n]!='\0' && n<10; n++ )
X		data[66+n] = name[n];
X	for ( ; n<10; n++ )
X		data[66+n] = ' ';
X} 
X
Xchar *
Xvisass(v)
X{
X	switch(v){
X	case 0: return("normal");
X	case 1: return("alternate");
X	}
X	return("");
X}
X
Xchar *
Xviskey(v)
X{
X	switch(v){
X	case 0: return("C");
X	case 1: return("C#");
X	case 2: return("D");
X	case 3: return("D#");
X	case 4: return("E");
X	case 5: return("F");
X	case 6: return("F#");
X	case 7: return("G");
X	case 8: return("G#");
X	case 9: return("A");
X	case 10: return("A#");
X	case 11: return("B");
X	}
X	return("");
X}
X
Xchar *
Xviseffect(v)
X{
X	switch(v){
X	case 0: return("none");
X	case 1: return("delay");
X	case 2: return("pan");
X	case 3: return("chord");
X	}
X	return("");
X}
X
Xchar *
Xvischan(v)
X{
X	if ( v >= 0 && v <= 15 ) {
X		sprintf(Pbuff,"%d",v+1);
X		return(Pbuff);
X	}
X	if ( v == 16 )
X		return("omni");
X	return("");
X}
X
Xchar *
Xvisnote(v)
X{
X	int octave;
X
X	octave = (v/12) - 2;
X	sprintf(Pbuff,"%s%d",viskey(v%12),octave);
X	return(Pbuff);
X}
X
Xchar *
Xvispshift(v)
X{
X	sprintf(Pbuff,"%d",v-24);
X	return(Pbuff);
X}
X
Xchar *
Xvistdetune(v)
X{
X	sprintf(Pbuff,"%d",v-7);
X	return(Pbuff);
X}
X
Xchar *
Xvistout(v)
X{
X	switch (v) {
X	case 0: return("off");
X	case 1: return("I");
X	case 2: return("II");
X	case 3: return("I+II");
X	}
X	return("");
X}
X
Xchar *
Xvislfo(v)
X{
X	switch (v) {
X	case 0: return("off");
X	case 1: return("inst1");
X	case 2: return("inst2");
X	case 3: return("vib");
X	}
X	return("");
X}
X
Xchar *
Xvisponoff(v)
X{
X	switch(v){
X	case 0: return("off");
X	case 1: return("on");
X	}
X	return("");
X}
X
Xchar *
Xvispvoice(v)
X{
X	char *p, *prefixes = "IABCD";
X	int bank, vnum, vindex;
X
X	bank = v/32;
X	vnum = (v%32) + 1;
X	sprintf(Pbuff,vnum<10?"%c0%d":"%c%d",prefixes[bank],vnum);
X	if ( bank > 0 ) {
X		vindex = (bank-1)*32+vnum-1;
X		if ( vindex >= 0 && vindex < 128 ) {
X			strcat(Pbuff,"~d~l~l~l");
X			p = tx81voices[vindex];
X			if ( strlen(p) <= 5 )
X				strcat(Pbuff,p);
X			else {
X				char buff[11];
X				strcpy(buff,p);
X				buff[5] = '\0';
X				strcat(Pbuff,buff);
X				strcat(Pbuff,"~d~l~l~l~l~l");
X				strcat(Pbuff,&p[5]);
X			}
X		}
X	}
X	return(Pbuff);
X}
END_OF_FILE
if test 14135 -ne `wc -c <'tx81p.mnu'`; then
    echo shar: \"'tx81p.mnu'\" unpacked with wrong size!
fi
# end of 'tx81p.mnu'
fi
echo shar: End of archive 8 \(of 15\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 15 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0