Index: ram/addfpu.c
===================================================================
--- ram/addfpu.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/addfpu.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,82 @@
+/*
+   =============================================================================
+	addfpu.c -- FPU time functions
+	Version 1 -- 1987-09-14 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+
+#define	MAXSEGT		32767
+
+extern	unsigned	tofpu(), fromfpu();
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	addfpu() -- find next higher FPU time 'k' milliseconds greater than 't'
+   =============================================================================
+*/
+
+unsigned
+addfpu(t, k)
+unsigned t;
+short k;
+{
+	register short x, z;
+	register unsigned y;
+
+	x = fromfpu(t);
+
+	if (x EQ MAXSEGT)
+		return(t);
+
+	y = t;
+	z = x + k;
+
+	if (z GE MAXSEGT)
+		return(tofpu(MAXSEGT));
+
+	while ((y EQ t) OR (z > x))
+		y = tofpu(++x);
+
+	return(y);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	subfpu() -- find next lower FPU time 'k' milliseconds less than 't'
+   =============================================================================
+*/
+
+unsigned
+subfpu(t, k)
+unsigned t;
+short k;
+{
+	register short x, z;
+	register unsigned y;
+
+	x = fromfpu(t);
+
+	if (x EQ 1)
+		return(t);
+
+	y = t;
+	z = x - k;
+
+	if (z LE 1)
+		return(tofpu(1));
+
+	while ((y EQ t) OR (z < x))
+		y = tofpu(--x);
+
+	return(y);
+}
Index: ram/adfield.c
===================================================================
--- ram/adfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/adfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,476 @@
+/*
+   =============================================================================
+	adfield.c -- assignment display field processing and cursor motion
+	Version 24 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "hwdefs.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	short	select(), whatbox(), nokey(), stdctp4();
+extern	short	cxkstd(), cykstd(), stdmkey(), stddkey();
+
+extern	short	et_null(), ef_null(), rd_null(), nd_null();
+extern	short	et_atab(), ef_atab(), rd_atab(), nd_atab();
+extern	short	et_aopt(), ef_aopt(), rd_aopt(), nd_aopt();
+extern	short	et_avgr(), ef_avgr(), rd_avgr(), nd_avgr();
+extern	short	et_accn(), ef_accn(), rd_accn(), nd_accn();
+extern	short	et_agpt(), ef_agpt(), rd_agpt(), nd_agpt();
+extern	short	et_agch(), ef_agch(), rd_agch(), nd_agch();
+extern	short	et_ains(), ef_ains(), rd_ains(), nd_ains();
+extern	short	et_adyn(), ef_adyn(), rd_adyn(), nd_adyn();
+extern	short	et_atun(), ef_atun(), rd_atun(), nd_atun();
+extern	short	et_aprg(), ef_aprg(), rd_aprg(), nd_aprg();
+extern	short	et_aint(), ef_aint(), rd_aint(), nd_aint();
+extern	short	et_arat(), ef_arat(), rd_arat(), nd_arat();
+extern	short	et_adep(), ef_adep(), rd_adep(), nd_adep();
+
+extern	short	vcputsv();
+
+extern	char	*memset();
+
+extern	short	adnamsw;
+extern	short	asgmod;
+extern	short	astat;
+extern	short	cmtype;
+extern	short	cmfirst;
+extern	short	curasg;
+extern	short	curhold;
+extern	short	curmop;
+extern	short	curslim;
+extern	short	cxval;
+extern	short	cyval;
+extern	short	cxrate;
+extern	short	cyrate;
+extern	short	hcwval;
+extern	short	hitbox;
+extern	short	hitcx;
+extern	short	hitcy;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	thcwval;
+extern	short	tvcwval;
+extern	short	vcwval;
+extern	short	vtccol;
+extern	short	vtcrow;
+extern	short	vtwcol;
+extern	short	vtwrow;
+extern	short	vtxval;
+extern	short	vtyval;
+
+extern	short	crate1[];
+
+extern	unsigned *asgob;
+
+extern	struct	asgent	asgtab[];
+
+extern	struct	selbox	adboxes[];
+extern	struct	selbox	*csbp;
+
+extern	short	grp2prt[12][2];
+extern	short	key2grp[];
+extern	short	mctlnum[];
+extern	short	vce2grp[];
+
+/* forward references */
+
+short	adcxupd(), adcyupd(), ad_xkey();
+
+/* 
+
+*/
+
+struct	fet	ad_fet1[] = {		/* field definitions */
+
+	{ 0,  9, 10, 0x0000, et_atab, ef_atab, rd_atab, nd_atab},
+
+	{ 1,  1, 10, 0x0000, et_null, ef_null, rd_null, nd_null},
+
+	{ 4, 10, 10, 0x0002, et_aopt, ef_aopt, rd_aopt, nd_aopt},
+
+	{ 3,  9, 10, 0x0003, et_aprg, ef_aprg, rd_aprg, nd_aprg},
+
+	{ 4, 15, 16, 0x0004, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 5, 15, 16, 0x0104, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 6, 15, 16, 0x0204, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 7, 15, 16, 0x0304, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 8, 15, 16, 0x0404, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 9, 15, 16, 0x0504, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 4, 21, 22, 0x0604, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 5, 21, 22, 0x0704, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 6, 21, 22, 0x0804, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 7, 21, 22, 0x0904, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 8, 21, 22, 0x0A04, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+	{ 9, 21, 22, 0x0B04, et_avgr, ef_avgr, rd_avgr, nd_avgr},
+
+	{ 5, 35, 36, 0x0005, et_accn, ef_accn, rd_accn, nd_accn},
+	{ 6, 35, 36, 0x0105, et_accn, ef_accn, rd_accn, nd_accn},
+	{ 7, 35, 36, 0x0205, et_accn, ef_accn, rd_accn, nd_accn},
+	{ 8, 35, 36, 0x0305, et_accn, ef_accn, rd_accn, nd_accn},
+
+	{ 4, 46, 46, 0x0006, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 5, 46, 46, 0x0106, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 6, 46, 46, 0x0206, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 7, 46, 46, 0x0306, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 8, 46, 46, 0x0406, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 9, 46, 46, 0x0506, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 4, 59, 59, 0x0606, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 5, 59, 59, 0x0706, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 6, 59, 59, 0x0806, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 7, 59, 59, 0x0906, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 8, 59, 59, 0x0A06, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+	{ 9, 59, 59, 0x0B06, et_agpt, ef_agpt, rd_agpt, nd_agpt},
+
+	{ 4, 48, 49, 0x0006, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 5, 48, 49, 0x0106, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 6, 48, 49, 0x0206, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 7, 48, 49, 0x0306, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 8, 48, 49, 0x0406, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 9, 48, 49, 0x0506, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 4, 61, 62, 0x0606, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 5, 61, 62, 0x0706, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 6, 61, 62, 0x0806, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 7, 61, 62, 0x0906, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 8, 61, 62, 0x0A06, et_agch, ef_agch, rd_agch, nd_agch},
+	{ 9, 61, 62, 0x0B06, et_agch, ef_agch, rd_agch, nd_agch},
+
+	{ 4, 41, 42, 0x0006, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 5, 41, 42, 0x0106, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 6, 41, 42, 0x0206, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 7, 41, 42, 0x0306, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 8, 41, 42, 0x0406, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 9, 41, 42, 0x0506, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 4, 54, 55, 0x0606, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 5, 54, 55, 0x0706, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 6, 54, 55, 0x0806, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 7, 54, 55, 0x0906, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 8, 54, 55, 0x0A06, et_ains, ef_ains, rd_ains, nd_ains},
+	{ 9, 54, 55, 0x0B06, et_ains, ef_ains, rd_ains, nd_ains},
+
+	{ 4, 44, 44, 0x0006, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 5, 44, 44, 0x0106, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 6, 44, 44, 0x0206, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 7, 44, 44, 0x0306, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 8, 44, 44, 0x0406, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 9, 44, 44, 0x0506, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 4, 57, 57, 0x0606, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 5, 57, 57, 0x0706, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 6, 57, 57, 0x0806, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 7, 57, 57, 0x0906, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 8, 57, 57, 0x0A06, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+	{ 9, 57, 57, 0x0B06, et_adyn, ef_adyn, rd_adyn, nd_adyn},
+
+	{ 5, 10, 10, 0x0009, et_atun, ef_atun, rd_atun, nd_atun},
+
+	{ 7,  9, 10, 0x000A, et_aint, ef_aint, rd_aint, nd_aint},
+	{ 8,  9, 10, 0x000A, et_arat, ef_arat, rd_arat, nd_arat},
+	{ 9,  9, 10, 0x000A, et_adep, ef_adep, rd_adep, nd_adep},
+
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+/* 
+
+*/
+
+short	adbox[][8] = {		/* display box parameters */
+
+	{  1,   1,  94,  27, ACFBX00, ACBBX00,  0,  1},	/* 0 */
+	{  1,  28,  94,  40, ACFBX01, ACBBX01,  2,  1},	/* 1 */
+	{  1,  56,  94,  68, ACFBX02, ACBBX02,  4,  1},	/* 2 */
+	{  1,  42,  94,  54, ACFBX03, ACBBX03,  3,  1},	/* 3 */
+	{ 96,   1, 190, 138, ACFBX04, ACBBX04,  0, 13},	/* 4 */
+	{192,   1, 302, 138, ACFBX05, ACBBX05,  0, 25},	/* 5 */
+	{304,   1, 510, 138, ACFBX06, ACBBX06,  0, 39},	/* 6 */
+	{  1, 140, 510, 348, ACFBX07, ACBBX07, 10,  1},	/* 7 */
+	{  1,  70,  38,  82, ACFBX08, ACBBX08,  5,  1},	/* 8 */
+	{ 40,  70,  94,  82, ACFBX09, ACBBX09,  5,  6},	/* 9 */
+	{  1,  84,  94, 138, ACFBX10, ACBBX10,  6,  1}	/* 10 */
+};
+
+char	*adbxlb[] = {		/* display box labels */
+
+	"Asgnmnt",			/* 0 */
+	"Stor/Fetch",			/* 1 */
+	"MIDI out",			/* 2 */
+	"PrgChng",			/* 3 */
+	"Assignment",			/* 4 */
+	"Assignmnt of"	,		/* 5 */
+	"Assignmnt of Instruments,",	/* 6 */
+	"G Assignment of Keys to Groups for MIDI Port 1               G", /* 7 */
+	"",				/* 8 */
+	"Tun",				/* 9 */
+	"PhaseShift"			/* 10 */
+};
+
+/* 
+
+*/
+
+struct curpak ad_flds = {
+
+	stdctp4,	/* curtype */
+	nokey,		/* premove */
+	nokey,		/* pstmove */
+	cxkstd,		/* cx_key */
+	cykstd,		/* cy_key */
+	adcxupd,	/* cx_upd */
+	adcyupd,	/* cy_upd */
+	nokey,		/* xy_up */
+	nokey,		/* xy_dn */
+	ad_xkey,	/* x_key */
+	select,		/* e_key */
+	stdmkey,	/* m_key */
+	stddkey,	/* d_key */
+	nokey,		/* not_fld */
+	ad_fet1,	/* curfet */
+	adboxes,	/* csbp */
+	crate1,		/* cratex */
+	crate1,		/* cratey */
+	CT_GRAF,	/* cmtype */
+	CTOX(0),	/* cxval */
+	RTOY(9)		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	adcyupd() -- update cursor y location
+   =============================================================================
+*/
+
+adcyupd()
+{
+	if (adnamsw) {
+
+		vtcrow = YTOR(vtyval += cyrate);
+
+		if (vtcrow > (vtwrow + 2))
+			vtyval = RTOY(vtcrow = vtwrow + 2);
+		else if (vtcrow < vtwrow)
+			vtyval = RTOY(vtcrow = vtwrow);
+
+	} else {
+
+		cyval += cyrate;
+
+		if (cyval GT (CYMAX - 1))
+			cyval = CYMAX - 1;
+		else if (cyval LT 1)
+			cyval = 1;
+	}
+}
+
+/*
+   =============================================================================
+	adcxupd() -- update cursor x location
+   =============================================================================
+*/
+
+adcxupd()
+{
+	if (adnamsw) {
+
+		vtccol = XTOC(vtxval += cxrate);
+
+		if (vtccol > (vtwcol + 29))
+			vtxval = CTOX(vtccol = vtwcol + 29);
+		else if (vtccol < vtwcol)
+			vtxval = CTOX(vtccol = vtwcol);
+
+	} else {
+
+		cxval += cxrate;
+
+		if (cxval GT (CXMAX - 1))
+			cxval = CXMAX - 1;
+		else if (cxval LT 1)
+			cxval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ad_xkey() -- process the X key
+   =============================================================================
+*/
+
+short
+ad_xkey(nn)
+short nn;
+{
+	register short row, col, grp, i;
+
+	if (astat) {
+
+		if (whatbox()) {
+
+			row = hitcy / 14;
+			col = hitcx >> 3;
+
+			switch (hitbox) {
+
+			case 0:		/* name */
+
+				if (row EQ 1) {
+
+					memset(asgtab[curasg].a_name, ' ', 16);
+					asgmod = TRUE;
+					adswin(0);
+					return(SUCCESS);
+
+				} else
+					return(FAILURE);
+			case 2:		/* MIDI output port */
+
+				if ((col GE 1) AND (col LE 10)) {
+
+					curmop = 0;
+					adswin(hitbox);
+					modasg();
+					return(SUCCESS);
+				}
+
+				break;
+/* 
+
+*/
+			case 4:		/* voice to group */
+
+				if (row LT 4)
+					break;
+
+				if ((col GE 13) AND (col LE 16)) {
+
+					grp = row - 4;
+					vce2grp[grp] = -1;
+					adswin(hitbox);
+					modasg();
+					return(SUCCESS);
+
+				} else if ((col GE 19) AND (col LE 22)) {
+
+					grp = row + 2;
+					vce2grp[grp] = -1;
+					adswin(hitbox);
+					modasg();
+					return(SUCCESS);
+				}
+
+				break;
+
+			case 5:		/* controller number */
+
+				if ((row LT 5) OR (row GT 8))
+					break;
+
+				if ((col EQ 35) OR (col EQ 36)) {
+
+					mctlnum[row - 5] = -1;
+					adswin(hitbox);
+					modasg();
+					return(SUCCESS);
+				}
+
+				break;
+/* 
+
+*/
+			case 6:		/* port or channel */
+
+				if (row LT 4)
+					break;
+
+				if (col EQ 46 ) {
+
+					/* port */
+
+					grp = row - 4;
+					grp2prt[grp][0] = 0;
+
+					for (i = 0; i < 88; i++)
+						key2grp[i] &= ~(0x0001 << grp);
+
+					adswin(hitbox);
+					drawk2g(grp);
+					modasg();
+					return(SUCCESS);
+
+				} else if ((col EQ 48) OR (col EQ 49)) {
+
+					/* channel */
+
+					grp = row - 4;
+					grp2prt[grp][1] = -1;
+					adswin(hitbox);
+					modasg();
+					return(SUCCESS);
+/* 
+
+*/
+				} else if (col EQ 59) {
+
+					/* port */
+
+					grp = row + 2;
+					grp2prt[grp][0] = 0;
+
+					for (i = 0; i < 88; i++)
+						key2grp[i] &= ~(0x0001 << grp);
+
+					adswin(hitbox);
+					drawk2g(grp);
+					modasg();
+					return(SUCCESS);
+
+				} else if ((col EQ 61) OR (col EQ 62)) {
+
+					/* channel */
+
+					grp = row + 2;
+					grp2prt[grp][1] = -1;
+					adswin(hitbox);
+					modasg();
+					return(SUCCESS);
+				}
+
+				break;
+			}
+		}
+	}
+
+	return(FAILURE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	adfield() -- setup field routines for the assignment editor
+   =============================================================================
+*/
+
+adfield()
+{
+	curslim = 140;
+
+	curset(&ad_flds);
+}
Index: ram/adselbx.c
===================================================================
--- ram/adselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/adselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,537 @@
+/*
+   =============================================================================
+	adselbx.c -- assignment editor box selection functions
+	Version 30 -- 1988-12-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+#define	ATWROW	10		/* typewriter row */
+#define	ATWCOL	1		/* typewriter column */
+#define	ATDECOL	1		/* data entry base column */
+
+extern	short	enterit(), adswin(), advacur(), bspacur();
+extern	short	nokey(), vtdisp(), adpoint();
+
+extern	short	(*itxput)();
+extern	short	(*point)();
+
+extern	short	admctl;
+extern	short	adnamsw;
+extern	short	asgfks;
+extern	short	asghit;
+extern	short	asgmod;
+extern	short	auxctl;
+extern	short	curasg;
+extern	short	cxval;
+extern	short	cyval;
+extern	short	hitbox;
+extern	short	hitcx;
+extern	short	hitcy;
+extern	short	lastam;
+extern	short	submenu;
+
+extern	short	adbox[][8];
+
+extern	short	grp2prt[12][2];
+extern	short	ins2grp[12];
+extern	short	asgkble[];
+extern	short	key2grp[];
+extern	short	mctlnum[];
+
+extern	struct	selbox	*csbp, *curboxp;
+
+extern	char	bfs[];
+extern	char	caname[];
+extern	char	vtlin1[], vtlin2[], vtlin3[];
+
+extern	unsigned	*asgob;
+
+/* forward references */
+
+short	bx_null(), adfnbox();
+
+/* 
+
+*/
+
+struct	selbox	adboxes[] = {
+
+	{  1,   0,  94,  27,      0, adfnbox},	/*  0:  curasg, caname */
+	{  1,  28,  94,  40,      1, adfnbox},	/*  1:  asgtab[curasg] */
+	{  1,  56,  94,  68,      2, enterit},	/*  2:  curmop */
+	{  1,  42,  94,  54,      3, enterit},	/*  3:  prgchan */
+	{ 96,   1, 190, 138,      4, enterit},	/*  4: 	vce2grp[voice] */
+	{192,   1, 302, 138,      5, adfnbox},	/*  5: 	mctlnum[srcvar] */
+	{304,   1, 510, 138,      6, adfnbox},	/*  6:  grp2prt[group][pt|ch] */
+	{  1, 140, 510, 348,      7, adfnbox},	/*  7:  key2grp[key] */
+	{  1,  70,  38,  82,      8, adfnbox},	/*  8:  auxctl */
+	{ 40,  70,  94,  82,      9, adfnbox},	/*  9:  curtun */
+	{  1,  84,  94, 138,     10, enterit},	/* 10:  ps_intn, ps_rate, ps_dpth */
+
+	{  0,   0,   0,   0,	  0, FN_NULL}		/* end of table */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	endatyp() -- end function for virtual typewriter
+   =============================================================================
+*/
+
+endatyp()
+{
+	adnamsw = FALSE;
+	submenu = FALSE;
+
+	if (admctl EQ -1)
+		adswin(7);		/* refresh key map window */
+	else
+		admenu(admctl);		/* refresh menu window */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	admtxt() -- output text to the submenu
+   =============================================================================
+*/
+
+admtxt(row, col, txt, tag)
+short row, col;
+char *txt;
+short tag;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(asgob, 64, ACFBX07, ACBBX07, row + 10, col, txt, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	admenu() -- put up or take down an assignment display submenu
+   =============================================================================
+*/
+
+admenu(n)
+short n;
+{
+	register short i;
+
+	if (n GE 0) {		/* put up a submenu */
+
+		itxput = admtxt;	/* setup output function */
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		vbfill4(asgob, 128, adbox[7][0], adbox[7][1],
+			adbox[7][2], adbox[7][3], exp_c(adbox[7][5]));
+
+		switch (n) {			/* fill the window */
+
+		case 0:		/* instruments */
+
+			showim();		/* show the instruments */
+			break;
+
+		case 1:		/* assignments */
+
+			showam(lastam);		/* show the assignments */
+			settc(0, 9);		/* position the cursor */
+			break;
+
+		case 2:		/* tunings */
+
+			showtm();		/* show the tunings */
+			settc(5, 10);		/* position the cursor */
+			break;
+
+		default:	/* eh ? */
+
+			break;
+		}
+
+	} else {		/* take down the submenu */
+
+		admctl = n;	/* set new menu type */
+		adswin(7);	/* refresh the window */
+	}
+
+	point = adpoint;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	lseg(  0, 0,   0, 349, AK_BORD);	/* fix left edge of screen */
+	lseg(511, 0, 511, 349, AK_BORD);	/* fix right edge of screen */
+
+	admctl = n;		/* set new menu type */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	adfnbox() -- assignment display box hit processor
+   =============================================================================
+*/
+
+short
+adfnbox(n)
+short n;
+{
+	register short i, grp, key, line;
+	short	row, col;
+
+	row = hitcy / 14;
+	col = hitcx >> 3;
+
+	switch (hitbox) {
+
+	case 0:		/* asignment number or name */
+
+		if ((NOT adnamsw) AND (row EQ 0)) {	/* menu or table */
+
+			if ((col GE 1) AND (col LE 7)) {	/* menu */
+
+				if (admctl NE 1) {
+
+					lastam = 0;
+					admenu(1);	/* put up menu */
+
+				} else {
+
+					if (lastam EQ 0) {	/* show page 2 */
+
+						lastam = 60;
+						admenu(1);
+
+					} else {		/* take down menu */
+
+						lastam = 0;
+						admenu(-1);
+					}
+				}
+
+				return(SUCCESS);
+
+			} else {				/* table */
+
+				return(enterit());	/* data entry */
+			}
+		}
+
+		if (adnamsw) {		/* typewriter is up */
+
+			if (vtyper()) {
+
+				if (NOT asgmod) {
+
+					asgmod = TRUE;
+					adswin(0);
+				}
+			}
+/* 
+
+*/
+		} else {		/* setup the typewriter */
+
+			vbank(0);
+			vbfill4(asgob, 128, CTOX(ATWCOL), RTOY(ATWROW),
+				CTOX(ATWCOL+30) - 1, RTOY(ATWROW+3) - 1,
+				exp_c(ACBBX04));
+
+			tsplot4(asgob, 64, ACFBX04, ATWROW,   ATWCOL, vtlin1, 14);
+			tsplot4(asgob, 64, ACFBX04, ATWROW+1, ATWCOL, vtlin2, 14);
+			tsplot4(asgob, 64, ACFBX04, ATWROW+2, ATWCOL, vtlin3, 14);
+
+			point = adpoint;	/* draw a border ... */
+
+			lseg(CTOX(ATWCOL) - 1, RTOY(ATWROW) - 1,	/* up, lt */
+				CTOX(ATWCOL+30), RTOY(ATWROW) - 1,	/* up, rt */
+				AK_BORD);
+
+			lseg(CTOX(ATWCOL+30), RTOY(ATWROW) - 1,		/* up, rt */
+				CTOX(ATWCOL+30), RTOY(ATWROW+3) - 1,	/* dn, rt */
+				AK_BORD);
+
+			lseg(CTOX(ATWCOL+30), RTOY(ATWROW+3) - 1,	/* dn, rt */
+				CTOX(1) - 1, RTOY(ATWROW+3) - 1,	/* dn, lt */
+				AK_BORD);
+
+			lseg(CTOX(1) - 1, RTOY(ATWROW+3) - 1,		/* dn, lt */
+				CTOX(1) - 1, RTOY(ATWROW) - 1,		/* up, lt */
+				AK_BORD);
+
+			vtsetup(asgob, vtdisp, ATDECOL,
+				caname,
+				ATWROW, ATWCOL,
+				advacur, bspacur, nokey, nokey, endatyp,
+				adbox[n][4], adbox[n][5]);
+
+			adnamsw = TRUE;
+			submenu = TRUE;
+		}
+
+		return(SUCCESS);
+/* 
+
+*/
+	case 1:
+
+		if ((col GE 1) AND (col LE 4)) {		/* store */
+
+			if (curasg EQ 0)
+				return(FAILURE);
+
+			putasg(curasg);
+			adswin(0);
+			return(SUCCESS);
+
+		} else if ((col GE 6) AND (col LE 10)) {	/* retrieve */
+
+			getasg(curasg);
+			awins();
+			return(SUCCESS);
+		}
+
+	case 5:		/* toggle controller omni mode */
+
+		if (col EQ 25) {
+
+			if ((row LT 5) OR (row GT 8))
+				return(FAILURE);
+
+			mctlnum[row - 5] ^= GTAG1;
+
+			if (v_regs[5] &0x0180)
+				vbank(0);
+
+			bfs[0] = row - 5 + '2';
+			bfs[1] = '\0';
+
+			tsplot4(asgob, 64,
+				(mctlnum[row - 5] & GTAG1) ?
+					AK_MODC : adbox[n][4],
+				row, adbox[n][7], bfs, 14);
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());
+		}
+/* 
+
+*/
+	case 6:		/* instruments, groups, ports, channels */
+
+		if (((col EQ 41) OR (col EQ 42) OR
+		     (col EQ 54) OR (col EQ 55)) AND (row EQ 3)) {
+
+			/* instrument menu */
+
+			if (admctl NE 0)
+				admenu(0);	/* put up menu */
+			else
+				admenu(-1);	/* take down menu */
+
+			return(SUCCESS);
+
+		} else if (col EQ 39) {	/* groups 1..6 */
+
+			if ((row LT 4) OR (row GT 9))
+				return(FAILURE);
+
+			/* toggle "legato" mode */
+
+			grp = row - 4;
+
+			ins2grp[grp] ^= GTAG1;
+
+			bfs[0] = '1' + grp;
+			bfs[1] = '\0';
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			tsplot4(asgob, 64,
+			       ((ins2grp[grp] & GTAG1) ? AK_MODC : adbox[n][4]),
+			       row, col, bfs, 14);
+
+			return(SUCCESS);
+/* 
+
+*/
+		} else if (col EQ 52) {		/* groups 7..12 */
+
+			if ((row LT 4) OR (row GT 9))
+				return(FAILURE);
+
+			/* toggle "legato" mode */
+
+			grp = row + 2;
+
+			ins2grp[grp] ^= GTAG1;
+
+			bfs[0] = grp + ((grp > 8) ? 163 : '1');
+			bfs[1] = '\0';
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			tsplot4(asgob, 64,
+			       ((ins2grp[grp] & GTAG1) ? AK_MODC : adbox[n][4]),
+			       row, col, bfs, 14);
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());	/* data entry */
+		}
+/* 
+
+*/
+	case 7:		/* assignment map */
+
+		if (admctl NE -1)
+			return(FAILURE);
+
+		if (asghit) {
+
+			if (asghit EQ (hitcy / 14)) {	/* previous hit ? */
+
+				/* toggle selected key status */
+
+				grp = asghit - 11;
+				line = (14 * grp) + AK_BASE;
+				key = 0;
+
+				for (i = 0; i < 88; i++)
+					if ((hitcx GE (asgkble[i] + 24)) AND
+					    (hitcx LE (asgkble[i] + (i EQ 87 ? 31 : 28))))
+						key = i + 1;
+
+				if (key-- EQ 0)
+					return(FAILURE);
+
+				if (key LT asgfks) {
+
+					i = asgfks;
+					asgfks = key;
+					key = i;
+				}
+
+				for (i = asgfks; i LE key; i++)
+					key2grp[i] ^= (0x0001 << grp);
+
+				drawk2g(grp);
+				asghit = 0;
+
+				if (NOT asgmod) {
+
+					asgmod = TRUE;
+					adswin(0);
+				}
+
+			} else {
+
+				/* clear the selection */
+
+				drawk2g(asghit - 11);
+				asghit = 0;
+			}
+/* 
+
+*/
+		} else {
+
+			/* make initial selection */
+
+			asghit = hitcy / 14;
+			grp = asghit - 11;
+
+			if (grp2prt[grp][0] NE 1) {
+
+				asghit = 0;
+				return(FAILURE);
+			}
+
+			line = (14 * grp) + AK_BASE;
+			key = 0;
+
+			for (i = 0; i < 88; i++)
+				if ((hitcx GE (asgkble[i] + 24)) AND
+				    (hitcx LE (asgkble[i] + (i EQ 87 ? 31 : 28))))
+					key = i + 1;
+
+			if (key-- EQ 0) {
+
+				asghit = 0;
+				return(FAILURE);
+			}
+
+			asgfks = key;
+
+			vbfill4(asgob, 128, asgkble[key] + 24, line,
+				asgkble[key] + (key EQ 87 ? 31 : 28),
+				line + 3, exp_c(AK_SELC2));
+
+		}
+
+		return(SUCCESS);
+
+	case 8:			/* aux ctl */
+
+		setaux(NOT auxctl);
+		adswin(8);
+		return(SUCCESS);
+
+	case 9:			/* tuning menu */
+
+		if ((col GE 6) AND (col LE 8)) {
+
+			if (admctl NE 2)
+				admenu(2);	/* put up menu */
+			else
+				admenu(-1);	/* take down menu */
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());	/* data entry */
+		}
+	}
+
+	return(FAILURE);
+}
Index: ram/asgdsp.c
===================================================================
--- ram/asgdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/asgdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1071 @@
+/*
+   =============================================================================
+	asgdsp.c -- MIDAS assignment editor
+	Version 50 -- 1988-10-04 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "memory.h"
+
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "charset.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+#define	PSG_ADDR	0
+#define	PSG_READ	0
+#define	PSG_WRIT	2
+
+#define	PSG_IOEN	7
+#define	PSG_IDLE	0xBF
+
+#define	PSG_PRTB	15	/* PSG Port B */
+
+#define	AUX_BIT		0x02	/* aux control bit in PSG port B */
+
+#define	AK_WIDTH	115	/* width, in words, of keyboard icon */
+
+/* 4 bit pixel patterns */
+
+#define	AKW_0	0x0000
+#define	AKW_1	0xF000
+#define	AKW_2	0x0F00
+#define	AKW_3	0xFF00
+#define	AKW_4	0x00F0
+#define	AKW_5	0xF0F0
+#define	AKW_6	0x0FF0
+#define	AKW_7	0xFFF0
+#define	AKW_8	0x000F
+#define	AKW_9	0xF00F
+#define	AKW_A	0x0F0F
+#define	AKW_B	0xFF0F
+#define	AKW_C	0x00FF
+#define	AKW_D	0xF0FF
+#define	AKW_E	0x0FFF
+#define	AKW_F	0xFFFF
+
+/* 
+
+*/
+
+/* things defined elsewhere */
+
+extern	int		(*point)();
+extern	unsigned	exp_c();
+
+extern	short	stcrow, stccol, cxval, cyval;
+extern	short	curtun, tunmod;
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	unsigned	*obj0, *obj2;
+
+extern	char	bfs[];
+extern	char	*adbxlb[];
+extern	char	caname[];
+
+extern	short	adbox[][8];
+
+extern	short	admctl;			/* assignment menu control */
+extern	short	adnamsw;		/* vitrual typewriter switch */
+extern	short	asgfks;			/* first key selected */
+extern	short	asghit;			/* row hit / assignment in progress */
+extern	short	asgmod;			/* assignment number or table modified */
+extern	short	auxctl;			/* aux control flag */
+extern	short	curasg;			/* current assignment table */
+extern	short	curmop;			/* current MIDI output port */
+extern	short	curvce;			/* current voice being edited */
+extern	short	prgchan;		/* MIDI program change channel  (port 1) */
+extern	short	ps_dpth;		/* phase shifter -- depth */
+extern	short	ps_intn;		/* phase shifter -- intensity */
+extern	short	ps_rate;		/* phase shifter -- rate */
+extern	short	submenu;		/* submenu flag */
+
+extern	short	grpdyn[12];		/* group dynamics table (0..9) */
+extern	short	ins2grp[12];		/* instrument to group table (00..NINST-1) */
+extern	short	mctlnum[4];		/* MIDI controller number table (-1, 00..99) */
+extern	short	s_inst[12];		/* instrument assignments */
+extern	short	vce2grp[12];		/* voice to group table (-1, 1..12)*/
+
+extern	short	grp2prt[12][2];	/* group to port and channel table */
+				/* port [0] = 0..4, channel [1] = -1, 1..16 */
+
+extern	short	key2grp[88];	/* port 1 key to group assignment table */
+				/* bit n = group n */
+
+extern	struct	asgent	asgtab[NASGS];	/* assignment table library */
+
+extern	unsigned	*asgob;
+
+extern	struct	octent	*adoct;
+
+/* 
+
+*/
+
+char	*gprep[] = {" ", "1", "2", "L"};
+
+char	*asgsrc[] = {	/* source labels */
+
+	"1 Pch/Hor",
+	"2 Mod/Vrt",
+	"3 Brth/LP",
+	"4 GPC/CV1",
+	"5 Pedal 1",
+	"6 Key Prs"
+};
+
+/* keys are 5 pixels wide on top, except the last one, which is 8 pixels wide */
+
+short	asgkble[88] = {		/* key left edge offsets */
+
+						/* piano	MIDI */
+
+	  1,   6,  11,				/*  1..3	 21..23 */
+	 17,  22,  27,  32,  37,		/*  4..8	 24..28 */
+	 43,  48,  53,  58,  63,  68,  73,	/*  9..15	 29..35 */
+	 79,  84,  89,  94,  99,		/* 16..20	 36..40 */
+	105, 110, 115, 120, 125, 130, 135,	/* 21..27	 41..47 */
+	141, 146, 151, 156, 161,		/* 28..32	 48..52 */
+	167, 172, 177, 182, 187, 192, 197,	/* 33..39	 53..59 */
+	203, 208, 213, 218, 223,		/* 40..44	 60..64 */
+	229, 234, 239, 244, 249, 254, 259,	/* 45..51	 65..71 */
+	265, 270, 275, 280, 285,		/* 52..56	 72..76 */
+	291, 296, 301, 306, 311, 316, 321,	/* 57..63	 77..83 */
+	327, 332, 337, 342, 347,		/* 64..68	 84..88 */
+	353, 358, 363, 368, 373, 378, 383,	/* 69..75	 89..95 */
+	389, 394, 399, 404, 409,		/* 76..80	 96..100 */
+	415, 420, 425, 430, 435, 440, 445,	/* 81..87	101..107 */
+	451					/* 88		108 */
+};
+
+/* 
+
+*/
+
+short	asgkbtp[AK_WIDTH] = {		/* keyboard icon top lines */
+
+	AKW_7, AKW_C, AKW_1, AKW_F,
+	AKW_7, AKW_C, AKW_1, AKW_F,
+	AKW_0, AKW_7, AKW_D, AKW_F,
+	AKW_0, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_0, AKW_7, AKW_D,
+	AKW_F, AKW_0, AKW_7, AKW_C,
+	AKW_1, AKW_F,
+
+	AKW_7, AKW_C, AKW_1, AKW_F,
+	AKW_0, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_0, AKW_7, AKW_D,
+	AKW_F, AKW_0, AKW_7, AKW_C,
+	AKW_1, AKW_F, AKW_0, AKW_7,
+	AKW_D, AKW_F, AKW_0, AKW_7,
+	AKW_C, AKW_1, AKW_F,
+
+	AKW_7, AKW_C, AKW_1, AKW_F,
+	AKW_0, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_0, AKW_7, AKW_D,
+	AKW_F, AKW_0, AKW_7, AKW_C,
+	AKW_1, AKW_F, AKW_0, AKW_7,
+	AKW_D, AKW_F, AKW_0, AKW_7,
+	AKW_C, AKW_1, AKW_F,
+
+	AKW_7, AKW_C, AKW_1, AKW_F,
+	AKW_0, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_7, AKW_C, AKW_1,
+	AKW_F, AKW_0, AKW_7, AKW_D,
+	AKW_F, AKW_0, AKW_7, AKW_C,
+	AKW_1, AKW_F, AKW_0, AKW_7,
+	AKW_D, AKW_F, AKW_E
+};
+
+/* 
+
+*/
+
+short	asgkbbt[AK_WIDTH] = {		/* keyboard icon bottom lines */
+
+	AKW_7, AKW_F, AKW_7, AKW_F,
+	AKW_7, AKW_F, AKW_7, AKW_F,
+	AKW_B, AKW_F, AKW_D, AKW_F,
+	AKW_E, AKW_F, AKW_F, AKW_7,
+	AKW_F, AKW_B, AKW_F, AKW_D,
+	AKW_F, AKW_E, AKW_F, AKW_E,
+	AKW_F, AKW_F,
+
+	AKW_7, AKW_F, AKW_B, AKW_F,
+	AKW_D, AKW_F, AKW_E, AKW_F,
+	AKW_F, AKW_7, AKW_F, AKW_B,
+	AKW_F, AKW_B, AKW_F, AKW_D,
+	AKW_F, AKW_E, AKW_F, AKW_F,
+	AKW_7, AKW_F, AKW_B, AKW_F,
+	AKW_D, AKW_F, AKW_E, AKW_F,
+	AKW_E, AKW_F, AKW_F,
+
+	AKW_7, AKW_F, AKW_B, AKW_F,
+	AKW_D, AKW_F, AKW_E, AKW_F,
+	AKW_F, AKW_7, AKW_F, AKW_B,
+	AKW_F, AKW_B, AKW_F, AKW_D,
+	AKW_F, AKW_E, AKW_F, AKW_F,
+	AKW_7, AKW_F, AKW_B, AKW_F,
+	AKW_D, AKW_F, AKW_E, AKW_F,
+	AKW_E, AKW_F, AKW_F,
+
+	AKW_7, AKW_F, AKW_B, AKW_F,
+	AKW_D, AKW_F, AKW_E, AKW_F,
+	AKW_F, AKW_7, AKW_F, AKW_B,
+	AKW_F, AKW_B, AKW_F, AKW_D,
+	AKW_F, AKW_E, AKW_F, AKW_F,
+	AKW_7, AKW_F, AKW_B, AKW_F,
+	AKW_D, AKW_F, AKW_E
+};
+
+/* 
+
+*/
+
+short	asgpal[16][3] = {	/* assignment editor color palette */
+
+	{0, 0, 0},	/* 0 */
+	{3, 3, 3},	/* 1 */
+	{0, 0, 2},	/* 2 */
+	{1, 0, 1},	/* 3 */
+	{0, 1, 2},	/* 4 */
+	{0, 1, 1},	/* 5 (was 0, 1, 0) */
+	{1, 1, 2},	/* 6 */
+	{0, 0, 1},	/* 7 */
+	{2, 2, 2},	/* 8 */
+	{0, 0, 0},	/* 9 */
+	{2, 2, 2},	/* 10 (was 1, 1, 0) */	
+	{2, 3, 3},	/* 11 */
+	{3, 3, 0},	/* 12 */
+	{3, 0, 0},	/* 13 */
+	{0, 0, 0},	/* 14 */
+	{0, 2, 3}	/* 15 (was 0, 3, 2) */
+};
+
+short	dyntab[10] = {		/* dynamics translation table */
+
+	0,		/* 0 */
+	( 120 << 5),	/* 1 */
+	( 180 << 5),	/* 2 */
+	( 250 << 5),	/* 3 */
+	( 320 << 5),	/* 4 */
+	( 400 << 5),	/* 5 */
+	( 500 << 5),	/* 6 */
+	( 630 << 5),	/* 7 */
+	( 790 << 5),	/* 8 */
+	(1000 << 5)	/* 9 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	advacur() -- advance the assignment display text cursor
+   =============================================================================
+*/
+
+advacur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol + 1;
+
+	if (newcol LE cfetp->frcol)
+		itcpos(stcrow, newcol);
+
+	cxval = stccol << 3;
+	cyval = stcrow * 14;
+}
+
+/*
+   =============================================================================
+	bspacur() -- backspace the assignment display text cursor
+   =============================================================================
+*/
+
+bspacur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol - 1;
+
+	if (newcol GE cfetp->flcol)
+		itcpos(stcrow, newcol);
+
+	cxval = stccol << 3;
+	cyval = stcrow * 14;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	keycpyw() -- copy words into the keyboard object
+   =============================================================================
+*/
+
+keycpyw(dest, src, len, wk, bk)
+register unsigned *dest, *src;
+register short len;
+unsigned wk, bk;
+{
+	register unsigned wkey, bkey, theword;
+	register short i;
+
+	wkey = exp_c(wk);
+	bkey = exp_c(bk);
+
+	for (i = 0; i < len; i++) {
+
+		theword = *src++;
+		*dest++ = (theword & wkey) | ((~theword) & bkey);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	asgkb() -- draw the assignment keyboard icon
+   =============================================================================
+*/
+
+asgkb()
+{
+	register unsigned *p;
+	register unsigned akline;
+	register short i, j;
+
+	akline = exp_c(AK_LINE);
+	p = asgob + (long)AKSTART;
+
+	for (j = 0; j < 12; j++) {
+
+		memsetw(p, akline, AK_WIDTH);
+		p += 128L;
+
+		for (i = 0; i < 13; i++) {
+
+			keycpyw(p, asgkbtp, AK_WIDTH, AK_WKEYT, AK_BKEYT);
+			p += 128L;
+		}
+	}
+
+	memsetw(p, akline, AK_WIDTH);
+	p += 128L;
+
+	for (i = 0; i < 14; i++) {
+
+		keycpyw(p, asgkbtp, AK_WIDTH, AK_WKEYB, AK_BKEYB);
+		p += 128L;
+	}
+
+	for (i = 0; i < 11; i++) {
+
+		keycpyw(p, asgkbbt, AK_WIDTH, AK_WKEYB, AK_BKEYB);
+		p += 128L;
+	}
+
+	memsetw(p, akline, AK_WIDTH);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	drawk2g() -- display key assignments for a group
+   =============================================================================
+*/
+
+drawk2g(grp)
+register short grp;
+{
+	register short i;
+	register short n;
+	register short key;
+	register short line;
+	register char *bfsp;
+	register unsigned *lp;
+
+	n = 7;		/* key to group window */
+
+	line = (14 * grp) + AK_BASE;
+	lp = asgob + ((long)line << 7) + 6L;
+
+	for (i = 0; i < 4; i++) {
+
+		keycpyw(lp, asgkbtp, AK_WIDTH, AK_WKEYT, AK_BKEYT);
+		lp += 128L;
+	}
+
+	if (grp2prt[grp][0] EQ 1) {
+
+		for (key = 0; key < 88; key++)
+			if (key2grp[key] & (0x0001 << grp))
+				vbfill4(asgob, 128, asgkble[key] + 24, line,
+					asgkble[key] + (key EQ 87 ? 31 : 28),
+					line + 3, exp_c(AK_SELC));
+
+		sprintf(bfs, "%c", (grp > 8) ? (grp + 163) : (grp + '1'));
+		bfsp = bfs;
+
+	} else {
+
+		bfsp = " ";
+	}
+
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6] + 1 + grp, adbox[n][7], bfsp, 14);
+
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6] + 1 + grp, adbox[n][7] + 61, bfsp, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	adpoint() -- plot a point for the lseg function
+   =============================================================================
+*/
+
+adpoint(x, y, pen)
+short x, y, pen;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputp(adoct, x, y, exp_c(pen));
+}
+
+/*
+   =============================================================================
+	numblk() -- return a number string or a blank string
+   =============================================================================
+*/
+
+char *
+numblk(buf, n)
+char *buf;
+short n;
+{
+	if (n EQ -1) {
+
+		strcpy(buf, "  ");
+		return(buf);
+
+	} else {
+
+		sprintf(buf, "%02.2d", n);
+		return(buf);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	adswin() -- display a window
+   =============================================================================
+*/
+
+adswin(n)
+register short n;
+{
+	register short cx, i;
+	register char *bfsp;
+	char buf1[4], buf2[4];
+
+	if ((n EQ 7) AND (admctl NE -1))
+		return;
+
+	cx = exp_c(adbox[n][5]);
+	point = adpoint;
+
+	/* first, fill the box with the background color */
+
+	vbank(0);
+	vbfill4(asgob, 128, adbox[n][0], adbox[n][1], adbox[n][2],
+		adbox[n][3], cx);
+
+	/* put in the box label */
+
+	tsplot4(asgob, 64, adbox[n][4], adbox[n][6], adbox[n][7],
+		adbxlb[n], 14);
+
+/* 
+
+*/
+	switch (n) {	/* final text - overlays above stuff */
+
+	case 0:		/* assignment table number and name */
+
+		sprintf(bfs, "%02.2d", curasg);
+		tsplot4(asgob, 64, (asgmod ? AK_MODC : adbox[n][4]),
+			adbox[n][6], adbox[n][7] + 8, bfs, 14);
+
+		sprintf(bfs, "%-10.10s", caname);
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 1,
+			adbox[n][7], bfs, 14);
+
+		return;
+
+	case 2:		/* output MIDI port number */
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6], adbox[n][7] + 9,
+			gprep[curmop], 14);
+
+		return;
+
+	case 3:		/* MIDI program change channel  (always on port 1) */
+
+		sprintf(bfs, "%02.2d", prgchan);
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6], adbox[n][7] + 8,
+			bfs, 14);
+
+		return;
+/* 
+
+*/
+	case 4:		/* groups to voices */
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 1, adbox[n][7],
+			"of Groups", 14);
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 2, adbox[n][7],
+			"to Voices", 14);
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 3, adbox[n][7],
+			"V Gr  V Gr", 14);
+
+		lseg(CTOX(13), RTOY(3) + 13,
+			CTOX(13) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(15), RTOY(3) + 13,
+			CTOX(16) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(19), RTOY(3) + 13,
+			CTOX(19) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(21), RTOY(3) + 13,
+			CTOX(22) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		for (i = 0; i < 6; i++) {
+
+			sprintf(bfs, "%c %s", i + '1',
+				numblk(buf1, vce2grp[i]));
+
+			tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + i + 4,
+				adbox[n][7], bfs, 14);
+
+			sprintf(bfs, "%c %s", (i > 2 ? (i + 169) : (i + '7')),
+				numblk(buf2, vce2grp[i + 6]));
+
+			tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + i + 4,
+				adbox[n][7] + 6, bfs, 14);
+		}
+
+		return;
+/* 
+
+*/
+	case 5:		/* MIDI controller number assignments */
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 1, adbox[n][7],
+			"Sources and", 14);
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 2, adbox[n][7],
+			"Controllers", 14);
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 3, adbox[n][7],
+			"# Source  CN", 14);
+
+		lseg(CTOX(25), RTOY(3) + 13,
+			CTOX(25) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(27), RTOY(3) + 13,
+			CTOX(33) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(35), RTOY(3) + 13,
+			CTOX(36) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		for (i = 0; i < 6; i++)
+			tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + i + 4,
+				adbox[n][7], asgsrc[i], 14);
+
+		for (i = 0; i < 4; i++) {
+
+			sprintf(bfs, "%s", numblk(buf1, (mctlnum[i] & 0x00FF)));
+
+			tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + i + 5,
+				adbox[n][7] + 10, bfs, 14);
+
+			if ((mctlnum[i] NE -1) AND (mctlnum[i] & CTAG1)) {
+
+				bfs[0] = '2' + i;
+				bfs[1] = '\0';
+
+				tsplot4(asgob, 64, AK_MODC, adbox[n][6] + i + 5,
+					adbox[n][7], bfs, 14);
+			}
+		}
+
+		return;
+/* 
+
+*/
+	case 6:		/* instruments, dynamics, MIDI ports and channels to groups */
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 1, adbox[n][7],
+			"Dynamics, MIDI Ports and", 14);
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 2, adbox[n][7],
+			"Channels to Groups", 14);
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + 3, adbox[n][7],
+			"G In D I Ch  G In D I Ch", 14);
+
+		lseg(CTOX(39), RTOY(3) + 13,
+			CTOX(39) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(41), RTOY(3) + 13,
+			CTOX(42) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(44), RTOY(3) + 13,
+			CTOX(44) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(46), RTOY(3) + 13,
+			CTOX(46) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(48), RTOY(3) + 13,
+			CTOX(49) + 7, RTOY(3) + 13, adbox[n][4]);
+
+
+		lseg(CTOX(52), RTOY(3) + 13,
+			CTOX(52) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(54), RTOY(3) + 13,
+			CTOX(55) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(57), RTOY(3) + 13,
+			CTOX(57) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(59), RTOY(3) + 13,
+			CTOX(59) + 7, RTOY(3) + 13, adbox[n][4]);
+
+		lseg(CTOX(61), RTOY(3) + 13,
+			CTOX(62) + 7, RTOY(3) + 13, adbox[n][4]);
+
+/* 
+
+*/
+		for (i = 0; i < 6; i++) {
+
+			sprintf(bfs, "%c %02.2d %d %s %s  %c %02.2d %d %s %s",
+
+				i + '1',
+				(ins2grp[i] & 0x00FF), grpdyn[i],
+				gprep[grp2prt[i][0]],
+				numblk(buf1, grp2prt[i][1]),
+
+				((i > 2) ? (i + 169) : (i + '7')),
+				(ins2grp[i + 6] & 0x00FF), grpdyn[i + 6],
+				gprep[grp2prt[i + 6][0]],
+				numblk(buf2, grp2prt[i + 6][1]));
+
+			tsplot4(asgob, 64, adbox[n][4], adbox[n][6] + i + 4,
+				adbox[n][7], bfs, 14);
+
+			if (GTAG1 & ins2grp[i]) {
+
+				bfs[1] = '\0';
+
+				tsplot4(asgob, 64, AK_MODC, adbox[n][6] + i + 4,
+					adbox[n][7], bfs, 14);
+			}
+
+			if (GTAG1 & ins2grp[i + 6]) {
+
+				bfs[14] = '\0';
+
+				tsplot4(asgob, 64, AK_MODC, adbox[n][6] + i + 4,
+					adbox[n][7] + 13, &bfs[13], 14);
+			}
+		}
+
+		return;
+/* 
+
+*/
+	case 7:		/* port 1 key to group assignments */
+
+		lseg(  8, 153,  15, 153, exp_c(adbox[n][4]));	/* underlines */
+		lseg(496, 153, 503, 153, exp_c(adbox[n][4]));
+
+		asgkb();					/* icon */
+
+		for (i = 0; i < 12; i++)			/* assignments */
+			drawk2g(i);
+
+		return;
+
+	case 8:		/* aux control */
+
+		tsplot4(asgob, 64, (auxctl ? AK_MODC : adbox[n][4]),
+			adbox[n][6], adbox[n][7], "Aux", 14);
+
+		return;
+
+	case 9:		/* tuning table */
+
+		tsplot4(asgob, 64, adbox[n][4], adbox[n][6], adbox[n][7],
+			"Tun", 14);
+
+		sprintf(bfs, "%d", curtun);
+		tsplot4(asgob, 64, (tunmod ? AK_MODC : adbox[n][4]),
+			adbox[n][6], adbox[n][7] + 4, bfs, 14);
+			
+		return;
+
+	case 10:	/* phase shifter variables -- intensity, rate depth */
+
+		sprintf(bfs, "Intnsty %02.2d", ps_intn);
+		tsplot4(asgob, 64, adbox[n][4],	adbox[n][6] + 1, adbox[n][7],
+			bfs, 14);
+			
+		sprintf(bfs, "ModRate %02.2d", ps_rate);
+		tsplot4(asgob, 64, adbox[n][4],	adbox[n][6] + 2, adbox[n][7],
+			bfs, 14);
+			
+		sprintf(bfs, "ModDpth %02.2d", ps_dpth);
+		tsplot4(asgob, 64, adbox[n][4],	adbox[n][6] + 3, adbox[n][7],
+			bfs, 14);
+			
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	initat() -- initialize assignment table
+   =============================================================================
+*/
+
+initat(n)
+short n;
+{
+	register struct asgent *ap;
+	register short i;
+
+	ap = &asgtab[n];
+	ap->a_mop  = 0;			/* output to NULL */
+	ap->a_tun  = 0;			/* tuning = default */
+	ap->a_aux  = 0;			/* aux ctl = OFF */
+	ap->a_intn = 70;		/* intensity */
+	ap->a_rate = 0;			/* rate */
+	ap->a_dpth = 70;		/* depth */
+
+	for (i = 0; i < 12; i++) {	/* groups 1..12 */
+
+		ap->a_i2grp[i] = 0;	/* instrument */
+		ap->a_gpdyn[i] = 9;	/* dynamics */
+	}
+
+	for (i = 0; i < 8; i++)		/* voices 1..8 to group 1 */
+		ap->a_v2grp[i] = 1;
+
+	for (i = 8; i < 12; i++)	/* voices 9..12 to group 2 */
+		ap->a_v2grp[i] = 2;
+
+	ap->a_mctln[0] = 1;		/* modulation wheel */
+	ap->a_mctln[1] = 2;		/* breath controller */
+	ap->a_mctln[2] = 80;		/* general controller 1 */
+	ap->a_mctln[3] = 4;		/* pedal controller 1 */
+
+	ap->a_g2prt[0][0] = 1;		/* group 1:  port 1 input */
+	ap->a_g2prt[0][1] = 1;		/* group 1:  channel 1 in and out */
+	ap->a_g2prt[1][0] = 3;		/* group 2:  local input */
+	ap->a_g2prt[1][1] = 1;		/* group 2:  channel 1 in and out*/
+
+	for (i = 2; i < 12; i++) {	/* groups 3..12 */
+
+		ap->a_g2prt[i][0] = 0;	/* no input port */
+		ap->a_g2prt[i][1] = -1;	/* no channel */
+	}
+
+	memsetw(ap->a_k2grp, 0x0001, 88);	/* all keys in group 1 */
+
+	memcpy(ap->a_name, n ? "{unused}        " : "{Default}       ", 16);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setaux() -- set aux control
+   =============================================================================
+*/
+
+setaux(aux)
+register short aux;
+{
+	register short psgdata;
+	register char *psg;
+
+	auxctl = aux;
+	psg = &io_tone;
+
+	*(psg + PSG_ADDR) = PSG_IOEN;		/* setup PSG I/O controls */
+	*(psg + PSG_WRIT) = PSG_IDLE;
+
+	*(psg + PSG_ADDR) = PSG_PRTB;		/* read current psg data */
+	psgdata = *(psg + PSG_READ) & ~AUX_BIT;
+
+	*(psg + PSG_ADDR) = PSG_PRTB;		/* send out updated aux data */
+	*(psg + PSG_WRIT) = psgdata | (aux ? 0 : AUX_BIT);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	getasg() -- get an assignment table from the library
+   =============================================================================
+*/
+
+getasg(n)
+short n;
+{
+	register struct asgent *ap;
+	register short i, grp, vce;
+
+	ap = &asgtab[n];
+	curmop = ap->a_mop;
+	gettun(ap->a_tun);
+	setaux(ap->a_aux);
+	ps_intn = ap->a_intn;
+	ps_rate = ap->a_rate;
+	ps_dpth = ap->a_dpth;
+	memcpyw(ins2grp, ap->a_i2grp, sizeof ins2grp / 2);
+	memcpyw(grpdyn, ap->a_gpdyn, sizeof grpdyn / 2);
+	memcpyw(vce2grp, ap->a_v2grp, sizeof vce2grp / 2);
+	memcpyw(mctlnum, ap->a_mctln, sizeof mctlnum / 2);
+	memcpyw(grp2prt, ap->a_g2prt, sizeof grp2prt / 2);
+	memcpyw(key2grp, ap->a_k2grp, sizeof key2grp / 2);
+	memcpy(caname, ap->a_name, 16);
+
+	for (i = 0; i < 12; i++)		/* fix old tables */
+		if (grp2prt[i][0] EQ 4)
+			grp2prt[i][0] = 3;
+
+	sendval(1, 0, (ps_intn * 10) << 5);
+	sendval(2, 0, (ps_rate * 10) << 5);
+	sendval(3, 0, (ps_dpth * 10) << 5);
+
+	for (vce = 0; vce < 12; vce++) {
+
+		grp = vce2grp[vce];
+
+		if (grp NE -1) {
+
+			s_inst[vce] = ins2grp[grp - 1] & 0x00FF;
+			execins(vce, s_inst[vce], 1);
+			sendval(vce, 8, dyntab[grpdyn[grp - 1]]);
+		}
+	}
+
+	newvce(curvce);
+	asgmod = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	putasg() -- put an assignment table into the library
+   =============================================================================
+*/
+
+putasg(n)
+short n;
+{
+	register struct asgent *ap;
+	register short i;
+
+	for (i = 0; i < 12; i++)		/* fix old tables */
+		if (grp2prt[i][0] EQ 4)
+			grp2prt[i][0] = 3;
+
+	ap = &asgtab[n];
+	ap->a_mop = curmop;
+	ap->a_tun = curtun;
+	ap->a_aux = auxctl;
+	ap->a_intn = ps_intn;
+	ap->a_rate = ps_rate;
+	ap->a_dpth = ps_dpth;
+	memcpyw(ap->a_i2grp, ins2grp, sizeof ins2grp / 2);
+	memcpyw(ap->a_gpdyn, grpdyn, sizeof grpdyn / 2);
+	memcpyw(ap->a_v2grp, vce2grp, sizeof vce2grp / 2);
+	memcpyw(ap->a_mctln, mctlnum, sizeof mctlnum / 2);
+	memcpyw(ap->a_g2prt, grp2prt, sizeof grp2prt / 2);
+	memcpyw(ap->a_k2grp, key2grp, sizeof key2grp / 2);
+	memcpy(ap->a_name, caname, 16);
+	asgmod = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	awins() -- display all assignment editor windows
+   =============================================================================
+*/
+
+awins()
+{
+	register short i;
+
+	for (i = 0; i < 11; i++)
+		adswin(i);
+}
+
+/*
+   =============================================================================
+	inital() -- initialize assignment library
+   =============================================================================
+*/
+
+inital()
+{
+	register short n;
+
+	for (n = 0; n < NASGS; n++)
+		initat(n);
+
+	getasg(0);
+	prgchan = 1;
+}
+
+/* 
+
+*/
+	
+/*
+   =============================================================================
+	adbord() -- draw the border for the  display
+   =============================================================================
+*/
+
+adbord()
+{
+	point = adpoint;
+
+	lseg(  0,   0, 511,   0, AK_BORD);	/* outer border */
+	lseg(511,   0, 511, 349, AK_BORD);
+	lseg(511, 349,   0, 349, AK_BORD);
+	lseg(  0, 349,   0,   0, AK_BORD);
+
+	lseg(  0,  41,  95,  41, AK_BORD);	/* windows - H lines */
+	lseg(  0,  55,  95,  55, AK_BORD);
+	lseg(  0,  69,  95,  69, AK_BORD);
+	lseg(  0,  83,  95,  83, AK_BORD);
+	lseg(  0, 139, 511, 139, AK_BORD);
+
+	lseg( 39,  69,  39,  83, AK_BORD);	/* windows - V lines */
+	lseg( 95,   0,  95, 139, AK_BORD);
+	lseg(191,   0, 191, 139, AK_BORD);
+	lseg(303,   0, 303, 139, AK_BORD);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	asgdsp() -- put up the assignment display
+   =============================================================================
+*/
+
+asgdsp()
+{
+	asgob = v_score;		/* setup object pointer */
+	obj0  = v_curs0;		/* setup cursor object pointer */
+	obj2  = v_tcur;			/* setup typewriter object pointer */
+	adoct = &v_obtab[ASGOBJ];	/* setup object control table pointer */
+
+	adnamsw = FALSE;		/* virtual typewriter not up */
+	submenu = FALSE;		/* no submenu cursor up */
+	admctl  = -1;			/* no submenu up */
+
+	dswap();			/* initialize display */
+
+	vbank(0);			/* clear the display */
+	memsetw(asgob, 0, 32767);
+	memsetw(asgob+32767L, 0, 12033);
+
+	SetObj(ASGOBJ, 0, 0, asgob, 512, 350,       0,       0,  ASGNFL, -1);
+	SetObj(     0, 0, 1,  obj0,  16,  16, CTOX(9), RTOY(0), OBFL_00, -1);
+	SetObj(TTCURS, 0, 1,  obj2,  16,  16,       0,       0,  TTCCFL, -1);
+
+	arcurs(AK_CURS);	/* setup arrow cursor object */
+	itcini(AK_CURS);	/* setup text cursor object */
+	ttcini(AK_CURS);	/* setup virtual typewriter cursor object */
+
+	adbord();		/* draw the border */
+	awins();		/* fill in the windows */
+
+	SetPri(ASGOBJ, ASGPRI);		/* enable screen object */
+
+	settc(0, 9);			/* display text cursor */
+
+	vsndpal(asgpal);		/* set the palette */
+}
Index: ram/asgvce.c
===================================================================
--- ram/asgvce.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/asgvce.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,463 @@
+/*
+   =============================================================================
+	asgvce.c -- MIDAS-VII -- assign voice / enter notes into score
+	Version 12 -- 1988-10-03 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#undef	DEBUGGER 		/* define to enable debug trace */
+
+#define	DEBUGIT		0
+
+#include "debug.h"
+
+#include "biosdefs.h"
+#include "stddefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "smdefs.h"
+#include "sclock.h"
+#include "score.h"
+#include "slice.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "scfns.h"
+#include "scdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+/* 
+
+*/
+
+extern	short	clksrc;		/* clock source */
+extern	short	curasg;		/* current assignment table */
+extern	short	legato;		/* "legato" mode flag */
+extern	short	lstbgnc;	/* last note begin entry count */
+extern	short	lstendc;	/* last note end entry count */
+extern	short	lstflag;	/* last note list end flag */
+extern	short	ndisp;		/* current display number */
+extern	short	newflag;	/* new data entered while t_ctr EQ t_cur */
+extern	short	nkdown;		/* number of keys down */
+extern	short	recsw;		/* record/play switch */
+extern	short	sd;		/* score display direction */
+extern	short	se;		/* score execution direction */
+extern	short	stepenb;	/* step enable */
+extern	short	stepint;	/* note interval */
+extern	short	stepwgt;	/* note weight */
+extern	short	velflag;	/* velocity display enable flag */
+
+extern	short	grpmode[];	/* group mode table */
+extern	short	grpstat[];	/* group status table */
+extern	short	ins2grp[];	/* instrument to group assigments */
+extern	short	vce2grp[];	/* voice to group map */
+extern	short	lastvce[];	/* last voice assigned in each group */
+extern	short	lastvel[];	/* last velocity seen by each group */
+extern	short	tuntab[];	/* current tuning table */
+extern	short	vce2trg[];	/* voice to trigger map (-1 EQ NULL) */
+
+extern	short	stepfrm[][17];	/* steps per frame table */
+
+extern	unsigned	*obj8;	/* score display object pointer */
+
+extern	struct	gdsel	*gdstbc[];	/* group status table - center slice */
+
+extern	struct	n_entry	*lstbgns[NLSTENTS];	/* note begin pointers */
+extern	struct	n_entry	*lstends[NLSTENTS];	/* note end pointers */
+
+extern	struct	nevent	*nefree;	/* pointer to free note entries */
+extern	struct	nevent	*nelist;	/* pointer to note entry list */
+
+extern	struct	nevent	nevents[NNEVTS];	/* note event list */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clrnl() -- clear note list
+   =============================================================================
+*/
+
+clrnl()
+{
+	register short i;
+
+	DB_ENTR("clrnl");
+
+	for (i = 0; i < NNEVTS - 1; i++) {
+
+		nevents[i].nxt   = &nevents[i + 1];
+		nevents[i].note  = 0;
+		nevents[i].group = 0;
+	}
+
+	nevents[NNEVTS - 1].nxt = (struct nevent *)0L;
+
+	nelist = (struct nevent *)0L;
+	nefree = &nevents[0];
+	nkdown = 0;
+
+	DB_EXIT("clrnl");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ne_end() -- enter a note end event
+   =============================================================================
+*/
+
+ne_end(trg, grp)
+short trg;
+register short grp;
+{
+	register short nn;
+	register long fcend;
+	register struct nevent *nx;
+	register struct n_entry *ep;
+
+	DB_ENTR("ne_end");
+
+	/* must be recording into a voice in record mode ... */
+
+	if ((recsw EQ 0) OR (grpmode[grp] NE 2)) {
+
+		DB_EXIT("ne_end");
+		return;			/* ... or, we're done */
+	}
+
+	DB_CMNT("ne_end - recording");
+
+	/* make pointers point in the forward direction */
+
+	if (sd EQ D_BAK)
+		chgsdf();
+
+	if (se EQ D_BAK)
+		chgsef();
+/* 
+
+*/
+	nn = trg & 0x007F;		/* note number */
+
+	if (clksrc NE CK_STEP) {	/* not in step mode */
+
+		DB_CMNT("ne_end - non-step");
+
+		if (E_NULL NE (ep = (struct n_entry *)e_alc(E_SIZE1))) {
+
+			DB_CMNT("ne_end - enter note end");
+			ep->e_time  = t_cur;
+			ep->e_type  = EV_NEND | 0x80;
+			ep->e_note  = nn;
+			ep->e_group = grp;
+			ep->e_vel   = SM_SCALE(64);
+
+			p_cur = e_ins((struct s_entry *)ep,
+				      ep_adj(p_cur, 0, t_cur))->e_fwd;
+
+			if (t_cur EQ t_ctr)
+				newflag = TRUE;
+
+			se_disp(ep, D_FWD, gdstbc, 1);
+
+		} else {
+
+			DB_CMNT("ne_end - no space");
+		}
+
+		DB_EXIT("ne_end");
+		return;
+/* 
+
+*/
+	} else if (nkdown GE 1) {	/* process note entry in step mode */
+
+		DB_CMNT("ne_end - log key up");
+
+		if (0 EQ --nkdown) {	/* if all keys are up ... */
+
+			if (stepenb) {
+
+				/* advance by the note weight */
+
+				DB_CMNT("ne_end - advance weight");
+				fcend = fc_val + stepfrm[3][stepint];
+				fc_val += stepfrm[stepwgt][stepint];
+				sc_trek(fc_val);
+				sc_trak(fc_val);
+				DB_CMNT("ne_end - doing note ends");
+			}
+
+			while (nelist) {
+
+				nn = nelist->note;	/* get note */
+				grp = nelist->group;	/* get group */
+
+				if (E_NULL NE (ep = (struct n_entry *)e_alc(E_SIZE1))) {
+
+					DB_CMNT("ne_end - enter note end");
+					ep->e_time  = t_cur;
+					ep->e_type  = EV_NEND | 0x80;
+					ep->e_note  = nn;
+					ep->e_group = grp;
+					ep->e_vel   = SM_SCALE(64);
+
+					p_cur = e_ins((struct s_entry *)ep,
+						      ep_adj(p_cur, 0, t_cur))->e_fwd;
+
+					se_disp(ep, D_FWD, gdstbc, 1);
+
+					if (lstendc < NLSTENTS)
+						lstends[lstendc++] = ep;
+
+				} else {
+
+					DB_CMNT("ne_end - no space");
+				}
+/* 
+
+*/
+				DB_CMNT("ne_end - freeing nevent");
+				nx = nelist->nxt;	/* get next nelist ptr */
+				nelist->nxt = nefree;	/* free nelist entry */
+				nefree = nelist;	/* ... */
+				nelist = nx;		/* update nelist */
+			}
+
+			lstflag = TRUE;		/* indicate end of list */
+
+			DB_CMNT("ne_end - note ends done");
+
+			if (stepenb) {
+
+				if (fc_val LT fcend) {	/* advance to the interval */
+
+					DB_CMNT("ne_end - advance interval");
+					fc_val = fcend;
+					sc_trek(fc_val);
+					sc_trak(fc_val);
+				}
+			}
+		}
+
+	} else {
+
+		nkdown  = 0;		/* no keys down */
+
+		lstendc = 0;		/* no step entries to delete */
+		lstbgnc = 0;
+		lstflag = FALSE;
+	}
+
+	DB_EXIT("ne_end");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ne_bgn() -- enter a note begin event
+   =============================================================================
+*/
+
+ne_bgn(grp, key, vel)
+register short grp, key, vel;
+{
+	register struct n_entry *ep;
+	register struct nevent *np;
+
+	DB_ENTR("ne_bgn");
+
+	/* must be recording into a group in record mode ... */
+
+	if ((recsw NE 0) AND (grpmode[grp] EQ 2)) {
+
+		DB_CMNT("ne_bgn - recording");
+
+		/* make pointers point in the forward direction */
+
+		if (sd EQ D_BAK)
+			chgsdf();
+
+		if (se EQ D_BAK)
+			chgsef();
+
+		if (lstflag) {			/* cancel old list of notes */
+
+			lstbgnc = 0;
+			lstendc = 0;
+			lstflag = FALSE;
+		}
+
+		if (clksrc EQ CK_STEP) {	/* step mode */
+
+			DB_CMNT("ne_bgn - step");
+			++nkdown;		/* count keys down */
+
+			if (nefree) {		/* log a key closure */
+
+				np        = nefree;
+				nefree    = np->nxt;
+				np->note  = key;
+				np->group = grp;
+				np->nxt   = nelist;
+				nelist    = np;
+				DB_CMNT("ne_bgn - key logged");
+
+			} else {
+
+				DB_CMNT("ne_bgn - nefree empty");
+			}
+		}
+/* 
+
+*/
+		if (E_NULL NE (ep = (struct n_entry *)e_alc(E_SIZE1))) {
+
+			DB_CMNT("ne_bgn - enter note begin");
+			ep->e_time  = t_cur;
+			ep->e_type  = EV_NBEG | 0x80;
+			ep->e_note  = key;
+			ep->e_group = grp;
+			ep->e_vel   = (clksrc EQ CK_STEP) ? SM_SCALE(64) : vel;
+
+			p_cur = e_ins((struct s_entry *)ep,
+				      ep_adj(p_cur, 0, t_cur))->e_fwd;
+
+			se_disp(ep, D_FWD, gdstbc, 1);
+
+			if (t_cur EQ t_ctr)
+				newflag = TRUE;
+
+			if ((clksrc EQ CK_STEP) AND (lstbgnc < NLSTENTS))
+				lstbgns[lstbgnc++] = ep;
+
+		} else {
+
+			DB_CMNT("ne_bgn - no space");
+		}
+	}
+
+	DB_EXIT("ne_bgn");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showvel() -- display velocity for a group
+   =============================================================================
+*/
+
+showvel(g, v)
+short g, v;
+{
+	char buf[6];
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	lastvel[g] = v;
+
+	sprintf(buf, "%03d", (v / 252));
+
+	vputs(obj8, 5, (g * 5) + 6, buf, SDW11ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	asgvce() -- assign a voice
+   =============================================================================
+*/
+
+asgvce(grp, port, chan, key, vel)
+short grp, port, chan, key, vel;
+{
+	register short i;
+	register short tv;
+	register short vp;
+	register short trg;
+	register short aflag;
+	register struct nevent *np;
+	register struct n_entry *ep;
+
+	DB_ENTR("asgvce");
+
+	trg = (port << 11) + (chan << 7) + key;	/* trigger number */
+	vp  = lastvce[grp] + 1;			/* voice to start with */
+	vp  = (vp > 11) ? 0 : vp;		/* ... (adjust into range) */
+
+/* 
+
+*/
+
+	DB_CMNT("asgvce - search unassgined");
+
+	for (i = 12; i--; ) {	/* search for unassigned voice */
+
+		if ((vce2trg[vp] EQ -1) AND (vce2grp[vp] EQ (grp + 1))) {
+
+			if ((ndisp EQ 2) AND velflag AND (NOT recsw))
+				showvel(grp, vel);
+
+			lastvce[grp] = vp;
+			execkey(trg, tuntab[key], vp, 0);
+			DB_EXIT("asgvce - free voice");
+			return;
+		}
+
+		if (++vp > 11)
+			vp = 0;
+	}
+
+	DB_CMNT("asgvce - seach non-held");
+
+	for (i = 12; i--; ) {	/* search for non-held voice */
+
+		tv = vce2trg[vp];
+
+		if (tv EQ -1)
+			aflag = TRUE;		/* OK - unassigned */
+		else if (0 EQ (tv & (MKEYHELD << 8)))
+			aflag = TRUE;		/* OK - not held */
+		else
+			aflag = FALSE;		/* NO - held */
+
+		if (aflag AND (vce2grp[vp] EQ (grp + 1))) {
+
+			if ((ins2grp[grp] & GTAG1) AND
+			    (tv NE trg) AND (tv NE -1))
+				legato = 1;
+
+			if ((ndisp EQ 2) AND velflag AND (NOT recsw))
+				showvel(grp, vel);
+
+			lastvce[grp] = vp;
+			execkey(trg, tuntab[key], vp, 0);
+ 			DB_EXIT("asgvce - stolen voice");
+			return;
+		}
+
+		if (++vp > 11)
+			vp = 0;
+	}
+
+ 	DB_EXIT("asgvce - no voice");
+}
Index: ram/barbadj.c
===================================================================
--- ram/barbadj.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/barbadj.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,359 @@
+/*
+   =============================================================================
+	barbadj.c -- MIDAS-VII -- GLC bar graph drivers
+	Version 8 -- 1988-10-27 -- D.N. Lynx Crowe
+
+	BarBadj(bar, val)
+	short bar, val;
+
+		Adjusts a bottom-zero bar graph, 'bar',
+		to read 'val'.
+
+	BarBset(bar, val)
+	short bar, val;
+
+		Sets a bottom-zero bar graph, 'bar',
+		to an intial value, 'val'.
+
+	BarCadj(bar, val)
+	short bar, val;
+
+		Adjusts a centered-zero bar graph, 'bar',
+		to read 'val'.
+
+	BarCset(bar, val)
+	short bar, val;
+
+		Sets a centered-zero bar graph, 'bar',
+		to an intial value, 'val'.
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "glcfns.h"
+#include "glcdefs.h"
+
+extern	short	BarBcur[];
+extern	short	BarCcur[];
+
+/* left-most bar columns */
+
+short	BarCols[14] = { 2, 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80 };
+
+/* bar dot data */
+
+short	BarDots[3] = { 0x1C, 0xFC, 0xE0 };
+
+#include "glcbars.h"		/* bar graph driver constant definitions */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	BarBadj() -- adjust a bottom-zero bar graph to a new value
+   =============================================================================
+*/
+
+BarBadj(bar, val)
+short bar, val;
+{
+	register short bardot, barpos, curdif;
+	register unsigned baradr;
+	short barcol, bardif, curbar, i, newbar;
+
+	newbar = BarBLn[val];		/* look up the new bar position */
+	curbar = BarBcur[bar];		/* get the current bar position */
+	bardif = newbar - curbar;	/* calculate how far to move the bar */
+
+	if (0 EQ bardif)	/* done if bar doesn't need to be moved */
+		return;
+
+	GLCcurs(G_ON);		/* turn on GLC cursor to enable writing */
+	barcol = BarCols[bar];	/* find leftmost column of bar */
+
+	if (bardif > 0) {	/* increasing value */
+
+		/* calculate initial GLC RAM write address */
+
+		baradr = barcol + (85 * (63 - (curbar + 1))) + G_PLANE2;
+
+		LCD_WC = G_CRSMUP;		/* set cursor motion "up" */
+
+		for (i = 0; i < 3; i++) {	/* for each bar column ... */
+
+			curdif = bardif;	/* set difference counter */
+			bardot = BarDots[i];	/* get the column dot value */
+
+			LCD_WC = G_CRSWR;	/* set cursor address */
+			LCD_WD = baradr & 0xFF;
+			LCD_WD = (baradr >> 8) & 0xFF;
+
+			++baradr;		/* update GLC start address */
+
+			LCD_WC = G_MWRITE;	/* setup to write */
+
+			while (curdif--)	/* write new dots */
+				LCD_WD = bardot;
+		}
+/* 
+
+*/
+	} else {		/* decreasing value */
+
+		/* calculate initial GLC RAM write address */
+
+		baradr = barcol + (85 * (63 - curbar)) + G_PLANE2;
+
+		LCD_WC = G_CRSMDN;		/* set cursor motion "down" */
+
+		for (i = 0; i < 3; i++) {	/* for each bar column ... */
+
+			curdif = -bardif;	/* set difference counter */
+
+			LCD_WC = G_CRSWR;	/* set cursor address */
+			LCD_WD = baradr & 0xFF;
+			LCD_WD = (baradr >> 8) & 0xFF;
+
+			++baradr;		/* update GLC start address */
+
+			LCD_WC = G_MWRITE;	/* setup to write */
+
+			while (curdif--)	/* erase old dots */
+				LCD_WD = 0x00;
+		}
+	}
+
+	LCD_WC = G_CRSMRT;		/* set cursor motion = "right" */
+	GLCcurs(G_OFF);			/* turn off the cursor */
+
+	BarBcur[bar] = newbar;		/* update current bar position */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	BarBset() -- set a bottom-zero bar graph to an initial value
+   =============================================================================
+*/
+
+BarBset(bar, val)
+short bar, val;
+{
+	register short bardot, barpos, newbar;
+	register unsigned baradr;
+	short barcol, i;
+
+	newbar = BarBLn[val];	/* look up the new bar position */
+	barcol = BarCols[bar];	/* find leftmost column of bar */
+
+	GLCcurs(G_ON);		/* turn on GLC cursor to enable writing */
+
+	/* calculate initial GLC RAM write address */
+
+	baradr = barcol + (85 * (63 - BBase)) + G_PLANE2;
+
+	LCD_WC = G_CRSMUP;		/* set cursor motion = "up" */
+
+	for (i = 0; i < 3; i++) {	/* for each bar column ... */
+
+		bardot = BarDots[i];	/* get the column dot value */
+		barpos = BBase;		/* get base of bar */
+
+		LCD_WC = G_CRSWR;	/* set cursor address */
+		LCD_WD = baradr & 0xFF;
+		LCD_WD = (baradr >> 8) & 0xFF;
+
+		++baradr;		/* update GLC start address */
+
+		LCD_WC = G_MWRITE;	/* setup to write */
+
+		while (barpos++ LE newbar)	/* write new dots */
+			LCD_WD = bardot;
+
+		while (barpos++ < BTop)		/* erase old dots */
+			LCD_WD = 0x00;
+	}
+
+	LCD_WC = G_CRSMRT;		/* set cursor motion = "right" */
+	GLCcurs(G_OFF);			/* turn off the cursor */
+	
+	BarBcur[bar] = newbar;		/* update current bar position */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	BarCadj() -- adjust a centered-zero bar graph to a new value
+   =============================================================================
+*/
+
+BarCadj(bar, val)
+short bar, val;
+{
+	register short bardot, barpos, newbar;
+	register unsigned baradr;
+	short barcol, bardif, curbar, i;
+
+	newbar = BarCLn[val + BOffset];	/* look up the new bar position */
+	curbar = BarCcur[bar];		/* get the current bar position */
+	bardif = newbar - curbar;	/* calculate how far to move the bar */
+
+	if (0 EQ bardif)	/* done if bar doesn't need to be moved */
+		return;
+
+	GLCcurs(G_ON);		/* turn on GLC cursor to enable writing */
+
+	barcol = BarCols[bar];	/* find leftmost column of bar */
+
+	/* calculate initial GLC RAM write address */
+
+	baradr = barcol + (85 * (63 - curbar)) + G_PLANE2;
+
+/* 
+
+*/
+	if (newbar > curbar) {	/* increasing value */
+
+		LCD_WC = G_CRSMUP;		/* set cursor motion "up" */
+
+		for (i = 0; i < 3; i++) {	/* for each bar column ... */
+
+			bardot = BarDots[i];	/* get the column dot value */
+			barpos = curbar;	/* set current vert. position */
+
+			LCD_WC = G_CRSWR;	/* set cursor address */
+			LCD_WD = baradr & 0xFF;
+			LCD_WD = (baradr >> 8) & 0xFF;
+
+			LCD_WC = G_MWRITE;	/* setup to write */
+
+			while (barpos NE newbar)	/* write bar on LCD */
+				if (barpos++ < BCenter)
+					LCD_WD = 0x00;		/* dots off */
+				else
+					LCD_WD = bardot;	/* dots on */
+
+			++baradr;		/* update GLC start address */
+		}
+/* 
+
+*/
+	} else {		/* decreasing value */
+
+		LCD_WC = G_CRSMDN;		/* set cursor motion "down" */
+
+		for (i = 0; i < 3; i++) {	/* for each bar column ... */
+
+			bardot = BarDots[i];	/* get column dot value */
+			barpos = curbar;	/* set current bar location */
+
+			LCD_WC = G_CRSWR;	/* set cursor address */
+			LCD_WD = baradr & 0xFF;
+			LCD_WD = (baradr >> 8) & 0xFF;
+
+			LCD_WC = G_MWRITE;	/* setup to write */
+
+			while (barpos NE newbar)	/* write bar to LCD */
+				if (barpos-- > BCenter)
+					LCD_WD= 0x00;		/* dots off */
+				else
+					LCD_WD = bardot;	/* dots on */
+
+			++baradr;		/* update GLC start address */
+		}
+	}
+
+	LCD_WC = G_CRSMRT;		/* set cursor motion = "right" */
+	GLCcurs(G_OFF);			/* turn off the cursor */
+	
+	BarCcur[bar] = newbar;		/* update current bar position */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	BarCset() -- set a centered-zero bar graph to an initial value
+   =============================================================================
+*/
+
+BarCset(bar, val)
+short bar, val;
+{
+	register short bardot, barpos, barloc1, barloc2;
+	register unsigned baradr;
+	short barcol, i, newbar;
+
+	GLCcurs(G_ON);		/* turn on GLC cursor to enable writing */
+
+	newbar = BarCLn[val + BOffset];	/* look up the new bar position */
+	barcol = BarCols[bar];		/* find leftmost column of bar */
+
+	/* calculate initial GLC RAM write address */
+
+	baradr = barcol + (85 * (63 - BBase)) + G_PLANE2;
+
+	if (newbar < BCenter) {		/* target below center */
+
+		barloc1 = newbar;	/* off limit */
+		barloc2 = BCenter;	/* on limit */
+
+	} else {			/* target at or above center */
+
+		barloc1 = BCenter;	/* off limit */
+		barloc2 = newbar;	/* on limit */
+	}
+
+	LCD_WC = G_CRSMUP;		/* set cursor motion "up" */
+
+/* 
+
+*/
+	for (i = 0; i < 3; i++) {	/* for each bar column ... */
+
+		bardot = BarDots[i];	/* get the column dot value */
+		barpos = BBase;		/* set current vert. position */
+
+		LCD_WC = G_CRSWR;	/* set cursor address */
+		LCD_WD = baradr & 0xFF;
+		LCD_WD = (baradr >> 8) & 0xFF;
+
+		LCD_WC = G_MWRITE;	/* setup to write */
+
+		while (barpos < barloc1) {	/* write "off" dots */
+
+			LCD_WD = 0x00;
+			barpos++;
+		}
+
+		while (barpos LE barloc2) {	/* write "on" dots */
+
+			LCD_WD = bardot;
+			barpos++;
+		}
+
+		while (barpos LE BTop) {	/* write "off" dots */
+
+			LCD_WD = 0x00;
+			barpos++;
+		}
+
+		++baradr;		/* update GLC start address */
+	}
+
+	LCD_WC = G_CRSMRT;		/* set cursor motion = "right" */
+	GLCcurs(G_OFF);			/* turn off the cursor */
+	
+	BarCcur[bar] = newbar;		/* update current bar position */
+}
Index: ram/chgsef.c
===================================================================
--- ram/chgsef.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/chgsef.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,245 @@
+/*
+   =============================================================================
+	chgsef.c -- MIDAS-VII -- change score direction
+	Version 1 -- 1988-08-01 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "sclock.h"
+#include "slice.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+
+extern	short	sd;
+extern	short	se;
+
+extern	struct	gdsel	*gdstbc[];
+extern	struct	gdsel	*gdstbn[];
+extern	struct	gdsel	*gdstbp[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	chgsef() -- change execution pointers to D_FWD
+   =============================================================================
+*/
+
+chgsef()
+{
+	register struct s_entry *ep;
+	register long rt;
+
+	se = D_FWD;
+
+	ep = p_cur;
+	rt = t_cur;
+
+	if (EV_FINI NE ep->e_type) {
+
+		ep = ep->e_fwd;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_FINI EQ ep->e_type)
+				break;
+
+			se_exec(ep, se);
+			ep = ep->e_fwd;
+		}
+
+		p_cur = ep;
+	}
+}
+
+/*
+   =============================================================================
+	chgseb() -- change execution pointers to D_BAK
+   =============================================================================
+*/
+
+chgseb()
+{
+	register struct s_entry *ep;
+	register long rt;
+
+	se = D_BAK;
+
+	ep = p_cur;
+	rt = t_cur;
+
+	if (EV_SCORE NE ep->e_type) {
+
+		ep = ep->e_bak;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_SCORE EQ ep->e_type)
+				break;
+
+			se_exec(ep, se);
+			ep = ep->e_bak;
+		}
+
+		p_cur = ep;
+	}
+}
+
+/*
+   =============================================================================
+	chgsdf() -- change display pointers to D_FWD
+   =============================================================================
+*/
+
+chgsdf()
+{
+	register struct s_entry *ep;
+	register long rt;
+
+	sd = D_FWD;
+
+	rslice(gdstbc);
+	rslice(gdstbn);
+	rslice(gdstbp);
+
+	ep = p_ctr;
+	rt = t_ctr;
+
+	if (EV_FINI NE ep->e_type) {
+
+		ep = ep->e_fwd;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_FINI EQ ep->e_type)
+				break;
+
+			se_disp(ep, D_FWD, gdstbc, 1);
+			ep = ep->e_fwd;
+		}
+
+		p_ctr = ep;
+	}
+
+	ep = p_bak;
+	rt = t_bak;
+
+	if (EV_FINI NE ep->e_type) {
+
+		ep = ep->e_fwd;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_FINI EQ ep->e_type)
+				break;
+
+			se_disp(ep, D_FWD, gdstbp, 0);
+			ep = ep->e_fwd;
+		}
+
+		p_bak = ep;
+	}
+
+	ep = p_fwd;
+	rt = t_fwd;
+
+	if (EV_FINI NE ep->e_type) {
+
+		ep = ep->e_fwd;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_FINI EQ ep->e_type)
+				break;
+
+			se_disp(ep, D_FWD, gdstbn, 0);
+			ep = ep->e_fwd;
+		}
+
+		p_fwd = ep;
+	}
+}
+
+/*
+   =============================================================================
+	chgsdb() -- change display pointers to D_BAK
+   =============================================================================
+*/
+
+chgsdb()
+{
+	register struct s_entry *ep;
+	register long rt;
+
+	sd = D_BAK;
+
+	rslice(gdstbc);
+	rslice(gdstbn);
+	rslice(gdstbp);
+
+	ep = p_ctr;
+	rt = t_ctr;
+
+	if (EV_SCORE NE ep->e_type) {
+
+		ep = ep->e_bak;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_SCORE EQ ep->e_type)
+				break;
+
+			se_disp(ep, D_BAK, gdstbc, 1);
+			ep = ep->e_bak;
+		}
+
+		p_ctr = ep;
+	}
+
+	ep = p_bak;
+	rt = t_bak;
+
+	if (EV_SCORE NE ep->e_type) {
+
+		ep = ep->e_bak;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_SCORE EQ ep->e_type)
+				break;
+
+			se_disp(ep, D_BAK, gdstbp, 0);
+			ep = ep->e_bak;
+		}
+
+		p_bak = ep;
+	}
+
+	ep = p_fwd;
+	rt = t_fwd;
+
+	if (EV_SCORE NE ep->e_type) {
+
+		ep = ep->e_bak;
+
+		while (ep->e_time EQ rt) {
+
+			if (EV_SCORE EQ ep->e_type)
+				break;
+
+			se_disp(ep, D_BAK, gdstbn, 0);
+			ep = ep->e_bak;
+		}
+
+		p_fwd = ep;
+	}
+}
Index: ram/chksec.c
===================================================================
--- ram/chksec.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/chksec.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,610 @@
+/*
+   =============================================================================
+	chksec.c -- section operation support functions
+	Version 18 -- 1988-07-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#undef	DEBUGGER		/* define to enable debug trace */
+
+#include "stddefs.h"
+#include "debug.h"
+#include "score.h"
+#include "scfns.h"
+#include "secops.h"
+#include "secdefs.h"
+
+extern	short	ancmsw;
+extern	short	grptran;
+
+extern	short	grpmode[];
+extern	short	grpstat[];
+extern	short	grptmap[];
+
+extern	short	varmode[][16];
+
+short	cmslens[N_ETYPES] = {	/* score event sizes for copy / merge */
+
+	0,	/*  0 - EV_NULL		not copied or merged */
+	0,	/*  1 - EV_SCORE	not copied or merged */
+	0,	/*  2 - EV_SBGN		not copied or merged */
+	0,	/*  3 - EV_SEND		not copied or merged */
+	6,	/*  4 - EV_INST */
+	5,	/*  5 - EV_NBEG */
+	5,	/*  6 - EV_NEND */
+	5,	/*  7 - EV_STOP */
+	5,	/*  8 - EV_INTP */
+	6,	/*  9 - EV_TMPO */
+	6,	/* 10 - EV_TUNE */
+	6,	/* 11 - EV_GRP */
+	6,	/* 12 - EV_LOCN */
+	6,	/* 13 - EV_DYN */
+	6,	/* 14 - EV_ANVL */
+	6,	/* 15 - EV_ANRS */
+	6,	/* 16 - EV_ASGN */
+	6,	/* 17 - EV_TRNS */
+	5,	/* 18 - EV_REPT */
+	5,	/* 19 - EV_PNCH */
+	5,	/* 20 - EV_PRES */
+	0,	/* 21 - EV_FINI		not copied or merged */
+	5,	/* 22 - EV_CPRS */
+	5,	/* 23 - EV_BAR */
+	5	/* 24 - EV_NEXT */
+};
+
+/* 
+
+*/
+
+char	cmgtags[N_ETYPES] = {	/* score event group sensitivity tags */
+
+	FALSE,	/*  0 - EV_NULL		not copied or merged */
+	FALSE,	/*  1 - EV_SCORE	not copied or merged */
+	FALSE,	/*  2 - EV_SBGN		not copied or merged */
+	FALSE,	/*  3 - EV_SEND		not copied or merged */
+	TRUE,	/*  4 - EV_INST */
+	TRUE,	/*  5 - EV_NBEG */
+	TRUE,	/*  6 - EV_NEND */
+	FALSE,	/*  7 - EV_STOP */
+	FALSE,	/*  8 - EV_INTP */
+	FALSE,	/*  9 - EV_TMPO */
+	FALSE,	/* 10 - EV_TUNE */
+	TRUE,	/* 11 - EV_GRP */
+	TRUE,	/* 12 - EV_LOCN */
+	TRUE,	/* 13 - EV_DYN */
+	TRUE,	/* 14 - EV_ANVL */
+	TRUE,	/* 15 - EV_ANRS */
+	FALSE,	/* 16 - EV_ASGN */
+	TRUE,	/* 17 - EV_TRNS */
+	FALSE,	/* 18 - EV_REPT */
+	FALSE,	/* 19 - EV_PNCH */
+	FALSE,	/* 20 - EV_PRES */
+	FALSE,	/* 21 - EV_FINI		not copied or merged */
+	TRUE,	/* 22 - EV_CPRS */
+	FALSE,	/* 23 - EV_BAR */
+	FALSE	/* 24 - EV_NEXT */
+};
+
+/* 
+
+*/
+
+char	cmgtype[N_ETYPES] = {	/* score event group types for copy / merge */
+
+	0,	/*  0 - EV_NULL		not copied or merged */
+	0,	/*  1 - EV_SCORE	not copied or merged */
+	0,	/*  2 - EV_SBGN		not copied or merged */
+	0,	/*  3 - EV_SEND		not copied or merged */
+	0,	/*  4 - EV_INST */
+	1,	/*  5 - EV_NBEG */
+	1,	/*  6 - EV_NEND */
+	0,	/*  7 - EV_STOP */
+	0,	/*  8 - EV_INTP */
+	0,	/*  9 - EV_TMPO */
+	0,	/* 10 - EV_TUNE */
+	0,	/* 11 - EV_GRP */
+	0,	/* 12 - EV_LOCN */
+	0,	/* 13 - EV_DYN */
+	0,	/* 14 - EV_ANVL */
+	0,	/* 15 - EV_ANRS */
+	0,	/* 16 - EV_ASGN */
+	0,	/* 17 - EV_TRNS */
+	0,	/* 18 - EV_REPT */
+	0,	/* 19 - EV_PNCH */
+	0,	/* 20 - EV_PRES */
+	0,	/* 21 - EV_FINI		not copied or merged */
+	1,	/* 22 - EV_CPRS */
+	0,	/* 23 - EV_BAR */
+	0	/* 24 - EV_NEXT */
+};
+
+/* 
+
+*/
+
+short	ehdlist[N_ETYPES] = {		/* hplist update type table */
+
+	-1,		/*  0 - EV_NULL	*/
+	-1,		/*  1 - EV_SCORE */
+	EH_SBGN,	/*  2 - EV_SBGN	*/
+	EH_SEND,	/*  3 - EV_SEND	*/
+	EH_INST,	/*  4 - EV_INST */
+	-1,		/*  5 - EV_NBEG */
+	-1,		/*  6 - EV_NEND */
+	-1,		/*  7 - EV_STOP */
+	EH_INTP,	/*  8 - EV_INTP */
+	EH_TMPO,	/*  9 - EV_TMPO */
+	EH_TUNE,	/* 10 - EV_TUNE */
+	EH_GRP,		/* 11 - EV_GRP */
+	EH_LOCN,	/* 12 - EV_LOCN */
+	EH_DYN,		/* 13 - EV_DYN */
+	-1,		/* 14 - EV_ANVL */
+	EH_ANRS,	/* 15 - EV_ANRS */
+	EH_ASGN,	/* 16 - EV_ASGN */
+	EH_TRNS,	/* 17 - EV_TRNS */
+	-1,		/* 18 - EV_REPT */
+	-1,		/* 19 - EV_PNCH */
+	-1,		/* 20 - EV_PRES */
+	-1,		/* 21 - EV_FINI */
+	-1,		/* 22 - EV_CPRS */
+	-1,		/* 23 - EV_BAR */
+	-1		/* 24 - EV_NEXT */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	oktocm() -- see if an event is OK to copy or merge
+
+	returns:
+
+		TRUE	OK to copy or merge
+		FALSE	don't copy or merge
+   =============================================================================
+*/
+
+short
+oktocm(ep)
+register struct s_entry *ep;
+{
+	register short et, grp, mode;
+
+	et = 0x007F & ep->e_type;		/* get event type */
+
+	if (0 EQ cmslens[et])			/* is this type not copied ? */
+		return(FALSE);			/* return FALSE if so */
+
+	if (NOT cmgtags[et])			/* is it group sensitive ? */
+		return(TRUE);			/* return TRUE if not */
+
+	/* get group number */
+
+	grp = 0x000F & (cmgtype[et] ? ep->e_data2 : ep->e_data1);
+
+	if (NOT grpstat[grp])		/* group enabled ? */
+		return(FALSE);		/* can't do it if not */
+
+	if ((et EQ EV_ANRS) OR (et EQ EV_ANVL))		/* analog */
+		mode = ancmsw ?
+			varmode[0x0007 & (ep->e_data1 >> 4)][grp] :
+			(grptmap[grp] EQ -1 ? 0 : 2);
+	else					/* other */
+		mode = grptmap[grp] EQ -1 ? 0 : 2;
+
+	/* return TRUE if in record mode */
+
+	return((mode EQ 2) ? TRUE : FALSE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	oktode() -- see if an non-note event is OK to delete
+
+	returns:
+
+		TRUE	OK to delete
+		FALSE	don't delete
+   =============================================================================
+*/
+
+short
+oktode(ep)
+register struct s_entry *ep;
+{
+	register short et, grp, mode;
+
+	et = 0x007F & ep->e_type;		/* get event type */
+
+	if ((et EQ EV_NBEG) OR (et EQ EV_NEND))	/* don't delete notes */
+		return(FALSE);
+
+	if (NOT cmgtags[et])			/* is event group sensitive ? */
+		return(TRUE);			/* return TRUE if not */
+
+	/* get group number */
+
+	grp = 0x000F & (cmgtype[et] ? ep->e_data2 : ep->e_data1);
+
+	if (NOT grpstat[grp])		/* enabled ? */
+		return(FALSE);		/* can't do it if not */
+
+	if ((et EQ EV_ANRS) OR (et EQ EV_ANVL))		/* analog */
+		mode = ancmsw ?
+			varmode[7 & (ep->e_data1 >> 4)][grp] : grpmode[grp];
+	else					/* other */
+		mode = grpmode[grp];
+
+	/* return TRUE if  in record mode */
+
+	return((mode EQ 2) ? TRUE : FALSE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	oktodg() -- see if a note event is OK to delete
+
+	returns:
+
+		TRUE	OK to delete
+		FALSE	don't delete
+   =============================================================================
+*/
+
+short
+oktodg(ep)
+register struct s_entry *ep;
+{
+	register short et, grp;
+
+	et = 0x007F & ep->e_type;	/* get event type */
+
+	if ((et NE EV_NBEG) AND		/* is it a note begin ... */
+	    (et NE EV_NEND))		/* ... or a note end ? */
+		return(FALSE);		/* return FALSE if not */
+
+	grp = ep->e_data2;		/* get group number */
+
+	if ((grpmode[grp] EQ 2) AND	/* is group in record mode ... */
+	     grpstat[grp])		/* ... and enabled ? */
+		return(TRUE);		/* return TRUE if so */
+	else
+		return(FALSE);		/* return FALSE if not */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	chksec() -- check for a valid section
+
+	returns:
+
+		0	section OK  (both ends found in proper order)
+		1	can't find the begin event
+		2	can't find the end event
+		3	section end occurs before section begin
+   =============================================================================
+*/
+
+short
+chksec(ns)
+register short ns;
+{
+	register struct s_entry *ep;
+
+	DB_ENTR("chksec");
+
+	/* find section beginning in seclist */
+
+	if (E_NULL EQ (p_sbgn = seclist[curscor][ns])) {
+
+		secopok = FALSE;
+		p_send = E_NULL;
+		DB_EXIT("chksec - 1");
+		return(1);
+	}
+
+	t_sbgn = p_sbgn->e_time;		/* save section start time */
+
+/* 
+
+*/
+	/* find section end by scanning hplist */
+
+	ep = hplist[curscor][EH_SEND];
+
+	while (ep) {
+
+		if (((ep->e_type & 0x007F) EQ EV_SEND) AND
+		    (ep->e_data1 EQ ns))
+			break;
+
+		ep = ep->e_up;
+	}
+
+	if (E_NULL EQ (p_send = ep)) {		/* error if not found */
+
+		secopok = FALSE;
+		DB_EXIT("chksec - 2");
+		return(2);
+	}
+
+	/* get section end and check that it occurs after section begin */
+
+	if (t_sbgn GE (t_send = ep->e_time)) {
+
+		secopok = FALSE;
+		DB_EXIT("chksec - 3");
+		return(3);
+	}
+
+	t_sect = 1 + t_send - t_sbgn;		/* calculate section time */
+
+	DB_EXIT("chksec - 0");
+	return(0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sizesec() -- find the size of a section
+
+	returns:	number of storage units required
+
+	Assumes that the section passed chksec() and that p_sbgn and p_send
+	are valid.  Fails badly if not.
+   =============================================================================
+*/
+
+long
+sizesec()
+{
+	register long ec;
+	register short et;
+	register struct s_entry *sbp, *sep;
+
+	DB_ENTR("sizesec");
+
+	ec = 0L;			/* start with zero length */
+	sbp = p_sbgn->e_fwd;		/* point to first event to copy */
+	sep = p_send;			/* point at section end */
+
+	while (sbp NE sep) {		/* scan up to section end ... */
+
+		et = 0x007F & sbp->e_type;	/* get event type */
+
+		if (oktocm(sbp))		/* if it's one we want ... */
+			ec += cmslens[et];	/* ... add its length */
+
+		sbp = sbp->e_fwd;		/* point at next event */
+	}
+
+#ifdef	DEBUGGER
+	if (ec)
+		DB_CMNT("sizesec - non-null copy");
+	else
+		DB_CMNT("sizesec - null copy");
+#endif
+
+	DB_EXIT("sizesec");
+	return(ec);		/* return number of longs required */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	edelta() -- adjust times in events above 'btime' by 'delta'
+
+	ep	pointer to event to start adjusting at
+	btime	base time
+	delta	adjustment factor added to event times
+   =============================================================================
+*/
+
+edelta(ep, btime, delta)
+register struct s_entry *ep;
+register long btime, delta;
+{
+	DB_ENTR("edelta");
+
+	while ((ep->e_type & 0x007F) NE EV_FINI) {		/* for each event */
+
+		if (ep->e_time > btime)		/* in range ? */
+			ep->e_time += delta;	/* add delta */
+
+		ep = ep->e_fwd;			/* point at next event */
+	}
+
+	DB_EXIT("edelta");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	madjsec() -- make a time-adjusted section copy
+
+	Returns a pointer to the copy, or E_NULL if copy is empty.
+
+	sbp	section begin pointer to section to copy
+	btime	base time of copy
+
+	Copy is bi-linked on e_fwd/e_bak, E_NULL terminated.
+
+	Assumes that the section is complete and well ordered, and that
+	we have enough free events to make the copy. Fails badly if not.
+   =============================================================================
+*/
+
+struct s_entry *
+madjsec(sbp, btime)
+register struct s_entry *sbp;
+register long btime;
+{
+	short ns, nv;
+	register short grp, es, et;
+	register struct s_entry *ep, *np;
+	struct s_entry *cp;
+	register long sat;
+
+	DB_ENTR("madjsec");
+
+	np  = ep = cp = E_NULL;		/* initialize np, ep and cp */
+	ns  = sbp->e_data1;		/* get section number */
+	sat = sbp->e_time - btime;	/* get section adjust time */
+	sbp = sbp->e_fwd;		/* advance to first event to copy */
+
+/* 
+
+*/
+
+	/* copy up to section end */
+
+	while (TRUE) {
+
+		et = sbp->e_type & 0x007F;	/* get event type */
+
+		/* we're done when we see the section end */
+
+		if ((EV_SEND EQ et) AND (sbp->e_data1 EQ ns))
+			break;
+
+		if (oktocm(sbp)) {	/* if event is copyable */
+
+			es = sbp->e_size;		/* get event size */
+			np = e_alc(es);			/* allocate event */
+			memcpyw(np, sbp, es << 1);	/* make copy */
+
+			if (cmgtags[et]) {	/* group sensitive ? */
+
+				grp = 0x000F & (cmgtype[et] ?
+					np->e_data2 : np->e_data1);
+
+				if ((et EQ EV_NBEG) OR (et EQ EV_NEND)) {
+
+					/* regroup */
+
+					np->e_data2 = (np->e_data2 & 0x00F0) |
+						grptmap[grp];
+
+					/* transpose */
+
+					nv = np->e_data1 + grptran;
+
+					if (nv > 127)
+						nv = 127;
+					else if (nv < 0)
+						nv = 0;
+
+					np->e_data1 = nv;
+
+				} else if ((et EQ EV_ANRS) OR (et EQ EV_ANVL)) {
+
+					/* regroup */
+
+					np->e_data1 = (np->e_data1 & 0x000F) |
+						(grptmap[grp] << 4);
+
+				} else {
+
+					/* regroup */
+
+					if (cmgtype[et])
+						np->e_data2 = (np->e_data2 & 0x00F0) |
+							grptmap[grp];
+					else
+						np->e_data1 = (np->e_data1 & 0x00F0) |
+							grptmap[grp];
+				}
+			}
+
+/* 
+
+*/
+			if (ep) {	/* if copy started */
+
+				ep->e_fwd = np;		/* link new event to copy */
+
+			} else {	/* first event in chain */
+
+				DB_CMNT("madjsec - making copy");
+				cp = np;		/* start the copy chain */
+			}
+
+			np->e_bak = ep;		/* link new event to previous one */
+			np->e_fwd = E_NULL;	/* terminate the copy chain */
+			np->e_time -= sat;	/* adjust the copied event time */
+			ep = np;		/* point ep at new event */
+		}
+
+		sbp = sbp->e_fwd;	/* point at next event to copy */
+	}
+
+	p_cbgn = cp;		/* save address of start of copy */
+	p_cend = np;		/* save address of end of copy */
+
+	if (cp) {
+
+		DB_CMNT("madjsec - copy made");
+		t_cbgn = cp->e_time;	/* save start time of copy */
+		t_cend = np->e_time;	/* save end time of copy */
+	}
+
+	DB_EXIT("madjsec");	
+	return(cp);		/* return start address of copy */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ehfix() -- put event headers in a copied section into hplist
+
+	cbp	pointer to first event in copy
+	cep	pointer to last event in copy
+   =============================================================================
+*/
+
+ehfix(cbp, cep)
+register struct s_entry *cbp, *cep;
+{
+	register short et;
+
+	for (;;) {	/* for each event from cbp to cep ... */
+
+		et = 0x007F & cbp->e_type;	/* get event type */
+
+		/* does event belong in hplist ? */
+
+		if (-1 NE ehdlist[et])
+			eh_ins(cbp, ehdlist[et]);	/* if so, update hplist */
+
+		if (cbp EQ cep)			/* see if we're done */
+			return;			/* return if so */
+
+		cbp = cbp->e_fwd;		/* advance to the next event */
+	}
+}
Index: ram/cminit.c
===================================================================
--- ram/cminit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/cminit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,397 @@
+/*
+   =============================================================================
+	cminit.c -- C-Meta parser functions
+	Version 5 -- 1987-07-10 -- D.N. Lynx Crowe
+
+	Some parser functions in C, modelled after HyperMeta(tm).
+	Designed for, but not dedicated to,  LR(k), top-down, recursive parsing.
+   =============================================================================
+*/
+
+#include <stddefs.h>
+#include <ctype.h>
+
+#define	CM_MXSTR	257	/* maximum parser string result length */
+
+#define	CM_DBLK		if (!QQanch) while (*QQip EQ ' ') ++QQip
+
+int	QQsw;		/* parser result switch */
+int	QQanch;		/* parser anchored match switch */
+
+char	*QQin;		/* parser initial input pointer */
+char	*QQip;		/* parser current input pointer */
+char	*QQop;		/* parser string output pointer */
+
+long	QQnum;		/* parser numeric result */
+int	QQlnum;		/* parser list element number result */
+char	QQdig;		/* parser digit result */
+char	QQchr;		/* parser character result */
+
+char	QQstr[CM_MXSTR];	/* parser string result */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMinit(ip) -- initialize the parser to work on the string at 'ip'.
+   =============================================================================
+*/
+
+int
+CMinit(ip)
+char *ip;
+{
+	register int i;
+	register char *t;
+
+	QQip = ip;
+	QQin = ip;
+	QQsw = TRUE;
+	QQanch = FALSE;
+	QQdig = '?';
+	QQchr = '?';
+	QQnum = 0;
+	QQop = QQstr;
+	t = QQstr;
+
+	for (i = 0; i < CM_MXSTR; i++)
+		*t++ = '\0';
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMchr(c) -- attempt to match character 'c' in the input.
+   =============================================================================
+*/
+
+int
+CMchr(c)
+char c;
+{
+	CM_DBLK;
+
+	if (c NE *QQip)
+		return(QQsw = FALSE);
+
+	QQchr = *QQip++;
+	return(QQsw = TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMuchr(c) -- attempt to match character 'c' in the input, ignoring case.
+   =============================================================================
+*/
+
+int
+CMuchr(c)
+register char c;
+{
+	register char t;
+
+	CM_DBLK;
+
+	t = *QQip;
+
+	if (isascii(c))
+		if (isupper(c))
+			c = _tolower(c);
+
+	if (isascii(t))
+		if (isupper(t))
+			t = _tolower(t);
+
+	if (c NE t)
+		return(QQsw = FALSE);
+
+	QQchr = *QQip++;
+	return(QQsw = TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMstr(s) -- attempt to match string at 's' in the input.
+   =============================================================================
+*/
+
+int
+CMstr(s)
+char *s;
+{
+	register char *t;
+	char *q;
+
+	CM_DBLK;
+
+	t = QQip;
+	q = s;
+
+	while (*s) {
+
+		if (*t++ NE *s++)
+			return(QQsw = FALSE);
+	}
+
+	QQop = QQstr;
+
+	while (*QQop++ = *q++) ;
+
+	QQip = t;
+	return(QQsw = TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMustr(s) -- attempt to match string 's' in the input, ignoring case.
+   =============================================================================
+*/
+
+int
+CMustr(s)
+register char *s;
+{
+	register char *t, t1, t2;
+	char *q;
+
+	CM_DBLK;
+
+	t = QQip;
+	q = s;
+
+	while (*s) {
+
+		t1 = *t++;
+		t2 = *s++;
+
+		if (isascii(t1))
+			if (isupper(t1))
+				t1 = _tolower(t1);
+
+		if (isascii(t2))
+			if (isupper(t2))
+				t2 = _tolower(t2);
+
+		if (t1 NE t2)
+			return(QQsw = FALSE);
+	}
+
+	QQop = QQstr;
+
+	while (*QQop++ = *q++) ;
+
+	QQip = t;
+	return(QQsw = TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMlong() -- attempt to parse a digit string in the input as a long.
+   =============================================================================
+*/
+
+int
+CMlong()
+{
+	register char *p;
+	register long n;
+	register char c;
+
+	CM_DBLK;
+
+	p = QQip;
+	n = 0L;
+	c = *p++;
+
+	if (!isascii(c))
+		return(QQsw = FALSE);
+
+	if (!isdigit(c))
+		return(QQsw = FALSE);
+
+	n = c - '0';
+		
+	while (c = *p) {
+
+		if (!isascii(c))
+			break;
+
+		if (!isdigit(c))
+			break;
+
+		n = (n * 10) + (c - '0');
+		++p;
+	}
+
+	QQip = p;
+	QQnum = n;
+	return(QQsw = TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMdig() -- attempt to match a digit in the input string.
+   =============================================================================
+*/
+
+int
+CMdig()
+{
+	register char c;
+
+	CM_DBLK;
+
+	c = *QQip;
+
+	if (!isascii(c))
+		return(QQsw = FALSE);
+
+	if (!isdigit(c))
+		return(QQsw = FALSE);
+
+	QQdig = c;
+	++QQip;
+	return(QQsw = TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMlist(l) -- attempt to match a string from the list 'l' in the input.
+   =============================================================================
+*/
+
+int
+CMlist(l)
+register char *l[];
+{
+	register int	n;
+	register char	*p, *q;
+
+	CM_DBLK;
+
+	n = 0;
+
+	while (p = *l++) {
+
+		q = p;
+
+		if (CMstr(p)) {
+
+			QQop = QQstr;
+
+			while (*QQop++ = *q++) ;
+
+			QQlnum = n;
+			return(QQsw = TRUE);
+		}
+
+		++n;
+	}
+
+	return(QQsw = FALSE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMulist(l) -- attempt to match a string from the list 'l' in the input
+	ignoring case in both the list and the input string.
+   =============================================================================
+*/
+
+int
+CMulist(l)
+register char *l[];
+{
+	register int	n;
+	register char	*p, *q;
+
+	CM_DBLK;
+
+	n = 0;
+
+	while (p = *l++) {
+
+		q = p;
+
+		if (CMustr(p)) {
+
+			QQop = QQstr;
+
+			while (*QQop++ = *q++) ;
+
+			QQlnum = n;
+			return(QQsw = TRUE);
+		}
+
+		++n;
+	}
+
+	return(QQsw = FALSE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	CMstat(msg) -- output 'msg and dump parser status.  Returns QQsw.
+   =============================================================================
+*/
+
+int
+CMstat(msg)
+char *msg;
+{
+	register char *tp;
+
+	tp = QQin;
+	printf("%s\r\n", msg);
+	printf("  QQsw: %s, QQanch: %s, QQchr: 0x%02x <%c>, QQdig: %c\r\n",
+		(QQsw ? "OK" : "NOGO"), (QQanch ? "anchored" : "deblanked"),
+		QQchr, (isascii(QQchr) ? (isprint(QQchr) ? QQchr : ' ') : ' '),
+		QQdig);
+	printf("  QQnum: %ld, QQlnum: %d\r\n", QQnum, QQlnum);
+	printf("  QQstr: %s\r\n", QQstr);
+	printf("  {%s}\r\n", QQin);
+	printf("   ");
+
+	while (tp++ NE QQip)
+		printf(" ");
+
+	printf("^\r\n");
+	return(QQsw);
+}
Index: ram/ctcpos.c
===================================================================
--- ram/ctcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ctcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,151 @@
+/*
+   =============================================================================
+	ctcpos.c -- character text cursor positioning
+	Version 12 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "hwdefs.h"
+#include "macros.h"
+#include "patch.h"
+
+#include "midas.h"
+
+short	ctcsw;				/* text cursor status */
+
+extern	short	CurLine;		/* current patch display line */
+extern	short	cxval, cyval;		/* patch text cursor x, y */
+extern	short	stcrow, stccol;		/* patch text cursor row,col */
+extern	short	vtcrow, vtccol;		/* menu text cursor row,col */
+
+extern	unsigned	*obj9;		/* patch cursor object pointer */
+extern	unsigned	*obj11;		/* menu cursor object pointer */
+
+short	mtcoldc;			/* previous cursor column location */
+short	mtcoldr;			/* previous cursor row location */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ctcpos() -- position the patch text cursor at ('row', 'col')
+   =============================================================================
+*/
+
+ctcpos(row, col)
+register short row, col;
+{
+	register short nrow;
+
+	if (ctcsw) {
+
+		if (v_regs[5] & 0x0180)		/* point at the control bank */
+			vbank(0);
+
+		nrow = CurLine + 7;
+
+		if (stcrow EQ DATAROW)		/* turn off old cursor */
+			vclrav(obj9, nrow, stccol, C_ULINE, 48);
+
+		if (row EQ DATAROW)		/* turn on new cursor */
+			vsetav(obj9, nrow, col, C_ULINE, 48);
+	}
+
+	stcrow = row;			/* update cursor position */
+	stccol = col;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ctcoff() -- turn off the patch text cursor
+   =============================================================================
+*/
+
+ctcoff()
+{
+	if (v_regs[5] & 0x0180)		/* point at the control bank */
+		vbank(0);
+
+	if (stcrow EQ DATAROW)		/* turn off cursor */
+		vclrav(obj9, CurLine + 7, stccol, C_ULINE, 48);
+
+	ctcsw = FALSE;
+}
+
+/*
+   =============================================================================
+	ctcon() -- turn on the patch text cursor
+   =============================================================================
+*/
+
+ctcon()
+{
+	if (v_regs[5] & 0x0180)		/* point at the control bank */
+		vbank(0);
+
+	if (stcrow EQ DATAROW) {	/* turn on cursor */
+
+		ctcsw = TRUE;
+		vsetav(obj9, CurLine + 7, stccol, C_ULINE, 48);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	mtcpos() -- position the menu text cursor at ('row', 'col')
+   =============================================================================
+*/
+
+mtcpos(row, col)
+register short row, col;
+{
+	if (v_regs[5] & 0x0180)			/* point at the control bank */
+		vbank(0);
+
+	if (inrange(mtcoldr, 19, 23)) {		/* turn off old cursor */
+
+		vclrav(obj11, mtcoldr - 18, mtcoldc, C_ULINE, 64);
+
+		mtcoldr = 0;			/* void old cursor location */
+		mtcoldc = 0;
+	}
+
+	if (inrange(row, 19, 23)) {		/* turn on new cursor */
+
+		vsetav(obj11, row - 18, col, C_ULINE, 64);
+
+		mtcoldr = row;			/* keep track of new cursor */
+		mtcoldc = col;
+	}
+
+	vtcrow = row;				/* update cursor position */
+	vtccol = col;
+}
+
+/*
+   =============================================================================
+	mtcoff() -- turn off the menu text cursor
+   =============================================================================
+*/
+
+mtcoff()
+{
+	if (v_regs[5] & 0x0180)		/* point at the control bank */
+		vbank(0);
+
+	if (inrange(mtcoldr, 19, 23))		/* turn off cursor */
+		vclrav(obj11, mtcoldr - 18, mtcoldc, C_ULINE, 64);
+}
Index: ram/curset.c
===================================================================
--- ram/curset.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/curset.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,318 @@
+/*
+   =============================================================================
+	curset.c -- cursor control and data entry parameter setup
+	Version 14 -- 1988-12-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "curpak.h"
+
+#include "midas.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugcs = 1;
+
+char	*C_TYPE[] = {
+
+	"CT_GRAF",	/*	0	graphics */
+	"CT_TEXT",	/*	1	text -- general */
+	"CT_VIRT",	/*	2	virtual -- graphic */
+	"CT_SCOR",	/*	3	text -- score */
+	"CT_SMTH",	/*	4	text -- smooth scroll */
+	"CT_MENU"	/*	5	virtual -- character */
+};
+#endif
+
+short	trkonly = FALSE;		/* set TRUE to force use of trackball */
+
+extern	short		txstd(), tystd(), cmvgen();
+
+extern	short		(*curmove)();
+extern	short		(*curtype)();
+extern	short		(*cx_key)();
+extern	short		(*cx_upd)();
+extern	short		(*cy_key)();
+extern	short		(*cy_upd)();
+extern	short		(*d_key)();
+extern	short		(*e_key)();
+extern	short		(*m_key)();
+extern	short		(*not_fld)();
+extern	short		(*premove)();
+extern	short		(*pstmove)();
+extern	short		(*x_key)();
+extern	short		(*xy_dn)();
+extern	short		(*xy_up)();
+
+extern	short		*cratex;
+extern	short		*cratey;
+
+/* 
+
+*/
+
+extern	short		chtime;
+extern	short		chwait;
+extern	short		cmfirst;
+extern	short		cmtype;
+extern	short		curhold;
+extern	short		curslim;
+extern	short		cvtime;
+extern	short		cvwait;
+extern	short		cxval;
+extern	short		cyval;
+extern	short		hcwval;
+extern	short		nchwait;
+extern	short		ncvwait;
+extern	short		stccol;
+extern	short		stcrow;
+extern	short		submenu;
+extern	short		syrate;
+extern	short		thcwval;
+extern	short		tvcwval;
+extern	short		vcwval;
+
+extern	struct fet	*infetp;
+extern	struct fet	*cfetp;
+extern	struct fet	*curfet;
+
+extern	struct selbox	*csbp;
+
+/* 
+
+*/
+
+#if	DEBUGIT
+
+/*
+   =============================================================================
+	SnapCT() -- snap dump curpak variables
+   =============================================================================
+*/
+
+SnapCT()
+{
+	printf("\ncurpak variables:\n");
+	printf("   curtype = $%lX\n", curtype);
+	printf("   premove = $%lX\n", premove);
+	printf("   pstmove = $%lX\n", pstmove);
+	printf("   cx_key  = $%lX\n", cx_key);
+	printf("   cy_key  = $%lX\n", cy_key);
+	printf("   cx_upd  = $%lX\n", cx_upd);
+	printf("   cy_upd  = $%lX\n", cy_upd);
+	printf("   xy_up   = $%lX\n", xy_up);
+	printf("   xy_dn   = $%lX\n", xy_dn);
+	printf("   x_key   = $%lX\n", x_key);
+	printf("   e_key   = $%lX\n", e_key);
+	printf("   m_key   = $%lX\n", m_key);
+	printf("   d_key   = $%lX\n", d_key);
+	printf("   not_fld = $%lX\n", not_fld);
+	printf("   curfet  = $%lX\n", curfet);
+	printf("   csbp    = $%lX\n", csbp);
+	printf("   cratex  = $%lX\n", cratex);
+	printf("   cratey  = $%lX\n", cratey);
+	printf("   cmtype  = %d\n", cmtype);
+	printf("   cxval   = %d\n", cxval);
+	printf("   cyval   = %d\n", cyval);
+	printf("\n");
+}
+
+#endif
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stdctp0() -- cursor type - text, virtual
+   =============================================================================
+*/
+
+short
+stdctp0()
+{
+	return(submenu ? CT_VIRT : CT_TEXT);
+}
+
+/*
+   =============================================================================
+	stdctp1() -- cursor type -- graphic, text, virtual -- text if > curslim
+   =============================================================================
+*/
+
+short
+stdctp1()
+{
+	if (submenu)
+		return(CT_VIRT);
+
+	return((cyval > curslim) ? CT_TEXT : CT_GRAF);
+}
+
+/*
+   =============================================================================
+	stdctp2() -- cursor type -- graphic
+   =============================================================================
+*/
+
+short
+stdctp2()
+{
+	return(CT_GRAF);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stdctp3() -- cursor type -- graphic, score text, virtual
+   =============================================================================
+*/
+
+short
+stdctp3()
+{
+	if (submenu)
+		return(CT_VIRT);
+
+	return(((cyval < 14) OR (cyval > 237)) ? CT_SCOR : CT_GRAF);
+}
+
+/*
+   =============================================================================
+	stdctp4() -- cursor type -- graphic, text, virtual -- text if < curslim
+   =============================================================================
+*/
+
+short
+stdctp4()
+{
+	if (submenu)
+		return(CT_VIRT);
+
+	return((cyval < curslim) ? CT_TEXT : CT_GRAF);
+}
+
+/*
+   =============================================================================
+	stdctp5() -- cursor type - text, virtual - character objects
+   =============================================================================
+*/
+
+short
+stdctp5()
+{
+	return(submenu ? CT_MENU : CT_SMTH);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	curset() -- setup the cursor control and data entry parameters
+   =============================================================================
+*/
+
+curset(s)
+register struct curpak *s;
+{
+#if	DEBUGIT
+	if (debugsw AND debugcs)
+		printf("curset($%lX): ENTRY old cmtype=%d\n", s, cmtype);
+#endif
+
+	curtype = s->curtype;
+	premove = s->premove;
+	pstmove = s->pstmove;
+
+	curmove = cmvgen;
+
+	if (trkonly) {
+
+		cx_key  = txstd;
+		cy_key  = tystd;
+
+	} else {
+
+		cx_key  = s->cx_key;
+		cy_key  = s->cy_key;
+	}
+
+	cx_upd  = s->cx_upd;
+	cy_upd  = s->cy_upd;
+	xy_up   = s->xy_up;
+	xy_dn   = s->xy_dn;
+	x_key   = s->x_key;
+	e_key   = s->e_key;
+	m_key   = s->m_key;
+	d_key   = s->d_key;
+	not_fld = s->not_fld;
+	curfet  = s->curfet;
+	csbp    = s->csbp;
+	cratex  = s->cratex;
+	cratey  = s->cratey;
+	cmtype  = s->cmtype;
+	cxval   = s->cxval;
+	cyval   = s->cyval;
+
+#if	DEBUGIT
+	if (debugsw AND debugcs)
+		printf("curset($%lX): new cmtype=%d\n", s, cmtype);
+#endif
+
+/* 
+
+*/
+	if (cmtype EQ CT_GRAF) {	/* graphics */
+
+		chtime  = hcwval;
+		cvtime  = vcwval;
+
+	} else {			/* text of some sort */
+
+		chtime  = thcwval;
+		cvtime  = (cmtype EQ CT_SMTH) ? syrate : tvcwval;
+	}
+
+	stccol  = XTOC(cxval);
+	stcrow  = YTOR(cyval);
+
+	chwait  = chtime;
+	cvwait  = cvtime;
+
+	nchwait = curhold;
+	ncvwait = curhold;
+
+	cmfirst = TRUE;
+
+	ebflag = FALSE;
+	memset(ebuf, '\0', sizeof ebuf);
+
+	cfetp  = (struct fet *)NULL;
+	infetp = (struct fet *)NULL;
+
+#if	DEBUGIT
+	if (debugsw AND debugcs) {
+
+		printf("curset($%lX): EXIT cmtype=%d=%s chtime=%d  cvtime=%d  curhold=%d\n",
+			s, cmtype,
+			(cmtype < 6) ? C_TYPE[cmtype] : "UNKNOWN",
+			chtime, cvtime, curhold);
+
+		SnapCT();
+	}
+#endif
+
+}
Index: ram/dbentr.c
===================================================================
--- ram/dbentr.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/dbentr.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,282 @@
+/*
+   =============================================================================
+	dbentr.c -- debug trace support functions
+	Version 3 -- 1988-03-03 -- D.N. Lynx Crowe
+
+	Use with the "debug.h" header file.  Define DEBUGGER to include
+	debug trace code.
+
+	Synopsis:
+
+	  Macros:
+
+		DB_ENTR(str)		trace an entry
+		DB_EXIT(str)		trace an exit
+		DB_CMNT(str)		put a comment in the trace
+
+	  Functions:
+
+		DB_Clr()		clear the debug buffer
+		DB_Dump()		dump and clear the debug buffer
+
+		DB_Entr(str)		trace an entry
+		DB_Exit(str)		trace an exit
+		DB_Cmnt(str)		put a comment in the trace
+
+	  Variables:
+
+		DB_Flag			don't trap to ROMP if non-zero
+   =============================================================================
+*/
+
+#include "stddefs.h"
+
+#define	DB_DEPTH	256		/* depth of the debug buffer */
+
+#define	DB_entr		0		/* entry tag */
+#define	DB_exit		1		/* exit tag */
+#define	DB_cmnt		2		/* comment tag */
+
+struct	DB_Data {			/* debug buffer entry structure */
+
+	char	*str;
+	short	tag;
+};
+
+/* 
+
+*/
+
+short	DB_In;				/* debug buffer 'in' pointer */
+short	DB_Out;				/* debug buffer 'out' pointer */
+short	DB_Flag;			/* ROMP trap disable flag */
+
+long	DB_Levl;			/* debug function call level */
+
+char	*DB_Last;			/* last debug string pointer */
+
+struct	DB_Data	DB_Ents[DB_DEPTH];	/* debug buffer */
+
+char	*DB_Type[] = {			/* debug buffer entry types */
+
+	"-->>",		/* 0 - DB_entr */
+	"<<--",		/* 1 - DB_exit */
+	"Note"		/* 2 - DB_cmnt */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	DB_Entr() -- log an entry in the trace buffer
+   =============================================================================
+*/
+
+DB_Entr(str)
+char *str;
+{
+	DB_Ents[DB_In].tag = DB_entr;	/* tag an entry */
+	DB_Ents[DB_In].str = str;
+
+	DB_Last = str;
+
+	++DB_Levl;
+
+	if (++DB_In GE DB_DEPTH)	/* update the 'in' pointer */
+		DB_In = 0;
+
+	if (DB_In EQ DB_Out) {		/* bump the output pointer if full */
+
+		if (++DB_Out GE DB_DEPTH)
+			DB_Out = 0;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	DB_Exit() -- log an exit in the trace buffer
+   =============================================================================
+*/
+
+DB_Exit(str)
+char *str;
+{
+	DB_Ents[DB_In].tag = DB_exit;	/* tag an exit */
+	DB_Ents[DB_In].str = str;
+
+	DB_Last = str;
+
+	if (DB_Levl > 0)
+		--DB_Levl;
+	else
+		DB_Levl = 0L;
+
+	if (++DB_In GE DB_DEPTH)	/* update the 'in' pointer */
+		DB_In = 0;
+
+	if (DB_In EQ DB_Out) {		/* bump the output pointer if full */
+
+		if (++DB_Out GE DB_DEPTH)
+			DB_Out = 0;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	DB_Cmnt() -- log a comment in the trace buffer
+   =============================================================================
+*/
+
+DB_Cmnt(str)
+char *str;
+{
+	DB_Ents[DB_In].tag = DB_cmnt;	/* tag a comment */
+	DB_Ents[DB_In].str = str;
+
+	DB_Last = str;
+
+	if (++DB_In GE DB_DEPTH)	/* update the 'in' pointer */
+		DB_In = 0;
+
+	if (DB_In EQ DB_Out) {		/* bump the output pointer if full */
+
+		if (++DB_Out GE DB_DEPTH)
+			DB_Out = 0;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	DB_Clr() -- clear the debug buffer
+   =============================================================================
+*/
+
+DB_Clr()
+{
+	register short i;
+
+	DB_In  = 0;
+	DB_Out = 0;
+
+	for (i = 0; i < DB_DEPTH; i++) {
+
+		DB_Ents[i].tag = 0;
+		DB_Ents[i].str = (char *)0L;
+	}
+
+	DB_Levl = 0L;
+	DB_Last = (char *)0L;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	DB_Dump() -- dump and reset the trace buffer
+   =============================================================================
+*/
+
+DB_Dump()
+{
+	register short tag;
+	register long i, lev;
+
+	if ((DB_In GE DB_DEPTH) OR (DB_In < 0)) {	/* check DB_In */
+
+		printf("DB_In was corrupt:  %d\n", DB_In);
+
+		xtrap15();		/* trap to ROMP */
+		
+		DB_Clr();		/* clear the buffer */
+		return;
+	}
+
+	if ((DB_Out GE DB_DEPTH) OR (DB_Out < 0)) {	/* check DB_Out */
+
+		printf("DB_Out was corrupt:  %d\n", DB_Out);
+
+		xtrap15();		/* trap to ROMP */
+		
+		DB_Clr();		/* clear the buffer */
+		return;
+	}
+
+	if (DB_In EQ DB_Out) {		/* check for an emtpy buffer */
+
+		printf("Debug buffer is empty:  In = Out = %d\n", DB_In);
+
+		if (DB_Levl)
+			printf("Debug trace level = %ld\n", DB_Levl);
+
+		if (DB_Last)
+			printf("Latest entry = \"%s\"\n", DB_Last);
+
+		if (DB_Flag EQ 0)	/* trap to ROMP */
+			xtrap15();
+
+		DB_Clr();		/* clear the buffer */
+		return;
+	}
+/* 
+
+*/
+	printf("Debug trace level = %ld\n\n", DB_Levl);
+
+	lev = 0L;
+
+	while (DB_Out NE DB_In) {	/* print the buffer entries */
+
+		for (i = 0L; i < lev; i++)
+			printf("|");
+
+		tag = DB_Ents[DB_Out].tag;
+
+		printf("%s:  %s\n", DB_Type[tag], DB_Ents[DB_Out].str);
+
+		switch (tag) {
+
+		case DB_entr:
+
+			++lev;
+			break;
+
+		case DB_exit:
+
+			if (--lev < 0L) {
+
+				lev = 0L;
+				printf("\n");
+			}
+
+			break;
+		}
+
+		if (++DB_Out GE DB_DEPTH)
+			DB_Out = 0;
+	}
+
+	printf("\n----- End of debug buffer -----\n\n");
+
+	DB_Clr();			/* clear the buffer */
+
+	if (DB_Flag EQ 0)
+		xtrap15();
+
+	return;
+}
Index: ram/dcopy.c
===================================================================
--- ram/dcopy.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/dcopy.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,107 @@
+/*
+   =============================================================================
+	dcopy.c -- copy MIDAS-VII to disk
+	Version 3 -- 1988-09-01 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "stdio.h"
+#include "objdefs.h"
+
+#define	PROGID	"midas.abs"		/* MIDAS-VII program file name */
+
+extern	short	defect;			/* error code */
+
+extern	char	end, edata, etext;	/* loader symbols */
+
+extern	long	p_dlen;			/* size of data (from basepage) */
+
+extern	Lo_RAM();			/* lowest address loaded (lowram.s) */
+
+extern	struct	EXFILE	mphead;		/* MIDAS-VII program header */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dcopy() -- copy MIDAS-VII to disk
+   =============================================================================
+*/
+
+short
+dcopy()
+{
+	register FILE *fp;
+	register char *from;
+	register long wrtlen, loadlen, bsslen, txtlen;
+
+	defect  = 0;				/* reset error word */
+
+	txtlen  = (long)&etext - (long)&Lo_RAM;	/* calculate text length */
+	bsslen  = (long)&end   - (long)&edata;	/* calculate BSS length */
+
+	loadlen = (long)&edata - (long)&Lo_RAM;	/* calculate write length */
+
+	/* create the object file header */
+
+	mphead.F_Magic  = F_R_C;		/* magic = contiguous file */
+	mphead.F_Text   = txtlen;		/* text length */
+	mphead.F_Data   = p_dlen;		/* data length */
+	mphead.F_BSS    = bsslen;		/* BSS length */
+	mphead.F_Symtab = 0L;			/* symbol table length */
+	mphead.F_Res1   = 0L;			/* reserved area #1 */
+	mphead.F_Res2   = &Lo_RAM;		/* text base */
+	mphead.F_Res3   = 0xFFFF;		/* flag word */
+
+	/* ***** initialize for a (possibly) new disk here ***** */
+
+	/* open MIDAS-VII object file for writing */
+
+	preio();	/* kill the LCD backlight */
+
+	if ((FILE *)NULL EQ (fp = fopenb(PROGID, "w"))) {
+
+		defect = 1;		/* couldn't open file */
+		postio();		/* restore LCD backlight */
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+	/* write program header to disk */
+
+	from = &mphead;
+
+	for (wrtlen = sizeof mphead; wrtlen--; )
+		if (EOF EQ putc(*from++, fp)) {
+
+			defect = 2;	/* couldn't write program header */
+			fclose(fp);
+			postio();	/* restore LCD backlight */
+			return(FAILURE);
+		}
+
+	/* write MIDAS-VII to disk */
+
+	from = &Lo_RAM;
+
+	for (wrtlen = loadlen; wrtlen--; )
+		if (EOF EQ putc(*from++, fp)) {
+
+			defect = 3;	/* couldn't write program */
+			fclose(fp);
+			postio();	/* restore LCD backlight */
+			return(FAILURE);
+		}
+
+	/* flush and close file */
+
+	fflush(fp);
+	fclose(fp);
+	postio();	/* restore LCD backlight */
+	return(SUCCESS);
+}
Index: ram/dec2fr.c
===================================================================
--- ram/dec2fr.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/dec2fr.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,212 @@
+/*
+   =============================================================================
+	dec2fr.c -- Buchla 700 fractional 2's complement conversion functions
+	Version 10 -- 1987-12-06 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	TESTER	0
+
+#include "stddefs.h"
+
+#define	SFACT	1000L		/* scale factor */
+
+static long d2f[][10] = {	/* decimal to fraction table */
+
+	{0x00000000L, 0x000019A0L, 0x00003336L, 0x00004CD0L, 0x00006668L,
+	 0x00008000L, 0x000099A0L, 0x0000B336L, 0x0000CCCEL, 0x0000E668L},
+
+	{0x00000000L, 0x00000290L, 0x00000520L, 0x000007B0L, 0x00000A40L,
+	 0x00000CD0L, 0x00000F60L, 0x000011F0L, 0x00001480L, 0x00001710L}
+};
+
+static long f2d[] = {		/* fraction to decimal table */
+
+	50000L, 25000L, 12500L,  6250L,
+	 3125L,	 1562L,   781L,   390L,
+	  195L,    97L,    48L,    24L,
+	   12L,     6L,     3L,     1L
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dec2fr() -- convert an ASCII decimal string to fractional binary
+
+	The input string is 4 characters in the range 100- to 100+ inclusive.
+	The result is a 2's complement binary fractional value.
+   =============================================================================
+*/
+
+short
+dec2fr(s)
+register char *s;
+{
+	register short i;
+
+	if (s[0] EQ '1') {
+
+		if (s[1] EQ '0') {
+
+			if (s[2] EQ '0') {
+
+				if (s[3] EQ '-')
+					return(0x8000);  /* -100 */
+				else
+					return(0x7FFF);  /* +100 */
+
+			} else {
+
+				return(0xFFFF);	/* ERROR */
+			}
+
+		} else {
+
+			return(0xFFFF);	/* ERROR */
+
+		}
+
+/* 
+
+*/
+
+	} else if (s[0] EQ '0') {
+
+		i = (d2f[0][s[1] - '0'] + d2f[1][s[2] - '0']) >> 1;
+
+		if (s[3] EQ '-') {
+
+			if (i) 
+				return(~i);	/* negative number */
+			else
+				return(0);	/* zero is always 0 */
+
+		} else {
+
+			return(i);	/* positive number */
+		}
+	}
+
+	return(0xFFFF);	/* ERROR */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	fr2dec() -- convert a 2's complement fraction to decimal ASCII notation
+
+	The input is a 2's complement binary fractional value.
+	The result string is 4 characters in the range 100- to 100+ inclusive.
+   =============================================================================
+*/
+
+char *
+fr2dec(v, s)
+register short v;
+register char *s;
+{
+	register long acc, sc;
+	register short i, p;
+
+	if (v EQ 0x7FFF) {	/* +100 */
+
+		sprintf(s, "100+");
+		return(s);
+	}
+
+	if (v EQ 0x8000) {	/* -100 */
+
+		sprintf(s, "100-");
+		return(s);
+	}
+
+	if (v & 0x8000) {
+
+		v = ~v;		/* negative number */
+		p = '-';
+
+	} else {
+
+		p = '+';	/* positive number */
+	}
+
+	acc = 0;
+
+	for (i = 0; i LT 15; i++)
+		if (v & (1 << (14 - i)))
+			acc += f2d[i];
+
+	sc = SFACT;
+	acc /= sc;
+	sprintf(s, "%03d%c", (short)acc, p);
+	return(s);
+}
+
+/* 
+
+*/
+
+#if TESTER
+
+#include "stdio.h"
+
+extern	int	memcmp();
+
+char t[8], v[8];
+
+/*
+   =============================================================================
+	test program for fractional two's complement conversion functions
+   =============================================================================
+*/
+
+main()
+{
+	register short i;
+	register short u;
+
+	for (i = 0; i < 101; i++) {
+
+		if (i EQ 50)
+			printf("\f");
+
+		sprintf(t, "%03d+", i);
+		u = dec2fr(t);
+
+		if (u EQ 0xFFFF) {
+
+			printf("[%s] = ERROR  = ??????    ", t);
+
+		} else {
+
+			fr2dec(u, v);
+			printf("[%s] = 0x%04x = [%s]", t, u, v);
+		}
+
+		printf(" %s    ", memcmp(t, v, 4) ? "<--" : "   ");
+
+		sprintf(t, "%03d-", i);
+		u = dec2fr(t);
+
+		if (u EQ 0xFFFF) {
+
+			printf("    [%s] = ERROR  = ??????\n", t);
+
+		} else {
+
+			fr2dec(u, v);
+			printf("    [%s] = 0x%04x = [%s]", t, u, v);
+		}
+
+		printf(" %s\n", memcmp(t, v, 4) ? "<--" : "");
+
+	}
+}
+
+#endif
Index: ram/delnote.c
===================================================================
--- ram/delnote.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/delnote.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,288 @@
+/*
+   =============================================================================
+	delnote.c -- MIDAS-VII note deletion
+	Version 16 -- 1988-10-27 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "score.h"
+#include "scfns.h"
+#include "graphdef.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+#define	TO_LFT		(TO_BAK + 1)
+
+extern	short	cflag;		/* accidental flag */
+extern	short	cnote;		/* note value at cursor */
+extern	short	cxval;		/* cursor x value */
+extern	short	cyval;		/* cursor y value */
+extern	short	lstflag;	/* last note entry list end flag */
+extern	short	recsw;		/* record status */
+
+extern	long	ctime;		/* time at cursor */
+
+extern	short	grpmode[12];	/* group record modes */
+extern	short	grpstat[12];	/* group status */
+/* 
+
+*/
+
+/*
+   =============================================================================
+	delnote() -- delete a note
+   =============================================================================
+*/
+
+short
+delnote()
+{
+	register struct n_entry *bp, *cp, *ep;
+	register long t_left;
+	register short tnote, grp;
+	register short runtag, scantag;
+	short disptag;
+
+	disptag = FALSE;	/* nothing changed yet */
+
+	if (NOT recsw)			/* must be in record mode */
+		return(FAILURE);
+
+	/* convert cursor position to note number and time */
+
+	if (pix2mid(cxval, cyval))
+		goto notnote;
+
+	++cflag;
+	tnote   = cnote;
+	t_left  = t_cur - TO_LFT;
+	cp      = (struct n_entry *)frfind(ctime, 0);
+
+/* 
+
+*/
+	while (cflag--) {	/* handle both naturals and accidentals */
+
+		for (grp = 0; grp < 12; grp++) {	/* for each group ... */
+
+			if ((grpstat[grp] EQ 0) OR	/* ... enabled and ... */
+			    (grpmode[grp] NE 2))	/* ... in record mode: */
+				continue;
+
+			runtag = TRUE;
+			bp = cp;		/* start at cursor */
+
+			while (runtag) {	/* scan left from cursor until: */
+
+				if ((bp->e_time LT t_left) OR
+				    (bp->e_type EQ EV_SCORE)) {	/* left edge */
+
+					/* done -- nothing to delete */
+
+					runtag = FALSE;
+					continue;
+/* 
+
+*/
+				} else if ((bp->e_type EQ EV_NEND) AND
+				    (bp->e_note EQ tnote) AND
+				    (bp->e_group EQ grp)) {	/* note end */
+
+					/* done -- overlap */
+
+					runtag = FALSE;
+					continue;
+/* 
+
+*/
+
+				} else if ((bp->e_type EQ EV_NBEG) AND
+				    (bp->e_note EQ tnote) AND
+				    (bp->e_group EQ grp)) {	/* note begin */
+
+					/* possible deletion */
+
+					/* scan right from note begin until: */
+
+					ep = bp->e_fwd;
+					scantag = TRUE;
+
+					while (scantag) {
+
+						/* note begin -- done -- overlap */
+
+						if ((ep->e_type EQ EV_NBEG) AND
+						    (ep->e_note EQ tnote) AND
+						    (ep->e_group EQ grp)) {
+
+								scantag = FALSE;
+								runtag  = FALSE;
+								continue;
+/* 
+
+*/
+								
+						} else if ((ep->e_type EQ EV_NEND) AND
+						    (ep->e_note EQ tnote) AND
+						    (ep->e_group EQ grp)) {
+
+							/* note end */
+
+							/* delete note end */
+
+							if (cp EQ ep)
+								cp = cp->e_bak;
+
+							if (p_ctr EQ ep)
+								p_ctr = p_ctr->e_bak;
+
+							if (p_bak EQ ep)
+								p_bak = p_bak->e_bak;
+
+							if (p_fwd EQ ep)
+								p_fwd = p_fwd->e_bak;
+
+							if (p_cur EQ ep)
+								p_cur = p_cur->e_bak;
+
+							e_del(e_rmv(ep));
+/* 
+
+*/
+
+							/* delete note begin */
+
+							if (cp EQ bp)
+								cp = cp->e_bak;
+
+							if (p_ctr EQ bp)
+								p_ctr = p_ctr->e_bak;
+
+							if (p_bak EQ bp)
+								p_bak = p_bak->e_bak;
+
+							if (p_fwd EQ bp)
+								p_fwd = p_fwd->e_bak;
+
+							if (p_cur EQ bp)
+								p_cur = p_cur->e_bak;
+
+							e_del(e_rmv(bp));
+
+							disptag = TRUE;
+							runtag  = FALSE;
+							scantag = FALSE;
+							continue;
+/* 
+
+*/
+
+						} else if (ep->e_type EQ EV_FINI) {
+
+							/* score end */
+
+							/* delete note begin */
+
+							if (cp EQ bp)
+								cp = cp->e_bak;
+
+							if (p_ctr EQ bp)
+								p_ctr = p_ctr->e_bak;
+
+							if (p_bak EQ bp)
+								p_bak = p_bak->e_bak;
+
+							if (p_fwd EQ bp)
+								p_fwd = p_fwd->e_bak;
+
+							if (p_cur EQ bp)
+								p_cur = p_cur->e_bak;
+
+							e_del(e_rmv(bp));
+
+							disptag = TRUE;
+							runtag  = FALSE;
+							scantag = FALSE;
+							continue;
+						}
+
+						/* scan right */
+
+						ep = ep->e_fwd;
+
+					}	/* end while (scantag) */
+
+				}	/* end if */
+/* 
+
+*/
+
+				/* scan left */
+
+				bp = bp->e_bak;
+
+			}	/* end while (runtag) */
+
+		}	/* end for (grp) */
+
+		/* handle accidentals */
+
+		if (ac_code EQ N_SHARP)
+			++tnote;	/* treat accidentals as sharps */
+		else
+			--tnote;	/* treat accidentals as flats */
+
+	}	/* end while (cflag) */
+
+
+/* 
+
+*/
+
+notnote:	/* jumped to if pix2mid() returned FAILURE (not on a note) */
+
+	/* check for a bar marker delete operation */
+
+	if (NOT disptag) {	/* if no notes were deleted, try for a bar */
+
+		if (ctime < 0L)	/* time has to be good */
+			return(FAILURE);
+
+		/* search current time for a bar marker - delete any found */
+
+		ep = ep_adj(p_cur, 1, ctime);
+
+		while (ctime EQ ep->e_time) {
+
+			bp = ep->e_fwd;
+
+			if (EV_BAR EQ ep->e_type) {
+
+				if (ep EQ p_bak)
+					p_bak = p_bak->e_bak;
+
+				if (ep EQ p_ctr)
+					p_ctr = p_ctr->e_bak;
+
+				if (ep EQ p_cur)
+					p_cur = p_cur->e_bak;
+
+				if (ep EQ p_fwd)
+					p_fwd = p_fwd->e_bak;
+
+				e_del(e_rmv(ep));
+				disptag = TRUE;
+			}
+
+			ep = bp;
+		}
+	}
+
+	if (disptag)
+		sc_refr(t_cur);
+
+	return(disptag ? SUCCESS : FAILURE);
+}
Index: ram/delpnts.c
===================================================================
--- ram/delpnts.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/delpnts.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,309 @@
+/*
+   =============================================================================
+	delpnts.c -- delete point(s) from (truncate) a function
+	Version 14 -- 1989-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#define	D_INSPNT	0	/* debug inspnt() */
+
+#include "stddefs.h"
+#include "fpu.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "smdefs.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#define	PT_SIZE	(sizeof (struct instpnt))
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugdf = 1;
+#endif
+
+extern	short	curfunc;
+extern	short	curvce;
+extern	short	pntsv;
+extern	short	subj;
+
+extern	short	finival[];
+extern	short	fnoff[];
+
+extern	struct	instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	delpnts() -- deletes the current point and any points to the right
+		of it in the current function in the current voice.
+   =============================================================================
+*/
+
+short
+delpnts()
+{
+	register struct instpnt *pp;
+	register char *pp1, *pp2;
+	register short np, pt1, i, pif, cf;
+	struct idfnhdr *fp;
+	struct instdef *vp;
+	unsigned *fpu;
+	short pt2, nmv, oldi;
+
+	vp  = &vbufs[curvce];			/* voice buffer pointer */
+	fp  = &vp->idhfnc[curfunc];		/* function pointer */
+
+	pif = 0x00FF & fp->idfpif;		/* number of points in function */
+	np  = pif - subj;			/* number of points to delete */
+	pt1 = (0x00FF & fp->idfpt1) + subj;	/* first point to delete */
+
+#if	DEBUGIT
+	if (debugsw AND debugdf) {
+
+		printf("delpnts():  curfunc = %d  curvce = %d\n",
+			curfunc, curvce);
+
+		printf("delpnts():  idfpt1=%d, pif=%d, np=%d, pt1=%d, vp=$%lX, fp=$%lX\n",
+			(0x00FF & fp->idfpt1), pif, np, pt1, vp, fp);
+	}
+#endif
+
+	if (np LE 0)			/* have to delete at least 1 point */
+		return(FAILURE);
+
+	if (subj GE pif)		/* make sure point number is valid */
+		return(FAILURE);
+
+	if ((pif - np) < 0)		/* make sure we have enough points */
+		return(FAILURE);
+
+	if ((subj + np) GE (pif + 1))	/* check the span */
+		return(FAILURE);
+
+	pt2 = pt1 + np;			/* move from point */
+	nmv = NIPNTS - pt2;		/* move count */
+
+#if	DEBUGIT
+	if (debugsw AND debugdf) {
+
+		printf("delpnts():  pt2=%d, nmv=%d\n", pt2, nmv);
+
+		printf("  fnc   pif\n");
+
+		for (cf = 0; cf < NFINST; cf++)
+			printf("  %3d   %3d%s\n",
+				cf, vp->idhfnc[cf].idfpif,
+				(cf EQ curfunc) ? " <-- curfunc" : "");
+
+		printf("\n");
+	}
+#endif
+
+/* 
+
+*/
+	oldi = setipl(FPU_DI);		/* +++++ disable FPU interrupts +++++ */
+
+	fpu = io_fpu + FPU_OFNC + (curvce << 8);	/* get fpu base */
+
+	for (i = 0; i < NFINST; i++) {	/* stop all functions for this voice */
+
+		fp  = &vp->idhfnc[i];	/* point at the function */
+
+		*(fpu + (fnoff[i] << 4) + FPU_TCTL) =
+		   (fp->idftmd = (fp->idftmd & ~3) | 1);
+	}
+					
+	fp  = &vp->idhfnc[curfunc];	/* point at the function */
+
+	if (subj) {			/* deleting trailing points */
+
+		/* move points down */
+
+		pp1 = &vp->idhpnt[pt1];
+		pp2 = &vp->idhpnt[pt2];
+
+		for (i = nmv * PT_SIZE; i > 0; i--)
+			*pp1++ = *pp2++;
+
+		/* adjust total points remaining */
+
+		vp->idhplft += np;
+
+		/* adjust number of points in this function */
+
+		vp->idhfnc[curfunc].idfpif -= np;
+
+		/* adjust starting points in other functions */
+
+		for (cf = curfunc + 1; cf < NFINST; cf++)
+			vp->idhfnc[cf].idfpt1 -= np;
+
+		setipl(oldi);		/* +++++ restore interrupts +++++ */
+
+		edfunc(curfunc);	/* set new current point */
+		subj -= 1;
+/* 
+
+*/
+	} else {			/* deleting all points */
+
+		/* reset first point in function */
+
+		pp = &vp->idhpnt[fp->idfpt1];
+
+		pp->iptim  = FPU_MINT;
+		pp->ipval  = finival[curfunc];
+		pp->ipvmlt = 0;
+		pp->ipvsrc = SM_NONE;
+		pp->ipact  = AC_NULL;
+		pp->ippar1 = 0;
+		pp->ippar2 = 0;
+		pp->ippar3 = 0;
+
+		/* adjust functions */
+
+		if (np > 1) {		/* if deleting more points than 1 ... */
+
+			--nmv;		/* one less point to move */
+			++pt1;		/* start one slot up */
+
+			/* move points down */
+
+			pp1 = &vp->idhpnt[pt1];
+			pp2 = &vp->idhpnt[pt2];
+
+			for (i = nmv * PT_SIZE; i > 0; i--)
+				*pp1++ = *pp2++;
+
+			/* adjust total points remaining */
+
+			vp->idhplft += (np - 1);
+
+			/* adjust number of points in this function */
+
+			vp->idhfnc[curfunc].idfpif -= (np - 1);
+
+			/* adjust starting points in other functions */
+
+			for (cf = curfunc + 1; cf < NFINST; cf++)
+				vp->idhfnc[cf].idfpt1 -= (np - 1);
+		}
+
+		setipl(oldi);		/* restore interrupts */
+
+		edfunc(curfunc);	/* make point 0 current */
+		subj = 0;
+	}	
+
+/* 
+
+*/
+#if	DEBUGIT
+	if (debugsw AND debugdf) {
+
+		printf("delpnts():  plft = %3d  pif = %3d  subj = %3d\n",
+			vp->idhplft, vp->idhfnc[curfunc].idfpif, subj);
+
+		printf("  fnc   pif\n");
+
+		for (cf = 0; cf < NFINST; cf++)
+			printf("  %3d   %3d%s\n",
+				cf, vp->idhfnc[cf].idfpif,
+				(cf EQ curfunc) ? " <-- curfunc" : "");
+
+		printf("\n");
+	}
+#endif
+
+	pntsel();
+	pntsv = 0;
+	showpt(1);
+	modinst();
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	inspnt() -- insert a new point into a function
+   =============================================================================
+*/
+
+short
+inspnt(ip, fn, inpnt)
+register struct instdef *ip;
+short fn, inpnt;
+{
+	register char *fp1, *fp2;
+	register short i, j, k, l, npts;
+	short topnt, frompt, oldi;
+
+	if (ip->idhplft EQ 0)		/* see if instrument has points left */
+		return(FALSE);
+
+	if (ip->idhfnc[fn].idfpif EQ 99)	/* see if function is full */
+		return(FALSE);
+
+	topnt = NIPNTS - ip->idhplft;		/* calculate move parameters */
+	frompt = topnt - 1;
+	npts = frompt - inpnt;
+	i = topnt;
+	j = frompt;
+
+#if D_INSPNT
+	if (debugsw)
+		printf("inspnt():  fn=%d, in=%d, to=%d, from=%d, npts=%d, pif=%d\r\n",
+			fn, inpnt, topnt, frompt, npts, ip->idhfnc[fn].idfpif);
+#endif
+
+/* 
+
+*/
+	oldi = setipl(FPU_DI);		/* disable FPU interrupts */
+
+/* ++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++++++ */
+
+	for (k = 0; k < npts; k++) {		/* move things up */
+
+		fp1 = &ip->idhpnt[i--];
+		fp2 = &ip->idhpnt[j--];
+
+		for (l = 0; l < sizeof (struct instpnt); l++)
+			*fp1++ = *fp2++;
+	}
+
+	for (i = fn + 1; i < NFINST; i++) {	/* update point numbers */
+
+		++ip->idhfnc[i].idfpt1;		/* first point */
+		++ip->idhfnc[i].idfcpt;		/* current point */
+	}
+
+	setipl(oldi);		/* restore interrupts */
+
+/* ++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++++ */
+
+	++ip->idhfnc[fn].idfpif;	/* update point totals */
+	--ip->idhplft;
+
+#if D_INSPNT
+	if (debugsw)
+		printf("inspnt():  idfpif=%d, idhplft=%d\r\n",
+			ip->idhfnc[fn].idfpif, ip->idhplft);
+#endif
+
+	return(TRUE);
+}
Index: ram/dformat.c
===================================================================
--- ram/dformat.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/dformat.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,145 @@
+/*
+   =============================================================================
+	dformat.c -- format a disk for the Buchla 700
+	Version 2 -- 1988-03-28 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "biosdefs.h"
+
+#define	DF_FREC		6		/* first sector of primary FAT */
+
+#define	DF_FSIZ		5		/* FAT size */
+#define	DF_DSIZ		7		/* directory size */
+
+extern	short	defect;			/* defect code */
+extern	short	dferror;		/* error code from BIOS or XBIOS */
+
+extern	short	dftype;			/* disk type code */
+extern	short	dfsides;		/* number of sides */
+
+extern	unsigned	dfbuf[4096];	/* track formatting buffer */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dformat() -- format a disk for the Bucla 700
+
+	entry:		dt = zero for single sided disk,
+			     non-zero for double sided disk
+
+	returns:	SUCCESS or FAILURE and:
+
+			defect  = formatting error code:
+
+				0	no errors
+				1	unable to format 1st side
+				2	unable to format 2nd side
+				3	unable to write boot sector
+				4	unable to write primary FAT
+				5	unable to write secondary FAT
+				6	unable to write directory
+
+			dferror = BIOS or XBIOS error code if an error occurred
+   =============================================================================
+*/
+
+short
+dformat(dt)
+short dt;
+{
+	register short trk;
+
+	if (dt) {	/* setup for double sided disk */
+
+		dftype  = 3;	/* 80 tracks, double sided */
+		dfsides = 2;	/* 2 sides */
+
+	} else {	/* setup for single sided disk */
+
+		dftype  = 2;	/* 80 tracks, single sided */
+		dfsides = 1;	/* 1 side */
+	}
+
+	/* format each side of each track */
+
+	for (trk = 0; trk < 80; trk++) {
+
+		if (dferror = (short)XBIOS(X_FORMAT, dfbuf, 0L, 0, 9,
+		    trk, 0, 1, 0x87654321L, 0xE5E5)) {
+
+			defect = 1;	/* unable to format 1st side */
+			return(FAILURE);
+		}
+
+		if (dfsides EQ 2) {	/* format second side */
+
+			if (dferror = (short)XBIOS(X_FORMAT, dfbuf, 0L, 0, 9,
+			    trk, 1, 1, 0x87654321L, 0xE5E5)) {
+
+				defect = 2;	/* unable to format 2nd side */
+				return(FAILURE);
+			}
+		}
+	}
+
+	/* create boot sector */
+
+	memsetw(dfbuf, 0, 4096);
+	XBIOS(X_PRBOOT, dfbuf, 0x01000000L, dftype, 0);
+
+	/* write boot sector to disk */
+
+	if (dferror = (short)XBIOS(X_FLOPWR, dfbuf, 0L, 0, 1, 0, 0, 1)) {
+
+		defect = 3;	/* unable to write boot sector */
+		return(FAILURE);
+	}
+
+	/* clear the FATs */
+
+	memsetw(dfbuf, 0, 4096);
+
+	if (dfsides EQ 2) {
+
+		dfbuf[0] = 0xFDFF;
+		dfbuf[1] = 0xFF00;
+
+	} else {
+
+		dfbuf[0] = 0xFCFF;
+		dfbuf[1] = 0xFF00;
+	}
+
+	if (dferror = (short)BIOS(B_RDWR, 3, dfbuf,
+	    DF_FSIZ, DF_FREC, 0)) {
+
+		defect = 4;	/* unable to write primary FAT */
+		return(FAILURE);
+	}
+
+	if (dferror = (short)BIOS(B_RDWR, 3, dfbuf,
+	    DF_FSIZ, DF_FREC-DF_FSIZ, 0)) {
+
+		defect = 5;	/* unable to write secondary FAT */
+		return(FAILURE);
+	}
+
+	/* clear the directory */
+
+	memsetw(dfbuf, 0, 4096);
+
+	if (dferror = (short)BIOS(B_RDWR, 3, dfbuf,
+	    DF_DSIZ, DF_FREC+DF_FSIZ, 0)) {
+
+		defect = 6;	/* unable to write directory */
+		return(FAILURE);
+	}
+
+	defect = 0;	/* no errors */
+	return(SUCCESS);
+}
Index: ram/dopatch.c
===================================================================
--- ram/dopatch.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/dopatch.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,662 @@
+/*
+   =============================================================================
+	dopatch.c -- MIDAS-VII Patch facility -- execution functions
+	Version 15 -- 1988-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGPA		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "wordq.h"
+#include "patch.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+#if	DEBUGPA
+extern	short	debugsw;
+
+short	debugpa = 1;
+#endif
+
+#define	ST_NUL	0x0000		/* no subaddress breakdown */
+#define	ST_VGT	0x0001		/* break subaddress into voice, group */
+#define	ST_PCT	0x0002		/* break subaddress into port, chan, trig */
+
+extern	char	*S1IoRec, *S2IoRec, *M1IoRec, *M2IoRec;
+
+unsigned short	seqdupd;		/* sequence display update flag */
+
+extern	short	bform;			/* oscillator buffer format */
+extern	short	curinst;		/* current instrument being edited */
+extern	short	curvce;			/* current voice being edited */
+extern	short	timemlt;		/* time multiplier */
+
+extern	short	expbit[];		/* FPU exponent bit table */
+extern	short	ins2grp[];		/* instrument to group assignments */
+extern	short	s_inst[];		/* instrument to voice assignments */
+extern	short	vce2grp[];		/* voice to group assignments */
+
+extern	unsigned short	seqflag[16];		/* sequencer flags */
+extern	unsigned short	seqline[16];		/* current sequencer line */
+extern	unsigned short	sregval[16];		/* register values */
+extern	unsigned short	trstate[16];		/* trigger states */
+
+extern	struct wordq	ptefifo;	/* trigger fifo */
+extern	struct instdef	vbufs[];	/* voice buffers */
+extern	struct wstbl	wslib[];	/* waveshape library */
+
+char	ledstat[24];			/* LED status */
+
+/* 
+
+*/
+
+short	frq2par[] = {1, 3, 5, 7};			/* Frq to par */
+
+short	ind2par[] = {9, 11, 12, 13, 14, 15};		/* Ind to par */
+
+short	cv2vce[] = {11, 10, 6, 8};			/* CV to voice */
+
+short	lg2base[7] = { 0, 3, 7, 10, 14, 17, 21};	/* LED group bases */
+
+char	vgtype[] = {
+
+	ST_NUL,		/* PA_NULL */
+
+	ST_PCT,		/* PA_KEY */
+	ST_PCT,		/* PA_TRG */
+
+	ST_NUL,		/* PA_PLS */
+	ST_NUL,		/* PA_LED */
+	ST_NUL,		/* PA_SLIN */
+	ST_NUL,		/* PA_SCTL */
+	ST_NUL,		/* PA_TUNE */
+	ST_NUL,		/* PA_RSET */
+	ST_NUL,		/* PA_RADD */
+
+	ST_VGT,		/* PA_INST */
+	ST_VGT,		/* PA_OSC */
+	ST_VGT,		/* PA_WAVA */
+	ST_VGT,		/* PA_WAVB */
+	ST_VGT,		/* PA_CNFG */
+	ST_VGT,		/* PA_LEVL */
+	ST_VGT,		/* PA_INDX */
+	ST_VGT,		/* PA_FREQ */
+	ST_VGT,		/* PA_FILT */
+	ST_VGT,		/* PA_FILQ */
+	ST_VGT,		/* PA_LOCN */
+	ST_VGT,		/* PA_DYNM */
+
+	ST_NUL,		/* PA_AUX */
+	ST_NUL,		/* PA_RATE */
+	ST_NUL,		/* PA_INTN */
+	ST_NUL,		/* PA_DPTH */
+	ST_NUL,		/* PA_VOUT */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pdows() -- get a waveshape for a voice
+   =============================================================================
+*/
+
+pdows(slot, voice, wsn)
+short slot, voice, wsn;
+{
+	unsigned short *fpuws;
+	
+	if (slot) {		/* waveshape slot B */
+
+		vbufs[voice].idhwsb = wsn;
+
+		memcpyw(vbufs[voice].idhwvbf, &wslib[wsn],
+			NUMHARM + (2 * NUMWPNT));
+
+		fpuws = io_fpu + FPU_OWST + (voice << 9) + 1;
+
+		memcpyw(fpuws, vbufs[voice].idhwvbf, NUMWPNT);
+
+		*(fpuws - 1) = vbufs[voice].idhwvbf[0];
+		*(fpuws + NUMWPNT) = vbufs[voice].idhwvbf[NUMWPNT - 1];
+
+	} else {		/* waveshape slot A */
+
+		vbufs[voice].idhwsa = wsn;
+
+		memcpyw(vbufs[voice].idhwvaf, &wslib[wsn],
+			NUMHARM + (2 * NUMWPNT));
+
+		fpuws = io_fpu + FPU_OWST + (voice << 9) + 0x0100 + 1;
+
+		memcpyw(fpuws, vbufs[curvce].idhwvaf, NUMWPNT);
+
+		*(fpuws - 1) = vbufs[voice].idhwvaf[0];
+		*(fpuws + NUMWPNT) = vbufs[voice].idhwvaf[NUMWPNT - 1];
+
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pfpufn() -- process an FPU function operation for a patch
+   =============================================================================
+*/
+
+pfpufn(voice, par, dat1, dat2)
+unsigned short voice, par, dat1, dat2;
+{
+	register unsigned short *fpu;
+	short delay;
+
+	fpu = io_fpu + FPU_OFNC + (voice << 8) + (par << 4);
+
+	switch (dat1) {
+
+	case PSA_SRC:		/* source */
+		break;
+
+	case PSA_MLT:		/* multiplier */
+
+		*(fpu + (long)FPU_TSF1) = dat2;
+		break;
+
+	case PSA_TIM:		/* time */
+
+		*(fpu + (long)FPU_TMNT) = (((long)dat2 & 0x0000FFF0L)
+		        * ((long)timemlt & 0x0000FFFFL)) >> 15;
+
+		++delay;
+
+		*(fpu + (long)FPU_TEXP) = expbit[dat2 & 0x000F];
+
+		break;
+
+	case PSA_VAL:		/* value */
+
+		sendval(voice, par, dat2);
+		break;
+
+	case PSA_FNC:		/* function */
+		break;
+
+	default:		/* something weird got in here ... */
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pdoctl() -- do oscillator control for a patch entry
+   =============================================================================
+*/
+
+pdoctl(voice, osc, dat1, dat2)
+register short voice, osc, dat1, dat2;
+{
+	register struct instdef *ip;
+
+	ip = &vbufs[voice];
+	bform = dat1;
+	setoval(ip, osc, dat2 >> 1);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dopatch() -- execute a patch entry
+   =============================================================================
+*/
+
+dopatch(pp)
+register struct patch *pp;
+{
+	register unsigned short suba, dat1, dat2;
+	register short i, temp;
+	register char *ser, *iorec;
+	unsigned short chan, oldsr, osc, port, spec, sat,trig, vgr, vgn, vgt;
+	short baseled, curled, ledctl;
+
+	spec = PE_SPEC & pp->paspec;		/* destination */
+	suba = pp->pasuba;			/* sub address */
+	dat1 = pp->padat1;			/* data word 1 */
+	dat2 = pp->padat2;			/* data word 2 */
+
+	sat = vgtype[spec];			/* sub-address type */
+
+	if (ST_VGT & sat) {		/* vg, osc sub-address types */
+
+		vgr  = 0x00FF & (suba >>  8);		/* voice / group */
+		osc  = 0x00FF &  suba;			/* oscillator */
+
+		if (vgr > 11) {		/* sort out voices from groups */
+
+			vgt = 1;		/* group */
+			vgn = vgr - 12;
+
+		} else {
+
+			vgt = 0;		/* voice */
+			vgn = vgr;
+		}
+
+	} else if (ST_PCT & sat) {	/* port, chan, trig sub-address types */
+
+		port = 0x0003 & (suba >> 11);		/* port */
+		chan = 0x000F & (suba >>  7);		/* channel */
+		trig = 0x007F &  suba;			/* trigger */
+	}
+/* 
+
+*/
+	switch (spec) {		/* dispatch on destination */
+
+	case PA_KEY:		/* key action */
+
+		if ((dat2 EQ 0) OR (dat2 EQ 2))
+			putwq(&ptefifo, suba & 0x1FFF);		/* closure */
+
+		if ((dat2 EQ 0) OR (dat2 EQ 1))
+			putwq(&ptefifo, suba | 0x8000);		/* release */
+
+		break;
+
+	case PA_TRG:		/* trigger */
+
+		trig &= 0x000F;
+		trstate[trig] = dat2;
+
+		if (dat2)
+			putwq(&ptefifo, suba);		/* closure */
+
+		seqdupd |= (1 << trig);
+		break;
+
+	case PA_PLS:		/* pulse output */
+
+		if (suba) {
+
+			ser   = &io_midi + 10L;	/* pulse 2 */
+			iorec = M2IoRec;
+
+		} else {
+
+			ser   = &io_midi + 2L;	/* pulse 1 */
+			iorec = M1IoRec;
+		}
+
+		oldsr = setsr(0x2700);		/* DISABLE INTERRUPTS */
+
+		temp  = iorec[29];		/* get current CFR1 */
+
+		switch (dat2) {			/* switch on operation */
+
+		case 0:				/* transient */
+
+			*ser = temp | 0x0082;			/* on */
+			*ser = (temp & 0x00FD) | 0x0080;	/* off */
+			break;
+
+		case 1:				/* off */
+
+			*ser = (temp & 0x00FD) | 0x0080;	/* off */
+			break;
+
+		case 2:				/* on */
+
+			*ser = temp | 0x0082;			/* on */
+			break;
+		}
+
+		setsr(oldsr);			/* RESTORE INTERRUPTS */
+
+		break;
+/* 
+
+*/
+	case PA_LED:		/* LED control */
+
+		baseled = lg2base[suba];	/* get base of LED group */
+
+		for (i = 0; i < (3 + (suba & 1)); i++) {	/* scan LEDs */
+
+			curled = i + baseled;
+			ledctl = 0x0003 & (dat1 >> (14 - (i << 1)));
+
+			if (ledctl EQ 1) {			/* on */
+
+				ledstat[curled] = TRUE;
+				io_leds = curled;
+
+			} else if (ledctl EQ 2) {		/* off */
+
+				ledstat[curled] = FALSE;
+				io_leds = curled | 0x0080;
+
+			} else if (ledctl EQ 3) {		/* toggle */
+
+				if (ledstat[curled]) {	/* on -> off */
+
+					ledstat[curled] = FALSE;
+					io_leds = curled | 0x0080;
+	
+				} else {			/* off -> on */
+
+					ledstat[curled] = TRUE;
+					io_leds = curled;
+				}
+			}
+		}
+
+		break;
+
+	case PA_SLIN:		/* sequence line */
+
+		seqline[suba] = dat1;
+		seqdupd |= (1 << suba);
+		break;
+
+	case PA_SCTL:		/* sequence control */
+
+
+		if (dat2) {	/* start */
+
+			seqflag[suba] |= (SQF_RUN|SQF_CLK);
+			seqtime[suba]  = seqtab[seqline[suba]].seqtime;
+
+#if	DEBUGPA
+	if (debugsw AND debugpa)
+		printf("dopatch($%08lX):  SLIN %02u %03u %5u RUN\n",
+			pp, suba, seqline[suba], seqtime[suba]);
+#endif
+
+		} else {	/* stop */
+
+			seqflag[suba] = 0;
+			seqtime[suba] = 0;
+
+#if	DEBUGPA
+	if (debugsw AND debugpa)
+		printf("dopatch($%08lX):  SLIN %02u %03u STOP\n",
+			pp, suba, seqline[suba]);
+#endif
+
+		}
+
+		seqdupd |= (1 << suba);
+		break;
+/* 
+
+*/
+	case PA_TUNE:		/* tuning table */
+
+		gettun(dat1);
+		break;
+
+	case PA_RSET:		/* register set */
+
+		sregval[suba] = dat1 ? sregval[dat2] : dat2;
+		seqdupd |= (1 << suba);
+		break;
+
+	case PA_RADD:		/* regsister add */
+
+		temp = sregval[suba] + (dat1 ? sregval[dat2] : dat2);
+
+		if (temp > 99)
+			temp = 99;
+		else if (temp < 0)
+			temp = 0;
+
+		sregval[suba] = temp;
+		seqdupd |= (1 << suba);
+		break;
+
+	case PA_INST:		/* instrument select */
+
+		if (vgt) {	/* group */
+
+			ins2grp[vgn] = (ins2grp[vgn] & 0xFF00) | dat1;
+			setv2gi(vgn);
+
+		} else {	/* voice */
+
+			if (curvce EQ vgn)
+				curinst = dat1;
+
+			s_inst[vgn] = dat1;
+			execins(vgn, dat1, 1);
+		}
+
+		break;
+/* 
+
+*/
+
+	case PA_OSC:		/* oscillator control */
+
+		if (vgt) {		/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pdoctl(i, osc, dat1, dat2);
+
+		} else {		/* voice */
+
+			pdoctl(vgn, osc, dat1, dat2);
+		}
+
+		break;
+/* 
+
+*/
+	case PA_WAVA:		/* waveshape A select */
+
+		if (vgt) {		/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pdows(0, i, dat1);
+
+		} else {		/* voice */
+
+			pdows(0, vgn, dat1);
+		}
+
+		break;
+
+	case PA_WAVB:		/* waveshape B select */
+
+		if (vgt) {		/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pdows(1, i, dat1);
+
+		} else {		/* voice */
+
+			pdows(1, vgn, dat1);
+		}
+
+		break;
+
+	case PA_CNFG:		/* configuration select */
+
+		if (vgt) {
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn)) {
+
+					vbufs[i].idhcfg = dat1;
+					dosync(i);
+				}
+		} else {
+
+			vbufs[vgn].idhcfg = dat1;
+			dosync(vgn);
+		}
+
+		break;
+/* 
+
+*/
+	case PA_LEVL:		/* level */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, 2, dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, 2, dat1, dat2);
+		}
+
+		break;
+
+	case PA_INDX:		/* index */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, ind2par[osc], dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, ind2par[osc], dat1, dat2);
+		}
+
+		break;
+/* 
+
+*/
+	case PA_FREQ:		/* frequency */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, frq2par[osc], dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, frq2par[osc], dat1, dat2);
+		}
+
+		break;
+
+	case PA_FILT:		/* filter frequency */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, 10, dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, 10, dat1, dat2);
+		}
+
+		break;
+/* 
+
+*/
+	case PA_FILQ:		/* filter resonance */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, 6, dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, 6, dat1, dat2);
+		}
+
+		break;
+
+	case PA_LOCN:		/* location */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, 4, dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, 4, dat1, dat2);
+		}
+
+		break;
+/* 
+
+*/
+	case PA_DYNM:		/* dynamics */
+
+		if (vgt) {	/* group */
+
+			for (i = 0; i < 12; i++)
+				if (vce2grp[i] EQ (1 + vgn))
+					pfpufn(i, 8, dat1, dat2);
+
+		} else {	/* voice */
+
+			pfpufn(vgn, 8, dat1, dat2);
+		}
+
+		break;
+
+	case PA_AUX:		/* auxiliary control */
+
+		pfpufn(9, 0, dat1, dat2);
+		break;
+
+	case PA_RATE:		/* phase shifter rate */
+
+		pfpufn(2, 0, dat1, dat2);
+		break;
+
+	case PA_INTN:		/* phase shifter intensity */
+
+		pfpufn(1, 0, dat1, dat2);
+		break;
+
+	case PA_DPTH:		/* phase shifter depth */
+
+		pfpufn(3, 0, dat1, dat2);
+		break;
+
+	case PA_VOUT:		/* control voltage output */
+
+		pfpufn(cv2vce[suba], 0, dat1, dat2);
+		break;
+
+	}
+}
Index: ram/enterit.c
===================================================================
--- ram/enterit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/enterit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,560 @@
+/*
+   =============================================================================
+	enterit.c -- MIDAS data entry and cursor support functions
+	Version 40 -- 1989-12-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "m7ver.h"
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "fields.h"
+#include "fpu.h"
+#include "macros.h"
+#include "panel.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+#include "wsdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugen = 1;
+#endif
+
+extern	short	(*cx_key)(), (*cy_key)(), (*cx_upd)(), (*cy_upd)();
+extern	short	(*xy_up)(), (*xy_dn)(), (*not_fld)();
+extern	short	(*x_key)(), (*e_key)(), (*m_key)(), (*d_key)();
+extern	short	(*premove)(), (*pstmove)(), (*curtype)();
+
+extern	short	*cratex;
+extern	short	*cratey;
+
+extern	short	asig, aval, astat, aflag;
+extern	short	xkstat, ykstat, xkcount, ykcount;
+extern	short	cmtype, cmfirst, xycntr, curpos;
+extern	short	cxrate, cyrate, cxval, cyval;
+extern	short	ncvwait, nchwait, chwait, cvwait, cvtime, chtime;
+extern	short	stcrow, stccol, runit, submenu, vtcrow, vtccol;
+extern	short	trkball, tkctrl, txflag, tyflag;
+extern	short	curhold, hcwval, thcwval, tvcwval, vcwval;
+
+extern	short	sigtab[128][2];
+
+extern	short	crate0[];
+
+short	syrate = SMYRATE;		/* smooth scroll vertical rate */
+
+short	LastRow = -1;
+short	LastCol = -1;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	enterit() -- standard data entry (ENTER) function  
+   =============================================================================
+*/
+
+enterit()
+{
+	if (NOT astat)					/* only on closures */
+		return;
+
+#if	DEBUGIT
+	if (debugsw AND debugen)
+		printf("enterit():  ENTRY  row = %d  col = %d  curfet =$%lX\n",
+			stcrow, stccol, curfet);
+#endif
+
+	if (infield(stcrow, stccol, curfet)) {		/* in a field ? */
+
+		cfetp = infetp;				/* set fet pointer */
+
+		if ((cfetp) AND (NOT ebflag))
+			(*cfetp->ebto)(cfetp->ftags);	/* load ebuf */
+
+		if (cfetp)
+			(*cfetp->ebfrom)(cfetp->ftags);	/* process ebuf */
+
+		if (cfetp)
+			(*cfetp->redisp)(cfetp->ftags);	/* redisplay */
+
+		ebflag = FALSE;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nokey() -- null key function
+   =============================================================================
+*/
+
+short
+nokey()
+{
+	return(FALSE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cmvgen() -- general cursor mover
+   =============================================================================
+*/
+
+cmvgen()
+{
+	register short nc, newrow, newcol, newpos;
+
+	(*premove)();				/* handle PRE-MOVE functions */
+
+	nc = (*curtype)();			/* get new CURSOR TYPE wanted */
+
+	newrow = YTOR(cyval);			/* setup new row */
+	newcol = XTOC(cxval);			/* setup new column */
+
+	if (cmtype NE nc) {			/* if changed ... */
+
+		nchwait = curhold;			/* set hold time */
+		ncvwait = curhold;
+
+		LastRow = -1;				/* reset last position */
+		LastCol = -1;
+	}
+
+	/* see if we've got a new text cursor position */
+
+	if ((newrow NE LastRow) OR (newcol NE LastCol))
+		newpos = TRUE;
+	else
+		newpos = FALSE;
+
+	/* setup horizontal and vertical timer counts */
+
+	chtime = (nc EQ CT_GRAF) ? hcwval : thcwval;
+	cvtime = (nc EQ CT_GRAF) ? vcwval : ((nc EQ CT_SMTH) ? syrate : tvcwval);
+
+	switch (nc) {			/* switch on new cursor type */
+
+	case CT_GRAF:				/* GRAPHIC CURSOR */
+
+		if (cmtype EQ CT_SCOR) {		/* change from score text */
+
+			stcoff();			/* turn off text */
+			sgcon();			/* turn on graphics */
+		}
+
+		cmtype = nc;				/* set cursor type */
+		gcurpos(cxval, cyval);			/* position cursor */
+		break;
+
+/* 
+
+*/
+	case CT_TEXT:				/* TEXT CURSOR */
+
+		cmtype = nc;				/* set cursor type */
+
+		if (newpos)
+			itcpos(newrow, newcol);		/* position cursor */
+
+		break;
+
+	case CT_VIRT:				/* VIRTUAL TYPEWRITER CURSOR */
+
+		cmtype = nc;				/* set cursor type */
+		ttcpos(vtcrow, vtccol);			/* position cursor */
+		break;
+
+	case CT_SCOR:				/* SCORE TEXT CURSOR */
+
+		if (cmtype EQ CT_GRAF)			/* change from graphics */
+			sgcoff();			/* turn off graphics */
+
+		cmtype = nc;				/* set cursor type */
+
+		if (newpos)
+			stcpos(newrow, newcol);		/* position cursor */
+
+		break;
+
+	case CT_SMTH:				/* SMOOTH SCROLL TEXT CURSOR */
+
+		cmtype = nc;				/* set cursor type */
+
+		if (newpos)
+			ctcpos(newrow, newcol);		/* position cursor */
+
+		break;
+
+	case CT_MENU:				/* SUBMENU CURSOR */
+
+		cmtype = nc;				/* set cursor type */
+		mtcpos(vtcrow, vtccol);			/* position cursor */
+		break;
+	}
+
+	LastRow = newrow;
+	LastCol = newcol;
+
+	(*pstmove)();				/* handle POST-MOVE functions */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	crxrate() -- calculate cursor X rate
+   =============================================================================
+*/
+
+short
+crxrate(cv)
+register short cv;
+{
+	register short cs;
+
+	if (cv GE xycntr) {
+
+		cv -= xycntr;
+		cs = 1;
+		curpos = -cv;
+
+	} else {
+
+		cv = xycntr - cv;
+		cs = 0;
+		curpos = cv;
+	}
+
+	if (cv > 127)
+		cv = 127;
+
+	return(cs ? -cratex[cv] : cratex[cv]);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cryrate() -- calculate cursor Y rate
+   =============================================================================
+*/
+
+short
+cryrate(cv)
+register short cv;
+{
+	register short cs;
+
+	if (cv GE xycntr) {
+
+		cv -= xycntr;
+		cs = 1;
+		curpos = -cv;
+
+	} else {
+
+		cv = xycntr - cv;
+		cs = 0;
+		curpos = cv;
+	}
+
+	if (cv > 127)
+		cv = 127;
+
+	return(cs ? -cratey[cv] : cratey[cv]);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cmfix() -- cursor motion initial movement processing
+   =============================================================================
+*/
+
+cmfix()
+{
+	register short acx, acy, scx, scy;
+
+	crxrate(sigtab[55][0]);		/* get cursor x value */
+	acx = abs(curpos);
+
+	cryrate(sigtab[56][0]);		/* get cursor y value */
+	acy = abs(curpos);
+
+	scx = sign(cxrate, 1);
+	scy = sign(cyrate, 1);
+
+	if (cmfirst) {			/* first motion ? */
+
+		if (acx GE acy) {	/* vertical movement */
+
+			cyrate = 0;
+			cxrate = scx;
+			nchwait = curhold;
+			ncvwait = cvtime;
+
+		} else {		/* horizontal movement */
+
+			cxrate = 0;
+			cyrate = scy;
+			ncvwait = curhold;
+			nchwait = chtime;
+		}
+
+		cmfirst = FALSE;
+
+	} else {
+
+		/* limit text movement to 1 axis */
+
+		if (cmtype NE CT_GRAF)
+			if (acx GE acy)
+				cyrate = 0;
+			else
+				cxrate = 0;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cxkstd() -- standard cursor x rate calculation
+   =============================================================================
+*/
+
+cxkstd()
+{
+	trkball = FALSE;
+	tkctrl  = FALSE;
+	txflag  = FALSE;
+	tyflag  = FALSE;
+
+	if (astat) {		/* contact */
+
+		if (xkstat EQ FALSE) {
+
+			if (xkcount) {		/* debounce */
+
+				xkcount--;
+				return;
+			}
+
+			xkstat  = TRUE;
+			chwait  = 1;
+			nchwait = curhold;
+
+			if (ykstat)
+				(*xy_dn)();
+		}
+
+		cxrate = -crxrate(aval);
+/* 
+
+*/
+	} else {		/* release */
+
+		if (xkstat AND ykstat)
+			(*xy_up)();
+
+		xkstat  = FALSE;
+		xkcount = 1;
+		cxrate  = 0;
+
+		if (ykstat EQ FALSE) {
+
+			cyrate  = 0;
+			ykcount = 1;
+			nchwait = chtime;
+			ncvwait = cvtime;
+			chwait  = 1;
+			cvwait  = 1;
+			cmfirst = TRUE;
+		}
+	}
+
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cykstd() -- standard cursor y rate calculation
+   =============================================================================
+*/
+
+cykstd()
+{
+	trkball = FALSE;
+	tkctrl  = FALSE;
+	txflag  = FALSE;
+	tyflag  = FALSE;
+
+	if (astat) {		/* contact */
+
+		if (ykstat EQ FALSE) {
+
+			if (ykcount) {		/* debounce */
+
+				ykcount--;
+				return;
+			}
+
+			ykstat  = TRUE;
+			cvwait  = 1;
+			ncvwait = curhold;
+
+			if (xkstat)
+				(*xy_dn)();
+		}
+
+		cyrate = cryrate(aval);
+/* 
+
+*/
+	} else {		/* release */
+
+		if (xkstat AND ykstat)
+			(*xy_up)();
+
+		ykstat  = FALSE;
+		ykcount = 1;
+		cyrate  = 0;
+
+		if (xkstat EQ FALSE) {
+
+			cxrate  = 0;
+			xkcount = 1;
+			nchwait = chtime;
+			ncvwait = cvtime;
+			chwait  = 1;
+			cvwait  = 1;
+			cmfirst = TRUE;
+		}
+	}
+
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stdmkey() -- standard M key processing
+   =============================================================================
+*/
+
+stdmkey()
+{
+	if (astat) {
+
+		runit = FALSE;
+		submenu = FALSE;
+	}
+}
+
+/*
+   =============================================================================
+	stddkey() - standard data key processing
+   =============================================================================
+*/
+
+stddkey()
+{
+	if (infield(stcrow, stccol, curfet)) {
+
+		cfetp = infetp;		/* set field pointer */
+
+		if (astat) {		/* only do action on closures */
+
+			if (!ebflag)
+				(*cfetp->ebto)(cfetp->ftags);	/* setup ebuf */
+
+			(*cfetp->datain)(cfetp->ftags, asig - 60);	/* enter */
+		}
+
+	} else {
+
+		if (astat)
+			(*not_fld)(asig - 60);		/* not in field */
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cxgen() -- standard cursor x update processing
+   =============================================================================
+*/
+
+cxgen()
+{
+	cxval += cxrate;
+
+	if (cxval > CXMAX)
+		cxval = CXMAX;
+	else if (cxval < 0)
+		cxval = 0;
+				
+	return;
+}
+
+/*
+   =============================================================================
+	cygen() -- standard cursor y update processing
+   =============================================================================
+*/
+
+cygen()
+{
+	cyval += cyrate;
+
+	if (cyval > CYMAX)
+		cyval = CYMAX;
+	else if (cyval < 0)
+		cyval = 0;
+
+	return;
+}
Index: ram/etaccn.c
===================================================================
--- ram/etaccn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etaccn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,156 @@
+/*
+   =============================================================================
+	etaccn.c -- assignment editor - source controller number field handlers
+	Version 7 -- 1988-03-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	char	*numblk();
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+extern	short	mctlnum[4];	/* MIDI controller number table (-1, 00..99) */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_accn() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_accn(n)
+short n;
+{
+	register short ctl;
+
+	char buf[4];
+
+	ctl = 0x00FF & (n >> 8);
+
+	numblk(ebuf, (mctlnum[ctl] & 0x00FF));
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_accn() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_accn(n)
+short n;
+{
+	register short tmpval, ctl, i;
+
+	ctl = 0x00FF & (n >> 8);
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	if ((ebuf[0] EQ ' ') AND (ebuf[1] EQ ' ')) {
+
+		tmpval = -1;
+
+	} else {
+
+		for (i = 0; i < 2; i++) {
+
+			if (ebuf[i] EQ ' ')
+				ebuf[i] = '0';
+
+			tmpval = (tmpval * 10) + (ebuf[i] - '0');
+		}
+	}
+
+	if (mctlnum[ctl] EQ -1)
+		mctlnum[ctl] = tmpval;
+	else
+		mctlnum[ctl] = (mctlnum[ctl] & 0xFF00) | tmpval;
+
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_accn() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_accn(nn)
+short nn;
+{
+	register short n, ctl;
+	char buf[4];
+
+	n = 0x00FF & nn;
+	ctl = 0x00FF & (nn >> 8);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		cfetp->frow, cfetp->flcol,
+		numblk(buf, (mctlnum[ctl] & 0x00FF)), 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_accn() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_accn(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	ebuf[stccol - cfetp->flcol] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etadep.c
===================================================================
--- ram/etadep.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etadep.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,126 @@
+/*
+   =============================================================================
+	etadep.c -- MIDAS assignment editor - phase shifter depth field
+	Version 4 -- 1987-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+extern	short	ps_dpth;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_adep() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_adep(n)
+short n;
+{
+	sprintf(ebuf, "%02d", ps_dpth);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_adep() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_adep(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	ps_dpth = tmpval;
+	sendval(3, 0, ((ps_dpth * 10) << 5));
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_adep() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_adep(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02.2d", ps_dpth);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6] + 3, adbox[n][7] + 8, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_adep() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_adep(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etadyn.c
===================================================================
--- ram/etadyn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etadyn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,214 @@
+/*
+   =============================================================================
+	etadyn.c -- MIDAS assignment editor -- dynamics to group field handlers
+	Version 7 -- 1988-07-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "fpu.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+#include "instdsp.h"
+
+extern	short	setsr();
+
+extern	unsigned	*asgob;
+
+extern	unsigned	curintp;
+
+extern	short		stccol;
+extern	short		stcrow;
+extern	short		timemlt;
+
+extern	char		dspbuf[];
+
+extern	short		vce2grp[];
+extern	short		grpdyn[];
+extern	short		dyntab[];
+
+extern	unsigned	expbit[];
+
+extern	short		adbox[][8];
+
+extern	struct instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_adyn() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_adyn(n)
+short n;
+{
+	register short grp;
+
+	grp = 0x00FF & (n >> 8);
+
+	ebuf[0] = grpdyn[grp] + '0';
+	ebuf[1] = '\0';
+
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setdyn() -- set dynamics for a group
+   =============================================================================
+*/
+
+setdyn(grp, dyn)
+short grp, dyn;
+{
+	register short g, i, val;
+	register long ltmp;
+	register unsigned *fpu;
+	register struct idfnhdr *fp;
+	unsigned fpmant, fpexp;
+	short oldsr;
+	short nop;
+
+	grpdyn[grp] = dyn;
+	val = dyntab[dyn];
+	g = grp + 1;
+
+	fpmant = (((long)curintp & 0x0000FFF0L) *
+		  ((long)timemlt & 0x0000FFFFL)) >> 15;
+
+	fpexp = expbit[curintp & 0x000F];
+
+/* 
+
+*/
+	for (i = 0; i < 12; i++)
+		if (g EQ vce2grp[i]) {
+
+			fp = &vbufs[i].idhfnc[8];
+			fpu = io_fpu + FPU_OFNC + (i << 8) + 0x0080;
+
+			oldsr = setsr(0x2200);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+			fp->idftmd ^= I_NVBITS;
+			*(fpu + (long)FPU_TMNT) = fpmant;
+			++nop;	++nop;	++nop;
+			*(fpu + (long)FPU_TEXP) = fpexp;
+			++nop;	++nop;	++nop;
+
+			if (fp->idftmd & I_VNSUBN)
+				*(fpu + (long)FPU_TNV1) = val;
+			else
+				*(fpu + (long)FPU_TNV0) = val;
+
+			++nop;	++nop;	++nop;
+
+			*(fpu + (long)FPU_TCTL) =
+				(fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0001;
+
+			setsr(oldsr);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+		}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_adyn() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_adyn(n)
+short n;
+{
+	register short dyn, grp;
+
+	grp = 0x00FF & (n >> 8);
+
+	ebuf[1] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	dyn = ebuf[0] - '0';
+
+	setdyn(grp, dyn);
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_adyn() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_adyn(nn)
+short nn;
+{
+	register short n, grp;
+
+	n = 0x00FF & nn;
+	grp = 0x00FF & (nn >> 8);
+
+	dspbuf[0] = grpdyn[grp] + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		cfetp->frow, cfetp->flcol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_adyn() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_adyn(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+
+	dspbuf[0] = ebuf[0] = k + '0';
+	dspbuf[1] = ebuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
Index: ram/etagch.c
===================================================================
--- ram/etagch.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etagch.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,152 @@
+/*
+   =============================================================================
+	etagch.c -- assignment editor - group to channel number field handlers
+	Version 6 -- 1987-12-10 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	char	*numblk();
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+extern	short	grp2prt[12][2];	/* group to port and channel table */
+				/* port [0] = 0..4, channel [1] = -1, 1..16 */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_agch() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_agch(n)
+short n;
+{
+	register short grp;
+
+	char buf[4];
+
+	grp = 0x00FF & (n >> 8);
+
+	numblk(ebuf, grp2prt[grp][1]);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_agch() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_agch(n)
+short n;
+{
+	register short tmpval, grp, i;
+
+	grp = 0x00FF & (n >> 8);
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	if ((ebuf[0] EQ ' ') AND (ebuf[1] EQ ' ')) {
+
+		tmpval = -1;
+
+	} else {
+
+		for (i = 0; i < 2; i++) {
+
+			if (ebuf[i] EQ ' ')
+				ebuf[i] = '0';
+
+			tmpval = (tmpval * 10) + (ebuf[i] - '0');
+		}
+
+		if ((tmpval EQ 0) OR (tmpval GT 16))
+			return(FAILURE);
+	}
+
+	grp2prt[grp][1] = tmpval;
+
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_agch() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_agch(nn)
+short nn;
+{
+	register short n, grp;
+	char buf[4];
+
+	n = 0x00FF & nn;
+	grp = 0x00FF & (nn >> 8);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		cfetp->frow, cfetp->flcol, numblk(buf, grp2prt[grp][1]), 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_agch() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_agch(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	ebuf[stccol - cfetp->flcol] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etagpt.c
===================================================================
--- ram/etagpt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etagpt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,152 @@
+/*
+   =============================================================================
+	etagpt.c -- assignment editor - group to input port field handlers
+	Version 5 -- 198-10-04 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	char	*numblk();
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+
+extern	char	dspbuf[];
+extern	char	*gprep[];
+
+extern	short	key2grp[];
+
+extern	short	adbox[][8];
+
+extern	short	grp2prt[12][2];	/* group to port and channel table */
+				/* port [0] = 0..3, channel [1] = -1, 1..16 */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_agpt() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_agpt(n)
+short n;
+{
+	register short grp;
+
+	grp = 0x00FF & (n >> 8);
+
+	ebuf[0] = grp2prt[grp][0];
+	ebuf[1] = '\0';
+
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_agpt() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_agpt(n)
+short n;
+{
+	register short tmpval, grp, i;
+
+	grp = 0x00FF & (n >> 8);
+
+	ebuf[1] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	grp2prt[grp][0] = ebuf[0];
+
+	if (grp2prt[grp][0] NE 1)
+		for (i = 0; i < 88; i++)
+			key2grp[i] &= ~(0x0001 << grp);
+
+	drawk2g(grp);
+
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_agpt() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_agpt(nn)
+short nn;
+{
+	register short n, grp;
+
+	n   = 0x00FF & nn;
+	grp = 0x00FF & (nn >> 8);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		cfetp->frow, cfetp->flcol, gprep[grp2prt[grp][0]], 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_agpt() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_agpt(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0x00FF;
+
+	if (k EQ 8) {		/* '-' */
+
+		if (--ebuf[0] LT 0)
+			ebuf[0] = 3;
+
+	} else if (k EQ 9) {	/* '+' */
+
+		if (++ebuf[0] GT 3)
+			ebuf[0] = 0;
+
+	} else {
+
+		return(FAILURE);
+	}
+
+	dspbuf[0] = *gprep[ebuf[0]];
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
Index: ram/etains.c
===================================================================
--- ram/etains.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etains.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,158 @@
+/*
+   =============================================================================
+	etains.c -- MIDAS assignment editor -- instrument to groups
+	Version 10 -- 1988-07-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	char	*numblk();
+
+extern	unsigned	*asgob;
+
+extern	short	asgmod;
+extern	short	stccol;
+extern	short	stcrow;
+
+extern	char	dspbuf[];
+
+extern	short	ins2grp[];
+
+extern	short	adbox[][8];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	modasg() -- indicate that the assignment table was modified
+   =============================================================================
+*/
+
+modasg()
+{
+	if (NOT asgmod) {
+
+		asgmod = TRUE;
+		adswin(0);
+	}
+}
+
+/*
+   =============================================================================
+	et_ains() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_ains(n)
+short n;
+{
+	register short grp;
+
+	char buf[4];
+
+	grp = 0x00FF & (n >> 8);
+
+	sprintf(ebuf, "%02.2d", ins2grp[grp] & 0x00FF);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_ains() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_ains(n)
+short n;
+{
+	register short tmpval, grp, i;
+
+	grp = 0x00FF & (n >> 8);
+	ebuf[2] = '\0';
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (tmpval GE NINST )
+		return(FAILURE);
+
+	ins2grp[grp] = tmpval | (ins2grp[grp] & 0xFF00);
+	modasg();
+	setv2gi(grp);
+	setinst();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ains() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_ains(nn)
+short nn;
+{
+	register short n, grp;
+	char buf[4];
+
+	n = 0x00FF & nn;
+	grp = 0x00FF & (nn >> 8);
+
+	sprintf(dspbuf, "%02.2d", ins2grp[grp] & 0x00FF);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		cfetp->frow, cfetp->flcol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_ains() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_ains(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	ebuf[stccol - cfetp->flcol] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etaint.c
===================================================================
--- ram/etaint.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etaint.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,126 @@
+/*
+   =============================================================================
+	etaint.c -- MIDAS assignment editor - phase shifter intensity field
+	Version 5 -- 1987-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+extern	short	ps_intn;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_aint() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_aint(n)
+short n;
+{
+	sprintf(ebuf, "%02d", ps_intn);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_aint() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_aint(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	ps_intn = tmpval;
+	sendval(1, 0, ((ps_intn * 10) << 5));
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_aint() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_aint(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02.2d", ps_intn);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6] + 1, adbox[n][7] + 8, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_aint() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_aint(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etaopt.c
===================================================================
--- ram/etaopt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etaopt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,126 @@
+/*
+   =============================================================================
+	etaopt.c -- assignment editor - MIDI output port number field handlers
+	Version 4 -- 1987-12-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+extern	short	curmop;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+extern	char	*gprep[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_aopt() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_aopt(n)
+short n;
+{
+	sprintf(ebuf, "%01.1d", curmop);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_aopt() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_aopt(n)
+short n;
+{
+	register short tmpval;
+
+	ebuf[1] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = ebuf[0] - '0';
+
+	if (tmpval GT 3)
+		return(FAILURE);
+
+	curmop = tmpval;
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_aopt() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_aopt(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6], adbox[n][7] + 9, gprep[curmop], 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_aopt() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_aopt(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	if ((k < 1) OR (k > 2))
+		return(FAILURE);
+
+	n = nn & 0xFF;
+	ebuf[0] = k + '0';
+	ebuf[1] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
Index: ram/etaprg.c
===================================================================
--- ram/etaprg.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etaprg.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,139 @@
+/*
+   =============================================================================
+	etaprg.c -- MIDAS assignment editor - program change channel field
+	Version 3 -- 1987-12-21 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+extern	short	prgchan;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_aprg() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_aprg(n)
+short n;
+{
+	sprintf(ebuf, "%02d", prgchan);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_aprg() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_aprg(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ef_aprg($%04.4X):  ebuf=[%s], tmpval=%d\n",
+			n, ebuf, tmpval);
+#endif
+
+	if ((tmpval EQ 0) OR (tmpval GT 16))
+		return(FAILURE);
+
+	prgchan = tmpval;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_aprg() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_aprg(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02.2d", prgchan);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6], adbox[n][7] + 8, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_aprg() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_aprg(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etarat.c
===================================================================
--- ram/etarat.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etarat.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,126 @@
+/*
+   =============================================================================
+	etarat.c -- MIDAS assignment editor - phase shifter rate field
+	Version 4 -- 1987-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+extern	short	ps_rate;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_arat() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_arat(n)
+short n;
+{
+	sprintf(ebuf, "%02d", ps_rate);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_arat() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_arat(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	ps_rate = tmpval;
+	sendval(2, 0, ((ps_rate * 10) << 5));
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_arat() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_arat(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02.2d", ps_rate);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6] + 2, adbox[n][7] + 8, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_arat() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_arat(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etatab.c
===================================================================
--- ram/etatab.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etatab.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,151 @@
+/*
+   =============================================================================
+	etatab.c -- assignment editor - assignment table number field handlers
+	Version 9 -- 1988-08-22 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	short	adpoint();
+
+extern	short	(*point)();
+
+extern	unsigned	*asgob;
+
+extern	short	asgmod;
+extern	short	curasg;
+extern	short	stccol;
+extern	short	stcrow;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_atab() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_atab(n)
+short n;
+{
+	sprintf(ebuf, "%02d", curasg);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_atab() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_atab(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (tmpval GE NASGS)
+		return(FAILURE);
+
+	curasg = tmpval;
+	asgmod = TRUE;
+	adswin(0);
+
+	settc(2, 6);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_atab() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_atab(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02.2d", curasg);
+
+	point = adpoint;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(asgob, 64, (asgmod ? exp_c(AK_MODC) : adbox[n][4]), adbox[n][5],
+		cfetp->frow, cfetp->flcol, dspbuf, 14);
+
+	lseg(0, 0, 128, 0, AK_BORD);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_atab() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_atab(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	point = adpoint;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	lseg(0, 0, 128, 0, AK_BORD);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etatun.c
===================================================================
--- ram/etatun.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etatun.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,121 @@
+/*
+   =============================================================================
+	etatun.c -- MIDAS assignment editor - tuning table field handlers
+	Version 1 -- 1987-12-10 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+extern	short	curtun;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_atun() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_atun(n)
+short n;
+{
+	sprintf(ebuf, "%01.1d", curtun);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_atun() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_atun(n)
+short n;
+{
+	register short tmpval;
+
+	ebuf[1] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = ebuf[0] - '0';
+
+	gettun(tmpval);
+
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_atun() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_atun(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "Tun %01.1d", curtun);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		adbox[n][6], adbox[n][7], dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_atun() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_atun(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	ebuf[0] = k + '0';
+	ebuf[1] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
Index: ram/etavgr.c
===================================================================
--- ram/etavgr.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etavgr.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,185 @@
+/*
+   =============================================================================
+	etavgr.c -- assignment editor - voice to group field handlers
+	Version 9 -- 1988-03-18 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	char	*numblk();
+
+extern	unsigned	*asgob;
+
+extern	short	stcrow, stccol;
+
+extern	short	adbox[][8];
+
+extern	char	dspbuf[];
+
+extern	short	vce2grp[12];		/* voice to group table */
+extern	short	ins2grp[12];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_avgr() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_avgr(nn)
+short nn;
+{
+	register short grp;
+	char buf[4];
+
+	grp = 0x00FF & (nn >> 8);
+
+	sprintf(ebuf, "%s", numblk(buf, vce2grp[grp]));
+	ebflag = TRUE;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("et_avgr($%04.4X):  ebuf=[%s]\n", nn, ebuf);
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_avgr() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_avgr(nn)
+short nn;
+{
+	register short tmpval, vce, i;
+
+	vce = 0x00FF & (nn >> 8);
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ef_avgr($%04.4X):  ebuf=[%s]\n", nn, ebuf);
+#endif
+
+	if ((ebuf[0] EQ ' ') AND (ebuf[1] EQ ' ')) {
+
+		tmpval = -1;
+
+	} else {
+
+		for (i = 0; i < 2; i++) {
+
+			if (ebuf[i] EQ ' ')
+				ebuf[i] = '0';
+
+			tmpval = (tmpval * 10) + (ebuf[i] - '0');
+		}
+
+		if ((tmpval EQ 0) OR (tmpval GT 12))
+			return(FAILURE);
+	}
+
+	vce2grp[vce] = tmpval;
+
+	if (tmpval > 0)
+		execinst(vce, (ins2grp[tmpval - 1] & 0x00FF), 1);
+
+	modasg();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_avgr() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_avgr(nn)
+short nn;
+{
+	register short n, grp;
+	char buf[4];
+
+	n = 0x00FF & nn;
+	grp = 0x00FF & (nn >> 8);
+
+	vbank(0);
+	vcputsv(asgob, 64, adbox[n][4], adbox[n][5],
+		cfetp->frow, cfetp->flcol, numblk(buf, vce2grp[grp]), 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_avgr() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_avgr(nn, k)
+short nn;
+register short  k;
+{
+	register short n, col;
+
+	n = nn & 0xFF;
+	col = stccol - cfetp->flcol;
+
+	ebuf[col] = k + '0';
+	ebuf[2] = '\0';
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("nd_avgr($%04.4X, %d):  cfetp=$%08.8lX, col=%d, ebuf=[%s]\n",
+			nn, k, cfetp, col, ebuf);
+#endif
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(asgob, 64, AK_ENTRY, adbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advacur();
+	return(SUCCESS);
+}
+
Index: ram/etdyn.c
===================================================================
--- ram/etdyn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etdyn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,150 @@
+/*
+   =============================================================================
+	etdyn.c -- dynamics field handlers
+	Version 8 -- 1988-06-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "instdsp.h"
+
+extern	unsigned	*obj8;
+
+extern	short	ctrsw, recsw, stccol;
+
+extern	short	grpdyn[], grpmode[], grpstat[];
+
+extern	struct	gdsel	*gdstbc[];
+
+/*
+   =============================================================================
+	et_dyn() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_dyn(n)
+short n;
+{
+	ebuf[0] =grpdyn[n] + '0';
+	ebuf[1] = '\0';
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_dyn() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_dyn(n)
+short n;
+{
+	register short ival;
+	register struct s_entry *ep;
+
+	ebuf[1] = '\0';
+	ival = ebuf[0] - '0';
+	ebflag = FALSE;
+
+	setdyn(n, ival);
+
+	if (recsw AND grpmode[n] AND (2 EQ grpmode[n])) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_DYN, n, -1))) {
+
+			ep->e_data2 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_DYN;
+			ep->e_data1 = n;
+			ep->e_data2 = ival;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_DYN);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_dyn() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_dyn(n)
+short n;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 4, 6+(n*5), (grpdyn[n] + '0'), SDW11ATR);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ds_dyn() -- display all dynamics to group assignments
+   =============================================================================
+*/
+
+ds_dyn()
+{
+	register short i;
+
+	for (i = 0; i < 12; i++)
+		rd_dyn(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_dyn() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_dyn(n, k)
+register short n, k;
+{
+	ebuf[0]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 4, stccol, k + '0', SDW11DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etiact.c
===================================================================
--- ram/etiact.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etiact.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,493 @@
+/*
+   =============================================================================
+	etiact.c -- point action field handlers
+	Version 16 -- 1988-08-31 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+/* functions defined elsewhere */
+
+extern	int	advicur();
+
+extern	char	*strcpy();
+
+/* variables defined elsewhere */
+
+extern	short	stcrow, stccol, curvce, curpnt, curfunc;
+extern	short	debugsw;
+
+extern	short	idbox[][8];
+
+extern	unsigned	*instob;
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+extern	short	aform;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_iact() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_iact(nn)
+short nn;
+{
+	register struct instpnt *pp;
+
+	pp = &vbufs[curvce].idhpnt[curpnt];
+
+	aform = pp->ipact;
+
+	switch (aform) {
+
+	case AC_NULL:
+	case AC_SUST:
+	case AC_ENBL:
+	case AC_UNDF:
+
+		ebuf[0] = '\0';
+		break;
+
+	case AC_JUMP:
+	case AC_KYUP:
+	case AC_KYDN:
+
+		sprintf(ebuf, "%02d", pp->ippar1);
+		break;
+
+	case AC_LOOP:
+
+		sprintf(ebuf, "%02d %02d", pp->ippar1, pp->ippar2);
+		break;
+	}
+
+#if DEBUGIT
+	if (debugsw)
+		printf("et_iact():  aform=%d, ebuf=[%s]\r\n", aform, ebuf);
+#endif
+
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_iact() -- unload (parse) edit buffer
+   =============================================================================
+*/
+
+short
+ef_iact(nn)
+short nn;
+{
+	register short i, tmp1, tmp2;
+	register struct instpnt *pp;
+	register struct idfnhdr *fp;
+
+	fp = &vbufs[curvce].idhfnc[curfunc];
+	pp = &vbufs[curvce].idhpnt[curpnt];
+	ebflag = FALSE;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_iact():  aform=%d, fp=$%08lX, pp=$%08lX\r\n",
+			aform, fp, pp);
+#endif
+
+	switch (aform) {
+
+	case AC_NULL:
+	case AC_UNDF:
+
+		aform = AC_NULL;
+
+	case AC_SUST:
+	case AC_ENBL:
+
+		pp->ipact = aform;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_iact():  aform=%d, ipact=%d, ippar1=%d, ippar2=%d\r\n",
+			aform, pp->ipact, pp->ippar1, pp->ippar2);
+#endif
+
+		modinst();
+		return(SUCCESS);
+
+	case AC_JUMP:
+	case AC_KYUP:
+	case AC_KYDN:
+
+		tmp1 = 0;
+
+		for (i = 0; i < 2; i++)
+			tmp1 = (tmp1 * 10) + (ebuf[i] - '0');
+
+		if (tmp1 GE fp->idfpif)
+			return(FAILURE);
+
+		pp->ipact = aform;
+		pp->ippar1 = tmp1;
+		pp->ippar2 = 0;
+		pp->ippar3 = 0;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_iact():  aform=%d, ipact=%d, ippar1=%d, ippar2=%d\r\n",
+			aform, pp->ipact, pp->ippar1, pp->ippar2);
+#endif
+
+		modinst();
+		return(SUCCESS);
+/* 
+
+*/
+	case AC_LOOP:
+
+		tmp1 = 0;
+
+		for (i = 0; i < 2; i++)
+			tmp1 = (tmp1 * 10) + (ebuf[i] - '0');
+
+		if (tmp1 GE fp->idfpif)
+			return(FAILURE);
+
+		tmp2 = 0;
+
+		for (i = 3; i < 5; i++)
+			tmp2 = (tmp2 * 10) + (ebuf[i] - '0');
+
+		pp->ipact = aform;
+		pp->ippar1 = tmp1;
+		pp->ippar2 = tmp2;
+		pp->ippar3 = 0;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_iact():  aform=%d, ipact=%d, ippar1=%d, ippar2=%d\r\n",
+			aform, pp->ipact, pp->ippar1, pp->ippar2);
+#endif
+
+		modinst();
+		return(SUCCESS);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_iact() -- (re)-display the field
+   =============================================================================
+*/
+
+short
+rd_iact(nn)
+short nn;
+{
+	register short pnt, par, n;
+	register struct instpnt *pp;
+	register char *s1;
+
+	n = nn & 0x00FF;
+	pp = &vbufs[curvce].idhpnt[curpnt];
+	pnt = pp->ippar1;
+	par = pp->ippar2;
+	aform = pp->ipact;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("rd_iact():  aform=%d, pp=$%08lX, pnt=%d, par=%d\r\n",
+			aform, pp, pnt, par);
+#endif
+
+	switch (aform) {
+
+	case AC_NULL:
+
+		s1 = "                 ";
+		break;
+
+	case AC_SUST:
+
+		sprintf(dspbuf, "Pause if key %c  ", SP_DNA);
+		s1 = dspbuf;
+		break;
+
+	case AC_ENBL:
+
+		sprintf(dspbuf, "Stop if key %c   ", SP_UPA);
+		s1 = dspbuf;
+		break;
+
+	case AC_JUMP:
+
+		sprintf(dspbuf, "GoTo %02d forever ", pnt);
+		s1 = dspbuf;
+		break;
+
+/* 
+
+*/
+	case AC_LOOP:
+
+		sprintf(dspbuf, "GoTo %02d %02d times", pnt, par);
+
+		if (dspbuf[8] EQ '9')
+			dspbuf[8] = 'R';
+
+		s1 = dspbuf;
+		break;
+
+	case AC_KYUP:
+
+		sprintf(dspbuf, "GoTo %02d if key %c", pnt, SP_UPA);
+		s1 = dspbuf;
+		break;
+
+	case AC_KYDN:
+
+		sprintf(dspbuf, "GoTo %02d if key %c", pnt, SP_DNA);
+		s1 = dspbuf;
+		break;
+
+	default:
+
+		s1 = "????????????????";
+		break;
+	}
+
+	vbank(0);
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],
+		idbox[n][6] + 1, idbox[n][7], s1, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setactb() -- set action field data entry buffer format
+   =============================================================================
+*/
+
+setactb(n)
+short n;
+{
+	register char *s1;
+
+	switch (aform) {
+
+	case AC_NULL:
+
+		s1 = "                ";
+		ebuf[0] = '\0';
+		break;
+
+	case AC_SUST:
+
+		sprintf(dspbuf, "Pause if key %c  ", SP_DNA);
+		s1 = dspbuf;
+		ebuf[0] = '\0';
+		break;
+
+	case AC_ENBL:
+
+		sprintf(dspbuf, "Stop if key %c   ", SP_UPA);
+		s1 = dspbuf;
+		ebuf[0] = '\0';
+		break;
+
+	case AC_JUMP:
+
+		s1 = "GoTo 00 forever ";
+		ebuf[0] = '0';
+		ebuf[1] = '0';
+		ebuf[2] = '\0';
+		break;
+
+/* 
+
+*/
+	case AC_LOOP:
+
+		s1 = "GoTo 00 00 times";
+		ebuf[0] = '0';
+		ebuf[1] = '0';
+		ebuf[2] = ' ';
+		ebuf[3] = '0';
+		ebuf[4] = '0';
+		ebuf[5] = '\0';
+		break;
+
+	case AC_KYUP:
+
+		sprintf(dspbuf, "GoTo 00 if key %c", SP_UPA);
+		s1 = dspbuf;
+		ebuf[0] = '0';
+		ebuf[1] = '0';
+		ebuf[2] = '\0';
+		break;
+
+	case AC_KYDN:
+
+		sprintf(dspbuf, "GoTo 00 if key %c", SP_DNA);
+		s1 = dspbuf;
+		ebuf[0] = '0';
+		ebuf[1] = '0';
+		ebuf[2] = '\0';
+		break;
+
+	default:
+
+		s1 = "????????????????";
+		ebuf[0] = '\0';
+		break;
+	}
+
+	vbank(0);
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6] + 1, idbox[n][7], s1, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_iact() -- process new data entry
+   =============================================================================
+*/
+
+short
+nd_iact(nn, k)
+short nn, k;
+{
+	register short n, ec;
+
+	n = nn & 0xFF;
+
+	if (stccol LT (idbox[n][7] + 5)) {
+
+		if (k EQ 8) {
+
+			if (--aform < 0)
+				aform = AC_KYDN;
+
+			setactb(n);
+			return(SUCCESS);
+
+		} else if (k EQ 9) {
+
+			if (++aform > AC_KYDN)
+				aform = AC_NULL;
+
+			setactb(n);
+			return(SUCCESS);
+		}
+
+		return(FAILURE);
+
+/* 
+
+*/
+	} else {
+
+		switch (aform) {
+
+		case AC_NULL:
+		case AC_UNDF:
+		case AC_ENBL:
+		case AC_SUST:
+
+			return(FAILURE);
+
+		case AC_KYUP:
+		case AC_KYDN:
+		case AC_JUMP:
+
+			if ((stccol EQ (idbox[n][7] + 5)) OR
+			    (stccol EQ (idbox[n][7] + 6))) {
+
+				ebuf[stccol - (idbox[n][7] + 5)] = k + '0';
+				dspbuf[0] = k + '0';
+				dspbuf[1] = '\0';
+
+				vbank(0);
+				vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+					stcrow, stccol, dspbuf, 14);
+
+				advicur();
+				return(SUCCESS);
+
+			} else {
+
+				return(FAILURE);
+			}
+/* 
+
+*/
+		case AC_LOOP:
+
+			if ((stccol GE (idbox[n][7] + 5)) AND
+			    (stccol LE (idbox[n][7] + 9))) {
+
+				ec = stccol - (idbox[n][7] + 5);
+
+				if (ec EQ 2)
+					return(FAILURE);
+
+				ebuf[ec] = k + '0';
+				dspbuf[0] = k + '0';
+				dspbuf[1] = '\0';
+
+				if ((ec EQ 3) AND (k EQ 9))
+					dspbuf[0] = 'R';
+
+				vbank(0);
+				vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+					stcrow, stccol, dspbuf, 14);
+
+				advicur();
+
+				if (ec EQ 1)
+					advicur();
+
+				return(SUCCESS);
+
+			} else {
+
+				return(FAILURE);
+			}
+		}
+	}
+}
Index: ram/eticnf.c
===================================================================
--- ram/eticnf.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/eticnf.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,145 @@
+/*
+   =============================================================================
+	eticnf.c -- instrument editor - configuration number field handlers
+	Version 16 -- 1988-08-23 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#define	CFG_OFF		10	/* display offset into configuration field */
+
+extern	unsigned	*instob;
+
+extern	short	stccol, curvce;
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_icnf() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_icnf(n)
+short n;
+{
+	sprintf(ebuf, "%02d", vbufs[curvce].idhcfg);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_icnf() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_icnf(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (tmpval GE NUMCFG)		/* check against limit */
+		return(FAILURE);
+
+	vbufs[curvce].idhcfg = tmpval;
+	dosync(curvce);
+	showcfg(tmpval);
+	modinst();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_icnf() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_icnf(n)
+short n;
+{
+	sprintf(dspbuf, "%02d", vbufs[curvce].idhcfg);	/* convert */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],		/* display */
+		idbox[n][6], idbox[n][7] + CFG_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_icnf() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_icnf(n, k)
+short n;
+register short  k;
+{
+	register short ec, c;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';		/* enter new data in buffer */
+	ebuf[2] = '\0';			/* make sure string is terminated */
+
+	dspbuf[0] = k + '0';		/* setup for display */
+	dspbuf[1] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	/* display the new data */
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6], stccol, dspbuf, 14);
+
+	advicur();			/* advance cursor */
+
+	return(SUCCESS);
+}
+
Index: ram/etidin.c
===================================================================
--- ram/etidin.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etidin.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,219 @@
+/*
+   =============================================================================
+	etidin.c -- MIDAS instrument editor - instrument number field handlers
+	Version 28 -- 1988-09-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#define	DIN_OFF		14
+
+extern	unsigned	*instob;
+
+extern	short	vtcrow, vtccol, stccol, curinst, curvce, idcfsw, idintmp;
+extern	short	editsw, curfunc, submenu;
+
+extern	short	idbox[][8];
+extern	short	instmod[];
+extern	short	vce2grp[];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	idefs[];
+extern	struct	instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_idin() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_idin(n)
+short n;
+{
+	sprintf(ebuf, "%02d", curinst);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+
+/*
+   =============================================================================
+	ef_idin() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_idin(n)
+short n;
+{
+	register short i, tmpval, j;
+	register struct instdef *ip;
+
+	if (idcfsw) {		/* 'E' with menu up */
+
+		if (vtcrow EQ 22) {		/* fetch or escape */
+
+			if (vtccol LT 35) {
+
+				newinst(idintmp);
+				execins(curvce, curinst, 1);
+
+				if (NOT editsw) {
+
+					if ((i = vce2grp[curvce]) > 0) {
+
+						for (j =0; j < 12; j++)
+							if (vce2grp[j] EQ i)
+								execins(j, curinst, 1);
+					}
+				}
+			}
+
+			objclr(TTCPRI);
+			idvlblc();
+			idcfsw = FALSE;
+			submenu = FALSE;
+
+			if (vtccol LT 35) {
+
+				allwins();
+
+			} else {
+
+				dswin(22);
+				dswin(19);
+			}
+/* 
+
+*/	
+		} else if (vtcrow EQ 23) {	/* copy to library */
+
+			if (idintmp) {
+
+				memcpyw(&idefs[idintmp], &vbufs[curvce],
+					(sizeof (struct instdef) / 2));
+
+				curinst = idintmp;
+				instmod[curvce] = FALSE;
+			}
+
+			objclr(TTCPRI);
+			idvlblc();
+			idcfsw = FALSE;
+			submenu = FALSE;
+			dswin(22);
+			dswin(19);
+
+			if (idintmp EQ 0)
+				return(FAILURE);
+
+		} else
+			return(FAILURE);
+
+		return(SUCCESS);
+/* 
+
+*/
+	} else {		/* 'E' with menu not up */
+	
+		ebuf[2] = '\0';			/* terminate the string in ebuf */
+		ebflag = FALSE;
+
+		tmpval = 0;
+
+		for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+			tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+		if (tmpval GE NINST)		/* check the range */
+			return(FAILURE);
+
+		idintmp = tmpval;		/* save selected value */
+		idcpfch();			/* put up copy/fetch menu */
+		dswin(22);
+		SetPri(TTCURS, TTCPRI);
+		ttcpos(22, 17);
+		idcfsw = TRUE;
+		submenu = TRUE;
+		return(SUCCESS);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_idin() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_idin(n)
+short n;
+{
+	if (idcfsw)			/* don't display if copy/fetch is up */
+		return(FAILURE);
+
+	/* convert to ASCII */
+
+	sprintf(dspbuf, "%02d", curinst);
+
+	vbank(0);			/* display the value */
+
+	vcputsv(instob, 64, (instmod[curvce] ? ID_CHGD : idbox[n][4]),
+		idbox[n][5], idbox[n][6], idbox[n][7] + DIN_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_idin() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_idin(n, k)
+short n;
+register short  k;
+{
+	register short ec, c;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6], stccol, dspbuf, 14);
+
+	advicur();
+
+	return(SUCCESS);
+}
+
Index: ram/etimlt.c
===================================================================
--- ram/etimlt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etimlt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,356 @@
+/*
+   =============================================================================
+	etimlt.c -- instrument editor - global source / multiplier field
+	Version 14 -- 1988-09-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "smdefs.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	short	advicur(), dec2fr(), dswin(), idvlbld(), ttcpos();
+
+extern	char	*fr2dec();
+
+extern	unsigned	*instob;
+
+extern	short	stcrow, stccol, curvce, curfunc, idsrcsw;
+extern	short	vtcrow, vtccol, submenu;
+
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	char	*srctbl[];
+
+extern	struct	instpnt	*pntptr;
+
+extern	struct	instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsimlt() -- decode a source / multiplier pair for display
+   =============================================================================
+*/
+
+char *
+dsimlt(buf, src, mltval)
+char *buf;
+short src;
+register short mltval;
+{
+	char mltstr[5], mlttmp[5];
+
+	fr2dec(mltval, mlttmp);		/* convert to ASCII from binary */
+
+	mltstr[0] = mlttmp[3];		/* sign */
+
+	if (mlttmp[0] EQ '0')		/* 1st digit & decimal point */
+		mltstr[1] = '.';
+	else
+		mltstr[1] = SP_1P;
+
+	mltstr[2] = mlttmp[1];		/* 2nd digit */
+	mltstr[3] = mlttmp[2];		/* 3rd digit */
+	mltstr[4] = '\0';		/* terminate the string */
+
+	sprintf(buf, "%7.7s %s", srctbl[src], mltstr);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("dsimlt($%08.8lX, %d, $%04.4X):  [%s]\n",
+			buf, src, mltval, buf);
+#endif
+
+	return(buf);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_imlt() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_imlt(n)
+short n;
+{
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+
+	ip = &vbufs[curvce];
+	fp = &ip->idhfnc[curfunc];
+
+	ebuf[0] = '0' + fp->idfsrc;
+	fr2dec(fp->idfmlt, &ebuf[1]);
+	ebuf[5] = '\0';
+
+	ebflag = TRUE;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("et_imlt():  ebuf=[%s]\n", ebuf);
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_imlt() -- parse (unload) the edit buffer  (called by 'E' key)
+   =============================================================================
+*/
+
+short
+ef_imlt(n)
+short n;
+{
+	register short i, tmpval, srctmp;
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+
+	ip = &vbufs[curvce];
+	fp = &ip->idhfnc[curfunc];
+
+	ebuf[5] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_imlt():  ebuf=[%s]\n", ebuf);
+#endif
+
+/* 
+
+*/
+	if (idsrcsw) {			/* entering the source */
+
+		idsrcsw = FALSE;
+		submenu = FALSE;
+
+		if (vtcrow EQ 22) {
+
+			/*  'PchW/HT', 'Pitch', 'Random', 'GPC/CV1' */
+
+			if (vtccol LT 24)
+				srctmp = SM_HTPW;
+			else if ((vtccol GT 24) AND (vtccol LT 28))
+				srctmp = SM_PTCH;
+			else if ((vtccol GT 28) AND (vtccol LT 32))
+				srctmp = SM_FREQ;
+			else if ((vtccol GT 32) AND (vtccol LT 40))
+				srctmp = SM_RAND;
+			else
+				srctmp = SM_CTL1;
+
+		} else if (vtcrow EQ 23) {
+
+			/* 'ModW/VT', 'Key Vel', 'Pedal 1' */
+
+			if (vtccol LT 24)
+				srctmp = SM_VTMW;
+			else if ((vtccol GT 24) AND (vtccol LT 32)) 
+				srctmp = SM_KVEL;
+			else if ((vtccol GT 32) AND (vtccol LT 40))
+				srctmp = SM_PED1;
+			else
+				srctmp = SM_NONE;
+
+		} else {	/* must be row 24 */
+
+			/* 'PchW/LP', 'Key Prs' */
+
+			if (vtccol LT 24)
+				srctmp = SM_LPBR;
+			else if ((vtccol GT 24) AND (vtccol LT 32))
+				srctmp = SM_KPRS;
+			else
+				srctmp = SM_NONE;
+		}
+
+		fp->idfsrc = srctmp;	/* set the source */
+		objclr(TTCPRI);		/* turn off the menu cursor */
+		idvlblc();		/* blank the menu area */
+		modinst();
+		dswin(22);		/* refresh the screen */
+/* 
+
+*/
+	} else if (stccol LT 8) {	/* selecting the source */
+
+		idsrcsw = TRUE;		/* set the select switch */
+		submenu = TRUE;
+		idvlbld();		/* load the menu area */
+		dswin(22);		/* refresh the screen */
+		SetPri(TTCURS, TTCPRI);	/* turn on the typewriter cursor */
+		ttcpos(22, 17);		/* position the typewriter cusor */
+
+	} else if (stccol GT 8) {	/* entering the multiplier */
+
+		tmpval = dec2fr(&ebuf[1]);
+
+		if (tmpval EQ 0xFFFF)
+			return(FAILURE);
+		else
+			fp->idfmlt = tmpval;
+
+		modinst();
+
+	} else
+		return(FAILURE);
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_imlt():  SUCCESS\n");
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_imlt() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_imlt(n)
+short n;
+{
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+
+	ip = &vbufs[curvce];
+	fp = &ip->idhfnc[curfunc];
+
+	dsimlt(dspbuf, fp->idfsrc, fp->idfmlt);
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],
+		idbox[n][6] + 1, idbox[n][7], dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_imlt() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_imlt(n, k)
+short n;
+register short  k;
+{
+	register short ec;
+
+	if (idsrcsw)			/* not if the source menu is up */
+		return(FAILURE);
+
+	if (stccol LT 9)		/* only in the multiplier field */
+		return(FAILURE);
+
+	ec = stccol - 9;		/* calculate edit buffer column */
+
+	switch (ec) {
+
+	case 0:		/* sign position */
+
+		if (k EQ 8) {		/* - */
+
+			ebuf[4] = '-';
+			dspbuf[0] = '-';	/* setup display buffer */
+
+		} else if (k EQ 9) {	/* + */
+
+			ebuf[4] = '+';
+			dspbuf[0] = '+';	/* setup display buffer */
+
+		} else
+			return(FAILURE);
+
+		break;
+
+	case 1:		/* 1st digit position  (0 or 1) */
+
+		if (k EQ 0) {		/* '0' -> '.' */
+
+			ebuf[1] = '0';
+			dspbuf[0] = '.';	/* setup display buffer */
+
+		} else if (k EQ 1) {	/* '1' -> '1.' */
+
+			ebuf[1] = '1';
+			dspbuf[0] = SP_1P;	/* setup display buffer */
+
+		} else
+			return(FAILURE);
+
+		break;
+
+	case 2:		/* 2nd digit position */
+	case 3:		/* 3rd digit position */
+
+		ebuf[ec] = k + '0';
+		dspbuf[0] = k + '0';		/* setup display buffer */
+		break;
+
+	default:
+		return(FAILURE);
+	}
+
+	ebuf[5] = '\0';
+	dspbuf[1] = '\0';
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("nd_imlt(): OK - k=%d, ec=%d, ebuf=[%s]\n", k, ec, ebuf);
+#endif
+
+	vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6] + 1, stccol, dspbuf, 14);
+
+	if (ec EQ 4)
+		return(SUCCESS);
+
+	advicur();
+
+	return(SUCCESS);
+}
Index: ram/etinst.c
===================================================================
--- ram/etinst.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etinst.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,166 @@
+/*
+   =============================================================================
+	etinst.c -- instrument field handlers
+	Version 23 -- 1988-07-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "instdsp.h"
+
+extern	unsigned	*obj8;
+
+extern	short	ctrsw;
+extern	short	recsw;
+extern	short	stccol;
+
+extern	short	grpmode[];
+extern	short	grpstat[];
+extern	short	ins2grp[];
+
+extern	struct	gdsel	*gdstbc[];
+
+/*
+   =============================================================================
+	et_inst() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_inst(n)
+short n;
+{
+	sprintf(ebuf, "%02.2d", ins2grp[n] & 0x00FF);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_inst() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_inst(n)
+short n;
+{
+	register short ival;
+	register struct s_entry *ep;
+
+	ebuf[2] = '\0';
+	ival = ((ebuf[0] - '0') * 10) + (ebuf[1] - '0');
+	ebflag = FALSE;
+
+	if (ival GE NINST)
+		return(FAILURE);
+
+	ins2grp[n] = ival | (ins2grp[n] & 0xFF00);
+	setv2gi(n);
+	setinst();
+
+	if (recsw AND grpstat[n] AND (2 EQ grpmode[n])) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_INST, n, -1))) {
+
+			ep->e_data2 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_INST;
+			ep->e_data1 = n;
+			ep->e_data2 = ival;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_INST);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_inst() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_inst(n)
+short n;
+{
+	char	buf[4];
+
+	sprintf(buf, "%02.2d", ins2grp[n] & 0x00FF);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 2, 7+(n*5), buf, SDW11ATR);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ds_inst() -- display all instrument to group assignments
+   =============================================================================
+*/
+
+ds_inst()
+{
+	register short i;
+
+	for (i = 0; i < 12; i++)
+		rd_inst(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_inst() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_inst(n, k)
+register short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;
+	ebuf[ec]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 2, stccol, k + '0', SDW11DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etioas.c
===================================================================
--- ram/etioas.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etioas.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,559 @@
+/*
+   =============================================================================
+	etioas.c -- line 17 field handlers  (I/O Assignment thru Interpolate)
+	Version 12 -- 1988-08-22 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "stddefs.h"
+#include "score.h"
+#include "scfns.h"
+#include "slice.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+extern	unsigned	fromfpu(), tofpu();
+
+extern	unsigned	*obj8;
+extern	unsigned	curintp;
+
+extern	short	ctrsw;
+extern	short	curasg;
+extern	short	curtun;
+extern	short	tmpoval;
+extern	short	recsw;
+extern	short	stccol;
+
+extern	char	dspbuf[];
+
+extern	struct	gdsel	*gdstbc[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Assignment table field handlers
+   =============================================================================
+*/
+
+/*
+   =============================================================================
+	et_ioas() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_ioas(n)
+short n;
+{
+	sprintf(ebuf, "%02.2d", curasg);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+/*
+   =============================================================================
+	ef_ioas() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_ioas(n)
+short n;
+{
+	register short ival;
+	register struct s_entry *ep;
+
+	ebuf[2] = '\0';
+	ival = ((ebuf[0] - '0') * 10) + (ebuf[1] - '0');
+
+	ebflag = FALSE;
+
+	if (ival GE NASGS)
+		return(FAILURE);
+
+	getasg(curasg = ival);
+	mpcupd();
+
+	if (recsw) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_ASGN, -1, -1))) {
+
+			ep->e_data1 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_ASGN;
+			ep->e_data1 = ival;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_ASGN);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ioas() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_ioas(n)
+short n;
+{
+	sprintf(dspbuf, "%02.2d", curasg);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 1, 11, dspbuf, SDW04ATR);
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_ioas() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_ioas(n, k)
+short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;
+	ebuf[ec]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 1, stccol, k + '0', SDW04DEA);
+	advscur();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Tuning field handlers
+   =============================================================================
+*/
+
+/*
+   =============================================================================
+	et_tune() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_tune(n)
+short n;
+{
+	ebuf[0] = '0' + curtun;
+	ebuf[1] = '\0';
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_tune() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_tune(n)
+short n;
+{
+	register short ival;
+	register struct s_entry *ep;
+
+	ebuf[1] = '\0';
+	ival = ebuf[0] - '0';
+	ebflag = FALSE;
+	gettun(ival);
+
+	if (recsw) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_TUNE, -1, -1))) {
+
+			ep->e_data1 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type = EV_TUNE;
+			ep->e_data1 = ival;
+			ep->e_time = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_TUNE);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_tune() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_tune(n)
+short n;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 1, 19, curtun + '0', SDW05ATR);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_tune() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_tune(n, k)
+short n, k;
+{
+	register short ec;
+
+	ebuf[0]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 1, stccol, k + '0', SDW05DEA);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Tempo field handlers
+   =============================================================================
+*/
+
+/*
+   =============================================================================
+	et_tmpo() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_tmpo(n)
+short n;
+{
+	sprintf(ebuf, "%03.3d", tmpoval);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_tmpo() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_tmpo(n)
+short n;
+{
+	register short ival;
+	register struct s_entry *ep;
+
+	ebuf[3] = '\0';
+	ival = ((ebuf[0] - '0') * 100) + ((ebuf[1] - '0') * 10)
+	       + (ebuf[2] - '0');
+
+	ebflag = FALSE;
+
+	if ((ival GT 240) OR (ival LT 4))
+		return(FAILURE);
+
+	settmpo(ival);
+
+	if (recsw) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_TMPO, -1, -1))) {
+
+			ep->e_data1 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_TMPO;
+			ep->e_data1 = ival;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_TMPO);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_tmpo() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_tmpo(n)
+short n;
+{
+	sprintf(dspbuf, "%03.3d", tmpoval);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 1, 27, dspbuf, SDW06ATR);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_tmpo() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_tmpo(n, k)
+register short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;
+	ebuf[ec]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 1, stccol, k + '0', SDW06DEA);
+	advscur();
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Interpolate field handlers
+   =============================================================================
+*/
+
+/*
+   =============================================================================
+	et_intp() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_intp(n)
+short n;
+{
+	register short th, tl;
+	register long tt, sc, sf;
+
+	sc = 1000L;
+	sf = 100L;
+	tt = fromfpu(curintp);
+	th = tt / sc;
+	tl = (tt - (th * sc)) / sf;
+
+	sprintf(ebuf, "%02d.%d", th, tl);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_intp() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_intp(n)
+short n;
+{
+	register short i;
+	register unsigned tmpval;
+	register struct s_entry *ep;
+
+	ebuf[2] = '.';			/* add implied decimal point */
+	ebuf[4] = '\0';			/* terminate the string in ebuf */
+	ebflag  = FALSE;
+	tmpval  = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	tmpval = ((tmpval * 10) + (ebuf[3] - '0')) * 100;
+
+	if (tmpval > (unsigned)64900)
+		return(FAILURE);
+
+	if (tmpval EQ 0)
+		tmpval = 1;
+
+	curintp = tofpu(tmpval);
+
+	if (recsw) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_INTP, -1, -1))) {
+
+			ep->e_data1 = (curintp >> 8);
+			ep->e_data2 = 0x00FF & curintp;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE3))) {
+
+			ep->e_type  = EV_INTP;
+			ep->e_time  = t_cur;
+			ep->e_data1 = (curintp >> 8);
+			ep->e_data2 = 0x00FF & curintp;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_INTP);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_intp() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_intp(n)
+short n;
+{
+	register short th, tl;
+	register long tt, sc, sf;
+
+	sc = 1000L;
+	sf = 100L;
+	tt = fromfpu(curintp);
+	th = tt / sc;
+	tl = (tt - (th * sc)) / sf;
+
+	sprintf(dspbuf, "%02d.%d", th, tl);	/* convert to ASCII */
+
+	vbank(0);			/* display the value */
+
+	vputs(obj8, 1, 35, dspbuf, SDW07ATR);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_intp() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_intp(n, k)
+short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	if (ec EQ 2)
+		return(FAILURE);
+
+	if ((ec EQ 0) AND (k > 6))
+		return(FAILURE);
+
+	if ((ec EQ 1) AND (ebuf[0] EQ '6') AND (k > 4))
+		return(FAILURE);
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '.';
+	ebuf[4] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+
+	vputs(obj8, 1, stccol, dspbuf, SDW07DEA);
+
+	advscur();
+
+	if (stccol EQ 37)
+		advscur();
+
+	return(SUCCESS);
+}
Index: ram/etiosc.c
===================================================================
--- ram/etiosc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etiosc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,899 @@
+/*
+   =============================================================================
+	etiosc.c -- MIDAS instrument editor -- oscillator field handlers
+	Version 31 -- 1988-10-27 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+/* functions defined elsewhere */
+
+extern	int	advicur(), dosync();
+
+extern	char	*strcpy();
+
+/* variables defined elsewhere */
+
+extern	short	stcrow, stccol, curvce;
+
+extern	short	idbox[][8];
+
+extern	unsigned	*instob;
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+extern	short	cents, bform;
+
+/* 
+
+*/
+
+/* initialized variables */
+
+/*		    C  C# D  D# E  F  F# G  G# A  A# B	*/
+short	notes[]  = {2, 2, 3, 3, 4, 5, 5, 6, 6, 0, 0, 1};
+
+/*		        A     B     C     D     E     F     G	*/
+short	pitches[] = { 900, 1100,    0,  200,  400,  500,  700};
+
+#include "ratio.h"	/* short ratio[]; */
+
+/*		    C  C# D  D# E  F  F# G  G# A  A# B	*/
+short	sharps[] = {7, 9, 7, 9, 7, 7, 9, 7, 9, 7, 9, 7};
+
+short	shrpflt[] = {  0, -100,    100};
+
+char	sfdsp[]   = {' ', D_FLAT,  D_SHARP};
+
+static	char	intstr[] = "+0000";
+static	char	ratstr[] = "1/1";
+static	char	frqstr[] = "00.0";
+static	char	pchstr[] = "0C 00";
+
+short	ndvals[10] = {0, 0, 1200, 1902, 2400, 2786, 3102, 3369, 3600, 3804};
+
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	int2rat() -- convert interval to ratio
+   =============================================================================
+*/
+
+int2rat(rat)
+short rat;
+{
+	register short den, inum, num;
+
+	ebuf[0] = '1';
+	ebuf[1] = '/';
+	ebuf[2] = '1';
+	ebuf[3] = '\0';
+
+	for (num = 1; num < 10; num++) {
+
+		inum = 10 * num;
+
+		for (den = 1; den < 10; den++) {
+
+			if (rat EQ ratio[inum + den]) {
+
+				ebuf[0] = num + '0';
+				ebuf[2] = den + '0';
+				return;
+			}
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cnvc2p() -- convert cents to pitch
+   =============================================================================
+*/
+
+cnvc2p(buf, cv)
+char *buf;
+short cv;
+{
+	short	rem, tmp;
+
+	cv -= 160;
+	buf[0] = cv / 1200;
+	rem = cv - (buf[0] * 1200);
+	tmp = rem / 100;
+	rem -= (tmp * 100);
+	buf[1] = notes[tmp];
+	buf[2] = sharps[tmp];
+	buf[3] = rem / 10;
+	buf[4] = rem - (buf[3] * 10);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cnvp2c() -- convert pitch to cents
+
+	input in edit buffer:
+
+		ebuf[0] = octave		0..9
+		ebuf[1] = note			A..G  (0..6)
+		ebuf[2] = type			natural, flat, sharp  (7..9)
+		ebuf[3] = ms byte of offset	0..9
+		ebuf[4] = ls byte of offset	0..9
+
+	output in cents
+   =============================================================================
+*/
+
+short
+cnvp2c()
+{
+	if (ebuf[0] EQ 9)		/* high limit is C9 00 */
+		if (ebuf[1] GT 2)
+			return(FAILURE);
+		else if (ebuf[1] EQ 2)
+			if (ebuf[2] NE 7)
+				return(FAILURE);
+			else if (ebuf[3] OR ebuf[4])
+				return(FAILURE);
+
+	cents = (ebuf[0] * 1200) + pitches[ebuf[1]] + shrpflt[ebuf[2] - 7]
+		+ (ebuf[3] * 10) + ebuf[4] + 160;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_iosc() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_iosc(nn)
+short nn;
+{
+	register struct instdef *ip;
+	register short val, ctl, fh, fl, v;
+
+	v = (nn >> 8) & 0x03;
+	ip = &vbufs[curvce];
+
+	switch (v) {
+
+	case 0:
+
+		val = ip->idhos1v;
+		ctl = ip->idhos1c;
+		break;
+
+	case 1:
+
+		val = ip->idhos2v;
+		ctl = ip->idhos2c;
+		break;
+
+	case 2:
+
+		val = ip->idhos3v;
+		ctl = ip->idhos3c;
+		break;
+
+	case 3:
+
+		val = ip->idhos4v;
+		ctl = ip->idhos4c;
+		break;
+	}
+/* 
+
+*/
+	bform = ctl & OC_MOD;
+
+	switch (bform) {
+
+	case OC_INT:		/* interval */
+
+		sprintf(ebuf, "%04d%c", ((val < 0 ? -val : val) >> 1),
+			(val < 0 ? '-' : '+'));
+
+		ebflag = TRUE;
+		return(SUCCESS);
+
+	case OC_RAT:		/* ratio */
+
+		int2rat(val >> 1);
+		ebflag = TRUE;
+		return(SUCCESS);
+
+	case OC_FRQ:		/* frequency */
+
+		fh = (val >> 1) / 10;
+		fl = (val >> 1) - (fh * 10);
+
+		sprintf(ebuf, "%02d.%d", fh, fl);
+		ebflag = TRUE;
+		return(SUCCESS);
+
+	case OC_PCH:
+
+		cnvc2p(ebuf, (val >> 1));
+		ebflag = TRUE;
+		return(SUCCESS);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setoval() -- set oscillator mode and pitch/ratio variables
+   =============================================================================
+*/
+
+setoval(ip, v, val)
+register struct instdef *ip;
+register short v, val;
+{
+	switch (v) {
+
+	case 0:
+
+		ip->idhos1v = val << 1;
+		ip->idhos1c = (ip->idhos1c & ~OC_MOD) | bform;
+		break;
+
+	case 1:
+
+		ip->idhos2v = val << 1;
+		ip->idhos2c = (ip->idhos2c & ~OC_MOD) | bform;
+		break;
+
+	case 2:
+
+		ip->idhos3v = val << 1;
+		ip->idhos3c = (ip->idhos3c & ~OC_MOD) | bform;
+		break;
+
+	case 3:
+
+		ip->idhos4v = val << 1;
+		ip->idhos4c = (ip->idhos4c & ~OC_MOD) | bform;
+		break;
+	}
+
+	ip->idhfnc[v].idftmd = (ip->idhfnc[v].idftmd & ~I_NRATIO)
+		| ((bform & 2) ? I_NRATIO : 0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_iosc() -- unload (parse) edit buffer
+   =============================================================================
+*/
+
+short
+ef_iosc(nn)
+short nn;
+{
+	register struct instdef *ip;
+	register short v, i, tmp;
+
+	v = (nn >> 8) & 3;
+	ip = &vbufs[curvce];
+	ebflag = FALSE;
+
+	switch (bform) {
+
+	case OC_INT:		/* interval */
+
+		tmp = 0;
+
+		for (i = 0; i < 4; i++)
+			tmp = (tmp * 10) + (ebuf[i] - '0');
+
+		if (ebuf[4] EQ '-')
+			tmp = -tmp;
+
+		setoval(ip, v, tmp);
+		modinst();
+		return(SUCCESS);
+
+	case OC_RAT:		/* ratio */
+
+		tmp = ndvals[ebuf[0] - '0'] - ndvals[ebuf[2] - '0'];
+
+		setoval(ip, v, tmp);
+		modinst();
+		return(SUCCESS);
+/* 
+
+*/
+	case OC_FRQ:		/* frequency */
+
+		tmp = 0;
+
+		for (i = 0; i < 2; i++)
+			tmp = (tmp * 10) + ebuf[i] - '0';
+
+		tmp = (tmp * 10) + ebuf[3] - '0';
+
+		if (tmp GT 159)
+			return(FAILURE);
+
+		setoval(ip, v, tmp);
+		modinst();
+		return(SUCCESS);
+
+	case OC_PCH:		/* pitch */
+
+		if (cnvp2c() EQ FAILURE)
+			return(FAILURE);
+
+		setoval(ip, v, cents);
+		modinst();
+		return(SUCCESS);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_iosc() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_iosc(nn)
+short nn;
+{
+	register struct instdef *ip;
+	register short val, ctl, fh, fl, v;
+	short n;
+	char ocs;
+
+	v = (nn >> 8) & 0x03;
+	n = nn & 0xFF;
+	ip = &vbufs[curvce];
+
+	switch (v) {
+
+	case 0:
+
+		val = ip->idhos1v;
+		ctl = ip->idhos1c;
+		break;
+
+	case 1:
+
+		val = ip->idhos2v;
+		ctl = ip->idhos2c;
+		break;
+
+	case 2:
+
+		val = ip->idhos3v;
+		ctl = ip->idhos3c;
+		break;
+
+	case 3:
+
+		val = ip->idhos4v;
+		ctl = ip->idhos4c;
+		break;
+	}
+/* 
+
+*/
+	bform = ctl & OC_MOD;
+	ocs = ((v EQ 3) ? ' ' : (ctl & OC_SYN ? 'S' : 's'));
+
+	switch (bform) {
+
+	case OC_INT:		/* interval */
+
+		sprintf(dspbuf, "Int %c%04d %c",
+			(val < 0 ? '-' : '+'),
+			((val < 0 ? -val : val) >> 1),
+			ocs);
+		break;
+
+	case OC_RAT:		/* ratio */
+
+		int2rat(val >> 1);
+		sprintf(dspbuf, "Rat %c/%c   %c", ebuf[0], ebuf[2], ocs);
+		break;
+
+	case OC_FRQ:		/* frequency */
+
+		fh = (val >> 1) / 10;
+		fl = (val >> 1) - (fh * 10);
+
+		sprintf(dspbuf, "Frq %02d.%d  %c", fh, fl, ocs);
+		break;
+
+	case OC_PCH:
+
+		strcpy(dspbuf, "Pch ");
+		cnvc2p(&dspbuf[4], (val >> 1));
+		dspbuf[4] += '0';
+		dspbuf[5] += 'A';
+		dspbuf[6] = sfdsp[dspbuf[6] - 7];
+		dspbuf[7] += '0';
+		dspbuf[8] += '0';
+		dspbuf[9] = ' ';
+		dspbuf[10] = ocs;
+		dspbuf[11] = '\0';
+		break;
+	}
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5], 18 + v , 36, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setoscb() -- change oscillator data entry buffer format
+   =============================================================================
+*/
+
+setoscb(n, v)
+short n, v;
+{
+	register struct instdef *ip;
+	register short bfm, ctl, val;
+	register char ocs;
+
+	ip = &vbufs[curvce];
+
+	switch (v) {
+
+	case 0:
+
+		ctl = ip->idhos1c;
+		val = ip->idhos1v;
+		break;
+
+	case 1:
+
+		ctl = ip->idhos2c;
+		val = ip->idhos2v;
+		break;
+
+	case 2:
+
+		ctl = ip->idhos3c;
+		val = ip->idhos3v;
+		break;
+
+	case 3:
+
+		ctl = ip->idhos4c;
+		val = ip->idhos4v;
+		break;
+	}
+
+	ocs = ((v EQ 3) ? ' ' : (ctl & OC_SYN ? 'S' : 's'));
+
+	bfm = ctl & OC_MOD;
+/* 
+
+*/
+	switch (bform) {
+
+	case OC_INT:		/* interval */
+
+		if ((bfm EQ OC_RAT) OR (bfm EQ OC_INT)) {
+
+			sprintf(ebuf, "%04d%c", ((val < 0 ? -val : val) >> 1),
+				(val < 0 ? '-' : '+'));
+
+			sprintf(dspbuf, "Int %c%04d %c",
+				(val < 0 ? '-' : '+'),
+				((val < 0 ? -val : val) >> 1),
+				ocs);
+
+		} else {
+
+			strcpy(ebuf, "0000+");
+			sprintf(dspbuf, "Int %s %c", intstr, ocs);
+		}
+
+		break;
+
+	case OC_RAT:		/* ratio */
+
+		if (bfm EQ OC_RAT) {
+
+			int2rat(val >> 1);
+
+			sprintf(dspbuf, "Rat %c/%c   %c",
+				ebuf[0], ebuf[2], ocs);
+
+		} else {
+
+			strcpy(ebuf, ratstr);
+			sprintf(dspbuf, "Rat %s   %c", ratstr, ocs);
+		}
+
+		break;
+/* 
+
+*/
+	case OC_FRQ:		/* frequency */
+
+		strcpy(ebuf, frqstr);
+		sprintf(dspbuf, "Frq %s  %c", frqstr, ocs);
+		break;
+
+	case OC_PCH:		/* pitch */
+
+		ebuf[0] = 0;	/* 0 */
+		ebuf[1] = 2;	/* C */
+		ebuf[2] = 7;	/*   */
+		ebuf[3] = 0;	/* 0 */
+		ebuf[4] = 0;	/* 0 */
+
+		sprintf(dspbuf, "Pch %s %c", pchstr, ocs);
+		break;
+	}
+
+	ebflag = TRUE;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		stcrow, 36, dspbuf, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setosyn() -- set oscillator sync mode
+   =============================================================================
+*/
+
+setosyn(n, v, t)
+short n, v, t;
+{
+	register struct instdef *ip;
+	register char *sc;
+
+	ip = &vbufs[curvce];
+
+	if (stcrow EQ 21)
+		return;
+
+	sc = t ? "S" : "s";
+
+	switch (v) {
+
+	case 0:
+
+		ip->idhos1c = (ip->idhos1c & ~OC_SYN) | (t ? OC_SYN : 0);
+		break;
+
+	case 1:
+
+		ip->idhos2c = (ip->idhos2c & ~OC_SYN) | (t ? OC_SYN : 0);
+		break;
+
+	case 2:
+
+		ip->idhos3c = (ip->idhos3c & ~OC_SYN) | (t ? OC_SYN : 0);
+		break;
+
+	case 3:
+
+		return;
+	}
+
+	dosync(curvce);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5], stcrow, stccol, sc, 14);
+	modinst();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_iosc() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_iosc(nn, k)
+short nn, k;
+{
+	register short v, n;
+
+	n = nn & 0xFF;
+	v = (nn >> 8) & 3;
+
+	if (stccol LT 39) {		/* mode */
+
+		if (k EQ 8) {		/* - */
+
+			if (--bform LT 0)
+				bform = 3;
+
+			setoscb(n, v);
+			return(SUCCESS);
+
+		} else if (k EQ 9) {	/* + */
+
+			if (++bform GT 3)
+				bform = 0;
+
+			setoscb(n, v);
+			return(SUCCESS);
+
+		} else
+			return(FAILURE);
+/* 
+
+*/
+	} else if (stccol EQ 46) {	/* sync */
+
+		if (stcrow EQ 21)
+			return(FAILURE);
+
+		if (k EQ 8) {		/* - */
+
+			setosyn(n, v, 0);	/* off */
+			return(SUCCESS);
+
+		} else if (k EQ 9) {	/* + */
+
+			setosyn(n, v, 1);	/* on */
+			return(SUCCESS);
+
+		} else
+			return(FAILURE);
+
+/* 
+
+*/
+	} else if ((stccol GE 40) AND (stccol LE 44)) {		/* value */
+
+		switch (bform) {
+
+		case OC_INT:		/* interval */
+
+			if (stccol EQ 40) {	/* sign */
+
+				if (k EQ 8) {		/* - */
+
+					k = '-';
+					ebuf[4] = '-';
+
+				} else if (k EQ 9) {	/* + */
+
+					k = '+';
+					ebuf[4] = '+';
+
+				} else
+					return(FAILURE);
+
+			} else {
+
+				ebuf[stccol - 41] = k + '0';
+			}
+
+			dspbuf[0] = (k > 9) ? k : (k + '0');
+			dspbuf[1] = '\0';
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+				stcrow, stccol, dspbuf, 14);
+
+			if (stccol EQ 44)
+				return(SUCCESS);
+
+			advicur();
+			return(SUCCESS);
+/* 
+
+*/
+		case OC_RAT:		/* ratio */
+
+			if (stccol EQ 40) {
+
+				if (k) {
+
+					ebuf[0] = dspbuf[0] = k + '0';
+					dspbuf[1] = '\0';
+
+					if (v_regs[5] & 0x0180)
+						vbank(0);
+
+					vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+						stcrow, stccol, dspbuf, 14);
+
+					advicur();
+					advicur();
+
+					return(SUCCESS);
+
+				} else
+					return(FAILURE);
+
+			} else if (stccol EQ 42) {
+
+				if (k) {
+
+					ebuf[2] = dspbuf[0] = k + '0';
+					dspbuf[1] = '\0';
+
+					if (v_regs[5] & 0x0180)
+						vbank(0);
+
+					vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+						stcrow, stccol, dspbuf, 14);
+
+					return(SUCCESS);
+
+				} else
+					return(FAILURE);
+			} else {
+
+				return(FAILURE);
+			}
+/* 
+
+*/
+		case OC_FRQ:		/* frequency */
+
+			if (stccol EQ 42)
+				return(FAILURE);
+
+			ebuf[stccol - 40] = k + '0';
+			dspbuf[0] = k + '0';
+			dspbuf[1] = '\0';
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+				stcrow, stccol, dspbuf, 14);
+
+			if (stccol EQ 44)
+				return(SUCCESS);
+
+			advicur();
+
+			if (stccol EQ 42)
+				advicur();
+
+			return(SUCCESS);
+/* 
+
+*/
+		case OC_PCH:		/* pitch */
+
+			switch (stccol) {
+
+			case 40:
+
+				ebuf[0] = k;
+				dspbuf[0] = k + '0';
+				break;
+
+			case 41:
+
+				if (k GT 6)
+					return(FAILURE);
+
+				ebuf[1] = k;
+				dspbuf[0] = k + 'A';
+				break;
+
+			case 42:
+
+				if (k EQ 7) {		/* blank */
+
+					ebuf[2] = k;
+					dspbuf[0] = sfdsp[0];
+					break;
+
+				} else if (k EQ 8) {	/* flat */
+
+					ebuf[2] = k;
+					dspbuf[0] = sfdsp[1];
+					break;
+
+				} else if (k EQ 9) {	/* sharp */
+
+					ebuf[2] = k;
+					dspbuf[0] = sfdsp[2];
+					break;
+
+				} else
+					return(FAILURE);
+			case 43:
+			case 44:
+
+				ebuf[stccol - 40] = k;
+				dspbuf[0] = k + '0';
+				break;
+			}
+/* 
+
+*/
+
+			dspbuf[1] = '\0';
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+				stcrow, stccol, dspbuf, 14);
+
+			if (stccol EQ 44)
+				return(SUCCESS);
+
+			advicur();
+			return(SUCCESS);
+		}
+
+	} else {
+
+		return(FAILURE);
+	}
+}
Index: ram/etipnt.c
===================================================================
--- ram/etipnt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etipnt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,195 @@
+/*
+   =============================================================================
+	etipnt.c -- instrument editor - point number field handlers
+	Version 15 -- 1988-01-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	short	advicur(), pntsel(), showpt(), timeto(), setseg();
+
+extern	unsigned	*instob;
+
+extern	short	stccol, subj, curvce, curfunc, curpnt;
+
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+extern	struct	instpnt	*pntptr;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_ipnt() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_ipnt(n)
+short n;
+{
+	sprintf(ebuf, "%02d", subj);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_ipnt() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_ipnt(n)
+short n;
+{
+	register short i, tmpval, endpnt, basept;
+	register struct idfnhdr *fp;
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];		/* set instrument pointer */
+	fp = &ip->idhfnc[curfunc];	/* set function pointer */
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	basept = fp->idfpt1;
+	endpnt = fp->idfpt1 + fp->idfpif - 1;	/* calculate last point */
+#if DEBUGIT
+	printf("ef_ipnt():  subj=%d, basept=%d, tmpval=%d, endpnt=%d, idpif=%d\r\n",
+		subj, basept, tmpval, endpnt, fp->idfpif);
+#endif
+	if (tmpval GE fp->idfpif) {	/* see if we want a new point */
+
+		if (fp->idfpif EQ 100) {	/* can't do it if we're full */
+
+			showpt(1);
+			return(FAILURE);
+		}
+#if DEBUGIT
+	printf("ef_ipnt():  NEW POINT REQUESTED\r\n");
+#endif
+		if (FALSE EQ inspnt(ip, curfunc, endpnt)) {	/* try to add it */
+#if DEBUGIT
+	printf("ef_ipnt():  inspnt() returned FALSE -- no point allocated\r\n");
+#endif
+			showpt(1);
+			return(FAILURE);
+
+		} else {
+
+			subj = fp->idfpif - 1;	/* make it the current point */
+			pntsel();
+			memset(pntptr, 0, sizeof (struct instpnt));
+			pntptr->ipval = (pntptr - 1)->ipval;
+			setseg(subj, timeto(curfunc, subj - 1) + 1);
+			showpt(1);
+#if DEBUGIT
+	printf("ef_ipnt():  NEW POINT SELECTED  curpnt=%d, subj=%d, idpif=%d\r\n",
+		curpnt, subj, fp->idfpif);
+#endif
+			modinst();
+			return(SUCCESS);
+		}
+
+	} else {	/* old point requested */
+#if DEBUGIT
+	printf("ef_ipnt():  OLD POINT REQUESTED\r\n");
+#endif
+		if ((tmpval + basept) > endpnt)		/* check range */
+			return(FAILURE);
+
+		subj = tmpval;			/* make it current */
+		pntsel();
+		showpt(1);
+#if DEBUGIT
+	printf("ef_ipnt():  OLD POINT SELECTED  curpnt=%d, subj=%d\r\n",
+		curpnt, subj);
+#endif
+		return(SUCCESS);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ipnt() -- (re)display the point number
+   =============================================================================
+*/
+
+short
+rd_ipnt(n)
+short n;
+{
+	sprintf(dspbuf, "%02d", subj);	/* convert to ASCII */
+
+	vbank(0);			/* display the value */
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],
+		idbox[n][6] + 1, idbox[n][7], dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_ipnt() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_ipnt(n, k)
+short n;
+register short  k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6] + 1, stccol, dspbuf, 14);
+
+	advicur();
+
+	return(SUCCESS);
+}
Index: ram/etires.c
===================================================================
--- ram/etires.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etires.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,152 @@
+/*
+   =============================================================================
+	etires.c -- instrument editor - resonance field handlers
+	Version 2 -- 1988-05-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	unsigned	*instob;
+
+extern	short	stcrow, stccol, curvce, curfunc;
+
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+extern	struct	instpnt	*pntptr;
+
+short	rsntab[] = {		/* resonance table */
+
+	0,		/* 0 =  0.00 */
+	(110 << 5),	/* 1 =  1.10 */
+	(220 << 5),	/* 2 =  2.20 */
+	(330 << 5),	/* 3 =  3.30 */
+	(440 << 5),	/* 4 =  4.40 */
+	(550 << 5),	/* 5 =  5.50 */
+	(660 << 5),	/* 6 =  6.60 */
+	(770 << 5),	/* 7 =  7.70 */
+	(880 << 5),	/* 8 =  8.80 */
+	(1000 << 5)	/* 9 = 10.00 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_ires() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_ires(n)
+short n;
+{
+	if (curfunc NE 4)
+		return(FAILURE);
+
+	ebuf[0] = '0' + vbufs[curvce].idhfnc[4].idfprm;
+	ebuf[1] = '\0';
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_ires() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_ires(n)
+short n;
+{
+	register short tmpval;
+
+	if (curfunc NE 4)
+		return(FAILURE);
+
+	ebuf[1] = '\0';
+	ebflag = FALSE;
+	tmpval = ebuf[0] - '0';
+	vbufs[curvce].idhfnc[4].idfprm = tmpval;
+	sendval(curvce, 6, rsntab[tmpval]);
+	modinst();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ires() -- (re)display the point number
+   =============================================================================
+*/
+
+short
+rd_ires(n)
+short n;
+{
+	register struct idfnhdr *fp;
+
+	fp = &vbufs[curvce].idhfnc[4];
+
+	if (curfunc NE 4)
+		return(FAILURE);
+
+	dspbuf[0] = '0' + fp->idfprm;
+	dspbuf[1] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, ((fp->idftmd & I_TM_KEY) ? idbox[n][4] : ID_INST),
+		idbox[n][5], idbox[n][6] + 1, idbox[n][7] + 8, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_ires() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_ires(n, k)
+short n;
+register short  k;
+{
+	if (curfunc NE 4)
+		return(FAILURE);
+
+	dspbuf[0] = ebuf[0] = k + '0';
+	dspbuf[1] = ebuf[1] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5], stcrow, stccol, dspbuf, 14);
+	return(SUCCESS);
+}
Index: ram/etitim.c
===================================================================
--- ram/etitim.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etitim.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,200 @@
+/*
+   =============================================================================
+	etitim.c -- instrument editor - time field handlers
+	Version 14 -- 1987-12-09 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	short	advicur(), edfunc(), pntsel();
+
+extern	unsigned	*instob;
+
+extern	short	stccol, subj, curvce, curfunc, curpnt;
+extern	short	pecase, npts, temin, temax, pntsv;
+
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+extern	struct	instpnt	*pntptr;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_itim() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_itim(n)
+short n;
+{
+	register short th, tl;
+	register long tt, sc;
+
+	pntsel();		/* make sure edit limits are current */
+
+	sc = 1000L;
+	tt = timeto(curfunc, subj);
+	th = tt / sc;
+	tl = tt - (th * sc);
+
+	sprintf(ebuf, "%02d.%03d", th, tl);
+	ebflag = TRUE;
+#if DEBUGIT
+	printf("et_itim(): voice=%d, func=%d, pnt=%d, ebuf=[%s]\r\n",
+		curvce, curfunc, curpnt, ebuf);
+	printf("et_itim(): npts=%d, subj=%d, case=%d, min=%d, max=%d\r\n",
+		npts, subj, pecase, temin, temax);
+#endif
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_itim() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_itim(n)
+short n;
+{
+	register short i, endpnt, basept;
+	register unsigned tmpval;
+	register struct idfnhdr *fp;
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];		/* set instrument pointer */
+	fp = &ip->idhfnc[curfunc];	/* set function pointer */
+
+	ebuf[2] = '.';			/* add implied decimal point */
+	ebuf[6] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+#if DEBUGIT
+	printf("ef_itim():  voice=%d, func=%d, ebuf=[%s]\r\n",
+		curvce, curfunc, ebuf);
+#endif
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	for (i = 3; i < 6; i++)
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+#if DEBUGIT
+	printf("ef_itim(): subj=%d, case=%d, min=%d, val=%d, max=%d\r\n",
+		subj, pecase, temin, tmpval, temax);
+#endif
+	if (tmpval > (unsigned)temax)
+		return(FAILURE);
+
+	if (tmpval < (unsigned)temin)
+		return(FAILURE);
+
+	setseg(subj, tmpval);
+
+	if (pecase EQ 2)
+		setseg(subj + 1, temax);
+#if DEBUGIT
+	printf("ef_itim():  SUCCESS   time %d set at point %d <%d> = %d\r\n",
+		tmpval, subj, curpnt, timeto(curfunc, subj));
+#endif
+	modinst();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_itim() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_itim(n)
+short n;
+{
+	register short th, tl;
+	register long tt, sc;
+
+	sc = 1000L;
+	tt = timeto(curfunc, subj);
+	th = tt / sc;
+	tl = tt - (th * sc);
+
+	sprintf(dspbuf, "%02d.%03d", th, tl);	/* convert to ASCII */
+
+	vbank(0);			/* display the value */
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],
+		idbox[n][6] + 1, idbox[n][7], dspbuf, 14);
+
+	edfunc(curfunc);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_itim() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_itim(n, k)
+short n;
+register short  k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	if (ec EQ 2)
+		return(FAILURE);
+
+	ebuf[ec] = k + '0';
+	ebuf[2] = '.';
+	ebuf[6] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6] + 1, stccol, dspbuf, 14);
+
+	advicur();
+
+	if (stccol EQ (idbox[n][7] + 2))
+		advicur();
+
+	return(SUCCESS);
+}
Index: ram/etival.c
===================================================================
--- ram/etival.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etival.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,339 @@
+/*
+   =============================================================================
+	etival.c -- MIDAS-VI -- instrument editor - value field handlers
+	Version 16 -- 1988-09-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "smdefs.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	short	advicur(), edfunc(), dec2fr();
+
+extern	char	*dsimlt(), *fr2dec();
+
+extern	unsigned	*instob;
+
+extern	short	stccol, curfunc;
+
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instpnt	*pntptr;
+
+extern	short	vtcrow, vtccol, idsrcsw, submenu;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_ival() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_ival(n)
+short n;
+{
+	register short vv, vh, vl;
+
+	vv = pntptr->ipval >> 5;
+	vh = vv / 100;
+	vl = vv - (vh * 100);
+
+	sprintf(ebuf, "%02d.%02d", vh, vl);
+	ebuf[5] = '0' + pntptr->ipvsrc;
+	fr2dec(pntptr->ipvmlt, &ebuf[6]);
+	ebuf[10] = '\0';
+	ebflag = TRUE;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("et_ival():  ebuf=[%s]\n", ebuf);
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_ival() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_ival(n)
+short n;
+{
+	register short i, tmpval, srctmp;
+
+	ebuf[2] = '.';
+	ebuf[10] = '\0';		/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_ival():  ebuf=[%s]\n", ebuf);
+#endif
+
+/* 
+
+*/
+	if (idsrcsw) {			/* entering the source */
+
+		idsrcsw = FALSE;
+		submenu = FALSE;
+
+		if (vtcrow EQ 22) {
+
+			/*  'PchW/HT", 'Pch/Frq', 'Random', 'Ctl V1' */
+
+			if (vtccol LT 24)
+				srctmp = SM_HTPW;
+			else if ((vtccol GT 24) AND (vtccol LT 28))
+				srctmp = SM_PTCH;
+			else if ((vtccol GT 28) AND (vtccol LT 32))
+				srctmp = SM_FREQ;
+			else if ((vtccol GT 32) AND (vtccol LT 40))
+				srctmp = SM_RAND;
+			else
+				srctmp = SM_CTL1;
+
+		} else if (vtcrow EQ 23) {
+
+			/* 'ModW/VT', 'Key Vel', 'Pedal 1' */
+
+			if (vtccol LT 24)
+				srctmp = SM_VTMW;
+			else if ((vtccol GT 24) AND (vtccol LT 32)) 
+				srctmp = SM_KVEL;
+			else if ((vtccol GT 32) AND (vtccol LT 40))
+				srctmp = SM_PED1;
+			else
+				srctmp = SM_NONE;
+
+		} else {	/* must be row 24 */
+
+			/* 'Brth/LP', 'Key Prs' */
+
+			if (vtccol LT 24)
+				srctmp = SM_LPBR;
+			else if ((vtccol GT 24) AND (vtccol LT 32))
+				srctmp = SM_KPRS;
+			else
+				srctmp = SM_NONE;
+		}
+
+		pntptr->ipvsrc = srctmp;	/* set the source */
+		objclr(TTCPRI);			/* turn off the menu cursor */
+		idvlblc();			/* blank the menu area */
+		dswin(22);			/* refresh the screen */
+		modinst();
+/* 
+
+*/
+	} else if (stccol LT 32) {		/* entering value */
+
+		tmpval = 0;
+
+		for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+			tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+		for (i = 3; i < 5; i++)		/* convert from ASCII to binary */
+			tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+		if (tmpval GT 1000) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ef_ival():  FAILURE - val - ebuf=[%s]\n", ebuf);
+#endif
+
+			return(FAILURE);
+		}
+
+		pntptr->ipval = tmpval << 5;
+		edfunc(curfunc);
+		modinst();
+
+	} else if ((stccol GE 33) AND (stccol LE 39)) {	/* selecting the source */
+
+		idsrcsw = TRUE;		/* set the select switch */
+		submenu = TRUE;
+		idvlbld();		/* load the menu area */
+		dswin(22);		/* refresh the screen */
+		SetPri(TTCURS, TTCPRI);	/* turn on the typewriter cursor */
+		ttcpos(22, 17);		/* position the typewriter cusor */
+
+	} else if ((stccol GE 41) AND (stccol LE 44)) {	/* entering the multiplier */
+
+		tmpval = dec2fr(&ebuf[6]);
+
+		if (tmpval EQ 0xFFFF) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ef_ival():  FAILURE - mlt - ebuf=[%s]\n", ebuf);
+#endif
+
+			return(FAILURE);
+
+		} else {
+
+			pntptr->ipvmlt = tmpval;
+			modinst();
+		}
+
+	} else
+		return(FAILURE);
+
+#if DEBUGIT
+	if (debugsw)
+		printf("ef_ival():  SUCCESS\n");
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ival() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_ival(n)
+short n;
+{
+	register short vv, vh, vl;
+
+	vv = pntptr->ipval >> 5;
+	vh = vv / 100;
+	vl = vv - (vh * 100);
+
+	sprintf(dspbuf, "%02d.%02d ", vh, vl);
+	dsimlt(&dspbuf[6], pntptr->ipvsrc, pntptr->ipvmlt);
+
+	vbank(0);			/* display the value */
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],
+		idbox[n][6] + 1, idbox[n][7], dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_ival() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_ival(n, k)
+short n;
+register short  k;
+{
+	if (idsrcsw)			/* not in source menu */
+		return(FAILURE);
+
+	if ((stccol GE 32) AND (stccol LE 40))	/* not in source */
+		return(FAILURE);
+
+	if (stccol EQ 29)		/* not in decimal point */
+		return(FAILURE);
+
+	ebuf[2] = '.';			/* setup the fixed stuff */
+	ebuf[10] = '\0';
+
+/* 
+
+*/
+	if (stccol LT 32) {		/* value */
+
+		ebuf[stccol - 27] = k + '0';
+		dspbuf[0] = k + '0';
+
+	} else if (stccol EQ 41) {	/* mutiplier sign */
+
+		if (k EQ 8) {		/* - */
+
+			ebuf[9] = '-';
+			dspbuf[0] = '-';
+
+		} else if (k EQ 9) {	/* + */
+
+			ebuf[9] = '+';
+			dspbuf[0] = '+';
+
+		} else
+			return(FAILURE);
+
+	} else if (stccol EQ 42) {		/* 1st digit */
+
+		if (k EQ 0) {		/* 0 */
+
+			ebuf[6] = '0';
+			dspbuf[0] = '.';
+
+		} else if (k EQ 1) {	/* 1 */
+
+			ebuf[6] = '1';
+			dspbuf[0] = SP_1P;
+
+		} else
+			return(FAILURE);
+
+	} else {				/* 2nd or 3rd digit */
+
+		ebuf[stccol - 36] = k + '0';
+		dspbuf[0] = k + '0';
+	}
+/* 
+
+*/
+	dspbuf[1]  = '\0';	/* terminate display buffer */
+
+	vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6] + 1, stccol, dspbuf, 14);
+
+	if ((stccol EQ 31) OR (stccol EQ 44))	/* last column of field ? */
+		return(SUCCESS);
+
+	advicur();
+
+	if (stccol EQ 29)			/* decimal point ? */
+		advicur();
+
+	return(SUCCESS);
+}
Index: ram/etivce.c
===================================================================
--- ram/etivce.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etivce.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,140 @@
+/*
+   =============================================================================
+	etivce.c -- instrument editor - voice number field handlers
+	Version 12 -- 1987-12-09 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#define	VCE_OFF		6
+
+extern	short	advicur(), newvce();
+
+extern	unsigned	*instob;
+
+extern	short	stccol, curvce;
+
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_ivce() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_ivce(n)
+short n;
+{
+	sprintf(ebuf, "%02d", curvce + 1);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_ivce() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_ivce(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if ((tmpval EQ 0) OR (tmpval GT 12))
+		return(FAILURE);
+
+	newvce(tmpval - 1);
+	allwins();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ivce() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_ivce(n)
+short n;
+{
+	/* convert to ASCII */
+
+	sprintf(dspbuf, "%02d", curvce + 1);
+
+	vbank(0);			/* display the value */
+
+	vcputsv(instob, 64, idbox[n][4], idbox[n][5],
+		idbox[n][6], idbox[n][7] + VCE_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_ivce() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_ivce(n, k)
+short n;
+register short  k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5],
+		idbox[n][6], stccol, dspbuf, 14);
+
+	advicur();
+
+	return(SUCCESS);
+}
+
Index: ram/etiwsn.c
===================================================================
--- ram/etiwsn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etiwsn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,184 @@
+/*
+   =============================================================================
+	etiwsn.c -- MIDAS instrument editor - waveshape number handlers
+	Version 6 -- 1988-04-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+extern	unsigned	*instob;
+
+extern	short	stcrow, stccol, curvce;
+extern	short	idbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+extern	struct	wstbl	wslib[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_iwsn() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_iwsn(nn)
+short nn;
+{
+	register short m;
+
+	m = nn >> 8;
+
+	sprintf(ebuf, "%02d", m ? vbufs[curvce].idhwsb + 1
+		: vbufs[curvce].idhwsa + 1);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_iwsn() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_iwsn(nn)
+short nn;
+{
+	register short i, tmpval, m;
+	register short *fpuws;
+
+	m = nn >> 8;
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if ((tmpval EQ 0) OR (tmpval GT NUMWAVS))
+		return(FAILURE);
+
+	if (m) {
+
+		/* slot B */
+		vbufs[curvce].idhwsb = tmpval - 1;
+
+		memcpyw(vbufs[curvce].idhwvbf, &wslib[tmpval - 1],
+			NUMHARM + (2 * NUMWPNT));
+
+		fpuws = io_fpu + FPU_OWST + (curvce << 9) + 1;
+
+		memcpyw(fpuws, vbufs[curvce].idhwvbf, NUMWPNT);
+
+		*(fpuws - 1) = vbufs[curvce].idhwvbf[0];
+		*(fpuws + NUMWPNT) = vbufs[curvce].idhwvbf[NUMWPNT - 1];
+
+	} else {
+
+		/* slot A */
+
+		vbufs[curvce].idhwsa = tmpval - 1;
+
+		memcpyw(vbufs[curvce].idhwvaf, &wslib[tmpval - 1],
+			NUMHARM + (2 * NUMWPNT));
+
+		fpuws = io_fpu + FPU_OWST + (curvce << 9) + 0x100 + 1;
+
+		memcpyw(fpuws, vbufs[curvce].idhwvaf, NUMWPNT);
+
+		*(fpuws - 1) = vbufs[curvce].idhwvaf[0];
+		*(fpuws + NUMWPNT) = vbufs[curvce].idhwvaf[NUMWPNT - 1];
+	}
+
+	dswin(21);
+	modinst();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_iwsn() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_iwsn(nn)
+short nn;
+{
+	register short m, n;
+
+	m = (nn >> 8) & 0x00FF;
+	n = nn & 0x00FF;
+
+	sprintf(dspbuf, "%02d", m ? vbufs[curvce].idhwsb + 1
+			: vbufs[curvce].idhwsa + 1);
+
+	vbank(0);
+
+	vcputsv(instob, 64, (m ? WSBFC : WSAFC), idbox[n][5],
+		cfetp->frow, cfetp->flcol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_iwsn() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_iwsn(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, c, n;
+
+	n = nn & 0x00FF;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';		/* enter new data in buffer */
+	ebuf[2] = '\0';			/* make sure string is terminated */
+
+	dspbuf[0] = k + '0';		/* setup for display */
+	dspbuf[1] = '\0';
+
+	vbank(0);			/* display the new data */
+	vcputsv(instob, 64, ID_ENTRY, idbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advicur();			/* advance cursor */
+
+	return(SUCCESS);
+}
+
Index: ram/etloc.c
===================================================================
--- ram/etloc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etloc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,242 @@
+/*
+   =============================================================================
+	etloc.c -- location field handlers
+	Version 11 -- 1988-07-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "instdsp.h"
+
+extern	short	setsr();
+
+extern	unsigned	*obj8;
+
+extern	unsigned	curintp;
+
+extern	short		ctrsw;
+extern	short		timemlt;
+extern	short		recsw;
+extern	short		stccol;
+
+extern	short		grploc[];
+extern	short		grpmode[];
+extern	short		grpstat[];
+extern	short		loctab[];
+extern	short		vce2grp[];
+
+extern	unsigned	expbit[];
+
+extern	struct gdsel	*gdstbc[];
+
+extern	struct instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_loc() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_loc(n)
+short n;
+{
+	ebuf[0] =grploc[n] + 1 + '0';
+	ebuf[1] = '\0';
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setloc() -- set location
+   =============================================================================
+*/
+
+setloc(grp, loc)
+short grp, loc;
+{
+	register short g, i, val;
+	register long ltmp;
+	register unsigned *fpu;
+	register struct idfnhdr *fp;
+	unsigned fpmant, fpexp;
+	short oldsr;
+	short nop;
+
+	grploc[grp] = loc;
+	val = (loctab[loc] << 1) ^ 0x8000;
+	g = grp + 1;
+
+	fpmant = (((long)curintp & 0x0000FFF0L) *
+		  ((long)timemlt & 0x0000FFFFL)) >> 15;
+
+	fpexp = expbit[curintp & 0x000F];
+
+/* 
+
+*/
+	for (i = 0; i < 12; i++)
+		if (g EQ vce2grp[i]) {
+
+			fp = &vbufs[i].idhfnc[4];
+			fpu = io_fpu + FPU_OFNC + (i << 8) + 0x0040;
+
+			oldsr = setsr(0x2200);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+			fp->idftmd ^= I_NVBITS;
+
+			*(fpu + (long)FPU_TMNT) = fpmant;
+			++nop;	++nop;	++nop;
+			*(fpu + (long)FPU_TEXP) = fpexp;
+			++nop;	++nop;	++nop;
+
+			if (fp->idftmd & I_VNSUBN)
+				*(fpu + (long)FPU_TNV1) = val;
+			else
+				*(fpu + (long)FPU_TNV0) = val;
+
+			++nop;	++nop;	++nop;
+
+			*(fpu + (long)FPU_TCTL) =
+				(fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0001;
+
+			setsr(oldsr);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+		}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_loc() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_loc(n)
+short n;
+{
+	register short ival;
+	register struct s_entry *ep;
+
+	ebuf[1] = '\0';
+	ival = ebuf[0] - '0';
+	ebflag = FALSE;
+
+	if (ival EQ 0)
+		return(FAILURE);
+
+	--ival;
+
+	setloc(n, ival);
+
+	if (recsw AND grpstat[n] AND (2 EQ grpmode[n])) {
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_LOCN, n, -1))) {
+
+			ep->e_data2 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_LOCN;
+			ep->e_data1 = n;
+			ep->e_data2 = ival;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_LOCN);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_loc() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_loc(n)
+short n;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 4, 8+(n*5), (grploc[n] + 1 + '0'), SDW11ATR);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ds_loc() -- display all location to group assignments
+   =============================================================================
+*/
+
+ds_loc()
+{
+	register short i;
+
+	for (i = 0; i < 12; i++)
+		rd_loc(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_loc() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_loc(n, k)
+register short n, k;
+{
+	ebuf[0]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 4, stccol, k + '0', SDW11DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etmcfn.c
===================================================================
--- ram/etmcfn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etmcfn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,298 @@
+/*
+   =============================================================================
+	etmcfn.c -- instrument editor - ws/cf menu field handlers
+	Version 7 -- 1988-08-26 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+extern	unsigned	*instob;
+
+extern	short	curvce;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	wmcsel;
+extern	short	wmctag;
+
+extern	char	dspbuf[];
+
+extern	short	idbox[][8];
+
+extern	struct	instdef	vbufs[];
+
+extern	struct	wstbl	wslib[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_mcfn() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_mcfn(n)
+short n;
+{
+	sprintf(ebuf, "%02d", vbufs[curvce].idhcfg);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_mcfn() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_mcfn(n)
+short n;
+{
+	register short tmpval;
+
+	wmctag = FALSE;
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = ((ebuf[0] - '0') * 10) + (ebuf[1] - '0');
+
+	if (tmpval GE NUMCFG)		/* check against limit */
+		return(FAILURE);
+
+	vbufs[curvce].idhcfg = tmpval;
+	dosync(curvce);
+	wmctag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_mcfn() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_mcfn(n)
+short n;
+{
+	sprintf(dspbuf, "%02d", vbufs[curvce].idhcfg);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, CFBX18, CBBX18, 24, 16, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_mcfn() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_mcfn(n, k)
+short n;
+register short  k;
+{
+	register short ec, c;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';		/* enter new data in buffer */
+	ebuf[2] = '\0';			/* make sure string is terminated */
+
+	dspbuf[0] = k + '0';		/* setup for display */
+	dspbuf[1] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	/* display the new data */
+
+	vcputsv(instob, 64, ID_ENTRY, CBBX18, stcrow, stccol, dspbuf, 14);
+
+	advicur();			/* advance cursor */
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_mwsn() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_mwsn(nn)
+short nn;
+{
+	wmcsel = (nn & 0xFF00) ? 1 : 0;
+
+	sprintf(ebuf, "%02d", 1 + (wmcsel ? vbufs[curvce].idhwsb
+		: vbufs[curvce].idhwsa));
+
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_mwsn() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_mwsn(nn)
+short nn;
+{
+	register short tmpval;
+	register short *fpuws;
+
+	wmcsel = (nn & 0xFF00) ? 1 : 0;
+
+	wmctag = FALSE;
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	/* convert from ASCII to binary */
+
+	tmpval = ((ebuf[0] -'0') * 10) + (ebuf[1] - '0');
+
+	if ((tmpval < 1) OR (tmpval > NUMWAVS))
+		return(FAILURE);
+/* 
+
+*/
+	if (wmcsel) {
+
+		/* slot B */
+		vbufs[curvce].idhwsb = tmpval - 1;
+
+		memcpyw(vbufs[curvce].idhwvbf, &wslib[tmpval - 1],
+			NUMHARM + (2 * NUMWPNT));
+
+		fpuws = io_fpu + FPU_OWST + (curvce << 9) + 1;
+
+		memcpyw(fpuws, vbufs[curvce].idhwvbf, NUMWPNT);
+
+		*(fpuws - 1) = vbufs[curvce].idhwvbf[0];
+		*(fpuws + NUMWPNT) = vbufs[curvce].idhwvbf[NUMWPNT - 1];
+
+	} else {
+
+		/* slot A */
+
+		vbufs[curvce].idhwsa = tmpval - 1;
+
+		memcpyw(vbufs[curvce].idhwvaf, &wslib[tmpval - 1],
+			NUMHARM + (2 * NUMWPNT));
+
+		fpuws = io_fpu + FPU_OWST + (curvce << 9) + 0x100 + 1;
+
+		memcpyw(fpuws, vbufs[curvce].idhwvaf, NUMWPNT);
+
+		*(fpuws - 1) = vbufs[curvce].idhwvaf[0];
+		*(fpuws + NUMWPNT) = vbufs[curvce].idhwvaf[NUMWPNT - 1];
+	}
+
+	wmctag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_mwsn() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_mwsn(nn)
+short nn;
+{
+	wmcsel = (nn & 0xFF00) ? 1 : 0;
+
+	sprintf(dspbuf, "%02d", 1 + (wmcsel ? vbufs[curvce].idhwsb
+			: vbufs[curvce].idhwsa));
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(instob, 64, CFBX23, CBBX23, 24, wmcsel ? 16 : 12, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_mwsn() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_mwsn(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, c;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';		/* enter new data in buffer */
+	ebuf[2]  = '\0';		/* make sure string is terminated */
+
+	dspbuf[0] = k + '0';		/* setup for display */
+	dspbuf[1] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);			/* display the new data */
+
+	vcputsv(instob, 64, ID_ENTRY, CBBX23, stcrow, stccol, dspbuf, 14);
+
+	advicur();			/* advance cursor */
+
+	return(SUCCESS);
+}
Index: ram/etrel.c
===================================================================
--- ram/etrel.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etrel.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,33 @@
+/*
+   =============================================================================
+	etrel.c -- release field handlers
+	Version 2 -- 1987-07-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "fields.h"
+#include "stddefs.h"
+
+short
+et_rel()
+{
+	return(FAILURE);
+}
+
+short
+ef_rel()
+{
+	return(FAILURE);
+}
+
+short
+rd_rel()
+{
+	return(FAILURE);
+}
+
+short
+nd_rel()
+{
+	return(FAILURE);
+}
Index: ram/etres1.c
===================================================================
--- ram/etres1.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etres1.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,451 @@
+/*
+   =============================================================================
+	etres1.c -- analog variable field handlers
+	Version 16 -- 1988-06-28 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "smdefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "score.h"
+#include "scfns.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+extern	short	ancmsw;
+extern	short	angroup;
+extern	short	ctrsw;
+extern	short	recsw;
+extern	short	stccol;
+
+extern	unsigned	*obj8;
+
+extern	short	anrs[8][16];
+extern	short	grpmode[12];
+extern	short	grpstat[12];
+extern	short	var2src[6];
+extern	short	varmode[8][16];
+
+extern	struct	gdsel	*gdstbc[];
+extern	struct	valent	valents[];
+
+/*
+   =============================================================================
+	et_res1() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_res1(n)
+short n;
+{
+	ebuf[0] = anrs[n][abs(angroup)-1];
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_res1() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_res1(n)
+short n;
+{
+	register short ival, grp, vg;
+	register struct s_entry *ep;
+
+	ebflag = FALSE;
+	grp = abs(angroup)-1;
+	ival = ebuf[0] & 0x00FF;
+
+	if ((ival < 3) OR (ival > 8))
+		return(FAILURE);
+
+	anrs[n][grp] = ival;
+
+	if (recsw AND grpstat[grp] AND
+	    (2 EQ (ancmsw ? varmode[n][grp] : grpmode[grp]))) {
+
+		vg = ((n << 4) | grp);
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_ANRS, vg, -1))) {
+
+			ep->e_data2 = ival;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_ANRS;
+			ep->e_data1 = vg;
+			ep->e_data2 = ival;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_ANRS);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_res1() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_res1(n)
+short n;
+{
+	register short grp, chr;
+
+	grp = abs(angroup) - 1;
+
+	chr = anrs[n][grp] + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 7, 6 + (n * 9), chr, SDW12ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_res1() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_res1(n, k)
+short n, k;
+{
+	ebuf[0] = k;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 7, stccol, k + '0', SDW12DEA);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_aval() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_aval(n)
+short n;
+{
+	register short val, grp, gs;
+	short val1, val2, val3;
+
+	grp = abs(angroup) - 1;
+	gs = (grp << 4) | var2src[n];
+	val = (valents[gs].val) >> 5;
+
+	if (val < 0 ) {
+
+		ebuf[0] = 8;
+		val = -val;
+
+	} else {
+
+		ebuf[0] = 9;
+	}
+
+	val1 = val / 100;
+	ebuf[4] = (val - (val1 * 100)) / 10;
+	val2 = val1 / 10;
+	ebuf[2] = val1 - (val2 * 10);
+	ebuf[1] = val2;
+
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_res1() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_aval(n)
+short n;
+{
+	register short val, grp, src, vg;
+	register struct s_entry *ep;
+
+	ebflag = FALSE;
+	grp = abs(angroup) - 1;
+	src = var2src[n];
+	val = ((ebuf[1] * 100) + (ebuf[2] * 10) + ebuf[4]) * 10;
+
+	if (val > 1000)
+		return(FAILURE);
+
+	if (ebuf[0] EQ 8)
+		val = -val;
+
+	val = val << 5;
+
+	setsv(grp, src, val);
+
+	if (recsw AND grpstat[grp] AND
+	    (2 EQ (ancmsw ? varmode[n][grp] : grpmode[grp]))) {
+
+		vg =  (n << 4) | grp;
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_ANVL, vg, -1))) {
+
+			ep->e_dn = (struct s_entry *)((long)val << 16);
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_ANVL;
+			ep->e_data1 = vg;
+			ep->e_dn    = (struct s_entry *)((long)val << 16);
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_aval() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_aval(n)
+short n;
+{
+	register short grp, val, gs;
+	short val1, val2;
+	char	buf[6];
+
+	grp = abs(angroup) - 1;
+	gs = (grp << 4) | var2src[n];
+	val = (valents[gs].val) >> 5;
+
+	if (val < 0) {
+
+		buf[0] = '-';
+		val = -val;
+
+	} else {
+
+		buf[0] = '+';
+	}
+
+	val1 = val / 100;
+	buf[4] = '0' + ((val - (val1 * 100)) / 10);
+	val2 = val1 / 10;
+	buf[2] = '0' + (val1 - (val2 * 10));
+	buf[1] = '0' + val2;
+	buf[3] = '.';
+	buf[5] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 7, 8 + (n * 9), buf, SDW12ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_aval() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_aval(n, k)
+register short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;
+
+	if (ec EQ 3)
+		return(FAILURE);
+
+	ebuf[ec] = k;
+
+	if (ec EQ 0)
+		k = (k EQ 8) ? '-' : '+';
+	else
+		k += '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 7, stccol, k, SDW12DEA);
+
+	if (ec EQ 4)
+		return(SUCCESS);
+
+	advscur();
+
+	if (ec EQ 2)
+		advscur();
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_agrp() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_agrp(n)
+short n;
+{
+	sprintf(ebuf, "%02.2d", abs(angroup));
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_agrp() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_agrp(n)
+short n;
+{
+	register short ival;
+
+	ebflag = FALSE;
+	ival = (10 * (ebuf[0] - '0')) + (ebuf[1] - '0');
+
+	if ((ival >12) OR (ival < 1))
+		return(FAILURE);
+
+	angroup = sign(angroup, ival);
+
+	ds_anmd();
+	ds_anrs();
+	ds_anvl();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_agrp() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_agrp(n)
+short n;
+{
+	char	buf[4];
+
+	sprintf(buf, "%02.2d", abs(angroup));
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 7, 61, buf, SDW12ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_agrp() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_agrp(n, k)
+short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;
+
+	ebuf[ec] = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 7, stccol, k + '0', SDW12DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etscor.c
===================================================================
--- ram/etscor.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etscor.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,121 @@
+/*
+   =============================================================================
+	etscor.c -- score field handlers
+	Version 7 -- 1988-08-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "stddefs.h"
+#include "score.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+extern	unsigned	*obj8;
+
+extern	short	curscor;
+extern	short	insmode;
+extern	short	stccol;
+
+extern	char	dspbuf[];
+
+/*
+   =============================================================================
+	et_scor() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_scor()
+{
+	sprintf(ebuf, "%02.2d", curscor + 1);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_scor() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_scor()
+{
+	register short ival;
+
+	ebuf[2] = '\0';
+	ival = ((ebuf[0] - '0') * 10) + (ebuf[1] - '0');
+
+	ebflag = FALSE;
+
+	if ((ival GT N_SCORES) OR (ival EQ 0))
+		return(FAILURE);
+
+	if (insmode) {
+
+		icancel();
+		dsimode();
+	}
+
+	selscor(ival - 1);
+	sdwins();
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	rd_scor() -- redisplay field
+   =============================================================================
+*/
+
+short
+rd_scor()
+{
+	sprintf(dspbuf, "%02.2d", curscor + 1);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 8, 7, dspbuf, SDW13ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+ 
+/*
+   =============================================================================
+	nd_scor() -- data entry
+   =============================================================================
+*/
+
+short
+nd_scor(n, k)
+short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;
+	ebuf[ec]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 8, stccol, k + '0', SDW13DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etsnbt.c
===================================================================
--- ram/etsnbt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etsnbt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,149 @@
+/*
+   =============================================================================
+	etsnbt.c -- beat field handlers
+	Version 4 -- 1988-07-28 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "stddefs.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "instdsp.h"
+
+extern	unsigned	*obj8;
+
+extern	short	clkrun;
+extern	short	insmode;
+extern	short	stccol;
+
+extern	long	t_cur;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_snbt() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_snbt(n)
+short n;
+{
+	register long curfr, beat;
+
+	if (clkrun) {
+
+		ebflag = FALSE;
+		return(FAILURE);
+	}
+
+	curfr = t_cur;
+	beat  = curfr / 48;
+
+	sprintf(ebuf, "%05ld", beat);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_snbt() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_snbt(n)
+short n;
+{
+	register long ival;
+	register short i;
+
+	if (clkrun)
+		return(FAILURE);
+
+	ival = 0L;
+
+	for (i = 0; i < 5; i++)
+		ival = (ival * 10) + (ebuf[i] - '0');
+
+	ebflag = FALSE;
+
+	if (insmode) {
+
+		icancel();
+		dsimode();
+	}
+
+	sc_goto(fc_val = ival * 48L);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_snbt() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_snbt(n)
+short n;
+{
+	register long curfr, beat;
+	char	buf[8];
+
+	curfr = t_cur;
+	beat  = curfr / 48;
+	sprintf(buf, "%05ld", beat);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 0, 11, buf, SDW00ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_snbt() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_snbt(n, k)
+register short n, k;
+{
+	register short ec;
+
+	if (clkrun)
+		return(FAILURE);
+
+	ec = stccol - cfetp->flcol;
+	ebuf[ec]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 0, stccol, k + '0', SDW00DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etstrn.c
===================================================================
--- ram/etstrn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etstrn.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,144 @@
+/*
+   =============================================================================
+	etstrn.c -- section edit group transposition field handlers
+	Version 3 -- 1989-11-14 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "stddefs.h"
+#include "score.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+extern	unsigned	*obj8;
+
+extern	short	grptran;
+extern	short	sdmctl;
+extern	short	vtccol;
+extern	short	vtcrow;
+extern	short	vtxval;
+extern	short	vtyval;
+
+extern	char	dspbuf[];
+
+/*
+   =============================================================================
+	et_strn() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_strn()
+{
+	sprintf(ebuf, "%c%02d", grptran < 0 ? '-' : '+', abs(grptran));
+
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_strn() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_strn()
+{
+	register short ival;
+
+	ebuf[3] = '\0';
+	ival = ((ebuf[1] - '0') * 10) + (ebuf[2] - '0');
+
+	ebflag = FALSE;
+
+	if ((ival NE 0) AND (ebuf[0] EQ '-'))
+		ival = -ival;
+
+	grptran = ival;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	rd_strn() -- redisplay field
+   =============================================================================
+*/
+
+short
+rd_strn()
+{
+	sprintf(dspbuf, "%c%02d", grptran < 0 ? '-' : '+', abs(grptran));
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 7, 22, dspbuf, SDMENUBG);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+ 
+/*
+   =============================================================================
+	nd_strn() -- data entry
+   =============================================================================
+*/
+
+short
+nd_strn(n, k)
+short n, k;
+{
+	register short ec;
+
+	if (sdmctl NE 4)
+		return(FAILURE);
+
+	if ((vtccol GE 22) AND (vtccol LE 24))
+		ec = vtccol - 22;
+	else
+		return(FAILURE);
+
+	if (ec EQ 0) {
+
+		if (k EQ 8)
+			k = '-';
+		else if (k EQ 9)
+			k = '+';
+		else
+			return(FAILURE);
+	} else
+		k += '0';
+
+	ebuf[ec] = k;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 7, vtccol, k, (SDBGMM | (SD_ENTR << 4)));
+
+	if (vtccol < 24) {
+
+		++vtccol;
+		vtxval = CTOX(vtccol);
+		ttcpos(vtcrow, vtccol);
+	}
+
+	return(SUCCESS);
+}
Index: ram/ettpch.c
===================================================================
--- ram/ettpch.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ettpch.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,285 @@
+/*
+   =============================================================================
+	ettpch.c -- MIDAS tuning table pitch field handlers
+	Version 6 -- 1987-12-21 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "tundsp.h"
+
+/* functions defined elsewhere */
+
+extern	short	cnvp2c();
+
+/* variables defined elsewhere */
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	short	stcrow, stccol, cents;
+
+extern	short	tdbox[][8];
+
+extern	short	tuntab[];
+
+extern	char	dspbuf[];
+extern	char	sfdsp[];
+
+extern	unsigned	*tunob;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	loc2key() -- convert a screen location to a key number or field code
+   =============================================================================
+*/
+
+short
+loc2key(row, col)
+short row, col;
+{
+	if (row EQ 24) {
+
+		if ((col > 6) AND (col < 39))
+			return(-1);		/* -1 = name */
+		else if (col > 52)
+			return(-9);		/* -9 = table # */
+		else
+			return(-10);		/* -10 = not a field */
+
+	} else if (col < 12)
+		return(row);			/* 0..23 = key 0..23 */
+	else if ((col > 11) AND (col < 22))
+		return(row + 24);		/* 24..47 = key 24..47 */
+	else if ((col > 21) AND (col < 32))
+		return(row + 48);		/* 48..71 = key 48..71 */
+	else if ((col > 31) AND (col < 42))
+		return(row + 72);		/* 72..95 = key 72..95 */
+	else if ((col > 41) AND (col < 53))
+		return(row + 96);		/* 96..119 = key 96..119 */
+	else if ((col > 52) AND (row < 8))
+		return(row + 120);		/* 120..127 = key 120..127 */
+	else if (col > 52) {
+
+		if ((row EQ 9) OR (row EQ 10))
+			return(-2);		/* -2 = transpose and copy */
+		else if (row EQ 12)
+			return(-3);		/* -3 = increment */
+		else if (row EQ 14)
+			return(-4);		/* -4 = interpolate */
+		else if (row EQ 16)
+			return(-5);		/* -5 = undo */
+		else if (row EQ 18)
+			return(-6);		/* -6 = value */
+		else if (row EQ 20)
+			return(-7);		/* -7 = store */
+		else if (row EQ 22)
+			return(-8);		/* -8 = retrieve */
+		else
+			return(-10);		/* -10 = not a field */
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_tpch() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_tpch(nn)
+short nn;
+{
+	register short key, val;
+
+	key = loc2key(stcrow, stccol);
+
+	if (key < 0)
+		return(FAILURE);
+
+	val = tuntab[key];
+	cnvc2p(ebuf, (val >> 1));
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_tpch() -- unload (parse) edit buffer
+   =============================================================================
+*/
+
+short
+ef_tpch(nn)
+short nn;
+{
+	register short key;
+
+	ebflag = FALSE;
+	key = loc2key(stcrow, stccol);
+
+	if (key < 0)
+		return(FAILURE);
+
+	if (cnvp2c() EQ FAILURE)
+		return(FAILURE);
+
+	modtun();
+	tuntab[key] = cents << 1;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_tpch() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_tpch(nn)
+short nn;
+{
+	register short val, key, n;
+
+	n = nn & 0xFF;
+	key = loc2key(cfetp->frow, cfetp->flcol);
+	val = tuntab[key];
+
+	cnvc2p(dspbuf, (val >> 1));
+
+	dspbuf[0] += '0';
+	dspbuf[1] += 'A';
+	dspbuf[2] = sfdsp[dspbuf[2] - 7];
+	dspbuf[3] += '0';
+	dspbuf[4] += '0';
+	dspbuf[5] = '\0';
+
+	vbank(0);
+	vcputsv(tunob, 64,
+		((val EQ 320) OR (val EQ 21920))
+		? TDMKEYC :  tdbox[n][4], tdbox[n][5],
+		cfetp->frow, cfetp->flcol, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_tpch() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_tpch(nn, k)
+short nn, k;
+{
+	register short col, n;
+
+	n = nn & 0xFF;
+
+	if (stccol < 11)
+		col = stccol - 6;
+	else if (stccol < 21)
+		col = stccol - 16;
+	else if (stccol < 31)
+		col = stccol - 26;
+	else if (stccol < 41)
+		col = stccol - 36;
+	else if (stccol < 52)
+		col = stccol - 47;
+	else
+		col = stccol - 58;
+
+	switch (col) {
+
+	case 0:
+
+		ebuf[0] = k;
+		dspbuf[0] = k + '0';
+		break;
+
+	case 1:
+
+		if (k GT 6)
+			return(FAILURE);
+
+		ebuf[1] = k;
+		dspbuf[0] = k + 'A';
+		break;
+/* 
+
+*/
+	case 2:
+
+		if (k EQ 7) {		/* blank */
+
+			ebuf[2] = k;
+			dspbuf[0] = sfdsp[0];
+			break;
+
+		} else if (k EQ 8) {	/* flat */
+
+			ebuf[2] = k;
+			dspbuf[0] = sfdsp[1];
+			break;
+
+		} else if (k EQ 9) {	/* sharp */
+
+			ebuf[2] = k;
+			dspbuf[0] = sfdsp[2];
+			break;
+
+		} else
+			return(FAILURE);
+/* 
+
+*/
+	case 3:
+	case 4:
+
+		ebuf[col] = k;
+		dspbuf[0] = k + '0';
+		break;
+	}
+
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(tunob, 64, TDENTRY, tdbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	if (col EQ 4)
+		return(SUCCESS);
+
+	advtcur();
+	return(SUCCESS);
+}
Index: ram/ettrns.c
===================================================================
--- ram/ettrns.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ettrns.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,318 @@
+/*
+   =============================================================================
+	ettrns.c -- transposition field handlers
+	Version 20 -- 1988-07-12 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT	0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "charset.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+extern	short	advscur();
+
+extern	unsigned	*obj8;
+
+extern	short	ctrsw, recsw, stccol, stcrow;
+
+extern	short	s_trns[12];	/* current transposition values */
+
+extern	char	dspbuf[65];
+
+extern	short	grpdyn[], grpmode[], grpstat[];
+
+extern	struct	gdsel	*gdstbc[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_trns() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_trns(n)
+short n;
+{
+	register short trval;
+	register char trsign;
+
+	trval = s_trns[n];
+
+	if (trval < 0) {
+
+		trval = (-trval);
+		trsign = '-';
+
+	} else {
+
+		trsign = '+';
+	}
+
+	sprintf(ebuf, "%04.4d%c", trval, trsign);
+
+	ebflag = TRUE;
+
+#if	DEBUGIT
+	printf("et_trns(0x%04.4x)  [%s]\r\n", n, ebuf);
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_trns() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_trns(n)
+short n;
+{
+	register short i, trval;
+	register struct s_entry *ep, *trnval;
+
+	ebuf[5] = '\0';			/* terminate the string in ebuf */
+
+#if	DEBUGIT
+	printf("ef_trns(0x%04.4x) [%s]\r\n", n, ebuf);
+#endif
+
+	ebflag = FALSE;
+	trval = 0;
+
+	for (i = 0; i < 4; i++)		/* convert from ASCII to binary */
+		trval = (trval * 10) + (ebuf[i] - '0');
+
+	if (trval GT 1200)		/* check against limit */
+		return(FAILURE);
+
+	if (ebuf[4] EQ '-')		/* fixup sign of value */
+		trval = (-trval);
+
+	s_trns[n] = trval;		/* store new value */
+	settune();			/* update FPU */
+
+	if (recsw AND grpmode[n] AND (2 EQ grpmode[n])) {
+
+		trnval = (struct s_entry *)((long)trval << 16);
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_TRNS, n, -1))) {
+
+			ep->e_lft = trnval;
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE3))) {
+
+			ep->e_type  = EV_TRNS;
+			ep->e_time  = t_cur;
+			ep->e_data1 = n;
+			ep->e_lft   = trnval;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_TRNS);
+			ctrsw = TRUE;
+			se_disp(ep, D_FWD, gdstbc, 1);
+			scupd();
+		}
+	}
+
+#if	DEBUGIT
+	printf("   SUCCESS: %d\r\n", trval);
+#endif
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_trns() -- (re)display the value
+   =============================================================================
+*/
+
+short
+rd_trns(n)
+short n;
+{
+	register short trval, i;
+	register char trsign;
+
+	trval = s_trns[n];		/* get the value */
+
+	if (trval < 0) {		/* adjust for the sign */
+
+		trsign = '-';
+		trval = (-trval);
+
+	} else {
+
+		trsign = '+';
+	}
+
+	sprintf(dspbuf, "%04.4d", trval);	/* convert to ASCII */
+
+#if	DEBUGIT
+	printf("rd_trns:  %d <%d> [%s] -> ", n, s_trns[n], dspbuf);
+#endif
+
+	if (trsign EQ '-') {		/* handle +1, -1 cases */
+
+		if (dspbuf[0] EQ '1')
+			dspbuf[0] = SP_M1;	/* -1 */
+		else
+			dspbuf[0] = '-';
+
+	} else {
+
+		if (dspbuf[0] EQ '1')
+			dspbuf[0] = SP_P1;	/* +1 */
+		else
+			dspbuf[0] = '+';
+	}
+
+#if	DEBUGIT
+	printf("{%02x %02x %02x %02x}\r\n",
+		dspbuf[0], dspbuf[1], dspbuf[2], dspbuf[3]);
+#endif
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);			/* display the value */
+
+	vputs(obj8, 3, (5 * (n + 1)), dspbuf, SDW11ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ds_trns() -- display all transposition values
+   =============================================================================
+*/
+
+ds_trns()
+{
+	register short i;
+
+	for (i = 0; i < 12; i++)	/* display each of the groups */
+		rd_trns(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_trns() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_trns(n, k)
+short n;
+register short  k;
+{
+	register short ec, c, advsw;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+#if	DEBUGIT
+	printf("nd_trns(0x%04.4x, 0x%02.2x) ec = %d, tp = 0x%08.8lx\r\n",
+		n, k, ec, tp);
+#endif
+
+	advsw = TRUE;
+
+	if (ec EQ 0) {		/* first column of field ? */
+
+		switch (k) {	/* what are we entering ? */
+
+		case 0:		/* digit 0 */
+
+			ebuf[0] = '0';
+			k = ebuf[4];
+			break;
+
+		case 1:		/* digit 1 */
+
+			if (ebuf[4] EQ '+')
+				k = SP_P1;	/* +1 */
+			else
+				k = SP_M1;	/* -1 */
+
+			ebuf[0] = '1';
+			break;
+
+		case 8:		/* - */
+
+			if (ebuf[0] EQ '0')
+				k = '-';
+			else
+				k = SP_M1;
+
+			ebuf[4] = '-';
+			advsw = FALSE;
+			break;
+
+
+		case 9:		/* + */
+
+			if (ebuf[0] EQ '0')
+				k = '+';
+			else
+				k = SP_P1;
+
+			ebuf[4] = '+';
+			advsw = FALSE;
+			break;
+
+		default:	/* anything else is an error */
+
+			return(FAILURE);
+		}
+
+	} else {	/* any other column */
+
+		ebuf[ec] = k + '0';
+	}
+
+	dspbuf[0] = (k > 9) ? k : (k + '0');
+	dspbuf[1] = '\0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 3, stccol, dspbuf, SDW11DEA);
+
+#if	DEBUGIT
+	printf("nd_trns: char=0x%02.2x, col=%d\n", dspbuf[0], stccol);
+#endif
+
+	if (advsw)
+		advscur();
+
+	return(SUCCESS);
+}
Index: ram/etttab.c
===================================================================
--- ram/etttab.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etttab.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,118 @@
+/*
+   =============================================================================
+	etttab.c -- MIDAS tuning editor - tuning table number field handlers
+	Version 3 -- 1988-08-22 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "tundsp.h"
+
+extern	unsigned	*tunob;
+
+extern	short	stcrow, stccol;
+extern	short	curtun, tunmod;
+
+extern	short	tdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_ttab() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_ttab(n)
+short n;
+{
+	sprintf(ebuf, "%d", curtun);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_ttab() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_ttab(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[1] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	curtun = ebuf[0] - '0';
+	modtun();
+	settc(22, 54);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ttab() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_ttab(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%d", curtun);
+
+	vbank(0);
+	vcputsv(tunob, 64, (tunmod ? TDCHGD : tdbox[n][4]), tdbox[n][5],
+		24, 61, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_ttab() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_ttab(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+
+	ebuf[0] = k + '0';
+	ebuf[1] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(tunob, 64, TDENTRY, tdbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	return(SUCCESS);
+}
Index: ram/ettval.c
===================================================================
--- ram/ettval.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ettval.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,202 @@
+/*
+   =============================================================================
+	ettval.c -- MIDAS tuning editor -- value field handlers
+	Version 2 -- 1987-12-09 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "tundsp.h"
+
+extern	unsigned	*tunob;
+
+extern	short	stcrow, stccol, tunval, tunmod;
+
+extern	short	tdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	modtun() -- indicate that the tuning table was modified
+   =============================================================================
+*/
+
+modtun()
+{
+	if (NOT tunmod) {
+
+		tunmod = TRUE;
+		tdswin(6);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_tval() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_tval(n)
+short n;
+{
+	register short tv;
+	register char ts;
+
+	tv = (tunval < 0 ? -tunval : tunval) >> 1;
+	ts = tunval < 0 ? '-' : '+';
+
+	sprintf(ebuf, "%c%04d", ts, tv);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_tval() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_tval(n)
+short n;
+{
+	register short *ov;
+	register short i, tmpval, tv;
+	register char ts;
+
+	ebuf[5] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 1; i < 5; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (ebuf[0] EQ '-')
+		tunval = -tmpval << 1;
+	else
+		tunval = tmpval << 1;
+
+	tv = (tunval < 0 ? -tunval : tunval) >> 1;
+	ts = tunval < 0 ? '-' : '+';
+	sprintf(dspbuf, "Val %c%04d", ts, tv);
+
+	vbank(0);
+	vcputsv(tunob, 64, tdbox[n][4], tdbox[n][5], 18, 54, dspbuf, 14);
+
+	modtun();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_tval() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_tval(nn)
+short nn;
+{
+	register short tv, n;
+	register char ts;
+
+	n = nn & 0xFF;
+
+	tv = (tunval < 0 ? -tunval : tunval) >> 1;
+	ts = tunval < 0 ? '-' : '+';
+
+	sprintf(dspbuf, "Val %c%04d", ts, tv);
+
+	vbank(0);
+	vcputsv(tunob, 64, tdbox[n][4], tdbox[n][5], 18, 54, dspbuf, 14);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_tval() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_tval(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	if (ec EQ 0) {
+
+		if (k EQ 8) {
+
+			ebuf[0] = '-';
+			ebuf[5] = '\0';
+
+			dspbuf[0] = '-';
+			dspbuf[1] = '\0';
+
+		} else if (k EQ 9) {
+
+			ebuf[0] = '+';
+			ebuf[5] = '\0';
+
+			dspbuf[0] = '+';
+			dspbuf[1] = '\0';
+
+		} else {
+
+			return(FAILURE);
+		}
+/* 
+
+*/
+	} else {
+
+		ebuf[ec] = k + '0';
+		ebuf[5] = '\0';
+
+		dspbuf[0] = k + '0';
+		dspbuf[1] = '\0';
+	}
+
+	vbank(0);
+	vcputsv(tunob, 64, TDENTRY, tdbox[n][5], stcrow, stccol, dspbuf, 14);
+
+	advtcur();
+	return(SUCCESS);
+}
+
Index: ram/etvel.c
===================================================================
--- ram/etvel.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etvel.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,151 @@
+/*
+   =============================================================================
+	etvel.c -- velocity field handlers
+	Version 2 -- 1988-06-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "instdsp.h"
+
+extern	unsigned	*obj8;
+
+extern	short	recsw;
+extern	short	stccol;
+
+extern	short	grpmode[];
+extern	short	grpstat[];
+extern	short	lastvel[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_vel() -- load edit buffer
+   =============================================================================
+*/
+
+short
+et_vel(n)
+short n;
+{
+	sprintf(ebuf, "%03d", lastvel[n] / 252);
+
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_vel() -- parse edit buffer
+   =============================================================================
+*/
+
+short
+ef_vel(n)
+short n;
+{
+	register short ival, i;
+	register struct s_entry *ep;
+
+	ival = 0;
+
+	for (i = 0; i < 3; i++)
+		ival = (ival * 10) + (ebuf[i] - '0');
+
+	ebflag = FALSE;
+
+	if (ival > 127)
+		return(FAILURE);
+
+	ival = SM_SCALE(ival);
+
+	if (recsw AND grpstat[n] AND (2 EQ grpmode[n])) {
+
+		lastvel[n] = ival;
+		ep = ep_adj(p_cur, 1, t_cur);
+
+		while (t_cur EQ ep->e_time) {
+
+			if ((EV_NBEG EQ (0x007F & ep->e_type)) AND
+			    (ep->e_data2 EQ n)) {
+
+				((struct n_entry *)ep)->e_vel = ival;
+			}
+
+			ep = ep->e_fwd;
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_vel() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_vel(n)
+short n;
+{
+	char buf[6];
+
+	sprintf(buf, "%03d", lastvel[n] / 252);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 5, 6 + (n * 5), buf, SDW11ATR);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_vel() -- data entry function
+   =============================================================================
+*/
+
+short
+nd_vel(n, k)
+register short n, k;
+{
+	register short ec;
+
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec]  = k + '0';
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 5, stccol, k + '0', SDW11DEA);
+	advscur();
+
+	return(SUCCESS);
+}
Index: ram/etwavs.c
===================================================================
--- ram/etwavs.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwavs.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,134 @@
+/*
+   =============================================================================
+	etwavs.c -- waveshape editor - waveshape number field handlers
+	Version 8 -- 1987-12-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "wsdsp.h"
+
+extern	short	advwcur();
+
+extern	unsigned	*waveob;
+
+extern	short	stccol, curwave, curvce, curwslt;
+
+extern	short	wsnmod[12][2];
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_wavs() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_wavs(n)
+short n;
+{
+	sprintf(ebuf, "%02d", curwave + 1);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_wavs() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_wavs(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if ((tmpval GT NUMWAVS) OR (tmpval EQ 0))
+		return(FAILURE);
+
+	wsnmod[curvce][curwslt] = TRUE;
+	curwave = tmpval - 1;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_wavs() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_wavs(nn)
+short nn;
+{
+	register short n;
+	register unsigned cx;
+
+	cx = exp_c(wsnmod[curvce][curwslt] ? WS_CHGC : wdbox[n][4]);
+	n = nn & 0x00FF;
+
+	sprintf(dspbuf, "%02d", curwave + 1);
+
+	vbank(0);
+	vcputsv(waveob, 64, cx, wdbox[n][5],
+		wdbox[n][6], wdbox[n][7] + WAVE_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_wavs() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_wavs(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		wdbox[n][6], stccol, dspbuf, 14);
+
+	advwcur();
+	return(SUCCESS);
+}
+
Index: ram/etwhar.c
===================================================================
--- ram/etwhar.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwhar.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,128 @@
+/*
+   =============================================================================
+	etwhar.c -- waveshape editor - harmonic number field handlers
+	Version 5 -- 1987-12-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "wsdsp.h"
+
+extern	short	advwcur(), newws(), wdswin();
+
+extern	unsigned	*waveob;
+
+extern	short	stccol, curwhrm;
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_whar() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_whar(n)
+short n;
+{
+	sprintf(ebuf, "%02d", curwhrm + 1);
+	ebflag = TRUE;
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_whar() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_whar(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if ((tmpval GT NUMHARM) OR (tmpval EQ 0))
+		return(FAILURE);
+
+	curwhrm = tmpval - 1;
+	newws();
+	wdswin(5);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_whar() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_whar(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02d", curwhrm + 1);
+
+	vbank(0);			/* display the value */
+	vcputsv(waveob, 64, wdbox[n][4], wdbox[n][5],
+		wdbox[n][6], wdbox[n][7] + WHRM_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_whar() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_whar(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		wdbox[n][6], stccol, dspbuf, 14);
+
+	advwcur();
+	return(SUCCESS);
+}
Index: ram/etwhrv.c
===================================================================
--- ram/etwhrv.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwhrv.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,203 @@
+/*
+   =============================================================================
+	etwhrv.c -- waveshape editor - harmonic value field handlers
+	Version 12 -- 1988-09-09 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+extern	short	advwcur(), wdswin();
+
+extern	unsigned	*waveob;
+
+extern	short	stcrow, stccol, curwhrv, curvce, curwslt, curwhrm;
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+extern	struct	instdef	vbufs[];
+
+extern	short	wsnmod[12][2];
+
+extern	short	vmtab[NUMHARM];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_whrv() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_whrv(n)
+short n;
+{
+	register short harv;
+	register char hvsgn;
+
+	if (curwhrv LT 0) {
+
+		hvsgn = '-';
+		harv = -curwhrv;
+
+	} else {
+
+		hvsgn = '+';
+		harv = curwhrv;
+	}
+
+	sprintf(ebuf, "%c%03d", hvsgn, harv);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_whrv() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_whrv(n)
+short n;
+{
+	register short *hv;
+	register short i, tmpval;
+
+	ebuf[4] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 1; i < 4; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (tmpval GT 100)
+		return(FAILURE);
+
+	if (ebuf[0] EQ '-')
+		curwhrv = -tmpval;
+	else
+		curwhrv = tmpval;
+
+	hv = curwslt ? vbufs[curvce].idhwvbh : vbufs[curvce].idhwvah;
+	hv[curwhrm] = curwhrv;
+	vmtab[curwhrm] = curwhrv;
+	adj(curwhrm);
+	wscalc();
+	whupd();
+	wsnmod[curvce][curwslt] = TRUE;
+	wdswin(0);
+	wdswin(2);
+	wdswin(4);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_whrv() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_whrv(nn)
+short nn;
+{
+	register short harv, n;
+	register char hvsgn;
+
+	n = nn & 0x00FF;
+
+	if (curwhrv LT 0) {
+
+		hvsgn = '-';
+		harv = -curwhrv;
+
+	} else {
+
+		hvsgn = '+';
+		harv = curwhrv;
+	}
+
+	sprintf(dspbuf, "%c%03d", hvsgn, harv);
+
+	vbank(0);			/* display the value */
+	vcputsv(waveob, 64, wdbox[n][4], wdbox[n][5],
+		wdbox[n][6] + 1, wdbox[n][7] + WHRV_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_whrv() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_whrv(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n  = nn & 0x00FF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	if (ec EQ 0) {
+
+		if (k EQ 8) {
+
+			ebuf[0] = dspbuf[0] = '-';
+			ebuf[4] = dspbuf[1] = '\0';
+
+		} else if (k EQ 9) {
+
+			ebuf[0] = dspbuf[0] = '+';
+			ebuf[4] = dspbuf[1] = '\0';
+
+		} else {
+
+			return(FAILURE);
+		}
+
+	} else {
+
+		ebuf[ec] = dspbuf[0] = k + '0';
+		ebuf[4]  = dspbuf[1] = '\0';
+	}
+
+	vbank(0);
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advwcur();
+	return(SUCCESS);
+}
Index: ram/etwoff.c
===================================================================
--- ram/etwoff.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwoff.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,218 @@
+/*
+   =============================================================================
+	etwoff.c -- waveshape editor - offset value field handlers
+	Version 16 -- 1987-12-22 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+extern	short	advwcur(), wdswin(), pntsup();
+
+extern	unsigned	*waveob;
+
+extern	short	stcrow, stccol, lstwoff, curwoff, curvce, curwslt, curwdth;
+
+extern	short	wsnmod[12][2];
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_woff() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_woff(n)
+short n;
+{
+	register short hoff;
+	register char hosgn;
+
+	lstwoff = curwoff;
+
+	if (curwoff LT 0) {
+
+		hosgn = '-';
+		hoff = -curwoff;
+
+	} else {
+
+		hosgn = '+';
+		hoff = curwoff;
+	}
+
+	sprintf(ebuf, "%c%04d", hosgn, hoff);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_woff() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_woff(n)
+short n;
+{
+	register short *ov;
+	register short i, tmpval;
+
+	ebuf[5] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 1; i < 5; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (tmpval GT 1023)
+		return(FAILURE);
+
+	if (ebuf[0] EQ '-')
+		curwoff = -tmpval;
+	else
+		curwoff = tmpval;
+
+	if (curwdth EQ NUMWIDS)
+		wdintp();
+	else
+		pntsup();
+
+	wdswin(0);
+	wdswin(2);
+	wdswin(4);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_woff() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_woff(nn)
+short nn;
+{
+	register short hoff, n;
+	register char hosgn;
+
+	n = nn & 0xFF;
+	lstwoff = curwoff;
+
+	if (curwoff LT 0) {
+
+		hosgn = '-';
+		hoff = -curwoff;
+
+	} else {
+
+		hosgn = '+';
+		hoff = curwoff;
+	}
+
+	sprintf(dspbuf, "%c%04d", hosgn, hoff);
+
+	/* display the value */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(waveob, 64, wdbox[n][4], wdbox[n][5],
+		wdbox[n][6], wdbox[n][7] + WOFF_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_woff() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_woff(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+
+	if (ec EQ 0) {
+
+		if (k EQ 8) {
+
+			ebuf[0] = '-';
+			ebuf[5] = '\0';
+
+			dspbuf[0] = '-';
+			dspbuf[1] = '\0';
+
+		} else if (k EQ 9) {
+
+			ebuf[0] = '+';
+			ebuf[5] = '\0';
+
+			dspbuf[0] = '+';
+			dspbuf[1] = '\0';
+
+		} else {
+
+			return(FAILURE);
+		}
+
+	} else {
+
+		ebuf[ec] = k + '0';
+		ebuf[5] = '\0';
+
+		dspbuf[0] = k + '0';
+		dspbuf[1] = '\0';
+	}
+/* 
+
+*/
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advwcur();
+	return(SUCCESS);
+}
Index: ram/etwpnt.c
===================================================================
--- ram/etwpnt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwpnt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,139 @@
+/*
+   =============================================================================
+	etwpnt.c -- waveshape editor - point number field handlers
+	Version 8 -- 1987-12-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "wsdsp.h"
+
+extern	short	advwcur(), wdswin(), newws();
+
+extern	unsigned	*waveob;
+
+extern	short	stccol, curwpnt;
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_wpnt() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_wpnt(n)
+short n;
+{
+	sprintf(ebuf, "%03d", curwpnt);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ef_wpnt() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_wpnt(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[3] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	tmpval = 0;
+
+	for (i = 0; i < 3; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if (tmpval GE NUMWPNT)
+		return(FAILURE);
+
+	curwpnt = tmpval;
+	newws();
+	wdswin(4);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_wpnt() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_wpnt(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%03d", curwpnt);
+
+	vbank(0);
+	vcputsv(waveob, 64, wdbox[n][4], wdbox[n][5],
+		wdbox[n][6], wdbox[n][7] + WPNT_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nd_wpnt() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_wpnt(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[3] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		wdbox[n][6], stccol, dspbuf, 14);
+
+	advwcur();
+
+	return(SUCCESS);
+}
Index: ram/etwslt.c
===================================================================
--- ram/etwslt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwslt.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,139 @@
+/*
+   =============================================================================
+	etwslt.c -- waveshape editor - waveshape slot field handlers
+	Version 8 -- 1987-12-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+#include "charset.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+extern	short	advwcur(), wdswin(), newws(), dsnewws();
+
+extern	unsigned	*waveob;
+
+extern	short	stcrow, stccol, curwslt;
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_wslt() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_wslt(n)
+short n;
+{
+	sprintf(ebuf, "%c", curwslt + 'A');
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_wslt() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_wslt(n)
+short n;
+{
+	ebuf[1] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+
+	curwslt = ebuf[0] - 'A';
+
+#if DEBUGIT
+	printf("ef_wslt($%04X):  ebuf[%s], curwslt=%d\r\n", n, ebuf, curwslt);
+#endif
+
+	newws();
+	dsnewws();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_wslt() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_wslt(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%c", curwslt + 'A');
+
+	vbank(0);
+	vcputsv(waveob, 64, wdbox[n][4], wdbox[n][5],
+		wdbox[n][6] + 1, wdbox[n][7] + WSLT_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_wslt() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_wslt(nn, k)
+short nn;
+register short  k;
+{
+	register short n;
+
+	n = nn & 0xFF;
+
+#if DEBUGIT
+	printf("nd_wslt($%04X, %d)\r\n", nn, k);
+#endif
+
+	if (k GT 1)
+		return(FAILURE);
+
+	ebuf[0] = k + 'A';
+	ebuf[1] = '\0';
+
+	dspbuf[0] = k + 'A';
+	dspbuf[1] = '\0';
+
+#if DEBUGIT
+	printf("nd_wslt($%04X, %d):  ebuf[%s]\r\n", nn, k, ebuf);
+#endif
+
+	vbank(0);
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advwcur();
+	return(SUCCESS);
+}
Index: ram/etwvce.c
===================================================================
--- ram/etwvce.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/etwvce.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,127 @@
+/*
+   =============================================================================
+	etwvce.c -- waveshape editor - voice field handlers
+	Version 8 -- 1987-12-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "wsdsp.h"
+
+extern	short	advwcur();
+
+extern	unsigned	*waveob;
+
+extern	short	stcrow, stccol, curvce;
+
+extern	short	wdbox[][8];
+
+extern	char	dspbuf[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_wvce() -- load the edit buffer
+   =============================================================================
+*/
+
+short
+et_wvce(n)
+short n;
+{
+	sprintf(ebuf, "%02d", curvce + 1);
+	ebflag = TRUE;
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	ef_wvce() -- parse (unload) the edit buffer
+   =============================================================================
+*/
+
+short
+ef_wvce(n)
+short n;
+{
+	register short i, tmpval;
+
+	ebuf[2] = '\0';			/* terminate the string in ebuf */
+	ebflag = FALSE;
+	tmpval = 0;
+
+	for (i = 0; i < 2; i++)		/* convert from ASCII to binary */
+		tmpval = (tmpval * 10) + (ebuf[i] - '0');
+
+	if ((tmpval EQ 0) OR (tmpval GT 12))
+		return(FAILURE);
+
+	newvce(tmpval - 1);
+	wwins();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_wvce() -- (re)display the field
+   =============================================================================
+*/
+
+short
+rd_wvce(nn)
+short nn;
+{
+	register short n;
+
+	n = nn & 0xFF;
+	sprintf(dspbuf, "%02d", curvce + 1);
+
+	vbank(0);
+	vcputsv(waveob, 64, wdbox[n][4], wdbox[n][5],
+		wdbox[n][6], wdbox[n][7] + WVCE_OFF, dspbuf, 14);
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	nd_wvce() -- handle new data entry
+   =============================================================================
+*/
+
+short
+nd_wvce(nn, k)
+short nn;
+register short  k;
+{
+	register short ec, n;
+
+	n = nn & 0xFF;
+	ec = stccol - cfetp->flcol;	/* setup edit buffer column */
+	ebuf[ec] = k + '0';
+	ebuf[2] = '\0';
+
+	dspbuf[0] = k + '0';
+	dspbuf[1] = '\0';
+
+	vbank(0);
+	vcputsv(waveob, 64, WS_ENTRY, wdbox[n][5],
+		stcrow, stccol, dspbuf, 14);
+
+	advwcur();
+	return(SUCCESS);
+}
Index: ram/execins.s
===================================================================
--- ram/execins.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/execins.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,220 @@
+* ------------------------------------------------------------------------------
+* execins.s -- execute an instrument selection
+* Version 9 -- 1988-09-09 -- D.N. Lynx Crowe
+*
+* Hand optimized C object code from:  execins.c -- ver 2 -- 1988-06-29
+* ------------------------------------------------------------------------------
+*
+		.text
+*
+DOUBLED		.equ	1			* double output to WS table
+*
+		.xdef	_execins
+*
+		.xref	_clrvce
+		.xref	_execkey
+*
+		.xref	_io_fpu
+		.xref	_instmod
+		.xref	_s_inst
+		.xref	_idefs
+		.xref	_vbufs
+*
+* register equates
+* ----------------
+SYNC		.equ	D4
+OLDSR		.equ	D5
+VCE		.equ	D7
+*
+IP		.equ	A5
+P1		.equ	A4
+P2		.equ	A3
+*
+P3		.equ	A2
+P4		.equ	A1
+*
+* parameter offsets
+* -----------------
+VOICE		.equ	8
+INS		.equ	10
+TAG		.equ	12
+*
+		.page
+*
+_execins:	link	A6,#0			* link stack frames
+		movem.l	D3-VCE/P2-IP,-(sp)	* preserve registers
+		move.w	VOICE(A6),VCE		* get voice number
+		move.w	VCE,D0			* calculate IP
+		add.w	D0,D0			* ...
+		add.w	D0,D0			* ...
+		lea	vibtabl,A0		* ...
+		movea.l	0(A0,D0.W),IP		* ...
+		add.l	#_vbufs,IP		* ...
+		move.w	VCE,(sp)		* clrvce(vce)
+		jsr	_clrvce			* ...
+		tst.w	TAG(A6)			* if (tag) {
+		beq	L2			* ...
+*
+		move.l	IP,P1			* p1 = ip;
+		move.w	INS(A6),D0		* p2 = &idefs[ins]
+		add.w	D0,D0			* ...
+		add.w	D0,D0			* ...
+		lea	vibtabl,A0		* ...
+		movea.l	0(A0,D0.W),P2		* ...
+		add.l	#_idefs,P2		* ...
+		move.w	#1968,D0		* set move count
+*
+L6:		move.w	(P2)+,(P1)+		* load voice buffer
+		dbra	D0,L6			* ...
+*
+		.page
+*
+		move.w	VCE,D0			* calculate FPU offset for voice
+		move.w	#9,D1			* ...
+		asl.w	D1,D0			* ...
+		asl.w	#1,D0			* ...
+		ext.l	D0			* ...
+		move.l	D0,P1			* ...
+		move.l	D0,P3			* ...
+		add.l	#_io_fpu,P1		* point P1 at FPU WS A
+		add.l	#$202,P1		* ...
+		lea	1778(IP),P2		* point P2 at instdef WS A
+		add.l	#_io_fpu,P3		* point P3 at FPU WS B
+		add.l	#2,P3			* ...
+		lea	2858(IP),P4		* point P4 at instdef WS B
+		move.w	#253,D0			* setup move count
+*
+		.ifne	DOUBLED
+		move.l	P1,-(a7)		* save P1 on stack
+		move.l	P2,-(a7)		* save P2 on stack
+		move.l	P3,-(a7)		* save P3 on stack
+		move.l	P4,-(a7)		* save P4 on stack
+		move.w	D0,-(a7)		* save D0 on stack
+		.endc
+*
+		move.w	SR,OLDSR		* turn off FPU interrupts
+		move.w	#$2200,SR		* ...
+*
+L10:		move.w	(P2)+,(P1)+		* set FPU WS A from instdef
+		nop				* delay for FPU timing
+		nop				* ...
+		nop				* ...
+		move.w	(P4)+,(P3)+		* set FPU WS B from instdef
+		nop				* delay for FPU timing
+		nop				* ...
+		dbra	D0,L10			* loop until done
+*
+		.ifne	DOUBLED
+		move.w	(a7)+,D0		* restore D0 from stack
+		movea.l	(a7)+,P4		* restore P4 from stack
+		movea.l	(a7)+,P3		* restore P3 from stack
+		movea.l	(a7)+,P2		* restore P2 from stack
+		movea.l	(a7)+,P1		* restore P1 from stack
+*
+L10A:		move.w	(P2)+,(P1)+		* set FPU WS A from instdef
+		nop				* delay for FPU timing
+		nop				* ...
+		nop				* ...
+		move.w	(P4)+,(P3)+		* set FPU WS B from instdef
+		nop				* delay for FPU timing
+		nop				* ...
+		dbra	D0,L10A			* loop until done
+*
+		.endc
+*
+		move.w	OLDSR,SR		* enable FPU interrupts
+*
+		.page
+*
+		move.w	VCE,A0			* instmod[vce] = FALSE
+		add.l	A0,A0			* ...
+		add.l	#_instmod,A0		* ...
+		clr.w	(A0)			* ...
+		move.w	VCE,A0			* s_inst[vce] = ins
+		add.l	A0,A0			* ...
+		add.l	#_s_inst,A0		* ...
+		move.w	INS(A6),(A0)		* ...
+		move.b	70(IP),SYNC		* get config bits
+		ext.w	SYNC			* ...
+		asl.w	#8,SYNC			* ...
+		btst	#2,74(IP)		* sync 2nd osc
+		beq	L15			* ...
+*
+		ori.w	#$2000,SYNC		* ...
+*
+L15:		btst	#2,75(IP)		* sync 3rd osc
+		beq	L16			* ...
+*
+		ori.w	#$4000,SYNC		* ...
+*
+L16:		btst	#2,76(IP)		* sync 4th osc
+		beq	L17			* ...
+*
+		ori.w	#$8000,SYNC		* ...
+*
+L17:		move.w	VCE,A0			* send sync to FPU
+		add.l	A0,A0			* ...
+		add.l	#_io_fpu,A0		* ...
+		add.l	#$5FE0,A0		* ...
+		move.w	SYNC,(A0)		* ...
+*
+L2:		move.w	#1,(sp)			* execkey(-1, 0, vce, 1)
+		move.w	VCE,-(sp)		* ...
+		clr.w	-(sp)			* ...
+		move.w	#-1,-(sp)		* ...
+		jsr	_execkey		* ...
+		addq.l	#6,sp			* ...
+		tst.l	(sp)+			* clean up stack
+		movem.l	(sp)+,SYNC-VCE/P2-IP	* restore registers
+		unlk	A6			* unlink stack frames
+		rts				* return
+*
+		.page
+*
+		.data
+*
+* vibtabl -- voice and instrument buffer offset table
+* -------    ----------------------------------------
+vibtabl:	.dc.l	0		* 0
+		.dc.l	3938		* 1
+		.dc.l	7876		* 2
+		.dc.l	11814		* 3
+		.dc.l	15752		* 4
+		.dc.l	19690		* 5
+		.dc.l	23628		* 6
+		.dc.l	27566		* 7
+		.dc.l	31504		* 8
+		.dc.l	35442		* 9
+		.dc.l	39380		* 10
+		.dc.l	43318		* 11
+		.dc.l	47256		* 12
+		.dc.l	51194		* 13
+		.dc.l	55132		* 14
+		.dc.l	59070		* 15
+		.dc.l	63008		* 16
+		.dc.l	66946		* 17
+		.dc.l	70884		* 18
+		.dc.l	74822		* 19
+		.dc.l	78760		* 20
+		.dc.l	82698		* 21
+		.dc.l	86636		* 22
+		.dc.l	90574		* 23
+		.dc.l	94512		* 24
+		.dc.l	98450		* 25
+		.dc.l	102388		* 26
+		.dc.l	106326		* 27
+		.dc.l	110264		* 28
+		.dc.l	114202		* 29
+		.dc.l	118140		* 30
+		.dc.l	122078		* 31
+		.dc.l	126016		* 32
+		.dc.l	129954		* 33
+		.dc.l	133892		* 34
+		.dc.l	137830		* 35
+		.dc.l	141768		* 36
+		.dc.l	145706		* 37
+		.dc.l	149644		* 38
+		.dc.l	153582		* 39
+		.dc.l	157520		* 40
+*
+		.end
Index: ram/execkey.s
===================================================================
--- ram/execkey.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/execkey.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,7533 @@
+* ------------------------------------------------------------------------------
+* execkey.s -- execute key -- FPU function start subroutine
+* Version 15 -- 1988-08-29 -- D.N. Lynx Crowe
+* Hand optimized version of execkey() and fnstart() from C compiler output
+* ------------------------------------------------------------------------------
+		.text
+*
+LOC_EOR		.equ	0
+LOC_SUB		.equ	1
+*
+		.xdef	_execkey
+*
+		.xref	_xgetran
+*
+		.xref	_rsntab
+		.xref	_expbit
+		.xref	_io_fpu
+		.xref	_legato
+		.xref	_prstab
+		.xref	_ptoftab
+		.xref	_timemlt
+		.xref	_valents
+		.xref	_vbufs
+		.xref	_vce2grp
+		.xref	_vce2trg
+		.xref	_veltab
+		.xref	_vpsms
+*
+		.page
+*
+* Offsets for execkey() parameters
+* -------------------------------- 
+TRG		.equ	8		* WORD -- trigger
+PCH		.equ	10		* WORD -- pitch
+VCE		.equ	12		* WORD -- voice  (0..11)
+TAG		.equ	14		* WORD -- I_TM_... inversion tag
+*
+* Register variables
+* ------------------
+A_FP		.equ	A5		* LONG -- struct idfnhdr *
+A_FPU		.equ	A4		* LONG -- FPU base address
+A_SMP		.equ	A3		* LONG -- struct sment *
+*
+R_FPMANT	.equ	D7		* WORD -- FPU time mantissa
+R_FPEXP		.equ	D6		* WORD -- FPU time exponent
+R_FPCTL		.equ	D5		* WORD -- FPU control word
+R_I		.equ	D4		* WORD -- loop index
+R_FPVAL		.equ	D3		* WORD -- FPU value
+*
+* Local (stack) variables
+* -----------------------
+PT		.equ	-4		* LONG -- instpnt *
+VEP		.equ	-8		* LONG -- struct valent *
+OLDI		.equ	-10		* WORD -- old IPL  (sr)
+OCTYPE		.equ	-12		* WORD -- oscillator 1 mode / scratch
+VP		.equ	-14		* WORD -- voice # + function # index
+SRCNUM		.equ	-16		* WORD -- general source #
+SRCVAL		.equ	-18		* WORD -- general source value
+TSRCVAL		.equ	-20		* WORD -- temporary general source value
+MLTVAL		.equ	-22		* WORD -- general source multiplier
+TFPVAL		.equ	-24		* WORD -- temporary FPU value
+LTMP		.equ	-28		* LONG -- long temporary
+IP		.equ	-32		* LONG -- struct instdef *
+GROUP		.equ	-34		* WORD -- group number << 4
+*
+* Symbolic constants
+* ------------------
+LASTLOCL	.equ	GROUP		* last local on the stack
+*
+FPU_DI		.equ	$2200		* sr value for disabling FPU interrupts
+PITCHMAX	.equ	21920		* maximum pitch value
+VALMAX		.equ	$00007D00	* maximum FPU value
+VALMIN		.equ	$FFFF8300	* minimum FPU value
+VBLEN		.equ	3938		* length of a voice buffer
+LSPCH		.equ	2		* left shift for pitch sources
+*
+		.page
+*
+* execkey(trg, pch, vce)
+* short trg, pch, vce;
+* {
+*
+_execkey:	link	A6,#LASTLOCL
+		movem.l	D2-R_FPMANT/A_SMP-A_FP,-(sp)
+*
+*	ip = &vbufs[vce];
+*
+		move.w	VCE(A6),D0
+		asl.w	#2,D0
+		lea	vbtab,A0
+		move.l	0(A0,D0.W),IP(A6)
+*
+*	vce2trg[vce] = trg;
+*
+		lsr.w	#1,D0
+		lea	_vce2trg,A0
+		move.w	TRG(A6),0(A0,D0.W)
+*
+*	group = (vce2grp[vce] - 1) << 4;
+*
+		move.w	VCE(A6),A0
+		add.l	A0,A0
+		move.l	#_vce2grp,A1
+		clr.l	D0
+		move.w	0(A0,A1.l),D0
+		sub.w	#1,D0
+		asl.w	#4,D0
+		move.w	D0,GROUP(A6)
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 0 -- Frq 1
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[0].idftmd & I_TM_KEY) {
+*
+		move.l	IP(A6),A0
+		move.b	93(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN00A
+*
+		jmp	FN01
+*
+*	vp = (vce << 4) + 1;
+*
+FN00A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#1,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[0];
+*
+		move.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F00L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F00L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F00L122
+*
+		asl	#2,D0
+		lea	F00L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F00L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F00L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F00L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F00L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F00L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F00L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F00L119:	move.w	PCH(A6),D0
+		asr.w	#7,D0
+		and.w	#$00FF,D0
+		move.w	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move.w	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F00L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F00L120:	move.w	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move.w	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F00L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F00L121:	move.w	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move.w	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F00L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F00L122:	move.l	VEP(A6),A0
+		move.w	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = addpch(tsrcval, 0);
+*
+F00L114:	move.w	TSRCVAL(A6),D0
+		ext.l	D0
+		asr.l	#5,D0
+*		sub.l	#500,D0
+		asl.l	#LSPCH,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F00L129A
+*
+		move.l	#PITCHMAX,D0
+*
+F00L129A:	move	D0,SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F00L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F00L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F00L144
+*
+		asl	#2,D0
+		lea	F00L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F00L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F00L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F00L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F00L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F00L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F00L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F00L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F00L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F00L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F00L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F00L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F00L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F00L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F00L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F00L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F00L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F00L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F00L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F00L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptim & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F00L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		octype = ip->idhos1c & OC_MOD;
+*
+F00L152:	move.l	IP(A6),A0
+		move.b	74(A0),D0
+		and	#3,D0
+*
+*		if ((octype EQ OC_FRQ) OR (octype EQ OC_PCH))
+*
+		cmp	#2,D0
+		beq	F00L1001
+*
+		cmp	#3,D0
+		bne	F00L153
+*
+*			fp->idfpch = ip->idhos1v;
+*
+F00L1001:	move.l	IP(A6),A0
+		move	78(A0),(A_FP)
+		bra	F00L154
+*
+*		else
+*			fp->idfpch = pch + ip->idhos1v;
+*
+F00L153:	move.w	PCH(A6),D0
+		ext.l	D0
+		move.w	78(A0),D1
+		ext.l	D1
+		add.l	d1,d0
+*
+*		if (fp->idfpch > PITCHMAX)
+*			fp->idfpch = PITCHMAX;
+*
+		cmp.l	#PITCHMAX,d0
+		ble	F00153A
+*
+		move.l	#PITCHMAX,d0
+*
+F00153A:	move.w	d0,(A_FP)
+*
+*		fpval = addpch(tfpval, fp->idfpch);
+*
+F00L154:	move.w	TFPVAL(A6),D1
+		ext.l	D1
+		asr.l	#5,D1
+		sub.l	#500,D1
+		asl.l	#LSPCH,D1
+		move.w	(A_FP),D0
+		ext.l	D0
+		add.l	D1,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F00L154A
+*
+		move.l	#PITCHMAX,D0
+*
+F00L154A:	move	D0,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F00L168:	clr.b	10(A0)
+		add.l	#12,A0
+		dbra	D0,F00L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F00L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F00L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F00L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F00L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F00L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*    }
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 1 -- Frq 2
+* ------------------------------------------------------------------------------
+*    if (legato) {
+*
+*	legato = 0;
+*	return;
+*    }
+FN01:		tst.w	_legato
+		beq	FN01AA
+*
+		clr.w	_legato
+		bra	FNEXIT
+*
+*    if (ip->idhfnc[1].idftmd & I_TM_KEY) {
+*
+FN01AA:		move.l	IP(A6),A0
+		move.b	105(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN01A
+*
+		jmp	FN02
+*
+*	vp = (vce << 4) + 3;
+*
+FN01A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#3,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[1];
+*
+		move.l	#12,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F01L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F01L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F01L122
+*
+		asl	#2,D0
+		lea	F01L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F01L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F01L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F01L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F01L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F01L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F01L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F01L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F01L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F01L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F01L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F01L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F01L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F01L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = addpch(tsrcval, 0);
+*
+F01L114:	move.w	TSRCVAL(A6),D0
+		ext.l	D0
+		asr.l	#5,D0
+*		sub.l	#500,D0
+		asl.l	#LSPCH,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F01L129A
+*
+		move.l	#PITCHMAX,D0
+*
+F01L129A:	move	D0,SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F01L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F01L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F01L144
+*
+		asl	#2,D0
+		lea	F01L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F01L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F01L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F01L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F01L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F01L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F01L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F01L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F01L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F01L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F01L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F01L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F01L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F01L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F01L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F01L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F01L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F01L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F01L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F01L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F01L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = ip->idhos2v;
+*
+F01L155:	move.l	IP(A6),A0
+		move.w	80(A0),(A_FP)
+*
+*		fpval = addpch(tfpval, fp_>idfpch);
+*
+		move.w	TFPVAL(A6),D1
+		ext.l	D1
+		asr.l	#5,D1
+		sub.l	#500,D1
+		asl.l	#LSPCH,D1
+		move.w	(A_FP),D0
+		ext.l	D0
+		add.l	D1,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F01L155A
+*
+		move.l	#PITCHMAX,D0
+*
+F01L155A:	move	D0,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F01L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F01L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F01L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F01L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F01L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F01L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F01L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 2 -- Frq 3
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[2].idftmd & I_TM_KEY) {
+*
+FN02:		move.l	IP(A6),A0
+		move.b	117(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN02A
+*
+		jmp	FN03
+*
+*	vp = (vce << 4) + 5;
+*
+FN02A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#5,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[2];
+*
+		move.l	#24,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F02L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F02L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F02L122
+*
+		asl	#2,D0
+		lea	F02L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F02L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F02L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F02L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F02L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F02L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F02L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F02L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F02L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F02L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F02L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F02L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F02L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F02L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = addpch(tsrcval, 0);
+*
+F02L114:	move.w	TSRCVAL(A6),D0
+		ext.l	D0
+		asr.l	#5,D0
+*		sub.l	#500,D0
+		asl.l	#LSPCH,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F02L129A
+*
+		move.l	#PITCHMAX,D0
+*
+F02L129A:	move	D0,SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F02L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F02L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F02L144
+*
+		asl	#2,D0
+		lea	F02L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F02L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F02L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F02L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F02L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F02L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F02L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F02L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F02L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F02L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F02L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F02L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F02L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F02L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F02L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F02L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F02L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F02L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F02L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F02L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F02L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = ip->idhos3v;
+*
+F02L156:	move.l	IP(A6),A0
+		move.w	82(A0),(A_FP)
+*
+*		fpval = addpch(tfpval, fp->idfpch);
+*
+		move.w	TFPVAL(A6),D1
+		ext.l	D1
+		asr.l	#5,D1
+		sub.l	#500,D1
+		asl.l	#LSPCH,D1
+		move.w	(A_FP),D0
+		ext.l	D0
+		add.l	D1,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F02L156A
+*
+		move.l	#PITCHMAX,D0
+*
+F02L156A:	move	D0,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F02L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F02L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F02L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F02L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F02L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F02L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F02L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 3 -- Frq 4
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[3].idftmd & I_TM_KEY) {
+*
+FN03:		move.l	IP(A6),A0
+		move.b	129(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN03A
+*
+		jmp	FN04
+*
+*	vp = (vce << 4) + 7;
+*
+FN03A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#7,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[3];
+*
+		move.l	#36,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F03L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F03L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F03L122
+*
+		asl	#2,D0
+		lea	F03L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F03L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F03L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F03L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F03L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F03L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F03L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F03L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F03L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F03L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F03L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F03L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F03L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F03L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = addpch(tsrcval, 0);
+*
+F03L114:	move.w	TSRCVAL(A6),D0
+		ext.l	D0
+		asr.l	#5,D0
+*		sub.l	#500,D0
+		asl.l	#LSPCH,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F03L129A
+*
+		move.l	#PITCHMAX,D0
+
+F03L129A:	move	D0,SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F03L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F03L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F03L144
+*
+		asl	#2,D0
+		lea	F03L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F03L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F03L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F03L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F03L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F03L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F03L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F03L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F03L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F03L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F03L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F03L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F03L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F03L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F03L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F03L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F03L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F03L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F03L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F03L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F03L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = ip->idhos4v;
+*
+F03L157:	move.l	IP(A6),A0
+		move.w	84(A0),(A_FP)
+*
+*		fpval = addpch(tfpval, fp->idfpch);
+*
+		move.w	TFPVAL(A6),D1
+		ext.l	D1
+		asr.l	#5,D1
+		sub.l	#500,D1
+		asl.l	#LSPCH,D1
+		move.w	(A_FP),D0
+		ext.l	D0
+		add.l	D1,D0
+		cmp.l	#PITCHMAX,D0
+		ble	F03L157A
+*
+		move.l	#PITCHMAX,D0
+*
+F03L157A:	move	D0,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F03L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F03L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F03L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F03L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F03L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F03L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F03L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 4 -- Filtr
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[4].idftmd & I_TM_KEY) {
+*
+FN04:		move.l	IP(A6),A0
+		move.b	141(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN04A
+*
+		jmp	FN05
+*
+*	vp = (vce << 4) + 10;
+*
+FN04A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#10,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[4];
+*
+		move.l	#48,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+		.page
+*
+*	Added code:
+*
+*		output resonance via table lookup with FPU interrupts off
+*
+		lea	_rsntab,A0
+		clr.w	D0
+		move.b	9(A_FP),D0
+		add.w	D0,D0
+		move.w	0(A0,D0.W),D1
+		move.w	VCE(A6),D0
+		asl.w	#4,d0
+		add.w	#6,d0
+		asl.w	#5,D0
+		ext.l	D0
+		move.l	D0,A0
+		add.l	#_io_fpu+$4000,A0
+		move.w	sr,OLDI(A6)
+		move.w	#FPU_DI,sr
+		move.w	d1,2(A0)
+		add.w	#1,OCTYPE(A6)
+		move.w	d1,$1C(A0)
+		add.w	#1,OCTYPE(A6)
+		move.w	#$0015,(A0)
+		move.w	OLDI(A6),sr
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F04L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F04L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F04L122
+*
+		asl	#2,D0
+		lea	F04L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F04L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F04L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F04L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F04L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F04L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F04L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F04L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F04L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F04L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F04L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F04L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F04L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F04L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		ltmp = ((long)tsrcval >> 1) + ((long)tsrcval >> 2);
+*
+F04L114:	move	TSRCVAL(A6),D0
+		ext.l	D0
+		asr.l	#1,D0
+		move	TSRCVAL(A6),D1
+		ext.l	D1
+		asr.l	#2,D1
+		add.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F04L131
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F04L132
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F04L131:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F04L132
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		srcval = (short)ltmp;
+*
+F04L132:	move.l	LTMP(A6),D0
+		move	D0,SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F04L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F04L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F04L144
+*
+		asl	#2,D0
+		lea	F04L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F04L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F04L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F04L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F04L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F04L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F04L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F04L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F04L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F04L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F04L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F04L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F04L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F04L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F04L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F04L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F04L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F04L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F04L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F04L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F04L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F04L158:	move	PCH(A6),(A_FP)
+*
+*		ltmp = ((long)tfpval >> 1) + ((longtfpval >>2)
+*			+ (long)fp->idfpch;
+*
+		move	TFPVAL(A6),D0
+		ext.l	D0
+		asr.l	#1,D0
+		move	TFPVAL(A6),D1
+		ext.l	D1
+		asr.l	#2,D1
+		add.l	D1,D0
+		move	(A_FP),D1
+		ext.l	D1
+		add.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F04L159
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F04L160
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F04L159:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F04L160
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		fpval = (short)ltmp;
+*
+F04L160:	move.l	LTMP(A6),D0
+		move	D0,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F04L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F04L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F04L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F04L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F04L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F04L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F04L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 5 -- Loctn
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[5].idftmd & I_TM_KEY) {
+*
+FN05:		move.l	IP(A6),A0
+		move.b	153(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN05A
+*
+		jmp	FN06
+*
+*	vp = (vce << 4) + 4;
+*
+FN05A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#4,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[5];
+*
+		move.l	#60,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F05L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F05L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F05L122
+*
+		asl	#2,D0
+		lea	F05L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F05L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F05L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F05L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F05L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F05L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F05L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F05L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F05L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F05L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F05L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F05L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F05L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F05L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F05L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F05L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F05L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F05L144
+*
+		asl	#2,D0
+		lea	F05L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F05L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F05L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F05L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F05L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F05L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F05L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F05L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F05L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F05L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F05L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F05L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F05L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F05L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F05L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F05L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F05L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F05L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F05L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F05L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F05L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F05L163:	move	PCH(A6),(A_FP)
+*
+*		if (tfpval > VALMAX)
+*			tfpval = VALMAX;
+*		else if (tfpval < 0)
+*			tfpval = 0;
+*
+		move.w	TFPVAL(A6),D0
+		cmp.w	#$7D00,D0
+		ble	F05L163B
+*
+		move.w	#$7D00,D0
+		bra	F05L163A
+		
+F05L163B:	tst.w	D0
+		bpl	F05L163A
+*
+		clr.w	D0
+*
+*#if	LOC_EOR
+*		fpval = (tfpval << 1) ^ 0x8000;
+*#endif
+*
+		.ifne	LOC_EOR
+F05L163A:	add.w	D0,D0
+		eor.w	#$8000,D0
+		.endc
+*
+*#if	LOC_SUB
+*		fpval = ((tfpval >> 5) - 500) << 6;
+*#endif
+*
+		.ifne	LOC_SUB
+F05L163A:	asr.w	#5,D0
+		sub.w	#500,D0
+		asl.w	#6,D0
+		.endc
+*
+		move.w	D0,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F05L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F05L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F05L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F05L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F05L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F05L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F05L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 6 -- Ind 1
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[2].idftmd & I_TM_KEY) {
+*
+FN06:		move.l	IP(A6),A0
+		move.b	165(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN06A
+*
+		jmp	FN07
+*
+*	vp = (vce << 4) + 9;
+*
+FN06A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#9,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[6];
+*
+		move.l	#72,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F06L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F06L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F06L122
+*
+		asl	#2,D0
+		lea	F06L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F06L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F06L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F06L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F06L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F06L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F06L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F06L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F06L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F06L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F06L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F06L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F06L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F06L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F06L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F06L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F06L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F06L144
+*
+		asl	#2,D0
+		lea	F06L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F06L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F06L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F06L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F06L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F06L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F06L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F06L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F06L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F06L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F06L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F06L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F06L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F06L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F06L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F06L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F06L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F06L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F06L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F06L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F06L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F06L163:	move	PCH(A6),(A_FP)
+*
+*		fpval = tfpval;
+*
+		move	TFPVAL(A6),R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F06L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F06L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F06L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F06L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F06L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F06L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F06L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 7 -- Ind 2
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[7].idftmd & I_TM_KEY) {
+*
+FN07:		move.l	IP(A6),A0
+		move.b	177(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN07A
+*
+		jmp	FN08
+*
+*	vp = (vce << 4) + 11;
+*
+FN07A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#11,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[7];
+*
+		move.l	#84,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F07L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F07L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F07L122
+*
+		asl	#2,D0
+		lea	F07L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F07L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F07L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F07L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F07L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F07L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F07L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F07L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F07L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F07L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F07L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F07L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F07L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F07L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F07L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F07L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F07L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F07L144
+*
+		asl	#2,D0
+		lea	F07L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F07L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F07L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F07L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F07L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F07L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F07L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F07L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F07L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F07L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F07L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F07L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F07L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F07L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F07L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F07L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F07L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F07L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F07L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F07L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F07L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F07L163:	move	PCH(A6),(A_FP)
+*
+*		fpval = tfpval;
+*
+		move	TFPVAL(A6),R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F07L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F07L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F07L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F07L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F07L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F07L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F07L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 8 -- Ind 3
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[8].idftmd & I_TM_KEY) {
+*
+FN08:		move.l	IP(A6),A0
+		move.b	189(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN08A
+*
+		jmp	FN09
+*
+*	vp = (vce << 4) + 12;
+*
+FN08A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#12,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[8];
+*
+		move.l	#96,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F08L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F08L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F08L122
+*
+		asl	#2,D0
+		lea	F08L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F08L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F08L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F08L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F08L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F08L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F08L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F08L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F08L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F08L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F08L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F08L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F08L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F08L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F08L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F08L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F08L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F08L144
+*
+		asl	#2,D0
+		lea	F08L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F08L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F08L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F08L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F08L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F08L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F08L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F08L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F08L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F08L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F08L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F08L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F08L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F08L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F08L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F08L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F08L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F08L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F08L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F08L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F08L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F08L163:	move	PCH(A6),(A_FP)
+*
+*		fpval = tfpval;
+*
+		move	TFPVAL(A6),R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F08L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F08L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F08L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F08L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F08L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F08L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F08L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 9 -- Ind 4
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[9].idftmd & I_TM_KEY) {
+*
+FN09:		move.l	IP(A6),A0
+		move.b	201(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN09A
+*
+		jmp	FN10
+*
+*	vp = (vce << 4) + 13;
+*
+FN09A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#13,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[9];
+*
+		move.l	#108,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F09L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F09L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F09L122
+*
+		asl	#2,D0
+		lea	F09L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F09L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F09L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F09L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F09L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F09L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F09L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F09L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F09L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F09L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F09L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F09L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F09L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F09L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F09L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F09L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F09L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F09L144
+*
+		asl	#2,D0
+		lea	F09L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F09L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F09L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F09L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F09L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F09L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F09L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F09L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F09L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F09L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F09L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F09L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F09L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F09L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F09L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F09L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F09L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F09L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F09L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F09L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F09L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F09L163:	move	PCH(A6),(A_FP)
+*
+*		fpval = tfpval;
+*
+		move	TFPVAL(A6),R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F09L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F09L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F09L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F09L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F09L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F09L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F09L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 10 -- Ind 5
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[10].idftmd & I_TM_KEY) {
+*
+FN10:		move.l	IP(A6),A0
+		move.b	213(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN10A
+*
+		jmp	FN11
+*
+*	vp = (vce << 4) + 14;
+*
+FN10A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#14,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[10];
+*
+		move.l	#120,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F10L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F10L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F10L122
+*
+		asl	#2,D0
+		lea	F10L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F10L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F10L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F10L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F10L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F10L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F10L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F10L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F10L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F10L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F10L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F10L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F10L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F10L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F10L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F10L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F10L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F10L144
+*
+		asl	#2,D0
+		lea	F10L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F10L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F10L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F10L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F10L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F10L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F10L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F10L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F10L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F10L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F10L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F10L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F10L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F10L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F10L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F10L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F10L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F10L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F10L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F10L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F10L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F10L163:	move	PCH(A6),(A_FP)
+*
+*		fpval = tfpval;
+*
+		move	TFPVAL(A6),R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F10L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F10L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F10L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F10L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F10L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F10L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F10L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 11 -- Ind 6
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[11].idftmd & I_TM_KEY) {
+*
+FN11:		move.l	IP(A6),A0
+		move.b	225(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN11A
+*
+		jmp	FN12
+*
+*	vp = (vce << 4) + 15;
+*
+FN11A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#15,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[11];
+*
+		move.l	#132,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F11L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F11L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F11L122
+*
+		asl	#2,D0
+		lea	F11L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F11L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F11L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F11L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F11L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F11L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F11L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F11L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F11L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F11L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F11L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F11L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F11L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F11L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F11L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F11L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F11L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F11L144
+*
+		asl	#2,D0
+		lea	F11L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F11L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F11L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F11L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F11L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F11L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F11L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F11L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F11L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F11L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F11L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F11L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F11L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F11L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F11L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F11L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F11L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F11L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F11L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F11L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F11L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F11L163:	move	PCH(A6),(A_FP)
+*
+*		fpval = tfpval;
+*
+		move	TFPVAL(A6),R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F11L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F11L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F11L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F11L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F11L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F11L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F11L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+		.page
+* ------------------------------------------------------------------------------
+* Start function 12 -- Level
+* ------------------------------------------------------------------------------
+*
+*    if (ip->idhfnc[12].idftmd & I_TM_KEY) {
+*
+FN12:		move.l	IP(A6),A0
+		move.b	237(A0),D0
+		move.w	TAG(A6),D1
+		eor.w	D1,D0
+		btst	#0,D0
+		bne	FN12A
+*
+		jmp	FNEXIT
+*
+*	vp = (vce << 4) + 2;
+*
+FN12A:		move	VCE(A6),D0
+		asl	#4,D0
+		add.w	#2,D0
+		move	D0,VP(A6)
+*
+*	fpu = io_fpu + FPU_OFNC + (vp << 4);
+*
+		asl	#5,D0
+		ext.l	D0
+		move.l	D0,A_FPU
+		add.l	#_io_fpu+$4000,A_FPU
+*
+*	fp = &ip->idhfnc[12];
+*
+		move.l	#144,A_FP
+		add.l	IP(A6),A_FP
+		add.l	#86,A_FP
+*
+*	pt = &ip->idhpnt[fp->idfpt1];
+*
+		clr.l	D0
+		move.b	6(A_FP),D0
+		lsl.l	#2,D0
+		move.l	D0,D1
+		add.l	D0,D0
+		add.l	D1,D0
+		add.l	IP(A6),D0
+		add.l	#242,D0
+		move.l	D0,PT(A6)
+*
+		.page
+*
+*	srcnum = group | fp->idfsrc;
+*
+		move.w	GROUP(A6),D0
+		ext.l	D0
+		clr.l	D1
+		move.b	4(A_FP),D1
+		or	D1,D0
+		move	D0,SRCNUM(A6)
+*
+*	vep = &valents[srcnum];
+*
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		add.l	#_valents,D0
+		move.l	D0,VEP(A6)
+*
+*	smp = vpsms[vp];
+*
+		move	VP(A6),A0
+		add.l	A0,A0
+		add.l	A0,A0
+		add.l	#_vpsms,A0
+		move.l	(A0),A_SMP
+*
+*	if (srcnum NE smp->sm) {
+*
+		clr	D0
+		move	10(A_SMP),D0
+		cmp	SRCNUM(A6),D0
+		beq	F12L113
+*
+*		(smp->prv)->nxt = smp->nxt;
+*
+		move.l	4(A_SMP),A0
+		move.l	(A_SMP),(A0)
+*
+*		(smp->nxt)->prv = smp->prv;
+*
+		move.l	(A_SMP),A0
+		move.l	4(A_SMP),4(A0)
+*
+*		smp->prv = (struct sment *)vep;
+*
+		move.l	VEP(A6),4(A_SMP)
+*
+*		smp->nxt = vep->nxt;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),(A_SMP)
+*
+*		(vep->nxt)->prv = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	(A0),A0
+		move.l	A_SMP,4(A0)
+*
+*		vep->nxt = smp;
+*
+		move.l	VEP(A6),A0
+		move.l	A_SMP,(A0)
+*
+*		smp->sm = srcnum;
+*
+		move	SRCNUM(A6),10(A_SMP)
+*
+*	}
+*
+*	mltval = fp->idfmlt;
+*
+F12L113:	move	2(A_FP),MLTVAL(A6)
+*
+		.page
+*
+*	switch (fp->idfsrc) {
+*
+		move.b	4(A_FP),D0
+		ext.w	d0
+		cmp	#10,D0
+		bhi	F12L122
+*
+		asl	#2,D0
+		lea	F12L123,A0
+		movea.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*	case SM_NONE:
+*		mltval = 0;
+*
+F12L116:	clr	MLTVAL(A6)
+*
+*		tsrcval = 0;
+*
+		clr	TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F12L114
+*
+*	case SM_RAND:
+*		tsrcval = xgetran(mltval);
+*
+F12L117:	move	MLTVAL(A6),(sp)
+		jsr	_xgetran
+		move	D0,TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F12L114
+*
+*	case SM_PTCH:
+*		tsrcval = pch;
+*
+F12L118:	move	PCH(A6),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F12L114
+*
+		.page
+*
+*	case SM_FREQ:
+*		tsrcval = ptoftab[(pch >> 7) & 0x00FF];
+*
+F12L119:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		add.l	#_ptoftab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F12L114
+*
+*	case SM_KVEL:
+*		tsrcval = veltab[trg];
+*
+F12L120:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_veltab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F12L114
+*
+*	case SM_KPRS:
+*		tsrcval = prstab[trg];
+*
+F12L121:	move	TRG(A6),A0
+		add.l	A0,A0
+		add.l	#_prstab,A0
+		move	(A0),TSRCVAL(A6)
+*
+*		break;
+*
+		bra	F12L114
+*
+*	default:
+*		tsrcval = vep->val;
+*
+F12L122:	move.l	VEP(A6),A0
+		move	8(A0),TSRCVAL(A6)
+*
+*	}
+*
+		.page
+*
+*		srcval = tsrcval;
+*
+F12L114:	move	TSRCVAL(A6),SRCVAL(A6)
+*
+		.page
+*
+*	if (pt->ipvsrc) {
+*
+F12L124:	move.l	PT(A6),A0
+		tst.b	6(A0)
+		beq	F12L136
+*
+*		switch (pt->ipvsrc) {
+*
+		move.l	PT(A6),A0
+		move.b	6(A0),D0
+		ext.w	D0
+		sub	#1,D0
+		cmp	#9,D0
+		bhi	F12L144
+*
+		asl	#2,D0
+		lea	F12L145,A0
+		move.l	0(A0,D0.W),A0
+		jmp	(A0)
+*
+*		case SM_RAND:
+*			ltmp = xgetran(pt_>ipvmlt);
+*
+F12L139:	move.l	PT(A6),A0
+		move	4(A0),(sp)
+		jsr	_xgetran
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F12L137
+*
+*		case SM_PTCH:
+*			ltmp = pch;
+*
+F12L140:	move	PCH(A6),A0
+		move.l	A0,LTMP(A6)
+*
+*			break;
+*
+		bra	F12L137
+*
+		.page
+*
+*		case SM_FREQ:
+*			ltmp = ptoftab[(pch >> 7) & 0x00FF];
+*
+F12L141:	move	PCH(A6),D0
+		asr	#7,D0
+		and	#255,D0
+		move	D0,A0
+		add.l	A0,A0
+		move.l	#_ptoftab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F12L137
+*
+*		case SM_KVEL:
+*			ltmp = veltab[trg];
+*
+F12L142:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_veltab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F12L137
+*
+		.page
+*
+*		case SM_KPRS:
+*			ltmp = prstab[trg];
+*
+F12L143:	move	TRG(A6),A0
+		add.l	A0,A0
+		move.l	#_prstab,A1
+		move	0(A0,A1.l),D0
+		ext.l	D0
+		move.l	D0,LTMP(A6)
+*
+*			break;
+*
+		bra	F12L137
+*
+		.page
+*
+*		default:
+*			ltmp = valents[group | pt->ipvsrc].val;
+*
+F12L144:	move.l	PT(A6),A0
+		clr.l	D0
+		move.b	6(A0),D0
+		or.w	GROUP(A6),D0
+		add.l	D0,D0
+		move.l	D0,D1
+		lsl.l	#2,D0
+		add.l	D1,D0
+		move.l	D0,A0
+		move.l	#_valents,A1
+		clr.l	D0
+		move	8(A0,A1.l),D0
+		move.l	D0,LTMP(A6)
+*
+*		}
+*
+*
+		.page
+*
+*		ltmp = (ltmp * pt->ipvmlt) >> 15;
+*
+F12L137:	move.l	PT(A6),A0
+		move.w	4(A0),D0
+		move.w	LTMP+2(A6),D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move.l	D0,LTMP(A6)
+*
+*		ltmp += (long)pt->ipval;
+*
+		move.l	PT(A6),A0
+		move	2(A0),D0
+		ext.l	D0
+		add.l	D0,LTMP(A6)
+*
+*		if (ltmp GT (long)VALMAX)
+*			ltmp = (long)VALMAX;
+*
+		cmp.l	#VALMAX,LTMP(A6)
+		ble	F12L146
+*
+		move.l	#VALMAX,LTMP(A6)
+		bra	F12L147
+*
+*		else if (ltmp LT (long)VALMIN)
+*			ltmp = (long)VALMIN;
+*
+F12L146:	cmp.l	#VALMIN,LTMP(A6)
+		bge	F12L147
+*
+		move.l	#VALMIN,LTMP(A6)
+*
+*		tfpval = (short)ltmp;
+*
+F12L147:	move.w	LTMP+2(A6),TFPVAL(A6)
+		bra	F12L149
+*
+*	} else {
+*
+*		tfpval = pt->ipval;
+*
+F12L136:	move.l	PT(A6),A0
+		move	2(A0),TFPVAL(A6)
+*
+*	}
+*
+		.page
+*
+*	fpmant = (((long)pt->iptom & 0x0000FFF0L)
+*		* ((long)timemlt & 0x0000FFFFL)) >> 15;
+*
+F12L149:	move.l	PT(A6),A0
+		move.w	(A0),D0
+		move.w	D0,D2
+		andi.w	#$FFF0,D0
+		move.w	_timemlt,D1
+		muls	D1,D0
+		move.l	#15,D1
+		asr.l	D1,D0
+		move	D0,R_FPMANT
+*
+*	fpexp = expbit[pt->iptim & 0x000F];
+*
+		and	#$000F,D2
+		move	D2,A0
+		add.l	A0,A0
+		add.l	#_expbit,A0
+		move	(A0),R_FPEXP
+*
+		.page
+*
+*		fp->idfpch = pch;
+*
+F12L162:	move	PCH(A6),(A_FP)
+*
+*		fpval = ((tfpval >> 5) - 500) << 6;
+*
+		move	TFPVAL(A6),R_FPVAL
+		asr	#5,R_FPVAL
+		add	#-500,R_FPVAL
+		asl	#6,R_FPVAL
+*
+		.page
+*
+		move.b	5(A_FP),D0
+		ext.w	D0
+		sub.w	#1,D0
+		movea.l	PT(A6),A0
+*
+*	oldi = setipl(FPU_DI);
+*
+		move	sr,OLDI(A6)
+		move	#FPU_DI,sr
+*
+F12L168:	clr.b	10(A0)
+		add.l	#12,a0
+		dbra	D0,F12L168
+*
+		.page
+*
+*	fp->idftmd ^= I_NVBITS;
+*
+F12L165:	eor.b	#24,7(A_FP)
+*
+*	fpctl = (fp->idftmd & (I_NRATIO | I_NVBITS)) | 0x0003;
+*
+		move.b	7(A_FP),R_FPCTL
+		and	#28,R_FPCTL
+		or	#3,R_FPCTL
+*
+*	fp->idfcpt = fp->idfpt1;
+*
+		move.b	6(A_FP),8(A_FP)
+*
+*	fp->idftmd |= I_ACTIVE;
+*
+		or.b	#2,7(A_FP)
+*
+*	fp->idftrf = trg;
+*
+		move	TRG(A6),10(A_FP)
+*
+*	*(fpu + (long)FPU_TCV1) = srcval;
+*
+		move	SRCVAL(A6),$8(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TSF1) = mltval;
+*
+		move	MLTVAL(A6),$A(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TMNT) = fpmant;
+*
+		move	R_FPMANT,$14(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TEXP) = fpexp;
+*
+		move	R_FPEXP,$16(A_FPU)
+*
+*	++octype;
+*
+		add	#1,OCTYPE(A6)
+*
+		.page
+*
+*	if (fp->idftmd & I_VNSUBN)
+*
+		btst	#3,7(A_FP)
+		beq	F12L169
+*
+*		*(fpu + (long)FPU_TNV1) = fpval;
+*
+		move	R_FPVAL,$1C(A_FPU)
+		bra	F12L170
+*
+*	else
+*		*(fpu + (long)FPU_TNV0) = fpval;
+*
+F12L169:	move	R_FPVAL,2(A_FPU)
+*
+*	++octype;
+*
+F12L170:	add	#1,OCTYPE(A6)
+*
+*	*(fpu + (long)FPU_TCTL) = fpctl;
+*
+		move	R_FPCTL,(A_FPU)
+*
+*	setipl(oldi);
+*
+		move	OLDI(A6),sr
+*
+*    }
+*
+		.page
+*
+FNEXIT:		tst.l	(sp)+
+		movem.l	(sp)+,R_FPVAL-R_FPMANT/A_SMP-A_FP
+		unlk	A6
+		rts
+*
+* }
+*
+		.page
+*
+		.data
+*
+* Jump tables for switch statements
+* ---------------------------------
+*
+F00L123:	.dc.l	F00L116
+		.dc.l	F00L117
+		.dc.l	F00L122
+		.dc.l	F00L122
+		.dc.l	F00L122
+		.dc.l	F00L118
+		.dc.l	F00L121
+		.dc.l	F00L120
+		.dc.l	F00L122
+		.dc.l	F00L122
+		.dc.l	F00L119
+*
+F00L145:	.dc.l	F00L139
+		.dc.l	F00L144
+		.dc.l	F00L144
+		.dc.l	F00L144
+		.dc.l	F00L140
+		.dc.l	F00L143
+		.dc.l	F00L142
+		.dc.l	F00L144
+		.dc.l	F00L144
+		.dc.l	F00L141
+*
+F01L123:	.dc.l	F01L116
+		.dc.l	F01L117
+		.dc.l	F01L122
+		.dc.l	F01L122
+		.dc.l	F01L122
+		.dc.l	F01L118
+		.dc.l	F01L121
+		.dc.l	F01L120
+		.dc.l	F01L122
+		.dc.l	F01L122
+		.dc.l	F01L119
+*
+F01L145:	.dc.l	F01L139
+		.dc.l	F01L144
+		.dc.l	F01L144
+		.dc.l	F01L144
+		.dc.l	F01L140
+		.dc.l	F01L143
+		.dc.l	F01L142
+		.dc.l	F01L144
+		.dc.l	F01L144
+		.dc.l	F01L141
+*
+F02L123:	.dc.l	F02L116
+		.dc.l	F02L117
+		.dc.l	F02L122
+		.dc.l	F02L122
+		.dc.l	F02L122
+		.dc.l	F02L118
+		.dc.l	F02L121
+		.dc.l	F02L120
+		.dc.l	F02L122
+		.dc.l	F02L122
+		.dc.l	F02L119
+*
+F02L145:	.dc.l	F02L139
+		.dc.l	F02L144
+		.dc.l	F02L144
+		.dc.l	F02L144
+		.dc.l	F02L140
+		.dc.l	F02L143
+		.dc.l	F02L142
+		.dc.l	F02L144
+		.dc.l	F02L144
+		.dc.l	F02L141
+*
+F03L123:	.dc.l	F03L116
+		.dc.l	F03L117
+		.dc.l	F03L122
+		.dc.l	F03L122
+		.dc.l	F03L122
+		.dc.l	F03L118
+		.dc.l	F03L121
+		.dc.l	F03L120
+		.dc.l	F03L122
+		.dc.l	F03L122
+		.dc.l	F03L119
+*
+F03L145:	.dc.l	F03L139
+		.dc.l	F03L144
+		.dc.l	F03L144
+		.dc.l	F03L144
+		.dc.l	F03L140
+		.dc.l	F03L143
+		.dc.l	F03L142
+		.dc.l	F03L144
+		.dc.l	F03L144
+		.dc.l	F03L141
+*
+F04L123:	.dc.l	F04L116
+		.dc.l	F04L117
+		.dc.l	F04L122
+		.dc.l	F04L122
+		.dc.l	F04L122
+		.dc.l	F04L118
+		.dc.l	F04L121
+		.dc.l	F04L120
+		.dc.l	F04L122
+		.dc.l	F04L122
+		.dc.l	F04L119
+*
+F04L145:	.dc.l	F04L139
+		.dc.l	F04L144
+		.dc.l	F04L144
+		.dc.l	F04L144
+		.dc.l	F04L140
+		.dc.l	F04L143
+		.dc.l	F04L142
+		.dc.l	F04L144
+		.dc.l	F04L144
+		.dc.l	F04L141
+*
+F05L123:	.dc.l	F05L116
+		.dc.l	F05L117
+		.dc.l	F05L122
+		.dc.l	F05L122
+		.dc.l	F05L122
+		.dc.l	F05L118
+		.dc.l	F05L121
+		.dc.l	F05L120
+		.dc.l	F05L122
+		.dc.l	F05L122
+		.dc.l	F05L119
+*
+F05L145:	.dc.l	F05L139
+		.dc.l	F05L144
+		.dc.l	F05L144
+		.dc.l	F05L144
+		.dc.l	F05L140
+		.dc.l	F05L143
+		.dc.l	F05L142
+		.dc.l	F05L144
+		.dc.l	F05L144
+		.dc.l	F05L141
+*
+F06L123:	.dc.l	F06L116
+		.dc.l	F06L117
+		.dc.l	F06L122
+		.dc.l	F06L122
+		.dc.l	F06L122
+		.dc.l	F06L118
+		.dc.l	F06L121
+		.dc.l	F06L120
+		.dc.l	F06L122
+		.dc.l	F06L122
+		.dc.l	F06L119
+*
+F06L145:	.dc.l	F06L139
+		.dc.l	F06L144
+		.dc.l	F06L144
+		.dc.l	F06L144
+		.dc.l	F06L140
+		.dc.l	F06L143
+		.dc.l	F06L142
+		.dc.l	F06L144
+		.dc.l	F06L144
+		.dc.l	F06L141
+*
+F07L123:	.dc.l	F07L116
+		.dc.l	F07L117
+		.dc.l	F07L122
+		.dc.l	F07L122
+		.dc.l	F07L122
+		.dc.l	F07L118
+		.dc.l	F07L121
+		.dc.l	F07L120
+		.dc.l	F07L122
+		.dc.l	F07L122
+		.dc.l	F07L119
+*
+F07L145:	.dc.l	F07L139
+		.dc.l	F07L144
+		.dc.l	F07L144
+		.dc.l	F07L144
+		.dc.l	F07L140
+		.dc.l	F07L143
+		.dc.l	F07L142
+		.dc.l	F07L144
+		.dc.l	F07L144
+		.dc.l	F07L141
+*
+F08L123:	.dc.l	F08L116
+		.dc.l	F08L117
+		.dc.l	F08L122
+		.dc.l	F08L122
+		.dc.l	F08L122
+		.dc.l	F08L118
+		.dc.l	F08L121
+		.dc.l	F08L120
+		.dc.l	F08L122
+		.dc.l	F08L122
+		.dc.l	F08L119
+*
+F08L145:	.dc.l	F08L139
+		.dc.l	F08L144
+		.dc.l	F08L144
+		.dc.l	F08L144
+		.dc.l	F08L140
+		.dc.l	F08L143
+		.dc.l	F08L142
+		.dc.l	F08L144
+		.dc.l	F08L144
+		.dc.l	F08L141
+*
+F09L123:	.dc.l	F09L116
+		.dc.l	F09L117
+		.dc.l	F09L122
+		.dc.l	F09L122
+		.dc.l	F09L122
+		.dc.l	F09L118
+		.dc.l	F09L121
+		.dc.l	F09L120
+		.dc.l	F09L122
+		.dc.l	F09L122
+		.dc.l	F09L119
+*
+F09L145:	.dc.l	F09L139
+		.dc.l	F09L144
+		.dc.l	F09L144
+		.dc.l	F09L144
+		.dc.l	F09L140
+		.dc.l	F09L143
+		.dc.l	F09L142
+		.dc.l	F09L144
+		.dc.l	F09L144
+		.dc.l	F09L141
+*
+F10L123:	.dc.l	F10L116
+		.dc.l	F10L117
+		.dc.l	F10L122
+		.dc.l	F10L122
+		.dc.l	F10L122
+		.dc.l	F10L118
+		.dc.l	F10L121
+		.dc.l	F10L120
+		.dc.l	F10L122
+		.dc.l	F10L122
+		.dc.l	F10L119
+*
+F10L145:	.dc.l	F10L139
+		.dc.l	F10L144
+		.dc.l	F10L144
+		.dc.l	F10L144
+		.dc.l	F10L140
+		.dc.l	F10L143
+		.dc.l	F10L142
+		.dc.l	F10L144
+		.dc.l	F10L144
+		.dc.l	F10L141
+*
+F11L123:	.dc.l	F11L116
+		.dc.l	F11L117
+		.dc.l	F11L122
+		.dc.l	F11L122
+		.dc.l	F11L122
+		.dc.l	F11L118
+		.dc.l	F11L121
+		.dc.l	F11L120
+		.dc.l	F11L122
+		.dc.l	F11L122
+		.dc.l	F11L119
+*
+F11L145:	.dc.l	F11L139
+		.dc.l	F11L144
+		.dc.l	F11L144
+		.dc.l	F11L144
+		.dc.l	F11L140
+		.dc.l	F11L143
+		.dc.l	F11L142
+		.dc.l	F11L144
+		.dc.l	F11L144
+		.dc.l	F11L141
+*
+F12L123:	.dc.l	F12L116
+		.dc.l	F12L117
+		.dc.l	F12L122
+		.dc.l	F12L122
+		.dc.l	F12L122
+		.dc.l	F12L118
+		.dc.l	F12L121
+		.dc.l	F12L120
+		.dc.l	F12L122
+		.dc.l	F12L122
+		.dc.l	F12L119
+*
+F12L145:	.dc.l	F12L139
+		.dc.l	F12L144
+		.dc.l	F12L144
+		.dc.l	F12L144
+		.dc.l	F12L140
+		.dc.l	F12L143
+		.dc.l	F12L142
+		.dc.l	F12L144
+		.dc.l	F12L144
+		.dc.l	F12L141
+*
+* vbtab -- vbuf pointer table -- indexed by voice number
+* -----    ---------------------------------------------
+vbtab:		.dc.l	_vbufs
+		.dc.l	_vbufs+VBLEN
+		.dc.l	_vbufs+(2*VBLEN)
+		.dc.l	_vbufs+(3*VBLEN)
+		.dc.l	_vbufs+(4*VBLEN)
+		.dc.l	_vbufs+(5*VBLEN)
+		.dc.l	_vbufs+(6*VBLEN)
+		.dc.l	_vbufs+(7*VBLEN)
+		.dc.l	_vbufs+(8*VBLEN)
+		.dc.l	_vbufs+(9*VBLEN)
+		.dc.l	_vbufs+(10*VBLEN)
+		.dc.l	_vbufs+(11*VBLEN)
+*
+		.end
Index: ram/fcnote.c
===================================================================
--- ram/fcnote.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/fcnote.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,126 @@
+/*
+   =============================================================================
+	fcnote.c -- MIDAS-VII note edit -- find complete note
+	Version 1 -- 1988-05-17 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "score.h"
+#include "scfns.h"
+#include "neddefs.h"
+
+#define	TO_LFT		(TO_BAK + 1)
+
+extern	long	ctime;		/* time at cursor */
+
+/*
+   =============================================================================
+	fcnote() -- find complete note
+
+	Arguments:
+
+		grp		group number
+		tnote		note number
+
+		ctime		cursor time to search from
+
+	Returns:
+
+		E_NULL		couldn't find the note
+		ptr		pointer to the begin event for the note
+
+		p_nbeg		pointer to note begin event
+		p_nend		pointer to note end event
+		t_note		duration of the note
+   =============================================================================
+*/
+
+/* 
+
+*/
+
+struct n_entry *
+fcnote(grp, tnote)
+register short grp, tnote;
+{
+	register struct n_entry *bp, *ep;
+	register short en, eg, et;
+	long t_left;
+
+	/* setup initial search parameters */
+
+	bp = (struct n_entry *)ep_adj(p_cur, 0, ctime);		/* cursor loc */
+	t_left  = t_cur - TO_LFT;		/* time at left edge of screen */
+	p_nbeg = (struct n_entry *)E_NULL;	/* no begin yet */
+	p_nend = (struct n_entry *)E_NULL;	/* no end yet */
+	t_note = 0L;				/* no duration yet */
+
+	FOREVER {	/* scan left from cursor */
+
+		et = 0x007F & bp->e_type;
+		en = bp->e_note;
+		eg = bp->e_group;
+
+		if ((bp->e_time LT t_left) OR (et EQ EV_SCORE)) {
+
+			/* done -- can't see begin,  or note not there */
+
+			return(E_NULL);
+
+		} else if ((et EQ EV_NEND) AND (en EQ tnote) AND (eg EQ grp)) {
+
+			/* done -- hit note end first -- notes overlap */
+
+			return(E_NULL);
+/* 
+
+*/
+		} else if ((et EQ EV_NBEG) AND (en EQ tnote) AND (eg EQ grp)) {
+
+			/* found note begin -- possible note starting at bp */
+
+			ep = bp->e_fwd;		/* scan to right of begin */
+
+			FOREVER {	/* scan right from note begin */
+
+				et = 0x007F & ep->e_type;	/* event type */
+				en = ep->e_note;		/* note */
+				eg = ep->e_group;		/* group */
+
+				if ((et EQ EV_NBEG) AND (en EQ tnote) AND
+				    (eg EQ grp)) {
+
+					/* hit note begin first -- done -- notes overlap */
+
+					return(E_NULL);
+/* 
+
+*/								
+				} else if ((et EQ EV_NEND) AND (en EQ tnote) AND
+					   (eg EQ grp)) {
+
+					/* hit note end -- done -- found complete note */
+
+					p_nbeg = bp;	/* note begin */
+					p_nend = ep;	/* note end */
+					t_note = ep->e_time - bp->e_time;
+					return(bp);
+
+				} else if (et EQ EV_FINI) {
+
+					/* hit score end -- done -- can't find end */
+
+					return(E_NULL);
+				}
+
+				ep = ep->e_fwd;		/* scan right */
+
+			}	/* end FOREVER */
+
+		}	/* end if */
+
+		bp = bp->e_bak;		/* scan left */
+
+	}	/* end FOREVER */
+}
Index: ram/fpuint.s
===================================================================
--- ram/fpuint.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/fpuint.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,969 @@
+* ------------------------------------------------------------------------------
+* fpuint.s -- process FPU interrupts / clear FPU
+* Version 63 -- 1988-08-31 -- D.N. Lynx Crowe
+* ------------------------------------------------------------------------------
+		.text
+*
+		.xdef	_fpuint		* process an FPU interrupt
+		.xdef	_fpuclr		* reset the FPU
+		.xdef	_clrvce		* quiet a voice
+*
+		.xdef	_fputrap	* a very good debug trap point
+*
+		.xdef	_fp_resv	* 'spare' function reset value table
+		.xdef	_fpuifnc	* FPU interrupt code  (voice / function)
+*
+		.xref	_irand		* ranged random number function
+		.xref	_scope		* diagnostic scope function
+		.xref	_xgetran	* random number function
+*
+		.xref	_expbit
+		.xref	_funcndx
+		.xref	_initcfg
+		.xref	_ndisp
+		.xref	_pflist
+		.xref	_pfqhdr
+		.xref	_prstab
+		.xref	_ptoftab
+		.xref	_scopef
+		.xref	_timemlt
+		.xref	_trgtab
+		.xref	_valents
+		.xref	_vce2grp
+		.xref	_vce2trg
+		.xref	_veltab
+*
+		.page
+* ------------------------------------------------------------------------------
+* Register usage
+* --------------
+*	d0	scratch
+*	d1	FPU function index
+*	d2	point index from FH_CPT  (idfcpt)
+*	d3	scratch
+*	d4	jump point number from PT_PAR1  (ippar1)
+*	d5	scratch
+*
+*	a0	scratch
+*	a1	function header base
+*	a2	point table base
+*	a3	FPU base
+*
+* ------------------------------------------------------------------------------
+* FPU definitions
+* ---------------
+*
+UPD_BIT		.equ	$0001			* update bit  (1 = update)
+INT_BIT		.equ	$0002			* int. bit    (0 = disable)
+RAT_BIT		.equ	$0004			* ratio bit   (0 = ratio)
+*
+VSUBNBIT	.equ	3			* new value select bit number
+VAL_BITS	.equ	$0018			* new value select bit mask
+*
+MSK_RNVB	.equ	$000C			* new value / ratio bits
+MSK_ONVB	.equ	$0010			* old new value bit
+*
+FKILL		.equ	$0014			* kill value for function
+FSEND		.equ	$0015			* send new value to function
+*
+CLREXP		.equ	$8000			* clear value for time exponent
+CLRMNT		.equ	$8000			* clear value for time mantissa
+*
+* ------------------------------------------------------------------------------
+* Miscellaneous definitions
+* -------------------------
+*
+PCHMAX		.equ	21920			* maximum pitch value
+VALMAX		.equ	32000			* maximum value to send to FPU
+VALMIN		.equ	-32000			* minimum value to send to FPU
+*
+LSPCH		.equ	2			* left shift for sources to freq
+*
+VALLEN		.equ	10			* length of the 'valent' struct
+VT_VAL		.equ	8			* value offset in 'valent'
+*
+		.page
+* ------------------------------------------------------------------------------
+* FPU addresses
+* -------------
+*
+FPUBASE		.equ	$180000			* FPU base address
+*
+FPUWST		.equ	FPUBASE			* FPU waveshape base
+FPUFUNC		.equ	FPUBASE+$4000		* FPU function base
+FPUINT1		.equ	FPUBASE+$4000		* FPU int. input address (R/O)
+FPUINT2		.equ	FPUBASE+$6000		* FPU int. reset address (W/O)
+FPUCFG		.equ	FPUBASE+$5FE0		* FPU config. data address (W/O)
+*
+F_CTL		.equ	$00			* control word
+F_VAL10		.equ	$02			* new value "10"
+F_CV1		.equ	$08			* control voltage 1
+F_SF1		.equ	$0A			* scale factor 1
+F_CV2		.equ	$0C			* control voltage 2
+F_SF2		.equ	$0E			* scale factor 2
+F_CV3		.equ	$10			* control voltage 3
+F_SF3		.equ	$12			* scale factor 3
+F_MNT		.equ	$14			* time mantissa
+F_EXP		.equ	$16			* time exponent
+F_VAL01		.equ	$1C			* new value "01"
+*
+P_FREQ1		.equ	$0020			* frequency 1
+P_FREQ2		.equ	$0060			* frequency 2
+P_FREQ3		.equ	$00A0			* frequency 3
+P_FREQ4		.equ	$00E0			* frequency 4
+P_FILTER	.equ	$0140			* filter
+P_FILTRQ	.equ	$00C0			* filter q
+*
+P_INDEX1	.equ	$0120			* index 1
+P_INDEX2	.equ	$0160			* index 2
+P_INDEX3	.equ	$0180			* index 3
+P_INDEX4	.equ	$01A0			* index 4
+P_INDEX5	.equ	$01C0			* index 5
+P_INDEX6	.equ	$01E0			* index 6
+*
+P_LEVEL		.equ	$0040			* level
+*
+P_LOCN		.equ	$0080			* location
+P_DYNAM		.equ	$0100			* dynamics
+*
+		.page
+* ------------------------------------------------------------------------------
+* Structure definitions
+* ------------------------------------------------------------------------------
+* The following MUST match the idfnhdr structure definition in instdsp.h:
+*
+FH_LEN		.equ	12		* length of the idfnhdr structure
+*
+FH_PCH		.equ	0		* WORD - pitch offset  (freq1 only)
+FH_MLT		.equ	2		* WORD - overall value multiplier
+FH_SRC		.equ	4		* BYTE - overall value source
+FH_PIF		.equ	5		* BYTE - # of points in the function
+FH_PT1		.equ	6		* BYTE - index of first point
+FH_TMD		.equ	7		* BYTE - trigger mode / control bits
+FH_CPT		.equ	8		* BYTE - current point
+FH_PRM		.equ	9		* BYTE - misc. function parameter
+FH_TRG		.equ	10		* WORD - trigger
+*
+I_ACTIVE	.equ	1		* 'Active' bit number        (in FH_TMD)
+*
+MSK_CTL		.equ	$001C		* mask for FPU hardware bits (in FH_TMD)
+*
+* ------------------------------------------------------------------------------
+* The following MUST match the instpnt structure definition in instdsp.h:
+*
+PT_LEN		.equ	12		* length of the instpnt structure
+*
+PT_TIM		.equ	0		* WORD - time (packed)
+PT_VAL		.equ	2		* WORD - value
+PT_VMLT		.equ	4		* WORD - value multiplier
+PT_VSRC		.equ	6		* BYTE - value source
+PT_ACT		.equ	7		* BYTE - action
+PT_PAR1		.equ	8		* BYTE - parameter 1
+PT_PAR2		.equ	9		* BYTE - parameter 2
+PT_PAR3		.equ	10		* BYTE - parameter 3
+PT_PAD		.equ	11		* BYTE - padding for even boundary
+*
+MSK_MNT		.equ	$FFF0		* mask for mantissa  (in PT_TIM)
+MSK_EXP		.equ	$000F		* mask for exponent  (in PT_TIM)
+*
+MAX_ACT		.equ	7		* maximum action code value
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* pflist definitions -- must match those in instdsp.h
+*
+PF_NEXT		.equ	0
+PF_TRIG		.equ	4
+PF_FUNC		.equ	6
+PF_D1		.equ	8
+PF_D2		.equ	12
+PF_D4		.equ	16
+PF_A1		.equ	20
+PF_A2		.equ	24
+PF_A3		.equ	28
+* ------------------------------------------------------------------------------
+* Source definitions -- must match those in 'smdefs.h'
+*
+SM_RAND		.equ	1		* random
+SM_PTCH		.equ	5		* pitch
+SM_KPRS		.equ	6		* key pressure
+SM_KVEL		.equ	7		* key velocity
+SM_FREQ		.equ	10		* frequency
+*
+		.page
+* ------------------------------------------------------------------------------
+* _fpuint() -- process FPU interrupts
+*
+*	void
+*	fpuint();
+*
+*		Processes FPU interrupts.  Must be the target of vector 26,
+*		which is Autovector Interrupt level 2.
+*
+* ------------------------------------------------------------------------------
+*
+_fpuint:	movem.l	d0-d5/a0-a3,-(a7)	* preserve registers we use
+		move.w	FPUINT1,d0	* read FPU interrupt status
+		andi.w	#$00FF,d0	* mask out garbage in MS bits
+		move.w	d0,_fpuifnc	* save for later use
+		move.w	_ndisp,d1	* get display number
+		cmpi.w	#11,d1		* see if we display
+		bne	nodisp		* jump if not
+*
+		tst.w	_scopef		* ...
+		beq	nodisp		* ...
+*
+		move.w	d0,-(a7)	* display value
+		jsr	_scope		* ...
+		tst.w	(a7)+		* ...
+*
+		move.w	_fpuifnc,d0	* get FPU status
+*
+nodisp:		move.w	d0,d1		* save in d1  (becomes function offset)
+*
+		lsl.w	#5,d1		* develop FPU function offset
+		lea	FPUFUNC,a3	* setup FPU function base address
+*
+		lsl.w	#3,d0		* develop funcndx[] index
+		lea	_funcndx,a0	* setup funcndx[] base address
+*
+		tst.l	0(a0,d0.W)	* see if function is defined
+		bne	fnok		* jump if so
+*
+		move.w	d1,d0		* get function offset in d0
+		andi.w	#$1E00,d0	* mask for voice number
+		cmpi.w	#$1800,d0	* see if it's a real voice  (0..11)
+		bge	fpexit		* don't send a kill if not a real voice
+*
+		move.w	#FKILL,F_CTL(a3,d1.W)	* kill the undefined function
+*
+fpexit:		clr.w	FPUINT2		* reset the FPU interrupt latch
+		movem.l	(a7)+,d0-d5/a0-a3	* restore the registers
+		rte			* return to interrupted code
+*
+		.page
+* ------------------------------------------------------------------------------
+* set up to process active functions,  stop ones that should be inactive
+* ------------------------------------------------------------------------------
+fnok:		movea.l	0(a0,d0.W),a1	* get pointer to function header
+		movea.l	4(a0,d0.W),a2	* get pointer to point table
+		btst	#I_ACTIVE,FH_TMD(a1)	* see if function is active
+		bne	doact		* go process action if so
+*
+* ------------------------------------------------------------------------------
+* stop a function
+* ------------------------------------------------------------------------------
+stopfn:		move.b	FH_TMD(a1),d0	* get function control bits
+		andi.w	#MSK_RNVB,d0	* mask for ratio / new new-value bit
+		move.w	d0,d3		* isolate new new-value bit
+		add.w	d3,d3		* ... from function header
+		andi.w	#MSK_ONVB,d3	* ... shift to old new-value bit
+		or.w	d3,d0		* ... and put new bit in old bit	
+		move.w	d0,F_CTL(a3,d1.W)	* stop the function
+		bclr	#I_ACTIVE,FH_TMD(a1)	* reset the active bit
+		bra	fpexit		* go restore registers and exit
+*
+		.page
+* ------------------------------------------------------------------------------
+* setup for and dispatch to the proper action handler
+* ------------------------------------------------------------------------------
+doact:		clr.w	d2		* get current point index in d2
+		move.b	FH_CPT(a1),d2	* ...
+		lsl.w	#2,d2		* multiply it by the length of a point
+		move.w	d2,d0		* ...  (fast multiply by PT_LEN = 12
+		add.w	d2,d2		* ...   via shift and add)
+		add.w	d0,d2		* ...
+		clr.w	d4		* get jump point # into d4
+		move.b	PT_PAR1(a2,d2.W),d4	* ...
+		clr.w	d3		* get action code in d3
+		move.b	PT_ACT(a2,d2.W),d3	* ...
+		cmpi.b	#MAX_ACT,d3	* check against the limit
+		bgt	stopfn		* stop things if it's a bad action code
+*
+		lsl.w	#2,d3		* develop index to action dispatch table
+		lea	actab,a0	* get the address of the action handler
+		movea.l	0(a0,d3.W),a0	* ...
+*
+* ------------------------------------------------------------------------------
+* At this point we're ready to do the action associated with the point,
+* and the registers are set up,  and will remain,  as follows:
+*
+*	d1	FPU function index	a1	function header base
+*	d2	point table index	a2	point table base
+*					a3	FPU function base
+*	d4	jump point number
+*
+*	d0, d3, d5, and a0 are used as scratch throughout the code.
+*
+* ------------------------------------------------------------------------------
+*
+_fputrap:	jmp	(a0)		* dispatch to action handler
+*
+		.page
+* ------------------------------------------------------------------------------
+* act0 -- AC_NULL -- no action
+* ----    --------------------
+act0:		move.b	FH_PT1(a1),d0	* get first point number
+		add.b	FH_PIF(a1),d0	* add number of points in function
+		subq.b	#1,d0		* make it last point number
+		cmp.b	FH_CPT(a1),d0	* see if we're at the last point
+		beq	stopfn		* stop function if so
+*
+		addq.b	#1,FH_CPT(a1)	* update function header for next point
+		addi.w	#PT_LEN,d2	* advance the point index
+*
+* ------------------------------------------------------------------------------
+* outseg -- output a segment
+* ------    ----------------
+outseg:		move.w	PT_TIM(a2,d2.w),d3	* get packed time
+		move.w	d3,d0			* extract mantissa
+		andi.w	#MSK_MNT,d0		* ...
+		mulu	_timemlt,d0		* multiply by panel time pot value
+		lsr.l	#8,d0			* ... and scale it
+		lsr.l	#7,d0			* ...
+		move.w	d0,F_MNT(a3,d1.W)	* send mantissa to FPU
+		andi.w	#MSK_EXP,d3		* extract exponent code
+		add.w	d3,d3			* look up decoded exponent
+		lea	_expbit,a0		* ... in expbit
+		move.w	0(a0,d3.W),F_EXP(a3,d1.W)	* send exponent to FPU
+		move.w	PT_VAL(a2,d2.W),d3	* get the function value
+*
+* ------------------------------------------------------------------------------
+* get the point source, if any
+* ------------------------------------------------------------------------------
+		tst.w	PT_VMLT(a2,d2.W)	* see if we have a point mlt.
+		beq	nosrc			* don't do anything for zero
+*
+		clr.w	d0			* get the source number
+		move.b	PT_VSRC(a2,d2.W),d0	* ...
+		beq	nosrc			* don't do anything for zero
+*
+* ------------------------------------------------------------------------------
+* SM_RAND -- random
+* ------------------------------------------------------------------------------
+		cmpi.w	#SM_RAND,d0		* is this the random source ?
+		bne	srctyp0			* jump if not
+*
+		movem.l	d1-d2/a0-a2,-(a7)	* preserve registers around call
+		move.w	PT_VMLT(a2,d2.W),-(a7)	* pass multiplier to xgetran()
+		jsr	_xgetran		* call for a random number
+		tst.w	(a7)+			* clean up stack
+		movem.l	(a7)+,d1-d2/a0-a2	* restore registers
+		move.w	d0,d5			* put random value in the value register
+		bra	applym			* go apply the multiplier
+*
+		.page
+* ------------------------------------------------------------------------------
+* SM_FREQ -- frequency
+* ------------------------------------------------------------------------------
+srctyp0:	cmpi.w	#SM_FREQ,d0	* is this the frequency source ?
+		bne	srctyp1		* jump if not
+*
+		move.w	(a1),d0		* get the pitch
+		lsr.w	#6,d0		* shift to a word index
+		andi.w	#$01FE,d0	* mask out extraneous bits
+		lea	_ptoftab,a0	* get entry from ptoftab[]
+		move.w	0(a0,d0.W),d5	* ...
+		bra	applym		* go apply the multiplier
+*
+* ------------------------------------------------------------------------------
+* SM_PTCH -- pitch
+* ------------------------------------------------------------------------------
+srctyp1:	cmpi.w	#SM_PTCH,d0	* is this the pitch source ?
+		bne	srctyp2		* jump if not
+*
+		move.w	(a1),d5		* get the pitch as the value
+		bra	applym		* go apply the multiplier
+*
+* ------------------------------------------------------------------------------
+* SM_KVEL -- velocity
+* ------------------------------------------------------------------------------
+srctyp2:	cmpi.w	#SM_KVEL,d0	* is this the key velocity source ?
+		bne	srctyp3		* jump if not
+*
+		move.w	FH_TRG(a1),d0	* get the trigger number
+		add.w	d0,d0		* ... as a word index
+		lea	_veltab,a0	* ... into veltab[]
+		move.w	0(a0,d0.W),d5	* get the velocity from veltab[trg]
+		bra	applym		* go apply the multiplier
+*
+* ------------------------------------------------------------------------------
+* SM_KPRS -- pressure
+* ------------------------------------------------------------------------------
+srctyp3:	cmpi.w	#SM_KPRS,d0	* is this the key pressure source ?
+		bne	srctyp4		* jump if not  (must be an analog input)
+*
+		move.w	FH_TRG(a1),d0	* get the trigger number
+		add.w	d0,d0		* ... as a word index
+		lea	_prstab,a0	* ... into prstab[]
+		move.w	0(a0,d0.W),d5	* get the pressure from prstab[trg]
+		bra	applym		* go apply the multiplier
+*
+		.page
+* ------------------------------------------------------------------------------
+* all other sources come out of the valents[] array
+* ------------------------------------------------------------------------------
+srctyp4:	lea	_vce2grp,a0	* point at vce2grp[]
+		move.w	_fpuifnc,d5	* get voice number in d5
+		lsr.w	#3,d5		* ...
+		andi.w	#$001E,d5	* ... as a word index
+		move.w	0(a0,d5.W),d5	* get the group number
+		subq.w	#1,d5		* ...
+		lsl.w	#4,d5		* shift it left a nybble
+		or.w	d5,d0		* OR it into the source number
+		add.w	d0,d0		* make source number a valents[] index
+		move.w	d0,d5		* ... (fast multiply by VALLEN = 10
+		lsl.w	#2,d0		* ...  via shift and add)
+		add.w	d5,d0		* ...
+		lea	_valents,a0	* get base of valents[]
+		move.w	VT_VAL(a0,d0.W),d5	* get value
+*
+* ------------------------------------------------------------------------------
+* apply the multiplier to the source, and add it to the function value
+* ------------------------------------------------------------------------------
+applym:		muls	PT_VMLT(a2,d2.W),d5	* apply the multiplier
+		asr.l	#7,d5		* scale the result
+		asr.l	#8,d5		* ...
+		ext.l	d3		* add the function value
+		add.l	d3,d5		* ...
+		cmpi.l	#VALMAX,d5	* check for overflow
+		ble	srcmlt1		* jump if no overflow
+*
+		move.l	#VALMAX,d5	* limit at VALMAX
+		bra	srcmlt2		* ...
+*
+srcmlt1:	cmpi.l	#VALMIN,d5	* check for underflow
+		bge	srcmlt2		* jump if no underflow
+*
+		move.l	#VALMIN,d5	* limit at VALMIN
+*
+srcmlt2:	move.w	d5,d3		* setup value for output to FPU
+*
+		.page
+* ------------------------------------------------------------------------------
+* adjust the value according to the function type
+* ------------------------------------------------------------------------------
+nosrc:		move.w	d1,d0		* get function type
+		andi.w	#$01E0,d0	* ...
+*
+* ------------------------------------------------------------------------------
+* level or location
+* ------------------------------------------------------------------------------
+		cmpi.w	#P_LEVEL,d0	* see if it's the level
+		beq	outsegl		* jump if so
+*
+		cmpi.w	#P_LOCN,d0	* see if it's the location
+		bne	outsegf		* jump if not
+*
+		tst.w	d3		* check sign of value
+		bpl	outsegc		* jump if positive
+*
+		clr.w	d3		* force negative values to 0
+*
+outsegc:	asr.w	#5,d3		* shift value to LS bits
+		sub.w	#500,d3		* subtract 5.00 from value
+		asl.w	#6,d3		* readjust to MS bits
+		bra	outseg3		* go output the value
+*
+outsegl:	tst.w	d3		* check sign of value
+		bpl	outsegm		* jump if positive
+*
+		clr.w	d3		* limit negative values at 0
+*
+outsegm:	asr.w	#5,d3		* shift value to LS bits
+		sub.w	#500,d3		* subtract 5.00 from value
+		asl.w	#6,d3		* readjust to MS bits
+		bra	outseg3		* go output the value
+*
+		.page
+* ------------------------------------------------------------------------------
+* filter
+* ------------------------------------------------------------------------------
+outsegf:	cmpi.w	#P_FILTER,d0	* see if it's filter
+		bne	outsegp		* jump if not
+*
+		ext.l	d3		* make function value a long
+		asr.l	#1,d3		* multiply function value by .75
+		move.l	d3,d0		* ...  (fast multiply by .75
+		asr.l	#1,d0		* ...   via shift and add)
+		add.l	d0,d3		* ...
+		move.w	(a1),d0		* add pitch
+		ext.l	d0		* ...
+		add.l	d0,d3		* ...
+		cmpi.l	#VALMAX,d3	* see if it's within limits
+		ble	outsega		* ...
+*
+		move.w	#VALMAX,d3	* limit at VALMAX
+		bra	outseg3		* ...
+*
+outsega:	cmpi.l	#VALMIN,d3	* ...
+		bge	outseg3		* ...
+*
+		move.w	#VALMIN,d3	* limit at VALMIN
+		bra	outseg3		* ...
+*
+		.page
+* ------------------------------------------------------------------------------
+* freq 1..4
+* ------------------------------------------------------------------------------
+outsegp:	cmpi.w	#P_FREQ1,d0	* see if it's freq1
+		beq	outseg0		* go process freq1
+*
+outsegq:	cmpi.w	#P_FREQ2,d0	* see if it's freq2
+		beq	outseg0		* process it if so
+*
+		cmpi.w	#P_FREQ3,d0	* see if it's freq3
+		beq	outseg0		* process it if so
+*
+		cmpi.w	#P_FREQ4,d0	* see if it's freq4
+		bne	outseg3		* jump if not
+*
+outseg0:	ext.l	d3		* scale the point value to cents offset
+		asr.l	#5,d3		* ...
+		sub.l	#500,d3		* ... value - 500
+		asl.l	#LSPCH,d3	* mult. by 2 and scale for 1/2 cent lsb
+		move.w	(a1),d0		* add pitch from function header
+		ext.l	d0		* ...
+		add.l	d0,d3		* ...
+		cmp.l	#PCHMAX,d3	* see if result is valid
+		ble	outseg3		* jump if within pitch limits
+*
+		move.l	#PCHMAX,d3	* limit at maximum pitch
+*
+* ------------------------------------------------------------------------------
+* send the value to the FPU
+* ------------------------------------------------------------------------------
+outseg3:	move.b	FH_TMD(a1),d0	* get hardware bits from function header
+		eor.w	#VAL_BITS,d0	* toggle new value select bits
+		move.b	d0,FH_TMD(a1)	* store updated word
+		btst.l	#VSUBNBIT,d0	* check which value address to use
+		beq	outseg1
+*
+		move.w	d3,F_VAL01(a3,d1.W)	* send value to FPU
+		bra	outseg2
+*
+outseg1:	move.w	d3,F_VAL10(a3,d1.W)	* send value to FPU
+*
+outseg2:	andi.w	#MSK_CTL,d0		* mask off software bits
+		ori.w	#UPD_BIT+INT_BIT,d0	* set the update & !lastseg bits
+		move.w	d0,F_CTL(a3,d1.W)	* send control word to FPU
+		bra	fpexit			* done -- exit
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act1 -- AC_SUST -- pause if key is down  (sustain)
+* ----    ------------------------------------------
+act1:		move.w	_fpuifnc,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* point at voice to trigger table
+		move.w	0(a0,d0.W),d0	* get trigger table entry into d0
+		cmpi.w	#-1,d0		* see if voice is free
+		beq	act0		* continue function if so
+*
+		btst	#15,d0		* see if voice is held by a pedal
+		bne	act1a		* sustain if so
+*
+		btst	#14,d0		* see if voice is sustained by a pedal
+		bne	act1a		* sustain if so
+*
+		lea	_trgtab,a0	* point at trigger table
+		tst.b	0(a0,d0.W)	* check trigger status
+		beq	act0		* continue function if not active
+*
+act1a:		move.l	_pfqhdr,d3	* see if any pflist entries remain
+		beq	act0		* continue if not  (shouldn't happen!)
+*
+		move.b	FH_PT1(a1),d0	* get first point number
+		add.b	FH_PIF(a1),d0	* add base to first point
+		subq.b	#1,d0		* make d0 last point number
+		cmp.b	FH_CPT(a1),d0	* check current point number
+		beq	stopfn		* done if this is the last point
+*
+		addq.b	#1,FH_CPT(a1)		* update current point number
+		addi.w	#PT_LEN,d2		* advance the point index
+		movea.l	d3,a0			* acquire a new pflist entry
+		move.l	(a0),_pfqhdr		* ...
+		move.l	_pflist,(a0)		* chain it to pflist
+		move.l	a0,_pflist		* ...
+		move.w	FH_TRG(a1),PF_TRIG(a0)		* set trigger number in entry
+		move.w	_fpuifnc,PF_FUNC(a0)		* set v/p word in entry
+		movem.l	d1-d2/d4/a1-a3,PF_D1(a0)	* set registers in entry
+		move.b	FH_TMD(a1),d0		* stop the function
+		andi.w	#MSK_RNVB,d0		* ...
+		move.w	d0,d3			* ...
+		add.w	d3,d3			* ...
+		andi.w	#MSK_ONVB,d3		* ...
+		or.w	d3,d0			* ...
+		move.w	d0,F_CTL(a3,d1.W)	* ...
+		bra	fpexit			* exit
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act2 -- AC_ENBL -- stop if key is up
+* ----    ----------------------------
+act2:		move.w	_fpuifnc,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* check to see if voice is free
+		move.w	0(a0,d0.W),d0	* ...
+		cmpi.w	#-1,d0		* ...
+		beq	stopfn		* if so, stop the function
+*
+		btst	#15,d0		* see if voice is held
+		bne	act0		* continue if so
+*
+		btst	#14,d0		* ...
+		bne	act0		* ...
+*
+		lea	_trgtab,a0	* check trigger table entry
+		tst.b	0(a0,d0.W)	* ...
+		bne	act0		* if trigger is active, continue
+*
+		bra	stopfn		* if not, stop the function
+*
+* ------------------------------------------------------------------------------
+* act3 -- AC_JUMP -- unconditional jump
+* ----    -----------------------------
+act3:		cmp.b	FH_PIF(a1),d4	* check jump point against limit
+		bcc	stopfn		* stop function if jump point invalid
+*
+		clr.w	d2		* get index of first point
+		move.b	FH_PT1(a1),d2	* ...
+		add.b	d4,d2		* add jump point
+		move.b	d2,FH_CPT(a1)	* make it the current point
+		lsl.w	#2,d2		* develop new point index in d2
+		move.w	d2,d0		* ... (fast multiply by PT_LEN = 12
+		add.w	d2,d2		* ...  via shift and add)
+		add.w	d0,d2		* ...
+		bra	outseg		* output the segment
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act4 -- AC_LOOP -- jump to point PT_PAR1 PT_PAR2 times
+* ----    ----------------------------------------------
+act4:		tst.b	PT_PAR3(a2,d2.W)	* check counter
+		bne	act4a			* jump if it's running
+*
+		move.b	PT_PAR2(a2,d2.W),d0	* get parameter
+		subi.w	#90,d0			* put parameter in random range
+		bmi	act4b			* treat as normal if < 90
+*
+		movem.l	d1-d2/a0-a2,-(a7)	* get ranged random number
+		move.w	d0,-(a7)		* ...
+		jsr	_irand			* ...
+		tst.w	(a7)+			* ...
+		movem.l	(a7)+,d1-d2/a0-a2	* ...
+		move.b	d0,PT_PAR3(a2,d2.w)	* set counter
+		beq	act0			* next segment if cntr set to 0
+*
+		bra	act3			* else jump to the point
+*
+act4b:		move.b	PT_PAR2(a2,d2.W),PT_PAR3(a2,d2.W)	* set counter
+		beq	act0			* next segment if cntr set to 0
+*
+		bra	act3			* else jump to the point
+*
+act4a:		subq.b	#1,PT_PAR3(a2,d2.W)	* decrement counter
+		beq	act0			* next segment if cntr ran out
+*
+		bra	act3			* jump if it's still non-zero
+*
+* ------------------------------------------------------------------------------
+* act5 -- AC_KYUP -- jump if key is up
+* ----    ----------------------------
+act5:		move.w	_fpuifnc,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* check to see if voice is free
+		move.w	0(a0,d0.W),d0	* ...
+		cmpi.w	#-1,d0		* ...
+		beq	act3		* if so (inactive), do the jump
+*
+		btst	#15,d0		* see if voice is held
+		bne	act0		* continue if so
+*
+		btst	#14,d0		* ...
+		bne	act0		* ...
+*
+		lea	_trgtab,a0	* check trigger table entry
+		tst.b	0(a0,d0.W)	* see if the trigger is active
+		beq	act3		* if not, do the jump
+*
+		bra	act0		* if so, do next segment
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act6 -- AC_KYDN -- jump if key is down
+* ----    ------------------------------
+act6:		move.w	_fpuifnc,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* check to see if voice is free
+		move.w	0(a0,d0.W),d0	* ...
+		cmpi.w	#-1,d0		* ...
+		beq	act0		* if so (inactive), continue
+*
+		btst	#15,d0		* see if voice is held
+		bne	act3		* do jump if so
+*
+		btst	#14,d0		* ...
+		bne	act3		* ...
+*
+		lea	_trgtab,a0	* check trigger table entry
+		tst.b	0(a0,d0.W)	* see if the trigger is active
+		bne	act3		* if so, do the jump
+*
+		bra	act0		* if not, do next segment
+*
+* ------------------------------------------------------------------------------
+* Test stub
+* ---------
+act7:		bra	act0		* AC_HERE: treat act7 as AC_NULL
+*
+		.page
+* ------------------------------------------------------------------------------
+*
+* _fpuclr -- clear the FPU
+* -------    -------------
+*
+*	void
+*	fpuclr()
+*
+*		Resets the FPU functions to their nominal values.
+*
+* ------------------------------------------------------------------------------
+*
+_fpuclr:	link	a6,#0			* link stack frames
+		move.w	sr,-(a7)		* save the interrupt level
+		ori.w	#$0700,sr		* turn off interrupts
+*
+		lea	FPUFUNC,a0		* point at the first function
+		lea	_fp_resv,a2		* point at reset value table
+		move.w	#11,d1			* set the outer loop count
+*
+		.page
+* ------------------------------------------------------------------------------
+* reset the 'spare' function for the voice
+* ------------------------------------------------------------------------------
+clr0:		move.w	#CLREXP,F_EXP(a0)	* set time exponent
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#CLRMNT,F_MNT(a0)	* set time mantissa
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	#0,F_SF3(a0)		* set scale factor 3
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV3(a0)		* set voltage 3
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	#0,F_SF2(a0)		* set scale factor 2
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV2(a0)		* set voltage 2
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	#0,F_SF1(a0)		* set scale factor 1
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV1(a0)		* set voltage 1
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	(a2),F_VAL10(a0)	* set value from variable table
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	(a2)+,F_VAL01(a0)	* ...
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#FSEND,F_CTL(a0)	* set control word
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		.page
+		adda.w	#$0020,a0		* point at 2nd function
+		lea	fprescon,a1		* set reset constant pointer
+		move.w	#14,d0			* set inner loop count
+*
+* ------------------------------------------------------------------------------
+* reset the other functions for the voice
+* ------------------------------------------------------------------------------
+clr1:		move.w	#CLREXP,F_EXP(a0)	* set time exponent
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#CLRMNT,F_MNT(a0)	* set time mantissa
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	#0,F_SF3(a0)		* set scale factor 3
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV3(a0)		* set voltage 3
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	#0,F_SF2(a0)		* set scale factor 2
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV2(a0)		* set voltage 2
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	#0,F_SF1(a0)		* set scale factor 1
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV1(a0)		* set voltage 1
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		move.w	(a1),F_VAL10(a0)	* set value from constant table
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	(a1)+,F_VAL01(a0)	* ...
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#FSEND,F_CTL(a0)	* set control word
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		.page
+* ------------------------------------------------------------------------------
+* loop through reset for all of the voices and functions
+* ------------------------------------------------------------------------------
+		adda.w	#$0020,a0		* point at next function
+		dbra	d0,clr1			* loop until all funcs. cleared
+*
+		dbra	d1,clr0			* loop until all voices cleared
+* ------------------------------------------------------------------------------
+* clear the FPU interrupt, and return
+* ------------------------------------------------------------------------------
+		move.w	#0,FPUINT2		* clear FPU interrupt
+		move.w	(a7)+,sr		* restore interrupts
+		unlk	a6			* unlink stack frames
+		rts				* return to caller
+*
+		.page
+*
+* _clrvce -- quiet a voice
+* -------    -------------
+*
+*	void
+*	clrvce(vce)
+*	short vce;
+*
+*		Quiet the voice by resetting the FPU functions it uses.
+*
+_clrvce:	link	a6,#0			* link stack frames
+		move.w	sr,-(a7)		* save the interrupt level
+		ori.w	#$0700,sr		* turn off interrupts
+*
+		lea	FPUFUNC+$20,a0		* point at the 2nd function
+		move.w	8(a6),d0		* get voice number
+		ext.l	d0			* ...
+		lsl.l	#8,d0			* shift into position
+		add.l	d0,d0			* ...
+		adda.l	d0,a0			* add to function base
+		lea	fprescon,a1		* set reset constant pointer
+		move.w	#14,d0			* set inner loop count
+*
+vclr1:		move.l	a0,d1			* see if we reset this function
+		and.w	#$01F0,d1		* ...
+*
+		cmpi.w	#$0100,d1		* dynamics ?
+		beq	vclr2			* skip it if so
+*
+		move.w	#CLREXP,F_EXP(a0)	* set time exponent
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#CLRMNT,F_MNT(a0)	* set time mantissa
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		cmpi.w	#$0020,d1		* freq 1 ?
+		beq	vclr3			* don't reset CV3 (fine tune)
+*
+		move.w	#0,F_SF3(a0)		* set scale factor 3
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV3(a0)		* set voltage 3
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+vclr3:		move.w	#0,F_SF1(a0)		* set scale factor 1
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#0,F_CV1(a0)		* set voltage 1
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+		.page
+*
+		move.w	(a1),F_VAL10(a0)	* set value from constant table
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	(a1),F_VAL01(a0)	* ...
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+		move.w	#FSEND,F_CTL(a0)	* set control word
+		tst.l	actab			* delay
+		tst.l	actab			* ...
+*
+vclr2:		adda.w	#2,a1			* point at next function
+		adda.w	#$0020,a0		*
+		dbra	d0,vclr1		* loop until all funcs. cleared
+*
+		move.w	(a7)+,sr		* restore interrupts
+		unlk	a6			* unlink stack frames
+		rts				* return to caller
+*
+		.page
+* ------------------------------------------------------------------------------
+		.data
+* ------------------------------------------------------------------------------
+*
+* actab -- action code dispatch table
+* -----    --------------------------
+actab:		dc.l	act0	* 0 - AC_NULL:  no action
+		dc.l	act1	* 1 - AC_SUST:  sustain
+		dc.l	act2	* 2 - AC_ENBL:  enable
+		dc.l	act3	* 3 - AC_JUMP:  unconditional jump
+		dc.l	act4	* 4 - AC_LOOP:  jump n times      (loop)
+		dc.l	act5	* 5 - AC_KYUP:  jump if key up    (enable jump)
+		dc.l	act6	* 6 - AC_KYDN:  jump if key down  (sustain jump)
+		dc.l	act7	* 7 - AC_HERE:  here on key up
+*
+* fprescon -- FPU reset constant table
+* --------    ------------------------
+fprescon:	dc.w	$0000	* frq 1		  0.00
+		dc.w	$8300	* level		-10.00
+		dc.w	$0000	* frq 2		  0.00
+		dc.w	$0000	* locn		  0.00
+		dc.w	$0000	* frq 3		  0.00
+		dc.w	$0000	* reson		  0.00
+		dc.w	$0000	* frq 4		  0.00
+		dc.w	$7D00	* dyn		+10.00
+		dc.w	$0000	* ind 1		  0.00
+		dc.w	$3E80	* filt		 +5.00
+		dc.w	$0000	* ind 2		  0.00
+		dc.w	$0000	* ind 3		  0.00
+		dc.w	$0000	* ind 4		  0.00
+		dc.w	$0000	* ind 5		  0.00
+		dc.w	$0000	* ind 6		  0.00
+*
+* ------------------------------------------------------------------------------
+		.bss
+* ------------------------------------------------------------------------------
+*
+_fp_resv:	ds.w	12		* fpu spare function reset values
+_fpuifnc:	ds.w	1		* interrupting function number from FPU
+*
+		.end
Index: ram/frfind.c
===================================================================
--- ram/frfind.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/frfind.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,447 @@
+/*
+   =============================================================================
+	frfind.c -- the frame finder, and other pointer pushers
+	Version 17 -- 1988-07-28 -- D.N. Lynx Crowe
+
+	struct s_entry *
+	ep_adj(sep, sdir, tval)
+	struct s_entry *sep;
+	int sdir;
+	long tval;
+
+		Returns a pointer to the event chain at the time 'tval'
+		starting from 'sep' in the direction 'sdir'.
+		The right end of the chain is returned when 'sdir' EQ 0,
+		and the left end is returned when 'sdir' NE 0.
+
+	struct s_entry *
+	frfind(tval, sdir)
+	long tval;
+	int sdir;
+
+		Returns a pointer to the event chain at the time 'tval'
+		in the current score in the direction 'sdir', or E_NULL
+		if the current score is empty.
+		The right end of the chain is returned when 'sdir' EQ 0,
+		and the left end is returned when 'sdir' NE 0.
+
+	struct s_entry *
+	findev(ep, te, et, d1, d2)
+	struct s_entry *ep;
+	long te;
+	short et, d1, d2;
+
+		Searches the event chain starting at 'ep' for an event at
+		a time of 'te' with:  a type of 'et', e_data1 EQ 'd1',
+		and e_data2 EQ 'd2'.  The values of 'd1' or 'd2' may be -1,
+		in which case e_data1 or e_data2 will be assumed to match.
+		Returns a pointer to the desired event if it is found, or
+		E_NULL if no event in the chain matches the criteria given.
+
+	struct s_entry *
+	ehfind(et, te, d1, d2)
+	short et;
+	long te;
+	short d1, d2;
+
+		Searches the event header chain starting for an event at
+		a time of 'te' with:  a type of 'et', e_data1 EQ 'd1',
+		and e_data2 EQ 'd2'.  The values of 'd1' or 'd2' may be -1,
+		in which case e_data1 or e_data2 will be assumed to match.
+		Returns a pointer to the desired event if it is found, or
+		E_NULL if no event in the chain matches the criteria given.
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+#define	CHECKP		0
+
+#include "stddefs.h"
+#include "score.h"
+#include "scfns.h"
+
+#if	DEBUGIT
+extern	short	verbose, testing;
+#endif
+
+extern	short	insmode;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ep_adj(sep, sdir, tval) -- Returns a pointer to the event chain
+	at the time 'tval' starting from 'sep' in the direction 'sdir'.
+   =============================================================================
+*/
+
+struct s_entry *
+ep_adj(sep, sdir, tval)
+register struct s_entry *sep;
+int sdir;
+register long tval;
+{
+	register struct s_entry *tep;
+
+#if	DEBUGIT
+	if (verbose)
+		printf("epadj($%08lX, %d, %ld):  sep->e_time=%ld\n", 
+			sep, sdir, tval, sep->e_time);
+#endif
+
+#if CHECKP
+	Pcheck(sep, "sep - ep_adj() entry");
+#endif
+
+	if (tval < 0)		/* return start of score for negative times */
+		return(scores[curscor]);
+		
+	if (sdir) {	/* find left (earliest) end of chain */
+
+		if (sep->e_time LT tval) {
+
+			while (E_NULL NE (tep = sep->e_fwd)) {
+
+#if CHECKP
+	Pcheck(tep, "tep - ep_adj() L .1.");
+#endif
+
+#if	DEBUGIT
+	if (verbose AND testing)
+		printf("  .1. sep=$%08lX, tep=$%08lX\n", sep, tep);
+#endif
+
+				if (sep->e_time LT tval)
+					sep = tep;
+				else
+					break;
+			}
+		}
+
+		while (E_NULL NE (tep = sep->e_bak)) {
+
+#if CHECKP
+	Pcheck(tep, "tep - ep_adj() L .2.");
+#endif
+
+#if	DEBUGIT
+	if (verbose AND testing)
+		printf("  .2. sep=$%08lX, tep=$%08lX\n", sep, tep);
+#endif
+
+			if ((tep->e_time LT tval) OR
+			    (tep->e_type EQ EV_SCORE)) {
+
+#if	DEBUGIT
+	if (verbose)
+		printf("  .3. $%08lX returned\n", sep);
+#endif
+				return(sep);
+			}
+
+			sep = tep;
+		}
+
+#if CHECKP
+	Pcheck(tep, "tep - ep_adj() L .4.");
+#endif
+
+#if	DEBUGIT
+	if (verbose)
+		printf("  .4. $%08lX returned\n", sep);
+#endif
+		return(sep);
+
+/* 
+
+*/
+
+	} else {	/* find right (latest) end of chain */
+
+		if (sep->e_time GT tval) {
+
+			while (E_NULL NE (tep = sep->e_bak)) {
+
+#if	CHECKP
+	Pcheck(tep, "tep - ep_adj() R .5.");
+#endif
+
+#if DEBUGIT
+	if (verbose AND testing)
+		printf("  .5. sep=$%08lX, tep=$%08lX\n", sep, tep);
+#endif
+
+				if ((sep->e_time LE tval) OR
+				    (sep->e_type EQ EV_SCORE))
+					break;
+				else
+					sep = tep;
+			}
+		}
+
+		while (E_NULL NE (tep = sep->e_fwd)) {
+
+#if CHECKP
+	Pcheck(tep, "tep - ep_adj() R .6.");
+#endif
+
+#if DEBUGIT
+	if (verbose AND testing)
+		printf("  .6. sep=$%08lX, tep=$%08lX\n", sep, tep);
+#endif
+
+			if (tep->e_time GT tval) {
+			    
+#if	DEBUGIT
+	if (verbose)
+		printf("  .7. $%08lX returned\n", sep);
+#endif
+				return(sep);
+			}
+
+			sep = tep;
+		}
+
+#if CHECKP
+	Pcheck(tep, "tep - ep_adj() R .8.");
+#endif
+
+#if DEBUGIT
+	if (verbose)
+		printf("  .8. $%08lX returned\n", sep);
+#endif
+		return(sep);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	frfind(tval, sdir) -- Returns a pointer to the event chain
+	at the time 'tval' in the current score in the direction 'sdir',
+	or E_NULL if the current score is empty.
+   =============================================================================
+*/
+
+struct s_entry *
+frfind(tval, sdir)
+register long tval;
+int sdir;
+{
+	register int	i;
+	register long	t_min, dt;
+	register struct	s_entry	*ep, *sep;
+
+#if	DEBUGIT
+	if (verbose) {
+
+		printf("frfind(%ld, %d):  searching\n", tval, sdir);
+	}
+#endif
+
+#if CHECKP
+	Pcheck(scp, "scp - frfind() - entry");
+	Pcheck(p_fwd, "p_fwd - frfind() - entry");
+	Pcheck(p_cur, "p_cur - frfind() - entry");
+	Pcheck(p_bak, "p_bak - frfind() - entry");
+#endif
+
+	if (scp EQ E_NULL) {			/* NULL if no score selected */
+
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind(%ld, %d):  found scp EQ E_NULL\n", tval, sdir);
+#endif
+		return(E_NULL);
+	}
+
+	if (tval < 0)
+		return(ep_adj(scp, sdir, tval));
+
+	if (p_cur->e_time EQ tval) {		/* at p_cur ? */
+
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind():  found tval at p_cur\n");
+#endif
+		return(ep_adj(p_cur, sdir, tval));
+	}
+
+	if (p_fwd->e_time EQ tval) {		/* at p_fwd ? */
+	
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind():  found tval at p_fwd\n");
+#endif
+		return(ep_adj(p_fwd, sdir, tval));
+	}
+
+	if (p_bak->e_time EQ tval) {		/* at p_bak ? */
+
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind():  found tval at p_bak\n");
+#endif
+		return(ep_adj(p_bak, sdir, tval));
+	}
+
+	t_min = (tval GT p_cur->e_time) ?		/* time from p_cur */
+		(tval - p_cur->e_time) :
+		(p_cur->e_time - tval);
+
+	ep = p_cur;
+
+	dt = (tval GT p_fwd->e_time) ?		/* time from p_fwd */
+		(tval - p_fwd->e_time) :
+		(p_fwd->e_time - tval);
+
+	if (dt LT t_min) {			/* select shortest time */
+
+		t_min = dt;
+		ep = p_fwd;
+
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind():  p_fwd dt=%ld\n", dt);
+#endif
+	}
+
+/* 
+
+*/
+
+	dt = (tval GT p_bak->e_time) ?		/* time to p_bak */
+		(tval - p_bak->e_time) :
+		(p_bak->e_time - tval);
+
+	if (dt LT t_min) {			/* select shortest time */
+
+		t_min = dt;
+		ep = p_bak;
+
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind():  p_bak dt=%ld\n", dt);
+#endif
+	}
+
+	if (NOT insmode) {
+
+		for (i = 0; i < N_SECTS; i++) {		/* search section list */
+
+			if (E_NULL NE (sep = seclist[curscor][i])) {
+
+				dt = (tval GT sep->e_time) ?	/* time to section */
+					(tval - sep->e_time) :
+					(sep->e_time - tval);
+
+				if (dt LT t_min) {		/* select shortest time */
+
+					t_min = dt;
+					ep = sep;
+
+#if	DEBUGIT
+	if (verbose)
+		printf("frfind():  section %d dt=%ld\n", i, dt);
+#endif
+				}
+			}
+		}
+	}
+
+#if	CHECKP
+	Pcheck(ep, "ep - frfind() - ep_adj()/exiting");
+#endif
+
+	return(ep_adj(ep, sdir, tval));	/* adjust the pointer */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	findev(ep, te, et, d1, d2) -- Searches the event chain
+	starting at 'ep' for an event at a time of 'te' with:
+	a type of 'et', e_data1 EQ 'd1', and e_data2 EQ 'd2'.
+
+	The values of 'd1' or 'd2' may be -1, in which case
+	e_data1 or e_data2 will be assumed to match.
+
+	Returns a pointer to the desired event if it is found, or
+	'E_NULL' if no event in the chain matches the criteria given.
+   =============================================================================
+*/
+
+struct s_entry *
+findev(ep, te, et, d1, d2)
+struct s_entry *ep;
+register long te;
+register short et, d1, d2;
+{
+	register struct s_entry *tp;
+
+	tp = ep_adj(ep, 1, te);		/* search from left end of chain */
+
+	while (tp->e_time EQ te) {		/* check the time, ... */
+
+		if ((tp->e_type EQ et) AND			/* ... e_type, */
+		    ((d1 EQ -1) OR (tp->e_data1 EQ d1)) AND	/* ... e_data1, */
+		    ((d2 EQ -1) OR (tp->e_data2 EQ d2)))	/* ... e_data2 */
+			return(tp);	/* found the event */
+
+		tp = tp->e_fwd;		/* search forward */
+	}
+
+	return(E_NULL);			/* event not found */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ehfind(eh, te, d1, d2) -- Searches the event header chain
+	for an event at a time of 'te' with:  a header type of 'eh',
+	e_data1 EQ 'd1', and e_data2 EQ 'd2'.
+
+	The value of 'te' may be -1, in which case e_time will
+	be assumed to match.
+
+	The values of 'd1' or 'd2' may be -1, in which case
+	e_data1 or e_data2 will be assumed to match.
+
+	Returns a pointer to the desired event if it is found, or
+	'E_NULL' if no event in the chain matches the criteria given.
+   =============================================================================
+*/
+
+struct s_entry *
+ehfind(eh, te, d1, d2)
+register short eh;
+register long te;
+register short d1, d2;
+{
+	register struct s_entry *tp;
+
+	tp = hplist[curscor][eh];	/* get head of chain */
+
+	while (E_NULL NE tp) {		/* check each event ... */
+
+		if (((te EQ -1L) OR (tp->e_time  EQ te)) AND	/* ... time, */
+		    ((d1 EQ  -1) OR (tp->e_data1 EQ d1)) AND	/* ... e_data1, */
+		    ((d2 EQ  -1) OR (tp->e_data2 EQ d2)))	/* ... e_data2 */
+			return(tp);	/* found the event */
+
+		tp = tp->e_up;		/* search up the chain */
+	}
+
+	return(tp);			/* event not found */
+}
Index: ram/gcurpos.c
===================================================================
--- ram/gcurpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/gcurpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,382 @@
+/*
+   =============================================================================
+	gcurpos.c -- MIDAS cursor arrow functions and arrow object definitions
+	Version 16 -- 1988-03-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddvars.h"
+
+#include "midas.h"
+
+#define	YOFF	15	/* y pixel offset */
+#define	XOFF	14	/* x pixel offset */
+
+extern	short	sgcsw;
+
+/* 4 bit pixel patterns */
+
+#define	AW_0	0x0000
+#define	AW_1	0xF000
+#define	AW_2	0x0F00
+#define	AW_3	0xFF00
+#define	AW_4	0x00F0
+#define	AW_5	0xF0F0
+#define	AW_6	0x0FF0
+#define	AW_7	0xFFF0
+#define	AW_8	0x000F
+#define	AW_9	0xF00F
+#define	AW_A	0x0F0F
+#define	AW_B	0xFF0F
+#define	AW_C	0x00FF
+#define	AW_D	0xF0FF
+#define	AW_E	0x0FFF
+#define	AW_F	0xFFFF
+
+extern	int	objclr(), SetPri(), vbank();
+
+extern	unsigned	exp_c();
+
+extern	short	stcrow, stccol;
+
+/* 
+
+*/
+
+static	int	ar_ule[] = {		/* upper left even pixel arrow */
+
+	AW_F, AW_0, AW_0, AW_0,		/* 0 */
+	AW_C, AW_0, AW_0, AW_0,		/* 1 */
+	AW_A, AW_0, AW_0, AW_0,		/* 2 */
+	AW_9, AW_0, AW_0, AW_0,		/* 3 */
+	AW_0, AW_8, AW_0, AW_0,		/* 4 */
+	AW_0, AW_4, AW_0, AW_0,		/* 5 */
+	AW_0, AW_2, AW_0, AW_0,		/* 6 */
+	AW_0, AW_1, AW_0, AW_0,		/* 7 */
+	AW_0, AW_0, AW_8, AW_0,		/* 8 */
+	AW_0, AW_0, AW_7, AW_8,		/* 9 */
+	AW_0, AW_0, AW_6, AW_0,		/* 10 */
+	AW_0, AW_0, AW_5, AW_E,		/* 11 */
+	AW_0, AW_0, AW_5, AW_8,		/* 12 */
+	AW_0, AW_0, AW_1, AW_4,		/* 13 */
+	AW_0, AW_0, AW_1, AW_2,		/* 14 */
+	AW_0, AW_0, AW_0, AW_0		/* 15 */
+};
+
+static	int	ar_ulo[] = {		/* upper left odd pixel arrow */
+
+	AW_7, AW_8, AW_0, AW_0,		/* 0 */
+	AW_6, AW_0, AW_0, AW_0,		/* 1 */
+	AW_5, AW_0, AW_0, AW_0,		/* 2 */
+	AW_4, AW_8, AW_0, AW_0,		/* 3 */
+	AW_0, AW_4, AW_0, AW_0,		/* 4 */
+	AW_0, AW_2, AW_0, AW_0,		/* 5 */
+	AW_0, AW_1, AW_0, AW_0,		/* 6 */
+	AW_0, AW_0, AW_8, AW_0,		/* 7 */
+	AW_0, AW_0, AW_4, AW_0,		/* 8 */
+	AW_0, AW_0, AW_3, AW_C,		/* 9 */
+	AW_0, AW_0, AW_3, AW_0,		/* 10 */
+	AW_0, AW_0, AW_2, AW_F,		/* 11 */
+	AW_0, AW_0, AW_2, AW_C,		/* 12 */
+	AW_0, AW_0, AW_0, AW_A,		/* 13 */
+	AW_0, AW_0, AW_0, AW_9,		/* 14 */
+	AW_0, AW_0, AW_0, AW_0		/* 15 */
+};
+
+/* 
+
+*/
+
+static	int	ar_ure[] = {		/* upper right even pixel arrow */
+
+	AW_0, AW_0, AW_1, AW_E,		/* 0 */
+	AW_0, AW_0, AW_0, AW_6,		/* 1 */
+	AW_0, AW_0, AW_0, AW_A,		/* 2 */
+	AW_0, AW_0, AW_1, AW_2,		/* 3 */
+	AW_0, AW_0, AW_2, AW_0,		/* 4 */
+	AW_0, AW_0, AW_4, AW_0,		/* 5 */
+	AW_0, AW_0, AW_8, AW_0,		/* 6 */
+	AW_0, AW_1, AW_0, AW_0,		/* 7 */
+	AW_0, AW_2, AW_0, AW_0,		/* 8 */
+	AW_3, AW_C, AW_0, AW_0,		/* 9 */
+	AW_0, AW_C, AW_0, AW_0,		/* 10 */
+	AW_F, AW_4, AW_0, AW_0,		/* 11 */
+	AW_3, AW_4, AW_0, AW_0,		/* 12 */
+	AW_5, AW_0, AW_0, AW_0,		/* 13 */
+	AW_9, AW_0, AW_0, AW_0,		/* 14 */
+	AW_0, AW_0, AW_0, AW_0		/* 15 */
+};
+
+static	int	ar_uro[] = {		/* upper right odd pixel arrow */
+
+	AW_0, AW_0, AW_0, AW_F,		/* 0 */
+	AW_0, AW_0, AW_0, AW_3,		/* 1 */
+	AW_0, AW_0, AW_0, AW_5,		/* 2 */
+	AW_0, AW_0, AW_0, AW_9,		/* 3 */
+	AW_0, AW_0, AW_1, AW_0,		/* 4 */
+	AW_0, AW_0, AW_2, AW_0,		/* 5 */
+	AW_0, AW_0, AW_4, AW_0,		/* 6 */
+	AW_0, AW_0, AW_8, AW_0,		/* 7 */
+	AW_0, AW_1, AW_0, AW_0,		/* 8 */
+	AW_1, AW_E, AW_0, AW_0,		/* 9 */
+	AW_0, AW_6, AW_0, AW_0,		/* 10 */
+	AW_7, AW_A, AW_0, AW_0,		/* 11 */
+	AW_1, AW_A, AW_0, AW_0,		/* 12 */
+	AW_2, AW_8, AW_0, AW_0,		/* 13 */
+	AW_4, AW_8, AW_0, AW_0,		/* 14 */
+	AW_0, AW_0, AW_0, AW_0		/* 15 */
+};
+
+/* 
+
+*/
+
+static	int	ar_lle[] = {		/* lower left even pixel arrow */
+
+	AW_0, AW_0, AW_0, AW_0,		/* 0 */
+	AW_0, AW_0, AW_1, AW_2,		/* 1 */
+	AW_0, AW_0, AW_1, AW_4,		/* 2 */
+	AW_0, AW_0, AW_5, AW_8,		/* 3 */
+	AW_0, AW_0, AW_5, AW_E,		/* 4 */
+	AW_0, AW_0, AW_6, AW_0,		/* 5 */
+	AW_0, AW_0, AW_7, AW_8,		/* 6 */
+	AW_0, AW_0, AW_8, AW_0,		/* 7 */
+	AW_0, AW_1, AW_0, AW_0,		/* 8 */
+	AW_0, AW_2, AW_0, AW_0,		/* 9 */
+	AW_0, AW_4, AW_0, AW_0,		/* 10 */
+	AW_0, AW_8, AW_0, AW_0,		/* 11 */
+	AW_9, AW_0, AW_0, AW_0,		/* 12 */
+	AW_A, AW_0, AW_0, AW_0,		/* 13 */
+	AW_C, AW_0, AW_0, AW_0,		/* 14 */
+	AW_F, AW_0, AW_0, AW_0		/* 15 */
+};
+
+static	int	ar_llo[] = {		/* lower left odd pixel arrow */
+
+	AW_0, AW_0, AW_0, AW_0,		/* 0 */
+	AW_0, AW_0, AW_0, AW_9,		/* 1 */
+	AW_0, AW_0, AW_0, AW_A,		/* 2 */
+	AW_0, AW_0, AW_2, AW_C,		/* 3 */
+	AW_0, AW_0, AW_2, AW_F,		/* 4 */
+	AW_0, AW_0, AW_3, AW_0,		/* 5 */
+	AW_0, AW_0, AW_3, AW_C,		/* 6 */
+	AW_0, AW_0, AW_4, AW_0,		/* 7 */
+	AW_0, AW_0, AW_8, AW_0,		/* 8 */
+	AW_0, AW_1, AW_0, AW_0,		/* 9 */
+	AW_0, AW_2, AW_0, AW_0,		/* 10 */
+	AW_0, AW_4, AW_0, AW_0,		/* 11 */
+	AW_4, AW_8, AW_0, AW_0,		/* 12 */
+	AW_5, AW_0, AW_0, AW_0,		/* 13 */
+	AW_6, AW_0, AW_0, AW_0,		/* 14 */
+	AW_7, AW_8, AW_0, AW_0		/* 15 */
+};
+
+/* 
+
+*/
+
+static	int	ar_lre[] = {		/* lower right even pixel arrow */
+
+	AW_0, AW_0, AW_0, AW_0,		/* 0 */
+	AW_9, AW_0, AW_0, AW_0,		/* 1 */
+	AW_5, AW_0, AW_0, AW_0,		/* 2 */
+	AW_3, AW_4, AW_0, AW_0,		/* 3 */
+	AW_F, AW_4, AW_0, AW_0,		/* 4 */
+	AW_0, AW_C, AW_0, AW_0,		/* 5 */
+	AW_3, AW_C, AW_0, AW_0,		/* 6 */
+	AW_0, AW_2, AW_0, AW_0,		/* 7 */
+	AW_0, AW_1, AW_0, AW_0,		/* 8 */
+	AW_0, AW_0, AW_8, AW_0,		/* 9 */
+	AW_0, AW_0, AW_4, AW_0,		/* 10 */
+	AW_0, AW_0, AW_2, AW_0,		/* 11 */
+	AW_0, AW_0, AW_1, AW_2,		/* 12 */
+	AW_0, AW_0, AW_0, AW_A,		/* 13 */
+	AW_0, AW_0, AW_0, AW_6,		/* 14 */
+	AW_0, AW_0, AW_1, AW_E		/* 15 */
+};
+
+static	int	ar_lro[] = {		/* lower right odd pixel arrow */
+
+	AW_0, AW_0, AW_0, AW_0,		/* 0 */
+	AW_4, AW_8, AW_0, AW_0,		/* 1 */
+	AW_2, AW_8, AW_0, AW_0,		/* 2 */
+	AW_1, AW_A, AW_0, AW_0,		/* 3 */
+	AW_7, AW_A, AW_0, AW_0,		/* 4 */
+	AW_0, AW_6, AW_0, AW_0,		/* 5 */
+	AW_1, AW_E, AW_0, AW_0,		/* 6 */
+	AW_0, AW_1, AW_0, AW_0,		/* 7 */
+	AW_0, AW_0, AW_8, AW_0,		/* 8 */
+	AW_0, AW_0, AW_4, AW_0,		/* 9 */
+	AW_0, AW_0, AW_2, AW_0,		/* 10 */
+	AW_0, AW_0, AW_1, AW_0,		/* 11 */
+	AW_0, AW_0, AW_0, AW_9,		/* 12 */
+	AW_0, AW_0, AW_0, AW_5,		/* 13 */
+	AW_0, AW_0, AW_0, AW_3,		/* 14 */
+	AW_0, AW_0, AW_0, AW_F		/* 15 */
+};
+
+/* 
+
+*/
+
+static	int	*arrows[] = {	/* arrow pointer table */
+
+	v_curs0,	/* 0 - upper left, even pixel */
+	v_curs1,	/* 1 - upper left, odd pixel */
+
+	v_curs2,	/* 2 - upper right, even pixel */
+	v_curs3,	/* 3 - upper right, odd pixel */
+
+	v_curs4,	/* 4 - lower left, even pixel */
+	v_curs5,	/* 5 - lower left, odd pixel */
+
+	v_curs6,	/* 6 - lower right, even pixel */
+	v_curs7		/* 7 - lower right, odd pixel */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	gcurpos(xloc, yloc) -- position the graphic cursor at ('xloc', 'yloc')
+
+	Also sets stcrow and stccol to keep them in sync.
+   =============================================================================
+*/
+
+int
+gcurpos(xloc, yloc)
+register int xloc, yloc;
+{
+	register int ab, xo, yo;
+	register struct octent *op;
+
+	if (xloc LT XCTR) {
+
+		xo = 0;		/* arrow points left */
+
+		if (yloc LT YCTR)
+			{ab = 0;	yo = 0;}	/* arrow points up */
+		else
+			{ab = 4;	yo = -YOFF;}	/* arrow points down */
+
+	} else {
+
+		xo = -XOFF;	/* arrow points right */
+
+		if (yloc LT YCTR)
+			{ab = 2;	yo = 0;}	/* arrow points up */
+		else
+			{ab = 6;	yo = -YOFF;}	/* arrow points down */
+	}
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	v_odtab[GCPRI][0] |= V_BLA;
+	objclr(GCPRI);
+
+	op = &v_obtab[GCURS];
+	op->objx = xloc + xo;
+	op->objy = yloc + yo;
+	op->obase = arrows[ab + (xloc & 0x0001)];
+	op->odtw1 = 0x0400 | (0x03FF & (op->objx >> 1));
+
+	SetPri(GCURS, GCPRI);
+
+	stcrow = yloc / 14;
+	stccol = xloc >> 3;
+	return(ab + (xloc & 0x0001));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	andcopy() -- copy a pattern
+   =============================================================================
+*/
+
+andcopy(to, from, with, len)
+register unsigned *to, *from, with;
+short len;
+{
+	register short i;
+
+	for (i = len; i--; )
+		*to++ = *from++ & with;
+}
+
+/*
+   =============================================================================
+	arcurs() -- setup the arrow cursor
+   =============================================================================
+*/
+
+arcurs(icolor)
+unsigned icolor;
+{
+	register short color;
+
+	color = exp_c(icolor);
+
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);
+
+	andcopy(v_curs0, ar_ule, color, 64);	/* setup arrow cursor */
+	andcopy(v_curs1, ar_ulo, color, 64);
+	andcopy(v_curs2, ar_ure, color, 64);
+	andcopy(v_curs3, ar_uro, color, 64);
+	andcopy(v_curs4, ar_lle, color, 64);
+	andcopy(v_curs5, ar_llo, color, 64);
+	andcopy(v_curs6, ar_lre, color, 64);
+	andcopy(v_curs7, ar_lro, color, 64);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sgcon() -- set graphic cursor object "on"
+   =============================================================================
+*/
+
+sgcon()
+{
+	if (sgcsw)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	v_odtab[GCPRI][0] &= ~V_BLA;
+	sgcsw = TRUE;
+}
+
+/*
+   =============================================================================
+	sgcoff() -- set graphic cursor object "off"
+   =============================================================================
+*/
+
+sgcoff()
+{
+	if (!sgcsw)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	v_odtab[GCPRI][0] |= V_BLA;
+	sgcsw = FALSE;
+}
Index: ram/idfield.c
===================================================================
--- ram/idfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/idfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,568 @@
+/*
+   =============================================================================
+	idfield.c -- instrument display field processing and cursor motion
+	Version 89 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "smdefs.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	short	select(), stdmkey(), stddkey(), nokey(), cxkstd(), cykstd();
+extern	short	vtoy(), ttox(), timeto(), vcputsv(), dswin(), stdctp1();
+extern	short	whatbox(), inspnt(), pntsel(), setseg(), showpt();
+
+extern	short	et_null(), ef_null(), rd_null(), nd_null();
+extern	short	et_ipnt(), ef_ipnt(), rd_ipnt(), nd_ipnt();
+extern	short	et_idin(), ef_idin(), rd_idin(), nd_idin();
+extern	short	et_ivce(), ef_ivce(), rd_ivce(), nd_ivce();
+extern	short	et_icnf(), ef_icnf(), rd_icnf(), nd_icnf();
+extern	short	et_ival(), ef_ival(), rd_ival(), nd_ival();
+extern	short	et_itim(), ef_itim(), rd_itim(), nd_itim();
+extern	short	et_iosc(), ef_iosc(), rd_iosc(), nd_iosc();
+extern	short	et_iact(), ef_iact(), rd_iact(), nd_iact();
+extern	short	et_iwsn(), ef_iwsn(), rd_iwsn(), nd_iwsn();
+extern	short	et_ires(), ef_ires(), rd_ires(), nd_ires();
+
+extern	unsigned	fromfpu();
+
+extern	char	*memset();
+
+/* 
+
+*/
+
+extern	short	curvce, curfunc, curpnt, hitbox, astat, idnamsw;
+extern	short	cxval, cyval, cxrate, cyrate, curslim, cmtype, cmfirst;
+extern	short	pecase, pntsv, npts, subj, idimsw, wcflag, imflag;
+extern	short	idcfsw, idsrcsw, vtcrow, vtccol, stcrow, stccol;
+extern	short	vtxval, vtyval;
+
+extern	unsigned	temax, temin;
+
+extern	short	*cratex, *cratey, crate0[], crate1[];
+
+extern	unsigned	*instob;
+
+extern	char	bfs[];
+extern	char	*idbxlbl[];
+
+extern	short	fnoff[];
+extern	short	idbox[][8];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	idboxes[];
+
+extern	struct	sment	sments[];
+extern	struct	sment	*vpsms[];
+
+extern	struct	valent	valents[];
+
+extern	struct	instpnt	*pntptr;
+
+extern	struct	instdef	vbufs[];
+
+short	idx_key(), idnfld(), idcxupd(), idcyupd(), ikyup(), ikydn();
+
+/* 
+
+*/
+
+short	zonemax[9] = { 63, 119, 175, 231, 287, 343, 399, 455, 509};
+
+short	zoneinc[9] = {  2,   2,   4,   9,  18,  36,  73, 146, 303};
+
+struct	fet	id_fet1[] = {
+
+	{ 5, 62, 62,     12, et_ires, ef_ires, rd_ires, nd_ires},
+	{16,  1, 12,     13, et_imlt, ef_imlt, rd_imlt, nd_imlt},
+	{16, 15, 16,     14, et_ipnt, ef_ipnt, rd_ipnt, nd_ipnt},
+	{16, 19, 24,     15, et_itim, ef_itim, rd_itim, nd_itim},
+	{16, 27, 44,     16, et_ival, ef_ival, rd_ival, nd_ival},
+	{16, 47, 62,     17, et_iact, ef_iact, rd_iact, nd_iact},
+	{17, 12, 13,     18, et_icnf, ef_icnf, rd_icnf, nd_icnf},
+	{17, 23, 24,     19, et_ivce, ef_ivce, rd_ivce, nd_ivce},
+	{17, 31, 32,     19, et_idin, ef_idin, rd_idin, nd_idin},
+	{17, 57, 58, 0x0015, et_iwsn, ef_iwsn, rd_iwsn, nd_iwsn},
+	{17, 61, 62, 0x0115, et_iwsn, ef_iwsn, rd_iwsn, nd_iwsn},
+	{18, 36, 46, 0x8014, et_iosc, ef_iosc, rd_iosc, nd_iosc},
+	{18, 17, 32,      0, et_null, ef_null, rd_null, nd_null},
+	{19, 36, 46, 0x8114, et_iosc, ef_iosc, rd_iosc, nd_iosc},
+	{19, 17, 32,      0, et_null, ef_null, rd_null, nd_null},
+	{20, 36, 46, 0x8214, et_iosc, ef_iosc, rd_iosc, nd_iosc},
+	{20, 17, 32,      0, et_null, ef_null, rd_null, nd_null},
+	{21, 36, 46, 0x8314, et_iosc, ef_iosc, rd_iosc, nd_iosc},
+	{21, 17, 32,      0, et_null, ef_null, rd_null, nd_null},
+
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+char	*srctbl[] = {		/* source label table */
+
+	"       ",	/*  0 */
+	"Random ",	/*  1 */
+	"GPC/CV1",	/*  2 */
+	"???????",	/*  3 */
+	"???????",	/*  4 */
+	"Pitch  ",	/*  5 */
+	"Key Prs",	/*  6 */
+	"Key Vel",	/*  7 */
+	"Pedal 1",	/*  8 */
+	"???????",	/*  9 */
+	"Freq   ",	/* 10 */
+	"PchW/HT",	/* 11 */
+	"ModW/VT",	/* 12 */
+	"Brth/LP",	/* 13 */
+};
+
+/* 
+
+*/
+
+struct curpak id_flds = {
+
+	stdctp1,	/* curtype */
+	nokey,		/* premove */
+	nokey,		/* pstmove */
+	cxkstd,		/* cx_key */
+	cykstd,		/* cy_key */
+	idcxupd,	/* cx_upd */
+	idcyupd,	/* cy_upd */
+	ikyup,		/* xy_up */
+	ikydn,		/* xy_dn */
+	idx_key,	/* x_key */
+	select,		/* e_key */
+	stdmkey,	/* m_key */
+	stddkey,	/* d_key */
+	idnfld,		/* not_fld */
+	id_fet1,	/* curfet */
+	idboxes,	/* csbp */
+	crate1,		/* cratex */
+	crate1,		/* cratey */
+	CT_GRAF,	/* cmtype */
+	ICURX,		/* cxval */
+	ICURY		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ikydn() -- process instrument cursor key down
+   =============================================================================
+*/
+
+ikydn()
+{
+	imflag = FALSE;
+}
+
+/*
+   =============================================================================
+	ikyup() -- process instrument cursor key up
+   =============================================================================
+*/
+
+ikyup()
+{
+	if (imflag)
+		modinst();
+}
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idcyupd() -- update cursor y location from value
+   =============================================================================
+*/
+
+idcyupd()
+{
+	register short pval, vh, vl;
+
+	if (wcflag NE -1)		/* ws/cf menu page can't be up */
+		return;
+
+	if (idimsw)			/* no y update if instrument menu is up */
+		return;
+
+	if (idsrcsw OR idcfsw) {	/* see if we're in the menu area */
+
+		vtcrow = YTOR(vtyval += cyrate);
+
+		if (vtcrow > 24)
+			vtyval = RTOY(vtcrow = 24);
+		else if (vtcrow < 22)
+			vtyval = RTOY(vtcrow = 22);
+
+	} else if (idnamsw) {		/* see if we're in the typewriter */
+
+		vtcyupd();
+
+	} else if (pntsv) {		/* see if we're moving a point */
+
+		pval = (pntptr->ipval >> 5) - (cyrate * 7);
+
+		if (pval GT 1000)		/* limit at +10.00 */
+			pval = 1000;
+		else if (pval LT 0)		/* limit at +00.00 */
+			pval = 0;
+
+		cyval = vtoy(pval, 12);		/* new cursor location */
+		pntptr->ipval = pval << 5;	/* update function value */
+
+		vh = pval / 100;		/* display the new value */
+		vl = pval - (vh * 100);
+
+		sprintf(bfs, "%02d.%02d", vh, vl);
+
+		vbank(0);
+		vcputsv(instob, 64, idbox[16][4], idbox[16][5],
+			idbox[16][6] + 1, idbox[16][7], bfs, 14);
+
+		imflag = TRUE;
+/* 
+
+*/
+	} else {		/* just moving the cursor */
+
+		cyval += cyrate;
+
+		if (cyval GT (CYMAX - 1))
+			cyval = CYMAX - 1;
+		else if (cyval LT 1)
+			cyval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idcxupd() -- update cursor x location from time
+   =============================================================================
+*/
+
+idcxupd()
+{
+	register unsigned th, tl;
+	register unsigned fptime, stime;
+	short zone;
+
+	if (idimsw) {			/* see if instrument menu is up */
+
+		cxval += cxrate;
+
+		if (cxval > CTOX(32))
+			cxval = CTOX(32);
+		else if (cxval < CTOX(26))
+			cxval = CTOX(26);
+
+	} if (idsrcsw OR idcfsw) {	/* see if we're in a submenu */
+
+		vtccol = XTOC(vtxval += cxrate);
+
+		if (vtccol > 46)
+			vtxval = CTOX(vtccol = 46);
+		else if (vtccol < 17)
+			vtxval = CTOX(vtccol = 17);
+
+	} else if (idnamsw) {		/* see if we're in the typewriter */
+
+		vtcxupd();
+/* 
+
+*/
+	} else if (pntsv) {		/* see if we're moving a point */
+
+		for (zone = 0; zone LE 8; zone++)	/* find display zone */
+			if (cxval LE zonemax[zone])
+				break;
+
+		switch (pecase) {
+
+		case 0:		/* single point */
+		case 1:		/* last point */
+
+			if (cxrate GE 0)
+				fptime = addfpu(pntptr->iptim,
+						cxrate * zoneinc[zone]);
+			else
+				fptime = subfpu(pntptr->iptim,
+						-cxrate * zoneinc[zone]);
+
+			stime = segtime(subj, fptime);
+
+			if (stime GE temax) {
+
+				setseg(subj, temax - 1);
+				break;
+
+			} else if (stime EQ 0) {
+
+				setseg(subj, 1);
+				break;
+			}
+
+			setseg(subj, stime);
+			break;
+
+/* 
+
+*/
+		case 2:		/* interior point */
+
+			if (cxrate GE 0)
+				fptime = addfpu(pntptr->iptim, cxrate * zoneinc[zone]);
+			else
+				fptime = subfpu(pntptr->iptim, -cxrate * zoneinc[zone]);
+
+			stime = temin + fromfpu(fptime);
+
+			if (stime GE temax)
+				break;
+
+			setseg(subj, segtime(subj, fptime));
+			setseg(subj + 1, temax);
+			break;
+		}
+
+		th  = timeto(curfunc, subj);		/* display the time */
+		tl  = th - ((th / 1000) * 1000);
+		th /= 1000;
+
+		sprintf(bfs, "%02d.%03d", th, tl);
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		vcputsv(instob, 64, idbox[15][4], idbox[15][5],
+			idbox[15][6] + 1, idbox[15][7], bfs, 14);
+
+		imflag = TRUE;
+		cxval = ttox(timeto(curfunc, subj), 12);
+
+	} else {		/* just moving the cursor */
+
+		cxval += cxrate;
+
+		if (cxval GT (CXMAX- 1))
+			cxval = CXMAX - 1;
+		else if (cxval LT 1)
+			cxval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idnfld() -- process not-in-field key entry
+   =============================================================================
+*/
+
+short
+idnfld(k)
+short k;
+{
+	register short endpnt, basepnt, t, fn;
+	register struct idfnhdr *fp;
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];
+	fp = &ip->idhfnc[curfunc];
+
+	if (astat) {
+
+		if (whatbox()) {
+
+			if (hitbox EQ 12) {		/* edit window */
+
+				if (k EQ 8)  {		/* - = toggle I_TM_KEY */
+
+					t = (fp->idftmd ^= I_TM_KEY);
+
+					if (v_regs[5] & 0x0180)
+						vbank(0);
+
+					tsplot4(instob, 64,
+						((t & I_TM_KEY) ?
+						  idbox[curfunc][4] : ID_INST),
+						4, 54, idbxlbl[curfunc], 14);
+
+					modinst();
+					return(SUCCESS);
+/* 
+
+*/
+				} else if (k EQ 9) {	/* + = new point */
+
+					basepnt = fp->idfpt1;
+					endpnt = basepnt + fp->idfpif - 1;
+
+					if (fp->idfpif EQ 99)
+						return(FAILURE);
+
+					if (FALSE EQ inspnt(ip, curfunc, endpnt)) {
+
+						return(FAILURE);
+
+					} else {
+
+						subj = fp->idfpif - 1;
+						pntsel();
+						pntsv = 1;
+						memset(pntptr, 0, sizeof (struct instpnt));
+						pntptr->ipval = (pntptr -1)->ipval;
+						setseg(subj, timeto(curfunc, subj - 1) + 1);
+						edfunc(curfunc);
+						showpt(1);
+						cxval = ttox(timeto(curfunc, subj), 12);
+						cyval = vtoy((pntptr->ipval >> 5), 12);
+						arcurs(ID_SELD);
+						gcurpos(cxval, cyval);
+						modinst();
+						return(SUCCESS);
+					}
+
+				}
+/* 
+
+*/
+			} else if (hitbox < 12 ) {	/* label window */
+
+				fn = (hitbox EQ curfunc) ? 12 : hitbox;
+
+				if (k EQ 8) {		/* + = toggle I_TM_KEY */
+
+					if (v_regs[5] & 0x0180)
+						vbank(0);
+
+					tsplot4(instob, 64,
+						(((ip->idhfnc[fn].idftmd ^= I_TM_KEY) & I_TM_KEY)
+						  ? idbox[fn][4] : ID_INST),
+						idbox[hitbox][6], idbox[hitbox][7],
+						idbxlbl[fn], 14);
+
+					modinst();
+				}
+			}
+		}
+
+		return(FAILURE);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idx_key() -- process the 'X' (delete) key
+   =============================================================================
+*/
+
+idx_key()
+{
+	register struct sment *smp;
+	register struct valent *vep;
+	register short i;
+	register struct instdef *ip;
+
+	if (astat) {
+
+		if (idsrcsw OR idcfsw OR idnamsw OR (wcflag NE -1))
+			return;
+
+		if (stcrow EQ 16) {
+
+			if ((stccol GE 1) AND (stccol LE 7)) {
+
+				/* general source */
+
+				vep = &valents[0];
+				smp = vpsms[(curvce << 4) + fnoff[curfunc]];
+
+				if (smp->sm NE SM_NONE) {	/* check for new general S/M */
+
+					(smp->prv)->nxt = smp->nxt;	/* unlink from old S/M chain */
+					(smp->nxt)->prv = smp->prv;
+
+					smp->prv = (struct sment *)vep;	/* link into new S/M chain */
+					smp->nxt = vep->nxt;
+					(vep->nxt)->prv = smp;
+					vep->nxt = smp;
+
+					smp->sm = SM_NONE;		/* update sment S/M entry */
+				}
+
+				vbufs[curvce].idhfnc[curfunc].idfsrc = SM_NONE;
+				dswin(13);
+				modinst();
+/* 
+
+*/
+			} else if ((stccol EQ 15) OR (stccol EQ 16)) {
+
+				/* current point and points to the right */
+
+				delpnts();
+
+			} else if ((stccol GE 33) AND (stccol LE 39)) {
+
+				/* point source */
+
+				pntptr->ipvsrc = SM_NONE;
+				dswin(16);
+				modinst();
+			}
+
+		} else if ((stcrow EQ 17) AND
+			((stccol EQ 31) OR (stccol EQ 32))) {
+
+			/* entire instrument */
+
+			initi(&vbufs[curvce]);
+			execins(curvce, 0, 0);
+			setinst();
+			allwins();
+			modinst();
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idfield() -- setup field routines for the score display
+   =============================================================================
+*/
+
+idfield()
+{
+	idimsw  = FALSE;
+	curslim = 210;
+
+	curset(&id_flds);
+}
Index: ram/idselbx.c
===================================================================
--- ram/idselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/idselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,622 @@
+/*
+   =============================================================================
+	idselbx.c -- instrument definition box selection functions
+	Version 46 -- 1988-09-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	short	(*itxput)();
+
+extern	short	lseg(), dswin(), tsplot4(), vbfill4(), enterit(), vtdisp();
+extern	short	advicur(), bspicur();
+
+extern	short	drawfn(), selpnt(), ttox(), vtoy();
+
+extern	unsigned	timeto(), exp_c();
+
+/* 
+
+*/
+
+extern	short	cursbox, cxval, cyval;
+extern	short	curvce, curfunc, curpnt;
+extern	short	hitbox, hitcx, hitcy, idnamsw, idimsw, idtdat;
+extern	short	pntsv, pecase, stccol, subj, submenu;
+
+extern	unsigned	temin, temax;
+
+extern	struct	selbox	*csbp, *curboxp;
+extern	struct	instdef vbufs[];
+extern	struct	instdef idefs[];
+
+extern	struct	instpnt	*pntptr;
+
+extern	short	idbox[][8];
+extern	short	instmod[];
+
+extern	char	*vtdeptr;
+
+extern	char	*idbxlbl[];
+extern	char	idhlbl[];
+extern	char	bfs[];
+
+extern	unsigned	*instob;
+
+/* forward references */
+
+short	bx_null(), idfnbox();
+
+/* 
+
+*/
+
+struct	selbox	idboxes[] = {
+
+	{  1,   1,  84,  26,      0, idfnbox},	/*  0: Freq 1 */
+	{ 86,   1, 169,  26,      1, idfnbox},	/*  1: Freq 2 */
+	{171,   1, 254,  26,      2, idfnbox},	/*  2: Freq 3 */
+	{256,   1, 339,  26,      3, idfnbox},	/*  3: Freq 4 */
+	{341,   1, 424,  26,      4, idfnbox},	/*  4: Filter / Resonance */
+	{426,   1, 509,  26,      5, idfnbox},	/*  5: Location */
+
+	{  1,  28,  84,  54,      6, idfnbox},	/*  6: Index 1 */
+	{ 86,  28, 169,  54,      7, idfnbox},	/*  7: Index 2 */
+	{171,  28, 254,  54,      8, idfnbox},	/*  8: Index 3 */
+	{256,  28, 339,  54,      9, idfnbox},	/*  9: Index 4 */
+	{341,  28, 424,  54,     10, idfnbox},	/* 10: Index 5 */
+	{426,  28, 509,  54,     11, idfnbox},	/* 11: Index 6 */
+
+	{  1,  56, 509, 208,     12, idfnbox},	/* 12: Level */
+
+	{  1, 210, 110, 236, 0x0000, enterit},	/* 13: Source- Mlt */
+	{112, 210, 142, 236, 0x0000, enterit},	/* 14: Pt */
+	{144, 210, 206, 236, 0x0000, enterit},	/* 15: Time */
+	{208, 210, 366, 236, 0x0000, enterit},	/* 16: Value */
+	{368, 210, 509, 236, 0x0000, enterit},	/* 17: Action */
+
+	{  1, 238, 131, 348, 0x0000, idfnbox},	/* 18: Algorithm */
+	{133, 238, 267, 251, 0x0000, idfnbox},	/* 19: Voice & Inst */
+	{269, 238, 379, 306, 0x0000, enterit},	/* 20: Oscillators */
+	{381, 238, 509, 348, 0x0000, idfnbox},	/* 21: Waveshape */
+
+	{133, 308, 379, 348, 0x0000, enterit},	/* 22: Variables */
+
+	{133, 252, 267, 306,     19, idfnbox},	/* 23: Name & Comments */
+
+	{  0,   0,   0,   0, 	  0, FN_NULL}	/* end of table */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idtxput() -- put out instrument menu text for the instrument display
+   =============================================================================
+*/
+
+idtxput(row, col, txt, tag)
+short row, col;
+char *txt;
+short tag;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	tsplot4(instob, 64, CFBX19, row, col, txt, 14);
+}
+
+/*
+   =============================================================================
+	showim() -- show the instrument menu
+   =============================================================================
+*/
+
+showim()
+{
+	register short row, col, ins;
+
+	ins = 0;
+
+	for (col = 1; col < 46; col += 22) {
+
+		(*itxput)(0, col, "No Instrument", 0);
+
+		for (row = 1; row < 15; row++) {
+
+			if (ins GE NINST)
+				break;
+
+			sprintf(bfs, "%02d %-16.16s", ins, idefs[ins].idhname);
+			(*itxput)(row, col, bfs, 1);
+			++ins;
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cdnicur() -- instrument definition virtual typewriter -- cursor down
+   =============================================================================
+*/
+
+cdnicur()
+{
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];
+
+	switch (idtdat) {
+
+	case 0:
+		idtdat = 1;
+		vtdeptr = ip->idhcom1;
+		settc(19, stccol);
+		return;
+
+	case 1:
+		idtdat = 2;
+		vtdeptr = ip->idhcom2;
+		settc(20, stccol);
+		return;
+
+	case 2:
+		idtdat = 3;
+		vtdeptr = ip->idhcom3;
+		settc(21, stccol);
+		return;
+
+	case 3:
+		idtdat = 0;
+		vtdeptr = ip->idhname;
+		settc(18, stccol);
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cupicur() -- instrument definition virtual typewriter -- cursor up
+   =============================================================================
+*/
+
+cupicur()
+{
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];
+
+	switch (idtdat) {
+
+	case 0:
+		idtdat = 3;
+		vtdeptr = ip->idhcom3;
+		settc(21, stccol);
+		return;
+
+	case 1:
+		idtdat = 0;
+		vtdeptr = ip->idhname;
+		settc(18, stccol);
+		return;
+
+	case 2:
+		idtdat = 1;
+		vtdeptr = ip->idhcom1;
+		settc(19, stccol);
+		return;
+
+	case 3:
+		idtdat = 2;
+		vtdeptr = ip->idhcom2;
+		settc(20, stccol);
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	edfunc() -- setup to edit a function
+   =============================================================================
+*/
+
+short
+edfunc(n)
+short n;
+{
+	register unsigned cx;
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];
+
+	/* first, put level in selected window */
+
+	cx = exp_c(ID_LVLC);	/* label background = level background */
+
+	vbank(0);
+	vbfill4(instob, 128, idbox[n][0], idbox[n][1],
+		idbox[n][2], idbox[n][3], cx);
+
+	tsplot4(instob, 64,
+		((ip->idhfnc[12].idftmd & I_TM_KEY) ? idbox[n][4] : ID_INST),
+		 idbox[n][6], idbox[n][7], idbxlbl[12], 14);
+
+	if (n NE 12)	/* if not editing the level, draw it in the label */
+		drawfn(12, 0, ID_CLVL, n);
+
+/* 
+
+*/
+	/* next, put the level and selected functions in the level window */
+
+	vbank(0);		/* clear the edit/level  box */
+	vbfill4(instob, 128, idbox[12][0], idbox[12][1],
+		idbox[12][2], idbox[12][3], cx);
+
+	/* label the function */
+
+	tsplot4(instob, 64,
+		((ip->idhfnc[n].idftmd & I_TM_KEY) ? idbox[n][4] : ID_INST),
+		idbox[12][6], idbox[12][7], idbxlbl[n], 14);
+
+	/* scale -- x labels */
+
+	tsplot4(instob, 64, TGRID, 14, 0, idhlbl, 14);
+
+	/* scale -- y labels */
+
+	tsplot4(instob, 64, TGRID, 14, 0, "\300", 14);
+	tsplot4(instob, 64, TGRID, 12, 0, "\302", 14);
+	tsplot4(instob, 64, TGRID, 10, 0, "\304", 14);
+	tsplot4(instob, 64, TGRID,  8, 0, "\306", 14);
+	tsplot4(instob, 64, TGRID,  6, 0, "\310", 14);
+	tsplot4(instob, 64, TGRID,  4, 0, "\312", 14);
+
+	lseg( 7,  56,   7, 196, LGRID);		/* draw the scale */
+	lseg( 7, 196, 509, 196, LGRID);
+
+	/* plot functions:  first level, then selected function */
+
+	if (n NE 12)	/* if not editing level, draw it as a reference */
+		drawfn(12, 0, ID_CLVL, 12);
+
+	drawfn(n, pntsv, ID_CLIN, 12);
+
+	curfunc = n;		/* make n the current function */
+
+	if (curfunc EQ 4) {
+
+		tsplot4(instob, 64,
+			((ip->idhfnc[n].idftmd & I_TM_KEY) ?
+				idbox[12][4] : ID_INST),
+			idbox[12][6] + 1, idbox[12][7] + 4, "Res", 14);
+
+		rd_ires(12);
+	}
+
+	return(TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showpt() -- show the data about a point
+   =============================================================================
+*/
+
+showpt(q)
+short q;
+{
+	register short	ptx, pty, i, j, k;
+	register struct instdef *ip;
+	short ptc;
+
+	if (q)
+		dswin(14);	/* point number */
+
+	dswin(15);		/* time */
+	dswin(16);		/* value */
+	dswin(17);		/* action */
+
+	ip = &vbufs[curvce];
+	j = ip->idhfnc[curfunc].idfpif;
+	k = ip->idhfnc[curfunc].idfpt1;
+
+	for (i = 0; i < j; i++) {
+
+		ptx = ttox(timeto(curfunc, i), 12);
+		pty = vtoy((ip->idhpnt[k + i].ipval) >> 5, 12);
+		ptc = ((ip->idhpnt[k + i].ipvsrc) OR (ip->idhpnt[k + i].ipact) ?
+			ID_ACTP : ID_CPNT);
+
+		drawpt(ptx, pty, ptc);
+	}
+
+	ptx = ttox(timeto(curfunc, subj), 12);
+	pty = vtoy((ip->idhpnt[k + subj].ipval) >> 5, 12);
+	drawpt(ptx, pty, ID_SELD);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	endityp() -- exit instrument definition virtual typewriter
+   =============================================================================
+*/
+
+endityp()
+{
+	idnamsw = FALSE;
+	submenu = FALSE;
+	idvlblc();
+	dswin(19);
+	dswin(22);
+}
+
+/*
+   =============================================================================
+	showfn() show the data about a function
+   =============================================================================
+*/
+
+showfn()
+{
+	dswin(13);	/* source multiplier */
+	showpt(1);	/* point, time, value, action */
+}
+
+/*
+   =============================================================================
+	bx_null() -- null item selection processor
+   =============================================================================
+*/
+
+short
+bx_null()
+{
+	return(TRUE);
+}
+
+/*
+   =============================================================================
+	iclrwin() -- clear an instrument editor window
+   =============================================================================
+*/
+
+iclrwin(n)
+register short n;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(instob, 128, idbox[n][0], idbox[n][1], idbox[n][2], idbox[n][3],
+		exp_c(idbox[n][5]));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idfnbox() -- instrument display function box hit processor
+   =============================================================================
+*/
+
+short
+idfnbox(n)
+short n;
+{
+	register short col, i, row;
+	register struct instdef *ip;
+	register char *ivtdptr;
+
+	ip = &vbufs[curvce];
+
+	row = hitcy / 14;
+	col = hitcx >> 3;
+
+/* 
+
+*/
+	if (hitbox EQ 12) {		/* process a hit in the level window */
+
+		/* handle data entry special case for resonance in filter fn. */
+
+		if ((curfunc EQ 4) AND (row EQ 5) AND (col EQ 62))
+			return(enterit());
+
+		switch (pntsv) {	/* dispatch off of point select state */
+
+		case 0:		/* nothing selected so far:  select a point */
+
+			subj = selpnt();	/* decide on the point */
+			pntsel();		/* make it current */
+			pntsv = 1;		/* say it's selected */
+
+			edfunc(curfunc);	/* update the display */
+			showpt(1);
+
+			/* set cursor to point */
+
+			cxval = ttox(timeto(curfunc, subj), 12);
+			cyval = vtoy((pntptr->ipval >> 5), 12);
+			arcurs(ID_SELD);
+			gcurpos(cxval, cyval);
+			break;
+
+		case 1:		/* point was selected:  unselect it */
+
+			pntsv = 0;
+			edfunc(curfunc);
+			arcurs(ID_NCUR);
+			gcurpos(cxval, cyval);
+			break;
+		}
+
+		return(TRUE);
+
+	} else if (hitbox EQ 18) {		/* configuration */
+
+		if ((row EQ 17) AND (col GE 4) AND (col LE 9)) {
+
+			wcmenu(0);
+			return(TRUE);
+
+		} else {
+
+			return(enterit());
+		}
+/* 
+
+*/
+	} else if (hitbox EQ 19) {		/* voice & inst. */
+
+		if ((col GE 26) AND (col LE 29) AND (row EQ 17)) {
+
+			if (idimsw) {	/* menu is up, take it down */
+
+				idimsw = FALSE;
+
+				if (v_regs[5] & 0x0180)
+					vbank(0);
+
+				idbord();
+				allwins();
+
+			} else {	/* menu is down, put it up */
+
+				idimsw = TRUE;
+				itxput = idtxput;
+
+				if (v_regs[5] & 0x0180)
+					vbank(0);
+
+				vbfill4(instob, 128, 1, 1, 510, 208,
+					exp_c(idbox[19][5]));
+
+				for (i = 13; i LE 18; i++)
+					iclrwin(i);
+
+				for (i = 20; i LE 22; i++)
+					iclrwin(i);
+
+				showim();
+			}
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());	/* do data entry */
+		}
+/* 
+
+*/
+	} else if (hitbox EQ 21) {	/* waveshapes */
+
+		if ((row EQ 17) AND (col GE 48) AND (col LE 54)) {
+
+			wcmenu(1);
+			return(TRUE);
+
+		} else {
+
+			return(enterit());
+		}
+
+	} else if (hitbox EQ 23) {	/* process a hit in the name window */
+
+		if (idnamsw) {		/* typewriter up - enter data */
+
+			vtyper();
+			instmod[curvce] = TRUE;
+
+		} else {		/* put up the typewriter */
+
+			/* set data pointer */
+
+			if (row EQ 18)
+				ivtdptr = ip->idhname;
+			else if (row EQ 19)
+				ivtdptr = ip->idhcom1;
+			else if (row EQ 20)
+				ivtdptr = ip->idhcom2;
+			else
+				ivtdptr = ip->idhcom3;
+
+			idtdat = row - 18;
+
+			idvtyp();		/* display typewriter */
+			dswin(22);
+			idnamsw = TRUE;
+			submenu = TRUE;
+
+			vtsetup(instob, vtdisp, 17, ivtdptr, 22, 17,
+				advicur, bspicur, cupicur, cdnicur, endityp,
+				idbox[19][4], idbox[19][5]);
+		}
+
+		return(TRUE);
+/* 
+
+*/
+	} else if (hitbox < 12) {	/* process a hit in a label window */
+
+		pntsv = 0;			/* unselect previous point */
+
+		arcurs(ID_NCUR);		/* set cursor color */
+		gcurpos(cxval, cyval);
+
+		if (n NE curfunc) {		/* new function selected */
+
+			if (curfunc NE 12)
+				dswin(curfunc);	/* stow old function */
+
+			edfunc(n);		/* select new function */
+
+		} else {			/* reselect level */
+
+			dswin(curfunc);		/* stow old function */
+			edfunc(12);		/* select level */
+		}
+
+		subj = 0;			/* reset function selection */
+		pntsel();
+
+		showfn();			/* update display */
+
+		setgc(ICURX, ICURY);		/* put cursor in center */
+		return(TRUE);
+	}
+
+	return(FALSE);
+}
Index: ram/im700.c
===================================================================
--- ram/im700.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/im700.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,936 @@
+/*
+   =============================================================================
+	im700.c -- variable definitions and initialization for MIDAS-VII
+	Version 102 -- 1989-11-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGVAL	0		/* initial value for debugsw */
+
+#define	FET_DEFS	1		/* so fields.h gets things right */
+#define	M7CAT		1		/* so libdsp.h gets it right */
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "cmeta.h"
+#include "curpak.h"
+#include "fields.h"
+#include "fpu.h"
+#include "glcfns.h"
+#include "glcdefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "macros.h"
+#include "memory.h"
+#include "objdefs.h"
+#include "panel.h"
+#include "sclock.h"
+#include "scwheel.h"
+#include "slice.h"
+#include "smdefs.h"
+#include "timers.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+
+#include "midas.h"
+
+#include "asgdsp.h"
+#include "instdsp.h"
+#include "libdsp.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+#include "wsdsp.h"
+
+extern	unsigned	tofpu();
+
+extern	short	nokey(), stdmkey(), cxkstd(), cykstd(), cxgen(), cygen();
+extern	short	cmvgen(), stdctp2();
+
+extern	short	blakpal[16][3];
+
+extern	PFS	t_prmtr[];
+
+extern	char	*funcndx[256][2];
+
+extern	char	keystat[24];
+extern	char	ldcmnt[38];
+extern	char	ldfile[9];
+extern	char	loadedc[NLTYPES][37];
+extern	char	loadedf[NLTYPES][8];
+extern	char	masens[3];
+extern	char	mctlval[NCTRLS];
+extern	char	mdbyte[3];
+extern	char	mpsust[48];
+extern	char	mrstat[3];
+extern	char	trgtab[NTRIGS];
+
+extern	short	fnoff[];
+
+extern	short	articen[12];		/* voice articulation enable status */
+extern	short	grpmode[12];		/* group mode - 0 = play, 1 = stdby, 2 = rec */
+extern	short	grpsel[12];		/* group select status for instrument selection */
+extern	short	grpstat[12];		/* group status - 0 = off, non-0 = on */
+extern	short	gtctab[12];		/* group to color table */
+extern	short	lastvce[12];		/* last voice assigned in each group */
+extern	short	lastvel[12];		/* last velocity sent to group */
+extern	short	mpbend[48];		/* MIDI pitch bend data, by port and channel */
+extern	short	msmstv[3];		/* MIDI state machine state variables */
+extern	short	prstab[NTRIGS];		/* pressure */
+extern	short	vce2trg[12];		/* voice to trigger map (-1 EQ NULL) */
+extern	short	veltab[NTRIGS];		/* velocity */
+
+/* 
+
+*/
+
+extern	PFS	(*oldsw)[];		/* saved swpt value */
+extern	PFS	(*swpt)[];		/* switch dispatch table pointer */
+
+extern	short	(*curmove)();		/* cursor move function */
+extern	short	(*curtype)();		/* cursor type function */
+extern	short	(*cx_key)();		/* x rate calculation */
+extern	short	(*cx_upd)();		/* x update */
+extern	short	(*cy_key)();		/* y rate calculation */
+extern	short	(*cy_upd)();		/* y update */
+extern	short	(*d_key)();		/* in-field data key processor */
+extern	short	(*e_key)();		/* E key processor */
+extern	short	(*m_key)();		/* M key processor */
+extern	short	(*not_fld)();		/* not-in-field data key processor */
+extern	short	(*premove)();		/* cursor pre-move function */
+extern	short	(*pstmove)();		/* cursor post-move function */
+extern	short	(*x_key)();		/* X key processor */
+extern	short	(*xy_dn)();		/* cursor - finger on (down) */
+extern	short	(*xy_up)();		/* cursor - finger off (up) */
+
+extern	short	*cratex;		/* cursor x rate table pointer */
+extern	short	*cratey;		/* cursor x rate table pointer */
+
+short	admctl;			/* assignment display submenu control variable */
+short	adnamsw;		/* assignment display virtual typewriter flag */
+short	aflag;			/* analog activity flag */
+short	aform;			/* action buffer format */
+short	amplval;		/* amplitude */
+short	ancmsw;			/* analog variable r/p control source */
+short	angroup;		/* analog variable group being shown */
+short	asgfks;			/* first key selected */
+short	asghit;			/* row hit / assignment in progress */
+short	asgmod;			/* assignment number or table modified */
+short	asig;			/* analog signal number */
+short	asmode;			/* panel assignment mode */
+short	astat;			/* analog signal status */
+short	auxctl;			/* aux control flag */
+short	aval;			/* analog signal value */
+short	bform;			/* oscillator data buffer format */
+short	catin;			/* catalog read in flag */
+short	cents;			/* pitch to cents conversion buffer */
+short	chtime;			/* horizontal cursor counter */
+short	chwait;			/* horizontal cursor wait time */
+short	cflag;			/* accidental flag */
+short	clkctl;			/* clock control */
+short	clkrun;			/* clock status */
+short	clksrc;			/* clock source */
+short	cmfirst;		/* first cursor motion switch */
+short	cmtype;			/* cursor motion type */
+short	cnote;			/* note value at cursor */
+short	ctrsw;			/* scupd center update switch */
+short	curasg;			/* current assignment table */
+short	curfunc;		/* current function number */
+short	curgrp;			/* current group */
+short	curinst;		/* current instrument number */
+short	curmop;			/* current MIDI output port */
+short	curpnt;			/* current point number (absolute) */
+short	curpos;			/* cursor pad position for current axis */
+short	cursbox;		/* currently selected box */
+short	curscor;		/* Current score number */
+short	cursect;		/* current section */
+short	curslim;		/* cursor type change point */
+short	curtun;			/* current tuning table */
+short	curvce;			/* current voice number */
+short	curwave;		/* current waveshape library slot */
+short	curwdth;		/* current waveshape cursor width */
+short	curwfnl;		/* current waveshape final value */
+short	curwhrm;		/* current waveshape harmonic number */
+short	curwhrv;		/* current waveshape harmonic value */
+short	curwoff;		/* current waveshape offset value */
+short	curwpnt;		/* current waveshape point number */
+short	curwslt;		/* current waveshape instrument slot */
+short	cvtime;			/* vertical cursor counter */
+short	cvwait;			/* veritcal cursor wait time */
+short	cxrate;			/* cursor x rate */
+short	cxval;			/* graphic cursor x value */
+short	cyrate;			/* cursor y rate */
+short	cyval;			/* graphic cursor y value */
+short	debugne;		/* debug flag for note entry */
+short	defect;			/* defect code */
+short	dferror;		/* error code from BIOS or XBIOS */
+short	dfsides;		/* number of sides */
+short	dftype;			/* disk type code */
+short	dsp_ok;			/* display update OK this cycle flag */
+short	dubsw;			/* overdub / replace switch */
+short	ebflag;			/* edit buffer data flag */
+short	editss;			/* edit panel switch state */
+short	editsw;			/* edit mode switch */
+short	endflg;			/* !end flag */
+short	ext_cv1;		/* CV-1 value */
+short	ext_cv2;		/* CV-2 value */
+short	ext_cv3;		/* CV-3 value */
+short	ext_cv4;		/* CV-4 value */
+short	ext_mod;		/* Aux Signal Mod value */
+short	gomode;			/* go to mode */
+short	grptran;		/* group translation value */
+short	gtmsel;			/* group transpose/map select */
+short	hitbox;			/* box we just hit */
+short	hitcx;			/* x of cursor when we hit the box */
+short	hitcy;			/* y of cursor when we hit the box */
+short	idcfsw;			/* copy / fetch menu switch */
+short	idimsw;			/* instrument display instrument menu switch */
+short	idintmp;		/* temporary for instrument number */
+short	idnamsw;		/* typewriter switch */
+short	idsrcsw;		/* source menu switch */
+short	idtdat;			/* current instrument vtyper data entry string */
+short	imflag;			/* instrument modified flag */
+short	initcfg;		/* initial configuration */
+short	insmode;		/* score insert mode */
+short	ismode;			/* instrument select mode */
+short	lampio;			/* LCD timeout disable switch state at I/O time */
+short	lampsw;			/* LCD timeout disable switch */
+short	lasgsw;			/* assignments store switch */
+short	lastam;			/* last assignment menu base */
+short	ldelsw;			/* delete switch */
+short	lderrsw;		/* error message displayed switch */
+short	ldidsiz;		/* getcat() did showsiz() switch */
+short	ldkind;			/* fetch file type */
+short	ldpass;			/* librarian load state variable */
+short	ldrow;			/* fetch select row */
+short	ldslot;			/* fetch select slot */
+short	legato;			/* execkey() "legato" mode switch */
+short	lksel;			/* librarian key slot selector */
+short	lmwtype;		/* librarian message window type */
+short	loadrow;		/* librarian row selected for load letter */
+short	loadsw;			/* panel "Load" mode state */
+short	lorchl;			/* load hi (TRUE) / lo (FALSE) orchestra */
+short	lorchsw;		/* hi orchestra (21 - 40) store switch */
+short	lorclsw;		/* lo orchestra (01 - 20) store switch */
+short	lpatsw;			/* patch table store switch */
+short	lrasw;			/* append (TRUE) / replace (FALSE) score */
+short	lscrsw;			/* score store switch */
+short	lselsw;			/* fetch select switch */
+short	lseqsw;			/* sequence table store switch */
+short	lstbgnc;		/* last note begin entry table index */
+short	lstendc;		/* last note end entry table index */
+short	lstflag;		/* last note list end switch */
+short	lstrsw;			/* store state switch */
+short	lstwoff;		/* last waveshape offset value */
+short	lstwpnt;		/* last waveshape point number */
+short	ltagged;		/* load tag switch */
+short	ltunsw;			/* tunings store switch */
+short	lwavsw;			/* waveshapes store switch */
+short	mascntr;		/* MIDI active sensing timeout counter */
+short	mdb1;			/* current MIDI data byte 1 */
+short	mdb2;			/* current MIDI data byte 2 */
+short	michan;			/* current MIDI channel */
+short	midiclk;		/* MIDI clock switch */
+short	midigo;			/* MIDI run switch */
+short	mistat;			/* current MIDI status */
+short	nchwait;		/* next chwait value */
+short	ncvwait;		/* next cvwait value */
+short	ndisp;			/* current display number */
+short	newflag;		/* new data entered while t_cur EQ t_ctr */
+short	nkdown;			/* number of keys down */
+short	notenum;		/* note number */
+short	noteop;			/* pending note operation code */
+short	notepit;		/* note pitch */
+short	notesel;		/* note selection state */
+short	npts;			/* number of points in function */
+short	nxtflag;		/* next score flag */
+short	oldltag;		/* previous load tag for tagslot */
+short	oldpk;			/* previous pkctrl state */
+short	oldsl;			/* previous sliders state */
+short	pchsw;			/* punch-in enable switch */
+short	pecase;			/* point edit case variable */
+short	pkctrl;			/* local performance key state */
+short	pntsv;			/* point selection state variable */
+short	prgchan;		/* MIDI program change channel  (port 1) */
+short	ps_dpth;		/* phase shifter -- depth */
+short	ps_intn;		/* phase shifter -- intensity */
+short	ps_rate;		/* phase shifter -- rate */
+short	pulsclk;		/* pulse clock state */
+short	recsw;			/* record / play switch */
+short	runit;			/* run switch for main scan loop */
+short	sbase;			/* score VSDD RAM scroll offset */
+short	scmctl;			/* score submenu control flag */
+short	scrlpot;		/* scroll pot state */
+short	sd;			/* score display direction */
+short	se;			/* score execution direction */
+short	sdmcol;			/* score menu - saved stccol */
+short	sdmctl;			/* score menu - control variable */
+short	sdmrow;			/* score menu - saved stcrow */
+short	secop;			/* pending score section operation */
+short	secopok;		/* section operation OK flag */
+short	sgcsw;			/* graphic cursor display switch */
+short	sgoflag;		/* section number relative column 0..3 */
+short	sharp;			/* sharp flag */
+short	sliders;		/* slider and switch state */
+short	soffset;		/* score scroll offset */
+short	ss_ptsw;		/* smooth scroll patch scroll switch */
+short	ss_sqsw;		/* smooth scroll sequence scroll switch */
+short	stccol;			/* score cursor col */
+short	stcrow;			/* score cursor row */
+short	stepclk;		/* note entry - step clock state */
+short	stepenb;		/* note entry - step enable flag */
+short	stepint;		/* note entry - note interval */
+short	stepwgt;		/* note entry - note weight */
+short	subj;			/* edited point number (relative) */
+short	submenu;		/* submenu active switch */
+short	swctrl;			/* scroll wheel 'srolling' flag */
+short	swdelta;		/* scroll wheel change while touched */
+short	swdir;			/* scroll wheel direction */
+short	swfiin;			/* scroll wheel fifo input pointer */
+short	swflag;			/* scroll wheel touched flag */
+short	swlast;			/* scroll wheel last value */
+short	swstop;			/* scroll wheel stop flag */
+short	swndx;			/* scroll wheel look back index */
+short	tagslot;		/* tagged load slot */
+short	tdnamsw;		/* tuning editor displaying typewriter */
+short	temax;			/* time upper limit */
+short	temin;			/* time lower limit */
+short	testing;		/* test level */
+short	tglclk;			/* clock on/off toggle flag */
+short	tglpch;			/* punch in/out toggle flag */
+short	thescore;		/* score selected from sqscan */
+short	timemlt;		/* time scaling */
+short	tkctrl;			/* trackball active flag */
+short	tmpomlt;		/* tempo multiplier */
+short	tmpoval;		/* tempo value */
+short	trkball;		/* trackball selected switch */
+short	ttcmdsv;		/* tuning editor edit state variable */
+short	ttsel1;			/* tuning editor key select variable 1 */
+short	ttsel2;			/* tuning editor key select variable 2 */
+short	ttsel3;			/* tuning editor key select variable 3 */
+short	tuneval;		/* fine tuning */
+short	tunmod;			/* tuning table modified */
+short	tunval;			/* tuning editor increment / transpose  value */
+short	txfiin;			/* trackball x fifo input pointer */
+short	txflag;			/* trackball x axis active flag */
+short	txlast;			/* trackball x axis last value */
+short	txstop;			/* trackball x axis filter counter */
+short	tyfiin;			/* trackball y fifo input pointer */
+short	tyflag;			/* trackball y axis active flag */
+short	tylast;			/* trackball y axis last value */
+short	tystop;			/* trackball y axis filter counter */
+short	velflag;		/* velocity display flag */
+short	verbose;		/* verbose output switch */
+short	vlbtype;		/* type of message window display */
+short	vrbw08;			/* score display video reset detail word */
+short	vrbw09;			/* score display video reset detail word */
+short	vrbw10;			/* score display video reset detail word */
+short	vrbw11;			/* score display video reset detail word */
+short	vrbw12;			/* score display video reset detail word */
+short	vrbw13;			/* score display video reset detail word */
+short	vrbw14;			/* score display video reset detail word */
+short	vrbw15;			/* score display video reset detail word */
+short	vrcw;			/* score display video reset control word */
+short	vtccol;			/* virtual typewriter cursor column */
+short	vtcrow;			/* virtual typewriter cursor row */
+short	vtdechr;		/* virtual typewriter data entry character */
+short	vtdecol;		/* virtual typewriter data entry column */
+short	vtpcol;			/* virtual typewriter column */
+short	vtprow;			/* virtual typewriter row */
+short	vtwcol;			/* virtual typewriter window left column */
+short	vtwrow;			/* virtual typewriter window top row */
+short	vtxval;			/* virtual typewriter cursor x value */
+short	vtyval;			/* virtual typewriter cursor y value */
+short	wcflag;			/* ws/cf menu select flag (cf=0, ws=1) */
+short	wcmcol;			/* ws/cf menu label column */
+short	wcmrow;			/* ws/cf menu label row */
+short	wcpage;			/* ws/cf menu page */
+short	wdupdfl;		/* waveshape display needs updated flag */
+short	wmcsel;			/* ws menu ws a/b select */
+short	wmctag;			/* ws/cf display update flag */
+short	wplast;			/* last point for interpolate operation */
+short	wpntsv;			/* waveshape point selection state variable */
+short	wshmax;			/* waveshape maximum value */
+short	wvlast;			/* last value for interpolate operation */
+short	xkcount;		/* cursor x key on count */
+short	xkstat;			/* cursor x key status */
+short	xycntr;			/* xy center for cursor pad */
+short	ykcount;		/* cursor y key on count */
+short	ykstat;			/* cursor y key status */
+
+short	anrs[8][16];			/* analog variable resolution */
+short	grp2prt[12][2];			/* group to port and channel table */
+short	sctctab[10][64];		/* score background color table */
+short	sigtab[128][2];			/* signals:  [0] = value, [1] = switch */
+short	tunlib[NTUNS][128];		/* tuning table library */
+short	varmode[8][16];			/* analog variable record mode */
+short	wsnmod[12][2];			/* waveshape number / data modified */
+
+struct	EXFILE	mphead;		/* MIDAS-VII program header */
+struct	fet	*cfetp;		/* current fet entry pointer */
+struct	fet	*curfet;	/* current fet table pointer */
+struct	fet	*infetp;	/* in-field fet pointer */
+struct	gdsel	*gdfsep;	/* gdsel freechain pointer */
+struct	instpnt	*pntptr;	/* pointer to edited point */
+struct	mlibhdr	ldhead;		/* library header */
+struct	nevent	*nefree;	/* pointer to free note entries */
+struct	nevent	*nelist;	/* pointer to note entry list */
+struct	octent	*adoct;		/* assignment display object control pointer */
+struct	octent	*ldoct;		/* librarian object control table pointer */
+struct	octent	*mdoct;		/* menu display object control table pointer */
+struct	octent	*tdoct;		/* tuning display object control table pointer */
+struct	octent	*wdoct;		/* object control table pointer */
+struct	octent	*idoct;		/* instrument display octent pointer */
+struct	pflent	*pflist;	/* pendant function list header */
+struct	pflent	*pfqhdr;	/* pendant function list entry freechain header */
+struct	s_entry	*libsp;		/* librarian score pointer */
+struct	s_entry	*peg;		/* insert mode 'peg' to hang the tail on */
+struct	s_entry	*size1;		/* score E_SIZE1 entry free list pointer */
+struct	s_entry	*size2;		/* score E_SIZE2 entry free list pointer */
+struct	s_entry	*size3;		/* score E_SIZE3 entry free list pointer */
+struct	selbox	*csbp;		/* current select box table pointer */
+struct	selbox	*curboxp;	/* current select box pointer */
+struct	s_entry *p_bak;		/* pointer to entry at left edge of display */
+struct	s_entry	*p_cbgn;	/* pointer to start of copy */
+struct	s_entry	*p_cend;	/* pointer to end of copy */
+struct	s_entry *p_cur;		/* pointer to entry at current execution time */
+struct	s_entry *p_ctr;		/* pointer to entry at center of display */
+struct	s_entry *p_fwd;		/* pointer to entry at right edge of display */
+struct	n_entry	*p_nbeg;	/* pointer to note begin */
+struct	n_entry	*p_nend;	/* pointer to note end */
+struct	s_entry	*p_sbgn;	/* pointer to start of section */
+struct	s_entry	*p_sec1;	/* pointer to start of 1st section */
+struct	s_entry	*p_sec2;	/* pointer to start of 2nd section */
+struct	s_entry	*p_send;	/* pointer to end of section */
+struct	s_entry *scp;		/* current score pointer */
+
+struct	asgent	asgtab[NASGS];		/* assignment table library */
+struct	fcat	filecat[FCMAX];		/* file catalog */
+struct	gdsel	*gdstbc[NGDSEL];	/* center group & event status lists */
+struct	gdsel	*gdstbn[NGDSEL];	/* right group & event status lists */
+struct	gdsel	*gdstbp[NGDSEL];	/* left group & event status lists */
+struct	gdsel	gdfsl[MAXFSL];		/* gdsel pool */
+struct	instdef	idefs[NINST];		/* current instrument definitions */
+struct	n_entry	*lstbgns[NLSTENTS];	/* last note begin entry table */
+struct	n_entry	*lstends[NLSTENTS];	/* last note end entry table */
+struct	instdef	vbufs[12];		/* voice instrument buffers */
+struct	nevent	nevents[NNEVTS];	/* note event list */
+struct	pflent	pfents[NPFENTS];	/* pendant function list entry pool */
+struct	scndx	sindex[N_SCORES];	/* score file table of contents */
+struct	sment	*vpsms[192];		/* voice parameter general S/M pointer table */
+struct	sment	sments[192];		/* source multiplier assignment table */
+struct	valent	valents[NGPSRS];	/* source value table */
+struct	wstbl	wslib[NUMWAVS];		/* waveshape library */
+struct	s_entry *scores[N_SCORES];	/* Score pointer table */
+
+struct	s_time	stimes[N_SCORES][N_SECTS];	/* score section SMPTE times */
+struct	s_entry *hplist[N_SCORES][N_TYPES];	/* Score change list pointers */
+struct	s_entry *seclist[N_SCORES][N_SECTS];	/* Section pointer table */
+
+unsigned	*asgob;		/* assignment display object pointer */
+unsigned	*consl;		/* constant slice pointer */
+unsigned	*cursl;		/* current (center) slice pointer */
+unsigned	*instob;	/* instrument object pointer */
+unsigned	*librob;	/* librarian display object pointer */
+unsigned	*menuob;	/* menu display object pointer */
+unsigned	*nxtsl;		/* next (right edge) slice pointer */
+unsigned	*obj0;		/* object  0 VSDD RAM pointer */
+unsigned	*obj1;		/* object  1 VSDD RAM pointer */
+unsigned	*obj2;		/* object  2 VSDD RAM pointer */
+unsigned	*obj3;		/* object  3 VSDD RAM pointer */
+unsigned	*obj4;		/* object  4 VSDD RAM pointer */
+unsigned	*obj5;		/* object  5 VSDD RAM pointer */
+unsigned	*obj6;		/* object  6 VSDD RAM pointer */
+unsigned	*obj7;		/* object  7 VSDD RAM pointer */
+unsigned	*obj8;		/* object  8 VSDD RAM pointer */
+unsigned	*obj9;		/* object  9 VSDD RAM pointer */
+unsigned	*obj10;		/* object 10 VSDD RAM pointer */
+unsigned	*obj11;		/* object 11 VSDD RAM pointer */
+unsigned	*obj12;		/* object 12 VSDD RAM pointer */
+unsigned	*obj13;		/* object 13 VSDD RAM pointer */
+unsigned	*obj14;		/* object 14 VSDD RAM pointer */
+unsigned	*obj15;		/* object 15 VSDD RAM pointer */
+unsigned	*prvsl;		/* previous (left edge) slice pointer */
+unsigned	*saddr;		/* score VSDD RAM base pointer */
+unsigned	*tunob;		/* tuning table display object pointer */
+unsigned	*vtobj;		/* virtual typewriter display object pointer */
+unsigned	*waveob;	/* waveshape display object pointer */
+
+unsigned	curintp;	/* current interpolate time (FPU format) */
+unsigned	scrl;		/* score VSDD object scroll register image */
+unsigned	vtbgval;	/* virtual typewriter data background color */
+unsigned	vtfgval;	/* virtual typewriter data foreground color */
+
+unsigned	dfbuf[4096];	/* track formatting buffer */
+unsigned	slices[896];	/* score display slices */
+
+/* 
+
+*/
+
+/* initialized variables */
+
+short	debugsw = DEBUGVAL;	/* debug output switch */
+
+short	swback  = SWBACK;	/* scroll wheel look back count */
+short	swthr   = SWTHR;	/* scroll wheel movement threshold */
+short	swtime  = SWTIME;	/* scroll wheel timer scan time */
+short	swwait	= SWWAIT;	/* scroll wheel wait count */
+
+short	tkback  = TKBACK;	/* trackball FIFO look back count */
+short	tkrmin  = TKRMIN;	/* trackball rate threshold */
+short	tkthr   = TKTHR;	/* trackball movement threshold */
+short	tktime  = TKTIME;	/* trackball timer scan time */
+short	tkwait	= TKWAIT;	/* trackball wait count */
+
+short	curhold = CURHOLD;	/* cursor hold time */
+short	hcwval  = HCWVAL;	/* graphics cursor X wait time */
+short	thcwval = THCWVAL;	/* text cursor H wait time */
+short	tvcwval = TVCWVAL;	/* text cursor V wait time */
+short	vcwval  = VCWVAL;	/* graphics cursor Y wait time */
+
+/* 
+
+*/
+
+short	tmultab[] = {		/* time multiplier table - indexed by voltage */
+
+	0xFFFF, 0xFAFA, 0xF627, 0xF182, 0xED09, 	/*   0 */
+	0xE8BA, 0xE492, 0xE08F, 0xDCB0, 0xD8F2, 	/*   5 */
+	0xD555, 0xD1D6, 0xCE73, 0xCB2C, 0xC800, 	/*  10 */
+	0xC4EC, 0xC1F0, 0xBF0B, 0xBC3C, 0xB981, 	/*  15 */
+	0xB6DB, 0xB448, 0xB1C7, 0xAF57, 0xACF9, 	/*  20 */
+	0xAAAA, 0xA86B, 0xA63B, 0xA41A, 0xA206, 	/*  25 */
+	0xA000, 0x9E06, 0x9C18, 0x9A37, 0x9861, 	/*  30 */
+	0x9696, 0x94D6, 0x9320, 0x9174, 0x8FD1, 	/*  35 */
+	0x8E38, 0x8CA8, 0x8B21, 0x89A2, 0x882B, 	/*  40 */
+	0x86BC, 0x8555, 0x83F5, 0x829C, 0x814A, 	/*  45 */
+	0x8000, 0x7EBB, 0x7D7D, 0x7C45, 0x7B13, 	/*  50 */
+	0x79E7, 0x78C1, 0x77A0, 0x7684, 0x756E, 	/*  55 */
+	0x745D, 0x7350, 0x7249, 0x7146, 0x7047, 	/*  60 */
+	0x6F4D, 0x6E58, 0x6D66, 0x6C79, 0x6B90, 	/*  65 */
+	0x6AAA, 0x69C8, 0x68EB, 0x6810, 0x6739, 	/*  70 */
+	0x6666, 0x6596, 0x64C9, 0x6400, 0x6339, 	/*  75 */
+	0x6276, 0x61B5, 0x60F8, 0x603D, 0x5F85, 	/*  80 */
+	0x5ED0, 0x5E1E, 0x5D6E, 0x5CC0, 0x5C16, 	/*  85 */
+	0x5B6D, 0x5AC7, 0x5A24, 0x5982, 0x58E3, 	/*  90 */
+	0x5846, 0x57AB, 0x5713, 0x567C, 0x55E7, 	/*  95 */
+	0x5555						/* 100 */
+};
+
+/* 
+
+*/
+
+short	crate0[] = {			/* cursor rate table 1 */
+
+	 0,  0,  0,  0,  0,  0,  0,  0,		/* 0..7 */
+	 0,  0,  0,  0,  1,  1,  1,  1,		/* 8..15 */
+	 1,  1,  1,  1,  1,  1,  1,  1,		/* 16..23 */
+	 1,  1,  1,  1,  1,  1,  1,  1,		/* 24..31 */
+	 1,  1,  1,  1,  1,  1,  1,  1,		/* 32..39 */
+	 1,  1,  1,  1,  1,  1,  1,  1,		/* 40..47 */
+	 1,  1,  1,  1,  1,  1,  1,  1,		/* 48..55 */
+	 1,  1,  1,  1,  1,  1,  1,  1		/* 56..63 */
+};
+
+short	crate1[] = {			/* cursor rate table 1 */
+
+	 0,  0,  0,  0,  0,  0,  0,  0,		/* 0..7 */
+	 1,  1,  1,  1,  1,  1,  1,  1,		/* 8..15 */
+	 3,  3,  3,  3,  3,  3,  3,  3,		/* 16..23 */
+	 5,  5,  5,  5,  5,  5,  5,  5,		/* 24..31 */
+	 7,  7,  7,  7,  7,  7,  7,  7,		/* 32..39 */
+	 9,  9,  9,  9,  9,  9,  9,  9,		/* 40..47 */
+	11, 11, 11, 11, 11, 11, 11, 11,		/* 48..55 */
+	13, 13, 13, 13, 13, 13, 13, 13		/* 56..63 */
+};
+
+short crate2[] = {			/* cursor rate table 2 */
+
+	  0,  0,  0,  0,  0,  0,  0,  0,	/* 0..7 */
+	  1,  1,  1,  1,  1,  1,  1,  1,	/* 8..15 */
+	  2,  2,  2,  2,  2,  2,  2,  2,	/* 16..23 */
+	  4,  4,  4,  4,  8,  8,  8,  8,	/* 24..31 */
+	 16, 16, 16, 16, 32, 32, 32, 32,	/* 32..39 */
+	 64, 64, 64, 64,128,128,128,128,	/* 40..47 */
+	 96, 96, 96, 96,256,256,256,256,	/* 48..55 */
+	256,256,256,256,256,256,256,256		/* 56..63 */
+};
+
+/* 
+
+*/
+
+short	loctab[9] = {
+
+	0,		/* 0 - left */
+
+	125 << 5,	/* 1 */
+	250 << 5,	/* 2 */
+	375 << 5,	/* 3 */
+
+	500 << 5,	/* 4 - center */
+
+	625 << 5,	/* 5 */
+	750 << 5,	/* 6 */
+	875 << 5,	/* 7 */
+
+	1000 << 5	/* 8 - right */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	valof() -- return initial value of a source
+   =============================================================================
+*/
+
+short
+valof(srcv)
+short srcv;
+{
+	switch (srcv) {
+
+	case SM_NONE:		/* -none- */
+		return(0);
+
+	case SM_RAND:		/* Random */
+		return(xgetran(0));
+
+	case SM_CTL1:		/* Ctl V1 */
+		return(SM_SCALE(sigtab[79][0]));
+
+	case SM_PTCH:		/* Pitch */
+	case SM_KPRS:		/* Key Prs */
+	case SM_KVEL:		/* Key Vel */
+		return(0);
+
+	case SM_PED1:		/* Pedal 1 */
+		return(SM_SCALE(sigtab[77][0]));
+
+	case SM_HTPW:		/* Hor Tab / Pch Whl */
+		return(0);
+
+	case SM_VTMW:		/* Vrt Tab / Mod Whl */
+		return(SM_SCALE(sigtab[54][0]));
+
+	case SM_LPBR:		/* LongPot / Breath */
+		return(SM_SCALE(sigtab[57][0]));
+
+	default:
+		return(0);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	inismtb() -- initialize source / multiplier data structures
+   =============================================================================
+*/
+
+inismtb()
+{
+	register short i, oldi;
+
+	oldi = setipl(FPU_DI);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+	for (i = 0; i < NGPSRS; i++) {
+
+		valents[i].nxt = &valents[i];
+		valents[i].prv = &valents[i];
+		valents[i].val = valof(i & 0x000F);
+	}
+
+	for (i = 0; i < 192; i++) {
+
+		vpsms[i] = &sments[i];
+
+		sments[i].prv = (struct sment *)&valents[0];
+		sments[i].nxt = valents[0].nxt;
+
+		valents[0].nxt->prv = &sments[i];
+		valents[0].nxt      = &sments[i];
+
+		sments[i].vp = i;
+		sments[i].sm = 0;
+	}
+
+	setipl(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clrpfl() -- clear pendant function list
+   =============================================================================
+*/
+
+clrpfl()
+{
+	register short i;
+
+	memsetw(&pfents[0], 0, (NPFENTS * sizeof (struct pflent))/2);
+
+	for (i = 0; i < NPFENTS-1; i++)
+		pfents[i].nextpf = &pfents[i+1];
+
+	pfqhdr = &pfents[0];
+	pflist = (struct pflent *)NULL;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	im700() -- initialize MIDAS 700
+   =============================================================================
+*/
+
+im700()
+{
+	register short i, j, k;
+	register char *ioadr;
+	register struct instdef *ip;
+
+	debugsw = DEBUGVAL;		/* initialize debug switch */
+
+	GLCinit();			/* initialize the GLC */
+	GLCcurs(G_ON);
+	GLCtext(2, 1, "MIDAS 7 -- Initialization in progress -- Please stand by");
+	GLCcurs(G_OFF);
+
+	vsndpal(blakpal);		/* setup the blackout palette */
+
+	VHinit();			/* clear the video hardware */
+	VSinit();			/* ... and the video software */
+
+	memset(keystat, 0, 24);		/* clear front panel key status */
+	memset(trgtab, 	0, NTRIGS);	/* clear trigger status table */
+	memset(mctlval, 0, NCTRLS);	/* clear MIDI controller values */
+
+	memsetw(grpmode, 0, 12);	/* set all groups to PLAY */
+	memsetw(grpstat, GS_ENBL, 12);	/* enable all groups for param. artic. */
+	memsetw(grpsel, TRUE, 12);	/* enable all groups for instr. sel. */
+	memsetw(sigtab, 0, ((sizeof sigtab) / (sizeof sigtab[0][0])));
+
+	memsetw(veltab, SM_SCALE(64), NTRIGS);	/* clear velocity table */
+	memsetw(lastvel, SM_SCALE(64), 12);	/* clear last velocity table */
+	memsetw(prstab, 0, NTRIGS);	/* clear pressure table */
+
+	curintp = tofpu(100);		/* set default interpolate time */
+
+	angroup = -1;			/* analog values:  group 1, not shown */
+	ancmsw  = FALSE;		/* analog variable mode from grpmode */
+	velflag = FALSE;		/* velocity not displayed */
+
+	dubsw   = TRUE;			/* set overdub mode */
+
+	sd = D_FWD;			/* set display direction */
+	se = D_FWD;			/* set execution direction */
+
+	swinit();			/* reset the scroll wheel variables */
+
+	inismtb();			/* clear the S/M data structures */
+	clrnl();			/* clear note entry lists */
+	clrpfl();			/* clear pendant function list */
+
+	lstbgnc = 0;			/* reset last note begin count */
+	lstendc = 0;			/* reset last note end count */
+	lstflag = TRUE;			/* set end of note entry list flag */
+
+	memsetw(lstbgns, 0, (NLSTENTS << 1));	/* clear note begin list */
+	memsetw(lstends, 0, (NLSTENTS << 1));	/* clear note end list */
+
+	/* set funcndx[] entries */
+
+	for (i = 0; i < 12; i++) {
+
+		ip = &vbufs[i];
+
+		for (j = 0; j < NFINST; j++) {
+
+			k = (i << 4) + fnoff[j];
+
+			funcndx[k][0] = &ip->idhfnc[j];
+			funcndx[k][1] = ip->idhpnt;
+		}
+	}
+
+/* 
+
+*/
+	for (i = 0; i < 3; i++) {	/* reset the state machines */
+
+		msmstv[i] = 0;		/* state = 0 */
+		mrstat[i] = 0;		/* clear running status */
+		mdbyte[i] = 0;		/* clear first byte buffer */
+		masens[i] = 0;		/* clear active sensing */
+	}
+
+	for (i = 0; i < 48; i++) {
+
+		mpbend[i] = 0;		/* clear bend values */
+		mpsust[i] = 0;		/* clear sustain values */
+	}
+
+	for (i = 0; i < 12; i++) {
+
+		for (j = 0; j < 6; j++) {
+
+			varmode[j][i] = 0;	/* set r/p mode */
+			anrs[j][i]    = 4;	/* set analog resolution */
+		}
+
+		setdyn(i, 6);		/* set group dynamics */
+		setloc(i, 4);		/* set group locations */
+		lastvce[i] = 0;		/* clear last voice assigned */
+		vce2trg[i] = -1;	/* clear voice to trigger table */
+	}
+
+	for (i = 0; i < NLTYPES; i++) {
+
+		memset(loadedc[i], ' ', 37);
+		memset(loadedf[i], ' ', 8);
+	}
+
+	memset(ldfile, ' ', 8);		/* clear the library file name field */
+	ldfile[8] = '\0';
+
+	memset(ldcmnt, ' ', 37);	/* clear the library comment field */
+	ldcmnt[37] = '\0';
+
+/* 
+
+*/
+	xkcount = 1;			/* reset cursor control variables */
+	ykcount = 1;
+	xycntr  = XYCENTRE;
+
+	clksrc  = CK_LOCAL;		/* clock source = local */
+	clkctl  = CK_LOCAL;		/* clock control = local */
+	clkrun  = FALSE;		/* clock stopped */
+	midiclk = FALSE;		/* ... */
+	pulsclk = FALSE;		/* ... */
+	stepclk = FALSE;		/* ... */
+	fc_sw   = 0;			/* stop the frame clock */
+	fc_val  = 0L;			/* ... and reset it */
+	scrlpot = 0;			/* not scrolling */
+	tmpomlt = 50;			/* initialize tempo multiplier */
+	io_leds = 0x18;			/* ... and turn off the LEDs */
+	io_leds = 0x19;			/* ... */
+	settmpo(60);			/* set default tempo */
+
+	timemlt = tmultab[50];		/* initialize time scaling */
+	io_leds = 0x1A;
+	io_leds = 0x1B;
+
+	tuneval = 0;			/* initialize fine tuning */
+	io_leds = 0x1C;
+	io_leds = 0x1D;
+
+	for (i = 0; i < 12; i++)	/* setup default values for gtctab */
+		gtctab[i] = ((i+3) << 12) | ((i+3) << 8) | ((i+3) << 4) | (i+3);
+
+	editsw  = FALSE;		/* setup edit switch state */
+	io_leds = 0x1E;
+	ioadr   = &io_ser + 2L;
+	editss  = *ioadr & 0x0008;
+
+	ac_code = N_SHARP;	/* default accidentals to display as sharps */
+
+	memsetw(articen, TRUE, 12);	/* enable articulation for all voices */
+/* 
+
+*/
+	curmove = cmvgen;
+	premove = nokey;
+	pstmove = nokey;
+	curtype = stdctp2;
+
+	x_key = nokey;		/* setup default key processors */
+	e_key = nokey;
+	m_key = stdmkey;
+	d_key = nokey;
+
+	not_fld = nokey;
+
+	cx_key  = cxkstd;	/* setup default cursor processors */
+	cy_key  = cykstd;
+	cx_upd  = cxgen;
+	cy_upd  = cygen;
+	xy_up   = nokey;
+	xy_dn   = nokey;
+
+	curslim = 349;		/* cursor limit for graphics to text switch */
+
+	chtime  = hcwval;	/* initialize default cursor wait times */
+	cvtime  = vcwval;
+	nchwait = curhold;
+	ncvwait = curhold;
+	chwait  = 1;
+	cvwait  = 1;
+
+	cratex  = crate1;	/* initialize default cursor x rate table */
+	cratey  = crate1;	/* initialize default cursor y rate table */
+
+	cmfirst = TRUE;		/* setup for first motion of cursor */
+	cmtype  = CT_GRAF;
+
+	cxval   = XCTR;		/* default cursor to center of screen */
+	cyval   = YCTR;
+
+	stcrow  = cyval / 14;	/* keep text position in sync */
+	stccol  = cxval / 8;
+
+	submenu = FALSE;	/* no submenu up to start with */
+/* 
+
+*/
+	curinst = 0;		/* current instrument = 0 */
+	curfunc = 12;		/* current function = 12 = level */
+	curvce  = 0;		/* current voice = 0 */
+
+	asmode  = FALSE;	/* deselect assignment mode */
+	gomode  = GO_NULL;	/* deselect go to mode */
+	ismode  = IS_NULL;	/* deselect instrument select mode */
+	pkctrl  = PK_PFRM;	/* select local performance key state */
+	oldpk   = pkctrl;	/* ... */
+	sliders = LS_PRMTR;	/* setup the LCD display pots and switches */
+	oldsl   = sliders;	/* ... */
+	swpt    = t_prmtr;	/* ... */
+	oldsw   = swpt;		/* ... */
+	setleds();		/* set performance keyboard leds */
+
+	initpt();		/* initialize the patch table */
+	initsq();		/* initialize the sequence table */
+	initil();		/* initialize the instrument library */
+	iniwslb();		/* initialize the waveshape library */
+	inital();		/* initialize the assignment library */
+	inittl();		/* initialize the tuning table library */
+	scinit();		/* initialize the score */
+
+	clearer(1, 0);		/* reset the fpu to its nominal values */
+	getasg(curasg = 0);	/* setup default assignments */
+
+	lcdlbls();		/* put up the LCD display */
+	lampsw = FALSE;		/* enable LCD timeout */
+}
Index: ram/infield.c
===================================================================
--- ram/infield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/infield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,46 @@
+/*
+   =============================================================================
+	infield.c -- field input functions
+	Version 6 -- 1988-10-20 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "fields.h"
+#include "stddefs.h"
+
+extern	short	stcrow, stccol;
+
+/*
+   =============================================================================
+	infield() -- Determines whether or not a given position is in a field.
+	Returns TRUE if in a field, FALSE if not.  If in a field, sets 'infetp'
+	to point at the fet entry.  If not in a field, sets 'infetp' to NULL.
+   =============================================================================
+*/
+
+short
+infield(row, col, fetp)
+register short row, col;
+register struct fet *fetp;
+{
+	infetp = (struct fet *)NULL;	/* setup for NULL infetp return */
+
+	if ((struct fet *)NULL EQ fetp)	/* handle NULL fet pointer */
+		return(FALSE);
+
+	while (fetp->redisp) {		/* redisp EQ NULL is end of table */
+
+		if ((row EQ fetp->frow) AND	/* check the entry */
+		     (col GE fetp->flcol) AND
+		     (col LE fetp->frcol)) {
+
+			infetp = fetp;		/* set new fet pointer */
+			return(TRUE);		/* return 'found' */
+		}
+
+		++fetp;				/* advance field pointer */
+	}
+
+	return(FALSE);				/* return 'not found' */
+}
+
Index: ram/initi.c
===================================================================
--- ram/initi.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/initi.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,604 @@
+/*
+   =============================================================================
+	initi.c -- MIDAS-VII - instrument editor support functions
+	Version 2 -- 1989-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGPS		0		/* define non-zero to debug pntsel() */
+
+#include "stddefs.h"
+#include "fpu.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	int		setipl();
+
+extern	unsigned	tofpu(), fromfpu();
+
+extern	short	s_inst[], vce2trg[], vce2grp[];
+
+extern	short	curfunc;	/* current function number */
+extern	short	curinst;	/* current instrument number */
+extern	short	curpnt;		/* current point number (absolute) */
+extern	short	curvce;		/* current voice number */
+extern	short	cxval;		/* graphics cursor x value */
+extern	short	editsw;		/* edit mode switch */
+extern	short	initcfg;	/* initialization cfg value */
+extern	short	npts;		/* number of points in function */
+extern	short	pecase;		/* point edit case variable */
+extern	short	pntsv;		/* point selection state variable */
+extern	short	subj;		/* edited point number (relative) */
+extern	short	temax;		/* time upper limit */
+extern	short	temin;		/* time lower limit */
+
+extern	char	*funcndx[256][2];	/* function header pointers */
+
+extern	short	idbox[][8];		/* display box parameters */
+extern	short	instmod[12];		/* intrument data modified */
+
+extern	short	fnoff[];		/* instrument fn to FPU fn table */
+
+extern	struct	instpnt	*pntptr;	/* pointer to edited point */
+
+extern	struct	instdef	idefs[NINST];	/* current instrument definitions */
+extern	struct	instdef	vbufs[12];	/* voice instrument buffers */
+
+/* 
+
+*/
+
+#include "dfltins.h"		/* short dfltins[]; default instrument */
+#include "ptoftab.h"		/* short ptoftab[]; pitch to frequency table */
+
+short finival[NFINST] = {	/* initial function values */
+
+	FPUVAL(500),	/*  0: Freq 1 */
+	FPUVAL(500),	/*  1: Freq 2 */
+	FPUVAL(500),	/*  2: Freq 3 */
+	FPUVAL(500),	/*  3: Freq 4 */
+	FPUVAL(500),	/*  4: Filter / Resonance */
+	FPUVAL(500),	/*  5: Location */
+
+	FPUVAL(0),	/*  6: Index 1 */
+	FPUVAL(0),	/*  7: Index 2 */
+	FPUVAL(0),	/*  8: Index 3 */
+	FPUVAL(0),	/*  9: Index 4 */
+	FPUVAL(0),	/* 10: Index 5 */
+	FPUVAL(0),	/* 11: Index 6 */
+
+	FPUVAL(0)	/* 12: Level */
+};
+
+short	expbit[16] = {	/* FPU time exponent bit expansion table */
+
+	0x0001,		/* 0 */
+	0x0002,		/* 1 */
+	0x0004,		/* 2 */
+	0x0008,		/* 3 */
+	0x0010,		/* 4 */
+	0x0020,		/* 5 */
+	0x0040,		/* 6 */
+	0x0080,		/* 7 */
+	0x0100,		/* 8 */
+	0x0200,		/* 9 */
+	0x0400,		/* 10 */
+	0x0800,		/* 11 */
+	0x1000,		/* 12 */
+	0x2000,		/* 13 */
+	0x4000,		/* 14 */
+	0x8000		/* 15 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	segtime() -- determine time to a point using a new segment time
+   =============================================================================
+*/
+
+short
+segtime(pn, ptime)
+short pn;
+unsigned ptime;
+{
+	register struct instpnt *pp;
+	register short i;
+	register unsigned tacc;
+
+	pp = &vbufs[curvce].idhpnt[vbufs[curvce].idhfnc[curfunc].idfpt1];
+	tacc = 0;
+
+	for (i = 0; i < pn; i++)
+		tacc += fromfpu(pp++->iptim);
+
+	tacc += fromfpu(ptime);
+
+	return(tacc);
+}
+
+/*
+   =============================================================================
+	setseg() -- set the time to a segment
+   =============================================================================
+*/
+
+setseg(pn, ptime)
+short pn;
+unsigned ptime;
+{
+	register short i;
+	register unsigned tacc;
+	register struct instpnt *pp;
+
+	pp = &vbufs[curvce].idhpnt[vbufs[curvce].idhfnc[curfunc].idfpt1];
+	tacc = 0;
+
+	for (i = 0; i < pn; i++)
+		tacc += fromfpu(pp++->iptim);
+
+	pp->iptim = tofpu(ptime - tacc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	timeto() -- find the time at a point in a function
+   =============================================================================
+*/
+
+short
+timeto(fn, pj)
+short fn, pj;
+{
+	register struct instdef *ip;
+	register struct instpnt *pt;
+	register short tf, pm, pn;
+
+	ip = &vbufs[curvce];
+	pn = ip->idhfnc[fn].idfpt1;
+	pt = &ip->idhpnt[pn];
+	pm = pn + pj;
+	tf = 0;
+
+	while (pn LE pm) {
+
+		tf += fromfpu(pt->iptim);
+		++pt;
+		++pn;
+	}
+
+	return(tf);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pntsel() -- setup editing limits for subj in the current function
+   =============================================================================
+*/
+
+pntsel()
+{
+	register struct idfnhdr *fp;
+
+	fp = &vbufs[curvce].idhfnc[curfunc];
+
+	curpnt = fp->idfpt1 + subj;
+	pntptr = &vbufs[curvce].idhpnt[curpnt];
+
+	npts = fp->idfpif;
+
+	if (npts EQ 1) {	/* detemine editing case */
+
+		pecase = 0;		/* single point */
+		temin = 1;
+		temax = 32767;
+
+	} else if (subj EQ (npts - 1)) {
+
+		pecase = 1;		/* last point */
+		temin = timeto(curfunc, subj - 1);
+		temax = 32767;
+
+	} else {
+
+		pecase = 2;		/* interior point */
+		temin = timeto(curfunc, subj - 1);
+		temax = timeto(curfunc, subj + 1);
+	}
+
+#if DEBUGPS
+	printf("pntsel(): curpnt=%d, subj=%d, fp=0x%08lx, pntptr=0x%08lx\r\n",
+		curpnt, subj, fp, pntptr);
+	printf("pntsel(): npts=%d, pecase=%d, temin=%d, temax=%d\r\n",
+		npts, pecase, temin, temax);
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	vtoy() -- convert a value to a y coordinate for display
+   =============================================================================
+*/
+
+short
+vtoy(val, window)
+short val, window;
+{
+	register short yval;
+
+	if (val GT 1000)
+		val = 1000;
+
+	yval = 56 + (((1000 - val) * 14) / 100);
+
+	if (window < 12)
+		return((short)(idbox[window][1] + (((yval - 56) * 100L) / 540L)));
+	else
+		return(yval);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ttox() -- convert a time to an x coordinate for display
+   =============================================================================
+*/
+
+short
+ttox(time, window)
+unsigned time;
+short window;
+{
+	register short xval;
+
+	if (time < 128)						/* 0..127 */
+		xval = 8 + (short)(((time * 1000L) / 2309L));
+	else if (time < 256)					/* 128..255 */
+		xval = 64 + (short)((((time - 128) * 1000L) / 2309L));
+	else if (time < 512)					/* 256..511 */
+		xval = 120 + (short)((((time - 256) * 1000L) / 4636L));
+	else if (time < 1024)					/* 512..1023 */
+		xval = 176 + (short)((((time - 512) * 1000L) / 9290L));
+	else if (time < 2048)					/* 1024..2047 */
+		xval = 232 + (short)((((time - 1024) * 1000L) / 18600L));
+	else if (time < 4096)					/* 2048..4095 */
+		xval = 288 + (short)((((time - 2048) * 1000L) / 37218L));
+	else if (time < 8192)					/* 4096..8191 */
+		xval = 344 + (short)((((time - 4096) * 1000L)/ 74454L));
+	else if (time < 16384)					/* 8192..16383 */
+		xval = 400 + (short)((((time - 8192) * 1000L) / 148927L));
+	else if (time < (unsigned)32768)			/* 16384..32767 */
+		xval = 456 + (short)((((time - 16384) * 1000L) / 309113L));
+	else
+		xval = 509;
+
+	if (xval > 509)
+		xval = 509;
+
+	if (window < 12)
+		return((short)(idbox[window][0] + (((xval - 8) * 100L) / 599L)));
+	else
+		return(xval);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	selpnt() -- select a point for editing
+   =============================================================================
+*/
+
+short
+selpnt()
+{
+	register struct idfnhdr *fp;
+
+	register short  i, xv, np;
+
+	short lo_x, lo_x_pt, hi_x, hi_x_pt;
+
+	fp = &vbufs[curvce].idhfnc[curfunc];
+	np = fp->idfpif;
+	lo_x_pt = 0;
+	lo_x = ttox(timeto(curfunc, lo_x_pt), 12);
+	hi_x_pt = np - 1;
+	hi_x = ttox(timeto(curfunc, hi_x_pt), 12);
+
+	for (i = 0; i < np; i++) {
+
+		xv = ttox(timeto(curfunc, i), 12);
+
+		if (xv LE cxval)		/* largest x LE cxval */
+			if (xv GE lo_x) {
+
+				lo_x = xv;
+				lo_x_pt = i;
+			}
+
+		if (xv GE cxval)		/* smallest x GE cxval*/
+			if (xv LT hi_x) {
+
+				hi_x = xv;
+				hi_x_pt = i;
+			}
+	}
+
+	if (lo_x EQ hi_x)
+		return(lo_x_pt);
+
+	if ((cxval - lo_x) LT (hi_x - cxval))
+		return(lo_x_pt);
+	else
+		return(hi_x_pt);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setinst() -- setup for editing a new instrument
+   =============================================================================
+*/
+
+setinst()
+{
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+
+	curfunc = 12;		/* current function = 12 = level */
+	subj = 0;		/* current edited point = 0 (first point) */
+	pntsv = 0;		/* point selection state = unselected */
+	pecase = 0;		/* point selection case = 0 (first point) */
+
+	ip = &vbufs[curvce];		/* instrument definition pointer */
+	fp = &ip->idhfnc[curfunc];	/* function pointer */
+
+	curpnt = subj + fp->idfpt1;	/* current point in function */
+	pntptr = &ip->idhpnt[curpnt];	/* current point pointer */
+
+	newws();			/* setup waveshape variables */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	newinst() -- select a new instrument
+   =============================================================================
+*/
+
+newinst(inst)
+short inst;
+{
+	curinst = inst;
+	s_inst[curvce] = inst;
+	setinst();
+}
+
+/*
+   =============================================================================
+	newvce() -- select a new voice
+   =============================================================================
+*/
+
+newvce(voice)
+short voice;
+{
+	curvce = voice;
+	curinst = s_inst[curvce];
+	setinst();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setivce() -- set instrument definition for a voice
+   =============================================================================
+*/
+
+setivce(voice)
+short voice;
+{
+	register short i, j, k, oldi;
+	register struct instdef *ip;
+
+	ip = &vbufs[voice];
+
+	oldi = setipl(FPU_DI);			/* disable FPU interrupts */
+
+/* +++++++++++++++++++++++ FPU interrupts disabled ++++++++++++++++++++++++++ */
+
+	for (j = 0; j < NFINST; j++) {		/* set funcndx[] entries */
+
+		k = (voice << 4) + fnoff[j];
+		funcndx[k][0] = &ip->idhfnc[j];
+		funcndx[k][1] = ip->idhpnt;
+	}
+
+	/* set waveshapes */
+
+	memcpyw((io_fpu + FPU_OWST + (voice << 9) + 0x0100 + 1),
+		ip->idhwvaf, NUMWPNT);
+
+	memcpyw((io_fpu + FPU_OWST + (voice << 9) + 1),
+		ip->idhwvbf, NUMWPNT);
+
+	setipl(oldi);				/* restore interrupts */
+
+/* ++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++++ */
+
+	instmod[voice] = FALSE;	/* instrument matches library */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	modinst() -- handle instrument modifications
+   =============================================================================
+*/
+
+modinst()
+{
+	short	f, i, grp, oldi;
+
+	if (NOT instmod[curvce]) {
+
+		instmod[curvce] = TRUE;
+		dswin(19);
+	}
+
+	if (NOT editsw) {
+
+		if ((grp = vce2grp[curvce]) > 0) {
+
+			oldi = setipl(FPU_DI);		/* +++++ disable FPU interrupts */
+
+			for (i = 0; i < 12; i++) {
+
+				if (vce2grp[i] EQ grp) {
+
+					memcpyw(&vbufs[i], &vbufs[curvce],
+						sizeof (struct instdef) / 2);
+
+					for (f = 0; f < 12; f++)
+						vbufs[i].idhfnc[f].idftmd
+							&= ~I_ACTIVE;
+
+					s_inst[i] = curinst;
+					clrvce(i);
+					setivce(i);
+					dosync(i);
+					execkey(0, 0, i, 1);
+					vce2trg[i] = -1;
+				}
+			}
+
+			setipl(oldi);		/* +++++ enable FPU interrupts */
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	initi() -- initialize an instrument definition
+   =============================================================================
+*/
+
+initi(ip)
+register struct instdef *ip;
+{
+	register short i, mintfpu, rb;
+
+	memsetw(ip, 0, sizeof (struct instdef) / 2);
+
+	memcpy(ip->idhname, "                ", MAXIDLN+1);
+	memcpy(ip->idhcom1, "                ", MAXIDLN+1);
+	memcpy(ip->idhcom2, "                ", MAXIDLN+1);
+	memcpy(ip->idhcom3, "                ", MAXIDLN+1);
+
+	ip->idhplft = NIPNTS - NFINST;
+	ip->idhcfg = (initcfg >> 8) & 0x00FF;
+	mintfpu = tofpu(1);
+
+	for (i = 0; i < NFINST; i++) {		/* for each function ... */
+
+		/* initialize the function header */
+
+		rb = ((i < 4) AND (i NE 0)) ? 0 : I_NRATIO;
+		ip->idhfnc[i].idfpif = 1;
+		ip->idhfnc[i].idfpt1 = i;
+		ip->idhfnc[i].idftmd = (I_TM_KEY | 0x0010) | rb;
+
+		/* initialize the first point in the function */
+
+		ip->idhpnt[i].iptim = mintfpu;
+		ip->idhpnt[i].ipval = finival[i];
+	}
+
+	for (i = 0; i < NUMWPNT; i++) {
+
+		ip->idhwvaf[i] = (ip->idhwvao[i] = 0x8000 ^ ((i + 1) << 8));
+		ip->idhwvbf[i] = (ip->idhwvbo[i] = 0x8000 ^ ((i + 1) << 8));
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	initil() -- initialize instrument library
+   =============================================================================
+*/
+
+initil()
+{
+	register short i;
+
+	setipl(FPU_DI);			/* disable FPU interrupts */
+
+/* +++++++++++++++++++++++ FPU interrupts disabled ++++++++++++++++++++++++++ */
+
+	fpuclr();			/* clear the FPU */
+
+	memcpyw(&idefs[0], dfltins, sizeof (struct instdef) / 2);
+
+	for (i = 1; i < NINST; i++)	/* initialize each instrument */
+		initi(&idefs[i]);
+
+	memset(funcndx, 0, sizeof funcndx);
+
+	for (i = 0; i < 12; i++) {	/* initialize voices */
+
+		memcpyw(&vbufs[i], &idefs[0], sizeof (struct instdef) / 2);
+		setivce(i);
+	}
+
+	setipl(FPU_EI);		/* enable FPU interrupts */
+
+/* ++++++++++++++++++++++++++ Interrupts enabled ++++++++++++++++++++++++++++ */
+
+	newvce(0);		/* setup editing for instrument 0, voice 0 */
+	newinst(0);
+}
+
Index: ram/instdsp.c
===================================================================
--- ram/instdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/instdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1127 @@
+/*
+   =============================================================================
+	instdsp.c -- instrument definition display driver and support functions
+	Version 181 -- 1988-10-06 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	D_EXECKI	0		/* debug execins() */
+
+#include "stddefs.h"
+#include "memory.h"
+
+#include "biosdefs.h"
+#include "charset.h"
+#include "fields.h"
+#include "fpu.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "graphdef.h"
+#include "smdefs.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#define	LSPCH		2		/* pitch source scale factor */
+#define	MAXRAND		(0x00FFFFFFL)	/* largest random number */
+
+/* things defined elsewhere */
+
+extern	int	(*point)(), fpuint(), setipl();
+extern	int	cnvc2p();
+
+extern	unsigned	tofpu(), fromfpu(), exp_c();
+
+extern	char	*dsimlt();
+
+extern	long	rand24();
+
+/* 
+
+*/
+
+extern	short	cxval, cyval, stcrow, stccol, initcfg;
+extern	short	curslim, idimsw;
+
+extern	unsigned	*obj0, *obj2;
+
+extern	char	bfs[], *srctbl[], sfdsp[];
+extern	char	vtlin1[], vtlin2[], vtlin3[];
+
+extern	struct	sment	sments[];
+extern	struct	valent	valents[];
+extern	struct	sment	*vpsms[];
+
+extern	short	s_inst[], vce2trg[], vce2grp[];
+
+extern	short	curfunc;	/* current function number */
+extern	short	curinst;	/* current instrument number */
+extern	short	curpnt;		/* current point number (absolute) */
+extern	short	curvce;		/* current voice number */
+extern	short	idcfsw;		/* copy / fetch menu switch */
+extern	short	idintmp;	/* temporary for instrument number */
+extern	short	idnamsw;	/* typewriter switch */
+extern	short	idsrcsw;	/* source menu switch */
+extern	short	npts;		/* number of points in function */
+extern	short	pecase;		/* point edit case variable */
+extern	short	pntsv;		/* point selection state variable */
+extern	short	subj;		/* edited point number (relative) */
+extern	short	submenu;	/* submenu cursor switch */
+extern	short	temax;		/* time upper limit */
+extern	short	temin;		/* time lower limit */
+extern	short	vlbtype;	/* type of message window display */
+extern	short	wcflag;		/* ws/cf menu type */
+extern	short	wcpage;		/* ws/cf menu page */
+
+extern	short	instmod[12];	/* intrument data modified */
+
+extern	unsigned *instob;	/* instrument object pointer */
+
+extern	struct	octent *idoct;		/* instrument display octent pointer */
+extern	struct	instpnt	*pntptr;	/* pointer to edited point */
+
+extern	struct	instdef	idefs[NINST];	/* current instrument definitions */
+extern	struct	instdef	vbufs[12];	/* voice instrument buffers */
+
+extern	char	*funcndx[256][2];	/* function header pointers */
+extern	char	*vlbptr[3];		/* variable label pointers */
+
+extern	char	idbuf[65];		/* display conversion work area */
+
+/* 
+
+*/
+
+/* forward references */
+
+short	idpoint();
+
+short	idbox[][8] = {	/* display box parameters */
+
+	{  1,   1,  84,  26, CFBX00, CBBX00,  0,  1},	/*  0: Freq 1 */
+	{ 86,   1, 169,  26, CFBX01, CBBX01,  0, 11},	/*  1: Freq 2 */
+	{171,   1, 254,  26, CFBX02, CBBX02,  0, 22},	/*  2: Freq 3 */
+	{256,   1, 339,  26, CFBX03, CBBX03,  0, 33},	/*  3: Freq 4 */
+	{341,   1, 424,  26, CFBX04, CBBX04,  0, 44},	/*  4: Filter / Resonance */
+	{426,   1, 509,  26, CFBX05, CBBX05,  0, 54},	/*  5: Location */
+
+	{  1,  29,  84,  54, CFBX06, CBBX06,  2,  1},	/*  6: Index 1 */
+	{ 86,  29, 169,  54, CFBX07, CBBX07,  2, 11},	/*  7: Index 2 */
+	{171,  29, 254,  54, CFBX08, CBBX08,  2, 22},	/*  8: Index 3 */
+	{256,  29, 339,  54, CFBX09, CBBX09,  2, 33},	/*  9: Index 4 */
+	{341,  29, 424,  54, CFBX10, CBBX10,  2, 44},	/* 10: Index 5 */
+	{426,  29, 509,  54, CFBX11, CBBX11,  2, 54},	/* 11: Index 6 */
+
+	{  1,  56, 509, 208, CFBX12, CBBX12,  4, 54},	/* 12: Level */
+
+	{  1, 210, 110, 236, CFBX13, CBBX13, 15,  1},	/* 13: Source- Mlt */
+	{112, 210, 142, 236, CFBX14, CBBX14, 15, 15},	/* 14: Pt */
+	{144, 210, 206, 236, CFBX15, CBBX15, 15, 19},	/* 15: Time */
+	{208, 210, 366, 236, CFBX16, CBBX16, 15, 27},	/* 16: Value */
+	{368, 210, 509, 236, CFBX17, CBBX17, 15, 47},	/* 17: Action */
+
+	{  1, 238, 131, 348, CFBX18, CBBX18, 17,  2},	/* 18: Configuration */
+	{133, 238, 267, 251, CFBX19, CBBX19, 17, 17},	/* 19: Voice & Inst */
+	{269, 238, 379, 306, CFBX20, CBBX20, 17, 35},	/* 20: Oscillators */
+	{381, 238, 509, 348, CFBX21, CBBX21, 17, 48},	/* 21: Waveshape */
+
+	{133, 308, 379, 348, CFBX22, CBBX22, 22, 17},	/* 22: (messages) */
+
+	{133, 252, 267, 306, CFBX23, CBBX23, 18, 17}	/* 23: Name & comments */
+};
+
+/* 
+
+*/
+
+/* instrument function to FPU function table */
+
+short	fnoff[NFINST] = {
+
+	1,	/*  0: Freq 1 */
+	3,	/*  1: Freq 2 */
+	5,	/*  2: Freq 3 */
+	7,	/*  3: Freq 4 */
+	10,	/*  4: Filter / Resonance */
+	4,	/*  5: Location */
+	9,	/*  6: Index 1 */
+	11,	/*  7: Index 2 */
+	12,	/*  8: Index 3 */
+	13,	/*  9: Index 4 */
+	14,	/* 10: Index 5 */
+	15,	/* 11: Index 6 */
+	2	/* 12: Level */
+};
+
+short	inspal[16][3] = {	/* instrument display color palette */
+
+	{0, 0, 0},	/*  0 */
+	{3, 3, 3},	/*  1 */
+	{2, 2, 2},	/*  2 */
+	{3, 0, 0},	/*  3 */
+	{0, 3, 2},	/*  4 */
+	{0, 0, 1},	/*  5 */
+	{0, 1, 1},	/*  6 */
+	{1, 0, 1},	/*  7 */
+	{3, 2, 0},	/*  8 */
+	{1, 1, 2},	/*  9 */
+	{2, 3, 0},	/* 10 */
+	{2, 3, 3},	/* 11 */
+	{3, 0, 2},	/* 12 */
+	{0, 2, 3},	/* 13 */
+	{0, 3, 0},	/* 14 */
+	{3, 3, 0}	/* 15 */
+};
+
+/* 
+
+*/
+
+char	*idbxlbl[] = {	/* display box labels */
+
+	"    Frq 1",		/*  0 */
+	"    Frq 2",		/*  1 */
+	"    Frq 3",		/*  2 */
+	"    Frq 4",		/*  3 */
+	"    Filtr",		/*  4 */
+	"    Loctn",		/*  5 */
+	"    Ind 1",		/*  6 */
+	"    Ind 2",		/*  7 */
+	"    Ind 3",		/*  8 */
+	"    Ind 4",		/*  9 */
+	"    Ind 5",		/* 10 */
+	"    Ind 6",		/* 11 */
+	"    Level",		/* 12 */
+	"Source  Mult",		/* 13 */
+	"Pt",			/* 14 */
+	"Time  ",		/* 15 */
+	"Value Source  Mult",	/* 16 */
+	"Conditioned Acts",	/* 17 */
+	"  Config  #",		/* 18 */
+	"Voice    Inst",	/* 19 */
+	"Oscillators",		/* 20 */
+	"Wavshpe",		/* 21 */
+	"",			/* 22 */
+	""			/* 23 */
+};
+
+char idhlbl[] =		/* main function time axis label */
+	"       \324\302     \325\305     \326      \301      \302      \304      \310     \321\306    \323\302";
+
+
+char	*osclbl[] = {	/* oscillator mode labels */
+			/* NOTE: must match values in instdsp.h */
+
+	"Int",		/* 0:  OC_INT - Interval */
+	"Rat",		/* 1:  OC_RAT - Ratio */
+	"Frq",		/* 2:  OC_FRQ - Frequency */
+	"Pch"		/* 3:  OC_PCH - Pitch */
+};
+
+/* 
+
+*/
+
+long	rngdiv[] = {	/* divisors for ranges of 0..9 */
+
+	MAXRAND,		/* 0..0 */
+	MAXRAND / 2,		/* 0..1 */
+	MAXRAND / 3,		/* 0..2 */
+	MAXRAND / 4,		/* 0..3 */
+	MAXRAND / 5,		/* 0..4 */
+	MAXRAND / 6,		/* 0..5 */
+	MAXRAND / 7,		/* 0..6 */
+	MAXRAND / 8, 		/* 0..7 */
+	MAXRAND / 9,		/* 0..8 */
+	MAXRAND / 10		/* 0..9 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	drawpt() -- draw a point as a cross
+   =============================================================================
+*/
+
+drawpt(px, py, pc)
+short px, py, pc;
+{
+	register short tmp;
+
+	tmp = px - 1;
+
+	if (tmp > 7)
+		idpoint(tmp, py, pc);
+
+	tmp = px + 1;
+
+	if (tmp < 509)
+		idpoint(tmp, py, pc);
+
+	tmp = py - 1;
+
+	if (tmp > 55)
+		idpoint(px, tmp, pc);
+
+	tmp = py + 1;
+
+	if (tmp < 196)
+		idpoint(px, tmp, pc);
+
+	idpoint(px, py, pc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	drawfn() -- draw a function
+   =============================================================================
+*/
+
+drawfn(fn, how, pen, wn)
+short fn, how, pen, wn;
+{
+	struct idfnhdr *fp;
+	struct instdef *ip;
+	register struct instpnt *pt1, *pt2;
+	register short i, npt1, npt2, xp;
+	register unsigned color;
+	short np, ptx, pty, ptc;
+
+	ip = &vbufs[curvce];
+	fp = &ip->idhfnc[fn];
+	point = idpoint;
+
+	np = fp->idfpif;	/* number of points in the function */
+	xp = subj;		/* edit point */
+
+	npt1 = 0;		/* left endpoint of line */
+	npt2 = 1;		/* right endpoint of line */
+
+	pt1 = &ip->idhpnt[fp->idfpt1];		/* left endpoint of line */
+	pt2 = pt1 + 1;				/* right endpoint of line */
+
+	color = exp_c(pen);	/* replicate 4 bit 'pen' for 16 bit 'color' */
+
+/* 
+
+*/
+	ptx = ttox(timeto(fn, npt1), wn);
+	pty = vtoy((pt1->ipval >> 5), wn);
+
+	ptc = how ? ID_SELD :
+		((pt1->ipact OR pt1->ipvsrc) ?
+			ID_ACTP : ID_CPNT);
+
+	if (np EQ 1) {		/* single point ? */
+
+		if (wn EQ 12)
+			drawpt(ptx, pty, ptc);
+		else
+			idpoint(ptx, pty, ptc);
+		
+		return;
+	}
+
+	if (how AND (xp EQ 0))
+		if (wn EQ 12)
+			drawpt(ptx, pty, ID_SELD);
+		else
+			idpoint(ptx, pty, ID_SELD);
+
+	for (i = 1; i < np; i++) {
+
+		ptx = ttox(timeto(fn, npt2), wn);
+		pty = vtoy((pt2->ipval >> 5), wn);
+
+		ptc = (pt2->ipact OR pt2->ipvsrc) ?
+			ID_ACTP : ID_CPNT;
+
+		if (how AND (xp EQ (i - 1))) {
+
+
+			if (wn EQ 12)
+				drawpt(ptx, pty, ptc);
+			else
+				idpoint(ptx, pty, ptc);
+
+		} else if (how AND (xp EQ i)) {
+
+			ptc = ID_SELD;
+
+			if (wn EQ 12)
+				drawpt(ptx, pty, ptc);
+			else
+				idpoint(ptx, pty, ptc);
+/* 
+
+*/
+		} else {
+
+			lseg(ttox(timeto(fn, npt1), wn),
+				vtoy((pt1->ipval >> 5), wn),
+				ptx, pty, color);
+
+			if (wn EQ 12) {
+
+				drawpt(ttox(timeto(fn, npt1), wn),
+					vtoy((pt1->ipval >> 5), wn),
+					(pt1->ipact OR pt1->ipvsrc) ?
+					 ID_ACTP : ID_CPNT);
+
+				drawpt(ptx, pty, ptc);
+
+			} else {
+
+				idpoint(ttox(timeto(fn, npt1), wn),
+					vtoy((pt1->ipval >> 5), wn),
+					(pt1->ipact OR pt1->ipvsrc) ?
+					 ID_ACTP : ID_CPNT);
+
+				idpoint(ptx, pty, ptc);
+			}
+		}
+
+		npt1++;
+		npt2++;
+		pt1++;
+		pt2++;
+	}
+
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	addpch() -- add an offset to a pitch function value
+   =============================================================================
+*/
+
+short
+addpch(p1, p2)
+short p1, p2;
+{
+	register long pl;
+
+	pl = ((((long)p1 >> 5) - 500L) << LSPCH) + (long)p2;
+
+	if (pl > PITCHMAX)
+		pl = PITCHMAX;
+
+	return((short)pl);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	irand() -- develop a random number in a given range
+   =============================================================================
+*/
+
+short
+irand(range)
+short range;
+{
+	if (range LE 0)		/* limit things to 'reasonable' values */
+		return(0);
+
+	if (range > 9)		/* limit things to 'reasonable' values */
+		range = 9;
+
+	return((short)(rand24() / rngdiv[range]));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	xgetran() -- develop a random number
+   =============================================================================
+*/
+
+short
+xgetran(mlt)
+short mlt;
+{
+	register short sltmp;
+
+	sltmp = (short)rand24();
+
+	if (mlt < 0)
+		sltmp += (short)rand24();
+
+	return(sltmp);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dosync() -- update sync and configuration register
+   =============================================================================
+*/
+
+dosync(vce)
+short vce;
+{
+	register short sync;
+	register struct instdef *ip;
+
+	ip = &vbufs[vce];
+	sync = ip->idhcfg << 8;
+
+	if (ip->idhos1c & OC_SYN)
+		sync |= 0x2000;
+
+	if (ip->idhos2c & OC_SYN)
+		sync |= 0x4000;
+
+	if (ip->idhos3c & OC_SYN)
+		sync |= 0x8000;
+
+	*(io_fpu + vce + (long)FPU_OCFG) = sync;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	oscdsp() -- display an oscillator frequency specification
+   =============================================================================
+*/
+
+oscdsp(row, val, n, lbl, frq)
+short row, val, n, frq;
+char *lbl;
+{
+		register short fh, fl;
+
+		tsplot4(instob, 64, idbox[n][4], row, 34, lbl, 14);
+		tsplot4(instob, 64, idbox[n][4], row, 36, osclbl[val & 3], 14);
+
+		switch (val & 3) {
+
+		case OC_INT:	/* interval */
+
+			sprintf(idbuf, "%c%04d", (frq < 0 ? '-' : '+'),
+				((frq < 0 ? -frq : frq) >> 1));
+
+			break;
+
+		case OC_RAT:	/* ratio */
+
+			int2rat(frq >> 1);
+
+			ebflag = FALSE;
+
+			idbuf[0] = ebuf[0];
+			idbuf[1] = ebuf[1];
+			idbuf[2] = ebuf[2];
+			idbuf[3] = '\0';
+
+			break;
+
+		case OC_FRQ:	/* frequency */
+
+			fh = (frq >> 1) / 10;
+			fl = (frq >> 1) - (fh * 10);
+
+			sprintf(idbuf, "%02d.%d ", fh, fl);
+			break;
+/* 
+
+*/
+		case OC_PCH:
+
+			cnvc2p(idbuf, (frq >> 1));
+			idbuf[0] += '0';
+			idbuf[1] += 'A';
+			idbuf[2] = sfdsp[idbuf[2]];
+			idbuf[3] += '0';
+			idbuf[4] += '0';
+			idbuf[5] = '\0';
+			break;
+		}
+
+		tsplot4(instob, 64, idbox[n][4], row, 40, idbuf, 14);
+
+		if (row NE 21)
+			tsplot4(instob, 64, idbox[n][4], row, 46,
+				((val & OC_SYN) ? "S" : "s"), 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pltws() -- plot a small waveshape display
+   =============================================================================
+*/
+
+pltws(ws, pen)
+register unsigned ws[];
+register short pen;
+{
+	register short i, x, y;
+
+	for (i = 1; i < 254; i++) {
+
+		x = 382 + (i >> 1);
+		y = 348 - ((ws[i] ^ 0x8000) / 676);
+
+		idpoint(x, y, pen);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dswin() -- display a window
+   =============================================================================
+*/
+
+dswin(n)
+register short n;
+{
+	short th, tl, vh, vl, vv, mltval, lboff;
+	char *s1, mltstr[6], mltsgn;
+	long tt, sc;
+	register short cx, pnt, par;
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+	register struct instpnt *pp;
+
+	if (wcflag NE -1)
+		return;
+
+	if (idimsw AND (n NE 19) AND (n < 22))
+		return;
+
+	ip = &vbufs[curvce];
+
+	fp = &ip->idhfnc[n LE 12 ? n : curfunc];
+
+	curpnt = subj + fp->idfpt1;
+	pp = &ip->idhpnt[curpnt];
+
+	cx = idbox[n][5];
+	cx |= cx << 4;
+	cx |= cx << 8;
+
+/* 
+
+*/
+
+	/* first, fill the box with the background color */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(instob, 128, idbox[n][0], idbox[n][1], idbox[n][2], idbox[n][3], cx);
+
+	if (n < 12)		/* draw the function if it's a label window */
+		drawfn(n, 0, ID_CLIN, n);
+
+	/* put in the box label */
+
+	if (n GT 12) {
+
+		tsplot4(instob, 64, idbox[n][4], idbox[n][6], idbox[n][7],
+			idbxlbl[n], 14);
+
+	} else {
+
+		tsplot4(instob, 64,
+			((ip->idhfnc[n].idftmd & I_TM_KEY) ?  idbox[n][4] : ID_INST),
+			idbox[n][6], idbox[n][7], idbxlbl[n], 14);
+	}
+
+/* 
+
+*/
+	switch (n) {	/* final text - overlays above stuff */
+
+	case 12:	/* level */
+
+		/* x labels */
+
+		tsplot4(instob, 64, TGRID, 14, 0, idhlbl, 14);
+
+		/* y labels */
+
+		tsplot4(instob, 64, TGRID, 14, 0, "\300", 14);
+		tsplot4(instob, 64, TGRID, 12, 0, "\302", 14);
+		tsplot4(instob, 64, TGRID, 10, 0, "\304", 14);
+		tsplot4(instob, 64, TGRID,  8, 0, "\306", 14);
+		tsplot4(instob, 64, TGRID,  6, 0, "\310", 14);
+		tsplot4(instob, 64, TGRID,  4, 0, "\312", 14);
+
+		lseg( 7,  56,   7, 196, LGRID);		/* draw the grid */
+		lseg( 7, 196, 509, 196, LGRID);
+
+		drawfn(12, 0, ID_CLIN, 12);		/* draw the function */
+
+		return;
+
+	case 13:	/* source - multiplier */
+
+		dsimlt(bfs, fp->idfsrc, fp->idfmlt);
+
+		tsplot4(instob, 64, idbox[n][4],
+			idbox[n][6]+1, idbox[n][7], bfs, 14);
+		return;
+
+	case 14:	/* point number */
+
+		sprintf(bfs, "%02d", subj);
+
+		tsplot4(instob, 64, idbox[n][4], idbox[n][6]+1, idbox[n][7], bfs, 14);
+
+		return;
+/* 
+
+*/
+	case 15:	/* time */
+
+		sc = 1000L;
+		tt = timeto(curfunc, subj);
+		th = tt / sc;
+		tl = tt - (th * sc);
+
+		sprintf(bfs, "%02d.%03d", th, tl);
+		tsplot4(instob, 64, idbox[n][4], idbox[n][6] + 1,
+			idbox[n][7], bfs, 14);
+
+		return;
+
+	case 16:	/* value */
+
+		vv = pp->ipval >> 5;
+		vh = vv / 100;
+		vl = vv - (vh * 100);
+
+		sprintf(bfs, "%02d.%02d ", vh, vl);
+
+		dsimlt(&bfs[6], pp->ipvsrc, pp->ipvmlt);
+
+		tsplot4(instob, 64, idbox[n][4], idbox[n][6] + 1,
+			idbox[n][7], bfs, 14);
+
+		return;
+
+/* 
+
+*/
+	case 17:	/* action */
+
+		pnt = pp->ippar1;
+		par = pp->ippar2;
+
+		switch (pp->ipact) {
+
+		case AC_NULL:
+
+			s1 = "                ";
+			break;
+
+		case AC_SUST:
+
+			sprintf(bfs, "Pause if key %c  ", SP_DNA);
+			s1 = bfs;
+			break;
+
+		case AC_ENBL:
+
+			sprintf(bfs, "Stop if key %c   ", SP_UPA);
+			s1 = bfs;
+			break;
+
+		case AC_JUMP:
+
+			sprintf(bfs, "GoTo %02d forever ", pnt);
+			s1 = bfs;
+			break;
+
+/* 
+
+*/
+		case AC_LOOP:
+
+			sprintf(bfs, "GoTo %02d %02d times", pnt, par);
+
+			if (bfs[8] EQ '9')		/* random */
+				bfs[8] = 'R';
+
+			s1 = bfs;
+			break;
+
+		case AC_KYUP:
+
+			sprintf(bfs, "GoTo %02d if key %c",
+				pnt, SP_UPA);
+			s1 = bfs;
+			break;
+
+		case AC_KYDN:
+
+			sprintf(bfs, "GoTo %02d if key %c",
+				pnt, SP_DNA);
+			s1 = bfs;
+			break;
+
+		default:
+
+			s1 = "????????????????";
+			break;
+		}
+
+		tsplot4(instob, 64, idbox[n][4], idbox[n][6] + 1,
+			idbox[n][7], s1, 14);
+
+		return;
+
+/* 
+
+*/
+
+	case 18:	/* configuration */
+
+		showcfg(ip->idhcfg);
+		return;
+
+	case 19:	/* voice & instrument */
+
+		sprintf(idbuf, "%02d", curvce + 1);
+		tsplot4(instob, 64, idbox[n][4], 17, 23, idbuf, 14);
+
+		sprintf(idbuf, "%02d", curinst);
+		tsplot4(instob, 64, (instmod[curvce] ? ID_CHGD :idbox[n][4]),
+			17, 31, idbuf, 14);
+
+		return;
+
+	case 20:	/* oscillators */
+
+		oscdsp(18, ip->idhos1c, n, "1", ip->idhos1v);
+		oscdsp(19, ip->idhos2c, n, "2", ip->idhos2v);
+		oscdsp(20, ip->idhos3c, n, "3", ip->idhos3v);
+		oscdsp(21, ip->idhos4c, n, "4", ip->idhos4v);
+
+		return;
+
+	case 21:	/* waveshapes */
+
+		sprintf(idbuf, "A%02d", ip->idhwsa + 1);
+		tsplot4(instob, 64, WSAFC, 17, 56, idbuf, 14);
+		pltws(ip->idhwvaf, WSAFC);
+
+		sprintf(idbuf, "B%02d", ip->idhwsb + 1);
+		tsplot4(instob, 64, WSBFC, 17, 60, idbuf, 14);
+		pltws(ip->idhwvbf, WSBFC);
+
+		return;
+/* 
+
+*/
+	case 22:	/* message window */
+
+		tsplot4(instob, 64, idbox[n][4], 22, 17, vlbptr[0], 14);
+		tsplot4(instob, 64, idbox[n][4], 23, 17, vlbptr[1], 14);
+		tsplot4(instob, 64, idbox[n][4], 24, 17, vlbptr[2], 14);
+
+		if (idsrcsw) {
+
+			point = idpoint;
+
+			lseg(196, 308, 196, 348, CBORD);
+			lseg(260, 308, 260, 348, CBORD);
+			lseg(324, 308, 324, 348, CBORD);
+		}
+
+		return;
+
+	case 23:	/* Name and comments */
+
+		tsplot4(instob, 64, idbox[n][4], 18, 17, ip->idhname, 14);
+		tsplot4(instob, 64, idbox[n][4], 19, 17, ip->idhcom1, 14);
+		tsplot4(instob, 64, idbox[n][4], 20, 17, ip->idhcom2, 14);
+		tsplot4(instob, 64, idbox[n][4], 21, 17, ip->idhcom3, 14);
+
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	allwins() -- display all windows
+   =============================================================================
+*/
+
+allwins()
+{
+	register short i;
+
+	for (i = 0; i < 24; i++)
+		dswin(i);
+}
+
+/*
+   =============================================================================
+	idpoint() -- plot a point for the lseg function
+   =============================================================================
+*/
+
+idpoint(x, y, pen)
+short x, y, pen;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputp(idoct, x, y, pen);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idbord() -- draw the border for the instrument display
+   =============================================================================
+*/
+
+idbord()
+{
+	point = idpoint;
+
+	lseg(  0,   0, 510,   0, CBORD);	/* outer border */
+	lseg(510,   0, 510, 349, CBORD);
+	lseg(510, 349,   0, 349, CBORD);
+	lseg(  0, 349,   0,   0, CBORD);
+
+	lseg(  0,  27, 510,  27, CBORD);	/* label widows - H lines */
+	lseg(  0,  55, 510,  55, CBORD);
+
+	lseg( 85,   1,  85,  54, CBORD);	/* label windows - V lines */
+	lseg(170,   1, 170,  54, CBORD);
+	lseg(255,   1, 255,  54, CBORD);
+	lseg(340,   1, 340,  54, CBORD);
+	lseg(425,   1, 425,  54, CBORD);
+
+	lseg(  0, 209, 510, 209, CBORD);	/* S/M, Time, Val - H lines */
+	lseg(  0, 237, 510, 237, CBORD);
+
+	lseg(111, 210, 111, 236, CBORD);	/* S/M, Time, Val - V lines */
+	lseg(143, 210, 143, 236, CBORD);
+	lseg(207, 210, 207, 236, CBORD);
+	lseg(367, 210, 367, 236, CBORD);
+
+	lseg(132, 238, 132, 349, CBORD);	/* Voice, Osc, Vars */
+	lseg(380, 238, 380, 349, CBORD);
+	lseg(132, 307, 380, 307, CBORD);
+	lseg(268, 238, 268, 306, CBORD);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idvlblc() -- clear the message window
+   =============================================================================
+*/
+
+idvlblc()
+{
+	vlbtype = 0;	/* nothing in the message window */
+
+	vlbptr[0] = vlbptr[1] = vlbptr[2] = "                              ";
+}
+
+/*
+   =============================================================================
+	idvlbld() -- put the labels in the message window
+   =============================================================================
+*/
+
+idvlbld()
+{
+	vlbtype = 1;	/* variable labels */
+
+/*                  "123456789012345678901234567890"  */
+
+	vlbptr[0] = "PchW/HT Pch/Frq Random  GPC/V1";
+	vlbptr[1] = "ModW/VT Key Vel Pedal 1       ";
+	vlbptr[2] = "Brth/LP Key Prs               ";
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	idvtyp() -- display the virtual typewriter in the message window
+   =============================================================================
+*/
+
+idvtyp()
+{
+	vlbtype = 2;	/* virtual typewriter */
+
+	vlbptr[0] = vtlin1;
+	vlbptr[1] = vtlin2;
+	vlbptr[2] = vtlin3;
+}
+
+/*
+   =============================================================================
+	idcpfch() -- display the copy / fetch menu in the message window
+   =============================================================================
+*/
+
+idcpfch()
+{
+	vlbtype = 3;	/* copy / fetch menu */
+
+/*		    "123456789012345678901234567890"	*/
+
+	vlbptr[0] = "Fetch from library     Escape ";
+	vlbptr[1] = "Copy to library               ";
+	vlbptr[2] = "                              ";
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	instdsp() -- put up the instrument display
+   =============================================================================
+*/
+
+instdsp()
+{
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+
+	instob = &v_score[0];		/* setup object pointer */
+	idoct  = &v_obtab[INSTOBJ];	/* setup object control table pointer */
+	obj0   = &v_curs0[0];		/* setup cursor object pointer */
+	obj2   = &v_tcur[0];		/* setup typewriter cursor pointer */
+
+	idnamsw = FALSE;	/* typewriter not up */
+	idsrcsw = FALSE;	/* source menu not up */
+	idcfsw  = FALSE;	/* copy / fetch menu not up */
+	idimsw  = FALSE;	/* instrument menu not up */
+	submenu = FALSE;	/* submenu cursor not enabled */
+	wcflag  = -1;		/* no menu page up */
+	wcpage	= 0;		/* initial ws/cf page */
+
+	setinst();		/* setup editing variables */
+
+	dswap();		/* initialize display */
+
+	vbank(0);		/* clear the display */
+	memsetw(instob, 0, 32767);
+	memsetw(instob+32767L, 0, 12033);
+
+	SetObj(INSTOBJ, 0, 0, instob, 512, 350, 0, 0, INSTFL, -1);
+	SetObj(0, 0, 1, obj0, 16, 16, ICURX, ICURY, OBFL_00, -1);
+	SetObj(TTCURS, 0, 1, obj2, 16, 16,     0,     0,  TTCCFL, -1);
+
+	arcurs(ID_NCUR);	/* setup arrow cursor object */
+	itcini(ID_TCUR);	/* setup text cursor object */
+	ttcini(ID_TCUR);	/* setup typewriter cursor object */
+
+	vbank(0);
+	idbord();		/* draw the border */
+	idvlblc();		/* no initial label */
+	allwins();		/* fill in the windows */
+
+	SetPri(INSTOBJ, INSTPRI);
+	SetPri(0, GCPRI);	/* display the graphic cursor */
+
+	setgc(ICURX, ICURY);
+
+	vsndpal(inspal);	/* set the palette */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	reshowi() -- redisplay the instrument
+   =============================================================================
+*/
+
+reshowi()
+{
+	idfield();		/* fix up field table, etc. */
+
+	wcflag = -1;		/* no menu page up */
+	wcpage = 0;		/* first page of waveshapes */
+
+	dswap();		/* initialize display */
+
+	vbank(0);		/* clear the display */
+	memsetw(instob, 0, 32767);
+	memsetw(instob+32767L, 0, 12033);
+
+	SetObj(INSTOBJ, 0, 0, instob, 512, 350, 0, 0, INSTFL, -1);
+	SetObj(0, 0, 1, obj0, 16, 16, ICURX, ICURY, OBFL_00, -1);
+	SetObj(TTCURS, 0, 1, obj2, 16, 16,     0,     0,  TTCCFL, -1);
+
+	arcurs(ID_NCUR);	/* setup arrow cursor object */
+	itcini(ID_TCUR);	/* setup text cursor object */
+	ttcini(ID_TCUR);	/* setup typewriter cursor object */
+
+	vbank(0);
+	idbord();		/* draw the border */
+	idvlblc();		/* no initial label */
+	allwins();		/* fill in the windows */
+
+	SetPri(INSTOBJ, INSTPRI);
+	SetPri(0, GCPRI);	/* enable the cursor */
+
+	if (cyval > curslim)
+		settc(stcrow, stccol);
+	else
+		setgc(cxval, cyval);
+
+	vsndpal(inspal);	/* set the palette */
+}
Index: ram/itcpos.c
===================================================================
--- ram/itcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/itcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,154 @@
+/*
+   =============================================================================
+	itcpos.c -- text cursor positioning for the instrument display
+	Version 12 -- 1989-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+#define	CW_0	0x0000
+#define	CW_F	0xFFFF
+
+extern	unsigned	exp_c();
+
+extern	short	stcrow, stccol;		/* text cursor row,col */
+
+extern	unsigned	*obj0;		/* cursor object pointer */
+
+/* 
+
+*/
+
+static short itcur[] = {
+
+	CW_0, CW_0, CW_0, CW_0,	/* 0 */
+	CW_0, CW_0, CW_0, CW_0,	/* 1 */
+	CW_0, CW_0, CW_0, CW_0,	/* 2 */
+	CW_0, CW_0, CW_0, CW_0,	/* 3 */
+	CW_0, CW_0, CW_0, CW_0,	/* 4 */
+	CW_0, CW_0, CW_0, CW_0,	/* 5 */
+	CW_0, CW_0, CW_0, CW_0,	/* 6 */
+	CW_0, CW_0, CW_0, CW_0,	/* 7 */
+	CW_0, CW_0, CW_0, CW_0,	/* 8 */
+	CW_0, CW_0, CW_0, CW_0,	/* 9 */
+	CW_0, CW_0, CW_0, CW_0,	/* 10 */
+	CW_0, CW_0, CW_0, CW_0,	/* 11 */
+	CW_F, CW_F, CW_0, CW_0,	/* 12 */
+	CW_0, CW_0, CW_0, CW_0,	/* 13 */
+	CW_0, CW_0, CW_0, CW_0,	/* 14 */
+	CW_0, CW_0, CW_0, CW_0	/* 15 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	itcini() -- initialize instrument text cursor
+   =============================================================================
+*/
+
+itcini(color)
+unsigned color;
+{
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);
+
+	andcopy(v_cur, itcur, exp_c(color), 64);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	itcpos() -- position the instrument text cursor at ('row', 'col')
+   =============================================================================
+*/
+
+itcpos(row, col)
+register short row, col;
+{
+	register short yrow, xcol;
+	register struct octent *op;
+
+	if (v_regs[5] & 0x0180)		/* point at the control bank */
+		vbank(0);
+
+	yrow = row * 14;		/* get cursor display position */
+	xcol = col * 8;
+
+	op = &v_obtab[TCURS];		/* point at v_obtab entry */
+	setipl(VID_DI);			/* disable Vertical Interval interrupt */
+	v_odtab[TCPRI][0] &= ~V_BLA;	/* blank the object */
+	objclr(TCPRI);			/* turn off the old location */
+
+	op->objx = xcol;		/* update v_obtab entry */
+	op->objy = yrow;
+	op->obase = &v_cur[0];
+	op->odtw1 = 0x0400 | (0x03FF & (xcol >> 1));
+
+	SetPri(TCURS, TCPRI);		/* turn on the new location */
+
+	stcrow = row;			/* update cursor position */
+	stccol = col;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	advicur() -- advance the instrument display text cursor
+   =============================================================================
+*/
+
+advicur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol + 1;
+
+	if (newcol LE cfetp->frcol)
+		itcpos(stcrow, newcol);
+}
+
+/*
+   =============================================================================
+	bspicur() -- backspace the instrument display text cursor
+   =============================================================================
+*/
+
+bspicur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol - 1;
+
+	if (newcol GE cfetp->flcol)
+		itcpos(stcrow, newcol);
+}
Index: ram/kbobj.c
===================================================================
--- ram/kbobj.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/kbobj.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,333 @@
+/*
+   =============================================================================
+	kbobj.c -- keyboard object display data
+	Version 6 -- 1988-02-02 -- D.N. Lynx Crowe
+
+	Defines the data for the Keyboard object.  Includes the "new data"
+	label.
+
+	Each group of keys is made up of groups of patterns KA..KD,
+	organized in 4 types of groups, 0..3, in 4 ways, W..Z.
+   =============================================================================
+*/
+
+#define	K_BLK	0	/* black keys */
+#define	K_WHT	1	/* white keys */
+#define	K_GRY	2	/* lines between keys */
+
+#define	LFC	((K_WHT << 12) | (K_WHT << 8) | (K_WHT << 4) | K_WHT)
+#define	LFB	((K_GRY << 12) | (K_GRY << 8) | (K_GRY << 4) | K_GRY)
+
+#define	LM(c)	((c & LFC) | ((~c) & LFB))
+
+#define	KA	((K_GRY << 12) | (K_GRY << 8) | (K_GRY << 4) | K_GRY)
+#define	KB	((K_WHT << 12) | (K_WHT << 8) | (K_WHT << 4) | K_WHT)
+#define	KC	((K_GRY << 12) | (K_WHT << 8) | (K_WHT << 4) | K_WHT)
+#define	KD	((K_BLK << 12) | (K_BLK << 8) | (K_BLK << 4) | K_BLK)
+
+int	kbobj[] = {
+
+	KA, KA, KA, KA,		/* 0 */		/* W */		/* C7 */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A7 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G6 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C6 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A6 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G5 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C5 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A5 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G4 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C4 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A4 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G3 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C3 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A3 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G2 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C2 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A2 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G1 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C1 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* X */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 1 */				/* A1 */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* G0 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* F */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 1 */		/* Y */		/* E */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 0 */				/* D */
+	KD, KD, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* C0 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+/* 
+ */
+
+	KA, KA, KA, KA,		/* 1 */		/* Z */		/* B */
+	KB, KB, KB, KC,
+	KB, KB, KB, KC,
+	KD, KD, KB, KC,
+
+	KD, KD, KA, KA,		/* 2 */				/* A0 */
+	KD, KD, KB, KC,
+	KB, KB ,KB, KC,
+	KB, KB, KB, KC,
+
+	KA, KA, KA, KA,		/* 3 */		/* Bottom border */
+	KD, KD, KD, KD,
+
+	/* New Data label */
+
+	LM(0x0000), LM(0x0000), LM(0x0000), LM(0x0000),
+	LM(0x00F0), LM(0xFF0F), LM(0x0F0F), LM(0x0F00),
+	LM(0x0FF0), LM(0x0F0F), LM(0x0F00), LM(0x0F00),
+	LM(0xF0F0), LM(0xFF0F), LM(0x0F00), LM(0x0F0F),
+	LM(0x00F0), LM(0x0F0F), LM(0xFF00), LM(0x0FF0),
+	LM(0x00F0), LM(0xFF0F), LM(0x0F0F), LM(0x0F00),
+	LM(0x0000), LM(0x0000), LM(0x0000), LM(0x0000),
+	LM(0x0000), LM(0x0000), LM(0x0000), LM(0x0000),
+	LM(0x0FF0), LM(0xFF00), LM(0xFFF0), LM(0x0FF0),
+	LM(0xF0F0), LM(0x00F0), LM(0x0F0F), LM(0xF00F),
+	LM(0xF0F0), LM(0xFFF0), LM(0x0F0F), LM(0xFFFF),
+	LM(0xF0F0), LM(0x00F0), LM(0x0F0F), LM(0xF00F),
+	LM(0x0FF0), LM(0x00F0), LM(0x0F0F), LM(0xF00F),
+	LM(0x0000), LM(0x0000), LM(0x0000), LM(0x0000)
+};
Index: ram/lcdlbls.c
===================================================================
--- ram/lcdlbls.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/lcdlbls.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,2091 @@
+/*
+   =============================================================================
+	lcdlbls.c -- MIDAS-VII front panel support functions
+	Version 48 -- 1989-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	ROMPOK		1		/* non-zero enables the ROMP switch */
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "graphdef.h"
+#include "glcfns.h"
+#include "glcdefs.h"
+#include "lcdline.h"
+#include "vsdd.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "cmeta.h"
+#include "fields.h"
+#include "fpu.h"
+#include "macros.h"
+#include "panel.h"
+#include "patch.h"
+#include "smdefs.h"
+#include "sclock.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "libdsp.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+
+#define	ARTIVAL(x)	(x << 5)
+#define	SL2GAIN(x)	(sl2gain[(x >> 11) + 16])
+
+#if	ROMPOK
+#define	ROMPFN	trapper		/* ROMP switch table entry */
+#else
+#define	ROMPFN	nokey		/* ROMP switch table entry */
+#endif
+
+#define	PCHMAX	21920L		/* maximum pitch value */
+
+/* 
+
+*/
+extern	char	gain2eq();
+
+extern	short	nokey();
+extern	short	setsr();
+
+extern	short	(*d_key)();
+extern	short	(*e_key)();
+extern	short	(*m_key)();
+extern	short	(*x_key)();
+extern	short	(*olddkey)();
+extern	short	(*oldekey)();
+extern	short	(*oldmkey)();
+extern	short	(*oldxkey)();
+extern	short	(*point)();
+
+extern	PFS	(*oldsw)[];
+extern	PFS	(*swpt)[];
+
+extern	PFS	aswtbl[14];
+
+extern	short	asig;
+extern	short	asmode;
+extern	short	astat;
+extern	short	aval;
+extern	short	clkrun;
+extern	short	ctrsw;
+extern	short	curasg;
+extern	short	gomode;
+extern	short	ismode;
+extern	short	lampio;
+extern	short	lampsw;
+extern	short	loadrow;
+extern	short	loadsw;
+extern	short	ltagged;
+extern	short	ndisp;
+extern	short	oldpk;
+extern	short	oldsl;
+extern	short	pkctrl;
+extern	short	recsw;
+extern	short	sliders;
+extern	short	tagslot;
+extern	short	tmpomlt;
+extern	short	tmpoval;
+extern	short	tuneval;
+
+extern	unsigned short	seqdupd;
+
+extern	short	BGeq[];
+extern	short	BGother[];
+extern	short	BGprmtr[];
+
+extern	short	articen[];
+extern	short	grpmode[];
+extern	short	grpsel[];
+extern	short	grpstat[];
+extern	short	ins2grp[];
+extern	short	lastart[];
+extern	short	s_trns[];
+extern	short	vce2grp[];
+extern	short	vce2trg[];
+
+extern	short	anrs[][16];
+
+extern	long	iotime;
+extern	long	lcdontm;
+extern	long	lcdtime;
+
+extern	struct	gdsel	*gdstbc[];
+
+extern	struct	valent	valents[];
+
+/* 
+
+*/
+
+/* forward references */
+
+short	l_prmtr(), l_other(), l_voice(), l_init(), l_clock(), l_eq();
+short	trapper(), setlamp(), rpctl(), quiet();
+short	l_group(), l_dflt(), l_inst(), l_goto(), l_asgn(), l_adfl(), l_load();
+
+/* initialized stuff */
+
+/* BarType -- LCD slider bar graph type table -- 0 = bottom, 1 = centered */
+
+short	BarType[14] = { 1, 0,   0, 0, 0,   1, 1, 1, 1,   0, 0, 0,   1, 0 };
+
+short	artitab[] = {		/* articulation pot initialization values */
+
+	ARTIVAL(500),	/* locn  */
+	ARTIVAL(0),	/* level */
+	ARTIVAL(0),	/* ind 1 */
+	ARTIVAL(0),	/* ind 2 */
+	ARTIVAL(0),	/* ind 3 */
+	ARTIVAL(500), 	/* frq 1 */
+	ARTIVAL(500), 	/* frq 2 */
+	ARTIVAL(500),	/* frq 3 */
+	ARTIVAL(500),	/* frq 4 */
+	ARTIVAL(0),	/* ind 4 */
+	ARTIVAL(0),	/* ind 5 */
+	ARTIVAL(0),	/* ind 6 */
+	ARTIVAL(500),	/* filtr */
+	ARTIVAL(0)	/* reson */
+};
+
+/* arpar[] -- articulation parameter map */
+/*	   sigtab[ 25  26  27  28  29  30  31  32  33  34  35  36  37  38] */ 
+
+short	arpar[] = { 4,  2,  9, 11, 12,  1,  3,  5,  7, 13, 14, 15, 10,  6};
+
+/* 
+
+*/
+
+short	sl2gain[32] = {		/* slider value to EQ gain conversion table */
+
+	-12, -12, -12, -12, -12, -11, -10, -9 ,-8 ,-7, -6, -5, -4, -3, -2, -1,
+	  0,   1,   2,   3,   4,   5,   6,  7,  8,  9, 10, 11, 12, 12, 12, 12
+};
+
+short	vmasks[16] = {		/* variable resolution masks */
+
+	0x8000, 0xC000, 0xE000, 0xF000,
+	0xF800, 0xFC00, 0xFE00, 0xFF00,
+	0xFF80, 0xFFC0, 0xFFE0, 0xFFF0,
+	0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF
+};
+
+short	src2var[14] = {		/* source number to analog variable number map */
+
+	-1, -1,  3, -1, -1, -1,  5, -1,  4, -1, -1,  0,  1,  2 };
+
+char	*potlbls[] = {		/* LCD pot labels */
+
+	/* Pot:  25    26    27    28    29    30    31    32    33    34    35    36    37    38 */
+
+	/* 0 */	"Locn  Level Ind 1 Ind 2 Ind 3 Frq 1 Frq 2 Frq 3 Frq 4 Ind 4 Ind 5 Ind 6 Filtr Reson",
+	/* 1 */	"Locn  Level Ind 1 Ind 2 Ind 3 Frq 1 Frq 2 Frq 3 Frq 4 Ind 4 Ind 5 Ind 6 Filtr Reson",
+	/* 2 */	"      Aux   Depth Rate  Inten CV 1  CV 2  CV 3  CV 4                               ",
+	/* 3 */	" 50    150   400    1k  2.5k    6k   15k   50    150   400    1k  2.5k    6k   15k ",
+	/* 4 */	"Locn  Level Ind 1 Ind 2 Ind 3 Frq 1 Frq 2 Frq 3 Frq 4 Ind 4 Ind 5 Ind 6 Filtr Reson",
+	/* 5 */	"Locn  Level Ind 1 Ind 2 Ind 3 Frq 1 Frq 2 Frq 3 Frq 4 Ind 4 Ind 5 Ind 6 Filtr Reson",
+	/* 6 */	"Locn  Level Ind 1 Ind 2 Ind 3 Frq 1 Frq 2 Frq 3 Frq 4 Ind 4 Ind 5 Ind 6 Filtr Reson",
+	/* 7 */	"Locn  Level Ind 1 Ind 2 Ind 3 Frq 1 Frq 2 Frq 3 Frq 4 Ind 4 Ind 5 Ind 6 Filtr Reson"
+};
+
+#if	ROMPOK
+char	*swtlbls[] = {		/* LCD switch labels -- ROMP ENABLED */
+
+	/* 0 */	"Quiet ROMP  Lamp  Clock  P/R  Go To Instr Asgmt Load              Other Voice Init ",
+	/* 1 */	"                                                                        Voice Init ",
+	/* 2 */	"Quiet ROMP  Lamp  Clock  P/R  Go To Instr Asgmt Load               EQ   Voice Init ",
+	/* 3 */	"Quiet ROMP  Lamp  Clock  P/R  Go To Instr Asgmt Load              Prmtr Voice Init ",
+	/* 4 */	"                                                                         +00  Deflt",
+	/* 5 */	"Quiet ROMP  Lamp  Clock  P/R  Go To Instr Asgmt Load              Other Voice Deflt",
+	/* 6 */	"Quiet ROMP  Lamp  Clock  P/R                                                       ",
+	/* 7 */	"Quiet ROMP  Lamp                                Load                               "
+};
+#else
+char	*swtlbls[] = {		/* LCD switch labels -- ROMP DISABLED */
+
+	/* 0 */	"Quiet       Lamp  Clock  P/R  Go To Instr Asgmt Load              Other Voice Init ",
+	/* 1 */	"                                                                        Voice Init ",
+	/* 2 */	"Quiet       Lamp  Clock  P/R  Go To Instr Asgmt Load               EQ   Voice Init ",
+	/* 3 */	"Quiet       Lamp  Clock  P/R  Go To Instr Asgmt Load              Prmtr Voice Init ",
+	/* 4 */	"                                                                         +00  Deflt",
+	/* 5 */	"Quiet       Lamp  Clock  P/R  Go To Instr Asgmt Load              Other Voice Deflt",
+	/* 6 */	"Quiet       Lamp  Clock  P/R                                                       ",
+	/* 7 */	"Quiet       Lamp                                Load                               "
+};
+#endif
+
+char	*aslbls[] = {		/* Assignment select key labels */
+
+	"Asgmt",	/* 0 */
+	" +00 ",	/* 1 */
+	" +20 ",	/* 2 */
+	" +40 ",	/* 3 */
+	" +60 ",	/* 4 */
+	" +80 "		/* 5 */
+};
+
+/* 
+
+*/
+
+PFS	t_prmtr[] = {	/* switch assignments for LS_PRMTR */
+
+	quiet,		/*  0: Quiet */
+	ROMPFN,		/*  1: ROMP */
+
+	setlamp,	/*  2: Lamp */
+	l_clock,	/*  3: Clock */
+	rpctl,		/*  4: R/P */
+
+	l_goto,		/*  5: Go To */
+	l_inst,		/*  6: Instr */
+	l_asgn,		/*  7: Asgmt */
+	l_load,		/*  8: Load */
+
+	nokey,		/*  9: -unused- */
+	nokey,		/* 10: -unused- */
+	l_other,	/* 11: Other */
+
+	l_prmtr,	/* 12: Prmtr */
+	l_init		/* 13: Init */
+};
+
+PFS	t_voice[] = {	/* switch assignments for LS_VOICE */
+
+	l_voice,	/*  0: toggle voice status */
+	l_voice,	/*  1: toggle voice status */
+
+	l_voice,	/*  2: toggle voice status */
+	l_voice,	/*  3: toggle voice status */
+	l_voice,	/*  4: toggle voice status */
+
+	l_voice,	/*  5: toggle voice status */
+	l_voice,	/*  6: toggle voice status */
+	l_voice,	/*  7: toggle voice status */
+	l_voice,	/*  8: toggle voice status */
+
+	l_voice,	/*  9: toggle voice status */
+	l_voice,	/* 10: toggle voice status */
+	l_voice,	/* 11: toggle voice status */
+
+	l_prmtr,	/* 12: Prmtr */
+	l_init		/* 13: Init */
+};
+
+/* 
+
+*/
+
+PFS	t_other[] = {	/* switch assignments for LS_OTHER */
+
+	quiet,		/*  0: Quiet */
+	ROMPFN,		/*  1: ROMP */
+
+	setlamp,	/*  2: Lamp */
+	l_clock,	/*  3: Clock */
+	rpctl,		/*  4: R/P */
+
+	l_goto,		/*  5: Go To */
+	l_inst,		/*  6: Instr */
+	l_asgn,		/*  7: Asgmt */
+	l_load,		/*  8: Load */
+
+	nokey,		/*  9: -unused- */
+	nokey,		/* 10: -unused- */
+	l_eq,		/* 11: EQ */
+
+	l_prmtr,	/* 12: Prmtr */
+	l_init		/* 13: Init */
+};
+
+PFS	t_eq[] = {	/* switch assignments for LS_EQ */
+
+	quiet,		/*  0: Quiet */
+	ROMPFN,		/*  1: ROMP */
+
+	setlamp,	/*  2: Lamp */
+	l_clock,	/*  3: Clock */
+	rpctl,		/*  4: R/P */
+
+	l_goto,		/*  5: Go To */
+	l_inst,		/*  6: Instr */
+	l_asgn,		/*  7: Asgmt */
+	l_load,		/*  8: Load */
+
+	nokey,		/*  9: -unused- */
+	nokey,		/* 10: -unused- */
+	l_eq,		/* 11: Prmtr */
+
+	l_prmtr,	/* 12: Voice */
+	l_init		/* 13: Init */
+};
+
+/* 
+
+*/
+
+PFS	t_inst[] = {	/* switch assignments for LS_INST */
+
+	l_group,	/*  0: toggle group status */
+	l_group,	/*  1: toggle group status */
+
+	l_group,	/*  2: toggle group status */
+	l_group,	/*  3: toggle group status */
+	l_group,	/*  4: toggle group status */
+
+	l_group,	/*  5: toggle group status */
+	l_group,	/*  6: toggle group status */
+	l_group,	/*  7: toggle group status */
+	l_group,	/*  8: toggle group status */
+
+	l_group,	/*  9: toggle group status */
+	l_group,	/* 10: toggle group status */
+	l_group,	/* 11: toggle group status */
+
+	l_inst,		/* 12: 01-20 / 21-40 */
+	l_dflt		/* 13: Deflt */
+};
+
+PFS	t_libr[] = {	/* switch assignments for LS_LIBR */
+
+	quiet,		/*  0: Quiet */
+	ROMPFN,		/*  1: ROMP */
+
+	setlamp,	/*  2: Lamp */
+	l_clock,	/*  3: Clock */
+	rpctl,		/*  4: R/P */
+
+	nokey,		/*  5: -unused- */
+	nokey,		/*  6: -unused- */
+	nokey,		/*  7: -unused- */
+	nokey,		/*  8: -unused- */
+
+	nokey,		/*  9: -unused- */
+	nokey,		/* 10: -unused- */
+	nokey,		/* 11: -unused- */
+
+	nokey,		/* 12: -unused- */
+	nokey		/* 13: -unused- */
+};
+
+/* 
+
+*/
+
+PFS	t_ngrp[] = {	/* switch assignments for LS_NGRP */
+
+	quiet,		/*  0: Quiet */
+	ROMPFN,		/*  1: ROMP */
+
+	setlamp,	/*  2: Lamp */
+	l_clock,	/*  3: Clock */
+	rpctl,		/*  4: R/P */
+
+	nokey,		/*  5: -unused- */
+	nokey,		/*  6: -unused- */
+	nokey,		/*  7: -unused- */
+	nokey,		/*  8: -unused- */
+
+	nokey,		/*  9: -unused- */
+	nokey,		/* 10: -unused- */
+	nokey,		/* 11: -unused- */
+
+	nokey,		/* 12: -unused- */
+	nokey		/* 13: -unused- */
+};
+
+PFS	t_load[] = {	/* switch assignments for LS_LOAD */
+
+	quiet,		/*  0: Quiet */
+	ROMPFN,		/*  1: ROMP */
+
+	setlamp,	/*  2: Lamp */
+	nokey,		/*  3: -unused- */
+	nokey,		/*  4: -unused- */
+
+	nokey,		/*  5: -unused- */
+	nokey,		/*  6: -unused- */
+	nokey,		/*  7: -unused- */
+	l_load,		/*  8: Load */
+
+	nokey,		/*  9: -unused- */
+	nokey,		/* 10: -unused- */
+	nokey,		/* 11: -unused- */
+
+	nokey,		/* 12: -unused- */
+	nokey		/* 13: -unused- */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	quiet() -- quiet the instrument
+   =============================================================================
+*/
+
+quiet()
+{
+	register short vce;
+
+	for (vce = 0; vce < 12; vce++)		/* for each voice ... */
+		sendval(vce, 2, 0);		/* ... set level = 0 */
+
+	memsetw(seqflag, 0, 16);		/* stop the sequences */
+	memsetw(seqtime, 0, 16);		/* ... */
+
+	memsetw(trstate, 0, 16);		/* reset the triggers */
+
+	seqdupd = 0xFFFF;			/* request display update */
+
+	stmproc(NULL_DEF);			/* trigger the blank definer */
+}
+
+/*
+   =============================================================================
+	rpctl() -- toggle record/play switch
+   =============================================================================
+*/
+
+rpctl(stat)
+short stat;
+{
+	if (NOT stat)
+		return;
+
+	recsw = NOT recsw;
+	dsrpmod();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	trapper() -- trap to ROMP
+   =============================================================================
+*/
+
+trapper(stat)
+short stat;
+{
+	if (stat)
+		xtrap15();
+}
+
+/*
+   =============================================================================
+	l_clock() -- process 'Clock' switch
+   =============================================================================
+*/
+
+l_clock(stat)
+short stat;
+{
+	if (NOT stat)
+		return;
+
+	clkset(NOT clkrun);
+	dclkmd();
+}
+
+/*
+   =============================================================================
+	ulamp() -- underline lamp if forced on
+   =============================================================================
+*/
+
+ulamp()
+{
+	if ((sliders EQ LS_VOICE) OR (sliders EQ LS_INST))
+		return;
+
+	point = GLCplot;	/* setup to draw line */
+	GLCcurs(G_ON);
+
+	if (lampsw)
+		lseg (LAMP_XL, LAMP_Y, LAMP_XR, LAMP_Y, 1);
+	else
+		lseg (LAMP_XL, LAMP_Y, LAMP_XR, LAMP_Y, 0);
+
+	GLCcurs(G_OFF);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	preio() -- turn off LCD backlight before disk I/O
+   =============================================================================
+*/
+
+preio()
+{
+	short oldipl;
+
+	oldipl = setipl(TIM_DI);
+
+	lampio  = lampsw;
+	iotime  = lcdtime;
+	lampsw  = FALSE;
+	io_leds = 0x1F;
+
+	setipl(oldipl);
+}
+
+/*
+   =============================================================================
+	postio() -- restore LCD backlight state after disk I/O
+   =============================================================================
+*/
+
+postio()
+{
+	short oldipl;
+
+	oldipl = setipl(TIM_DI);
+
+	lampsw = lampio;
+
+	if (iotime OR lampsw) {
+
+		lcdtime = lcdontm;
+		io_leds = 0x9F;
+	}
+
+	setipl(oldipl);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setlamp() -- toggle LCD backlight mode
+   =============================================================================
+*/
+
+setlamp(stat)
+{
+	register short oldi;
+
+	if (NOT stat)		/* only act on key closures */
+		return;
+
+	oldi = setipl(TIM_DI);	/* disable interrupts to keep out the timer */
+
+	lcdtime = lcdontm;	/* set the LCD backlight timer */
+
+	if (lampsw) {
+
+		lampsw = FALSE;		/* enable LCD timeouts */
+		io_leds = 0x1F;		/* turn off the LCD backlight */
+
+	} else {
+
+		lampsw = TRUE;		/* disable LCD timeouts */
+		io_leds = 0x9F;		/* turn on the LCD backlight */
+	}
+
+	setipl(oldi);		/* turn interrupts back on */
+
+	ulamp();		/* update underline on lamp key label */
+}
+
+/*
+   =============================================================================
+	lcd_on() -- turn on the LCD backlight
+   =============================================================================
+*/
+
+lcd_on()
+{
+	register short oldi;
+
+	oldi = setipl(TIM_DI);	/* disable interrupts to keep out the timer */
+
+	lcdtime = lcdontm;	/* set the LCD backlight timer */
+	io_leds = 0x9F;		/* turn on the LCD backlight */
+
+	setipl(oldi);		/* turn interrupts back on */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	loadkey() -- process data keys in load mode
+   =============================================================================
+*/
+
+loadkey(key)
+short key;
+{
+	if (NOT astat)
+		return;
+
+	if (loadsw) {				/* if it's load time */
+
+		if (key < 7) {			/* ... and the key is valid */
+
+			loadem(key + 'A');	/* ... load the files */
+
+			loadsw  = FALSE;
+			ltagged = FALSE;
+			d_key = olddkey;
+			x_key = oldxkey;
+			e_key = oldekey;
+			m_key = oldmkey;
+			pkctrl  = oldpk;
+			sliders = oldsl;
+			swpt    = oldsw;
+			lcdlbls();
+		}
+
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pcancel() -- cancel panel modes
+   =============================================================================
+*/
+
+pcancel(pm)
+short pm;
+{
+	point = GLCplot;		/* setup to plot on LCD */
+	GLCcurs(G_ON);
+
+	if ((pm NE 0) AND asmode) {
+
+		/* cancel assignment mode */
+
+		asmode = 0;	
+		pkctrl = oldpk;
+		swpt   = oldsw;
+		lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 0);
+	}
+
+	if ((pm NE 1) AND (gomode NE GO_NULL)) {
+
+		/* cancel Go To mode */
+
+		gomode = GO_NULL;
+		pkctrl = oldpk;
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+	}
+
+	if ((pm NE 2) AND (ismode NE IS_NULL)) {
+
+		/* cancel instrument select mode */
+
+		ismode  = IS_NULL;
+		pkctrl  = oldpk;
+		sliders = oldsl;
+		swpt    = oldsw;
+		lcdlbls();
+	}
+
+	GLCcurs(G_OFF);
+	setleds();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_load() -- process "Load" key
+   =============================================================================
+*/
+
+l_load(stat)
+short stat;
+{
+	if (NOT stat)
+		return;
+
+	pcancel(3);			/* cancel panel selections */
+	lcancel(3);			/* cancel librarian selections */
+
+	point = GLCplot;		/* setup to plot on LCD */
+	GLCcurs(G_ON);
+
+	if (loadsw) {		/* if load is selected, deselect */
+
+		d_key   = olddkey;
+		e_key   = oldekey;
+		m_key   = oldmkey;
+		x_key   = oldxkey;
+
+		pkctrl  = oldpk;
+		sliders = oldsl;
+		swpt    = oldsw;
+
+		loadsw  = FALSE;
+
+		lcdlbls();
+/* 
+
+*/
+	} else {		/* setup for load mode */
+
+		clkset(0);	/* stop the clock */
+
+		if (ltagged) {	/* cancel tag mode */
+
+			dslslot(tagslot, exp_c(LCFBX01), loadrow);
+			ltagged = FALSE;
+		}
+
+		if ((pkctrl EQ PK_PFRM) OR (pkctrl EQ PK_NOTE))
+			oldpk = pkctrl;
+
+		if (sliders NE LS_LOAD)
+			oldsl = sliders;
+
+		pkctrl  = PK_LOAD;
+		sliders = LS_LOAD;
+		oldsw   = swpt;
+		swpt    = t_load;
+
+		olddkey = d_key;
+		oldxkey = x_key;
+		oldekey = e_key;
+		oldmkey = m_key;
+		d_key   = loadkey;
+		x_key   = l_load;
+		e_key   = l_load;
+		m_key   = l_load;
+
+		loadsw = TRUE;
+
+		lcdlbls();
+		lseg(LOAD_XL, LOAD_Y, LOAD_XR, LOAD_Y, 1);
+	}
+
+	GLCcurs(G_OFF);
+	setleds();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	lcdlbls() -- put up the labels on the LCD display
+   =============================================================================
+*/
+
+lcdlbls()
+{
+	register short i, barval;
+	char buf[8];
+	char dsp[86];
+
+	point = GLCplot;		/* set up to plot on the LCD */
+
+	GLCinit();			/* clear the LCD display */
+	GLCcurs(G_ON);
+
+	/* label the switches */
+
+	switch (sliders) {
+
+	case LS_PRMTR:		/* parameter articulation */
+	case LS_OTHER:		/* other stuff */
+	case LS_EQ:		/* equalization */
+
+		GLCtext(0, 1, swtlbls[sliders]);
+
+		switch (gomode) {
+
+		case GO_SECT:
+
+			GLCtext(0, 31, "Sectn");
+			lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 1);
+			break;
+
+		case GO_SCOR:
+
+			GLCtext(0, 31, "Score");
+			lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 1);
+			break;
+
+		default:
+
+			GLCtext(0, 31, "Go To");
+			lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+			break;
+		}
+
+		break;
+/* 
+
+*/
+	case LS_VOICE:		/* voice selection */
+
+		dsp[0] = '\0';
+
+		for (i = 0; i < 12; i++) {
+
+			sprintf(buf, "%c%2d %c ",
+				(articen[i] ? '\176' : ' '), i + 1,
+				(articen[i] ? '\177' : ' '));
+
+			strcat(dsp, buf);
+		}
+
+		strcat(dsp, "Voice Init ");
+
+		GLCtext(0, 1, dsp);
+		break;
+
+	case LS_INST:		/* instrument selection */
+
+		dsp[0] = '\0';
+
+		for (i = 0; i < 12; i++) {
+
+			sprintf(buf, "%c%2d %c ",
+				(grpsel[i] ? '\176' : ' '), i + 1,
+				(grpsel[i] ? '\177' : ' '));
+
+			strcat(dsp, buf);
+		}
+
+		if (ismode EQ IS_HORC)
+			strcat(dsp, " +20 ");	/* hi orc */
+		else
+			strcat(dsp, " +00 ");	/* lo orc */
+
+		strcat(dsp, " Deflt");
+
+		GLCtext(0, 1, dsp);
+		break;
+
+	case LS_LIBR:
+	case LS_NGRP:
+	case LS_LOAD:
+
+		GLCtext(0, 1, swtlbls[sliders]);
+		break;
+	}
+
+/* 
+
+*/
+	GLCtext(7, 1, potlbls[sliders]);	/* label the pots */
+
+	for (i = 0; i < 13; i++)
+		lseg(39 + (i * 36), 0, 39 + (i * 36), 63, 1);
+
+	switch (sliders) {			/* draw the slider bars */
+
+	case LS_PRMTR:	/* parameter articulation */
+	case LS_VOICE:	/* voice articulation enable */
+	case LS_INST:	/* instrument select */
+	case LS_LIBR:	/* library select */
+	case LS_NGRP:	/* group select */
+	case LS_LOAD:	/* load select */
+
+		for (i = 0; i < 14; i++) {
+
+			if (BarType[i]) {
+
+				barval = (((BGprmtr[i] >> 5) - 500) << 6) / 252;
+				BarCset(i, barval);
+
+			} else {
+
+				barval = BGprmtr[i] / 252;
+				BarBset(i, barval);
+			}
+		}
+
+		break;
+
+	case LS_OTHER:
+	
+		for (i = 0; i < 14; i++)
+			BarBset(i, (BGother[i] / 252));
+
+		break;
+
+	case LS_EQ:
+
+		for (i = 0; i < 14; i++)
+			BarCset(i, BGeq[i]);
+
+		break;
+
+	default:
+
+		break;
+	}
+
+	GLCcurs(G_OFF);
+	dsrpmod();
+	dclkmd();
+	ulamp();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	selasg() -- select assignment table
+   =============================================================================
+*/
+
+selasg(n)
+short n;
+{
+	register struct s_entry *ep;
+
+	getasg(curasg = n);	/* set the assignment */
+
+	if (recsw) {		/* if we're recording ... */
+
+		if (E_NULL NE (ep = findev(p_cur, t_cur, EV_ASGN, -1, -1))) {
+
+			ep->e_data1 = n;	/* update old event */
+
+		} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_type  = EV_ASGN;	/* create new event */
+			ep->e_data1 = n;
+			ep->e_time  = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_ASGN);
+
+			if (ndisp EQ 2) {	/* if the score is up ... */
+
+				ctrsw = TRUE;
+				se_disp(ep, D_FWD, gdstbc, 1);
+				scupd();
+			}
+		}
+	}
+
+	asmode = 0;			/* drop out of assignment mode */
+	pkctrl = oldpk;			/* restore previous mode */
+	swpt   = oldsw;
+
+	point = GLCplot;		/* update the LCD */
+	GLCcurs(G_ON);
+	lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 0);
+	GLCtext(0, 1, swtlbls[sliders]);
+	GLCcurs(G_OFF);
+
+	mpcupd();			/* update the video display ... */
+	setleds();			/* ... and the LEDs */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_adfl() -- select default assignment table
+   =============================================================================
+*/
+
+l_adfl(stat)
+short stat;
+{
+	if (NOT stat)
+		return;
+
+	selasg(0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_asgn() -- select assignment
+   =============================================================================
+*/
+
+l_asgn(stat)
+short stat;
+{
+	if (NOT stat)			/* only do this on key closure */
+		return;
+
+	point = GLCplot;		/* set up to plot on the LCD */
+	GLCcurs(G_ON);
+
+	if (ismode NE IS_NULL) {	/* cancel instrument select mode */
+
+		ismode  = IS_NULL;
+		pkctrl  = oldpk;
+		sliders = oldsl;
+		swpt    = oldsw;
+		lcdlbls();
+	}
+
+	if (gomode NE GO_NULL) {	/* cancel Go To mode */
+
+		gomode = GO_NULL;
+		pkctrl = oldpk;
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+	}
+/* 
+
+*/
+	switch (asmode) {
+
+	case 0:			/* initial actuation */
+
+		if ((pkctrl EQ PK_PFRM) OR (pkctrl EQ PK_NOTE))
+			oldpk = pkctrl;
+
+		asmode = (curasg ? ((curasg - 1) / 20) : 0) + 1;
+		pkctrl = PK_ASGN;
+		memcpy(aswtbl, swpt, sizeof t_prmtr);
+		oldsw = swpt;
+		swpt  = aswtbl;
+		aswtbl[13] = l_adfl;
+		lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 1);
+		GLCtext(0, 79, "Deflt");
+		break;
+
+	case 1:			/* +00 -- 01..20 to +20 */
+	case 2:			/* +20 -- 21..40 to +40 */
+	case 3:			/* +40 -- 41..60 to +60 */
+	case 4:			/* +60 -- 61..80 to +80 */
+
+		++asmode;
+		break;
+
+	case 5:			/* +80 -- 81..99 to +00 */
+
+		asmode = 1;
+		break;
+
+	}
+
+	GLCtext(0, 43, aslbls[asmode]);
+	GLCcurs(G_OFF);
+	setleds();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_inst() -- set select instrument mode
+   =============================================================================
+*/
+
+l_inst(stat)
+short stat;
+{
+	if (NOT stat)
+		return;
+
+	point = GLCplot;		/* set up to plot on the LCD */
+	GLCcurs(G_ON);
+
+	if (asmode) {			/* cancel assignment mode */
+
+		asmode = 0;	
+		pkctrl = oldpk;
+		swpt   = oldsw;
+		lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 0);
+	}
+
+	if (gomode NE GO_NULL) {	/* cancel Go To mode */
+
+		gomode = GO_NULL;
+		pkctrl = oldpk;
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+	}
+
+	GLCcurs(G_OFF);
+/* 
+
+*/
+	switch (ismode) {
+
+	case IS_NULL:		/* select +00 -- low orchestra */
+
+		if ((pkctrl EQ PK_PFRM) OR (pkctrl EQ PK_NOTE))
+			oldpk = pkctrl;
+
+		if (sliders NE LS_INST)
+			oldsl = sliders;
+
+		oldsw   = swpt;
+		swpt    = t_inst;
+		pkctrl  = PK_INST;
+		ismode  = IS_LORC;
+		sliders = LS_INST;
+		lcdlbls();
+		break;
+
+	case IS_LORC:		/* select +20 -- high orchestra */
+
+		ismode  = IS_HORC;
+		GLCcurs(G_ON);
+		GLCtext(0, 73, " +20 ");
+		GLCcurs(G_OFF);
+		break;
+
+	case IS_HORC:		/* deselect */
+	default:
+
+		ismode  = IS_NULL;
+		pkctrl  = oldpk;
+		sliders = oldsl;
+		swpt    = oldsw;
+		lcdlbls();
+		break;
+	}
+
+	setleds();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	selins() -- select an instrument
+   =============================================================================
+*/
+
+selins(ival)
+register short ival;
+{
+	register short n;
+	register struct s_entry *ep;
+
+	for (n = 0; n < 12; n++) {
+
+		if (FALSE EQ grpsel[n])
+			continue;
+
+		ins2grp[n] = ival | (ins2grp[n] & 0xFF00);
+		setv2gi(n);
+
+		if (recsw AND grpstat[n] AND (2 EQ grpmode[n])) {
+
+			if (E_NULL NE (ep = findev(p_cur, t_cur, EV_INST, n, -1))) {
+
+				ep->e_data2 = ival;
+
+			} else if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+				ep->e_type  = EV_INST;
+				ep->e_data1 = n;
+				ep->e_data2 = ival;
+				ep->e_time  = t_cur;
+				p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+				eh_ins(ep, EH_INST);
+
+				if (ndisp EQ 2) {
+
+					ctrsw = TRUE;
+					se_disp(ep, D_FWD, gdstbc, 1);
+					scupd();
+				}
+			}
+		}
+	}
+
+	setinst();
+
+/* 
+
+*/
+	ismode  = IS_NULL;
+	pkctrl  = oldpk;
+	sliders = oldsl;
+	swpt    = oldsw;
+	lcdlbls();
+	setleds();
+	mpcupd();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_dflt() -- select default isntrument
+   =============================================================================
+*/
+
+l_dflt(stat)
+short stat;
+{
+	if (NOT stat)
+		return;
+
+	selins(0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_goto() -- go to (section / score)
+   =============================================================================
+*/
+
+l_goto(stat)
+short stat;
+{
+	if (NOT stat)			/* only do this on key closure */
+		return;
+
+	point = GLCplot;		/* set up to plot on the LCD */
+	GLCcurs(G_ON);
+
+	if (asmode) {			/* cancel assignment mode */
+
+		asmode = 0;	
+		pkctrl = oldpk;
+		swpt = oldsw;
+		lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 0);
+	}
+
+	if (ismode NE IS_NULL) {	/* cancel instrument select mode */
+
+		ismode  = IS_NULL;
+		sliders = oldsl;
+		pkctrl  = oldpk;
+		swpt    = oldsw;
+		lcdlbls();
+	}
+
+	recsw = FALSE;			/* force play mode */
+	dsrpmod();
+/* 
+
+*/
+	switch (gomode) {		/* select Go To mode */
+
+	case GO_NULL:
+
+		if ((pkctrl EQ PK_PFRM) OR (pkctrl EQ PK_NOTE))
+			oldpk = pkctrl;
+
+		pkctrl = PK_GOTO;
+		gomode = GO_SECT;
+		GLCtext(0, 31, "Sectn");
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 1);
+		break;
+
+	case GO_SECT:
+
+		gomode = GO_SCOR;
+		GLCtext(0, 31, "Score");
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 1);
+		break;
+
+	case GO_SCOR:
+	default:
+
+		pkctrl = oldpk;
+		gomode = GO_NULL;
+		GLCtext(0, 31, "Go To");
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+		break;
+	}
+
+	GLCcurs(G_OFF);
+	setleds();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	newpps() -- send out new polyphonic pressure source value
+   =============================================================================
+*/
+
+newpps(trg, grp, src, ival)
+register short trg;
+short grp, src;
+register short ival;
+{
+	register struct sment *smf, *smp;
+	register unsigned *fpu;
+	register long ltmp;
+	register short val;
+	register short vce;
+	short gs, oldi;
+
+	gs = (grp << 4) | src;		/* calculate group/source index */
+	fpu = io_fpu + FPU_OFNC;	/* point at FPU base */
+	valents[gs].val = ival;		/* update value in table */
+	smp = smf = (struct sment *)&valents[gs];
+
+/* 
+
+*/
+	while (smf NE (smp = smp->nxt)) {	/* for each function ... */
+
+		vce = (smp->vp >> 4) & 0x0F;	/* extract voice number */
+
+		if (vce2trg[vce] EQ trg) {	/* for each key that matches ... */
+
+			switch (smp->vp & 0x000F) {
+
+			case 1:		/* frq 1 */
+			case 3:		/* frq 2 */
+			case 5:		/* frq 3 */
+			case 7:		/* frq 4 */
+
+				val = ival >> 3;
+				break;
+
+			case 10:	/* filtr */
+
+				ltmp = ((long)ival >> 1) + ((long)ival >> 2);
+
+				if (ltmp > (long)VALMAX)
+					ltmp = (long)VALMAX;
+				else if (ltmp < (long)VALMIN)
+					ltmp = (long)VALMIN;
+
+				val = (short)ltmp;
+				break;
+
+			default:
+
+				val = ival;
+			}
+
+			oldi = setipl(FPU_DI);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+			*(fpu + (smp->vp << 4) + FPU_TCV1) = val;
+
+			setipl(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	newsv() -- send out new source value if it's changed
+   =============================================================================
+*/
+
+short
+newsv(grp, src, ival)
+short grp, src;
+register short ival;
+{
+	register struct sment *smf, *smp;
+	register unsigned *fpu;
+	register long ltmp;
+	register short val;
+	register short gs;
+	register short oldi;
+	short vmask, var;
+
+	gs  = (grp << 4) | src;			/* calculate grp/src index */
+
+	if (-1 NE (var = src2var[src])) {	/* see if its a variable */
+
+		vmask = vmasks[anrs[var][grp]];	/* setup resolution mask */
+
+		/* see if we have a change in the selected significant bits */
+
+		if (((val = valents[gs].val) & vmask) EQ (ival & vmask)) {
+
+			/* make sure we always see a change to zero */
+
+			if (NOT ((ival EQ 0) AND val))	/* if not becoming zero */
+				return(FALSE);	/* ... it didn't change enough */
+		}
+	}
+
+	fpu = io_fpu + FPU_OFNC;		/* point to FPU */
+
+	valents[gs].val = ival;			/* update value in table */
+
+	smf = (struct sment *)&valents[gs];	/* point at value table */
+	smp = smf;
+
+/* 
+
+*/
+	while (smf NE (smp = smp->nxt)) {	/* update functions */
+
+		switch (smp->vp & 0x000F) {
+
+		case 1:		/* frq 1 */
+		case 3:		/* frq 2 */
+		case 5:		/* frq 3 */
+		case 7:		/* frq 4 */
+
+			val = ival >> 3;
+			break;
+
+		case 10:	/* filtr */
+
+			ltmp = ((long)ival >> 1) + ((long)ival >> 2);
+
+			if (ltmp > (long)VALMAX)
+				ltmp = (long)VALMAX;
+			else if (ltmp < (long)VALMIN)
+				ltmp = (long)VALMIN;
+
+			val = (short)ltmp;
+			break;
+
+		default:
+
+			val = ival;
+		}
+
+		oldi = setipl(FPU_DI);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+		*(fpu + (smp->vp << 4) + FPU_TCV1) = val;
+
+		setipl(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+	}
+
+	return(TRUE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setsv() -- unconditionally send out new source value
+   =============================================================================
+*/
+
+setsv(grp, src, ival)
+short grp, src;
+register short ival;
+{
+	register struct sment *smf, *smp;
+	register unsigned *fpu;
+	register long ltmp;
+	register short val;
+	register short gs;
+	register short oldi;
+
+	gs  = (grp << 4) | src;			/* calculate grp/src index */
+	fpu = io_fpu + FPU_OFNC;		/* point to FPU */
+
+	valents[gs].val = ival;			/* update value in table */
+
+	smf = (struct sment *)&valents[gs];	/* point at value table */
+	smp = smf;
+
+/* 
+
+*/
+	while (smf NE (smp = smp->nxt)) {	/* update functions */
+
+		switch (smp->vp & 0x000F) {
+
+		case 1:		/* frq 1 */
+		case 3:		/* frq 2 */
+		case 5:		/* frq 3 */
+		case 7:		/* frq 4 */
+
+			val = ival >> 3;
+			break;
+
+		case 10:	/* filtr */
+
+			ltmp = ((long)ival >> 1) + ((long)ival >> 2);
+
+			if (ltmp > (long)VALMAX)
+				ltmp = (long)VALMAX;
+			else if (ltmp < (long)VALMIN)
+				ltmp = (long)VALMIN;
+
+			val = (short)ltmp;
+			break;
+
+		default:
+
+			val = ival;
+		}
+
+		oldi = setipl(FPU_DI);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+		*(fpu + (smp->vp << 4) + FPU_TCV1) = val;
+
+		setipl(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_prmtr() -- set parameter articulation status
+   =============================================================================
+*/
+
+l_prmtr(stat, sig)
+short stat, sig;
+{
+	if (NOT stat)
+		return;
+
+	switch (sliders) {
+
+	case LS_PRMTR:
+	case LS_OTHER:
+	case LS_EQ:
+
+		sliders = LS_VOICE;
+		swpt    = t_voice;
+		break;
+
+	case LS_VOICE:
+	default:
+
+		sliders = LS_PRMTR;
+		swpt    = t_prmtr;
+		break;
+	}
+
+	lcdlbls();
+	setleds();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_voice() -- set voice selection status
+   =============================================================================
+*/
+
+l_voice(stat, vce)
+short stat, vce;
+{
+	register short ap, j, par;
+	register unsigned *fpu;
+
+	char buf[8];
+
+	if (NOT stat)
+		return;
+
+	articen[vce] = NOT articen[vce];	/* toggle voice enable */
+
+	sprintf(buf, "%c%2d %c", (articen[vce] ? '\176' : ' '), vce + 1,
+		(articen[vce] ? '\177' : ' '));
+
+	GLCcurs(G_ON);
+	GLCtext(0, (1 + (6 * vce)), buf);
+	GLCcurs(G_OFF);
+
+	if (articen[vce]) {	/* turn articulation on if voice is enabled */
+
+		for (ap = 0; ap < 14; ap++) {
+
+			par = arpar[ap];
+			sendart(vce, par, lastart[par]);
+		}
+
+	} else {	/* ... or turn it off if voice is disabled */
+
+		fpu = io_fpu + FPU_OFNC + (vce << 8);
+
+		for (j = 1; j < 16; j++)
+			*(fpu + (j << 4) + FPU_TSF2) = 0;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_group() -- set group selection status
+   =============================================================================
+*/
+
+l_group(stat, grp)
+short stat, grp;
+{
+	char buf[8];
+
+	if (NOT stat)
+		return;
+
+	grpsel[grp] = NOT grpsel[grp];	/* toggle voice enable */
+
+	sprintf(buf, "%c%2d %c", (grpsel[grp] ? '\176' : ' '), grp + 1,
+		(grpsel[grp] ? '\177' : ' '));
+
+	GLCcurs(G_ON);
+	GLCtext(0, (1 + (6 * grp)), buf);
+	GLCcurs(G_OFF);
+}
+
+/*
+   =============================================================================
+	l_other -- set aux function status
+   =============================================================================
+*/
+
+l_other(stat, sig)
+short stat, sig;
+{
+	if (NOT stat)
+		return;
+
+	sliders = LS_OTHER;
+	swpt    = t_other;
+
+	lcdlbls();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_eq -- set eq mode
+   =============================================================================
+*/
+
+l_eq(stat, sig)
+short stat, sig;
+{
+	if (NOT stat)
+		return;
+
+	if (sliders EQ LS_EQ) {
+
+		sliders = LS_PRMTR;
+		swpt    = t_prmtr;
+
+	} else {
+
+		sliders = LS_EQ;
+		swpt    = t_eq;
+	}
+
+	lcdlbls();
+}
+
+/*
+   =============================================================================
+	artclr() -- clear the articulation pot values
+   =============================================================================
+*/
+
+artclr()
+{
+	register short i;
+
+	for (i = 0; i < 14; i++)
+		lastart[arpar[i]] = artitab[i];
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	l_init() -- initialize articulation values  (reset the sliders)
+   =============================================================================
+*/
+
+l_init(stat, sig)
+short stat, sig;
+{
+	register unsigned *fpu;
+	register short barval, i, j;
+	char buf[16];
+
+	if (NOT stat)
+		return;
+
+	fpu = io_fpu + FPU_OFNC;
+
+	switch (sliders) {
+
+	case LS_PRMTR:
+	case LS_VOICE:
+	case LS_INST:
+	case LS_LIBR:
+	case LS_NGRP:
+	case LS_LOAD:
+
+		/* clear all but spares in voices 1..12 */
+
+		for (i = 0; i < 12; i++)
+			for (j = 1; j < 16; j++)
+				*(fpu + (i << 8) + (j << 4) + FPU_TSF2) = 0;
+
+		artclr();
+
+		for (i = 0; i < 14; i++) {
+
+			BGprmtr[i] = artitab[i];
+
+			if (BarType[i]) {
+
+				barval = (((artitab[i] >> 5) - 500) << 6) / 252;
+				BarCset(i, barval);
+
+			} else {
+
+				barval = artitab[i] / 252;
+				BarBset(i, barval);
+			}
+		}
+
+		break;
+
+	case LS_OTHER:
+
+		/* clear spares in voices 2..12 */
+
+		for (i = 1; i < 12; i++)
+			*(fpu + (i << 8) + FPU_TSF2) = 0;
+
+		for (i = 0; i < 14; i++)
+			BarBset(i, BGother[i] = 0);
+
+		break;
+
+	case LS_EQ:
+
+		for (i = 0; i < 14; i++) {
+
+			sendeq(i, gain2eq(0));
+			BarCset(i, BGeq[i] = 0);
+		}
+
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sendart() -- send out an articulation value
+   =============================================================================
+*/
+
+sendart(vce, par, ival)
+short vce, par, ival;
+{
+	register unsigned *fpu;
+	register short val, oldi, mult;
+	short nop;
+
+	lastart[par] = ival;
+
+	fpu = io_fpu + FPU_OFNC + (vce << 8) + (par << 4);
+	mult = 0x7FFF;
+
+	switch (par) {
+
+	case 1:		/* freq 1 */
+	case 3:		/* freq 2 */
+	case 5:		/* freq 3 */
+	case 7:		/* freq 4 */
+
+		val = addpch(ival, 0);
+		break;
+
+	case 10:	/* filter */
+
+		val = ((ival >> 5) - 500) << 5;
+		break;
+
+/* 
+
+*/
+
+	case 2:		/* level */
+
+		val = ival;
+		mult = 0xFFFF;
+		break;
+
+	case 4:		/* location */
+
+		val = ((ival >> 5) - 500) << 5;
+		mult = 0xFFFF;
+		break;
+
+	default:
+
+		val = ival;
+	}
+
+	oldi = setipl(FPU_DI);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+	*(fpu + FPU_TCV2) = val;
+	++nop;	++nop;	++nop;
+	*(fpu + FPU_TSF2) = mult;
+
+	setipl(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	doslide() -- update a changed slider value
+   =============================================================================
+*/
+
+doslide()
+{
+	register short arp, bar, barval, i, slval;
+
+	slval = ART_VAL(aval);	/* scaled articulation value */
+	bar   = asig - 25;	/* bar number */
+
+	switch (sliders) {
+
+	case LS_PRMTR:		/* parameter articulation */
+	case LS_VOICE:
+	case LS_INST:
+	case LS_LIBR:
+	case LS_NGRP:
+	case LS_LOAD:
+
+		BGprmtr[bar] = slval;
+		arp = arpar[bar];
+
+		for (i = 0; i < 12; i++)
+			if (articen[i])
+				sendart(i, arp, slval);
+
+		if (BarType[bar]) {		/* center-zero bar */
+
+			barval = (((slval >> 5) - 500) << 6) / 252;
+			BarCadj(bar, barval);
+
+		} else {			/* bottom-zero bar */
+
+			barval = slval / 252;
+			BarBadj(bar, barval);
+		}
+
+		return;
+/* 
+
+*/
+	case LS_OTHER:		/* aux, dome, cv control */
+
+		switch (asig) {
+
+		case 26:	/* aux mod */
+			sendart(9, 0, slval);
+			break;
+
+		case 27:	/* depth */
+			sendart(3, 0, slval);
+			break;
+
+		case 28:	/* rate */
+			sendart(2, 0, slval);
+			break;
+
+		case 29:	/* intensity */
+			sendart(1, 0, slval);
+			break;
+
+		case 30:	/* cv1 */
+			sendart(11, 0, slval);
+			break;
+
+		case 31:	/* cv2 */
+			sendart(10, 0, slval);
+			break;
+
+		case 32:	/* cv3 */
+			sendart(6, 0, slval);
+			break;
+
+		case 33:	/* cv4 */
+			sendart(8, 0, slval);
+			break;
+
+		default:
+			slval = 0;	/* force unused pots to stay zero */
+			break;
+		}
+
+		BGother[bar] = slval;
+		barval = slval / 252;
+		BarBadj(bar, barval);
+
+		return;
+
+/* 
+
+*/
+	case LS_EQ:		/* eq control */
+
+		barval = (((slval >> 5) - 500) << 6) / 252;
+		BGeq[bar] = barval;
+		sendeq(bar, gain2eq(SL2GAIN(slval)));
+		BarCadj(bar, barval);
+
+		return;
+
+	default:
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	settmpo() -- set the tempo
+   =============================================================================
+*/
+
+settmpo(val)
+short val;
+{
+	register short timeval;
+
+	tmpoval  = val;
+	timeval  = ( ( (tmpomlt + 50) * tmpoval) / 100);
+	timeval  = (short)( (192000L / timeval) - 1);
+	TIME_T2H = timeval >> 8;
+	TIME_T2L = timeval & 0x00FF;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	settune() -- send the fine tuning from tuneval to the FPU
+   =============================================================================
+*/
+
+settune()
+{
+	register short oldi, i, grp;
+	register unsigned *fpu;
+	register long trval, trmax;
+	short nop;
+
+	trmax = PCHMAX;
+
+	oldi = setsr(0x2200);
+
+/* +++++++++++++++++++++++ FPU interrupts disabled ++++++++++++++++++++++++++ */
+
+	for (i = 0; i < 12; i++) {
+
+		if (-1 NE (grp = vce2grp[i])) {
+
+			trval = (long)tuneval + ((long)s_trns[grp - 1] << 1);
+
+			if (trval > trmax)
+				trval = trmax;
+
+		} else {
+
+			trval = (long)tuneval;
+		}
+
+		fpu = io_fpu + FPU_OFNC + (i << 8) + 0x0010;	/* freq 1 */
+
+		*(fpu + FPU_TCV3) = (unsigned)(0x0000FFFFL & trval);
+		++nop;	++nop;	++nop;
+		*(fpu + FPU_TSF3) = 0x7FFF;
+	}
+
+	setsr(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+}
Index: ram/ldfield.c
===================================================================
--- ram/ldfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ldfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,547 @@
+/*
+   =============================================================================
+	ldfield.c -- librarian display field processing and cursor motion
+	Version 47 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "panel.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "libdsp.h"
+#include "score.h"
+
+extern	short	select(), whatbox(), nokey(), cxkstd(), cykstd(), stdmkey();
+extern	short	et_null(), ef_null(), rd_null(), nd_null(), lmwclr();
+extern	short	vcputsv(), ftkind(), _clsvol(), lcancel(), stdctp0();
+extern	short	ldline(), lin2slt(), dslslot(), putcat(), showcat(), showsiz();
+
+extern	unsigned	exp_c();
+
+extern	char	*memset(), *slotnam();
+
+/* 
+
+*/
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	short	astat;
+extern	short	catin;
+extern	short	cmfirst;
+extern	short	cxrate;
+extern	short	cxval;
+extern	short	cyrate;
+extern	short	cyval;
+extern	short	ldelsw;
+extern	short	lderrsw;
+extern	short	ldkind;
+extern	short	ldpass;
+extern	short	ldrow;
+extern	short	ldslot;
+extern	short	lmwtype;
+extern	short	loadrow;
+extern	short	loadsw;
+extern	short	lorchl;
+extern	short	lrasw;
+extern	short	lselsw;
+extern	short	ltagged;
+extern	short	ndisp;
+extern	short	oldltag;
+extern	short	oldpk;
+extern	short	oldsl;
+extern	short	pkctrl;
+extern	short	sliders;
+extern	short	stcrow;
+extern	short	stccol;
+extern	short	submenu;
+extern	short	tagslot;
+extern	short	thcwval;
+extern	short	tvcwval;
+
+extern	unsigned *librob;
+
+extern	char	bfs[];
+extern	char	ldfile[];
+extern	char	ldcmnt[];
+
+extern	short	crate1[];
+extern	short	ldmap[];
+
+extern	PFS	(*swpt)[];
+extern	PFS	(*oldsw)[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	ldboxes[];
+
+/* forward reference */
+
+short	ld_prmv(), ldxkey(), ldmkey(), ldkey(), ldcxupd(), ldcyupd();
+
+/* 
+
+*/
+
+struct	fet	ld_fet1[] = {
+
+	{21, 10, 17, 0x0000, et_null, ef_null, rd_null, nd_null},  /* name */
+	{21, 27, 63, 0x0000, et_null, ef_null, rd_null, nd_null},  /* comment */
+
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+short	ldbox[][8] = {	/* display box parameters */
+
+	{  1,   1, 510,  13, LCFBX00, LCBBX00,  0,  1},	/*  0 - index area label */
+	{  1,  14, 510, 292, LCFBX01, LCBBX01,  1,  1},	/*  1 - index area */
+	{  1, 294,  78, 307, LCFBX02, LCBBX02, 21,  1},	/*  2 - file name label */
+	{ 80, 294, 143, 307, LCFBX03, LCBBX03, 21, 10},	/*  3 - file name */
+	{145, 294, 214, 307, LCFBX04, LCBBX04, 21, 19},	/*  4 - comment label */
+	{216, 294, 510, 307, LCFBX05, LCBBX05, 21, 27},	/*  5 - comment */
+	{  1, 309,  70, 321, LCFBX06, LCBBX06, 22,  1},	/*  6 - fetch */
+	{  1, 322,  70, 335, LCFBX07, LCBBX07, 23,  1},	/*  7 - replace / append */
+	{  1, 336,  70, 348, LCFBX08, LCBBX08, 24,  1},	/*  8 - lo orch / hi orch */
+	{ 72, 309, 255, 348, LCFBX09, LCBBX09, 22, 10},	/*  9 - store */
+	{257, 309, 510, 348, LCFBX10, LCBBX10, 22, 33}	/* 10 - message window */
+};
+
+char	*ldbxlb0[] = {	/* display box labels */
+
+	"RecrdType L FileName Comment                               Mem", /*  0 */
+	"",			/*  1 */
+	"FileName",		/*  2 */
+	"",			/*  3 */
+	"Comment",		/*  4 */
+	"",			/*  5 */
+	"Index",		/*  6 */
+	"",			/*  7 */
+	"",			/*  8 */
+	"",			/*  9 */
+	""			/* 10 */
+};
+
+/* 
+
+*/
+
+struct curpak ld_flds = {
+
+	stdctp0,	/* curtype */
+	ld_prmv,	/* premove */
+	nokey,		/* pstmove */
+	cxkstd,		/* cx_key */
+	cykstd,		/* cy_key */
+	ldcxupd,	/* cx_upd */
+	ldcyupd,	/* cy_upd */
+	nokey,		/* xy_up */
+	nokey,		/* xy_dn */
+	ldxkey,		/* x_key */
+	select,		/* e_key */
+	ldmkey,		/* m_key */
+	ldkey,		/* d_key */
+	nokey,		/* not_fld */
+	ld_fet1,	/* curfet */
+	ldboxes,	/* csbp */
+	crate1,		/* cratex */
+	crate1,		/* cratey */
+	CT_TEXT,	/* cmtype */
+	LCURX,		/* cxval */
+	LCURY		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldxkey() -- handle the 'X' (delete) key
+   =============================================================================
+*/
+
+short
+ldxkey()
+{
+	register char *fn;
+	register short slot;
+	char buf[4];
+
+	if (NOT astat)		/* only on key closure */
+		return(FAILURE);
+
+	clrerms();
+	stcrow = cyval / 14;
+	stccol = cxval >> 3;
+
+	if (lselsw AND lrasw) {
+
+		if (0 NE (slot = ldline(cyval))) {
+
+			slot -= 1;
+			ldmap[slot] = -1;
+			dpy_scr(ldbox[1][4], slot);
+			return(SUCCESS);
+
+		} else
+			return(FAILURE);
+	}
+
+	if (lcancel(2))
+		return(SUCCESS);
+
+	if (NOT ldelsw) {	/* deletion not yet selected ? */
+
+		if (0 NE (ldrow = ldline(cyval))) {	/* index area ? */
+
+			if (stccol EQ 11) {	/* load tag ? */
+
+				if (-1 EQ (slot = lin2slt(stcrow)))
+					return(FAILURE);
+
+				if (ltagged) {
+
+					if (slot NE tagslot) {
+
+						filecat[tagslot].fcp0 = oldltag;
+						ltagged = FALSE;
+						showcat();
+						return(FAILURE);
+					}
+
+					putcat();
+					ltagged = FALSE;
+					showcat();
+
+				} else {
+
+					oldltag = filecat[slot].fcp0;
+					filecat[slot].fcp0 = ' ';
+					ltagged = TRUE;
+					tagslot = slot;
+
+					buf[0] = oldltag;
+					buf[1] = '\0';
+
+					if (v_regs[5] & 0x0180)
+						vbank(0);
+
+					vcputsv(librob, 64, exp_c(LD_DELC), ldbox[1][5],
+						stcrow, 11, buf, 14);
+				}
+
+				return(SUCCESS);
+			}
+
+			if ((stccol < 13) OR (stccol > 20))	/* name ? */
+				return(FAILURE);
+
+			if (-1 NE (ldslot = lin2slt(ldrow))) {
+
+				/* select file to delete */
+
+				dslslot(ldslot, exp_c(LD_DELC), ldrow);
+				ldelsw = TRUE;
+				return(SUCCESS);
+			}
+/* 
+
+*/
+		} else {	/* not in the index area */
+
+			if (21 EQ stcrow) {	/* filename or comment ? */
+
+				if ((stccol GE 10) AND (stccol LE 17)) {
+
+					/* clear filename field */
+
+					memset(ldfile, ' ', 8);
+					ldswin(3);
+					return(SUCCESS);
+
+				} else if (stccol GE 27) {
+
+					/* clear comment field */
+
+					memset(ldcmnt, ' ', 37);
+					ldswin(5);
+					return(SUCCESS);
+				}
+			}
+
+			return(FAILURE);
+		}
+
+/* 
+
+*/
+
+	} else {	/* file selected for deletion */
+
+		/* delete the file if cursor hasn't moved */
+
+		if (ldrow EQ ldline(cyval)) {
+
+			filecat[ldslot].fcsize[0] = 0;
+			fn = slotnam(ldslot, ftkind(ldslot));
+
+			unlink(fn);
+
+			ldelsw = FALSE;
+			putcat();
+
+			_clsvol();
+			showcat();
+			showsiz();
+
+			return(SUCCESS);
+		}
+
+		ldelsw = FALSE;
+		showcat();
+		return(SUCCESS);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ld_prmv() -- librarian cursor pre-move function
+   =============================================================================
+*/
+
+ld_prmv()
+{
+	if (lderrsw)		/* clear any error messages in the window */
+		clrerms();
+
+	if (ltagged) {		/* clear any non-stored load tag */
+
+		filecat[tagslot].fcp0 = oldltag;
+		ltagged = FALSE;
+		showcat();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldcyupd() -- update cursor y location
+   =============================================================================
+*/
+
+ldcyupd()
+{
+	if (lmwtype EQ 1) {
+
+		vtcyupd();	/* update virtual typewriter cursor y */
+
+	} else {
+
+		cyval += cyrate;
+
+		if (cyval GT (CYMAX - 1))
+			cyval = CYMAX - 1;
+		else if (cyval LT 1)
+			cyval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldcxupd() -- update cursor x location
+   =============================================================================
+*/
+
+ldcxupd()
+{
+	if (lmwtype EQ 1 ) {
+
+		vtcxupd();	/* update virtual typewriter cursor x */
+
+	} else {
+
+		cxval += cxrate;
+
+		if (cxval GT (CXMAX - 1))
+			cxval = CXMAX - 1;
+		else if (cxval LT 1)
+			cxval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldmkey() -- librarian menu key processor
+   =============================================================================
+*/
+
+ldmkey()
+{
+	if (astat) {
+
+		ltagged = FALSE;
+
+		if ((sliders EQ LS_LIBR) OR (pkctrl EQ PK_LIBR)) {
+
+			sliders = oldsl;
+			swpt = oldsw;
+			pkctrl = oldpk;
+			lcdlbls();
+			setleds();
+		}
+	}
+
+	stdmkey();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	loadem() -- load multiple files
+   =============================================================================
+*/
+
+loadem(key)
+short key;
+{
+	register short c, i, rc, slot;
+
+	rc = FALSE;
+
+	if (getcat(0))				/* get the file catalog */
+		return;
+
+	for (ldslot = 0; ldslot < 20; ldslot++) {	/* check each slot */
+
+		if (ocslot(ldslot) AND
+		    ((c = filecat[ldslot].fcp0) & 0x007F) EQ (key & 0x007F)) {
+
+			ldkind = ftkind(ldslot);
+
+			if ((ldkind EQ FT_ORC) OR
+			    (ldkind EQ FT_ORL) OR
+			    (ldkind EQ FT_ORH))
+				lorchl = (c & 0x0080) ? 1 : 0;
+
+			if (ldkind EQ FT_SCR)
+				for (i = 0; i < N_SCORES; i++)
+					ldmap[i] = i;
+
+			if(getit())
+				return;
+
+			rc = TRUE;
+		}
+	}
+
+	if (rc AND (ndisp EQ -1))
+		m7menu();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldkey() -- process data key entry
+   =============================================================================
+*/
+
+ldkey(k)
+short k;
+{
+	register short c, col, row, slot;
+	char buf[4];
+
+	if (NOT astat)				/* only on key closure */
+		return(FAILURE);
+
+	if (NOT catin)				/* catalog must be valid */
+		return;
+
+	row = cyval / 14;			/* determine cursor position */
+	col = cxval >> 3;
+
+	if (col NE 11)				/* must be column 11 */
+		return;
+
+	if (-1 EQ (slot = lin2slt(row)))	/* ... and a valid slot */
+		return;
+
+	if (NOT ltagged) {
+
+		oldltag = filecat[slot].fcp0;	/* save old tag */
+		lcancel(3);			/* cancel other selections */
+	}
+
+/* 
+
+*/
+	/* process the key */
+
+	if (k < 7)
+		filecat[slot].fcp0 = (c = k + 'A');
+	else if (k EQ 7)
+		return;
+	else if (k EQ 8)
+		filecat[slot].fcp0 = (c = filecat[slot].fcp0 & 0x007F);
+	else	/* k EQ 9 */
+		filecat[slot].fcp0 = (c = filecat[slot].fcp0 | 0x0080);
+
+	loadrow = row;
+	tagslot = slot;
+	ltagged = TRUE;
+
+	dslslot(slot, exp_c(LD_SELC), row);
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldfield() -- setup field routines for the librarian
+   =============================================================================
+*/
+
+ldfield()
+{
+	lmwtype = 0;
+	ltagged = FALSE;
+	submenu = FALSE;
+
+	curset(&ld_flds);
+}
Index: ram/ldselbx.c
===================================================================
--- ram/ldselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ldselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1158 @@
+/*
+   =============================================================================
+	ldselbx.c -- librarian box selection functions
+	Version 46 -- 1988-11-18 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stdio.h"
+#include "stddefs.h"
+#include "fields.h"
+#include "graphdef.h"
+#include "glcfns.h"
+#include "glcdefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "lcdline.h"
+#include "panel.h"
+#include "vsdd.h"
+#include "vsddvars.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "libdsp.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+
+extern	short	ldswin(), advlcur(), bsplcur(), ttcpos(), fcindex(), storit();
+extern	short	showsiz(), get_asg(), get_orc(), get_tun(), get_wav(), nokey();
+extern	short	ldline(), lin2slt(), dslslot(), vtdisp(), ldpoint(), rd_ec();
+extern	short	fcreset(), ftkind(), ldwmsg(), ldbusy(), ckstor();
+extern	short	get_pat(), get_scr();
+
+extern	unsigned exp_c();
+
+extern	char	*slotnam();
+
+/* 
+
+*/
+
+#if DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	short	(*point)();
+
+extern	short	asmode;
+extern	short	catin;
+extern	short	cxrate;
+extern	short	cxval;
+extern	short	cyrate;
+extern	short	cyval;
+extern	short	errno;
+extern	short	gomode;
+extern	short	hitcx;
+extern	short	hitcy;
+extern	short	ismode;
+extern	short	lasgsw;
+extern	short	ldelsw;
+extern	short	lderrsw;
+extern	short	ldkind;
+extern	short	ldrow;
+extern	short	ldslot;
+extern	short	lksel;
+extern	short	lmwtype;
+extern	short	lorchl;
+extern	short	lorchsw;
+extern	short	lorclsw;
+extern	short	ldpass;
+extern	short	lpatsw;
+extern	short	lrasw;
+extern	short	lscrsw;
+extern	short	lselsw;
+extern	short	lseqsw;
+extern	short	lstrsw;
+extern	short	ltagged;
+extern	short	ltunsw;
+extern	short	lwavsw;
+extern	short	ndisp;
+extern	short	oldpk;
+extern	short	oldsl;
+extern	short	pkctrl;
+extern	short	sliders;
+extern	short	stcrow;
+extern	short	stccol;
+extern	short	tagslot;
+
+extern	unsigned	*librob;
+
+extern	short	ldmap[];
+extern	short	scsizes[][2];
+
+extern	short	ldbox[][8];
+
+extern	struct	scndx	sindex[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	*curboxp;
+
+extern	PFS	(*swpt)[];
+extern	PFS	(*oldsw)[];
+extern	PFS	t_libr[];
+
+extern	char	bfs[];
+extern	char	ldfile[];
+extern	char	ldcmnt[];
+
+extern	char	loadedf[][8];
+extern	char	loadedc[][37];
+
+/* forward references */
+
+short	bx_null(), ldfnbox();
+
+/* 
+
+*/
+
+short	ft2lt[] = {	/* file type to load type map */
+
+	LT_ASG,
+	LT_ORL,
+	LT_ORH,
+	LT_SCR,
+	LT_TUN,
+	LT_WAV,
+	LT_ORL,
+	LT_PAT,
+	LT_SEQ
+};
+
+struct	selbox	ldboxes[] = {
+
+	{  1,   1, 510,  13,      0, ldfnbox},	/*  0 - index area label */
+	{  1,  14, 510, 293,      1, ldfnbox},	/*  1 - index area */
+	{  1, 294,  78, 307,      2, ldfnbox},	/*  2 - file name label */
+	{ 80, 294, 143, 307,      3, ldfnbox},	/*  3 - file name */
+	{145, 294, 214, 307,      4, ldfnbox},	/*  4 - comment label */
+	{216, 294, 510, 307,      5, ldfnbox},	/*  5 - comment */
+	{  1, 308,  70, 321,      6, ldfnbox},	/*  6 - fetch */
+	{  1, 322,  70, 335,      7, ldfnbox},	/*  7 - replace / append */
+	{  1, 336,  70, 349,      8, ldfnbox},	/*  8 - lo orch / hi orch */
+	{ 72, 308, 255, 349,      9, ldfnbox},	/*  9 - store */
+	{257, 308, 510, 349,     10, ldfnbox},	/* 10 - message window */
+
+	{  0,   0,   0,   0, 	  0, FN_NULL}	/* end of table */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	skperr() -- complain about an error while skipping a score
+   =============================================================================
+*/
+
+skperr(sn)
+short sn;
+{
+	char	scid[32];
+	char	erms[64];
+
+	clrlsel();
+
+	sprintf(scid, "  score %d", sn + 1);
+	sprintf(erms, "  errno = %d", errno);
+
+	ldermsg("Couldn't skip", scid, erms,
+		LD_EMCF, LD_EMCB);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	skp_ec() -- skip with error checking
+   =============================================================================
+*/
+
+short
+skp_ec(fp, len)
+register FILE *fp;
+register long len;
+{
+	register long count;
+	register int c;
+	char errbuf[64];
+
+	for (count = 0; count < len; count++) {
+
+		errno = 0;
+
+		if (EOF EQ (c = getc(fp))) {
+
+			sprintf(errbuf, "errno = %d", errno);
+
+			ldermsg("Unexpected EOF",
+				errbuf, (char *)NULL, LD_EMCF, LD_EMCB);
+
+#if	DEBUGIT
+			if (debugsw)
+				FILEpr(fp);
+#endif
+
+			fclose(fp);
+			postio();		/* restore LCD backlight */
+			return(FAILURE);
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scskip() -- skip a score starting with its section list
+   =============================================================================
+*/
+
+short
+scskip(fp, ns)
+register FILE *fp;
+short ns;
+{
+	register short ehdr, go;
+	char etype;
+	char erms[64];
+
+	go = TRUE;
+
+	if (skp_ec(fp, (long)(N_SECTS * 12))) { 	/* skip section times */
+
+		skperr(ns);
+		return(FAILURE);
+	}
+
+	if (rd_ec(fp, &etype, 1L)) {	/* read first score header event */
+
+		skperr(ns);
+		return(FAILURE);
+	}
+
+	if (etype NE EV_SCORE) {	/* complain if it's not a score event */
+
+		sprintf(erms, "  score %d  etype = %d", ns + 1, etype);
+
+		ldermsg("Bad score --", "  1st event is wrong",
+			erms, LD_EMCF, LD_EMCB);
+
+		return(FAILURE);
+	}
+
+	if (skp_ec(fp, (long)(scsizes[etype][1] - 1))) {	/* skip data */
+
+		skperr(ns);
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+	do {		/* skip remaining score events */
+
+		if (rd_ec(fp, &etype, 1L)) {	/* get event type */
+
+			skperr(ns);
+			return(FAILURE);
+		}
+
+		/* skip the event's data */
+
+		if (skp_ec(fp, (long)(scsizes[etype][1] - 1))) {
+
+			skperr(ns);
+			return(FAILURE);
+		}
+
+		if (etype EQ EV_FINI)		/* check for score end */
+			go = FALSE;
+
+	} while (go);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldermsg() -- display an error message if none is up already
+   =============================================================================
+*/
+
+ldermsg(p1, p2, p3, p4, p5)
+char *p1, *p2, *p3;
+unsigned p4, p5;
+{
+	char msgbuf[64];
+
+	if (NOT lderrsw) {			/* put up new messages only */
+
+		strcpy(msgbuf, "ERROR: ");
+		strcat(msgbuf, p1);
+
+		ldwmsg(p1, p2, p3, p4, p5);
+	}
+
+	lderrsw = TRUE;				/* set error state */
+}
+
+/*
+   =============================================================================
+	clrerms() -- clear an error message from the message window
+   =============================================================================
+*/
+
+clrerms()
+{
+	if (lderrsw) {
+
+		lderrsw = FALSE;
+		lmwclr();
+		ldswin(10);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clrlsel() -- clear library selection
+   =============================================================================
+*/
+
+clrlsel()
+{
+	if (lselsw) {
+
+		if (lrasw) {
+
+			lksel   = -1;
+			ldpass  = 0;
+			pkctrl  = oldpk;
+			sliders = oldsl;
+			swpt    = oldsw;
+			lcdlbls();
+			setleds();
+			fcindex();
+
+		} else {
+
+			dslslot(ldslot, exp_c(ldbox[1][4]), ldrow);
+		}
+	}
+
+	fcreset();
+}
+
+/*
+   =============================================================================
+	endltyp() -- end function for virtual typewriter
+   =============================================================================
+*/
+
+endltyp()
+{
+	lmwclr();
+	ldswin(10);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	savefc() -- save name and comment from loaded or stored file
+   =============================================================================
+*/
+
+savefc(kind)
+short kind;
+{
+	short fi;
+
+	fi = ft2lt[kind - 1];
+
+	if (kind EQ FT_ORC)
+		fi = lorchl ? LT_ORH : LT_ORL;
+
+	memcpy(loadedf[fi], ldfile, 8);
+	memcpy(loadedc[fi], ldcmnt, 37);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	lcancel() -- cancel librarian selections
+   =============================================================================
+*/
+
+short
+lcancel(lct)
+short lct;
+{
+	short rc;
+
+	rc = FALSE;
+
+	if ((lct NE 0) AND lselsw) {
+
+		rc = TRUE;
+		clrlsel();
+	}
+
+	if ((lct NE 1) AND (lstrsw OR (NOT ckstor()))) {
+
+		rc = TRUE;
+		streset();
+	}
+
+	if ((lct NE 2) AND ldelsw) {
+
+		rc = TRUE;
+		ldelsw = FALSE;
+		dslslot(ldslot, exp_c(ldbox[1][4]), ldrow);
+	}
+
+	return(rc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dpy_scr() -- display score contents entry
+   =============================================================================
+*/
+
+dpy_scr(color, ns)
+unsigned color;
+short ns;
+{
+	char buf[40];
+	long scl;
+
+	if (ndisp NE 0)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	if (ldmap[ns] EQ -1)
+		strcpy(buf, "  ");
+	else
+		sprintf(buf, "%02d", 1 + ldmap[ns]);
+
+	vcputsv(librob, 64, ldbox[1][4], ldbox[1][5], 1 + ns, 1, buf, 14);
+
+	if (-1L EQ (scl = sindex[ns].sclen))
+		strcpy(buf, "{ empty score  }      0");
+	else
+		sprintf(buf, "%-16.16s  %5ld", sindex[ns].scfnm, scl);
+
+	vcputsv(librob, 64, color, ldbox[1][5], 1 + ns, 4, buf, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	lst_scr() -- list the score contents directory
+   =============================================================================
+*/
+
+lst_scr()
+{
+	register short i;
+	unsigned cx;
+
+	if (ndisp NE 0)
+		return;
+
+	point = ldpoint;
+
+	cx = exp_c(ldbox[0][5]);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(librob, 128, ldbox[0][0], ldbox[0][1],
+		ldbox[0][2], ldbox[0][3], cx);
+
+	tsplot4(librob, 64, ldbox[0][4], ldbox[0][6], ldbox[0][7],
+		"No Score Name       Length", 14);
+
+	lseg(  8, 13,  23, 13, LUNDRLN);
+	lseg( 32, 13, 159, 13, LUNDRLN);
+	lseg(168, 13, 215, 13, LUNDRLN);
+
+	cx = exp_c(ldbox[1][5]);
+
+	vbfill4(librob, 128, ldbox[1][0], ldbox[1][1],
+		ldbox[1][2], ldbox[1][3], cx);
+
+	for (i = 0; i < N_SCORES; i++)
+		dpy_scr(ldbox[1][4], i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ndx_scr() -- display the table of contents for a score
+   =============================================================================
+*/
+
+short
+ndx_scr(slot)
+register short slot;
+{
+	register FILE *fp;
+	register short i;
+	register long rlen;
+	long rdlen;
+	char msgbuf1[64];
+	char msgbuf2[64];
+
+	ldpass = 0;
+
+	for (i = 0; i < N_SCORES; i++) {
+
+		sindex[i].sclen = -1L;
+		memset(sindex[i].scfnm, ' ', 16);
+	}
+
+	errno = 0;
+
+	if ((FILE *)NULL EQ (fp = fopenb(slotnam(slot, FT_SCR), "r"))) {
+
+		sprintf(msgbuf2, "  errno = %d", errno);
+
+		ldermsg("Couldn't open the file",
+			"  for the scores", msgbuf2,
+			LD_EMCF, LD_EMCB);
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+	errno = 0;
+
+	if (fseek(fp, 60L, 1)) {		/* seek past header */
+
+		sprintf(msgbuf2, "  errno = %d", errno);
+
+		ldermsg("Seek failure",
+			(char *)NULL, msgbuf2,
+			LD_EMCF, LD_EMCB);
+
+
+#if DEBUGIT
+		if (debugsw)
+			FILEpr(fp);
+#endif
+
+		fclose(fp);
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+#if DEBUGIT
+	if (debugsw)
+		FILEpr(fp);
+#endif
+
+	for (i = 0; i < N_SCORES; i++) {
+
+		if (rd_ec(fp, &rdlen, 4L)) {
+
+			sprintf(msgbuf1, "  of score %d", i + 1);
+			sprintf(msgbuf2, "  errno = %d", errno);
+
+			ldermsg("Unable to read the length",
+				msgbuf1, msgbuf2,
+				LD_EMCF, LD_EMCB);
+
+
+#if DEBUGIT
+			if (debugsw)
+				FILEpr(fp);
+#endif
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		sindex[i].sclen = rdlen;
+
+		if (-1L NE rdlen) {
+
+			if (rd_ec(fp, sindex[i].scfnm, 16L)) {
+
+				sprintf(msgbuf1, "  of score %d", i + 1);
+				sprintf(msgbuf2, "  errno = %d", errno);
+
+				ldermsg("Unable to read the name",
+					msgbuf1, msgbuf2,
+					LD_EMCF, LD_EMCB);
+
+
+#if DEBUGIT
+				if (debugsw)
+					FILEpr(fp);
+#endif
+
+				clrlsel();
+				return(FAILURE);
+			}
+
+			errno = 0;
+
+			if (scskip(fp, i)) {
+
+				sprintf(msgbuf1, "  score %d", i + 1);
+				sprintf(msgbuf2, "  errno=%d  rlen=%ld",
+					errno, rlen);
+
+				ldermsg("Unable to skip past",
+					msgbuf1, msgbuf2,
+					LD_EMCF, LD_EMCB);
+
+
+#if DEBUGIT
+				if (debugsw)
+					FILEpr(fp);
+#endif
+
+				fclose(fp);
+				postio();		/* restore LCD backlight */
+				clrlsel();
+				return(FAILURE);
+			}
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	ldpass = 1;
+	lst_scr();
+
+/* 
+
+*/
+	point = GLCplot;
+	GLCcurs(G_ON);
+
+	if (ismode NE IS_NULL) {	/* cancel inst. mode */
+
+		ismode  = IS_NULL;
+		pkctrl  = oldpk;
+		sliders = oldsl;
+		swpt    = oldsw;
+		lcdlbls();
+	}
+
+	if (gomode NE GO_NULL) {	/* cancel goto mode */
+
+		gomode = GO_NULL;
+		pkctrl = oldpk;
+		lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+	}
+
+	if (asmode) {			/* cancel assign mode */
+
+		asmode = 0;
+		pkctrl = oldpk;
+		swpt   = oldsw;
+		lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 0);
+	}
+
+	if ((pkctrl EQ PK_PFRM) OR (pkctrl EQ PK_NOTE))
+		oldpk = pkctrl;
+
+	if (sliders NE LS_LIBR)
+		oldsl = sliders;
+
+	oldsw   = swpt;
+	swpt    = t_libr;
+	pkctrl  = PK_LIBR;
+	sliders = LS_LIBR;
+	
+	lcdlbls();
+	setleds();
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	getit() -- read selected file
+   =============================================================================
+*/
+
+short
+getit()
+{
+	ldkind = ftkind(ldslot);
+
+	if (ldkind EQ -1) {
+
+		ldermsg("Unknown file type",
+			(char *)NULL, (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+	ldbusy("         Reading file");
+/* 
+
+*/
+	switch (ldkind) {
+
+	case FT_ASG:
+
+		if (get_asg())
+			return(FAILURE);
+
+		break;
+
+	case FT_ORH:
+	case FT_ORL:
+	case FT_ORC:
+
+		if (get_orc(lorchl, ldkind))
+			return(FAILURE);
+
+		break;
+
+	case FT_PAT:
+
+		if (get_pat())
+			return(FAILURE);
+
+		break;
+
+	case FT_SCR:
+
+		if (get_scr())
+			return(FAILURE);
+
+		break;
+
+	case FT_SEQ:
+
+		if (get_seq())
+			return(FAILURE);
+
+		break;
+
+	case FT_TUN:
+
+		if (get_tun())
+			return(FAILURE);
+
+		break;
+
+	case FT_WAV:
+
+		if (get_wav())
+			return(FAILURE);
+
+		break;
+
+	default:
+
+		ldermsg("ldkind bad",
+			(char *)NULL, (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		clrlsel();
+		return(FAILURE);
+	}
+/* 
+
+*/
+
+	memcpy(ldfile, filecat[ldslot].fcname, 8);
+	memcpy(ldcmnt, filecat[ldslot].fccmnt, 37);
+	savefc(ldkind);
+
+	clrlsel();
+
+	if (lrasw) {
+
+		ldswin(0);
+		ldswin(8);
+	}
+
+	ldswin(3);
+	ldswin(5);
+	showsiz();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldfnbox() -- librarian display box hit processor
+   =============================================================================
+*/
+
+short
+ldfnbox(n)
+short n;
+{
+	register short col, i, slot, sn;
+
+	col = hitcx >> 3;
+
+	if (lderrsw)
+		clrerms();
+
+	switch (n) {
+
+	case 1:		/* index area */
+
+		if (lcancel(0))
+			return(SUCCESS);
+
+		if (lselsw) {		/* something already selected ? */
+
+			if (lrasw) {	/* content mode ? */
+
+				if (ldkind EQ FT_SCR) {		/* score */
+
+					sn = ldline(hitcy) - 1;
+
+					if (sindex[sn].sclen NE -1L) {
+
+						if ((1 + sn) NE ldrow) {
+
+							dpy_scr(ldbox[1][4], ldrow - 1);
+							ldrow = 1 + sn;
+						}
+
+						dpy_scr(LD_SELC, sn);
+						lksel = sn;
+
+					} else {
+
+						lksel = -1;
+					}
+
+					return(SUCCESS);
+				}
+			}
+
+			if (ldrow NE ldline(hitcy)) {
+
+				clrlsel();
+				return(SUCCESS);
+			}
+
+			return(getit());
+/* 
+
+*/
+		} else {	/* nothing selected yet */
+
+			if (0 NE (ldrow = ldline(hitcy))) {
+
+				if (col EQ 11) {
+
+					if (catin AND ltagged) {
+
+						slot = lin2slt(ldrow);
+
+						if (slot EQ tagslot) {
+
+							putcat();
+							ltagged = FALSE;
+							showcat();
+						}
+					}
+
+				} else {
+
+					if (-1 NE (ldslot = lin2slt(ldrow))) {
+
+						lselsw = TRUE;
+						ldswin(8);
+						ldkind = ftkind(ldslot);
+
+						for (i = 0; i < N_SCORES; i++)
+							ldmap[i] = i;
+
+						if (lrasw AND (ldkind EQ FT_SCR))
+							return(ndx_scr(ldslot));
+
+						dslslot(ldslot, exp_c(LD_SELC), ldrow);
+						return(SUCCESS);
+					}
+				}
+			}
+
+			clrlsel();
+			return(FAILURE);
+		}
+/* 
+
+*/
+	case 3:		/* file name field */
+
+		if (lcancel(3))
+			return(SUCCESS);
+
+		if (lmwtype NE 1) {
+
+			lmwvtyp();		/* setup for the typewriter */
+			ldswin(10);		/* display the typewriter */
+
+			vtsetup(librob, vtdisp, 10, ldfile, 22, 33,
+				advlcur, bsplcur, nokey, nokey, endltyp,
+				ldbox[n][4], ldbox[n][5]);
+
+		} else {
+
+			vtyper();
+		}
+
+		return(SUCCESS);
+
+	case 5:		/* comment field */
+
+		if (lcancel(3))
+			return(SUCCESS);
+
+		if (lmwtype NE 1) {
+
+			lmwvtyp();		/* setup for the typewriter */
+			ldswin(10);		/* display the typewriter */
+
+			vtsetup(librob, vtdisp, 27, ldcmnt, 22, 33,
+				advlcur, bsplcur, nokey, nokey, endltyp,
+				ldbox[n][4], ldbox[n][5]);
+
+		} else {
+
+			vtyper();
+		}
+
+		return(SUCCESS);
+
+/* 
+
+*/
+
+	case 6:		/* "Index" */
+
+		if (lcancel(0))
+			return(SUCCESS);
+
+		clrlsel();
+		return(fcindex());
+
+	case 7:		/* "Content" */
+
+		if (lselsw AND lrasw)
+			return(getit());
+
+		lrasw = NOT lrasw;
+		ldswin(7);
+		return(SUCCESS);
+
+	case 8:		/* "Hi Orch" / "Lo Orch" */
+
+		lorchl = NOT lorchl;
+		ldswin(8);
+		return(SUCCESS);
+
+/* 
+
+*/
+	case 9:		/* "Store" */
+
+		if (lcancel(1))
+			return(SUCCESS);
+
+		if (cyval < 321) {
+
+			/* row 22:  "Store", "Score", or "Hi Orch" */
+
+			if (cxval < 120) {
+
+				/* "Store" */
+
+				if (lstrsw) {
+
+					storit();
+
+				 } else {
+
+					lstrsw = TRUE;
+					ldswin(9);
+				}
+
+				return(SUCCESS);
+
+			} else if ((cxval > 135) AND (cxval < 176)) {
+
+				/* "Score" */
+
+				lscrsw = NOT lscrsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+
+			} else if (cxval > 191) {
+
+				/* "Hi Orch" */
+
+				lorchsw = NOT lorchsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+			}
+/* 
+
+*/
+		} else if ((cyval > 321) AND (cyval < 335)) {
+
+			/* row 23:  "Waves",  "Patch",  or "Lo Orch" */
+
+			if (cxval < 120) {		/* "Waves" */
+
+				lwavsw = NOT lwavsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+
+			} else if ((cxval > 135) AND (cxval < 176)) {
+
+				/* "Patch" */
+
+				lpatsw = NOT lpatsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+
+			} else if (cxval > 191) {	/* "Lo Orch" */
+
+				lorclsw = NOT lorclsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+			}
+/* 
+
+*/
+		} else if (cyval > 335) {
+
+			/* row 24:  "Assgn", "Seqnc", or "Tunings" */
+
+			if (cxval < 120) {		/* "Assgn" */
+
+				lasgsw = NOT lasgsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+
+			} else if ((cxval > 135) AND (cxval < 176)) {
+
+				/* "Seqnc" */
+
+				lseqsw = NOT lseqsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+
+			} else if (cxval > 191) {	/* "Tunings" */
+
+				ltunsw = NOT ltunsw;
+				ldswin(9);
+
+				if (lstrsw)
+					storit();
+
+				return(SUCCESS);
+			}
+		}
+
+		return(FAILURE);
+
+	default:
+
+		lcancel(3);
+		return(FAILURE);
+	}
+}
Index: ram/libdsp.c
===================================================================
--- ram/libdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/libdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1898 @@
+/*
+   =============================================================================
+	libdsp.c -- MIDAS librarian display
+	Version 64 -- 1988-11-17 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGRE		0
+#define	DEBUGWE		0
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "curpak.h"
+#include "memory.h"
+#include "stdio.h"
+#include "errno.h"
+
+#include "ascii.h"
+#include "charset.h"
+#include "fpu.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+#include "instdsp.h"
+#include "libdsp.h"
+#include "wsdsp.h"
+
+#if	(DEBUGRE|DEBUGWE)
+extern	short	debugsw;
+#endif
+
+#if	DEBUGRE
+short	debugre = 1;
+#endif
+
+#if	DEBUGWE
+short	debugwe = 1;
+#endif
+
+extern	short	lcancel();
+
+extern	long	ptsizer();
+extern	long	scsizer();
+extern	long	sqsizer();
+
+/* 
+
+*/
+
+/* things defined elsewhere */
+
+extern	short	vbfill4(), tsplot4(), (*point)(), lseg();
+extern	short	clrlsel(), _clsvol(), setgc();
+
+extern	int	errno;
+extern	int	_bpbin;
+
+extern	short	chtime;
+extern	short	cmtype;
+extern	short	cvtime;
+extern	short	cxval;
+extern	short	cyval;
+extern	short	sgcsw;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	submenu;
+extern	short	thcwval;
+extern	short	tvcwval;
+
+extern	unsigned	*obj0, *obj2;
+
+extern	char	*ldbxlb0[];
+extern	char	vtlin1[], vtlin2[], vtlin3[];
+
+extern	short	ldbox[][8];
+extern	struct	instdef	idefs[];
+
+extern	struct	bpb	*_thebpb;
+
+/* 
+
+*/
+
+extern	unsigned *librob;		/* display object pointer */
+
+extern	short	catin;			/* catalog read in flag */
+extern	short	lrasw;			/* append (TRUE) / replace (FALSE) score */
+extern	short	lorchl;			/* hi (TRUE) / lo (FALSE) orchestra */
+extern	short	ldrow;			/* fetch select row */
+extern	short	ldslot;			/* fetch select slot */
+extern	short	lselsw;			/* fetch select switch */
+extern	short	ldkind;			/* fetch file type */
+extern	short	lstrsw;			/* store state switch */
+extern	short	lasgsw;			/* assignments store switch */
+extern	short	lksel;			/* librarian key slot selector */
+extern	short	lorchsw;		/* hi orchestra (21 - 40) store switch */
+extern	short	lorclsw;		/* lo orchestra (01 - 20) store switch */
+extern	short	lpatsw;			/* patch store switch */
+extern	short	lscrsw;			/* score store switch */
+extern	short	lseqsw;			/* sequence store switch */
+extern	short	ltunsw;			/* tunings store switch */
+extern	short	lwavsw;			/* waveshapes store switch */
+extern	short	ldelsw;			/* delete switch */
+extern	short	lderrsw;		/* error message displayed switch */
+extern	short	ldidsiz;		/* getcat() did showsiz() switch */
+extern	short	lmwtype;		/* librarian message window type */
+extern	short	ltagged;		/* load tag update in progress flag */
+extern	short	ndisp;			/* display number currently up */
+
+extern	long	lcsum;			/* library checksum */
+extern	long	ndbytes;		/* bytes needed for storage */
+
+extern	char	*lmln22;		/* message window line 22 */
+extern	char	*lmln23;		/* message window line 23 */
+extern	char	*lmln24;		/* message window line 24 */
+
+extern	char	ldfile[9];		/* file name field */
+extern	char	ldcmnt[38];		/* comment field */
+extern	char	ldmsg1[65];		/* messsage build area 1 */
+extern	char	ldmsg2[65];		/* messsage build area 2 */
+extern	char	ldmsg3[65];		/* messsage build area 3 */
+extern	char	errbuf[65];		/* error message build area */
+
+extern	struct	octent	*ldoct;		/* object control table pointer */
+
+extern	struct	mlibhdr	ldhead;		/* library header */
+
+/* forward references */
+
+short	ldpoint();
+
+/* 
+
+*/
+
+char	*ftypes[][3] = {	/* file types  (must match libdsp.h) */
+
+	{"ASG", "Assignmnt", "Assignmnt"},	/* FT_ASG */
+	{"ORL", "Orchestra", "Orchestra"},	/* FT_ORL */
+	{"ORH", "Orchestra", "Orchestra"},	/* FT_ORH */
+	{"SCR",	"    Score", "Score"},		/* FT_SCR */
+	{"TUN", "   Tuning", "Tuning"},		/* FT_TUN */
+	{"WAV", "Waveshape", "Waveshape"},	/* FT_WAV */
+	{"ORC", "Orchestra", "Orchestra"},	/* FT_ORC */
+	{"PAT", "    Patch", "Patch"},		/* FT_PAT */
+	{"SEQ", " Sequence", "Sequence"}	/* FT_SEQ */
+};
+
+char	ld_em1[] = "No files stored on disk";
+char	ld_em2[] = " by this operation";
+
+short	lbrpal[16][3] = {	/* librarian color palette */
+
+	{0, 0, 0},	/* 0 */
+	{3, 3, 3},	/* 1 */
+	{1, 0, 0},	/* 2 */
+	{1, 1, 0},	/* 3 */
+	{2, 1, 0},	/* 4 (was 2, 2, 0) */
+	{1, 1, 0},	/* 5 */
+	{2, 1, 0},	/* 6 (was 2, 2, 0) */
+	{1, 0, 0},	/* 7 */
+	{0, 1, 1},	/* 8 (was 0, 1, 0) */
+	{1, 0, 0},	/* 9 */
+	{1, 1, 0},	/* 10 */
+	{2, 2, 2},	/* 11 */
+	{2, 3, 3},	/* 12 */
+	{3, 3, 0},	/* 13 */
+	{3, 0, 0},	/* 14 */
+	{0, 0, 0}	/* 15 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ftkind() -- return the file type for a given file catalog slot
+
+		ns = catalog slot index
+		-1 returned on error   (returns 1..NFTYPES for a good type)
+   =============================================================================
+*/
+
+short
+ftkind(ns)
+short ns;
+{
+	register short i;
+
+	for (i = 0; i < NFTYPES; i++)
+		if (0 EQ memcmpu(filecat[ns].fcextn, ftypes[i][0], 3))
+			return(++i);
+
+	return(-1);
+}
+
+/*
+   =============================================================================
+	fctstr() -- return a string showing the file catalog entry type
+
+		ns = catalog slot index
+		just = 0: right justify string,  1: left justify string
+   =============================================================================
+*/
+
+char *
+fctstr(ns, just)
+short ns, just;
+{
+	static char fcbad[11];
+	register short i;
+
+	for (i = 0; i < NFTYPES; i++)
+		if (0 EQ memcmpu(filecat[ns].fcextn, ftypes[i][0], 3))
+			return(ftypes[i][just ? 2 : 1]);
+
+	sprintf(fcbad, "?? %3.3s  ??", filecat[ns].fcextn);
+	return(fcbad);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ocslot() -- determine if a slot is occupied
+   =============================================================================
+*/
+
+short
+ocslot(slot)
+short slot;
+{
+	if (memcmp(filecat[slot].fcsize, "000", 3)
+	    AND (0 NE filecat[slot].fcsize[0]))
+		return(TRUE);
+	else
+		return(FALSE);
+}
+
+/*
+   =============================================================================
+	ldline() -- determine which catalog line the cursor is on, if any
+   =============================================================================
+*/
+
+short
+ldline(cy)
+short cy;
+{
+	if (cy > 292)
+		return(0);
+
+	if (cy < 14)
+		return(0);
+
+	return(cy / 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	lin2slt() -- determine which slot a line corresponds to, if any
+
+		-1 returned on error  (0..FCMAX-1 returned for a good slot)
+   =============================================================================
+*/
+
+short
+lin2slt(line)
+short line;
+{
+	register short slot, row;
+
+	row = 0;
+
+	for (slot = 0; slot < FCMAX; slot++)
+		if (ocslot(slot))
+			if (++row EQ line)
+				return(slot);
+
+	return(-1);
+}
+
+/*
+   =============================================================================
+	exp_c() -- expand a 4 bit color to 16 bits
+   =============================================================================
+*/
+
+unsigned
+exp_c(cx)
+register unsigned cx;
+{
+	cx &= 0x000F;		/* use low 4 bits as the basis */
+	cx |= cx << 4;		/* turn them into 8 bits */
+	cx |= cx << 8;		/* make it a full 16 bits */
+
+	return(cx);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldwmsg() -- display a message in the message window
+   =============================================================================
+*/
+
+ldwmsg(line1, line2, line3, fgcolor, bgcolor)
+char *line1, *line2, *line3;
+unsigned fgcolor, bgcolor;
+{
+	lderrsw = FALSE;		/* clear error switch */
+	lmwtype = 2;			/* message type */
+	submenu = FALSE;
+
+	if (ndisp NE 0)
+		return;
+
+	bgcolor = exp_c(bgcolor);	/* expand background color */
+	fgcolor = exp_c(fgcolor);	/* expand foreground color */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	/* clear the window */
+
+	vbfill4(librob, 128, ldbox[10][0], ldbox[10][1],
+		ldbox[10][2], ldbox[10][3], bgcolor);
+
+	if ((char *)NULL NE line1)
+		tsplot4(librob, 64, fgcolor, ldbox[10][6], ldbox[10][7],
+			line1, 14);
+
+	if ((char *)NULL NE line2)
+		tsplot4(librob, 64, fgcolor, (ldbox[10][6] + 1), ldbox[10][7],
+			line2, 14);
+
+	if ((char *)NULL NE line3)
+		tsplot4(librob, 64, fgcolor, (ldbox[10][6] + 2), ldbox[10][7],
+			line3, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	chksum() -- checksum an area of memory
+   =============================================================================
+*/
+
+long
+chksum(area, len)
+register char *area;
+register long len;
+{
+	register long cs, i;
+
+	cs = 0L;
+
+	for (i = 0; i < len; i++)
+		cs += 0x000000FFL & *area++;
+
+	return(cs);
+}
+
+/*
+   =============================================================================
+	makelh() -- make a library header
+   =============================================================================
+*/
+
+makelh(kind)
+short kind;
+{
+	memset(ldhead.l_csum, '?', 8);			/* checksum */
+	memcpy(ldhead.l_name, ldfile, 8);		/* file name */
+	memcpy(ldhead.l_type, ftypes[kind - 1][0], 3);	/* file type */
+	memcpy(ldhead.l_cmnt, ldcmnt, 37);		/* comment */
+
+	lcsum = chksum(ldhead.l_name, (long)(LH_LEN - 8));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldbusy() -- put up a "Busy" message
+   =============================================================================
+*/
+
+ldbusy(msg)
+char *msg;
+{
+	if (ndisp NE 0)
+		return;
+
+	ldwmsg((char *)NULL, "    Busy - Please stand by", msg,
+		ldbox[10][4], ldbox[10][5]);
+}
+
+/*
+   =============================================================================
+	noslot() -- complain about not finding a slot we expected
+   =============================================================================
+*/
+
+noslot(fctype)
+{
+	sprintf(ldmsg1, " the %s file,", ftypes[fctype - 1][2]);
+
+	ldermsg("Can't find a slot for",
+		ldmsg1, " and one was expected", LD_EMCF, LD_EMCB);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wr_ec() -- write with error checking
+   =============================================================================
+*/
+
+short
+wr_ec(fp, from, len)
+register FILE *fp;
+register char *from;
+register long len;
+{
+	register long count;
+	register char c;
+	for (count = 0; count < len; count++) {
+
+		errno = 0;
+		c  = *from++;
+
+		if (EOF EQ putc(c, fp)) {
+
+			sprintf(errbuf, "errno = %d", errno);
+
+			ldermsg("Disk may be full",
+				errbuf, (char *)NULL, LD_EMCF, LD_EMCB);
+
+			fclose(fp);
+			postio();		/* restore LCD backlight */
+			return(FAILURE);
+		}
+
+#if	DEBUGWE
+	if (debugsw AND debugwe)
+		printf(" %02.2X", 0x00FF & c);
+#endif
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rd_ec() -- read with error checking
+   =============================================================================
+*/
+
+short
+rd_ec(fp, to, len)
+register FILE *fp;
+register char *to;
+register long len;
+{
+	register long count;
+	register int c;
+
+	for (count = 0; count < len; count++) {
+
+		errno = 0;
+
+		if (EOF EQ (c = getc(fp))) {
+
+			sprintf(errbuf, "errno = %d", errno);
+
+			ldermsg("Unexpected EOF",
+				errbuf, (char *)NULL, LD_EMCF, LD_EMCB);
+
+			fclose(fp);
+			postio();		/* restore LCD backlight */
+			return(FAILURE);
+
+		} else {
+
+			*to++ = c;
+
+#if	DEBUGRE
+	if (debugsw AND debugre)
+		printf(" %02.2X", 0x00FF & c);
+#endif
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	srchcat() -- search the file catalog
+	
+		returns -1 on 'not found',  slot 0..FCMAX-1 if found
+   =============================================================================
+*/
+
+short
+srchcat(extn)
+char extn[];
+{
+	register short fcslot;
+
+	for (fcslot = 0; fcslot < FCMAX; fcslot++) {
+
+		if (ocslot(fcslot))
+			if (0 EQ (memcmp(filecat[fcslot].fcname, ldfile, 8))
+			    AND (0 EQ memcmpu(filecat[fcslot].fcextn, extn, 3)))
+				return(fcslot);
+	}
+
+	return(-1);
+}
+
+/*
+   =============================================================================
+	clrcat() -- clear the file catalog
+   =============================================================================
+*/
+
+clrcat()
+{
+	register short i;
+	char fcebuf[1 + sizeof (struct fcat)];
+
+	for (i = 0; i < FCMAX; i++) {
+
+		sprintf(fcebuf, "000 Empty-%02.2d ??? %-37.37s%c%c",
+			i, "1234567890123456789012345678901234567",
+			A_CR, A_LF);
+
+		memcpy(&filecat[i], fcebuf, sizeof (struct fcat));
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clreq() -- return number of clusters needed for a file
+
+		Assumes the BPB pointer is valid.
+   =============================================================================
+*/
+
+short
+clreq(bytes)
+long bytes;
+{
+	register short rclusts;
+	register long clmask;
+
+	clmask = _thebpb->clsizb - 1;
+
+	rclusts = (bytes / _thebpb->clsizb)
+		  + ((bytes & clmask) ? 1 : 0);
+
+	return(rclusts);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	spacerq() -- return space required for storing a file
+   =============================================================================
+*/
+
+short
+spacerq(kind)
+short kind;
+{
+	register short howmuch;
+	register long k;
+
+	k = 0L;
+
+	switch (kind) {
+
+	case FT_ASG:	/* Assignment file */
+
+		k = (sizeof (struct asgent) * (long)NASGLIB) + LH_LEN;
+		break;
+
+	case FT_ORL:
+	case FT_ORH:
+	case FT_ORC:
+
+		k = ((OR_LEN1 + (2 * OR_LEN2)) * (long)NINORC) + LH_LEN;
+		break;
+
+	case FT_PAT:	/* Patch file */
+
+		k = ptsizer() + LH_LEN;
+		break;
+
+	case FT_SCR:	/* Score file */
+
+		k = scsizer() + LH_LEN;
+		break;
+
+	case FT_SEQ:	/* Sequence file */
+
+		k = sqsizer() + LH_LEN;
+		break;
+
+	case FT_TUN:	/* Tuning file */
+
+		k = (NTUNSLIB * 256L) + (NTUNSLIB * 32L) + LH_LEN;
+		break;
+
+	case FT_WAV:	/* Waveshape file */
+
+		k = ((long)NUMWAVS * OR_LEN2) + LH_LEN;
+		break;
+
+	default:
+
+		k = 0L;
+		break;
+	}
+/* 
+
+*/
+	howmuch = k ? clreq(k) : -1;
+	ndbytes = k;
+	return(howmuch);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ckstor() -- check for storage type selection
+   =============================================================================
+*/
+
+short
+ckstor()
+{
+	if (lasgsw)			/* assignments */
+		return(SUCCESS);
+
+	if (lorchsw)			/* hi orch */
+		return(SUCCESS);
+
+	if (lorclsw)			/* lo orch */
+		return(SUCCESS);
+
+	if (lpatsw)			/* patches */
+		return(SUCCESS);
+
+	if (lscrsw)			/* score */
+		return(SUCCESS);
+
+	if (lseqsw)			/* sequences */
+		return(SUCCESS);
+
+	if (ltunsw)			/* tunings */
+		return(SUCCESS);
+
+	if (lwavsw)			/* waveshapes */
+		return(SUCCESS);
+
+	return(FAILURE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ckdups() -- check for duplicate file type entries in the file catalog
+   =============================================================================
+*/
+
+short
+ckdups()
+{
+	if (lasgsw)
+		if (-1 NE srchcat("asg"))
+			return(FT_ASG);
+
+	if (lorchsw)
+		if (-1 NE srchcat("orh"))
+			return(FT_ORH);
+
+	if (lorclsw)
+		if (-1 NE srchcat("orl"))
+			return(FT_ORL);
+
+	if (lorchsw OR lorclsw)
+		if (-1 NE srchcat("orc"))
+			return(FT_ORC);
+
+	if (lpatsw)
+		if (-1 NE srchcat("pat"))
+			return(FT_PAT);
+
+	if (lscrsw)
+		if (-1 NE srchcat("scr"))
+			return(FT_SCR);
+
+	if (lseqsw)
+		if (-1 NE srchcat("seq"))
+			return(FT_SEQ);
+
+	if (ltunsw)
+		if (-1 NE srchcat("tun"))
+			return(FT_TUN);
+
+	if (lwavsw)
+		if (-1 NE srchcat("wav"))
+			return(FT_WAV);
+	return(0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showsiz() -- display disk capacity and usage
+
+		Forces the disk to be read to get the BPB and FAT.
+   =============================================================================
+*/
+
+showsiz()
+{
+	register short dcap, drem, dused;
+
+	_bpbin = FALSE;		/* force disk to be read */
+
+	dcap = dspace(0);
+
+	if (dcap EQ -1) {
+
+		ldermsg("Disk not ready ?",
+			(char *)NULL, (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		return(FAILURE);
+	}
+
+	drem = dspace(1);
+	dused = dcap - drem;
+
+	sprintf(ldmsg1, "Microdisk capacity %4u blocks", dcap);
+	sprintf(ldmsg2, "This disk consumes %4u blocks", dused);
+	sprintf(ldmsg3, "Available space is %4u blocks", drem);
+
+	ldwmsg(ldmsg1, ldmsg2, ldmsg3, ldbox[10][4], ldbox[10][5]);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	getcat() -- get the file catalog from disk
+   =============================================================================
+*/
+
+short
+getcat(msgsw)
+short msgsw;
+{
+	register FILE *fp;
+	int	rc, fesize;
+
+	ldidsiz = FALSE;		/* we didn't show the size (yet) */
+	_bpbin  = FALSE;		/* guarantee we read the directory */
+	catin   = FALSE;		/* catalog not valid */
+
+	errno = 0;
+	preio();			/* kill LCD backlight */
+	fp = fopenb(CATNAME, "r");	/* open the catalog file */
+
+	if (NULL EQ fp) {
+
+		clrcat();
+		catin = TRUE;
+
+		if (msgsw) {		/* see if we show the message */
+
+			showsiz();
+			ldidsiz = TRUE;	/* showed the size */
+		}
+
+		return(SUCCESS);	/* no catalog is OK, too */
+	}
+
+	fesize = sizeof(struct fcat);
+	memset(filecat, 0, sizeof (struct fcat) * FCMAX);
+
+/* 
+
+*/
+	errno = 0;
+	rc = fread(filecat, fesize, FCMAX, fp);
+
+	if (rc NE FCMAX) {
+
+		if (rc) {
+
+			sprintf(ldmsg1, "  fread returned %d", rc);
+			sprintf(ldmsg2, "  errno = %d, fesize=%d",
+				errno, fesize);
+
+			ldermsg("Unable to read catalog",
+				ldmsg1, ldmsg2, LD_EMCF, LD_EMCB);
+
+			catin = FALSE;
+
+		} else {
+
+			ldermsg("File catalog is NULL",
+				(char *)NULL, (char *)NULL,
+				LD_EMCF, LD_EMCB);
+
+			clrcat();
+			catin = TRUE;
+		}
+
+		fclose(fp);
+		postio();		/* restore LCD backlight */
+		return(FAILURE);
+	}
+
+	catin = TRUE;
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	putcat() -- write the updated catalog on disk
+   =============================================================================
+*/
+
+short
+putcat()
+{
+	register FILE *fp;
+	register int	i, rc, fesize;
+
+	for (i = 0; i < FCMAX; i++) {		/* clean up the catalog */
+
+		filecat[i].fceol[0] = A_CR;
+		filecat[i].fceol[1] = A_LF;
+	}
+
+	errno = 0;
+	preio();			/* kill LCD backlight */
+	fp = fopenb(CATNAME, "w");	/* open the catalog file */
+
+	if (NULL EQ fp) {
+
+		sprintf(ldmsg2, "  errno = %d", errno);
+
+		ldermsg("Unable to open catalog",
+				(char *)NULL, ldmsg2, LD_EMCF, LD_EMCB);
+
+		return(FAILURE);
+	}
+
+	fesize = sizeof (struct fcat);
+
+/* 
+
+*/
+	errno = 0;
+	rc = fwrite(filecat, fesize, FCMAX, fp);
+
+	if (rc NE FCMAX) {
+
+		if (rc) {
+
+			sprintf(ldmsg1, "  fwrite returned %d", rc);
+			sprintf(ldmsg2, "  errno = %d, fesize=%d",
+				errno, fesize);
+
+			ldermsg("Can't write catalog",
+				ldmsg1, ldmsg2, LD_EMCF, LD_EMCB);
+
+		} else {
+
+			sprintf(ldmsg2, "  errno = %d", errno);
+
+			ldermsg("Disk may be full",
+				(char *)NULL, ldmsg2,
+				LD_EMCF, LD_EMCB);
+		}
+
+		fclose(fp);
+		postio();		/* restore LCD backlight */
+		return(FAILURE);
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dslslot() -- display a file catalog entry
+   =============================================================================
+*/
+
+dslslot(slot, fg, row)
+register short slot;
+unsigned fg;
+short row;
+{
+	register unsigned color, chilon, chilorc;
+	short c;
+	char buf[40];
+
+	if (ndisp NE 0)
+		return;
+
+	color   = exp_c(fg);		/* foreground color */
+	chilon  = exp_c(ldbox[1][4]);
+	chilorc = exp_c(HILORC);
+
+	/* file type */
+
+	vcputsv(librob, 64, color, ldbox[1][5], row, 1, fctstr(slot, 0), 14);
+
+	/* load letter */
+
+	c = filecat[slot].fcp0;
+	buf[0] = 0x007F & c;
+	buf[1] = '\0';
+	vcputsv(librob, 64, (c & 0x0080) ? chilorc : chilon,
+		ldbox[1][5], row, 11, buf, 14);
+
+	/* file name */
+
+	memcpy(buf, filecat[slot].fcname, 8);
+	buf[8] = '\0';
+	vcputsv(librob, 64, color, ldbox[1][5], row, 13, buf, 14);
+
+	/* comment */
+
+	memcpy(buf, filecat[slot].fccmnt, 37);
+	buf[37] = '\0';
+	vcputsv(librob, 64, chilon, ldbox[1][5], row, 22, buf, 14);
+
+	/* size */
+
+	memcpy(buf, filecat[slot].fcsize, 3);
+	buf[3] = '\0';
+	vcputsv(librob, 64, chilon, ldbox[1][5], row, 60, buf, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showcat() -- display the file catalog entries
+   =============================================================================
+*/
+
+short
+showcat()
+{
+	register short i, fcslot, fcrow, fcount;
+	register unsigned color;
+
+	if (ndisp NE 0)
+		return;
+
+	ldswin(0);			/* fix up the title */
+
+	color = exp_c(ldbox[1][5]);	/* background color */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(librob, 128, ldbox[1][0], ldbox[1][1],
+		ldbox[1][2], ldbox[1][3], color);
+
+	color = ldbox[1][4];		/* foreground color */
+
+	fcrow  = 1;
+	fcount = 0;
+
+	for (fcslot = 0; fcslot < FCMAX; fcslot++) {
+
+		if (ocslot(fcslot))  {
+
+			dslslot(fcslot, color, fcrow);
+			fcrow++;
+			fcount++;
+		}
+	}
+
+	return(fcount);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	fcindex() -- display the file catalog
+   =============================================================================
+*/
+
+short
+fcindex()
+{
+	if (NOT lderrsw)
+		ldbusy("       Reading catalog");
+
+	if (getcat(1))			/* get catalog, possibly display size */
+		return(FAILURE);
+
+	if (NOT lderrsw)
+		showcat();		/* display the catalog */
+
+	/* show size if getcat() didn't */
+
+	if ((NOT ldidsiz) AND (NOT lderrsw))
+		showsiz();
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	streset() -- reset the switches after a store or an error
+   =============================================================================
+*/
+
+streset()
+{
+	lstrsw  = FALSE;
+
+	lasgsw  = FALSE;
+	lorchsw = FALSE;
+	lorclsw = FALSE;
+	lpatsw  = FALSE;
+	lscrsw  = FALSE;
+	lseqsw  = FALSE;
+	ltunsw  = FALSE;
+	lwavsw  = FALSE;
+
+	ldswin(9);
+}
+
+/*
+   =============================================================================
+	fcreset() -- reset the switches after a fetch or an error
+   =============================================================================
+*/
+
+fcreset()
+{
+	lselsw = FALSE;
+
+	ldswin(6);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	getslot() -- find a free file catalog slot
+
+		returns -1 on error,  slot # 0..FCMAX-1 if a slot was found
+   =============================================================================
+*/
+
+short
+getslot()
+{
+	register short i;
+
+	for (i = 0; i < FCMAX; i++)
+		if (NOT ocslot(i))
+			return(i);
+
+	return(-1);
+}
+
+/*
+   =============================================================================
+	slotnam() -- return the file name for a slot
+   =============================================================================
+*/
+
+char *
+slotnam(slot, kind)
+unsigned slot, kind;
+{
+	static	char thename[13];
+
+	sprintf(thename, "M7SLOT%02.2u.%-3.3s",
+		slot, ftypes[kind - 1][0]);
+
+	return(thename);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrtfile() -- write a file on the disk
+   =============================================================================
+*/
+
+short
+wrtfile(kind)
+short kind;
+{
+	register short slot, flspace, tkind;
+	char sizetmp[4];
+
+	slot = getslot();
+
+	if (-1 EQ slot) {
+
+		noslot(kind);
+		streset();
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+
+	switch (kind) {
+
+	case FT_ASG:
+
+		if (wrt_asg(slot))
+			return(FAILURE);
+		else
+			break;
+	
+	case FT_ORL:		/* lo orch write */
+
+		if (wrt_orc(slot, 0))
+			return(FAILURE);
+		else
+			break;
+	
+	case FT_ORH:		/* hi orch write */
+
+		if (wrt_orc(slot, 1))
+			return(FAILURE);
+		else
+			break;
+
+	case FT_PAT:
+
+		if (wrt_pat(slot))
+			return(FAILURE);
+		else
+			break;
+
+	case FT_SCR:
+
+		if (wrt_scr(slot))
+			return(FAILURE);
+		else
+			break;
+
+	case FT_SEQ:
+
+		if (wrt_seq(slot))
+			return(FAILURE);
+		else
+			break;
+
+/* 
+
+*/
+	case FT_TUN:
+
+		if (wrt_tun(slot))
+			return(FAILURE);
+		else
+			break;
+	
+	case FT_WAV:
+
+		if (wrt_wav(slot))
+			return(FAILURE);
+		else
+			break;
+	
+	default:
+
+		sprintf(ldmsg1, " kind=%d", kind);
+
+		ldermsg("bad wrtfile argument:",
+			ldmsg1, (char *)NULL, LD_EMCF, LD_EMCB);
+
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+
+	/* update the file catalog */
+
+	if ((kind EQ FT_ORL) OR (kind EQ FT_ORH))
+		tkind = FT_ORC;
+	else
+		tkind = kind;
+
+	flspace = spacerq(kind);
+
+	sprintf(sizetmp, "%03.3d", flspace);	/* size */
+	memcpy(filecat[slot].fcsize, sizetmp, 3);
+
+	memcpy(filecat[slot].fcname, ldfile, 8);		/* name */
+	memcpy(filecat[slot].fcextn, ftypes[tkind - 1][0], 3);	/* type */
+	memcpy(filecat[slot].fccmnt, ldcmnt, 37);		/* comment */
+
+	savefc(kind);
+
+	filecat[slot].fceol[0] = A_CR;
+	filecat[slot].fceol[1] = A_LF;
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	writem() -- write selected files
+   =============================================================================
+*/
+
+short
+writem()
+{
+	if (lasgsw)			/* Assignments */
+		if (wrtfile(FT_ASG))
+			return(FAILURE);
+
+	if (lorchsw)			/* Hi Orch */
+		if (wrtfile(FT_ORH))
+			return(FAILURE);
+
+	if (lorclsw)			/* Lo Orch */
+		if (wrtfile(FT_ORL))
+			return(FAILURE);
+
+	if (lpatsw)			/* Patches */
+		if (wrtfile(FT_PAT))
+			return(FAILURE);
+
+	if (lscrsw)			/* Score */
+		if (wrtfile(FT_SCR))
+			return(FAILURE);
+
+	if (lseqsw)			/* Sequences */
+		if (wrtfile(FT_SEQ))
+			return(FAILURE);
+
+	if (ltunsw)			/* Tunings */
+		if (wrtfile(FT_TUN))
+			return(FAILURE);
+
+	if (lwavsw)			/* Waveshapes */
+		if (wrtfile(FT_WAV))
+			return(FAILURE);
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	storit() -- store selected files on disk
+   =============================================================================
+*/
+
+short
+storit()
+{
+	register int weneed, i, slotnd, slothv;
+	int	rc, drem;
+
+	/* make sure the file is named */
+
+	if (0 EQ memcmp(ldfile, "        ", 8)) {
+
+		ldermsg("File must be named",
+			ld_em1, ld_em2, LD_EMCF, LD_EMCB);
+
+		streset();
+		return(FAILURE);
+	}
+
+	/* make sure something was selected */
+
+	if (ckstor()) {
+
+		ldermsg("No file type selected",
+			ld_em1, ld_em2, LD_EMCF, LD_EMCB);
+
+		streset();
+		return(FAILURE);
+	}
+
+	if (NOT lderrsw)
+		ldbusy("       Storing files");
+
+	if (getcat(0)) {		/* get the catalog */
+
+		streset();
+		return(FAILURE);
+	}
+
+	/* find out how much space we need to store everything */
+
+	drem   = dspace(1);
+	slotnd = 0;
+	weneed = 0;
+
+/* 
+
+*/
+	if (lasgsw) {
+
+		weneed += spacerq(FT_ASG);
+		++slotnd;
+	}
+
+	if (lorchsw) {
+
+		weneed += spacerq(FT_ORH);
+		++slotnd;
+	}
+
+	if (lorclsw) {
+
+		weneed += spacerq(FT_ORL);
+		++slotnd;
+	}
+
+	if (lpatsw) {
+
+		weneed += spacerq(FT_PAT);
+		++slotnd;
+	}
+
+	if (lscrsw) {
+
+		weneed += spacerq(FT_SCR);
+		++slotnd;
+	}
+
+	if (lseqsw) {
+
+		weneed += spacerq(FT_SEQ);
+		++slotnd;
+	}
+
+	if (ltunsw) {
+
+		weneed += spacerq(FT_TUN);
+		++slotnd;
+	}
+
+	if (lwavsw) {
+
+		weneed += spacerq(FT_WAV);
+		++slotnd;
+	}
+
+	if (drem < weneed) {
+
+		nospace(0, weneed, drem);
+		streset();
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+
+	/* see if we have enough catalog space */
+
+	slothv = 0;
+
+	for (i = 0; i < FCMAX; i++)
+		if (NOT ocslot(i))
+			++slothv;
+
+	if (slothv < slotnd) {
+
+		nospace(1, slothv, slotnd);
+		streset();
+		return(FAILURE);
+	}
+
+	/* make sure the name is unique */
+
+	if (rc = ckdups()) {
+
+		sprintf(ldmsg1, "Duplicate %s", ftypes[rc - 1][2]);
+		ldermsg(ldmsg1, ld_em1, ld_em2, LD_EMCF, LD_EMCB);
+
+		streset();
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+
+	/* write the files */
+
+	rc = writem();
+
+	if (NOT rc)
+		ldbusy("       Writing catalog");
+
+	if (putcat()) {
+
+		_clsvol();
+		streset();
+		showcat();
+		return(FAILURE);
+	}
+
+	_clsvol();
+	streset();
+	showcat();
+
+	if (rc)
+		return(FAILURE);
+
+	showsiz();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	advlcur() -- advance the librarian display text cursor
+   =============================================================================
+*/
+
+advlcur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol + 1;
+
+	if (newcol LE cfetp->frcol)
+		itcpos(stcrow, newcol);
+
+	cxval = stccol * 8;
+	cyval = stcrow * 14;
+}
+
+/*
+   =============================================================================
+	bsplcur() -- backspace the librarian display text cursor
+   =============================================================================
+*/
+
+bsplcur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol - 1;
+
+	if (newcol GE cfetp->flcol)
+		itcpos(stcrow, newcol);
+
+	cxval = stccol * 8;
+	cyval = stcrow * 14;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldswin() -- display a window
+   =============================================================================
+*/
+
+ldswin(n)
+register short n;
+{
+	register short cx, cy;
+
+	if (ndisp NE 0)
+		return;
+
+	if ((n EQ 10) AND (lmwtype EQ 1))
+		cx = exp_c(TTBACK);	/* use black for the typewriter */
+	else
+		cx = exp_c(ldbox[n][5]);   /* expand the background color */
+
+	/* first, fill the box with the background color */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(librob, 128, ldbox[n][0], ldbox[n][1], ldbox[n][2],
+		ldbox[n][3], cx);
+
+	/* put in the box label */
+
+	tsplot4(librob, 64, ldbox[n][4], ldbox[n][6], ldbox[n][7],
+		ldbxlb0[n], 14);
+
+/* 
+
+*/
+	switch (n) {	/* final text - overlays above stuff */
+
+	case 0:		/* titles */
+
+		point = ldpoint;
+
+		lseg(  8, 13,  79, 13, LUNDRLN);
+		lseg( 88, 13,  95, 13, LUNDRLN);
+		lseg(104, 13, 167, 13, LUNDRLN);
+		lseg(176, 13, 471, 13, LUNDRLN);
+		lseg(480, 13, 504, 13, LUNDRLN);
+
+		return;
+
+	case 1:		/* index area */
+
+		return;
+
+	case 3:		/* current file name */
+
+		tsplot4(librob, 64, ldbox[n][4], ldbox[n][6], ldbox[n][7],
+			ldfile, 14);
+		return;
+
+	case 5:		/* current comment field */
+
+		tsplot4(librob, 64, ldbox[n][4], ldbox[n][6], ldbox[n][7],
+			ldcmnt, 14);
+		return;
+
+/* 
+
+*/
+
+	case 7:		/* "Replace" / "Append" */
+
+		if (lrasw)
+			cy = exp_c(LD_SELC);
+		else
+			cy = ldbox[n][4];
+
+		tsplot4(librob, 64, cy, ldbox[n][6], ldbox[n][7],
+			"Content", 14);
+
+		return;
+
+	case 8:		/* "Hi Orch" / "Lo Orch" */
+
+		if (lselsw) {
+
+			ldkind = ftkind(ldslot);
+
+			if ((ldkind EQ FT_ORC) OR
+			    (ldkind EQ FT_ORL) OR
+			    (ldkind EQ FT_ORH))
+				cy = exp_c(LD_SELC);
+			else
+				cy = ldbox[n][4];
+
+		} else {
+
+			cy = ldbox[n][4];
+		}
+
+		tsplot4(librob, 64, cy, ldbox[n][6], ldbox[n][7],
+			(lorchl ? "Hi Orch" : "Lo Orch"), 14);
+
+		return;
+/* 
+
+*/
+	case 9:		/* "Store" status */
+
+		cy = exp_c(lstrsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 22, 10, "Store", 14);
+
+		cy = exp_c(lscrsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 22, 17, "Score", 14);
+
+		cy = exp_c(lorchsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 22, 24, "Hi Orch", 14);
+
+
+		cy = exp_c(lwavsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 23, 10, "Waves", 14);
+
+		cy = exp_c(lpatsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 23, 17, "Patch", 14);
+
+		cy = exp_c(lorclsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 23, 24, "Lo Orch", 14);
+
+
+		cy = exp_c(lasgsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 24, 10, "Assgn", 14);
+
+		cy = exp_c(lseqsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 24, 17, "Seqnc", 14);
+
+		cy = exp_c(ltunsw ? LD_SELC : ldbox[n][4]);
+		tsplot4(librob, 64, cy, 24, 24, "Tunings", 14);
+
+		return;
+
+	case 10:	/* typewriter / error messages */
+
+		tsplot4(librob, 64, ldbox[n][4], 22, ldbox[n][7], lmln22, 14);
+		tsplot4(librob, 64, ldbox[n][4], 23, ldbox[n][7], lmln23, 14);
+		tsplot4(librob, 64, ldbox[n][4], 24, ldbox[n][7], lmln24, 14);
+
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	lwins() -- display all librarian windows
+   =============================================================================
+*/
+
+lwins()
+{
+	register short i;
+
+	for (i = 0; i < 11; i++)
+		ldswin(i);
+}
+
+/*
+   =============================================================================
+	ldpoint() -- plot a point for the lseg function
+   =============================================================================
+*/
+
+ldpoint(x, y, pen)
+short x, y, pen;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputp(ldoct, x, y, exp_c(pen));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ldbord() -- draw the border for the librarian display
+   =============================================================================
+*/
+
+ldbord()
+{
+	point = ldpoint;
+
+	lseg(  0,   0, 511,   0, LBORD);	/* outer border */
+	lseg(511,   0, 511, 349, LBORD);
+	lseg(511, 349,   0, 349, LBORD);
+	lseg(  0, 349,   0,   0, LBORD);
+
+	lseg(  0, 293, 511, 293, LBORD);	/* windows - H lines */
+	lseg(511, 308,   0, 308, LBORD);
+
+	lseg( 79, 293,  79, 308, LBORD);	/* windows - V lines */
+	lseg(144, 293, 144, 308, LBORD);
+	lseg(215, 293, 215, 308, LBORD);
+	lseg( 71, 308,  71, 349, LBORD);
+	lseg(256, 308, 256, 349, LBORD);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	lwclr() -- clear the message window text strings
+   =============================================================================
+*/
+
+lmwclr()
+{
+	lmwtype = 0;
+	submenu = FALSE;
+
+	lmln22 = "";
+	lmln23 = "";
+	lmln24 = "";
+}
+
+/*
+   =============================================================================
+	lmwvtyp() -- load the typewriter into the message window text strings
+   =============================================================================
+*/
+
+lmwvtyp()
+{
+	lmwtype = 1;
+	submenu = TRUE;
+
+	lmln22 = vtlin1;
+	lmln23 = vtlin2;
+	lmln24 = vtlin3;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	libdsp() -- put up the librarian display
+   =============================================================================
+*/
+
+libdsp()
+{
+	librob = &v_score[0];		/* setup display object pointer */
+	obj0   = &v_curs0[0];		/* setup cursor object pointer */
+	obj2   = &v_tcur[0];		/* setup typewriter cursor pointer */
+	ldoct  = &v_obtab[LIBROBJ];	/* setup object control table pointer */
+
+	lselsw  = FALSE;
+	ldelsw  = FALSE;
+	lstrsw  = FALSE;
+
+	lasgsw	= FALSE;
+	lorchsw = FALSE;
+	lorclsw = FALSE;
+	lpatsw  = FALSE;
+	lscrsw  = FALSE;
+	lseqsw  = FALSE;
+	ltunsw  = FALSE;
+	lwavsw  = FALSE;
+
+	lderrsw = FALSE;
+	ltagged = FALSE;
+	lksel   = -1;
+/* 
+
+*/
+	clrcat();		/* void the catalog */
+	catin = FALSE;
+
+	lmwclr();		/* clear the message window text strings */
+
+	dswap();		/* initialize display */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	memsetw(librob, 0, 32767);
+	memsetw(librob+32767L, 0, 12033);
+
+	SetObj(LIBROBJ, 0, 0, librob, 512, 350,     0,     0,  LIBRFL, -1);
+	SetObj(      0, 0, 1,   obj0,  16,  16, LCURX, LCURY, OBFL_00, -1);
+	SetObj( TTCURS, 0, 1,   obj2,  16,  16,     0,     0,  TTCCFL, -1);
+
+	arcurs(TTCURC);		/* setup arrow cursor object */
+	itcini(TTCURC);		/* setup text cursor object */
+	ttcini(TTCURC);		/* setup typewriter cursor object */
+
+	ldbord();		/* draw the border */
+	lwins();
+
+	vsndpal(lbrpal);	/* setup the palette */
+
+	SetPri(LIBROBJ, LIBRPRI);
+	SetPri(0, GCPRI);	/* display the graphic cursor */
+
+	setgc(LCURX, LCURY);
+
+	chtime = thcwval;	/* turn it into a text cursor */
+	cvtime = tvcwval;
+	cmtype = CT_TEXT;
+	itcpos(cyval / 14, cxval >> 3);
+}
Index: ram/librw.c
===================================================================
--- ram/librw.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/librw.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1106 @@
+/*
+   =============================================================================
+	librw.c -- MIDAS librarian read / write functions
+	Version 22 -- 1988-11-18 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "memory.h"
+#include "stdio.h"
+#include "errno.h"
+
+#include "ascii.h"
+#include "charset.h"
+#include "fpu.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "fields.h"
+#include "patch.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+#include "instdsp.h"
+#include "libdsp.h"
+#include "wsdsp.h"
+
+/* 
+
+*/
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	char	*slotnam();
+
+extern	long	chksum();
+
+extern	short	ldslot, lderrsw, lrasw;
+extern	short	tunlib[][128];
+
+extern	long	lcsum, schksum, sntlreq;
+
+extern	char	tunname[][32];
+extern	char	ldfile[9];
+extern	char	ldcmnt[38];
+
+extern	struct	mlibhdr	ldhead;
+extern	struct	asgent	asgtab[];
+extern	struct	wstbl	wslib[];
+extern	struct	instdef	idefs[];
+extern	struct	s_time	stimes[N_SCORES][N_SECTS];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_asg() -- write an assignment on the disk
+   =============================================================================
+*/
+
+short
+wrt_asg(slot)
+short slot;
+{
+	register FILE *fp;
+	register int	i;
+	char cstemp[8];
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_ASG), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the assignments", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_ASG);			/* make header */
+
+	for (i = 0; i < NASGLIB; i++)
+		lcsum += chksum(&asgtab[i + 1], (long)(sizeof (struct asgent)));
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_asg():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	for (i = 0; i < NASGLIB; i++) {
+
+		if (wr_ec(fp, &asgtab[i + 1], (long)(sizeof (struct asgent)))) {
+
+			streset();
+			return(FAILURE);
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_asg() -- read an assignment library from the disk
+   =============================================================================
+*/
+
+short
+get_asg()
+{
+	register FILE *fp;
+	register int	i;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, FT_ASG), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the assignments", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_asg():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+
+	for (i = 0; i < NASGLIB; i++) {
+
+		if (rd_ec(fp, &asgtab[i + 1], (long)(sizeof (struct asgent)))) {
+
+			clrlsel();
+			return(FAILURE);
+		}
+	}
+
+	clrlsel();
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_orc() -- write an orchestra on the disk
+   =============================================================================
+*/
+
+short
+wrt_orc(slot, lorh)
+short slot, lorh;
+{
+	register FILE *fp;
+	register int	i;
+	register struct instdef *ip;
+	char cstemp[8];
+
+	if (lorh)
+		ldbusy("       Writing Hi Orch");
+	else
+		ldbusy("       Writing Lo Orch");
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_ORC), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the orchestra", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_ORC);			/* make header */
+
+	for (i = 0; i < NINORC; i++) {
+
+		ip = &idefs[i + 1 + (lorh ? NINORC : 0)];
+
+		lcsum += chksum(ip, (long)OR_LEN1);
+		lcsum += chksum(ip->idhwvao, (long)OR_LEN2);
+		lcsum += chksum(ip->idhwvbo, (long)OR_LEN2);
+	}
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_orc():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	for (i = 0; i < NINORC; i++) {
+
+		ip = &idefs[i + 1 + (lorh ? NINORC : 0)];
+
+		if (wr_ec(fp, ip, (long)OR_LEN1)) {		/* functions */
+
+			streset();
+			return(FAILURE);
+		}
+
+		if (wr_ec(fp, ip->idhwvao, (long)OR_LEN2)) {	/* WS A */
+
+			streset();
+			return(FAILURE);
+		}
+
+		if (wr_ec(fp, ip->idhwvbo, (long)OR_LEN2)) {	/* WS B */
+
+			streset();
+			return(FAILURE);
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_orc() -- read an orchestra from the disk
+   =============================================================================
+*/
+
+short
+get_orc(lorh, kind)
+short lorh, kind;
+{
+	register FILE *fp;
+	register int	i;
+	register struct instdef *ip;
+
+	if (lorh)
+		ldbusy("       Reading Hi Orch");
+	else
+		ldbusy("       Reading Lo Orch");
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, kind), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the orchestra", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_orc():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+
+	for (i = 0; i < NINORC; i++) {
+
+		ip = &idefs[i + 1 + (lorh ? NINORC : 0)];
+
+		if (rd_ec(fp, ip, (long)OR_LEN1)) {		/* functions */
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		if (rd_ec(fp, ip->idhwvao, (long)OR_LEN2)) {	/* WS A */
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		if (rd_ec(fp, ip->idhwvbo, (long)OR_LEN2)) {	/* WS B */
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		/* unpack offsets (and eventually harmonics) into finals */
+
+		memcpyw(ip->idhwvaf, ip->idhwvao, NUMWPNT);
+		memcpyw(ip->idhwvbf, ip->idhwvbo, NUMWPNT);
+	}
+
+	clrlsel();
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_tun() -- write a tuning library on the disk
+   =============================================================================
+*/
+
+short
+wrt_tun(slot)
+short slot;
+{
+	register FILE *fp;
+	register int	i;
+	char cstemp[8];
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_TUN), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the tunings", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_TUN);			/* make header */
+
+	for (i = 0; i < NTUNSLIB; i++) {
+
+		lcsum += chksum(&tunlib[i + 1], 256L);
+		lcsum += chksum(&tunname[i + 1], 32L);
+	}
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_tun():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	for (i = 0; i < NTUNSLIB; i++) {
+
+		if (wr_ec(fp, &tunlib[i + 1], 256L)) {
+
+			streset();
+			return(FAILURE);
+		}
+
+		if (wr_ec(fp, &tunname[i + 1], 32L)) {
+
+			streset();
+			return(FAILURE);
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_tun() -- read a tuning library from the disk
+   =============================================================================
+*/
+
+short
+get_tun()
+{
+	register FILE *fp;
+	register int	i;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, FT_TUN), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the tunings", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_tun():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+
+	for (i = 0; i < NTUNSLIB; i++) {
+
+		if (rd_ec(fp, &tunlib[i + 1], 256L)) {
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		if (rd_ec(fp, &tunname[i + 1], 32L)) {
+
+			clrlsel();
+			return(FAILURE);
+		}
+	}
+
+	clrlsel();
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_pat() -- write a patch file on the disk
+   =============================================================================
+*/
+
+short
+wrt_pat(slot)
+short slot;
+{
+	register FILE *fp;
+	char cstemp[8];
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_PAT), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the patches", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_PAT);			/* make header */
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_pat():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {		/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	if (ptwrite(fp)) {				/* patches */
+
+		streset();
+		return(FAILURE);
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_pat() -- read a patch file from the disk
+   =============================================================================
+*/
+
+short
+get_pat()
+{
+	register FILE *fp;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, FT_PAT), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the patches", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_pat():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+	if (lrasw EQ 0)		/* clear all patches if in replace mode */
+		initpt();
+
+	if (ptread(fp)) {
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	clrlsel();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_scr() -- write a score file on the disk
+   =============================================================================
+*/
+
+short
+wrt_scr(slot)
+short slot;
+{
+	register FILE *fp;
+	register int	i;
+	long tnb;
+	char cstemp[8];
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_SCR), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the scores", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_SCR);			/* make header */
+
+	lcsum += sntlreq;
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_scr():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {		/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	if (wr_ec(fp, &sntlreq, 4L)) {		/* total longs required */
+
+		streset();
+		return(FAILURE);
+	}
+
+	for (i = 0; i < N_SCORES; i++) {	/* scores */
+
+		if (scwrite(i, fp)) {
+
+			streset();
+			return(FAILURE);
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_scr() -- read a score file from the disk
+   =============================================================================
+*/
+
+short
+get_scr()
+{
+	register FILE *fp;
+	register int	i;
+	long tnl;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, FT_SCR), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the scores", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_scr():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+
+	if (rd_ec(fp, &tnl, 4L)) {	/* longs required */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+	if (lrasw EQ 0)		/* clear all scores if in replace mode */
+		scinit();
+
+	for (i = 0; i < N_SCORES; i++) {	/* read scores */
+
+		if (scread(i, fp)) {
+
+			clrlsel();
+			return(FAILURE);
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+
+	p_bak = p_cur = p_ctr = p_fwd = scp = E_NULL;
+	t_cur = t_ctr = 0L;
+	t_bak = t_cur - TO_BAK;
+	t_fwd = t_cur + TO_FWD;
+
+	selscor(0);
+
+	clrlsel();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_seq() -- write a sequence file on the disk
+   =============================================================================
+*/
+
+short
+wrt_seq(slot)
+short slot;
+{
+	register FILE *fp;
+	char cstemp[8];
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_SEQ), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the sequences", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_SEQ);			/* make header */
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_seq():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {		/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	if (sqwrite(fp)) {				/* sequences */
+
+		streset();
+		return(FAILURE);
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_seq() -- read a sequence file from the disk
+   =============================================================================
+*/
+
+short
+get_seq()
+{
+	register FILE *fp;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, FT_SEQ), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the sequences", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_seq():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+	initsq();
+
+	if (sqread(fp)) {
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	clrlsel();
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wrt_wav() -- write a waveshape library on the disk
+   =============================================================================
+*/
+
+short
+wrt_wav(slot)
+short slot;
+{
+	register FILE *fp;
+	register int	i;
+	char cstemp[8];
+	register struct wstbl *wp;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(slot, FT_WAV), "w");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't create a file",
+			" for the waveshapes", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		streset();
+		return(FAILURE);
+	}
+
+	makelh(FT_WAV);			/* make header */
+
+	for (i = 0; i < NUMWAVS; i++) {
+
+		wp = &wslib[i];
+
+		lcsum += chksum(wp->offset, (long)(NUMWPNT * 2));
+		lcsum += chksum(wp->harmon, (long)(NUMHARM * 2));
+	}
+
+	sprintf(cstemp, "%08.8lX", lcsum);
+	memcpy(ldhead.l_csum, cstemp, 8);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("wrt_wav():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+/* 
+
+*/
+	if (wr_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		streset();
+		return(FAILURE);
+	}
+
+	for (i = 0; i < NUMWAVS; i++) {
+
+		wp = &wslib[i];
+
+		if (wr_ec(fp, wp->offset, (long)(NUMWPNT * 2))) {
+
+			streset();
+			return(FAILURE);
+		}
+
+		if (wr_ec(fp, wp->harmon, (long)(NUMHARM * 2))) {
+
+			streset();
+			return(FAILURE);
+		}
+	}
+
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	get_wav() -- read a waveshape library from the disk
+   =============================================================================
+*/
+
+short
+get_wav()
+{
+	register FILE *fp;
+	register int	i;
+	register struct wstbl *wp;
+
+	preio();	/* kill LCD backlight */
+
+	fp = fopenb(slotnam(ldslot, FT_WAV), "r");
+
+	if ((FILE *)NULL EQ fp) {
+
+		ldermsg("Couldn't open the file",
+			" for the waveshapes", (char *)NULL,
+			LD_EMCF, LD_EMCB);
+
+		postio();		/* restore LCD backlight */
+		clrlsel();
+		return(FAILURE);
+	}
+
+	memcpy(ldfile, "        ", 8);
+	memcpy(ldcmnt, "                                     ", 37);
+	ldswin(3);
+	ldswin(5);
+
+/* 
+
+*/
+	if (rd_ec(fp, &ldhead, (long)LH_LEN)) {			/* header */
+
+		clrlsel();
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("get_wav():  hdr=[%-.56s]\n", &ldhead);
+#endif
+
+
+	for (i = 0; i < NUMWAVS; i++) {
+
+		wp = &wslib[i];
+
+		if (rd_ec(fp, wp->offset, (long)(NUMWPNT * 2))) {
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		if (rd_ec(fp, wp->harmon, (long)(NUMHARM * 2))) {
+
+			clrlsel();
+			return(FAILURE);
+		}
+
+		/* unpack offsets (and eventually harmonics) into finals */
+
+		memcpyw(wp->final, wp->offset, NUMWPNT);
+	}
+
+	clrlsel();
+	fclose(fp);
+	postio();		/* restore LCD backlight */
+	return(SUCCESS);
+}
+
Index: ram/localkb.c
===================================================================
--- ram/localkb.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/localkb.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,637 @@
+/*
+   =============================================================================
+	localkb.c -- local keyboard processing
+	Version 39 -- 1988-11-28 -- D.N. Lynx Crowe
+
+	List with the pr -e4 option to expand tabs to 4 spaces instead of 8.
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "glcdefs.h"
+#include "glcfns.h"
+#include "hwdefs.h"
+#include "lcdline.h"
+#include "vsdd.h"
+#include "panel.h"
+#include "smdefs.h"
+#include "slice.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+
+#define	LCL_PRT		3	/* 1-origin local keyboard port number */
+
+/* 
+
+*/
+
+extern	short	(*point)();
+
+extern	short	ancmsw;
+extern	short	angroup;
+extern	short	asmode;
+extern	short	astat;
+extern	short	aval;
+extern	short	ctrsw;
+extern	short	curasg;
+extern	short	curtun;
+extern	short	curvce;
+extern	short	editsw;
+extern	short	gomode;
+extern	short	gtmsel;
+extern	short	insmode;
+extern	short	ismode;
+extern	short	ldpass;
+extern	short	lksel;
+extern	short	lstbgnc;
+extern	short	lstendc;
+extern	short	lstflag;
+extern	short	oldpk;
+extern	short	pkctrl;
+extern	short	recsw;
+extern	short	stepenb;
+extern	short	stepint;
+extern	short	stepwgt;
+
+extern	char	keystat[];
+extern	char	trgtab[];
+
+extern	short	grpmode[];
+extern	short	grpstat[];
+extern	short	grptmap[];
+extern	short	ldmap[];
+extern	short	prstab[];
+extern	short	tuntab[];
+extern	short	veltab[];
+extern	short	vce2grp[];
+extern	short	vce2trg[];
+
+extern	short	grp2prt[][2];
+extern	short	ldbox[][8];
+extern	short	varmode[][16];
+
+extern	struct	gdsel	*gdstbc[];
+
+extern	struct	n_entry	*lstbgns[NLSTENTS];
+extern	struct	n_entry	*lstends[NLSTENTS];
+
+/* 
+
+*/
+
+short	lclkmap[24] = {		/* local key to MIDI key number map table */
+
+	    0,    1,    2,      3,    4,    5,    6,	/*  1..7 */
+	    7,    8,    9,     10,   11,   12,   13,	/*  8..14 */
+	  114,  115,  116,    117,  118,  119,  120,	/* 15..21 */
+	  121,  122,  123				/* 22..24 */
+};
+
+short	panlkey[24] = {		/* default tunings, in cents, for local keys */
+
+	       560,  960,  1360, 1760, 2160,  2560, 2960, 3360,
+	3760, 4160, 4560,  4960, 5360, 5760,  6160, 6560, 6960,
+	7360, 7760, 8160,  8560, 8960, 9360,  9760
+};
+
+/* 
+
+*/
+
+short	stepfrm[4][17] = {	/* step mode frame counts */
+
+	/*  1    1    1    1    1    1		*/
+	/* --   --   --    -    -    -		*/
+	/* 64   32   16    8    4    2    1	*/
+
+	{   3,   4,  10,  22,  46,  94, 190,	/* legato - normal */
+		 7,  16,  34,  70, 142, 286,	/* legato - dotted */
+		 3,   6,  14,  30},		/* legato - triplets */
+
+	{   2,   4,   8,  16,  32,  64, 128,	/* normal - normal */
+		 6,  12,  24,  48,  96, 192,	/* normal - dotted */
+		 3,   5,  10,  20},		/* normal - triplets */
+
+	{   2,   3,   4,   6,  10,  16,  24,	/* stacato - normal */
+		 4,   5,   8,  12,  20,  30,	/* stacato - dotted */
+		 3,   4,   5,   8},		/* stacato - triplets */
+
+	{   3,   6,  12,  24,  48,  96, 192,	/* interval - normal */
+		 9,  18,  36,  72, 144, 288,	/* interval - dotted */
+		 4,   8,  16,  32}		/* interval - triplets */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setleds() -- set LEDs according to pkctrl, etc.
+   =============================================================================
+*/
+
+setleds()
+{
+	register short i;
+
+	for (i = 0; i < 24; i++)		/* turn off all LEDs */
+		io_leds = 0x0080 | i;
+
+	switch (pkctrl) {
+
+	default:
+	case PK_PFRM:		/* performance */
+	case PK_INST:		/* instrument */
+	case PK_LOAD:		/* load */
+
+		return;
+
+	case PK_NOTE:		/* note entry */
+
+		if (stepenb)
+			io_leds = 0x01;
+
+		io_leds = 6 - stepwgt;
+		io_leds = 7 + stepint;
+		return;
+
+	case PK_ASGN:		/* assignment table */
+
+		if (curasg EQ 0)
+			return;
+
+		io_leds = (curasg - 1) % 20;	/* indicate current assignment */
+		return;
+/* 
+
+*/
+	case PK_GOTO:		/* go to */
+
+		if (gomode EQ GO_SECT) {	/* indicate active sections */
+
+			for (i = 0; i < 20; i++)
+				if (E_NULL NE seclist[curscor][i])
+					io_leds = i;
+
+		} else {			/* indicate active scores */
+
+			for (i = 0; i < 20; i++)
+				if (E_NULL NE scores[i])
+					io_leds = i;
+		}
+
+		return;
+
+	case PK_LIBR:
+
+		for (i = 0; i < 20; i++)
+			if (E_NULL NE scores[i])
+				io_leds = i;
+
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	localkb() -- local keyboard processing
+   =============================================================================
+*/
+
+localkb(sig)
+short sig;
+{
+	register short i, trg, lclkey, key, vel;
+	register struct s_entry *ep;
+	short val, disptag;
+
+	key = sig - 1;
+
+	switch (pkctrl) {
+
+	case PK_PFRM:		/* performance */
+
+		lclkey = lclkmap[key];
+		trg = ((LCL_PRT - 1) << 11) + lclkey;
+
+		if (astat) {		/* key down */
+
+			prstab[trg] = SM_SCALE(aval);
+
+			if (keystat[key] EQ 0) {	/* initial key closure */
+
+				trgtab[trg] |= M_KSTATE;
+				veltab[trg]  = vel = SM_SCALE(64);
+				keystat[key] = 1;
+
+				stmproc(trg);	/* process as a patch stimulus */
+
+				if (editsw) {		/* edit mode */
+
+					execkey(trg, tuntab[lclkey], curvce, 0);
+
+				} else {		/* normal mode */
+
+					for (i = 0; i < 12; i++)
+						if ((grp2prt[i][0] EQ LCL_PRT) AND
+						    (grp2prt[i][1] EQ 1)) {
+
+							asgvce(i, LCL_PRT - 1, 0, lclkey, vel);
+							ne_bgn(i, lclkey, vel);
+						}
+				}
+/* 
+
+*/
+			} else {	/* pressure change */
+
+				val = SM_SCALE(aval);
+
+				for (i = 0; i < 12; i++) {
+
+					if ((grp2prt[i][0] EQ LCL_PRT) AND
+					    (grp2prt[i][1] EQ 1)) {
+
+						if (newsv(i, SM_KPRS, val)) {
+
+							if (recsw AND grpstat[i] AND
+							    (2 EQ (ancmsw ? varmode[5][i] : grpmode[i]))) {
+
+								if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+									ep->e_time = t_cur;
+									ep->e_type = EV_ANVL;
+									ep->e_data1 = 0x0050 | i;
+									ep->e_dn = (struct s_entry *)((long)val << 16);
+									p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+									ctrsw = TRUE;
+									se_disp(ep, D_FWD, gdstbc, 1);
+									ctrsw = FALSE;
+								}
+
+							} else if ((angroup - 1) EQ i) {
+
+								dsanval(5);
+							}
+						}
+					}
+				}
+			}
+/* 
+
+*/
+		} else {		/* key release */
+
+			keystat[key] = 0;
+			trgtab[trg] &= ~M_KSTATE;
+			prstab[trg] = 0;
+
+			if (NOT trgtab[trg]) {
+
+				for (i = 0; i < 12; i++) {
+
+					if (vce2trg[i] EQ trg) {
+
+						vce2trg[i] = -1;
+						procpfl(trg);
+					}
+
+					if ((grp2prt[i][0] EQ LCL_PRT) AND
+					    (grp2prt[i][1] EQ 1))
+						ne_end(trg, i);
+				}
+
+				stmproc(0x8000 | trg);	/* process as a patch stimulus */
+			}
+		}
+
+		return;
+
+/* 
+
+*/
+	case PK_NOTE:		/* note entry - interval and weight selection */
+
+		if (astat) {		/* key down */
+
+			if (keystat[key] EQ 0) {	/* closure */
+
+				keystat[key] = 1;
+
+				if (key EQ 0) {		/* delete last entry */
+
+					disptag = FALSE;
+
+					while (lstendc-- > 0) {	/* note ends */
+
+						ep = lstends[lstendc];
+						lstends[lstendc] = (struct n_entry *)NULL;
+
+						if ((struct n_entry *)NULL EQ ep)
+							continue;
+
+						if (ep EQ p_bak)
+							p_bak = p_bak->e_bak;
+
+						if (ep EQ p_ctr)
+							p_ctr = p_ctr->e_bak;
+
+						if (ep EQ p_cur)
+							p_cur = p_cur->e_bak;
+
+						if (ep EQ p_fwd)
+							p_fwd = p_fwd->e_bak;
+
+						e_del(e_rmv(ep));
+						disptag = TRUE;
+					}
+
+					lstendc = 0;
+/* 
+
+*/
+					while (lstbgnc-- > 0) {	/* note begins */
+
+						ep = lstbgns[lstbgnc];
+						lstbgns[lstbgnc] = (struct n_entry *)NULL;
+
+						if ((struct n_entry *)NULL EQ ep)
+							continue;
+
+						if (ep EQ p_bak)
+							p_bak = p_bak->e_bak;
+
+						if (ep EQ p_ctr)
+							p_ctr = p_ctr->e_bak;
+
+						if (ep EQ p_cur)
+							p_cur = p_cur->e_bak;
+
+						if (ep EQ p_fwd)
+							p_fwd = p_fwd->e_bak;
+
+						e_del(e_rmv(ep));
+						disptag = TRUE;
+					}
+
+					lstbgnc = 0;
+					lstflag = FALSE;
+
+					if (disptag) {
+
+						if ((fc_val - stepfrm[3][stepint]) GE 0L)
+							fc_val -= stepfrm[3][stepint];
+
+						sc_refr(fc_val);
+					}
+
+				} else if (key EQ 1) {	/* enable step */
+
+					stepenb = NOT stepenb;
+					setleds();
+
+/* 
+
+*/
+				} else if (key EQ 2) {	/* insert bar */
+
+					if (recsw) {
+
+						if (E_NULL NE (ep = e_alc(E_SIZE1))) {
+
+							ep->e_type = EV_BAR;
+							ep->e_time = t_cur;
+							p_cur = e_ins(ep, ep_adj(p_cur, 1, t_cur)->e_bak)->e_fwd;
+							sc_refr(fc_val);
+						}
+					}
+
+				} else if (key EQ 3) {	/* insert a rest */
+
+					if ((fc_val + stepfrm[3][stepint]) < 0x00FFFFFEL)
+						fc_val += stepfrm[3][stepint];
+
+				} else if ((key GE 4) AND (key LE 6)) {
+
+					stepwgt = 6 - key;	/* select weight */
+					setleds();
+
+				} else if ((key GE 7) AND (key LE 23)) {
+
+					stepint = key - 7;	/* select interval */
+					setleds();
+				}
+			}
+
+		} else {	/* key up */
+
+			keystat[key] = 0;
+		}
+
+		return;
+/* 
+
+*/
+
+	case PK_INST:		/* instrument selection */
+
+		if (astat) {
+
+			if (keystat[key] EQ 0) {
+
+				keystat[key] = 1;
+
+				if (key GE 20)
+					return;
+
+				if (ismode EQ IS_LORC)
+					selins(key + 1);
+				else
+					selins(key + 21);
+			}
+
+		} else {
+
+			keystat[key] = 0;
+		}
+
+		return;
+
+	case PK_ASGN:		/* assignment table selection */
+
+		if (astat) {
+
+			if (keystat[key] EQ 0) {
+
+				keystat[key] = 1;
+
+				if ((asmode EQ 5) AND (key GE 19))
+					return;
+				else if (key GE 20)
+					return;
+
+				selasg(key + 1 + ((asmode - 1) * 20));
+			}
+
+		} else {
+
+			keystat[key] = 0;
+		}
+
+		return;
+/* 
+
+*/
+	case PK_GOTO:		/* go to */
+
+		if (astat) {
+
+			if (keystat[key] EQ 0) {
+
+				keystat[key] = 1;
+
+				if (key GE 20)		/* limit key range */
+					return;
+
+				if (gomode EQ GO_SECT) {	/* section */
+
+					if (E_NULL NE (ep = seclist[curscor][key])) {
+
+						if (insmode) {
+
+							icancel();
+							dsimode();
+						}
+
+						sc_goto(fc_val = ep->e_time);
+						pkctrl = oldpk;
+						gomode = GO_NULL;
+						GLCcurs(G_ON);
+						GLCtext(0, 31, "Go To");
+						point = GLCplot;
+						lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+						GLCcurs(G_OFF);
+						setleds();
+						return;
+					}
+/* 
+
+*/
+				} else {			/* score */
+
+					if (E_NULL NE scores[key]) {
+
+						if (insmode) {
+
+							icancel();
+							dsimode();
+						}
+
+						selscor(key);
+						pkctrl = oldpk;
+						gomode = GO_NULL;
+						GLCcurs(G_ON);
+						GLCtext(0, 31, "Go To");
+						point = GLCplot;
+						lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+						GLCcurs(G_OFF);
+						setleds();
+						return;
+					}
+				}
+			}
+
+		} else {
+
+			keystat[key] = 0;
+		}
+
+		return;
+/* 
+
+*/
+	case PK_LIBR:
+
+		if (astat) {
+
+			if (keystat[key] EQ 0) {
+
+				keystat[key] = 1;
+
+				if ((-1 NE lksel) AND (key < 20)) {
+
+					ldpass = 2;
+
+					for (i = 0; i < N_SCORES; i++)
+						if (ldmap[i] EQ key) {
+
+							ldmap[i] = -1;
+							dpy_scr(ldbox[1][4], i);
+						}
+
+					ldmap[lksel] = key;
+					dpy_scr(ldbox[1][4], lksel);
+					lksel = -1;
+				}
+			}
+
+		} else {
+
+			keystat[key] = 0;
+		}
+
+		return;
+/* 
+
+*/
+	case PK_NGRP:
+
+		if (astat) {
+
+			if (keystat[key] EQ 0) {
+
+				keystat[key] = 1;
+
+				if ((-1 NE gtmsel) AND (key < 12)) {
+
+					for (i = 0; i < 12; i++)
+						if (grptmap[i] EQ key) {
+
+							grptmap[i] = -1;
+							dsgtme(i);
+						}
+
+					grptmap[gtmsel] = key;
+					dsgtmn(gtmsel, FALSE);
+					dsgtme(gtmsel);
+					gtmsel = -1;
+				}
+			}
+
+		} else {
+
+			keystat[key] = 0;
+		}
+
+		return;
+
+	case PK_LOAD:
+
+		if (astat)
+			keystat[key] = 1;
+		else
+			keystat[key] = 0;
+
+		return;
+	}
+}
Index: ram/m7menu.c
===================================================================
--- ram/m7menu.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/m7menu.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,624 @@
+/*
+   =============================================================================
+	m7menu.c -- MIDAS main menu functions
+	Version 42 -- 1989-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "fields.h"
+#include "graphdef.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "menu.h"
+#include "libdsp.h"
+
+#define	DENSITY		1		/* double density */
+
+#define	M_COPY		8		/* "copy" text index in mtexts[] */
+#define	M_FORM		10		/* "format" text index in mtexts[] */
+
+#define	VER_ROW		2		/* version message row */
+#define	VER_COL		51		/* version message column */
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugm7 = 1;
+#endif
+
+extern	char	m7verms[], bfs[], loadedf[][8];
+
+extern	struct	selbox	*csbp, *curboxp;
+
+extern	short	(*point)();
+
+extern	short	nokey(), select(), cxkstd(), cykstd();
+extern	short	cxgen(), cygen(), stdctp2();
+
+extern	unsigned	exp_c();
+
+extern	short	ndisp, runit, curslim, sgcsw, cxval, cyval, stcrow, stccol;
+extern	short	crate1[], defect, dsp_ok;
+
+extern	struct	octent	*mdoct;
+
+extern	unsigned	*menuob, *obj0, vi_ctl;
+
+static char	ml01[61], ml02[61], ml03[61], ml04[61], ml05[61];
+
+short	mdselbx(), mdpoint();
+
+/* 
+
+*/
+
+static char mlc01[] = {1, 0xBA,  58, 0xB1,  1, 0xBB,  -1};
+static char mlc02[] = {1, 0xB6,  29, 0xB1,  1, 0xB7,  28, 0xB1,  1, 0xB4,  -1};
+static char mlc03[] = {1, 0xB6,  29, 0xB1,  1, 0xB2,  28, 0xB1,  1, 0xB4,  -1};
+static char mlc04[] = {1, 0xB6,  29, 0xB1,  1, 0xB5,  28, 0xB1,  1, 0xB4,  -1};
+static char mlc05[] = {1, 0xB9,  58, 0xB1,  1, 0xB8,  -1};
+
+static char	*mtexts[] = {
+
+	/* 0 */		"MIDAS VII      for the Buchla 700      Version",
+	/* 1 */		"Librarian",
+	/* 2 */		"Patch Editor",
+	/* 3 */		"Score editor",
+	/* 4 */		"Sequence Editor",
+	/* 5 */		"Instrument designer",
+	/* 6 */		"Initialize system",
+	/* 7 */		"Waveshape editor",
+	/* 8 */		"Write program to disk",
+	/* 9 */		"Tuning tables",
+	/* 10 */	"Format disk",
+	/* 11 */	"Assignment tables",
+	/* 12 */	"Diagnostics",
+	/* 13 */	"created by Buchla and Associates of Berkeley, California",
+};
+
+/* 
+
+*/
+
+static short mlintab[][4] = {
+
+	{ 18,  26,  18, 322},
+
+	{ 21,  26,  21,  42},
+	{ 21,  54,  21,  84},
+	{ 21,  96,  21, 126},
+	{ 21, 138,  21, 168},
+	{ 21, 180,  21, 210},
+	{ 21, 222,  21, 252},
+	{ 21, 264,  21, 294},
+	{ 21, 306,  21, 322},
+
+	{258,  54, 258,  84},
+	{258,  96, 258, 126},
+	{258, 138, 258, 168},
+	{258, 180, 258, 210},
+	{258, 222, 258, 252},
+	{258, 264, 258, 294},
+
+	{261,  54, 261,  84},
+	{261,  96, 261, 126},
+	{261, 138, 261, 168},
+	{261, 180, 261, 210},
+	{261, 222, 261, 252},
+	{261, 264, 261, 294},
+
+	{490,  26, 490,  42},
+	{490,  54, 490,  84},
+	{490,  96, 490, 126},
+	{490, 138, 490, 168},
+	{490, 180, 490, 210},
+	{490, 222, 490, 252},
+	{490, 264, 490, 294},
+	{490, 306, 490, 322},
+
+	{493,  26, 493, 322},
+
+	{ -1,  -1,  -1,  -1}
+};
+
+/* 
+
+*/
+
+static short	mrowcol[][2] = {
+
+	{ 2,  4},	/* 0 */
+	{ 4,  4},	/* 1 */
+	{ 4, 34},	/* 2 */
+	{ 7,  4},	/* 3 */
+	{ 7, 34},	/* 4 */
+	{10,  4},	/* 5 */
+	{10, 34},	/* 6 */
+	{13,  4},	/* 7 */
+	{13, 34},	/* 8 */
+	{16,  4},	/* 9 */
+	{16, 34},	/* 10 */
+	{19,  4},	/* 11 */
+	{19, 34},	/* 12 */
+	{22,  4}	/* 13 */
+};
+
+struct	selbox	mdboxes[] = {	/* main menu box definitions */
+
+	{ 22,  53, 257,  87,  0, mdselbx},	/* 0 */
+	{262,  53, 489,  87,  1, mdselbx},	/* 1 */
+	{ 22,  95, 257, 129,  2, mdselbx},	/* 2 */
+	{262,  95, 489, 129,  3, mdselbx},	/* 3 */
+	{ 22, 137, 257, 171,  4, mdselbx},	/* 4 */
+	{262, 137, 489, 171,  5, mdselbx},	/* 5 */
+	{ 22, 179, 257, 213,  6, mdselbx},	/* 6 */
+	{262, 179, 489, 213,  7, mdselbx},	/* 7 */
+	{ 22, 221, 257, 255,  8, mdselbx},	/* 8 */
+	{262, 221, 489, 255,  9, mdselbx},	/* 9 */
+	{ 22, 263, 257, 297, 10, mdselbx},	/* 10 */
+	{262, 263, 489, 297, 11, mdselbx},	/* 11 */
+	{  0,   0,   0,   0,  0, FN_NULL}	/* end of table */
+};
+
+/* 
+
+*/
+
+short	menupal[16][3] = {	/* menu display color palette */
+
+	{0, 0, 0},	/* 0 */
+	{2, 1, 0},	/* 1	MCURSOR		cursor color */
+	{0, 0, 0},	/* 2	MBKGRND		background color */
+	{3, 0, 2},	/* 3 */
+	{2, 1, 0},	/* 4	MBUCHLA		"Created by ..." color */
+	{2, 1, 0},	/* 5	MTITLE		title color */
+	{0, 1, 0},	/* 6 */
+	{2, 0, 0},	/* 7	MHILITE		hilite color */
+	{2, 2, 2},	/* 8	MLFILES		file name color */
+	{0, 0, 0},	/* 9 */
+	{1, 1, 2},	/* 10	MLINES		outline color */
+	{2, 3, 3},	/* 11	MBUTTON		button legend color */
+	{3, 1, 1},	/* 12 */
+	{3, 3, 0},	/* 13 */
+	{0, 3, 3},	/* 14 */
+	{0, 0, 3}	/* 15 */
+};
+
+short	blakpal[16][3] = {		/* black palette */
+
+	{0, 0, 0},	/* 0 */
+	{0, 0, 0},	/* 1 */
+	{0, 0, 0},	/* 2 */
+	{0, 0, 0},	/* 3 */
+	{0, 0, 0},	/* 4 */
+	{0, 0, 0},	/* 5 */
+	{0, 0, 0},	/* 6 */
+	{0, 0, 0},	/* 7 */
+	{0, 0, 0},	/* 8 */
+	{0, 0, 0},	/* 9 */
+	{0, 0, 0},	/* 10 */
+	{0, 0, 0},	/* 11 */
+	{0, 0, 0},	/* 12 */
+	{0, 0, 0},	/* 13 */
+	{0, 0, 0},	/* 14 */
+	{0, 0, 0}	/* 15 */
+};
+
+/* 
+
+*/
+
+short	mfrc[][2] = {	/* file name row and column  by load type LT_??? */
+
+	{20,  6},	/* assignments */
+	{11,  6},	/* lo orchestra */
+	{11, 20},	/* hi orchestra */
+	{ 8,  6},	/* score */
+	{17,  6},	/* tunings */
+	{14,  6},	/* waveshapes */
+	{ 5, 36},	/* patches */
+	{ 8, 36}	/* sequences */
+};
+
+/* 
+
+*/
+
+struct curpak m7_flds = {	/* main menu cursor package definitions */
+
+	stdctp2,		/* curtype */
+	nokey,			/* premove */
+	nokey,			/* pstmove */
+	cxkstd,			/* cx_key */
+	cykstd,			/* cy_key */
+	cxgen,			/* cx_upd */
+	cygen,			/* cy_upd */
+	nokey,			/* xy_up */
+	nokey,			/* xy_dn */
+	nokey,			/* x_key */
+	select,			/* e_key */
+	nokey,			/* m_key */
+	nokey,			/* d_key */
+	nokey,			/* not_fld */
+	(struct fet *)NULL,	/* curfet */
+	mdboxes,		/* csbp */
+	crate1,			/* cratex */
+	crate1,			/* cratey */
+	CT_GRAF,		/* cmtype */
+	MCURX,			/* cxval */
+	MCURY			/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dswap() -- clear the screen for display switching
+   =============================================================================
+*/
+
+dswap()
+{
+	register short i;
+
+	vsndpal(blakpal);			/* blackout the palette */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);			/* select bank 0 */
+
+	setipl(VID_DI);				/* disable the un-blanker */
+	vi_ctl = 0;				/* reset un-blank control */
+
+	for (i = 0; i < 16; i++)		/* blank the objects */
+		v_odtab[i][0] |= V_BLA;
+
+	VHinit();				/* init VSDD hardware */
+	VSinit();				/* init VSDD software */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	mlbld() -- build a menu line
+   =============================================================================
+*/
+
+mlbld(where, from)
+char *where, *from;
+{
+	register short i, j;
+	register char c;
+
+	while (-1 NE (i = *from++)) {
+
+		c = *from++;
+
+		for (j = 0; j < i; j++)
+			*where++ = c;
+	}
+
+	*where = '\0';
+}
+
+/*
+   =============================================================================
+	mlpoint() -- draw a point for the MIDAS 700 main menu
+   =============================================================================
+*/
+
+mlpoint(x, y, pen)
+short x, y, pen;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputp(mdoct, x, y, pen);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	mdselbx() -- process a hit in a window for the MIDAS 700 main menu
+   =============================================================================
+*/
+
+short
+mdselbx(n)
+short n;
+{
+	register unsigned mlcv, mbcv, mbak;
+	register short rc;
+
+#if	DEBUGIT
+	if (debugsw AND debugm7)
+		printf("mdselbx(%d): ENTRY  old ndisp = %d\n", n, ndisp);
+#endif
+
+	mlcv = exp_c(MLINES);
+	mbcv = exp_c(MBUTTON);
+	mbak = exp_c(MBKGRND);
+
+	rc   = SUCCESS;
+
+	if (ndisp EQ 7) {		/* "Write program to disk" selected */
+
+		if (n EQ 7) {		/* verified, time to do it */
+
+			if (dcopy()) {
+
+				sprintf(bfs, "  FAILED -- Error %d", defect);
+
+				vcputsv(menuob, 64, MHILITE, mbak,
+					mrowcol[M_COPY][0] + 1,
+					mrowcol[M_COPY][1],
+					bfs, 14);
+
+				rc = FAILURE;
+			}
+
+			ndisp = -1;
+
+		} else {		/* not verified, cancel it */
+
+			ndisp = n;	/* display number = box number */
+			runit = FALSE;	/* cue msl() to setup the new display */
+			dsp_ok = FALSE;	/* disallow display updates */
+		}
+
+		vcputsv(menuob, 64, mbcv, mbak,
+			mrowcol[M_COPY][0], mrowcol[M_COPY][1],
+			mtexts[M_COPY], 14);
+
+/* 
+
+*/
+
+	} else if (ndisp EQ 9) {	/* "Format disk" selected */
+
+		if (n EQ 9) {		/* verified, time to do it */
+
+			if (dformat(DENSITY)) {
+
+				sprintf(bfs, "  FAILED -- Error %d", defect);
+
+				vcputsv(menuob, 64, MHILITE, mbak,
+					mrowcol[M_FORM][0] + 1,
+					mrowcol[M_FORM][1],
+					bfs, 14);
+
+				rc = FAILURE;
+			}
+
+			ndisp = -1;
+
+		} else {		/* not verified, cancel it */
+
+			ndisp  = n;	/* display number = box number */
+			runit  = FALSE;	/* cue msl() to setup the new display */
+			dsp_ok = FALSE;	/* disallow display updates */
+		}
+
+		vcputsv(menuob, 64, mbcv, mbak,
+			mrowcol[M_FORM][0], mrowcol[M_FORM][1],
+			mtexts[M_FORM], 14);
+
+/* 
+
+*/
+	} else {	/* select a new menu item */
+
+		ndisp = n;		/* display number = box number */
+
+		if (n EQ 7) {		/* select "Write program to disk" */
+
+			vcputsv(menuob, 64, MHILITE, mbak,
+				mrowcol[M_COPY][0], mrowcol[M_COPY][1],
+				mtexts[M_COPY], 14);
+			
+		} else if (n EQ 9) {	/* select "Format disk" */
+
+			vcputsv(menuob, 64, MHILITE, mbak,
+				mrowcol[M_FORM][0], mrowcol[M_FORM][1],
+				mtexts[M_FORM], 14);
+			
+		} else {
+
+			runit  = FALSE;	/* cue msl() to setup the new display */
+			dsp_ok = FALSE;	/* disallow display updates */
+		}
+	}
+
+#if	DEBUGIT
+	if (debugsw AND debugm7)
+		printf("mdselbx(%d): EXIT  ndisp = %d  rc = %d  runit = %d\n",
+			n, ndisp, rc, runit);
+#endif
+
+	return(rc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	drawm() -- draw the MIDAS 700 main menu
+   =============================================================================
+*/
+
+drawm()
+{
+	register short *mlp;
+	register short i;
+	register unsigned mlcv, mbcv, mbak;
+	char buf[16];
+
+	mlcv = exp_c(MLINES);
+	mbcv = exp_c(MBUTTON);
+	mbak = exp_c(MBKGRND);
+
+	if (ml01[0] EQ 0) {
+
+		mlbld(ml01, mlc01);
+		mlbld(ml02, mlc02);
+		mlbld(ml03, mlc03);
+		mlbld(ml04, mlc04);
+		mlbld(ml05, mlc05);
+	}
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(menuob, 128, 0, 0, 511, 349, mbak);
+
+	vcputsv(menuob, 64, mlcv, mbak,  1,  2,   ml01, 14);
+	vcputsv(menuob, 64, mlcv, mbak,  2,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  2, 61, "\260", 14);
+
+	vcputsv(menuob, 64, mlcv, mbak,  3,  2,   ml02, 14);
+	vcputsv(menuob, 64, mlcv, mbak,  4,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  4, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  4, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  5,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  5, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  5, 61, "\260", 14);
+
+	vcputsv(menuob, 64, mlcv, mbak,  6,  2,   ml03, 14);
+	vcputsv(menuob, 64, mlcv, mbak,  7,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  7, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  7, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  8,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  8, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak,  8, 61, "\260", 14);
+/* 
+
+*/
+	vcputsv(menuob, 64, mlcv, mbak,  9,  2,   ml03, 14);
+	vcputsv(menuob, 64, mlcv, mbak, 10,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 10, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 10, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 11,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 11, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 11, 61, "\260", 14);
+
+	vcputsv(menuob, 64, mlcv, mbak, 12,  2,   ml03, 14);
+	vcputsv(menuob, 64, mlcv, mbak, 13,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 13, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 13, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 14,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 14, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 14, 61, "\260", 14);
+
+	vcputsv(menuob, 64, mlcv, mbak, 15,  2,   ml03, 14);
+	vcputsv(menuob, 64, mlcv, mbak, 16,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 16, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 16, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 17,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 17, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 17, 61, "\260", 14);
+
+	vcputsv(menuob, 64, mlcv, mbak, 18,  2,   ml03, 14);
+	vcputsv(menuob, 64, mlcv, mbak, 19,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 19, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 19, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 20,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 20, 32, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 20, 61, "\260", 14);
+
+	vcputsv(menuob, 64, mlcv, mbak, 21,  2,   ml04, 14);
+	vcputsv(menuob, 64, mlcv, mbak, 22,  2, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 22, 61, "\260", 14);
+	vcputsv(menuob, 64, mlcv, mbak, 23,  2,   ml05, 14);
+/* 
+
+*/
+	mlp = &mlintab[0][0];
+	point = mlpoint;
+
+	while (-1  NE mlp[0]) {
+
+		lseg(mlp[0], mlp[1], mlp[2], mlp[3], mlcv);
+		mlp += 4;
+	}
+
+	vcputsv(menuob, 64, MTITLE, mbak, mrowcol[0][0], mrowcol[0][1],
+		mtexts[0], 14);
+
+	vcputsv(menuob, 64, MTITLE, mbak, VER_ROW, VER_COL, m7verms, 14);
+
+	for (i = 1; i < 13; i++)
+		vcputsv(menuob, 64, mbcv, mbak, mrowcol[i][0], mrowcol[i][1],
+			mtexts[i], 14);
+
+	vcputsv(menuob, 64, MBUCHLA, mbak, mrowcol[13][0], mrowcol[13][1],
+		mtexts[13], 14);
+
+	for (i = 0; i < NLTYPES; i++) {
+
+		memcpy(buf, loadedf[i], 8);
+		buf[8] = '\0';
+
+		vcputsv(menuob, 64, MLFILES, mbak, mfrc[i][0], mfrc[i][1],
+			buf, 14);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	m7menu() -- setup the MIDAS 700 main menu display
+   =============================================================================
+*/
+
+m7menu()
+{
+	menuob = &v_score[0];
+	obj0   = &v_curs0[0];
+	mdoct  = &v_obtab[MENUOBJ];
+
+	curslim = 350;
+
+	curset(&m7_flds);
+
+	ndisp = -1;
+	dswap();
+
+	vbank(0);
+	memsetw(menuob, 0, 32767);
+	memsetw(menuob+32767L, 0, 12033);
+
+	SetObj(MENUOBJ, 0, 0, menuob, 512, 350, 0, 0, MENUFL, -1);
+	SetObj(0, 0, 1, obj0, 16, 16, MCURX, MCURY, OBFL_00, -1);
+
+	arcurs(MCURSOR);
+
+	drawm();
+
+	vsndpal(menupal);
+
+	SetPri(MENUOBJ, MENUPRI);
+	SetPri(0, GCPRI);
+
+	setgc(MCURX, MCURY);
+}
Index: ram/m7ver.h
===================================================================
--- ram/m7ver.h	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/m7ver.h	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,8 @@
+/*
+   =============================================================================
+	m7ver.h -- MIDAS-VII version message header
+	MIDAS-VII was written by:  D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	M7VERMSG	"881028.02"
Index: ram/midas.c
===================================================================
--- ram/midas.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/midas.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,318 @@
+/*
+   =============================================================================
+	midas.c -- MIDAS-VII main function
+	Version 26 -- 1989-07-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "vsdd.h"
+#include "hwdefs.h"
+#include "wordq.h"
+#include "sclock.h"
+
+#include "graphdef.h"
+#include "midas.h"
+
+#define	LCD_TIME	((long)(800 * 240))	/* LCD backlight 'on' time */
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugmm = 1;
+#endif
+
+extern	short	fpuint(), clk_ped(), pch_ped();
+
+extern	short	(*foot1)(), (*foot2)(), (*pulse1)(), (*pulse2)();
+
+extern	char	*end, *etext, *edata;
+
+extern	short	clkrun, clksrc, initcfg, ndisp, verbose;
+
+extern	long	lcdontm, lcdtime;
+
+extern	short	fp_resv[];
+
+extern	char	*script0[];
+
+extern	char	VerDate[];
+
+extern	struct wordq	ptefifo;	/* trigger fifo */
+
+char	m7verms[32];	/* version message for the main menu */
+
+short	clkdiv;		/* clock divider */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dopls1() -- process pulse 1 inputs
+   =============================================================================
+*/
+
+dopls1()
+{
+	putwq(&ptefifo, 0x1180);	/* pulse 1 trigger -> STM fifo */
+
+	if (NOT clkrun)				/* check for clock enable */
+		return;				/* done if not enabled */
+
+	if (clksrc EQ CK_PLS24) {		/* Pulse 24 mode ? */
+
+		fc_val += 2L;			/* 2 clocks per pulse */
+
+		if (fc_val > 0x00FFFFFFL)	/* limit clock at maximum */
+			fc_val = 0x00FFFFFFL;
+
+	} else if (clksrc EQ CK_PLS48) {	/* Pulse 48 mode ? */
+
+		++fc_val;			/* 1 clock per pulse */
+
+		if (fc_val > 0x00FFFFFFL)	/* limit clock at maximum */
+			fc_val = 0x00FFFFFFL;
+
+	} else if (clksrc EQ CK_PLS96) {	/* Pulse 96 mode ? */
+
+		if (clkdiv++) {			/* 2 pulses per clock */
+
+			clkdiv = 0;		/* reset divider */
+			++fc_val;		/* update frame clock */
+
+			if (fc_val > 0x00FFFFFFL)	/* limit clock at maximum */
+				fc_val = 0x00FFFFFFL;
+		}
+	}
+}
+
+/*
+   =============================================================================
+	dopls2() -- process pulse 2 inputs
+   =============================================================================
+*/
+
+dopls2()
+{
+	putwq(&ptefifo, 0x1181);	/* pulse 2 trigger -> STM fifo */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	mpcupd() -- MIDI program change display update
+   =============================================================================
+*/
+
+mpcupd()
+{
+	switch (ndisp) {
+
+	case 0:		/* Librarian */
+
+		break;
+
+	case 1:		/* Patch Editor */
+
+		break;
+
+	case 2:		/* Score Editor */
+
+		sdwins();		/* fill in the windows */
+		break;
+
+	case 3:		/* Sequence Editor */
+
+		break;
+
+	case 4:		/* Instrument Editor */
+
+		setinst();		/* bring variables up to date */
+		allwins();		/* fill in the windows */
+		break;
+
+	case 5:		/* Initialize System */
+
+		break;
+
+	case 6:		/* Waveshape Editor */
+
+		newws();		/* bring variables up to date */
+		wwins();		/* fill in the windows */
+		break;
+
+	case 7:		/* Write Program to Disk */
+
+		break;
+
+	case 8:		/* Tuning Editor */
+
+		twins();		/* fill in the windows */
+		break;
+
+	case 9:		/* Format Disk */
+
+		break;
+
+	case 10:	/* Assignment Editor */
+
+		awins();		/* fill in the windows */
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MIDAS 700 main function
+   =============================================================================
+*/
+
+main()
+{
+	setipl(FPU_DI);			/* disable FPU interrupts */
+
+/* +++++++++++++++++++++++ FPU INTERRUPTS DISABLED ++++++++++++++++++++++++++ */
+
+	BIOS(B_SETV, 26, fpuint);	/* set level 2 int. vector for FPU */
+
+	initcfg    = 0;			/* set initial configuration  (in MS bits) */
+	fp_resv[0] = (-1000) << 5;	/* initial output amplitude = 0.0 */
+
+	fpuclr();		/* quiet the FPU */
+
+	tsetup();		/* setup the timer and timer interrupts */
+	setsio();		/* setup the serial I/O port interrupts */
+
+	foot1 = clk_ped;	/* setup clock on/off pedal processing */
+	foot2 = pch_ped;	/* setup punch in/out pedal processing */
+
+	pulse1 = dopls1;	/* setup pulse input 1 processing */
+	pulse2 = dopls2;	/* setup pulse input 2 processing */
+
+	lcdontm = LCD_TIME;	/* set the LCD backlight 'on' time */
+	lcd_on();		/* turn on the LCD backlight */
+
+	strcpy(m7verms, &VerDate[2]);	/* setup the version message */
+
+	im700();		/* initialize everything */
+	settune();		/* ... including fine tuning */
+
+	ndisp = -1;		/* say nothing has been selected yet */
+	verbose = FALSE;	/* setup to run the script quietly */
+	rscript(script0);	/* run the initial script */
+	sc_goto(0L);		/* position the score */
+
+	MouseWK();		/* wake up the mouse if it's there */
+
+	goto startup;		/* go put up the main menu */
+
+/* 
+
+*/
+
+newdisp:
+
+	msl();		/* run the new display */
+
+startup:
+
+#if	DEBUGIT
+	if (debugsw AND debugmm)
+		printf("main():  switching to MAIN MENU\N");
+#endif
+
+	m7menu();	/* put up the main menu */
+	msl();		/* run the main menu */
+
+#if	DEBUGIT
+	if (debugsw AND debugmm)
+		printf("main():  switching to %d\n", ndisp);
+#endif
+
+	switch (ndisp) {	/* setup for a new display */
+
+	case 0:		/* =================== librarian ==================== */
+
+		ldfield();	/* setup the librarian field handlers */
+		libdsp();	/* setup the librarian display */
+		break;
+
+	case 1:		/* =================== patch editor ================= */
+
+		ptfield();	/* setup the patch field handlers */
+		ptdisp();	/* setup the patch display */
+		break;
+
+	case 2:		/* =================== score editor ================= */
+
+		scfield();		/* initialize score field handlers */
+		sdsetup();		/* setup the score display */
+		break;
+
+	case 3:		/* ================ sequence editor ================= */
+
+		sqfield();		/* initialize sequence field handlers */
+		sqdisp();		/* setup the sequence display */
+		break;
+/* 
+
+*/
+	case 4:		/* =============== instrument editor ================ */
+
+		idfield();		/* setup instrument field handlers */
+		instdsp();		/* setup the instrument display */
+		break;
+
+	case 6:		/* ================ waveshape editor ================ */
+
+		wdfield();		/* setup waveshape field handlers */
+		wsdsp();		/* setup the waveshape display */
+		break;
+
+	case 8:		/* ================ tuning editor ================ */
+
+		tdfield();		/* setup tuning editor field handlers */
+		tundsp();		/* setup the tuning display */
+		break;
+
+	case 10:	/* ================ assignment editor =============== */
+
+		adfield();		/* setup assignment field handlers */
+		asgdsp();		/* setup the assignment display */
+		break;
+
+	case 11:	/* ================ diagnostics ===================== */
+
+		scopeon();		/* setup the diagnostics */
+		break;
+
+	default:
+
+#if	DEBUGIT
+	if (debugsw AND debugmm)
+		printf("main():  UNKNOWN display (%d)\n", ndisp);
+#endif
+
+		ndisp = -1;
+		goto startup;
+	}
+
+#if	DEBUGIT
+	if (debugsw AND debugmm)
+		printf("main():  display switch complete to %d\n", ndisp);
+#endif
+
+	goto newdisp;
+}
Index: ram/msl.c
===================================================================
--- ram/msl.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/msl.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,838 @@
+/*
+   =============================================================================
+	msl.c -- midas main scan loop
+	Version 102 -- 1989-11-14 -- D.N. Lynx Crowe
+
+	List with pr -e4 option to expand tabs to 4 spaces instead of 8.
+   =============================================================================
+*/
+
+#define	DEBUGIT		0	/* enable debug code */
+
+#define	OLDTIME		0	/* use old tempo time calculations */
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "graphdef.h"
+#include "glcfns.h"
+#include "glcdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "cmeta.h"
+#include "fields.h"
+#include "fpu.h"
+#include "macros.h"
+#include "patch.h"
+#include "smdefs.h"
+#include "sclock.h"
+#include "scwheel.h"
+#include "slice.h"
+#include "timers.h"
+#include "wordq.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+#include "wsdsp.h"
+#include "asgdsp.h"
+
+#define	LCL_PRT		3	/* 1-origin local keyboard port number */
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugms = 1;
+#endif
+
+/* 
+
+*/
+
+/* variables defined elsewhere */
+
+extern	short	(*cx_key)();
+extern	short	(*cy_key)();
+extern	short	(*d_key)();
+extern	short	(*e_key)();
+extern	short	(*m_key)();
+extern	short	(*x_key)();
+
+extern	PFS	(*swpt)[];
+
+extern	short	aflag;
+extern	short	amplval;
+extern	short	ancmsw;
+extern	short	angroup;
+extern	short	asig;
+extern	short	astat;
+extern	short	aval;
+extern	short	clkctl;
+extern	short	clkrun;
+extern	short	ctrsw;
+extern	short	cxrate;
+extern	short	cxval;
+extern	short	cyrate;
+extern	short	cyval;
+extern	short	dsp_ok;
+extern	short	editss;
+extern	short	editsw;
+extern	short	lampsw;
+extern	short	ndisp;
+extern	short	nxtflag;
+extern	short	pchsw;
+extern	short	recsw;
+extern	short	runit;
+extern	short	swback;
+extern	short	swctrl;
+extern	short	swdelta;
+extern	short	swdir;
+extern	short	swfiin;
+extern	short	swflag;
+extern	short	swlast;
+extern	short	swndx;
+extern	short	swstop;
+extern	short	swthr;
+extern	short	swtime;
+extern	short	swwait;
+extern	short	sd;
+extern	short	se;
+extern	short	stcrow;
+extern	short	stccol;
+extern	short	tglclk;
+extern	short	tglpch;
+extern	short	timemlt;
+extern	short	tmpomlt;
+extern	short	tmpoval;
+extern	short	tuneval;
+extern	short	vtpcol;
+extern	short	vtprow;
+
+/* 
+
+*/
+
+extern	unsigned short	*obj8;
+
+extern	long	afi;
+extern	long	lcdtime;
+extern	long	swcount;
+extern	long	swrate;
+extern	long	swrmin;
+extern	long	swtemp;
+
+extern	short	grpmode[];
+extern	short	grpstat[];
+extern	short	prstab[];
+extern	short	simled[];
+extern	short	swfifo[NSWFIFO];
+extern	short	tmultab[];
+extern	short	vce2trg[];
+extern	short	veltab[];
+
+extern	char	trgtab[];
+
+extern	short	grp2prt[][2];
+extern	short	sigtab[][2];
+extern	short	varmode[][16];
+
+extern	struct	gdsel	*gdstbc[];
+
+extern	struct 	wordq	ptefifo;
+
+unsigned short fifoval;
+
+/* 
+
+*/
+
+/* 
+   =============================================================================
+		clk_ped() -- process clock on/off toggle pedal
+   =============================================================================
+*/
+
+clk_ped(stat)
+short stat;
+{
+	if (stat)
+		tglclk = TRUE;
+}
+
+/* 
+   =============================================================================
+		pch_ped() -- process punch in/out toggle pedal
+   =============================================================================
+*/
+
+pch_ped(stat)
+short stat;
+{
+	if (stat AND pchsw)
+		tglpch = TRUE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	msl() -- MIDAS main scan loop
+   =============================================================================
+*/
+
+msl()
+{
+	register char *ioadr;
+	register unsigned *fpu;
+	register struct s_entry *ep;
+	register short i, ti, val;
+	register long rt;
+	unsigned short chan, crel, oldsr, port, trg, trig, vel;
+	short cxprev, cyprev, esi, newsig, oldclk, oldrec;
+	long fctemp;
+
+#if	DEBUGIT
+	if (debugsw AND debugms)
+		printf("msl():  ENTRY  ndisp=%d\n", ndisp);
+#endif
+
+	runit = TRUE;		/* set run state */
+
+	while (runit) {
+
+		dsp_ok = TRUE;		/* set display-OK flag for this pass */
+
+		ioadr = &io_ser + 2L;	/* get edit switch status */
+		esi   = *ioadr & 0x0008;
+
+		if (editss NE esi) {	/* check for edit switch change */
+
+			editss = esi;
+
+			if (editss)	/* toggle edit state if it went hi */
+				editsw = NOT editsw;
+		}
+
+		if (editsw)		/* update edit LED */
+			io_leds = 0x9E;
+		else
+			io_leds = 0x1E;
+
+		if ((NOT lampsw) AND lcdtime) {
+
+			if (0 EQ --lcdtime)
+				io_leds = 0x1F;	/* turn off the LCD backlight */
+		}
+
+		msm();			/* scan the MIDI ports */
+/* 
+
+*/
+
+		if (tglclk) {		/* check for clock on/off toggle */
+
+			oldsr  = setsr(0x2700);		/* disable interrupts */
+			tglclk = FALSE;			/* cancel toggle flag */
+			setsr(oldsr);			/* enable interrupts */
+
+			clkset(NOT clkrun);		/* toggle clock mode */
+			dclkmd();			/* update display */
+		}
+
+		if (tglpch) {		/* check for punch in/out toggle */
+
+			oldsr  = setsr(0x2700);		/* disable interrupts */
+			tglpch = FALSE;			/* cancel toggle flag */
+			setsr(oldsr);			/* enable interrupts */
+
+			if ((ndisp EQ 2) AND (v_regs[5] & 0x0180))
+				vbank(0);
+
+			for (i = 0; i < 12; i++) {	/* scan the groups */
+
+				if (grpmode[i] EQ 1) {	/* stdby -> rec */
+
+					grpmode[i] = 2;
+
+					if (ndisp EQ 2)
+						vputc(obj8, 2, 6 + (i * 5),
+							'*', simled[grpmode[i]]);
+
+				} else if (grpmode[i] EQ 2) {	/* rec -> play */
+
+					grpmode[i] = 0;
+
+					if (ndisp EQ 2)
+						vputc(obj8, 2, 6 + (i * 5),
+							'*', simled[grpmode[i]]);
+				}
+			}
+		}
+
+/* 
+
+*/
+		/* process stimulli from the patch stimulus fifo */
+
+		if (getwq(&ptefifo, &fifoval) GE 0) {
+
+			crel = 0x8000   &  fifoval;
+
+			trg  = TRG_MASK &  fifoval;
+			port = 0x0003   & (fifoval >> 11);
+			chan = 0x000F   & (fifoval >>  7);
+			trig = 0x007F   &  fifoval;
+
+			veltab[trg] = vel =  SM_SCALE(64);
+			prstab[trg] = 0;
+
+			if (crel) {		/* release */
+
+				trgtab[trg] &= ~M_KSTATE;
+
+				for (i = 0; i < 12; i++) {
+
+					if (vce2trg[i] EQ trg) {
+
+						vce2trg[i] = -1;
+						procpfl(trg);
+
+					}
+				}
+
+				stmproc(fifoval);	/* do it as a patch stimulus */
+
+			} else {		/* closure */
+
+				trgtab[trg] |= M_KSTATE;
+
+				stmproc(fifoval);	/* do it as a patch stimulus */
+
+				for (i = 0; i < 12; i++)
+					if ((grp2prt[i][0] EQ 1 + port) AND
+					    (grp2prt[i][1] EQ 1 + chan))
+						asgvce(i, port, chan, trig, vel);
+			}
+		}
+/* 
+
+*/
+		if (-1L NE (afi = XBIOS(X_ANALOG))) {	/* check panel inputs */
+
+			asig  = (afi >> 8) & 0x007F;	/* signal number */
+			astat = (afi >> 7) & 0x0001;	/* status */
+			aval  = afi & 0x007F;		/* value */
+
+			if (asig) {	/* active signal */
+
+				aflag  = TRUE;
+				newsig = astat AND (NOT sigtab[asig][1]);
+
+				sigtab[asig][0] = aval;
+				sigtab[asig][1] = astat;
+
+			} else {	/* all keys up */
+
+				aflag  = FALSE;
+				newsig = FALSE;
+
+				for (i = 0; i < 128; i++)
+					sigtab[i][1] = 0;
+			}
+
+/* 
+
+*/
+			if (aflag) {	/* anything changed ? */
+
+				if ((asig GE 1) AND (asig LE 24)) {
+
+					/* local keyboard performance key */
+
+					localkb(asig);
+
+				} else if ((asig GE 25) AND (asig LE 38)) {
+
+					if (astat)
+						lcd_on();
+
+					if (NOT newsig)
+						doslide();
+
+				} else if ((asig GE 39) AND (asig LE 52)) {
+
+					if (astat)
+						lcd_on();
+
+					(*(*swpt)[asig - 39])(astat, (asig - 39));
+
+				} else if ((asig GE 60) AND (asig LE 69)) {
+
+					(*d_key)(asig - 60);
+
+/* 
+
+*/
+				} else 	switch (asig) {
+
+				case 53:		/* tablet x */
+
+					val = SM_SCALE(aval);
+
+					for (i = 0; i < 12; i++) {
+
+						if (grp2prt[i][0] EQ LCL_PRT) {
+
+							if (newsv(i, SM_HTPW, val)) {
+
+								if (recsw AND grpstat[i] AND
+								    (2 EQ (ancmsw ? varmode[0][i] : grpmode[i]))) {
+
+									if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+										ep->e_time = t_cur;
+										ep->e_type = EV_ANVL;
+										ep->e_data1 = i;
+										ep->e_dn = (struct s_entry *)((long)val << 16);
+										p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+										ctrsw = TRUE;
+										se_disp(ep, D_FWD, gdstbc, 1);
+										ctrsw = FALSE;
+									}
+
+								} else if ((angroup - 1) EQ i) {
+
+									dsanval(0);
+								}
+							}
+						}
+					}
+
+					break;
+/* 
+
+*/
+				case 54:		/* tablet y */
+
+					val = SM_SCALE(aval);
+
+					for (i = 0; i < 12; i++) {
+
+						if (grp2prt[i][0] EQ LCL_PRT) {
+
+							if (newsv(i, SM_VTMW, val)) {
+
+								if (recsw AND grpstat[i] AND
+								    (2 EQ (ancmsw ? varmode[1][i] : grpmode[i]))) {
+
+									if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+										ep->e_time = t_cur;
+										ep->e_type = EV_ANVL;
+										ep->e_data1 = 0x0010 | i;
+										ep->e_dn = (struct s_entry *)((long)val << 16);
+										p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+										ctrsw = TRUE;
+										se_disp(ep, D_FWD, gdstbc, 1);
+										ctrsw = FALSE;
+									}
+
+								} else if ((angroup - 1) EQ i) {
+
+									dsanval(1);
+								}
+							}
+						}
+					}
+
+					break;
+
+				case 55:		/* cursor x */
+				
+					(*cx_key)();	break;
+
+				case 56:		/* cursor y */
+
+					(*cy_key)();	break;
+/* 
+
+*/
+				case 58:		/* longpot r */
+
+					val = SM_SCALE(aval);
+
+					for (i = 0; i < 12; i++) {
+
+						if (grp2prt[i][0] EQ LCL_PRT) {
+
+							if (newsv(i, SM_LPBR, val)) {
+
+								if (recsw AND grpstat[i] AND
+								    (2 EQ (ancmsw ? varmode[2][i] : grpmode[i]))) {
+
+									if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+										ep->e_time = t_cur;
+										ep->e_type = EV_ANVL;
+										ep->e_data1 = 0x0020 | i;
+										ep->e_dn = (struct s_entry *)((long)val << 16);
+										p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+										ctrsw = TRUE;
+										se_disp(ep, D_FWD, gdstbc, 1);
+										ctrsw = FALSE;
+									}
+
+								} else if ((angroup - 1) EQ i) {
+
+									dsanval(2);
+								}
+							}
+						}
+					}
+
+					break;
+
+/* 
+
+*/
+				case 59:		/* scroll wheel */
+
+					wheel();	break;
+
+				case 70:		/* X key */
+
+					(*x_key)();	break;
+
+				case 71:		/* E key */
+
+#if	DEBUGIT
+	if (debugsw AND debugms)
+		printf("msl():  -> e_key ($%lX)  astat=%d  ndisp=%d\n",
+			e_key, astat, ndisp);
+#endif
+					(*e_key)();
+
+#if	DEBUGIT
+	if (debugsw AND debugms)
+		printf("msl():  <- e_key ($%lX)  astat=%d  ndisp=%d  runit=%d\n",
+			e_key, astat, ndisp, runit);
+#endif
+
+					break;
+
+				case 72:		/* M key */
+
+					(*m_key)();	break;
+
+				case 73:		/* Tempo */
+
+					if (aval > 50)		/* dead band */
+						if (aval < 53)
+							aval = 50;
+						else
+							aval -= 2;
+
+					tmpomlt = aval > 100 ? 100 : aval;
+#if	OLDTIME
+					ti  = ( (tmpomlt + 50) * tmpoval) / 100;
+					ti  = (short)( (192000L / ti) - 1);
+#else
+					ti  = (tmpomlt + 50) * tmpoval;
+					ti  = (short)( (19200000L / ti) - 1);
+#endif
+					TIME_T2H = ti >> 8;
+					TIME_T2L = ti & 0x00FF;
+
+					if (tmpomlt EQ 50) {	/* 0 */
+
+						io_leds = 0x18;	/* green off */
+						io_leds = 0x19;	/* red off */
+
+					} else if (tmpomlt GT 50) {	/* hi */
+
+						io_leds = 0x98;	/* green on */
+						io_leds = 0x19;	/* red off */
+
+					} else {		/* lo */
+
+						io_leds = 0x18;	/* green off */
+						io_leds = 0x99;	/* red on */
+					}
+
+					break;
+/* 
+
+*/
+				case 74:		/* Time */
+
+					if (aval > 50)		/* dead band */
+						if (aval < 53)
+							aval = 50;
+						else
+							aval -= 2;
+
+					ti = aval > 100 ? 100 : aval;
+					timemlt = tmultab[ti];
+
+					if (ti EQ 50) {		/* 0 */
+
+						io_leds = 0x1A;	/* green off */
+						io_leds = 0x1B;	/* red off */
+
+					} else if (ti GT 50) {	/* hi */
+
+						io_leds = 0x9A;	/* green on */
+						io_leds = 0x1B;	/* red off */
+
+					} else {		/* lo */
+
+						io_leds = 0x1A;	/* green off */
+						io_leds = 0x9B;	/* red on */
+					}
+
+					break;
+
+/* 
+
+*/
+				case 75:		/* Tuning */
+
+					if (aval > 50)		/* dead band */
+						if (aval < 53)
+							aval = 50;
+						else
+							aval -= 2;
+
+					i = (aval > 100) ? 100 : aval;
+					tuneval = (i - 50) << 2;
+					settune();
+
+					if (i EQ 50) {
+
+						io_leds = 0x1C;	/* green off */
+						io_leds = 0x1D;	/* red off */
+
+					} else if (i GT 50) {
+
+						io_leds = 0x9C;	/* green on */
+						io_leds = 0x1D;	/* red off */
+
+					} else {
+
+						io_leds = 0x1C;	/* green off */
+						io_leds = 0x9D;	/* red on */
+					}
+
+					break;
+/* 
+
+*/
+				case 76:		/* amplitude */
+
+				aval += aval >> 2;
+
+				if (aval > 127)
+					aval = 127;
+
+				amplval = (aval << 9) ^ 0x8000;
+					sendval(0, 0, amplval);
+					break;
+
+				case 77:		/* pedal 1 */
+
+					val = SM_SCALE(aval);
+
+					for (i = 0; i < 12; i++) {
+
+						if (grp2prt[i][0] EQ LCL_PRT) {
+
+							if (newsv(i, SM_PED1, val)) {
+
+								if (recsw AND grpstat[i] AND
+								    (2 EQ (ancmsw ? varmode[4][i] : grpmode[i]))) {
+
+									if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+										ep->e_time = t_cur;
+										ep->e_type = EV_ANVL;
+										ep->e_data1 = 0x0040 | i;
+										ep->e_dn = (struct s_entry *)((long)val << 16);
+										p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+										ctrsw = TRUE;
+										se_disp(ep, D_FWD, gdstbc, 1);
+										ctrsw = FALSE;
+									}
+
+								} else if ((angroup - 1) EQ i) {
+
+									dsanval(4);
+								}
+							}
+						}
+					}
+
+					break;
+
+/* 
+
+*/
+				case 79:		/* cv 1 */
+
+					val = SM_SCALE(aval);
+
+					for (i = 0; i < 12; i++) {
+
+						if (grp2prt[i][0] EQ LCL_PRT) {
+
+							if (newsv(i, SM_CTL1, val)) {
+
+								if (recsw AND grpstat[i] AND
+								    (2 EQ (ancmsw ? varmode[3][i] : grpmode[i]))) {
+
+									if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+										ep->e_time = t_cur;
+										ep->e_type = EV_ANVL;
+										ep->e_data1 = 0x0030 | i;
+										ep->e_dn = (struct s_entry *)((long)val << 16);
+										p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+										ctrsw = TRUE;
+										se_disp(ep, D_FWD, gdstbc, 1);
+										ctrsw = FALSE;
+									}
+
+								} if ((angroup - 1)EQ i) {
+
+									dsanval(3);
+								}
+							}
+						}
+					}
+
+					break;
+
+				}
+			}
+		}
+/* 
+
+*/
+
+#if	DEBUGIT
+	if (debugsw AND debugms AND (NOT runit))
+		printf("msl():  end of asig cases -- dsp_ok = %d\n", dsp_ok);
+#endif
+
+		/* memory allocation changed ? */
+
+		if ((ndisp EQ 2) AND se_chg AND dsp_ok) {
+
+			dsmem();		/* display memory remaining */
+			se_chg = FALSE;
+		}
+
+		nxtflag = FALSE;		/* clear 'next score' flag */
+		fctemp  = fc_val;		/* sample the frame clock */
+
+		if (t_cur NE fctemp) {		/* see if frame clock changed */
+
+			if (t_cur LT fctemp) {		/* clock incremented */
+
+				if (se EQ D_BAK)	/* change direction ? */
+					chgsef();
+
+				sc_trek(fctemp);	/* track frame clock */
+
+			} else {			/* clock decremented */
+
+				if (se EQ D_FWD)	/* change direction ? */
+					chgseb();
+
+				sc_trek(fctemp);	/* track frame clock */
+			}
+
+		/* handle display update if there's time for it */
+
+		} else if (dsp_ok AND (t_ctr NE t_cur)) {
+
+			if (t_ctr LT t_cur) {	/* clock incremented */
+
+				if (sd EQ D_BAK)	/* change direction ? */
+					chgsdf();
+
+				sc_trak(t_ctr + 1);	/* track frame clock */
+
+			} else {		/* clock decremented */
+
+				if (sd EQ D_FWD)	/* change direction ? */
+					chgsdb();
+
+				sc_trak(t_ctr - 1);	/* track frame clock */
+			}
+		}
+/* 
+
+*/
+#if	DEBUGIT
+	if (debugsw AND debugms AND (NOT runit))
+		printf("msl():  end of clock processing -- dsp_ok = %d\n",
+			dsp_ok);
+#endif
+
+		/* handle 'next score' flag */
+
+		if (nxtflag AND (sd EQ D_FWD)) {	/* switch scores ? */
+
+			oldrec = recsw;
+			oldclk = clkrun;
+
+			ti = curscor + 1;
+
+			if (ti GE N_SCORES)
+				ti = 0;
+
+			for (i = 0; i < N_SCORES; i++) {
+
+				if (E_NULL NE scores[ti]) {
+
+					selscor(ti);
+					break;
+				}
+
+				if (++ti GE N_SCORES)
+					ti = 0;
+			}
+
+			clkset(oldclk);		/* restore clock mode */
+			dsclk();
+			recsw = oldrec;		/* restore record/play mode */
+			dsrpmod();
+			nxtflag = FALSE;	/* clear 'next score' flag */
+		}
+
+#if	DEBUGIT
+	if (debugsw AND debugms AND (NOT runit))
+		printf("msl():  curproc\n");
+#endif
+
+		curproc();			/* process wheel and ball */
+
+#if	DEBUGIT
+	if (debugsw AND debugms AND (NOT runit))
+		printf("msl():  seqproc\n");
+#endif
+
+		seqproc();			/* process sequences */
+	}
+
+#if	DEBUGIT
+	if (debugsw AND debugms)
+		printf("msl():  EXIT  ndisp=%d\n", ndisp);
+#endif
+}
Index: ram/msm.c
===================================================================
--- ram/msm.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/msm.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,912 @@
+/*
+   =============================================================================
+	msm.c -- MIDAS-VII -- MIDI state machine
+	Version 75 -- 1988-11-02 -- D.N. Lynx Crowe
+
+	List with pr -e4 option to expand tabs to 4 spaces instead of 8.
+   =============================================================================
+*/
+
+#include "biosdefs.h"
+#include "stddefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "smdefs.h"
+#include "sclock.h"
+#include "score.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "scfns.h"
+
+extern	short	ancmsw;		/* analog variable r/p control source */
+extern	short	angroup;	/* analog variable group being displayed */
+extern	short	clkctl;		/* clock control sources */
+extern	short	ctrsw;		/* se_disp center update switch */
+extern	short	curasg;		/* current assignment table */
+extern	short	curvce;		/* current voice being edited */
+extern	short	dsp_ok;		/* display update OK this cycle flag */
+extern	short	editsw;		/* edit switch state */
+extern	short	mascntr;	/* MIDI active sensing timeout counter */
+extern	short	mdb1;		/* current MIDI data byte 1 */
+extern	short	mdb2;		/* current MIDI data byte 2 */
+extern	short	michan;		/* current MIDI channel */
+extern	short	midiclk;	/* MIDI clock switch */
+extern	short	midigo;		/* MIDI run switch */
+extern	short	mistat;		/* current MIDI status */
+extern	short	ndisp;		/* current display */
+extern	short	recsw;		/* record/play switch */
+extern	short	prgchan;	/* MIDI program change channel */
+
+/* 
+
+*/
+
+extern	char	masens[];	/* MIDI port active sensing flags */
+extern	char	mctlval[];	/* MIDI controller values */
+extern	char	mdbyte[];	/* MIDI data byte buffers */
+extern	char	mpsust[];	/* MIDI sustain status, by port and channel */
+extern	char	mrstat[];	/* MIDI running status */
+extern	char	trgtab[];	/* trigger status */
+
+extern	short	grpmode[];	/* group mode table */
+extern	short	grpstat[];	/* group status table */
+extern	short	key2grp[];	/* key to group map */
+extern	short	vce2grp[];	/* voice to group map */
+extern	short	veltab[];	/* velocity */
+extern	short	mctlnum[];	/* MIDI controller number map */
+extern	short	mpbend[];	/* MIDI pitch bend data, by port and channel */
+extern	short	msmstv[];	/* MIDI state machine state variables */
+extern	short	prstab[];	/* pressure */
+extern	short	src2var[];	/* source to variable number map */
+extern	short	tuntab[];	/* current tuning table */
+extern	short	vce2trg[];	/* voice to trigger map (-1 EQ NULL) */
+
+extern	short	grp2prt[][2];	/* group to port/channel map */
+extern	short	varmode[][16];	/* analog variable record mode */
+
+extern	struct	gdsel	*gdstbc[];	/* group status table - center slice */
+
+/* initialized stuff */
+
+/* mpmap[] -- MIDI port to BIOS device table */
+
+short	mpmap[3]   = {MC1_DEV, MC2_DEV, CON_DEV};
+
+/* msmnext[] -- MIDI state machine -- channel message next state table */
+
+short	msmnext[8] = {2, 2, 2, 2, 1, 1, 2, 0};
+
+/* msmcnxt[] -- MIDI state machine -- system message next state table */
+
+short	msmcnxt[8] = {0, 0, 2, 1, 0, 0, 0, 0};
+
+/* ctl2src -- controller to source table */
+
+short	ctl2src[] = {SM_VTMW, SM_LPBR, SM_CTL1, SM_PED1};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	msm() -- MIDI state machine
+   =============================================================================
+*/
+
+msm()
+{
+	register short miport;
+	register short midiin;
+	register short i;
+	register short t1;
+	register short t2;
+	register struct s_entry *ep;
+	short j, nvel;
+	long where;
+
+	for (miport = 0; miport < NMPORTS; miport++) {	/* for each port ... */
+
+		while (BIOS(B_RDAV, mpmap[miport])) {	/* anything there ? */
+
+			dsp_ok = FALSE;			/* disallow display update */
+
+			midiin = 0x00FF & BIOS(B_GETC, mpmap[miport]);	/* get input */
+
+			if (masens[miport])		/* update active sensing */
+				masens[miport] |= 0x0F;
+
+			switch (msmstv[miport]) {	/* switch on state */
+/* 
+
+*/
+			case 0:		/* waiting for status */
+
+				if (0x0080 & midiin) {	/* status */
+
+					michan = 0x000F & midiin;
+					mistat = 0x000F & (midiin >> 4);
+
+					if (midiin < 0x00F0) {		/* channel */
+
+						msmstv[miport] = msmnext[mistat & 0x07];
+						mrstat[miport] = midiin;
+
+					} else if (midiin < 0x00F8) {	/* common */
+
+						msmstv[miport] = msmcnxt[michan & 0x07];
+						mrstat[miport] = midiin;
+/* 
+
+*/
+					} else {			/* real-time */
+
+						switch (0x0007 & midiin) {
+
+						case 0:		/* clock */
+
+							if (midiclk AND midigo)
+								if ((fc_val += 2) > 0x00FFFFFFL)
+									fc_val = 0x00FFFFFFL;
+
+							break;
+
+						case 2:		/* start */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+
+								if (fc_val)
+									sc_goto(fc_val = 0L);
+
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+
+						case 3:		/* continue */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+/* 
+
+*/
+						case 4:		/* stop */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    midigo) {
+
+								midigo = FALSE;
+								clkset(FALSE);
+								dsclk();
+							}
+
+							break;
+
+						case 6:		/* active sensing */
+
+							masens[miport] |= 0x00FF;
+							break;
+
+						case 7:		/* reset */
+
+							for (i = 0; i < NMPORTS; i++) {
+
+								mrstat[i] = 0;
+								msmstv[i] = 0;
+								masens[i] = 0;
+							}
+
+							break;
+						}
+					}
+				}
+
+				continue;
+/* 
+
+*/
+			case 1:		/* waiting for 1 data byte */
+
+				if (0x80 & midiin) {	/* status */
+
+					michan = 0x0F & midiin;
+					mistat = 0x0F & (midiin >> 4);
+
+					if (midiin < 0x00F0) {		/* channel */
+
+						msmstv[miport] = msmnext[mistat & 0x07];
+						mrstat[miport] = midiin;
+
+					} else if (midiin < 0x00F8) {	/* common */
+
+						msmstv[miport] = msmcnxt[michan & 0x07];
+						mrstat[miport] = midiin;
+/* 
+
+*/
+					} else {			/* real-time */
+
+						switch (0x0007 & midiin) {
+
+						case 0:		/* clock */
+
+							if (midiclk AND midigo)
+								if ((fc_val += 2) > 0x00FFFFFFL)
+									fc_val = 0x00FFFFFFL;
+
+							break;
+
+						case 2:		/* start */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+
+								if (fc_val)
+									sc_goto(fc_val = 0L);
+
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+
+						case 3:		/* continue */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+/* 
+
+*/
+						case 4:		/* stop */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    midigo) {
+
+								midigo = FALSE;
+								clkset(FALSE);
+								dsclk();
+							}
+
+							break;
+
+						case 6:		/* active sensing */
+
+							masens[miport] |= 0x00FF;
+							break;
+
+						case 7:		/* reset */
+
+							for (i = 0; i < NMPORTS; i++) {
+
+								mrstat[i] = 0;
+								msmstv[i] = 0;
+								masens[i] = 0;
+							}
+
+							break;
+						}
+					}
+/* 
+
+*/
+				} else {	/* data */
+
+					michan = 0x000F & mrstat[miport];
+					mistat = 0x000F & (mrstat[miport] >> 4);
+
+					if (mistat EQ 0x0C) {
+
+						/* program change */
+
+						if ((miport EQ 0) AND
+						    ((michan + 1) EQ prgchan) AND
+						    (midiin LT NASGS)) {
+
+							getasg(curasg = midiin);
+							mpcupd();
+						}
+/* 
+
+*/
+					} else if (mistat EQ 0x0D) {
+
+						/* channel pressure */
+
+						mdb1 = SM_SCALE(midiin);
+						t1 = (miport << 11) | (michan << 7);
+						t2 = t1 + 128;
+
+						for (i = t1; i < t2; i++)
+							prstab[i] = mdb1;
+
+						for (i = 0; i < 12; i++) {
+
+							if ((grp2prt[i][0] EQ (miport + 1)) AND
+							    (grp2prt[i][1] EQ (michan + 1))) {
+
+								if (newsv(i, SM_KPRS, mdb1)) {
+
+									if (recsw AND grpstat[i] AND
+									    (2 EQ (ancmsw ? varmode[5][i] : grpmode[i]))) {
+
+										if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+											ep->e_time = t_cur;
+											ep->e_type = EV_ANVL;
+											ep->e_data1 = 0x0050 | i;
+											ep->e_dn = (struct s_entry *)((long)mdb1 << 16);
+											p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+											ctrsw = TRUE;
+											se_disp(ep, D_FWD, gdstbc, 1);
+											ctrsw = FALSE;
+										}
+
+									} else if ((angroup - 1) EQ i) {
+
+										dsanval(5);
+									}
+								}
+							}
+						}
+/* 
+
+*/
+					} else if ((mistat EQ 0x0F) AND
+						   (michan EQ 3) AND
+						   (NOT midigo)) {	/* song select */
+
+						if (midiin < N_SCORES) {
+
+							selscor(midiin);
+
+							if (ndisp EQ 2)
+								sdwins();
+						}
+
+					} else {	/* error -- state mismatch */
+
+						msmstv[miport] = 0;
+						mrstat[miport] = 0;
+					}
+				}
+
+				continue;
+/* 
+
+*/
+			case 2:		/* waiting for 1st data byte */
+
+				if  (0x80 & midiin) {	/* status */
+
+					michan = 0x0F & midiin;
+					mistat = 0x0F & (midiin >> 4);
+
+					if (midiin < 0x00F0) {		/* channel */
+
+						msmstv[miport] = msmnext[mistat & 0x07];
+						mrstat[miport] = midiin;
+
+					} else if (midiin < 0x00F8) {	/* common */
+
+						msmstv[miport] = msmcnxt[michan & 0x07];
+						mrstat[miport] = midiin;
+/* 
+
+*/
+					} else {			/* real-time */
+
+						switch (0x0007 & midiin) {
+
+						case 0:		/* clock */
+
+							if (midiclk AND midigo)
+								if ((fc_val += 2) > 0x00FFFFFFL)
+									fc_val = 0x00FFFFFFL;
+
+							break;
+
+						case 2:		/* start */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+
+								if (fc_val)
+									sc_goto(fc_val = 0L);
+
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+
+						case 3:		/* continue */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+/* 
+
+*/
+						case 4:		/* stop */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    midigo) {
+
+								midigo = FALSE;
+								clkset(FALSE);
+								dsclk();
+							}
+
+							break;
+
+						case 6:		/* active sensing */
+
+							masens[miport] |= 0x00FF;
+							break;
+
+						case 7:		/* reset */
+
+							for (i = 0; i < NMPORTS; i++) {
+
+								mrstat[i] = 0;
+								msmstv[i] = 0;
+								masens[i] = 0;
+							}
+
+							break;
+						}
+					}
+
+				} else {	/* data */
+
+					mdbyte[miport] = midiin;
+					msmstv[miport] = 3;
+				}
+
+				continue;
+/* 
+
+*/
+			case 3:		/* waiting for 2nd data byte */
+
+				if (0x80 & midiin) {	/* status */
+
+					michan = 0x0F & midiin;
+					mistat = 0x0F & (midiin >> 4);
+
+					if (midiin < 0x00F0) {		/* channel */
+
+						msmstv[miport] = msmnext[mistat & 0x07];
+						mrstat[miport] = midiin;
+
+					} else if (midiin < 0x00F8) {	/* common */
+
+						msmstv[miport] = msmcnxt[michan & 0x07];
+						mrstat[miport] = midiin;
+/* 
+
+*/
+					} else {			/* real-time */
+
+						switch (0x0007 & midiin) {
+
+						case 0:		/* clock */
+
+							if (midiclk AND midigo)
+								if ((fc_val += 2) > 0x00FFFFFFL)
+									fc_val = 0x00FFFFFFL;
+
+							break;
+
+						case 2:		/* start */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+
+								if (fc_val)
+									sc_goto(fc_val = 0L);
+
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+
+						case 3:		/* continue */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								midigo = TRUE;
+								clkset(TRUE);
+								dsclk();
+							}
+
+							break;
+/* 
+
+*/
+						case 4:		/* stop */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    midigo) {
+
+								midigo = FALSE;
+								clkset(FALSE);
+								dsclk();
+							}
+
+							break;
+
+						case 6:		/* active sensing */
+
+							masens[miport] |= 0x00FF;
+							break;
+
+						case 7:		/* reset */
+
+							for (i = 0; i < NMPORTS; i++) {
+
+								mrstat[i] = 0;
+								msmstv[i] = 0;
+								masens[i] = 0;
+							}
+
+							break;
+						}
+					}
+/* 
+
+*/
+				} else {	/* data */
+
+					michan = 0x0F & mrstat[miport];
+					mistat = 0x0F & (mrstat[miport] >> 4);
+					mdb1 = mdbyte[miport];
+					mdb2 = midiin;
+					msmstv[miport] = 2;
+
+					switch (mistat) {	/* switch on status */
+
+					case 9:		/* note on */
+
+						if (mdb2) {
+
+							t1 = (miport << 11) + (michan << 7) + mdb1;
+							trgtab[t1] |= mpsust[(miport << 4) + michan] | M_KSTATE;
+							veltab[t1] = nvel = SM_SCALE(mdb2);
+							prstab[t1] = 0;
+
+							stmproc(t1);	/* process as a patch stimulus */
+
+							if (editsw) {	/* edit mode */
+
+								execkey(t1, tuntab[mdb1], curvce, 0);
+								break;
+							}
+
+							if (miport) {	/* port 1 or 2 */
+
+								for (i = 0; i < 12; i++)
+									if ((grp2prt[i][0] EQ (miport + 1)) AND
+									    (grp2prt[i][1] EQ (michan + 1))) {
+
+										asgvce(i, miport, michan, mdb1, nvel);
+										ne_bgn(i, mdb1, nvel);
+									}
+
+							} else {	/* port 0 */
+
+								t2 = ((mdb1 < 21) OR (mdb1 > 108)) ?
+									0 : key2grp[mdb1 - 21];
+
+								for (i = 0; i < 12; i++)
+									if ((t2 & (0x0001 << i)) AND
+									    (grp2prt[i][1] EQ (michan + 1))) {
+
+										asgvce(i, miport, michan, mdb1, nvel);
+										ne_bgn(i, mdb1, nvel);
+									}
+							}
+		
+							break;
+						}
+/* 
+
+*/
+					case 8:		/* note off */
+
+						t1 = (miport << 11) + (michan << 7) + mdb1;
+						trgtab[t1] &= ~M_KSTATE;
+
+						if (0 EQ trgtab[t1]) {
+
+							for (i = 0; i < 12; i++) {
+
+								if (vce2trg[i] EQ t1) {
+
+									vce2trg[i] = -1;
+									procpfl(t1);
+								}
+
+								if ((grp2prt[i][0] EQ (miport + 1)) AND
+								    (grp2prt[i][1] EQ (michan + 1)))
+									ne_end(t1, i);
+							}
+
+							stmproc(0x8000 | t1);	/* process as a patch stimulus */
+						}
+
+						break;
+
+					case 10:	/* poly pressure */
+
+						t1 = (miport << 11) + (michan << 7) + mdb1;
+						t2 = SM_SCALE(mdb2);
+						prstab[t1] = t2;
+
+						for (i = 0; i < 12; i++)
+							if ((grp2prt[i][0] EQ (miport + 1)) AND
+							    (grp2prt[i][1] EQ (michan + 1)))
+								newpps(t1, i, SM_KPRS, t2);
+
+						break;
+/* 
+
+*/
+					case 11:	/* control change */
+
+						mctlval[(miport << 11) + (michan << 7) + mdb1] = mdb2;
+
+						if (mdb1 EQ MIDISUS) {
+
+							/* sustain changed */
+
+							t1 = (miport << 11) | (michan << 7);
+							t2 = t1 + 128;
+
+							if (mdb2 GT MSW_ON) {	/* switch on */
+
+								mpsust[(miport << 4) + michan] = M_CHNSUS;
+
+								for (i = t1; i < t2; i++)
+									if (trgtab[i])
+										trgtab[i] |= M_CHNSUS;
+
+							} else if (mdb2 LT MSW_OFF) {	/* switch off */
+
+								mpsust[(miport << 4) + michan] = 0;
+
+								for (i = t1; i < t2; i++) {
+
+									if (trgtab[i]) {
+
+										trgtab[i] &= ~M_CHNSUS;
+
+										if (0 EQ trgtab[i]) {
+
+											for (t1 = 0; t1 < 12; t1++) {
+
+												if (vce2trg[t1] EQ i) {
+
+													vce2trg[t1] = -1;
+													procpfl(i);
+												}
+
+												if ((grp2prt[t1][0] EQ (miport + 1)) AND
+												    (grp2prt[t1][1] EQ (michan + 1)))
+													ne_end(i, t1);
+											}
+										}
+									}
+								}
+							}
+/* 
+
+*/
+						} else if (mdb1 EQ MIDIHLD) {
+
+							/* hold changed */
+
+							t1 = (miport << 11) | (michan << 7);
+							t2 = t1 + 128;
+
+							if (mdb2 GT MSW_ON) {	/* switch on */
+
+								for (i = t1; i < t2; i++)
+									if (trgtab[i] & M_KSTATE) {
+
+										for (t1 = 0; t1 < 12; t1++)
+											if ((vce2trg[t1] & ~(MKEYHELD << 8)) EQ i)
+												vce2trg[t1] |= (M_CHNHLD << 8);
+									}
+
+							} else if (mdb2 LT MSW_OFF) {	/* switch off */
+
+								for (i = 0; i <12; i++) {
+
+									if (vce2trg[i] NE -1) {
+
+										vce2trg[i] &= ~(M_CHNHLD << 8);
+
+										if (0 EQ (vce2trg[i] & (MKEYHELD << 8))) {
+
+											t1 = vce2trg[i];
+
+											if (0 EQ trgtab[t1]) {
+
+												vce2trg[i] = -1;
+												procpfl(t1);
+											}
+										}
+									}
+								}
+							}
+/* 
+
+*/
+						} else {	/* other controllers */
+
+							t1 = (miport << 11) | (michan << 7) | mdb1;
+							t2 = SM_SCALE(mdb2);
+							mctlval[t1] = t2;
+
+							for (j = 0; j < 4; j++) {
+
+								if ((mctlnum[j] & 0x00FF) EQ mdb1) {
+
+									i = ctl2src[j];
+
+									for (t1 = 0; t1 < 12; t1++) {
+
+										if ((mctlnum[j] & CTAG1) OR
+										    ((grp2prt[t1][0] EQ (miport + 1)) AND
+										     (grp2prt[t1][1] EQ (michan + 1)))) {
+
+											if (newsv(t1, i, t2)) {
+
+												if (recsw AND grpstat[t1] AND
+												    (2 EQ (ancmsw ? varmode[src2var[i]][t1] : grpmode[t1]))) {
+
+													if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+														ep->e_time = t_cur;
+														ep->e_type = EV_ANVL;
+														ep->e_data1 = (src2var[i] << 4) | t1;
+														ep->e_dn = (struct s_entry *)((long)t2 << 16);
+														p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+														ctrsw = TRUE;
+														se_disp(ep, D_FWD, gdstbc, 1);
+														ctrsw = FALSE;
+													}
+
+												} else if ((angroup - 1) EQ t1) {
+
+													dsanval(src2var[i]);
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+
+						break;
+/* 
+
+*/
+					case 14:	/* pitch bend */
+
+						t1 = (miport << 4) | michan;
+						t2 = ((mdb2 << 9) | (mdb1 << 2)) ^ 0x8000;
+						mpbend[t1] = t2;
+
+						for (i = 0; i < 12; i++) {
+
+							if ((grp2prt[i][0] EQ (miport + 1)) AND
+							    (grp2prt[i][1] EQ (michan + 1))) {
+
+								if (newsv(i, SM_HTPW, t2)) {
+
+									if (recsw AND grpstat[i] AND
+									    (2 EQ (ancmsw ? varmode[0][i] : grpmode[i]))) {
+
+										if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+											ep->e_time = t_cur;
+											ep->e_type = EV_ANVL;
+											ep->e_data1 = i;
+											ep->e_dn = (struct s_entry *)((long)t2 << 16);
+											p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+											ctrsw = TRUE;
+											se_disp(ep, D_FWD, gdstbc, 1);
+											ctrsw = FALSE;
+										}
+
+									} else if ((angroup - 1) EQ i) {
+
+										dsanval(0);
+									}
+								}
+							}
+						}
+
+						break;
+/* 
+
+*/
+					case 15:	/* common */
+
+						if (michan EQ 2) {	/* song position */
+
+							if ((clkctl EQ CK_MIDI) AND
+							    (NOT midigo)) {
+
+								where = 12 * ((mdb1 << 7) | mdb2);
+
+								if (fc_val NE where)
+									sc_goto(fc_val = where);
+							}
+
+							break;
+
+						} else {		/* bad running status */
+
+							msmstv[miport] = 0;
+							mrstat[miport] = 0;
+							break;
+						}				
+
+					default:	/* error -- bad status */
+
+						msmstv[miport] = 0;
+						mrstat[miport] = 0;
+						break;
+
+					}	/* end switch (on status) */
+
+				}	/* end if (status) */
+
+				continue;
+
+			default:	/* error -- bad state */
+
+				msmstv[miport] = 0;
+				mrstat[miport] = 0;
+				break;
+
+			}	/* end switch (on state) */
+		}		/* end while (data available) */
+	}			/* end for (each port) */
+}
Index: ram/nedacc.c
===================================================================
--- ram/nedacc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/nedacc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,842 @@
+/*
+   =============================================================================
+	nedacc.c -- MIDAS-VII note edit functions
+	Version 11 -- 1988-08-16 -- D.N. Lynx Crowe
+
+	This file contains the note edit operations:
+
+		NOP_ACC		Begin Acc	ned_acc()
+		NOP_NAT		Begin Nat	ned_nat()
+		NOP_END		End Note	ned_end()
+		NOP_MVN		Move Note	ned_mvn()
+		NOP_MVB		Move Begin	ned_mvb()
+		NOP_MVE		Move End	ned_mve()
+
+	and some related support functions:
+
+		accnote()
+		donote()
+		nedesub()
+   =============================================================================
+*/
+
+#undef	DEBUGGER		/* define to enable debug trace */
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "debug.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "score.h"
+#include "scfns.h"
+#include "secops.h"
+#include "neddefs.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+/* 
+
+*/
+
+extern	short	pix2mid();
+
+extern	struct	n_entry	*fcnote();
+
+extern	short	cflag;			/* accidental flag */
+extern	short	cnote;			/* note value at cursor */
+extern	short	cyval;			/* cursor y value */
+extern	short	cxval;			/* cursor x value */
+extern	short	recsw;			/* record / play switch */
+extern	short	scmctl;			/* area 1 menu status */
+
+extern	short	grpmode[];		/* group record / play status */
+extern	short	grpstat[];		/* group enable status */
+
+extern	long	ctime;			/* time at cursor */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	accnote() -- return accidental note number or -1 for errors
+   =============================================================================
+*/
+
+short
+accnote()
+{
+	register short rc;
+
+	DB_ENTR("accnote");
+
+	rc = -1;
+
+	if ((ac_code EQ N_SHARP) AND cflag) {
+
+		DB_CMNT("accnote - N_SHARP");
+		rc = cnote + 1;
+
+	} else if ((ac_code EQ N_FLAT) AND cflag) {
+
+		DB_CMNT("accnote - N_FLAT");
+		rc = cnote - 1;
+
+	} else {
+
+		DB_CMNT("accnote - no accidental possible");
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("accnote():  cnote = %d, ac_code = %d, cflag = %d, rc = %d\n",
+			cnote, ac_code, cflag, rc);
+#endif
+	DB_EXIT("accnote");
+	return(rc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ned_acc() -- enter accidental note
+   =============================================================================
+*/
+
+short
+ned_acc(grp)
+short grp;
+{
+	register short nn;
+	register struct n_entry *ep;
+
+	DB_ENTR("ned_acc");
+
+	if (-1 EQ (nn = accnote())) {
+
+		DB_EXIT("ned_acc - accnote() failed");
+		return(FAILURE);
+	}
+
+	if (E_NULL NE (ep = (struct n_entry *)e_alc(E_SIZE1))) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ned_acc():  NBEG g=%d, n=%d, t=%ld, ep=$%08lX\n",
+			grp, nn, ctime, ep);
+#endif
+		DB_CMNT("ned_acc - entering note begin");
+		ep->e_time  = ctime;
+		ep->e_type  = EV_NBEG;
+		ep->e_note  = nn;
+		ep->e_group = grp;
+		ep->e_vel   = SM_SCALE(64);
+		e_ins((struct s_entry *)ep, ep_adj(p_cur, 0, ctime));
+		noteop = NOP_END;	/* setup for end of note */
+		DB_EXIT("ned_acc - note begin entered");
+		return(SUCCESS);
+	}
+
+	noteop = NOP_NUL;	/* clear pending operation code */
+	DB_EXIT("ned_acc - no space for note begin");
+	return(FAILURE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ned_nat() -- enter natural note
+   =============================================================================
+*/
+
+short
+ned_nat(grp)
+short grp;
+{
+	register struct n_entry *ep;
+
+	DB_ENTR("ned_nat");
+
+	if (E_NULL NE (ep = (struct n_entry *)e_alc(E_SIZE1))) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ned_nat():  NBEG g=%d, n=%d, t=%ld, ep=$%08lX\n",
+			grp, cnote, ctime, ep);
+#endif
+		DB_CMNT("ned_nat - entering note begin");
+		ep->e_time  = ctime;
+		ep->e_type  = EV_NBEG;
+		ep->e_note  = cnote;
+		ep->e_group = grp;
+		ep->e_vel   = SM_SCALE(64);
+		e_ins((struct s_entry *)ep, ep_adj(p_cur, 0, ctime));
+		noteop = NOP_END;	/* set up for end of note */
+		DB_EXIT("ned_nat - note begin entered");
+		return(SUCCESS);
+	}
+
+	noteop = NOP_NUL;	/* clear pending operation code */
+	DB_EXIT("ned_nat - no space for note begin");
+	return(FAILURE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nedesub() -- enter note end subroutine
+
+	Returns:
+
+		-1	note end not entered - out of space
+		 0	note end entered OK
+		 1	note end not entered - no matching begin
+   =============================================================================
+*/
+
+short
+nedesub(grp, note)
+register short grp, note;
+{
+	register struct s_entry *ep, *np;
+	register short et;
+
+	DB_ENTR("nedesub");
+
+	ep = ep_adj(p_cur, 0, ctime);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("nedesub(%d, %d):  ctime=%ld, ep=$%08lX, t_cur=%ld, p_cur=$%08lX\n",
+			grp, note, ctime, ep, t_cur, p_cur);
+#endif
+
+/* 
+
+*/
+	DB_CMNT("nedesub - left scan");
+
+	FOREVER {		/* left scan */
+
+		et = 0x007F & ep->e_type;
+
+		switch (et) {		/* dispatch off of event type */
+
+		case EV_NEND:		/* note end */
+
+			if ((ep->e_data1 EQ note) AND
+			    (ep->e_data2 EQ grp)) {
+
+				DB_EXIT("nedesub - note end hit");
+				return(1);
+			} else
+				break;
+
+		case EV_SCORE:		/* score begin */
+
+			DB_EXIT("nedesub - score begin hit");
+			return(1);
+
+		case EV_NBEG:		/* note begin */
+
+			if ((ep->e_data1 EQ note) AND
+			    (ep->e_data2 EQ grp)) {	/* group and note match */
+
+				ep = ep->e_fwd;		/* setup for scan */
+				DB_CMNT("nedesub - NBEG nit - right scan");
+/* 
+
+*/
+				FOREVER {	/* right scan */
+
+					et = 0x007F & ep->e_type;
+
+					switch (et) {
+
+					case EV_NEND:
+
+						if ((ep->e_data1 EQ note) AND
+						    (ep->e_data2 EQ grp)) {
+
+							DB_EXIT("nedesub - note end hit");
+							return(1);
+
+						} else
+							break;
+/* 
+
+*/
+					case EV_NBEG:
+
+						if ((ep->e_data1 EQ note) AND
+						    (ep->e_data2 EQ grp)) {
+
+					case EV_FINI:
+
+							DB_CMNT("nedesub - note begin / fini hit");
+
+							if (E_NULL NE (np = (struct n_entry *)e_alc(E_SIZE1))) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("nedesub():  note end entered - $%08lX t=%ld g=%d n=%d\n",
+			np, ctime, grp, note);
+#endif
+								DB_CMNT("nedesub - entering note end");
+								np->e_time  = ctime;
+								np->e_type  = EV_NEND;
+								np->e_note  = note;
+								np->e_group = grp;
+								np->e_vel   = SM_SCALE(64);
+								e_ins((struct s_entry *)np, ep_adj(p_cur, 0, ctime));
+								DB_EXIT("nedesub - note end entered");
+								return(0);
+
+							} else {
+
+								DB_EXIT("nedesub - no space for note end");
+								return(-1);
+							}
+
+						}	/* end if */
+
+					}	/* end switch */
+
+					ep = ep->e_fwd;		/* point at next event */
+
+				}	/* end FOREVER - right scan */
+
+			}	/* end if */
+
+		}	/* end switch */
+
+		ep = ep->e_bak;		/* back up to previous event */
+
+	}	/* end FOREVER - left scan */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ned_end() -- enter note end
+   =============================================================================
+*/
+
+short
+ned_end(grp)
+short grp;
+{
+	register short rc;
+
+	DB_ENTR("ned_end");
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ned_end():  trying grp = %d, note = %d\n",
+			grp, cnote);
+#endif
+	DB_CMNT("ned_end - trying natural");
+
+	if (-1 EQ (rc = nedesub(grp, cnote))) {	/* try for a natural */
+
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_end - nedesub returned -1  (no space)");
+		return(FAILURE);
+
+	} else if (0 EQ rc) {
+
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_end - natural note end entered");
+		return(SUCCESS);
+
+	} else if (1 NE rc) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ned_end():  nedesub(%d, %d) returned %d\n",
+			grp, cnote + 1, rc);
+#endif
+
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_end - nedesub returned non-zero  (unknown error)");
+		return(FAILURE);
+	}
+/* 
+
+*/
+#if	DEBUGIT
+	if (debugsw)
+		printf("ned_end():  trying grp = %d, note = %d\n",
+			grp, cnote + 1);
+#endif
+
+	DB_CMNT("ned_end - trying accidental");
+
+	if (-1 EQ (rc = nedesub(grp, cnote + 1))) {	/* try for an accidental */
+
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_end - nedesub returned -1  (no space)");
+		return(FAILURE);
+
+	} else if (1 EQ rc) {
+
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_end - nedesub returned 1  (no match)");
+		return(FAILURE);
+
+	} else if (0 NE rc) {
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("ned_end():  nedesub(%d, %d) returned %d\n",
+			grp, cnote + 1, rc);
+#endif
+
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_end - nedesub returned non-zero  (unknown error)");
+		return(FAILURE);
+	}
+
+	noteop = NOP_NUL;	/* clear pending operation code */
+	DB_EXIT("ned_end - accidental note end entered");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ned_mvn() -- move entire note
+   =============================================================================
+*/
+
+short
+ned_mvn(grp)
+short grp;
+{
+	register struct n_entry *bp, *ep;
+	register short note;
+
+	DB_ENTR("ned_mvn");
+
+	if (notesel) {		/* note selected -- now do the dirty work */
+
+		bp = p_nbeg;		/* point at note begin event */
+		ep = p_nend;		/* point at note end event */
+
+		/* clip out the note begin event */
+
+		DB_CMNT("ned_mvn - clipping out begin");
+
+		if (p_bak EQ bp)
+			p_bak = bp->e_fwd;
+
+		if (p_ctr EQ bp)
+			p_ctr = bp->e_fwd;
+
+		if (p_cur EQ bp)
+			p_cur = bp->e_fwd;
+
+		if (p_fwd EQ bp)
+			p_fwd = bp->e_fwd;
+
+		e_rmv((struct s_entry *)bp);
+/* 
+
+*/
+		/* clip out the note end event */
+
+		DB_CMNT("ned_mvn - clipping out end");
+
+		if (p_bak EQ ep)
+			p_bak = ep->e_fwd;
+
+		if (p_ctr EQ ep)
+			p_ctr = ep->e_fwd;
+
+		if (p_cur EQ ep)
+			p_cur = ep->e_fwd;
+
+		if (p_fwd EQ ep)
+			p_fwd = ep->e_fwd;
+
+		e_rmv((struct s_entry *)ep);
+
+		bp->e_time = ctime;		/* correct begin time */
+		ep->e_time = ctime + t_note;	/* correct end time */
+
+		/* re-insert the note */
+
+		DB_CMNT("ned_mvn - re-inserting note");
+
+		e_ins((struct s_entry *)bp, ep_adj(p_cur, 0, ctime));
+		e_ins((struct s_entry *)ep, ep_adj(p_cur, 0, ctime + t_note));
+
+		notesel = FALSE;	/* note not selected */
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_mvn - note moved");
+		return(SUCCESS);
+
+	} else {
+
+		if (E_NULL NE fcnote(grp, cnote)) {
+
+			notesel = TRUE;			/* note selected */
+			DB_EXIT("ned_mvn - natural selected");
+			return(FAILURE);
+
+		} else if (-1 NE (note = accnote())) {
+
+			if (E_NULL NE (bp = fcnote(grp, note))) {
+
+				notesel = TRUE;		/* note selected */
+				DB_EXIT("ned_mvn - accidental selected");
+				return(FAILURE);
+			}
+		}
+
+		notesel = FALSE;	/* note not selected */
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_mvn - uanble to find note");
+		return(FAILURE);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ned_mvb() -- move beginning of note
+   =============================================================================
+*/
+
+short
+ned_mvb(grp)
+short grp;
+{
+	register struct n_entry *bp, *ep;
+	register short note;
+
+	DB_ENTR("ned_mvb");
+
+	if (notesel) {		/* note selected -- now do the dirty work */
+
+		bp = p_nbeg;	/* point at note begin event */
+		ep = p_nend;	/* point at note end event */
+
+		if (ctime GE ep->e_time) {	/* check move point */
+
+			noteop = NOP_NUL;	/* clear pending operation */
+			notesel = FALSE;	/* note not selected */
+			DB_EXIT("ned_mvb - move point after end");
+			return(FAILURE);
+		}
+
+		/* clip out the note begin event */
+
+		DB_CMNT("ned_mvb - clipping out begin");
+
+		if (p_bak EQ bp)
+			p_bak = bp->e_fwd;
+
+		if (p_ctr EQ bp)
+			p_ctr = bp->e_fwd;
+
+		if (p_cur EQ bp)
+			p_cur = bp->e_fwd;
+
+		if (p_fwd EQ bp)
+			p_fwd = bp->e_fwd;
+
+		e_rmv((struct s_entry *)bp);
+
+		bp->e_time = ctime;		/* correct begin time */
+
+		/* re-insert begin event */
+
+		e_ins((struct s_entry *)bp, ep_adj(p_cur, 0, ctime));
+
+		noteop = NOP_NUL;	/* clear pending operation */
+		notesel = FALSE;	/* note not selected */
+		DB_EXIT("ned_mvb - begin moved");
+		return(SUCCESS);
+/* 
+
+*/		
+	} else {
+
+		if (E_NULL NE fcnote(grp, cnote)) {	/* natural ? */
+
+			notesel = TRUE;			/* note selected */
+			DB_EXIT("ned_mvb - natural selected");
+			return(FAILURE);
+
+		} else if (-1 NE (note = accnote())) {	/* accidental ? */
+
+			if (E_NULL NE (bp = fcnote(grp, note))) {
+
+				notesel = TRUE;		/* note selected */
+				DB_EXIT("ned_mvb - accidental selected");
+				return(FAILURE);
+			}
+		}
+
+		notesel = FALSE;	/* note not selected */
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_mvb - unable to find note");
+		return(FAILURE);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ned_mve() -- move end of note
+   =============================================================================
+*/
+
+short
+ned_mve(grp)
+short grp;
+{
+	register struct n_entry *bp, *ep;
+	register short note;
+
+	DB_ENTR("ned_mve");
+
+	if (notesel) {		/* note selected -- now do the dirty work */
+
+		bp = p_nbeg;	/* point at note begin event */
+		ep = p_nend;	/* point at note end event */
+
+		if (ctime LE bp->e_time) {	/* check move point */
+
+			noteop = NOP_NUL;	/* clear pending operation */
+			notesel = FALSE;	/* note not selected */
+			DB_EXIT("ned_mve - move point before begin");
+			return(FAILURE);
+		}
+
+		/* clip out the note end event */
+
+		DB_CMNT("ned_mve - clipping out end");
+
+		if (p_bak EQ ep)
+			p_bak = ep->e_fwd;
+
+		if (p_ctr EQ ep)
+			p_ctr = ep->e_fwd;
+
+		if (p_cur EQ ep)
+			p_cur = ep->e_fwd;
+
+		if (p_fwd EQ ep)
+			p_fwd = ep->e_fwd;
+
+		e_rmv((struct s_entry *)ep);
+
+		ep->e_time = ctime;	/* correct end time */
+
+		/* re-insert end event */
+
+		e_ins((struct s_entry *)ep, ep_adj(p_cur, 0, ctime));
+
+		noteop = NOP_NUL;	/* clear pending operation */
+		notesel = FALSE;	/* note not selected */
+		DB_EXIT("ned_mve - end moved");
+		return(SUCCESS);
+
+	} else {
+
+		if (E_NULL NE fcnote(grp, cnote)) {	/* natural ? */
+
+			notesel = TRUE;			/* note selected */
+			DB_EXIT("ned_mve - natural selected");
+			return(FAILURE);
+
+		} else if (-1 NE (note = accnote())) {
+
+			if (E_NULL NE (bp = fcnote(grp, note))) {	/* accidental ? */
+
+				notesel = TRUE;		/* note selected */
+				DB_EXIT("ned_mve - accidental selected");
+				return(FAILURE);
+			}
+		}
+
+		notesel = FALSE;	/* note not selected */
+		noteop = NOP_NUL;	/* clear pending operation code */
+		DB_EXIT("ned_mve - unable to find note");
+		return(FAILURE);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	donote() -- do a note operation
+   =============================================================================
+*/
+
+donote()
+{
+	register short grp, i, gs;
+
+	DB_ENTR("donote");
+
+	if (scmctl NE -1) {		/* area 1 menu must be down */
+
+		DB_EXIT("donote - scmctl NE -1");
+		return;
+	}
+
+	if (NOT recsw) {		/* must be in record mode */
+
+		DB_EXIT("donote - not in record mode");
+		return;
+	}
+
+	/* determine which group we want to work with */
+
+	gs = 0;
+	grp = -1;
+
+	for (i = 0; i < 12; i++) {	/* scan the groups */
+
+		if ((grpmode[i] EQ 2) AND grpstat[i]) {
+
+			grp = i;	/* log the group */
+			++gs;		/* count enabled groups */
+#if	DEBUGIT
+	if (debugsw)
+		printf("donote():  gs = %d, grp = %d\n", gs, grp);
+#endif
+		}
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("donote():  final gs = %d, grp = %d\n", gs, grp);
+#endif
+
+/* 
+
+*/
+	if (gs NE 1) {			/* must have a single group enabled */
+
+		DB_EXIT("donote - no single group enabled");
+		return;
+	}
+
+	if (pix2mid(cxval, cyval)) {	/* must point at a note position */
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("donote():  no note at cxval = %d, cyval = %d\n",
+			cxval, cyval);
+#endif
+		DB_EXIT("donote - not at a note position");
+		return;
+	}
+/* 
+
+*/
+#if	DEBUGIT
+	if (debugsw)
+		printf("donote():  at (cxval=%d, cyval=%d):  cnote=%d, cflag=%d, ctime=%ld\n",
+			cxval, cyval, cnote, cflag, ctime);
+#endif
+
+	DB_CMNT("donote - dispatching");
+
+	switch (noteop) {	/* dispatch off of note operation code */
+
+	case NOP_ACC:		/* Begin Acc */
+
+		if (ned_acc(grp))
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case NOP_NAT:		/* Begin Nat */
+
+		if (ned_nat(grp))
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case NOP_END:		/* End Note */
+
+		if (ned_end(grp))
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+/* 
+
+*/
+	case NOP_MVN:		/* Move Note */
+
+		if (ned_mvn(grp))
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case NOP_MVB:		/* Move Begin */
+
+		if (ned_mvb(grp))
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case NOP_MVE:		/* Move End */
+
+		if (ned_mve(grp))
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	default:
+
+		DB_CMNT("donote - bad operation");
+		noteop = NOP_NUL;	/* clear pending operation code */
+	}
+
+	dnedmod();		/* update note edit window */
+	DB_EXIT("donote");
+	return;
+}
Index: ram/pix2mid.c
===================================================================
--- ram/pix2mid.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/pix2mid.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,155 @@
+/*
+   =============================================================================
+	pix2mid.c -- convert cursor position to MIDI note number and score time
+	Version 9 -- 1988-10-27 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "score.h"
+
+#include "midas.h"
+#include "scfns.h"
+#include "scdsp.h"
+
+#define	PCENTER		256	/* pixel offset of 0 time line */
+
+extern	short	cflag;		/* accidental flag */
+extern	short	cnote;		/* note value at cursor */
+extern	short	cyval;		/* cursor y value */
+extern	short	cxval;		/* cursor x value */
+
+extern	long	ctime;		/* time at cursor */
+extern	long	t_cur;		/* time at p_cur */
+
+/* 
+
+*/
+
+short	mpixtab[52][4] = {	/* pixel to MIDI note for the white keys */
+
+/* [0] = center pixel, [1] = MIDI note, [2] = sharp tag, [3] = flat tag */
+
+	{  1, 108, 0, 0},	/* 8C 00 --  0 */
+
+
+	{  5, 107, 0, 1},	/* 7B 00 --  1 */
+	{  9, 105, 1, 1},	/* 7A 00 --  2 */
+	{ 13, 103, 1, 1},	/* 7G 00 --  3 */
+	{ 17, 101, 1, 0},	/* 7F 00 --  4 */
+
+	{ 21, 100, 0, 1},	/* 7E 00 --  5 */
+	{ 25,  98, 1, 1},	/* 7D 00 --  6 */
+	{ 29,  96, 1, 0},	/* 7C 00 --  7 */
+
+
+	{ 33,  95, 0, 1},	/* 6B 00 --  8 */
+	{ 37,  93, 1, 1},	/* 6A 00 --  9 */
+	{ 41,  91, 1, 1},	/* 6G 00 -- 10 */
+	{ 45,  89, 1, 0},	/* 6F 00 -- 11 */
+
+	{ 49,  88, 0, 1},	/* 6E 00 -- 12 */
+	{ 53,  86, 1, 1},	/* 6D 00 -- 13 */
+	{ 57,  84, 1, 0},	/* 6C 00 -- 14 */
+
+
+	{ 61,  83, 0, 1},	/* 5B 00 -- 15 */
+	{ 65,  81, 1, 1},	/* 5A 00 -- 16 */
+	{ 69,  79, 1, 1},	/* 5G 00 -- 17 */
+	{ 73,  77, 1, 0},	/* 5F 00 -- 18 */
+
+	{ 77,  76, 0, 1},	/* 5E 00 -- 19 */
+	{ 81,  74, 1, 1},	/* 5D 00 -- 20 */
+	{ 85,  72, 1, 0},	/* 5C 00 -- 21 */
+
+	{ 89,  71, 0, 1},	/* 4B 00 -- 22 */
+	{ 93,  69, 1, 1},	/* 4A 00 -- 23 */
+	{ 97,  67, 1, 1},	/* 4G 00 -- 24 */
+	{101,  65, 1, 0},	/* 4F 00 -- 25 */
+
+	{105,  64, 0, 1},	/* 4E 00 -- 26 */
+	{109,  62, 1, 1},	/* 4D 00 -- 27 */
+	{113,  60, 1, 0},	/* 4C 00 -- 28 -- Middle C */
+
+/* 
+
+*/
+
+	{117,  59, 0, 1},	/* 3B 00 -- 29 */
+	{121,  57, 1, 1},	/* 3A 00 -- 30 */
+	{125,  55, 1, 1},	/* 3G 00 -- 31 */
+	{129,  53, 1, 0},	/* 3F 00 -- 32 */
+
+	{133,  52, 0, 1},	/* 3E 00 -- 33 */
+	{137,  50, 1, 1},	/* 3D 00 -- 34 */
+	{141,  48, 1, 0},	/* 3C 00 -- 35 */
+
+
+	{145,  47, 0, 1},	/* 2B 00 -- 36 */
+	{149,  45, 1, 1},	/* 2A 00 -- 37 */
+	{153,  43, 1, 1},	/* 2G 00 -- 38 */
+	{157,  41, 1, 0},	/* 2F 00 -- 39 */
+
+	{161,  40, 0, 1},	/* 2E 00 -- 40 */
+	{165,  38, 1, 1},	/* 2D 00 -- 41 */
+	{169,  36, 1, 0},	/* 2C 00 -- 42 */
+
+
+	{173,  35, 0, 1},	/* 1B 00 -- 43 */
+	{177,  33, 1, 1},	/* 1A 00 -- 44 */
+	{181,  31, 1, 1},	/* 1G 00 -- 45 */
+	{185,  29, 1, 0},	/* 1F 00 -- 46 */
+
+	{189,  28, 0, 1},	/* 1E 00 -- 47 */
+	{193,  26, 1, 1},	/* 1D 00 -- 48 */
+	{197,  24, 1, 0},	/* 1C 00 -- 49 */
+
+
+	{201,  23, 0, 1},	/* 0B 00 -- 50 */
+	{205,  21, 1, 0}	/* 0A 00 -- 51 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pix2mid() -- convert (px, py) to MIDI note and score time
+   =============================================================================
+*/
+
+short
+pix2mid()
+{
+	register short i, cy, mpc;
+	register long ct;
+
+	cnote = -1;
+	ctime = -1L;
+	cflag = -1;
+	mpc   = ac_code EQ N_SHARP ? 2 : 3;
+
+	ct = t_cur + ((long)cxval - (long)PCENTER);
+
+	if (ct < 0L)
+		return(FAILURE);
+
+	ctime = ct;
+	cy    = cyval - 14;
+
+	for (i = 0; i < 52; i++) {
+
+		if ((cy GE mpixtab[i][0]) AND
+		    (cy LE mpixtab[i][0] + 2)) {
+
+			cnote = mpixtab[i][1];
+			cflag = mpixtab[i][mpc];
+			break;
+		}
+	}
+
+	return((cnote EQ -1L) ? FAILURE : SUCCESS);
+}
Index: ram/procpfl.s
===================================================================
--- ram/procpfl.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/procpfl.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,758 @@
+* ------------------------------------------------------------------------------
+* procpfl.s -- process pendant functions  (sustain release processing)
+* Version 8 -- 1988-08-31 -- D.N. Lynx Crowe
+* ------------------------------------------------------------------------------
+		.text
+*
+		.xdef	_procpfl
+*
+		.xdef	_curpf_f	* current function (v/p)
+		.xdef	_curpf_l	* current pflist entry
+		.xdef	_curpf_t	* current trigger
+*
+		.xref	_irand
+		.xref	_xgetran
+*
+		.xref	_expbit
+		.xref	_funcndx
+		.xref	_pflist
+		.xref	_pfqhdr
+		.xref	_prstab
+		.xref	_ptoftab
+		.xref	_timemlt
+		.xref	_trgtab
+		.xref	_valents
+		.xref	_vce2grp
+		.xref	_vce2trg
+		.xref	_veltab
+*
+		.page
+* ------------------------------------------------------------------------------
+* Register usage
+* --------------
+*	d0	scratch
+*	d1	FPU function index
+*	d2	point index from FH_CPT  (idfcpt)
+*	d3	scratch
+*	d4	jump point number from PT_PAR1  (ippar1)
+*	d5	scratch
+*
+*	a0	scratch
+*	a1	function header base
+*	a2	point table base
+*	a3	FPU base
+*
+* ------------------------------------------------------------------------------
+* FPU definitions
+* ---------------
+*
+UPD_BIT		.equ	$0001			* update bit  (1 = update)
+INT_BIT		.equ	$0002			* int. bit    (0 = disable)
+RAT_BIT		.equ	$0004			* ratio bit   (0 = ratio)
+*
+VSUBNBIT	.equ	3			* new value select bit number
+VAL_BITS	.equ	$0018			* new value select bit mask
+*
+MSK_RNVB	.equ	$000C			* new value / ratio bits
+MSK_ONVB	.equ	$0010			* old new value bit
+*
+FKILL		.equ	$0014			* kill value for function
+FSEND		.equ	$0015			* send new value to function
+*
+CLREXP		.equ	$8000			* clear value for time exponent
+CLRMNT		.equ	$8000			* clear value for time mantissa
+*
+* ------------------------------------------------------------------------------
+* Miscellaneous definitions
+* -------------------------
+*
+PCHMAX		.equ	21920			* maximum pitch value
+VALMAX		.equ	32000			* maximum value to send to FPU
+VALMIN		.equ	-32000			* minimum value to send to FPU
+*
+LSPCH		.equ	2			* left shift for sources to freq
+*
+VALLEN		.equ	10			* length of the 'valent' struct
+VT_VAL		.equ	8			* value offset in 'valent'
+*
+		.page
+* ------------------------------------------------------------------------------
+* FPU addresses
+* -------------
+*
+FPUBASE		.equ	$180000			* FPU base address
+*
+FPUWST		.equ	FPUBASE			* FPU waveshape base
+FPUFUNC		.equ	FPUBASE+$4000		* FPU function base
+FPUINT1		.equ	FPUBASE+$4000		* FPU int. input address (R/O)
+FPUINT2		.equ	FPUBASE+$6000		* FPU int. reset address (W/O)
+FPUCFG		.equ	FPUBASE+$5FE0		* FPU config. data address (W/O)
+*
+F_CTL		.equ	$00			* control word
+F_VAL10		.equ	$02			* new value "10"
+F_CV1		.equ	$08			* control voltage 1
+F_SF1		.equ	$0A			* scale factor 1
+F_CV2		.equ	$0C			* control voltage 2
+F_SF2		.equ	$0E			* scale factor 2
+F_CV3		.equ	$10			* control voltage 3
+F_SF3		.equ	$12			* scale factor 3
+F_MNT		.equ	$14			* time mantissa
+F_EXP		.equ	$16			* time exponent
+F_VAL01		.equ	$1C			* new value "01"
+*
+P_FREQ1		.equ	$0020			* frequency 1
+P_FREQ2		.equ	$0060			* frequency 2
+P_FREQ3		.equ	$00A0			* frequency 3
+P_FREQ4		.equ	$00E0			* frequency 4
+P_FILTER	.equ	$0140			* filter
+P_FILTRQ	.equ	$00C0			* filter q
+*
+P_INDEX1	.equ	$0120			* index 1
+P_INDEX2	.equ	$0160			* index 2
+P_INDEX3	.equ	$0180			* index 3
+P_INDEX4	.equ	$01A0			* index 4
+P_INDEX5	.equ	$01C0			* index 5
+P_INDEX6	.equ	$01E0			* index 6
+*
+P_LEVEL		.equ	$0040			* level
+*
+P_LOCN		.equ	$0080			* location
+P_DYNAM		.equ	$0100			* dynamics
+*
+		.page
+* ------------------------------------------------------------------------------
+* Structure definitions
+* ------------------------------------------------------------------------------
+* The following MUST match the idfnhdr structure definition in instdsp.h:
+*
+FH_LEN		.equ	12		* length of the idfnhdr structure
+*
+FH_PCH		.equ	0		* WORD - pitch offset
+FH_MLT		.equ	2		* WORD - overall value multiplier
+FH_SRC		.equ	4		* BYTE - overall value source
+FH_PIF		.equ	5		* BYTE - # of points in the function
+FH_PT1		.equ	6		* BYTE - index of first point
+FH_TMD		.equ	7		* BYTE - trigger mode / control bits
+FH_CPT		.equ	8		* BYTE - current point
+FH_PRM		.equ	9		* BYTE - misc. function parameter
+FH_TRG		.equ	10		* WORD - trigger
+*
+I_ACTIVE	.equ	1		* 'Active' bit number        (in FH_TMD)
+*
+MSK_CTL		.equ	$001C		* mask for FPU hardware bits (in FH_TMD)
+*
+* ------------------------------------------------------------------------------
+* The following MUST match the instpnt structure definition in instdsp.h:
+*
+PT_LEN		.equ	12		* length of the instpnt structure
+*
+PT_TIM		.equ	0		* WORD - time (packed)
+PT_VAL		.equ	2		* WORD - value
+PT_VMLT		.equ	4		* WORD - value multiplier
+PT_VSRC		.equ	6		* BYTE - value source
+PT_ACT		.equ	7		* BYTE - action
+PT_PAR1		.equ	8		* BYTE - parameter 1
+PT_PAR2		.equ	9		* BYTE - parameter 2
+PT_PAR3		.equ	10		* BYTE - parameter 3
+PT_PAD		.equ	11		* BYTE - padding for even boundary
+*
+MSK_MNT		.equ	$FFF0		* mask for mantissa  (in PT_TIM)
+MSK_EXP		.equ	$000F		* mask for exponent  (in PT_TIM)
+*
+MAX_ACT		.equ	7		* maximum action code value
+*
+* ------------------------------------------------------------------------------
+* Source definitions -- must match those in 'smdefs.h'
+*
+SM_RAND		.equ	1		* random
+SM_PTCH		.equ	5		* pitch
+SM_KPRS		.equ	6		* key pressure
+SM_KVEL		.equ	7		* key velocity
+SM_FREQ		.equ	10		* frequency
+*
+		.page
+*
+* Layout of pflist entries	32 bytes each
+* ------------------------
+PF_NEXT		.equ	0		* LONG - next entry pointer
+PF_TRIG		.equ	4		* WORD - trigger number
+PF_FUNC		.equ	6		* WORD - fpuifnc value
+PF_D1		.equ	8		* LONG - d1
+PF_D2		.equ	12		* LONG - d2
+PF_D4		.equ	16		* LONG - d4
+PF_A1		.equ	20		* LONG - a1
+PF_A2		.equ	24		* LONG - a2
+PF_A3		.equ	28		* LONG - a3
+*
+* Parameter offset
+* ----------------
+TRIG		.equ	8		* WORD - trigger number
+*
+* Register equates
+* ----------------
+RCUR		.equ	a4		* current pflist entry pointer
+RPRV		.equ	a5		* previous pflist entry pointer
+*
+		.page
+* ------------------------------------------------------------------------------
+* _procpfl() -- process pendant functions
+*
+*	void
+*	procpfl(trig);
+*	unsigned trig;
+*
+*		Processes pendant (sustained) functions by restarting them
+*	when the trigger (trig) that's sustaining them is released.
+*	Invoked by key release processing in msm() and localkb().
+*
+* ------------------------------------------------------------------------------
+*
+_procpfl:	nop				* FOR DEBUGGING PATCH
+*
+		link	a6,#0			* allocate stack frame
+		movem.l	d3-d7/a3-a5,-(a7)	* preserve registers we use
+*
+		move.w	sr,d7			* save interrupt state
+		move.w	#$2200,sr		* turn off FPU interrupts
+*
+		move.w	TRIG(a6),d6		* get trigger we're processing
+		move.w	d6,_curpf_t		* ...
+		movea.l	#_pflist,RPRV		* point at 'previous' pflist entry
+		bra	pfscan			* go scan the chain
+*
+pfpass:		movea.l	RCUR,RPRV		* point at previous entry
+*
+pfscan:		move.l	(RPRV),d5		* get next pflist entry pointer
+		beq	pfexit			* done if no more
+*
+		movea.l	d5,RCUR			* point at  current entry
+		move.l	d5,_curpf_l		* ...
+*
+		cmp.w	PF_TRIG(RCUR),d6	* see if this entry is wanted
+		bne	pfpass			* jump if not
+*
+		movem.l	PF_D1(RCUR),d1-d2/d4/a1-a3	* restore processing state
+		move.w	PF_FUNC(RCUR),_curpf_f		* ...
+*
+		btst	#I_ACTIVE,FH_TMD(a1)	* see if function is active
+		bne	doact			* continue function if so
+*
+		bra	stopfn			* stop function if not
+*
+pfnext:		move.l	(RCUR),(RPRV)		* remove entry from pflist
+		move.l	_pfqhdr,(RCUR)		* chain entry to free list
+		move.l	RCUR,_pfqhdr		* ...
+		bra	pfscan			* go look at next entry
+*
+pfexit:		move.w	d7,sr			* restore interrupt level
+		movem.l	(a7)+,d3-d7/a3-a5	* restore the registers we used
+		unlk	a6			* deallocate stack frame
+		rts				* return to caller
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* stop a function
+* ------------------------------------------------------------------------------
+stopfn:		move.b	FH_TMD(a1),d0	* get function control bits
+		andi.w	#MSK_RNVB,d0	* mask for ratio / new new-value bit
+		move.w	d0,d3		* isolate new new-value bit
+		add.w	d3,d3		* ... from function header
+		andi.w	#MSK_ONVB,d3	* ... shift to old new-value bit
+		or.w	d3,d0		* ... and put new bit in old bit	
+		move.w	d0,F_CTL(a3,d1.W)	* stop the function
+		bclr	#I_ACTIVE,FH_TMD(a1)	* reset the active bit
+		bra	pfnext		* go restore registers and exit
+*
+* ------------------------------------------------------------------------------
+* setup for and dispatch to the proper action handler
+* ------------------------------------------------------------------------------
+doact:		clr.w	d2		* get current point index in d2
+		move.b	FH_CPT(a1),d2	* ...
+		lsl.w	#2,d2		* multiply it by the length of a point
+		move.w	d2,d0		* ...  (fast multiply by PT_LEN = 12
+		add.w	d2,d2		* ...   via shift and add)
+		add.w	d0,d2		* ...
+		clr.w	d4		* get jump point # into d4
+		move.b	PT_PAR1(a2,d2.W),d4	* ...
+		clr.w	d3		* get action code in d3
+		move.b	PT_ACT(a2,d2.W),d3	* ...
+		cmpi.b	#MAX_ACT,d3	* check against the limit
+		bgt	stopfn		* stop things if it's a bad action code
+*
+		lsl.w	#2,d3		* develop index to action dispatch table
+		lea	actab,a0	* get the address of the action handler
+		movea.l	0(a0,d3.W),a0	* ...
+*
+* ------------------------------------------------------------------------------
+* At this point we're ready to do the action associated with the point,
+* and the registers are set up,  and will remain,  as follows:
+*
+*	d1	FPU function index	a1	function header base
+*	d2	point table index	a2	point table base
+*					a3	FPU function base
+*	d4	jump point number
+*
+*	d0, d3, d5, and a0 are used as scratch throughout the code.
+*
+* ------------------------------------------------------------------------------
+*
+		jmp	(a0)		* dispatch to action handler
+*
+		.page
+* ------------------------------------------------------------------------------
+* act0 -- AC_NULL -- no action
+* ----    --------------------
+act0:		move.b	FH_PT1(a1),d0	* get first point number
+		add.b	FH_PIF(a1),d0	* add number of points in function
+		subq.b	#1,d0		* make it last point number
+		cmp.b	FH_CPT(a1),d0	* see if we're at the last point
+		beq	stopfn		* stop function if so
+*
+		addq.b	#1,FH_CPT(a1)	* update function header for next point
+		addi.w	#PT_LEN,d2	* advance the point index
+*
+* ------------------------------------------------------------------------------
+* outseg -- output a segment
+* ------    ----------------
+outseg:		move.w	PT_TIM(a2,d2.w),d3	* get packed time
+		move.w	d3,d0			* extract mantissa
+		andi.w	#MSK_MNT,d0		* ...
+		mulu	_timemlt,d0		* multiply by panel time pot value
+		lsr.l	#8,d0			* ... and scale it
+		lsr.l	#7,d0			* ...
+		move.w	d0,F_MNT(a3,d1.W)	* send mantissa to FPU
+		andi.w	#MSK_EXP,d3		* extract exponent code
+		add.w	d3,d3			* look up decoded exponent
+		lea	_expbit,a0		* ... in expbit
+		move.w	0(a0,d3.W),F_EXP(a3,d1.W)	* send exponent to FPU
+		move.w	PT_VAL(a2,d2.W),d3	* get the function value
+*
+		.page
+* ------------------------------------------------------------------------------
+* get the point source, if any
+* ------------------------------------------------------------------------------
+		tst.w	PT_VMLT(a2,d2.W)	* see if we have a point mlt.
+		beq	nosrc			* don't do anything for zero
+*
+		clr.w	d0			* get the source number
+		move.b	PT_VSRC(a2,d2.W),d0	* ...
+		beq	nosrc			* don't do anything for zero
+*
+* ------------------------------------------------------------------------------
+* SM_RAND -- random
+* ------------------------------------------------------------------------------
+		cmpi.w	#SM_RAND,d0		* is this the random source ?
+		bne	srctyp0			* jump if not
+*
+		movem.l	d1-d2/a0-a2,-(a7)	* preserve registers around call
+		move.w	PT_VMLT(a2,d2.W),-(a7)	* pass multiplier to xgetran()
+		jsr	_xgetran		* call for a random number
+		tst.w	(a7)+			* clean up stack
+		movem.l	(a7)+,d1-d2/a0-a2	* restore registers
+		move.w	d0,d5			* put random value in the value register
+		bra	applym			* go apply the multiplier
+*
+		.page
+* ------------------------------------------------------------------------------
+* SM_FREQ -- frequency
+* ------------------------------------------------------------------------------
+srctyp0:	cmpi.w	#SM_FREQ,d0	* is this the frequency source ?
+		bne	srctyp1		* jump if not
+*
+		move.w	(a1),d0		* get the pitch
+		lsr.w	#6,d0		* shift to a word index
+		andi.w	#$01FE,d0	* mask out extraneous bits
+		lea	_ptoftab,a0	* get entry from ptoftab[]
+		move.w	0(a0,d0.W),d5	* ...
+		bra	applym		* go apply the multiplier
+*
+* ------------------------------------------------------------------------------
+* SM_PTCH -- pitch
+* ------------------------------------------------------------------------------
+srctyp1:	cmpi.w	#SM_PTCH,d0	* is this the pitch source ?
+		bne	srctyp2		* jump if not
+*
+		move.w	(a1),d5		* get the pitch as the value
+		bra	applym		* go apply the multiplier
+*
+* ------------------------------------------------------------------------------
+* SM_KVEL -- velocity
+* ------------------------------------------------------------------------------
+srctyp2:	cmpi.w	#SM_KVEL,d0	* is this the key velocity source ?
+		bne	srctyp3		* jump if not
+*
+		move.w	FH_TRG(a1),d0	* get the trigger number
+		add.w	d0,d0		* ... as a word index
+		lea	_veltab,a0	* ... into veltab[]
+		move.w	0(a0,d0.W),d5	* get the velocity from veltab[trg]
+		bra	applym		* go apply the multiplier
+*
+* ------------------------------------------------------------------------------
+* SM_KPRS -- pressure
+* ------------------------------------------------------------------------------
+srctyp3:	cmpi.w	#SM_KPRS,d0	* is this the key pressure source ?
+		bne	srctyp4		* jump if not  (must be an analog input)
+*
+		move.w	FH_TRG(a1),d0	* get the trigger number
+		add.w	d0,d0		* ... as a word index
+		lea	_prstab,a0	* ... into prstab[]
+		move.w	0(a0,d0.W),d5	* get the pressure from prstab[trg]
+		bra	applym		* go apply the multiplier
+*
+		.page
+* ------------------------------------------------------------------------------
+* all other sources come out of the valents[] array
+* ------------------------------------------------------------------------------
+srctyp4:	lea	_vce2grp,a0	* point at vce2grp[]
+		move.w	_curpf_f,d5	* get voice number in d5
+		lsr.w	#3,d5		* ...
+		andi.w	#$001E,d5	* ... as a word index
+		move.w	0(a0,d5.W),d5	* get the group number
+		subq.w	#1,d5		* ...
+		lsl.w	#4,d5		* shift it left a nybble
+		or.w	d5,d0		* OR it into the source number
+		add.w	d0,d0		* make source number a valents[] index
+		move.w	d0,d5		* ... (fast multiply by VALLEN = 10
+		lsl.w	#2,d0		* ...  via shift and add)
+		add.w	d5,d0		* ...
+		lea	_valents,a0	* get base of valents[]
+		move.w	VT_VAL(a0,d0.W),d5	* get value
+*
+* ------------------------------------------------------------------------------
+* apply the multiplier to the source, and add it to the function value
+* ------------------------------------------------------------------------------
+applym:		muls	PT_VMLT(a2,d2.W),d5	* apply the multiplier
+		asr.l	#7,d5		* scale the result
+		asr.l	#8,d5		* ...
+		ext.l	d3		* add the function value
+		add.l	d3,d5		* ...
+		cmpi.l	#VALMAX,d5	* check for overflow
+		ble	srcmlt1		* jump if no overflow
+*
+		move.l	#VALMAX,d5	* limit at VALMAX
+		bra	srcmlt2		* ...
+*
+srcmlt1:	cmpi.l	#VALMIN,d5	* check for underflow
+		bge	srcmlt2		* jump if no underflow
+*
+		move.l	#VALMIN,d5	* limit at VALMIN
+*
+srcmlt2:	move.w	d5,d3		* setup value for output to FPU
+*
+		.page
+* ------------------------------------------------------------------------------
+* adjust the value according to the function type
+* ------------------------------------------------------------------------------
+nosrc:		move.w	d1,d0		* get function type
+		andi.w	#$01E0,d0	* ...
+*
+* ------------------------------------------------------------------------------
+* level or location
+* ------------------------------------------------------------------------------
+		cmpi.w	#P_LEVEL,d0	* see if it's the level
+		beq	outsegl		* jump if so
+*
+		cmpi.w	#P_LOCN,d0	* see if it's the location
+		bne	outsegf		* jump if not
+*
+		tst.w	d3		* check sign of value
+		bpl	outsegc		* jump if positive
+*
+		clr.w	d3		* force negative values to 0
+*
+outsegc:	asr.w	#5,d3		* shift value to LS bits
+		sub.w	#500,d3		* subtract 5.00 from value
+		asl.w	#6,d3		* readjust to MS bits
+		bra	outseg3		* go output the value
+*
+outsegl:	tst.w	d3		* check sign of value
+		bpl	outsegm		* jump if positive
+*
+		clr.w	d3		* limit negative values at 0
+*
+outsegm:	asr.w	#5,d3		* shift value to LS bits
+		sub.w	#500,d3		* subtract 5.00 from value
+		asl.w	#6,d3		* readjust to MS bits
+		bra	outseg3		* go output the value
+*
+		.page
+* ------------------------------------------------------------------------------
+* filter
+* ------------------------------------------------------------------------------
+outsegf:	cmpi.w	#P_FILTER,d0	* see if it's the filter
+		bne	outsegp		* jump if not
+*
+		ext.l	d3		* make function value a long
+		asr.l	#1,d3		* multiply function value by .75
+		move.l	d3,d0		* ...  (fast multiply by .75
+		asr.l	#1,d0		* ...   via shift and add)
+		add.l	d0,d3		* ...
+		move.w	(a1),d0		* add pitch
+		ext.l	d0		* ...
+		add.l	d0,d3		* ...
+		cmpi.l	#VALMAX,d3	* see if it's within limits
+		ble	outsega		* ...
+*
+		move.w	#VALMAX,d3	* limit at VALMAX
+		bra	outseg3		* ...
+*
+outsega:	cmpi.l	#VALMIN,d3	* ...
+		bge	outseg3		* ...
+*
+		move.w	#VALMIN,d3	* limit at VALMIN
+		bra	outseg3		* ...
+*
+		.page
+* ------------------------------------------------------------------------------
+* freq 1..4
+* ------------------------------------------------------------------------------
+outsegp:	cmpi.w	#P_FREQ1,d0	* see if it's freq1
+		beq	outseg0		* go process freq1
+*
+outsegq:	cmpi.w	#P_FREQ2,d0	* see if it's freq2
+		beq	outseg0		* process it if so
+*
+		cmpi.w	#P_FREQ3,d0	* see if it's freq3
+		beq	outseg0		* process it if so
+*
+		cmpi.w	#P_FREQ4,d0	* see if it's freq4
+		bne	outseg3		* jump if not
+*
+outseg0:	ext.l	d3		* scale the point value to cents offset
+		asr.l	#5,d3		* ...
+		sub.l	#500,d3		* ... value - 500
+		asl.l	#LSPCH,d3	* mult. by 2 and scale for 1/2 cent lsb
+		move.w	(a1),d0		* add pitch from function header
+		ext.l	d0		* ...
+		add.l	d0,d3		* ...
+		cmp.l	#PCHMAX,d3	* see if result is valid
+		ble	outseg3		* jump if within pitch limits
+*
+		move.l	#PCHMAX,d3	* limit at maximum pitch
+*
+* ------------------------------------------------------------------------------
+* send the value to the FPU
+* ------------------------------------------------------------------------------
+outseg3:	move.b	FH_TMD(a1),d0	* get hardware bits from function header
+		eor.w	#VAL_BITS,d0	* toggle new value select bits
+		move.b	d0,FH_TMD(a1)	* store updated word
+		btst.l	#VSUBNBIT,d0	* check which value address to use
+		beq	outseg1
+*
+		move.w	d3,F_VAL01(a3,d1.W)	* send value to FPU
+		bra	outseg2
+*
+outseg1:	move.w	d3,F_VAL10(a3,d1.W)	* send value to FPU
+*
+outseg2:	andi.w	#MSK_CTL,d0		* mask off software bits
+		ori.w	#UPD_BIT+INT_BIT,d0	* set the update & !lastseg bits
+		move.w	d0,F_CTL(a3,d1.W)	* send control word to FPU
+		bra	pfnext			* done -- exit
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act2 -- AC_ENBL -- stop if key is up
+* ----    ----------------------------
+act2:		move.w	_curpf_f,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* check to see if voice is free
+		move.w	0(a0,d0.W),d0	* ...
+		cmpi.w	#-1,d0		* ...
+		beq	stopfn		* if so, stop the function
+*
+		btst	#15,d0		* see if voice is held
+		bne	act0		* continue if so
+*
+		btst	#14,d0		* ...
+		bne	act0		* ...
+*
+		lea	_trgtab,a0	* check trigger table entry
+		tst.b	0(a0,d0.W)	* ...
+		bne	act0		* if trigger is active, continue
+*
+		bra	stopfn		* if not, stop the function
+*
+* ------------------------------------------------------------------------------
+* act3 -- AC_JUMP -- unconditional jump
+* ----    -----------------------------
+act3:		cmp.b	FH_PIF(a1),d4	* check jump point against limit
+		bcc	stopfn		* stop function if jump point invalid
+*
+		clr.w	d2		* get index of first point
+		move.b	FH_PT1(a1),d2	* ...
+		add.b	d4,d2		* add jump point
+		move.b	d2,FH_CPT(a1)	* make it the current point
+		lsl.w	#2,d2		* develop new point index in d2
+		move.w	d2,d0		* ... (fast multiply by PT_LEN = 12
+		add.w	d2,d2		* ...  via shift and add)
+		add.w	d0,d2		* ...
+		bra	outseg		* output the segment
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act4 -- AC_LOOP -- jump to point PT_PAR1 PT_PAR2 times
+* ----    ----------------------------------------------
+act4:		tst.b	PT_PAR3(a2,d2.W)	* check counter
+		bne	act4a			* jump if it's running
+*
+		move.b	PT_PAR2(a2,d2.W),d0	* get parameter
+		subi.w	#90,d0			* put parameter in random range
+		bmi	act4b			* treat as normal if < 90
+*
+		movem.l	d1-d2/a0-a2,-(a7)	* get ranged random number
+		move.w	d0,-(a7)		* ...
+		jsr	_irand			* ...
+		tst.w	(a7)+			* ...
+		movem.l	(a7)+,d1-d2/a0-a2	* ...
+		move.b	d0,PT_PAR3(a2,d2.w)	* set counter
+		beq	act0			* next segment if cntr set to 0
+*
+		bra	act3			* else jump to the point
+*
+act4b:		move.b	PT_PAR2(a2,d2.W),PT_PAR3(a2,d2.W)	* set counter
+		beq	act0			* next segment if cntr set to 0
+*
+		bra	act3			* else jump to the point
+*
+act4a:		subq.b	#1,PT_PAR3(a2,d2.W)	* decrement counter
+		beq	act0			* next segment if cntr ran out
+*
+		bra	act3			* jump if it's still non-zero
+*
+* ------------------------------------------------------------------------------
+* act5 -- AC_KYUP -- jump if key is up
+* ----    ----------------------------
+act5:		move.w	_curpf_f,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* check to see if voice is free
+		move.w	0(a0,d0.W),d0	* ...
+		cmpi.w	#-1,d0		* ...
+		beq	act3		* if so (inactive), do the jump
+*
+		btst	#15,d0		* see if voice is held
+		bne	act0		* continue if so
+*
+		btst	#14,d0		* ...
+		bne	act0		* ...
+*
+		lea	_trgtab,a0	* check trigger table entry
+		tst.b	0(a0,d0.W)	* see if the trigger is active
+		beq	act3		* if not, do the jump
+*
+		bra	act0		* if so, do next segment
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* act6 -- AC_KYDN -- jump if key is down
+* ----    ------------------------------
+act6:		move.w	_curpf_f,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* check to see if voice is free
+		move.w	0(a0,d0.W),d0	* ...
+		cmpi.w	#-1,d0		* ...
+		beq	act0		* if so (inactive), continue
+*
+		btst	#15,d0		* see if voice is held
+		bne	act3		* do jump if so
+*
+		btst	#14,d0		* ...
+		bne	act3		* ...
+*
+		lea	_trgtab,a0	* check trigger table entry
+		tst.b	0(a0,d0.W)	* see if the trigger is active
+		bne	act3		* if so, do the jump
+*
+		bra	act0		* if not, do next segment
+*
+* ------------------------------------------------------------------------------
+act7:		bra	act0		* AC_HERE: treat act7 as AC_NULL
+*
+		.page
+*
+* act1 -- AC_SUST -- pause if key is down (sustain)
+* ----    -----------------------------------------
+act1:		move.w	_curpf_f,d0	* get voice as a word index
+		lsr.w	#3,d0		* ...
+		andi.w	#$001E,d0	* ...
+		lea	_vce2trg,a0	* point at voice to trigger table
+		move.w	0(a0,d0.W),d0	* get trigger table entry
+		cmpi.w	#-1,d0		* see if voice is free
+		beq	act0		* treat as no-op if so
+*
+		btst	#15,d0		* see if voice is held by a pedal
+		bne	act1a		* sustain if so
+*
+		btst	#14,d0		* see if voice is sustained by a pedal
+		bne	act1a		* sustain if so
+*
+		lea	_trgtab,a0	* point at trigger table
+		tst.b	0(a0,d0.W)	* check trigger status
+		beq	act0		* continue if not active
+*
+act1a:		move.l	_pfqhdr,d3	* see if any pflist entries remain
+		beq	act0		* no-op if not  (shouldn't happen ...)
+*
+		move.b	FH_PT1(a1),d0	* get first point number
+		add.b	FH_PIF(a1),d0	* add base to first point
+		subq.b	#1,d0		* make d0 last point number
+		cmp.b	FH_CPT(a1),d0	* check current point number
+		beq	stopfn		* done if this is the last point
+*
+		addq.b	#1,FH_CPT(a1)		* update current point number
+		addi.w	#PT_LEN,d2		* update point index
+		movea.l	d3,a0			* acquire a new pflist entry
+		move.l	(a0),_pfqhdr		* ...
+		move.l	_pflist,(a0)		* ...
+		move.l	a0,_pflist		* ...
+		move.w	FH_TRG(a1),PF_TRIG(a0)	* set trigger number in entry
+		move.w	_curpf_f,PF_FUNC(a0)	* set v/p word in entry
+		movem.l	d1-d2/d4/a1-a3,PF_D1(a0)	* set registers in entry
+		move.b	FH_TMD(a1),d0		* stop the function
+		andi.w	#MSK_RNVB,d0		* ...
+		move.w	d0,d3			* ...
+		add.w	d3,d3			* ...
+		andi.w	#MSK_ONVB,d3		* ...
+		or.w	d3,d0			* ...
+		move.w	d0,F_CTL(a3,d1.W)	* ...
+		bra	pfnext			* go do next list entry
+*
+		.page
+* ------------------------------------------------------------------------------
+		.data
+* ------------------------------------------------------------------------------
+*
+* actab -- action code dispatch table
+* -----    --------------------------
+actab:		dc.l	act0	* 0 - AC_NULL:  no action
+		dc.l	act1	* 1 - AC_SUST:  sustain
+		dc.l	act2	* 2 - AC_ENBL:  enable
+		dc.l	act3	* 3 - AC_JUMP:  unconditional jump
+		dc.l	act4	* 4 - AC_LOOP:  jump n times      (loop)
+		dc.l	act5	* 5 - AC_KYUP:  jump if key up    (enable jump)
+		dc.l	act6	* 6 - AC_KYDN:  jump if key down  (sustain jump)
+		dc.l	act7	* 7 - AC_HERE:  here on key up
+*
+* ------------------------------------------------------------------------------
+		.bss
+* ------------------------------------------------------------------------------
+*
+* ----------------- local variables --------------------------------------------
+*
+_curpf_f:	ds.w	1	* interrupting voice & parameter from FPU
+*
+* ----------------- debug variables --------------------------------------------
+*
+_curpf_t:	ds.w	1	* current trigger
+*
+_curpf_l:	ds.l	1	* current pflist entry
+*
+* ------------------------------------------------------------------------------
+*
+		.end
Index: ram/ptdisp.c
===================================================================
--- ram/ptdisp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ptdisp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,342 @@
+/*
+   =============================================================================
+	ptdisp.c -- MIDAS-VII Patch editor display functions
+	Version 32 -- 1989-11-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "patch.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+extern	short	LineBak(), LineFwd();
+
+extern	short	(*BakLine)(), (*FwdLine)();
+
+extern	unsigned short	pt_alc();
+
+extern	unsigned short	*obj8, *obj9, *obj10, *obj11;
+extern	unsigned short	*LineBuf, *ScObAdr, *OldLine;
+extern	unsigned short	LineAtr;
+
+extern	short	CurLine, CurScan;
+extern	short	ScrlObj, SmScNsl;
+extern	short	PdScDnF, PdScUpF;
+extern	short	ctcsw, submenu;
+extern	short	cxval;
+
+extern	unsigned short	cg3[];
+
+unsigned short	seqflag[16];		/* sequence flags */
+unsigned short	seqline[16];		/* current sequencer line */
+unsigned short	seqstim[16];		/* sequence stimulus */
+unsigned short	seqtime[16];		/* sequence timers */
+unsigned short	sregval[16];		/* register values */
+unsigned short	trstate[16];		/* trigger states */
+
+struct seqent	seqtab[NSLINES];	/* sequence table */
+
+/* 
+
+*/
+
+char	pthead[] = 
+
+	"\260 Definer p ch Stmulus p ch Destnation \275\276 Datum \260 No Seq Rg T \260";
+
+char	*ptmcon[] = {
+
+	"\260 Key  SeqLin  Instr  Index  Level  V Out  Srce  PchWh  Pitch \260",
+	"\260 Rel  SeqCtl  Osc    Freq   Loctn  Depth  Mult  ModWh  Freq  \260",
+	"\260 Trg  Tuning  WaveA  Pitch  Filtr  Rate   Time  Breth  KeyVl \260",
+	"\260 Pls  RegSet  WaveB  Intvl  Fil Q  Inten  Valu  Pedal  KeyPr \260",
+	"\260 LED  RegAdd  Confg  Ratio  Dynmc  Aux    Func  GPC/V  Randm \260"
+};
+
+short	ptabpal[16][3] = {		/* patch display palette */
+
+	{0, 0, 0},	/*  0 - black */
+	{2, 3, 3},	/*  1 - white */
+	{0, 0, 1},	/*  2 - dark blue #1 */
+	{2, 0, 2},	/*  3 - dark violet */
+	{0, 0, 3},	/*  4 - dark blue #2 */
+	{3, 0, 0},	/*  5 - red */
+	{3, 3, 0},	/*  6 - yellow */
+	{1, 2, 0},	/*  7 - dark green */
+	{0, 3, 3},	/*  8 - light blue */
+	{2, 2, 2},	/*  9 - gray */
+	{0, 3, 0},	/* 10 - light green */
+	{3, 1, 2},	/* 11 - light violet */
+	{0, 2, 3},	/* 12 - medium blue */
+	{2, 0, 0},	/* 13 - dark red */
+	{1, 1, 2},	/* 14 - electric purple */
+	{3, 3, 3}	/* 15 - bright white */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptwin() -- fill in a patch table display window
+   =============================================================================
+*/
+
+ptwin(n)
+short n;
+{
+	register short i, j;
+	short atrbuf[64];
+	char  linbuf[66];
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	switch (n) {
+
+	case 0:		/* headings and box outline */
+
+		/* row 0 */
+
+		memset(linbuf, '\261', 63);
+		linbuf[0]  = '\272';
+		linbuf[48] = '\267';
+		linbuf[62] = '\273';
+		linbuf[63] = '\0';
+
+		memsetw(atrbuf, PTBATR, 63);
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj8, 0, 0, linbuf, atrbuf);
+
+		/* row 1 */
+
+		memsetw(atrbuf, PTHATR+0x0100, 64);
+		atrbuf[0]  = PTBATR;
+		atrbuf[1]  = PTHATR;
+		atrbuf[14] = PTHATR;
+		atrbuf[27] = PTHATR;
+		atrbuf[41] = PTHATR;
+		atrbuf[47] = PTHATR;
+		atrbuf[48] = PTBATR;
+		atrbuf[49] = PTHATR;
+		atrbuf[52] = PTHATR;
+		atrbuf[56] = PTHATR;
+		atrbuf[59] = PTHATR;
+		atrbuf[61] = PTHATR;
+		atrbuf[62] = PTBATR;
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj8, 1,  0, pthead, atrbuf);
+/* 
+
+*/
+		/* row 18 */
+
+		memset(linbuf, '\261', 63);
+		linbuf[0]  = '\266';
+		linbuf[48] = '\265';
+		linbuf[62] = '\264';
+		linbuf[63] = '\0';
+
+		memsetw(atrbuf, PTBATR, 63);
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj11, 0, 0, linbuf, atrbuf);
+
+		/* row 24 */
+
+		memset(linbuf, '\261', 63);
+		linbuf[0]  = '\271';
+		linbuf[62] = '\270';
+		linbuf[63] = '\0';
+
+		memsetw(atrbuf, PTBATR, 63);
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj11, 6, 0, linbuf, atrbuf);
+
+		break;
+/* 
+
+*/
+	case 1:		/* patches */
+
+		SetDTop(0, 13);
+
+		for (i = 0; i < 16; i++) {
+
+			for (j = 0; j < 47; j++)
+				linbuf[j] = ' ';
+
+			linbuf[47] = '\0';
+
+			UpdVid(i, 0, "\260", PTBATR);
+
+			UpdVid(i, 1, linbuf,
+				(i EQ 7) ? PTEATR : PTPATR);
+		}
+
+		dptw();
+
+		break;
+/* 
+
+*/
+	case 2:		/* sequence status */
+
+		for (i = 0; i < 16; i++) {
+
+			sprintf(linbuf, "    %03d %02d %d ",
+				seqline[i], sregval[i], trstate[i]);
+
+			vvputsv(obj10, 16, PDBORFG, PDSEQBG,
+				i, 0, "\260", 14, 14, cg3);
+
+			vvputsv(obj10, 16, PDSEQFG, PDSEQBG,
+				i, 1, linbuf, 14, 14, cg3);
+
+			vvputsv(obj10, 16, PDBORFG, PDSEQBG,
+				i, 14, "\260", 14, 14, cg3);
+
+			if (i EQ 7) {
+
+				if (48 EQ XTOC(cxval)) {
+
+					vsplot4(obj10, 16, PDPTRFG,
+						i, 0, "\277", 14, 14, cg3);
+
+				} else {
+
+					vsplot4(obj10, 16, PDPTRFG,
+						i, 0, "\274", 14, 14, cg3);
+				}
+			}
+
+			sprintf(linbuf, "%02d", i + 1);
+
+			vvputsv(obj10, 16,
+				(seqflag[i] & SQF_RUN) ? PDSEQRN : PDSEQFG, PDSEQBG,
+				i, 2, linbuf, 14, 14, cg3);
+		}
+
+		break;
+
+	case 3:		/* menu */
+
+		memsetw(atrbuf, PTMATR, 64);
+		atrbuf[0]  = PTBATR;
+		atrbuf[62] = PTBATR;
+		atrbuf[63] = 0x0000;
+
+		for (i = 0; i < 5; i++)
+			vputsa(obj11, (i + 1), 0, ptmcon[i], atrbuf);
+
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptwins() -- draw the patch table display
+   =============================================================================
+*/
+
+ptwins()
+{
+	register short i;
+
+	for (i = 0; i < 4; i++)
+		ptwin(i);
+}
+
+/*
+   =============================================================================
+	ptdisp() -- setup the patch table display
+   =============================================================================
+*/
+
+ptdisp()
+{
+	dswap();				/* clear the video display */
+
+	BakLine = LineBak;
+	FwdLine = LineFwd;
+
+	/* setup object pointers */
+
+	obj8  = &v_score[OB08LOC];		/*  8 - headings */
+	obj9  = &v_score[OB09LOC];		/*  9 - patches */
+	obj10 = &v_score[OB10LOC];		/* 10 - status */
+	obj11 = &v_score[OB11LOC];		/* 11 - menu */
+
+	ScrlObj = 9;
+	ScObAdr = obj9;
+	LineBuf = obj9;
+	OldLine = (unsigned short *)NULL;
+	LineAtr = PTPATR;
+
+	CurLine = 0;
+	CurScan = 13;
+
+	PdScDnF = FALSE;
+	PdScUpF = FALSE;
+
+	/* ---------------- initialize object table -------------------- */
+	/*     obj,  typ, bnk,  base, xpix, ypix,  x0,  y0,   flags, pri */
+
+	SetObj(  8,    1,   0,  obj8,  512,   28,   0,   0, PDFL_08, -1);
+	SetObj(  9,    1,   0,  obj9,  384,  224,   0,  28, PDFL_09, -1);
+	SetObj( 10,    0,   0, obj10,  128,  224, 384,  28, PDFL_10, -1);
+	SetObj( 11,    1,   0, obj11,  512,   98,   0, 252, PDFL_11, -1);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	memsetw(v_score, 0, 32767);		/* clear display objects */
+	memsetw(v_score+32767L, 0, 24577);
+
+	voidpb();				/* void the patch buffer */
+	ptwins();				/* fill up the windows */
+
+/* 
+
+*/
+	/* display some objects */
+
+	SetPri( 8,  8);				/* headings */
+	SetPri( 9,  9);				/* patches */
+	SetPri(10,  10);			/* sequence status */
+	SetPri(11,  11);			/* menu */
+
+	if (v_regs[5] & 0x0180)			/* select bank 0 */
+		vbank(0);
+
+	memcpyw(v_cgtab, cg3, 3584);		/* setup character generator */
+	v_regs[1] = (v_regs[1] & 0x0FFF) | 0xE000;
+
+	/* fix the initial scan line specs in the object descriptor table */
+
+	v_odtab[ 8][0] = (v_odtab[ 8][0] & 0x0FFF) | 0xD000;
+	v_odtab[ 9][0] = (v_odtab[ 9][0] & 0x0FFF) | 0xD000;
+
+	v_odtab[11][0] = (v_odtab[11][0] & 0x0FFF) | 0xD000;
+
+	submenu = FALSE;
+
+	ctcsw = TRUE;				/* enable cursor */
+	ctcpos(DATAROW, 2);				/* set initial cursor */
+	aftercm();				/* set initial submenu */
+
+	vsndpal(ptabpal);			/* set the palette */
+}
Index: ram/ptdkey.c
===================================================================
--- ram/ptdkey.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ptdkey.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1398 @@
+/*
+   =============================================================================
+	ptdkey.c -- MIDAS-VII patch display data entry functions
+	Version 29 -- 1988-12-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGPD		0
+#define	DEBUGVP		0
+#define	DUMPDEF		0
+#define	DUMPSTM		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "fields.h"
+#include "curpak.h"
+#include "patch.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#if	DEBUGPD
+short	debugpd = 1;
+short	snappb  = 0;
+#endif
+
+#if	DEBUGVP
+short	debugvp = 1;
+#endif
+
+#if	DUMPDEF
+short	dumpdef = 0;
+#endif
+
+#if	DUMPSTM
+short	dumpstm = 0;
+#endif
+
+#if	(DEBUGPD|DEBUGVP|DUMPDEF|DUMPSTM)
+extern	short	debugsw;
+#endif
+
+extern	short	asig, astat;
+
+extern	short	dpepred, dpecpos, dpesucc;
+
+extern	short	ptegood, ptedfok, ptestok, ptedsok, ptedtok;
+
+extern	short	ptedef, ptestm, ptespec, ptesuba, ptedat1, ptedat2;
+
+extern	short	ptedftp, ptedfst, ptedest, ptedata;
+
+extern	short	pteset, ptbflag, ptemenu;
+
+extern	short	ptepred, ptecpos, ptesucc;
+
+extern	short	stccol, stcrow;
+
+extern	char	ptdebuf[50];
+
+extern	struct patch	ptebuf;
+
+/* 
+
+*/
+
+short	dsdecol[5][2][2] =  {	/* destination data entry column table */
+
+	 6,  8, 19, 21,		/* 0 -- key, rel -- key number */
+	 7,  8, 20, 21,		/* 1 -- trg -- trigger number */
+	 8,  8, 21, 21,		/* 2 -- pls -- pulse number */
+	10, 10, 23, 23,		/* 3 -- key, rel -- port number */
+	12, 13, 25, 26 		/* 4 -- key, rel -- channel number */
+};
+
+short	des2fmt[] = {		/* destination type to data entry format */
+
+	-1,	0,	1,	2,	3,	4,	4,	5,
+	4,	4,	6,	9,	6,	6,	6,	10,
+	9,	9,	10,	10,	10,	10,	7,	7,
+	7,	7,	8
+};
+
+short	dtabl7[] = { 11, 1, 2, 3, 10 };		/* aux datum format table */
+
+short	dtabl9[] = { 11, 1, 2, 3, 9 };		/* FPU datum format table */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SnapPTV() -- snap dump patch variables
+   =============================================================================
+*/
+
+SnapPTV(s)
+char *s;
+{
+	register unsigned short stim;
+	register short i;
+	char dbuf[50];
+
+	printf("\n%s():  called SnapPTV()\n", s);
+
+	memcpy(dbuf, ptdebuf, 48);
+
+	for (i = 0; i < 48; i++)
+		if (dbuf[i] EQ '\0')
+			dbuf[i] = ' ';
+		else if (dbuf[i] & 0x0080)
+			dbuf[i] = '~';
+
+	dbuf[48] = '\0';
+
+	printf("  ptdebuf = \"%s\"\n", dbuf);
+
+	printf("  pte  $%04.4X $%04.4X   $%04.4X $%04.4X   $%04.4X $%04.4X\n",
+		ptedef, ptestm, ptespec, ptesuba, ptedat1, ptedat2);
+
+	printf("  ptb  $%04.4X $%04.4X   $%04.4X $%04.4X   $%04.4X $%04.4X\n",
+		ptebuf.defnum, ptebuf.stmnum, ptebuf.paspec,
+		ptebuf.pasuba, ptebuf.padat1, ptebuf.padat2);
+
+	printf("  pte  dftp: %2d  dfst: %2d  dest: %2d  data: %2d  menu: %2d\n",
+		ptedftp, ptedfst, ptedest, ptedata, ptemenu);
+
+	printf("  pte  good: %d  dfok: %d  stok: %d  dsok: %d  dtok: %d  set: %d  flag: %d\n",
+		ptegood, ptedfok, ptestok, ptedsok, ptedtok, pteset, ptbflag);
+
+	printf("  pte  pred: %3d  cpos: %3d  succ: %3d\n",
+		ptepred, ptecpos, ptesucc);
+
+/* 
+
+*/
+
+#if	DUMPDEF
+
+	if (dumpdef) {
+
+		printf("  dpe  pred: %3d  cpos: %3d  succ: %3d\n",
+			dpepred, dpecpos, dpesucc);
+
+		for (stim = 0; stim < NDEFSTMS; stim++) {
+
+			if (defptr[stim]) {
+
+				printf("  defptr[$%04.4X] = %3d%s\n",
+					stim, defptr[stim],
+					((TRG_MASK & ptedef) EQ stim) ?
+						" <-- ptedef" : "");
+			}
+		}
+	}
+#endif
+
+#if	DUMPSTM
+	if (dumpstm) {
+
+		for (stim = 0; stim < NDEFSTMS; stim++)
+			if (stmptr[stim])
+				printf("  stmptr[$%04.4X] = %3d%s\n",
+					stim, stmptr[stim],
+					((TRG_MASK & ptestm) EQ stim) ?
+						" <-- ptestm" : "");
+	}
+#endif
+
+	printf("\n");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	buf2pte() -- pack the patch buffer
+   =============================================================================
+*/
+
+buf2pte()
+{
+	ptebuf.defnum = ptedef;
+	ptebuf.stmnum = ptestm;
+	ptebuf.paspec = ptespec;
+	ptebuf.pasuba = ptesuba;
+	ptebuf.padat1 = ptedat1;
+	ptebuf.padat2 = ptedat2;
+
+	pteset = TRUE;
+
+#if	DEBUGPD
+	if (debugsw AND debugpd) {
+
+		if (snappb)
+			SnapPTV("buf2pte");
+
+		printf("buf2pte():  ptebuf setup\n");
+	}
+#endif
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	voidpb() -- void the patch buffer
+   =============================================================================
+*/
+
+voidpb()
+{
+	memset(ptdebuf, ' ', 50);		/* clear data entry buffer */
+
+	ptebuf.defnum = ptedef  = NULL_DEF;	/* blank definer */
+	ptebuf.stmnum = ptestm  = 0x0000;
+	ptebuf.paspec = ptespec = 0x0000;
+	ptebuf.pasuba = ptesuba = 0x0000;
+	ptebuf.padat1 = ptedat1 = 0x0000;
+	ptebuf.padat2 = ptedat2 = 0x0000;
+
+	ptbflag = FALSE;
+
+	pteset  = FALSE;
+
+	ptegood = FALSE;
+
+	ptedfok = TRUE;		/* definer is OK until it's screwed up */
+	ptestok = FALSE;
+	ptedsok = FALSE;
+	ptedtok = FALSE;
+
+	ptedfst = -1;
+	ptedest = -1;
+	ptedata = -1;
+
+#if	DEBUGVP
+	if (debugsw AND debugvp) {
+
+		if (snappb)
+			SnapPTV("voidpb");
+
+		printf("voidpb():  patch buffer VOIDED\n");
+	}
+#endif
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+
+   =============================================================================
+*/
+
+setptcv()
+{
+	register unsigned short spec;
+
+	ptedest = des2fmt[spec = ptespec & PE_SPEC];
+
+	switch (ptedest) {		/* setup datum entry format */
+
+	case 0:		/* key */
+	case 2:		/* pulse */
+
+		ptedata = 8;
+		break;
+
+	case 1:		/* trigger */
+
+		ptedata = 9;
+		break;
+
+	case 3:		/* led */
+
+		ptedata = 14;
+		break;
+/* 
+
+*/
+	case 4:		/* seq, reg */
+
+		if (spec EQ PA_SLIN)
+			ptedata = 13;
+		else if (spec EQ PA_SCTL)
+			ptedata = 9;
+		else
+			ptedata = 12;
+
+		break;
+
+	case 5:		/* tuning */
+
+		ptedata = 18;
+		break;
+
+	case 6:		/* inst, wave, config */
+
+		if (spec EQ PA_INST)
+			ptedata = 15;
+		else if (spec EQ PA_CNFG)
+			ptedata = 17;
+		else
+			ptedata = 16;
+
+		break;
+
+	case 7:		/* aux, rate, inten, dpth */
+	case 8:		/* vout */
+
+		ptedata = dtabl7[ptedat1];
+		break;
+
+	case 9:		/* osc, ind, frq */
+	case 10:	/* level, filtr, fil q, loctn, dynmc */
+
+		if (spec EQ PA_OSC)
+			ptedata = ptedat1 + 4;
+		else
+			ptedata = dtabl9[ptedat1];
+
+		break;
+
+	default:	/* something weird got in here somehow ... */
+
+#if	DEBUGPD
+	if (debugsw AND debugpd)
+		printf("setptcv():  BAD ptedest ($%04.4X),  spec = $%04.4X\n",
+			ptedest, spec);
+#endif
+
+		ptedata = -1;
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pte2buf() -- convert ptebuf to ptdebuf format and load edit variables
+   =============================================================================
+*/
+
+pte2buf()
+{
+	register unsigned short spec;
+
+	memset(ptdebuf, ' ', 50);
+
+	ptbflag = TRUE;
+
+	if (pteset) {				/* if ptebuf is valid ... */
+
+		ptedef  = ptebuf.defnum;	/* ... setup the edit variables */
+		ptestm  = ptebuf.stmnum;
+		ptespec = ptebuf.paspec;
+		ptesuba = ptebuf.pasuba;
+		ptedat1 = ptebuf.padat1;
+		ptedat2 = ptebuf.padat2;
+
+		setptcv();			/* setup control variables */
+
+		dspdfst(&ptdebuf[ 2], ptedef);	/* setup the patch buffer */
+		dspdfst(&ptdebuf[15], ptestm);
+		dspdest(&ptdebuf[28], &ptebuf);
+		ptdebuf[ 0] = ' ';
+		ptdebuf[ 1] = ' ';
+		ptdebuf[14] = ' ';
+		ptdebuf[27] = ' ';
+
+/* 
+
+*/
+		ptegood = TRUE;			/* validate the patch buffer */
+		ptedfok = TRUE;
+		ptestok = TRUE;
+		ptedsok = TRUE;
+		ptedtok = TRUE;
+
+#if	DEBUGPD
+	if (debugsw AND debugpd) {
+
+		if (snappb)
+			SnapPTV("pte2buf");
+
+		printf("pte2buf():  patch buffer LOADED\n");
+	}
+#endif
+
+	} else {
+
+		voidpb();			/* void the patch buffer */
+
+#if	DEBUGPD
+	if (debugsw AND debugpd)
+		printf("pte2buf():  patch buffer VOIDED\n");
+#endif
+
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptde_ds() -- digit data entry for definer / stimulus fields
+   =============================================================================
+*/
+
+ptde_ds(n, key)
+register short n, key;
+{
+	register short chan, port, stim;
+	char buf[8], buf2[8];
+
+	if (n ? ptestok : ptedfok) {
+
+		if ((n EQ 0) AND (ptedef EQ 0xFFFF))
+			return;
+
+		port = ((n ? ptestm : ptedef) >> 11) & 0x0003;
+		chan = ((n ? ptestm : ptedef) >>  7) & 0x000F;
+		stim =  (n ? ptestm : ptedef)        & 0x007F;
+
+		if ((port EQ 0) OR (port EQ 1) OR ((port EQ 2) AND (chan < 2))) {
+
+			/* Key / Rel */
+
+			if (inrange(stccol, dsdecol[0][n][0], dsdecol[0][n][1]) OR
+			    inrange(stccol, dsdecol[3][n][0], dsdecol[3][n][1]) OR
+			    inrange(stccol, dsdecol[4][n][0], dsdecol[4][n][1])) {
+
+				if (stccol EQ dsdecol[3][n][1]) {
+
+					if ((key < 1) OR (key > 3))
+						return;
+
+					if (key EQ 3) {
+
+						buf[0] = 'L';
+						UpdVid(7, n ? 25 : 12, "  ", PTDATR);
+
+						if (n)
+							ptestm &= 0xF87F;
+						else
+							ptedef &= 0xF87F;
+
+					} else {
+
+						sprintf(buf2, "%02d", 1 + chan);
+						buf[0] = key + '0';
+						UpdVid(7, n ? 25 : 12, buf2, PTDATR);
+					}
+/* 
+
+*/
+					port = key - 1;
+
+					if (n)
+						ptestm = (ptestm & 0xE7FF) | (port << 11);
+					else
+						ptedef = (ptestm & 0xE7FF) | (port << 11);
+
+				} else {
+
+					buf[0] = key + '0';
+				}
+
+				ptdebuf[stccol] = buf[0];
+				buf[1] = '\0';
+
+				UpdVid(7, stccol, buf, PTDATR);
+
+				if (stccol EQ dsdecol[4][n][1]) {
+
+					ctcon();
+					return;
+				}
+
+				if ((stccol EQ dsdecol[0][n][1]) OR
+				    (stccol EQ dsdecol[3][n][1]))
+					++stccol;
+
+				movectc(stcrow, ++stccol);
+			}
+
+			return;
+/* 
+
+*/
+		} else if ((port EQ 2) AND (chan EQ 2)) {
+
+			/* Trig */
+
+			if (inrange(stccol, dsdecol[1][n][0], dsdecol[1][n][1])) {
+
+				ptdebuf[stccol] = key + '0';
+				buf[0] = key + '0';
+				buf[1] = '\0';
+
+				UpdVid(7, stccol, buf, PTDATR);
+
+				if (stccol EQ dsdecol[1][n][1]) {
+
+					ctcon();
+					return;
+				}
+
+				movectc(stcrow, ++stccol);
+			}
+
+			return;
+
+		} else if ((port EQ 2) AND (chan EQ 3)) {
+
+			/* Pulse */
+
+			if (stccol EQ dsdecol[2][n][1]) {
+
+				if ((key < 1) OR (key > 2))
+					return;
+
+				ptdebuf[stccol] = key + '0';
+				buf[0] = key + '0';
+				buf[1] = '\0';
+
+				UpdVid(7, stccol, buf, PTDATR);
+				ctcon();
+			}
+
+			return;
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptdkey() -- patch digit data entry function
+   =============================================================================
+*/
+
+ptdkey()
+{
+	register short key, val, vg;
+	char buf[8];
+
+	if (NOT astat)			/* only do this on key closures */
+		return;
+
+	if (NOT ptbflag)		/* load up the edit buffer */
+		pte2buf();
+
+	key = asig - 60;
+
+	if (inrange(stccol, 2, 13)) {		/* DEFINER */
+
+		ptde_ds(0, key);
+		return;
+
+	} else if (inrange(stccol, 15, 26)) {	/* STIMULUS */
+
+		ptde_ds(1, key);
+		return;
+/* 
+
+*/
+	} else if (inrange(stccol, 28, 40)) {	/* DESTINATION */
+
+		if (ptedsok) {
+
+			switch (ptedest) {
+
+			case 0:		/* key */
+
+				if (inrange(stccol, 30, 32) OR
+				    (stccol EQ 34) OR
+				    inrange(stccol, 36, 37)) {
+
+					if (stccol EQ 34) {
+
+						if ((key < 1) OR (key > 3))
+							return;
+
+						if (key EQ 3)
+							buf[0] = 'L';
+						else
+							buf[0] = key + '0';
+
+					} else {
+
+						buf[0] = key + '0';
+					}
+
+					ptdebuf[stccol] = buf[0];
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+
+					if ((stccol EQ 32) OR (stccol EQ 34))
+						++stccol;
+
+					if (stccol EQ 37)
+						ctcon();
+					else
+						movectc(stcrow, ++stccol);
+				}
+
+				return;
+/* 
+
+*/
+			case 1:		/* trg */
+
+				if (inrange(stccol, 36, 37)) {
+
+					ptdebuf[stccol] = key + '0';
+					buf[0] = key + '0';
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+
+					if (stccol EQ 37)
+						ctcon();
+					else
+						movectc(stcrow, ++stccol);
+				}
+
+				return;
+
+			case 2:		/* pls */
+
+				if (stccol EQ 34) {
+
+					if ((key < 1) OR (key > 2))
+						return;
+
+					ptdebuf[stccol] = key + '0';
+					buf[0] = key + '0';
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+					ctcon();
+				}
+
+				return;
+/* 
+
+*/
+			case 3:		/* led */
+
+				if (stccol EQ 32) {
+
+					if (key > 6)
+						return;
+
+					ptdebuf[stccol] = key + 'A';
+					buf[0] = key + 'A';
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+					ctcon();
+				}
+
+				return;
+
+			case 4:		/* seqlin, seqctl, regset, regadd */
+
+				if (inrange(stccol, 32, 33)) {
+
+					ptdebuf[stccol] = key + '0';
+					buf[0] = key + '0';
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+
+					if (stccol EQ 33)
+						ctcon();
+					else
+						movectc(stcrow, ++stccol);
+				}
+
+				return;
+/* 
+
+*/
+			case 5:		/* tune */
+			case 7:		/* aux, rate, inten, depth */
+
+				return;
+
+			case 8:		/* v out */
+
+				if (stccol EQ 32) {
+
+					if ((key < 1) OR (key > 5))
+						return;
+
+					ptdebuf[stccol] = key + '0';
+					buf[0] = key + '0';
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+					movectc(DATAROW, 34);
+				}
+
+				return;
+
+			case 9:		/* osc, index, freq */
+
+				if (stccol EQ 32) {
+
+					if ((key < 1) OR (key > 4))
+						return;
+
+					ptdebuf[stccol] = key + '0';
+					buf[0] = key + '0';
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+					movectc(DATAROW, 34);
+					return;
+				}
+
+				/* FALL-THROUGH to handle v/g in columns 39..40 */
+/* 
+
+*/
+			case 6:		/* inst, wava, wavb, conf */
+			case 10:	/* level, filtr, fil q, loctn, dynmc */
+
+				if (inrange(stccol, 39, 40)) {
+
+					vg = (ptesuba >> 8) & 0x00FF;
+
+					if (stccol EQ 39) {
+
+						if ((key EQ 8) OR (key EQ 9)) {
+
+							if (vg > 11) {
+
+								vg -= 12;
+								val = 'V';
+
+							} else {
+
+								vg += 12;
+								val = 'G';
+							}
+
+							ptesuba = (ptesuba & 0x00FF) |
+								  (vg << 8);
+
+						} else {
+
+							return;
+						}
+/* 
+
+*/
+					} else {	/* column 40 */
+
+						if ( ((vg EQ 0) OR (vg EQ 12)) AND
+						     ((key EQ 0) OR (key EQ 1) OR (key EQ 2)) )
+							key += 10;
+						else if (key EQ 0)
+							return;
+
+						val = key + ((key > 9) ? '\242' :'0') ;
+
+						--key;
+
+						if (vg > 11)
+							vg = key + 12;
+						else
+							vg = key;
+
+						ptesuba = (ptesuba & 0x00FF) |
+							  (vg << 8);
+					}
+
+					ptdebuf[stccol] = val;
+					buf[0] = val;
+					buf[1] = '\0';
+
+					UpdVid(7, stccol, buf, PTDATR);
+
+					if (stccol EQ 40)
+						ctcon();
+					else
+						movectc(stcrow, ++stccol);
+				}
+
+				return;
+
+			default:	/* Eh ? */
+
+				return;
+			}
+		}
+/* 
+
+*/
+	} else if (inrange(stccol, 42, 46)) {	/* DATUM */
+
+		switch (ptedata) {
+
+		case 1:		/* multiplier -- +1.00 */
+
+			switch (stccol) {
+
+			case 42:	/* + | - */
+
+				if (key EQ 8)
+					buf[0] = '-';
+				else if (key EQ 9)
+					buf[0] = '+';
+				else
+					return;
+
+				break;
+
+			case 43:	/* 0 | 1 */
+
+				if ((key EQ 0) OR (key EQ 1))
+					buf[0] = key + '0';
+				else
+					return;
+
+				break;
+
+			case 45:	/* 0..9 */
+			case 46:	/* 0..9 */
+
+				buf[0] = key + '0';
+				break;
+
+			case 44:	/* . */
+			default:
+
+				return;
+			}
+/* 
+
+*/
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 43)
+				++stccol;
+
+			if (stccol EQ 46)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 2:		/* time -- 32767 */
+
+			if ((stccol EQ 42) AND (key > 3))
+				return;
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 46)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+
+/* 
+
+*/
+		case 3:		/* value -- +10.00 */
+
+			switch (stccol) {
+
+			case 42:
+
+				if (key EQ 8) {
+
+					if (ptdebuf[42] EQ '\240')
+						buf[0] = '\241';
+					else if (ptdebuf[42] EQ '\241')
+						buf[0] = '\241';
+					else
+						buf[0] = '-';
+
+				} else if (key EQ 9) {
+
+					if (ptdebuf[42] EQ '\240')
+						buf[0] = '\240';
+					else if (ptdebuf[42] EQ '\241')
+						buf[0] = '\240';
+					else
+						buf[0] = '+';
+
+				} else if (key EQ 0) {
+
+					if (ptdebuf[42] EQ '\240')
+						buf[0] = '+';
+					else if (ptdebuf[42] EQ '\241')
+						buf[0] = '-';
+					else
+						return;
+
+				} else if (key EQ 1) {
+
+					if (ptdebuf[42] EQ '\240')
+						buf[0] = '\240';
+					else if (ptdebuf[42] EQ '\241')
+						buf[0] = '\241';
+					else if (ptdebuf[42] EQ '+')
+						buf[0] = '\240';
+					else if (ptdebuf[42] EQ '-')
+						buf[0] = '\241';
+					else
+						return;
+
+				} else
+					return;
+
+				break;
+/* 
+
+*/
+			case 43:
+			case 45:
+			case 46:
+
+				buf[0] = key + '0';
+				break;
+
+			case 44:
+			default:
+				return;
+			}
+
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 43)
+				++stccol;
+
+			if (stccol EQ 46)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 4:		/* interval -- +1200 */
+
+			if (stccol EQ 42) {
+
+				if (key EQ 8)
+					buf[0] = '-';
+				else if (key EQ 9)
+					buf[0] = '+';
+				else
+					return;
+
+			} else if (stccol EQ 43) {
+
+				if (key > 1)
+					return;
+				else
+					buf[0] = key + '0';
+
+			} else {
+
+				buf[0] = key + '0';
+			}
+
+			ptdebuf[stccol] = buf[0];
+			buf[1] = '\0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 46)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 5:		/* ratio -- 9/9 */
+
+			switch (stccol) {
+
+			case 42:
+			case 44:
+
+				buf[0] = key +'0';
+				break;
+
+			case 43:
+			case 45:
+			case 46:
+
+				return;
+			}
+
+			ptdebuf[stccol] = buf[0];
+			buf[1] = '\0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 42)
+				++stccol;
+
+			if (stccol EQ 44)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 6:		/* frequency -- 15.9 */
+
+			switch (stccol) {
+
+			case 42:
+
+				if (key > 1)
+					return;
+
+				/* FALL-THROUGH */
+
+			case 43:
+			case 45:
+
+				buf[0] = key + '0';
+				break;
+
+			case 44:
+			case 46:
+
+				return;
+			}
+
+			ptdebuf[stccol] = buf[0];
+			buf[1] = '\0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 43)
+				++stccol;
+
+			if (stccol EQ 45)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 7:		/* pitch -- 9C#99 */
+
+			switch (stccol) {
+
+			case 43:
+
+				if (key > 6)
+					return;
+
+				buf[0] = key + 'A';
+				break;
+
+			case 44:
+
+				if (key EQ 7)
+					buf[0] = ' ';
+				else if (key EQ 8)
+					buf[0] = '\251';
+				else if (key EQ 9)
+					buf[0] = '\250';
+				else
+					return;
+
+				break;
+
+			case 42:
+			case 45:
+			case 46:
+
+				buf[0] = key + '0';
+				break;
+			}
+
+			ptdebuf[stccol] = buf[0];
+			buf[1] = '\0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 46) 
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 8:		/* trans | stop | start */
+
+			switch (key) {
+
+			case 7:		/* trans */
+
+				strcpy(buf, "Trans");
+				ptedat2 = 0;
+				break;
+
+			case 8:		/* stop */
+
+				strcpy(buf, "Stop ");
+				ptedat2 = 1;
+				break;
+
+			case 9:		/* start */
+
+				strcpy(buf, "Start");
+				ptedat2 = 2;
+				break;
+
+			default:
+
+				return;
+			}
+
+			strcpy(&ptdebuf[42], buf);
+			UpdVid(7, 42, buf, PTDATR);
+			movectc(stcrow, 46);
+			return;
+/* 
+
+*/
+		case 9:		/* stop | start */
+
+			if (key EQ 8) {			/* stop */
+
+				strcpy(buf, "Stop ");
+				ptedat2 = 0;
+
+			} else if (key EQ 9) {		/* start */
+
+				strcpy(buf, "Start");
+				ptedat2 = 1;
+
+			} else {
+
+				return;
+			}
+
+			strcpy(&ptdebuf[42], buf);
+			UpdVid(7, 42, buf, PTDATR);
+			movectc(stcrow, 46);
+			return;
+
+		case 10:	/* off | on */
+
+			if (key EQ 8) {			/* off */
+
+				strcpy(buf, "Off   ");
+				ptedat2 = 0;
+
+			} else if (key EQ 9) {		/* on */
+
+				strcpy(buf, "On   ");
+				ptedat2 = 1;
+
+			} else {
+
+				return;
+			}
+
+			strcpy(&ptdebuf[42], buf);
+			UpdVid(7, 42, buf, PTDATR);
+			movectc(stcrow, 46);
+			return;
+/* 
+
+*/
+		case 11:	/* source */
+
+			return;
+
+		case 12:	/* register | value */
+
+			switch (stccol) {
+
+			case 42:
+
+				if (key EQ 7)
+					buf[0] = 'R';
+				else if (key EQ 8 AND ((PE_SPEC & ptespec) NE PA_RSET))
+					buf[0] = '-';
+				else if (key EQ 9)
+					buf[0] = '+';
+				else
+					return;
+
+				break;
+
+			case 43:
+			case 44:
+
+				buf[0] = key + '0';
+				break;
+
+			default:
+
+				return;
+			}
+
+			ptdebuf[stccol] = buf[0];
+			buf[1] = '\0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 44)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 13:	/* sequence line */
+
+			if (stccol > 44)
+				return;
+
+			buf[0] = key + '0';
+			ptdebuf[stccol] = buf[0];
+			buf[1] = '\0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 44)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+
+		case 14:	/* LED controls */
+
+			if ((key > 3) OR (stccol EQ 46))
+				return;
+
+			if ((stccol EQ 45) AND (0 EQ (ptesuba & 0x0001)))
+				return;
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (((ptesuba & 0x0001) AND (stccol EQ 45)) OR
+			    ((0 EQ ptesuba & 0x0001) AND (stccol EQ 44)))
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 15:	/* instrument number */
+
+			if (stccol > 43)
+				return;
+
+			if ((stccol EQ 42) AND (key > 4))
+				return;
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 43)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 16:	/* waveshape number */
+
+			if (stccol > 43)
+				return;
+
+			if ((stccol EQ 42) AND (key > 2))
+				return;
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 43)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+
+		case 17:	/* configuration number */
+
+			if (stccol > 43)
+				return;
+
+			if ((stccol EQ 42) AND (key > 1))
+				return;
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (stccol EQ 43)
+				ctcon();
+			else
+				movectc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case 18:	/* tuning table number */
+
+			if (stccol > 42)
+				return;
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			ptdebuf[stccol] = buf[0];
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			ctcon();
+			return;
+
+		default:
+
+			return;
+		}
+	}
+}
Index: ram/ptfield.c
===================================================================
--- ram/ptfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ptfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,979 @@
+/*
+   =============================================================================
+	ptfield.c -- MIDAS-VII patch display field functions
+	Version 35 -- 1989-11-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGXP		0
+
+#define	USEVECTR	0	/* to force vector cursor control */
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "fields.h"
+#include "curpak.h"
+#include "patch.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#if	DEBUGXP
+extern	short	debugsw;
+
+short	debugxp = 1;
+#endif
+
+#if	USEVECTR
+short	usevect = TRUE;
+
+extern	short	(*cx_key)(), (*cy_key)();
+#endif
+
+extern	short	(*xy_up)(), (*xy_dn)();
+extern	short	(*premove)(), (*pstmove)();
+extern	short	(*curtype)();
+
+extern	unsigned short	fromfpu();
+
+extern	short	select(), nokey(), stdctp5();
+extern	short	cxkstd(), cykstd(), stdmkey(), stddkey();
+extern	short	stopcm(), smxupd(), smyupd();
+extern	short	aftercm();
+extern	short	ptdkey();
+
+extern	short	astat;
+extern	short	chtime;
+extern	short	chwait;
+extern	short	cmfirst;
+extern	short	cmtype;
+extern	short	curhold;
+extern	short	cvtime;
+extern	short	cvwait;
+extern	short	ncvwait;
+extern	short	ptbflag;
+extern	short	ptecpos;
+extern	short	ptedef;
+extern	short	ptedfok;
+extern	short	pteset;
+extern	short	ptestm;
+extern	short	ptestok;
+extern	short	ss_ptsw;
+extern	short	ss_sqsw;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	syrate;
+extern	short	tvcwval;
+extern	short	vcwval;
+
+extern	short	crate1[];
+
+extern	char	ptdebuf[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	ptboxes[];
+
+extern	struct	patch	ptebuf;
+
+short	ptxkey();		/* forward reference */
+short	ptmkey();		/* forward reference */
+short	ptekey();		/* forward reference */
+
+/* 
+
+*/
+
+char	*trdata[] = {	"Trans", "Stop ", "Start"	 };
+char	*ssdata[] = {	"Stop ", "Start" };
+
+char	*stdata[] = {	"Srce" , "Mult", "Time", "Valu", "Func"	};
+
+char	*smdata[] = {
+
+	"     ",	/* SM_NONE	0	No source - always 0 */
+	"Randm",	/* SM_RAND	1	Random source */
+	"GPC/V",	/* SM_CTL1	2	Control Voltage 1 / MIDI GPC 1 */
+	"??3??",	/* -------	3	-unused- */
+	"??4??",	/* -------	4	-unused- */
+	"Pitch",	/* SM_PTCH	5	Key Pitch */
+	"KeyPr",	/* SM_KPRS	6	Key Pressure */
+	"KeyVL", 	/* SM_KVEL	7	Key Velocity */
+	"Pedal",	/* SM_PED1	8	Pedal 1 */
+	"??9??",	/* -------	9	-unused- */
+	"Freq ",	/* SM_FREQ	10	Key Frequency */
+	"PchWh",	/* SM_HTPW	11	Tablet X / MIDI Pitch Wheel */
+	"ModWh",	/* SM_VTMW	12	Tablet Y / MIDI Mod Wheel */
+	"Breth", 	/* SM_LPBR	13	LongPot / MIDI Breath Controller */
+};
+
+struct curpak pt_flds = {
+
+	stdctp5,		/* curtype */
+	nokey,			/* premove */
+	aftercm,		/* pstmove */
+	cxkstd,			/* cx_key */
+	cykstd,			/* cy_key */
+	smxupd,			/* cx_upd */
+	smyupd,			/* cy_upd */
+	stopcm,			/* xy_up */
+	nokey,			/* xy_dn */
+	ptxkey,			/* x_key */
+	ptekey,			/* e_key */
+	ptmkey,			/* m_key */
+	ptdkey,			/* d_key */
+	nokey,			/* not_fld */
+	(struct fet *)NULL,	/* curfet */
+	ptboxes,		/* csbp */
+	crate1,			/* cratex */
+	crate1,			/* cratey */
+	CT_SMTH,		/* cmtype */
+	CTOX(2),		/* cxval */
+	RTOY(DATAROW)		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptmkey() -- M key processing for the patch display
+   =============================================================================
+*/
+
+ptmkey()
+{
+	register short nc;
+
+	if (astat) {
+
+		if (stccol EQ 48) {
+
+			if (ss_sqsw EQ 0) {
+
+				(*xy_dn)();		/* handle KEY_DOWN functions */
+
+				(*premove)();		/* handle PRE-MOVE functions */
+
+				nc = (*curtype)();	/* get new CURSOR TYPE wanted */
+
+				cvtime  = syrate;
+				ncvwait = curhold;
+
+				ss_ptsw = -1;
+				cmtype  = nc;
+				cvwait  = 1;
+			}
+
+		} else 
+			stdmkey();
+
+	} else {
+
+		if (stccol EQ 48) {
+
+			ss_ptsw = 0;
+			cvwait  = 1;
+			ncvwait = cvtime;
+			cmfirst = TRUE;
+
+			if (ss_sqsw EQ 0)
+				(*xy_up)();
+
+			(*pstmove)();		/* handle POST-MOVE functions */
+
+		} else
+			stdmkey();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptekey() -- E key processing for the patch display
+   =============================================================================
+*/
+
+ptekey()
+{
+	register short nc;
+
+	if (astat) {
+
+		if (stccol EQ 48) {
+
+			if (ss_sqsw EQ 0) {
+
+				(*xy_dn)();		/* handle KEY_DOWN functions */
+
+				(*premove)();		/* handle PRE-MOVE functions */
+
+				nc = (*curtype)();	/* get new CURSOR TYPE wanted */
+
+				cvtime  = syrate;
+				ncvwait = curhold;
+
+				ss_ptsw = 1;
+				cmtype  = nc;
+				cvwait  = 1;
+			}
+
+		} else
+			select();
+
+	} else {
+
+		if (stccol EQ 48) {
+
+			ss_ptsw = 0;
+			cvwait  = 1;
+			ncvwait = cvtime;
+			cmfirst = TRUE;
+
+			if (ss_sqsw EQ 0)
+				(*xy_up)();
+
+			(*pstmove)();		/* handle POST-MOVE functions */
+
+		} else
+			select();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptxkey() -- X key processing for the patch display
+   =============================================================================
+*/
+
+ptxkey()
+{
+	register short i, cp, pp, sp, stm;
+
+	if (NOT astat)				/* only on key closures ... */
+		return;
+
+	if (inrange(stccol, 2, 13)) {			/* definer -- clear definer */
+
+		if (ptecpos AND NOT ptbflag) {		/* refresh data entry stuff */
+
+			memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+			pteset = TRUE;
+			pte2buf();
+		}
+
+		ptedef 	= NULL_DEF;
+		ptedfok = TRUE;
+
+		memset(&ptdebuf[2], ' ', 12);
+
+		for (i = 0; i < 48; i++)
+			if (ptdebuf[i] EQ '\0')
+				ptdebuf[i] = ' ';
+
+		ptdebuf[0] = '\260';
+		ptdebuf[48] = '\0';
+
+		UpdVid(7, 0, ptdebuf, PTEATR);
+		movectc(stcrow, stccol);
+
+/* 
+
+*/
+	} else if (inrange(stccol, 15, 26)) {		/* stimulus -- clear stimulus */
+
+		if (ptecpos AND NOT ptbflag) {		/* refresh data entry stuff */
+
+			memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+			pteset = TRUE;
+			pte2buf();
+		}
+
+		ptestm 	= NULL_DEF;
+		ptestok = FALSE;
+
+		memset(&ptdebuf[15], ' ', 12);
+
+		for (i = 0; i < 48; i++)
+			if (ptdebuf[i] EQ '\0')
+				ptdebuf[i] = ' ';
+
+		ptdebuf[0] = '\260';
+		ptdebuf[48] = '\0';
+
+		UpdVid(7, 0, ptdebuf, PTEATR);
+		movectc(stcrow, stccol);
+
+	} else if (inrange(stccol, 28, 40)) {		/* destination -- clear line */
+
+		voidpb();		/* void the patch buffer */
+
+		ptdebuf[0] = '\260';
+		ptdebuf[48] = '\0';
+
+		UpdVid(7, 0, ptdebuf, PTEATR);
+		movectc(stcrow, stccol);
+/* 
+
+*/
+	} else if (inrange(stccol, 42, 46)) {		/* datum -- delete the patch */
+
+		if (ptecpos) {
+
+			cp  = ptecpos;			/* setup indices */
+			pp  = patches[cp].prevstm;
+			sp  = patches[cp].nextstm;
+
+			stm = patches[cp].stmnum;	/* get stimulus used */
+#if	DEBUGXP
+	if (debugsw AND debugxp)
+		printf("ptxkey():  DELETING PATCH  pp = %d  cp = %d  sp = %d\n",
+			pp, cp, sp);
+#endif
+
+			if (pp)				/* adjust predecessor */
+				patches[pp].nextstm = sp;
+			else				/* adjust stmptr */
+				stmptr[TRG_MASK & stm] = sp;
+
+			if (sp)				/* adjust successor */
+				patches[sp].prevstm = pp;
+
+			if (sp = findnxt(cp))		/* adjust ptecpos */
+				ptecpos = sp;
+			else if (pp = findprv(cp))
+				ptecpos = pp;
+			else
+				ptecpos = 0;
+
+			pt_del(cp);			/* delete the patch entry */
+/* 
+
+*/
+			for (i = 0; i < NDEFSTMS; ++i) {	/* adjust defptr list */
+
+				if (cp = defptr[i]) {		/* in use ? */
+
+					pp = 0;		/* initial predecessor */
+
+					while (cp) {		/* check the chain */
+
+					sp = defents[cp].nextdef;	/* successor */
+
+						if (defents[cp].stm EQ stm) {
+
+#if	DEBUGXP
+	if (debugsw AND debugxp) {
+
+		printf("ptxkey():  DELETING DEF  trg=$%04.4X  stm=$%04.4X\n",
+			i, stm);
+
+		printf("ptxkey():  DELETING DEF  pp=%d  cp=%d  sp=%d\n",
+			pp, cp, sp);
+	}
+#endif
+
+							if (pp)		/* adjust predecessor */
+								defents[pp].nextdef = sp;
+							else		/* adjust defptr */
+								defptr[i] = sp;
+
+							dt_del(cp);	/* delete def entry */
+
+						} else {
+
+							pp = cp;	/* update predecessor index */
+						}
+
+						cp = sp;		/* next defent */
+					}
+				}
+			}
+
+			dptw();		/* update the display */
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dspdfst() -- convert a patch DEF or STM value for display
+   =============================================================================
+*/
+
+dspdfst(buf, val)
+char *buf;
+register unsigned short val;
+{
+	register unsigned short chan, port, stim;
+
+	if (val EQ NULL_DEF) {		/* handle possible blank definer */
+
+		strcpy(buf, "            ");
+		return;
+	}
+
+	port = (val >> 11) & 0x0003;
+	chan = (val >>  7) & 0x000F;
+	stim = val & 0x007F;
+
+	switch (port) {		/* use port to decode possible types */
+
+	case 0:		/* MIDI-1 - Keys */
+	case 1:		/* MIDI-2 - Keys */
+
+		sprintf(buf, "%s %03u %u %02u",
+			(val & 0x8000) ? "Rel" : "Key",
+			1 + stim, 1 + port, 1 + chan);
+
+		break;
+/* 
+
+*/
+
+	case 2:		/* Local Keys */
+
+		switch (chan) {		/* use channel to further decode */
+
+		case 0:		/* Keys - Local Keyboard */
+
+			sprintf(buf, "%s %03u L   ",
+				(val & 0x8000) ? "Rel" : "Key",
+				1 + stim);
+
+			break;
+
+		case 2:		/* Triggers */
+
+			sprintf(buf, "Trig %02u     ", 1 + stim);
+			break;
+
+		case 3:		/* Pulses */
+
+			sprintf(buf, "Pulse %u     ", 1 + stim);
+			break;
+
+		default:	/* spurious type -- shouldn't happen */
+
+			sprintf(buf, "%s?? %03u L %02u",
+				(val & 0x8000) ? "r" : "c",
+				1 + stim, 1 + chan);
+			break;
+
+		}
+
+		break;
+
+	default:	/* spurious port -- should never happen */
+
+		sprintf(buf, "??? %03u %u %02u", 1 + stim, 1 + port, 1 + chan);
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dfpdat() -- convert FPU datum for display
+   =============================================================================
+*/
+
+char *
+dfpdat(pp)
+register struct patch *pp;
+{
+	static char buf[32];
+	unsigned short sgn, vp1, vp2;
+	short val;
+
+	val = pp->padat2;
+
+	switch (pp->padat1) {
+
+	case PSA_SRC:		/* source */
+
+		strcpy(buf, smdata[val]);
+		break;
+
+	case PSA_MLT:		/* multiplier */
+
+		fr2dec(val, ebuf);
+
+		buf[0] = ebuf[3];
+		buf[1] = ebuf[0];
+		buf[2] = '.';
+		buf[3] = ebuf[1];
+		buf[4] = ebuf[2];
+		buf[5] = '\0';
+		break;
+/* 
+
+*/
+	case PSA_VAL:		/* value */
+
+		val >>= 5;
+
+		if (val < 0) {
+
+			val = -val;
+			sgn = '-';
+
+		} else {
+
+			sgn = '+';
+		}
+
+		vp1 = val / 100;
+		vp2 = val - (vp1 * 100);
+
+		if (vp1 > 9) {
+
+			vp1 = 0;
+
+			if (sgn EQ '+')
+				sgn = '\240';
+			else
+				sgn = '\241';
+		}
+
+		sprintf(buf, "%c%u.%02u", sgn, vp1, vp2);
+		break;
+/* 
+
+*/
+	case PSA_TIM:		/* time */
+
+		vp1 = fromfpu(val);
+
+		sprintf(buf, "%5u", vp1);
+		break;
+
+	case PSA_FNC:		/* function / control */
+
+		if ((PE_SPEC & pp->paspec) EQ PA_AUX)
+			sprintf(buf, "%s", (val & 0x0001) ? "On   " : "Off  ");
+		else
+			sprintf(buf, "%s", (val & 0x0001) ? "Start" : "Stop ");
+
+		break;
+
+	default:
+
+		sprintf(buf, "$%04.4X", val);
+		break;
+	}
+
+	return(buf);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pafpu1() -- convert patch for display -- aaaaa ssss tn  ddddd
+
+		Level, Filtr, Fil Q, Loctn, Dynmc
+   =============================================================================
+*/
+
+pafpu1(bf, ad, gt, gn, pp)
+char *bf;
+char *ad;
+unsigned short gt, gn;
+register struct patch *pp;
+{
+	sprintf(bf, "%s %s %c%c %s", ad, stdata[pp->padat1], gt, gn, dfpdat(pp));
+}
+
+/*
+   =============================================================================
+	pafpu2() -- convert patch for display -- aaa n ssss tn  ddddd
+
+		Index, Freq
+   =============================================================================
+*/
+
+pafpu2(bf, ad, os, gt, gn, pp)
+char *bf;
+char *ad;
+unsigned short os, gt, gn;
+register struct patch *pp;
+{
+	sprintf(bf, "%s %d %s %c%c %s", ad, os, stdata[pp->padat1], gt, gn, dfpdat(pp));
+}
+
+/*
+   =============================================================================
+	pafpu3() -- convert patch for display -- aaaaa ssss     ddddd
+
+		Aux, Rate, Inten, Depth, Vlt
+   =============================================================================
+*/
+
+pafpu3(bf, ad, pp)
+char *bf;
+char *ad;
+register struct patch *pp;
+{
+	sprintf(bf, "%s %s    %s", ad, stdata[pp->padat1], dfpdat(pp));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dspdest() -- convert patch destination and datum for display
+   =============================================================================
+*/
+
+dspdest(buf, pp)
+char *buf;
+register struct patch *pp;
+{
+	unsigned short chan, osc, port, stim, vg, vgt, vgn, vp1, vp2, sgn;
+	short val;
+	char buf2[16], *rtype;
+
+	port = (pp->pasuba >> 11) & 0x0003;		/* for trg types */
+	chan = (pp->pasuba >>  7) & 0x000F;
+	stim =  pp->pasuba        & 0x007F;
+
+	vg   = (pp->pasuba >>  8) & 0x00FF;		/* for vg types */
+	osc  = (pp->pasuba        & 0x00FF) + 1;
+
+	if (vg > 11) {
+
+		vgt = 'G';
+		vgn = vg - 11;
+
+	} else {
+
+		vgt = 'V';
+		vgn = vg + 1;
+	}
+
+	vgn = vgn + ((vgn > 9) ? '\242' : '0');
+
+/* 
+
+*/
+	switch (PE_SPEC & pp->paspec) {
+
+	case PA_KEY:		/* key action */
+
+		sprintf(buf, "K %03u %u %02u    %s",
+			1 + stim, 1 + port, 1 + chan,
+			trdata[pp->padat2 & 0x0003]);
+
+		break;
+
+	case PA_TRG:
+
+		sprintf(buf, "Trigger %02u    %s",
+			1 + stim,
+			ssdata[pp->padat2 & 0x0001]);
+
+		break;
+
+	case PA_PLS:
+
+		sprintf(buf, "Pulse %u       %s",
+			1 + stim,
+			trdata[pp->padat2 & 0x0003]);
+
+		break;
+/* 
+
+*/
+	case PA_LED:
+
+		if (pp->pasuba & 0x0001) {
+
+			sprintf(buf, "LED %c         %c%c%c%c",
+				'A' + pp->pasuba,
+				'0' + ((pp->padat1 >> 14) & 0x0003),
+				'0' + ((pp->padat1 >> 12) & 0x0003),
+				'0' + ((pp->padat1 >> 10) & 0x0003),
+				'0' + ((pp->padat1 >>  8) & 0x0003));
+
+		} else {
+
+			sprintf(buf, "LED %c         %c%c%c",
+				'A' + pp->pasuba,
+				'0' + ((pp->padat1 >> 14) & 0x0003),
+				'0' + ((pp->padat1 >> 12) & 0x0003),
+				'0' + ((pp->padat1 >> 10) & 0x0003));
+		}
+
+		break;
+
+	case PA_SLIN:
+
+		sprintf(buf, "Seq %02u Lin    %03u",
+			1 + pp->pasuba,
+			pp->padat1);
+
+		break;
+
+	case PA_SCTL:
+
+		sprintf(buf, "Seq %02u Ctl    %s",
+			1 + pp->pasuba,
+			ssdata[pp->padat2 & 0x0001]);
+
+		break;
+
+	case PA_TUNE:
+
+		sprintf(buf, "Tune Table    %u",
+			pp->padat1);
+
+		break;
+/* 
+
+*/
+	case PA_RSET:
+
+		rtype = "Set";
+		goto doregs;
+
+	case PA_RADD:
+
+		rtype = "Add";
+
+doregs:
+
+		if (pp->padat1 & 0x0001) {
+
+			sprintf(buf, "Reg %02u %s    R%02u",
+				1 + pp->pasuba, rtype,
+				1 + pp->padat2);
+
+		} else {
+
+			if ((val = pp->padat2) < 0) {
+
+				sgn = '-';
+				val = - val;
+
+			} else {
+
+				sgn = '+';
+			}
+
+			sprintf(buf, "Reg %02u %s    %c%02u",
+				1 + pp->pasuba, rtype,
+				sgn, val);
+		}
+
+		break;
+
+	case PA_INST:
+
+		sprintf(buf, "Instrument %c%c %02u",
+			vgt, vgn, pp->padat1);
+
+		break;
+/* 
+
+*/
+	case PA_OSC:
+
+		val = pp->padat2 >> 1;
+
+		switch (pp->padat1) {
+
+		case PSO_INT:		/* interval */
+
+			if (val < 0) {
+
+				sgn = '-';
+				val = -val;
+
+			} else {
+
+				sgn = '+';
+			}
+
+			sprintf(buf, "Osc %u Int  %c%c %c%04u",
+				osc, vgt, vgn, sgn, val);
+
+			break;
+
+		case PSO_RAT:		/* ratio */
+
+			int2rat(val);
+
+			sprintf(buf, "Osc %u Rat  %c%c %s",
+				osc, vgt, vgn, ebuf);
+
+			break;
+
+		case PSO_FRQ:		/* frequency */
+
+			vp1 = val / 10;
+			vp2 = val - (vp1 * 10);
+
+			sprintf(buf, "Osc %u Frq  %c%c %02u.%u",
+				osc, vgt, vgn, vp1, vp2);
+
+			break;
+/* 
+
+*/
+		case PSO_PCH:		/* pitch */
+
+			cnvc2p(ebuf, val);
+
+			sprintf(buf, "Osc %u Pch  %c%c %s",
+				osc, vgt, vgn, ebuf);
+
+			break;
+
+		default:
+
+			break;
+		}
+
+		break;
+/* 
+
+*/
+	case PA_WAVA:
+
+		sgn = 'A';
+		goto dowaves;
+
+	case PA_WAVB:
+
+		sgn = 'B';
+
+dowaves:
+
+		sprintf(buf, "Waveshape%c %c%c %02u",
+			sgn, vgt, vgn, pp->padat1);
+
+		break;
+
+	case PA_CNFG:
+
+		sprintf(buf, "Configure  %c%c %02u",
+			vgt, vgn, pp->padat1);
+
+		break;
+/* 
+
+*/
+	case PA_LEVL:
+
+		pafpu1(buf, "Level", vgt, vgn, pp);
+		break;
+
+	case PA_INDX:
+
+		pafpu2(buf, "Ind", osc, vgt, vgn, pp);
+		break;
+
+	case PA_FREQ:
+
+		pafpu2(buf, "Frq", osc, vgt, vgn, pp);
+		break;
+
+	case PA_FILT:
+
+		pafpu1(buf, "Filtr", vgt, vgn, pp);
+		break;
+
+	case PA_FILQ:
+
+		pafpu1(buf, "Fil Q", vgt, vgn, pp);
+		break;
+
+	case PA_LOCN:
+
+		pafpu1(buf, "Loctn", vgt, vgn, pp);
+		break;
+
+	case PA_DYNM:
+
+		pafpu1(buf, "Dynmc", vgt, vgn, pp);
+		break;
+/* 
+
+*/
+	case PA_AUX:
+
+		pafpu3(buf, "Aux  ", pp);
+		break;
+
+	case PA_RATE:
+
+		pafpu3(buf, "Rate ", pp);
+		break;
+
+	case PA_INTN:
+
+		pafpu3(buf, "Inten", pp);
+		break;
+
+	case PA_DPTH:
+
+		pafpu3(buf, "Depth", pp);
+		break;
+
+	case PA_VOUT:
+
+		sprintf(buf2, "Vlt %u", pp->pasuba);
+		pafpu3(buf, buf2, pp);
+		break;
+
+	default:
+
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptfield() -- setup field routines for the patch editor
+   =============================================================================
+*/
+
+ptfield()
+{
+	curset(&pt_flds);
+
+#if	USEVECTR
+	if (usevect) {
+
+		cx_key = cxkstd;
+		cy_key = cykstd;
+	}
+#endif
+
+}
Index: ram/ptread.c
===================================================================
--- ram/ptread.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ptread.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,466 @@
+/*
+   =============================================================================
+	ptread.c -- librarian - read patch functions
+	Version 5 -- 1988-11-18 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGRE		0
+#define	DEBUGSP		0
+
+#include "graphdef.h"
+#include "stddefs.h"
+#include "stdio.h"
+#include "patch.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+#if	(DEBUGRE|DEBUGSP)
+extern	short	debugsw;
+#endif
+
+#if	DEBUGRE
+extern	short	debugre;
+#endif
+
+#if	DEBUGSP
+short	debugsp = 1;
+#endif
+
+extern	short	dpecpos;
+extern	short	dpepred;
+extern	short	dpesucc;
+extern	short	errno;
+extern	short	ptecpos;
+extern	short	ptepred;
+extern	short	ptesucc;
+
+extern	struct	patch	ptebuf;
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stashp() -- stash an incoming patch
+   =============================================================================
+*/
+
+short
+stashp()
+{
+	register short c;
+	register unsigned short np, stim;
+
+	c = findpte();
+
+	if (c EQ 0) {		/* old patch -- just update it */
+
+		memcpyw(&patches[ptecpos].defnum, &ptebuf.defnum, 6);
+		patches[ptecpos].paspec |= PE_TBIT;	/* define it */
+
+#if	DEBUGSP
+	if (debugsw AND debugsp) {
+
+		printf("stashp():  UPDATED\n");
+		SnapPTV("stashp");
+	}
+#endif
+
+		return(SUCCESS);
+	}
+
+	/* allocate a patch entry and fill it in */
+
+	if (0 EQ (ptecpos = pt_alc())) {
+
+#if	DEBUGSP
+	if (debugsw AND debugsp)
+		printf("stashp():  patch table FULL\n");
+#endif
+			return(FAILURE);	/* no patch entries left */
+	}
+
+	memcpyw(&patches[ptecpos].defnum, &ptebuf.defnum, 6);
+	patches[ptecpos].paspec |= PE_TBIT;	/* define it */
+	stim = TRG_MASK & ptebuf.stmnum;
+
+	if (c EQ 1) {		/* new patch -- no STM entry yet */
+
+		ptepred = 0;
+		stmptr[stim] = ptecpos;
+	}
+/* 
+
+*/
+	/* put patch in STM chain */
+
+	if (ptepred) {		/* predecessor exits */
+
+		ptesucc = patches[ptepred].nextstm;
+
+		patches[ptecpos].nextstm = ptesucc;
+		patches[ptecpos].prevstm = ptepred;
+
+		patches[ptepred].nextstm = ptecpos;
+
+		if (ptesucc)
+			patches[ptesucc].prevstm = ptecpos;
+
+	} else {		/* no predecessor */
+
+		patches[ptecpos].prevstm = 0;
+
+		if (c EQ -1) {
+
+			ptesucc = stmptr[stim];
+
+			patches[ptecpos].nextstm = ptesucc;
+
+			patches[ptesucc].prevstm = ptecpos;
+
+			stmptr[stim] = ptecpos;
+
+		} else {
+
+			patches[ptecpos].nextstm = 0;
+		}
+	}
+/* 
+
+*/
+	/* update DEF table */
+
+	if (0 EQ (c = finddpe())) {
+
+#if	DEBUGSP
+	if (debugsw AND debugsp) {
+
+		printf("stashp():  defent already exists -- dpecpos = %d\n",
+			dpecpos);
+
+		printf("stashp():  ENTERED\n");
+		SnapPTV("stashp");
+	}
+#endif
+		return(SUCCESS);	/* defent already exists */
+	}
+
+	if (0 EQ (dpecpos = dt_alc())) {
+
+#if	DEBUGSP
+	if (debugsw AND debugsp)
+		printf("stashp():  defent table FULL\n");
+#endif
+			return(FAILURE);	/* no defents left */
+	}
+
+	defents[dpecpos].nextdef = 0;
+	defents[dpecpos].stm     = ptebuf.stmnum;
+	defents[dpecpos].adspec  = ptebuf.paspec;
+	defents[dpecpos].adsuba  = ptebuf.pasuba;
+	defents[dpecpos].addat1  = ptebuf.padat1;
+
+	np = TRG_MASK & ptebuf.defnum;
+
+	if (c EQ 1) {
+
+		dpepred = 0;
+		defptr[np] = dpecpos;
+	}
+/* 
+
+*/
+	if (dpepred) {
+
+		dpesucc = defents[dpepred].nextdef;
+		defents[dpecpos].nextdef = dpesucc;
+		defents[dpepred].nextdef = dpecpos;
+
+	} else {
+
+		if (c EQ -1) {
+
+			dpesucc = defptr[np];
+			defents[dpecpos].nextdef = dpesucc;
+			defptr[np] = dpecpos;
+
+		} else {
+
+			defents[dpecpos].nextdef = 0;
+		}
+	}
+
+#if	DEBUGSP
+	if (debugsw AND debugsp) {
+
+		printf("stashp():  new defent created -- dpecpos = %d\n",
+			dpecpos);
+
+		printf("stashp():  ENTERED\n");
+		SnapPTV("stashp");
+	}
+#endif
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptioerr() -- put up an I/O error message
+   =============================================================================
+*/
+
+ptioerr()
+{
+	char erms[40];
+
+	clrlsel();
+
+	sprintf(erms, "  errno = %d", errno);
+
+	ldermsg("Couldn't read", " the patch table", erms,
+		LD_EMCF, LD_EMCB);
+}
+
+/*
+   =============================================================================
+	nopatch() -- give an error message after running out of space
+   =============================================================================
+*/
+
+nopatch()
+{
+	clrlsel();
+
+	ldermsg("Couldn't read", "  the patch table.", "  Ran out of space",
+		LD_EMCF, LD_EMCB);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptread() -- read a patch
+   =============================================================================
+*/
+
+short
+ptread(fp)
+register FILE *fp;
+{
+	register short go;
+	char cb;
+
+	go = TRUE;
+
+	ldwmsg(" Busy -- please stand by", (char *)NULL, "  Reading patches",
+		LCFBX10, LCBBX10);
+
+	for (;;) {
+
+		voidpb();			/* clear the patch buffer */
+
+		ptecpos = ptepred = ptesucc = 0;
+
+#if	DEBUGRE
+	if (debugsw AND debugre)
+		printf("ptread():  reading\n");
+#endif
+		if (rd_ec(fp, &cb, 1L)) {	/* get control byte */
+
+			ptioerr();
+			return(FAILURE);
+		}
+
+		if (0 EQ cb)			/* if it's 0, we're done */
+			break;
+
+		ptebuf.paspec = PE_TBIT | (PE_SPEC & cb);
+
+		if (rd_ec(fp, &ptebuf.defnum, 4L))	/* DEF and STM */
+			return(FAILURE);
+/* 
+
+*/
+		switch (cb) {
+
+		case PA_KEY:
+		case PA_TRG:
+
+			if (rd_ec(fp, &ptebuf.pasuba, 2L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat2 + 1, 1L))
+				return(FAILURE);
+
+			break;
+
+		case PA_PLS:
+		case PA_SCTL:
+
+			if (rd_ec(fp, (char *)&ptebuf.pasuba + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat2 + 1, 1L))
+				return(FAILURE);
+
+			break;
+
+/* 
+
+*/
+		case PA_LED:
+
+			if (rd_ec(fp, (char *)&ptebuf.pasuba + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, &ptebuf.padat1, 1L))
+				return(FAILURE);
+
+			break;
+
+		case PA_SLIN:
+
+			if (rd_ec(fp, (char *)&ptebuf.pasuba + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, &ptebuf.padat1, 2L))
+				return(FAILURE);
+
+			break;
+
+		case PA_TUNE:
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			break;
+/* 
+
+*/
+		case PA_RSET:
+		case PA_RADD:
+
+			if (rd_ec(fp, (char *)&ptebuf.pasuba + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat2 + 1, 1L))
+				return(FAILURE);
+
+			break;
+
+		case PA_INST:
+		case PA_WAVA:
+		case PA_WAVB:
+		case PA_CNFG:
+
+			if (rd_ec(fp, &ptebuf.pasuba, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			break;
+
+		case PA_OSC:
+		case PA_INDX:
+		case PA_FREQ:
+
+			if (rd_ec(fp, &ptebuf.pasuba, 2L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, &ptebuf.padat2, 2L))
+				return(FAILURE);
+
+			break;
+/* 
+
+*/
+		case PA_LEVL:
+		case PA_FILT:
+		case PA_FILQ:
+		case PA_LOCN:
+		case PA_DYNM:
+
+			if (rd_ec(fp, &ptebuf.pasuba, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, &ptebuf.padat2, 2L))
+				return(FAILURE);
+
+			break;
+
+		case PA_AUX:
+		case PA_RATE:
+		case PA_INTN:
+		case PA_DPTH:
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, &ptebuf.padat2, 2L))
+				return(FAILURE);
+
+			break;
+
+		case PA_VOUT:
+
+			if (rd_ec(fp, (char *)&ptebuf.pasuba + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, (char *)&ptebuf.padat1 + 1, 1L))
+				return(FAILURE);
+
+			if (rd_ec(fp, &ptebuf.padat2, 2L))
+				return(FAILURE);
+
+			break;
+/* 
+
+*/
+		default:
+
+			return(FAILURE);
+		}
+
+#if	DEBUGRE
+	if (debugsw AND debugre)
+		printf("\n\n");
+#endif
+
+		if (stashp()) {		/* stash the patch */
+
+			nopatch(fp);
+			ptecpos = 0;
+			voidpb();
+			return(FAILURE);
+		}
+	}
+
+#if	DEBUGRE
+	if (debugsw AND debugre)
+		printf("ptread():  terminator read -- end of patch file\n");
+#endif
+
+	ptecpos = 0;
+	voidpb();
+	return(SUCCESS);
+}
Index: ram/ptselbx.c
===================================================================
--- ram/ptselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ptselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1489 @@
+/*
+   =============================================================================
+	ptselbx.c -- MIDAS-VII Patch editor box selection functions
+	Version 45 -- 1988-12-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+#define	SNAPDUMP	0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "patch.h"
+#include "macros.h"
+#include "smdefs.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#if	SNAPDUMP
+short	snapit = 0;
+#endif
+
+#if	(SNAPDUMP|DEBUGIT)
+extern	short	debugsw;
+
+short	debug01 = 1;
+#endif
+
+#define	HT_0	0x01	/* definer, stimulus */
+#define	HT_1	0x02	/* source */
+#define	HT_2	0x04	/* destination */
+#define	HT_3	0x08	/* oscillator */
+#define	HT_4	0x10	/* level, index, freq, location, filter */
+#define	HT_5	0x20	/* filq, dynamc, vout, depth, rate, inten, aux */
+#define	HT_OFF	0x00	/* no submenu highlighted */
+
+/* 
+
+*/
+
+extern	short	enterit(), nokey(), cnvp2c(), dec2fr();
+
+extern	unsigned short	exp_c();
+
+extern	short	CurLine;
+
+extern	short	cents;
+extern	short	cmtype;
+extern	short	cxval;
+extern	short	cyval;
+extern	short	hitcx;
+extern	short	hitcy;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	submenu;
+extern	short	vtccol;
+extern	short	vtcrow;
+
+extern	short	ndvals[];
+
+extern	unsigned short	*obj11;
+
+extern	struct selbox	*csbp;
+extern	struct selbox	*curboxp;
+
+extern	char	*smdata[];
+extern	char	*ssdata[];
+extern	char	*stdata[];
+extern	char	*trdata[];
+
+short	ptfnbox();
+
+/* 
+
+*/
+
+short	ptegood;		/* pte buffer -- entire entry valid flag */
+
+short	ptedfok;		/* pte buffer -- def valid flag */
+short	ptestok;		/* pte buffer -- stm valid flag */
+short	ptedsok;		/* pte buffer -- destination valid flag */
+short	ptedtok;		/* pte buffer -- datum valid flag */
+
+short	ptedef;			/* pte buffer -- definer number */
+short	ptestm;			/* pte buffer -- stimulus number */
+short	ptespec;		/* pte buffer -- address type */
+short	ptesuba;		/* pte buffer -- sub-address */
+short	ptedat1;		/* pte buffer -- data word 1 */
+short	ptedat2;		/* pte buffer -- data word 2 */
+
+short	ptedftp;		/* definer / stimulus entry flag */
+
+short	ptedfst;		/* current definer/stimulus data entry format */
+short	ptedest;		/* current destination data entry format */
+short	ptedata;		/* current datum data entry format */
+
+short	ptemenu;		/* current submenu highlighting */
+
+short	pteset;			/* pte buffer setup flag */
+short	ptbflag;		/* pdbuf setup flag */
+
+short	ptecpos;		/* current patch entry index */
+short	ptepred;		/* predecessor entry index */
+short	ptesucc;		/* successor entry index */
+
+struct patch	ptebuf;		/* pte buffer -- patch table format */
+
+char	ptdebuf[50];		/* patch edit buffer */
+
+/* 
+
+*/
+
+char	*rawdfst[] = {		/* def/stm field initial contents */
+
+	"Key 001 1 01",
+	"Rel 001 1 01",
+	"Trig 01     ",
+	"Pulse 1     "
+};
+
+char	*rawdest[] = {		/* destination field initial contents */
+
+	"??????? 00 ??",	/* ??????	00 */
+	"K 001 1 01   ",	/* PA_KEY	01 */
+	"Trigger 01   ",	/* PA_TRG	02 */
+	"Pulse 1      ",	/* PA_PLS	03 */
+	"LED A        ",	/* PA_LED	04 */
+	"Seq 01 Lin   ",	/* PA_SLIN	05 */
+	"Seq 01 Ctl   ",	/* PA_SCTL	06 */
+	"Tune Table   ",	/* PA_TUNE	07 */
+	"Reg 01 Set   ",	/* PA_RSET	08 */
+	"Reg 01 Add   ",	/* PA_RADD	09 */
+	"Instrument V1",	/* PA_INST	10 */
+	"Osc 1 Int  V1",	/* PA_OSC	11 */
+	"WaveshapeA V1",	/* PA_WAVA	12 */
+	"WaveshapeB V1",	/* PA_WAVB	13 */
+	"Configure  V1",	/* PA_CNFG	14 */
+	"Level Srce V1",	/* PA_LEVL	15 */
+	"Ind 1 Srce V1",	/* PA_INDX	16 */
+	"Frq 1 Srce V1",	/* PA_FREQ	17 */
+	"Filtr Srce V1",	/* PA_FILT	18 */
+	"Fil Q Srce V1",	/* PA_FILQ	19 */
+	"Loctn Srce V1",	/* PA_LOCN	20 */
+	"Dynmc Srce V1",	/* PA_DYNM	21 */
+	"Aux   Srce   ",	/* PA_AUX	22 */
+	"Rate  Srce   ",	/* PA_RATE	23 */
+	"Inten Srce   ",	/* PA_INTN	24 */
+	"Depth Srce   ",	/* PA_DPTH	25 */
+	"Vlt 1 Srce   "		/* PA_VOUT	26 */
+};
+
+/* 
+
+*/
+
+char	*rawmode[] = { "Frq ",  "Pch ",   "Int ",  "Rat " };	/* oscillator modes */
+char	*rawmdat[] = { "00.1 ", "0C 00",  "+0000", "1/1  " };	/* oscillator data */
+
+short	omtabl[]   = { PSO_FRQ, PSO_PCH, PSO_INT, PSO_RAT };	/* oscillator modes */
+short	omdtab[]   = { 2,       320,     0,       0       };	/* oscillator data */
+short	omftab[]   = { 6,       7,       4,       5       };	/* mode data format */
+
+char	*rawfpud[] = { "PchWh", "+0.00", "00001", "\2400.00", "Start" };
+
+short	fpudtab[]  = { SM_HTPW,       0,          1,       0,	    1 };
+short	fpuetab[]  = {      11,       1,          2,       3,       9 };
+
+short	dfsttab[] = { 0x0000, 0x8000, 0x1100, 0x1180 };
+
+short	defcols[] = {  2,  6,  7,  8};	/* def data entry columns */
+short	stmcols[] = { 15, 19, 20, 21};	/* stm data entry columns */
+
+short	dstcols[] = {			/* destination data entry columns */
+
+/*	-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10	*/
+	28, 30, 36, 34, 32, 32, 42, 39, 34, 32, 32, 34
+};
+
+short	dfsttp[] = { 1,  1,  2,  3 };	/* def/stm formats */
+
+short	datasrc[] = {
+
+	SM_HTPW,  SM_VTMW,  SM_LPBR,  SM_PED1,  SM_CTL1,
+	SM_PTCH,  SM_FREQ,  SM_KVEL,  SM_KPRS,  SM_RAND
+};
+
+/* 
+
+*/
+
+short	destype[] = {			/* destination type table */
+
+	PA_KEY,		-1,		PA_TRG,		PA_PLS,		PA_LED,
+	PA_SLIN,	PA_SCTL,	PA_TUNE,	PA_RSET,	PA_RADD,
+	PA_INST,	PA_OSC,		PA_WAVA,	PA_WAVB,	PA_CNFG,
+	PA_INDX,	PA_FREQ,	-1,		-1,		-1,
+	PA_LEVL,	PA_LOCN,	PA_FILT,	PA_FILQ,	PA_DYNM,
+	PA_VOUT,	PA_DPTH,	PA_RATE,	PA_INTN,	PA_AUX,
+	-1,		-1,		-1,		-1,		-1,
+	-1,		-1,		-1,		-1,		-1,
+	-1,		-1,		-1,		-1,		-1
+};
+
+char	destfmt[] = {		/* destination data entry format table */
+
+	 0,	-1,	 1,	 2,	 3,	/*  1 ..  5 */
+	 4,	 4,	 5,	 4,	 4,	/*  6 .. 10 */
+	 6,	 9,	 6,	 6,	 6,	/* 11 .. 15 */
+	 9,	 9,	-1,	-1,	-1,	/* 16 .. 20 */
+	10,	10,	10,	10,	10,	/* 21 .. 25 */
+	 8,	 7,	 7,	 7,	 7	/* 26 .. 30 */
+};
+
+char	datafmt[] = {		/* datum data entry format table */
+
+	8,		-1,		9,		8,		14,
+	13,		9,		18,		12,		12,
+	15,		4,		16,		16,		17,
+	11,		11,		-1,		-1,		-1,
+	11,		11,		11,		11,		11,
+	11,		11,		11,		11,		11
+};
+
+/* 
+
+*/
+
+char	desdatf[] = {		/* data entry default flags */
+
+	2,		0,		2,		2,		1,
+	1,		2,		1,		3,		3,
+	1,		0,		1,		1,		1,
+	2,		2,		0,		0,		0,
+	2,		2,		2,		2,		2,
+	2,		2,		2,		2,		2
+};
+
+short	desdat1[] = {		/* data word 1 defaults */
+
+	0,		0,		0,		0,		0,
+	0,		0,		0,		0,		0,
+	0,		0,		0,		0,		0,
+	0,		0,		0,		0,		0,
+	0,		0,		0,		0,		0,
+	0,		0,		0,		0,		0
+};
+
+short	desdat2[] = {		/* data word 2 defaults */
+
+	0,		0,		1,		0,		0,
+	0,		1,		0,		0,		1,
+	0,		0,		0,		0,		0,
+	SM_HTPW,	SM_HTPW,	0,		0,		0,
+	SM_HTPW,	SM_HTPW,	SM_HTPW,	SM_HTPW,	SM_HTPW,
+	SM_HTPW,	SM_HTPW,	SM_HTPW,	SM_HTPW,	SM_HTPW
+};
+
+/* 
+
+*/
+
+char	*rawdata[] = {
+
+	"Trans",	"     ",	"Start",	"Trans",	"000  ",
+	"000  ",	"Start",	"0    ",	"+00  ",	"+01  ",
+	"00   ",	"+0000",	"01   ",	"01   ",	"00   ",
+	"PchWh",	"PchWh",	"     ",	"     ",	"     ",
+	"PchWh",	"PchWh",	"PchWh",	"PchWh",	"PchWh",
+	"PchWh",	"PchWh",	"PchWh",	"PchWh",	"PchWh"
+};
+
+char	hilitab[][8] = {		/* submenu highlight table */
+
+	/* start, width, row1, row2, row3, row4, row5, pad */
+
+	{  2,  3,  HT_0|HT_2,  HT_0,       HT_0|HT_2,  HT_0|HT_2,  HT_2,  0},
+	{  7,  6,  HT_2,       HT_2,       HT_2,       HT_2,       HT_2,  0},
+	{ 15,  5,  HT_2,       HT_2,       HT_2,       HT_2,       HT_2,  0},
+	{ 22,  5,  HT_2,       HT_2|HT_3,  HT_3,       HT_3,       HT_3,  0},
+	{ 29,  5,  HT_2,       HT_2,       HT_2,       HT_2,       HT_2,  0},
+	{ 36,  5,  HT_2,       HT_2,       HT_2,       HT_2,       HT_2,  0},
+	{ 43,  4,  HT_4|HT_5,  HT_4|HT_5,  HT_4|HT_5,  HT_4|HT_5,  0,     0},
+	{ 49,  5,  HT_1,       HT_1,       HT_1,       HT_1,       HT_1,  0},
+	{ 56,  5,  HT_1,       HT_1,       HT_1,       HT_1,       HT_1,  0}
+};
+
+struct	selbox	ptboxes[] = {		/* selection boxes */
+
+	{CTOX(1), RTOY(DATAROW), CTOX(48)-1, RTOY(1+DATAROW)-1,   0, ptfnbox},	/* current patch */
+
+	{      0,        0,          0,          0,   0, FN_NULL}
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	hilitpm() -- highlight patch submenu
+   =============================================================================
+*/
+
+hilitpm(n)
+register char n;
+{
+	register short chr, h, v, w;
+
+	ptemenu = n;				/* set current submenu type */
+
+	for (h = 0; h < 9; h++) {		/* scan the columns */
+
+		for (v = 0; v < 5; v++) {	/* scan the rows */
+
+			chr = hilitab[h][0];	/* starting character */
+
+			for (w = hilitab[h][1]; w-- > 0; )
+				vsetcv(obj11, v + 1, chr++,
+					(hilitab[h][v + 2] & n) ?
+					 PTIATR : PTMATR, 64);
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	aftercm() -- determine state after cursor motion
+   =============================================================================
+*/
+
+aftercm()
+{
+	switch (stccol) {	/* switch based on current cursor column */
+
+	case 2:			/* definer */
+	case 3:
+	case 4:
+		hilitpm(HT_0);
+		break;
+
+	case 15:		/* stimulus */
+	case 16:
+	case 17:
+
+		hilitpm(HT_0);
+		break;
+
+	case 28:		/* destination */
+
+		hilitpm(HT_2);
+		break;
+
+/* 
+
+*/
+	case 34:		/* may be a destination sub-address */
+	case 35:
+	case 36:
+	case 37:
+
+		if (ptedsok) {		/* if destination is good ... */
+
+			switch (PE_SPEC & ptespec) {
+
+			case PA_OSC:
+
+				hilitpm(HT_3);
+				break;
+
+			case PA_LEVL:
+			case PA_INDX:
+			case PA_FREQ:
+			case PA_LOCN:
+			case PA_FILT:
+
+				hilitpm(HT_4);
+				break;
+
+			case PA_FILQ:
+			case PA_DYNM:
+			case PA_VOUT:
+			case PA_DPTH:
+			case PA_RATE:
+			case PA_INTN:
+			case PA_AUX:
+
+				hilitpm(HT_5);
+				break;
+
+			default:
+
+				hilitpm(HT_OFF);
+				break;
+			}
+
+		} else {
+
+			hilitpm(HT_OFF);
+		}
+
+		break;
+/* 
+
+*/
+	case 42:		/* datum */
+
+		if (ptedtok) {		/* if datum is valid ... */
+
+			switch (PE_SPEC & ptespec) {
+
+			case PA_LEVL:
+			case PA_INDX:
+			case PA_FREQ:
+			case PA_LOCN:
+			case PA_FILT:
+			case PA_FILQ:
+			case PA_DYNM:
+			case PA_VOUT:
+			case PA_DPTH:
+			case PA_RATE:
+			case PA_INTN:
+			case PA_AUX:
+
+				if (ptedat1 EQ PSA_SRC)
+					hilitpm(HT_1);
+				else
+					hilitpm(HT_OFF);
+
+				break;
+
+			default:
+
+				hilitpm(HT_OFF);
+				break;
+			}
+
+		} else {
+
+			hilitpm(HT_OFF);
+		}
+
+		break;
+
+	default:		/* not in a starting place */
+
+		hilitpm(HT_OFF);
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	movectc() -- move cursor and reset highlighting
+   =============================================================================
+*/
+
+movectc(r, c)
+short r, c;
+{
+	ctcpos(r, c);
+	aftercm();
+}
+
+/*
+   =============================================================================
+	endpsm() -- end patch submenu data entry
+   =============================================================================
+*/
+
+endpsm(row, col)
+short row, col;
+{
+	submenu = FALSE;
+	cmtype  = CT_SMTH;
+
+	ptegood = ptedfok AND ptestok AND ptedsok AND ptedtok;
+
+	mtcoff();
+	movectc(row, col);
+
+	srdspte();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	edefstm() -- enter a def or a stm field
+   =============================================================================
+*/
+
+edefstm(du, n)
+short du, n;
+{
+	short chan, port, stim;
+	register short i, left, right;
+	register long ltemp;
+
+#if	DEBUGIT
+	if (debugsw AND snapit)
+		printf("edefstm(%d):  pte stok=%d  dfok=%d\n",
+			n, ptestok, ptedfok);
+#endif
+
+	if (n) {
+
+		if (NOT ptestok) {
+
+			movectc(DATAROW, 15);
+			return;
+		}
+
+	} else {
+
+		if (NOT ptedfok) {
+
+			movectc(DATAROW, 2);
+			return;
+		}
+	}
+
+	port = ((n ? ptestm : ptedef) >> 11) & 0x0003;
+	chan = ((n ? ptestm : ptedef) >>  7) & 0x000F;
+	stim =  (n ? ptestm : ptedef)        & 0x007F;
+
+/* 
+
+*/
+
+	if ( (port EQ 0) OR (port EQ 1) OR
+	     ((port EQ 2) AND (chan < 2)) ) {		/* key / rel */
+
+		ltemp = 0;		/* stimulus number */
+		left  = n ? 19 : 6;
+		right = n ? 22 : 9;
+
+		for (i = left; i < right; i++)
+			ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 128L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		stim = ltemp - 1;
+
+		if (port EQ 2) {
+
+			chan = 0;
+
+		} else {
+
+			ltemp = 0;			/* channel */
+			left  = n ? 25 : 12;
+			right = n ? 27 : 14;
+
+			for (i = left; i < right; i++)
+				ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+			if ((ltemp EQ 0) OR (ltemp > 16L)) {
+
+				movectc(DATAROW, left);
+				return;
+			}
+
+			chan = ltemp - 1;
+		}
+
+		if (n)
+			ptestm = (ptestm & 0x8000) | (port << 11) | (chan << 7) | stim;
+		else
+			ptedef = (ptedef & 0x8000) | (port << 11) | (chan << 7) | stim;
+/* 
+
+*/
+	} else if ((port EQ 2) AND (chan EQ 2)) {	/* Trig */
+
+		ltemp = 0;
+		left  = n ? 20 : 7;
+		right = n ? 22 : 9;
+
+		for (i = left; i < right; i++)
+			ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 16L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		stim = ltemp - 1;
+
+		if (n)
+			ptestm = 0x1100 | stim;
+		else
+			ptedef = 0x1100 | stim;
+/* 
+
+*/
+	} else if ((port EQ 2) AND (chan EQ 3)) {	/* Pulse */
+
+		left = n ? 21 : 8;
+		ltemp = ptdebuf[left] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 2L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		stim = ltemp - 1;
+
+		if (n)
+			ptestm = 0x1180 | stim;
+		else
+			ptedef = 0x1180 | stim;
+
+	} else {
+
+		movectc(DATAROW, n ? 15 : 2);
+		return;
+	}
+
+	if (n)
+		ptestok = TRUE;
+	else
+		ptedfok = TRUE;
+
+#if	SNAPDUMP
+	if (debugsw AND snapit)
+		SnapPTV("edefstm");
+#endif
+
+	if (du) {	/* if display is to be updated ... */
+
+		srdspte();
+		movectc(DATAROW, n ? 28 : 15);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptdest() -- enter patch destination field
+   =============================================================================
+*/
+
+ptdest(du)
+short du;
+{
+	register long ltemp;
+	register short i, left, right, stim;
+	short port, chan;
+
+#if	DEBUGIT
+	if (debugsw AND debug01)
+		printf("ptdest(%d): entry -- ptedest = %d\n", du, ptedest);
+#endif
+
+	switch (ptedest) {
+
+	case 0:		/* key */
+
+		ltemp = 0;
+		left  = 30;
+		right = 33;
+
+		for (i = left; i < right; i++)
+			ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 128L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		stim  = ltemp - 1;
+		ltemp = 0;
+		left  = 36;
+		right = 38;
+
+		for (i = left; i < right; i++)
+			ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 16L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		chan = ltemp - 1;
+/* 
+
+*/
+		if (ptdebuf[34] EQ 'L') {
+
+			port = 2;
+			chan = 0;
+
+		} else {
+
+			port = ptdebuf[34] - '1';
+		}
+
+		ptesuba = (port << 11) | (chan << 7) | stim;
+		break;
+/* 
+
+*/
+	case 1:		/* trigger */
+
+		ltemp = 0;
+		left  = 36;
+		right = 38;
+
+		for (i = left; i < right; i++)
+			ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 16L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		stim    = ltemp - 1;
+		ptesuba = 0x1100 | stim;
+		break;
+
+	case 2:		/* pulse */
+
+		ptesuba = ptdebuf[34] - '1';
+		break;
+
+	case 3:		/* led */
+		
+		ptesuba = ptdebuf[32] - 'A';
+		break;
+
+	case 4:		/* seq / reg */
+
+		ltemp = 0;
+		left  = 32;
+		right = 34;
+
+		for (i = left; i < right; i++)
+			ltemp = (ltemp * 10) + ptdebuf[i] - '0';
+
+		if ((ltemp EQ 0) OR (ltemp > 16L)) {
+
+			movectc(DATAROW, left);
+			return;
+		}
+
+		ptesuba = ltemp - 1;
+		break;
+
+/* 
+
+*/
+	case 5:		/* tuning */
+	case 7:		/* aux, rate, inten, depth */
+
+		break;
+
+	case 6:		/* inst, wave, config */
+	case 10:	/* level, filtr, fil Q, loctn, dynmc */
+
+		if (ptdebuf[39] EQ 'V')
+			stim = 0;
+		else
+			stim = 12;
+
+		i = ptdebuf[40] & 0x00FF;
+
+		if (i GE '\254')
+			stim += i - '\242';
+		else
+			stim += i - '0';
+
+		--stim;
+		ptesuba = stim << 8;
+		break;
+
+	case 8:		/* vlt */
+
+		ptesuba = ptdebuf[32] - '0';
+		break;
+/* 
+
+*/
+	case 9:		/* osc, ind, frq */
+
+		if (ptdebuf[39] EQ 'V')
+			stim = 0;
+		else
+			stim = 12;
+
+		i = ptdebuf[40] & 0x00FF;
+
+		if (i GE '\254')
+			stim += i - '\242';
+		else
+			stim += i - '0';
+
+		--stim;
+		ptesuba = (stim << 8) | (ptdebuf[32] - '0');
+		break;
+
+	default:	/* something weird got in here ... */
+
+		movectc(DATAROW, 28);
+		return;
+	}
+
+	ptedsok = TRUE;
+
+#if	SNAPDUMP
+	if (debugsw AND snapit)
+		SnapPTV("ptdest");
+#endif
+
+	if (du) {
+
+		srdspte();
+		movectc(DATAROW, 42);
+	}
+
+#if	DEBUGIT
+	if (debugsw AND debug01)
+		printf("ptdest(%d): exit\n", du);
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	epatch() -- enter patch and reposition cursor to the DEF field
+   =============================================================================
+*/
+
+epatch()
+{
+#if	DEBUGIT
+	if (debugsw AND debug01)
+		printf("epatch(): entry\n");
+#endif
+
+	ptedtok = TRUE;		/* data just got parsed or we wouldn't be here */
+	edefstm(0, 0);		/* parse def */
+	edefstm(0, 1);		/* parse stm */
+	ptdest(0);		/* parse dest */
+	entrpte();		/* enter the patch */
+	srdspte();		/* adjust the display */
+	movectc(DATAROW, 2);	/* reposition the cursor */
+
+#if	SNAPDUMP
+	if (debugsw AND snapit)
+		SnapPTV("epatch");
+#endif
+
+#if	DEBUGIT
+	if (debugsw AND debug01)
+		printf("epatch(): exit\n");
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	badpdat() -- position cursor at bad data field
+   =============================================================================
+*/
+
+badpdat()
+{
+	ptedtok = FALSE;
+	movectc(DATAROW, 42);
+}
+
+/*
+   =============================================================================
+	setsubm() -- setup submenu
+   =============================================================================
+*/
+
+setsubm(r, c)
+short r, c;
+{
+	submenu = TRUE;
+	cmtype  = CT_MENU;
+	mtcpos(r, c);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptfnbox() -- patch display box hit processor
+   =============================================================================
+*/
+
+short
+ptfnbox(n)
+short n;
+{
+	register short i, box, ptd, ptt;
+	register long ltemp;
+
+	if (NOT submenu) {			/* PATCH DATA ENTRY LINE */
+
+		if (inrange(stccol, 2, 13)) {		/* DEFINER */
+
+			ptedftp = 1;		/* def */
+
+			if (inrange(stccol, 2, 4)) {	/* select */
+
+				setsubm(19, 2);
+
+			} else {			/* enter */
+
+				edefstm(0, 1);
+				ptdest(0);
+				edefstm(1, 0);
+			}
+
+			return(SUCCESS);
+
+		} else if (inrange(stccol, 15, 26)) {	/* STIMULUS */
+
+			ptedftp = 2;		/* stm */
+
+			if (inrange(stccol, 15, 17)) {	/* select */
+
+				setsubm(19, 2);
+
+			} else {			/* enter */
+
+				edefstm(0 ,0);
+				ptdest(0);
+				edefstm(1, 1);
+			}
+
+			return(SUCCESS);
+/* 
+
+*/
+		} else if (inrange(stccol, 28, 40)) {	/* DESTINATION */
+
+			ptedftp = 0;		/* not def/stm */
+
+			if (stccol EQ 28) {		/* select */
+
+				setsubm(19, 2);
+
+			} else if (ptemenu EQ HT_3) { 
+
+				setsubm(20, 22);
+
+			} else if ((ptemenu EQ HT_4) OR
+				   (ptemenu EQ HT_5)) {
+
+				setsubm(19, 43);
+
+			} else {			/* enter */
+
+				edefstm(0, 0);
+				edefstm(0, 1);
+				ptdest(1);
+			}
+
+			return(SUCCESS);
+/* 
+
+*/
+		} else if (inrange(stccol, 42, 46)) {	/* DATUM */
+
+			ptedftp = 0;		/* not def/stm */
+			setptcv();		/* setup control variables */
+
+#if	DEBUGIT
+	if (debugsw AND debug01)
+		SnapPTV("ptfnbox");
+#endif
+			switch (ptedata) {	/* switch on Datum format */
+
+			case 0:		/* -none- */
+
+				ptedtok = FALSE;
+				return(FAILURE);
+
+			case 1:		/* multiplier -- +1.00 */
+
+				ebuf[0] = ptdebuf[43];
+				ebuf[1] = ptdebuf[45];
+				ebuf[2] = ptdebuf[46];
+				ebuf[3] = ptdebuf[42];
+
+				if (0xFFFF EQ (i = dec2fr(ebuf))) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat2 = i;
+				epatch();	/* enter -- multiplier */
+				return(SUCCESS);
+/* 
+
+*/
+			case 2:		/* time -- 32767 */
+
+				ltemp = 0;
+
+				for (i = 42; i < 47; i++)
+					ltemp = (ltemp * 10) + (ptdebuf[i] - '0');
+
+				if (ltemp > 32767L) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat2 = tofpu((unsigned short)ltemp);
+				epatch();	/* enter -- time */
+				return(SUCCESS);
+
+			case 3:		/* value -- +10.00 */
+
+				i = ptdebuf[42] & 0x00FF;
+
+				if ((i EQ '\240') OR (i EQ '\241'))
+					ltemp = 1000;
+				else
+					ltemp = 0;
+
+				ltemp += ((ptdebuf[43] - '0') * 100) +
+					 ((ptdebuf[45] - '0') *  10) +
+					  (ptdebuf[46] - '0');
+
+				if (ltemp > 1000L) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				if ((i EQ '-') OR (i EQ '\241'))
+					ltemp = -ltemp;
+
+				ptedat2 = ltemp << 5;
+				epatch();	/* enter -- value */
+				return(SUCCESS);
+
+/* 
+
+*/
+			case 4:		/* interval -- +1200 */
+
+				ltemp = 0;
+
+				for (i = 43; i < 47; i++)
+					ltemp = (ltemp * 10) + (ptdebuf[i] - '0');
+
+				if (ltemp > 1200L) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				if (ptdebuf[42] EQ '-')
+					ltemp = -ltemp;
+
+				ptedat2 = ltemp << 1;
+				epatch();	/* enter -- interval */
+				return(SUCCESS);
+/* 
+
+*/
+			case 5:		/* ratio -- 9/9 */
+
+				ptedat2 = ndvals[ptdebuf[42] - '0'] -
+					  ndvals[ptdebuf[44] - '0'];
+
+				epatch();	/* enter -- ratio */
+				return(SUCCESS);
+
+			case 6:		/* frequency -- 15.9 */
+
+				ltemp = ((ptdebuf[42] - '0') * 100) +
+					((ptdebuf[43] - '0') *  10) +
+					 (ptdebuf[45] - '0');
+
+				if (ltemp > 159L) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat2 = ltemp << 1;
+				epatch();	/* enter -- frequency */
+				return(SUCCESS);
+
+			case 7:		/* pitch -- 9C#99 */
+
+				memcpy(ebuf,& ptdebuf[42], 5);
+
+				if (FAILURE EQ cnvp2c()) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat2 = cents;
+				epatch();	/* enter - pitch */
+				return(SUCCESS);
+/* 
+
+*/
+			case 8:		/* trans/stop/start */
+			case 9:		/* stop/start */
+			case 10:	/* off/on */
+
+				epatch();	/* enter -- control */
+				return(SUCCESS);
+
+			case 11:	/* source */
+
+				if (stccol EQ 42)
+					setsubm(19, 49);	/* select */
+				else
+					epatch();	/* enter -- source */
+
+				return(SUCCESS);
+
+			case 12:	/* register/value -- R16 | +99 */
+
+				ltemp = ((ptdebuf[43] - '0') * 10) +
+					(ptdebuf[44] - '0');
+
+				if (ptdebuf[42] EQ 'R') {
+
+					if ((ltemp EQ 0) OR (ltemp > 16L)) {
+
+						badpdat();
+						return(FAILURE);
+					}
+
+					--ltemp;
+					ptedat1 = 1;
+
+				} else {
+
+					ptedat1 = 0;
+				}
+
+				ptedat2 = ltemp;
+				epatch();	/* enter -- register | value */
+				return(SUCCESS);
+/* 
+
+*/
+			case 13:	/* sequence line */
+
+				ltemp = 0;
+
+				for (i = 42; i < 45; i++)
+					ltemp = (ltemp * 10) + (ptdebuf[i] - '0');
+
+				ptedat1 = ltemp;
+				epatch();	/* enter  -- sequence line */
+				return(SUCCESS);
+
+			case 14:	/* LED controls */
+
+				ltemp = 0;
+
+				if (ptesuba & 0x0001) {
+
+					for (i = 42; i < 46; i++)
+						ltemp = (ltemp << 2) | (ptdebuf[i] - '0');
+
+					ptedat1 = ltemp << 8;
+
+				} else {
+
+					for (i = 42; i < 45; i++)
+						ltemp = (ltemp << 2) | (ptdebuf[i] - '0');
+
+					ptedat1 = ltemp << 10;
+				}
+
+				epatch();	/* enter -- LED controls */
+				return(SUCCESS);
+
+/* 
+
+*/
+			case 15:	/* instrument number */
+
+				ltemp = ((ptdebuf[42] - '0') * 10) +
+					(ptdebuf[43] - '0');
+
+				if (ltemp > 40L) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat1 = ltemp;
+				epatch();	/* enter -- instrument number */
+				return(SUCCESS);
+
+			case 16:	/* waveshape number */
+
+				ltemp = ((ptdebuf[42] - '0') * 10) +
+					(ptdebuf[43] - '0');
+
+				if ((ltemp EQ 0) OR (ltemp > 20L)) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat1 = ltemp;
+				epatch();	/* enter -- waveshape number */
+				return(SUCCESS);
+/* 
+
+*/
+			case 17:	/* configuration number */
+
+				ltemp = ((ptdebuf[42] - '0') * 10) +
+					(ptdebuf[43] - '0');
+
+				if (ltemp > 11L) {
+
+					badpdat();
+					return(FAILURE);
+				}
+
+				ptedat1 = ltemp;
+				epatch();	/* enter -- configuration number */
+				return(SUCCESS);
+
+			case 18:	/* tuning table number */
+
+				ptedat1 = ptdebuf[42] - '0';
+				epatch();	/* enter -- tuning table number */
+				return(SUCCESS);
+
+			default:	/* something weird got in here ... */
+
+				ptedtok = FALSE;
+				return(FAILURE);
+			}
+		}
+
+		return(FAILURE);
+/* 
+
+*/
+	} else {				/* SUBMENU SELECTION */
+
+		/* determine the "box" we're pointing at */
+
+		if (inrange(vtccol, 2, 4))
+			box = vtcrow - 18;
+		else if (inrange(vtccol, 7, 12))
+			box = vtcrow - 13;
+		else if (inrange(vtccol, 15, 19))
+			box = vtcrow - 8;
+		else if (inrange(vtccol, 22, 26))
+			box = vtcrow - 3;
+		else if (inrange(vtccol, 29, 33))
+			box = vtcrow + 2;
+		else if (inrange(vtccol, 36, 40))
+			box = vtcrow + 7;
+		else if (inrange(vtccol, 43, 46))
+			box = vtcrow + 12;
+		else if (inrange(vtccol, 49, 53))
+			box = vtcrow + 17;
+		else if (inrange(vtccol, 56, 60))
+			box = vtcrow + 22;
+		else
+			return(FAILURE);
+
+/* 
+
+*/
+		switch (ptemenu) {	/* switch on submenu type */
+
+		case HT_0:	/* DEFINERS / STIMULLI */
+
+			if (inrange(box, 1, 4)) {	/* Key, Rel, Trg, Pls */
+
+				i = box - 1;
+				ptedfst = dfsttp[i];
+
+				if (ptedftp EQ 1) {		/* def */
+
+					ptedfok = TRUE;
+					ptbflag = TRUE;
+
+					ptedef  = dfsttab[i];
+
+					strcpy(&ptdebuf[2], rawdfst[i]);
+
+					UpdVid(7, 2, rawdfst[i], PTDATR);
+					endpsm(DATAROW, defcols[ptedfst]);
+
+					return(SUCCESS);
+
+				} else if (ptedftp EQ 2) {	/* stm */
+
+					ptestok = TRUE;
+					ptbflag = TRUE;
+
+					ptestm = dfsttab[i];
+
+					strcpy(&ptdebuf[15], rawdfst[i]);
+
+					UpdVid(7, 15, rawdfst[i], PTDATR);
+					endpsm(DATAROW, stmcols[ptedfst]);
+
+					return(SUCCESS);
+				}
+			}
+
+			return(FAILURE);
+/* 
+
+*/
+		case HT_1:	/* SOURCES */
+
+			if (inrange(box, 36, 45)) {
+
+				ptedtok = TRUE;
+				ptbflag = TRUE;
+
+				ptedat2 = datasrc[box - 36];
+
+				strcpy(&ptdebuf[42], smdata[ptedat2]);
+
+				UpdVid(7, 42, smdata[ptedat2], PTDATR);
+				endpsm(DATAROW, 46);
+
+				return(SUCCESS);
+			}
+
+			return(FAILURE);
+/* 
+
+*/
+		case HT_2:	/* DESTINATIONS */
+
+			i   = box - 1;
+			ptt = destype[i];
+
+			if (ptt NE -1) {
+
+				ptedsok = TRUE;
+				ptedtok = TRUE;
+				ptbflag = TRUE;
+
+				ptedest = destfmt[i];
+				ptedata = datafmt[i];
+				ptespec = ptt;
+				ptesuba = 0x0000;
+				ptedat1 = 0x0000;
+				ptedat2 = 0x0000;
+
+				if (ptd = desdatf[i]) {
+
+					if (ptd & 1)
+						ptedat1 = desdat1[i];
+
+					if (ptd & 2)
+						ptedat2 = desdat2[i];
+				}
+
+				strcpy(&ptdebuf[28], rawdest[ptt]);
+				strcpy(&ptdebuf[42], rawdata[i]);
+
+				UpdVid(7, 28, rawdest[ptt], PTDATR);
+				UpdVid(7, 42, rawdata[i], PTDATR);
+				endpsm(DATAROW, dstcols[1 + ptedest]);
+
+				return(SUCCESS);
+			}
+
+			return(FAILURE);
+/* 
+
+*/
+		case HT_3:	/* OSCILLATOR MODES */
+
+			if (inrange(box, 17, 20)) {
+
+				i = box - 17;
+
+				ptedsok = TRUE;
+				ptedtok = TRUE;
+				ptbflag = TRUE;
+
+				ptedat1 = omtabl[i];
+				ptedat2 = omdtab[i];
+
+				ptedata = omftab[i];
+
+				strcpy(&ptdebuf[34], rawmode[i]);
+				strcpy(&ptdebuf[42], rawmdat[i]);
+
+				UpdVid(7, 34, rawmode[i], PTDATR);
+				UpdVid(7, 42, rawmdat[i], PTDATR);
+				endpsm(DATAROW, 39);
+
+				return(SUCCESS);
+			}
+
+			return(FAILURE);
+/* 
+
+*/
+		case HT_5:	/* FPU OUTPUTS WITHOUT FUNCTIONS */
+
+			if (NOT inrange(box, 31, 34))
+				return(FAILURE);
+
+		case HT_4:	/* FPU OUTPUTS WITH FUNCTIONS */
+
+			if (NOT inrange(box, 31, 35))
+				return(FAILURE);
+
+			i = box - 31;
+
+			ptedsok = TRUE;
+			ptedtok = TRUE;
+			ptbflag = TRUE;
+
+			ptedat1 = i;
+			ptedat2 = fpudtab[i];
+
+			ptedata = fpuetab[i];
+
+			strcpy(&ptdebuf[34], stdata[i]);
+			strcpy(&ptdebuf[42], rawfpud[i]);
+
+			UpdVid(7, 34, stdata[i], PTDATR);
+			UpdVid(7, 42, rawfpud[i], PTDATR);
+			endpsm(DATAROW, 42);
+
+			return(SUCCESS);
+
+		default:	/* -BOGUS- */
+
+			endpsm(stcrow, stccol);
+
+			return(FAILURE);
+		}
+	}
+
+	return(FAILURE);
+}
Index: ram/ptwrite.c
===================================================================
--- ram/ptwrite.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ptwrite.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,386 @@
+/*
+   =============================================================================
+	ptwrite.c -- librarian - write patch functions
+	Version 7 -- 1988-11-18 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGWE		0
+#define	DEBUGPW		0
+
+#include "stddefs.h"
+#include "stdio.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "patch.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+#if	(DEBUGPW|DEBUGWE)
+extern	short	debugsw;
+#endif
+
+#if	DEBUGPW
+short	debugpw = 1;
+#endif
+
+#if	DEBUGWE
+extern	short	debugwe;
+#endif
+
+extern	long	chksum();
+
+/* 
+
+*/
+
+char	ptsizes[] = {
+
+	0,	/* NULL - end of list */
+	4,	/* PA_KEY  */
+	4,	/* PA_TRG  */
+	3,	/* PA_PLS  */
+	3,	/* PA_LED  */
+	4,	/* PA_SLIN */
+	3,	/* PA_SCTL */
+	2,	/* PA_TUNE */
+	4,	/* PA_RSET */
+	4,	/* PA_RADD */
+	3,	/* PA_INST */
+	6,	/* PA_OSC  */
+	3,	/* PA_WAVA */
+	3,	/* PA_WAVB */
+	3,	/* PA_CNFG */
+	5,	/* PA_LEVL */
+	6,	/* PA_INDX */
+	6,	/* PA_FREQ */
+	5,	/* PA_FILT */
+	5,	/* PA_FILQ */
+	5,	/* PA_LOCN */
+	5,	/* PA_DYNM */
+	4,	/* PA_AUX  */
+	4,	/* PA_RATE */
+	4,	/* PA_INTN */
+	4,	/* PA_DPTH */
+	5	/* PA_VOUT */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptsizer() -- return number of bytes necessary for storing active patches
+   =============================================================================
+*/
+
+long
+ptsizer()
+{
+	register short pp;
+	register long nb;
+
+	nb = 0L;
+
+	if (pp = find1st()) {
+
+		while (pp) {
+
+			nb += (ptsizes[PE_SPEC & patches[pp].paspec] + 4);
+			pp = findnxt(pp);
+		}
+	}
+
+	if (nb)
+		++nb;		/* ... and one for the terminator */
+
+#if	DEBUGPW
+	if (debugsw AND debugpw)
+		printf("ptsizer():  %ld bytes required\n", nb);
+#endif
+
+	return(nb);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ptwrite() -- store a patch table
+   =============================================================================
+*/
+
+short
+ptwrite(fp)
+register FILE *fp;
+{
+	register short pp;
+	char cb, zero;
+
+#if	DEBUGPW
+	if (debugsw AND debugpw)
+		printf("ptwrite($%08lX):  entered\n", fp);
+#endif
+
+	zero = '\0';
+
+	ldwmsg("Busy -- Please stand by", (char *)0L, "  writing patches",
+		LCFBX10, LCBBX10);
+
+	if (pp = find1st()) {
+
+		while (pp) {
+
+#if	DEBUGWE
+	if (debugsw AND debugwe) {
+
+		printf("ptwrite():  %3d  %04.4X %04.4X  %04.4X %04.4X  %04.4X %04.4X\n    ",
+			pp, patches[pp].defnum, patches[pp].stmnum,
+			patches[pp].paspec, patches[pp].pasuba,
+			patches[pp].padat1, patches[pp].padat2);
+	}
+#endif
+
+			switch (cb = (PE_SPEC & patches[pp].paspec)) {
+
+			case PA_KEY:
+			case PA_TRG:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].pasuba, 2L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat2 + 1, 1L))
+					return(FAILURE);
+
+				break;
+/* 
+
+*/
+			case PA_PLS:
+			case PA_SCTL:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].pasuba + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat2 + 1, 1L))
+					return(FAILURE);
+
+				break;
+
+			case PA_LED:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].pasuba + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].padat1, 1L))
+					return(FAILURE);
+
+				break;
+
+			case PA_SLIN:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].pasuba + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].padat1, 2L))
+					return(FAILURE);
+
+				break;
+
+			case PA_TUNE:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				break;
+/* 
+
+*/
+			case PA_RSET:
+			case PA_RADD:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].pasuba + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat2 + 1, 1L))
+					return(FAILURE);
+
+				break;
+
+			case PA_INST:
+			case PA_WAVA:
+			case PA_WAVB:
+			case PA_CNFG:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].pasuba, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				break;
+
+			case PA_OSC:
+			case PA_INDX:
+			case PA_FREQ:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].pasuba, 2L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].padat2, 2L))
+					return(FAILURE);
+
+				break;
+/* 
+
+*/
+			case PA_LEVL:
+			case PA_FILT:
+			case PA_FILQ:
+			case PA_LOCN:
+			case PA_DYNM:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].pasuba, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].padat2, 2L))
+					return(FAILURE);
+
+				break;
+
+			case PA_AUX:
+			case PA_RATE:
+			case PA_INTN:
+			case PA_DPTH:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].padat2, 2L))
+					return(FAILURE);
+
+				break;
+
+			case PA_VOUT:
+
+				if (wr_ec(fp, &cb, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].defnum, 4L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].pasuba + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, (char *)&patches[pp].padat1 + 1, 1L))
+					return(FAILURE);
+
+				if (wr_ec(fp, &patches[pp].padat2, 2L))
+					return(FAILURE);
+
+				break;
+/* 
+
+*/
+			default:
+
+				return(FAILURE);
+			}
+
+#if	DEBUGWE
+	if (debugsw AND debugwe)
+		printf("\n\n");
+#endif
+
+			pp = findnxt(pp);	/* find the next patch */
+		}
+
+		if (wr_ec(fp, &zero, 1L))	/* write the terminator */
+			return(FAILURE);
+
+	} else {
+
+		return(FAILURE);		/* no patches to write */
+	}
+
+#if	DEBUGPW
+	if (debugsw AND debugpw)
+		printf("ptwrite():  SUCCESS\n");
+#endif
+
+	return(SUCCESS);
+}
Index: ram/puteq.c
===================================================================
--- ram/puteq.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/puteq.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,280 @@
+/*
+   =============================================================================
+	puteq.c -- output functions for the LMC835 EQ chip on the Buchla 700
+	Version 3 -- 1987-12-10 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	TESTER		0
+
+#if	TESTER
+
+#include "ascii.h"
+#include "biosdefs.h"
+#include "ctype.h"
+#include "rawio.h"
+
+#define	MAXLINE		4
+
+#endif
+
+#include "hwdefs.h"
+#include "stddefs.h"
+
+#define	EQ_STB		0x04
+#define	EQ_DAT		0x08
+#define	EQ_CLK		0x10
+
+#define	EQ_IDL		(EQ_STB | EQ_CLK)
+#define	EQ_MASK		(EQ_STB | EQ_CLK | EQ_DAT)
+
+#define	EQ_A6DB		0x20
+#define	EQ_B6DB		0x10
+
+#define	EQ_6DB		(EQ_A6DB | EQ_B6DB)
+
+#define	EQ_ADD		0x40
+
+#define	PSG_ADDR	0
+#define	PSG_READ	0
+#define	PSG_WRIT	2
+
+#define	PSG_IOEN	7
+#define	PSG_IDLE	0xBF
+
+#define	PSG_PRTB	15
+
+/* 
+
+*/
+
+#if	TESTER
+char	cmdline[32];
+#endif
+
+char eqgaint[] = {
+
+	0x00,	/*  0 db */
+	0x20,	/*  1 db */
+	0x10,	/*  2 db */
+	0x08,	/*  3 db */
+	0x04,	/*  4 db */
+	0x02,	/*  5 db */
+	0x12,	/*  6 db */
+	0x2A,	/*  7 db */
+	0x16,	/*  8 db */
+	0x01,	/*  9 db */
+	0x29,	/* 10 db */
+	0x2D,	/* 11 db */
+	0x2F	/* 12 db */
+};
+
+/* 
+
+*/
+
+puteq(byte)
+register char byte;
+{
+	register short i;
+	register char *psg;
+	register char eqdata;
+
+	psg = &io_tone;
+
+	*(psg + PSG_ADDR) = PSG_IOEN;		/* setup PSG I/O controls */
+	*(psg + PSG_WRIT) = PSG_IDLE;
+
+	*(psg + PSG_ADDR) = PSG_PRTB;		/* setup EQ control lines */
+	eqdata = EQ_IDL | (*(psg + PSG_READ) & ~EQ_MASK);
+
+	for (i = 0; i < 8; i++) {		/* send out 8 bits */
+
+		if (byte & 1)			/* setup data line from LSB */
+			eqdata |= EQ_DAT;	/* "1" */
+		else
+			eqdata &= ~EQ_DAT;	/* "0" */
+
+		eqdata &= ~EQ_CLK;		/* set clock low */
+
+		*(psg + PSG_ADDR) = PSG_PRTB;
+		*(psg + PSG_WRIT) = eqdata;
+
+		eqdata |= EQ_CLK;		/* set clock high */
+
+		*(psg + PSG_ADDR) = PSG_PRTB;
+		*(psg + PSG_WRIT) = eqdata;
+
+		byte >>= 1;			/* shift next bit into LSB */
+	}
+
+	eqdata &= ~EQ_STB;			/* set strobe low */
+
+	*(psg + PSG_ADDR) = PSG_PRTB;
+	*(psg + PSG_WRIT) = eqdata;
+
+	eqdata |= EQ_STB;			/* set strobe high */
+
+	*(psg + PSG_ADDR) = PSG_PRTB;
+	*(psg + PSG_WRIT) = eqdata;
+}
+
+/* 
+
+*/
+
+sendeq(band, gain)
+char band, gain;
+{
+	puteq(band);
+	puteq(gain);
+}
+
+char
+gain2eq(gain)
+short gain;
+{
+	register char eqdat;
+
+	if (gain > 0)
+		eqdat = eqgaint[gain] | EQ_ADD;
+	else
+		eqdat = eqgaint[-gain];
+
+	return(eqdat);
+}
+
+/* 
+
+*/
+
+#if	TESTER
+
+extern	int	xtrap15();
+
+char	ahex[] = "0123456789abcdefABCDEF";
+
+/*
+   ============================================================================
+	xdtoi -- convert hex ASCII to an int digit
+   ============================================================================
+*/
+
+int
+xdtoi(c)
+register int c;
+{
+	register int i;
+	register char *ap = &ahex[0];
+
+	for (i = 0; i < 22; i++)
+		if (c EQ *ap++)
+			if (i >15)
+				return(i - 6);
+			else
+				return(i);
+
+	return(-1);
+}
+
+/* 
+
+*/
+
+main()
+{
+	short	rc, c, j;
+	register long	temp;
+	char	gain, band;
+	register char	*aptr;
+
+	printf("\n\nBuchla 700 EQ chip test -- Enter data in hex\n\n");
+
+	do {
+
+		printf("Band = ");
+
+		rc = getln(CON_DEV, MAXLINE, cmdline);
+
+		if (rc EQ A_CR) {
+
+			printf("\n");
+
+			temp = 0L;
+			aptr = cmdline;
+
+			if (A_CR EQ (*aptr & 0x00FF)) {
+
+				xtrap15();
+				continue;
+			}
+
+			if (CTL('G') EQ (*aptr & 0x00FF)) {
+
+				while (0 EQ BIOS(B_RDAV, CON_DEV))
+					sendeq(band, gain);
+
+				BIOS(B_GETC, CON_DEV);
+				continue;
+			}
+
+			while (isxdigit(c = *aptr++))
+				temp = (temp << 4) + xdtoi(c);
+
+			if (temp > 255) {
+
+				printf("\nInput must be < 100\n\n");
+				continue;
+			}
+
+			band = (char)(temp & 0x000000FFL);
+
+		} else {
+
+			printf("Huh ?\n\n");
+			continue;
+		}
+/* 
+
+*/
+		printf("Gain = ");
+
+		rc = getln(CON_DEV, MAXLINE, cmdline);
+
+		if (rc EQ A_CR) {
+
+			printf("\n");
+
+			temp = 0L;
+			aptr = cmdline;
+
+			if (A_CR EQ (*aptr  & 0x00FF)) {
+
+				xtrap15();
+				continue;
+			}
+
+			while (isxdigit(c = *aptr++))
+				temp = (temp << 4) + xdtoi(c);
+
+			if (temp > 255) {
+
+				printf("\nInput must be < 100\n\n");
+				continue;
+			}
+
+			gain = (char)(temp & 0x000000FFL);
+
+		} else {
+
+			printf("Huh ?\n\n");
+			continue;
+		}
+
+		sendeq(band, gain);
+		printf("\n");
+
+	} while (1);
+}
+
+#endif
Index: ram/rscript.c
===================================================================
--- ram/rscript.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/rscript.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,53 @@
+/*
+   =============================================================================
+	rscript.c -- define the score test script for scordsp.c
+	Version 13 -- 1988-11-03 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+extern	int	sqscan();
+
+extern	int	endflg;
+
+char	*script0[] = {		/* initialization score selection string */
+
+	"!quiet !normal !score=0 !weight=60 !end",
+	(char *)0L
+};
+
+/*
+   =============================================================================
+	rscript() -- run a script and return the end condition
+
+		-1	error returned by sqscan
+		 0	end of strings, no errors
+		 1	!end statement encountered
+   =============================================================================
+*/
+
+short
+rscript(p)
+register char *p[];
+{
+	short rc;
+
+	sqinit();		/* initialize the score string interpreter */
+	rc = 0;			/* preset rc for end of script return */
+
+	while (*p) {		/* feed the interpreter the score strings */
+
+		if (!sqscan(*p++)) {	/* ... until we have an error ... */
+
+			rc = -1;		/* error return */
+			break;
+		}
+
+		if (endflg) {		/* ... or until we hit the !end */
+
+			rc = 1;			/* !end return */
+			break;
+		}
+	}
+
+	return(rc);
+}
Index: ram/scadv.c
===================================================================
--- ram/scadv.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scadv.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,313 @@
+/*
+   =============================================================================
+	scadv.c -- MIDAS-VII -- move score 1 frame forward or backward
+	Version 48 -- 1989-12-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#undef	DEBUGGER	/* define to enable debug trace */
+
+#undef	TRACEIT		/* define to enable step by step trace */
+
+#include "debug.h"
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "score.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+#ifdef	TRACEIT
+short	tracesw;
+#endif
+
+/* variables defined elsewhere */
+
+extern	unsigned	*consl;
+extern	unsigned	*cursl;
+extern	unsigned	*nxtsl;
+extern	unsigned	*prvsl;
+extern	unsigned	*saddr;
+
+extern	unsigned	scrl;
+extern	unsigned	vi_sadr;
+extern	unsigned	vi_scrl;
+
+extern	short	ctrsw;
+extern	short	ndisp;
+extern	short	sbase;
+extern	short	sd;
+extern	short	soffset;
+
+extern	struct	gdsel	*gdstbc[];
+extern	struct	gdsel	*gdstbn[];
+extern	struct	gdsel	*gdstbp[];
+
+/* 
+
+*/
+
+/* initialized stuff */
+
+short	nbmoff = 3;
+short	wrdoff = 3;
+
+short	nbmasks[4] = {		/* nybble masks */
+
+	0x000F,
+	0x00F0,
+	0x0F00,
+	0xF000
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sc_adv() -- advance the score display 1 frame
+
+	Note that the score display actually only moves every other frame,
+	due to VSDD limitations, but it moves 2 pixels.
+   =============================================================================
+*/
+
+sc_adv()
+{
+	register short masksl, maskpx, i;
+	register unsigned sword;
+	register long tl;
+	register unsigned *optr, *pptr, *fsl;
+	unsigned *qptr;
+	unsigned pscrl;
+
+	DB_ENTR("sc_adv");
+
+#ifdef TRACEIT
+	if (tracesw) {
+
+		printf("scadv ----------------------\n");
+		SEctrl();
+	}
+
+	if (tracesw & 0x0001) {
+
+		SCslice();
+	}
+#endif
+
+	if (v_regs[5] & 0x0180)		/* make sure we're in bank 0 */
+		vbank(0);
+
+	tl = 128L;			/* setup VSDD line increment */
+
+	DB_CMNT("sc_adv - center ucslice");
+
+	ucslice();			/* update the center slice */
+
+/* 
+
+*/
+	/* see if it's time to update VRAM from edges */
+
+	if ((ndisp EQ 2) AND (soffset EQ ((sd EQ D_BAK) ? 0 : 3))) {
+
+		if (sd EQ D_BAK) {	/* set source and target pointers */
+
+			fsl  = prvsl;
+			optr = saddr + wrdoff;
+
+		} else {
+
+			fsl  = nxtsl;
+			optr = saddr + tl;
+		}
+
+		if (sbase > 28544) {		/* possible double update ? */
+
+			/* set target pointer #2 */
+
+			pptr = saddr - ((sd EQ D_BAK) ? 28542L : 28545L);
+
+			if (sbase < 28672) {	/* double update - right and left */
+
+				DB_CMNT("sc_adv - double update");
+
+				for (i = 224; i--; ) {
+
+					sword = *fsl++;	/* copy a slice word to the VSDD */
+					*optr = sword;
+					*pptr = sword;
+					optr += tl;	/* advance the VSDD pointers */
+					pptr += tl;
+				}
+
+			} else {		/* single update - left */
+
+				DB_CMNT("sc_adv - left update");
+
+				for (i = 224; i--; ) {
+
+					*pptr = *fsl++;		/* copy a slice word to the VSDD */
+					pptr += tl;		/* advance the VSDD pointers */
+				}
+			}
+/* 
+
+*/
+		} else {			/* single update - right */
+
+				DB_CMNT("sc_adv - right update");
+
+			for (i = 224; i--; ) {
+
+				*optr = *fsl++;		/* copy a slice word to the VSDD */
+				optr += tl;		/* advance the VSDD pointers */
+			}
+		}
+
+		optr  = nxtsl;	/* refresh update slices from constant slice */
+		pptr  = cursl;
+		qptr  = prvsl;
+		fsl   = consl;
+
+		for (i = 224; i--; ) {
+
+			sword = *fsl++;
+			*optr++ = sword;
+			*pptr++ = sword;
+			*qptr++ = sword;
+		}
+
+		DB_CMNT("sc_adv - slices refreshed");
+	}
+
+/* 
+
+*/
+	if (sd EQ D_FWD) {
+
+		if (++soffset > 3) {			/* advance scroll counter */
+
+			soffset = 0;			/* roll over scroll counter */
+			++saddr;			/* advance VRAM address */
+
+			if (++sbase > 28672) {		/* advance scroll offset */
+
+				saddr = v_score;	/* roll over VRAM address */
+				sbase = 0;		/* roll over scroll offset */
+			}
+		}
+
+	} else {
+
+		if (--soffset < 0) {			/* decrement scroll counter */
+
+			soffset = 3;			/* roll over scroll counter */
+			--saddr;			/* advance VRAM address */
+
+			if (--sbase < 0) {		/* advance scroll offset */
+
+				saddr = v_score + 28672L;	/* roll over VRAM address */
+				sbase = 28672;		/* roll over scroll offset */
+			}
+		}
+	}
+/* 
+
+*/
+	pscrl = scrl;			/* save old scrl value */
+
+	DB_CMNT("sc_adv - edge uslice");
+
+	maskpx = nbmasks[soffset];	/* setup source pixel mask */
+	masksl = ~maskpx;		/* setup target pixel mask */
+
+	uslice(prvsl, maskpx, masksl, gdstbp);		/* update left edge */
+
+	uslice(nxtsl, maskpx, masksl, gdstbn);		/* update right edge */
+
+	scrl  = 0x8000 | ((soffset >> 1) ^ 0x0001);
+
+	/* only update VSDD registers if score is up and scrl changed */
+
+	if ((ndisp EQ 2) AND (scrl NE pscrl)) {
+
+		sword = (unsigned)((char *)saddr >> 1);
+
+		setipl(VID_DI);		/* disable video interrupts */
+
+		vi_scrl = scrl;
+		vi_sadr = sword;
+
+		setipl(VID_EI);		/* enable video interrupts */
+	}
+
+	ctrsw = FALSE;
+
+#ifdef TRACEIT
+	if (tracesw & 0x0002) {
+
+		SCslice();
+	}
+#endif
+
+	DB_EXIT("sc_adv");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scupd() -- update the center slice without scrolling
+   =============================================================================
+*/
+
+scupd()
+{
+	register short masksl, maskpx, i;
+	register unsigned sword;
+	register long tl;
+	register unsigned *optr, *qptr, *fsl;
+	short soff;
+
+	DB_ENTR("scupd");
+
+	if (v_regs[5] & 0x0180)			/* make sure we're in bank 0 */
+		vbank(0);
+
+	soff   = (nbmoff + soffset) & 3;	/* calculate offset to use */
+	maskpx = nbmasks[(2 + soff) & 3];	/* setup source pixel mask */
+	masksl = ~maskpx;			/* setup target pixel mask */
+	tl = 128L;				/* setup VSDD line increment */
+
+	/* update VRAM, if it's time */
+
+	if (cslice(cursl, maskpx, masksl, gdstbc) AND (ndisp EQ 2)) {
+
+		DB_CMNT("scupd - center write ...");
+
+		fsl  = cursl;
+		optr = saddr + ((soff > 1) ? 64L : 63L);
+		qptr = consl;
+
+		for (i = 224; i--; ) {
+
+			if (sword = maskpx & *fsl)
+				*optr = (*optr & masksl) | sword;
+
+			*fsl++ = *qptr++;	/* clean up the slice */
+			optr += tl;
+		}
+
+		DB_CMNT("scupd - center written");
+	}
+
+	ctrsw = FALSE;
+}
Index: ram/scfield.c
===================================================================
--- ram/scfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1041 @@
+/*
+   =============================================================================
+	scfield.c -- score editor field setup
+	Version 62 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "panel.h"
+#include "macros.h"
+#include "score.h"
+#include "scfns.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+#define	PCENTER		256L
+
+/* functions defined elsewhere */
+
+extern	char	*memset();
+
+extern	short	cxkstd(), cykstd(), select(), oktode(), stdctp3();
+extern	short	enterit(), stddkey(), nokey(), stdmkey();
+
+extern	short	et_strn(), ef_strn(), rd_strn(), nd_strn();
+extern	short	et_snbt(), ef_snbt(), rd_snbt(), nd_snbt();
+
+extern	short	et_ioas(), ef_ioas(), rd_ioas(), nd_ioas();
+extern	short	et_tune(), ef_tune(), rd_tune(), nd_tune();
+extern	short	et_tmpo(), ef_tmpo(), rd_tmpo(), nd_tmpo();
+extern	short	et_intp(), ef_intp(), rd_intp(), nd_intp();
+
+extern	short	et_inst(), ef_inst(), rd_inst(), nd_inst();
+extern	short	et_trns(), ef_trns(), rd_trns(), nd_trns();
+extern	short	et_dyn(), ef_dyn(), rd_dyn(), nd_dyn();
+extern	short	et_loc(), ef_loc(), rd_loc(), nd_loc();
+extern	short	et_vel(), ef_vel(), rd_vel(), nd_vel();
+
+extern	short	et_res1(), ef_res1(), rd_res1(), nd_res1();
+extern	short	et_aval(), ef_aval(), rd_aval(), nd_aval();
+extern	short	et_agrp(), ef_agrp(), rd_agrp(), nd_agrp();
+
+extern	short	et_scor(), ef_scor(), rd_scor(), nd_scor();
+
+/* forward references */
+
+short	et_null(), ef_null(), rd_null(), nd_null();
+short	sdcxu(), sdcyu(), sdxkey(), sdmkey(), scntfld();
+
+/* 
+
+*/
+
+/* variables defined elsewhere */
+
+extern	short	ancmsw;
+extern	short	angroup;
+extern	short	astat;
+extern	short	clkrun;
+extern	short	cmfirst;
+extern	short	cmtype;
+extern	short	curhold;
+extern	short	curscor;
+extern	short	cxrate;
+extern	short	cxval;
+extern	short	cyrate;
+extern	short	cyval;
+extern	short	ebflag;
+extern	short	hcwval;
+extern	short	insmode;
+extern	short	oldpk;
+extern	short	oldsl;
+extern	short	pkctrl;
+extern	short	recsw;
+extern	short	scmctl;
+extern	short	sdmctl;
+extern	short	sliders;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	thcwval;
+extern	short	tvcwval;
+extern	short	vcwval;
+extern	short	vtccol;
+extern	short	vtcrow;
+extern	short	vtxval;
+extern	short	vtyval;
+
+extern	long	ctime;
+extern	long	t_ins;
+
+extern	char	ebuf[MAXEBUF+1];
+
+extern	short	crate1[];
+extern	short	ehdlist[];
+extern	short	grpmode[];
+extern	short	grpstat[];
+extern	short	grptmap[];
+extern	short	sdmlim[][4];
+extern	short	varmode[8][16];
+
+extern	PFS	(*swpt)[];
+extern	PFS	(*oldsw)[];
+
+extern	struct	fet	*cfetp;
+extern	struct	fet	*curfet;
+extern	struct	fet	*infetp;
+
+extern	struct	selbox	*csbp;
+
+extern	struct	selbox	sdboxes[];
+
+extern	struct	s_entry	*peg;
+
+/* 
+
+*/
+
+struct	fet	sc_fet1[] = {
+
+	{ 0,  2,  4, 0x0000, et_strn, ef_strn, rd_strn, nd_strn},
+	{ 0, 11, 15, 0x0000, et_snbt, ef_snbt, rd_snbt, nd_snbt},
+
+	{17, 11, 12, 0x0000, et_ioas, ef_ioas, rd_ioas, nd_ioas},
+	{17, 19, 19, 0x0000, et_tune, ef_tune, rd_tune, nd_tune},
+	{17, 27, 29, 0x0000, et_tmpo, ef_tmpo, rd_tmpo, nd_tmpo},
+	{17, 35, 38, 0x0000, et_intp, ef_intp, rd_intp, nd_intp},
+
+	{18,  7,  8,      0, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 12, 13,      1, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 17, 18,      2, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 22, 23,      3, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 27, 28,      4, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 32, 33,      5, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 37, 38,      6, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 42, 43,      7, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 47, 48,      8, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 52, 53,      9, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 57, 58,     10, et_inst, ef_inst, rd_inst, nd_inst},
+	{18, 62, 63,     11, et_inst, ef_inst, rd_inst, nd_inst},
+
+	{19,  5,  8,      0, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 10, 13,      1, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 15, 18,      2, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 20, 23,      3, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 25, 28,      4, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 30, 33,      5, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 35, 38,      6, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 40, 43,      7, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 45, 48,      8, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 50, 53,      9, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 55, 58,     10, et_trns, ef_trns, rd_trns, nd_trns},
+	{19, 60, 63,     11, et_trns, ef_trns, rd_trns, nd_trns},
+
+/* 
+
+*/
+
+	{20,  6,  6,      0, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20,  8,  8,      0, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 11, 11,      1, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 13, 13,      1, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 16, 16,      2, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 18, 18,      2, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 21, 21,      3, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 23, 23,      3, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 26, 26,      4, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 28, 28,      4, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 31, 31,      5, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 33, 33,      5, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 36, 36,      6, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 38, 38,      6, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 41, 41,      7, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 43, 43,      7, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 46, 46,      8, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 48, 48,      8, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 51, 51,      9, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 53, 53,      9, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 56, 56,     10, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 58, 58,     10, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+	{20, 61, 61,     11, et_dyn,  ef_dyn,  rd_dyn,  nd_dyn},
+	{20, 63, 63,     11, et_loc,  ef_loc,  rd_loc,  nd_loc},
+
+/* 
+
+*/
+
+	{21,  6,  8,      0, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 11, 13,      1, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 16, 18,      2, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 21, 23,      3, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 26, 28,      4, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 31, 33,      5, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 36, 38,      6, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 41, 43,      7, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 46, 48,      8, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 51, 53,      9, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 56, 58,     10, et_vel,  ef_vel,  rd_vel,  nd_vel},
+	{21, 61, 63,     11, et_vel,  ef_vel,  rd_vel,  nd_vel},
+
+
+	{23,  6,  6,      0, et_res1, ef_res1, rd_res1, nd_res1},
+	{23,  8, 12,      0, et_aval, ef_aval, rd_aval, nd_aval},
+
+	{23, 15, 15,      1, et_res1, ef_res1, rd_res1, nd_res1},
+	{23, 17, 21,      1, et_aval, ef_aval, rd_aval, nd_aval},
+
+	{23, 24, 24,      2, et_res1, ef_res1, rd_res1, nd_res1},
+	{23, 26, 30,      2, et_aval, ef_aval, rd_aval, nd_aval},
+
+	{23, 33, 33,      3, et_res1, ef_res1, rd_res1, nd_res1},
+	{23, 35, 39,      3, et_aval, ef_aval, rd_aval, nd_aval},
+
+	{23, 42, 42,      4, et_res1, ef_res1, rd_res1, nd_res1},
+	{23, 44, 48,      4, et_aval, ef_aval, rd_aval, nd_aval},
+
+	{23, 51, 51,      5, et_res1, ef_res1, rd_res1, nd_res1},
+	{23, 53, 57,      5, et_aval, ef_aval, rd_aval, nd_aval},
+
+	{23, 61, 62,      0, et_agrp, ef_agrp, rd_agrp, nd_agrp},
+
+	{24,  7,  8, 0x0000, et_scor, ef_scor, rd_scor, nd_scor},
+	{24, 10, 25, 0x0000, et_null, ef_null, rd_null, nd_null},
+
+
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+/* 
+
+*/
+
+struct curpak sc_flds = {
+
+	stdctp3,	/* curtype */
+	nokey,		/* premove */
+	nokey,		/* pstmove */
+	cxkstd,		/* cx_key */
+	cykstd,		/* cy_key */
+	sdcxu,		/* cx_upd */
+	sdcyu,		/* cy_upd */
+	nokey,		/* xy_up */
+	nokey,		/* xy_dn */
+	sdxkey,		/* x_key */
+	select,		/* e_key */
+	sdmkey,		/* m_key */
+	stddkey,	/* d_key */
+	scntfld,	/* not_fld */
+	sc_fet1,	/* curfet */
+	sdboxes,	/* csbp */
+	crate1,		/* cratex */
+	crate1,		/* cratey */
+	CT_GRAF,	/* cmtype */
+	C1X,		/* cxval */
+	C1Y		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	et_null() .. nd_null() -- null data entry key processors
+   =============================================================================
+*/
+
+short		/* null et_... */
+et_null()
+{
+	return(SUCCESS);
+}
+
+short		/* null ef_... */
+ef_null()
+{
+	return(SUCCESS);
+}
+
+short		/* null rd_... */
+rd_null()
+{
+	return(SUCCESS);
+}
+
+short		/* null nd_... */
+nd_null()
+{
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	istart() -- start insert mode
+   =============================================================================
+*/
+
+istart()
+{
+	register struct s_entry *ep, *pp, *tp;
+
+	if (insmode)				/* can't already be inserting */
+		return;
+
+	ep    = ep_adj(p_cur, 1, t_cur);	/* locate tail */
+
+	if (EV_SCORE EQ (0x007F & ep->e_type))	/* skip begin score event */
+		ep = ep->e_fwd;
+
+	if (EV_FINI EQ (0x007F & ep->e_type))	/* null if at end of score */
+		return;
+		
+	tp = scores[curscor]->e_bak;		/* locate end of score */
+	pp = ep->e_bak;				/* locate end of head */
+
+	ep->e_bak = E_NULL;			/* unhook tail from head */
+	pp->e_fwd = tp;				/* unhook head from tail */
+	(tp->e_bak)->e_fwd = E_NULL;		/* unhook tail from end */
+
+	tp->e_bak = pp;				/* connect end to head */
+
+	t_ins = t_cur;				/* record tail time */
+	peg   = ep;				/* hang tail on peg */
+
+	p_cur = ep_adj(pp, 0, t_cur);		/* adjust p_cur */
+	p_ctr = p_cur;				/* adjust p_ctr */
+	p_bak = ep_adj(p_cur, 0, t_bak);	/* adjust p_bak */
+	p_fwd = ep_adj(p_cur, 0, t_fwd);	/* adjust p_fwd */
+
+	insmode = TRUE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	icancel() -- cancel insert mode
+   =============================================================================
+*/
+
+icancel()
+{
+	register struct s_entry *ep, *tp, *rp;
+	struct s_entry *pp;
+	long endtime;
+
+	if (NOT insmode)
+		return;
+
+	tp = scores[curscor]->e_bak;		/* locate end of score */
+	pp = tp->e_bak;				/* locate end of head */
+
+	endtime = pp->e_time;			/* find last time in score */
+
+	if (t_cur > endtime)			/* use max of t_cur, endtime */
+		endtime = t_cur;
+
+	rp = peg;				/* point at start of tail */
+
+	while (E_NULL NE rp) {			/* scan each event in the tail */
+
+		ep = rp;			/* update pointers */
+		rp = ep->e_fwd;
+
+		ep->e_time = (ep->e_time - t_ins) + endtime;	/* adjust time */
+	}
+
+	ep->e_fwd = tp;				/* connect tail to end */
+	tp->e_bak = ep;				/* connect end to tail */
+
+	pp->e_fwd  = peg;			/* connect head to tail */
+	peg->e_bak = pp;			/* connect tail to head */
+
+	p_cur = ep_adj(pp, 0, t_cur);		/* adjust p_cur */
+	p_ctr = p_cur;				/* adjust p_ctr */
+	p_bak = ep_adj(p_cur, 0, t_bak);	/* adjust p_bak */
+	p_fwd = ep_adj(p_cur, 0, t_fwd);	/* adjust p_fwd */
+
+	insmode = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdcxu() -- score cursor x update processing
+   =============================================================================
+*/
+
+sdcxu()
+{
+	if (sdmctl EQ 0) {		/* typewriter up */
+
+		vtcxupd();
+
+	} else if (sdmctl > 0) {	/* menu up */
+
+		vtccol = XTOC(vtxval += cxrate);
+
+		if (vtccol > sdmlim[sdmctl][3])
+			vtxval = CTOX(vtccol = sdmlim[sdmctl][3]);
+		else if (vtccol < sdmlim[sdmctl][1])
+			vtxval = CTOX(vtccol = sdmlim[sdmctl][1]);
+
+	} else {		/* no menu showing */
+
+		cxval += cxrate;
+
+		if (cxval > CXMAX)
+			cxval = CXMAX;
+		else if (cxval < 0)
+			cxval = 0;
+	}
+
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdcyu() -- score cursor y update processing
+   =============================================================================
+*/
+
+sdcyu()
+{
+	if (sdmctl EQ 0) {
+
+		vtcyupd();
+
+	} else if (sdmctl > 0) {	/* menu up */
+
+		vtcrow = YTOR(vtyval += cyrate);
+
+		if (vtcrow < sdmlim[sdmctl][0])
+			vtyval = RTOY(vtcrow = sdmlim[sdmctl][0]);
+		else if (vtcrow > sdmlim[sdmctl][2])
+			vtyval = RTOY(vtcrow = sdmlim[sdmctl][2]);
+
+	} else {		/* no menu showing */
+
+		cyval += cyrate;
+
+		if (cyval > CYMAX)
+			cyval = CYMAX;
+		else if (cyval < 0)
+			cyval = 0;
+
+	}
+
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scntfld() -- not-in-field data entry key processing
+   =============================================================================
+*/
+
+short
+scntfld(k)
+short k;
+{
+	register short grp, fnc, var;
+
+	if (NOT astat)
+		return(FAILURE);
+
+	if (stcrow EQ 18) {		/* group status or mode */
+
+		if (stccol LT 5)
+			return(FAILURE);
+
+		grp = (stccol - 5) / 5;		/* group */
+		fnc = (stccol - 5) % 5;		/* status or mode */
+
+		if (fnc EQ 0) {			/* status */
+
+			if (k EQ 8) {		/* '-' */
+
+				grpstat[grp] = FALSE;
+				dsgstat(grp);
+				return(SUCCESS);
+
+			} else if (k EQ 9) {	/* '+' */
+
+				grpstat[grp] = TRUE;
+				dsgstat(grp);
+				return(SUCCESS);
+
+			} else
+				return(FAILURE);
+/* 
+
+*/
+		} else if (fnc EQ 1) {		/* mode */
+
+			if (k EQ 8) {		/* '-' */
+
+				grpmode[grp] = 0;
+				dsgmode(grp);
+				return(SUCCESS);
+
+			} else if (k EQ 9) {	/* '+' */
+
+				if (++grpmode[grp] GT 1)
+					grpmode[grp] = 2;
+
+				dsgmode(grp);
+				return(SUCCESS);
+
+			} else
+				return(FAILURE);
+
+		} else
+			return(FAILURE);
+/* 
+
+*/
+	} else if (stcrow EQ 22) {	/* analog variables */
+
+		if (stccol < 5)
+			return(FAILURE);
+
+		var = (stccol - 5) / 9;		/* variable */
+		fnc = (stccol - 5) % 9;		/* field column */
+		grp = abs(angroup) - 1;		/* group */
+
+		if (fnc EQ 0) {			/* mode column */
+
+			if (k EQ 8) {		/* '-' */
+
+				varmode[var][grp] = 0;
+				dsvmode(var);
+				return(SUCCESS);
+
+			} else if (k EQ 9) {	/* '+' */
+
+				if (++varmode[var][grp] GT 1)
+					varmode[var][grp] = 2;
+
+				dsvmode(var);
+				return(SUCCESS);
+			}
+		}
+	}
+
+	return(FAILURE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cp2time() -- check cursor position and convert it to time
+
+	Sets 'ctime' if the cursor x argument, 'cx',  is within the score.
+   =============================================================================
+*/
+
+short
+cp2time(cx)
+short cx;
+{
+	register long ct;
+
+	ct = t_cur + ((long)cx - PCENTER);
+
+	if (ct < 0L)			/* if out of score time range */
+		return(FALSE);		/* ... return FALSE */
+
+	ctime = ct;			/* set ctime */
+	return(TRUE);			/* ... and return TRUE */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	delevts() -- delete record enabled non-note events at current time
+   =============================================================================
+*/
+
+short
+delevts(etp, thetime)
+register short etp;
+register long thetime;
+{
+	register struct s_entry *ep, *np;
+	register short et;
+	register short rc;
+	register short dsw;
+
+	rc = FALSE;				/* intialize return code */
+
+	ep = ep_adj(p_cur, 1, thetime);		/* start at left end of chain */
+
+/* 
+
+*/
+	while (ep->e_time EQ thetime) {		/* for each event at ctime ... */
+
+		np = ep->e_fwd;			/* get next event pointer */
+		et = 0x007F & ep->e_type;	/* get type */
+		dsw = oktode(ep);		/* get deletion status */
+
+		if (dsw AND	/* delete event if it's deletable ... */
+		    ((etp EQ -1) OR (et EQ etp))) {  /* ... and the right kind */
+
+			rc = TRUE;
+
+			if (-1 NE ehdlist[et])	/* if this is a header event ... */
+				eh_rmv(ep, ehdlist[et]);  /* remove from hdr list */
+
+			/* fix up any effected pointers */
+
+			if (p_bak EQ ep)
+				p_bak = np;
+
+			if (p_cur EQ ep)
+				p_cur = np;
+
+			if (p_ctr EQ ep)
+				p_ctr = np;
+
+			if (p_fwd EQ ep)
+				p_fwd = np;
+
+			e_del(e_rmv(ep));	/* delete the event */
+		}
+
+		ep = np;
+	}
+
+	if (rc)				/* if anything was deleted ... */
+		sc_refr(t_cur);		/* ... update the display */
+
+	return(rc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	deladat() -- delete analog varaible data
+   =============================================================================
+*/
+
+short
+deladat()
+{
+	register struct s_entry *ep, *rp;
+	register short grp, rc, var, vc, vn;
+
+	rc = FALSE;
+
+	if (stccol < 6)				/* pointing at var ? */
+		return(rc);
+
+	vn = (stccol - 6) / 9;			/* variable number */
+	vc = (stccol - 6) % 9;			/* variable column */
+
+	ep = ep_adj(p_cur, 1, t_cur);		/* start at left end of chain */
+
+	if (vc EQ 0) {				/* resolution */
+
+		while (t_cur EQ ep->e_time) {
+
+			rp = ep->e_fwd;
+
+			if (EV_ANRS EQ (0x007F & ep->e_type)) {
+
+				grp = 0x000F & ep->e_data1;
+				var = 0x000F & (ep->e_data1 >> 4);
+
+				if ((var EQ vn) AND grpstat[grp] AND
+				    (2 EQ (ancmsw ? varmode[var][grp] :
+				     grpmode[grp]))) {
+
+					/* fix pointers */
+
+					if (p_bak EQ ep)
+						p_bak = rp;
+
+					if (p_cur EQ ep)
+						p_cur = rp;
+
+					if (p_ctr EQ ep)
+						p_ctr = rp;
+
+					if (p_fwd EQ ep)
+						p_fwd = rp;
+
+					/* delete event */
+
+					eh_rmv(ep, EH_ANRS);
+					e_del(e_rmv(ep));
+					rc = TRUE;
+				}
+			}
+
+			ep = rp;		/* next event */
+		}
+/* 
+
+*/
+	} else if ((vc GE 2) AND (vc LE 6)) {	/* value */
+
+		while (t_cur EQ ep->e_time) {
+
+			rp = ep->e_fwd;
+
+			if (EV_ANVL EQ (0x007F & ep->e_type)) {
+
+				grp = 0x000F & ep->e_data1;
+				var = 0x000F & (ep->e_data1 >> 4);
+
+				if ((var EQ vn) AND grpstat[grp] AND
+				    (2 EQ (ancmsw ? varmode[var][grp] :
+				     grpmode[grp]))) {
+
+					/* fix pointers */
+
+					if (p_bak EQ ep)
+						p_bak = rp;
+
+					if (p_cur EQ ep)
+						p_cur = rp;
+
+					if (p_ctr EQ ep)
+						p_ctr = rp;
+
+					if (p_fwd EQ ep)
+						p_fwd = rp;
+
+					e_del(e_rmv(ep));	/* delete */
+					rc = TRUE;
+				}
+			}
+
+			ep = rp;	/* next event */
+		}
+	}
+
+	if (rc) {			/* refresh the screen if it changed */
+
+		sc_refr(fc_val);
+		ds_anrs();
+		ds_anvl();
+	}
+
+	return(rc);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdxkey() -- score delete key processing
+   =============================================================================
+*/
+
+sdxkey()
+{
+	register short col, grp, sect;
+	register struct s_entry *ep, *rp;
+
+	if (NOT astat)			/* only do when key goes down */
+		return;
+
+	if (clkrun)			/* ... and not while clock is running */
+		return;
+
+	if (scmctl NE -1)		/* ... and area 1 menu is down */
+		return;
+/* 
+
+*/
+	if (sdmctl EQ 4) {		/* section menu is up */
+
+		if (((vtcrow EQ 19) OR (vtcrow EQ 20)) AND
+		    (vtccol GE 24)) {
+
+			if (NOT recsw)
+				return;
+
+			/* set up to delete a section marker */
+
+			sect = ((vtccol - 24) >> 2) + ((vtcrow EQ 20) ? 10 : 0);
+			col  = (vtccol - 24) & 3;
+
+			switch (col) {
+
+			case 0:		/* delete begin section */
+
+
+				if (E_NULL NE (ep = seclist[curscor][sect])) {
+
+					/* fix pointers */
+
+					rp = ep->e_fwd;
+
+					if (p_bak EQ ep)
+						p_bak = rp;
+
+					if (p_cur EQ ep)
+						p_cur = rp;
+
+					if (p_ctr EQ ep)
+						p_ctr = rp;
+
+					if (p_fwd EQ ep)
+						p_fwd = rp;
+
+					eh_rmv(ep, EH_SBGN);	/* delete */
+					e_del(e_rmv(ep));
+					seclist[curscor][sect] = E_NULL;
+					sdmenu(-1);		/* take down menu */
+					sc_refr(fc_val);	/* refresh screen */
+				}
+
+				break;
+/* 
+
+*/
+			case 1:		/* section number */
+			case 2:
+				break;
+
+			case 3:		/* delete end section */
+
+				if (E_NULL NE
+				   (ep = ehfind(EV_SEND, -1L, sect, -1))) {
+
+					/* fix pointers */
+
+					rp = ep->e_fwd;
+
+					if (p_bak EQ ep)
+						p_bak = rp;
+
+					if (p_cur EQ ep)
+						p_cur = rp;
+
+					if (p_ctr EQ ep)
+						p_ctr = rp;
+
+					if (p_fwd EQ ep)
+						p_fwd = rp;
+
+					eh_rmv(ep, EH_SEND);	/* delete */
+					e_del(e_rmv(ep));
+					sdmenu(-1);		/* take down menu */
+					sc_refr(fc_val);	/* refresh screen */
+				}
+
+				break;
+			}
+
+			return;
+
+/* 
+
+*/
+		} else if ((vtcrow EQ 23) AND
+			   (vtccol GE 28) AND (vtccol LE 62)) {
+
+			/* group map entry */
+
+			col = vtccol - 28;
+
+			if (2 EQ (col % 3))
+				return;
+
+			grp = col / 3;
+			grptmap[grp] = -1;
+			dsgtme(grp);
+			return;
+		}
+	}
+
+	if (NOT recsw)	/* do only if recording */
+		return;
+
+	if ((cyval GE 14) AND (cyval LE 223)) {			/* notes */
+
+		delnote();		/* delete a note */
+
+	} else if ((cyval GE 224) AND (cyval LE 237)) {		/* new data */
+
+		if (cp2time(cxval))
+			delevts(-1, ctime);	/* delete all events at cursor */
+
+/* 
+
+*/
+
+	} else if (stcrow EQ 17) {
+
+		if ((stccol GE 11) AND (stccol LE 12))
+			delevts(EV_ASGN, t_cur);		/* assignment */
+		else if (stccol EQ 19)
+			delevts(EV_TUNE, t_cur);		/* tuning */
+		else if ((stccol GE 27) AND (stccol LE 29))
+			delevts(EV_TMPO, t_cur);		/* tempo */
+		else if ((stccol GE 36) AND (stccol LE 38))
+			delevts(EV_INTP, t_cur);		/* interpolation */
+		else if ((stccol GE 40) AND (stccol LE 43))
+			delevts(EV_STOP, t_cur);		/* stop */
+		else if ((stccol GE 45) AND (stccol LE 48))
+			delevts(EV_NEXT, t_cur);		/* next */
+		else if ((stccol GE 50) AND (stccol LE 55))
+			delevts(EV_PNCH, t_cur);		/* punch in/out */
+
+	} else if ((stcrow EQ 18) AND
+		   (0 EQ ((stccol - 5) % 5))) {			/* group status */
+
+		delevts(EV_GRP, t_cur);
+
+	} else if ((stcrow EQ 18) AND
+		    ((2 EQ ((stccol - 5) % 5)) OR
+		     (3 EQ ((stccol - 5) % 5)))) {		/* instrument */
+
+		delevts(EV_INST, t_cur);
+
+	} else if (stcrow EQ 19) {				/* transposition */
+
+		delevts(EV_TRNS, t_cur);
+
+	} else if ((stcrow EQ 20) AND (stccol GE 6) AND
+		   (0 EQ ((stccol - 6) % 5))) {			/* dynamics */
+
+		delevts(EV_DYN, t_cur);
+
+	} else if ((stcrow EQ 20) AND (stccol GE 6) AND
+		   (2 EQ ((stccol - 6) % 5))) {			/* location */
+
+		delevts(EV_LOCN, t_cur);
+
+	} else if (stcrow EQ 23) {				/* analog */
+
+		deladat();
+/* 
+
+*/
+	} else if (stcrow EQ 24) {				/* score */
+
+		if (stccol LE 4) {
+
+			/* clear score */
+
+			if (insmode)		/* cancel insert mode */
+				icancel();
+
+			sc_clr(curscor);	/* clear score itself */
+			selscor(curscor);	/* refresh the display */
+
+		} else if ((stccol GE 10) AND (stccol LE 25)) {
+
+			/* clear score name */
+
+			memset(scname[curscor], ' ', 16);
+			dswin(13);
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdmkey() -- score display menu key processor
+   =============================================================================
+*/
+
+sdmkey()
+{
+	if (astat) {
+
+		if (insmode)
+			icancel();
+	}
+
+	stdmkey();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scfield() -- setup field routines for the score display
+   =============================================================================
+*/
+
+scfield()
+{
+	curset(&sc_flds);
+}
Index: ram/scgoto.c
===================================================================
--- ram/scgoto.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scgoto.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,251 @@
+/*
+   =============================================================================
+	scgoto.c -- position display at a given frame time
+	Version 48 -- 1988-09-23 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUG_GO	0	/* define non-zero for sc_goto() debug */
+#define	CHECKPTR	0	/* define non-zero to check pointers */
+
+#include "hwdefs.h"
+#include "stddefs.h"
+#include "graphdef.h"
+#include "score.h"
+#include "scfns.h"
+#include "memory.h"
+#include "vsdd.h"
+#include "slice.h"
+#include "midas.h"
+
+/* variables defined elsewhere */
+
+#if	DEBUG_GO
+extern	short	verbose, testing;
+#endif
+
+extern	short	recsw;
+extern	short	ndisp;
+extern	short	sd;
+extern	short	swctrl;
+extern	short	swflag;
+
+extern	struct	gdsel	*gdfsep;
+
+extern	struct	gdsel	*gdstbc[];
+extern	struct	gdsel	*gdstbn[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sc_goto(tval) -- position score display at time 'tval'
+   =============================================================================
+*/
+
+int
+sc_goto(tval)
+register long tval;
+{
+	register struct gdsel	*gdsp;
+	register struct s_entry *rp;
+	register long	tf, rt;
+	register short	mod48 = 48;
+
+#if	CHECKPTR
+	Pcheck(p_fwd, "p_fwd - sc_goto entry");
+	Pcheck(p_ctr, "p_ctr - sc_goto entry");
+	Pcheck(p_bak, "p_bak - sc_goto entry");
+	Pcheck(p_cur, "p_cur - sc_goto entry");
+#endif
+
+	/* quick check of pointers so we don't crash */
+
+	if ((p_fwd EQ E_NULL) OR (p_cur EQ E_NULL) OR
+	    (p_bak EQ E_NULL) OR (p_ctr EQ E_NULL))
+		return(FAILURE);
+
+	if (v_regs[5] & 0x0180)		/* setup for VSDD bank 0 */
+		vbank(0);
+
+	sd     = D_FWD;			/* set display and scroll direction */
+	swctrl = FALSE;			/* stop scroll wheel */
+	swflag = FALSE;			/* ... */
+	
+	recsw = FALSE;			/* force play mode on goto */
+	dsrpmod();			/* update video and LCD displays */
+
+	if (ndisp EQ 2)
+		sreset();		/* reset highlighting if score is up */
+
+	quiet();			/* quiet the instrument */
+	clrnl();			/* clear note entry lists */
+	clrsctl();			/* clear slice control data */
+
+	t_bak = tval - TO_BAK;		/* set target time at p_bak */
+	t_fwd = t_bak;			/* set target time at p_fwd */
+	t_ctr = tval;			/* set target time at p_ctr */
+	t_cur = tval;			/* set target time at p_cur */
+
+	p_bak = frfind(t_bak, 0);	/* position p_bak at t_bak */
+	p_cur = frfind(t_cur, 1);	/* position p_cur at t_cur */
+	p_fwd = frfind(t_fwd, 1);	/* position p_fwd at t_fwd */
+
+/* 
+
+*/
+	/* reset the display pointers to the target time */
+
+	if ((t_fwd LE 0) AND (p_fwd->e_type EQ EV_SCORE))
+		p_fwd = p_fwd->e_fwd;	/* skip score header */
+
+	rp = p_fwd;			/* current forward event pointer */
+	rt = t_fwd;			/* current forward event time */
+	tf = tval + TO_FWD;		/* target event time */
+
+#if	DEBUG_GO
+	if (verbose) {
+
+		printf("## sc_goto(%8ld) ENTRY - tf: %8ld\n", tval, tf);
+
+		printf("  t_bak: %8ld  t_ctr: %8ld  t_fwd: %8ld  t_cur: %8ld\n",
+			t_bak, t_ctr, t_fwd, t_cur);
+
+		printf("  p_bak: %08lX  p_ctr: %08lX  p_fwd: %08lX  p_cur: %08lX\n",
+			p_bak, p_ctr, p_fwd, p_cur);
+	}
+#endif
+
+/* 
+
+*/
+
+	while (rt++ LT tf) {		/* advance p_fwd chain to tf */
+
+		if (rp->e_type NE EV_FINI) {	/* don't pass end of score */
+
+			while (rp->e_time LE rt) {	/* check event time */
+
+				if (ndisp EQ 2)		/* display event */
+					se_disp(rp, D_FWD, gdstbn, 0);
+
+				rp = rp->e_fwd;	/* point at next event */
+
+				if (rp->e_type EQ EV_FINI)	/* done if at end */
+					break;
+			}
+		}
+
+		if (ndisp EQ 2) {
+
+			if (0 EQ (rt % mod48)) {	/* handle beat markers */
+
+				if ((struct gdsel *)NULL NE (gdsp = gdfsep)) {
+
+					gdfsep = gdsp->next;
+
+					gdsp->next = gdstbn[12];
+					gdsp->note = 0x1111;
+					gdsp->code = 1;
+
+					gdstbn[12] = gdsp;
+				}
+			}
+
+			sc_adv();	/* scroll the display */
+		}
+	}
+
+	p_fwd  = rp;		/* update p_fwd for next event */
+	t_fwd  = tf;		/* update t_fwd */
+
+/* 
+
+*/
+	/* execute & display things at current time to start things out right */
+
+	if (ndisp EQ 2)		/* if score is up ... */
+		dssect();	/* display section */
+
+	rp = p_cur;		/* current event pointer */
+	rt = t_cur;		/* current event time */
+
+	if ((rt LE 0) AND (rp->e_type EQ EV_SCORE))	/* skip score header */
+		rp = rp->e_fwd;
+
+	if (rp->e_type NE EV_FINI) {	/* if we aren't at end of score */
+
+		while (rp->e_time EQ rt) {	/* do events at current time */
+
+			se_exec(rp, D_FWD);		/* execute event */
+
+			if (ndisp EQ 2)
+				se_disp(rp, D_FWD, gdstbc, 1);	/* update center slice */
+
+			rp = rp->e_fwd;			/* point at next event */
+
+			if (rp->e_type EQ EV_FINI)	/* done if at end */
+				break;
+		}
+	}
+
+	p_cur = rp;		/* update p_cur */
+	p_ctr = rp;		/* update p_ctr */
+
+	if (ndisp EQ 2) {		/* if score is up ... */
+
+		scupd();	/* update event display */
+		sdwins();	/* refresh windows */
+	}
+
+/* 
+
+*/
+
+#if	DEBUG_GO
+	if (verbose) {
+
+		printf("## sc_goto(%8ld) EXIT\n");
+
+		printf("  t_bak: %8ld  t_ctr: %8ld  t_fwd: %8ld  t_cur: %8ld\n",
+			t_bak, t_ctr, t_fwd, t_cur);
+
+		printf("  p_bak: %08lx  p_ctr: %08lx  p_fwd: %08lx  p_cur: %08lx\n",
+			p_bak, p_ctr, p_fwd, p_cur);
+	}
+#endif
+
+#if	CHECKPTR
+	Pcheck(p_fwd, "p_fwd - sc_goto exiting");
+	Pcheck(p_ctr, "p_ctr - sc_goto exiting");
+	Pcheck(p_bak, "p_bak - sc_goto exiting");
+	Pcheck(p_cur, "p_cur - sc_goto exiting");
+#endif
+
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sc_refr() -- refresh the display to a particular time
+   =============================================================================
+*/
+
+short
+sc_refr(t)
+long t;
+{
+	short oldrs, rc;
+
+	oldrs = recsw;		/* save recsw */
+	rc = sc_goto(t);	/* refresh the display via a goto */
+	recsw = oldrs;		/* restore recsw */
+	dsrpmod();		/* update display of recsw */
+	return(rc);		/* return status from sc_goto */
+}
Index: ram/scinit.c
===================================================================
--- ram/scinit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scinit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,689 @@
+/*
+   =============================================================================
+	scinit.c -- score list functions
+	Version 33 -- 1988-07-28 -- D.N. Lynx Crowe
+
+	long
+	scinit()
+
+		Initializes the score data structures.
+		Returns the number of free storage units.
+
+	struct s_entry *
+	e_clr(e1)
+	struct s_entry *e1;
+
+		Clears the event pointed to by 'e1'.  Returns 'e1'.
+		Preserves e_size field, all others set to zero.
+
+	struct s_entry *
+	e_ins(e1, e2)
+	struct s_entry *e1, *e2;
+
+		Inserts the event pointed to by 'e1' after the event
+		pointed to by 'e2'.  Returns 'e1'.
+
+	struct s_entry *
+	e_rmv(e1)
+	struct s_entry *e1;
+
+		Removes the event pointed to by 'e1' from the list it's in.
+		Returns 'e1'.
+
+	struct s_entry *
+	e_alc(w)
+	int w;
+
+		Allocates a new event entry.
+		Returns the event entry address, or E_NULL
+		if none can be allocated.
+
+	short
+	e_del(e1)
+	struct s_entry *e1;
+
+		Deallocates the event entry pointed to by 'e1'.
+		Returns 0 if successful, 1 if not.
+
+	long
+	evleft()
+
+		Returns total number of longs left for score storage.
+
+
+	eh_ins(ne, et)
+	struct s_entry *ne;
+	short et;
+
+		Inserts event 'ne' of type 'et' into score header list
+		"hplist[curscor][et]" along the "up" chain.
+
+	eh_rmv(ev, et)
+	struct s_entry *ev;
+	short et;
+
+		Removes event 'ev' of type 'et' from score header list
+		"hplist[curscor][et]" along the "up" chain.
+
+	sc_clr(ns)
+	short ns;
+
+		Clears score 'ns'.
+
+	short
+	selscor(ns)
+	short ns;
+
+		Selects score 'ns' for use.
+
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "score.h"
+
+/* 
+
+*/
+
+extern	short	sd;		/* Scroll direction */
+extern	short	curasg;		/* Current assgnment table */
+extern	short	tmpoval;	/* Current tempo */
+extern	short	curtun;		/* Current tuning table */
+
+extern	BOOL	se_chg;		/* Score free list changed flag */
+
+extern	long	spcount;	/* Score storage pool free entry count */
+extern	long	frags;		/* Score storage pool fragment count */
+
+extern	long	se1_cnt;	/* Score free list E_SIZE1 entry count */
+extern	long	se2_cnt;	/* Score free list E_SIZE2 entry count */
+extern	long	se3_cnt;	/* Score free list E_SIZE3 entry count */
+
+extern	long	*pspool;	/* Score storage pool pointer */
+
+extern	struct	s_entry	*size1;	/* Score E_SIZE1 entry free list pointer */
+extern	struct	s_entry	*size2;	/* Score E_SIZE2 entry free list pointer */
+extern	struct	s_entry	*size3;	/* Score E_SIZE3 entry free list pointer */
+
+extern	struct s_entry *scores[N_SCORES];	/* Score pointer table */
+extern	struct s_entry *seclist[N_SCORES][N_SECTS];	/* Section pointer table */
+extern	struct s_entry *hplist[N_SCORES][N_TYPES];	/* Score change list pointers */
+
+extern	struct	s_time	stimes[N_SCORES][N_SECTS];	/* section times */
+
+extern	char	scname[N_SCORES][16];	/* Score names */
+
+extern	short	curscor;	/* Current score number */
+extern	short	cursect;	/* Current section number in score */
+
+extern	struct s_entry *scp;	/* Current score pointer */
+
+extern	long	t_bak;		/* Time at p_bak */
+extern	long	t_cur;		/* Time at p_cur */
+extern	long	t_ctr;		/* Time at p_ctr */
+extern	long	t_fwd;		/* Time at p_fwd */
+
+extern	struct s_entry *p_bak;	/* Pointer to entry at left edge of display */
+extern	struct s_entry *p_cur;	/* Pointer to entry at current execution time */
+extern	struct s_entry *p_ctr;	/* Pointer to entry at center of display */
+extern	struct s_entry *p_fwd;	/* Pointer to entry at right edge of display */
+
+extern	long	spool[];	/* Score storage pool */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	evleft() -- returns total number of longs left for score storage.
+   =============================================================================
+*/
+
+long
+evleft()
+{
+	return(spcount + (se1_cnt * E_SIZE1) + (se2_cnt * E_SIZE2) +
+		(se3_cnt * E_SIZE3));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scinit() -- initializes the score data structures.
+	Returns the number of free storage units.
+   =============================================================================
+*/
+
+long
+scinit()
+{
+	register long i, *cp;
+
+	se1_cnt = 0L;					/* fragments */
+	size1   = E_NULL;
+	se2_cnt = 0L;
+	size2   = E_NULL;
+	se3_cnt = 0L;
+	size3   = E_NULL;
+	se_chg  = TRUE;
+	frags   = 0L;
+
+	spcount = (long)MAX_SE;				/* storage pool */
+	pspool  = spool;
+	cp = spool;
+
+	for (i = spcount; i-- > 0; )
+		*cp++ = 0L;
+
+	for (i = 0; i < N_SCORES; i++)			/* score names */
+		memcpy(scname[i], "{ empty score  }", 16);
+
+	memsetw(scores,  0,  2 * N_SCORES);		/* score list */
+	memsetw(hplist,  0,  2 * N_SCORES * N_TYPES);	/* header lists */
+	memsetw(seclist, 0,  2 * N_SCORES * N_SECTS);	/* section lists */
+	memset(stimes,   0, 12 * N_SCORES * N_SECTS);	/* section times */
+
+	t_cur = t_ctr = 0L;					/* times */
+	t_bak = t_cur - TO_BAK;
+	t_fwd = t_cur + TO_FWD;
+
+	p_bak = E_NULL;					/* pointers */
+	p_cur = E_NULL;
+	p_ctr = E_NULL;
+	p_fwd = E_NULL;
+	scp   = E_NULL;
+
+	curscor = 0;					/* current score */
+	cursect = 0;					/* current section */
+
+	return(evleft());
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	e_clr(e1) -- clear the event pointed to by 'e1'.  Returns 'e1'.
+	Preserves e_size field, all others set to zero.
+   =============================================================================
+*/
+
+struct s_entry *
+e_clr(e1)
+register struct s_entry *e1;
+{
+	switch (e1->e_size) {
+
+	case E_SIZE3:
+
+		e1->e_lft   = E_NULL;
+		e1->e_rgt   = E_NULL;
+
+	case E_SIZE2:
+
+		e1->e_up    = E_NULL;
+		e1->e_dn    = E_NULL;
+
+	case E_SIZE1:
+
+		e1->e_fwd   = E_NULL;
+		e1->e_bak   = E_NULL;
+
+		e1->e_time  = 0L;
+		e1->e_type  = EV_NULL;
+		e1->e_data1 = 0;
+		e1->e_data2 = 0;
+	}
+
+	return(e1);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	e_ins(e1, e2) -- inserts the event pointed to by 'e1' after the event
+	pointed to by 'e2'.  Returns 'e1'.
+   =============================================================================
+*/
+
+struct s_entry *
+e_ins(e1, e2)
+register struct s_entry *e1, *e2;
+{
+	register struct s_entry *t1;
+
+	t1 = e2->e_fwd;
+	e1->e_fwd = t1;
+	e1->e_bak = e2;
+	e2->e_fwd = e1;
+	t1->e_bak = e1;
+	return(e1);
+}
+
+/*
+   =============================================================================
+	e_rmv(e1) -- removes the event pointed to by 'e1' from the list it's in.
+	Returns 'e1'.
+   =============================================================================
+*/
+
+struct s_entry *
+e_rmv(e1)
+register struct s_entry *e1;
+{
+	register struct s_entry *t1, *t2;
+
+	t1 = e1->e_bak;
+	t2 = e1->e_fwd;
+	t1->e_fwd = t2;
+	t2->e_bak = t1;
+	e1->e_fwd = E_NULL;
+	e1->e_bak = E_NULL;
+	return(e1);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	e_alc() -- allocates a new event entry.
+	Returns the event entry address, or E_NULL if none can be allocated.
+   =============================================================================
+*/
+
+struct s_entry *
+e_alc(w)
+short w;
+{
+	register struct s_entry *ev, *ex;
+
+	se_chg = TRUE;
+
+	switch (w) {
+
+	case E_SIZE1:
+
+		if (spcount LT E_SIZE1) {	/* try raw free pool first */
+
+			if (se1_cnt EQ 0) {	/* try for a deleted entry */
+
+				if (se3_cnt) {	/* try to split a size3 entry */
+
+					ex = size3;
+					size3 = ex->e_fwd;
+					++frags;
+					--se3_cnt;
+					ex->e_size = E_SIZE1;
+					ex->e_fwd  = E_NULL;
+					return(ex);
+
+				} else {
+
+					if (se2_cnt) {	/* try a size2 split */
+
+						ex = size2;
+						size2 = size2->e_fwd;
+						ex->e_size = E_SIZE1;
+						ex->e_fwd = E_NULL;
+						++frags;
+						--se2_cnt;
+						return(ex);
+
+					} else {
+
+						return(E_NULL);	/* no space */
+					}
+				}
+/* 
+
+*/
+			} else {	/* deleted entry available */
+
+				ex = size1;
+				size1 = size1->e_fwd;
+				ex->e_fwd = E_NULL;
+				--se1_cnt;
+				return(ex);
+			}
+
+		} else {	/* raw storage available */
+
+			ex = (struct s_entry *)pspool;
+			pspool += E_SIZE1;
+			spcount -= E_SIZE1;
+			ex->e_size = E_SIZE1;
+			return(ex);
+		}
+
+/* 
+
+*/
+
+	case E_SIZE2:
+
+		if (spcount LT E_SIZE2) {	/* try for raw storage */
+
+			if (se2_cnt EQ 0) {	/* try for a deleted entry */
+
+				if (se3_cnt) {	/* try to split a size3 entry */
+
+					ex = size3;
+					size3 = size3->e_fwd;
+					ex->e_size = E_SIZE2;
+					ex->e_fwd = E_NULL;
+					--se3_cnt;
+					++frags;
+					return(ex);
+
+				} else {
+
+					return(E_NULL);		/* no space */
+				}
+
+			} else {	/* deleted entry available */
+
+				ex = size2;
+				size2 = size2->e_fwd;
+				ex->e_fwd = E_NULL;
+				--se2_cnt;
+				return(ex);
+			}
+
+		} else {	/* raw storage available */
+
+			ex = (struct s_entry *)pspool;
+			pspool += E_SIZE2;
+			spcount -= E_SIZE2;
+			ex->e_size = E_SIZE2;
+			return(ex);
+
+		}
+
+/* 
+
+*/
+
+	case E_SIZE3:
+
+		if (spcount LT E_SIZE3) {	/* try for raw storage */
+
+			if (se3_cnt EQ 0) {	/* try for a deleted entry */
+
+				return(E_NULL);		/* no space left */
+
+			} else {	/* deleted entry available */
+
+				ex = size3;
+				size3 = size3->e_fwd;
+				ex->e_fwd = E_NULL;
+				--se3_cnt;
+				return(ex);
+			}
+
+		} else {	/* raw storage available */
+
+			ex = (struct s_entry *)pspool;
+			pspool += E_SIZE3;
+			spcount -= E_SIZE3;
+			ex->e_size = E_SIZE3;
+			return(ex);
+		}
+
+	default:
+
+		return(E_NULL);		/* invalid request */
+	}
+
+	return(E_NULL);		/* something went 'worng' ... */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	e_del(e1) -- deallocates the event entry pointed to by 'e1'.
+	Returns 0 if successful, 1 if not.
+   =============================================================================
+*/
+
+short
+e_del(e1)
+register struct s_entry *e1;
+{
+	e_clr(e1);
+
+	switch (e1->e_size) {
+
+	case E_SIZE1:
+
+		e1->e_fwd = size1;
+		size1 = e1;
+		++se1_cnt;
+		break;
+
+	case E_SIZE2:
+
+		e1->e_fwd = size2;
+		size2 = e1;
+		++se2_cnt;
+		break;
+
+	case E_SIZE3:
+
+		e1->e_fwd = size3;
+		size3 = e1;
+		++se3_cnt;
+		break;
+
+	default:
+		return(1);
+	}
+
+	se_chg = TRUE;
+	return(0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	eh_ins(ne, et) -- insert event 'ne' of type 'et' into score header list
+	"hplist[curscor][et]" along the "up" chain.
+   =============================================================================
+*/
+
+eh_ins(ne, et)
+register struct s_entry *ne;
+short et;
+{
+	register struct s_entry *hp, *ep;
+
+	hp = hplist[curscor][et];		/* get list pointer */
+
+	if (hp EQ E_NULL) {			/* if list was empty */
+
+		hplist[curscor][et] = ne;	/* start the list */
+		ne->e_up = E_NULL;
+		ne->e_dn = E_NULL;
+		return;
+	}
+
+	if (hp->e_time GT ne->e_time) {		/* if first entry was later */
+
+		hp->e_dn = ne;			/* add to start of list */
+		ne->e_up = hp;
+		ne->e_dn = E_NULL;
+		hplist[curscor][et] = ne;
+		return;
+	}
+
+	while (E_NULL NE (ep = hp->e_up)) {	/* search forward */
+
+		if (ep->e_time GT ne->e_time) {	/* if we find a later event */
+
+			ne->e_up = ep;		/* insert into list */
+			ne->e_dn = hp;
+			hp->e_up = ne;
+			ep->e_dn = ne;
+			return;
+		}
+
+		hp = ep;
+	}
+
+	hp->e_up = ne;		/* add to end of list */
+	ne->e_up = E_NULL;
+	ne->e_dn = hp;
+	return;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	eh_rmv(ev, et) -- remove event 'ev' of type 'et' from score header list
+	"hplist[curscor][et]" along the "up" chain.
+   =============================================================================
+*/
+
+eh_rmv(ev, et)
+register struct s_entry *ev;
+short et;
+{
+	if (hplist[curscor][et] EQ ev)			/* update hplist */
+		hplist[curscor][et] = ev->e_up;
+
+	if (ev->e_up NE E_NULL)				/* update entry above */
+		(ev->e_up)->e_dn = ev->e_dn;
+
+	if (ev->e_dn NE E_NULL)				/* update entry below */
+		(ev->e_dn)->e_up = ev->e_up;
+
+	ev->e_up = ev->e_dn = E_NULL;			/* update entry itself */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sc_clr(ns) -- clear score 'ns'.
+   =============================================================================
+*/
+
+sc_clr(ns)
+register short ns;
+{
+	register struct s_entry *dsp, *nsp;
+	register short i;
+
+	if (E_NULL NE (nsp = scores[ns])) {
+
+		while (nsp NE (dsp = nsp->e_fwd)) {
+
+			e_del(e_rmv(nsp));	/* delete this one */
+			nsp = dsp;		/* point at the next one */
+
+		}
+
+		e_del(nsp);			/* delete final entry */
+	}
+
+	for (i = 0; i < N_TYPES; i++)		/* clear header list */
+		hplist[ns][i] = E_NULL;
+
+	for (i = 0; i < N_SECTS; i++) {		/* clear section lists */
+
+		seclist[ns][i] = E_NULL;
+		memset(stimes[ns], 0, 12);
+	}
+
+	memcpy(scname[ns], "{ empty score  }", 16);
+
+	scores[ns] = E_NULL;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	selscor(ns) -- select score 'ns' for use
+   =============================================================================
+*/
+
+short
+selscor(ns)
+register short ns;
+{
+	register short	oldscor, grp;
+	register struct	s_entry *nsp, *ep;
+
+	clkset(0);		/* stop the clock */
+	dsclk();
+	fc_val = 0L;		/* reset to start of score */
+	sd = D_FWD;
+	oldscor = curscor;	/* setup for new score */
+	curscor = ns;
+
+	if (E_NULL EQ (nsp = scores[ns])) {	/* initialize score if needed */
+
+		if (E_NULL EQ (nsp = e_alc(E_SIZE1))) {	/* score header */
+
+			curscor = oldscor;
+			return(FAILURE);
+		}
+
+		scores[ns]   = nsp;
+		nsp->e_fwd   = nsp;
+		nsp->e_bak   = nsp;
+		nsp->e_type  = EV_SCORE;
+		nsp->e_data1 = ns;
+		nsp->e_time  = 0L;
+
+		if (E_NULL EQ (ep = e_alc(E_SIZE1))) {	/* score end */
+
+			sc_clr(ns);
+			curscor = oldscor;
+			return(FAILURE);
+		}
+
+		ep->e_type = EV_FINI;
+		ep->e_data1 = ns;
+		e_ins(ep, nsp);
+		ep->e_time = 0x7FFFFFFFL;
+		nsp = scores[ns];
+		memcpy(&scname[ns][0], "%%% Untitled %%%", 16);
+	}
+
+	scp   = nsp;
+	p_bak = nsp;
+	p_cur = nsp;
+	p_ctr = nsp;
+	p_fwd = nsp;
+	cursect = 0;
+	sc_goto(0L);
+	return(SUCCESS);
+}
Index: ram/scope.c
===================================================================
--- ram/scope.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scope.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,178 @@
+/*
+   =============================================================================
+	scope.c -- MIDAS-VII diagnostic scope functions
+	Version 6 -- 1988-10-12 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "fields.h"
+#include "curpak.h"
+
+#include "midas.h"
+
+#define	SCOPEOLD	0x0014		/* scope old text attribute */
+#define	SCOPENEW	0x0054		/* scope new text attribute */
+
+short		scopec;			/* scope col position */
+short		scopef;			/* scope control flag */
+short		scoper;			/* scope row position */
+
+unsigned	scopev;			/* last scope value */
+
+unsigned	*scopeob;		/* scope display object */
+
+char		scopebf[65];		/* scope display buffer */
+
+extern	short	nokey(), stdmkey();
+
+extern	short	astat;
+extern	short	ndisp;
+
+extern	short	scorpal[][3];
+
+extern	short	crate1[];
+
+/* forward reference */
+
+short	scptogl();
+
+/* 
+
+*/
+
+struct curpak dt_flds = {
+
+	nokey,			/* curtype */
+	nokey,			/* premove */
+	nokey,			/* pstmove */
+	nokey,			/* cx_key */
+	nokey,			/* cy_key */
+	nokey,			/* cx_upd */
+	nokey,			/* cy_upd */
+	nokey,			/* xy_up */
+	nokey,			/* xy_dn */
+	nokey,			/* x_key */
+	scptogl,		/* e_key */
+	stdmkey,		/* m_key */
+	nokey,			/* d_key */
+	nokey,			/* not_fld */
+	(struct fet *)NULL,	/* curfet */
+	(struct selbox *)NULL,	/* csbp */
+	crate1,			/* cratex */
+	crate1,			/* cratey */
+	CT_GRAF,		/* cmtype */
+	0,			/* cxval */
+	0			/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scope() -- display a value in binary on the crt
+   =============================================================================
+*/
+
+scope(val)
+register unsigned val;
+{
+	register short i;
+	register char *bp = scopebf;
+
+	if ((ndisp NE 11) OR (NOT scopef))
+		return;
+
+	vputs(scopeob, scoper++, scopec, scopebf, SCOPEOLD);
+
+	*bp++ = ' ';
+
+	if (scoper > 24) {
+
+		scoper = 0;
+		scopec += 12;
+
+		if (scopec GE 60)
+			scopec = 0;
+	}
+
+	scopev = val;
+
+	for (i = 0; i < 4; i++)
+		if (val & (0x0080 >> i))
+			*bp++ = '1';
+		else
+			*bp++ = '0';
+
+	*bp++ = ' ';
+
+	for (i = 4; i < 8; i++)
+		if (val & (0x0080 >> i))
+			*bp++ = '1';
+		else
+			*bp++ = '0';
+
+	*bp++ = ' ';
+	*bp = 0;
+
+	vputs(scopeob, scoper, scopec, scopebf, SCOPENEW);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scptogl() -- toggle "scope" status
+   =============================================================================
+*/
+
+scptogl()
+{
+	if (NOT astat)
+		return;
+
+	scopef = NOT scopef;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scopeon() -- put up the "scope" display
+   =============================================================================
+*/
+
+scopeon()
+{
+	scopeob = &v_score[0];
+
+	curset(&dt_flds);
+
+	scopec  = 0;
+	scopef  = TRUE;
+	scoper  = 0;
+	scopev  = 0;
+
+	strcpy(scopebf, " ???? ???? ");
+
+	dswap();
+
+	vbank(0);
+
+	memsetw(scopeob, 0, 32767);
+	memsetw(scopeob+32767L, 0, 12033);
+
+	SetObj(0, 1, 0, scopeob, 512, 350, 0, 0, CHR3, -1);
+	vsndpal(scorpal);
+
+	SetPri(0, 15);
+}
Index: ram/scordsp.c
===================================================================
--- ram/scordsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scordsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1113 @@
+/*
+   =============================================================================
+	scordsp.c -- MIDAS score display driver
+	Version 136 -- 1988-12-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "glcdefs.h"
+#include "glcfns.h"
+#include "graphdef.h"
+#include "lcdline.h"
+#include "memory.h"
+#include "secops.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "cmeta.h"
+#include "macros.h"
+#include "panel.h"
+#include "smdefs.h"
+
+#include "midas.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+#include "secdefs.h"
+#include "neddefs.h"
+
+/* 
+
+*/
+
+extern	unsigned	exp_c();
+
+/* variables defined elsewhere */
+
+extern	short	(*point)();
+
+extern	unsigned *obj0, *obj2, *obj3, *obj8, *obj11, *obj13, *obj14, *obj15;
+
+extern	unsigned	*consl;		/* constant slice pointer */
+extern	unsigned	*saddr;		/* score VSDD RAM base pointer */
+
+extern	unsigned	scrl;		/* score VSDD object scroll register image */
+
+extern	short	ancmsw;			/* analog variable r/p control source */
+extern	short	angroup;		/* analog variable group being shown */
+extern	short	clkctl;			/* clock control */
+extern	short	clkrun;			/* clock run switch */
+extern	short	clksrc;			/* clock source */
+extern	short	cxval;			/* cursor x */
+extern	short	cyval;			/* cursor y */
+extern	short	dubsw;			/* overdub / replace switch */
+extern	short	insmode;		/* insert switch */
+extern	short	lastam;			/* last assignment menu page */
+extern	short	ndisp;			/* display number */
+extern	short	pchsw;			/* punch-in enable switch */
+extern	short	recsw;			/* record / play switch */
+extern	short	sbase;			/* score VSDD RAM scroll offset */
+extern	short	scmctl;			/* score submenu #2 state */
+extern	short	sd;			/* score scroll direction */
+extern	short	sdmctl;			/* score submenu #1 state */
+extern	short	secop;			/* section operation */
+extern	short	sgcsw;			/* score graphic / text cursor switch */
+extern	short	sliders;		/* slider function */
+extern	short	soffset;		/* score scroll offset */
+extern	short	stccol;			/* text cursor column */
+extern	short	stcrow;			/* text cursor row */
+extern	short	submenu;		/* submenu cursor switch */
+extern	short	velflag;		/* velocity display enable flag */
+
+extern	char	bfs[];			/* display generation buffer */
+
+extern	char	*nedlbl[];		/* note edit labels */
+
+extern	short	kbobj[];		/* keyboard icon */
+
+extern	short	grpmode[];		/* group mode - 0 = play, 1 = stdby, 2 = rec */
+extern	short	grpstat[];		/* group status - 0 = off, non-0 = on */
+extern	short	lastvel[];		/* last velocity sent to group */
+
+extern	short	anrs[][16];		/* analog variable resolution */
+extern	short	varmode[][16];		/* analog variable record mode */
+
+extern	unsigned	slices[];	/* score display slices */
+
+extern	struct	valent	valents[];	/* s/m value table */
+
+/* 
+
+*/
+
+/* initialized stuff */
+
+short	var2src[6] = {		/* analog variable map */
+
+	SM_HTPW, SM_VTMW, SM_LPBR, SM_CTL1, SM_PED1, SM_KPRS
+};
+
+short	simled[3] = {		/* simulated LED colors for group modes */
+
+	0x00A2,		/* play mode    = green */
+	0x0062,		/* standby mode = yellow */
+	0x0052		/* record mode  = red */
+};
+
+char	nsvtab[] = {		/* note value modifier (accidental) table */
+
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  21 ..  32 -- A0 .. G#0 */
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  33 ..  44 -- A1 .. G#1 */
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  45 ..  56 -- A2 .. G#2 */
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  57 ..  68 -- A3 .. G#3 */
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  69 ..  80 -- A4 .. G#4 */
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  81 ..  92 -- A5 .. G#5 */
+	0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,	/*  93 .. 104 -- A6 .. G#6 */
+	0, 1, 0, 0				/* 105 .. 108 -- A7 .. C7  */
+};
+
+short	scorpal[16][3] = {		/* score palette */
+
+	{0, 0, 0},	/*  0 - black */
+	{2, 3, 3},	/*  1 - white */
+	{0, 0, 1},	/*  2 - dark blue #1 */
+	{2, 0, 2},	/*  3 - dark violet */
+	{0, 0, 3},	/*  4 - dark blue #2 */
+	{3, 0, 0},	/*  5 - red */
+	{3, 3, 0},	/*  6 - yellow */
+	{1, 2, 0},	/*  7 - dark green */
+	{0, 3, 3},	/*  8 - light blue */
+	{3, 2, 0},	/*  9 - tan */
+	{0, 3, 0},	/* 10 - light green */
+	{3, 1, 2},	/* 11 - light violet */
+	{0, 2, 3},	/* 12 - medium blue */
+	{2, 0, 0},	/* 13 - dark red */
+	{2, 2, 1},	/* 14 - ivory */
+	{3, 3, 3}	/* 15 - bright white */
+};
+
+/* 
+
+*/
+
+char	*clklbl[] = {	/* clock control and scource labels */
+
+	"Local",	/* 0 - CK_LOCAL */
+	"MIDI ",	/* 1 - CK_MIDI  */
+	"SMPTE",	/* 2 - CK_SMPTE */
+	"PLS24",	/* 3 - CK_PLS24 */
+	"PLS48",	/* 4 - CK_PLS48 */
+	"PLS96",	/* 5 - CK_PLS96 */
+	"Step "		/* 6 - CK_STEP  */
+};
+
+char	*sdisp[] = {	/* score display fixed text strings */
+
+	/* 0 */		"\230\231\232\233     ",	/* Interpolate */
+
+	/* 1 */		"\200\201\202\203 1    2    3    4    5    6    7    8    9    \254    \255    \256    ",
+			/* Group / Instrument */
+
+	/* 2 */		"\220\221\222\223  Pch/Hor  Mod/Vrt  Brth/LP  GPC/CV1  Pedal 1  Key Prs Group",
+			/* Analog Source */
+
+	/* 3 */		"\015\016\017 Play Recrd OvrDub PunchIn ",
+			/* Rec Mode */
+
+	/* 4 */		"\204\205\206\207",	/* Transpose */
+
+	/* 5 */		"\210\211\212\213   /    /    /    /    /    /    /    /    /    /    /    / ",
+			/* Dynamics / Location */
+			
+	/* 6 */		"\214\215\216\217",	/* Velocity */
+
+	/* 7 */		"\224\225\226\227  0/+00.0  0/+00.0  0/+00.0  0/+00.0  0/+00.0  0/+00.0 # 00 ",
+			/* Resolution / Value */
+
+	/* 8 */		"                                                            "
+
+
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	makeln(lnc, lec) -- create the constant slice at 'consl'.
+	make the line object color 'lnc', and ledger line color 'lec', 
+   =============================================================================
+*/
+
+makeln(lnc, lew)
+register unsigned lnc, lew;
+{
+	register unsigned *lp, *cp;
+	register short i;
+	register unsigned lbg;
+
+	lp = obj15;			/* setup line object pointer */
+	cp = consl;			/* setup constant slice pointer */
+
+	lew = exp_c(lew);		/* create ledger line constant */
+
+	lnc &= 0x000F;			/* mask cursor line color */
+
+/* 
+
+*/	
+	for (i = 0; i < 224; i++) {
+
+		/* stuff data into line object */
+
+		if ((i EQ  42) OR	/* top ledger line */
+		    (i EQ  50) OR	/* top ledger line */
+		    (i EQ  58) OR	/* top ledger line */
+		    (i EQ  66) OR	/* top ledger line */
+		    (i EQ 162) OR	/* bottom ledger line */
+		    (i EQ 170) OR	/* bottom ledger line */
+		    (i EQ 178) OR	/* bottom ledger line */
+		    (i EQ 186)) {
+
+			lbg = lew;
+			*lp++ = lbg & 0xFFF0;
+			*lp++ = lbg;
+			*lp++ = lbg;
+			*lp++ = lbg;
+
+		} else if (i > 209) {	/* new data area */
+
+			lbg = 0;
+			*lp++ = lbg & 0xFFF0;
+			*lp++ = lbg;
+			*lp++ = lbg;
+			*lp++ = lbg;
+
+		} else {
+
+			lbg = 0;
+			*lp++ = lbg & 0xFFF0;
+			*lp++ = lbg;
+			*lp++ = (lbg & 0xFFF0) | lnc;
+			*lp++ = lbg;
+		}
+
+		*cp++ = 0;		/* clear a line in the constant slice */
+	}
+
+/* 
+
+*/
+
+	consl[74]  = lew;		/* constant slice treble clef lines */
+	consl[82]  = lew;
+	consl[90]  = lew;
+	consl[98]  = lew;
+	consl[106] = lew;
+
+	consl[122] = lew;		/* constant slice bass clef lines */
+	consl[130] = lew;
+	consl[138] = lew;
+	consl[146] = lew;
+	consl[154] = lew;
+
+	consl[210] = exp_c(NDMC);	/* constant slice new data margin line */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ds_vmod() -- display velocity mode
+   =============================================================================
+*/
+
+ds_vmod()
+{
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 5, 0, sdisp[6],
+		velflag ? ((SD_CHNG << 4) | SDBG11) : SDW11ATR);
+}
+
+/*
+   =============================================================================
+	ds_vel() -- display velocities
+   =============================================================================
+*/
+
+ds_vel()
+{
+	register short i;
+	char buf[6];
+
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	ds_vmod();
+
+	for (i = 0; i < 12; i++) {
+
+		sprintf(buf, "%03d", lastvel[i] / 252);
+		vputs(obj8, 5, (i * 5) + 6, buf, SDW11ATR);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsvmode() -- display variable mode
+   =============================================================================
+*/
+
+dsvmode(n)
+short n;
+{
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 6, 5 + (n * 9), '*', simled[varmode[n][abs(angroup) - 1]]);
+}
+
+
+/*
+   =============================================================================
+	ds_anmd() -- display mode for all variables
+   =============================================================================
+*/
+
+ds_anmd()
+{
+	register short i;
+
+	if (ndisp NE 2)
+		return;
+
+	for (i = 0; i < 6; i++)
+		dsvmode(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ds_angr() -- display analog variable group number
+   =============================================================================
+*/
+
+ds_angr()
+{
+	char buf[4];
+
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	sprintf(buf, "# %2.2d", abs(angroup));
+	vputs(obj8, 7, 59, buf, SDW12ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ds_anrs() -- display analog resolution
+   =============================================================================
+*/
+
+ds_anrs()
+{
+	register short i;
+	char buf[3];
+
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	buf[1] = '/';
+	buf[2] = '\0';
+
+	for (i = 0; i < 6; i++) {
+
+		buf[0] = '0' + anrs[i][abs(angroup) - 1];
+		vputs(obj8, 7, 6 + (i * 9), buf, SDW12ATR);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsanval() -- display analog value
+   =============================================================================
+*/
+
+dsanval(var)
+short var;
+{
+	register short tmp, val, v1, v2;
+	char buf[16];
+
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	val = valents[((abs(angroup) - 1) << 4) | var2src[var]].val >> 5;
+	tmp = abs(val);	
+	v1 = tmp / 100;
+	v2 = (tmp - (v1 * 100)) / 10;
+	sprintf(buf, "%c%02d.%1d", ((val < 0) ? '-' : '+'), v1, v2);
+	vputs(obj8, 7, 8 + (var * 9), buf, SDW12ATR);
+}
+
+/*
+   =============================================================================
+	ds_anvl() -- display analog values
+   =============================================================================
+*/
+
+ds_anvl()
+{
+	register short i;
+
+	if (ndisp NE 2)
+		return;
+
+	for (i = 0; i < 6; i++)
+		dsanval(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	uclk() -- underline clock label
+   =============================================================================
+*/
+
+uclk()
+{
+	if (sliders NE LS_VOICE) {
+
+		point = GLCplot;
+
+		GLCcurs(G_ON);
+
+		if (clkrun)
+			lseg(CK_XL, CK_Y, CK_XR, CK_Y, 1);	/* clock on */
+		else
+			lseg(CK_XL, CK_Y, CK_XR, CK_Y, 0);	/* clock off */
+
+		GLCcurs(G_OFF);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dclkmd() -- display clock mode
+   =============================================================================
+*/
+
+dclkmd()
+{
+	uclk();
+
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 0, 29, "Clock",
+		clkrun ? ((SD_CHNG << 4) | SDBG02) : SDW02ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsclk() -- display clock status, control, and source
+   =============================================================================
+*/
+
+dsclk()
+{
+	short	atr[26];
+
+	uclk();
+
+	if (ndisp NE 2)
+		return;
+
+	memsetw(atr, SDW02ATR, 26);
+
+	if (clkrun)
+		memsetw(atr, (SDBG02 | (SD_CHNG << 4)), 5);
+
+	sprintf(bfs, "Clock Con %5.5s Src %5.5s ",
+		clklbl[clkctl], clklbl[clksrc]);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputsa(obj8, 0, 29, bfs, atr);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dssect() -- display current score section
+   =============================================================================
+*/
+
+dssect()
+{
+	if (ndisp NE 2)
+		return;
+
+	sprintf(bfs, "%02d", cursect + 1);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 0, 6, bfs, SDW01ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dslocn() -- display current score location
+   =============================================================================
+*/
+
+dslocn()
+{
+	register long curfr, beat;
+	register short frame;
+
+	if (ndisp NE 2)
+		return;
+
+	curfr = t_ctr;
+	beat  = curfr / 48;
+	frame = curfr % 48;
+
+	sprintf(bfs, "%05ld F %02d", beat, frame);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 0, 11, bfs, SDW00ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dnedmod() -- display note edit mode
+   =============================================================================
+*/
+
+dnedmod()
+{
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 0, 55, nedlbl[noteop],
+		(notesel ? ((SD_CHNG << 4) | SDBG03) : SDW03ATR) |
+		(noteop EQ NOP_NUL ? 0 : C_BLINK));
+}
+
+/*
+   =============================================================================
+	dsmem() -- display remaining memory 'units'  (long words)
+   =============================================================================
+*/
+
+dsmem()
+{
+	if (ndisp NE 2)
+		return;
+
+	sprintf(bfs, "M %05ld", evleft());
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 8, 57, bfs, SDW15ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsgstat() -- display group status
+   =============================================================================
+*/
+
+dsgstat(n)
+short n;
+{
+	char c;
+
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	c = 1 + n + (grpstat[n] ? ((n > 8) ? 162 : '0') : 192);
+	vputc(obj8, 2, 5 + (n * 5), c, (((n + 3) << 4) | 2));
+}
+
+/*
+   =============================================================================
+	dsgmode() -- display group mode
+   =============================================================================
+*/
+
+dsgmode(n)
+short n;
+{
+	if (ndisp NE 2)
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputc(obj8, 2, 6 + (n * 5), '*', simled[grpmode[n]]);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsgmods() -- display mode and status for all groups
+   =============================================================================
+*/
+
+dsgmods()
+{
+	register short i;
+
+	if (ndisp NE 2)
+		return;
+
+	for (i = 0; i < 12; i++) {
+
+		dsgstat(i);
+		dsgmode(i);
+	}
+}
+
+/*
+   =============================================================================
+	dsgmodz() -- display modes for all groups and variables
+   =============================================================================
+*/
+
+dsgmodz()
+{
+	register short i;
+
+	if (ndisp NE 2)
+		return;
+
+	for (i = 0; i < 12; i++)	/* group modes */
+		dsgmode(i);
+
+	for (i = 0; i < 6; i++)		/* variable modes */
+		dsvmode(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsrpmod() -- display record / play modes
+   =============================================================================
+*/
+
+dsrpmod()
+{
+	short	atr[25];
+
+	switch (sliders) {
+
+	case LS_PRMTR:
+	case LS_OTHER:
+	case LS_EQ:
+	case LS_NGRP:
+
+		point = GLCplot;
+
+		GLCcurs(G_ON);
+
+		if (recsw) {
+
+			lseg(RP_RL, RP_Y, RP_RR, RP_Y, 1);	/* record */
+			lseg(RP_PL, RP_Y, RP_PR, RP_Y, 0);
+
+		} else {
+
+			lseg(RP_RL, RP_Y, RP_RR, RP_Y, 0);	/* play */
+			lseg(RP_PL, RP_Y, RP_PR, RP_Y, 1);
+		}
+
+		GLCcurs(G_OFF);
+	}
+/* 
+
+*/
+	if (ndisp NE 2)
+		return;
+
+	memsetw(atr, SDW14ATR, 25);
+
+	if (recsw)	/* record */
+		memsetw(&atr[5], (C_BLINK | SDBG14 | (SD_CHNG << 4)), 5);
+	else		/* play */
+		memsetw(&atr[0], (SDBG14 | (SD_CHNG << 4)), 4);
+
+	if (dubsw)	/* overdub */
+		memsetw(&atr[11], (SDBG14 | (SD_CHNG << 4)), 6);
+
+	if (pchsw)	/* punch in enable */
+		memsetw(&atr[18], (SDBG14 | (SD_CHNG << 4)), 7);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputsa(obj8, 8, 31, "Play Recrd OvrDub PunchIn", atr);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsimode() -- display insert mode
+   =============================================================================
+*/
+
+dsimode()
+{
+	short	atr[7];
+
+	if (ndisp NE 2)
+		return;
+
+	if (insmode)
+		memsetw(atr, (SDBG01 | (SD_CHNG << 4)), 7);
+	else
+		memsetw(atr, SDW01ATR, 7);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputsa(obj8, 0, 22, "Insert ", atr);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdwin() -- fill in a score display window
+   =============================================================================
+*/
+
+sdwin(n)
+short n;
+{
+	short atr[64], atrib, i;
+
+	if (ndisp NE 2)			/* only if score is selected */
+		return;
+
+	if (v_regs[5] & 0x0180)		/* select bank 0 */
+		vbank(0);
+
+	switch (n) {			/* dispatch off of window number */
+
+	case 0:		/* score location */
+
+		vputs(obj8, 0,  0,
+			ac_code EQ N_SHARP ? "\250 " : "\251 ",
+			SDW00ATR);
+
+		vputs(obj8, 0,  2, "Sec    ",		SDW01ATR);
+		vputs(obj8, 0,  9, "B       F    ",	SDW00ATR);
+
+		dssect();		/* display current section */
+		dslocn();		/* display score location */
+		return;
+
+	case 1:		/* insert mode */
+
+		dsimode();		/* display score insert mode */
+		return;
+
+	case 2:		/* clock */
+
+		dsclk();		/* display clock status */
+		return;
+
+	case 3:		/* note edit */
+
+		dnedmod();
+		return;
+/* 
+
+*/
+	case 4:		/* assignment */
+
+		vputs(obj8, 1,  0, "Assignment    ", SDW04ATR);
+		rd_ioas(0);		/* display assignment table number */
+		return;
+
+	case 5:		/* tuning */
+
+		vputs(obj8, 1, 14, "Tune   ", SDW05ATR);
+		rd_tune(0);		/* display tuning table number */
+		return;
+
+	case 6:		/* tempo */
+
+		vputs(obj8, 1, 21, "Tempo     ", SDW06ATR);
+		rd_tmpo(0);		/* display tempo */
+		return;
+
+	case 7:		/* interpolate */
+
+		vputs(obj8, 1, 31, "Int     ", SDW07ATR);
+		rd_intp(0);
+		return;
+
+	case 8:		/* stop/next */
+
+		vputs(obj8, 1, 40, "Stop/Next ", SDW08ATR);
+		return;
+/* 
+
+*/
+
+	case 9:		/* punch in/out */
+
+		vputs(obj8, 1, 50, "In/Out ", SDW09ATR);
+		return;
+
+	case 10:	/* output */
+
+		vputs(obj8, 1, 57, "Output ", SDW10ATR);
+		return;
+
+	case 11:	/* group/instr, transposition, dyn/loc, velocity */
+
+		vputs(obj8, 2,  0, sdisp[1], SDW11ATR);
+		dsgmods();		/* display mode and status for all groups */
+		ds_inst();		/* display instruments */
+
+		vputs(obj8, 3,  4, sdisp[8], SDW11ATR);
+		vputs(obj8, 3,  0, sdisp[4], SDW11ATR);
+		ds_trns();		/* display transpositions */
+
+		vputs(obj8, 4,  4, sdisp[8], SDW11ATR);	/* dyn/loc */
+		vputs(obj8, 4,  0, sdisp[5], SDW11ATR);
+		ds_dyn();		/* display dynamics */
+		ds_loc();		/* display locations */
+
+		vputs(obj8, 5,  4, sdisp[8], SDW11ATR);	/* velocity */
+		vputs(obj8, 5,  0, sdisp[6], SDW11ATR);
+		ds_vel();		/* display velocities */
+
+		return;
+/* 
+
+*/
+	case 12:	/* analog variables */
+
+		vputs(obj8, 6,  0, sdisp[2], SDW12ATR);
+		vputs(obj8, 7,  0, sdisp[7], SDW12ATR);
+
+		if (angroup < 0)
+			atrib = SDW12ATR;
+		else
+			atrib = (SD_CHNG << 4) | SDBG12;
+
+		for (i = 0; i < 4; i++)
+			vputa(obj8, 7, i, atrib);
+
+		if (ancmsw)
+			atrib = (SD_CHNG << 4) | SDBG12;
+		else
+			atrib = SDW12ATR;
+
+		for (i = 0; i < 4; i++)
+			vputa(obj8, 6, i, atrib);
+
+		ds_anmd();
+		ds_angr();
+		ds_anrs();
+		ds_anvl();
+
+		return;
+
+	case 13:	/* score */
+
+		sprintf(bfs, "Score  %02.2d %16.16s ",
+			curscor + 1, scname[curscor]);
+
+		vputs(obj8, 8,  0, bfs, SDW13ATR);
+		return;
+
+	case 14:	/* record/play, overdub, punchin */
+
+		vputs(obj8, 8, 27, sdisp[3], SDW14ATR);		/* Rec Mode */
+		dsrpmod();		/* display rec/play modes */
+		return;
+
+	case 15:	/* memory */
+
+		dsmem();		/* display available events */
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdwins() -- display all score windows
+   =============================================================================
+*/
+
+sdwins()
+{
+	register short i;
+
+	if (ndisp NE 2)			/* only if score display is selected */
+		return;
+
+	for (i = 0; i < 17; i++)	/* refresh each of the windows */
+		sdwin(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdsetup() -- setup the score display
+   =============================================================================
+*/
+
+sdsetup()
+{
+	dswap();		/* clear the video display */
+
+	sd     	= D_FWD;	/* display direction = forward */
+	noteop 	= NOP_NUL;	/* no pending note edit operation */
+	notesel = FALSE;	/* no note selected */
+	secop  	= SOP_NUL;	/* no pending section edit operation */
+	scmctl  = -1;		/* no area 1 menu up */
+	sdmctl 	= -1;		/* no area 2 menu up */
+	submenu = FALSE;	/* submenu cursor not enabled */
+	lastam  =  0;		/* reset assignment menu page */
+
+	clrsctl();		/* clear out the slices */
+
+	/* setup object pointers */
+
+	obj0  = v_curs0;		/*  0 - cursor (arrow) */
+	obj2  = v_tcur;			/*  2 - cursor (typewriter) */
+	obj3  = v_cur;			/*  3 - cursor (underline) */
+	obj8  = v_ct0;			/*  8 - character text */
+	obj11 = v_win0;			/* 11 - window */
+	obj13 = v_kbobj;		/* 13 - keyboard */
+	obj14 = v_score;		/* 14 - score */
+	obj15 = v_lnobj;		/* 15 - line */
+
+	/* ---------------- initialize object table -------------------- */
+	/*     obj,  typ, bnk,  base, xpix, ypix,  x0,  y0,   flags, pri */
+
+	SetObj(  0,    0,   1,  obj0,   16,   16, C1X, C1Y, OBFL_00, -1);
+	SetObj(TTCURS, 0,   1,  obj2,   16,   16,   0,   0, TTCCFL,  -1);
+	SetObj(  3,    0,   1,  obj3,  512,   18,   0,   0, OBFL_01, -1);
+	SetObj(  8,    1,   0,  obj8,  512,  108,   0,   0, OBFL_08, -1);
+	SetObj( 11,    0,   1, obj11,  512,  224,   0,  14, OBFL_11, -1);
+	SetObj( 13,    0,   1, obj13,   16,  224,   0,  14, OBFL_13, -1);
+	SetObj( 14,    0,   0, obj14,  512,  224,   0,  14, OBFL_14, -1);
+	SetObj( 15,    0,   1, obj15,   16,  224, 248,  14, OBFL_15, -1);
+
+	if (v_regs[5] & 0x0180)			/* select bank 0 */
+		vbank(0);
+
+	memsetw(obj14, 0, 32767);		/* clear score object */
+	memsetw(obj14+32767L, 0, 24577);
+
+	vbank(1);				/* select bank 1 */
+
+	stcset();				/* setup text cursor colors */
+	stcclr();				/* clear text cursors */
+	arcurs(SDCURSR);			/* setup arrow cursor */
+	ttcini(SDCURSR);			/* setup typewriter cursor */
+
+/* 
+
+*/
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);			/* select bank 1 */
+
+	memcpyw(obj13, kbobj, 896);		/* setup 'keyboard' object */
+	makeln(LN_VRT, LN_HOR);			/* setup 'lines' object */
+	sdwins();				/* fill in the windows */
+
+	/* display some objects */
+
+	SetPri( 3, 12);		/* Underline cursors */
+	objclr(12);
+	objon(12,  12, 2);	/* ... row  0 */
+	objon(12, 250, 2);	/* ... row 17 */
+	objon(12, 264, 2);	/* ... row 18 */
+	objon(12, 278, 2);	/* ... row 19 */
+	objon(12, 292, 2);	/* ... row 20 */
+	objon(12, 306, 2);	/* ... row 21 */
+	objon(12, 320, 2);	/* ... row 22 */
+	objon(12, 334, 2);	/* ... row 23 */
+	objon(12, 348, 2);	/* ... row 24 */
+
+	SetPri( 8,  7);		/* Character Text */
+	objclr(7);
+	objon(7,   0, 12);	/* ... row  0 */
+	objon(7, 238, 12);	/* ... row 17 */
+	objon(7, 252, 12);	/* ... row 18 */
+	objon(7, 266, 12);	/* ... row 19 */
+	objon(7, 280, 12);	/* ... row 20 */
+	objon(7, 294, 12);	/* ... row 21 */
+	objon(7, 308, 12);	/* ... row 22 */
+	objon(7, 322, 12);	/* ... row 23 */
+	objon(7, 336, 12);	/* ... row 24 */
+	
+	SetPri(13,  2);		/* Keyboard object */
+	SetPri(14,  1);		/* Score object */
+	SetPri(15,  0);		/* Line object */
+
+	vsndpal(scorpal);	/* set the palette */
+
+	SetPri( 0, 15);		/* Turn on arrow cursor */
+	setgc(C1X, C1Y);
+
+	sc_refr(t_cur);		/* position the score on the display */
+}
Index: ram/scread.c
===================================================================
--- ram/scread.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scread.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,601 @@
+/*
+   =============================================================================
+	scread.c -- librarian - read score functions
+	Version 15 -- 1988-08-02 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "graphdef.h"
+#include "stddefs.h"
+#include "stdio.h"
+#include "score.h"
+#include "scfns.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+extern	short	scskip();
+
+extern	long	schksum;		/* score checksum */
+
+extern	short	errno;			/* system error number */
+extern	short	lderrsw;		/* librarian error message switch */
+extern	short	lrasw;			/* "Content" switch */
+
+extern	short	ldmap[];		/* librarian gather-read map */
+
+extern	struct	s_entry	*libsp;		/* librarian score insert pointer */
+
+extern	struct	s_time	stimes[N_SCORES][N_SECTS];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scioerr() -- clear a partially built score after an I/O error
+   =============================================================================
+*/
+
+scioerr(sn, ep)
+short sn;
+struct s_entry *ep;
+{
+	char scid[40];
+	char erms[40];
+
+	if (E_NULL NE ep)
+		e_del(ep);
+
+	sc_clr(sn);
+	clrlsel();
+
+	sprintf(scid, "  score %d", sn + 1);
+	sprintf(erms, "  errno = %d", errno);
+
+	ldermsg("Couldn't read", scid, erms,
+		LD_EMCF, LD_EMCB);
+}
+
+/*
+   =============================================================================
+	noevent() -- clear a partially built score after running out of space
+   =============================================================================
+*/
+
+noevent(sn)
+{
+	char scid[24];
+
+	sc_clr(sn);
+	clrlsel();
+
+	sprintf(scid, "  score %d", sn + 1);
+
+	ldermsg("Couldn't read", scid, "  Ran out of space",
+		LD_EMCF, LD_EMCB);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scread() -- read a score
+   =============================================================================
+*/
+
+short
+scread(ns, fp)
+short ns;
+register FILE *fp;
+{
+	register struct s_entry *ep;
+	register short ehdr, go, sn;
+	long nbr, nev;
+	char etype;
+	char scid[40];
+	char erms[40];
+
+	sn = ldmap[ns];		/* map the score */
+
+	if (-1 EQ sn) {		/* skip score if map = -1 */
+
+		if (rd_ec(fp, &nbr, 4L)) {	/* get length */
+
+			skperr(ns);
+			return(FAILURE);
+		}
+
+		if (nbr EQ -1L)			/* done if it's null */
+			return(SUCCESS);
+
+		if (skp_ec(fp, 16L)) {		/* skip the score name */
+
+			skperr(ns);
+			return(FAILURE);
+		}
+
+		return(scskip(fp, ns));		/* skip the rest of it */
+	}
+
+/* 
+
+*/
+	go = TRUE;
+
+	sprintf(scid, "  Reading score %2d", ns + 1);
+	sprintf(erms, "       as score %2d", sn + 1);
+
+	ldwmsg(" Busy -- please stand by", scid, erms,
+		LCFBX10, LCBBX10);
+
+	if (rd_ec(fp, &nbr, 4L)) {	/* get number of longs required */
+
+		scioerr(sn, 0L);
+		return(FAILURE);
+	}
+
+	if (nbr EQ -1L) {		/* see if it's a null score marker */
+
+		return(SUCCESS);
+	}
+
+	if (lrasw)			/* clear target if in append mode */
+		sc_clr(sn);
+
+	if (nbr > (nev = evleft())) {		/* see if we have enough space */
+
+		sprintf(scid, "  score %d - no space", sn + 1);
+		sprintf(erms, "  Need %ld, Have %ld", nbr, nev);
+
+		ldermsg("Couldn't read", scid, erms,
+			 LD_EMCF, LD_EMCB);
+
+		return(FAILURE);
+	}
+
+	if (rd_ec(fp, &scname[sn], 16L)) {	/* score name */
+
+		scioerr(sn, 0L);
+		return(FAILURE);
+	}
+
+	if (rd_ec(fp, &stimes[sn], (long)(N_SECTS * 12))) { /* section times */
+
+		scioerr(sn, 0L);
+		return(FAILURE);
+	}
+
+	if (rd_ec(fp, &etype, 1L)) {	/* read score header event */
+
+		scioerr(sn, 0L);
+		return(FAILURE);
+	}
+
+	if (etype NE EV_SCORE) {	/* complain if it's not a score event */
+
+		sprintf(scid, "  score %d", sn + 1);
+
+		ldermsg("Bad score --", "  1st event is wrong",
+			scid, LD_EMCF, LD_EMCB);
+
+		return(FAILURE);
+	}
+
+	if (E_NULL EQ (ep = e_alc(E_SIZE1))) {	/* allocate header space */
+
+		noevent(sn);
+		return(FAILURE);
+	}
+
+	libsp = ep;
+	scores[sn] = ep;
+
+	ep->e_type = EV_SCORE;
+	
+	if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+		scioerr(sn, ep);
+		return(FAILURE);
+	}
+
+	ep->e_fwd = ep;
+	ep->e_bak = ep;
+/* 
+
+*/
+	do {
+
+		if (rd_ec(fp, &etype, 1L)) {	/* get event type */
+
+			scioerr(sn, 0L);
+			return(FAILURE);
+		}
+
+		switch (etype) {		/* process event entry */
+
+		case EV_BAR:		/* bar marker */
+		case EV_STOP:		/* stop */
+		case EV_NEXT:		/* next */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE1))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}			
+
+			libsp = e_ins(ep, libsp);
+			break;
+/* 
+
+*/
+		case EV_SBGN:		/* section begin */
+
+			ehdr = EH_SBGN;
+			goto doit1;
+
+		case EV_SEND:		/* section end */
+
+			ehdr = EH_SEND;
+			goto doit1;
+
+		case EV_TMPO:		/* tempo */
+
+			ehdr = EH_TMPO;
+			goto doit1;
+
+		case EV_TUNE:		/* tuning */
+
+			ehdr = EH_TUNE;
+			goto doit1;
+
+		case EV_ASGN:		/* I/O assign */
+
+			ehdr = EH_ASGN;
+/* 
+
+*/
+		doit1:
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE2))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			eh_ins(ep, ehdr);
+
+			if (etype EQ EV_SBGN)
+				seclist[sn][ep->e_data1] = ep;
+
+			break;
+/* 
+
+*/
+		case EV_SCORE:		/* score begin */
+		case EV_REPT:		/* repeat */
+		case EV_PNCH:		/* punch in/out */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE1))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			break;
+/* 
+
+*/
+		case EV_NBEG:		/* note begin */
+		case EV_NEND:		/* note end */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE1))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data2, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_dn, 2L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			break;
+/* 
+
+*/
+		case EV_PRES:		/* polyphonic pressure */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE1))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data2, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			break;
+/* 
+
+*/
+		case EV_CPRS:		/* channel pressure */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE1))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data2, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			break;
+
+/* 
+
+*/
+		case EV_INST:		/* instrument change */
+
+			ehdr = EH_INST;
+			goto doit2;
+
+		case EV_INTP:		/* interpolate */
+
+			ehdr = EH_INTP;
+			goto doit2;
+
+		case EV_GRP:		/* group status */
+
+			ehdr = EH_GRP;
+			goto doit2;
+
+		case EV_LOCN:		/* location */
+
+			ehdr = EH_LOCN;
+			goto doit2;
+
+		case EV_DYN:		/* dynamics */
+
+			ehdr = EH_DYN;
+			goto doit2;
+
+		case EV_ANRS:		/* analog resolution */
+
+			ehdr = EH_ANRS;
+/* 
+
+*/
+		doit2:
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE2))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data2, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			eh_ins(ep, ehdr);
+			break;
+/* 
+
+*/
+		case EV_TRNS:		/* transposition */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE3))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_lft, 2L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			eh_ins(ep, EH_INTP);
+			break;
+/* 
+
+*/
+		case EV_ANVL:		/* analog value */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE2))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			ep->e_dn = 0L;
+
+			if (rd_ec(fp, &ep->e_dn, 2L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			break;
+/* 
+
+*/
+		case EV_FINI:		/* score end */
+
+			if (E_NULL EQ (ep = e_alc(E_SIZE1))) {
+
+				noevent(sn);
+				return(FAILURE);
+			}
+
+			ep->e_type = etype;
+
+			if (rd_ec(fp, &ep->e_time, 4L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			if (rd_ec(fp, &ep->e_data1, 1L)) {
+
+				scioerr(sn, ep);
+				return(FAILURE);
+			}
+
+			libsp = e_ins(ep, libsp);
+			go = FALSE;
+		}
+
+	} while (go);
+
+	return(SUCCESS);
+}
Index: ram/scselbx.c
===================================================================
--- ram/scselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1993 @@
+/*
+   =============================================================================
+	scselbx.c -- MIDAS-VII -- score editor box selection functions
+	Version 87 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddvars.h"
+#include "glcfns.h"
+#include "glcdefs.h"
+#include "graphdef.h"
+#include "lcdline.h"
+#include "panel.h"
+#include "score.h"
+#include "scfns.h"
+#include "sclock.h"
+#include "slice.h"
+#include "secops.h"
+#include "secdefs.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "asgdsp.h"
+#include "scdsp.h"
+
+/* functions defined elsewhere */
+
+extern	short	enterit(), advscur(), oktode(), nokey();
+
+/* 
+
+*/
+
+/* variables defined elsewhere */
+
+extern	short	(*itxput)();
+extern	short	(*point)();
+
+extern	short	ancmsw;
+extern	short	angroup;
+extern	short	asmode;
+extern	short	clkrun;
+extern	short	clkctl;
+extern	short	clksrc;
+extern	short	ctrsw;
+extern	short	cxval;
+extern	short	cyval;
+extern	short	dubsw;
+extern	short	gomode;
+extern	short	grptran;
+extern	short	gtmsel;
+extern	short	hitbox;
+extern	short	hitcx;
+extern	short	hitcy;
+extern	short	insmode;
+extern	short	ismode;
+extern	short	lastam;
+extern	short	midiclk;
+extern	short	noteop;
+extern	short	notesel;
+extern	short	oldpk;
+extern	short	oldsl;
+extern	short	pchsw;
+extern	short	pkctrl;
+extern	short	pulsclk;
+extern	short	recsw;
+extern	short	scmctl;
+extern	short	sdmcol;
+extern	short	sdmctl;
+extern	short	sdmrow;
+extern	short	secop;
+extern	short	sgoflag;
+extern	short	sliders;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	stepclk;
+extern	short	stepenb;
+extern	short	submenu;
+extern	short	velflag;
+extern	short	vtccol;
+extern	short	vtcrow;
+
+/* 
+
+*/
+
+extern	short	grptmap[];
+
+extern	short	sctctab[][64];
+
+extern	struct	asgent	asgtab[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	*curboxp;
+
+extern	struct	s_time	stimes[N_SCORES][N_SECTS];	/* section times */
+
+extern	unsigned	*obj8, *obj11;
+
+extern	PFS	(*swpt)[];
+extern	PFS	(*oldsw)[];
+extern	PFS	t_ngrp[];
+
+extern	char	bfs[];
+extern	char	tunname[][32];
+
+extern	struct	gdsel	*gdstbc[];
+
+/* forward references */
+
+short	sdboxfn(), bspscur(), svtdsp(), svtstop();
+
+/* 
+
+*/
+
+char	*sdmenus[][3] = {	/* score display menus */
+
+	/* 0 - typewriter */
+
+	{" ABCDEFGHIJKLMNOPQRSTUVWXYZ  |                                  ",
+	 " abcdefghijklmnopqrstuvwxyz -*-                                 ",
+	 "  0123456789+-/*().,:;!?&<>  |                                  "},
+
+	/* 1 - note edit */
+
+	{" Begin Acc   Move Note   Escape                                 ",
+	 " Begin Nat   Move Begin                                         ",
+	 " End Note    Move End                                           "},
+
+	/* 2 - clock source */
+
+	{" Local   PLS24   Step                                           ",
+	 " MIDI    PLS48                                                  ",
+	 " SMPTE   PLS96                                                  "},
+
+	/* 3 - clock control */
+
+	{" Local                                                          ",
+	 " MIDI                                                           ",
+	 " SMPTE                                                          "},
+
+	/* 4 - Section menu */
+
+	{" GoTo   Move   SMPTE                                            ",
+	 " Begin  Copy   Del Gr                                           ",
+	 " End    Merge  Del Ev                                           "}
+};
+
+char	sdmln3[] =
+	 "        ReGrp  Remove Trn S                                     ";
+
+char	sdmln4[] =
+	 "Escape                    D                                     ";
+
+/* 
+
+*/
+
+short	sdmht[][3] = {		/* score section menu highlight table */
+
+	/* row,	lcol,	rcol */
+
+	{ 6,  	0,	 0},		/*  0 - SOP_NUL */
+	{ 3,  	1,	 4},		/*  1 - SOP_GO  */
+	{ 4,  	1,	 5},		/*  2 - SOP_BGN */
+	{ 5,  	1,	 3},		/*  3 - SOP_END */
+	{ 3,  	8,	11},		/*  4 - SOP_MOV */
+	{ 4,  	8,	11},		/*  5 - SOP_CPY */
+	{ 5,  	8,	12},		/*  6 - SOP_MRG */
+	{ 3, 	15,	19},		/*  7 - SOP_STC */
+	{ 4, 	15,	23},		/*  8 - SOP_DGR */
+	{ 5, 	15,	23},		/*  9 - SOP_DEV */
+	{ 6, 	15,	20},		/* 10 - SOP_RMV */
+	{ 6,	8,	12}		/* 11 - SOP_GRP */
+};
+
+short	sdmlim[][4] = {		/* score display menu cursor limits */
+
+	/* top,	left,	bottom,	right */
+
+	{ 19,  	1,	 21,	 30 },		/* 0 - typewriter */
+	{ 19,	1,	 21,	 30 },		/* 1 - note edit */
+	{ 19, 	1,	 21,	 20 },		/* 2 - clock source */
+	{ 19, 	1,	 21,	 19 },		/* 3 - clock control */
+	{ 19, 	1,	 23,	 62 }		/* 4 - section menu */
+};
+
+/* 
+
+*/
+
+char	*nedlbl[] = {		/* note edit function labels */
+
+	"Note Edit",	/* 0 - NOP_NUL */
+	"Begin Acc",	/* 1 - NOP_ACC */
+	"Begin Nat",	/* 2 - NOP_NAT */
+	"End Note ",	/* 3 - NOP_END */
+	"Move Note",	/* 4 - NOP_MVN */
+	"Move Beg ",	/* 5 - NOP_MVB */
+	"Move End "	/* 6 - NOP_MVE */
+};
+
+/* 
+
+*/
+
+struct	selbox	sdboxes[] = {
+
+	{  0,   0, 175,  13,       0, sdboxfn},	/*  0 - Sec, Beat, Frame */
+	{176,   0, 231,  13,       1, sdboxfn},	/*  1 - Insert */
+	{232,   0, 439,  13,       2, sdboxfn},	/*  2 - Clock */
+	{440,   0, 511,  13,       3, sdboxfn},	/*  3 - Note Edit */
+
+	{  0, 238, 111, 251,       4, sdboxfn},	/*  4 - Assignment */
+	{112, 238, 167, 251,       5, sdboxfn},	/*  5 - Tune */
+	{168, 238, 247, 251,       6, enterit},	/*  6 - Tempo */
+	{248, 238, 319, 251,       7, enterit},	/*  7 - Interpolate */
+	{320, 238, 398, 251,       8, sdboxfn},	/*  8 - Stop/Next */
+	{400, 238, 455, 251,       9, sdboxfn},	/*  9 - In/Out */
+	{456, 238, 511, 251,      10, sdboxfn},	/* 10 - Output */
+
+	{  0, 252, 511, 307,      11, sdboxfn},	/* 11 - Grp, Trns, Dyn, Vel */
+
+	{  0, 308, 511, 335,      12, sdboxfn},	/* 12 - Ansrc, Anval */
+
+	{  0, 336, 215, 349,      13, sdboxfn},	/* 13 - Score Title */
+	{216, 336, 455, 349,      14, sdboxfn},	/* 14 - Rec Mode */
+	{456, 336, 511, 349,      15, sdboxfn},	/* 15 - Memory */
+
+	{  0,  14, 511, 237,      16, sdboxfn},	/* 16 - Note Display */
+
+	{  0,   0,   0,   0,       0, FN_NULL}	/* end of table */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	insect() -- return section number pointed to in section menu, or -1
+   =============================================================================
+*/
+
+short
+insect()
+{
+	register short col;
+
+	col = vtccol - 24;
+
+	if (col < 0)
+		return(-1);
+
+	sgoflag = col & 3;
+
+	if ((vtcrow < 19) OR (vtcrow > 20))
+		return(-1);
+
+	return((col >> 2) + (10 * (vtcrow - 19)));
+}
+
+/*
+   =============================================================================
+	svtdsp() -- display data for the virtual typewriter
+   =============================================================================
+*/
+
+svtdsp(obj, fg, bg, row, col, buf)
+unsigned *obj;
+unsigned fg, bg;
+short row, col;
+char *buf;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj, row - 16, col, buf, SDW13ATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	svtstop() -- end vitrual typewriter data entry
+   =============================================================================
+*/
+
+svtstop()
+{
+	sdmenu(-1);
+}
+
+/*
+   =============================================================================
+	bspscur() -- backspace the score display text cursor
+   =============================================================================
+*/
+
+bspscur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol - 1;
+
+	if (newcol GE cfetp->flcol)
+		stcpos(stcrow, newcol);
+
+	cxval = CTOX(stccol);
+	cyval = RTOY(stcrow);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsects() -- display list of section numbers
+	Highlight active sections and indicate SMPTE time-coded sections.
+   =============================================================================
+*/
+
+dsects()
+{
+	register short atr, row, col, i, j;
+	char buf[8];
+	char cl, cr, csl, csr;
+	short begun;
+
+	register struct s_entry *sp;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	row = 3;
+
+	for (i = 0; i < N_SECTS; i += 10) {
+
+		col = 24;
+
+		for (j = 0; j < 10; j++) {
+
+			if (stimes[curscor][i + j].sflags) {	/* SMPTE time */
+
+				csl = '[';
+				csr = ']';
+
+			} else {		/* no SMPTE time */
+
+				csl = '{';
+				csr = '}';
+			}
+
+			cl = ' ';
+			cr = ' ';
+
+			if (E_NULL NE seclist[curscor][i + j]) {
+
+				begun = TRUE;
+				atr = (SDBGMM | (SD_CHNG << 4));
+				cl  = csl;
+
+			} else {
+
+				begun = FALSE;
+				atr = SDMENUBG;
+			}
+
+			sp = hplist[curscor][EH_SEND];
+
+			while (sp) {
+
+				if (sp->e_data1 EQ (i + j)) {
+
+					cr = begun ? csr : '}';
+					break;
+				}
+
+				sp = sp->e_up;
+			}
+
+			sprintf(buf, "%c%02d%c", cl, 1 + (i + j), cr);
+
+			vputs(obj8, row, col, buf, atr);
+			col += 4;
+		}
+
+		++row;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsgtmn() -- display group map source group number
+   =============================================================================
+*/
+
+dsgtmn(n, f)
+short n, f;
+{
+	char buf[4];
+	short atr, col;
+
+	sprintf(buf, "%02d", n + 1);
+
+	col = (3 * n) + 28;
+	atr = f ? (SDBGMM | (SD_CHNG <<4)) : SDMENUBG;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 6, col, buf, atr);
+}
+
+/*
+   =============================================================================
+	dsgtme() -- display group map destination group number
+   =============================================================================
+*/
+
+dsgtme(n)
+short n;
+{
+	char buf[4];
+	short col;
+
+	if (grptmap[n] EQ -1)
+		strcpy(buf, "  ");
+	else
+		sprintf(buf, "%02d", grptmap[n] + 1);
+
+	col = (3 * n) + 28;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputs(obj8, 7, col, buf, SDMENUBG);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsgtmap() -- display group map and transposition value
+   =============================================================================
+*/
+
+dsgtmap()
+{
+	char buf[6];
+	register short i;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	sprintf(buf, "%c%02d", grptran < 0 ? '-' : '+', abs(grptran));
+
+	vputs(obj8, 7, 22, buf, SDMENUBG);
+
+	for (i = 0; i < 12; i++) {
+
+		dsgtmn(i, gtmsel EQ i);
+		dsgtme(i);
+	}
+}
+
+/*
+   =============================================================================
+	ingroup() -- return group number selected
+   =============================================================================
+*/
+
+short
+ingroup()
+{
+	register short col;
+
+	col = vtccol - 28;
+
+	if (col < 0)
+		return(-1);
+
+	if (2 EQ (col % 3))
+		return(-1);
+
+	return(col / 3);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdmtxt() -- output text to the score area submenu
+   =============================================================================
+*/
+
+sdmtxt(row, col, txt, tag)
+short row, col;
+char *txt;
+short tag;
+{
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);
+
+	vcputsv(obj11, 64, SD_TEXT, SDBG16, row, col, txt, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showam() -- show menu of assignments
+   =============================================================================
+*/
+
+showam(asg)
+register short asg;
+{
+	register short col, na, row;
+
+	if (asg EQ 1)
+		na = 48;
+	else
+		na = NASGS;
+
+	for (col = 2; col < 60; col += 15) {
+
+		if (asg GE na)
+			return;
+
+		(*itxput)(0, col, "No Assignment", 0);
+
+		for (row = 1; row < 15; row++) {
+
+			if (asg GE na)
+				return;
+
+			sprintf(bfs, "%02d %-10.10s", asg, asgtab[asg].a_name);
+			(*itxput)(row, col, bfs, 1);
+			++asg;
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showtm() -- show menu of tunings
+   =============================================================================
+*/
+
+showtm()
+{
+	register short row, tun;
+
+	tun = 0;
+
+	(*itxput)(0, 0, "N Name", 0);
+
+	for (row = 1; row < 11; row++) {
+
+		sprintf(bfs, "%d %-32.32s", tun, tunname[tun]);
+		(*itxput)(row, 0, bfs, 1);
+		++tun;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showsm() -- show menu of scores
+   =============================================================================
+*/
+
+showsm()
+{
+	register short col, row, scr;
+
+	scr = 1;
+
+	for (col = 1; col < 46; col+= 22) {
+
+		if (scr > N_SCORES)
+			return;
+
+		(*itxput)(0, col, "No Score", 0);
+
+		for (row = 1; row < 15; row++) {
+
+			if (scr > N_SCORES)
+				return;
+
+			sprintf(bfs, "%02d %-16.16s", scr, scname[scr - 1]);
+			(*itxput)(row, col, bfs, 1);
+			++scr;
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scmenu() -- display a submenu in area 1  (score area)
+   =============================================================================
+*/
+
+scmenu(n)
+register short n;
+{
+	register short i;
+	register struct octent *op;
+
+	if (n GE 0) {		/* put up a submenu */
+
+		itxput = sdmtxt;	/* setup output function */
+
+		vbank(0);
+
+		v_odtab[0][0] |= V_BLA;		/* turn off line objcect */
+		objclr(0);
+
+		v_odtab[1][0] |= V_BLA;		/* turn off score object */
+		objclr(1);
+
+		v_odtab[2][0] |= V_BLA;		/* turn off keyboard object */
+		objclr(2);
+
+		vbank(1);			/* clear the window */
+		vbfill4(obj11, 128, 0, 0, 511, 223, exp_c(SDBG16));
+
+		vbank(0);			/* turn on window object */
+		SetPri(11, 4);
+
+		switch (n) {			/* fill the window */
+
+		case 0:		/* instruments */
+
+			showim();		/* show the instruments */
+			break;
+
+		case 1:		/* assignments */
+
+			showam(lastam);		/* show the assignments */
+			stcpos(17, 11);		/* position the cursor */
+
+			cxval = CTOX(11);
+			cyval = RTOY(17);
+
+			if (infield(stcrow, stccol, curfet))
+				cfetp = infetp;
+
+			break;
+
+		case 2:		/* tunings */
+
+			showtm();		/* show the tunings */
+			stcpos(17, 19);		/* position the cursor */
+
+			cxval = CTOX(19);
+			cyval = RTOY(17);
+
+			if (infield(stcrow, stccol, curfet))
+				cfetp = infetp;
+
+			break;
+
+		case 3:		/* scores */
+
+			showsm();		/* show the scores */
+			stcpos(24, 7);		/* position the cursor */
+
+			cxval = CTOX(7);
+			cyval = RTOY(24);
+
+			if (infield(stcrow, stccol, curfet))
+				cfetp = infetp;
+
+			break;
+
+		default:	/* eh ? */
+
+			break;
+		}
+
+	} else {		/* take down the submenu */
+
+		vbank(0);
+
+		v_odtab[4][0] |= V_BLA;		/* turn off window object */
+		objclr(4);
+
+		op = &v_obtab[13];		/* turn on keyboard object */
+		objon(2, op->objy, op->ysize);
+		v_odtab[2][0] &= ~V_BLA;
+
+		op = &v_obtab[14];		/* turn on score object */
+		objon(1, op->objy, op->ysize);
+		v_odtab[1][0] &= ~V_BLA;
+
+		op = &v_obtab[15];		/* turn on line object */
+		objon(0, op->objy, op->ysize);
+		v_odtab[0][0] &= ~V_BLA;
+	}
+
+	scmctl = n;		/* set new menu type */
+}
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdmenu() -- display a submenu in area 2  (text areas)
+   =============================================================================
+*/
+
+sdmenu(n)
+register short n;
+{
+	register short i, wasup;
+
+	wasup  = sdmctl;	/* save previous menu type */
+	sdmctl = n;		/* set new menu type */
+
+	if (n GE 0) {		/* put up a menu */
+
+		submenu = TRUE;		/* indicate there's a menu up */
+
+		sdmrow = stcrow;	/* save underline cursor position */
+		sdmcol = stccol;	/* ... */
+
+		memsetw(&sctctab[3][0], exp_c(SDBGMM), 64);	/* recolor */
+		memsetw(&sctctab[4][0], exp_c(SDBGMM), 64);
+		memsetw(&sctctab[5][0], exp_c(SDBGMM), 64);
+
+		if (n EQ 4) {		/* extra 2 lines for section menu */
+
+			memsetw(&sctctab[6][0], exp_c(SDBGMM), 64);
+			memsetw(&sctctab[7][0], exp_c(SDBGMM), 64);
+		}
+
+		stcclr();		/* re-color the cursor background */
+		stcpos(sdmrow, sdmcol);	/* turn underline cursor back on */
+
+		if (infield(stcrow, stccol, curfet))
+			cfetp = infetp;
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		for (i = 0; i < 3; i++)	/* top 3 lines of menu */
+			vputs(obj8, 3 + i, 0, sdmenus[n][i], SDMENUBG);
+/* 
+
+*/
+		if (n EQ 4) {		/* extra 2 lines for section menu */
+
+			vputs(obj8, 6, 0, sdmln3, SDMENUBG);
+			vputs(obj8, 7, 0, sdmln4, SDMENUBG);
+
+			secop = SOP_NUL;	/* clear section operation code */
+
+			grptran = 0;		/* reset transpose value */
+			gtmsel  = -1;		/* de-select source group */
+
+			for (i = 0; i < 12; i++)	/* reset the map */
+				grptmap[i] = i;
+
+			dsects();	/* display list of sections */
+			dsgtmap();	/* display group map and transpose */
+
+			point = GLCplot;	/* setup to plot on LCD */
+			GLCcurs(G_ON);
+
+			if (ismode NE IS_NULL) {	/* cancel inst. mode */
+
+				ismode  = IS_NULL;
+				pkctrl  = oldpk;
+				sliders = oldsl;
+				swpt    = oldsw;
+				lcdlbls();
+			}
+
+			if (gomode NE GO_NULL) {	/* cancel goto mode */
+
+				gomode = GO_NULL;
+				pkctrl = oldpk;
+				lseg(GOTO_XL, GOTO_Y, GOTO_XR, GOTO_Y, 0);
+			}
+
+			if (asmode) {			/* cancel assign mode */
+
+				asmode = 0;
+				pkctrl = oldpk;
+				swpt   = oldsw;
+				lseg(ASGN_XL, ASGN_Y, ASGN_XR, ASGN_Y, 0);
+			}
+
+			if ((pkctrl EQ PK_PFRM) OR (pkctrl EQ PK_NOTE))
+				oldpk = pkctrl;
+
+			if (sliders NE LS_LIBR)
+				oldsl = sliders;
+
+			oldsw   = swpt;		/* put panel in group mode */
+			swpt    = t_ngrp;
+			pkctrl  = PK_NGRP;
+			sliders = LS_NGRP;
+	
+			lcdlbls();
+			setleds();
+		}
+
+		SetPri(TTCURS, TTCPRI);		     /* turn on menu cursor */
+		ttcpos(sdmlim[n][0], sdmlim[n][1]);  /* position menu cursor */
+/* 
+
+*/
+	} else {		/* take down the menu */
+
+		submenu = FALSE;	/* indicate menu has gone bye bye */
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		objclr(TTCPRI);		/* turn off the menu cursor */
+		stcset();		/* restore underline cursor */
+		stcclr();		/* ... */
+		sdwin(11);		/* redisplay window 11 data */
+
+		if (wasup EQ 4) {
+
+			sdwin(12);		/* redisplay window 12 data */
+
+			stcpos(sdmrow, sdmcol);	/* display underline cursor */
+
+			cxval = CTOX(sdmcol);
+			cyval = RTOY(sdmrow);
+
+			if (infield(stcrow, stccol, curfet))
+				cfetp = infetp;
+
+			pkctrl  = oldpk;	/* restore panel state */
+			sliders = oldsl;
+			swpt    = oldsw;
+
+			lcdlbls();		/* refresh LCD */
+			setleds();		/* refresh LEDs */
+
+		} else {
+
+			stcpos(sdmrow, sdmcol);	/* display underline cursor */
+
+			cxval = CTOX(sdmcol);
+			cyval = RTOY(sdmrow);
+
+			if (infield(stcrow, stccol, curfet))
+				cfetp = infetp;
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	hilitnt() -- setup for a note operation
+   =============================================================================
+*/
+
+hilitnt(nop)
+short nop;
+{
+	noteop  = nop;		/* set note operation */
+	notesel = FALSE;	/* indicate no note selected */
+	sdmenu(-1);		/* take down the menu */
+	dnedmod();		/* update the note edit window */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	hilitop() -- highlight a section operation and set secop
+   =============================================================================
+*/
+
+hilitop(n)
+register short n;
+{
+	register short row, lc, rc, col;
+
+	if (clkrun)	/* don't do anything if clock is running */
+		return;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	if (secop NE SOP_NUL) {
+
+		row = sdmht[secop][0];
+		lc  = sdmht[secop][1];
+		rc  = sdmht[secop][2];
+
+		for (col = lc; col LE rc; col++)
+			vputa(obj8, row, col, SDMENUBG);
+	}
+
+	secop = n;
+
+	row = sdmht[n][0];
+	lc  = sdmht[n][1];
+	rc  = sdmht[n][2];
+
+	for (col = lc; col LE rc; col++)
+		vputa(obj8, row, col, (SDBGMM | (SD_ENTR << 4)));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dosecop() -- do the current section operation
+   =============================================================================
+*/
+
+dosecop()
+{
+	register short sect;
+	register struct s_entry *ep;
+
+	if (clkrun OR (-1 EQ (sect = insect()))) {
+
+		secop = SOP_NUL;
+		return;
+	}
+
+	if (insmode) {
+
+		icancel();
+		dsimode();
+	}
+
+	switch (secop) {
+
+	case SOP_GO:	/* GoTo */
+
+		if (sgoflag EQ 3) {	/* GoTo End Section */
+
+			ep = hplist[curscor][EH_SEND];
+
+			while (ep) {
+
+				if (ep->e_data1 EQ sect) {
+
+					sc_goto(fc_val = ep->e_time);
+					break;
+				}
+
+				ep = ep->e_up;
+			}
+
+		} else {		/* GoTo Begin Section */
+
+			if (E_NULL NE (ep = seclist[curscor][sect]))
+				sc_goto(fc_val = ep->e_time);
+		}
+
+		break;
+/* 
+
+*/
+	case SOP_BGN:	/* Begin */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		if (E_NULL NE (ep = seclist[curscor][sect])) {
+
+			eh_rmv(ep, EH_SBGN);
+			e_rmv(ep);
+			ep->e_time = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 1, t_cur)->e_bak)->e_fwd;
+			eh_ins(ep, EH_SBGN);
+			se_exec(ep, D_FWD);
+
+		} else  if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_time  = t_cur;
+			ep->e_type  = EV_SBGN;
+			ep->e_data1 = sect;
+			p_cur = e_ins(ep, ep_adj(p_cur, 1, t_cur)->e_bak)->e_fwd;
+			eh_ins(ep, EH_SBGN);
+			seclist[curscor][sect] = ep;
+			se_exec(ep, D_FWD);
+		}
+
+		sc_refr(fc_val);	/* refresh the screen */
+		break;
+/* 
+
+*/
+	case SOP_END:	/* End */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		if (E_NULL NE (ep = ehfind(EH_SEND, -1L, sect, -1))) {
+
+			eh_rmv(ep, EH_SEND);
+			e_rmv(ep);
+			ep->e_time = t_cur;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_SEND);
+			se_exec(ep, D_FWD);
+
+		} else  if (E_NULL NE (ep = e_alc(E_SIZE2))) {
+
+			ep->e_time  = t_cur;
+			ep->e_type  = EV_SEND;
+			ep->e_data1 = sect;
+			p_cur = e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(ep, EH_SEND);
+			se_exec(ep, D_FWD);
+		}
+
+		sc_refr(fc_val);	/* refresh the screen */
+		break;
+/* 
+
+*/
+	case SOP_MOV:	/* Move */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_mov(sect))	/* move the section */
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case SOP_CPY:	/* Copy */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_cpy(sect))	/* copy the section */
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case SOP_MRG:	/* Merge */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_mrg(sect))	/* merge the section */
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+	case SOP_GRP:	/* ReGrp */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_grp(sect))	/* regroup the section */
+			break;
+
+		sc_refr(fc_val);	/* refresh screen if successful */
+		break;
+
+/* 
+
+*/
+	case SOP_STC:	/* SMPTE */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		break;
+
+	case SOP_DGR:	/* Delete Gr */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_dgr(sect))	/* delete note events */
+			break;
+
+		sc_refr(fc_val);	/* refresh display if successful */
+		break;
+
+	case SOP_DEV:	/* Delete Ev */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_dev(sect))	/* delete non-note events */
+			break;
+
+		sc_refr(fc_val);	/* refresh display if successful */
+		break;
+
+	case SOP_RMV:	/* Remove */
+
+		if (NOT recsw)		/* only in record mode */
+			break;
+
+		if (sec_rmv(sect))	/* remove section */
+			break;
+
+		sc_refr(fc_val);	/* refresh display if successful */
+		break;
+	}
+
+	secop = SOP_NUL;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clkset() -- set the clock state
+   =============================================================================
+*/
+
+clkset(st)
+register short st;
+{
+	clkrun = st;
+
+	switch (clksrc) {
+
+	case CK_LOCAL:				/* Local */
+	case CK_SMPTE:				/* SMPTE */
+
+		midiclk = FALSE;
+		pulsclk = FALSE;
+
+		if (st)
+			fc_sw   = 1;
+		else
+			fc_sw   = 0;
+
+		return;
+
+	case CK_MIDI:				/* MIDI */
+
+		fc_sw   = 0;
+		pulsclk = FALSE;
+
+		if (st)
+			midiclk = TRUE;
+		else
+			midiclk = FALSE;
+
+		return;
+/* 
+
+*/
+	case CK_PLS24:				/* PLS24 */
+	case CK_PLS48:				/* PLS48 */
+	case CK_PLS96:				/* PLS96 */
+
+		fc_sw   = 0;
+		midiclk = FALSE;
+
+		if (st)
+			pulsclk = TRUE;
+		else
+			pulsclk = FALSE;
+
+		return;
+
+	case CK_STEP:				/* Step */
+
+		fc_sw   = 0;
+		midiclk = FALSE;
+		pulsclk = FALSE;
+
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sdboxfn() -- process score display box hits
+   =============================================================================
+*/
+
+short
+sdboxfn(n)
+short n;
+{
+	register short	row, col, grp, what, i;
+	register struct s_entry *ep;
+	short atr, modewas;
+
+	row = hitcy / 14;
+	col = hitcx >> 3;
+
+	switch (hitbox) {
+
+	case 0:		/* signature, section, beat, frame */
+
+		if (col EQ 0) {				/* signature */
+
+			if (clkrun)		/* clock can't be running */
+				return(FAILURE);
+
+			if (ac_code EQ N_SHARP)
+				ac_code = N_FLAT;
+			else
+				ac_code = N_SHARP;
+
+			sc_refr(fc_val);
+			return(SUCCESS);
+
+		} else if ((col GE 2) AND (col LE 4)) {	/* section menu */
+
+			if (clkrun)		/* clock can't be running */
+				return(FAILURE);
+
+			if (sdmctl EQ -1) {	/* menu not up yet */
+
+				sdmenu(4);	/* put up the menu */
+				return(SUCCESS);
+/* 
+
+*/
+			} else {		/* menu up */
+
+				if (vtcrow EQ 19) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 4)) {	      /* GoTo */
+
+						hilitop(SOP_GO);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 8) AND
+						   (vtccol LE 11)) {  /* Move */
+
+						hilitop(SOP_MOV);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 15) AND
+						   (vtccol LE 19)) {  /* SMPTE */
+
+						hilitop(SOP_STC);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 24) AND
+						   (vtccol LE 62)) {  /* number */
+
+						if (-1 NE insect()) {
+
+							sdmenu(-1);
+							dosecop();
+						}
+
+						return(SUCCESS);
+					}
+/* 
+
+*/
+				} else if (vtcrow EQ 20) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {	      /* Begin */
+
+						hilitop(SOP_BGN);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 8) AND
+						   (vtccol LE 11)) {  /* Copy */
+
+						hilitop(SOP_CPY);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 15) AND
+						   (vtccol LE 20)) {  /* Del Gr */
+
+						hilitop(SOP_DGR);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 24) AND
+						   (vtccol LE 62)) {  /* number */
+
+						if (-1 NE insect()) {
+
+							sdmenu(-1);
+							dosecop();
+						}
+
+						return(SUCCESS);
+					}
+/* 
+
+*/
+				} else if (vtcrow EQ 21) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 3)) {	      /* End */
+
+						hilitop(SOP_END);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 8) AND
+						   (vtccol LE 12)) {  /* Merge */
+
+						hilitop(SOP_MRG);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 15) AND
+						   (vtccol LE 20)) {  /* Del Ev */
+
+						hilitop(SOP_DEV);
+						return(SUCCESS);
+					}
+
+/* 
+
+*/
+				} else if (vtcrow EQ 22) {
+
+					if ((vtccol GE 8) AND
+						   (vtccol LE 12)) {  /* ReGrp */
+
+						hilitop(SOP_GRP);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 15) AND
+					    (vtccol LE 20)) {         /* Remove */
+
+						hilitop(SOP_RMV);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 28) AND
+						   (vtccol LE 62)) {  /* number */
+
+						if (gtmsel GE 0)
+							dsgtmn(gtmsel, FALSE);
+
+						if (-1 NE (gtmsel = ingroup()))
+							dsgtmn(gtmsel, TRUE);
+
+						return(SUCCESS);
+					}
+
+				} else if (vtcrow EQ 23) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 6)) {	      /* Escape */
+
+						secop = SOP_NUL;
+						sdmenu(-1);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 22) AND
+						   (vtccol LE 24)) {	/* Transpose */
+
+						return(enterit());
+					}
+				}
+			}
+
+			return(FAILURE);
+
+		} else
+			return(enterit());
+
+/* 
+
+*/
+	case 1:		/* insert */
+
+		modewas = insmode;		/* save old insert state */
+
+		if (insmode)			/* toggle ... */
+			icancel();		/* ... insert on -> off */
+		else
+			istart();		/* ... insert of -> on */
+
+		if (modewas NE insmode)		/* only refresh if changed */
+			sc_refr(fc_val);
+
+		dsimode();			/* update insert mode display */
+		return(SUCCESS);
+
+	case 2:		/* clock control, source */
+
+		if (col LE 33) {				/* clock */
+
+			clkset(NOT clkrun);
+			dsclk();
+			return(SUCCESS);
+
+/* 
+
+*/
+		} else if ((col GE 35) AND (col LE 43)) {	/* control */
+
+			if (sdmctl EQ -1) {	/* menu not yet up */
+
+				sdmenu(3);
+				return(SUCCESS);
+
+			} else {		/* menu up */
+
+				if (vtcrow EQ 19) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {
+
+						clkctl = CK_LOCAL;
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+					}
+
+				} else if (vtcrow EQ 20) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {
+
+						clkctl = CK_MIDI;
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+					}
+
+				} else if (vtcrow EQ 21) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {
+
+						clkctl = CK_SMPTE;
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+					}
+				}
+			}
+
+			return(FAILURE);
+/* 
+
+*/
+		} else if (col GE 45) {				/* source */
+
+			if (sdmctl EQ -1) {	/* menu not yet up */
+
+				sdmenu(2);
+				setleds();
+				return(SUCCESS);
+
+			} else {		/* menu up */
+
+				if (vtcrow EQ 19) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {
+
+						clksrc = CK_LOCAL;
+						pkctrl = PK_PFRM;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 9) AND
+						   (vtccol LE 13)) {
+
+						clksrc = CK_PLS24;
+						pkctrl = PK_PFRM;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 17) AND
+						   (vtccol LE 20)) {
+
+						clksrc 	= CK_STEP;
+						pkctrl 	= PK_NOTE;
+						stepenb = TRUE;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+					}
+
+/* 
+
+*/
+				} else if (vtcrow EQ 20) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {
+
+						clksrc = CK_MIDI;
+						pkctrl = PK_PFRM;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 9) AND
+						   (vtccol LE 13)) {
+
+						clksrc = CK_PLS48;
+						pkctrl = PK_PFRM;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+					}
+/* 
+
+*/
+				} else if (vtcrow EQ 21) {
+
+					if ((vtccol GE 1) AND
+					    (vtccol LE 5)) {
+
+						clksrc = CK_SMPTE;
+						pkctrl = PK_PFRM;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+
+					} else if ((vtccol GE 9) AND
+						   (vtccol LE 13)) {
+
+						clksrc = CK_PLS96;
+						pkctrl = PK_PFRM;
+						setleds();
+						sdmenu(-1);
+						sdwin(2);
+						return(SUCCESS);
+					}
+				}
+			}
+		}
+
+		return(FAILURE);
+
+/* 
+
+*/
+	case 3:		/* note edit */
+
+		if (clkrun)		/* clock can't be running */
+			return(FAILURE);
+
+		if (scmctl NE -1)
+			scmenu(-1);
+
+		if (sdmctl EQ -1) {	/* menu not up */
+
+			sdmenu(1);
+			noteop = NOP_NUL;
+			return(SUCCESS);
+
+		} else {		/* menu up - select operation */
+
+			if (vtcrow EQ 19) {
+
+				if ((vtccol GE 1) AND
+				    (vtccol LE 9)) {		/* Begin Acc */
+
+					hilitnt(NOP_ACC);
+					return(SUCCESS);
+
+				} else if ((vtccol GE 13) AND
+					   (vtccol LE 21)) {	/* Move Note */
+
+					hilitnt(NOP_MVN);
+					return(SUCCESS);
+
+				} else if ((vtccol GE 25) AND
+					   (vtccol LE 30)) {	/* Escape */
+
+					hilitnt(NOP_NUL);
+					return(SUCCESS);
+
+				}
+
+				return(FAILURE);
+/* 
+
+*/
+			} else if (vtcrow EQ 20) {
+
+				if ((vtccol GE 1) AND
+				    (vtccol LE 9)) {		/* Begin Nat */
+
+					hilitnt(NOP_NAT);
+					return(SUCCESS);
+
+				} else if ((vtccol GE 13) AND
+					   (vtccol LE 22)) {	/* Move Begin */
+
+					hilitnt(NOP_MVB);
+					return(SUCCESS);
+				}
+
+				return(FAILURE);
+
+			} else if (vtcrow EQ 21) {
+
+				if ((vtccol GE 1) AND
+				    (vtccol LE 8)) {		/* End Note */
+
+					hilitnt(NOP_END);
+					return(SUCCESS);
+
+				} else if ((vtccol GE 13) AND
+					   (vtccol LE 20)) {	/* Move End */
+
+					hilitnt(NOP_MVE);
+					return(SUCCESS);
+				}
+
+				return(FAILURE);
+
+			} else
+				return(FAILURE);
+		}
+
+		return(FAILURE);
+
+/* 
+
+*/
+	case 4:		/* assignments */
+
+		if (col LE 9) {
+
+			if (scmctl NE 1) {	/* not up yet -- show page 1 */
+
+				lastam = 0;
+				scmenu(1);
+
+			} else {		/* up - switch pages */
+
+				if (lastam EQ 0) {	/* show page 2 */
+
+					lastam = 60;
+					scmenu(1);
+
+				} else  {		/* take down menu */
+
+					lastam = 0;
+					scmenu(-1);
+				}
+			}
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());	/* data entry */
+		}
+
+	case 5:		/* tunings */
+
+		if ((col GE 14) AND (col LE 17)) {
+
+			if (scmctl NE 2)
+				scmenu(2);	/* put up menu */
+			else
+				scmenu(-1);	/* take down menu */
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());	/* data entry */
+		}
+/* 
+
+*/
+	case 8:		/* stop/next */
+
+		if ((col GE 40) AND (col LE 43)) {	/* stop */
+
+			if (recsw) {
+
+				if (v_regs[5] & 0x0180)
+					vbank(0);
+
+				if (E_NULL NE (ep = findev(p_cur, t_cur, EV_STOP, -1, -1))) {
+
+					se_exec(ep, D_FWD);
+
+				} else if (E_NULL NE (ep = e_alc(E_SIZE1))) {
+
+					ep->e_time = t_cur;
+					ep->e_type = EV_STOP;
+					p_cur= e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+					se_exec(ep, D_FWD);
+					ctrsw = TRUE;
+					se_disp(ep, D_FWD, gdstbc, 1);
+					scupd();
+				}
+			}
+
+		} else if ((col GE 45) AND (col LE 48)) {	/* next */
+
+			if (recsw) {
+
+				if (v_regs[5] & 0x0180)
+					vbank(0);
+
+				if (E_NULL NE (ep = findev(p_cur, t_cur, EV_NEXT, -1, -1))) {
+
+					se_exec(ep, D_FWD);
+
+				} else if (E_NULL NE (ep = e_alc(E_SIZE1))) {
+
+					ep->e_time = t_cur;
+					ep->e_type = EV_NEXT;
+					p_cur= e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+					se_exec(ep, D_FWD);
+					ctrsw = TRUE;
+					se_disp(ep, D_FWD, gdstbc, 1);
+					scupd();
+				}
+			}
+
+		}
+
+		return(SUCCESS);
+
+/* 
+
+*/
+	case 9:		/* punch in/out */
+
+		if ((col GE 50) AND (col LE 51)) {	/* punch in */
+
+			if (recsw) {
+
+				if (v_regs[5] & 0x0180)
+					vbank(0);
+
+				if (E_NULL NE (ep = findev(p_cur, t_cur, EV_STOP, 1, -1))) {
+
+					se_exec(ep, D_FWD);
+
+				} else if (E_NULL NE (ep = e_alc(E_SIZE1))) {
+
+					ep->e_time = t_cur;
+					ep->e_type = EV_PNCH;
+					ep->e_data1 = 1;
+					p_cur= e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+					se_exec(ep, D_FWD);
+					ctrsw = TRUE;
+					se_disp(ep, D_FWD, gdstbc, 1);
+					scupd();
+				}
+			}
+
+		} else if ((col GE 53) AND (col LE 55)) {	/* punch out */
+
+			if (recsw) {
+
+				if (v_regs[5] & 0x0180)
+					vbank(0);
+
+				if (E_NULL NE (ep = findev(p_cur, t_cur, EV_PNCH, 0, -1))) {
+
+					se_exec(ep, D_FWD);
+
+				} else if (E_NULL NE (ep = e_alc(E_SIZE1))) {
+
+					ep->e_time = t_cur;
+					ep->e_type = EV_PNCH;
+					ep->e_data1 = 0;
+					p_cur= e_ins(ep, ep_adj(p_cur, 0, t_cur))->e_fwd;
+					se_exec(ep, D_FWD);
+					ctrsw = TRUE;
+					se_disp(ep, D_FWD, gdstbc, 1);
+					scupd();
+				}
+			}
+
+		}
+
+		return(SUCCESS);
+/* 
+
+*/
+	case 10:	/* Output */
+
+		return(SUCCESS);
+
+	case 11:	/* group/ins, trans, dyn/loc, velocity */
+
+		if ((row EQ 18) AND (col LE 3)) {		/* inst. menu */
+
+			if (scmctl NE 0)
+				scmenu(0);	/* put up the menu */
+			else
+				scmenu(-1);	/* take down the menu */
+
+			return(SUCCESS);
+
+		} else if ((row EQ 21) AND (col LE 3)) {	/* velocity flag */
+
+			velflag = NOT velflag;
+			ds_vmod();
+			return(SUCCESS);
+
+		} else
+			return(enterit());			/* inst. number */
+
+/* 
+
+*/
+	case 12:	/* analog source, value */
+
+		if ((row EQ 23) AND (col LE 4)) {	/* display enable */
+
+			angroup = -angroup;
+
+			if (angroup < 0)
+				atr = SDW12ATR;
+			else
+				atr = (SD_CHNG << 4) | SDBG12;
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			for (i = 0; i < 4; i++)
+				vputa(obj8, 7, i, atr);
+
+			return(SUCCESS);
+
+		} else if ((row EQ 22) AND (col LE 4)) {	/* r/p source */
+
+			ancmsw = NOT ancmsw;
+
+			if (ancmsw)
+				atr = (SD_CHNG << 4) | SDBG12;
+			else
+				atr = SDW12ATR;
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			for (i = 0; i < 4; i++)
+				vputa(obj8, 6, i, atr);
+
+			return(SUCCESS);
+
+		} else {
+
+			return(enterit());
+		}
+/* 
+
+*/
+	case 13:	/* score number and title */
+
+		if (col LE 4) {					/* score menu */
+
+			if (scmctl NE 3)
+				scmenu(3);	/* put up menu */
+			else
+				scmenu(-1);	/* take down menu */
+
+			return(SUCCESS);
+
+		} else if ((col GE 10) AND (col LE 25)) {	/* score name */
+
+			if (sdmctl NE 0) {
+
+				sdmenu(0);
+
+				vtsetup(obj8, svtdsp, 10, scname[curscor], 19, 1,
+					advscur, bspscur, nokey, nokey, svtstop,
+					SDW13DEA, SDBG13);
+
+			} else {
+
+				vtyper();
+			}
+
+			return(SUCCESS);
+
+		} else
+			return(enterit());
+/* 
+
+*/
+	case 14:	/* rec mode */
+
+		if ((col GE 31) AND (col LE 34)) {		/* Play */
+
+			recsw = FALSE;
+			dsrpmod();
+			return(SUCCESS);
+
+		} else if ((col GE 36) AND (col LE 40)) {	/* Recrd */
+
+			recsw = TRUE;
+			dsrpmod();
+			return(SUCCESS);
+
+		} else if ((col GE 42) AND (col LE 47)) {	/* OvrDub */
+
+			dubsw = NOT dubsw;
+			dsrpmod();
+			return(SUCCESS);
+
+		} else if ((col GE 49) AND (col LE 55)) {	/* PunchIn */
+
+			pchsw = NOT pchsw;
+			dsrpmod();
+			return(SUCCESS);
+
+		}
+
+		return(FAILURE);
+
+	case 16:	/* note display */
+
+		if (NOP_NUL NE noteop)
+			donote();
+
+		return(SUCCESS);
+	}
+
+	return(FAILURE);
+}
Index: ram/sctrak.c
===================================================================
--- ram/sctrak.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sctrak.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,474 @@
+/*
+   =============================================================================
+	sctrak.c -- advance the score to a given frame
+	Version 28 -- 1988-09-23 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#undef	DEBUGGER 		/* define to enable debug trace */
+
+#undef	DEBUG_TR		/* define for sc_trak() debug */
+
+#undef	CHECKPTR		/* define to check pointers */
+
+#include "debug.h"
+
+#include "hwdefs.h"
+#include "stddefs.h"
+#include "score.h"
+#include "scfns.h"
+#include "memory.h"
+#include "slice.h"
+
+#ifdef	DEBUG_TR
+extern	short	debugsw;
+#endif
+
+extern	short	ancmsw;
+extern	short	dubsw;
+extern	short	ndisp;
+extern	short	recsw;
+extern	short	sbase;
+extern	short	sd;
+extern	short	se;
+extern	short	soffset;
+
+extern	short	grpmode[];
+extern	short	grpstat[];
+
+extern	short	varmode[][16];
+
+extern	struct	gdsel	*gdfsep;
+
+extern	struct	gdsel	*gdstbc[];
+extern	struct	gdsel	*gdstbn[];
+extern	struct	gdsel	*gdstbp[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sc_trak(tval) -- position score display such that t_ctr EQ 'tval'
+	Assumes that the pointers are correct.
+   =============================================================================
+*/
+
+int
+sc_trak(tval)
+register long tval;
+{
+	register struct s_entry *rpb, *rpc, *rpf;
+	register long	rtb, rtc, rtf;
+	register short	mod48 = 48;
+	struct gdsel	*gdsp;
+
+	DB_ENTR("sc_trak");
+
+	if (ndisp NE 2) {
+
+		DB_EXIT("sc_trak - ndisp NE 2");
+		return(FAILURE);
+	}
+
+#ifdef	CHECKPTR
+	Pcheck(p_fwd, "p_fwd - sc_trak - entry");
+	Pcheck(p_ctr, "p_ctr - sc_trak - entry");
+	Pcheck(p_bak, "p_bak - sc_trak - entry");
+#endif
+
+	if ((p_fwd EQ E_NULL) OR (p_ctr EQ E_NULL) OR (p_bak EQ E_NULL)) {
+
+		DB_EXIT("sc_trak - NULL ptr");
+		return(FAILURE);
+	}
+/* 
+
+*/
+	if (v_regs[5] & 0x0180)		/* setup for VSDD bank 0 */
+		vbank(0);
+
+	rpf = p_fwd;			/* forward event pointer */
+	rtf = t_fwd;			/* forward event time */
+
+	rpc = p_ctr;			/* current event pointer */
+	rtc = t_ctr;			/* current event time */
+
+	rpb = p_bak;			/* backward event pointer */
+	rtb = t_bak;			/* backward event time */
+
+#ifdef	DEBUG_TR
+	if (debugsw) {
+
+		printf("\n## sc_trak(%10ld) ENTRY - fc_val=%10ld  sd = %s  sbase=%d  soffset=%d\n",
+			tval, fc_val, sd ? "BAK" : "FWD", sbase, soffset);
+
+		printf("   p_bak:   %08lX  p_ctr:   %08lX  p_fwd:   %08lX\n",
+			p_bak, p_ctr, p_fwd);
+
+		printf("   t_bak: %10ld  t_ctr: %10ld  t_fwd: %10ld\n",
+			t_bak, t_ctr, t_fwd);
+
+		printf("   T.bak: %10ld  T.ctr: %10ld  T.fwd: %10ld\n",
+			p_bak->e_time, p_ctr->e_time, p_fwd->e_time);
+	}
+#endif
+
+/* 
+
+*/
+	DB_CMNT("sc_trak - update loop");
+
+	if (sd EQ D_FWD) {		/* scroll forward */
+
+		DB_CMNT("sc_trak - forward");
+
+		while (rtc++ LT tval) {		/* advance to tval */
+
+			sreset();		/* reset highlighting */
+
+			++rtb;			/* update target time at p_bak */
+			++rtf;			/* update target time at p_fwd */
+
+			if (rpb->e_type NE EV_FINI) {	/* up to end of score */
+
+				while (rpb->e_time EQ rtb) {		/* check event time */
+
+					se_disp(rpb, D_FWD, gdstbp, 0);	/* display event */
+					rpb = rpb->e_fwd;		/* point at next event */
+
+					if (rpb->e_type EQ EV_FINI)	/* stop at end of score */
+						break;
+				}
+			}
+
+			if (0 EQ (rtb % mod48)) {	/* handle beat markers */
+
+				if ((struct gdsel *)NULL NE (gdsp = gdfsep)) {
+
+					gdfsep = gdsp->next;
+
+					gdsp->next = gdstbp[12];
+					gdsp->note = 0x1111;
+					gdsp->code = 1;
+
+					gdstbp[12] = gdsp;
+				}
+			}
+/* 
+
+*/
+			if (rpc->e_type NE EV_FINI) {	/* up to end of score */
+
+				while (rpc->e_time EQ rtc) {		/* check event time */
+
+					se_disp(rpc, D_FWD, gdstbc, 1);	/* display event */
+					rpc = rpc->e_fwd;		/* point at next event */
+
+					if (rpc->e_type EQ EV_FINI)	/* stop at end of score */
+						break;
+				}
+			}
+
+			if (rpf->e_type NE EV_FINI) {	/* up to end of score */
+
+				while (rpf->e_time EQ rtf) {		/* check event time */
+
+					se_disp(rpf, D_FWD, gdstbn, 0);	/* display event */
+					rpf = rpf->e_fwd;		/* next event pointer */
+
+					if (rpf->e_type EQ EV_FINI)	/* stop at end of score */
+						break;
+				}
+			}
+
+			if (0 EQ (rtf % mod48)) {	/* handle beat markers */
+
+				if ((struct gdsel *)NULL NE (gdsp = gdfsep)) {
+
+					gdfsep = gdsp->next;
+
+					gdsp->next = gdstbn[12];
+					gdsp->note = 0x1111;
+					gdsp->code = 1;
+
+					gdstbn[12] = gdsp;
+				}
+			}
+
+			sc_adv();	/* scroll the display */
+		}
+
+/* 
+
+*/
+	} else {	/* scroll backward */
+
+		DB_CMNT("sc_trak - backward");
+
+		while (rtc-- GT tval) {		/* advance to tval */
+
+			sreset();		/* reset highlighting */
+
+			--rtb;			/* update target time at p_bak */
+			--rtf;			/* update target time at p_fwd */
+
+			if (rpb->e_type NE EV_SCORE) {	/* up to start of score */
+
+				while (rpb->e_time EQ rtb) {		/* check event time */
+
+					se_disp(rpb, D_BAK, gdstbp, 0);
+					rpb = rpb->e_bak;		/* point at next event */
+
+					if (rpb->e_type EQ EV_SCORE)	/* stop at end of score */
+						break;
+				}
+			}
+
+			if (0 EQ (rtb % mod48)) {	/* handle beat markers */
+
+				if ((struct gdsel *)NULL NE (gdsp = gdfsep)) {
+
+					gdfsep = gdsp->next;
+
+					gdsp->next = gdstbp[12];
+					gdsp->note = 0x1111;
+					gdsp->code = 1;
+
+					gdstbp[12] = gdsp;
+				}
+			}
+/* 
+
+*/
+			if (rpc->e_type NE EV_SCORE) {	/* up to start of score */
+
+				while (rpc->e_time EQ rtc) {		/* check event time */
+
+					se_disp(rpc, D_BAK, gdstbc, 1);	/* display event */
+					rpc = rpc->e_bak;		/* point at next event */
+
+					if (rpc->e_type EQ EV_SCORE)	/* stop at end of score */
+						break;
+				}
+			}
+
+			if (rpf->e_type NE EV_SCORE) {	/* up to end of score */
+
+				while (rpf->e_time EQ rtf) {		/* check event time */
+
+					se_disp(rpf, D_BAK, gdstbn, 0);	/* display event */
+					rpf = rpf->e_bak;		/* next event pointer */
+
+					if (rpf->e_type EQ EV_SCORE)	/* stop at end of score */
+						break;
+				}
+			}
+
+			if (0 EQ (rtf % mod48)) {	/* handle beat markers */
+
+				if ((struct gdsel *)NULL NE (gdsp = gdfsep)) {
+
+					gdfsep = gdsp->next;
+
+					gdsp->next = gdstbn[12];
+					gdsp->note = 0x1111;
+					gdsp->code = 1;
+
+					gdstbn[12] = gdsp;
+				}
+			}
+
+			sc_adv();	/* scroll the display */
+		}
+	}
+/* 
+
+*/
+	p_fwd  = rpf;			/* update p_fwd */
+	t_fwd  = tval + TO_FWD;		/* update t_fwd */
+
+	p_ctr  = rpc;			/* update p_ctr */
+	t_ctr  = tval;			/* update t_ctr */
+
+	p_bak  = rpb;			/* update p_bak */
+	t_bak  = tval - TO_BAK;		/* update t_bak */
+
+	DB_CMNT("sc_trak - dslocn");
+	dslocn();			/* display current location */
+
+#ifdef	DEBUG_TR
+	if (debugsw) {
+
+		printf("\n## sc_trak(%10ld) EXIT - fc_val=%10ld  sbase=%d  soffset=%d\n",
+			tval, fc_val, sbase, soffset);
+
+		printf("   p_bak:   %08lX,  p_ctr:   %08lX,  p_fwd:   %08lX\n",
+			p_bak, p_ctr, p_fwd);
+
+		printf("   t_bak: %10ld,  t_ctr: %10ld,  t_fwd: %10ld\n",
+			t_bak, t_ctr, t_fwd);
+
+		printf("   T.bak: %10ld  T.ctr: %10ld  T.fwd: %10ld\n",
+			p_bak->e_time, p_ctr->e_time, p_fwd->e_time);
+	}
+#endif
+
+	DB_EXIT("sc_trak");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sc_trek(tval) -- follow score chain such that t_cur EQ 'tval'
+   =============================================================================
+*/
+
+int
+sc_trek(tval)
+register long tval;
+{
+	register struct s_entry *rp, *ep;
+	register long tc, rt;
+	register short et, grp;
+
+	DB_ENTR("sc_trek");
+
+#ifdef	CHECKPTR
+	Pcheck(p_cur, "p_cur - sc_trek - entry");
+#endif
+
+	if (p_cur EQ E_NULL) {
+
+		DB_EXIT("sc_trek - NULL ptr");
+		return(FAILURE);
+	}
+
+	rp = p_cur;		/* current event pointer */
+	rt = t_cur;		/* current event time */
+
+	DB_CMNT("sc_trek - chasing p_cur");
+
+#ifdef DEBUGGER
+	if (se EQ D_FWD)
+		DB_CMNT("sc_trek - forward");
+	else
+		DB_CMNT("sc_trek - backward");
+#endif
+
+/* 
+
+*/
+	while (rt NE tval) {	/* track tval */
+
+		if (se EQ D_FWD)
+			++rt;
+		else
+			--rt;
+
+		if (rp->e_type NE EV_FINI) {
+
+			while (rp->e_time EQ rt) {	/* process events a rt */
+
+				/* "erase head" logic */
+
+				if (recsw AND (se EQ D_FWD)) {
+
+					et = 0x007F & rp->e_type;
+
+					if ((NOT dubsw) AND
+					    ((et EQ EV_NBEG) OR (et EQ EV_NEND))) {
+
+						grp = rp->e_data2;
+
+						if (grpstat[grp] AND (2 EQ grpmode[grp])) {
+
+							DB_CMNT("sc_trek - erasing note");
+
+							/* erasing a note */
+
+							ep = rp->e_fwd;
+
+							if (rp EQ p_bak)
+								p_bak = ep;
+
+							if (rp EQ p_cur)
+								p_cur = ep;
+
+							if (rp EQ p_ctr)
+								p_ctr = ep;
+
+							if (rp EQ p_fwd)
+								p_fwd = ep;
+
+							e_del(e_rmv(rp));
+							rp = ep;
+							goto nextev;
+						}
+/* 
+
+*/
+					} else if (et EQ EV_ANVL) {
+
+						grp = 0x000F & rp->e_data1;
+
+						if (grpstat[grp] AND (2 EQ (ancmsw ?
+						     varmode[0x000F & (rp->e_data1 >> 4)][grp] :
+						     grpmode[grp]))) {
+
+							DB_CMNT("sc_trek - erasing var");
+
+							/* erasing an analog variable */
+
+							ep = rp->e_fwd;
+
+							if (rp EQ p_bak)
+								p_bak = ep;
+
+							if (rp EQ p_cur)
+								p_cur = ep;
+
+							if (rp EQ p_ctr)
+								p_ctr = ep;
+
+							if (rp EQ p_fwd)
+								p_fwd = ep;
+
+							e_del(e_rmv(rp));
+							rp = ep;
+							goto nextev;
+						}
+					}
+				}
+
+				if (rp->e_time EQ rt) {	/* check event time */
+
+					se_exec(rp, se);	/* execute event */
+
+					if (se EQ D_FWD)
+						rp = rp->e_fwd;		/* point at next event */
+					else
+						rp = rp->e_bak;		/* point at next event */
+				}
+
+nextev:
+				if (((se EQ D_FWD) AND (rp->e_type EQ EV_FINI)) OR
+				    ((se EQ D_BAK) AND (rp->e_type EQ EV_SCORE)))
+					break;
+			}
+		}
+	}
+/* 
+
+*/
+	p_cur  = rp;		/* update p_cur */
+	t_cur  = tval;		/* update t_cur */
+
+	DB_EXIT("sc_trek");
+	return(SUCCESS);
+}
Index: ram/scwrite.c
===================================================================
--- ram/scwrite.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/scwrite.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,454 @@
+/*
+   =============================================================================
+	scwrite.c -- librarian - write score functions
+	Version 14 -- 1988-06-22 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "stdio.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "score.h"
+#include "scfns.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	long	chksum();
+
+extern	long	schksum;	/* score checksum */
+extern	long	snbreq;		/* number of disk bytes required */
+extern	long	snlreq;		/* number of score bytes required */
+extern	long	sntbreq;	/* total number of disk bytes required */
+extern	long	sntlreq;	/* total number of score bytes required */
+
+extern	long	nlpersc[N_SCORES];	/* number of longs per score */
+extern	long	scsums[N_SCORES];	/* score checksums */
+
+extern	struct	s_time	stimes[N_SCORES][N_SECTS];	/* section times */
+
+/* 
+
+*/
+
+long	m1con = -1L;			/* null score constant */
+
+short	scsizes[N_ETYPES][2] = {	/* score event sizes  (in bytes) */
+
+	/* [0] = score, [1] = disk */
+
+	{20,  0},	/*  0 - EV_NULL */
+	{20,  6},	/*  1 - EV_SCORE */
+	{24,  6},	/*  2 - EV_SBGN */
+	{24,  6},	/*  3 - EV_SEND */
+	{24,  7},	/*  4 - EV_INST */
+	{20,  9},	/*  5 - EV_NBEG */
+	{20,  9},	/*  6 - EV_NEND */
+	{20,  5},	/*  7 - EV_STOP */
+	{20,  7},	/*  8 - EV_INTP */
+	{24,  6},	/*  9 - EV_TMPO */
+	{24,  6},	/* 10 - EV_TUNE */
+	{24,  7},	/* 11 - EV_GRP */
+	{24,  7},	/* 12 - EV_LOCN */
+	{24,  7},	/* 13 - EV_DYN */
+	{24,  8},	/* 14 - EV_ANVL */
+	{24,  7},	/* 15 - EV_ANRS */
+	{24,  6},	/* 16 - EV_ASGN */
+	{32,  8},	/* 17 - EV_TRNS */
+	{20,  6},	/* 18 - EV_REPT */
+	{20,  6},	/* 19 - EV_PNCH */
+	{20,  7},	/* 20 - EV_PRES */
+	{20,  6},	/* 21 - EV_FINI */
+	{20,  7},	/* 22 - EV_CPRS */
+	{20,  5},	/* 23 - EV_BAR */
+	{20,  5}	/* 24 - EV_NEXT */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scsize() -- return number of bytes needed for a score
+   =============================================================================
+*/
+
+long
+scsize(sn)
+short sn;
+{
+	register long nb, nl, sc;
+	register struct s_entry *ep;
+	register short go;
+
+	snbreq  = nb = 0L;	/* number of disk bytes required */
+	snlreq  = nl = 0L;	/* number of score bytes required */
+	schksum = sc = 0L;	/* score checksum */
+
+	ep = scores[sn];	/* pointer to score begin */
+
+	if (E_NULL EQ ep) {	/* empty scores don't take any space */
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("scsize(%d):  empty score\n", sn);
+#endif
+		return(0L);
+	}
+
+	go = TRUE;
+
+/* 
+
+*/
+	do {
+		ep->e_type &= 0x7F;		/* clear new-data flag */
+
+		nl += scsizes[ep->e_type][0];
+		nb += scsizes[ep->e_type][1];
+
+		switch (ep->e_type) {
+
+		case EV_BAR:		/* bar marker */
+		case EV_STOP:		/* stop */
+		case EV_NEXT:		/* next */
+
+			sc += ep->e_type + ep->e_time;
+			break;
+
+		case EV_SCORE:		/* score begin */
+		case EV_SBGN:		/* section begin */
+		case EV_SEND:		/* section end */
+		case EV_TMPO:		/* tempo */
+		case EV_TUNE:		/* tuning */
+		case EV_ASGN:		/* I/O assign */
+		case EV_REPT:		/* repeat */
+		case EV_PNCH:		/* punch in/out */
+
+			sc += ep->e_type + ep->e_time + ep->e_data1;
+			break;
+
+		case EV_NBEG:		/* note begin */
+		case EV_NEND:		/* note end */
+
+			sc += ep->e_type + ep->e_time + ep->e_data1
+			      + ep->e_data2 + (struct n_entry *)ep->e_vel;
+
+			break;
+/* 
+
+*/
+		case EV_INST:		/* instrument change */
+		case EV_INTP:		/* interpolate */
+		case EV_GRP:		/* group status */
+		case EV_LOCN:		/* location */
+		case EV_DYN:		/* dynamics */
+		case EV_PRES:		/* polyphonic pressure */
+		case EV_CPRS:		/* channel pressure */
+		case EV_ANRS:		/* analog resolution */
+
+			sc += ep->e_type + ep->e_time + ep->e_data1
+			      + ep->e_data2;
+
+			break;
+
+		case EV_TRNS:		/* transposition */
+
+			sc += ep->e_type + ep->e_time + ep->e_data1
+			      + (short)ep->e_lft;
+
+			break;
+
+		case EV_ANVL:		/* analog value */
+
+			sc += ep->e_type + ep->e_time + ep->e_data1
+			      + (short)(0x0000FFFFL & ((long)ep->e_dn >> 16));
+
+			break;
+
+		case EV_FINI:		/* score end */
+
+			sc += ep->e_type + ep->e_time + ep->e_data1;
+			go = FALSE;
+			break;
+		}
+
+		ep = ep->e_fwd;
+
+	} while (go);		
+
+	schksum = sc;
+	snbreq  = nb;
+	snlreq  = (nl + 3L) >> 2;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("scsize(%d):  %ld bytes, checksum = %ld\n", nb, schksum);
+#endif
+
+	return(nb);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scsizer() -- return number of bytes necessary for storing active scores
+   =============================================================================
+*/
+
+long
+scsizer()
+{
+	register short i;
+	register long nb;
+
+	sntlreq = 0L;
+	nb = 0L;
+
+	for (i = 0; i < N_SCORES; i++) {
+
+		nlpersc[i] = 0L;
+		scsums[i] = 0L;
+
+		nb += 4L;	/* overhead for number of longs or -1L marker */
+
+		if (scores[i] NE E_NULL) {
+
+			/* add storage length of events + name + times */
+
+			nb += scsize(i) + 16L
+			      + (long)(N_SECTS * sizeof (struct s_time));
+
+			nlpersc[i] = snlreq;	/* update size table */
+			scsums[i]  = schksum;	/* update checksum table */
+			sntlreq   += snlreq;	/* update total longs count */
+		}
+	}
+
+	nb += 4L;	/* overhead for total longs count */
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("scsizer():  %ld bytes required\n", nb);
+#endif
+
+	sntbreq = nb;
+
+	return(nb);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	scwrite() -- store a score
+   =============================================================================
+*/
+
+short
+scwrite(sn, fp)
+short sn;
+register FILE *fp;
+{
+	register struct s_entry *ep;
+	register short go;
+	char scid[48];
+
+	ep = scores[sn];		/* pointer to score begin */
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("scwrite(%d, $%08lX):  ep = $%08lX\n", sn, fp, ep);
+#endif
+	
+	if (E_NULL EQ ep) {		/* empty scores only get a flag */
+
+		sprintf(scid, "score %d was empty", sn + 1);
+
+		ldwmsg((char *)0L, scid, (char *)0L, LCFBX10, LCBBX10);
+
+		if (wr_ec(fp, &m1con, 4L))
+			return(FAILURE);
+		else
+			return(SUCCESS);
+	}
+
+	sprintf(scid, "  writing score %d", sn + 1);
+
+	ldwmsg("Busy -- Please stand by", (char *)0L, scid,
+		LCFBX10, LCBBX10);
+
+	if (wr_ec(fp, &nlpersc[sn], 4L))	/* number of longs required */
+		return(FAILURE);
+
+	if (wr_ec(fp, &scname[sn], 16L))	/* score name */
+		return(FAILURE);
+
+	if (wr_ec(fp, &stimes[sn], (long)(N_SECTS * 12)))  /* section times */
+		return(FAILURE);
+
+	go = TRUE;
+
+	do {
+
+		switch (ep->e_type) {
+
+		case EV_BAR:		/* bar marker */
+		case EV_STOP:		/* stop */
+		case EV_NEXT:		/* next */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FAILURE);			
+
+			break;
+
+		case EV_SCORE:		/* score begin */
+		case EV_SBGN:		/* section begin */
+		case EV_SEND:		/* section end */
+		case EV_TMPO:		/* tempo */
+		case EV_TUNE:		/* tuning */
+		case EV_ASGN:		/* I/O assign */
+		case EV_REPT:		/* repeat */
+		case EV_PNCH:		/* punch in/out */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data1, 1L))
+				return(FAILURE);
+
+			break;
+/* 
+
+*/
+		case EV_INST:		/* instrument change */
+		case EV_INTP:		/* interpolate */
+		case EV_GRP:		/* group status */
+		case EV_LOCN:		/* location */
+		case EV_DYN:		/* dynamics */
+		case EV_PRES:		/* polyphonic pressure */
+		case EV_CPRS:		/* channel pressure */
+		case EV_ANRS:		/* analog resolution */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data1, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data2, 1L))
+				return(FAILURE);
+
+			break;
+/* 
+
+*/
+		case EV_NBEG:		/* note begin */
+		case EV_NEND:		/* note end */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data1, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data2, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &(((struct n_entry *)ep)->e_vel), 2L))
+				return(FAILURE);
+
+			break;
+
+		case EV_TRNS:		/* transposition */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data1, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_lft, 2L))
+				return(FAILURE);
+
+			break;
+/* 
+
+*/
+		case EV_ANVL:		/* analog value */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_data1, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_dn, 2L))
+				return(FAILURE);
+
+			break;
+
+		case EV_FINI:		/* score end */
+
+			if (wr_ec(fp, &ep->e_type, 1L))
+				return(FAILURE);
+
+			if (wr_ec(fp, &ep->e_time, 4L))
+				return(FALSE);
+
+			if (wr_ec(fp, &ep->e_data1, 1L))
+				return(FAILURE);
+
+			go = FALSE;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("scwrite():  EV_FINI\n");
+#endif
+			break;
+
+		}
+
+		ep = ep->e_fwd;
+
+	} while (go);		
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("scwrite():  SUCCESS\n");
+#endif
+
+	return(SUCCESS);
+}
Index: ram/seccpy.c
===================================================================
--- ram/seccpy.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/seccpy.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,772 @@
+/*
+   =============================================================================
+	seccpy.c -- section operation functions
+	Version 12 -- 1988-07-16 -- D.N. Lynx Crowe
+
+	This file contains the section operation functions for:
+
+		SOP_CPY		copy			sec_cpy()
+		SOP_MRG		merge			sec_mrg()
+		SOP_MOV		move			sec_mov()
+		SOP_RMV		remove			sec_rmv()
+		SOP_GRP		regroup			sec_grp()
+		SOP_DGR		delete groups		sec_dgr()
+		SOP_DEV		delete events		sec_dev()
+   =============================================================================
+*/
+
+#undef	DEBUGGER		/* define to enable debug trace */
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "debug.h"
+#include "score.h"
+#include "scfns.h"
+#include "secops.h"
+#include "secdefs.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	short	chksec(), oktocm(), oktode(), oktodg();
+
+extern	long	sizesec();
+
+extern	struct	s_entry	*madjsec();
+
+extern	short	grptran;
+
+extern	char	cmgtags[];
+extern	char	cmgtype[];
+
+extern	short	ehdlist[];
+extern	short	grptmap[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_cpy() -- copy section 'ns' into the score at t_cur
+
+	ns	section number to be copied
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_cpy(ns)
+register short ns;
+{
+	register struct s_entry *cp, *lp, *rp;
+	register long newet;
+
+	DB_ENTR("sec_cpy");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_cpy - FAILED chksec");
+		return(FAILURE);
+	}
+
+	/* see if we have enough free event space to make the copy */
+
+	if (sizesec() > evleft()) {
+
+		DB_EXIT("sec_cpy - FAILED sizesec");
+		return(FAILURE);
+	}
+
+	/* make sure we won't overflow the time range */
+
+	newet = t_sect + ((scp->e_bak)->e_bak)->e_time;
+
+	if ((newet < 0) OR (newet GE 0x00FFFFFFL)) {
+
+		DB_EXIT("sec_cpy - FAILED time check");
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+	/* make a time adjusted copy of the section */
+
+	if (E_NULL EQ (cp = madjsec(p_sbgn, t_cur))) {
+
+		DB_EXIT("sec_cpy - FAILED madjsec");
+		return(FAILURE);
+	}
+
+	/* point at the events in the score that will surround the copy */
+
+	lp = ep_adj(p_cur, 0, t_cur);		/* events left of the copy */
+	rp = lp->e_fwd;				/* events right of the copy */
+	
+	/* adjust the times in the score past the copy */
+
+	edelta(lp, t_cur, t_sect);
+
+	/* insert the copy into the score */
+
+	lp->e_fwd = p_cbgn;	/* link copy to left events */
+	p_cbgn->e_bak = lp;
+
+	rp->e_bak = p_cend;	/* link copy to right events */
+	p_cend->e_fwd = rp;
+
+	/* fix-up the event headers in the copy */
+
+	ehfix(p_cbgn, p_cend);
+
+	DB_EXIT("sec_cpy - SUCCESS");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_mrg() -- merge section 'ns' into the score at t_cur
+
+	ns	section number to be merged
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_mrg(ns)
+register short ns;
+{
+	register struct s_entry *cp, *lp, *rp;
+	register long newet;
+	register short et;
+
+	DB_ENTR("sec_mrg");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_mrg - FAILED chksec");
+		return(FAILURE);
+	}
+
+	/* see if we have enough free event space to make the copy */
+
+	if (sizesec() > evleft()) {
+
+		DB_EXIT("sec_mrg - FAILED sizesec");
+		return(FAILURE);
+	}
+
+	/* make sure we won't overflow the time range */
+
+	newet = t_sect + ((scp->e_bak)->e_bak)->e_time;
+
+	if ((newet < 0) OR (newet GE 0x00FFFFFFL)) {
+
+		DB_EXIT("sec_mrg - FAILED time check");
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+	/* make a time adjusted copy of the section */
+
+	if (E_NULL EQ (cp = madjsec(p_sbgn, t_cur))) {
+
+		DB_EXIT("sec_mrg - FAILED madjsec");
+		return(FAILURE);
+	}
+
+	DB_CMNT("sec_mrg - merging events");
+
+	lp = ep_adj(p_cur, 0, t_cur);	/* get merge point */
+
+	while (cp) {		/* merge events into score starting at p_cur */
+
+		rp = cp->e_fwd;				/* point at next event */
+		lp = ep_adj(lp, 0, cp->e_time);		/* update merge point */
+		lp = e_ins(cp, lp);			/* insert the element */
+		et = cp->e_type & 0x007F;		/* get event type */
+
+		if (-1 NE ehdlist[et])			/* see if it's a header */
+			eh_ins(cp, ehdlist[et]);	/* update header list */
+
+		cp = rp;				/* update copy pointer */
+	}
+
+	DB_EXIT("sec_mrg - SUCCESS");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_grp() -- regroup section 'ns'
+
+	ns	section number to be re-grouped
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_grp(ns)
+register short ns;
+{
+	register struct s_entry *cp, *rp;
+	register short et, nv, grp;
+
+	DB_ENTR("sec_grp");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_grp - FAILED chksec");
+		return(FAILURE);
+	}
+
+	cp = p_sbgn;			/* point at start of section */
+
+	while (cp NE p_send) {		/* regroup events in section */
+
+		rp = cp->e_fwd;			/* point at next event */
+		et = cp->e_type & 0x007F;	/* get event type */
+
+		if (cmgtags[et]) {		/* group sensitive ? */
+
+			grp = 0x000F & (cmgtype[et] ?
+				cp->e_data2 : cp->e_data1);
+
+			if ((et EQ EV_NBEG) OR (et EQ EV_NEND)) {
+
+				/* regroup */
+
+				cp->e_data2 = (cp->e_data2 & 0x00F0) |
+					grptmap[grp];
+
+				/* transpose */
+
+				nv = cp->e_data1 + grptran;
+
+				if (nv > 127)
+					nv = 127;
+				else if (nv < 0)
+					nv = 0;
+
+				cp->e_data1 = nv;
+
+			} else if ((et EQ EV_ANRS) OR (et EQ EV_ANVL)) {
+
+				/* regroup */
+
+				cp->e_data1 = (cp->e_data1 & 0x000F) |
+					(grptmap[grp] << 4);
+
+			} else {
+
+				/* regroup */
+
+				if (cmgtype[et])
+					cp->e_data2 = (cp->e_data2 & 0x00F0) |
+						grptmap[grp];
+				else
+					cp->e_data1 = (cp->e_data1 & 0x00F0) |
+						grptmap[grp];
+			}
+		}
+
+		cp = rp;		/* update event pointer */
+	}
+
+	DB_EXIT("sec_grp - SUCCESS");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_mov() -- move section 'ns' to t_cur
+
+	ns	section number to be moved
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_mov(ns)
+register short ns;
+{
+	register struct s_entry *cp, *lp, *rp;
+	register long newet;
+	register short et, grp, nv;
+
+	DB_ENTR("sec_mov");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_mov - FAILED chksec");
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw) {
+
+		printf("sec_mov:  t_cur = %ld, t_sbgn = %ld, t_send = %ld, t_sect = %ld\n",
+			t_cur, t_sbgn, t_send, t_sect);
+
+		printf("sec_mov:  p_cur = $%08lX, p_sbgn = $%08lX, p_send = $%08lX\n",
+			p_cur, p_sbgn, p_send);
+	}
+#endif
+
+	/* verify that section isn't being moved into itself */
+
+	if ((t_cur GE t_sbgn) AND (t_cur LE t_send)) {
+
+		DB_EXIT("sec_mov -- bad target");
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+	lp = ep_adj(p_cur, 0, t_cur);	/* get left move point */
+	cp = p_send->e_fwd;		/* get adjustment point */
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_mov: lp = $%08lX, cp = $%08lX\n", lp, cp);
+#endif
+
+	/* clip out the section and close up the hole */
+
+	(p_sbgn->e_bak)->e_fwd = p_send->e_fwd;
+	(p_send->e_fwd)->e_bak = p_sbgn->e_bak;
+	p_sbgn->e_bak = E_NULL;
+	p_send->e_fwd = E_NULL;
+
+	/* adjust the times above the clip point to end of score */
+
+	if (t_cur GE t_send)	/* adjust t_cur if above clip point */
+		t_cur -= t_sect;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_mov: adjusted t_cur = %ld\n", t_cur);
+#endif
+
+	while (EV_FINI NE (et = 0x007F & cp->e_type)) {
+
+		cp->e_time -= t_sect;	/* adjust event time */
+		cp = cp->e_fwd;		/* point at next event */
+	}
+
+/* 
+
+*/
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_mov: adjusted p_cur->e_time = %ld\n",
+			p_cur->e_time);
+#endif
+
+	/* relativize the section to 0 and unlink event headers from hplist */
+
+	rp = p_sbgn;			/* start at the beginning */
+	newet = p_sbgn->e_time;		/* relativize to begin time EQ 0 */
+
+	while (rp) {
+
+		rp->e_time -= newet;		/* relativize the time */
+		et = 0x007F & rp->e_type;	/* get event type */
+
+		if (cmgtags[et]) {	/* group sensitive ? */
+
+			grp = 0x000F & (cmgtype[et] ?
+				rp->e_data2 : rp->e_data1);
+
+			if ((et EQ EV_NBEG) OR (et EQ EV_NEND)) {
+
+				/* regroup */
+
+				rp->e_data2 = (rp->e_data2 & 0x00F0) |
+					grptmap[grp];
+
+				/* transpose */
+
+				nv = rp->e_data1 + grptran;
+
+				if (nv > 127)
+					nv = 127;
+				else if (nv < 0)
+					nv = 0;
+
+				rp->e_data1 = nv;
+
+			} else if ((et EQ EV_ANRS) OR (et EQ EV_ANVL)) {
+
+				/* regroup */
+
+				rp->e_data1 = (rp->e_data1 & 0x000F) |
+					(grptmap[grp] << 4);
+
+			} else {
+
+				/* regroup */
+
+				if (cmgtype[et])
+					rp->e_data2 = (rp->e_data2 & 0x00F0) |
+						grptmap[grp];
+				else
+					rp->e_data1 = (rp->e_data1 & 0x00F0) |
+						grptmap[grp];
+			}
+		}
+
+		if (-1 NE ehdlist[et])			/* if it's a header ... */
+			eh_rmv(rp, ehdlist[et]);	/* ... remove it from hplist */
+
+		rp = rp->e_fwd;			/* point at the next event */
+	}
+
+	rp = lp->e_fwd;				/* get right insert pointer */
+
+	/* insert the moved section */
+
+	p_sbgn->e_bak = lp;
+	p_send->e_fwd = rp;
+	lp->e_fwd = p_sbgn;
+	rp->e_bak = p_send;
+
+/* 
+
+*/
+	/* derelativize the moved section and put headers back on hplist */
+
+	cp = p_sbgn;
+	newet = t_cur;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_mov:  lp = $%08lX, cp = $%08lX, rp = $%08lX, newet = %ld\n",
+			lp, cp, rp, newet);
+#endif
+
+	while (cp NE rp) {
+
+		et = 0x007F & cp->e_type;	/* get event type */
+		cp->e_time += newet;		/* derelativize the time */
+
+		if (-1 NE ehdlist[et])			/* if event is a header ... */
+			eh_ins(cp, ehdlist[et]);	/* ... put event on hplist */
+
+		cp = cp->e_fwd;			/* point at next event */
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_mov: adjusting times above $%08lx (%ld) by %ld\n",
+			cp, cp->e_time, t_sect);
+#endif
+
+	/* adjust times above move point */
+
+	while (EV_FINI NE (et = 0x007F & cp->e_type)) {
+
+		cp->e_time += t_sect;		/* adjust the time */
+		cp = cp->e_fwd;			/* point at next event */
+	}
+
+	DB_EXIT("sec_mov - SUCCESS");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_rmv() --remove section 'ns'
+
+	ns	section number to be removed
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_rmv(ns)
+register short ns;
+{
+	register struct s_entry *cp, *lp, *rp;
+	register short et;
+	struct s_entry *pp;
+
+	DB_ENTR("sec_rmv");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_rmv - FAILED chksec");
+		return(FAILURE);
+	}
+
+	pp = cp = p_send->e_fwd;	/* get adjustment point */
+
+#if	DEBUGIT
+	if (debugsw) {
+
+		printf("sec_rmv:  t_cur = %ld, t_sbgn = %ld, t_send = %ld, t_sect = %ld\n",
+			t_cur, t_sbgn, t_send, t_sect);
+
+		printf("sec_rmv:  p_cur = $%08lX, p_sbgn = $%08lX, p_send = $%08lX\n",
+			p_cur, p_sbgn, p_send);
+
+		printf("sec_rmv: cp = $%08lX\n", cp);
+	}
+#endif
+
+/* 
+
+*/
+	/* clip out the section and close up the hole */
+
+	(p_sbgn->e_bak)->e_fwd = p_send->e_fwd;
+	(p_send->e_fwd)->e_bak = p_sbgn->e_bak;
+	p_sbgn->e_bak = E_NULL;
+	p_send->e_fwd = E_NULL;
+
+	/* adjust the times above the clip point to end of score */
+
+	if (t_cur GE t_send)	/* adjust t_cur if above clip point */
+		t_cur -= t_sect;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_rmv: adjusted t_cur = %ld\n", t_cur);
+#endif
+
+	while (EV_FINI NE (et = 0x007F & cp->e_type)) {
+
+		cp->e_time -= t_sect;	/* adjust event time */
+		cp = cp->e_fwd;		/* point at next event */
+	}
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sec_rmv: adjusted p_cur->e_time = %ld\n",
+			p_cur->e_time);
+#endif
+
+	/* unlink event headers from hplist, fix pointers, and delete events */
+
+	rp = p_sbgn;			/* start at the beginning */
+
+	while (rp) {
+
+		lp = rp->e_fwd;			/* get next event pointer */
+		et = 0x007F & rp->e_type;	/* get event type */
+
+		if (p_bak EQ rp)		/* fix p_bak */
+			p_bak = pp;
+
+		if (p_cur EQ rp)		/* fix p_cur */
+			p_cur = pp;
+
+		if (p_ctr EQ rp)		/* fix p_ctr */
+			p_ctr = pp;
+
+		if (p_fwd EQ rp)		/* fix p_fwd */
+			p_fwd = pp;
+
+		if (-1 NE ehdlist[et])			/* if it's a header ... */
+			eh_rmv(rp, ehdlist[et]);	/* ... remove it from hplist */
+
+		e_del(e_rmv(rp));		/* delete the event */
+		rp = lp;			/* point at next event */
+	}
+
+	seclist[curscor][ns] = E_NULL;		/* delete section from seclist */
+	DB_EXIT("sec_rmv");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_dgr() --delete notes in enabled groups in section 'ns'
+
+	ns	section number to be processed
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_dgr(ns)
+register short ns;
+{
+	register struct s_entry *lp, *rp;
+
+	DB_ENTR("sec_dgr");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_dgr - FAILED chksec");
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw) {
+
+		printf("sec_dgr:  t_cur = %ld, t_sbgn = %ld, t_send = %ld, t_sect = %ld\n",
+			t_cur, t_sbgn, t_send, t_sect);
+
+		printf("sec_dgr:  p_cur = $%08lX, p_sbgn = $%08lX, p_send = $%08lX\n",
+			p_cur, p_sbgn, p_send);
+	}
+#endif
+
+/* 
+
+*/
+	/* delete note events for record enabled groups */
+
+	DB_CMNT("sec_dgr - deleting");
+
+	rp = p_sbgn->e_fwd;			/* start at the beginning */
+
+	while (rp NE p_send) {
+
+		lp = rp->e_fwd;			/* get next event pointer */
+
+		if (oktodg(rp)) {		/* if it's one we want ... */
+
+			if (p_bak EQ rp)	/* fix p_bak */
+				p_bak = lp;
+
+			if (p_cur EQ rp)	/* fix p_cur */
+				p_cur = lp;
+
+			if (p_ctr EQ rp)	/* fix p_ctr */
+				p_ctr = lp;
+
+			if (p_fwd EQ rp)	/* fix p_fwd */
+				p_fwd = lp;
+
+			e_del(e_rmv(rp));	/* ... delete it */
+		}
+
+		rp = lp;			/* point at next event */
+	}
+
+	DB_EXIT("sec_dgr");
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sec_dev() --delete non-note events in enabled groups in section 'ns'
+
+	ns	section number to be processed
+
+	returns SUCCESS or FAILURE
+   =============================================================================
+*/
+
+short
+sec_dev(ns)
+register short ns;
+{
+	register struct s_entry *lp, *rp;
+
+	DB_ENTR("sec_dev");
+
+	secopok = TRUE;
+
+	if (chksec(ns)) {		/* check that section is OK */
+
+		DB_EXIT("sec_dev - FAILED chksec");
+		return(FAILURE);
+	}
+
+#if	DEBUGIT
+	if (debugsw) {
+
+		printf("sec_dev:  t_cur = %ld, t_sbgn = %ld, t_send = %ld, t_sect = %ld\n",
+			t_cur, t_sbgn, t_send, t_sect);
+
+		printf("sec_dev:  p_cur = $%08lX, p_sbgn = $%08lX, p_send = $%08lX\n",
+			p_cur, p_sbgn, p_send);
+	}
+#endif
+
+/* 
+
+*/
+	/* delete non-note events for record enabled groups */
+
+	DB_CMNT("sec_dev - deleting");
+
+	rp = p_sbgn->e_fwd;			/* start at the beginning */
+
+	while (rp NE p_send) {
+
+		lp = rp->e_fwd;			/* get next event pointer */
+
+		if (oktode(rp)) {		/* if it's one we want ... */
+
+			if (p_bak EQ rp)	/* fix p_bak */
+				p_bak = lp;
+
+			if (p_cur EQ rp)	/* fix p_cur */
+				p_cur = lp;
+
+			if (p_ctr EQ rp)	/* fix p_ctr */
+				p_ctr = lp;
+
+			if (p_fwd EQ rp)	/* fix p_fwd */
+				p_fwd = lp;
+
+			e_del(e_rmv(rp));	/* ... delete it */
+		}
+
+		rp = lp;			/* point at next event */
+	}
+
+	DB_EXIT("sec_dev");
+	return(SUCCESS);
+}
Index: ram/sedisp.s
===================================================================
--- ram/sedisp.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sedisp.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1229 @@
+* ------------------------------------------------------------------------------
+* sedisp.s -- score event display driver
+* Version 43 -- 1988-09-26 -- D.N. Lynx Crowe
+*
+*	se_disp(ep, sd, gdstb, cf)
+*	struct s_entry *ep;
+*	short sd;
+*	struct gdsel *gdstb[];
+*	short cf;
+*
+*		Displays the event at 'ep', scrolling in direction 'sd', by
+*		updating 'gdstb'.  Uses the accidental code in 'ac_code', and
+*		the note type table 'nsvtab'.  Checks 'cf' to determine if
+*		we're displaying in the center of the screen.
+*		Allocates gdsel events as needed for new events.
+* ------------------------------------------------------------------------------
+		.text
+*
+		.xdef	_se_disp
+*
+		.xdef	_ac_code
+		.xdef	numstr
+*
+		.xref	_dclkmd
+		.xref	_dsgmodz
+		.xref	_fromfpu
+		.xref	_mpcupd
+		.xref	_vputa
+		.xref	_vputc
+		.xref	_vputs
+*
+		.xref	_angroup
+		.xref	_ctrsw
+		.xref	_grpstat
+		.xref	_ins2grp
+		.xref	_ndisp
+		.xref	_obj8
+		.xref	_gdfsep
+		.xref	_lastvel
+		.xref	_nsvtab
+		.xref	_velflag
+		.xref	_vrbw08
+		.xref	_vrbw09
+		.xref	_vrbw10
+		.xref	_vrbw11
+		.xref	_vrbw12
+		.xref	_vrbw13
+		.xref	_vrbw14
+		.xref	_vrbw15
+		.xref	_vrcw
+*
+		.page
+*
+* parameter offsets
+* -----------------
+* for se_disp:
+* ------------
+P_EP		.equ	8		* LONG - event pointer
+P_SD		.equ	12		* WORD - scroll direction
+P_SL		.equ	14		* LONG - slice control table pointer
+P_CF		.equ	18		* WORD - center slice flag
+*
+* for vputa:
+* ----------
+ROW		.equ	4		* WORD - 'row' parameter offset
+COL		.equ	6		* WORD - 'col' parameter offset
+ATR		.equ	8		* WORD - 'atr' parameter offset
+*
+* Character field attributes for highlighting
+* -------------------------------------------
+AT01		.equ	$0054
+AT04		.equ	$0053
+AT05		.equ	$0054
+AT06		.equ	$0053
+AT07		.equ	$0054
+AT08		.equ	$0053
+AT09		.equ	$0054
+AT10		.equ	$0053
+AT11		.equ	$0052
+AT12		.equ	$0052
+*
+* Special character equates
+* -------------------------
+SP_M1		.equ	$A1			* -1
+SP_P1		.equ	$A0			* +1
+*
+		.page
+*
+* event structure offsets
+* -----------------------
+*		      offset		 length
+*		      ------             ------
+E_TIME		.equ	0		* LONG
+E_SIZE		.equ	4		* BYTE
+E_TYPE		.equ	5		* BYTE
+E_DATA1		.equ	6		* BYTE
+E_NOTE		.equ	6		* BYTE
+E_DATA2		.equ	7		* BYTE
+E_GROUP		.equ	7		* BYTE
+E_BAK		.equ	8		* LONG
+E_FWD		.equ	12		* LONG
+E_DN		.equ	16		* LONG
+E_VEL		.equ	16		* WORD
+E_DATA4		.equ	18		* WORD
+E_UP		.equ	20		* LONG
+E_LFT		.equ	24		* LONG
+E_RGT		.equ	28		* LONG
+*
+N_ETYPES	.equ	25		* number of event types
+*
+* gdsel structure definitions
+* ---------------------------
+G_NEXT		.equ	0		* long - 'next' field	(struct gdsel *)
+G_NOTE		.equ	4		* word - 'note' field	(short)
+G_CODE		.equ	6		* word - 'code' field	(short)
+*
+NATCH_B		.equ	3		* uslice note code:  'begin natural'
+NOTE_E		.equ	6		* uslice note code:  'end note'
+*
+NGDSEL		.equ	17		* number of event slots in gdstb
+*
+BARFLAG		.equ	4*(NGDSEL-1)	* offset to the bar marker flag
+*
+		.page
+*
+* A few words about se_disp:
+* --------------------------
+* se_disp has to be very fast, so it's written in assembly language,
+* rather than C, which is usually pretty good, but not quite good enough
+* for this application.  The faster this routine runs, the higher the
+* tempo we can keep up with.  If this code is fast enough, we end up
+* hardware limited by the maximum rate of the timer, and the VSDD update rate.
+*
+_se_disp:	link	a6,#0			* allocate and link stack frame
+		movea.l	P_EP(a6),a0		* get event pointer 'ep' into a0
+		move.b	E_TYPE(a0),d1		* get event type into d1.W
+		andi.w	#$007F,d1		* mask off new-note flag
+		cmp.b	#N_ETYPES,d1		* see if it's valid
+		blt	seds1			* jump if it is
+*
+dsexit:		unlk	a6			* done -- unlink stack frames
+		rts				* return to caller
+*
+seds1:		lea	sddtab,a1		* get base of dispatch table
+		lsl.w	#2,d1			* multiplty event by 4 for index
+		movea.l	0(a1,d1.W),a2		* get address of event routine
+		jmp	(a2)			* jump to event display routine
+*
+* On entry, the individual display routines only depend on a0 pointing at the
+* event they were dispatched for.  Registers a6 and a7 have their usual meaning,
+* a6 = frame pointer, a7 = stack pointer.
+*
+* d0..d2 are used for scratch, as are a0..a2, and are not saved by this code.
+*
+		.page
+*
+* dsnbx -- dispatch to begin / end based on sd
+* -----    -----------------------------------
+dsnbx:		tst.w	P_SD(a7)		* check direction
+		bne	dsne			* treat as end if going backward
+*
+* dsnb -- display note begin
+* ----    ------------------
+dsnb:		move.b	E_TYPE(a0),d1		* get event type
+		move.w	d1,d2			* save in d2
+		andi.w	#$007F,d1		* clear new-note flag
+		move.b	d1,E_TYPE(a0)		* store type back in event
+		clr.w	d0			* get group number
+		move.b	E_GROUP(a0),d0		* ... in d0
+		move.w	d0,d1			* save group in d1
+		add.w	d0,d0			* make d0 a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* check center slice flag
+		beq	dsnb0			* jump if not center slice
+*
+		tst.w	_velflag		* see if we display velocity
+		beq	dsnvx			* jump if not
+*
+		move.w	d2,-(a7)		* save new-note flag on stack
+		move.w	d1,-(a7)		* save group number on stack
+		move.w	E_VEL(a0),d0		* get velocity
+		move.w	d1,d2			* point into lastvel[]
+		add.w	d2,d2			* ...
+		lea	_lastvel,a1		* ...
+		move.w	d0,0(a1,d2.W)		* update lastvel[group]
+		ext.l	d0			* scale
+		divu	#252,d0			* ...
+		cmpi.w	#100,d0			* convert MS digit
+		bcs	dsnv0			* ...
+*
+		move.b	#'1',numstr		* ...
+		subi.w	#100,d0			* ...
+		bra	dsnv1			* ...
+*
+dsnv0:		move.b	#'0',numstr		* ...
+*
+dsnv1:		ext.l	d0			* convert middle & LS digits
+		divu	#10,d0			* ...
+		addi.l	#$00300030,d0		* ...
+		move.b	d0,numstr+1		* ...
+		swap	d0			* ...
+		move.b	d0,numstr+2		* ...
+		clr.b	numstr+3		* terminate string
+		move.w	d1,d0			* col = group
+		asl.w	#2,d0			* ... * 5
+		add.w	d1,d0			* ...
+		add.w	#6,d0			* ... + 6
+		move.l	a0,-(a7)		* save event pointer on stack
+		move.w	#AT11,-(a7)		* put attribute on stack
+		move.l	#numstr,-(a7)		* put string address on stack
+		move.w	d0,-(a7)		* put column on stack
+		move.w	#5,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put VSDD address on stack
+		jsr	_vputs			* update the screen
+		add.l	#14,a7			* clean up stack
+		movea.l	(a7)+,a0		* restore event pointer
+*
+		.page
+*
+		move.w	(a7)+,d0		* get group from stack
+		cmpi.w	#12,d0			* see which byte it's in
+		bcc	dsnv2			* jump if in MS byte
+*
+		bset	d0,_vrbw12+1		* set group bit in LS byte
+		bra	dsnv3			* ...
+*
+dsnv2:		bset	d0,_vrbw12		* set group bit in MS byte
+*
+dsnv3:		bset	#4,_vrcw		* set video reset type bit
+		move.w	(a7)+,d2		* get new-note flag from stack
+*
+dsnvx:		btst.l	#7,d2			* check new-note flag
+		beq	dsexit			* done if not set
+*
+dsnb0:		clr.w	d1			* get note number nn (0..127)
+		move.b	E_NOTE(a0),d1		* ... in d1
+		sub.w	#21,d1			* subtract base of piano scale
+		bmi	dsexit			* done if not displayable
+*
+		cmp.w	#87,d1			* see if it's too high
+		bgt	dsexit			* done if not displayable
+*
+		move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		clr.w	d2			* d2 = ep->group
+		move.b	E_GROUP(a0),d2		* ...
+		lsl.w	#2,d2			* ... * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[ep->group]
+		move.l	a1,0(a2,d2.W)		* gdstb[ep->group] = gdsp
+		move.w	d1,G_NOTE(a1)		* gdsp->note = nn
+		lea	_nsvtab,a2		* a2 points at nsvtab
+		tst.b	0(a2,d1.W)		* check nsvtab[nn]
+		beq	dsnb1			* jump if natural note
+*
+		move.b	_ac_code,d1		* setup for an accidental note
+		bra	dsnb2			* ...
+*
+dsnb1:		move.b	#NATCH_B,d1		* setup for a natural note
+*
+dsnb2:		move.w	d1,G_CODE(a1)		* gdsp->code = note type
+		bra	dsexit			* done
+*
+		.page
+*
+* dsnex -- dispatch to end/begin based on sd
+* -----    ---------------------------------
+dsnex:		tst.w	P_SD(a7)		* check direction
+		bne	dsnb			* treat as begin if going backward
+*
+* dsne -- display note end
+* ----    ----------------
+dsne:		move.b	E_TYPE(a0),d1		* get event type
+		move.w	d1,d2			* save in d2
+		andi.w	#$007F,d1		* clear new-note flag
+		move.b	d1,E_TYPE(a0)		* store type back in event
+		clr.w	d0			* get group number
+		move.b	E_GROUP(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* check center slice flag
+		beq	dsne3			* jump if not center slice
+*
+		btst.l	#7,d2			* check new-note flag
+		beq	dsexit			* done if not set
+*
+dsne3:		move.b	E_NOTE(a0),d1		* d1 = note number nn (0..127)
+		sub.w	#21,d1			* subtract base of piano scale
+		bmi	dsexit			* done if not displayable
+*
+		cmp.w	#87,d1			* see if it's too high
+		bgt	dsexit			* done if not displayable
+*
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		clr.w	d2			* get group in d2
+		move.b	E_GROUP(a0),d2		* ...
+		lsl.w	#2,d2			* ... * 4
+		move.l	0(a2,d2.W),d0		* check gdstb[ep->group]
+		beq	dsexit
+*
+dsne0:		movea.l	d0,a1			* a1 = gdsp
+*
+dsne1:		cmp.w	G_NOTE(a1),d1		* compare nn to gdsp->note
+		bne	dsne2			* jump if not the one we want
+*
+		move.w	#NOTE_E,G_CODE(a1)	* gdsp->code = NOTE_E  (end note)
+*
+dsne2:		move.l	G_NEXT(a1),d0		* get gdsp->next
+		beq	dsexit			* done if next = NULL
+*
+		bra	dsne0			* loop for next one
+*
+		.page
+*
+* dssbgn -- display section begin
+* ------    ---------------------
+dssbgn:		tst.w	P_CF(a6)		* center update ?
+		beq	dsbgn0			* jump if not
+*
+		clr.w	d1			* get section number
+		move.b	E_DATA1(a0),d1		* ... from the event
+		addq.w	#1,d1			* ... adjusted for display
+		ext.l	d1			* ... as a long in d1
+		divu	#10,d1			* divide by 10 for conversion
+		add.l	#$00300030,d1		* add '0' for ASCII conversion
+		move.b	d1,numstr		* put MS byte in work area
+		swap	d1			* swap register halves
+		move.b	d1,numstr+1		* put LS byte in work area
+		clr.b	numstr+2		* terminate string
+		move.w	#AT01,-(a7)		* put attribute on stack
+		move.l	#numstr,-(a7)		* put buffer address on stack
+		move.w	#6,-(a7)		* put column on stack
+		move.w	#0,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputs			* update the screen
+		add.l	#14,a7			* clean up stack
+		bset	#4,_vrcw+1		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsbgn0:		move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#48,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$1111,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#0,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dssend -- display section end
+* ------    -------------------
+dssend:		tst.w	P_CF(a6)		* center update ?
+		beq	dssend0			* jump if not
+*
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dssend0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#48,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$1111,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#2,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+* dsbeat -- display beat
+* ------    ------------
+dsbeat:		tst.w	P_CF(a6)		* center update ?
+		bne	dsexit			* done if so
+*
+		move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#48,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$1111,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#1,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dstune -- display tuning
+* ------    --------------
+dstune:		tst.w	P_CF(a6)		* center update ?
+		beq	dstune0			* jump if not
+*
+		clr.w	d1			* get current tuning
+		move.b	E_DATA1(a0),d1		* ...
+		add.w	#$0030,d1		* add '0' for ASCII conversion
+		move.w	#AT05,-(a7)		* put attribute on stack
+		move.w	d1,-(a7)		* put character on stack
+		move.w	#19,-(a7)		* put column on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputc			* display character
+		add.l	#12,a7			* clean up stack
+		bset	#1,_vrcw+1		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dstune0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#52,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$CCCC,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#3,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[priority] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dstrns -- display transposition
+* ------    ---------------------
+dstrns:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* center update
+		beq	dstrns0			* jump if not
+*
+		move.w	E_LFT(a0),d1		* get transposition value
+		bpl	dstrns1			* jump if positive
+*
+		move.b	#'-',numstr		* note negative sign
+		neg.w	d1			* make number positive
+		bra	dstrns2			* ...
+*
+dstrns1:	move.b	#'+',numstr		* note positive sign
+*
+dstrns2:	cmpi.w	#1000,d1		* is number GE 1000 ?
+		bcs	dstrns3			* jump if not
+*
+		subi.w	#1000,d1		* adjust number
+		cmpi.b	#'-',numstr		* was number negative
+		bne	dstrns4			* jump if not
+*
+		move.b	#SP_M1,numstr		* set -1 in numstr
+		bra	dstrns3			* ...
+*
+dstrns4:	move.b	#SP_P1,numstr		* set +1 in numstr
+*
+dstrns3:	ext.l	d1			* make d1 a long
+		divu	#100,d1			* convert 1st digit
+		addi.w	#$0030,d1		* ... to ASCII
+		move.b	d1,numstr+1		* ... in numstr
+		swap	d1			* convert 2nd digit
+		ext.l	d1			* ...
+		divu	#10,d1			* ...
+		addi.w	#$0030,d1		* ... to ASCII
+		move.b	d1,numstr+2		* ... in numstr
+		swap	d1			* convert 3rd digit
+		addi.w	#$0030,d1		* ... to ASCII
+		move.b	d1,numstr+3		* ... in numstr
+		clr.b	numstr+4		* terminate numstr
+*
+		.page
+*
+		move.w	d0,d1			* get group number
+		asr.w	#1,d1			* ... in d1
+		move.w	d1,-(a7)		* save group number on stack
+		add.w	d0,d0			* calculate column
+		add.w	d0,d1			* ... = 5 * group
+		addi.w	#5,d1			* ... + 5
+		move.w	#AT11,-(a7)		* vputs(obj8, 3, col, numstr, atr11)
+		move.l	#numstr,-(a7)		* ...
+		move.w	d1,-(a7)		* ...
+		move.w	#3,-(a7)		* ...
+		move.l	_obj8,-(a7)		* ...
+		jsr	_vputs			* ...
+		add.l	#14,a7			* ...
+		move.w	(a7)+,d0		* get group number
+		cmpi.w	#8,d0			* see which byte it's in
+		bcc	dstrns5			* jump if in MS byte
+*
+		bset	d0,_vrbw09+1		* set group bit in LS byte
+		bra	dstrns6			* ...
+*
+dstrns5:	sub.w	#8,d0			* adjust for byte
+		bset	d0,_vrbw09		* set group bit in MS byte
+*
+dstrns6:	bset	#1,_vrcw		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dstrns0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#52,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#4,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsdyn -- display dynamics
+* -----    ----------------
+dsdyn:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* center update ?
+		beq	dsdyn00			* jump if not
+*
+		clr.w	d0			* get dynamics
+		move.b	E_DATA2(a0),d0		* ... in d0
+		move.w	d0,-(a7)		* save dyanmics
+		clr.w	d1			* get group number
+		move.b	E_DATA1(a0),d1		* ... in d1
+		move.w	d1,-(a7)		* save group number
+		move.w	(a7),d0			* col = group number
+		add.w	d0,d0			* ... * 5
+		add.w	d0,d0			* ...
+		move.w	(a7)+,d2		* ...  (d2 = group number)
+		add.w	d2,d0			* ...
+		add.w	#6,d0			* ... + 6
+		move.w	(a7)+,d1		* get dynamics
+		add.w	#$0030,d1		* add '0' for ASCII conversion
+		move.w	d2,-(a7)		* save group number
+		move.w	#AT11,-(a7)		* put attribute on stack
+		move.w	d1,-(a7)		* put digit on stack
+		move.w	d0,-(a7)		* put column on stack
+		move.w	#4,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put object address on stack
+		jsr	_vputc			* update the screen
+		add.l	#12,a7			* clean up stack
+		move.w	(a7)+,d0		* get group number
+		cmp.w	#8,d0			* see which word it's in
+		bcc	dsdyn1			* jump if in MS word
+*
+		bset	d0,_vrbw10+1		* set group bit in LS byte
+		bra	dsdyn2			* ...
+*
+dsdyn1:		sub.w	#8,d0			* adjust for for byte
+		bset	d0,_vrbw10		* set group bit in MS byte
+*
+dsdyn2:		bset	#2,_vrcw		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+		.page
+dsdyn00:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#52,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#5,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dslocn -- display location
+* ------    ----------------
+dslocn:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* center update ?
+		beq	dsloc00			* jump if not
+*
+		clr.w	d0			* get location
+		move.b	E_DATA2(a0),d0		* ... in d0
+		move.w	d0,-(a7)		* save location
+		clr.w	d1			* get group number
+		move.b	E_DATA1(a0),d1		* ... in d1
+		move.w	d1,-(a7)		* save group number
+		move.w	(a7),d0			* col = group number
+		add.w	d0,d0			* ... * 5
+		add.w	d0,d0			* ...
+		move.w	(a7)+,d2		* ...  (d2 = group number)
+		add.w	d2,d0			* ...
+		add.w	#8,d0			* ... + 8
+		move.w	(a7)+,d1		* get location
+		add.w	#$0031,d1		* add '0' for ASCII conversion
+		move.w	d2,-(a7)		* save group number
+		move.w	#AT11,-(a7)		* put attribute on stack
+		move.w	d1,-(a7)		* put character on stack
+		move.w	d0,-(a7)		* put column on stack
+		move.w	#4,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put object address on stack
+		jsr	_vputc			* update the screen
+		add.l	#12,a7			* clean up stack
+		move.w	(a7)+,d0		* get group number
+		cmp.w	#8,d0			* see which word it's in
+		bcc	dslocn1			* jump if in MS word
+*
+		bset	d0,_vrbw11+1		* set group bit in LS byte
+		bra	dslocn2			* ...
+*
+dslocn1:	sub.w	#8,d0			* adjust for for byte
+		bset	d0,_vrbw11		* set group bit in MS byte
+*
+dslocn2:	bset	#3,_vrcw		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+		.page
+dsloc00:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#52,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#5,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsanrs -- display analog resolution
+* ------    -------------------------
+dsanrs:		move.b	E_DATA1(a0),d1		* get var / group
+		move.w	d1,d0			* extract group number
+		andi.w	#$000F,d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* center update ?
+		beq	dsanrs0			* jump if not
+*
+		move.w	_angroup,d2		* see if we display
+		bmi	dsexit			* jump if not
+*
+		subq.w	#1,d2			* adust selected group number
+		move.w	d1,d0			* extract group from event
+		andi.w	#$000F,d0		* ...
+		cmp.w	d0,d2			* see if we display
+		bne	dsexit			* jump if not
+*
+		lsr.w	#4,d1			* extract variable number
+		andi.w	#$000F,d1		* ...
+		move.w	d1,-(a7)		* save variable number
+		move.w	d1,d0			* calculate display offset
+		lsl.w	#3,d0			* ... (var * 9) + 6
+		add.w	d0,d1			* ... in d1
+		addq.w	#6,d1			* ...
+		move.b	E_DATA2(a0),d0		* get resolution
+		addi.w	#$0030,d0		* convert for display
+		move.w	#AT12,-(a7)		* put attribute on stack
+		move.w	d0,-(a7)		* put character on stack
+		move.w	d1,-(a7)		* put column on stack
+		move.w	#7,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputc			* update the screen
+		add.l	#12,a7			* clean up stack
+		move.w	(a7)+,d0		* get variable number
+		bset	d0,_vrbw13+1		* set variable bit
+		bset	#5,_vrcw		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+		.page
+dsanrs0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#52,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#6,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsanvl -- display analog value
+* ------    --------------------
+dsanvl:		move.w	_angroup,d2		* see if we display
+		bmi	dsexit			* jump if not
+*
+		move.b	E_DATA1(a0),d1		* get var / group
+		move.w	d1,d0			* extract group number
+		andi.w	#$000F,d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* center update ?
+		beq	dsanvl0			* jump if not
+*
+		subq.w	#1,d2			* adust group number
+		move.w	d1,d0			* extract group
+		andi.w	#$000F,d0		* ...
+		cmp.w	d0,d2			* see if we display
+		bne	dsexit			* jump if not
+*
+		lsr.w	#4,d1			* extract variable number
+		andi.w	#$000F,d1		* ...
+		move.w	d1,-(a7)		* save variable number
+		move.w	d1,d0			* calculate display offset
+		lsl.w	#3,d0			* ... (var * 9) + 8
+		add.w	d0,d1			* ... in d1
+		addi.w	#8,d1			* ...
+		move.w	E_DN(a0),d0		* get value
+		asr.w	#5,d0			* adjust to low 11 bits
+		bpl	dsanvl1			* jump if positive
+*
+		move.b	#'-',numstr		* set sign = '-'
+		neg.w	d0			* make value positive
+		bra	dsanvl2
+*
+dsanvl1:	move.b	#'+',numstr		* set sign = '+'
+*
+		.page
+dsanvl2:	ext.l	d0			* convert MS digit
+		divu	#1000,d0		* ...
+		add.w	#$0030,d0		* ...
+		move.b	d0,numstr+1		* ...
+		swap	d0			* convert middle digit
+		ext.l	d0			* ...
+		divu	#100,d0			* ...
+		add.w	#$0030,d0		* ...
+		move.b	d0,numstr+2		* ...
+		move.b	#'.',numstr+3		* insert decimal point
+		swap	d0			* convert LS digit
+		ext.l	d0			* ...
+		divu	#10,d0			* ...
+		add.w	#$0030,d0		* ...
+		move.b	d0,numstr+4		* ...
+		clr.b	numstr+5		* terminate string
+		move.w	#AT12,-(a7)		* put attribute on stack
+		move.l	#numstr,-(a7)		* put buffer address on stack
+		move.w	d1,-(a7)		* put column on stack
+		move.w	#7,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputs			* update the screen
+		add.l	#14,a7			* clean up stack
+		move.w	(a7)+,d0		* get variable number
+		bset	d0,_vrbw14+1		* set variable bit
+		bset	#6,_vrcw		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsanvl0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#52,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#6,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsasgn -- display assignment
+* ------    ------------------
+dsasgn:		tst.w	P_CF(a6)		* center update ?
+		beq	dsasgn0			* jump if not
+*
+		move.l	a0,-(a7)		* stash a0
+		jsr	_mpcupd			* update changed stuff
+		movea.l	(a7)+,a0		* restore a0
+		clr.w	d1			* get assignment
+		move.b	E_DATA1(a0),d1		* ... from the event
+		ext.l	d1			* ... as a long in d1
+		divu	#10,d1			* divide by 10 for conversion
+		add.l	#$00300030,d1		* add '0' for ASCII conversion
+		move.b	d1,numstr		* put MS byte in work area
+		swap	d1			* swap register halves
+		move.b	d1,numstr+1		* put LS byte in work area
+		clr.b	numstr+2		* terminate string
+		move.w	#AT04,-(a7)		* put attribute on stack
+		move.l	#numstr,-(a7)		* put buffer address on stack
+		move.w	#11,-(a7)		* put column on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputs			* update the screen
+		add.l	#14,a7			* clean up stack
+		bset	#0,_vrcw+1		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+	 	beq	dsexit			* done if not
+*
+dsasgn0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#56,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$3333,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#3,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dstmpo -- display tempo
+* ------    -------------
+dstmpo:		tst.w	P_CF(a6)		* center update ?
+		beq	dstmpo0			* jump if not
+*
+		clr.w	d1			* get tempo
+		move.b	E_DATA1(a0),d1		* ... from event
+		ext.l	d1			* ... as a long in d1
+		divu	#10,d1			* divide by 10 for conversion
+		swap	d1			* swap register halves
+		add.w	#$0030,d1		* add '0' for ASCII conversion
+		move.b	d1,numstr+2		* put LS byte in work area
+		swap	d1			* swap register halves
+		ext.l	d1			* divide again
+		divu	#10,d1			* ...
+		add.l	#$00300030,d1		* add '0' for ASCII conversion
+		move.b	d1,numstr		* put MS byte in work area
+		swap	d1			* swap register halves
+		move.b	d1,numstr+1		* put middle byte in work area
+		clr.b	numstr+3		* terminate string
+		move.w	#AT06,-(a7)		* put attribute on stack
+		move.l	#numstr,-(a7)		* put buffer address on stack
+		move.w	#27,-(a7)		* put column on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputs			* display tempo
+		add.l	#14,a7			* clean up stack
+		bset	#2,_vrcw+1		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dstmpo0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#56,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$3333,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#4,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsstop -- display stop
+* ------    ------------
+dsstop:		tst.w	P_CF(a6)		* center update ?
+		beq	dsstop0			* jump if not
+*
+		jsr	_dclkmd			* show that clock is stopped
+		move.w	#AT08,-(a7)		* put attribute on stack
+		move.w	#40,-(a7)		* put 1st column on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputa			* hilite first column
+		move.w	#41,COL(a7)		* put 2nd column on stack
+		jsr	_vputa			* hilite second column
+		move.w	#42,COL(a7)		* put 3rd column on stack
+		jsr	_vputa			* hilite third column
+		move.w	#43,COL(a7)		* put 4th column on stack
+		jsr	_vputa			* hilite fourth column
+		add.l	#10,a7			* clean up stack
+		bset	#7,_vrcw		* set video reset type bits
+		bset	#0,_vrbw15		* ...
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsstop0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#56,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$3333,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#5,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsnext -- display next
+* ------    ------------
+dsnext:		tst.w	P_CF(a6)		* center update ?
+		beq	dsnext0			* jump if not
+*
+		move.w	#AT08,-(a7)		* put attribute on stack
+		move.w	#45,-(a7)		* put 1st column on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put sbase on stack
+		jsr	_vputa			* hilite first column
+		move.w	#46,COL(a7)		* put 2nd column on stack
+		jsr	_vputa			* hilite second column
+		move.w	#47,COL(a7)		* put 3rd column on stack
+		jsr	_vputa			* hilite third column
+		move.w	#48,COL(a7)		* put 4th column on stack
+		jsr	_vputa			* hilite fourth column
+		add.l	#10,a7			* clean up stack
+		bset	#7,_vrcw		* set video reset type bits
+		bset	#1,_vrbw15		* ...
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsnext0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#56,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$3333,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#5,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsgrp -- display group status
+* -----    --------------------
+dsgrp:		tst.w	P_CF(a6)		* center update ?
+		beq	dsgrp0			* jump if not
+*
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsgrp0:		move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#60,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#3,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsinst -- display instrument
+* ------    ------------------
+dsinst:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	dsexit			* done if not enabled
+*
+		tst.w	P_CF(a6)		* center update ?
+		beq	dsins00			* jump if not
+*
+		lea	_ins2grp,a1		* point at ins2grp[]
+		clr.w	d0			* get instrument number
+		move.b	E_DATA2(a0),d0		* ... in d0
+		move.w	d0,-(a7)		* save instrument number
+		clr.w	d1			* get group number
+		move.b	E_DATA1(a0),d1		* ... in d1
+		move.w	d1,-(a7)		* save group number
+		move.w	(a7),d0			* col = group number
+		add.w	d0,d0			* ... * 5
+		add.w	d0,d0			* ...
+		move.w	(a7)+,d2		* ...  (d2 = group number)
+		add.w	d2,d0			* ...
+		add.w	#7,d0			* ... + 7
+		clr.l	d1			* get instrument number
+		move.w	(a7)+,d1		* ... as a long in d1
+		divu	#10,d1			* divide by 10 for conversion
+		add.l	#$00300030,d1		* add '0' for ASCII conversion
+		move.b	d1,numstr		* put MS byte in work area
+		swap	d1			* swap register halves
+		move.b	d1,numstr+1		* put LS byte in work area
+		clr.b	numstr+2		* terminate string
+		move.w	d2,-(a7)		* save group number
+		move.w	#AT11,-(a7)		* put attribute on stack
+		move.l	#numstr,-(a7)		* put buffer address on stack
+		move.w	d0,-(a7)		* put column on stack
+		move.w	#2,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put object address on stack
+		jsr	_vputs			* update the screen
+		add.l	#14,a7			* clean up stack
+*
+		.page
+		move.w	(a7)+,d0		* get group number
+		cmp.w	#8,d0			* see which word it's in
+		bcc	dsinst1			* jump if in MS word
+*
+		bset	d0,_vrbw08+1		* set group bit in LS byte
+		bra	dsinst2			* ...
+*
+dsinst1:	sub.w	#8,d0			* adjust for for byte
+		bset	d0,_vrbw08		* set group bit in MS byte
+*
+dsinst2:	bset	#0,_vrcw		* set video reset type bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsins00:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#60,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$9999,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#3,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsintp -- display interpolation
+* ------    ---------------------
+dsintp:		tst.w	P_CF(a6)		* center update ?
+		beq	dsintp0			* jump if not
+*
+		move.w	E_DATA1(a0),-(a7)	* get interpolate value
+		jsr	_fromfpu		* convert to milliseconds
+		tst.w	(a7)+			* ...
+		andi.l	#$0000FFFF,d0		* clear high bits
+		divu	#10000,d0		* convert 1st digit
+		addi.w	#$0030,d0		* ... to ASCII
+		move.b	d0,numstr		* ... in numstr
+		swap	d0			* convert 2nd digit
+		ext.l	d0			* ...
+		divu	#1000,d0		* ...
+		addi.w	#$0030,d0		* ... to ASCII
+		move.b	d0,numstr+1		* ... in numstr
+		move.b	#'.',numstr+2		* insert decimal point
+		swap	d0			* convert 3rd digit
+		ext.l	d0			* ...
+		divu	#100,d0			* ...
+		addi.w	#$0030,d0		* ... to ASCII
+		move.b	d0,numstr+3		* ... in numstr
+		clr.b	numstr+4		* terminate numstr
+		move.w	#AT07,-(a7)		* vputs(obj8, 1, 35, numstr, AT07)
+		move.l	#numstr,-(a7)		* ...
+		move.w	#35,-(a7)		* ...
+		move.w	#1,-(a7)		* ...
+		move.l	_obj8,-(a7)		* ...
+		jsr	_vputs			* ...
+		add.l	#14,a7			* ...
+		bset	#3,_vrcw+1		* set video reset bit
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsintp0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#60,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$CCCC,G_NOTE(a1)	* gdsp->note = COLOR
+		move.w	#4,G_CODE(a1)		* gdsp->code = PATTERN
+		move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dspnch -- display punch in/out
+* ------    --------------------
+dspnch:		tst.w	P_CF(a6)		* center update ?
+		beq	dspnch0			* jump if not
+*
+		tst.w	E_DATA1(a0)		* punch in ?
+		beq	dspnch1			* jump if not
+*
+		move.w	#AT09,-(a7)		* put attribute on stack
+		move.w	#50,-(a7)		* put 1st col on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put object address on stack
+		jsr	_vputa			* highlight 1st column
+		move.w	#51,COL(a7)		* put 2nd col on stack
+		jsr	_vputa			* highlight 2nd col
+		add.l	#10,a7			* clean up stack
+		bset	#5,_vrcw+1		* set video reset bit
+		bra	dspnch2			* go do maker update
+*
+dspnch1:	move.w	#AT09,-(a7)		* put attribute on stack
+		move.w	#53,-(a7)		* put 1st col on stack
+		move.w	#1,-(a7)		* put row on stack
+		move.l	_obj8,-(a7)		* put object address on stack
+		jsr	_vputa			* highlight 1st column
+		move.w	#54,COL(a7)		* put 2nd col on stack
+		jsr	_vputa			* highlight 2nd column
+		move.w	#55,COL(a7)		* put 3rd col on stack
+		jsr	_vputa			* highlight 3rd column
+		add.l	#10,a7			* clean up stack
+		bset	#6,_vrcw+1		* set video reset bit
+*
+dspnch2:	jsr	_dsgmodz		* display updated modes
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dspnch0:	move.l	_gdfsep,d0		* quit if no elements left
+		beq	dsexit			* ...
+*
+		movea.l	d0,a1			* a1 = gdsp
+		move.l	G_NEXT(a1),_gdfsep	* gdfsep = gdsp->next
+		move.w	#60,d2			* d2 = event PRIORITY * 4
+		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	0(a2,d2.W),G_NEXT(a1)	* gdsp->next = gdstb[pri]
+		move.w	#$CCCC,G_NOTE(a1)	* gdsp->note = COLOR
+		tst.w	E_DATA1(a0)		* see which kind we have
+		bne	dspnchi			* jump if 'punch in'
+*
+		move.w	#6,G_CODE(a1)		* gdsp->code = 'out' PATTERN
+		bra	dspnchx
+*
+dspnchi:	move.w	#5,G_CODE(a1)		* gdsp->code = 'in' PATTERN
+*
+dspnchx:	move.l	a1,0(a2,d2.W)		* gdstb[pri] = gdsp
+		bra	dsexit			* done
+*
+		.page
+*
+* dsbar -- display a bar marker
+* -----    --------------------
+dsbar:		tst.w	P_CF(a6)		* center update ?
+		beq	dsbar0			* jump if not
+*
+		tst.w	_ctrsw			* update center for scupd ?
+		beq	dsexit			* done if not
+*
+dsbar0:		movea.l	P_SL(a6),a2		* a2 points at gdstb
+		move.l	#-1,BARFLAG(a2)		* set the bar marker flag
+		bra	dsexit			* done
+*
+		.page
+*
+* ==============================================================================
+		.data
+* ==============================================================================
+*
+* sddtab -- score display dispatch table -- MUST match score.h definitions
+* ------    ----------------------------    ------------------------------
+sddtab:		dc.l	dsexit		* 0	null
+		dc.l	dsexit		* 1	score begin
+		dc.l	dssbgn		* 2	section begin
+		dc.l	dssend		* 3	section end
+		dc.l	dsinst		* 4	instrument change
+		dc.l	dsnbx		* 5	note begin
+		dc.l	dsnex		* 6	note end
+		dc.l	dsstop		* 7	stop
+		dc.l	dsintp		* 8	interpolate
+		dc.l	dstmpo		* 9	tempo
+		dc.l	dstune		* 10	tuning
+		dc.l	dsgrp		* 11	group status
+		dc.l	dslocn		* 12	location
+		dc.l	dsdyn		* 13	dynamics
+		dc.l	dsanvl		* 14	analog value
+		dc.l	dsanrs		* 15	analog resolution
+		dc.l	dsasgn		* 16	I/O assign
+		dc.l	dstrns		* 17	transposition
+		dc.l	dsexit		* 18	repeat
+		dc.l	dspnch		* 19	punch in/out
+		dc.l	dsexit		* 20	polyphonic pressure
+		dc.l	dsexit		* 21	score end
+		dc.l	dsexit		* 22	channel pressure
+		dc.l	dsbar		* 23	bar marker
+		dc.l	dsnext		* 24	next score
+*
+* ==============================================================================
+		.bss
+* ==============================================================================
+*
+* globals:
+* --------
+_ac_code:	ds.b	1		* accidental code
+*
+* locals:
+* -------
+numstr:		ds.b	65		* video display update work area
+*
+* ------------------------------------------------------------------------------
+*
+		.end
Index: ram/sedump.c
===================================================================
--- ram/sedump.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sedump.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,770 @@
+/*
+   =============================================================================
+	sedump.c -- dump various kinds of MIDAS-VII data in readable format
+	Version 42 -- 1988-08-24 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "stddefs.h"
+#include "score.h"
+#include "scfns.h"
+#include "slice.h"
+#include "secdefs.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	unsigned	scrl;
+
+extern	short	curfunc;
+extern	short	curvce;
+extern	short	sbase;
+extern	short	sd;
+extern	short	se;
+extern	short	soffset;
+extern	short	subj;
+
+extern	short	varmode[][16];
+
+extern	struct	gdsel	*gdstbc[NGDSEL];
+extern	struct	gdsel	*gdstbn[NGDSEL];
+extern	struct	gdsel	*gdstbp[NGDSEL];
+
+extern	struct	gdsel	*gdfsep;
+extern	struct	gdsel	gdfsl[MAXFSL];
+
+extern	struct	instdef	vbufs[];
+
+extern	char	*idbxlbl[];
+extern	char	*osclbl[];
+
+/* 
+
+*/
+
+char	*A6PTR = 0L;		/* traceback a6 starting address */
+char	*A7PTR = 0L;		/* traceback a7 starting address */
+char	*A7TOP = 0x000FFFFFL;	/* traceback stack top */
+
+short	SCnumv = 0;		/* voice for SCvoice()  to dump (0..11) */
+short	SL_Flag;		/* ROMP trap disable flag */
+short	x_unrec;		/* unrecognized event type or size flag */
+
+long	SCdlim = MAX_SE;	/* score dump limit */
+
+char *evkinds[N_ETYPES] = {	/* event types (must match score.h) */
+
+	"00: EV_NULL  null event   ",	"01: EV_SCORE score begin  ",
+	"02: EV_SBGN  section begin",	"03: EV_SEND  section end  ",
+	"04: EV_INST  instr. change",	"05: EV_NBEG  note begin   ",
+	"06: EV_NEND  note end     ",	"07: EV_STOP  stop         ",
+	"08: EV_INTP  interpolate  ",	"09: EV_TMPO  tempo        ",
+	"0A: EV_TUNE  tuning       ",	"0B: EV_GRP   group status ",
+	"0C: EV_LOCN  location     ",	"0D: EV_DYN   dynamics     ",
+	"0E: EV_ANVL  analog value ",	"0F: EV_ANRS  analog res.  ",
+	"10: EV_ASGN  I/O assign   ",	"11: EV_TRNS  transposition",
+	"12: EV_REPT  repeat       ",	"13: EV_PNCH  punch in/out ",
+	"14: EV_PRES  poly pressure",	"15: EV_FINI  score end    ",
+	"16: EV_CPRS  chan pressure",	"17: EV_BAR   bar marker   "
+};
+
+char	*hpname[N_TYPES] = {	/* header type names (must match score.h) */
+
+	"EH_INST",	"EH_GRP ",	"EH_LOCN",	"EH_DYN ",
+	"EH_ANRS",	"EH_TRNS",	"EH_INTP",	"EH_TMPO",
+	"EH_TUNE",	"EH_ASGN",	"EH_SBGN",	"EH_SEND"
+};
+
+char	*var_lbl[6] = {		/* variable names */
+
+	"Pch/Hor",	"Mod/Vrt",	"Brth/LP",	"GPC/CV1",
+	"Pedal 1",	"Key Prs"
+};
+
+char	*srcname[] = {		/* source names (must match smdefs.h) */
+
+	"NONE",	"RAND",	"CTL1",	"?03?",	"?04?",	"PTCH",	"KPRS",	"KVEL",
+	"PED1",	"?09?",	"FREQ",	"HTPW",	"VTMW",	"LPBR"
+};
+
+char	*actname[] = {		/* function action names */
+
+	"NULL",	"SUST",	"ENBL",	"JUMP",	"LOOP",	"KYUP",	"KYDN",	"HERE"
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ev_kind(sep) -- returns a pointer to a string describing the event
+	at 'sep', or a NULL pointer if the event is unrecognized.
+	Sets x_unrec according to the result.
+   =============================================================================
+*/
+
+char *
+ev_kind(sep)
+struct s_entry *sep;
+{
+	if ((sep->e_type & 0x00FF) GE N_ETYPES) {
+
+		x_unrec = TRUE;
+		return(NULL);
+	}
+
+	x_unrec = FALSE;
+
+	return(evkinds[sep->e_type]);
+}
+
+/* 
+
+*/
+
+/* 
+   =============================================================================
+	SEctrl() -- print current score pointers and times
+   =============================================================================
+*/
+
+SEctrl()
+{
+	printf("curscor: %d  \"%-16.16s\"  cursect: %d  scp: $%08lX\n\n",
+		curscor, scname[curscor], cursect, scp);
+
+
+	printf("   fc_val: %8ld  fc_sw:  %d\n\n",
+		fc_val, fc_sw);
+
+
+	printf("   t_bak:  %8ld  t_cur:  %8ld  t_ctr:  %8ld  t_fwd:  %8ld\n",
+		t_bak, t_cur, t_ctr, t_fwd);
+
+	printf("   p_bak: $%08lX  p_cur: $%08lX  p_ctr: $%08lX  p_fwd: $%08lX\n\n",
+		p_bak, p_cur, p_ctr, p_fwd);
+
+}
+
+/*
+   =============================================================================
+	SEsnap() -- snap dump critical score storage variables
+   =============================================================================
+*/
+
+SEsnap()
+{
+	register short i, j;
+
+	printf("\n");
+
+	printf("evleft: %ld  spcount: %ld  frags: %ld\n",
+		evleft(), spcount, frags);
+
+	printf("   se1_cnt=%ld  se2_cnt=%ld  se3_cnt=%ld\n",
+		se1_cnt, se2_cnt, se3_cnt);
+
+	printf("   pspool=$%08lX  size1=$%08lX  size2=$%08lX  size3=$%08lX\n",
+		pspool, size1, size2, size3);
+
+	SEctrl();
+
+	for (i = 0; i < N_SCORES; i++)
+		printf("%2d:  \"%-16.16s\"  $%08lX %s\n",
+			i + 1, scname[i], scores[i],
+			(i EQ curscor) ? "<--- curscor" : "");
+
+	printf("\n\n");
+
+	printf("Variable modes for each group:\n\n");
+
+	printf("V# VarName  01 02 03 04 05 06 07 08 09 10 11 12\n");
+	printf("-- -------  -- -- -- -- -- -- -- -- -- -- -- --\n");
+
+	for (i = 0; i < 6; i++) {
+
+		printf("%02d %s  ", i, var_lbl[i]);
+
+		for (j = 0; j < 12; j++)
+			printf(" %d ", varmode[i][j]);
+
+		printf("\n");
+	}
+
+	printf("\n");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SEdump(sep) -- dumps the event at 'sep' in readable format.
+	Returns 'sep'.  Sets x_unrec TRUE if the event is unrecognized,
+	FALSE if the event is recognized.
+   =============================================================================
+*/
+
+struct s_entry *
+SEdump(sep)
+struct s_entry *sep;
+{
+	char	*et;
+
+	x_unrec = TRUE;
+
+	switch (sep->e_size) {
+
+	case E_SIZE1:
+	case E_SIZE2:
+	case E_SIZE3:
+
+		break;
+
+	default:
+
+		printf("[%08lX]:  ** Bad event size: $%02.2X **\n",
+			sep, sep->e_size);
+
+		return(sep);
+	}
+
+	if (NULL EQ (et = ev_kind(sep))) {
+
+		printf("[%08lX]:  ** Bad event type: $%02.2X **\n",
+			sep, sep->e_type);
+
+		return(sep);
+	}
+
+	x_unrec = FALSE;
+
+	printf("$%08lX: t=%10ld  F:$%08lX  B:$%08lX * %s\n",
+		sep, sep->e_time, sep->e_fwd, sep->e_bak, et);
+
+	printf("  data = $%02.2X $%02.2X",
+		0x00FF & sep->e_data1, 0x00FF & sep->e_data2);
+
+	if (sep->e_size EQ E_SIZE1)
+	    	printf(" $%04.4X $%04.4X",
+			(struct n_entry *)sep->e_vel,
+			(struct n_entry *)sep->e_data4);
+
+	printf("\n");
+
+	if (sep->e_size GT E_SIZE1)
+		printf("  up: $%08lX  dn: $%08lX",
+			sep->e_up, sep->e_dn);
+	else
+		return(sep);
+
+	if (sep->e_size GT E_SIZE2)
+		printf("  lft: $%08lX  rgt: $%08lX",
+			sep->e_lft, sep->e_rgt);
+
+	printf("\n");
+
+	return(sep);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SEchase() -- print up to 'n' events or to the end of the score,
+	starting with event 'ep'.
+   =============================================================================
+*/
+
+struct s_entry *
+SEchase(ep, n)
+register struct s_entry *ep;
+register long n;
+{
+	register long i;
+	register struct s_entry *np;
+
+	printf("\n");
+
+	if (ep EQ E_NULL) {
+
+		printf("NULL pointer\n");
+		return(scp);
+	}
+
+	if (Pcheck(ep, "ep - SEchase()"))
+		return(scp);
+
+	for (i = 0; i < n; i++) {
+
+		SEdump(ep);
+
+		if ((ep->e_type EQ EV_FINI) OR x_unrec)
+			return(scp);
+
+		np = ep->e_fwd;
+
+		if (Pcheck(np, "e_fwd - SEchase()"))
+			return(scp);
+
+		if (Pcheck(ep->e_bak, "e_bak - SEchase()"))
+			return(scp);
+
+		ep = np;
+	}
+
+	printf("\n");
+
+	return(ep);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SLdump() -- print slice control data
+   =============================================================================
+*/
+
+SLdump()
+{
+	register short i;
+	register struct gdsel *gp;
+
+	printf("\n");
+
+	printf("sd = %s  se = %s  sbase = %d  soffset = %d  scrl = $%04.4X\n",
+		sd ? "BAK" : "FWD", se ? "BAK" : "FWD", sbase, soffset, scrl);
+
+	printf("gdfsep = $%08lX\n\n", gdfsep);
+
+	printf("gr  $ gdstbp  $ gdstbc  $ gdstbn\n");
+	printf("    %08lX  %08lX  %08lX\n", gdstbp, gdstbc, gdstbn);
+	printf("--  --------  --------  --------\n");
+
+	for (i = 0; i < NGDSEL; i++) {
+
+		printf("%2d  %08lX  %08lX  %08lX\n",
+			i + 1, gdstbp[i], gdstbc[i], gdstbn[i]);
+
+		if (i EQ 11)
+			printf("\n");
+	}
+
+	printf("\n");
+
+	if (SL_Flag EQ FALSE)
+		xtrap15();
+
+	SL_Flag = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SECdump() -- dump section variables and hplist
+   =============================================================================
+*/
+
+SECdump()
+{
+	register short i;
+
+	printf("p_sbgn = $%08lX  p_send = $%08lX\n",
+		p_sbgn, p_send);
+
+	printf("t_sbgn =  %8ld  t_send =  %8ld  t_sect =  %8ld\n\n",
+		t_sbgn, t_send, t_sect);
+
+
+	printf("p_cbgn = $%08lX  p_cend = $%08lX\n",
+		p_cbgn, p_cend);
+
+	printf("t_cbgn =  %8ld  t_cend =  %8ld\n\n",
+		t_cbgn, t_cend);
+
+
+	printf("seclist[curscor][]\n");
+	printf("------------------\n\n");
+
+	printf("Sec Addr_____  Sec Addr_____  Sec Addr_____  Sec Addr_____  Sec Addr_____  \n");
+
+	for (i = 0; i < N_SECTS; i += 5) {
+
+		printf("%2d  $%08lX  ", i + 1, seclist[curscor][i]);
+
+		if ((i + 1) < N_SECTS)
+			printf("%2d  $%08lX  ", i + 2, seclist[curscor][i + 1]);
+
+		if ((i + 2) < N_SECTS)
+			printf("%2d  $%08lX  ", i + 3, seclist[curscor][i + 2]);
+
+		if ((i + 3) < N_SECTS)
+			printf("%2d  $%08lX  ", i + 4, seclist[curscor][i + 3]);
+
+		if ((i + 4) < N_SECTS)
+			printf("%2d  $%08lX  ", i + 5, seclist[curscor][i + 4]);
+
+		printf("\n");
+	}
+
+	printf("\n");
+
+	printf("hplist[curscor][]\n");
+	printf("-----------------\n");
+	printf("Type___  Addr_____\n");
+
+	for (i = 0; i < N_TYPES; i++)
+		printf("%s  $%08lX\n", hpname[i], hplist[curscor][i]);
+
+	printf("\n");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	DOA() -- do a simple stack traceback
+   =============================================================================
+*/
+
+DOA()
+{
+	register long *olda6, *cura6;
+	register short n, *prptr;
+
+	if (A6PTR AND A7PTR) {
+
+		printf("Stack dump:  $%08lX to $%08lX\n\n", A7PTR, A7TOP);
+		mdump(A7PTR, A7TOP, A7PTR);
+		printf("\n\n");
+		printf("Stack traceback:  from A6 = $%08lX\n\n", A6PTR);
+		printf("A6          Old A6    Return\n");
+
+	} else {
+
+		printf("Set A6PTR ($%08lX) and A7PTR ($%08lX) first\n",
+			&A6PTR, &A7PTR);
+
+		xtrap15();
+	}
+
+	cura6 = A6PTR;
+
+	while (cura6) {
+
+		olda6 = *cura6;
+
+		printf("$%08lX:  $%08lX  $%08lX\n",
+			cura6, olda6, *(cura6 + 4L));
+
+		prptr = cura6 + 8L;
+		n = 8;
+
+		while (prptr < olda6) {
+
+			printf("  +%-4d [$%08lX]:  $%04.4X\n",
+				n, prptr, *prptr);
+
+			n += 2;
+			++prptr;
+		}
+
+		cura6 = olda6;
+	}
+
+	xtrap15();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SCPanic() -- print the score control variables
+   =============================================================================
+*/
+
+SCPanic()
+{
+	SEsnap();		/* control data */
+	xtrap15();
+}
+
+/*
+   =============================================================================
+	SCdump() -- print the score control variables and the current score
+   =============================================================================
+*/
+
+SCdump()
+{
+	SEsnap();		/* control data */
+	SECdump();		/* section variables */
+	SEchase(scp, SCdlim);	/* current score */
+	xtrap15();
+}
+
+/*
+   =============================================================================
+	SCcrash() -- print all of the score related data and the current score
+   =============================================================================
+*/
+
+SCcrash()
+{
+	SL_Flag = TRUE;
+	SLdump();		/* slice data */
+	SCdump();		/* control data and current score */
+}
+
+/*
+   =============================================================================
+	SCtimes() -- print the score times and pointers
+   =============================================================================
+*/
+
+SCtimes()
+{
+	SEctrl();
+	xtrap15();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SCslice() -- print details of the slices
+   =============================================================================
+*/
+
+SCslice()
+{
+	register short i, s;
+	register struct gdsel *gp;
+
+	/* print details of gdstbp */
+
+	s = FALSE;
+
+	for (i = 0; i < NGDSEL; i++) {
+
+		if ((struct gdsel *)NULL NE (gp = gdstbp[i])) {
+
+			if (NOT s) {
+
+				printf("gdstbp:");
+				s = TRUE;
+			}
+
+			while (gp) {
+
+				printf("  %02d:%02d:%d",
+					i + 1, gp->note, gp->code);
+
+				gp = gp->next;
+			}
+		}
+	}
+
+	if (s)
+		printf("\n");
+
+/* 
+
+*/
+	/* print details of gdstbc */
+
+	s = FALSE;
+
+	for (i = 0; i < NGDSEL; i++) {
+
+		if ((struct gdsel *)NULL NE (gp = gdstbc[i])) {
+
+			if (NOT s) {
+
+				printf("gdstbc:");
+				s = TRUE;
+			}
+
+			while (gp) {
+
+				printf("  %02d:%02d:%d",
+					i + 1, gp->note, gp->code);
+
+				gp = gp->next;
+			}
+		}
+	}
+
+	if (s)
+		printf("\n");
+/* 
+
+*/
+	/* print details of gdstbn */
+
+	s = FALSE;
+
+	for (i = 0; i < NGDSEL; i++) {
+
+		if ((struct gdsel *)NULL NE (gp = gdstbn[i])) {
+
+			if (NOT s) {
+
+				printf("gdstbn:");
+				s = TRUE;
+			}
+
+			while (gp) {
+
+				printf("  %02d:%02d:%d",
+					i + 1, gp->note, gp->code);
+
+				gp = gp->next;
+			}
+		}
+	}
+
+	if (s)
+		printf("\n");
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SCvce() -- dump voice buffer instrument definition
+   =============================================================================
+*/
+
+SCvce(n)
+{
+	register short i, j, pif, pt1;
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+	register struct instpnt *pp;
+
+	ip = &vbufs[n];
+
+	/* dump instrument header */
+
+	printf("VOICE %2d:  %-16.16s  %-16.16s %-16.16s %-16.16s\n",
+		(1 + n), ip->idhname, ip->idhcom1, ip->idhcom2, ip->idhcom3);
+
+	printf("  flag=%04.4X  Cfg=%d  #plft=%d  WsA=%d  WsB=%d\n",
+		ip->idhflag, (0x00FF & ip->idhcfg), (0x00FF & ip->idhplft),
+		(1 + (0x00FF & ip->idhwsa)), (1 + (0x00FF & ip->idhwsb)));
+
+	printf("  Osc 1:%s %c %04.4X  2:%s %c %04.4X  3:%s %c %04.4X  4:%s %c %04.4X\n",
+		osclbl[ip->idhos1c & OC_MOD],
+		((ip->idhos1c & OC_SYN) ? 'S' : ' '),
+		ip->idhos1v,
+		osclbl[ip->idhos2c & OC_MOD],
+		((ip->idhos2c & OC_SYN) ? 'S' : ' '),
+		ip->idhos2v,
+		osclbl[ip->idhos3c & OC_MOD],
+		((ip->idhos3c & OC_SYN) ? 'S' : ' '),
+		ip->idhos3v,
+		osclbl[ip->idhos4c & OC_MOD],
+		((ip->idhos4c & OC_SYN) ? 'S' : ' '),
+		ip->idhos4v);
+
+	/* dump function headers */
+
+	printf("\nFunction headers\n");
+
+	printf("  Fn Pch  Mult Sr Pif Pt1 Cpt Md Pr Trg \n");
+	printf("  -- ---- ---- -- --- --- --- -- -- ----\n");
+
+	for (i = 0; i < NFINST; i++) {
+
+		fp = &ip->idhfnc[i];
+
+		printf("  %2d %04.4X %04.4X %02X %3d %3d %3d %02x %02x %04.4x  %s\n",
+			i, fp->idfpch, fp->idfmlt, (0x00FF & fp->idfsrc),
+			(0x00FF & fp->idfpif), (0x00FF & fp->idfpt1),
+			(0x00FF & fp->idfcpt), (0x00FF & fp->idftmd),
+			(0x00FF & fp->idfprm), fp->idftrg, idbxlbl[i]);
+
+	}
+
+	/* dump occupied points for each function */
+
+	printf("\nOccupied points\n");
+	printf("  Fn Fpt Ipt Time Val  Mult Src  Act  P1 P2 P3 Pd\n");
+	printf("  -- --- --- ---- ---- ---- ---- ---- -- -- -- --\n");
+
+	for (i = 0; i < NFINST; i++) {
+	
+		fp  = &ip->idhfnc[i];
+		pif = 0x00FF & fp->idfpif;
+		pt1 = 0x00FF & fp->idfpt1;
+
+		for (j = 0; j < pif; j++) {
+
+			pp  = &ip->idhpnt[pt1 + j];
+
+			printf("  %2d %3d %3d %04.4X %04.4X %04.4X %4s %4s %2X %2X %2X %2X\n",
+				i, j, (pt1 + j), pp->iptim, pp->ipval, pp->ipvmlt,
+				srcname[0x00FF & pp->ipvsrc],
+				actname[0x00FF & pp->ipact],
+				(0x00FF & pp->ippar1), (0x00FF & pp->ippar2),
+				(0x00FF & pp->ippar3), (0x00FF & pp->ippad));
+		}
+	}
+
+	printf("\n");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SCvces() -- dump voice buffer instrument definitions
+   =============================================================================
+*/
+
+SCvces()
+{
+	register short i;
+
+	for (i = 0; i < 12; i++)
+		SCvce(i);
+
+	xtrap15();
+}
+
+/*
+   =============================================================================
+	SCvoice() -- dump voice buffer instrument definition
+   =============================================================================
+*/
+
+SCvoice()
+{
+	SCvce(SCnumv);
+	xtrap15();
+}
Index: ram/seexec.s
===================================================================
--- ram/seexec.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/seexec.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,522 @@
+* ------------------------------------------------------------------------------
+* seexec.s -- score event execution driver
+* Version 40 -- 1988-10-06 -- D.N. Lynx Crowe
+*
+*	struct s_entry *
+*	se_exec(ep, sd)
+*	struct s_entry *ep;
+*	short sd;
+*
+*		Executes the event at 'ep', scrolling in direction 'sd'.
+*
+* ------------------------------------------------------------------------------
+		.text
+*
+		.xdef	_se_exec
+*
+		.xdef	BadEvnt
+*
+		.xdef	_xevent
+*
+		.xref	_asgvce
+		.xref	_clkset
+		.xref	_getasg
+		.xref	_gettun
+		.xref	_procpfl
+		.xref	_selscor
+		.xref	_setdyn
+		.xref	_setloc
+		.xref	_setsv
+		.xref	_settmpo
+		.xref	_settune
+		.xref	_setv2gi
+*
+		.xref	_anrs
+		.xref	_var2src
+		.xref	_curasg
+		.xref	_curintp
+		.xref	_cursect
+		.xref	_grpmode
+		.xref	_grpstat
+		.xref	_ins2grp
+		.xref	_nxtflag
+		.xref	_recsw
+		.xref	_s_trns
+		.xref	_trgtab
+		.xref	_varmode
+		.xref	_vce2grp
+		.xref	_vce2trg
+		.xref	_veltab
+*
+		.page
+*
+* parameter offsets
+* -----------------
+P_EP		.equ	8		* WORD - 'ep' parameter offset
+P_SD		.equ	12		* WORD - 'sd' parameter offset
+*
+* event structure offsets -- MUST match score.h definitions
+* -----------------------    ------------------------------
+*		      offset		 length
+*		      ------             ------
+E_TIME		.equ	0		* LONG
+E_SIZE		.equ	4		* BYTE
+E_TYPE		.equ	5		* BYTE
+E_DATA1		.equ	6		* BYTE
+E_NOTE		.equ	6		* BYTE
+E_DATA2		.equ	7		* BYTE
+E_GROUP		.equ	7		* BYTE
+E_BAK		.equ	8		* LONG
+E_FWD		.equ	12		* LONG
+E_DN		.equ	16		* LONG
+E_VEL		.equ	16		* WORD
+E_DATA4		.equ	18		* WORD
+E_UP		.equ	20		* LONG
+E_LFT		.equ	24		* LONG
+E_RGT		.equ	28		* LONG
+*
+* Miscellaneous constants
+* -----------------------
+N_ETYPES	.equ	25		* number of event types
+*
+M_KSTATE	.equ	$01		* keys status bit
+N_KSTATE	.equ	$FE		* keys status bit complement
+*
+D_BAK		.equ	1		* code for backward scrolling
+*
+LCL_PRT		.equ	2		* 0-origin local port number
+LCL_PCH		.equ	$1080		* port and channel for trigger
+*
+		.page
+*
+* A few words about se_exec:
+*
+* se_exec has to be very fast, so it's written in assembly language,
+* rather than C, which is usually pretty good, but not quite good enough
+* for this application.  The faster this routine runs, the higher the
+* tempo we can keep up with.  If this code is fast enough, we end up
+* hardware limited by the timer.
+*
+_se_exec:	link	a6,#0			* link stack frames
+		movea.l	P_EP(a6),a0		* get event pointer 'ep' into a0
+		move.l	a0,_xevent		* save in xevent
+		move.b	E_TYPE(a0),d1		* get event type into d1.W
+		andi.w	#$007F,d1		* ... and mask off new-data flag
+		cmp.b	#N_ETYPES,d1		* see if it's valid
+		blt	sexc1			* jump if it is
+*
+BadEvnt:	move.l	a0,d0			* setup to return pointer we got
+		bra	done			* exit
+*
+exexit:		movea.l	_xevent,a0		* point at next event
+		move.l	E_FWD(a0),d0		* ...
+*
+done:		unlk	a6			* done -- unlink stack frames
+		rts				* return to caller
+*
+sexc1:		lea	sextab,a1		* get base of dispatch table
+		lsl.w	#2,d1			* multiplty event by 4 for index
+		movea.l	0(a1,d1.W),a2		* get address of event routine
+		jmp	(a2)			* jump to event execution routine
+*
+* On entry, the individual execution routines only depend on a0 pointing at the
+* event they were dispatched for.
+*
+* The usual C function register usage conventions apply:
+*
+* d0..d2 and a0..a2 are used for scratch, and are not preserved.
+*
+* d3..d6 and a3..a5 are register variables, and are preserved.
+* a6 = frame pointer, a7 = stack pointer, and are preserved.
+*
+		.page
+*
+* exnbeg -- execute note begin
+* ------    ------------------
+* If things need to be sped up, we could incorporate the functions of
+* asgvce() here, rather than calling it.  asgvce() could also be re-written in
+* assembly language to make it a shade faster.
+*
+exnbeg:		cmpi.w	#D_BAK,P_SD(a6)		* check direction
+		beq	nendex			* if backward, treat as note end
+*
+nbegex:		clr.w	d1			* clear d1
+		move.b	E_GROUP(a0),d1		* get group number
+		add.w	d1,d1			* ... * 2
+		lea	_grpstat,a1		* point at grpstat
+		tst.w	0(a1,d1.W)		* see if group is enabled
+		beq	exexit			* done if not
+*
+		move.b	E_NOTE(a0),d1		* d1 = note number nn (0..127)
+		move.w	#LCL_PCH,d2		* put port and channel in d2
+		add.w	d1,d2			* d2 = trg 
+		lea	_trgtab,a1		* point at trgtab[trg]
+		move.b	0(a1,d2.W),d0		* ...
+		or.b	#M_KSTATE,d0		* set trigger table entry on
+		move.b	d0,0(a1,d2.W)		* ...
+		lea	_veltab,a1		* point at veltab
+		add.w	d2,d2			* ...
+		move.w	E_VEL(a0),0(a1,d2.W)	* put velocity in veltab
+		move.w	E_VEL(a0),-(a7)		* put velocity on the stack
+		move.w	d1,-(a7)		* put note number on the stack
+		move.w	#1,-(a7)		* put channel on the stack
+		move.w	#LCL_PRT,-(a7)		* put port on the stack
+		move.b	E_GROUP(a0),d1		* d1 = group number  (0..11)
+		move.w	d1,-(a7)		* put group number on the stack
+		jsr	_asgvce			* start the note
+		add.l	#10,a7			* clean up the stack		
+		bra	exexit			* done
+*
+		.page
+*
+* exnend -- execute note end
+* ------    ----------------
+* If things need to be sped up, we could incorporate the functions of
+* procpfl() here, rather than calling it.  procpfl() could also be re-written in
+* assembly language to make it a shade faster.
+*
+exnend:		cmpi.w	#D_BAK,P_SD(a6)		* check direction
+		beq	nbegex			* if backward, treat as beginning
+*
+nendex:		clr.w	d1			* clear d1
+		move.b	E_GROUP(a0),d1		* get group number
+		add.w	d1,d1			* ... * 2
+		lea	_grpstat,a1		* point at grpstat
+		tst.w	0(a1,d1.W)		* check group status
+		beq	exexit			* done if disabled
+*
+		move.b	E_NOTE(a0),d1		* d1 = note number nn (0..127)
+		move.w	#LCL_PCH,d2		* put port and channel in d2
+		add.w	d1,d2			* d2 = trg * 2
+		add.w	d2,d2			* ...
+		lea	_trgtab,a1		* set trigger table entry off
+		move.b	0(a1,d2.W),d0		* ...
+		and.b	#N_KSTATE,d0		* ...
+		move.b	d0,0(a1,d2.W)		* ...
+		bne	exexit			* done if note still active
+*
+		.page
+*
+		lsr.w	#1,d2			* adjust d2
+		clr.w	d1			* set loop index
+		lea	_vce2trg,a2		* point at vce2trg table
+*
+exnend1:	cmp.w	(a2),d2			* see if this voice uses trg
+		bne	exnend2			* jump if not
+*
+		move.w	#-1,(a2)		* set entry to -1
+		move.l	a2,-(a7)		* save a2 on stack
+		move.w	d1,-(a7)		* save d1 on stack
+		move.w	d2,-(a7)		* save d2 on stack
+		lea	_vce2grp,a1		* put group on stack
+		move.w	d1,d0			* ...
+		add.w	d0,d0			* ...
+		move.w	0(a1,d0.W),-(a7)	* ...
+		move.w	d2,-(a7)		* put trg on stack
+		jsr	_procpfl		* process sustained voices
+		addq.l	#4,a7			* clean up stack
+		move.w	(a7)+,d2		* restore d2
+		move.w	(a7)+,d1		* restore d1
+		movea.l	(a7)+,a2		* restore a2
+*
+exnend2:	addq.l	#2,a2			* point at next vce2trg entry
+		addq.w	#1,d1			* loop until all are checked
+		cmp.w	#12,d1			* ...
+		bne	exnend1			* ...
+*
+		bra	exexit			* done
+*
+		.page
+*
+* exsbgn -- execute section begin
+* ------    ---------------------
+exsbgn:		clr.w	d0			* get section number
+		move.b	E_DATA1(a0),d0		* ...
+		move.w	d0,_cursect		* set section number
+		bra	exexit			* done
+*
+* exasgn -- execute assignment event
+* ------    ------------------------
+exasgn:		clr.w	d0			* get assignment
+		move.b	E_DATA1(a0),d0		* ...
+		move.w	d0,-(a7)		* getasg(curasg = asgn)
+		move.w	d0,_curasg		* ...
+		jsr	_getasg			* ...
+		tst.w	(a7)+			* ...
+		bra	exexit			* done
+*
+* extune -- execute tuning event
+* ------    --------------------
+extune:		clr.w	d0			* get tuning
+		move.b	E_DATA1(a0),d0		* ...
+		move.w	d0,-(a7)		* gettun(tuning)
+		jsr	_gettun			* ...
+		tst.w	(a7)+			* ...
+		bra	exexit			* done
+*
+* extrns -- execute transposition event
+* ------    ---------------------------
+extrns:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ...
+		add.w	d0,d0			* ... as an index in d0
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	exexit			* done if disabled
+*
+		lea	_s_trns,a1		* set group transposition
+		move.w	E_LFT(a0),0(a1,d0.W)	* ...
+		jsr	_settune		* ...
+		bra 	exexit			* done
+*
+		.page
+*
+* extmpo -- execute tempo event
+* ------    -------------------
+extmpo:		clr.w	d0			* get tempo
+		move.b	E_DATA1(a0),d0		* ...
+		move.w	d0,-(a7)		* settmpo(tempo)
+		jsr	_settmpo		* ...
+		tst.w	(a7)+			* ...
+		bra	exexit			* done
+*
+* exstop -- execute stop event
+* ------    ------------------
+exstop:		clr.w	-(a7)			* stop the clock
+		jsr	_clkset			* ...
+		tst.w	(a7)+			* ...
+		bra	exexit			* that's all, folks
+*
+* exintp -- execute interpolate event
+* ------    -------------------------
+exintp:		move.w	E_DATA1(a0),_curintp	* set interpolate value
+		bra	exexit			* done
+*
+		.page
+*
+* exinst -- execute instrument change event
+* ------    -------------------------------
+exinst:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	exexit			* done if not enabled
+*
+		lea	_ins2grp,a1		* point at ins2grp[]
+		clr.w	d0			* get instrument number
+		move.b	E_DATA2(a0),d0		* ... in d0
+		clr.w	d1			* get group number
+		move.b	E_DATA1(a0),d1		* ... in d1
+		move.w	d1,-(a7)		* put group number on stack
+		add.w	d1,d1			* make d1 a word pointer
+		move.w	0(a1,d1.W),d2		* get ins2grp[group]
+		and.w	#$FF00,d2		* mask off GTAG1..GTAG8
+		or.w	d0,d2			* OR in new instrument number
+		move.w	d2,0(a1,d1.W)		* set ins2grp[group]
+		jsr	_setv2gi		* setv2gi(group)
+		tst.w	(a7)+			* clean up stack
+		bra	exexit			* done
+*
+		.page
+*
+* exdyn -- execute dynamics event
+* -----    ----------------------
+exdyn:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	exexit			* done if not enabled
+*
+		clr.w	d0			* get dynamics
+		move.b	E_DATA2(a0),d0		* ... in d0
+		clr.w	d1			* get group number
+		move.b	E_DATA1(a0),d1		* ... in d1
+		move.w	d0,-(a7)		* setdyn(group, dyn)
+		move.w	d1,-(a7)		* ...
+		jsr	_setdyn			* ...
+		adda.l	#4,a7			* clean up stack
+		bra	exexit			* done
+*
+* exlocn -- execute location event
+* ------    ----------------------
+exlocn:		clr.w	d0			* get group number
+		move.b	E_DATA1(a0),d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	exexit			* done if not enabled
+*
+		clr.w	d0			* get location
+		move.b	E_DATA2(a0),d0		* ... in d0
+		clr.w	d1			* get group number
+		move.b	E_DATA1(a0),d1		* ... in d1
+		move.w	d0,-(a7)		* setloc(group, loc)
+		move.w	d1,-(a7)		* ...
+		jsr	_setloc			* ...
+		adda.l	#4,a7			* clean up stack
+		bra	exexit			* done
+*
+		.page
+*
+* exanrs -- execute analog resolution event
+* ------    -------------------------------
+exanrs:		move.b	E_DATA1(a0),d0		* get group number
+		andi.w	#$000F,d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	exexit			* done if not enabled
+*
+		clr.w	d1			* get variable / group numbers
+		move.b	E_DATA1(a0),d1		* ...
+		add.w	d1,d1			* convert to word index
+		clr.w	d0			* get resolution
+		move.b	E_DATA2(a0),d0		* ... in d0
+		lea	_anrs,a1		* point at resolution table base
+		move.w	d0,0(a1,d1.W)		* save resolution in table
+		bra	exexit			* done
+*
+* exanvl -- execute analog value event
+* ------    --------------------------
+exanvl:		move.b	E_DATA1(a0),d0		* get group number
+		andi.w	#$000F,d0		* ... in d0
+		add.w	d0,d0			* ... as a word offset
+		lea	_grpstat,a1		* check grpstat[grp]
+		tst.w	0(a1,d0.W)		* ...
+		beq	exexit			* done if not enabled
+*
+		move.w	E_DN(a0),-(a7)		* put value on stack
+		clr.w	d2			* get variable / group numbers
+		move.b	E_DATA1(a0),d2		* ... into d2
+		move.w	d2,d1			* extract group number
+		andi.w	#$000F,d1		* ... into d1
+		lsr.w	#3,d2			* extract variable number
+		andi.w	#$001E,d2		* ... as a word index in d2
+		lea	_var2src,a1		* point at variable map
+		move.w	0(a1,d2.W),-(a7)	* put source number on stack
+		move.w	d1,-(a7)		* put group number on stack
+		jsr	_setsv			* setsv(group, src, val)
+		adda.l	#6,a7			* clean up stack
+		bra	exexit			* done
+*
+* exnext -- next score
+* ------    ----------
+exnext:		move.w	#1,_nxtflag		* set next score flag
+		bra	exexit			* done
+*
+		.page
+*
+* expnch -- execute punch in/out
+* ------    --------------------
+expnch:		tst.w	_recsw			* recording ?
+		beq	exexit			* ignore if not
+*
+		tst.w	E_DATA1(a0)		* punch in ?
+		bne	expnch5			* jump if so
+*
+* punch out
+* 
+		lea	_grpmode,a1		* setup for group modes
+		move.w	#11,d0			* ...
+*
+expnch0:	cmpi.w	#2,(a1)			* in record mode ?
+		bne	expnch1			* jump if not
+*
+		clr.w	(a1)			* set to play mode
+*
+expnch1:	addq.l	#2,a1			* point at next entry
+		dbra	d0,expnch0		* loop through all groups
+*
+		lea	_varmode,a1		* setup for variable modes
+		move.w	#5,d1			* set variable count
+*
+expnch4:	clr.w	d0			* clear offset
+*
+expnch2:	cmpi.w	#2,0(a1,d0.W)		* in record mode ?
+		bne	expnch3			* jump if not
+*
+		clr.w	0(a1,d0.W)		* set to play mode
+*
+expnch3:	addq.w	#2,d0			* update offset
+		cmpi.w	#24,d0			* check for final group
+		bne	expnch2			* loop through all groups
+*
+		add.l	#32,a1			* point at next variable
+		dbra	d1,expnch4		* loop through all variables
+*
+		bra	exexit
+*
+		.page
+*
+* punch in
+*
+expnch5:	lea	_grpmode,a1		* setup for group modes
+		move.w	#11,d0			* ...
+*
+expnch6:	cmpi.w	#1,(a1)			* in standby mode ?
+		bne	expnch7			* jump if not
+*
+		move.w	#2,(a1)			* set to record mode
+*
+expnch7:	addq.l	#2,a1			* point at next entry
+		dbra	d0,expnch6		* loop through all groups
+*
+		lea	_varmode,a1		* setup for variable modes
+		move.w	#5,d1			* set variable count
+*
+expnch10:	clr.w	d0			* clear offset
+*
+expnch8:	cmpi.w	#1,0(a1,d0.W)		* in standby mode ?
+		bne	expnch9			* jump if not
+*
+		move.w	#2,0(a1,d0.W)		* set to record mode
+*
+expnch9:	addq.w	#2,d0			* update offset
+		cmpi.w	#24,d0			* check for final group
+		bne	expnch8			* loop through all groups
+*
+		adda.l	#32,a1			* point at next variable
+		dbra	d1,expnch10		* loop through all variables
+*
+		bra	exexit
+*
+		.page
+*
+* sextab -- score execution dispatch table -- MUST match score.h definitions
+* ------    ----------------------------------------------------------------
+sextab:		dc.l	exexit		* 0	null
+		dc.l	exexit		* 1	score begin
+		dc.l	exsbgn		* 2	section begin
+		dc.l	exexit		* 3	section end
+		dc.l	exinst		* 4	instrument change
+		dc.l	exnbeg		* 5	note begin
+		dc.l	exnend		* 6	note end
+		dc.l	exstop		* 7	stop
+		dc.l	exintp		* 8	interpolate
+		dc.l	extmpo		* 9	tempo
+		dc.l	extune		* 10	tuning
+		dc.l	exexit		* 11	group status
+		dc.l	exlocn		* 12	location
+		dc.l	exdyn		* 13	dynamics
+		dc.l	exanvl		* 14	analog value
+		dc.l	exanrs		* 15	analog resolution
+		dc.l	exasgn		* 16	I/O assign
+		dc.l	extrns		* 17	transposition
+		dc.l	exexit		* 18	repeat
+		dc.l	expnch		* 19	punch in/out
+		dc.l	exexit		* 20	-unused- (polyphonic pressure)
+		dc.l	exexit		* 21	score end
+		dc.l	exexit		* 22	-unused- (channel pressure)
+		dc.l	exexit		* 23	bar marker
+		dc.l	exnext		* 24	next score
+*
+		.bss
+*
+* Variable storage areas
+* ----------------------
+* globals:
+* --------
+_xevent:	ds.l	1		* next event pointer
+*
+		.end
Index: ram/select.c
===================================================================
--- ram/select.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/select.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,128 @@
+/*
+   =============================================================================
+	select.c -- field selection processing
+	Version 9 -- 1988-12-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugsf = 1;;
+#endif
+
+extern	short	cxval, cyval, astat;
+
+extern	short	cursbox;		/* currently selected box */
+extern	short	hitbox;			/* box we just hit */
+extern	short	hitcx, hitcy;		/* x,y of cursor when we hit the box */
+
+extern	struct	selbox	*csbp;		/* current select box table pointer */
+extern	struct	selbox	*curboxp;	/* current select box pointer */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	whatbox() -- determine which selection box a hit occured in
+   =============================================================================
+*/
+
+short
+whatbox()
+{
+	register struct selbox *sb;
+
+	sb = csbp;
+	hitbox = -1;
+
+#if	DEBUGIT
+	if (debugsw AND debugsf)
+		printf("whatbox():  ENTRY  cxval=%d  cyval=%d  cursbox=%d  csbp=$%lX\n",
+			cxval, cyval, cursbox, csbp);
+#endif
+
+	if (0L EQ sb)
+		return(FALSE);
+
+	while (sb->boxhit) {
+
+		hitbox++;
+
+		if ((cxval GE sb->sbxmin) AND
+		    (cxval LE sb->sbxmax) AND
+		    (cyval GE sb->sbymin) AND
+		    (cyval LE sb->sbymax)) {
+
+			hitcx = cxval;
+			hitcy = cyval;
+			curboxp = sb;
+
+#if	DEBUGIT
+	if (debugsw AND debugsf)
+		printf("whatbox():  HIT  hitbox=%d, curboxp=$%lX, sbarg=$%04.4X\n",
+			hitbox, curboxp, sb->sbarg);
+#endif
+
+			return(TRUE);
+		}
+
+		sb++;
+	}
+
+#if	DEBUGIT
+	if (debugsw AND debugsf)
+		printf("whatbox():  FAILED\n");
+#endif
+
+	hitbox = -1;
+	return(FALSE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	select() -- standard item selection processing
+   =============================================================================
+*/
+
+select()
+{
+	if (astat) {	/* only when the E key goes down */
+
+#if	DEBUGIT
+	if (debugsw AND debugsf)
+		printf("select():  ENTRY\n");
+#endif
+
+		if (whatbox()) {	/* see if we're in a box */
+
+#if	DEBUGIT
+	if (debugsw AND debugsf)
+		printf("select():  HIT  hitbox = %d  curboxp $%lX\n",
+			hitbox, curboxp);
+#endif
+
+			(*curboxp->boxhit)(curboxp->sbarg);	/* process it */
+			cursbox = hitbox;
+
+		} else {
+
+#if	DEBUGIT
+	if (debugsw AND debugsf)
+		printf("select():  FAILED\n");
+#endif
+
+		}
+	}
+}
Index: ram/sendval.c
===================================================================
--- ram/sendval.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sendval.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,233 @@
+/*
+   =============================================================================
+	sendval.c -- MIDAS-VII -- FPU output and clear functions
+	Version 4 -- 1988-09-27 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "m7ver.h"
+#include "stddefs.h"
+#include "biosdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "fpu.h"
+#include "panel.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "score.h"
+#include "scdsp.h"
+#include "scfns.h"
+#include "wsdsp.h"
+
+/* functions defined elsewhere */
+
+extern	unsigned	tofpu();
+
+extern	int	setipl();
+
+extern	short	amplval, ext_cv1, ext_cv2, ext_cv3, ext_cv4, ext_mod;
+extern	short	lstbgnc, lstendc, ps_intn, ps_rate, ps_dpth, sliders;
+
+extern	short	lastart[];
+extern	short	dyntab[];
+extern	short	expbit[];
+extern	short	fnoff[];
+extern	short	fp_resv[];
+extern	short	grpdyn[];
+extern	short	grploc[];
+extern	short	lastvce[];
+extern	short	prstab[];
+extern	short	vce2grp[];
+extern	short	vce2trg[];
+extern	short	veltab[];
+
+extern	short	sigtab[128][2];
+
+extern	char	keystat[];
+extern	char	mpsust[];
+extern	char	trgtab[];
+
+extern	struct	n_entry	*lstbgns[NLSTENTS];
+extern	struct	n_entry	*lstends[NLSTENTS];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sendval() -- send a value to a voice parameter
+   =============================================================================
+*/
+
+sendval(voice, par, ival)
+short voice, par, ival;
+{
+	register unsigned *fpu;
+	register short oldi, val;
+	register long ltmp;
+	short nop;
+
+	fpu = io_fpu + FPU_OFNC + (voice << 8) + (par << 4);
+
+	switch (par) {
+
+	case 1:		/* freq 1 */
+	case 3:		/* freq 2 */
+	case 5:		/* freq 3 */
+	case 7:		/* freq 4 */
+
+		val = addpch(ival, 0);
+		break;
+
+	case 4:		/* location */
+
+		val = (ival << 1) ^ 0x8000;
+		break;
+
+	case 10:	/* filter */
+
+		ltmp = ((long)ival >> 1) + ((long)ival >>2);
+
+		if (ltmp GT (long)VALMAX)
+			ltmp = (long)VALMAX;
+		else if (ltmp LT (long)VALMIN)
+			ltmp = (long)VALMIN;
+
+		val = (short)ltmp;
+		break;
+/* 
+
+*/
+	case 2:		/* level */
+
+		val = (((short)ival >> 5) - 500) << 6;
+		break;
+
+	default:
+
+		val = ival;
+	}
+
+	oldi = setipl(FPU_DI);
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+	*(fpu + (long)FPU_TNV0) = val;
+	++nop;	++nop;	++nop;
+	*(fpu + (long)FPU_TNV1) = val;
+	++nop;	++nop;	++nop;
+	*(fpu + (long)FPU_TCTL) = 0x0015;
+
+	setipl(oldi);
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clearer() -- clear the FPU
+   =============================================================================
+*/
+
+clearer(stat, sig)
+short stat, sig;
+{
+	register unsigned *fpu;
+	register unsigned fpexp, fpmant, fptime;
+	register short oldi, i;
+	short nop, olds;
+
+	if (stat) {
+
+		fp_resv[0]  = 0x8300;			/* amplitude (off) */
+		fp_resv[1]  = (ps_intn * 10) << 5;	/* intensity */
+		fp_resv[2]  = (ps_rate * 10) << 5;	/* sweep rate */
+		fp_resv[3]  = (ps_dpth * 10) << 5;	/* sweep depth */
+		fp_resv[4]  = 0;			/* - unused - */
+		fp_resv[5]  = 0;			/* - unused - */
+		fp_resv[6]  = ext_cv3;			/* CV-3 */
+		fp_resv[7]  = 0;			/* - unused - */
+		fp_resv[8]  = ext_cv4;			/* CV-4 */
+		fp_resv[9]  = ext_mod;			/* Aux Signal Mod */
+		fp_resv[10] = ext_cv2;			/* CV-2 */
+		fp_resv[11] = ext_cv1;			/* CV-1 */
+
+		fpu    = io_fpu + FPU_OFNC;	/* setup to set slew rate */
+		fptime = tofpu(AMP_TIME);
+		fpexp  = expbit[fptime & 0x000F];
+		fpmant = fptime & 0xFFF0;
+/* 
+
+*/
+		oldi = setipl(FPU_DI);		/* disable FPU interrupts */
+
+/* ++++++++++++++++++++++++++++ FPU interrupts disabled +++++++++++++++++++++ */
+
+		fpuclr();			/* reset the FPU to nominal */
+
+		*(fpu + FPU_TMNT) = fpmant;	/* set amplitude slew rate */
+		++nop;	++nop;
+		*(fpu + FPU_TEXP) = fpexp;
+
+		/* reset execution control tables */
+
+		memset(trgtab,   0, NTRIGS);		/* trigger table */
+		memset(keystat,  0, 24);		/* local key status */
+
+		memsetw(prstab,  0, NTRIGS);		/* pressure table */
+		memsetw(veltab, SM_SCALE(64), NTRIGS);	/* velocity table */
+
+		clrpfl();			/* clear pendant functions */
+
+		for (i = 0; i < 48; i++)	/* sustain pedal table */
+			mpsust[i] = 0;
+
+		for (i = 0; i < 12; i++) {
+
+			vce2trg[i] = -1;	/* voice to trigger table */
+			lastvce[i] = 0;		/* last voice used table */
+		}
+
+		olds = sliders;			/* reset articulation pots */
+		sliders = LS_PRMTR;
+		l_init(1, 0);
+		sliders = LS_OTHER;
+		l_init(1, 0);
+		sliders = olds;
+
+		setipl(oldi);			/* restore interrupts */
+
+/* ++++++++++++++++++++++++++++ Interrupts restored +++++++++++++++++++++++++ */
+
+/* 
+
+*/
+		lstbgnc = 0;		/* reset last note begin count */
+		lstendc = 0;		/* reset last note end count */
+
+		memsetw(lstbgns, 0, (NLSTENTS << 1));	/* clear begin table */
+		memsetw(lstends, 0, (NLSTENTS << 1));	/* clear end table */
+
+	 	/* re-establish dynamics and locations */
+
+		for (i = 0; i < 12; i++) {
+
+			setdyn(i, grpdyn[i]);
+			setloc(i, grploc[i]);
+		}
+
+		settune();			/* set tuning */
+		sendval(0, 0, amplval);		/* set amplitude */
+	}
+}
Index: ram/serintr.s
===================================================================
--- ram/serintr.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/serintr.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,531 @@
+* ------------------------------------------------------------------------------
+* serintr.s -- MIDAS-VII serial I/O subroutines
+* Version 4 -- 1988-12-13 -- D.N. Lynx Crowe
+*
+* These subroutines replace those in bios.s in order to add support for
+* MIDAS-VII foot pedal and pulse inputs, and pulse outputs.
+*
+* WARNING:  The code below uses addresses in the bios RAM area.  These addresses
+* correspond to those in PROMS dated 1988-06-20 et seq.  If the bios is changed,
+* the addresses marked with <== may have to be changed.
+* ------------------------------------------------------------------------------
+*
+		.text
+*
+		.xdef	_setsio
+*
+		.xdef	_foot1
+		.xdef	_foot2
+		.xdef	_pulse1
+		.xdef	_pulse2
+*
+		.xdef	serintr
+*
+		.xdef	serint
+		.xdef	midint
+*
+		.xdef	wrapin
+		.xdef	wrapout
+*
+		.xdef	serput
+		.xdef	midput
+*
+		.xdef	rtschk
+*
+		.xdef	rtson
+		.xdef	rtsoff
+*
+* ==============================================================================
+*
+* The following addresses, marked by <==, are bios version dependent:
+*
+RAM		.equ	$00000400	* Beginning of system RAM area	<==
+*
+SR1IOREC	.equ	RAM+$0AB0	* Serial-1 iorec structure	<==
+SR2IOREC	.equ	RAM+$0AD8	* Serial-2 iorec structure	<==
+MC1IOREC	.equ	RAM+$0B00	* MIDI-1 iorec structure	<==
+MC2IOREC	.equ	RAM+$0B28	* MIDI-2 iorec structure	<==
+*
+* End of bios version dependent addresses.
+*
+* ==============================================================================
+*
+		.page
+*
+SERVECT		.equ	$000074		* Level 5 interrupt autovector address
+*
+IPL7		.equ	$0700		* IPL 7 value for sr
+*
+* ACIA I/O Addresses:
+* -------------------
+SR1ACIA		.equ	$3A8001		* Serial-1 ACIA base address
+SR2ACIA		.equ	$3A8009		* Serial-2 ACIA base address
+MC1ACIA		.equ	$3AC001		* MIDI-1 ACIA base address
+MC2ACIA		.equ	$3AC009		* MIDI-2 ACIA base address
+*
+* ACIA Register offsets:
+* ----------------------
+ACIA_IER	.equ	0		* ACIA IER offset
+ACIA_ISR	.equ	0		* ACIA ISR offset
+ACIA_CSR	.equ	2		* ACIA CSR offset
+ACIA_CFR	.equ	2		* ACIA CFR offset
+ACIA_TBR	.equ	4		* ACIA TBR offset
+ACIA_TDR	.equ	6		* ACIA TDR offset
+ACIA_RDR	.equ	6		* ACIA RDR offset
+*
+* iorec structure definitions:
+* ----------------------------
+IORECLN		.equ	40		* Length of an iorec structure
+*
+ibuf		.equ	0		* Input buffer base address
+ibufsize	.equ	4		* Input buffer size  (bytes)
+ibufhd		.equ	6		* Input buffer head index
+ibuftl		.equ	8		* Input buffer tail index
+ibuflow		.equ	10		* Input buffer low water mark
+ibufhi		.equ	12		* Input buffer high water mark
+obuf		.equ	14		* Output buffer base address
+obufsize	.equ	18		* Output buffer size  (bytes)
+obufhd		.equ	20		* Output buffer head index
+obuftl		.equ	22		* Output buffer tail index
+obuflow		.equ	24		* Output buffer low water mark
+obufhi		.equ	26		* Output buffer high water mark
+cfr0		.equ	28		* ACIA CFR, MS bit = 0
+cfr1		.equ	29		* ACIA CFR, MS bit = 1
+flagxon		.equ	30		* XON flag  (non-zero = XOFF sent)
+flagxoff	.equ	31		* XOFF flag  (non-zero = active)
+linedisc	.equ	32		* Line discipline flags
+erbyte		.equ	33		* Last error byte
+isr		.equ	34		* ACIA ISR on interrupt
+csr		.equ	35		* ACIA CSR on interrupt
+errct		.equ	36		* Error count  (FRM/OVR/BRK)
+ibfct		.equ	38		* Input buffer full count
+*
+		.page
+*
+* serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler
+* -------    -------------------------------------------------------------
+serintr:	movem.l	d0-d3/a0-a2,-(a7)	* Save registers
+		lea	SR1IOREC,a0		* Point at Serial-1 iorec
+		lea	SR1ACIA,a1		* Point at Serial-1 ACIA
+		movea.l	_foot1,a2		* Point at foot sw. 1 processor
+		bsr	serint			* Go process (possible) int.
+*
+		lea	SR2IOREC,a0		* Point at Serial-2 iorec
+		lea	SR2ACIA,a1		* Point at Serial-2 ACIA
+		movea.l	_foot2,a2		* Point at foot sw. 2 processor
+		bsr	serint			* Go process (possible) int.
+*
+		lea	MC1IOREC,a0		* Point at MIDI-1 iorec
+		lea	MC1ACIA,a1		* Point at MIDI-1 ACIA
+		movea.l	_pulse1,a2		* Point at pulse 1 processor
+		bsr	midint			* Go process (possible) int.
+*
+		lea	MC2IOREC,a0		* Point at MIDI-2 iorec
+		lea	MC2ACIA,a1		* Point at MIDI-2 ACIA
+		movea.l	_pulse2,a2		* Point at pulse 2 processor
+		bsr	midint			* Go process (possible) int.
+*
+		movem.l	(a7)+,d0-d3/a0-a2	* Restore registers
+		rte				* Return from exception
+*
+		.page
+*
+* serint -- Process an interrupt from Serial-1 or Serial-2
+* ------    ----------------------------------------------
+serint:		move.b	ACIA_ISR(a1),isr(a0)	* Get and save ISR
+		move.b	ACIA_CSR(a1),csr(a0)	* Get and save CSR
+*
+		btst.b	#7,isr(a0)		* Was int for this device ?
+		beq	serintx			* Jump if not
+*
+serchk:		btst.b	#1,isr(a0)		* FRM/OVR/BRK error ?
+		bne	sererr			* Jump if so
+*
+		btst.b	#0,isr(a0)		* Receiver interrupt ?
+		bne	serrx			* Jump if so
+*
+sertxq:		btst.b	#6,isr(a0)		* Transmitter interrupt ?
+		bne	sertx			* Jump if so
+*
+serctq:		btst.b	#5,isr(a0)		* CTS interrupt ?
+		bne	sercts			* Jump if so
+*
+serintx:	btst.b	#4,isr(a0)		* DCD interrupt ?
+		bne	calldcd			* Jump if so
+*
+serdone:	rts				* Return to caller
+*
+calldcd:	move.b	csr(a0),d0		* Get CSR interrupt status
+		btst.l	#4,d0			* Check DCD input  (0 = active)
+		bne	calldcd0		* Jump if line was inactive
+*
+		moveq.l	#1,d0			* Set footswitch status to TRUE
+		bra	calldcd1		* ...
+*
+calldcd0:	moveq.l	#0,d0			* Set footswitch status to FALSE
+*
+calldcd1:	move.w	d0,-(a7)		* Call the footswitch processor
+		jsr	(a2)			* ... (*footX)(status)
+		tst.w	(a7)+			* ...
+		rts				* Return to caller
+*
+		.page
+*
+* Handle serial I/O port error
+*
+sererr:		addq.w	#1,errct(a0)		* Update error count
+		move.b	ACIA_RDR(a1),erbyte(a0)	* Get error byte
+		rts				* Return to caller
+*
+*
+* Handle CTS interupt
+*
+sercts:		btst.b	#1,linedisc(a0)		* RTS/CTS mode ?
+		beq	serintx			* Ignore if not
+*
+		btst.b	#5,csr(a0)		* CTS set ?
+		beq	serintx			* Ignore if not
+*
+sercts1:	btst.b	#6,isr(a0)		* TDRE set ?
+		beq	sercts1			* Loop until it is  (!)
+*
+		move.w	obufhd(a0),d2		* Head index to d2
+		cmp.w	obuftl(a0),d2		* Compare to tail index
+		beq	serintx			* Done if buffer empty
+*
+		bsr	wrapout			* Adjust pointer for wraparound
+		move.l	obuf(a0),a2		* Get buffer base in a2
+		move.b	0(a2,d2),ACIA_TDR(a1)	* Send byte on its way
+		move.w	d2,obufhd(a0)		* Save updated head index
+		bra	serintx			* Done
+*
+		.page
+*
+* Handle receiver interrupt
+*
+serrx:		btst.b	#1,linedisc(a0)		* RTS/CTS mode set ?
+		beq	serrx1			* Jump if not
+*
+		bsr	rtsoff			* Turn off RTS
+*
+serrx1:		move.b	ACIA_RDR(a1),d0		* Read data from ACIA
+		btst.b	#1,linedisc(a0)		* RTS/CTS mode set ?
+		bne	serrx3			* Jump if so
+*
+		btst.b	#0,linedisc(a0)		* XON/XOFF mode set ?
+		beq	serrx3			* Jump if not
+*
+		cmpi.b	#$11,d0			* Is this an XON ?
+		bne	serrx2			* Jump if not
+*
+		move.b	#$00,flagxoff(a0)	* Clear flagxoff
+		bra	sertxq			* Done
+*
+serrx2:		cmpi.b	#$13,d0			* Is this an XOFF ?
+		bne	serrx3			* Jump if not
+*
+		move.b	#$FF,flagxoff(a0)	* Set flagxoff
+		bra	sertxq			* Done
+*
+serrx3:		move.w	ibuftl(a0),d1		* Get tail index in d1
+		bsr	wrapin			* Adjust for wraparound
+		cmp.w	ibufhd(a0),d1		* Head = tail ?
+		beq	seribf			* If so, we drop the character
+*
+		.page
+		move.l	ibuf(a0),a2		* Get buffer address
+		move.b	d0,0(a2,d1)		* Stash byte in buffer
+		move.w	d1,ibuftl(a0)		* Save updated tail index
+		move.w	ibuftl(a0),d2		* Tail index to d2
+		move.w	ibufhd(a0),d3		* Head index to d3
+		cmp.w	d3,d2			* Head > Tail ?
+		bhi	rsi_1			* Jump if not
+*
+		add.w	ibufsize(a0),d2		* Add buffer size to tail index
+*
+rsi_1:		sub.w	d3,d2			* Length = (adjusted)Tail - Head
+		cmp.w	ibufhi(a0),d2		* Hit high water mark ?
+		bne	serrx4			* Jump if not
+*
+		btst.b	#1,linedisc(a0)		* RTS/CTS mode set ?
+		bne	sertxq			* Done if so
+*
+		btst.b	#0,linedisc(a0)		* XON/XOFF mode set ?
+		beq	serrx4			* Jump if not
+*
+		tst.b	flagxon(a0)		* XOFF already sent ?
+		bne	serrx4			* Jump if so
+*
+		move.b	#$FF,flagxon(a0)	* Set the flag
+		move.b	#$13,d1			* Send an XOFF
+		bsr	serput			* ...
+*
+serrx4:		btst	#1,linedisc(a0)		* RTS/CTS mode set ?
+		beq	sertxq			* Done if not
+*
+		bsr	rtson			* Turn on RTS
+		bra	sertxq			* Done
+*
+		.page
+*
+* Handle transmitter interrupt
+*
+sertx:		btst.b	#1,linedisc(a0)		* RTS/CTS mode set ?
+		bne	sertx2			* If so, go check CTS
+*
+		btst.b	#0,linedisc(a0)		* XON/XOFF mode set ?
+		beq	sertx1			* Jump if not
+*
+		tst.b	flagxoff(a0)		* Check flagxoff
+		bne	serctq			* Done if set
+*
+sertx1:		move.w	obufhd(a0),d2		* Head index to d2
+		cmp.w	obuftl(a0),d2		* Compare to tail index
+		beq	serctq			* Done if buffer empty
+*
+		bsr	wrapout			* Adjust pointer for wraparound
+		move.l	obuf(a0),a2		* Get buffer base address
+		move.b	0(a2,d2),ACIA_TDR(a1)	* Send byte on its way
+		move.w	d2,obufhd(a0)		* Save updated head index
+		bra	serctq			* Done
+*
+sertx2:		btst.b	#5,csr(a0)		* CTS set in csr ?
+		beq	serctq			* If not, go check for CTS int
+*
+		bra	sertx1			* CTS was set, go transmit
+*
+seribf:		move.b	d0,erbyte(a0)		* Log dropped character
+		addq.w	#1,ibfct(a0)		* ...
+		bra	sertxq			* Go check Tx interrupt
+*
+		.page
+*
+* midint -- Process an interrupt from MIDI-1 or MIDI-2
+* ------    ------------------------------------------
+midint:		move.b	ACIA_ISR(a1),isr(a0)	* Get and save ISR
+		move.b	ACIA_CSR(a1),csr(a0)	* Get and save CSR
+*
+		btst.b	#7,isr(a0)		* Was int for this device ?
+		beq	midintx			* Jump if not
+*
+midchk:		btst.b	#1,isr(a0)		* FRM/OVR/BRK error ?
+		bne	miderr			* Jump if so
+*
+		btst.b	#0,isr(a0)		* Receiver interrupt ?
+		bne	midrx			* Jump if so
+*
+midtxq:		btst.b	#6,isr(a0)		* Transmitter interrupt ?
+		bne	midtx			* Jump if so
+*
+midintx:	btst	#4,isr(a0)		* DCD interrupt ?
+		bne	mididcd			* Jump if so
+*
+mididone:	rts				* Return to caller
+*
+mididcd:	jmp	(a2)			* Exit through the DCD processor
+*
+miderr:		addq.w	#1,errct(a0)		* Update error count
+		move.b	ACIA_RDR(a1),erbyte(a0)	* Get error byte
+		rts
+*
+* Handle receiver interrupt
+*
+midrx:		move.b	ACIA_RDR(a1),d0		* Read data from ACIA
+		move.w	ibuftl(a0),d1		* Get tail index in d1
+		bsr	wrapin			* Adjust for wraparound
+		cmp.w	ibufhd(a0),d1		* Head = tail ?
+		beq	midibf			* If so, we drop the character
+*
+		move.l	ibuf(a0),a2		* Get buffer address
+		move.b	d0,0(a2,d1)		* Stash byte in buffer
+		move.w	d1,ibuftl(a0)		* Save updated tail index
+		bra	midtxq			* Done  (go check tx int)
+*
+		.page
+*
+* Handle transmitter interrupt
+*
+midtx:		move.w	obufhd(a0),d2		* Head index to d2
+		cmp.w	obuftl(a0),d2		* Compare to tail index
+		beq	midintx			* Done if buffer empty
+*
+		bsr	wrapout			* Adjust pointer for wraparound
+		move.l	obuf(a0),a2		* Get buffer base address
+		move.b	0(a2,d2),ACIA_TDR(a1)	* Send byte on its way
+		move.w	d2,obufhd(a0)		* Save updated head index
+		bra	midintx			* Done
+*
+midibf:		move.b	d0,erbyte(a0)		* Log dropped character
+		addq.w	#1,ibfct(a0)		* ...
+		bra	midtxq			* Go check Tx interrupt
+*
+		.page
+*
+* serput -- Output a character to a serial port
+* ------    -----------------------------------
+serput:		move.w	sr,-(a7)		* Save status register
+		ori.w	#IPL7,sr		* DISABLE INTERRUPTS
+		move.b	ACIA_ISR(a1),isr(a0)	* Get ACIA isr
+		move.b	ACIA_CSR(a1),csr(a0)	* Get ACIA csr
+		btst	#0,linedisc(a0)		* XON/XOFF mode ?
+		beq	serpt_1			* Jump if not
+*
+		tst.b	flagxoff(a0)		* XON active ?
+		bne	serpt_2			* Jump if so
+*
+serpt_1:	btst.b	#6,isr(a0)		* Is ACIA still sending ?
+		beq	serpt_2			* Jump if so
+*
+		move.w	obufhd(a0),d2		* Head index to d2
+		cmp.w	obuftl(a0),d2		* Compare to tail index
+		bne	serpt_2			* Jump if buffer not empty
+*
+		move.b	d1,ACIA_TDR(a1)		* Give byte to ACIA to send
+		bra	serpt_3			* Go deal with RTS/CTS if needed
+*
+serpt_2:	move.w	obuftl(a0),d2		* Tail index to d2
+		bsr	wrapout			* Adjust for wraparound
+		cmp.w	obufhd(a0),d2		* Compare to head index
+		beq	serpt_4			* Jump if buffer full
+*
+		move.l	obuf(a0),a2		* Get buffer base address in a2
+		move.b	d1,0(a2,d2)		* Put character in buffer
+		move.w	d2,obuftl(a0)		* Update buffer tail index
+*
+serpt_3:	bsr	serchk			* Check status on our way out
+		bsr	rtschk			* Handle RTS protocol
+		move.w	(a7)+,sr		* RESTORE INTERRUPTS
+		andi	#$FFFE,sr		* Clear carry flag = OK
+		rts				* Return to caller
+*
+serpt_4:	bsr	serchk			* Check status on our way out
+		bsr	rtschk			* Handle RTS protocol
+		move.w	(a7)+,sr		* RESTORE INTERRUPTS
+		ori	#$0001,sr		* Set carry flag = buffer full
+		rts				* Return to caller
+*
+		.page
+*
+* midput -- Output to MIDI
+* ------    --------------
+midput:		move.w	sr,-(a7)		* Save status register
+		ori.w	#IPL7,sr		* DISABLE INTERRUPTS
+		move.b	ACIA_ISR(a1),isr(a0)	* Get ACIA isr
+		move.b	ACIA_CSR(a1),csr(a0)	* Get ACIA csr
+		btst.b	#6,isr(a0)		* Is ACIA still sending ?
+		beq	midpt_2			* Jump if so
+*
+		move.w	obufhd(a0),d2		* Head index to d2
+		cmp.w	obuftl(a0),d2		* Compare to tail index
+		bne	midpt_2			* Jump if buffer not empty
+*
+		move.b	d1,ACIA_TDR(a1)		* Give byte to ACIA to send
+		bra	midpt_3			* Go set final status and exit
+*
+midpt_2:	move.w	obuftl(a0),d2		* Tail index to d2
+		bsr	wrapout			* Adjust for wraparound
+		cmp.w	obufhd(a0),d2		* Compare to head index
+		beq	midpt_4			* Jump if buffer full
+*
+		move.l	obuf(a0),a2		* Get buffer base address in a2
+		move.b	d1,0(a2,d2)		* Put character in buffer
+		move.w	d2,obuftl(a0)		* Update buffer tail index
+*
+midpt_3:	bsr	midchk			* Check status on our way out
+		move.w	(a7)+,sr		* RESTORE INTERRUPTS
+		andi	#$FFFE,sr		* Clear carry flag = OK
+		rts				* Return to caller
+*
+midpt_4:	bsr	midchk			* Check status on our way out
+		move.w	(a7)+,sr		* RESTORE INTERRUPTS
+		ori	#$0001,sr		* Set carry flag = buffer full
+		rts				* Return to caller
+*
+		.page
+*
+* rtschk -- Check RTS mode and turn on RTS if it's enabled
+* ------    ----------------------------------------------
+rtschk:		btst	#1,linedisc(a0)		* RTS/CTS mode set ?
+		beq	rtsexit			* Jump to exit if not
+*
+* rtson -- Turn on RTS line
+* -----    ----------------
+rtson:		move.b	cfr1(a0),d0		* Pick up CFR1 image
+		bclr	#0,d0			* Turn on RTS line  (0 = on)
+		bra	rtscmn			* Join common RTS code below
+*
+* rtsoff -- Turn off RTS line
+* ------    -----------------
+rtsoff:		move.b	cfr1(a0),d0		* Pick up CFR1 image
+		bset	#0,d0			* Turn off RTS line  (1 = off)
+
+rtscmn:		bset	#7,d0			* Make sure MS bit is set
+		move.b	d0,cfr1(a0)		* Update CFR1 image
+		move.b	d0,ACIA_CFR(a1)		* Send CFR to hardware
+*
+rtsexit:	rts				* Return to caller
+*
+		.page
+*
+* wrapin -- Check input pointer for wraparound
+* ------    ----------------------------------
+wrapin:		add.w	#1,d1			* Head index +1
+		cmp.w	ibufsize(a0),d1		* = buffer size ?
+		bcs	wrapin1			* Jump if not
+*
+		moveq.l	#0,d1			* Wraparound
+*
+wrapin1:	rts				* Return to caller
+*
+* wrapout -- Check output pointer for wraparound
+* -------    -----------------------------------
+wrapout:	addq.w	#1,d2			* Tail index +1
+		cmp.w	obufsize(a0),d2		* = buffer size ?
+		bcs	wrapout1		* Jump if not
+*
+		moveq.l	#0,d2			* Wrap around if so
+*
+wrapout1:	rts				* Return to caller
+*
+		.page
+*
+* _setsio -- setsio() -- initialize serial I/O vectors and DCD interrupts
+* -------    ------------------------------------------------------------
+_setsio:	move.w	sr,-(a7)		* Preserve status register
+		ori.w	#$IPL7,sr		* DISABLE INTERRUPTS
+*
+		lea	nulsiox,a0		* Get null return address
+		move.l	a0,_foot1		* Initialize foot1 vector
+		move.l	a0,_foot2		* Initialize foot2 vector
+		move.l	a0,_pulse1		* Initialize pulse1 vector
+		move.l	a0,_pulse2		* Initialize pulse2 vector
+*
+		lea	SR1ACIA,a1		* Point at Serial-1 ACIA
+		move.b	#$90,ACIA_IER(a1)	* Enable DCD interrupts
+*
+		lea	SR2ACIA,a1		* Point at Serial-2 ACIA
+		move.b	#$90,ACIA_IER(a1)	* Enable DCD interrupts
+*
+		lea	MC1ACIA,a1		* Point at MIDI-1 ACIA
+		move.b	#$90,ACIA_IER(a1)	* Enable DCD interrupts
+*
+		lea	MC2ACIA,a1		* Point at MIDI-2 ACIA
+		move.b	#$90,ACIA_IER(a1)	* Enable DCD interrupts
+*
+		lea	serintr,a0		* Initialize interrupt vector
+		move.l	a0,SERVECT		* ... in processor RAM
+*
+		move.w	(a7)+,sr		* RESTORE INTERRUPTS
+*
+nulsiox:	rts				* Return to caller
+*
+		.bss
+*
+* DCD interrupt processor vectors
+* -------------------------------
+_foot1:		.ds.l	1			* short (*foot1)();
+_foot2:		.ds.l	1			* short (*foot2)();
+_pulse1:	.ds.l	1			* short (*pulse1)();
+_pulse2:	.ds.l	1			* short (*pulse2)();
+*
+		.end
Index: ram/setgc.c
===================================================================
--- ram/setgc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/setgc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,75 @@
+/*
+   =============================================================================
+	setgc.c -- set cursors and keep them in sync
+	Version 2 -- 1988-08-19 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "curpak.h"
+#include "fields.h"
+
+extern	short	infield();
+
+extern	short	cmtype;
+extern	short	cxval;
+extern	short	cyval;
+extern	short	sgcsw;
+extern	short	stccol;
+extern	short	stcrow;
+
+/*
+   =============================================================================
+	setgc() -- set graphics cursor
+   =============================================================================
+*/
+
+setgc(xv, yv)
+register short xv, yv;
+{
+	gcurpos(xv, yv);
+
+	cxval  = xv;
+	cyval  = yv;
+
+	stcrow = yv / 14;
+	stccol = xv >> 3;
+
+	sgcsw  = TRUE;
+	cmtype = CT_GRAF;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		cfetp = (struct fet *)NULL;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	settc() -- set text cursor
+   =============================================================================
+*/
+
+settc(rv, cv)
+register short rv, cv;
+{
+	itcpos(rv, cv);
+
+	stcrow = rv;
+	stccol = cv;
+
+	cyval  = rv * 14;
+	cxval  = cv << 3;
+
+	sgcsw  = FALSE;
+	cmtype = CT_TEXT;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		cfetp = (struct fet *)NULL;
+}
Index: ram/setv2gi.c
===================================================================
--- ram/setv2gi.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/setv2gi.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,59 @@
+/*
+   =============================================================================
+	setv2gi.c -- MIDAS-VII -- set the voices to the instrument for a group
+	Version 2 -- 1988-07-11 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "instdsp.h"
+
+extern	short	curinst;
+extern	short	curvce;
+
+extern	short	ins2grp[];
+extern	short	s_inst[];
+extern	short	vce2grp[];
+
+extern	struct	instdef	vbufs[];
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setv2gi() -- set voices to the instrument for a group
+   =============================================================================
+*/
+
+setv2gi(group)
+short group;
+{
+	register short grp, vce, ins;
+	register struct instdef *ip;
+	register struct idfnhdr *fp;
+
+	ins = ins2grp[group] & 0x00FF;
+	grp = group + 1;
+
+	for (vce = 0; vce < 12; vce++) {
+
+		if (vce2grp[vce] EQ grp) {	/* for each voice in the group */
+
+			if (curvce EQ vce) {
+
+				curinst = ins;
+				s_inst[curvce] = ins;
+			}
+
+			execins(vce, ins, 1);
+		}
+	}
+}
+
Index: ram/setwq.c
===================================================================
--- ram/setwq.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/setwq.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,149 @@
+/*
+   ============================================================================
+	setwq.c -- word queue functions
+	Version 1 -- 1988-11-02 -- D.N. Lynx Crowe
+   ============================================================================
+*/
+
+#define	WORDQHDR		/* so wordq.h gets it right */
+
+#include "stddefs.h"
+#include "wordq.h"
+
+/*
+   ============================================================================
+	setwq(qp, qadr, qsiz, hi, lo) -- setup a word queue
+
+		Where:
+
+			struct wordq   *qp	queue structure pointer
+			unsigned short *qadr	queue buffer pointer
+			unsigned short qsiz	maximum length of queue
+			unsigned short hi	high water mark count
+			unsigned short lo	low water mark count
+
+		Return value:
+
+			unsigned short qsiz	size of queue
+   ============================================================================
+*/
+
+unsigned short
+setwq(qp, qadr, qsiz, hi, lo)
+register struct wordq *qp;
+unsigned short *qadr;
+unsigned short qsiz, hi, lo;
+{
+	if ((unsigned short *)0L EQ qadr)
+		qsiz = 0;
+
+	qp->qbuf  = qadr;
+	qp->qsize = qsiz;
+	qp->qlen  = 0;
+	qp->qin   = 0;
+	qp->qout  = 0;
+	qp->qhi   = hi;
+	qp->qlo   = lo;
+
+	return(qsiz);
+}
+
+/* 
+
+*/
+
+/*
+   ============================================================================
+	putwq(qp, c) -- put a word in a word queue
+
+		Where:
+
+			qp	queue structure pointer
+			c	word to put in the queue
+
+		Return values:
+
+			-2	error,  queue size was 0
+			-1	queue was full,  word not added to queue
+			 0	word added to queue
+			 1	at high water mark,  word added to queue
+   ============================================================================
+*/
+
+short
+putwq(qp, c)
+register struct wordq *qp;
+register unsigned short c;
+{
+	if (0 NE qp->qsize) {				/* verify queue is ok */
+
+		if (qp->qlen EQ qp->qsize)		/* check queue length */
+			return(-1);			/* -1 = full */
+
+		qp->qbuf[qp->qin++] = c;		/* put word in queue */
+
+		if (qp->qin GE qp->qsize)		/* update input index */
+			qp->qin = 0;			/* wrap around */
+
+		if (++qp->qlen EQ qp->qhi)		/* check length again */
+			return(1);			/* 1 = at hi water */
+		else
+			return(0);			/* 0 = OK */
+
+	} else {
+
+		return(-2);				/* -2 = error */
+	}
+}
+
+/* 
+
+*/
+
+/*
+   ============================================================================
+	getwq(qp, p) -- get a word from a word queue
+
+		Where:
+
+			qp	queue structure pointer
+			p	word pointer for returned word
+
+		Return values:
+
+			-2	error,  queue size was 0
+			-1	queue was empty,  no word returned
+			 0	word returned
+			 1	at low water,  word returned
+   ============================================================================
+*/
+
+short
+getwq(qp, p)
+register struct wordq *qp;
+register unsigned short *p;
+{
+	if (0 NE qp->qsize) {				/* check queue is ok */
+
+		if (0 NE qp->qlen) {			/* check queue length */
+
+			*p = qp->qbuf[qp->qout++];	/* get word from queue */
+
+			if (qp->qout GE qp->qsize)	/* check out pointer */
+				qp->qout = 0;		/* wrap around */
+
+			if (--qp->qlen EQ qp->qlo)	/* check length again */
+				return(1);		/* 1 = at low water */
+			else
+				return(0);		/* 0 = OK */
+
+		} else {
+
+			return(-1);			/* -1 = emtpy */
+		}
+
+	} else {
+
+		return(-2);				/* -2 = error */
+	}
+}
Index: ram/showcfg.c
===================================================================
--- ram/showcfg.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/showcfg.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,673 @@
+/*
+   =============================================================================
+	showcfg.c -- display a configuration diagram
+	Version 14 -- 1988-08-26 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+#define	MAXPAT		35
+
+#include "configs.h"
+
+/* instrument display configuration box parameters */
+
+#define	LFT_EDGE	1		/* left edge of configuration box */
+#define	TOP_EDGE	238		/* top edge of configuration box */
+#define	RGT_EDGE	131		/* right edge of configuration box */
+#define	BOT_EDGE	348		/* bottom edge of configuration box */
+
+/* external functions */
+
+extern	unsigned	exp_c();
+
+extern	short		enterit();
+extern	short		idpoint();
+extern	short		nokey();
+
+extern	short		et_mcfn(), ef_mcfn(), rd_mcfn(), nd_mcfn();
+extern	short		et_mwsn(), ef_mwsn(), rd_mwsn(), nd_mwsn();
+
+/* forward references */
+
+short	imfnbox();
+
+/* 
+
+*/
+
+/* variables defined elsewhere */
+
+extern	short		(*point)();	/* point plotting function pointer */
+extern	short		(*x_key)();	/* "X" key handler pointer */
+
+extern	short		LftEdge;	/* left edge of current box */
+extern	short		TopEdge;	/* top edge of current box */
+extern	short		RgtEdge;	/* right edge of current box */
+extern	short		BotEdge;	/* bottom edge of current box */
+
+extern	short		curslim;	/* cursor changeover point */
+extern	short		curvce;		/* currently edited voice */
+extern	short		hitbox;		/* selected box number */
+extern	short		hitcx;		/* selection cursor x value */
+extern	short		hitcy;		/* selection cursor y value */
+extern	short		stccol;		/* text cursor column */
+extern	short		stcrow;		/* text cursor row */
+extern	short		wcflag;		/* ws/cf menu select flag (cf=0, ws=1) */
+extern	short		wcmcol;		/* ws/cf menu label column */
+extern	short		wcmrow;		/* ws/cf menu label row */
+extern	short		wcpage;		/* ws/cf menu page */
+extern	short		wmcsel;		/* ws slot select */
+extern	short		wmctag;		/* ws/cf display update flag */
+
+extern	unsigned	*instob;	/* instrument display object pointer */
+
+extern	struct	octent	*idoct;		/* object control table pointer */
+
+extern	struct	selbox	*csbp;		/* current box select table pointer */
+
+extern	struct	instdef	vbufs[];	/* voice buffers */
+
+extern	struct	wstbl	wslib[];	/* waveshape library */
+
+/* 
+
+*/
+
+struct	fet	id_fet2[] = {	/* waveshape number fet */
+
+	{24, 12, 13, 0x0000, et_mwsn, ef_mwsn, rd_mwsn, nd_mwsn},
+	{24, 16, 17, 0x0100, et_mwsn, ef_mwsn, rd_mwsn, nd_mwsn},
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+struct	fet	id_fet3[] = {	/* configuration number fet */
+
+	{24, 16, 17,      0, et_mcfn, ef_mcfn, rd_mcfn, nd_mcfn},
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+struct	selbox	idmbox[] = {
+
+	{  1,   1, 127, 111,      0, imfnbox},	/* slot 00 */
+	{129,   1, 255, 111,      1, imfnbox},	/* slot 01 */
+	{257,   1, 383, 111,      2, imfnbox},	/* slot 02 */
+	{385,   1, 510, 111,      3, imfnbox},	/* slot 03 */
+
+	{  1, 113, 127, 223,      4, imfnbox},	/* slot 04 */
+	{129, 113, 255, 223,      5, imfnbox},	/* slot 05 */
+	{257, 113, 383, 223,      6, imfnbox},	/* slot 06 */
+	{385, 113, 510, 223,      7, imfnbox},	/* slot 07 */
+
+	{  1, 225, 127, 334,      8, imfnbox},	/* slot 08 */
+	{129, 225, 255, 334,      9, imfnbox},	/* slot 09 */
+	{257, 225, 383, 334,     10, imfnbox},	/* slot 10 */
+	{385, 225, 510, 334,     11, imfnbox},	/* slot 11 */
+
+	{  1, 336, 510, 349,     12, imfnbox},	/* number */
+};
+
+/* 
+
+*/
+
+short	patctab[MAXPAT] = {	/* pattern colors */
+
+	0,	/* 1 */
+	0,	/* 2 */
+	0,	/* 3 */
+	0,	/* 4 */
+	0,	/* 5 */
+	0,	/* 6 */
+	12,	/* 7 */
+	12,	/* 8 */
+	12,	/* 9 */
+	12,	/* 10 */
+	0,	/* 11 */
+	0,	/* 12 */
+	0,	/* 13 */
+	0,	/* 14 */
+	13,	/* 15 */
+	8,	/* 16 */
+	0,	/* 17 */
+	0,	/* 18 */
+	2,	/* 19 */
+	2,	/* 20 */
+	2,	/* 21 */
+	2,	/* 22 */
+	2,	/* 23 */
+	2,	/* 24 */
+	2,	/* 25 */
+	2,	/* 26 */
+	0,	/* 27 */
+	0,	/* 28 */
+	0,	/* 29 */
+	0,	/* 30 */
+	0,	/* 31 */
+	0,	/* 32 */
+	0,	/* 33 */
+	0,	/* 34 */
+	4	/* 35 */
+};
+
+/* 
+
+*/
+
+short	pat[MAXPAT][16] = {		/* configuration pattern elements */
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 1 */
+	 0x0080, 0x0180, 0x0080, 0x0080,
+	 0x0080, 0x0080, 0x0080, 0x01C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 2 */
+	 0x03C0, 0x0420, 0x0020, 0x0020,
+	 0x03C0, 0x0400, 0x0400, 0x07E0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 3 */
+	 0x03C0, 0x0420, 0x0020, 0x01C0,
+	 0x0020, 0x0020, 0x0420, 0x03C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 4 */
+	 0x0040, 0x00C0, 0x0140, 0x0240,
+	 0x0440, 0x07E0, 0x0040, 0x0040,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 5 */
+	 0x03C0, 0x0200, 0x0200, 0x03C0,
+	 0x0020, 0x0020, 0x0420, 0x03C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 6 */
+	 0x03C0, 0x0400, 0x0400, 0x07C0,
+	 0x0420, 0x0420, 0x0420, 0x03C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x03C0, 0x07E0, 0x0FF0,	/* 7 */
+	 0x1FF8, 0x1FF8, 0x3FFC, 0x3FFC,
+	 0x7FFE, 0x7FFE, 0x7FFE, 0xFFFF,
+	 0xFFFF, 0xFFFF, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0xFFFF, 0xFFFF,	/* 8 */
+	 0xFFFF, 0x7FFE, 0x7FFE, 0x7FFE,
+	 0x3FFC, 0x3FFC, 0x1FF8, 0x1FF8,
+	 0x0FF0, 0x07E0, 0x03C0, 0x0000},
+
+	{0x3800, 0x3F00, 0x3FC0, 0x3FF0,	/* 9 */
+	 0x3FF8, 0x3FFC, 0x3FFE, 0x3FFE,
+	 0x3FFE, 0x3FFE, 0x3FFC, 0x3FF8,
+	 0x3FF0, 0x3FC0, 0x3F00, 0x3800},
+
+	{0x001C, 0x00FC, 0x03FC, 0x0FFC,	/* 10 */
+	 0x1FFC, 0x3FFC, 0x7FFC, 0x7FFC,
+	 0x7FFC, 0x7FFC, 0x3FFC, 0x1FFC,
+	 0x0FFC, 0x03FC, 0x00FC, 0x001C},
+/* 
+
+*/
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 11 */
+	 0x0080, 0x0180, 0x0080, 0x0000,
+	 0x0000, 0x0000, 0x0000, 0x01C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 12 */
+	 0x03C0, 0x0420, 0x0020, 0x0000,
+	 0x03C0, 0x0400, 0x0000, 0x07E0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 13 */
+	 0x03C0, 0x0420, 0x0020, 0x01C0,
+	 0x0020, 0x0000, 0x0420, 0x03C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 14 */
+	 0x0000, 0x0000, 0x0000, 0x0000,
+	 0x0000, 0x0000, 0x0000, 0x0000,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x07E0, 0x1FF8, 0x3FFC,	/* 15 */
+	 0x7FFE, 0x7FFE, 0xFFFF, 0xFFFF,
+	 0xFFFF, 0xFFFF, 0x7FFE, 0x7FFE,
+	 0x3FFC, 0x1FF8, 0x07E0, 0x0000},
+
+	{0x0000, 0x7FFE, 0x7FFE, 0x7FFE,	/* 16 */
+	 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+	 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+	 0x7FFE, 0x7FFE, 0x7FFE, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 17 */
+	 0x03C0, 0x0420, 0x0420, 0x0420,
+	 0x07E0, 0x0420, 0x0420, 0x0420,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 18 */
+	 0x07C0, 0x0220, 0x0220, 0x03C0,
+	 0x0220, 0x0220, 0x0220, 0x07C0,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 19 */
+	 0x0000, 0x0000, 0x0000, 0x007F,
+	 0x00FF, 0x01C0, 0x0180, 0x0180,
+	 0x0180, 0x0180, 0x0180, 0x0180},
+
+	{0x0180, 0x0180, 0x0180, 0x0180,	/* 20 */
+	 0x0180, 0x0180, 0x0380, 0xFF00,
+	 0xFE00, 0x0000, 0x0000, 0x0000,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+/* 
+
+*/
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 21 */
+	 0x0000, 0x0000, 0x0000, 0xFE00,
+	 0xFF00, 0x0380, 0x0180, 0x0180,
+	 0x0180, 0x0180, 0x0180, 0x0180},
+
+	{0x0180, 0x0180, 0x0180, 0x0180,	/* 22 */
+	 0x0180, 0x0180, 0x01C0, 0x00FF,
+	 0x007F, 0x0000, 0x0000, 0x0000,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 23 */
+	 0x0000, 0x0000, 0x0000, 0xFFFF,
+	 0xFFFF, 0x0000, 0x0000, 0x0000,
+	 0x0000, 0x0000, 0x0000, 0x0000},
+
+	{0x0180, 0x0180, 0x0180, 0x0180,	/* 24 */
+	 0x0180, 0x0180, 0x0180, 0x0180,
+	 0x0180, 0x0180, 0x0180, 0x0180,
+	 0x0180, 0x0180, 0x0180, 0x0180},
+
+	{0x0003, 0x0007, 0x000E, 0x001C,	/* 25 */
+	 0x0038, 0x0070, 0x00E0, 0x01C0,
+	 0x0380, 0x0700, 0x0E00, 0x1C00,
+	 0x3800, 0x7000, 0xE000, 0xC000},
+
+	{0xC000, 0xE000, 0x7000, 0x3800,	/* 26 */
+	 0x1C00, 0x0E00, 0x0700, 0x0380,
+	 0x01C0, 0x00E0, 0x0070, 0x0038,
+	 0x001C, 0x000E, 0x0007, 0x0003}
+
+	{0x0000, 0x0000, 0x0000, 0x03C0,	/* 27 */
+	 0x07E0, 0x0E70, 0x0C30, 0x0C30,
+	 0x0FF0, 0x0FF0, 0x0C30, 0x0C30,
+	 0x0C30, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0FE0,	/* 28 */
+	 0x0FF0, 0x0630, 0x0630, 0x07E0,
+	 0x07E0, 0x0630, 0x0630, 0x0FF0,
+	 0x0FE0, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0080,	/* 29 */
+	 0x0180, 0x0380, 0x0180, 0x0180,
+	 0x0180, 0x0180, 0x0180, 0x03C0,
+	 0x03C0, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x03C0,	/* 30 */
+	 0x07E0, 0x0660, 0x0060, 0x03E0,
+	 0x07C0, 0x0600, 0x0600, 0x07E0,
+	 0x07E0, 0x0000, 0x0000, 0x0000},
+/* 
+
+*/
+	{0x0000, 0x0000, 0x0000, 0x03C0,	/* 31 */
+	 0x07E0, 0x0660, 0x0060, 0x01C0,
+	 0x01C0, 0x0060, 0x0660, 0x07E0,
+	 0x03C0, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x0000,	/* 32 */
+	 0x0060, 0x0660, 0x0660, 0x0660,
+	 0x07F0, 0x07F0, 0x0060, 0x0060,
+	 0x0060, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x07C0,	/* 33 */
+	 0x07C0, 0x0600, 0x0600, 0x07C0,
+	 0x07E0, 0x0060, 0x0060, 0x07E0,
+	 0x03C0, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x0000, 0x0000, 0x03C0,	/* 34 */
+	 0x07C0, 0x0600, 0x0600, 0x07C0,
+	 0x07E0, 0x0660, 0x0660, 0x07E0,
+	 0x03C0, 0x0000, 0x0000, 0x0000},
+
+	{0x0000, 0x7FFE, 0x7FFE, 0x7FFE,	/* 35 */
+	 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+	 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+	 0x7FFE, 0x7FFE, 0x7FFE, 0x0000}
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	putpat() -- display a pattern in a configuration diagram
+   =============================================================================
+*/
+
+putpat(pn, px, py, patc)
+short pn, px, py, patc;
+{
+	register short xp, yp, pr, pc;
+	register unsigned pw;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	for (pr = 0; pr < 16; pr++) {
+
+		pw = pat[pn - 1][pr];
+		yp = py - 8 + pr + TopEdge;
+
+		if ((yp GE TopEdge) AND
+		    (yp LE BotEdge)) {
+
+			for (pc = 0; pc < 16; pc++) {
+
+				xp = px - 8 + pc + LftEdge;
+
+				if ((xp GE LftEdge) AND
+				    (xp LE RgtEdge) AND
+				    (pw & (1 << (15 - pc)))) {
+
+					vputp(idoct, xp, yp, patc);
+				}
+			}
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dispcfg() -- display a configuration on the screen
+   =============================================================================
+*/
+
+dispcfg(nn)
+register short nn;
+{
+	register short i, np;
+	short idbuf[8];
+	register char *cfgdat, *cfp;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	tsplot4(instob, 64, CFBX18, wcmrow, 4 + wcmcol, "Config #", 14);
+
+	sprintf(idbuf, "%02d", nn);
+	tsplot4(instob, 64, CFBX18, wcmrow, 12 + wcmcol, idbuf, 14);
+
+	cfgdat = cfgptr[nn];
+
+	for (i = 0; i < 64; i++) {
+
+		cfp = cfgdat + (i << 1) + i;
+		np = *cfp;
+
+		if (np)
+			putpat(np, *(cfp + 1), *(cfp + 2), patctab[np - 1]);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	showcfg() -- display a configuration in the configuration window
+   =============================================================================
+*/
+
+showcfg(nn)
+short nn;
+{
+	LftEdge = LFT_EDGE;
+	TopEdge = TOP_EDGE;
+	RgtEdge = RGT_EDGE;
+	BotEdge = BOT_EDGE;
+	wcmrow  = 17;
+	wcmcol  = 0;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(instob, 128, LftEdge, TopEdge, RgtEdge, BotEdge,
+		exp_c(CBBX18));
+
+	dispcfg(nn);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dispws() -- display a waveshape
+   =============================================================================
+*/
+
+dispws(ws)
+short ws;
+{
+	register unsigned *wsp;
+	register short i, x, y;
+	char buf[64];
+
+	if (ws GE NUMWAVS)		/* number must be valid */
+		return;
+
+	wsp = wslib[ws].final;		/* point at the data */
+
+	/* label the waveshape */
+
+	sprintf(buf, "Waveshape #%02d", ws + 1);
+	tsplot4(instob, 64, CFBX21, wcmrow, wcmcol + 2, buf, 14);
+
+	for (i = 1; i < 254; i++) {	/* draw the points */
+
+		x = LftEdge + (i >> 1);
+		y = BotEdge - ((wsp[i] ^ 0x8000) / 676);
+
+		idpoint(x, y, WSBFC);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wcmenu() -- setup the display for a waveshape or configuration menu
+   =============================================================================
+*/
+
+wcmenu(wc)
+short wc;
+{
+	register short i;
+	char buf[32];
+
+	wcflag = wc;				/* set menu page type */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(instob, 128, 0, 0, 511, 349, exp_c(CBBX18));
+
+	point = idpoint;
+
+	lseg(  0,   0, 511,   0, CBORD);	/* outside border */
+	lseg(511,   0, 511, 349, CBORD);
+	lseg(511, 349,   0, 349, CBORD);
+	lseg(  0, 349,   0,   0, CBORD);
+
+	lseg(  0, 112, 511, 112, CBORD);	/* horizontal lines */
+	lseg(  0, 224, 511, 224, CBORD);
+	lseg(  0, 335, 511, 335, CBORD);
+
+	lseg(128,   0, 128, 335, CBORD);	/* vertical lines */
+	lseg(256,   0, 256, 335, CBORD);
+	lseg(384,   0, 384, 335, CBORD);
+
+	ebflag = FALSE;				/* clear edit buffer */
+	memset(ebuf, '\0', sizeof ebuf);
+
+	curslim = RTOY(24)-1;			/* text cursor in bottom row */
+
+	x_key   = nokey;
+	csbp    = idmbox;
+
+/* 
+
+*/
+	if (wc) {				/* waveshape */
+
+		for (i = 0; i < 12; i++) {	/* fill in waveshapes */
+
+			LftEdge = ((i % 4) * 128) + 1;
+			BotEdge = ((i / 4) * 112) + 111;
+			wcmrow = (i / 4) << 3;
+			wcmcol = (i % 4) << 4;
+
+			dispws(i + (wcpage * 12));
+		}
+
+		/* label data entry area and show page number */
+
+		sprintf(buf, "Waveshape A%02d B%02d Page",
+			1 + vbufs[curvce].idhwsb,
+			1 + vbufs[curvce].idhwsa);
+
+		tsplot4(instob, 64, CFBX18, 24, 1, buf, 14);
+
+		tsplot4(instob, 64, wcpage ? CFBX18 : ID_ENTRY,
+			24, 26, "1", 14);
+
+		tsplot4(instob, 64, wcpage ? ID_ENTRY : CFBX18,
+			24, 28, "2", 14);
+
+		curfet = id_fet2;
+		settc(24, 12);
+/* 
+
+*/
+	} else {				/* configuration */
+
+		for (i = 0; i < 12; i++) {	/* fill in configurations */
+
+			LftEdge = ((i % 4) * 128) + 1;
+			TopEdge = ((i / 4) * 112) + 1;
+			RgtEdge = LftEdge + 128;
+			BotEdge = TopEdge + 112;
+			wcmrow = (i / 4) << 3;
+			wcmcol = (i % 4) << 4;
+
+			dispcfg(i);
+		}
+
+		/* label data entry area */
+
+		tsplot4(instob, 64, CFBX18, 24, 1, "Configuration #", 14);
+
+		sprintf(buf, "%02d", vbufs[curvce].idhcfg);
+		tsplot4(instob, 64, CFBX18, 24, 16, buf, 14);
+
+		curfet = id_fet3;
+		settc(24, 16);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	imfnbox() -- instrument menu box hit processor
+   =============================================================================
+*/
+
+imfnbox(n)
+short n;
+{
+	register short row, col;
+
+	row = hitcy / 14;
+	col = hitcx >> 3;
+
+	if (hitbox EQ 12) {
+
+		if (wcflag) {				/* waveshape */
+
+			if (col < 10) {			/* take down menu */
+
+				reshowi();
+				settc(17, wmcsel ? 61 : 57);
+
+			} else if ((col GE 19) AND (col LE 22)) {
+
+				 /* toggle waveshape display page */
+
+				if (wcpage)
+					wcpage = 0;	/* to page 1 */
+				else
+					wcpage = 1;	/* to page 2 */
+
+				wcmenu(1);
+				return;
+
+			} else {			/* data entry */
+
+				wmctag = FALSE;
+				enterit();
+
+				if (wmctag)
+					modinst();
+
+				return;
+			}
+/* 
+
+*/
+		} else {				/* configuration */
+
+			if (col < 14) {			/* take down menu */
+
+				reshowi();
+				settc(17, 12);
+				
+			} else {			/* data entry */
+
+				wmctag = FALSE;
+				enterit();
+
+				if (wmctag)
+					modinst();
+
+				return;
+			}
+		}
+	}
+}
Index: ram/smscrl.c
===================================================================
--- ram/smscrl.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/smscrl.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,667 @@
+/*
+   =============================================================================
+	smscrl.c -- MIDAS-VII smooth scrolling functions
+	Version 37 -- 1989-11-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	OLDSCRL		0
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "curpak.h"
+#include "patch.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#define	SS_NSL		16			/* number of scrolled lines */
+#define	SS_TOP		(2 * (SS_NSL + 1))	/* total line count */
+#define	SS_LIM		(SS_TOP - SS_NSL)	/* top line limit */
+#define	SS_LEN		48			/* length of a scrolled line */
+#define	NSCANS		14			/* number of scan lines */
+#define	TOPSCAN		(NSCANS - 1)		/* top scan line */
+
+extern	short	cmtype;				/* cursor type */
+extern	short	ctcsw;				/* cursor status */
+extern	short	curslin;			/* current sequence line */
+extern	short	cxrate;				/* cursor X update rate */
+extern	short	cxval;				/* cursor X location */
+extern	short	cyrate;				/* cursor Y update rate */
+extern	short	cyval;				/* cursor Y location */
+extern	short	ptecpos;			/* current patch index */
+extern	short	pteset;				/* ptebuf set flag */
+extern	short	sqdeflg;			/* sequence data entry flag */
+extern	short	stccol;				/* main cursor column */
+extern	short	submenu;			/* submenu switch */
+extern	short	vtccol;				/* submenu cursor column */
+extern	short	vtcrow;				/* submenu cursor row */
+extern	short	vtxval;				/* submenu cursor x value */
+extern	short	vtyval;				/* subment cursor y value */
+
+extern	unsigned short	*obj10;			/* sequence status object pointer */
+
+extern	unsigned short	cg3[];			/* character generator table */
+
+extern	char	ptdebuf[];			/* patch data entry buffer */
+extern	char	sqdebuf[];			/* sequence data entry buffer */
+
+extern	struct patch	ptebuf;			/* current patch image */
+extern	struct patch	patches[];		/* the patch table */
+
+extern	struct seqent	seqbuf;			/* sequence line buffer */
+extern	struct seqent	seqtab[];		/* sequence table */
+
+char	TheBuf[66];				/* display build buffer */
+
+/* 
+
+*/
+
+char	*(*BakLine)();			/* next line backward function pointer */
+char	*(*FwdLine)();			/* next line forward function pointer */
+
+short	PdScDnF;			/* scroll down flag */
+short	PdScUpF;			/* scroll up flag */
+
+short	CurLine;			/* top line being displayed */
+short	CurScan;			/* current scan line */
+short	DupLine;			/* write pointer for other page */
+short	ScrlObj;			/* object descriptor table index */
+
+char	*LinePtr;			/* line to scroll onto screen */
+
+unsigned short	LineAtr;		/* attribute for the new line */
+
+unsigned short	*LineBuf;		/* current display memory pointer */
+unsigned short	*OldLine;		/* old display memory pointer */
+unsigned short	*ScObAdr;		/* display memory base pointer */
+
+short	LineCon = SS_LEN * 3;		/* line offset constant */
+short	LineLen = SS_LEN;		/* length of a scrolled line */
+short	SmScLim = SS_LIM;		/* top line limit */
+short	SmScNsl = SS_NSL;		/* number of scrolled lines */
+short	SmScTop = SS_TOP;		/* total line count */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	LineFwd() -- return the next patch line in the forward direction
+   =============================================================================
+*/
+
+char *
+LineFwd()
+{
+	register short j, k;
+
+	for (j = 0; j < 48; j++)
+		TheBuf[j] = ' ';
+
+	TheBuf[0]  = '\260';
+	TheBuf[48] = '\0';
+
+	if (0 EQ ptecpos)
+		return((char *)NULL);
+
+	if (0 EQ (j = findnxt(ptecpos)))
+		return((char *)NULL);
+
+	ptecpos = j;
+
+	memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+	pteset = TRUE;
+	pte2buf();
+
+	k = ptecpos;
+
+	for (j = 0; j < 8; j++)
+		if (0 EQ (k = findnxt(k)))
+			return(TheBuf);
+
+	dspdfst(&TheBuf[ 2], patches[k].defnum);
+	dspdfst(&TheBuf[15], patches[k].stmnum);
+	dspdest(&TheBuf[28], &patches[k]);
+
+	for (j = 0; j < 50; j++)
+		if(TheBuf[j] EQ '\0')
+			TheBuf[j] = ' ';
+
+	TheBuf[48] = '\0';
+	return(TheBuf);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	LineBak() -- return the next patch line in the backward direction
+   =============================================================================
+*/
+
+char *
+LineBak()
+{
+	register short j, k;
+
+	for (j = 0; j < 48; j++)
+		TheBuf[j] = ' ';
+
+	TheBuf[0]  = '\260';
+	TheBuf[48] = '\0';
+
+	if (0 EQ ptecpos)
+		return((char *)NULL);
+
+	if (0 EQ (j = findprv(ptecpos)))
+		return((char *)NULL);
+
+	ptecpos = j;
+
+	memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+	pteset = TRUE;
+	pte2buf();
+
+	k = ptecpos;
+
+	for (j = 0; j < 7; j++)
+		if (0 EQ (k = findprv(k)))
+			return(TheBuf);
+
+	dspdfst(&TheBuf[ 2], patches[k].defnum);
+	dspdfst(&TheBuf[15], patches[k].stmnum);
+	dspdest(&TheBuf[28], &patches[k]);
+
+	for (j = 0; j < 50; j++)
+		if(TheBuf[j] EQ '\0')
+			TheBuf[j] = ' ';
+
+	TheBuf[48] = '\0';
+	return(TheBuf);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	WrVideo() -- write a line to the video display
+   =============================================================================
+*/
+
+WrVideo(row, col, str, atr)
+register short row, col;
+register char *str;
+register unsigned short atr;
+{
+	register char chr;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	while ('\0' NE (chr = *str++)) {
+
+		vputcv(ScObAdr, row, col, chr,
+			(col EQ 0) ? PTBATR : atr, LineLen);
+
+		col++;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SetDTop() -- set the top line of the display
+   =============================================================================
+*/
+
+SetDTop(row, scan)
+short row, scan;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	LineBuf = (unsigned short *)((char *)ScObAdr + (row * LineCon));
+
+	if (OldLine NE LineBuf)
+		v_odtab[ScrlObj][2] = ((char *)LineBuf >> 1) & 0xFFFF;
+
+	OldLine = LineBuf;
+
+	v_odtab[ScrlObj][0] = (v_odtab[ScrlObj][0] & 0x0FFF) | (scan << 12);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	UpdVid() -- update the video display on both pages
+   =============================================================================
+*/
+
+UpdVid(row, col, str, atr)
+short row, col;
+char *str;
+unsigned short atr;
+{
+	WrVideo(CurLine + row, col, str, atr);
+
+	DupLine = CurLine + SmScNsl + 2 + row;
+
+	if (DupLine < SmScTop)
+		WrVideo(DupLine, col, str, PTPATR);
+
+	DupLine = CurLine - SmScNsl - 2 + row;
+
+	if (DupLine GE 0)
+		WrVideo(DupLine, col, str, PTPATR);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	bgncm() -- begin patch display cursor motion
+   =============================================================================
+*/
+
+bgncm()
+{
+	register short j;
+
+	memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+	pteset = TRUE;
+	pte2buf();
+
+	memcpy(TheBuf, ptdebuf, 48);
+
+	for (j = 0; j < 50; j++)
+		if(TheBuf[j] EQ '\0')
+			TheBuf[j] = ' ';
+
+	TheBuf[0] = '\260';
+	TheBuf[1] = ' ';
+	TheBuf[48] = '\0';
+
+	UpdVid(7, 0, TheBuf, PTPATR);
+	ctcoff();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stopcm() -- stop patch display cursor motion
+   =============================================================================
+*/
+
+stopcm()
+{
+	register short i;
+
+	if (PdScDnF)
+		SetDTop(CurLine, CurScan = TOPSCAN);
+	else if (PdScUpF)
+		SetDTop(++CurLine, CurScan = TOPSCAN);
+
+	if (NOT ctcsw) {		/* if we scrolled ... */
+
+		if (ptecpos) {		/* if something is there ... */
+
+			/* refresh editing variables */
+
+			memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+			pteset = TRUE;
+			pte2buf();
+			setptcv();
+
+		} else {		/* ... nothing there */
+
+			voidpb();	/* void the patch buffer */
+		}
+	}
+
+	ctcon();			/* re-enable cursor */
+
+	PdScDnF = FALSE;		/* turn off the scrolling flags */
+	PdScUpF = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stopsm() -- stop sequence display cursor motion
+   =============================================================================
+*/
+
+stopsm()
+{
+	register short i;
+
+	if (PdScDnF)
+		SetDTop(CurLine, CurScan = TOPSCAN);
+	else if (PdScUpF)
+		SetDTop(++CurLine, CurScan = TOPSCAN);
+
+	memcpyw(&seqbuf, &seqtab[curslin], NSEQW);
+	dsqlin(sqdebuf, curslin);
+	sqdeflg = TRUE;
+	ctcon();
+
+	PdScDnF = FALSE;
+	PdScUpF = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	smscrl() -- smooth scroll the text display up or down
+   =============================================================================
+*/
+
+smscrl()
+{
+	if (PdScUpF) {			/* SCROLL UP (toward NEW data) ? */
+
+		if (CurScan EQ TOPSCAN) {	/* ready for a new line ? */
+
+			if ((char *)NULL NE (LinePtr = (*FwdLine)())) {	/* get a line */
+
+				if (CurLine EQ SmScLim) {	/* *** swap display pages *** */
+
+					/* update page we're going to */
+
+					WrVideo(SmScNsl, 0, LinePtr, LineAtr);
+
+					/* point at new page */
+
+					SetDTop(CurLine = 0, CurScan = TOPSCAN);
+
+				} else {		/* *** stay on this page *** */
+
+					/* update scroll target line */
+
+					WrVideo(CurLine + SmScNsl, 0, LinePtr, LineAtr);
+
+					/* update other page if it's in range */
+
+					DupLine = CurLine - 2;
+
+					if (DupLine GE 0)
+						WrVideo(DupLine, 0, LinePtr, LineAtr);
+				}
+
+					/* do first scroll up of new line */
+
+					SetDTop(CurLine, --CurScan);
+			}
+
+		} else {		/* scrolling -- scroll some more */
+
+			if (CurScan EQ 0)
+				SetDTop(++CurLine, CurScan = TOPSCAN);
+			else
+				SetDTop(CurLine, --CurScan);
+		}
+/* 
+
+*/
+	} else if (PdScDnF) {		/* SCROLL DOWN (toward old data) ? */
+
+		if (CurScan EQ TOPSCAN) {	/* ready for a new line ? */
+
+			if ((char *)NULL NE (LinePtr = (*BakLine)())) {	/* get a line */
+
+				if (CurLine EQ 0) {	/* *** swap display pages *** */
+
+					/* update page we're going to */
+
+					WrVideo(SmScLim - 1, 0, LinePtr, LineAtr);
+
+					/* point at new page */
+
+					SetDTop(CurLine = SmScLim - 1, CurScan = 0);
+
+				} else {		/* *** stay on this page *** */
+
+					/* update scroll target line */
+
+					WrVideo(CurLine - 1, 0, LinePtr, LineAtr);
+
+					/* update other page if it's in range */
+
+					DupLine = CurLine + SmScNsl + 1;
+
+					if (DupLine < SmScTop)
+						WrVideo(DupLine, 0, LinePtr, LineAtr);
+
+					/* do first scroll down of new line */
+
+					SetDTop(--CurLine, CurScan = 0);
+				}
+			}
+
+		} else {		/* scrolling -- scroll some more */
+
+			if (CurScan NE TOPSCAN)
+				SetDTop(CurLine, ++CurScan);
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	smxupd() -- patch / sequence smooth scroll X axis update
+   =============================================================================
+*/
+
+smxupd()
+{
+	short oldcx;
+
+	oldcx = cxval;
+
+	if (submenu) {
+
+		vtccol = XTOC(vtxval += cxrate);
+
+		if (vtccol > 60)
+			vtxval = CTOX(vtccol = 60);
+		else if (vtccol < 2)
+			vtxval = CTOX(vtccol = 2);
+
+	} else {
+
+		cxval += cxrate;
+
+		if (cxval > CTOX(48))
+			cxval = CTOX(48);
+		else if (cxval < CTOX(2))
+			cxval = CTOX(2);
+
+		if (cxval EQ oldcx)
+			return;
+
+		if (47 EQ XTOC(cxval)) {
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			vvputsv(obj10, 16, PDBORFG, PDSEQBG,
+				7, 0, "\260", 14, 14, cg3);
+
+			vsplot4(obj10, 16, PDPTRFG,
+				7, 0, "\274", 14, 14, cg3);
+
+		} else if (48 EQ XTOC(cxval)) {
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			vvputsv(obj10, 16, PDBORFG, PDSEQBG,
+				7, 0, "\260", 14, 14, cg3);
+
+			vsplot4(obj10, 16, PDPTRFG,
+				7, 0, "\277", 14, 14, cg3);
+
+		}
+				
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	smy_up() -- patch display smooth scrolling
+   =============================================================================
+*/
+
+smy_up(tag)
+short tag;
+{
+
+	if (0 EQ ptecpos) {		/* see if anything is there */
+
+		dptw();			/* try to find something ... */
+		return;			/* ... may scroll next time */
+	}
+
+	if (ctcsw)			/* if we haven't scrolled yet ... */
+		bgncm();		/* ... setup for scrolling */
+
+	if (tag < 0) {		/* scroll up */
+
+		if (0 EQ findnxt(ptecpos))
+			return;
+
+		PdScUpF = TRUE;
+		PdScDnF = FALSE;
+		smscrl();
+
+	} else if (tag > 0) {	/* scroll down */
+
+		if (0 EQ findprv(ptecpos))
+			return;
+
+		PdScDnF = TRUE;
+		PdScUpF = FALSE;
+		smscrl();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	smyupd() -- patch display smooth scroll Y axis update
+   =============================================================================
+*/
+
+smyupd()
+{
+	if (submenu) {
+
+		vtcrow = YTOR(vtyval += cyrate);
+
+		if (vtcrow > 23)
+			vtyval = RTOY(vtcrow = 23);
+		else if (vtcrow < 19)
+			vtyval = RTOY(vtcrow = 19);
+
+	}
+
+#if	OLDSCRL
+	smy_up(cyrate);
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqy_up() -- sequence smooth scrolling
+   =============================================================================
+*/
+
+sqy_up(tag)
+short tag;
+{
+	if (ctcsw)
+		ctcoff();
+
+	if (tag < 0) {		/* scroll up */
+
+		PdScUpF = TRUE;
+		PdScDnF = FALSE;
+		smscrl();
+
+	} else if (tag > 0) {	/* scroll down */
+
+		PdScDnF = TRUE;
+		PdScUpF = FALSE;
+		smscrl();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqyupd() -- sequence smooth scroll Y axis update
+   =============================================================================
+*/
+
+sqyupd()
+{
+	if (submenu) {
+
+		vtcrow = YTOR(vtyval += cyrate);
+
+		if (vtcrow > 23)
+			vtyval = RTOY(vtcrow = 23);
+		else if (vtcrow < 19)
+			vtyval = RTOY(vtcrow = 19);
+
+	}
+
+#if	OLDSCRL
+	sqy_up(cyrate);
+#endif
+}
Index: ram/sqdisp.c
===================================================================
--- ram/sqdisp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqdisp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,671 @@
+/*
+   =============================================================================
+	sqdisp.c -- MIDAS-VII sequence editor display functions
+	Version 24 -- 1989-11-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGSQ		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "patch.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#if	DEBUGSQ
+extern	short	debugsw;
+
+short	debugsq = 1;
+#endif
+
+extern	short	nokey();
+
+extern	char	*(*BakLine)(), *(*FwdLine)();
+
+extern	unsigned short	*obj8, *obj9, *obj10, *obj11;
+extern	unsigned short	*LineBuf, *ScObAdr, *OldLine;
+extern	unsigned short	LineAtr;
+
+extern	short	CurLine, CurScan;
+extern	short	ScrlObj, SmScNsl;
+extern	short	PdScDnF, PdScUpF;
+extern	short	ctcsw, submenu;
+extern	short	stccol, stcrow;
+extern	short	cxval;
+
+extern	unsigned short	cg3[];
+
+extern	char	TheBuf[];		/* display build buffer */
+
+short	curslin;			/* current sequence line */
+
+/* 
+
+*/
+
+char	sqhead[] = 
+
+	"\260 Lin Time  Action 1    Action 2    Action 3    \260 No Seq Rg T \260";
+
+char	*sqmcon[] = {
+
+	"\260 Key transient  Trigger on   Stop         Set reg   Value    \260",
+	"\260 Key closure    Trigger off  Jump to lin  Inc Reg   Register \260",
+	"\260 Key release    Trig toggle               If reg =  Voltage  \260",
+	"\260 If key active  If trig act  If stim act  If reg <  Random   \260",
+	"\260                                          If reg >           \260"
+};
+
+short	seqpal[16][3] = {		/* sequence display palette */
+
+	{0, 0, 0},	/*  0 - black */
+	{2, 3, 3},	/*  1 - white */
+	{0, 0, 1},	/*  2 - dark blue #1 */
+	{2, 0, 2},	/*  3 - dark violet */
+	{0, 0, 3},	/*  4 - dark blue #2 */
+	{3, 0, 0},	/*  5 - red */
+	{3, 3, 0},	/*  6 - yellow */
+	{1, 2, 0},	/*  7 - dark green */
+	{0, 3, 3},	/*  8 - light blue */
+	{2, 2, 2},	/*  9 - gray */
+	{0, 3, 0},	/* 10 - light green */
+	{3, 1, 2},	/* 11 - light violet */
+	{0, 2, 3},	/* 12 - medium blue */
+	{2, 0, 0},	/* 13 - dark red */
+	{1, 1, 2},	/* 14 - electric purple */
+	{3, 3, 3}	/* 15 - bright white */
+};
+
+/* 
+
+*/
+
+short	sqatype[] = {		/* sequence action types by box number */
+
+	SQ_NULL,	/*	"           "	0 */
+	SQ_TKEY,	/*	"Kt 001 1 01"	1 */
+	SQ_CKEY,	/*	"Kc 001 1 01"	2 */
+	SQ_RKEY,	/*	"Kr 001 1 01"	3 */
+	SQ_IKEY,	/*	"If 001 1 01"	4 */
+	SQ_STRG,	/*	"Trig on  01"	5 */
+	SQ_CTRG,	/*	"Trig off 01"	6 */
+	SQ_TTRG,	/*	"Trig tgl 01"	7 */
+	SQ_ITRG,	/*	"If trig act"	8 */
+	SQ_STOP,	/*	"Stop       "	9 */
+	SQ_JUMP,	/*	"Jump to 000"	10 */
+	SQ_NULL,	/*	"???????????"	11 */
+	SQ_ISTM,	/*	"If stim act"	12 */
+	SQ_SREG,	/*	"Set R01=00 "	13 */
+	SQ_AREG,	/*	"Inc R01+00 "	14 */
+	SQ_IREQ,	/*	"If  R01=00 "	15 */
+	SQ_IRLT,	/*	"If  R01<00 "	16 */
+	SQ_IRGT		/*	"If  R01>00 "	17 */
+};
+
+/* 
+
+*/
+
+char	*sqdsptb[] = {		/* sequence action display strings by action */
+
+	"           ",		/* SQ_NULL	0x0000	null action */
+	"Kc 001 1 01",		/* SQ_CKEY	0x0001	Key closure */
+	"Kr 001 1 01",		/* SQ_RKEY	0x0002	Key release */
+	"Kt 001 1 01",		/* SQ_TKEY	0x0003	Key transient */
+	"If 001 1 01",		/* SQ_IKEY	0x0004	If key active */
+	"Trig on  01",		/* SQ_STRG	0x0005	Trigger on */
+	"Trig off 01",		/* SQ_CTRG	0x0006	Trigger off */
+	"Trig tgl 01",		/* SQ_TTRG	0x0007	Trigger toggle */
+	"If trig  01",		/* SQ_ITRG	0x0008	If trigger active */
+	"Set R01=00 ",		/* SQ_SREG	0x0009	Set register */
+	"If  R01=00 ",		/* SQ_IREQ	0x000A	If register = */
+	"If  R01<00 ",		/* SQ_IRLT	0x000B	If register < */
+	"If  R01>00 ",		/* SQ_IRGT	0x000C	If register > */
+	"If stim act",		/* SQ_ISTM	0x000D	If stimulus active */
+	"Jump to 000",		/* SQ_JUMP	0x000E	Jump to sequence line */
+	"Stop       ",		/* SQ_STOP	0x000F	Stop sequence */
+	"Inc R01+00 "		/* SQ_AREG	0x0010	Increment register */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	initsq() -- initialize the sequence data structures
+   =============================================================================
+*/
+
+initsq()
+{
+	register short i;
+
+	for (i = 0; i < 16; i++) {
+
+		seqflag[i] = 0;
+		seqline[i] = 0;
+		sregval[i] = 0;
+		trstate[i] = 0;
+		seqstim[i] = 0;
+		seqtime[i] = 0;
+	}
+
+	memsetw(&seqtab, 0, (NSEQW * NSLINES));
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsact() -- convert sequence action code and data to display format
+   =============================================================================
+*/
+
+dsact(buf, act, dat)
+char *buf;
+unsigned short act, dat;
+{
+	unsigned short sqa, sqd, sqf, sqr, sqt, t1, t2, val;
+	unsigned short chan, i, key, port;
+
+	sqa = SQ_MACT & act;
+
+	strcpy(buf, sqdsptb[sqa]);
+
+	switch (sqa) {
+
+	case SQ_CKEY:		/* Key closure */
+	case SQ_RKEY:		/* Key release */
+	case SQ_TKEY:		/* Key transient */
+	case SQ_IKEY:		/* If key active */
+
+		port = 0x0003 & (dat >> 11);
+		chan = 0x000F & (dat >>  7);
+		key  = 0x007F &  dat;
+
+		if (port EQ 2)
+			sprintf(&buf[3], "%03u L   ", 1 + key);
+		else
+			sprintf(&buf[3], "%03u %u %02u", 1 + key, 1 + port, 1 + chan);
+
+		break;
+
+	case SQ_STRG:		/* Trigger on */
+	case SQ_CTRG:		/* Trigger off */
+	case SQ_TTRG:		/* Trigger toggle */
+	case SQ_ITRG:		/* If trigger active */
+
+		sprintf(&buf[9], "%02u", 1 + dat);
+		break;
+/* 
+
+*/
+	case SQ_AREG:		/* Increment register */
+
+		sqf = (dat & SQ_MFLG) ? '-' : '+';
+		goto doval;
+
+	case SQ_SREG:		/* Set register */
+	case SQ_IREQ:		/* If register = */
+
+		sqf = '=';
+		goto doval;
+
+	case SQ_IRLT:		/* If register < */
+
+		sqf = '<';
+		goto doval;
+
+	case SQ_IRGT:		/* If register > */
+
+		sqf = '>';
+
+doval:
+
+		sqr = 1 + ((SQ_MOBJ & act) >> 8);
+		sqd = SQ_MVAL & dat;
+		sqt = SQ_MTYP & dat;
+
+		switch (sqt) {
+
+		case SQ_REG:		/* register */
+
+			sprintf(&buf[4], "R%02u%cR%02u", sqr, sqf, 1 + sqd);
+			break;
+
+		case SQ_VAL:		/* value */
+
+			sprintf(&buf[4], "R%02u%c%02u ", sqr, sqf, sqd);
+			break;
+
+		case SQ_VLT:		/* voltage */
+
+			sprintf(&buf[4], "R%02u%cV%u ", sqr, sqf, 1 + sqd);
+			break;
+
+		case SQ_RND:		/* random */
+
+			sprintf(&buf[4], "R%02u%c?%u ", sqr, sqf, sqd);
+			break;
+		}
+
+		break;
+/* 
+
+*/
+	case SQ_JUMP:		/* Jump to sequence line */
+
+		sprintf(&buf[8], "%03u", dat);
+		break;
+
+	case SQ_NULL:		/* null action */
+	case SQ_ISTM:		/* If stimulus active */
+	case SQ_STOP:		/* Stop sequence */
+
+		break;
+	}
+
+	for (i = 0; i < 12; i++)
+		if (buf[i] EQ '\0')
+			buf[i] = ' ';
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsqlin() -- convert a sequence line to display format
+   =============================================================================
+*/
+
+dsqlin(buf, slin)
+char *buf;
+short slin;
+{
+	register struct seqent *sp;
+	register short i, t1, t2;
+
+	sp = &seqtab[slin];
+
+	t1 = sp->seqtime / 100;
+	t2 = sp->seqtime - (t1 * 100);
+
+	sprintf(buf, "  %03u %02u.%02u", slin, t1, t2);
+
+	dsact(&buf[12], sp->seqact1, sp->seqdat1);
+	dsact(&buf[24], sp->seqact2, sp->seqdat2);
+	dsact(&buf[36], sp->seqact3, sp->seqdat3);
+
+	buf[0] = '\260';
+
+	for (i = 0; i < 48; i++)
+		if (buf[i] EQ '\0')
+			buf[i] = ' ';
+
+	buf[48] = '\0';
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dcursq() -- display current sequence line
+   =============================================================================
+*/
+
+dcursq()
+{
+	dsqlin(TheBuf, curslin);
+	UpdVid(7, 0, TheBuf, PTEATR);
+	ctcon();
+}
+
+/*
+   =============================================================================
+	dstw() -- display sequence table window around current sequence line
+   =============================================================================
+*/
+
+dstw()
+{
+	register short slin, srow;
+
+	slin = curslin - 7;
+
+	if (slin < 0)
+		slin += NSLINES;
+
+	for (srow = 0; srow < 16; srow++) {
+
+		dsqlin(TheBuf, slin);
+		UpdVid(srow, 0, TheBuf, (srow EQ 7) ? PTEATR : PTPATR);
+
+		if (++slin GE NSLINES)
+			slin -= NSLINES;
+	}
+
+	seq2buf();
+	ctcon();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqwin() -- fill in a sequence display window
+   =============================================================================
+*/
+
+sqwin(n)
+short n;
+{
+	register short i, j;
+	short atrbuf[64];
+	char  linbuf[66];
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	switch (n) {
+
+	case 0:		/* headings and box outline */
+
+		/* row 0 */
+
+		memset(linbuf, '\261', 63);
+		linbuf[0]  = '\272';
+		linbuf[48] = '\267';
+		linbuf[62] = '\273';
+		linbuf[63] = '\0';
+
+		memsetw(atrbuf, PTBATR, 63);
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj8, 0, 0, linbuf, atrbuf);
+
+		/* row 1 */
+
+		memsetw(atrbuf, PTHATR+0x0100, 64);
+		atrbuf[ 0] = PTBATR;
+		atrbuf[ 1] = PTHATR;
+		atrbuf[ 5] = PTHATR;
+		atrbuf[11] = PTHATR;
+		atrbuf[23] = PTHATR;
+		atrbuf[35] = PTHATR;
+		atrbuf[47] = PTHATR;
+		atrbuf[48] = PTBATR;
+		atrbuf[49] = PTHATR;
+		atrbuf[52] = PTHATR;
+		atrbuf[56] = PTHATR;
+		atrbuf[59] = PTHATR;
+		atrbuf[61] = PTHATR;
+		atrbuf[62] = PTBATR;
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj8, 1,  0, sqhead, atrbuf);
+/* 
+
+*/
+		/* row 18 */
+
+		memset(linbuf, '\261', 63);
+		linbuf[ 0] = '\266';
+		linbuf[48] = '\265';
+		linbuf[62] = '\264';
+		linbuf[63] = '\0';
+
+		memsetw(atrbuf, PTBATR, 63);
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj11, 0, 0, linbuf, atrbuf);
+
+		/* row 24 */
+
+		memset(linbuf, '\261', 63);
+		linbuf[ 0] = '\271';
+		linbuf[62] = '\270';
+		linbuf[63] = '\0';
+
+		memsetw(atrbuf, PTBATR, 63);
+		atrbuf[63] = 0x0000;
+
+		vputsa(obj11, 6, 0, linbuf, atrbuf);
+
+		break;
+/* 
+
+*/
+	case 1:		/* sequences */
+
+		SetDTop(0, 13);
+		dstw();
+		break;
+
+	case 2:		/* sequence status */
+
+		for (i = 0; i < 16; i++) {
+
+			sprintf(linbuf, "    %03d %02d %d ",
+				seqline[i], sregval[i], trstate[i]);
+
+			vvputsv(obj10, 16, PDBORFG, PDSEQBG,
+				i, 0, "\260", 14, 14, cg3);
+
+			vvputsv(obj10, 16, PDSEQFG, PDSEQBG,
+				i, 1, linbuf, 14, 14, cg3);
+
+			vvputsv(obj10, 16, PDBORFG, PDSEQBG,
+				i, 14, "\260", 14, 14, cg3);
+
+			if (i EQ 7) {
+
+				if (48 EQ XTOC(cxval)) {
+
+					vsplot4(obj10, 16, PDPTRFG,
+						i, 0, "\277", 14, 14, cg3);
+
+				} else {
+
+					vsplot4(obj10, 16, PDPTRFG,
+						i, 0, "\274", 14, 14, cg3);
+				}
+			}
+
+			sprintf(linbuf, "%02d", i + 1);
+
+			vvputsv(obj10, 16,
+				(seqflag[i] & SQF_RUN) ? PDSEQRN : PDSEQFG, PDSEQBG,
+				i, 2, linbuf, 14, 14, cg3);
+		}
+
+		break;
+
+	case 3:		/* menu */
+
+		memsetw(atrbuf, PTMATR, 64);
+		atrbuf[0]  = PTBATR;
+		atrbuf[62] = PTBATR;
+		atrbuf[63] = 0x0000;
+
+		for (i = 0; i < 5; i++)
+			vputsa(obj11, (i + 1), 0, sqmcon[i], atrbuf);
+
+		break;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SqBakLn() -- return the next sequence line in the backward direction
+   =============================================================================
+*/
+
+char *
+SqBakLn()
+{
+	register short slin;
+
+	if (--curslin < 0)
+		curslin += NSLINES;
+
+	slin = curslin - 7;
+
+	if (slin < 0)
+		slin += NSLINES;
+
+	dsqlin(TheBuf, slin);
+	return(TheBuf);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	SqFwdLn() -- return the next sequence line in the forward direction
+   =============================================================================
+*/
+
+char *
+SqFwdLn()
+{
+	register short slin;
+
+	if (++curslin GE NSLINES)
+		curslin -= NSLINES;
+
+	slin = curslin + 8;
+
+	if (slin GE NSLINES)
+		slin -= NSLINES;
+
+	dsqlin(TheBuf, slin);
+	return(TheBuf);
+}
+
+/*
+   =============================================================================
+	sqwins() -- draw the sequence display
+   =============================================================================
+*/
+
+sqwins()
+{
+	register short i;
+
+	for (i = 0; i < 4; i++)
+		sqwin(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqdisp() -- setup the sequence display
+   =============================================================================
+*/
+
+sqdisp()
+{
+#if	DEBUGSQ
+	if (debugsw AND debugsq)
+		printf("sqdisp(): ENTRY\n");
+#endif
+
+	dswap();				/* clear the video display */
+
+	BakLine = SqBakLn;
+	FwdLine = SqFwdLn;
+
+	/* setup object pointers */
+
+	obj8  = &v_score[OB08LOC];		/*  8 - headings */
+	obj9  = &v_score[OB09LOC];		/*  9 - sequences */
+	obj10 = &v_score[OB10LOC];		/* 10 - status */
+	obj11 = &v_score[OB11LOC];		/* 11 - menu */
+
+	ScrlObj = 9;
+	ScObAdr = obj9;
+	LineBuf = obj9;
+	OldLine = (unsigned short *)NULL;
+	LineAtr = PTPATR;
+
+	CurLine = 0;
+	CurScan = 13;
+
+	PdScDnF = FALSE;
+	PdScUpF = FALSE;
+
+	/* ---------------- initialize object table -------------------- */
+	/*     obj,  typ, bnk,  base, xpix, ypix,  x0,  y0,   flags, pri */
+
+	SetObj(  8,    1,   0,  obj8,  512,   28,   0,   0, PDFL_08, -1);
+	SetObj(  9,    1,   0,  obj9,  384,  224,   0,  28, PDFL_09, -1);
+	SetObj( 10,    0,   0, obj10,  128,  224, 384,  28, PDFL_10, -1);
+	SetObj( 11,    1,   0, obj11,  512,   98,   0, 252, PDFL_11, -1);
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	memsetw(v_score, 0, 32767);		/* clear display objects */
+	memsetw(v_score+32767L, 0, 24577);
+
+	sqwins();				/* fill up the windows */
+
+/* 
+
+*/
+	/* display some objects */
+
+	SetPri( 8,  8);				/* headings */
+	SetPri( 9,  9);				/* sequences */
+	SetPri(10,  10);			/* sequence status */
+	SetPri(11,  11);			/* menu */
+
+	if (v_regs[5] & 0x0180)			/* select bank 0 */
+		vbank(0);
+
+	memcpyw(v_cgtab, cg3, 3584);		/* setup character generator */
+	v_regs[1] = (v_regs[1] & 0x0FFF) | 0xE000;
+
+	/* fix the initial scan line specs in the object descriptor table */
+
+	v_odtab[ 8][0] = (v_odtab[ 8][0] & 0x0FFF) | 0xD000;
+	v_odtab[ 9][0] = (v_odtab[ 9][0] & 0x0FFF) | 0xD000;
+
+	v_odtab[11][0] = (v_odtab[11][0] & 0x0FFF) | 0xD000;
+
+	submenu = FALSE;
+
+	ctcsw = TRUE;				/* enable cursor */
+	ctcpos(DATAROW, 2);			/* set initial cursor */
+	postcm();				/* set initial submenu */
+
+	vsndpal(seqpal);			/* set the palette */
+
+#if	DEBUGSQ
+	if (debugsw AND debugsq)
+		printf("sqdisp():  EXIT\n");
+#endif
+
+}
Index: ram/sqdkey.c
===================================================================
--- ram/sqdkey.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqdkey.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,462 @@
+/*
+   =============================================================================
+	sqdkey.c -- MIDAS-VII sequence display data entry functions
+	Version 8 -- 1988-11-22 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "fields.h"
+#include "curpak.h"
+#include "patch.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+extern	short	asig, astat;
+
+extern	short	action;
+extern	short	curslin;
+extern	short	sqdeflg;
+extern	short	stccol;
+extern	short	stcrow;
+
+extern	char	sqdebuf[50];
+
+extern	struct seqent	seqbuf;
+extern	struct seqent	seqtab[];
+
+short	actfmt;		/* action code format */
+
+/* 
+
+*/
+
+char	actlft[] = { 12, 24, 36 };	/* action field leftmost columns */
+
+char	seqdfmt[] = {			/* action data entry format by action */
+
+	0,  1, 1, 1, 1,  2, 2, 2, 2,  3, 3, 3, 3,  0, 4, 0,  3
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	seq2buf() -- load the edit buffer from the current sequence line
+   =============================================================================
+*/
+
+seq2buf()
+{
+	memcpyw(&seqbuf, &seqtab[curslin], NSEQW);
+	dsqlin(sqdebuf, curslin);
+	sqdeflg = TRUE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqactde() -- sequence action digit data entry function
+   =============================================================================
+*/
+
+sqactde(key)
+register short key;
+{
+	register short col;
+	short defmt;
+	unsigned short act, vtype;
+	char buf[8];
+
+	col = stccol - actlft[action];		/* get field data entry column */
+
+	switch (action) {	/* get action code from sequence entry */
+
+	case 0:		/* action 1 */
+
+		act = seqbuf.seqact1;
+		vtype = SQ_MTYP & seqbuf.seqdat1;
+		break;
+
+	case 1:		/* action 2 */
+
+		act = seqbuf.seqact2;
+		vtype = SQ_MTYP & seqbuf.seqdat2;
+		break;
+
+	case 2:		/* action 3 */
+
+		act = seqbuf.seqact3;
+		vtype = SQ_MTYP & seqbuf.seqdat3;
+		break;
+
+	default:	/* something weird got in here */
+
+		return;
+	}
+
+	defmt = seqdfmt[SQ_MACT & act];		/* get data entry format code */
+/* 
+
+*/
+	switch (defmt) {		/* switch off of data entry format */
+
+	case 1:		/* key, port, chan */
+
+		if (inrange(col, 3, 5)) {	/* key */
+
+			if ((col EQ 3) AND (key > 1))
+				return;
+
+			buf[0] = key + '0';
+
+		} else if (col EQ 7) {		/* port */
+
+			if ((key EQ 1) OR (key EQ 2)) {		/* MIDI */
+
+				buf[0] = key + '0';
+
+				UpdVid(7, stccol + 1, " 01", PTDATR);
+				memcpy(&sqdebuf[stccol + 1], " 01", 3);
+
+			} else if (key EQ 3) {			/* local */
+
+				buf[0] = 'L';
+
+				UpdVid(7, stccol + 1, "   ", PTDATR);
+				memset(&sqdebuf[stccol + 1], ' ', 3);
+
+			} else {
+
+				return;
+			}
+
+		} else if (inrange(col, 9, 10)) {	/* channel */
+
+			if ((col EQ 9) AND (key > 1))
+				return;
+
+			buf[0] = key + '0';
+		}
+
+		buf[1] = '\0';
+		sqdebuf[stccol] = buf[0];
+
+		UpdVid(7, stccol, buf, PTDATR);
+
+		if ((col EQ 5) OR (col EQ 7)) {		/* skip blanks */
+
+			++stccol;
+			++col;
+		}
+
+		if (col EQ 10)
+			ctcon();
+		else
+			movestc(stcrow, ++stccol);
+
+		return;
+/* 
+
+*/
+	case 2:		/* trigger */
+
+		if (inrange(col, 9, 10)) {
+
+			if ((col EQ 9) AND (key > 1))
+				return;
+
+		} else {
+
+			return;
+		}
+
+		buf[0] = key + '0';
+		buf[1] = '\0';
+		sqdebuf[stccol] = key + '0';
+
+		UpdVid(7, stccol, buf, PTDATR);
+
+		if (col EQ 10)
+			ctcon();
+		else
+			movestc(stcrow, ++stccol);
+
+		return;
+/* 
+
+*/
+	case 3:		/* register operations */
+
+		if ((col EQ 7) AND (act EQ SQ_AREG)) {
+
+			if (key EQ 8)			/* - */
+				buf[0] = '-';
+			else if (key EQ 9)		/* + */
+				buf[0] = '+';
+			else
+				return;
+
+			buf[1] = '\0';
+			sqdebuf[stccol] = buf[0];
+			UpdVid(7, stccol, buf, PTDATR);
+			movestc(stcrow, ++stccol);
+			return;
+		}
+
+		switch (vtype) {
+
+		case SQ_REG:		/* register contents */
+
+			if (inrange(col, 5, 6) OR inrange(col, 9, 10)) {
+
+				if ( ((col EQ 5) OR (col EQ 9)) AND (key > 1) )
+					return;
+
+			} else {
+
+				return;
+			}
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			sqdebuf[stccol] = key + '0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (col EQ 6) {
+
+				col    += 2;
+				stccol += 2;
+			}
+
+			if (col EQ 10)
+				ctcon();
+			else
+				movestc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case SQ_VAL:		/* constant value */
+
+			if (inrange(col, 5, 6) OR inrange(col, 8, 9)) {
+
+				if ((col EQ 5) AND (key > 1))
+					return;
+
+			} else {
+
+				return;
+			}
+	
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			sqdebuf[stccol] = key + '0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (col EQ 6) {
+
+				++col;
+				++stccol;
+			}
+
+			if (col EQ 9)
+				ctcon();
+			else
+				movestc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case SQ_VLT:		/* voltage input */
+
+			if (inrange(col, 5, 6) OR (col EQ 9)) {
+
+				if ((col EQ 5) AND (key > 1))
+					return;
+				else if ( (col EQ 9) AND ((key < 1) OR (key > 4)) )
+					return;
+
+			} else {
+
+				return;
+			}
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			sqdebuf[stccol] = key + '0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (col EQ 6) {
+
+				col    += 2;
+				stccol += 2;
+			}
+
+			if (col EQ 9)
+				ctcon();
+			else
+				movestc(stcrow, ++stccol);
+
+			return;
+/* 
+
+*/
+		case SQ_RND:		/* random value */
+
+			if (inrange(col, 5, 6) OR (col EQ 9)) {
+
+				if ((col EQ 5) AND (key > 1))
+					return;
+
+				if ((col EQ 9) AND (key > 6))
+					return;
+
+			} else {
+
+				return;
+			}
+
+			buf[0] = key + '0';
+			buf[1] = '\0';
+			sqdebuf[stccol] = key + '0';
+
+			UpdVid(7, stccol, buf, PTDATR);
+
+			if (col EQ 6) {
+
+				col    += 2;
+				stccol += 2;
+			}
+
+			if (col EQ 9)
+				ctcon();
+			else
+				movestc(stcrow, ++stccol);
+
+			return;
+		}
+/* 
+
+*/
+	case 4:		/* sequence line */
+
+		if (inrange(col, 0, 7))
+			return;
+
+		buf[0] = key + '0';
+		buf[1] = '\0';
+		sqdebuf[stccol] = key + '0';
+
+		UpdVid(7, stccol, buf, PTDATR);
+
+		if (col EQ 10)
+			ctcon();
+		else
+			movestc(stcrow, ++stccol);
+
+		return;
+
+	case 0:		/* -none- */
+	default:
+
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqdkey() -- sequence digit data entry control function
+   =============================================================================
+*/
+
+sqdkey()
+{
+	register short key;
+	char buf[8];
+
+	if (NOT astat)			/* only do this on key closures */
+		return;
+
+	if (NOT sqdeflg)		/* load up the edit buffer */
+		seq2buf();
+
+	key = asig - 60;
+
+	if (inrange(stccol, 2, 4)) {			/* line */
+
+		buf[0] = key + '0';
+		buf[1] = '\0';
+
+		sqdebuf[stccol] = key + '0';
+
+		UpdVid(7, stccol, buf, PTDATR);
+
+		if (stccol EQ 4)
+			ctcon();
+		else
+			movestc(stcrow, ++stccol);
+
+		return;
+/* 
+
+*/
+	} else if (inrange(stccol, 6, 10)) {		/* time */
+
+		if (stccol EQ 8)
+			return;
+
+		buf[0] = key + '0';
+		buf[1] = '\0';
+
+		sqdebuf[stccol] = key + '0';
+
+		UpdVid(7, stccol, buf, PTDATR);
+
+		if (stccol EQ 7)
+			++stccol;
+
+		if (stccol EQ 10)
+			ctcon();
+		else
+			movestc(stcrow, ++stccol);
+
+		return;
+
+	} else if (inrange(stccol, 12, 22)) {		/* action 1 */
+
+		action = 0;
+		sqactde(key);
+		return;
+
+	} else if (inrange(stccol, 24, 34)) {		/* action 2 */
+
+		action = 1;
+		sqactde(key);
+		return;
+
+	} else if (inrange(stccol, 36, 46)) {		/* action 3 */
+
+		action = 2;
+		sqactde(key);
+		return;
+	}
+}
Index: ram/sqexec.c
===================================================================
--- ram/sqexec.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqexec.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,439 @@
+/*
+   =============================================================================
+	sqexec.c -- MIDAS-VII sequence action execution code
+	Version 12 -- 1988-12-13 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGSX		0
+#define	DEBUGSP		0
+
+#define	UPD_LINE	1
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "wordq.h"
+#include "patch.h"
+#include "timers.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#if	(DEBUGSP|DEBUGSX)
+extern	short	debugsw;
+#endif
+
+#if	DEBUGSP
+short	debugsp = 1;
+#endif
+
+#if	DEBUGSX
+short	debugsx = 1;
+#endif
+
+extern	unsigned short	setsr();
+extern	long	rand24();
+
+extern	char		trgtab[];
+
+extern	short		curslin;
+extern	short		dsp_ok;
+extern	short		ndisp;
+
+extern	unsigned short	seqdupd;
+
+extern	unsigned short	*obj10;
+
+extern	unsigned short	cg3[];
+
+extern	struct wordq	ptefifo;
+
+short	seqdspn;
+
+short	rtab[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F,
+		   0x003F, 0x003F, 0x003F };
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	evaltv() -- evaluate a typed value
+   =============================================================================
+*/
+
+unsigned short
+evaltv(dat)
+register unsigned short dat;
+{
+	switch (SQ_MTYP & dat) {
+
+	case SQ_REG:	/* register contents */
+
+		return(sregval[SQ_MVAL & dat]);
+
+	case SQ_VAL:	/* constant value */
+
+		return(SQ_MVAL & dat);
+
+	case SQ_VLT:	/* voltage input */
+
+		return(0);
+
+	case SQ_RND:	/* random number */
+
+		return((short)rand24() & rtab[SQ_MVAL & dat]);
+
+	default:	/* something weird got in here ... */
+
+		return(0);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dosqact() -- do a sequence action
+   =============================================================================
+*/
+
+short
+dosqact(seq, act, dat)
+unsigned short seq;
+register unsigned short act, dat;
+{
+	register unsigned short obj, val;
+	register short sv;
+
+	obj = (SQ_MOBJ & act) >> 8;
+	val =  SQ_MVAL & dat;
+
+	switch (SQ_MACT & act) {
+
+	case SQ_NULL:			/* null action */
+
+		return(0);
+
+	case SQ_CKEY:			/* Key closure */
+
+		putwq(&ptefifo, dat & TRG_MASK);
+		return(0);
+
+	case SQ_RKEY:			/* Key release */
+
+		putwq(&ptefifo, dat | 0x8000);
+		return(0);
+
+	case SQ_TKEY:			/* Key transient */
+
+		putwq(&ptefifo, dat & TRG_MASK);	/* closure */
+		putwq(&ptefifo, dat | 0x8000);		/* release */
+		return(0);
+
+	case SQ_IKEY:			/* If key active */
+
+		if (trgtab[TRG_MASK & dat])
+			return(0);
+		else
+			return(1);
+/* 
+
+*/
+	case SQ_STRG:			/* Trigger on */
+
+		trstate[val] = 1;
+		putwq(&ptefifo, (0x1100 | val));
+		seqdupd |= (1 << val);
+		return(0);
+
+	case SQ_CTRG:			/* Trigger off */
+
+		trstate[val] = 0;
+		seqdupd |= (1 << val);
+		return(0);
+
+	case SQ_TTRG:			/* Trigger toggle */
+
+		trstate[val] = trstate[val] ? 0 : 1;
+
+		if (trstate[val])
+			putwq(&ptefifo, (0x1100 | val));
+
+		seqdupd |= (1 << val);
+		return(0);
+
+	case SQ_ITRG:			/* If trigger active */
+
+		return(trstate[val] ? 0 : 1);
+/* 
+
+*/			
+	case SQ_SREG:			/* Set register */
+
+		sregval[obj] = evaltv(dat);
+		seqdupd |= (1 << obj);
+		return(0);
+
+	case SQ_AREG:			/* Increment register */
+
+		if (dat & SQ_MFLG) {
+
+			sv = sregval[obj] - evaltv(dat);
+
+			if (sv < 0)
+				sv = 0;
+
+			sregval[obj] = sv;
+
+		} else {
+
+			sv = sregval[obj] + evaltv(dat);
+
+			if (sv > 99)
+				sv = 99;
+
+			sregval[obj] = sv;
+
+		}
+
+		seqdupd |= (1 << obj);
+		return(0);
+
+	case SQ_IREQ:			/* If register = */
+
+		val = evaltv(dat);
+
+		if (sregval[obj] EQ val)
+			return(0);
+		else
+			return(1);
+
+	case SQ_IRLT:			/* If register < */
+
+		val = evaltv(dat);
+
+		if (sregval[obj] < val)
+			return(0);
+		else
+			return(1);
+
+	case SQ_IRGT:			/* If register > */
+
+		val = evaltv(dat);
+
+		if (sregval[obj] > val)
+			return(0);
+		else
+			return(1);
+/* 
+
+*/
+	case SQ_ISTM:			/* If stimulus active */
+
+		if (trgtab[TRG_MASK & seqstim[seq]])
+			return(0);
+		else
+			return(1);
+
+	case SQ_JUMP:			/* Jump to sequence line */
+
+		seqline[seq]  = dat;
+		seqtime[seq]  = seqtab[dat].seqtime;
+		seqflag[seq] |= SQF_CLK;
+
+		seqdupd |= (1 << seq);
+		return(-1);
+
+
+	case SQ_STOP:			/* Stop sequence */
+	default:
+
+		seqflag[seq] = 0;
+		seqtime[seq] = 0;
+
+		seqdupd |= (1 << seq);
+		return(-1);
+
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqexec() -- execute a line for a sequence
+   =============================================================================
+*/
+
+sqexec(seq)
+register unsigned short seq;
+{
+	register unsigned short act, dat, line;
+	register struct seqent *sp;
+	register short rc;
+
+	line = seqline[seq];
+	sp   = &seqtab[line];
+
+	act = sp->seqact1;	/* do Action 1 */
+	dat = sp->seqdat1;
+
+	rc = dosqact(seq, act, dat);
+
+#if	DEBUGSX
+	if (debugsw AND debugsx)
+		printf("sqexec(%02u):  Line %03u  Act 1 $%04.4X $%04.4X  $%04.4X %d\n",
+			seq, line, act, dat, seqflag[seq], rc);
+#endif
+
+	if (rc EQ 1)		/* skip action 2 */
+		goto act3;
+	else if (rc EQ -1)	/* jump or stop */
+		return;
+
+	act = sp->seqact2;	/* do Action 2 */
+	dat = sp->seqdat2;
+
+	rc = dosqact(seq, act, dat);
+
+#if	DEBUGSX
+	if (debugsw AND debugsx)
+		printf("sqexec(%02u):  Line %03u  Act 2 $%04.4X $%04.4X  $%04.4X %d\n",
+			seq, line, act, dat, seqflag[seq], rc);
+#endif
+
+	if (rc EQ 1)		/* skip action 3 */
+		goto nxtline;
+	else if (rc EQ -1)	/* jump or stop */
+		return;
+
+act3:
+	act = sp->seqact3;	/* do Action 3 */
+	dat = sp->seqdat3;
+
+	rc = dosqact(seq, act, dat);
+
+#if	DEBUGSX
+	if (debugsw AND debugsx)
+		printf("sqexec(%02u):  Line %03u  Act 3 $%04.4X $%04.4X  $%04.4X %d\n",
+			seq, line, act, dat, seqflag[seq], rc);
+#endif
+
+	if (rc EQ -1)		/* jump or stop */
+		return;
+
+nxtline:		/* increment line counter */
+
+	if (++seqline[seq] GE NSLINES)
+		seqline[seq] = 0;
+
+	seqtime[seq] = seqtab[seqline[seq]].seqtime;
+	seqflag[seq] |= SQF_CLK;
+
+#if	DEBUGSX
+	if (debugsw AND debugsx)
+		printf("sqexec(%02u):  Next %03u  %5u  $%04.4X\n",
+			seq, line, seqtime[seq], seqflag[seq]);
+#endif
+
+	seqdupd |= (1 << seq);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	seqproc() -- process sequences
+   =============================================================================
+*/
+
+seqproc()
+{
+	register unsigned short oldsr, seq;
+	register short dspn;
+	register unsigned short *fp;
+	char  linbuf[66];
+
+	if (0 EQ timers[SQTIMER]) {
+
+		for (seq = 0; seq < 16; seq++) {
+
+			fp = &seqflag[seq];
+
+			if ( (SQF_RUN|SQF_CLK) EQ
+			    ((SQF_RUN|SQF_CLK) & *fp) ) {
+
+				if (seqtime[seq]) {
+
+					if (0 EQ --seqtime[seq])
+						*fp &= ~SQF_CLK;
+
+				} else {
+
+					*fp &= ~SQF_CLK;
+				}
+			}
+		}
+
+		oldsr = setsr(0x2700);
+		timers[SQTIMER] = SEQTIME;
+		setsr(oldsr);
+	}
+
+	for (seq = 0; seq < 16; seq++)
+		if (SQF_RUN EQ ((SQF_RUN|SQF_CLK) & seqflag[seq]) )
+			sqexec(seq);
+/* 
+
+*/
+	if (((ndisp EQ 1) OR (ndisp EQ 3)) AND dsp_ok AND seqdupd) {
+
+#if	DEBUGSX
+	if (debugsw AND debugsx)
+		printf("seqproc():  ndisp = %d  seqdupd = $%04.4X\n",
+			ndisp, seqdupd);
+#endif
+		if (seqdupd & (1 << seqdspn)) {
+
+			dspn = seqdspn;
+
+			if (v_regs[5] & 0x0180)
+				vbank(0);
+
+			sprintf(linbuf, "    %03d %02d %c ",
+				seqline[dspn],
+				sregval[dspn],
+				'0' + trstate[dspn]);
+
+			vvputsv(obj10, 16, PDSEQFG, PDSEQBG,
+				dspn, 1, linbuf, 14, 14, cg3);
+
+#if	UPD_LINE
+			sprintf(linbuf, "%02d", dspn + 1);
+
+			vvputsv(obj10, 16,
+				(seqflag[dspn] & SQF_RUN) ?
+				 PDSEQRN : PDSEQFG, PDSEQBG,
+				dspn, 2, linbuf, 14, 14, cg3);
+#else
+			vsetcv(obj10, dspn, 2,
+				( ( (seqflag[dspn] & SQF_RUN) ?
+				  PDSEQRN : PDSEQFG) << 4) | PDSEQBG, 16);
+#endif
+			seqdupd &= ~(1 << dspn);
+		}
+
+		if (++seqdspn > 15)
+			seqdspn = 0;
+	}
+}
Index: ram/sqfield.c
===================================================================
--- ram/sqfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,285 @@
+/*
+   =============================================================================
+	sqfield.c -- MIDAS-VII sequence display field functions
+	Version 9 -- 1989-11-16 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "fields.h"
+#include "curpak.h"
+#include "patch.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+
+short	debugqf = 1;
+#endif
+
+extern	short	(*xy_up)(), (*xy_dn)();
+extern	short	(*premove)(), (*pstmove)();
+extern	short	(*curtype)();
+
+extern	short	select(), nokey(), stdctp5();
+extern	short	cxkstd(), cykstd(), stdmkey(), stddkey();
+extern	short	stopsm(), smxupd(), sqyupd();
+extern	short	postcm();
+
+extern	short	astat;
+extern	short	cmfirst;
+extern	short	cmtype;
+extern	short	curhold;
+extern	short	curslin;
+extern	short	cvtime;
+extern	short	cvwait;
+extern	short	ncvwait;
+extern	short	sqdeflg;
+extern	short	stccol;
+extern	short	ss_ptsw;
+extern	short	ss_sqsw;
+extern	short	syrate;
+extern	short	tvcwval;
+extern	short	vcwval;
+
+extern	short	crate1[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	sqboxes[];
+
+extern	struct	seqent	seqbuf;
+extern	struct	seqent	seqtab[];
+
+extern	char	sqdebuf[];
+
+short	sqxkey();		/* forward reference */
+short	sqekey();		/* forward reference */
+short	sqmkey();		/* forward reference */
+
+/* 
+
+*/
+
+struct curpak sq_flds = {
+
+	stdctp5,		/* curtype */
+	nokey,			/* premove */
+	postcm,			/* pstmove */
+	cxkstd,			/* cx_key */
+	cykstd,			/* cy_key */
+	smxupd,			/* cx_upd */
+	sqyupd,			/* cy_upd */
+	stopsm,			/* xy_up */
+	nokey,			/* xy_dn */
+	sqxkey,			/* x_key */
+	sqekey,			/* e_key */
+	sqmkey,			/* m_key */
+	sqdkey,			/* d_key */
+	nokey,			/* not_fld */
+	(struct fet *)NULL,	/* curfet */
+	sqboxes,		/* csbp */
+	crate1,			/* cratex */
+	crate1,			/* cratey */
+	CT_SMTH,		/* cmtype */
+	CTOX(2),		/* cxval */
+	RTOY(DATAROW)		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqmkey() -- M key processing for the sequence display
+   =============================================================================
+*/
+
+sqmkey()
+{
+	register short nc;
+
+	if (astat) {
+
+		if (stccol EQ 48) {
+
+			if (ss_ptsw EQ 0) {
+
+				(*xy_dn)();		/* handle KEY_DOWN functions */
+
+				(*premove)();		/* handle PRE-MOVE functions */
+
+				nc = (*curtype)();	/* get new CURSOR TYPE wanted */
+
+				cvtime  = syrate;
+				ncvwait = curhold;
+
+				ss_sqsw = -1;
+				cmtype  = nc;
+				cvwait  = 1;
+			}
+
+		} else
+			stdmkey();
+
+	} else {
+
+		if (stccol EQ 48) {
+
+			ss_sqsw = 0;
+			cvwait  = 1;
+			ncvwait = cvtime;
+			cmfirst = TRUE;
+
+			if (ss_ptsw EQ 0)
+				(*xy_up)();
+
+			(*pstmove)();		/* handle POST-MOVE functions */
+
+		} else
+			stdmkey();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqekey() -- E key processing for the sequence display
+   =============================================================================
+*/
+
+sqekey()
+{
+	register short nc;
+
+	if (astat) {
+
+		if (stccol EQ 48) {
+
+			if (ss_ptsw EQ 0) {
+
+				(*xy_dn)();		/* handle KEY_DOWN functions */
+
+				(*premove)();		/* handle PRE-MOVE functions */
+
+				nc = (*curtype)();	/* get new CURSOR TYPE wanted */
+
+				cvtime  = syrate;
+				ncvwait = curhold;
+
+				ss_sqsw = 1;
+				cmtype  = nc;
+				cvwait  = 1;
+			}
+
+		} else
+			select();
+
+	} else {
+
+		if (stccol EQ 48) {
+
+			ss_sqsw = 0;
+			cvwait  = 1;
+			ncvwait = cvtime;
+			cmfirst = TRUE;
+
+			if (ss_ptsw EQ 0)
+				(*xy_up)();
+
+			(*pstmove)();		/* handle POST-MOVE functions */
+
+		} else
+			select();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqxkey() -- delete key handler
+   =============================================================================
+*/
+
+sqxkey()
+{
+	if (NOT astat)
+		return;
+
+	if (inrange(stccol, 2, 4)) {
+
+		memsetw(&seqbuf, 0, NSEQW);
+		memsetw(&seqtab[curslin], 0, NSEQW);
+		dsqlin(sqdebuf, curslin);
+		sqdeflg = TRUE;
+		dcursq();
+
+	} else if (inrange(stccol, 12, 22)) {
+
+		seqtab[curslin].seqact1 = 0;
+		seqtab[curslin].seqdat1 = 0;
+		memcpyw(&seqbuf, &seqtab[curslin], NSEQW);
+		dsqlin(sqdebuf, curslin);
+		sqdeflg = TRUE;
+		dcursq();
+
+	} else if (inrange(stccol, 24, 34)) {
+
+		seqtab[curslin].seqact2 = 0;
+		seqtab[curslin].seqdat2 = 0;
+		memcpyw(&seqbuf, &seqtab[curslin], NSEQW);
+		dsqlin(sqdebuf, curslin);
+		sqdeflg = TRUE;
+		dcursq();
+
+	} else if (inrange(stccol, 36, 46)) {
+
+		seqtab[curslin].seqact3 = 0;
+		seqtab[curslin].seqdat3 = 0;
+		memcpyw(&seqbuf, &seqtab[curslin], NSEQW);
+		dsqlin(sqdebuf, curslin);
+		sqdeflg = TRUE;
+		dcursq();
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqfield() -- setup field routines for the sequence editor
+   =============================================================================
+*/
+
+sqfield()
+{
+
+#if	DEBUGIT
+	if (debugsw AND debugqf)
+		printf("sqfield(): ENTRY\n");
+#endif
+
+	curset(&sq_flds);
+
+#if	DEBUGIT
+	if (debugsw AND debugqf)
+		printf("sqfield(): EXIT\n");
+#endif
+
+}
Index: ram/sqread.c
===================================================================
--- ram/sqread.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqread.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,113 @@
+/*
+   =============================================================================
+	sqread.c -- librarian - read sequence functions
+	Version 2 -- 1988-11-17 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "graphdef.h"
+#include "stddefs.h"
+#include "stdio.h"
+#include "patch.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+extern	short	errno;			/* system error number */
+
+
+/*
+   =============================================================================
+	sqioerr() -- put up an I/O error message
+   =============================================================================
+*/
+
+sqioerr()
+{
+	char erms[40];
+
+	clrlsel();
+
+	sprintf(erms, "  errno = %d", errno);
+
+	ldermsg("Couldn't read", " the sequence table", erms,
+		LD_EMCF, LD_EMCB);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqread() -- read a sequence
+   =============================================================================
+*/
+
+short
+sqread(fp)
+register FILE *fp;
+{
+	char cb;
+	short seq;
+
+	ldwmsg(" Busy -- please stand by", (char *)NULL, "  Reading sequences",
+		LCFBX10, LCBBX10);
+
+	for (;;) {
+
+		if (rd_ec(fp, &cb, 1L)) {	/* get control byte */
+
+			sqioerr();
+			return(FAILURE);
+		}
+
+		if (0 EQ cb)			/* zero control byte is end */
+			return(SUCCESS);
+
+		if (rd_ec(fp, &seq, 2L)) {	/* get Line number */
+
+			sqioerr();
+			return(FAILURE);
+		}
+
+		if (cb & 0x08) {		/* get Time */
+
+			if (rd_ec(fp, &seqtab[seq].seqtime, 2L)) {
+
+				sqioerr();
+				return(FAILURE);
+			}
+		}
+/* 
+
+*/
+		if (cb & 0x04) {		/* get Action 1 */
+
+			if (rd_ec(fp, &seqtab[seq].seqact1, 4L)) {
+
+				sqioerr();
+				return(FAILURE);
+			}
+		}
+
+		if (cb & 0x02) {		/* get Action 2 */
+
+			if (rd_ec(fp, &seqtab[seq].seqact2, 4L)) {
+
+				sqioerr();
+				return(FAILURE);
+			}
+		}
+
+		if (cb & 0x01) {		/* get Action 3 */
+
+			if (rd_ec(fp, &seqtab[seq].seqact3, 4L)) {
+
+				sqioerr();
+				return(FAILURE);
+			}
+		}
+	}
+}
Index: ram/sqscan.c
===================================================================
--- ram/sqscan.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqscan.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1165 @@
+/*
+   =============================================================================
+	sqscan.c -- scan a string and turn it into score events
+	Version 24 -- 1988-06-20 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	CHEKSTOP	1		/* non-zero to trap to ROMP on error */
+
+#include "stddefs.h"
+#include "cmeta.h"
+#include "score.h"
+#include "scfns.h"
+#include "biosdefs.h"
+
+#if	CHEKSTOP
+short	chkstop = TRUE;
+#endif
+
+extern	short	notenum, notepit, curgrp, thescore, verbose;
+extern	short	testing;
+extern	short	sharp, endflg;
+
+extern	long	curtime, noteon, noteoff, noteval, noteper, nrest;
+extern	long	dvwork;
+
+char	*nlist[]  = { "a", "b", "c", "d", "e", "f", "g", NULL };
+
+int	notetab[] = { 0, 2, 3, 5, 7, 8, 10 };
+int	octab[]   = { 21, 33, 45, 57, 69, 81, 93, 105 };
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	nospace(et) -- print error message for no space condition
+   =============================================================================
+*/
+
+nospace(et)
+char *et;
+{
+
+#if	CHEKSTOP
+	if (chkstop) {
+
+		printf("\n** sqscan: ERROR - no space for %s **\n\n", et);
+		xtrap15();	/* ERROR:  trap to ROMP */
+
+		SEsnap();
+		waitcr();
+	}
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Pcheck(ptr, msg) -- check 'ptr' for validity -- output msg if bad.
+	A pointer is invalid if it points outside the score or is null.
+	Returns SUCCESS for a good pointer, FAILURE for a bad one.
+   =============================================================================
+*/
+
+int
+Pcheck(ptr, msg)
+struct s_entry *ptr;
+char *msg;
+{
+	register struct s_entry *cval;
+
+	if (ptr EQ E_NULL) {
+
+		printf("** Pcheck($%08.8lx):  ZERO - %s **\n", ptr, msg);
+
+#if	CHEKSTOP
+		if (chkstop)
+			xtrap15();	/* ERROR:  trap to ROMP */
+#endif
+		return(FAILURE);
+	}
+		
+	cval = spool;
+
+	if (ptr LT cval) {
+
+		printf("** Pcheck($%08.8lx):  LOW - %s **\n", ptr, msg);
+#if	CHEKSTOP
+		if (chkstop)
+			xtrap15();	/* ERROR:  trap to ROMP */
+#endif
+		return(FAILURE);
+	}
+		
+	cval = &spool[(long)MAX_SE-1];
+
+	if (ptr GT cval) {
+
+		printf("** Pcheck($%08.8lx): HIGH - %s **\n", ptr, msg);
+#if	CHEKSTOP
+		if (chkstop)
+			xtrap15();	/* ERROR:  trap to ROMP */
+#endif
+		return(FAILURE);
+	}
+		
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	insnevt() -- insert a note event at t_cur/p_cur
+   =============================================================================
+*/
+
+struct n_entry *
+insnevt(nsp, nt, grp, note, vel)
+register struct n_entry *nsp;
+short nt, grp, note, vel;
+{
+	nsp->e_time  = t_cur;
+	nsp->e_type  = nt;
+	nsp->e_note  = note;
+	nsp->e_group = grp;
+	nsp->e_vel   = vel;
+
+	return(e_ins((struct s_entry *)nsp, ep_adj(p_cur, 0, t_cur))->e_fwd);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Qevent() -- 'event' syntax equation
+   =============================================================================
+*/
+
+int
+Qevent()
+{
+	register int aux1, aux2, aux3, aux4, aux5;
+	register char *chptr;
+	register struct s_entry *tsp1, *tsp2;
+	struct s_entry *tsp3;
+
+	if (!CM_CHR('!'))		/* all commands start with ! */
+		CM_NOGO;
+
+	if (CM_USTR("group")) {		/* !group = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		curgrp = QQnum;
+
+		if (verbose)
+			printf("<Current group = %d>\n", curgrp);
+
+		CM_OK;
+	}
+
+/* 
+
+*/
+	if (CM_USTR("status")) {	/* !status = {on|off} */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (CM_USTR("on")) {
+
+			if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+				nospace("!status=on");
+				CM_NOGO;
+			}
+
+			tsp1->e_time  = t_cur;
+			tsp1->e_type  = EV_GRP;
+			tsp1->e_data1 = curgrp;
+			tsp1->e_data2 = GS_ENBL;
+
+			p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(tsp1, EH_GRP);
+
+			if (verbose)
+				printf("%8ld: Group %d enabled\n",
+					t_cur, curgrp);
+			CM_OK;
+
+		} else if (CM_USTR("off")) {
+
+			if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+				nospace("!status=off");
+				CM_NOGO;
+			}
+
+			tsp1->e_time  = t_cur;
+			tsp1->e_type  = EV_GRP;
+			tsp1->e_data1 = curgrp;
+			tsp1->e_data2 = GS_DSBL;
+
+			p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+			eh_ins(tsp1, EH_GRP);
+
+			if (verbose)
+				printf("%8ld: Group %d disabled\n",
+					t_cur, curgrp);
+			CM_OK;
+
+		} else
+			CM_NOGO;
+	}
+
+/* 
+
+*/
+	if (CM_USTR("tempo")) {		/* !tempo = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		aux1 = QQnum;
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+			nospace("!tempo");
+			CM_NOGO;
+		}
+
+		tsp1->e_time  = t_cur;
+		tsp1->e_type  = EV_TMPO;
+		tsp1->e_data1 = aux1;
+
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+		eh_ins(tsp1, EH_TMPO);
+
+		if (verbose)
+			printf("%8ld: Tempo = %d\n", t_cur, aux1);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("inst")) {		/* !inst = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		aux1 = QQnum;
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+			nospace("!inst");
+			CM_NOGO;
+		}
+
+		tsp1->e_time  = t_cur;
+		tsp1->e_type  = EV_INST;
+		tsp1->e_data1 = curgrp;
+		tsp1->e_data2 = aux1;
+
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+		eh_ins(tsp1, EH_INST);
+
+		if (verbose)
+			printf("%8ld: group %d set to inst %d\n",
+				t_cur, curgrp, aux1);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("tuning")) {	/* !tuning = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		aux1 = QQnum;
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+			nospace("!tuning");
+			CM_NOGO;
+		}
+
+		tsp1->e_time  = t_cur;
+		tsp1->e_type  = EV_TUNE;
+		tsp1->e_data1 = aux1;
+
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+		eh_ins(tsp1, EH_TUNE);
+
+		if (verbose)
+			printf("%8ld: Tuning %d selected\n", t_cur, aux1);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("trans")) {		/* !trans = {+|-} n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (CM_CHR('+')) {
+
+		} else if (CM_CHR('-')) {
+
+		} else
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		aux1 = QQnum;
+
+		if (QQchr EQ '-')
+			aux1 = -aux1;
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+			nospace("!trans");
+			CM_NOGO;
+		}
+
+		tsp1->e_time  = t_cur;
+		tsp1->e_type  = EV_TRNS;
+		tsp1->e_data1 = curgrp;
+		(long)(tsp1->e_lft) = aux1;
+
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+		eh_ins(tsp1, EH_TRNS);
+
+		if (verbose)
+			printf("%8ld: Transposition set to %d\n",
+				t_cur, aux1);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("dyn")) {		/* !dyn = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		aux1 = QQnum;
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+			nospace("!dyn");
+			CM_NOGO;
+		}
+
+		tsp1->e_time  = t_cur;
+		tsp1->e_type  = EV_DYN;
+		tsp1->e_data1 = curgrp;
+		tsp1->e_data2 = aux1;
+
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+		eh_ins(tsp1, EH_DYN);
+
+		if (verbose)
+			printf("%8ld: Dynamics set to %d\n", t_cur, aux1);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("loc")) {		/* !loc = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		aux1 = QQnum;
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE2))) {
+
+			nospace("!loc");
+			CM_NOGO;
+		}
+
+		tsp1->e_time  = t_cur;
+		tsp1->e_type  = EV_LOCN;
+		tsp1->e_data1 = curgrp;
+		tsp1->e_data2 = aux1;
+		
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+		eh_ins(tsp1, EH_LOCN);
+
+		if (verbose)
+			printf("%8ld: Location set to %d\n", t_cur, aux1);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("goto")) {		/* !goto n @ n */
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		curtime = QQnum * 48;
+
+		if (!CM_CHR('@'))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		sc_goto(curtime += QQnum);
+
+		if (verbose)
+			printf("\n<Score time set to %ld>\n", t_cur);
+
+		CM_OK;
+	}
+
+/* 
+
+*/
+
+	if (CM_USTR("pos")) {		/* !pos = n @ n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		curtime = QQnum * 48;
+
+		if (!CM_CHR('@'))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		t_cur = (curtime += QQnum);
+		p_cur = frfind(t_cur, 0);
+
+		if (verbose)
+			printf("\n<Score time set to %ld>\n", t_cur);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("beat")) {		/* !beat = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		t_cur = QQnum * 48;
+		p_cur = frfind(t_cur, 0);
+
+		if (verbose)
+			printf("\n<Score time set to %ld>\n", t_cur);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("frame")) {		/* !frame = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		t_cur = QQnum;
+		p_cur = frfind(t_cur, 0);
+
+		if (verbose)
+			printf("\n<Score time set to %ld>\n", t_cur);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("score")) {		/* !score = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		if (QQnum > 127)
+			CM_NOGO;
+
+		thescore = QQnum;
+
+		selscor(thescore);
+
+		if (verbose)
+			printf("\n<Score %d selected>\n", thescore);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("weight")) {	/* !weight = n */
+
+		if (!CM_CHR('='))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		if (QQnum > 100L)
+			CM_NOGO;
+
+		noteper = QQnum;
+
+		if (verbose)
+			printf("<Note weight = %ld percent>\n", noteper);
+
+		CM_OK;
+	}
+
+	if (CM_USTR("snap")) {		/* !snap */
+
+		SEsnap();
+		CM_OK;
+	}
+
+	if (CM_USTR("wait")) {		/* !wait */
+
+		waitcr();
+		CM_OK;
+	}
+
+	if (CM_USTR("stop")) {		/* !stop */
+
+		if (E_NULL EQ (tsp1 = e_alc(E_SIZE1))) {
+
+			nospace("!stop");
+			CM_NOGO;
+		}
+
+		tsp1->e_time = t_cur;
+		tsp1->e_type = EV_STOP;
+
+		p_cur = e_ins(tsp1, ep_adj(p_cur, 0, t_cur))->e_fwd;
+
+		if (verbose)
+			printf("%8ld: Stop entered\n", t_cur);
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("clear")) {		/* !clear {n | * | $} */
+
+		if (CM_NUM) {
+
+			aux1 = QQnum;
+			sc_clr(aux1);
+
+			if (verbose)
+				printf("\n<Score %d cleared>\n", aux1);
+
+			CM_OK;
+		}
+
+		if (CM_CHR('*')) {
+
+			scinit();
+
+			if (verbose)
+				printf("\n<All scores cleared>\n");
+
+			CM_OK;
+		}
+
+		if (CM_CHR('$')) {
+
+			sc_clr(curscor);
+
+			if (verbose)
+				printf("\n<Current score (%d) cleared>\n", curscor);
+
+			CM_OK;
+		}
+
+		CM_NOGO;
+	}
+/* 
+
+*/
+	if (CM_USTR("show")) {		/* !show {active | names | sections} */
+
+		if (CM_USTR("active")) {
+
+			printf("<Active scores:\n");
+			aux1 = aux2 = 0;
+
+			for (aux3 = 0; aux3 < 4; aux3++) {
+
+				printf("<");
+
+				for (aux4 = 0; aux4 < 16; aux4++) {
+
+					if (scores[aux1]) {
+
+						printf("%3d ", aux1);
+						++aux2;
+
+					} else {
+
+						printf("... ");
+					}
+
+					++aux1;
+				}
+
+				printf(">\n");
+			}
+
+			printf("<%d active scores, score %d is current>\n\n",
+				aux2, curscor);
+			CM_OK;
+		}
+/* 
+
+*/
+		if (CM_USTR("names")) {
+
+			printf("<Active score names:>\n");
+			aux2 = 0;
+
+			for (aux1 = 0; aux1 < 128; aux1++) {
+
+				if (scores[aux1] NE E_NULL) {
+
+					printf("<%3d: ", aux1);
+					chptr = scname[aux1];
+					printf("[$%08.8lx, $%08.8lx] ",
+						scores[aux1], chptr);
+
+					for (aux3 = 0; aux3 < 16; aux3++)
+						printf("%c", (*chptr++ & 0xFF));
+
+					printf(">\n");
+					++aux2;
+				}
+			}
+
+			printf("<%d active scores, %d is current>\n\n",
+				aux2, curscor);
+
+			CM_OK;
+		}
+/* 
+
+*/
+		if (CM_USTR("sections")) {
+
+			printf("<Active sections:>\n");
+			aux1 = aux2 = 0;
+
+			for (aux3 = 0; aux3 < 5; aux3++) {
+
+				printf("<");
+
+				for (aux4 = 0; aux4 < 10; aux4++) {
+
+					if (seclist[curscor][aux1]) {
+
+						printf("%3d ", aux1);
+						++aux2;
+
+					} else {
+
+						printf("... ");
+					}
+
+					++aux1;
+				}
+
+				printf(">\n");
+			}
+
+			printf("<%d active sections, %d is current>\n\n",
+				aux2, cursect);
+			CM_OK;
+		}
+
+		CM_NOGO;
+	}
+/* 
+
+*/
+	if (CM_USTR("find")) {		/* !find {l | r} n */
+
+		if (CM_UCHR('l'))
+			aux1 = 1;
+		else if (CM_UCHR('r'))
+			aux1 = 0;
+		else
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		tsp1 = frfind(QQnum, aux1);
+
+		if (tsp1 NE E_NULL) {
+
+			if (verbose)
+				printf("\n<FIND:  Found %ld at $%08.8lx>\n\n",
+					QQnum, tsp1);
+
+			p_cur = tsp1;
+			t_cur = QQnum;
+
+		} else {
+
+			if (verbose)
+				printf("<FIND:  Found the current score empty>\n\n");
+
+			CM_NOGO;
+		}
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_USTR("chase")) {		/* !chase */
+
+		if (E_NULL EQ (tsp1 = p_cur)) {
+
+			printf("<CHASE:  Current score not active>\n\n");
+			CM_NOGO;
+		}
+
+		tsp2 = tsp1;
+
+		while (tsp2) {
+
+			tsp3 = &spool[0];
+
+			if (tsp2 LT tsp3) {
+
+				printf("\nCHASE:  Error\n");
+				printf("** Bad pointer:  $%08.8lx\n", tsp2);
+				printf("**       spool:  $%08.8lx,  pspool: $%08.8lx\n",
+					&spool[0], pspool);
+				CM_NOGO;
+			}
+
+			tsp3 = &spool[MAX_SE-1];
+
+			if (tsp2 GT tsp3) {
+
+				printf("\nCHASE:  Error\n");
+				printf("** Bad pointer:  $%08.8lx\n", tsp2);
+				printf("**       spool:  $%08.8lx,  pspool: $%08.8lx\n",
+					&spool[0], pspool);
+				CM_NOGO;
+			}
+
+			SEdump(tsp2);
+			tsp2 = tsp2->e_fwd;
+
+			if ((tsp1 EQ tsp2) OR
+			    (tsp2->e_type EQ EV_SCORE)) {
+
+				printf("-- End of chain --\n\n");
+				break;
+			}
+		}
+
+		CM_OK;
+	}
+/* 
+
+*/		
+	if (CM_USTR("verbose")) {	/* !verbose */
+
+		verbose = TRUE;
+		CM_OK;
+	}
+
+	if (CM_USTR("quiet")) {		/* !quiet */
+
+		verbose = FALSE;
+		CM_OK;
+	}
+
+	if (CM_USTR("test")) {		/* !test */
+
+		testing = TRUE;
+		CM_OK;
+	}
+
+	if (CM_USTR("normal")) {	/* !normal */
+
+		testing = FALSE;
+		CM_OK;
+	}
+		
+	if (CM_USTR("end")) {		/* !end */
+
+		if (verbose)
+			printf("\n<End command encountered>\n");
+
+		endflg = TRUE;
+		CM_OK;
+	}
+
+	CM_NOGO;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Qnote() -- 'note' and rest syntax equation
+
+		"val [#] oct [+|-|/n]" | "r n / m"
+		 e.g.:  a#0+ .. a#0- .. c3/4 , r2/1 d3 , e3
+   =============================================================================
+*/
+
+int
+Qnote()
+{
+	struct n_entry *nsp1;
+
+	if (CM_UCHR('r')) {		/* try for a rest */
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		nrest = QQnum;
+
+		if (!CM_CHR('/'))
+			CM_NOGO;
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		dvwork  = 192L;
+		noteval = dvwork / QQnum;
+		t_cur  += (noteval * nrest);
+		p_cur   = ep_adj(p_cur, 0, t_cur);
+
+		if (verbose)
+			printf("%8ld: <rest>\n", t_cur);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (!CM_ULIST(nlist))		/* try for a note */
+		CM_NOGO;
+
+	notepit = QQlnum;
+
+	if (CM_CHR('#'))
+		sharp = 1;
+	else
+		sharp = 0;
+
+	if (!CM_DIG)
+		CM_NOGO;
+
+	if (QQdig > '7')
+		CM_NOGO;
+
+	notenum = octab[QQdig - '0'] + notetab[notepit] + sharp;
+
+	if (CM_CHR('+')) {	/* output note begin */
+
+		if (E_NULL EQ (nsp1 = (struct n_entry *)e_alc(E_SIZE1))) {
+
+			nospace("note event");
+			CM_NOGO;
+		}
+
+		noteon = t_cur;
+		p_cur = insnevt(nsp1, EV_NBEG, curgrp, notenum, 64);
+
+		if (verbose)
+			printf("%8ld: Note %3d ON\n", noteon, notenum);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_CHR('-')) {	/* output note end */
+
+		if (E_NULL EQ (nsp1 = (struct n_entry *)e_alc(E_SIZE1))) {
+
+			nospace("note event");
+			CM_NOGO;
+		}
+
+		noteoff = t_cur;
+		p_cur = insnevt(nsp1, EV_NEND, curgrp, notenum, 64);
+
+		if (verbose)
+			printf("%8ld: Note %3d OFF\n", noteoff, notenum);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	if (CM_CHR('/')) {	/* output note begin and end, given value */
+
+		if (!CM_NUM)
+			CM_NOGO;
+
+		dvwork  = 192L;
+		noteval = dvwork / QQnum;
+		noteon  = t_cur;
+		dvwork  = 100L;
+		noteoff = t_cur + ((noteper * noteval) / dvwork);
+
+		if (E_NULL EQ (nsp1 = (struct n_entry *)e_alc(E_SIZE1))) {
+
+			nospace("note event");
+			CM_NOGO;
+		}
+
+		p_cur = insnevt(nsp1, EV_NBEG, curgrp, notenum, 64);
+
+		if (E_NULL EQ (nsp1 = (struct n_entry *)e_alc(E_SIZE1))) {
+
+			nospace("note event");
+			CM_NOGO;
+		}
+
+		p_cur = ep_adj(p_cur, 0, (t_cur = noteoff));
+
+		insnevt(nsp1, EV_NEND, curgrp, notenum, 64);
+
+		p_cur = ep_adj(p_cur, 0, (t_cur = noteon));
+
+		if (verbose)
+			printf("%8ld: Note %3d ON at %8ld, OFF at %8ld\n",
+				t_cur, notenum, noteon, noteoff);
+
+		CM_OK;
+	}
+/* 
+
+*/
+	/* output note begin and end, use previous value */
+
+	noteon = t_cur;
+	dvwork = 100L;
+	noteoff = t_cur + ((noteval * noteper) / dvwork);
+
+	if (E_NULL EQ (nsp1 = (struct n_entry *)e_alc(E_SIZE1))) {
+
+		nospace("note event");
+		CM_NOGO;
+	}
+
+	p_cur = insnevt(nsp1, EV_NBEG, curgrp, notenum, 64);
+
+	if (E_NULL EQ (nsp1 = (struct n_entry *)e_alc(E_SIZE1))) {
+
+		nospace("note event");
+		CM_NOGO;
+	}
+
+	p_cur = ep_adj(p_cur, 0, (t_cur = noteoff));
+
+	insnevt(nsp1, EV_NEND, curgrp, notenum, 64);
+
+	p_cur = ep_adj(p_cur, 0, (t_cur = noteon));
+
+	if (verbose)		
+		printf("%8ld: Note %3d ON at %8ld, OFF at %8ld\n",
+			t_cur, notenum, noteon, noteoff);
+	CM_OK;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Qadv() -- 'adv' syntax equation
+   =============================================================================
+*/
+
+int
+Qadv()
+{
+	if (CM_CHR('.')) {	/* advance by 1 frame */
+
+		++t_cur;
+		p_cur = ep_adj(p_cur, 0, t_cur);
+		CM_OK;
+	}
+
+	if (CM_CHR(',')) {	/* advance by current note value */
+
+		t_cur += noteval;
+		p_cur = ep_adj(p_cur, 0, t_cur);
+		CM_OK;
+	}
+
+	if (CM_CHR(';')) {	/* avance to next beat */
+
+		dvwork = 48L;
+		t_cur = ((t_cur / dvwork) + 1L) * 48L;
+		p_cur = ep_adj(p_cur, 0, t_cur);
+		CM_OK;
+	}
+
+	if (CM_CHR(':')) {	/* advance by one beat interval */
+
+		t_cur += 48L;
+		p_cur = ep_adj(p_cur, 0, t_cur);
+		CM_OK;
+	}
+
+	CM_NOGO;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	Qseq() -- 'seq' syntax equation
+   =============================================================================
+*/
+
+int
+Qseq()
+{
+	CM_DBLK;
+
+	if (!*QQip)
+		CM_OK;
+
+	if (Qnote() OR Qadv() OR (Qevent() AND !endflg)) {
+
+		CM_DBLK;
+
+		if (!*QQip)
+			return(QQsw);
+
+		while (QQsw AND !endflg) {
+
+			if (!Qadv())
+				if (!Qnote())
+					Qevent();
+
+			CM_DBLK;
+
+			if (!*QQip)
+				return(QQsw);
+		}
+	}
+
+	return(QQsw);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqinit() -- setup score interpreter variables
+   =============================================================================
+*/
+
+sqinit()
+{
+	verbose = FALSE;
+	testing = FALSE;
+	endflg  = FALSE;
+
+	noteval = 48L;		/* default value = 1/4 note  (192/48) */
+	noteper = 80L;		/* default weight = 80 percent */
+
+	curtime = t_cur = t_ctr = 0L;
+	t_bak   = t_cur - TO_BAK;
+	t_fwd   = t_cur + TO_FWD;
+
+	p_bak = p_cur = p_ctr = p_fwd = E_NULL;
+
+	curgrp   = 0;
+	thescore = 0;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqscan(ip) -- scans the string at 'ip' and converts the event
+	descriptions therein to events in the current score.  Returns
+	the value of the parser switch.
+   =============================================================================
+*/
+
+int
+sqscan(ip)
+char *ip;
+{
+	endflg = FALSE;
+	CMinit(ip);
+
+	if (!Qseq())
+		CMstat("Syntax error");
+
+	return(QQsw);
+}
Index: ram/sqselbx.c
===================================================================
--- ram/sqselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,728 @@
+/*
+   =============================================================================
+	sqselbx.c -- MIDAS-VII sequence editor box selection functions
+	Version 19 -- 1988-11-18 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "patch.h"
+#include "macros.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+#define	ST_0		0x01		/* initial Action 1 or Action 2*/
+#define	ST_1		0x02		/* operand type */
+#define	ST_2		0x04		/* initial Action 3*/
+
+#define	ST_OFF		0x00		/* cancel highlighting */
+
+/* 
+
+*/
+
+extern	short	cmtype;
+extern	short	curslin;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	submenu;
+extern	short	vtccol;
+extern	short	vtcrow;
+
+extern	char	actlft[];
+
+extern	short	sqatype[];
+
+extern	unsigned short	*obj11;
+
+extern	struct seqent	seqtab[];
+
+short	action;				/* current action column */
+short	sqdeflg;			/* sequence data entry buffer filled */
+short	sqmenu;				/* sqeuence submenu state */
+
+char	sqdebuf[50];			/* sequence data entry buffer */
+
+struct seqent	seqbuf;			/* sequence line buffer */
+
+short	sqfnbox();
+
+/* 
+
+*/
+
+char	sqhilit[][8] = {		/* submenu highlight table */
+
+	/* start, width, row1, row2, row3, row4, row5, pad */
+
+	{  2,  13,  ST_0|ST_2,  ST_0|ST_2,  ST_0|ST_2,  ST_0,  0,    0},
+	{ 17,  11,  ST_0|ST_2,  ST_0|ST_2,  ST_0|ST_2,  ST_0,  0,    0},
+	{ 30,  11,  ST_0|ST_2,  ST_0|ST_2,  0,          ST_0,  0,    0},
+	{ 43,   8,  ST_0|ST_2,  ST_0|ST_2,  ST_0,       ST_0,  ST_0, 0},
+	{ 53,   8,  ST_1,       ST_1,       ST_1,       ST_1,  0,    0},
+};
+
+struct	selbox	sqboxes[] = {		/* selection boxes */
+
+	{CTOX(1), RTOY(DATAROW), CTOX(48)-1, RTOY(1+DATAROW)-1,   0, sqfnbox},	/* current patch */
+
+	{      0,        0,          0,          0,   0, FN_NULL}
+};
+
+char	sqopreq[] = {		/* action needs operand type flag table */
+
+	0,  0, 0, 0, 0,  0, 0, 0, 0,  1, 1, 1, 1,  0, 0, 0,  1
+};
+
+char	nextact[] = {  24, 36, 6 };	/* next column after action entry */
+
+/* 
+
+*/
+
+short	sqidata[] = {		/* intial data by box */
+
+	0x0000,	/*	"           "	0 */
+	0x0000,	/*	"Kt 001 1 01"	1 */
+	0x0000,	/*	"Kc 001 1 01"	2 */
+	0x0000,	/*	"Kr 001 1 01"	3 */
+	0x0000,	/*	"If 001 1 01"	4 */
+	0x0000,	/*	"Trig on  01"	5 */
+	0x0000,	/*	"Trig off 01"	6 */
+	0x0000,	/*	"Trig tgl 01"	7 */
+	0x0000,	/*	"If trig  01"	8 */
+	0x0000,	/*	"Stop       "	9 */
+	0x0000,	/*	"Jump to 000"	10 */
+	0x0000,	/*	"???????????"	11 */
+	0x0000,	/*	"If stim act"	12 */
+	SQ_VAL,	/*	"Set R01=00 "	13 */
+	SQ_VAL,	/*	"Inc R01+00 "	14 */
+	SQ_VAL,	/*	"If  R01=00 "	15 */
+	SQ_VAL,	/*	"If  R01<00 "	16 */
+	SQ_VAL	/*	"If  R01>00 "	17 */
+};
+
+/* 
+
+*/
+
+char	actcol[] = {			/* action data entry column by action */
+
+	0,  3, 3, 3, 3,  9, 9, 9, 9,  5, 5, 5, 5,  10, 8, 3,  5
+};
+
+char	sqvcol[]  = { 9, 8, 9, 9 };	/* value entry column - type order */
+
+char	seqvcol[] = { 8, 8, 9, 9, 9 };	/* value entry column - box order */
+
+short	sqndata[] = {			/* data types in box order */
+
+	SQ_VAL, SQ_REG, SQ_VLT, SQ_RND
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	hilitsq() -- highlight sequence submenu
+   =============================================================================
+*/
+
+hilitsq(n)
+register char n;
+{
+	register short chr, h, v, w;
+
+	sqmenu = n;				/* set current submenu type */
+
+	for (h = 0; h < 5; h++) {		/* scan the columns */
+
+		for (v = 0; v < 5; v++) {	/* scan the rows */
+
+			chr = sqhilit[h][0];	/* starting character */
+
+			for (w = sqhilit[h][1]; w-- > 0; )
+				vsetcv(obj11, v + 1, chr++,
+					(sqhilit[h][v + 2] & n) ?
+					 PTIATR : PTMATR, 64);
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	postcm() -- determine state after cursor motion
+   =============================================================================
+*/
+
+postcm()
+{
+	if (inrange(stccol, 12, 22)) {
+
+		if (inrange(stccol, 12, 13))
+			hilitsq(ST_0);
+		else if ((sqopreq[seqbuf.seqact1 & SQ_MACT]) AND (stccol EQ 19))
+			hilitsq(ST_1);
+		else
+			hilitsq(ST_OFF);
+
+		return;
+
+	} else if (inrange(stccol, 24, 34)) {
+
+		if (inrange(stccol, 24, 25))
+			hilitsq(ST_0);
+		else if ((sqopreq[seqbuf.seqact2 & SQ_MACT]) AND (stccol EQ 31))
+			hilitsq(ST_1);
+		else
+			hilitsq(ST_OFF);
+
+		return;
+
+	} else if (inrange(stccol, 36, 46)) {
+
+		if (inrange(stccol, 36, 37))
+			hilitsq(ST_2);
+		else if ((sqopreq[seqbuf.seqact3 & SQ_MACT]) AND (stccol EQ 43))
+			hilitsq(ST_1);
+		else
+			hilitsq(ST_OFF);
+
+		return;
+
+	} else {
+
+		hilitsq(ST_OFF);
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	movestc() -- move cursor and reset highlighting
+   =============================================================================
+*/
+
+movestc(r, c)
+short r, c;
+{
+	ctcpos(r, c);
+	postcm();
+}
+
+/*
+   =============================================================================
+	endssm() -- end patch submenu data entry
+   =============================================================================
+*/
+
+endssm(row, col)
+short row, col;
+{
+	submenu = FALSE;
+	cmtype  = CT_SMTH;
+
+	mtcoff();
+	ctcon();
+	movestc(row, col);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	setsqm() -- setup submenu
+   =============================================================================
+*/
+
+setsqm(r, c)
+short r, c;
+{
+	submenu = TRUE;
+	cmtype  = CT_MENU;
+	mtcpos(r, c);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqenter() -- enter an action
+   =============================================================================
+*/
+
+short
+sqenter()
+{
+	register short i, lcol;
+	register long ltemp;
+	register unsigned short *ap, *dp;
+	unsigned short theact, port, chan, key, val, obj, dtype;
+
+	switch (action) {
+
+	case 0:
+
+		ap   = &seqbuf.seqact1;
+		dp   = &seqbuf.seqdat1;
+		break;
+
+	case 1:
+
+		ap   = &seqbuf.seqact2;
+		dp   = &seqbuf.seqdat2;
+		break;
+
+	case 2:
+
+		ap   = &seqbuf.seqact3;
+		dp   = &seqbuf.seqdat3;
+		break;
+
+	default:
+
+		action = 0;
+		movestc(DATAROW, actlft[action]);
+		return(FAILURE);
+	}
+
+/* 
+
+*/
+	lcol   = actlft[action];
+	theact = SQ_MACT & *ap;
+
+	switch (theact) {
+
+	case SQ_TKEY:	/*	"Kt 001 1 01" */
+	case SQ_CKEY:	/*	"Kc 001 1 01" */
+	case SQ_RKEY:	/*	"Kr 001 1 01" */
+	case SQ_IKEY:	/*	"If 001 1 01" */
+
+		ltemp = 0;
+
+		for (i = lcol + 3; i < lcol + 6; i++)
+			ltemp = (ltemp * 10) + (sqdebuf[i] - '0');
+
+		if ((ltemp < 1L) OR (ltemp > 128L)) {
+
+			movestc(DATAROW, actlft[action] + 3);
+			return(FAILURE);
+		}
+
+		key = ltemp - 1;
+/* 
+
+*/
+		i = sqdebuf[lcol + 7];
+
+		if ((i EQ '1') OR (i EQ '2')) {
+
+			port = i - '1';
+
+		} else if (i EQ 'L') {
+
+			port = 2;
+
+		} else {
+
+			movestc(DATAROW, actlft[action] + 7);
+			return(FAILURE);
+		}
+
+		ltemp = ((sqdebuf[lcol +  9] - '0') * 10) +
+			 (sqdebuf[lcol + 10] - '0');
+
+		if ((ltemp < 1L) OR (ltemp > 16L)) {
+
+			movestc(DATAROW, actlft[action] + 9);
+			return(FAILURE);
+		}
+
+		chan = ltemp - 1;
+		*dp = (port << 11) | (chan << 7) | key;
+
+		break;
+/* 
+
+*/
+	case SQ_STRG:	/*	"Trig on  01" */
+	case SQ_CTRG:	/*	"Trig off 01" */
+	case SQ_TTRG:	/*	"Trig tgl 01" */
+
+		ltemp = ((sqdebuf[lcol +  9] - '0') * 10)+
+			 (sqdebuf[lcol + 10] - '0');
+
+		if ((ltemp < 1L) OR (ltemp > 16)) {
+
+			movestc(DATAROW, actlft[action] + 9);
+			return(FAILURE);
+		}
+
+		*dp = ltemp - 1;
+
+		break;
+
+	case SQ_NULL:	/*	"           " */
+	case SQ_ITRG:	/*	"If trig act" */
+	case SQ_STOP:	/*	"Stop       " */
+	case SQ_ISTM:	/*	"If stim act" */
+
+		break;
+
+	case SQ_JUMP:	/*	"Jump to 000" */
+
+		ltemp = 0;
+
+		for (i = lcol + 8; i < lcol + 11; i++)
+			ltemp = (ltemp * 10) + (sqdebuf[i] - '0');
+
+		*dp = ltemp;
+
+		break;
+/* 
+
+*/
+	case SQ_SREG:	/*	"Set R01=00 " */
+	case SQ_AREG:	/*	"Inc R01+00 " */
+	case SQ_IREQ:	/*	"If  R01=00 " */
+	case SQ_IRLT:	/*	"If  R01<00 " */
+	case SQ_IRGT:	/*	"If  R01>00 " */
+
+		dtype = *dp & SQ_MTYP;
+
+		ltemp = ((sqdebuf[lcol + 5] - '0') * 10) +
+			 (sqdebuf[lcol + 6] - '0');
+
+		if ((ltemp < 1) OR (ltemp > 16)) {
+
+			movestc(DATAROW, actlft[action] + 5);
+			return(FAILURE);
+		}
+
+		obj = ltemp - 1;
+
+		switch (dtype) {
+
+		case SQ_REG:	/* register */
+
+			ltemp = ((sqdebuf[lcol +  9] - '0') * 10) +
+				 (sqdebuf[lcol + 10] - '0');
+
+			if ((ltemp < 1) OR (ltemp > 16)) {
+
+				movestc(DATAROW, actlft[action] + 9);
+				return(FAILURE);
+			}
+
+			val = ltemp - 1;
+			break;
+
+		case SQ_VAL:	/* constant value */
+
+			val = ((sqdebuf[lcol + 8] - '0') * 10) +
+			       (sqdebuf[lcol + 9] - '0');
+
+			break;
+/* 
+
+*/
+		case SQ_VLT:	/* control voltage */
+
+			val = (sqdebuf[lcol + 9] - '0') - 1;
+			break;
+
+		case SQ_RND:	/* random value */
+
+			val = sqdebuf[lcol + 9] - '0';
+			break;
+
+		default:
+
+			movestc(DATAROW, actlft[action] + 8);
+			return(FAILURE);
+		}
+
+		if (((*ap & SQ_MACT) EQ SQ_AREG) AND
+		    (sqdebuf[lcol + 7] EQ '-'))
+			val |= 0x1000;
+
+		*ap = (*ap & SQ_MACT) | (obj << 8);
+		*dp = (*dp & SQ_MTYP) | val;
+
+		break;
+
+	default:
+
+		movestc(DATAROW, actlft[action]);
+		return(FAILURE);
+	}
+/* 
+
+*/
+	memcpyw(&seqtab[curslin], &seqbuf, NSEQW);
+	dsqlin(sqdebuf, curslin);
+	sqdeflg = TRUE;
+	dcursq();
+	movestc(DATAROW, nextact[action]);
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqfnbox() -- sequence display box hit processor
+   =============================================================================
+*/
+
+short
+sqfnbox(n)
+short n;
+{
+	short act, vtype;
+	register short box;
+	register short i;
+	register long ltemp;
+
+	if (NOT submenu) {			/* SEQUENCE DATA ENTRY LINE */
+
+		if (inrange(stccol, 2, 4)) {		/* Line */
+
+			ltemp = 0;
+
+			for (i = 2; i < 5; i++)
+				ltemp = (ltemp * 10) + (sqdebuf[i] - '0');
+
+			curslin = ltemp;
+			sqdeflg = FALSE;
+			dstw();
+			movestc(DATAROW, 2);
+			return(SUCCESS);
+
+		} else if (inrange(stccol, 6, 10)) {	/* Time */
+
+			ltemp = 0;
+
+			for (i = 6; i < 8; i++)
+				ltemp = (ltemp * 10) + (sqdebuf[i] - '0');
+
+			for (i = 9; i < 11; i++)
+				ltemp = (ltemp * 10) + (sqdebuf[i] - '0');
+
+			seqtab[curslin].seqtime = ltemp;
+			seqbuf.seqtime = ltemp;
+			dsqlin(sqdebuf, curslin);
+			sqdeflg = TRUE;
+			dcursq();
+			movestc(DATAROW, 12);
+			return(SUCCESS);
+/* 
+
+*/
+		} else if (inrange(stccol, 12, 22)) {	/* Action 1 */
+
+			action = 0;
+
+			if (inrange(stccol, 12, 13)) {
+
+				setsqm(19, 2);
+				return(SUCCESS);
+
+			} else if ((sqopreq[seqbuf.seqact1 & SQ_MACT]) AND
+				(stccol EQ 19)) {
+
+				setsqm(19, 53);
+				return(SUCCESS);
+
+			} else {
+
+				return(sqenter());
+			}
+
+		} else if (inrange(stccol, 24, 34)) {	/* Action 2 */
+
+			action = 1;
+
+			if (inrange(stccol, 24, 25)) {
+
+				setsqm(19, 2);
+				return(SUCCESS);
+
+			} else if ((sqopreq[seqbuf.seqact2 & SQ_MACT]) AND
+				(stccol EQ 31)) {
+
+				setsqm(19, 53);
+				return(SUCCESS);
+
+			} else {
+
+				return(sqenter());
+			}
+/* 
+
+*/
+		} else if (inrange(stccol, 36, 46)) {	/* Action 3 */
+
+			action = 2;
+
+			if (inrange(stccol, 36, 37)) {
+
+				setsqm(19, 2);
+				return(SUCCESS);
+
+			} else if ((sqopreq[seqbuf.seqact3 & SQ_MACT]) AND
+				(stccol EQ 43)) {
+
+				setsqm(19, 53);
+				return(SUCCESS);
+
+			} else {
+
+				return(sqenter());
+			}
+
+		} else
+			return(FAILURE);
+/* 
+
+*/
+	} else {				/* SUBMENU SELECTION */
+
+		/* determine the "box" we're pointing at */
+
+		if (inrange(vtccol, 2, 14))
+			box = vtcrow - 18;
+		else if (inrange(vtccol, 17, 27))
+			box = vtcrow - 14;
+		else if (inrange(vtccol, 30, 40))
+			box = vtcrow - 10;
+		else if (inrange(vtccol, 43, 50))
+			box = vtcrow - 6;
+		else if (inrange(vtccol, 53, 60))
+			box = vtcrow - 1;
+		else
+			return(FAILURE);
+/* 
+
+*/
+		switch (sqmenu) {	/* switch on submenu type */
+
+		case ST_0:	/* Action 1 or Action 2 type */
+		case ST_2:	/* Action 3 type */
+
+			if (inrange(box, 18, 21))
+				return(FAILURE);
+
+			switch (action) {
+
+			case 0:		/* action 1 */
+
+				act   = SQ_MACT & (seqbuf.seqact1 = sqatype[box]);
+				vtype = 0x000F & ((seqbuf.seqdat1 = sqidata[box]) >> 8);
+				break;
+
+			case 1:		/* action 2 */
+
+				act   = SQ_MACT & (seqbuf.seqact2 = sqatype[box]);
+				vtype = 0x000F & ((seqbuf.seqdat2 = sqidata[box]) >> 8);
+				break;
+
+			case 2:		/* action 3 */
+
+				if ((box EQ 4) OR (box EQ 8) OR (box EQ 12) OR
+				    inrange(box, 15, 17))
+					return(FAILURE);
+
+				act   = SQ_MACT & (seqbuf.seqact3 = sqatype[box]);
+				vtype = 0x000F & ((seqbuf.seqdat3 = sqidata[box]) >> 8);
+				break;
+			}
+
+			memcpyw(&seqtab[curslin], &seqbuf, NSEQW);
+			dsqlin(sqdebuf, curslin);
+			sqdeflg = TRUE;
+			dcursq();
+
+			if (sqopreq[act])
+				endssm(stcrow, actlft[action] + sqvcol[vtype]);
+			else if ((act EQ SQ_ISTM) OR (act EQ SQ_STOP))
+				endssm(stcrow, nextact[action]);
+			else
+				endssm(stcrow, actlft[action] + actcol[act]);
+
+			return(SUCCESS);
+/* 
+
+*/
+		case ST_1:	/* operand type */
+
+			if (NOT inrange(box, 18, 21))
+				return(FAILURE);
+
+			switch (action) {
+
+			case 0:		/* action 1 */
+
+				if (NOT sqopreq[act = SQ_MACT & seqbuf.seqact1])
+					return(FAILURE);
+
+				seqbuf.seqdat1 = (seqbuf.seqdat1 & SQ_MFLG) | sqndata[box - 18];
+				break;
+
+			case 1:		/* action 2 */
+
+				if (NOT sqopreq[act = SQ_MACT & seqbuf.seqact2])
+					return(FAILURE);
+
+				seqbuf.seqdat2 = (seqbuf.seqdat2 & SQ_MFLG) | sqndata[box - 18];
+				break;
+
+			case 2:		/* action 3 */
+
+				if (NOT sqopreq[act = SQ_MACT & seqbuf.seqact3])
+					return(FAILURE);
+
+				seqbuf.seqdat3 = (seqbuf.seqdat3 & SQ_MFLG) | sqndata[box - 18];
+				break;
+			}
+
+			break;
+
+		default:	/* -BOGUS- */
+
+			endssm(stcrow, stccol);
+			return(FAILURE);
+		}
+
+		memcpyw(&seqtab[curslin], &seqbuf, NSEQW);
+		dsqlin(sqdebuf, curslin);
+		sqdeflg = TRUE;
+		dcursq();
+		endssm(stcrow, actlft[action] + seqvcol[box - 18]);
+		return(SUCCESS);
+	}
+
+	return(FAILURE);
+}
Index: ram/sqwrite.c
===================================================================
--- ram/sqwrite.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sqwrite.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,155 @@
+/*
+   =============================================================================
+	sqwrite.c -- librarian - write sequence functions
+	Version 2 -- 1988-11-17 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "stdio.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "patch.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+#if	DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	long	chksum();
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqsizer() -- return number of bytes necessary for storing
+		active sequence lines
+   =============================================================================
+*/
+
+long
+sqsizer()
+{
+	register short i, na;
+	register long nb;
+
+	nb = 0L;
+
+	for (i = 0; i < NSLINES; i++) {
+
+		na = 0;
+
+		if (seqtab[i].seqtime)		/* check the time */
+			na += 2L;
+
+		if (seqtab[i].seqact1)		/* check action 1 */
+			na += 4L;
+
+		if (seqtab[i].seqact2)		/* check action 2 */
+			na += 4L;
+
+		if (seqtab[i].seqact3)		/* check action 3 */
+			na += 4L;
+
+		if (na)				/* tote up the result */
+			nb += (na + 3);
+	}
+
+	if (nb)
+		++nb;
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sqsizer():  %ld bytes required\n", nb);
+#endif
+
+	return(nb);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	sqwrite() -- store a sequence table
+   =============================================================================
+*/
+
+short
+sqwrite(fp)
+register FILE *fp;
+{
+	short seq;
+	char cb, zero;
+	char scid[48];
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sqwrite($%08lX):  entered\n", fp);
+#endif
+
+	zero = 0;
+
+	ldwmsg("Busy -- Please stand by", (char *)0L, "  writing sequences",
+		LCFBX10, LCBBX10);
+
+	for (seq = 0; seq < NSLINES; seq++) {
+
+		cb = 0x00;
+
+		if (seqtab[seq].seqtime)
+			cb |= 0x08;
+
+		if (seqtab[seq].seqact1)
+			cb |= 0x04;
+
+		if (seqtab[seq].seqact2)
+			cb |= 0x02;
+
+		if (seqtab[seq].seqact3)
+			cb |= 0x01;
+
+		if (0 EQ cb)
+			continue;
+
+		if (wr_ec(fp, &cb, 1L))		/* Control byte */
+			return(FAILURE);
+
+		if (wr_ec(fp, &seq, 2L))	/* Line number */
+			return(FAILURE);
+
+		if (cb & 0x08)			/* Time */
+			if (wr_ec(fp, &seqtab[seq].seqtime, 2L))
+				return(FAILURE);
+
+		if (cb & 0x04)			/* Action 1 */
+			if (wr_ec(fp, &seqtab[seq].seqact1, 4L))
+				return(FAILURE);
+
+		if (cb & 0x02)			/* Action 2 */
+			if (wr_ec(fp, &seqtab[seq].seqact2, 4L))
+				return(FAILURE);
+
+		if (cb & 0x01)			/* Action 3 */
+			if (wr_ec(fp, &seqtab[seq].seqact3, 4L))
+				return(FAILURE);
+	}
+
+	if (wr_ec(fp, &zero, 1L))		/* terminator */
+		return(FAILURE);
+
+#if	DEBUGIT
+	if (debugsw)
+		printf("sqwrite():  SUCCESS\n");
+#endif
+
+	return(SUCCESS);
+}
Index: ram/sreset.s
===================================================================
--- ram/sreset.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/sreset.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,995 @@
+* ------------------------------------------------------------------------------
+* sreset.s -- reset score highlighting
+* Version 14 -- 1988-07-28 -- D.N. Lynx Crowe
+* ------------------------------------------------------------------------------
+		.text
+*
+		.xdef	_sreset		* sreset()
+*
+		.xref	_vputa		* vputa(sbase, row, col, attrib)
+*
+		.xref	_ndisp		* WORD - display number
+		.xref	_obj8		* LONG - object base address
+		.xref	_vrbw08		* WORD - detail word for bit 8
+		.xref	_vrbw09		* WORD - detail word for bit 9
+		.xref	_vrbw10		* WORD - detail word for bit 10
+		.xref	_vrbw11		* WORD - detail word for bit 11
+		.xref	_vrbw12		* WORD - detail word for bit 12
+		.xref	_vrbw13		* WORD - detail word for bit 13
+		.xref	_vrbw14		* WORD - detail word for bit 14
+		.xref	_vrbw15		* WORD - detail word for bit 15
+		.xref	_vrcw		* WORD - video reset control word
+*
+ROW		.equ	4
+COL		.equ	6
+ATR		.equ	8
+*
+AT01		.equ	$0014
+AT04		.equ	$0013
+AT05		.equ	$0014
+AT06		.equ	$0013
+AT07		.equ	$0014
+AT08		.equ	$0013
+AT09		.equ	$0014
+AT10		.equ	$0013
+AT11		.equ	$0012
+AT12		.equ	$0012
+*
+		.page
+*
+* sreset() -- reset highlighting
+* --------    ------------------
+_sreset:	link	a6,#0		* link stack frame
+		cmp.w	#2,_ndisp	* see if we should update display
+		bne	srsexit		* jump if not
+*
+		move.w	_vrcw,d0	* get and check vrcw
+		bne	srs0		* jump if something to do
+*
+srsexit:	unlk	a6		* unlink stack frame
+		rts			* return to caller
+*
+srs0:		move.w	sr,d1		* <<<<< disable interrupts >>>>>
+		ori.w	#$0700,sr	* ...
+*
+		move.w	_vrcw,vrcw	* make local copies of control variables
+		clr.w	_vrcw		* ... and clear them for the next pass
+		move.w	_vrbw08,vrbw08	* ...
+		clr.w	_vrbw08		* ...
+		move.w	_vrbw09,vrbw09	* ...
+		clr.w	_vrbw09		* ...
+		move.w	_vrbw10,vrbw10	* ...
+		clr.w	_vrbw10		* ...
+		move.w	_vrbw11,vrbw11	* ...
+		clr.w	_vrbw11		* ...
+		move.w	_vrbw12,vrbw12	* ...
+		clr.w	_vrbw12		* ...
+		move.w	_vrbw13,vrbw13	* ...
+		clr.w	_vrbw13		* ...
+		move.w	_vrbw14,vrbw14	* ...
+		clr.w	_vrbw14		* ...
+		move.w	_vrbw15,vrbw15	* ...
+		clr.w	_vrbw15		* ...
+*
+		move.w	d1,sr		* <<<<< restore interrupts >>>>>
+*
+* Setup STACK for subsequent calls to vputa(sbase, row, col, atr):
+*
+*	0(a7)	sbase
+*
+*	4(a7)	row	ROW
+*	6(a7)	col	COL
+*	8(a7)	atr	ATR
+*
+		clr.w	-(a7)		* put dummy attribute on stack
+		clr.w	-(a7)		* put dummy column on stack
+		clr.w	-(a7)		* put dummy row on stack
+		move.l	_obj8,-(a7)	* put sbase on stack
+*
+		.page
+*
+* assignment
+* ----------
+		btst	#0,d0		* assignment ?
+		beq	srs1		* jump if not
+*
+		move.w	#AT04,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#11,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#12,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+* tuning
+* ------
+srs1:		btst	#1,d0		* tuning ?
+		beq	srs2		* jump if not
+*
+		move.w	#AT05,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#19,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+* tempo
+* -----
+srs2:		btst	#2,d0		* tempo ?
+		beq	srs3		* jump if not
+*
+		move.w	#AT06,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#27,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#28,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#29,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* interpolate
+* -----------
+srs3:		btst	#3,d0		* interpolate ?
+		beq	srs4		* jump if not
+*
+		move.w	#AT07,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#35,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#36,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#37,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#38,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+* section begin
+* -------------
+srs4:		btst	#4,d0		* section begin ?
+		beq	srs5		* jump if not
+*
+		move.w	#AT01,ATR(a7)	* put attribute on stack
+		move.w	#0,ROW(a7)	* put row on stack
+		move.w	#6,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#7,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+*
+		.page
+*
+* punch in
+* --------
+srs5:		btst	#5,d0		* punch in ?
+		beq	srs6		* jump if not
+*
+		move.w	#AT09,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#50,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#51,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+* punch out
+* ---------
+srs6:		btst	#6,d0		* punch out ?
+		beq	srs7		* jump if not
+*
+		move.w	#AT09,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#53,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#54,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#55,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+* Output
+* ------
+srs7:		btst	#7,d0		* output ?
+		beq	srs8		* jump if not
+*
+		move.w	#AT10,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#57,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#58,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#59,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#60,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#61,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+		move.w	#62,COL(a7)	* put 6th column on stack
+		jsr	_vputa		* reset sixth column
+		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* instrument
+* ----------
+srs8:		btst	#8,d0		* instrument ?
+		beq	srs9		* jump if not
+*
+		move.w	#2,ROW(a7)	* put row on stack
+		move.w	#AT11,ATR(a7)	* put attribute on stack
+		btst	#0,vrbw08+1	* group 1 ?
+		beq	srs8a		* jump if not
+*
+		move.w	#7,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#8,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+*
+srs8a:		btst	#1,vrbw08+1	* group 2 ?
+		beq	srs8b		* jump if not
+*
+		move.w	#12,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#13,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8b:		btst	#2,vrbw08+1	* group 3 ?
+		beq	srs8c		* jump if not
+*
+		move.w	#17,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#18,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8c:		btst	#3,vrbw08+1	* group 4 ?
+		beq	srs8d		* jump if not
+*
+		move.w	#22,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#23,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+		.page
+*
+srs8d:		btst	#4,vrbw08+1	* group 5 ?
+		beq	srs8e		* jump if not
+*
+		move.w	#27,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#28,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8e:		btst	#5,vrbw08+1	* group 6 ?
+		beq	srs8f		* jump if not
+*
+		move.w	#32,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#33,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8f:		btst	#6,vrbw08+1	* group 7 ?
+		beq	srs8g		* jump if not
+*
+		move.w	#37,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#38,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8g:		btst	#7,vrbw08+1	* group 8 ?
+		beq	srs8h		* jump if not
+*
+		move.w	#42,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#43,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+		.page
+*
+srs8h:		btst	#0,vrbw08	* group 9
+		beq	srs8j		* jump if not
+*
+		move.w	#47,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#48,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8j:		btst	#1,vrbw08	* group 10
+		beq	srs8k		* jump if not
+*
+		move.w	#52,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#53,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8k:		btst	#2,vrbw08	* group 11
+		beq	srs8m		* jump if not
+*
+		move.w	#57,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#58,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8m:		btst	#3,vrbw08	* group 12
+		beq	srs8x		* jump if not
+*
+		move.w	#62,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first character
+		move.w	#63,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second character
+*
+srs8x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* transpose
+* ---------
+srs9:		btst	#9,d0		* transpose ?
+		beq	srs10		* jump if not
+*
+		move.w	#AT11,ATR(a7)	* put attribute on stack
+		move.w	#3,ROW(a7)	* put row on stack
+		btst	#0,vrbw09+1	* group 1 ?
+		beq	srs9a		* jump if not
+*
+		move.w	#5,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#6,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#7,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#8,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9a:		btst	#1,vrbw09+1	* group 2 ?
+		beq	srs9b		* jump if not
+*
+		move.w	#10,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#11,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#12,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#13,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9b:		btst	#2,vrbw09+1	* group 3 ?
+		beq	srs9c		* jump if not
+*
+		move.w	#15,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#16,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#17,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#18,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+		.page
+*
+srs9c:		btst	#3,vrbw09+1	* group 4 ?
+		beq	srs9d		* jump if not
+*
+		move.w	#20,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#21,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#22,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#23,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9d:		btst	#4,vrbw09+1	* group 5 ?
+		beq	srs9e		* jump if not
+*
+		move.w	#25,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#26,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#27,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#28,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9e:		btst	#5,vrbw09+1	* group 6 ?
+		beq	srs9f		* jump if not
+*
+		move.w	#30,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#31,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#32,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#33,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+		.page
+*
+srs9f:		btst	#6,vrbw09+1	* group 7 ?
+		beq	srs9g		* jump if not
+*
+		move.w	#35,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#36,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#37,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#38,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9g:		btst	#7,vrbw09+1	* group 8 ?
+		beq	srs9h		* jump if not
+*
+		move.w	#40,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#41,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#42,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#43,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9h:		btst	#0,vrbw09	* group 9
+		beq	srs9j		* jump if not
+*
+		move.w	#45,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#46,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#47,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#48,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+		.page
+*
+srs9j:		btst	#1,vrbw09	* group 10
+		beq	srs9k		* jump if not
+*
+		move.w	#50,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#51,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#52,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#53,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9k:		btst	#2,vrbw09	* group 11
+		beq	srs9m		* jump if not
+*
+		move.w	#55,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#56,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#57,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#58,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9m:		btst	#3,vrbw09	* group 12
+		beq	srs9x		* jump if not
+*
+		move.w	#60,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#61,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#62,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#63,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs9x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* dynamics
+* --------
+srs10:		btst	#10,d0		* dynamics ?
+		beq	srs11		* jump if not
+*
+		move.w	#AT11,ATR(a7)	* put attribute on stack
+		move.w	#4,ROW(a7)	* put row on stack
+		btst	#0,vrbw10+1	* group 1 ?
+		beq	srs10a		* jump if not
+*
+		move.w	#6,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10a:		btst	#1,vrbw10+1	* group 2 ?
+		beq	srs10b		* jump if not
+*
+		move.w	#11,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10b:		btst	#2,vrbw10+1	* group 3 ?
+		beq	srs10c		* jump if not
+*
+		move.w	#16,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10c:		btst	#3,vrbw10+1	* group 4 ?
+		beq	srs10d		* jump if not
+*
+		move.w	#21,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+		.page
+*
+srs10d:		btst	#4,vrbw10+1	* group 5 ?
+		beq	srs10e		* jump if not
+*
+		move.w	#26,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10e:		btst	#5,vrbw10+1	* group 6 ?
+		beq	srs10f		* jump if not
+*
+		move.w	#31,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10f:		btst	#6,vrbw10+1	* group 7 ?
+		beq	srs10g		* jump if not
+*
+		move.w	#36,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10g:		btst	#7,vrbw10+1	* group 8 ?
+		beq	srs10h		* jump if not
+*
+		move.w	#41,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+		.page
+*
+srs10h:		btst	#0,vrbw10	* group 9
+		beq	srs10j		* jump if not
+*
+		move.w	#46,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10j:		btst	#1,vrbw10	* group 10
+		beq	srs10k		* jump if not
+*
+		move.w	#51,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10k:		btst	#2,vrbw10	* group 11
+		beq	srs10m		* jump if not
+*
+		move.w	#56,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10m:		btst	#3,vrbw10	* group 12
+		beq	srs10x		* jump if not
+*
+		move.w	#61,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs10x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* location
+* --------
+srs11:		btst	#11,d0		* location ?
+		beq	srs12		* jump if not
+*
+		move.w	#AT11,ATR(a7)	* put attribute on stack
+		move.w	#4,ROW(a7)	* put row on stack
+		btst	#0,vrbw11+1	* group 1 ?
+		beq	srs11a		* jump if not
+*
+		move.w	#8,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11a:		btst	#1,vrbw11+1	* group 2 ?
+		beq	srs11b		* jump if not
+*
+		move.w	#13,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11b:		btst	#2,vrbw11+1	* group 3 ?
+		beq	srs11c		* jump if not
+*
+		move.w	#18,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11c:		btst	#3,vrbw11+1	* group 4 ?
+		beq	srs11d		* jump if not
+*
+		move.w	#23,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+		.page
+*
+srs11d:		btst	#4,vrbw11+1	* group 5 ?
+		beq	srs11e		* jump if not
+*
+		move.w	#28,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11e:		btst	#5,vrbw11+1	* group 6 ?
+		beq	srs11f		* jump if not
+*
+		move.w	#33,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11f:		btst	#6,vrbw11+1	* group 7 ?
+		beq	srs11g		* jump if not
+*
+		move.w	#38,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11g:		btst	#7,vrbw11+1	* group 8 ?
+		beq	srs11h		* jump if not
+*
+		move.w	#43,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+		.page
+*
+srs11h:		btst	#0,vrbw11	* group 9
+		beq	srs11j		* jump if not
+*
+		move.w	#48,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11j:		btst	#1,vrbw11	* group 10
+		beq	srs11k		* jump if not
+*
+		move.w	#53,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11k:		btst	#2,vrbw11	* group 11
+		beq	srs11m		* jump if not
+*
+		move.w	#58,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11m:		btst	#3,vrbw11	* group 12
+		beq	srs11x		* jump if not
+*
+		move.w	#63,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs11x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* velocity
+* --------
+srs12:		btst	#12,d0		* velocity ?
+		beq	srs13		* jump if not
+*
+		move.w	#AT11,ATR(a7)	* put attribute on stack
+		move.w	#5,ROW(a7)	* put row on stack
+		btst	#0,vrbw12+1	* group 1 ?
+		beq	srs12a		* jump if not
+*
+		move.w	#6,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#7,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#8,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12a:		btst	#1,vrbw12+1	* group 2 ?
+		beq	srs12b		* jump if not
+*
+		move.w	#11,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#12,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#13,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12b:		btst	#2,vrbw12+1	* group 3 ?
+		beq	srs12c		* jump if not
+*
+		move.w	#16,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#17,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#18,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+		.page
+*
+srs12c:		btst	#3,vrbw12+1	* group 4 ?
+		beq	srs12d		* jump if not
+*
+		move.w	#21,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#22,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#23,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12d:		btst	#4,vrbw12+1	* group 5 ?
+		beq	srs12e		* jump if not
+*
+		move.w	#26,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#27,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#28,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12e:		btst	#5,vrbw12+1	* group 6 ?
+		beq	srs12f		* jump if not
+*
+		move.w	#31,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#32,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#33,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+		.page
+*
+srs12f:		btst	#6,vrbw12+1	* group 7 ?
+		beq	srs12g		* jump if not
+*
+		move.w	#36,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#37,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#38,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12g:		btst	#7,vrbw12+1	* group 8 ?
+		beq	srs12h		* jump if not
+*
+		move.w	#41,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#42,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#43,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12h:		btst	#0,vrbw12	* group 9
+		beq	srs12j		* jump if not
+*
+		move.w	#46,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#47,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#48,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+		.page
+*
+srs12j:		btst	#1,vrbw12	* group 10
+		beq	srs12k		* jump if not
+*
+		move.w	#51,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#52,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#53,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12k:		btst	#2,vrbw12	* group 11
+		beq	srs12m		* jump if not
+*
+		move.w	#56,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#57,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#58,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12m:		btst	#3,vrbw12	* group 12
+		beq	srs12x		* jump if not
+*
+		move.w	#61,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#62,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#63,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+*
+srs12x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* resolution
+* ----------
+srs13:		btst	#13,d0		* resolution ?
+		beq	srs14		* jump if not
+*
+		move.w	#AT12,ATR(a7)	* put attribute on stack
+		move.w	#7,ROW(a7)	* put row on stack
+		btst	#0,vrbw13+1	* variable 1 ?
+		beq	srs13a		* jump if not
+*
+		move.w	#6,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs13a:		btst	#1,vrbw13+1	* variable 2 ?
+		beq	srs13b		* jump if not
+*
+		move.w	#15,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs13b:		btst	#2,vrbw13+1	* variable 3 ?
+		beq	srs13c		* jump if not
+*
+		move.w	#24,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs13c:		btst	#3,vrbw13+1	* variable 4 ?
+		beq	srs13d		* jump if not
+*
+		move.w	#33,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs13d:		btst	#4,vrbw13+1	* variable 5 ?
+		beq	srs13e		* jump if not
+*
+		move.w	#42,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs13e:		btst	#5,vrbw13+1	* variable 6 ?
+		beq	srs13x		* jump if not
+*
+		move.w	#51,COL(a7)	* put column on stack
+		jsr	_vputa		* reset column
+*
+srs13x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* analog value
+* ------------
+srs14:		btst	#14,d0		* analog value ?
+		beq	srs15		* jump if not
+*
+		move.w	#AT12,ATR(a7)	* put attribute on stack
+		move.w	#7,ROW(a7)	* put row on stack
+		btst	#0,vrbw14+1	* variable 1 ?
+		beq	srs14a		* jump if not
+*
+		move.w	#8,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#9,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#10,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#11,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#12,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+*
+srs14a:		btst	#1,vrbw14+1	* variable 2 ?
+		beq	srs14b		* jump if not
+*
+		move.w	#17,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#18,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#19,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#20,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#21,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+*
+		.page
+*
+srs14b:		btst	#2,vrbw14+1	* variable 3 ?
+		beq	srs14c		* jump if not
+*
+		move.w	#26,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#27,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#28,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#29,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#30,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+*
+srs14c:		btst	#3,vrbw14+1	* variable 4 ?
+		beq	srs14d		* jump if not
+*
+		move.w	#35,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#36,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#37,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#38,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#39,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+*
+		.page
+*
+srs14d:		btst	#4,vrbw14+1	* variable 5 ?
+		beq	srs14e		* jump if not
+*
+		move.w	#44,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#45,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#46,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#47,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#48,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+*
+srs14e:		btst	#5,vrbw14+1	* variable 6 ?
+		beq	srs14x		* jump if not
+*
+		move.w	#53,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#54,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#55,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#56,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+		move.w	#57,COL(a7)	* put 5th column on stack
+		jsr	_vputa		* reset fifth column
+*
+srs14x:		move.w	vrcw,d0		* restore vrcw to d0
+*
+		.page
+*
+* stop/next
+* ---------
+srs15:		btst	#15,d0		* stop/next ?
+		beq	srs16		* jump if not
+*
+		btst	#0,vrbw15	* stop ?
+		beq	srs15a		* jump if not
+*
+		move.w	#AT08,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#40,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#41,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#42,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#43,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs15a:		btst	#1,vrbw15	* next ?
+		beq	srs16		* jump if not
+*
+		move.w	#AT08,ATR(a7)	* put attribute on stack
+		move.w	#1,ROW(a7)	* put row on stack
+		move.w	#45,COL(a7)	* put 1st column on stack
+		jsr	_vputa		* reset first column
+		move.w	#46,COL(a7)	* put 2nd column on stack
+		jsr	_vputa		* reset second column
+		move.w	#47,COL(a7)	* put 3rd column on stack
+		jsr	_vputa		* reset third column
+		move.w	#48,COL(a7)	* put 4th column on stack
+		jsr	_vputa		* reset fourth column
+*
+srs16:		add.l	#10,a7		* clean up stack
+		bra	srsexit		* done
+*
+		.page
+*
+		.bss
+*
+* local copies of _vrcw, _vrbw08.._vrbw15
+*
+vrcw:		.ds.w	1
+vrbw08:		.ds.w	1
+vrbw09:		.ds.w	1
+vrbw10:		.ds.w	1
+vrbw11:		.ds.w	1
+vrbw12:		.ds.w	1
+vrbw13:		.ds.w	1
+vrbw14:		.ds.w	1
+vrbw15:		.ds.w	1
+*
+		.end
Index: ram/stcpos.c
===================================================================
--- ram/stcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/stcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,312 @@
+/*
+   =============================================================================
+	stcpos.c -- text cursor positioning for the score display
+	Version 19 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "scdsp.h"
+
+#define	STCOBJ		obj3
+
+#define	SDLINE		4		/* dividing line color - analog stuff */
+
+extern	unsigned	exp_c();
+
+extern	unsigned	*STCOBJ;	/* text cursor address in VSDD RAM */
+
+extern	short	cxval, cyval;		/* score cursor x,y */
+extern	short	stcrow, stccol;		/* score cursor row,col */
+extern	short	sctctab[10][64];	/* score background color table */
+
+/* 
+
+*/
+
+short	sctccon[10][64] = {		/* score background color constants */
+
+	/* 0 - row  0 */
+
+	{SDBG00, SDBG00, SDBG01, SDBG01, SDBG01, SDBG01, SDBG01, SDBG01,
+	 SDBG01, SDBG00, SDBG00, SDBG00, SDBG00, SDBG00, SDBG00, SDBG00,
+	 SDBG00, SDBG00, SDBG00, SDBG00, SDBG00, SDBG00, SDBG01, SDBG01,
+	 SDBG01, SDBG01, SDBG01, SDBG01, SDBG01, SDBG02, SDBG02, SDBG02,
+
+	 SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02,
+	 SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02,
+	 SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG02, SDBG03,
+	 SDBG03, SDBG03, SDBG03, SDBG03, SDBG03, SDBG03, SDBG03, SDBG03},
+
+	/* 1 - row 17 */
+
+	{SDBG04, SDBG04, SDBG04, SDBG04, SDBG04, SDBG04, SDBG04, SDBG04,
+	 SDBG04, SDBG04, SDBG04, SDBG04, SDBG04, SDBG04, SDBG05, SDBG05,
+	 SDBG05, SDBG05, SDBG05, SDBG05, SDBG05, SDBG06, SDBG06, SDBG06,
+	 SDBG06, SDBG06, SDBG06, SDBG06, SDBG06, SDBG06, SDBG06, SDBG07,
+
+	 SDBG07, SDBG07, SDBG07, SDBG07, SDBG07, SDBG07, SDBG07, SDBG07,
+	 SDBG08, SDBG08, SDBG08, SDBG08, SDBG08, SDBG08, SDBG08, SDBG08,
+	 SDBG08, SDBG08, SDBG09, SDBG09, SDBG09, SDBG09, SDBG09, SDBG09,
+	 SDBG09, SDBG10, SDBG10, SDBG10, SDBG10, SDBG10, SDBG10, SDBG10},
+
+	/* 2 - row 18 */
+
+	{SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11},
+/* 
+
+*/
+	/* 3 - row 19 */
+
+	{SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11},
+
+	/* 4 - row 20 */
+
+	{SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11},
+
+	/* 5 - row 21 */
+
+	{SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11,
+	 SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11, SDBG11},
+/* 
+
+*/
+	/* 6 - row 22 */
+
+	{SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12},
+
+	/* 7 - row 23 */
+
+	{SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12,
+	 SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12, SDBG12},
+
+	/* 8 - row 24 */
+
+	{SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13,
+	 SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13,
+	 SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13, SDBG13,
+	 SDBG13, SDBG13, SDBG13, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14,
+
+	 SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14,
+	 SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14,
+	 SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14, SDBG14,
+	 SDBG14, SDBG15, SDBG15, SDBG15, SDBG15, SDBG15, SDBG15, SDBG15},
+
+	/* 9 - special - bottom of row 21 - top is entry 5 */
+
+	{SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE,
+	 SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE, SDLINE}
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stcclr() -- turn off all of the score text cursors
+   =============================================================================
+*/
+
+stcclr()
+{
+	register unsigned *obj;
+	register short i, j;
+	register unsigned k;
+
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);	/* select the correct bank */
+
+	stcrow = 0;		/* leave score cursor row,col = 0,0 */
+	stccol = 0;
+
+	obj = STCOBJ;		/* intialize pointers */
+
+	for (i = 0; i < 9; i++) {	/* clear each cursor row */
+
+		for (j = 0; j < 64; j++) {	/* top cursor row */
+
+			k = exp_c(sctctab[i][j]);
+
+			*obj++ = k;
+			*obj++ = k;
+		}
+
+		for (j = 0; j < 64; j++) {	/* bottom cursor row */
+
+			k = exp_c(sctctab[i EQ 5 ? 9 : i][j]);
+
+			*obj++ = k;
+			*obj++ = k;
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stcoff() -- turn off text cursor for the score display
+   =============================================================================
+*/
+
+stcoff()
+{
+	register unsigned ccv, *tcp;
+	register short tcrow;
+
+	tcrow = stcrow ? (stcrow - 16) : 0;	/* get old object row */
+
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);
+
+	tcp = STCOBJ + (tcrow << 8) + (stccol << 1);	/* object pointer */
+
+	/* background color */
+
+	ccv = exp_c(sctctab[tcrow][stccol]);
+
+	*tcp++ = ccv;			/* turn off the text cursor */
+	*tcp   = ccv;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stcpos() -- position the score text cursor at ('row', 'col')
+   =============================================================================
+*/
+
+stcpos(row, col)
+short row, col;
+{
+	register unsigned *ccp, *tcp;
+	register unsigned curson, ccv;
+	register short ncrow, tcrow;
+
+	tcrow = stcrow ? (stcrow - 16) : 0;	/* get old object row */
+	ncrow = row ? (row - 16) : 0;		/* get new object row */
+
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);			/* select the cursor bank */
+
+	curson = exp_c(SDCURSR);		/* get cursor color */
+
+	/* get old cursor background color */
+
+	ccv    = exp_c(sctctab[tcrow][stccol]);
+
+	tcp = STCOBJ + (tcrow << 8) + (stccol << 1);	/* old cursor pointer */
+	ccp = STCOBJ + (ncrow << 8) + (col << 1);	/* new cursor pointer */
+
+	*tcp++ = ccv;				/* turn off the old cursor */
+	*tcp   = ccv;
+
+	*ccp++ = curson;			/* turn on the new cursor */
+	*ccp   = curson;
+
+	stcrow = row;				/* update cursor position */
+	stccol = col;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	advscur() -- advance the score text cursor
+   =============================================================================
+*/
+
+advscur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol + 1;
+
+	if (newcol LE cfetp->frcol)
+		stcpos(stcrow, newcol);
+}
+
+/*
+   =============================================================================
+	stcset() -- setup the score text cursor color table
+   =============================================================================
+*/
+
+stcset()
+{
+	memcpyw(&sctctab[0][0], &sctccon[0][0], 640);
+}
Index: ram/stmproc.c
===================================================================
--- ram/stmproc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/stmproc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1166 @@
+/*
+   =============================================================================
+	stmproc.c -- MIDAS-VII Patch facility support functions
+	Version 33 -- 1988-12-06 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGDP		0
+#define	DEBUGEP		0
+#define	DEBUGFD		0
+#define	DEBUGFP		0
+#define	DEBUGSR		0
+
+#define	PATCHDEF			/* so patch.h gets it right */
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "patch.h"
+#include "vsdd.h"
+#include "wordq.h"
+
+#include "midas.h"
+#include "ptdisp.h"
+
+extern	short	ptegood, ptedfok, ptestok, ptedsok, ptedtok;
+
+extern	short	ptedef, ptestm, ptespec, ptesuba, ptedat1;
+
+extern	short	pteset;
+
+extern	short	ptecpos, ptepred, ptesucc;
+
+extern	struct patch	ptebuf;
+
+extern	char	ptdebuf[];
+
+#if	DEBUGDP
+short	debugdp = 1;
+#endif
+
+#if	DEBUGEP
+short	debugep = 0;
+short	snapep  = 1;
+#endif
+
+#if	DEBUGFD
+short	debugfd = 0;
+#endif
+
+#if	DEBUGFP
+short	debugfp = 1;
+#endif
+
+#if	DEBUGSR
+short	debugsr = 1;
+short	snapsr  = 1;
+#endif
+
+#if	(DEBUGDP|DEBUGEP|DEBUGFD|DEBUGFP|DEBUGSR)
+extern	short	debugsw;
+#endif
+
+unsigned short	dtfree;			/* defent free list index */
+unsigned short	ptfree;			/* patch free list index */
+
+unsigned short	dpepred;		/* defent predecessor index */
+unsigned short	dpecpos;		/* current defent index */
+unsigned short	dpesucc;		/* defent successor index */
+
+char	ptdsbuf[50];			/* patch display build buffer */
+
+char	defptr[NDEFSTMS];		/* definition index table */
+char	stmptr[NDEFSTMS];		/* stimulus index table */
+
+struct	defent	defents[RAWDEFS];	/* definition control table */
+
+struct	patch	patches[MAXPATCH];	/* patch table */
+
+struct	wordq	ptefifo;		/* patch trigger fifo header */
+
+unsigned short	ptewrds[NPTEQELS];	/* patch trigger fifo entries */
+
+char	dmatch[] = {			/* addat1 match tags */
+
+	0, 0, 0, 0, 0, 0, 0, 0,		/*  0 ..  7 */
+	0, 0, 0, 1, 0, 0, 0, 0,		/*  8 .. 15 */
+	1, 1, 1, 1, 1, 1, 1, 1,		/* 16 .. 23 */
+	1, 1, 1				/* 24 .. 26 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	initpt() -- initialize patch table data structure
+   =============================================================================
+*/
+
+initpt()
+{
+	register unsigned short i;
+
+	/* initialize the trigger fifo */
+
+	setwq(&ptefifo, ptewrds, NPTEQELS, NPTEQHI, NPTEQLO);
+
+	/* clear DEF / STM index tables */
+
+	memset(defptr, 0, sizeof defptr);
+	memset(stmptr, 0, sizeof stmptr);
+
+	/* setup patch free chain */
+
+	memset(patches, 0, sizeof patches);
+
+	for (i = 1; i < 255; i++)
+		patches[i].nextstm = 1 + i;
+
+	ptfree = 1;
+
+	/* setup defent free chain */
+
+	memset(defents, 0, sizeof defents);
+
+	for (i = 1; i < 255; i++)
+		defents[i].nextdef = 1 + i;
+
+	dtfree = 1;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pt_alc() -- allocate a patch table entry from the free list
+   =============================================================================
+*/
+
+unsigned short
+pt_alc()
+{
+	register unsigned short pe;
+
+	if (0 NE (pe = ptfree))
+		ptfree = patches[pe].nextstm;
+
+	return(pe);
+}
+
+/*
+   =============================================================================
+	pt_del() -- return a patch table entry to the free list
+   =============================================================================
+*/
+
+pt_del(pe)
+register unsigned short pe;
+{
+	patches[pe].nextstm = ptfree;
+	ptfree = pe;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dt_alc() -- allocate a def table entry from the free list
+   =============================================================================
+*/
+
+unsigned short
+dt_alc()
+{
+	register unsigned short de;
+
+	if (0 NE (de = dtfree))
+		dtfree = defents[de].nextdef;
+
+	return(de);
+}
+
+/*
+   =============================================================================
+	dt_del() -- return a def table entry to the free list
+   =============================================================================
+*/
+
+dt_del(de)
+register unsigned short de;
+{
+	defents[de].nextdef = dtfree;
+	dtfree = de;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cprdpe() -- compare patch buffer to def table entry
+
+	Returns:
+		-1 = buffer <  table entry
+		 0 = buffer EQ table entry
+		+1 = buffer >  table entry
+   =============================================================================
+*/
+
+short
+cprdpe(np)
+unsigned short np;
+{
+	register unsigned short ca, cb, ct;
+	register struct defent *pp;
+
+	pp = &defents[np];
+
+	if ((cb = ptestm) < (ct = pp->stm))
+		return(-1);
+
+	if (cb > ct)
+		return(1);
+
+	if ((ca = (PE_SPEC & ptespec)) < (ct = (PE_SPEC & pp->adspec)))
+		return(-1);
+
+	if (ca > ct)
+		return(1);
+
+	if ((cb = ptesuba) < (ct = pp->adsuba))
+		return(-1);
+
+	if (cb > ct)
+		return(1);
+/* 
+
+*/
+	/* check for extended destinations -- they need further testing */
+
+	if (dmatch[ca]) {		/* check destination type */
+
+		if ((cb = ptedat1) < (ct = pp->addat1))
+			return(-1);
+
+		if (cb > ct)
+			return(1);
+		else
+			return(0);
+
+	} else {
+
+		return(0);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	finddpe() -- find def table entry
+
+	Returns:	+1 = new def -- no DEF entry yet
+			 0 = old def -- entry found in DEF chain
+			-1 = new def -- entry not in DEF chain
+
+	Sets:		dpepred		predecessor index,  or 0 if none exists
+			dpecpos		def table index,    or 0 if none exists
+			dpesucc		successor index,    or 0 if none exists
+   =============================================================================
+*/
+
+short
+finddpe()
+{
+	register unsigned short c, idef;
+
+	dpepred = 0;		/* initialize dpepred = 0  (no predecessor) */
+	dpecpos = 0;		/* initialize dpecpos = 0  (no current defent */
+	dpesucc = 0;		/* initialize dpesucc = 0  (no successor) */
+
+#if	DEBUGFD
+	if (debugsw AND debugfd) {
+
+		printf("finddpe():  entry\n");
+
+		printf("  ptb  $%04.4X $%04.4X   $%04.4X $%04.4X   $%04.4X $%04.4X\n",
+			ptebuf.defnum, ptebuf.stmnum, ptebuf.paspec,
+			ptebuf.pasuba, ptebuf.padat1, ptebuf.padat2);
+	}
+#endif
+
+	/* try to find the DEF chain index for the defent in defptr[] */
+
+	if (0 EQ (idef = defptr[TRG_MASK & ptebuf.defnum])) {
+
+#if	DEBUGFD
+	if (debugsw AND debugfd) {
+
+		printf("finddpe():   1 -- NO DEF -- ");
+		printf("dpe pred: %3d  cpos: %3d  succ: %3d\n",
+			dpepred, dpecpos, dpesucc);
+	}
+#endif
+
+		return(1);	/* +1 = new defent -- no DEF entry yet */
+	}
+
+/* 
+
+*/
+
+	while (idef) {		/* search the DEF chain */
+
+		/* compare ptebuf to defents[idef] */
+
+		if (1 NE (c = cprdpe(idef))) {
+
+			if (c EQ 0) {	/* if we find the defent ... */
+
+				dpecpos = idef;	/* ... point at it */
+				dpesucc = defents[idef].nextdef;
+
+			}
+
+#if	DEBUGFD
+	if (debugsw AND debugfd) {
+
+		printf("finddpe():  %d --  %s -- ", c,
+			c ? "NOT FOUND (>)" : "FOUND");
+
+		printf("dpe pred: %3d  cpos: %3d  succ: %3d\n",
+			dpepred, dpecpos, dpesucc);
+	}
+#endif
+			return(c);	/* return search result */
+		}
+
+		dpepred = idef;	/* point at next entry in DEF chain */
+		idef   = defents[idef].nextdef;
+	}
+
+#if	DEBUGFD
+	if (debugsw AND debugfd) {
+
+		printf("finddpe(): -1 -- NOT FOUND (<) -- ");
+		printf("dpe pred: %3d  cpos: %3d  succ: %3d\n",
+			dpepred, dpecpos, dpesucc);
+	}
+#endif
+
+	return(-1);	/* -1 = new defent -- entry not in DEF chain */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cprpte() -- compare patch buffer to patch table entry
+
+	Returns:
+		-1 = buffer <  table entry
+		 0 = buffer EQ table entry
+		+1 = buffer >  table entry
+   =============================================================================
+*/
+
+short
+cprpte(np)
+unsigned short np;
+{
+	register unsigned short ca, cb, ct;
+	register struct patch *pb, *pp;
+
+	pb = &ptebuf;
+	pp = &patches[np];
+
+	if ((cb = pb->stmnum) < (ct = pp->stmnum))
+		return(-1);
+
+	if (cb > ct)
+		return(1);
+
+	if ((cb = pb->defnum) < (ct = pp->defnum))
+		return(-1);
+
+	if (cb > ct)
+		return(1);
+
+	if ((ca = (PE_SPEC & pb->paspec)) < (ct = (PE_SPEC & pp->paspec)))
+		return(-1);
+
+	if (ca > ct)
+		return(1);
+
+	if ((cb = pb->pasuba) < (ct = pp->pasuba))
+		return(-1);
+
+	if (cb > ct)
+		return(1);
+/* 
+
+*/
+	/* check for extended destinations -- they need further testing */
+
+	if (dmatch[ca]) {		/* check destination type */
+
+		if ((cb = pb->padat1) < (ct = pp->padat1))
+			return(-1);
+
+		if (cb > ct)
+			return(1);
+		else
+			return(0);
+
+	} else {
+
+		return(0);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	findpte() -- find patch table entry
+
+	Returns:	+1 = new patch -- no STM entry yet
+			 0 = old patch -- entry found in STM chain
+			-1 = new patch -- entry not in STM chain
+
+	Sets:		ptepred		predecessor index,  or 0 if none exists
+			ptecpos		patch table index,  or 0 if none exists
+			ptesucc		successor index,    or 0 if none exists
+   =============================================================================
+*/
+
+short
+findpte()
+{
+	register unsigned short c, istim;
+
+	ptepred = 0;		/* initialize ptepred = 0  (no predecessor) */
+	ptecpos = 0;		/* initialize ptecpos = 0  (no current patch */
+	ptesucc = 0;		/* initialize ptesucc = 0  (no successor) */
+
+#if	DEBUGFP
+	if (debugsw AND debugfp) {
+
+		printf("findpte():  entry\n");
+
+		printf("  ptb  $%04.4X $%04.4X   $%04.4X $%04.4X   $%04.4X $%04.4X\n",
+			ptebuf.defnum, ptebuf.stmnum, ptebuf.paspec,
+			ptebuf.pasuba, ptebuf.padat1, ptebuf.padat2);
+	}
+#endif
+
+	/* try to find the STM chain index for the patch in stmptr[] */
+
+	if (0 EQ (istim = stmptr[TRG_MASK & ptebuf.stmnum])) {
+
+#if	DEBUGFP
+	if (debugsw AND debugfp) {
+
+		printf("findpte():   1 -- NO STM -- ");
+		printf("pte pred: %3d  cpos: %3d  succ: %3d\n",
+			ptepred, ptecpos, ptesucc);
+	}
+#endif
+
+		return(1);	/* +1 = new patch -- no STM entry yet */
+	}
+
+/* 
+
+*/
+
+	while (istim) {		/* search the STM chain */
+
+		/* compare ptebuf to patches[istim] */
+
+		if (1 NE (c = cprpte(istim))) {
+
+			if (c EQ 0) {	/* if we find the patch ... */
+
+				ptecpos = istim;	/* ... point at it */
+				ptesucc = patches[istim].nextstm;
+
+			}
+
+#if	DEBUGFP
+	if (debugsw AND debugfp) {
+
+		printf("findpte():  %d --  %s -- ", c,
+			c ? "NOT FOUND (>)" : "FOUND");
+
+		printf("pte pred: %3d  cpos: %3d  succ: %3d\n",
+			ptepred, ptecpos, ptesucc);
+	}
+#endif
+			return(c);	/* return search result */
+		}
+
+		ptepred = istim;	/* point at next entry in STM chain */
+		istim   = patches[istim].nextstm;
+	}
+
+#if	DEBUGFP
+	if (debugsw AND debugfp) {
+
+		printf("findpte(): -1 -- NOT FOUND (<) -- ");
+		printf("pte pred: %3d  cpos: %3d  succ: %3d\n",
+			ptepred, ptecpos, ptesucc);
+	}
+#endif
+
+	return(-1);	/* -1 = new patch -- entry not in STM chain */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	entrpte() -- enter or update a patch table entry
+   =============================================================================
+*/
+
+entrpte()
+{
+	register short c;
+	register unsigned short np, stim;
+
+	ptegood = ptedfok AND ptestok AND ptedsok AND ptedtok;
+
+	if (ptegood) {
+
+		buf2pte();
+
+		c = findpte();
+
+		if (c EQ 0) {		/* old patch -- just update it */
+
+			memcpyw(&patches[ptecpos].defnum, &ptebuf.defnum, 6);
+
+			patches[ptecpos].paspec |= PE_TBIT;	/* define it */
+
+#if	DEBUGEP
+	if (debugsw AND debugep) {
+
+		if (snapep)
+			SnapPTV("entrpte");
+
+		printf("entrpte():  UPDATED\n");
+	}
+#endif
+
+			return;
+		}
+/* 
+
+*/
+		/* allocate a patch entry and fill it in */
+
+		if (0 EQ (ptecpos = pt_alc())) {
+
+#if	DEBUGEP
+	if (debugsw AND debugep)
+		printf("entrpte():  patch table FULL\n");
+#endif
+			return;		/* no patch entries left */
+		}
+
+		memcpyw(&patches[ptecpos].defnum, &ptebuf.defnum, 6);
+		patches[ptecpos].paspec |= PE_TBIT;	/* define it */
+		stim = TRG_MASK & ptebuf.stmnum;
+
+		if (c EQ 1) {		/* new patch -- no STM entry yet */
+
+			ptepred = 0;
+			stmptr[stim] = ptecpos;
+		}
+/* 
+
+*/
+		/* put patch in STM chain */
+
+		if (ptepred) {		/* predecessor exits */
+
+			ptesucc = patches[ptepred].nextstm;
+
+			patches[ptecpos].nextstm = ptesucc;
+			patches[ptecpos].prevstm = ptepred;
+
+			patches[ptepred].nextstm = ptecpos;
+
+			if (ptesucc)
+				patches[ptesucc].prevstm = ptecpos;
+
+		} else {		/* no predecessor */
+
+			patches[ptecpos].prevstm = 0;
+
+			if (c EQ -1) {
+
+				ptesucc = stmptr[stim];
+
+				patches[ptecpos].nextstm = ptesucc;
+
+				patches[ptesucc].prevstm = ptecpos;
+
+				stmptr[stim] = ptecpos;
+
+			} else {
+
+				patches[ptecpos].nextstm = 0;
+			}
+		}
+/* 
+
+*/
+		/* update DEF table */
+
+		if (0 EQ (c = finddpe())) {
+
+#if	DEBUGEP
+	if (debugsw AND debugep)
+		printf("entrpte():  defent already exists\n");
+#endif
+			return;		/* defent already exists */
+		}
+
+		if (0 EQ (dpecpos = dt_alc())) {
+
+#if	DEBUGEP
+	if (debugsw AND debugep)
+		printf("entrpte():  defent table FULL\n");
+#endif
+			return;		/* no defents left */
+		}
+
+		defents[dpecpos].nextdef = 0;
+		defents[dpecpos].stm     = ptestm;
+		defents[dpecpos].adspec  = ptespec;
+		defents[dpecpos].adsuba  = ptesuba;
+		defents[dpecpos].addat1  = ptedat1;
+
+		np = TRG_MASK & ptebuf.defnum;
+
+		if (c EQ 1) {
+
+			dpepred = 0;
+			defptr[np] = dpecpos;
+		}
+
+		if (dpepred) {
+
+			dpesucc = defents[dpepred].nextdef;
+			defents[dpecpos].nextdef = dpesucc;
+			defents[dpepred].nextdef = dpecpos;
+
+		} else {
+
+			if (c EQ -1) {
+
+				dpesucc = defptr[np];
+				defents[dpecpos].nextdef = dpesucc;
+				defptr[np] = dpecpos;
+
+			} else {
+
+				defents[dpecpos].nextdef = 0;
+			}
+		}
+
+#if	DEBUGEP
+	if (debugsw AND debugep) {
+
+		if (snapep)
+			SnapPTV("entrpte");
+
+		printf("entrpte():  ENTERED\n");
+	}
+#endif
+		return;
+	}
+
+#if	DEBUGEP
+	if (debugsw AND debugep) {
+
+		if (snapep)
+			SnapPTV("entrpte");
+
+		printf("entrpte():  INVALID\n");
+	}
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	find1st() -- find the first patch in the patch table
+   =============================================================================
+*/
+
+short
+find1st()
+{
+	register short cp, pp;
+
+	for (cp = 0; cp < NDEFSTMS; cp++)
+		if (0 NE (pp = ADR_MASK & stmptr[cp]))
+			return(pp);
+
+	return(0);
+}
+
+/*
+   =============================================================================
+	findnxt() -- find the next patch in the patch table
+   =============================================================================
+*/
+
+short
+findnxt(cp)
+short cp;
+{
+	register short np, stim;
+
+	if (0 NE (np = patches[cp].nextstm))
+		return(np);
+
+	stim = TRG_MASK & patches[cp].stmnum;
+
+	while (++stim < NDEFSTMS)
+		if (0 NE (np = ADR_MASK & stmptr[stim]))
+			return(np);
+
+	return(0);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	findprv() -- find the previous patch in the patch table
+   =============================================================================
+*/
+
+short
+findprv(cp)
+short cp;
+{
+	register short np, pp, stim;
+
+	if (0 NE (np = patches[cp].prevstm))	/* return prevstm if set */
+		return(np);
+
+	stim = TRG_MASK & patches[cp].stmnum;	/* extract the stimulus */
+
+	while (--stim GE 0) {		/* back up one stimulus if we can */
+
+		if (0 NE (np = ADR_MASK & stmptr[stim])) {	/* any there ? */
+
+			/* find the end of the chain for the stimulus */
+
+			while (pp = patches[np].nextstm)
+				np = pp;
+
+			return(np);
+		}
+	}
+
+	return(0);	/* backed up to the start of the table */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dpte() -- display a patch at a given line on the screen
+   =============================================================================
+*/
+
+dpte(pe, row, atr)
+register short pe, row, atr;
+{
+	register short i;
+
+	memset(ptdsbuf, ' ', 50);
+
+	if (pe) {
+
+		dspdfst(&ptdsbuf[ 2], patches[pe].defnum);
+		dspdfst(&ptdsbuf[15], patches[pe].stmnum);
+		dspdest(&ptdsbuf[28], &patches[pe]);
+
+		for (i = 0; i < 50; i++)
+			if (ptdsbuf[i] EQ '\0')
+				ptdsbuf[i] = ' ';
+	
+		ptdsbuf[48] = '\0';
+	}
+
+	UpdVid(row, 0, "\260 ", PTBATR);
+	UpdVid(row, 1, &ptdsbuf[1], atr);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dptw() -- display window around current patch at ptecpos
+   =============================================================================
+*/
+
+dptw()
+{
+	register short cp, r, row, pp;
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  ENTRY  ptecpos = %d\n", ptecpos);
+#endif
+
+	if (ptecpos) {
+
+		/* search back from ptecpos for predecessors */
+
+		row = 7;
+		pp  = ptecpos;
+
+		while (0 NE (cp = findprv(pp))) {
+
+			pp = cp;
+
+			if (--row EQ 0)
+				break;
+		}
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  backed up to row = %d  pp = %d\n", row, pp);
+#endif
+
+		if (row) {	/* blank any unused lines  (rows 0..6) */
+
+			for (r = 0; r < row; r++)
+				dpte(0, r, PTPATR);
+		}
+
+		while (row < 7) {	/* display predecessors  (rows 0..6) */
+
+			dpte(pp, row++, PTPATR);
+			pp = findnxt(pp);
+		}
+/* 
+
+*/
+		/* display ptecpos at the center  (row 7) */
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  row = %d  pp = %d  ptecpos = %d\n",
+			row, pp, ptecpos);
+#endif
+
+		dpte(pp, row++, PTEATR);
+
+		/* display forward from ptecpos  (rows 8..15) */
+
+		while (0 NE (pp = findnxt(pp))) {
+
+			dpte(pp, row++, PTPATR);
+
+			if (row > 15)
+				break;
+		}
+
+		/* blank any unused display lines  (rows 8..15) */
+		while (row < 16)
+			dpte(0, row++, PTPATR);
+/* 
+
+*/			
+	} else {
+
+		if (0 NE (ptecpos = find1st())) {
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  found 1st at %d\n", ptecpos);
+#endif
+
+			/* clear lines above the center (rows 0..6) */
+
+			for (row = 0; row < 7; ++row)
+				dpte(0, row, PTPATR);
+
+			/* display ptecpos at the center (row 7) */
+
+			dpte(pp = ptecpos, row++, PTEATR);
+
+			/* display forward from ptecpos (rows 8..15) */
+
+			while (0 NE (pp = findnxt(pp))) {
+
+				dpte(pp, row++, PTPATR);
+
+				if (row > 15)
+					break;
+			}
+
+			/* blank any unused display lines (rows 8..15) */
+
+			while (row < 16)
+				dpte(0, row++, PTPATR);
+/* 
+
+*/
+		} else {
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  no patches to display\n");
+#endif
+
+			/* clear the patch display */
+
+			for (row = 0; row < 16; ++row)
+				dpte(0, row, (row EQ 7) ? PTEATR : PTPATR);
+		}
+	}
+
+	if (ptecpos) {
+
+		memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+		pteset = TRUE;
+		pte2buf();
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  EXIT -- LOADED buffer,  ptecpos = %d\n",
+			ptecpos);
+#endif
+
+	} else {
+
+		pteset = FALSE;
+		voidpb();
+
+#if	DEBUGDP
+	if (debugsw AND debugdp)
+		printf("dptw():  EXIT -- VOIDED buffer,  ptecpos = %d\n",
+			ptecpos);
+#endif
+
+
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	srdspte() -- search for and display patch table entry
+   =============================================================================
+*/
+
+srdspte()
+{
+	short	oldcpos, oldpred, oldsucc;
+#if	DEBUGSR
+	register short i;
+	char dbuf[50];
+#endif
+
+	ptegood = ptedfok AND ptestok AND ptedsok AND ptedtok;
+
+#if	DEBUGSR
+	if (debugsw AND debugsr) {
+
+		printf("srdspte():  ENTRY  pte good=%d dfok=%d stok=%d dsok=%d dtok=%d\n",
+			ptegood, ptedfok, ptestok, ptedsok, ptedtok);
+
+		memcpy(dbuf, ptdebuf, 48);
+
+		for (i = 0; i < 48; i++)
+			if (dbuf[i] EQ '\0')
+				dbuf[i] = ' ';
+			else if (dbuf[i] & 0x0080)
+				dbuf[i] = '~';
+
+		dbuf[48] = '\0';
+
+		printf("  ptdebuf = \"%s\"\n", dbuf);
+	}
+#endif
+
+	if (ptegood) {
+
+		oldcpos = ptecpos;	/* save patch pointers */
+		oldpred = ptepred;
+		oldsucc = ptesucc;
+
+		buf2pte();
+
+		if (0 EQ findpte()) {
+
+#if	DEBUGSR
+	if (debugsw AND debugsr)
+		printf("srdspte():  FOUND patch at ptecpos = %d\n", ptecpos);
+#endif
+
+			memcpyw(&ptebuf.defnum, &patches[ptecpos].defnum, 6);
+			pteset = TRUE;
+			pte2buf();
+			dptw();
+
+		} else {
+
+			ptecpos = oldcpos;	/* restore patch pointers */
+			ptepred = oldpred;
+			ptesucc = oldsucc;
+
+#if	DEBUGSR
+	if (debugsw AND debugsr) {
+
+		printf("srdspte():  patch not found\n");
+
+		if (snapsr)
+			SnapPTV("srdspte");
+
+	}
+#endif
+
+		}
+	}
+
+#if	DEBUGSR
+	if (debugsw AND debugsr)
+		printf("srdspte():  EXIT -- ptecpos = %d\n", ptecpos);
+#endif
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	stmproc() -- process a trigger as a definer and a stimulus
+   =============================================================================
+*/
+
+stmproc(trg)
+register unsigned short trg;
+{
+	register struct defent	*nextdef;
+	register struct patch	*nextpch;
+	register unsigned short adspec, adsuba, np, stim;
+	unsigned short addat1, adrtag;
+
+	/* ***** DEFINER PROCESSING PHASE ***** */
+
+	np      = ADR_MASK & defptr[TRG_MASK & trg];
+	nextdef = np ? &defents[np] : (struct defent *)NULL;	/* point at DEF chain */
+
+/* 
+
+*/
+	while ((struct defent *)NULL NE nextdef) {		/* process DEF chain */
+
+		/* setup search criteria */
+
+		adspec = nextdef->adspec;
+		adsuba = nextdef->adsuba;
+		addat1 = nextdef->addat1;
+		stim   = nextdef->stm;
+		adrtag = dmatch[adspec];
+
+		/* point at the start of the STM chain */
+
+		np      = ADR_MASK & stmptr[TRG_MASK & stim];
+		nextpch = np ? &patches[np] : (struct patch *)NULL;
+
+		while ((struct patch *)NULL NE nextpch) {	/* process STM chain */
+
+			/* if this patch matches our search criteria ... */
+
+			if ((stim   EQ  nextpch->stmnum) AND
+			    (adspec EQ (nextpch->paspec & PE_SPEC)) AND
+			    (adsuba EQ  nextpch->pasuba)) {
+
+				if ((NOT adrtag) OR
+				    (adrtag AND addat1 EQ nextpch->padat1)) {
+
+					if (nextpch->defnum EQ trg)
+						nextpch->paspec |= PE_TBIT;	/* define */
+					else
+						nextpch->paspec &= ~PE_TBIT;	/* undefine */
+				}
+			}
+
+			/* point at the next patch in the STM chain */
+
+			np      = nextpch->nextstm;
+			nextpch = np ? &patches[np] : (struct patch *)NULL;
+		}
+
+		/* point at the next DEF entry */
+
+		np      = nextdef->nextdef;
+		nextdef = np ? &defents[np] : (struct defent *)NULL;
+	}
+/* 
+
+*/
+
+	/* ***** STIMULUS PROCESSING PHASE ***** */
+
+	/* setup initial STM chain pointer */
+
+	np = ADR_MASK & stmptr[TRG_MASK & trg];
+	nextpch = np ? &patches[np] : (struct patch *)NULL;
+
+	/* process the STM chain */
+
+	while ((struct patch *)NULL NE nextpch) {	/* for each patch .. */
+
+		if ((nextpch->paspec & PE_TBIT) AND	/* if it's defined ... */
+		    (nextpch->stmnum EQ trg))		/* ... and stm matches */
+			dopatch(nextpch);		/* ... do the patch */
+
+		/* point at the next patch */
+
+		np = nextpch->nextstm;
+		nextpch = np ? &patches[np] : (struct patch *)NULL;
+	}
+}
Index: ram/swinit.c
===================================================================
--- ram/swinit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/swinit.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,231 @@
+/*
+   =============================================================================
+	swinit.c -- MIDAS-VII -- more variable definitions and initializations
+	Version 12 -- 1988-10-12 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	FET_DEFS	1		/* so fields.h gets things right */
+
+#include "stddefs.h"
+#include "scwheel.h"
+#include "score.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+
+#include "midas.h"
+
+#include "scdsp.h"
+#include "libdsp.h"
+#include "wsdsp.h"
+
+extern	short	swctrl;
+extern	short	swdir;
+extern	short	swfiin;
+extern	short	swflag;
+
+extern	short	swfifo[NSWFIFO];
+
+/* 
+
+*/
+
+BOOL	se_chg;			/* Score free list changed flag */
+
+PFS	(*oldsw)[];		/* saved swpt value */
+PFS	(*swpt)[];		/* switch dispatch table pointer */
+
+PFS	aswtbl[14];		/* assignment switch table */
+
+short	(*curmove)();		/* cursor move function */
+short	(*curtype)();		/* cursor type function */
+short	(*cx_key)();		/* x rate calculation */
+short	(*cx_upd)();		/* x update */
+short	(*cy_key)();		/* y rate calculation */
+short	(*cy_upd)();		/* y update */
+short	(*d_key)();		/* in-field data key processor */
+short	(*e_key)();		/* E key processor */
+short	(*m_key)();		/* M key processor */
+short	(*itxput)();		/* instrument menu text put function */
+short	(*not_fld)();		/* not-in-field data key processor */
+short	(*olddkey)();		/* saved d_key value */
+short	(*oldekey)();		/* saved e_key value */
+short	(*oldmkey)();		/* saved m_key value */
+short	(*oldxkey)();		/* saved x_key value */
+short	(*premove)();		/* cursor pre-move function */
+short	(*pstmove)();		/* cursor post-move function */
+short	(*vt_adv)();		/* vtyper data cursor advance function */
+short	(*vt_bsp)();		/* vtyper data cursor backspace function */
+short	(*vt_cdn)();		/* vtyper data cursor down function */
+short	(*vt_cup)();		/* vtyper data cursor up function */
+short	(*vt_dsp)();		/* vtyper display function */
+short	(*vt_stop)();		/* vtyper exit function */
+short	(*x_key)();		/* X key processor */
+short	(*xy_dn)();		/* cursor - finger on (down) */
+short	(*xy_up)();		/* cursor - finger off (up) */
+
+short	*cratex;		/* cursor x rate table pointer */
+short	*cratey;		/* cursor x rate table pointer */
+
+short	BotEdge;		/* configuration box bottom edge */
+short	LftEdge;		/* configuration box left edge */
+short	RgtEdge;		/* configuration box right edge */
+short	TopEdge;		/* configuration box top edge */
+
+short	BarBcur[14];		/* current bottom-zero bar values */
+short	BarCcur[14];		/* current centered-zero bar values */
+short	BGeq[14];		/* current EQ bar settings */
+short	BGother[14];		/* current other pot bar settings */
+short	BGprmtr[14];		/* current parameter pot bar settings */
+
+short	articen[12];		/* voice articulation enable status */
+short	grpdyn[12];		/* group dynamics table (0..9) */
+short	grploc[12];		/* group location table (0..8) */
+short	grpmode[12];		/* group mode - 0 = play, 1 = stdby, 2 = rec */
+short	grpsel[12];		/* group select status for instrument selection */
+short	grpstat[12];		/* group status - 0 = off, non-0 = on */
+short	grptmap[12];		/* group map */
+short	gtctab[12];		/* group to color table */
+short	ins2grp[12];		/* instrument to group table (00..NINST-1) */
+short	instmod[12];		/* intrument data modified */
+short	key2grp[88];		/* port 1 key to group assignment table */
+short	lastart[16];		/* last articulation values (by parameter) */
+short	lastvce[12];		/* last voice assigned in each group */
+short	lastvel[12];		/* last velocity sent to group */
+short	ldmap[N_SCORES];	/* gather read map */
+short	mctlnum[4];		/* MIDI controller number table (-1, 00..99) */
+short	mpbend[48];		/* MIDI pitch bend data, by port and channel */
+short	msmstv[3];		/* MIDI state machine state variables */
+short	offsets[NUMWPCAL];	/* offsets for current waveshape */
+short	oldtun[128];		/* previous tuning table for undo */
+short	prstab[NTRIGS];		/* pressure */
+short	s_inst[12];		/* instrument selections */
+short	s_trns[12];		/* current transposition values */
+short	swfifo[NSWFIFO];	/* scroll wheel fifo */
+short	txfifo[NTKFIFO];	/* trackball X fifo */
+short	tyfifo[NTKFIFO];	/* trackball Y fifo */
+short	tuntab[128];		/* current tuning table */
+short	vce2grp[12];		/* voice to group table (-1, 1..12)*/
+short	vce2trg[12];		/* voice to trigger map (-1 EQ NULL) */
+short	veltab[NTRIGS];		/* velocity */
+short	vmtab[NUMHARM];		/* harmonics for current waveshape */
+short	wsbuf[NUMWPCAL];	/* final values for current waveshape */
+
+/* 
+
+*/
+
+char	*lmln22;		/* message window line 22 */
+char	*lmln23;		/* message window line 23 */
+char	*lmln24;		/* message window line 24 */
+char	*vtdeptr;		/* virtual typewriter data entry pointer */
+
+char	*funcndx[256][2];	/* function header pointers */
+char	*vlbptr[3];		/* variable label pointers */
+
+char	bfs[128];		/* display generation buffer */
+char	caname[16];		/* current assignment table name */
+char	dspbuf[65];		/* display generation buffer */
+char	ebuf[MAXEBUF+1];	/* edit data entry buffer */
+char	errbuf[65];		/* error message build area */
+char	idbuf[65];		/* display format conversion work area */
+char	keystat[24];		/* front panel key status */
+char	ldcmnt[38];		/* comment field */
+char	ldfile[9];		/* file name field */
+char	ldmsg1[65];		/* messsage build area 1 */
+char	ldmsg2[65];		/* messsage build area 2 */
+char	ldmsg3[65];		/* messsage build area 3 */
+char	loadedc[NLTYPES][37];	/* loaded file comments */
+char	loadedf[NLTYPES][8];	/* loaded file names */
+char	masens[3];		/* MIDI port active sensing flags */
+char	mctlval[NCTRLS];	/* MIDI controller values */
+char	mdbyte[3];		/* MIDI data byte buffers */
+char	mpsust[48];		/* MIDI sustain status, by port and channel */
+char	mrstat[3];		/* MIDI running status */
+char	scname[N_SCORES][16];	/* Score names */
+char	trgtab[NTRIGS];		/* trigger status */
+char	tuncurn[33];		/* current tuning table name */
+char	tunname[NTUNS][32];	/* tuning table names */
+
+/* 
+
+*/
+
+long	*pspool;		/* Score storage pool pointer */
+
+long	afi;			/* analog processor FIFO value */
+long	curtime;		/* current sqscan time */
+long	ctime;			/* time at cursor */
+long	dvwork;			/* divide work area */
+long	frags;			/* Score storage pool fragment count */
+long	iotime;			/* saved lcdtime value */
+long	lcdontm;		/* LCD backlight on time */
+long	lcdtime;		/* LCD backlight timer */
+long	lcsum;			/* library checksum */
+long	ndbytes;		/* bytes needed for storage */
+long	noteoff;		/* note off time */
+long	noteon;			/* note on time */
+long	noteper;		/* note period */
+long	noteval;		/* note value */
+long	nrest;			/* number of rests */
+long	schksum;		/* Score checksum */
+long	se1_cnt;		/* Score - free list E_SIZE1 entry count */
+long	se2_cnt;		/* Score - free list E_SIZE2 entry count */
+long	se3_cnt;		/* Score - free list E_SIZE3 entry count */
+long	snbreq;			/* Score - disk bytes required */
+long	snlreq;			/* Score - score bytes required */
+long	sntbreq;		/* Score - total disk bytes required */
+long	sntlreq;		/* Score - total score bytes required */
+long	spcount;		/* Score - storage pool free entry count */
+long	swcount;		/* scroll wheel counter */
+long	swrate;			/* scroll wheel rate */
+long	swtemp;			/* scroll wheel work area */
+long	t_bak;			/* time at p_bak */
+long	t_cbgn;			/* time at p_cbgn */
+long	t_cend;			/* time at p_cend */
+long	t_cur;			/* time at p_cur */
+long	t_ctr;			/* time at p_ctr */
+long	t_fwd;			/* time at p_fwd */
+long	t_ins;			/* time at peg */
+long	t_note;			/* note duration between p_nbeg and p_nend */
+long	t_sbgn;			/* time at p_sbgn */
+long	t_sec1;			/* time at p_sec1 */
+long	t_sec2;			/* time at p_sec2 */
+long	t_sect;			/* section time */
+long	t_send;			/* time at p_send */
+long	wshfac;			/* waveshape scale factor */
+
+long	hwave[NUMWPCAL];	/* harmonic waveshape generation buffer */
+long	nlpersc[N_SCORES];	/* number of longs per score */
+long	scsums[N_SCORES];	/* score checksums */
+long	spool[MAX_SE];		/* Score storage pool */
+
+long	vknm[NUMHARM][NUMWPCAL];	/* scaled harmonics for current ws */
+
+long	swrmin = SWRMIN;		/* scroll wheel rate threshold */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	swinit() -- initialize scroll wheel variables
+   =============================================================================
+*/
+
+swinit()
+{
+	swflag  = FALSE;		/* stop the scroll wheel */
+	swctrl  = FALSE;		/* ... */
+	swdir   = D_FWD;		/* ... */
+	swrate  = 0;			/* ... */
+	swcount = 0;			/* ... */
+
+	memsetw(swfifo, 0, NSWFIFO);	/* clear scroll wheel fifo */
+	swfiin = 0;			/* ... */
+
+	tkinit();			/* initialize the trackball */
+}
Index: ram/tdfield.c
===================================================================
--- ram/tdfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/tdfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,336 @@
+/*
+   =============================================================================
+	tdfield.c -- MIDAS-VII tuning display field processing and cursor motion
+	Version 18 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "hwdefs.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "tundsp.h"
+
+extern	short	select(), whatbox(), nokey(), stdctp0();
+extern	short	cxkstd(), cykstd(), stdmkey(), stddkey();
+
+extern	short	et_null(), ef_null(), rd_null(), nd_null();
+extern	short	et_ttab(), ef_ttab(), rd_ttab(), nd_ttab();
+extern	short	et_tval(), ef_tval(), rd_tval(), nd_tval();
+extern	short	et_tpch(), ef_tpch(), rd_tpch(), nd_tpch();
+
+extern	char	*memset();
+
+extern	short	cxval, cyval, cxrate, cyrate;
+extern	short	stcrow, stccol, submenu, vtcrow, vtccol, vtwrow, vtwcol;
+extern	short	vtxval, vtyval;
+
+extern	short	crate1[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	tdboxes[];
+
+extern	short	tunmod, tdnamsw;
+
+/* forward references */
+
+short	tdcxupd(), tdcyupd();
+
+/* 
+
+*/
+
+struct	fet	td_fet1[] = {		/* field definitions */
+
+	{ 0,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 1,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 2,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 3,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 4,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 5,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 6,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 7,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 8,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 9,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{10,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{11,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{12,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{13,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{14,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{15,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{16,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{17,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{18,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{19,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{20,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{21,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{22,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{23,  6, 10,  0, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+
+	{ 0, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 1, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 2, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 3, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 4, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 5, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 6, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 7, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 8, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 9, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{10, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{11, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{12, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{13, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{14, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{15, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{16, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{17, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{18, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{19, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{20, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{21, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{22, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{23, 16, 20,  1, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+/* 
+
+*/
+	{ 0, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 1, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 2, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 3, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 4, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 5, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 6, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 7, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 8, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 9, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{10, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{11, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{12, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{13, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{14, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{15, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{16, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{17, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{18, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{19, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{20, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{21, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{22, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{23, 26, 30,  2, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+
+	{ 0, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 1, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 2, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 3, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 4, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 5, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 6, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 7, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 8, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 9, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{10, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{11, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{12, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{13, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{14, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{15, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{16, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{17, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{18, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{19, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{20, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{21, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{22, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{23, 36, 40,  3, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+/* 
+
+*/
+	{ 0, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 1, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 2, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 3, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 4, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 5, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 6, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 7, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 8, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 9, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{10, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{11, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{12, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{13, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{14, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{15, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{16, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{17, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{18, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{19, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{20, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{21, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{22, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{23, 47, 51,  4, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+
+	{ 0, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 1, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 2, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 3, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 4, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 5, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 6, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+	{ 7, 58, 62,  5, et_tpch, ef_tpch, rd_tpch, nd_tpch},
+
+	{18, 58, 62,  6, et_tval, ef_tval, rd_tval, nd_tval},
+
+	{24,  7, 38,  7, et_null, ef_null, rd_null, nd_null},
+	{24, 61, 61,  6, et_ttab, ef_ttab, rd_ttab, nd_ttab},
+
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+/* 
+
+*/
+
+short	tdbox[][8] = {		/* display box parameters */
+
+	{  0,   0,  95, 335, TCFBX00, TCBBX00,  0,  1},	/* 0 */
+	{ 96,   0, 175, 335, TCFBX01, TCBBX01,  0, 13},	/* 1 */
+	{176,   0, 255, 335, TCFBX02, TCBBX02,  0, 23},	/* 2 */
+	{256,   0, 335, 335, TCFBX03, TCBBX03,  0, 33},	/* 3 */
+	{336,   0, 423, 335, TCFBX04, TCBBX04,  0, 43},	/* 4 */
+	{424,   0, 511, 118, TCFBX05, TCBBX05,  0, 54},	/* 5 */
+	{424, 119, 511, 349, TCFBX06, TCBBX06,  9, 54},	/* 6 */
+	{  0, 336, 423, 349, TCFBX07, TCBBX07, 24,  1}	/* 7 */
+};
+
+char	*tdbxlb[] = {		/* display box labels */
+
+	"",		/* 0 */
+	"",		/* 1 */
+	"",		/* 2 */
+	"",		/* 3 */
+	"",		/* 4 */
+	"",		/* 5 */
+	"",		/* 6 */
+	"Name:"		/* 7 */
+};
+
+/* 
+
+*/
+
+struct curpak td_flds = {
+
+	stdctp0,	/* curtype */
+	nokey,		/* premove */
+	nokey,		/* pstmove */
+	cxkstd,		/* cx_key */
+	cykstd,		/* cy_key */
+	tdcxupd,	/* cx_upd */
+	tdcyupd,	/* cy_upd */
+	nokey,		/* xy_up */
+	nokey,		/* xy_dn */
+	nokey,		/* x_key */
+	select,		/* e_key */
+	stdmkey,	/* m_key */
+	stddkey,	/* d_key */
+	nokey,		/* not_fld */
+	td_fet1,	/* curfet */
+	tdboxes,	/* csbp */
+	crate1,		/* cratex */
+	crate1,		/* cratey */
+	CT_TEXT,	/* cmtype */
+	TDCURX,		/* cxval */
+	TDCURY		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tdcyupd() -- update cursor y location
+   =============================================================================
+*/
+
+tdcyupd()
+{
+	register short pval, vh, vl;
+
+	if (tdnamsw) {	/* see if we're in the menu area */
+
+		vtcrow = YTOR(vtyval += cyrate);
+
+		if (vtcrow > (vtwrow + 2))
+			vtyval = RTOY(vtcrow = vtwrow + 2);
+		else if (vtcrow < vtwrow)
+			vtyval = RTOY(vtcrow = vtwrow);
+
+	} else {		/* just moving the cursor */
+
+		cyval += cyrate;
+
+		if (cyval GT (CYMAX - 1))
+			cyval = CYMAX - 1;
+		else if (cyval LT 1)
+			cyval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tdcxupd() -- update cursor x location
+   =============================================================================
+*/
+
+tdcxupd()
+{
+
+	if (tdnamsw) {	/* see if we're in the menu area */
+
+		vtccol = XTOC(vtxval += cxrate);
+
+		if (vtccol > (vtwcol + 29))
+			vtxval = CTOX(vtccol = vtwcol + 29);
+		else if (vtccol < vtwcol)
+			vtxval = CTOX(vtccol = vtwcol);
+
+	} else {			/* just moving the cursor */
+
+		cxval += cxrate;
+
+		if (cxval GT (CXMAX- 1))
+			cxval = CXMAX - 1;
+		else if (cxval LT 1)
+			cxval = 1;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tdfield() -- setup field routines for the tuning editor
+   =============================================================================
+*/
+
+tdfield()
+{
+	tdnamsw = FALSE;
+	submenu = FALSE;
+
+	curset(&td_flds);
+}
Index: ram/tdselbx.c
===================================================================
--- ram/tdselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/tdselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,419 @@
+/*
+   =============================================================================
+	tdselbx.c -- tuning editor box selection functions
+	Version 14 -- 1988-12-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "tundsp.h"
+
+extern	short	enterit(), loc2key(), advtcur(), bsptcur(), vtdisp(), nokey();
+
+extern	unsigned	exp_c();
+
+extern	short	hitbox, cxval, cyval, hitcx, hitcy, submenu;
+extern	short	tunmod, curtun, tdnamsw;
+extern	short	ttcmdsv, ttsel1, ttsel2, ttsel3;
+
+extern	short	tdbox[][8];
+
+extern	struct	selbox	*csbp, *curboxp;
+
+extern	unsigned	*tunob;
+
+extern	short	tuntab[];
+extern	short	oldtun[];
+
+extern	char	tuncurn[];
+extern	char	vtlin1[], vtlin2[], vtlin3[];
+
+/* forward references */
+
+short	bx_null(), tdfnbox();
+
+/* 
+
+*/
+
+struct	selbox	tdboxes[] = {
+
+	{  0,   0,  95, 335,      0, tdfnbox},	/*  0: keys   0..23 */
+	{ 96,   0, 175, 335,      1, tdfnbox},	/*  1: keys  24..47 */
+	{176,   0, 255, 335,      2, tdfnbox},	/*  2: keys  48..71 */
+	{256,   0, 335, 335,      3, tdfnbox},	/*  3: keys  72..95 */
+	{336,   0, 423, 335,      4, tdfnbox},	/*  4: keys  96..119 */
+	{424,   0, 511, 118,      5, tdfnbox},	/*  5: keys 120..127 */
+	{424, 119, 511, 349,      6, tdfnbox},	/*  6: commands */
+	{  0, 336, 423, 349,      7, tdfnbox},	/*  7: name */
+
+	{  0,   0,   0,   0,	  0, FN_NULL}		/* end of table */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	endttyp() -- end function for virtual typewriter
+   =============================================================================
+*/
+
+endttyp()
+{
+	tdnamsw = FALSE;
+	submenu = FALSE;
+	tdswin(0);
+	tdswin(1);
+	tdswin(2);
+	tdswin(6);
+}
+
+/*
+   =============================================================================
+	tcoladj() -- adjust select column to be a display column
+   =============================================================================
+*/
+
+short
+tcoladj(icol)
+short icol;
+{
+	if (icol < 12)
+		return(6);
+	else if (icol < 22)
+		return(16);
+	else if (icol < 32)
+		return(26);
+	else if (icol < 42)
+		return(36);
+	else if (icol < 53)
+		return(47);
+	else
+		return(58);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tdhilit() -- highlight selected tuning entries
+   =============================================================================
+*/
+
+tdhilit(from, to)
+short from, to;
+{
+	register short i, row, col, box;
+
+	if (to < from) {
+
+		i = to;
+		to = from;
+		from = i;
+	}
+/* 
+
+*/
+	for (i = from; i LE to; i++) {
+
+		if (i < 24) {
+
+			row = i;
+			col = 6;
+			box = 0;
+
+		} else if (i < 48) {
+
+			row = i - 24;
+			col = 16;
+			box = 1;
+
+		} else if (i < 72) {
+
+			row = i - 48;
+			col = 26;
+			box = 2;
+
+		} else if (i < 96) {
+
+			row = i - 72;
+			col = 36;
+			box = 3;
+
+		} else if (i < 120) {
+
+			row = i - 96;
+			col = 47;
+			box = 4;
+
+		} else {
+
+			row = i - 120;
+			col = 58;
+			box = 5;
+		}
+
+		dsttval(row, col, tuntab[i], TDSELD, tdbox[box][5]);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tdfnbox() -- tuning display box hit processor
+   =============================================================================
+*/
+
+short
+tdfnbox(n)
+short n;
+{
+	register short i, key, dcol, row, col;
+
+	row = hitcy / 14;
+	col = hitcx >> 3;
+
+	switch (hitbox) {
+
+	case 0:				/* pitch area */
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+
+		switch (ttcmdsv) {	/* switch on editing state */
+
+		case 0:			/* data entry */
+
+			enterit();
+			return(SUCCESS);
+/* 
+
+*/
+		case 1:			/* transpose and copy -- start */
+
+			ttsel1 = loc2key(row, col);
+
+			if (ttsel1 < 0) {
+
+				ttcmdsv = 0;
+				tdswin(6);
+				return(SUCCESS);
+			}
+
+			ttcmdsv = 2;
+			dcol = tcoladj(col);
+			dsttval(row, dcol, tuntab[ttsel1], TDSELD,
+				tdbox[hitbox][5]);
+
+			return(SUCCESS);
+
+		case 2:			/* transpose and copy -- finish */
+
+			ttsel2 = loc2key(row, col);
+
+			if (ttsel2 < 0) {
+
+				ttcmdsv = 0;
+				tdswin(6);
+				return(SUCCESS);
+			}
+
+			ttcmdsv = 3;
+			tdhilit(ttsel1, ttsel2);
+			return(SUCCESS);
+
+		case 3:			/* transpose and copy -- dest */
+
+			ttsel3 = loc2key(row, col);
+
+			if (ttsel3 GE 0)
+				tt_trcp(ttsel1, ttsel2, ttsel3);
+
+			ttcmdsv = 0;
+
+			for (i = 0; i < 7; i++)
+				tdswin(i);
+
+			return(SUCCESS);
+/* 
+
+*/
+		case 4:			/* increment -- from */
+
+			ttsel1 = loc2key(row, col);
+
+			if (ttsel1 < 0) {
+
+				ttcmdsv = 0;
+				tdswin(6);
+				return(SUCCESS);
+			}
+
+			ttcmdsv = 5;
+			dcol = tcoladj(col);
+			dsttval(row, dcol, tuntab[ttsel1], TDSELD,
+				tdbox[hitbox][5]);
+
+			return(SUCCESS);
+
+		case 5:			/* increment -- to */
+
+			ttsel2 = loc2key(row, col);
+
+			if (ttsel2 GE 0)
+				tt_incr(ttsel1, ttsel2);
+
+			ttcmdsv = 0;
+
+			for (i = 0; i < 7; i++)
+				tdswin(i);
+
+			return(SUCCESS);
+/* 
+
+*/
+		case 6:			/* interpolate -- from */
+
+			ttsel1 = loc2key(row, col);
+
+			if (ttsel1 < 0) {
+
+				ttcmdsv = 0;
+				tdswin(6);
+				return(SUCCESS);
+			}
+
+			ttcmdsv = 7;
+			dcol = tcoladj(col);
+			dsttval(row, dcol, tuntab[ttsel1], TDSELD,
+				tdbox[hitbox][5]);
+
+			return(SUCCESS);
+
+		case 7:			/* interpolate -- to */
+
+			ttsel2 = loc2key(row, col);
+
+			if (ttsel2 GE 0)
+				tt_intp(ttsel1, ttsel2);
+
+			ttcmdsv = 0;
+
+			for (i = 0; i < 7; i++)
+				tdswin(i);
+
+			return(SUCCESS);
+		}
+
+		return(FAILURE);
+/* 
+
+*/
+	case 6:				/* command, value, table # */
+
+		switch (row) {
+
+		case 9:				/* transpose and copy */
+		case 10:
+
+			ttcmdsv = 1;
+			td_trcp(1);
+			return(SUCCESS);
+
+		case 12:			/* increment */
+
+			ttcmdsv = 4;
+			td_incr(1);
+			return(SUCCESS);
+
+		case 14:			/* interpolate */
+
+			ttcmdsv = 6;
+			td_intp(1);
+			return(SUCCESS);
+
+		case 16:			/* undo */
+
+			ttcmdsv = 0;
+			memcpyw(tuntab, oldtun, 128);
+			twins();
+			return(SUCCESS);
+/* 
+
+*/
+		case 18:			/* data entry */
+		case 24:
+
+			enterit();
+			return(SUCCESS);
+
+		case 20:			/* store */
+
+			if (curtun EQ 0)
+				return(FAILURE);
+
+			puttun(curtun);
+			memcpyw(oldtun, tuntab, 128);
+			tdswin(6);
+			return(SUCCESS);
+
+		case 22:			/* retrieve */
+
+			gettun(curtun);
+			memcpyw(oldtun, tuntab, 128);
+			twins();
+			return(SUCCESS);
+		}
+
+		return(FAILURE);
+
+/* 
+
+*/
+	case 7:		/* tuning table name */
+
+		if ((col < 7) OR (col GT 38))
+			return(FAILURE);
+
+		if (tdnamsw) {
+
+			vtyper();
+			tunmod = TRUE;
+
+		} else {
+
+			vbank(0);
+			vbfill4(tunob, 128, CTOX(1), RTOY(21),
+				CTOX(31) - 1, RTOY(24) - 1, exp_c(TDTCURB));
+
+			tsplot4(tunob, 64, TDTCHRC, 21, 1, vtlin1, 14);
+			tsplot4(tunob, 64, TDTCHRC, 22, 1, vtlin2, 14);
+			tsplot4(tunob, 64, TDTCHRC, 23, 1, vtlin3, 14);
+
+			vtsetup(tunob, vtdisp, 7, tuncurn, 21, 1,
+				advtcur, bsptcur, nokey, nokey, endttyp,
+				tdbox[n][4], tdbox[n][5]);
+
+			tdnamsw = TRUE;
+			submenu = TRUE;
+		}
+
+		return(SUCCESS);
+	}
+
+	return(FAILURE);
+}
Index: ram/timeint.s
===================================================================
--- ram/timeint.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/timeint.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,385 @@
+* ------------------------------------------------------------------------------
+* timeint.s -- MIDAS-VII timer interrupt handler
+* Version 15 -- 1989-07-20 -- D.N. Lynx Crowe
+* ------------------------------------------------------------------------------
+*
+* This code replaces the interrupt handler in bios.s, which is known to
+* have a bug in it, and adds support for the VSDD and an array of programable
+* timers with 1 Ms resolution.
+*
+* WARNING:  There are equates to addresses in the bios EPROM which may change
+* when the bios is reassembled.  If the bios is reassembled be sure to update
+* the equates flagged by "<<<=====".
+*
+* The addresses currently in the equates are for EPROMs dated 1988-04-18 or
+* 1988-06-20 ONLY.
+*
+* ------------------------------------------------------------------------------
+* Hardware timer usage:
+* ---------------------
+*	Timer 1		PLL divider for score clock -- fixed at 64
+*	Timer 2		PLL divider for score clock -- nominally 3200
+*	Timer 3		1 Ms Real Time Clock
+*
+* ------------------------------------------------------------------------------
+*
+		.text
+*
+		.xdef	_tsetup		* tsetup() -- timer setup function
+		.xdef	timeint		* timer interrupt handler
+*
+		.xdef	_M1IoRec	* MIDI channel 1 IoRec		
+		.xdef	_M2IoRec	* MIDI channel 2 IoRec		
+		.xdef	_S1IoRec	* RS232 channel 1 IoRec		
+		.xdef	_S2IoRec	* RS232 channel 2 IoRec		
+		.xdef	_timers		* timer array -- short timers[NTIMERS]
+		.xdef	_vi_clk		* VSDD scroll delay timer
+		.xdef	_vi_tag		* VSDD VI tag
+*
+		.xref	lclsadr		* score object base address
+		.xref	lclscrl		* score object scroll offset
+		.xref	_v_odtab	* VSDD object descriptor table
+*
+		.page
+* ==============================================================================
+*
+FRAMES		.equ	0		* set non-zero to enable frame pulses
+*
+* Equates to variables in bios.s:
+* -------------------------------
+* These variables are permanently assigned.
+*
+TIMEVEC		.equ	$00000400	* LONG - System timer trap vector
+*
+FC_SW		.equ	$00000420	* WORD - Frame clock switch
+FC_VAL		.equ	$00000422	* LONG - Frame clock value
+*
+HZ_1K		.equ	$0000049A	* LONG - 1000 Hz clock
+HZ_200		.equ	$0000049E	* LONG - 200 Hz clock
+FRCLOCK		.equ	$000004A2	* LONG - 50 Hz clock
+*
+T3COUNT		.equ	$000004AA	* WORD - Timer 3 count
+*
+* ------------------------------------------------------------------------------
+*
+* WARNING:  The address of "FLOCK" depends on the version of the bios EPROM.
+* The address below is for EPROMs dated 1988-04-18 or 1988-06-20 ONLY.
+*
+FLOCK		.equ	$00000E0C	* WORD - Floppy semaphore	<<<=====
+*
+* ==============================================================================
+*
+* Equates to routines in bios.s:
+* ------------------------------
+*
+* WARNING:  The address of "FLOPVBL" depends on the version of the bios EPROM.
+* The address below is for EPROMs dated 1988-04-18 or 1988-06-20 ONLY.
+*
+FLOPVBL		.equ	$001015EE	* floppy VI handler address	<<<=====
+*
+* ==============================================================================
+*
+		.page
+*
+* Hardware address equates:
+* -------------------------
+TI_VEC		.equ	$00000070	* Timer interrupt autovector
+*
+TIMER		.equ	$003A0001	* Timer base address
+M1_ACIA		.equ	$003AC001	* MIDI ACIA channel 1 base address
+*
+* ------------------------------------------------------------------------------
+*
+* Timer register equates:
+* -----------------------
+TIME_CRX	.equ	TIMER		* Control register 1 or 3
+TIME_CR2	.equ	TIMER+2		* Control register 2
+TIME_T1H	.equ	TIMER+4		* Timer 1 high byte
+TIME_T1L	.equ	TIMER+6		* Timer 1 low byte
+TIME_T2H	.equ	TIMER+8		* Timer 2 high byte
+TIME_T2L	.equ	TIMER+10	* Timer 2 low byte
+TIME_T3H	.equ	TIMER+12	* Timer 3 high byte
+TIME_T3L	.equ	TIMER+14	* Timer 3 low byte
+*
+* Serial I/O equates:
+* -------------------
+ACIA_CFR	.equ	2		* CFR offset from ACIA base
+DTR_BIT		.equ	1		* DTR bit in ACIA CFR1
+*
+IO_CFR1		.equ	29		* cfr1 offset in M1IoRec
+*
+* ==============================================================================
+*
+* Miscellaneous equates:
+* ----------------------
+IPL7		.equ	$0700		* IPL mask for interrupt disable
+*
+FCMAX		.equ	$00FFFFFF	* Maximum frame counter value
+FCMIN		.equ	$00000000	* Minimum frame counter value
+*
+NTIMERS		.equ	8		* Number of timers in the timer array
+*
+XBIOS		.equ	14		* XBIOS TRAP number
+X_PIOREC	.equ	0		* X_PIOREC code
+SR1_DEV		.equ	0		* RS232 ACIA channel 1
+SR2_DEV		.equ	1		* RS232 ACIA channel 2
+MC1_DEV		.equ	3		* MIDI ACIA channel 1
+MC2_DEV		.equ	4		* MIDI ACIA channel 2
+* ==============================================================================
+*
+		.page
+* ==============================================================================
+* _tsetup -- tsetup() -- timer setup function
+* ==============================================================================
+*
+_tsetup:	move.w	sr,-(a7)		* Save old interrupt mask
+		ori.w	#IPL7,sr		* Disable interrupts
+*
+		move.w	#SR1_DEV,-(a7)		* Establish S1IoRec
+		move.w	#X_PIOREC,-(a7)		* ...
+		trap	#XBIOS			* ...
+		add.l	#4,a7			* ...
+		move.l	d0,_S1IoRec		* ...
+*
+		move.w	#SR2_DEV,-(a7)		* Establish S2IoRec
+		move.w	#X_PIOREC,-(a7)		* ...
+		trap	#XBIOS			* ...
+		add.l	#4,a7			* ...
+		move.l	d0,_S2IoRec		* ...
+*
+		move.w	#MC1_DEV,-(a7)		* Establish M1IoRec
+		move.w	#X_PIOREC,-(a7)		* ...
+		trap	#XBIOS			* ...
+		add.l	#4,a7			* ...
+		move.l	d0,_M1IoRec		* ...
+*
+		move.w	#MC2_DEV,-(a7)		* Establish M2IoRec
+		move.w	#X_PIOREC,-(a7)		* ...
+		trap	#XBIOS			* ...
+		add.l	#4,a7			* ...
+		move.l	d0,_M2IoRec		* ...
+*
+		.page
+*
+		clr.w	FC_SW			* Stop the frame clock
+		clr.l	FC_VAL			* ... and reset it
+		clr.w	_vi_tag			* Clear VSDD VI tag
+		clr.w	_vi_clk			* Clear VSDD delay timer
+		clr.w	lclsadr			* Clear score scroll address
+		clr.w	lclscrl			* Clear score scroll offset
+*
+		lea	_timers,a0		* Point at timer array
+		move.w	#NTIMERS-1,d0		* Setup to clear timer array
+*
+tclr:		clr.w	(a0)+			* Clear a timer array entry
+		dbra	d0,tclr			* Loop until done
+*
+		move.l	#nullrts,TIMEVEC	* Set timer interrupt vector
+		move.l	#timeint,TI_VEC		* Set timer trap vector
+*
+		move.b	#$00,TIME_T1H		* Setup timer 1  (PLL)
+		move.b	#$1F,TIME_T1L		* ... for divide by 64
+		move.b	#$0C,TIME_T2H		* Setup timer 2  (FC)
+		move.b	#$7F,TIME_T2L		* ... for divide by 3200
+		move.b	#$03,TIME_T3H		* Setup timer 3  (RTC)
+		move.b	#$20,TIME_T3L		* ... for 1Ms interval
+		move.b	#$42,TIME_CRX		* Setup CR3
+		move.b	#$41,TIME_CR2		* Setup CR2
+		move.b	#$81,TIME_CRX		* Setup CR1
+		move.b	#$80,TIME_CRX		* Start the timers
+*
+		move.w	(a7)+,sr		* Restore interrupts
+*
+nullrts:	rts				* Return to caller
+*
+		.page
+* ==============================================================================
+* timeint -- timer interrupt handler
+* ==============================================================================
+*
+timeint:	movem.l	d0-d7/a0-a6,-(a7)	* Save registers
+		move.b	TIME_CR2,d0		* Get timer interrupt status
+* ------------------------------------------------------------------------------
+* process 1 MS timer
+* ------------------------------------------------------------------------------
+		btst.l	#2,d0			* Check timer 3 status
+		beq	tmi02			* Jump if not active
+*
+		move.b	TIME_T3H,d1		* Read timer 3 count
+		lsl.w	#8,d1			* ...
+		move.b	TIME_T3L,d1		* ...
+		move.w	d1,T3COUNT		* ... and save it
+*
+		addq.l	#1,HZ_1K		* Update 1ms clock  (1 KHz)
+*
+		move.l	d0,-(a7)		* Preserve D0
+* ------------------------------------------------------------------------------
+* process VSDD timer
+* ------------------------------------------------------------------------------
+		tst.w	_vi_tag			* Does the VSDD need service ?
+		beq	updtime			* Jump if not
+*
+		move.w	_vi_clk,d0		* Get VSDD scroll delay timer
+		subq.w	#1,d0			* Decrement timer
+		move.w	d0,_vi_clk		* Update timer
+		bne	updtime			* Jump if it's not zero yet
+*
+		move.w	lclsadr,_v_odtab+12	* Update scroll address
+		move.w	lclscrl,_v_odtab+10	* Update scroll offset
+		clr.w	_vi_tag			* Reset the tag
+*
+		.page
+*
+* ------------------------------------------------------------------------------
+* process programable timers
+* ------------------------------------------------------------------------------
+*
+updtime:	move.w	#NTIMERS-1,d0		* Setup timer array counter
+		lea	_timers,a0		* Point at timer array
+*
+tdcr:		move.w	(a0),d1			* Get timer array entry
+		beq	tdcr1			* Jump if already 0
+*
+		subq.w	#1,d1			* Decrement timer
+*
+tdcr1:		move.w	d1,(a0)+		* Store updated timer value
+		dbra	d0,tdcr			* Loop until done
+*
+* ------------------------------------------------------------------------------
+* process timer hook vector
+* ------------------------------------------------------------------------------
+		movea.l	TIMEVEC,a0		* Get RTC vector
+		move.w	#1,-(a7)		* Pass 1 msec on stack
+		jsr	(a0)			* Process RTC vector
+		addq.l	#2,a7			* Clean up stack
+*
+		move.l	(a7)+,d0		* Restore D0
+*
+		.page
+* ------------------------------------------------------------------------------
+* process 5 Ms clock
+* ------------------------------------------------------------------------------
+		move.w	tdiv1,d1		* Update divider
+		addq.w	#1,d1			* ...
+		move.w	d1,tdiv1		* ...
+*
+		cmpi.w	#5,d1			* Do we need to update HZ_200 ?
+		blt	tmi02			* Jump if not
+*
+		addq.l	#1,HZ_200		* Update 5ms clock   (200 Hz)
+* ------------------------------------------------------------------------------
+* process 20 Ms floppy clock
+* ------------------------------------------------------------------------------
+		move.w	tdiv2,d1		* Update divider
+		addq.w	#1,d1			* ...
+		move.w	d1,tdiv2		* ...
+*
+		cmpi.w	#4,d1			* Do we need to update FRCLOCK ?
+		blt	tmi01			* Jump if not
+*
+		addq.l	#1,FRCLOCK		* Update 20 Ms clock  (50 Hz)
+		tst.w	FLOCK			* See if floppy is active
+		bne	tmi00			* Don't call FLOPVBL if so
+*
+		jsr	FLOPVBL			* Check on the floppy
+*
+tmi00:		move.w	#0,tdiv2		* Reset tdiv2
+*
+tmi01:		move.w	#0,tdiv1		* Reset tdiv1
+*
+		.page
+* ------------------------------------------------------------------------------
+* process PLL timers
+* ------------------------------------------------------------------------------
+*
+tmi02:		btst.l	#0,d0			* Check timer 1 int
+		beq	tmi03			* Jump if not set
+*
+		move.b	TIME_T1H,d1		* Read timer 1 to clear int.
+		move.b	TIME_T1L,d1		* ...
+*
+tmi03:		btst.l	#1,d0			* Check for timer 2 int.
+		beq	tmi04			* Jump if not set
+*
+		move.b	TIME_T2H,d1		* Read timer 2 to clear int.
+		move.b	TIME_T2L,d1		* ...
+*
+		.page
+* ------------------------------------------------------------------------------
+* update score frame counter
+* ------------------------------------------------------------------------------
+		tst.w	FC_SW			* Should we update the frame ?
+		beq	tmi04			* Jump if not
+*
+		bmi	tmi05			* Jump if we count down
+*
+		move.l	FC_VAL,d0		* Get the frame count
+		cmp.l	#FCMAX,d0		* See it we've topped out
+		bge	tmi06			* Jump if limit was hit
+*
+		addq.l	#1,d0			* Count up 1 frame
+		move.l	d0,FC_VAL		* Store updated frame count
+*
+		.ifne	FRAMES
+		move.w	sr,d1			* Preserve interrupt status
+		ori.w	#$0700,sr		* Disable interrupts
+*
+		movea.l	_M1IoRec,a0		* Point at M1IoRec
+		move.b	IO_CFR1(a0),d0		* Get MIDI-1 CFR1 value
+		or.b	#$80,d0			* Force MSB = 1 for CFR1 output
+		movea.l	#M1_ACIA,a0		* Point at MIDI-1 ACIA channel
+		bchg.l	#DTR_BIT,d0		* Toggle DTR for output
+		move.b	d0,ACIA_CFR(a0)		* Output toggled DTR
+		bchg.l	#DTR_BIT,d0		* Toggle DTR for output
+		move.b	d0,ACIA_CFR(a0)		* Output toggled DTR
+		move.w	d1,sr			* Restore interrupts
+		.endc
+*
+		bra	tmi04			* Done
+*
+tmi07:		move.l	#FCMIN,FC_VAL		* Force hard limit, just in case
+		bra	tmi04			* Done
+*
+tmi06:		move.l	#FCMAX,FC_VAL		* Force hard limit, just in case
+		bra	tmi04			* Done
+*
+tmi05:		move.l	FC_VAL,d0		* Get the frame count
+		ble	tmi07			* Done if already counted down
+*
+		subq.l	#1,d0			* Count down 1 frame
+		move.l	d0,FC_VAL		* Store udpated frame count
+		bra	tmi04			* Done
+*
+		nop				* Filler to force equal paths
+*
+tmi04:		movem.l	(a7)+,d0-d7/a0-a6	* Restore registers
+		rte				* Return to interrupted code
+*
+		.page
+* ==============================================================================
+		.bss
+* ==============================================================================
+*
+* A note on tdiv1 and tdiv2:
+* --------------------------
+*
+* tdiv1 and tdiv2 are actually defined in the bios,  but since they could move
+* we define them here and ignore the ones in the bios.
+*
+tdiv1:		ds.w	1		* Timer divider 1  (divides HZ_1K)
+tdiv2:		ds.w	1		* Timer divider 2  (divides HZ_200)
+*
+* ------------------------------------------------------------------------------
+*
+_timers:	ds.w	NTIMERS		* Timer array -- short timers[NTIMERS];
+*
+_vi_clk:	ds.w	1		* VSDD scroll delay timer
+_vi_tag:	ds.w	1		* VSDD VI 'needs service' tag
+*
+_S1IoRec:	ds.l	1		* address of RS232 channel 1 IoRec
+_S2IoRec:	ds.l	1		* address of RS232 channel 2 IoRec
+_M1IoRec:	ds.l	1		* address of MIDI channel 1 IoRec
+_M2IoRec:	ds.l	1		* address of MIDI channel 2 IoRec
+* ==============================================================================
+*
+		.end
Index: ram/tofpu.s
===================================================================
--- ram/tofpu.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/tofpu.s	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,76 @@
+* ------------------------------------------------------------------------------
+* tofpu.s -- convert between millisecond time interval and FPU increment formats
+* Version 9 -- 1987-12-21 -- D.N. Lynx Crowe
+*
+*	unsigned short
+*	tofpu(time)
+*	unsigned short time;
+*
+*		Converts 'time' in milliseconds to FPU format.
+*
+*	unsigned short
+*	fromfpu(fputime)
+*	unsigned short fputime;
+*
+*		Converts 'fputime' from FPU format to milliseconds.
+* ------------------------------------------------------------------------------
+		.text
+*
+		.xdef	_tofpu
+		.xdef	_fromfpu
+*
+TIME		.equ	8		* WORD - time argument  (either format)
+*
+TCYCL		.equ	$3B000000	* LONG - scaled FPU cycle time  (.4608)
+*
+		.page
+_tofpu:		link	a6,#0		* link stack frames
+		move.w	TIME(a6),d1	* get time interval
+		beq	notime		* jump if zero time
+*
+		clr.w	d2		* clear shift count
+*
+sloop:		btst	#15,d1		* see if MSB is set yet
+		bne	gotexp		* jump if so
+*
+		lsl.w	d1		* shift time left a bit
+		addq.w	#1,d2		* increment the shift count
+		cmpi.w	#15,d2		* see if we've hit the maximum
+		bne	sloop		* try again if not
+*
+gotexp:		move.l	#TCYCL,d0	* divide FPU cycle time by shifted value
+		divu	d1,d0		* ...
+		andi.w	#$FFF0,d0	* mask result
+		or.w	d2,d0		* set the exponent
+*
+finis:		unlk	a6		* unlink stack frames
+		rts			* return to caller
+*
+notime:		clr.w	d0		* zero time is zero ...
+		bra	finis		* return value for zero time
+*
+		.page
+_fromfpu:	link	a6,#0		* link stack frames
+		move.w	TIME(a6),d1	* get FPU formatted time
+		beq	zerotime	* done if it's zero
+*
+		move.w	d1,d2		* extract shift count
+		andi.w	#$000F,d2	* ...
+		andi.w	#$FFF0,d1	* extract mantissa
+		beq	zerotime	* ... just in case it's zero  (an error)
+*
+		move.l	#TCYCL,d0	* get FPU cycle time
+		divu	d1,d0		* divide by mantissa
+		bvc	divok		* jump if divide ok
+*
+		move.w	#$FFFF,d0	* jam maximum value for overflow
+*
+divok:		lsr.w	d2,d0		* shift result into position
+*
+byebye:		unlk	a6		* unlink stack frames
+		rts			* return to caller
+*
+zerotime:	clr.l	d0		* return a zero result
+		bra	byebye		* ...
+*
+		.end
Index: ram/ttcpos.c
===================================================================
--- ram/ttcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ttcpos.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,102 @@
+/*
+   =============================================================================
+	ttcpos.c -- virtual typewriter cursor positioning
+	Version 9 -- 1988-03-08 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "hwdefs.h"
+#include "memory.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "libdsp.h"
+
+#define	CW_0	0x0000
+#define	CW_F	0xFFFF
+
+extern	unsigned	exp_c();
+
+extern	short	vtcrow;		/* virtual typewriter cursor row */
+extern	short	vtccol;		/* virtual typewriter cursor column */
+
+/* 
+
+*/
+
+static short ttcur[] = {
+
+	CW_0, CW_0, CW_0, CW_0,	/* 0 */
+	CW_0, CW_0, CW_0, CW_0,	/* 1 */
+	CW_0, CW_0, CW_0, CW_0,	/* 2 */
+	CW_0, CW_0, CW_0, CW_0,	/* 3 */
+	CW_0, CW_0, CW_0, CW_0,	/* 4 */
+	CW_0, CW_0, CW_0, CW_0,	/* 5 */
+	CW_0, CW_0, CW_0, CW_0,	/* 6 */
+	CW_0, CW_0, CW_0, CW_0,	/* 7 */
+	CW_0, CW_0, CW_0, CW_0,	/* 8 */
+	CW_0, CW_0, CW_0, CW_0,	/* 9 */
+	CW_0, CW_0, CW_0, CW_0,	/* 10 */
+	CW_0, CW_0, CW_0, CW_0,	/* 11 */
+	CW_F, CW_F, CW_0, CW_0,	/* 12 */
+	CW_0, CW_0, CW_0, CW_0,	/* 13 */
+	CW_0, CW_0, CW_0, CW_0,	/* 14 */
+	CW_0, CW_0, CW_0, CW_0	/* 15 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ttcini() -- initialize typewriter cursor
+   =============================================================================
+*/
+
+ttcini(color)
+unsigned color;
+{
+	if ((v_regs[5] & 0x0180) NE 0x0100)
+		vbank(1);
+
+	andcopy(v_tcur, ttcur, exp_c(color), 64);
+}
+
+/*
+   =============================================================================
+	ttcpos() -- position the typewriter cursor at ('row', 'col')
+   =============================================================================
+*/
+
+ttcpos(row, col)
+register short row, col;
+{
+	register short yrow, xcol;
+	register struct octent *op;
+
+	if (v_regs[5] & 0x0180)		/* point at the control bank */
+		vbank(0);
+
+	yrow = row * 14;		/* get cursor display position */
+	xcol = col << 3;
+
+	op = &v_obtab[TTCURS];		/* point at v_obtab entry */
+
+	v_odtab[TTCPRI][0] |= V_BLA;	/* blank the object */
+	objclr(TTCPRI);			/* turn off the old location */
+
+	op->objx = xcol;		/* update v_obtab entry */
+	op->objy = yrow;
+	op->odtw1 = 0x0400 | (0x03FF & (xcol >> 1));
+
+	SetPri(TTCURS, TTCPRI);		/* turn on the new location */
+
+	vtcrow = row;			/* update cursor position variables */
+	vtccol = col;
+}
Index: ram/tundsp.c
===================================================================
--- ram/tundsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/tundsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,655 @@
+/*
+   =============================================================================
+	tundsp.c -- MIDAS tuning table editor
+	Version 23 -- 1988-11-28 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "hwdefs.h"
+#include "biosdefs.h"
+#include "stddefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "charset.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "tundsp.h"
+
+#define	TUN_VAL	100		/* default value for tunval in cents */
+
+extern	short	stcrow, stccol, cxval, cyval;
+
+extern	short	curtun;		/* current tuning table */
+extern	short	submenu;	/* submenu cursor switch */
+extern	short	tunmod;		/* tuning table modified */
+extern	short	tunval;		/* tuning table generator value */
+extern	short	ttcmdsv;	/* tuning table editing state variable */
+extern	short	tdnamsw;	/* tuning editor displaying typewriter */
+
+extern	short	oldtun[];	/* previous tuning table for undo */
+extern	short	tuntab[];	/* current tuning table */
+extern	short	tunlib[][128];	/* tuning table library */
+
+extern	short	panlkey[];	/* local key tunings */
+extern	short	lclkmap[];	/* local key to MIDI key map */
+
+extern	char	tuncurn[];	/* current tuning table name */
+extern	char	tunname[][32];	/* tuning table names */
+extern	char	sfdsp[];
+
+extern	unsigned	*obj0, *obj2;
+
+extern	char	bfs[];
+extern	char	*tdbxlb[];
+
+extern	short	tdbox[][8];
+
+extern	unsigned	*tunob;
+
+extern	struct	octent	*tdoct;
+
+/* 
+
+*/
+
+short	tunpal[16][3] = {	/* color palette */
+
+	{0, 0, 0},	/* 0 */
+	{3, 3, 3},	/* 1 */
+	{0, 0, 0},	/* 2 */
+	{3, 3, 3},	/* 3 */
+	{1, 1, 0},	/* 4 */
+	{1, 0, 1},	/* 5 */
+	{0, 1, 1},	/* 6 (was 0, 1, 0) */
+	{0, 1, 1},	/* 7 (was 0, 1, 0) */
+	{0, 0, 1},	/* 8 (was 0, 0, 2) */
+	{0, 2, 3},	/* 9 (was 0, 3, 0) */
+	{2, 2, 2},	/* 10 */
+	{2, 3, 3},	/* 11 */
+	{3, 3, 0},	/* 12 */
+	{3, 3, 0},	/* 13 */
+	{3, 0, 0},	/* 14 */
+	{0, 0, 3}	/* 15 */
+};
+
+			/*   12345678901234567890123456789012	*/
+static	char	dfltnam[] = "Local 3rds + MIDI 12 tone scale ";
+
+char	*tdlabl[] = {
+
+	"C", "#", "D", "#", "E", "F", "#", "G",
+	"#", "A", "#", "B", "C", "#", "D", "#",
+	"E", "F", "#", "G", "#", "A", "#", "B"
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	gettun() -- retrieve a tuning table from the tuning table library
+   =============================================================================
+*/
+
+gettun(n)
+short n;
+{
+	memcpyw(tuntab, tunlib[n], 128);
+	memcpy(tuncurn, tunname[n], 32);
+	curtun = n;
+	tunmod = FALSE;
+}
+
+/*
+   =============================================================================
+	puttun() -- store a tuning table in the tuning table library
+   =============================================================================
+*/
+
+puttun(n)
+short n;
+{
+	memcpyw(tunlib[n], tuntab, 128);
+	memcpy(tunname[n], tuncurn, 32);
+	tunmod = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	inittt() -- initialize tuning table to equal tempered 12 tone scale
+   =============================================================================
+*/
+
+inittt(n)
+short n;
+{
+	register short i;
+
+	for (i = 0; i < 128; i++)
+		tunlib[n][i] = ((i < 21) ? 160 : (i > 108) ? 10960 : 
+			(160 + ((i - 12) * 100))) << 1;
+
+	for (i = 0; i < 24; i++)
+		tunlib[n][lclkmap[i]] = panlkey[i] << 1;
+
+	strcpy(tunname[n], dfltnam);
+}
+
+
+/*
+   =============================================================================
+	inittl() -- initialize tuning table library
+   =============================================================================
+*/
+
+inittl()
+{
+	register short i;
+
+	for (i = 0; i < NTUNS; i++)
+		inittt(i);
+
+	tunval = TUN_VAL << 1;
+	gettun(0);
+	memcpyw(oldtun, tuntab, 128);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tt_trcp() -- transpose and copy tuning table values
+   =============================================================================
+*/
+
+tt_trcp(start, finish, dest)
+short start, finish, dest;
+{
+	register short i;
+	register long v;
+
+	memcpyw(oldtun, tuntab, 128);	/* preserve old table for undo */
+
+	if (start > finish) {
+
+		for (i = finish; ((i LE start) AND (dest < 128)); i++) {
+
+			/* reverse copy */
+
+			v = oldtun[i] + (long)tunval;	/* transpose */
+
+			if (v GT (long)PITCHMAX)	/* limit */
+				v = (long)PITCHMAX;
+			else if (v LT (long)PITCHMIN)
+				v = (long)PITCHMIN;
+
+			tuntab[dest++] = (short)v;	/* store the value */
+		}
+
+	} else {
+
+		for (i = start; ((i LE finish) AND (dest < 128)); i++) {
+
+			/* forward copy */
+
+			v = oldtun[i] + (long)tunval;	/* transpose */
+
+			if (v GT (long)PITCHMAX)	/* limit */
+				v = (long)PITCHMAX;
+			else if (v LT (long)PITCHMIN)
+				v = (long)PITCHMIN;
+
+			tuntab[dest++] = (short)v;	/* store the value */
+		}
+	}
+
+	tunmod = TRUE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tt_intp() -- interpolate tuning table values
+   =============================================================================
+*/
+
+short
+tt_intp(from, to)
+short from, to;
+{
+	register short i, j, k, n;
+	register long t;
+
+	memcpyw(oldtun, tuntab, 128);	/* preserve old table for undo */
+
+	if (from > to) {	/* adjust to and from for forward scan */
+
+		i = from;
+		from = to;
+		to = i;
+	}
+
+	n = to - from;			/* get interval size */
+
+	if (n < 2)
+		return(FAILURE);
+
+	k = tuntab[from];
+	t = (((long)tuntab[to] - (long)k) << 16) / n;
+	j = 1 + from;
+	n--;
+
+	for (i = 0; i < n ; i++)
+		tuntab[j++] = (short)((t * (1 + i)) >> 16) + k;
+
+	tunmod = TRUE;
+	return(SUCCESS);
+}
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tt_incr() -- increment tuning table values
+   =============================================================================
+*/
+
+short
+tt_incr(from, to)
+short from, to;
+{
+	register short i;
+	register long v;
+
+	memcpyw(oldtun, tuntab, 128);	/* preserve old table for undo */
+
+	if (from > to) {	/* adjust to and from for forward scan */
+
+		i = from;
+		from = to;
+		to = i;
+
+	}
+
+	v = (long)oldtun[from];		/* initial value */
+
+	if (from++ EQ to)		/* interval has to be at least 1 */
+		return(FAILURE);
+
+	for (i = from; i LE to; i++) {
+
+		v += (long)tunval;		/* increment */
+
+		if (v GT (long)PITCHMAX)	/* limit */
+			v = (long)PITCHMAX;
+		else if (v LT (long)PITCHMIN)
+			v = (long)PITCHMIN;
+
+		tuntab[i] = (short)v;		/* store the value */
+	}
+
+	tunmod = TRUE;
+	return(SUCCESS);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	td_trcp() -- display transpose select label
+   =============================================================================
+*/
+
+td_trcp(mode)
+short mode;
+{
+	register unsigned cx;
+
+	cx = exp_c(mode ? TDSELD : tdbox[6][4]);
+	vbank(0);
+	vcputsv(tunob, 64, cx, tdbox[6][5],  9, 54, "Transpose", 14);
+	vcputsv(tunob, 64, cx, tdbox[6][5], 10, 54, "and Copy", 14);
+}
+
+/*
+   =============================================================================
+	td_incr() -- display increment select label
+   =============================================================================
+*/
+
+td_incr(mode)
+short mode;
+{
+	register unsigned cx;
+
+	cx = exp_c(mode ? TDSELD : tdbox[6][4]);
+	vbank(0);
+	vcputsv(tunob, 64, cx, tdbox[6][5],  12, 54, "Increment", 14);
+}
+
+/*
+   =============================================================================
+	td_intp() -- display interpolate select label
+   =============================================================================
+*/
+
+td_intp(mode)
+short mode;
+{
+	register unsigned cx;
+
+	cx = exp_c(mode ? TDSELD : tdbox[6][4]);
+	vbank(0);
+	vcputsv(tunob, 64, cx, tdbox[6][5],  14, 54, "Intrpolat", 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	advtcur() -- advance the tuning display text cursor
+   =============================================================================
+*/
+
+advtcur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol + 1;
+
+	if (newcol LE cfetp->frcol)
+		itcpos(stcrow, newcol);
+
+	cxval = stccol * 8;
+	cyval = stcrow * 14;
+}
+
+/*
+   =============================================================================
+	bsptcur() -- backspace the tuning display text cursor
+   =============================================================================
+*/
+
+bsptcur()
+{
+	register short newcol;
+
+	if (infield(stcrow, stccol, curfet))
+		cfetp = infetp;
+	else
+		return;
+
+	newcol = stccol - 1;
+
+	if (newcol GE cfetp->flcol)
+		itcpos(stcrow, newcol);
+
+	cxval = stccol * 8;
+	cyval = stcrow * 14;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsttval() -- display a tuning table value
+   =============================================================================
+*/
+
+dsttval(row, col, val, fg, bg)
+short row, col, val;
+unsigned fg, bg;
+{
+	register unsigned cfg, cbg;
+
+	cfg = exp_c(fg);
+	cbg = exp_c(bg);
+
+	cnvc2p(bfs, (val >> 1));
+
+	bfs[0] += '0';
+	bfs[1] += 'A';
+	bfs[2] = sfdsp[bfs[2] - 7];
+	bfs[3] += '0';
+	bfs[4] += '0';
+	bfs[5] = '\0';
+
+	vbank(0);
+	vcputsv(tunob, 64, cfg, cbg, row, col, bfs, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tdswin() -- display a window
+   =============================================================================
+*/
+
+tdswin(n)
+register short n;
+{
+	register short cx, i, tv;
+	char ts;
+
+	cx = exp_c(tdbox[n][5]);
+
+	/* first, fill the box with the background color */
+
+	vbank(0);
+	vbfill4(tunob, 128, tdbox[n][0], tdbox[n][1], tdbox[n][2],
+		tdbox[n][3], cx);
+
+	/* put in the box label */
+
+	tsplot4(tunob, 64, tdbox[n][4], tdbox[n][6], tdbox[n][7],
+		tdbxlb[n], 14);
+
+/* 
+
+*/
+	switch (n) {	/* final text - overlays above stuff */
+
+	case 0:		/* keys 0..23 */
+
+		for (i = 0; i < 24; i++) {
+
+			tsplot4(tunob, 64, TDLABEL, i, 1, tdlabl[i], 14);
+			sprintf(bfs, "%2d", 1 + i);
+			tsplot4(tunob, 64, TDMKEYC, i, 3, bfs, 14);
+			dsttval(i, 6, tuntab[i],
+				((tuntab[i] EQ 320) OR (tuntab[i] EQ 21920))
+				? TDMKEYC : tdbox[n][4], tdbox[n][5]);
+		}
+
+		return;
+
+	case 1:		/* keys 24..47 */
+
+		for (i = 24; i < 48; i++) {
+
+			sprintf(bfs, "%2d", 1 + i);
+			tsplot4(tunob, 64, TDMKEYC, i - 24, 13, bfs, 14);
+			dsttval(i - 24, 16, tuntab[i],
+				((tuntab[i] EQ 320) OR (tuntab[i] EQ 21920))
+				? TDMKEYC : tdbox[n][4], tdbox[n][5]);
+		}
+
+		return;
+
+	case 2:		/* keys 48..71 */
+
+		for (i = 48; i < 72; i++) {
+
+			sprintf(bfs, "%2d", 1 + i);
+			tsplot4(tunob, 64, TDMKEYC, i - 48, 23, bfs, 14);
+			dsttval(i - 48, 26, tuntab[i],
+				((tuntab[i] EQ 320) OR (tuntab[i] EQ 21920))
+				? TDMKEYC : tdbox[n][4], tdbox[n][5]);
+		}
+
+		return;
+/* 
+
+*/
+	case 3:		/* keys 72..95 */
+
+		for (i = 72; i < 96; i++) {
+
+			sprintf(bfs, "%2d", 1 + i);
+			tsplot4(tunob, 64, TDMKEYC, i - 72, 33, bfs, 14);
+			dsttval(i - 72, 36, tuntab[i],
+				((tuntab[i] EQ 320) OR (tuntab[i] EQ 21920))
+				? TDMKEYC : tdbox[n][4], tdbox[n][5]);
+		}
+
+		return;
+
+	case 4:		/* keys 96..119 */
+
+		for (i = 96; i < 120; i++) {
+
+			sprintf(bfs, "%3d", 1 + i);
+			tsplot4(tunob, 64, TDMKEYC, i - 96, 43, bfs, 14);
+			dsttval(i - 96, 47, tuntab[i],
+				((tuntab[i] EQ 320) OR (tuntab[i] EQ 21920))
+				? TDMKEYC : tdbox[n][4], tdbox[n][5]);
+		}
+
+		return;
+
+	case 5:		/* keys 120..127 */
+
+		for (i = 120; i < 128; i++) {
+
+			sprintf(bfs, "%3d", 1 + i);
+			tsplot4(tunob, 64, TDMKEYC, i - 120, 54, bfs, 14);
+			dsttval(i - 120, 58, tuntab[i],
+				((tuntab[i] EQ 320) OR (tuntab[i] EQ 21920))
+				? TDMKEYC : tdbox[n][4], tdbox[n][5]);
+		}
+
+		return;
+/* 
+
+*/
+	case 6:
+
+		td_trcp(0);
+		td_incr(0);
+		td_intp(0);
+		tsplot4(tunob, 64, tdbox[n][4], 16, 54, "Undo", 14);
+
+		tv = (tunval GE 0 ? tunval : -tunval) >> 1;
+		ts = tunval GE 0 ? '+' : '-';
+		sprintf(bfs, "Val %c%04d", ts, tv);
+		tsplot4(tunob, 64, tdbox[n][4], 18, 54, bfs, 14);
+
+		tsplot4(tunob, 64, tdbox[n][4], 20, 54, "Store", 14);
+		tsplot4(tunob, 64, tdbox[n][4], 22, 54, "Retrieve", 14);
+
+		tsplot4(tunob, 64, tdbox[n][4], 24, 54, "Table #", 14);
+		bfs[0] = curtun + '0';
+		bfs[1] = '\0';
+		tsplot4(tunob, 64, tunmod ? TDCHGD : tdbox[n][4],
+			24, 61, bfs, 14);
+
+		return;
+
+	case 7:		/* tuning table name */
+
+		tsplot4(tunob, 64, tdbox[n][4], 24, 7, tuncurn, 14);
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	twins() -- display all tuning editor windows
+   =============================================================================
+*/
+
+twins()
+{
+	register short i;
+
+	for (i = 0; i < 8; i++)
+		tdswin(i);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tundsp() -- put up the tuning display
+   =============================================================================
+*/
+
+tundsp()
+{
+	tunob = &v_score[0];		/* setup object pointer */
+	obj0  = &v_curs0[0];		/* setup cursor object pointer */
+	obj2  = &v_tcur[0];		/* setup typewriter object pointer */
+	tdoct = &v_obtab[TUNOBJ];	/* setup object control table pointer */
+
+	ttcmdsv = 0;			/* nothing selected */
+	tdnamsw = FALSE;
+	submenu = FALSE;
+
+	dswap();			/* initialize display */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	memsetw(tunob, 0, 32767);	/* clear the display */
+	memsetw(tunob+32767L, 0, 12033);
+
+	SetObj(TUNOBJ, 0, 0, tunob, 512, 350,      0,      0,   TUNFL, -1);
+	SetObj(     0, 0, 1,  obj0,  16,  16, TDCURX, TDCURY, OBFL_00, -1);
+	SetObj(TTCURS, 0, 1,  obj2,  16,  16,      0,      0,  TTCCFL, -1);
+
+	arcurs(TDCURSR);	/* setup arrow cursor object */
+	itcini(TDCURSR);	/* setup text cursor object */
+	ttcini(TDTCURC);	/* setup typewriter cursor object */
+
+	twins();
+
+	SetPri(TUNOBJ, TUNPRI);
+
+	settc(YTOR(TDCURY), XTOC(TDCURX));	/* display the text cursor */
+
+	vsndpal(tunpal);
+}
Index: ram/ucslice.c
===================================================================
--- ram/ucslice.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/ucslice.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,241 @@
+/*
+   =============================================================================
+	ucslice.c -- update score display center slice
+	Version 7 -- 1988-09-28 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#undef	DEBUGGER
+
+#include "debug.h"
+
+#include "stddefs.h"
+#include "slice.h"
+#include "hwdefs.h"
+#include "score.h"
+#include "graphdef.h"
+#include "vsdd.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "scfns.h"
+
+/* variables defined elsewhere */
+
+extern	unsigned	*saddr;		/* score object base address */
+
+extern	short		ndisp;		/* current display number */
+extern	short		sd;		/* scroll direction flag */
+extern	short		soffset;	/* score object scroll offset */
+
+extern	short		gtctab[];	/* group to color table */
+extern	short		lintab1[];	/* note top line table - N_SHARP */
+extern	short		lintab2[];	/* note top line table - N_FLAT */
+extern	short		nbmasks[];	/* pixel mask table for slices */
+extern	short		nttab1[];	/* gdsel code transition table - fwd */
+extern	short		nttab2[];	/* gdsel code transition table - bak */
+
+extern	short		pxtbl[][4];	/* pixel mask table - notes */
+extern	short		epxtbl[][16];	/* pixel mask table - events */
+
+extern	struct	gdsel	*gdfsep;	/* gdsel freechain pointer */
+
+extern	struct	gdsel	*gdstbc[];	/* group status list heads */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	ucslice()
+
+	Updates the center slice.
+
+	Note transitions are based on the value of global variable 'sd',
+	which is zero for forward, and non-zero for backward scrolling.
+
+	Note colors come from 'gtctab[]'.
+
+	This code must be very fast or the display bogs down the system.
+   =============================================================================
+*/
+
+ucslice()
+{
+	register unsigned *pxptr, *slptr;
+	register struct gdsel *gdsep;
+	register long lc;
+	register unsigned i, ncolor, mask1, mask2;
+	unsigned *ncptr, *nctabp;
+	struct gdsel **gdstp, *gdprv, *gdnxt;
+	short *lintab;
+
+	DB_ENTR("ucslice()");
+
+	lc = 128L;
+	mask1 = nbmasks[soffset];
+	mask2 = ~mask1;
+
+	/* initialize note color, note control, and group control pointers */
+
+	gdstp = gdstbc;				/* group control table */
+	nctabp = sd ? nttab2 : nttab1;		/* note transition table */
+	ncptr = gtctab;				/* group to color table */
+
+	lintab = (ac_code EQ N_SHARP) ? lintab1 : lintab2;	/* line table */
+
+/* 
+
+*/
+
+	for (i = 0; i < 12; i++) {	/* scan the group control table ... */
+
+		ncolor = mask1 & *ncptr++;	/* get note color mask */
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active group ... */
+
+			do {	/* ... for each note played by the group ... */
+
+				if (ndisp EQ 2) {	/* ... if display is up */
+
+					/* setup slice and pixel pointers */
+
+					slptr = saddr + 64L +
+						((long)lintab[gdsep->note] << 7);
+
+					pxptr = &pxtbl[gdsep->code][0];
+
+					/* update the slice */
+
+					*slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
+					slptr += lc;
+
+					*slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
+					slptr += lc;
+
+					*slptr = (*slptr & mask2) | (*pxptr++ & ncolor);
+
+				}
+
+				gdnxt = gdsep->next;	/* set 'next element' pointer */
+
+				/* update and check element code */
+
+				if (0 EQ (gdsep->code = nctabp[gdsep->code])) {
+
+					/* if it's zero, delete the element */
+
+					gdprv->next = gdnxt;
+					gdsep->next = gdfsep;
+					gdfsep = gdsep;
+
+				} else
+					gdprv = gdsep;
+
+				gdsep = gdnxt;	/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+/* 
+
+*/
+	for (; i < NGDSEL; i++) {
+
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active event priority ... */
+
+			do {	/* ... for each event of this priority  ... */
+
+				if (ndisp EQ 2) {	/* ... if display is up */
+
+					/* setup slice and pixel pointers */
+
+					slptr = saddr + 27200L;
+					pxptr = &epxtbl[gdsep->code][0];
+
+					/* get event color */
+
+					ncolor = mask1 & gdsep->note;
+
+					/* update the slice */
+
+					if (*pxptr++)  /* 212 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 213 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 214 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 215 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 216 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 217 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+/* 
+
+*/
+					if (*pxptr++)  /* 218 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 219 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 220 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 221 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr++)  /* 222 */
+						*slptr = (*slptr & mask2) | ncolor;
+
+					slptr += lc;
+
+					if (*pxptr)    /* 223 */
+						*slptr = (*slptr & mask2) | ncolor;
+				}
+
+				gdnxt = gdsep->next;	/* set next pointer */
+				gdprv->next = gdnxt;	/* delete the element */
+				gdsep->next = gdfsep;
+				gdfsep = gdsep;
+				gdsep  = gdnxt;		/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+	DB_EXIT("ucslice");
+}
Index: ram/uslice.c
===================================================================
--- ram/uslice.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/uslice.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,748 @@
+/*
+   =============================================================================
+	uslice.c -- update score display slice
+	Version 32 -- 1988-09-28 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#undef	DEBUGGER
+
+#define	DEBUGIT		0
+
+#include "debug.h"
+
+#include "stddefs.h"
+#include "slice.h"
+#include "hwdefs.h"
+#include "score.h"
+#include "vsdd.h"
+#include "graphdef.h"
+
+#include "midas.h"
+#include "scdsp.h"
+#include "scfns.h"
+
+#define	BARCOLOR	0x3333
+
+/* variables defined elsewhere */
+
+#if DEBUGIT
+extern	short	debugsw;
+#endif
+
+extern	unsigned	scrl;
+
+extern	short		sbase;
+extern	short		sd;
+extern	short		soffset;
+
+extern	unsigned	*consl;
+extern	unsigned	*cursl;
+extern	unsigned	*nxtsl;
+extern	unsigned	*prvsl;
+extern	unsigned	*saddr;
+
+extern	unsigned	slices[];
+
+extern	short		gtctab[12];		/* group to color table */
+
+extern	struct	gdsel	*gdfsep;		/* gdsel freechain pointer */
+
+extern	struct	gdsel	*gdstbc[NGDSEL];	/* group status list heads */
+extern	struct	gdsel	*gdstbn[NGDSEL];	/* group status list heads */
+extern	struct	gdsel	*gdstbp[NGDSEL];	/* group status list heads */
+
+extern	struct	gdsel	gdfsl[MAXFSL];		/* gdsel pool */
+
+/* 
+
+*/
+
+/* initialized data */
+
+short	lintab1[] = {			/* note top line table */
+
+	205, 205, 201, 197, 197, 193, 193, 189, 185, 185, 181, 181,
+	177, 177, 173, 169, 169, 165, 165, 161, 157, 157, 153, 153, 
+	149, 149, 145, 141, 141, 137, 137, 133, 129, 129, 125, 125,
+	121, 121, 117, 113, 113, 109, 109, 105, 101, 101,  97,  97,
+	 93,  93,  89,  85,  85,  81,  81,  77,  73,  73,  69,  69,
+	 65,  65,  61,  57,  57,  53,  53,  49,  45,  45,  41,  41,
+	 37,  37,  33,  29,  29,  25,  25,  21,  17,  17,  13,  13,
+	  9,   9,   5,   1
+};
+
+short	lintab2[] = {			/* note top line table - N_FLAT */
+
+	205, 201, 201, 197, 193, 193, 189, 189, 185, 181, 181, 177, 
+	177, 173, 173, 169, 165, 165, 161, 161, 157, 153, 153, 149, 
+	149, 145, 145, 141, 137, 137, 133, 133, 129, 125, 125, 121, 
+	121, 117, 117, 113, 109, 109, 105, 105, 101,  97,  97,  93, 
+	 93,  89,  89,  85,  81,  81,  77,  77,  73,  69,  69,  65, 
+	 65,  61,  61,  57,  53,  53,  49,  49,  45,  41,  41,  37, 
+	 37,  33,  33,  29,  25,  25,  21,  21,  17,  13,  13,   9, 
+	  9,   5,   5,   1
+};
+
+short	nttab1[] = {		/* forward code transition table */
+
+	0,	/* 0 */
+	2,	/* 1 */
+	3,	/* 2 */
+	3,	/* 3 */
+	5,	/* 4 */
+	3,	/* 5 */
+	0	/* 6 */
+};
+
+short	nttab2[] = {		/* backward code transition table */
+
+	0,	/* 0 */
+	0,	/* 1 */
+	1,	/* 2 */
+	3,	/* 3 */
+	0,	/* 4 */
+	4,	/* 5 */
+	0	/* 6 */
+};
+
+/* 
+
+*/
+
+short	pxtbl[][4] = {		/* pixel mask table for notes */
+
+	{ 0x0000, 0x0000, 0x0000, 0 },	/* 0 */
+	{ 0x0000, 0x0000, 0xFFFF, 0 },	/* 1 */
+	{ 0x0000, 0xFFFF, 0xFFFF, 0 },	/* 2 */
+	{ 0xFFFF, 0xFFFF, 0xFFFF, 0 },	/* 3 */
+	{ 0xFFFF, 0x0000, 0x0000, 0 },	/* 4 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 0 },	/* 5 */
+	{ 0xFFFF, 0xFFFF, 0xFFFF, 0 }	/* 6 */
+};
+
+short	epxtbl[][16] = {	/* pixel mask table for events */
+
+	{ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,	/* 0 */
+	  0xFFFF, 0x0000, 0x0000, 0x0000,
+	  0x0000, 0x0000, 0x0000, 0x0000,
+	  0, 0, 0, 0 },
+
+	{ 0x0000, 0x0000, 0x0000, 0x0000,	/* 1 */
+	  0x0000, 0xFFFF, 0xFFFF, 0x0000,
+	  0x0000, 0x0000, 0x0000, 0x0000,
+	  0, 0, 0, 0 },
+
+	{ 0x0000, 0x0000, 0x0000, 0x0000,	/* 2 */
+	  0x0000, 0x0000, 0x0000, 0xFFFF,
+	  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+	  0, 0, 0, 0 },
+
+	{ 0xFFFF, 0xFFFF, 0xFFFF, 0x0000,	/* 3 */
+	  0x0000, 0x0000, 0x0000, 0x0000,
+	  0x0000, 0x0000, 0x0000, 0x0000,
+	  0, 0, 0, 0 },
+
+	{ 0x0000, 0x0000, 0x0000, 0xFFFF,	/* 4 */
+	  0xFFFF, 0xFFFF, 0x0000, 0x0000,
+	  0x0000, 0x0000, 0x0000, 0x0000,
+	  0, 0, 0, 0 },
+
+	{ 0x0000, 0x0000, 0x0000, 0x0000,	/* 5 */
+	  0x0000, 0x0000, 0xFFFF, 0xFFFF,
+	  0xFFFF, 0x0000, 0x0000, 0x0000,
+	  0, 0, 0, 0 },
+
+	{ 0x0000, 0x0000, 0x0000, 0x0000,	/* 6 */
+	  0x0000, 0x0000, 0x0000, 0x0000,
+	  0x0000, 0xFFFF, 0xFFFF, 0xFFFF,
+	  0, 0, 0, 0 }
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	uslice(slice, mask1, mask2, gdstb)
+
+	Updates 'slice[]' using 'mask1' and 'mask2' for the pixel mask
+	and the slice mask, respectively, and 'gdstb[]' for the group table.
+
+	Note transitions are based on the value of global variable 'sd',
+	which is zero for forward, and non-zero for backward scrolling.
+
+	Returns count of active groups and event priority levels.
+
+	Note colors come from 'gtctab[]'.
+
+	This code must be very fast or the display bogs down the system.
+   =============================================================================
+*/
+
+short
+uslice(slice, mask1, mask2, gdstb)
+unsigned *slice;
+register unsigned mask1, mask2;
+struct gdsel *gdstb[];
+{
+	register unsigned *pxptr, *slptr;
+	register struct gdsel *gdsep;
+	register unsigned i, ncolor, w;
+	unsigned *ncptr, *nctabp;
+	struct gdsel **gdstp, *gdprv, *gdnxt;
+	short wrote;
+	short *lintab;
+
+	DB_ENTR("uslice()");
+
+	/* initialize note color, note control, and group control pointers */
+
+	gdstp = gdstb;				/* group control table */
+	nctabp = sd ? nttab2 : nttab1;		/* note transition table */
+	ncptr = gtctab;				/* group to color table */
+	wrote = 0;				/* reset count of active groups */
+
+	lintab = (ac_code EQ N_SHARP) ? lintab1 : lintab2;	/* line table */
+
+	if (gdstb[NGDSEL - 1]) {	/* check for a bar marker */
+
+		slptr = slice;			/* point at the slice */
+		ncolor = mask1 & BARCOLOR;	/* setup bar write variable */
+
+		for (i = 211; i--; )		/* draw the bar */
+			*slptr++ = (*slptr & mask2) | ncolor;
+
+		gdstb[NGDSEL - 1] = (struct gdsel *)NULL;	/* clear flag */
+	}
+
+/* 
+
+*/
+
+	for (i = 0; i < 12; i++) {	/* scan the group control table ... */
+
+		ncolor = mask1 & *ncptr++;	/* get note color mask */
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active group ... */
+
+			++wrote;	/* indicate slice was updated */
+
+			do {	/* ... for each note played by the group ... */
+
+				/* setup slice and pixel pointers */
+
+				slptr = slice + lintab[gdsep->note];
+				pxptr = &pxtbl[gdsep->code][0];
+
+				/* update the slice */
+
+				*slptr++ = (*slptr & mask2) | (*pxptr++ & ncolor);
+				*slptr++ = (*slptr & mask2) | (*pxptr++ & ncolor);
+				*slptr   = (*slptr & mask2) | (*pxptr++ & ncolor);
+
+				gdnxt = gdsep->next;	/* set next pointer */
+
+				/* update and check update note status code */
+
+				if (0 EQ (gdsep->code = nctabp[gdsep->code])) {
+
+					/* if it's zero, delete the element */
+
+					gdprv->next = gdnxt;
+					gdsep->next = gdfsep;
+					gdfsep = gdsep;
+
+				} else
+					gdprv = gdsep;
+
+				gdsep = gdnxt;	/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+/* 
+
+*/
+	for (; i < (NGDSEL - 1); i++) {
+
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active event priority ... */
+
+			++wrote;	/* indicate slice was updated */
+
+			do {	/* ... for each event of this priority  ... */
+
+				/* setup slice and pixel pointers */
+
+				slptr = slice + 212;
+				pxptr = &epxtbl[gdsep->code][0];
+
+				/* get event color */
+
+				ncolor = mask1 & gdsep->note;
+
+				/* update the slice */
+
+				if (w = *pxptr++)  /* 212 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 213 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 214 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 215 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 216 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 217 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 218 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 219 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 220 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 221 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 222 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr)    /* 223 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				gdnxt = gdsep->next;	/* set next pointer */
+				gdprv->next = gdnxt;	/* delete the element */
+				gdsep->next = gdfsep;
+				gdfsep = gdsep;
+				gdsep  = gdnxt;	/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+	DB_EXIT(wrote ? "uslice - slice written" : "uslice - no write");
+
+	return(wrote);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	rslice(gdstb)
+
+	Reverses the slice codes in 'gdstb' based the value of sd,
+	which is zero for forward, and non-zero for backward scrolling.
+   =============================================================================
+*/
+
+rslice(gdstb)
+struct gdsel *gdstb[];
+{
+	register struct gdsel *gdsep;
+	register struct gdsel **gdstp;
+	register unsigned *nctabp;
+	register unsigned i, nc;
+	struct gdsel *gdprv, *gdnxt;
+
+	DB_ENTR("rslice");
+
+#if DEBUGIT
+	if (debugsw)
+		printf("\nrslice($%lX):  sd = %s\n", gdstb, sd ? "BAK" : "FWD");
+#endif
+
+	/* initialize note control and group control pointers */
+
+	nctabp = sd ? nttab2 : nttab1;	/* note control table pointer */
+	gdstp = gdstb;			/* group control table pointer */
+
+/* 
+
+*/
+	/* reverse note codes */
+
+	for (i = 0; i < 12; i++) {	/* scan the group control table ... */
+
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active group ... */
+
+			do {	/* ... for each note played by the group ... */
+
+				gdnxt = gdsep->next;	/* set next pointer */
+
+				/* update and check update note status code */
+
+				if (0 EQ (gdsep->code = nctabp[nc = gdsep->code])) {
+
+#if DEBUGIT
+	if (debugsw)
+		printf("rslice:  note %d - %d -> %d\n",
+			gdsep->note, nc, gdsep->code);
+#endif
+
+					/* if it's zero, delete the element */
+
+					gdprv->next = gdnxt;
+					gdsep->next = gdfsep;
+					gdfsep = gdsep;
+
+				} else {
+
+#if DEBUGIT
+	if (debugsw)
+		printf("rslice:  note %d - %d -> %d\n",
+			gdsep->note, nc, gdsep->code);
+#endif
+
+					gdprv = gdsep;
+				}
+
+				gdsep = gdnxt;	/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+/* 
+
+*/
+	/* delete event codes */
+
+	for (; i < NGDSEL - 1; i++) {
+
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active event priority ... */
+
+			do {	/* ... for each event of this priority  ... */
+
+				gdnxt = gdsep->next;	/* set next pointer */
+				gdprv->next = gdnxt;	/* delete the element */
+				gdsep->next = gdfsep;
+				gdfsep = gdsep;
+				gdsep  = gdnxt;		/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+	gdstb[NGDSEL - 1] = (struct gdsel *)NULL;	/* clear bar flag */
+
+	DB_EXIT("rslice");
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	cslice(slice, mask1, mask2, gdstb)
+
+	Updates 'slice[]' using 'mask1' and 'mask2' for the pixel mask
+	and the slice mask, respectively, using 'gdstb[]' as the group table.
+
+	Differs from uslice() in that no note gdstb events are deleted.
+	Used for center slice updates.
+
+	Note transitions are based on the value of global variable 'sd',
+	which is zero for forward, and non-zero for backward scrolling.
+
+	Returns count of active groups and event priority levels.
+
+	Note colors come from 'gtctab[]'.
+
+	This code has to be very fast.
+   =============================================================================
+*/
+
+short
+cslice(slice, mask1, mask2, gdstb)
+unsigned *slice;
+register unsigned mask1, mask2;
+struct gdsel *gdstb[];
+{
+	register unsigned *pxptr, *slptr;
+	register struct gdsel *gdsep;
+	register unsigned i, ncolor, w;
+	unsigned *ncptr, *nctabp;
+	struct gdsel **gdstp, *gdprv, *gdnxt;
+	short wrote;
+	short *lintab;
+
+	DB_ENTR("cslice()");
+
+	/* initialize note color, note control, and group control pointers */
+
+	gdstp = gdstb;				/* group control table */
+	nctabp = sd ? nttab2 : nttab1;		/* note transition table */
+	ncptr = gtctab;				/* group to color table */
+	wrote = 0;				/* reset count of active groups */
+
+	lintab = (ac_code EQ N_SHARP) ? lintab1 : lintab2;	/* line table */
+
+	if (gdstb[NGDSEL - 1]) {	/* check for a bar marker */
+
+		slptr = slice;			/* point at the slice */
+		ncolor = mask1 & BARCOLOR;	/* setup bar write variable */
+
+		for (i = 211; i--; )		/* draw the bar */
+			*slptr++ = (*slptr & mask2) | ncolor;
+
+		gdstb[NGDSEL - 1] = (struct gdsel *)NULL;	/* clear flag */
+	}
+
+/* 
+
+*/
+
+	for (i = 0; i < 12; i++) {	/* scan the group control table ... */
+
+		ncolor = *ncptr++;		/* get note color */
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active group ... */
+
+#ifdef	DEBUGGER
+	sprintf(DBvar, "cslice - g=%d  gdsep=$%lX", i, gdsep);	DB_CMNT(DBvar);
+#endif
+			++wrote;	/* indicate slice was updated */
+
+			do {	/* ... for each note played by the group ... */
+
+				/* setup slice and pixel pointers */
+
+				slptr = slice + lintab[gdsep->note];
+				pxptr = &pxtbl[gdsep->code][0];
+
+				/* update the slice */
+
+				*slptr++ = (*slptr & mask2) | (*pxptr++ & ncolor);
+				*slptr++ = (*slptr & mask2) | (*pxptr++ & ncolor);
+				*slptr   = (*slptr & mask2) | (*pxptr++ & ncolor);
+
+				gdnxt = gdsep->next;	/* set nxt pointer */
+				gdprv = gdsep;		/* set prv pointer */
+				gdsep = gdnxt;	/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+/* 
+
+*/
+	for (; i < (NGDSEL - 1); i++) {	/* scan the event priorities ... */
+
+		gdprv = (struct gdsel *)gdstp;	/* setup previous pointer */
+		gdsep = *gdstp++;		/* setup current pointer */
+
+		if (gdsep) {	/* ... process each active event priority ... */
+
+			++wrote;	/* indicate slice was updated */
+
+			do {	/* ... for each event of this priority  ... */
+
+				/* setup slice and pixel pointers */
+
+				slptr = slice + 212;
+				pxptr = &epxtbl[gdsep->code][0];
+
+				ncolor = gdsep->note;	/* get event color */
+
+				/* update the slice */
+
+				if (w = *pxptr++)  /* 212 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 213 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 214 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 215 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 216 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 217 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 218 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 219 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 220 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 221 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr++)  /* 222 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				++slptr;
+
+				if (w = *pxptr)    /* 223 */
+					*slptr = (*slptr & mask2) | (w & ncolor);
+
+				gdnxt = gdsep->next;	/* set next pointer */
+				gdprv->next = gdnxt;	/* delete the element */
+				gdsep->next = gdfsep;
+				gdfsep = gdsep;
+				gdsep  = gdnxt;	/* set pointer for next pass */
+
+			} while (gdsep);
+		}
+	}
+
+	DB_EXIT(wrote ? "cslice - slice written" : "cslice - no write");
+
+	return(wrote);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clrsctl() -- clear slice control list and pointers
+   =============================================================================
+*/
+
+clrsctl()
+{
+	register struct gdsel *gdsp, *gnxt, **gp;
+	register short i;
+
+	gdfsep = gdsp = &gdfsl[0];	/* initialize slice control pool */
+	gnxt   = &gdfsl[1];
+
+	for (i = MAXFSL - 1; i--; ) {
+
+		gdsp->code = 0;
+		gdsp->note = 0;
+		gdsp->next = gnxt;
+
+		gdsp++;
+		gnxt++;
+	}
+
+	gdsp->code = 0;
+	gdsp->note = 0;
+	gdsp->next = (struct gdsel *)0L;
+
+	gp = gdstbc;			/* clear gdstbc */
+
+	for (i = NGDSEL; i--; )
+		*gp++ = (struct gdsel *)0L;
+
+	gp = gdstbn;			/* clear gdstbn */
+
+	for (i = NGDSEL; i--; )
+		*gp++ = (struct gdsel *)0L;
+
+	gp = gdstbp;			/* clear gdstbp */
+
+	for (i = NGDSEL; i--; )
+		*gp++ = (struct gdsel *)0L;
+
+	sbase   = I_SBASE;		/* initialize score video RAM offset */
+	soffset = I_OFFSET;		/* initialize scroll register offset */
+	saddr   = &v_score[sbase];	/* initialize score area base address */
+
+	consl = &slices[672];		/* initialize constant slice pointer */
+	prvsl = &slices[448];		/* initialize previous slice pointer */
+	cursl = &slices[224];		/* initialize current slice pointer */
+	nxtsl = &slices[0];		/* initialize next slice pointer */
+/* 
+
+*/
+	{
+		register unsigned *p1, *p2, *p3, sword;
+		unsigned *p4;
+
+		p1 = consl;			/* clear slices */
+		p2 = nxtsl;
+		p3 = cursl;
+		p4 = prvsl;
+
+		for (i = 224; i--; ) {
+
+			sword = *p1++;
+			*p2++ = sword;
+			*p3++ = sword;
+			*p4++ = sword;
+		}
+	}
+}
Index: ram/vtyper.c
===================================================================
--- ram/vtyper.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/vtyper.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,262 @@
+/*
+   =============================================================================
+	vtyper.c -- virtual typewriter support functions
+	Version 8 -- 1989-11-14 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "fields.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "graphdef.h"
+
+#include "midas.h"
+
+extern	unsigned exp_c();
+
+extern	short	cxrate;		/* data entry cursor x (col) update increment */
+extern	short	cyrate;		/* data entry cursor y (row) update increment */
+extern	short	stccol;		/* data entry text cursor column */
+extern	short	stcrow;		/* data entry text cursor row */
+extern	short	vtccol;		/* vtyper cursor column */
+extern	short	vtcrow;		/* vtyper cursor row */
+extern	short	vtdecol;	/* vtyper data entry column */
+extern	short	vtxval;		/* vtyper cursor x value */
+extern 	short	vtyval;		/* vtyper cursor y value */
+
+extern	char	*vtdeptr;	/* vtyper data entry pointer */
+
+extern	char	vtdechr;	/* vtyper data entry character */
+
+extern	char	bfs[];		/* display string buffer */
+
+extern	short	vtwrow;		/* vtyper window top row */
+extern	short	vtwcol;		/* vtyper window left column */
+
+extern	short	(*vt_adv)();	/* vtyper data cursor advance function */
+extern	short	(*vt_bsp)();	/* vtyper data cursor backspace function */
+extern	short	(*vt_cdn)();	/* vtyper data cursor down function */
+extern	short	(*vt_cup)();	/* vtyper data cursor up function */
+extern	short	(*vt_stop)();	/* vtyper exit function */
+extern	short	(*vt_dsp)();	/* vtyper display function */
+
+extern	unsigned *vtobj;	/* vtyper display object pointer */
+extern	unsigned vtfgval;	/* vtyper data foreground color */
+extern	unsigned vtbgval;	/* vtyper data background color */
+
+/* virtual typewriter display line constants */
+
+/*			"123456789012345678901234567890"  */
+char	vtlin1[] =	"ABCDEFGHIJKLMNOPQRSTUVWXYZ  | ";	/* top */
+char	vtlin2[] =	"abcdefghijklmnopqrstuvwxyz -*-";	/* center */
+char	vtlin3[] =	" 0123456789+-/#().,:;!?&<>  | ";	/* bottom */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	vtsetup() -- setup the virtual typewriter for data entry
+
+	This sets up the parameters for the virtual typewriter:
+
+		obj	VSDD display object pointer
+		dsp	character display function
+		col	data entry area -- leftmost column on the screen
+		ptr	data string base pointer
+		tr	typewriter window topmost row
+		tc	typewriter window leftmost column
+		adv	data entry cursor advance function
+		bsp	data entry cursor backspace function
+		cup	data entry cursor up function
+		cdn	data entry cursor down function
+		stop	virtual typewriter end function
+		fg	data entry text foreground color
+		bg	data entry text background color
+   =============================================================================
+*/
+
+vtsetup(obj, dsp, col, ptr, tr, tc, adv, bsp, cup, cdn, stop, fg, bg)
+unsigned *obj;
+short (*dsp)();
+short col;
+char *ptr;
+short tr, tc;
+short (*adv)(), (*bsp)(), (*cup)(), (*cdn)(), (*stop)();
+unsigned fg, bg;
+{
+	vtobj   = obj;		/* setup object pointer */
+	vt_adv  = adv;		/* setup cursor advance function pointer */
+	vt_bsp  = bsp;		/* setup cursor backspace function pointer */
+	vt_cup  = cup;		/* setup cursor up function pointer */
+	vt_cdn  = cdn;		/* setup cursor down function pointer */
+	vt_dsp  = dsp;		/* setup display function pointer */
+	vt_stop = stop;		/* setup exit typewriter function pointer */
+	vtwrow  = tr;		/* setup typewriter window row */
+	vtwcol  = tc;		/* setup typewriter window column */
+	vtdecol = col;		/* setup data entry base column */
+	vtdeptr = ptr;		/* setup data entry area base address */
+	vtfgval = exp_c(fg);	/* setup foreground color value */
+	vtbgval = exp_c(bg);	/* setup background color value */
+	SetPri(TTCURS, TTCPRI);	/* turn on the typewriter cursor */
+	vtxval = CTOX(tc);	/* setup vt x value */
+	vtyval = YTOR(tr);	/* setup vt y value */
+	ttcpos(tr, tc);		/* position the typewriter cusor */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	vtcxupd() -- update virtual typewriter cursor x value
+
+	Standard cursor x update for use when the typewriter is displayed.
+
+	Reference this in the cursor x update for the particular display
+	when the virtual typewriter is displayed.
+   =============================================================================
+*/
+
+vtcxupd()
+{
+	vtccol = XTOC(vtxval += cxrate);
+
+	if (vtccol > (vtwcol + 29))
+		vtxval = CTOX(vtccol = vtwcol + 29);
+	else if (vtccol < vtwcol)
+		vtxval = CTOX(vtccol = vtwcol);
+}
+
+/*
+   =============================================================================
+	vtcyupd() -- update virtual typewriter cursor y value
+
+	Standard cursor y update for use when the typewriter is displayed.
+
+	Reference this in the cursor y update for the particular display
+	when the virtual typewriter is displayed.
+   =============================================================================
+*/
+
+vtcyupd()
+{
+	vtcrow = YTOR(vtyval += cyrate);
+
+	if (vtcrow > (vtwrow + 2))
+		vtyval = RTOY(vtcrow = vtwrow + 2);
+	else if (vtcrow < vtwrow)
+		vtyval = RTOY(vtcrow = vtwrow);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	vtdisp() -- virtual typewriter data entry display   (4 bit graphics)
+
+	Standard function for virtual typewriter output to a graphic screen.
+	Assumes that the graphic object is a 4 bit per pixel object in bank 0.
+   =============================================================================
+*/
+
+vtdisp(obj, fg, bg, row, col, buf)
+unsigned *obj;
+unsigned fg, bg;
+short row, col;
+char *buf;
+{
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vcputsv(obj, 64, fg, bg, row, col, buf, 14);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	vtyper() -- do data entry with the virtual typewriter
+
+	Called when enter is hit to do data entry from the select function
+	for the display.  Returns TRUE if data entry occurred, FALSE otherwise.
+   =============================================================================
+*/
+
+vtyper()
+{
+	/* check for data entry */
+
+	if (vtccol < (vtwcol + 26)) {			/* enter data */
+
+		/* convert (vtcrow, vtccol) to data entry character */
+
+		if (vtcrow EQ vtwrow)
+			vtdechr = vtlin1[vtccol - vtwcol];
+		else if (vtcrow EQ (vtwrow + 1))
+			vtdechr = vtlin2[vtccol - vtwcol];
+		else if (vtcrow EQ (vtwrow + 2))
+			vtdechr = vtlin3[vtccol - vtwcol];
+		else {
+
+			vtdechr = '*';			/* error -- bad row */
+			return(FALSE);
+		}
+
+		vtdeptr[stccol - vtdecol] = vtdechr;	/* update data area */
+
+		/* update the screen */
+
+		bfs[0] = vtdechr;
+		bfs[1] = '\0';
+
+		(*vt_dsp)(vtobj, vtfgval, vtbgval, stcrow, stccol, bfs);
+
+		(*vt_adv)();				/* advance cursor */
+		return(TRUE);
+/* 
+
+*/
+	/* check for exit or cursor controls */
+
+	} else if ((vtcrow EQ (vtwrow + 1))
+		AND (vtccol EQ (vtwcol + 28))) {	/* exit */
+
+		objclr(TTCPRI);		/* turn off typewriter cursor */
+		(*vt_stop)();		/* refresh typewriter window */
+		return(FALSE);
+
+	} else if ((vtcrow EQ vtwrow)
+		AND (vtccol EQ (vtwcol + 28))) {	/* cursor up */
+
+		(*vt_cup)();		/* move cursor up a row */
+		return(FALSE);
+
+	} else if ((vtcrow EQ (vtwrow + 2))
+		AND (vtccol EQ (vtwcol + 28))) {	/* cursor down */
+
+		(*vt_cdn)();		/* move cursor down a row */
+		return(FALSE);
+
+	} else if ((vtcrow EQ (vtwrow + 1))
+		AND (vtccol EQ (vtwcol + 27))) {	/* cursor lft */
+
+		(*vt_bsp)();		/* move cursor left a column */
+		return(FALSE);
+
+	} else if ((vtcrow EQ (vtwrow + 1))
+		AND (vtccol EQ (vtwcol + 29))) {	/* cursor rgt */
+
+		(*vt_adv)();		/* move cursor right a column */
+		return(FALSE);
+	} 
+}
+
Index: ram/wdfield.c
===================================================================
--- ram/wdfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/wdfield.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,851 @@
+/*
+   =============================================================================
+	wdfield.c -- waveshape display field processing and cursor motion
+	Version 46 -- 1989-11-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DOUBLED		1		/* non-zero for doubled WS outputs */
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "hwdefs.h"
+#include "fpu.h"
+#include "macros.h"
+#include "curpak.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+#define	WCSCALE		32768L
+#define	WCROUND		16384L
+
+extern	short	select(),	whatbox(),	nokey(),	stdctp1();
+extern	short	cxkstd(),	cykstd(),	stdmkey(),	stddkey();
+
+extern	short	et_null(), ef_null(), rd_null(), nd_null();
+extern	short	et_wavs(), ef_wavs(), rd_wavs(), nd_wavs();
+extern	short	et_wvce(), ef_wvce(), rd_wvce(), nd_wvce();
+extern	short	et_wslt(), ef_wslt(), rd_wslt(), nd_wslt();
+extern	short	et_wpnt(), ef_wpnt(), rd_wpnt(), nd_wpnt();
+extern	short	et_woff(), ef_woff(), rd_woff(), nd_woff();
+extern	short	et_whar(), ef_whar(), rd_whar(), nd_whar();
+extern	short	et_whrv(), ef_whrv(), rd_whrv(), nd_whrv();
+
+extern	short	vcputsv();
+
+extern	char	*memset();
+
+/* 
+
+*/
+
+extern	short	astat;
+extern	short	cmtype;
+extern	short	curfunc;
+extern	short	curinst;
+extern	short	curslim;
+extern	short	curvce;
+extern	short	curwave;
+extern	short	curwdth;
+extern	short	curwfnl;
+extern	short	curwhrm;
+extern	short	curwhrv;
+extern	short	curwoff;
+extern	short	curwpnt;
+extern	short	curwslt;
+extern	short	cxrate;
+extern	short	cxval;
+extern	short	cyrate;
+extern	short	cyval;
+extern	short	hitbox;
+extern	short	lstwoff;
+extern	short	lstwpnt;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	wdupdfl;
+extern	short	wplast;
+extern	short	wpntsv;
+extern	short	wvlast;
+
+/* 
+
+*/
+
+extern	short	crate1[];
+extern	short	offsets[NUMWPCAL];
+extern	short	vmtab[NUMHARM];
+extern	short	wsbuf[NUMWPCAL];
+
+extern	short	wsnmod[12][2];
+
+extern	unsigned *waveob;
+
+extern	char	bfs[];
+
+extern	struct	instdef	vbufs[];
+
+extern	struct	selbox	*csbp;
+extern	struct	selbox	wdboxes[];
+
+/* forward references */
+
+short	wdxkey(), wdnfld(), wdcxupd(), wdcyupd(), wdykup(), wdykdn();
+
+/* 
+
+*/
+
+#include "wdcurtb.h"		/* short wdcurtb[];  short wdcurct[8][2]; */
+
+short	wxrate = 1;		/* WS interpolate X movement increment */
+
+struct	fet	wd_fet1[] = {
+
+	{23, 10, 11, 0x0002, et_wavs, ef_wavs, rd_wavs, nd_wavs},
+	{23, 19, 20, 0x0102, et_wvce, ef_wvce, rd_wvce, nd_wvce},
+	{23, 34, 36, 0x0004, et_wpnt, ef_wpnt, rd_wpnt, nd_wpnt},
+	{23, 44, 48, 0x0104, et_woff, ef_woff, rd_woff, nd_woff},
+	{23, 61, 62, 0x0005, et_whar, ef_whar, rd_whar, nd_whar},
+
+	{24, 20, 20, 0x0302, et_wslt, ef_wslt, rd_wslt, nd_wslt},
+	{24, 57, 60, 0x0105, et_whrv, ef_whrv, rd_whrv, nd_whrv},
+
+	{ 0,  0,  0, 0x0000, FN_NULL, FN_NULL, FN_NULL, FN_NULL}
+};
+
+short	wdbox[][8] = {	/* display box parameters */
+
+	{  1,   1, 510, 307, WCFBX00, WCBBX00,  0,  1},	/*  0 */
+	{  1, 309, 510, 320, WCFBX01, WCBBX01, 22,  0},	/*  1 */
+	{  1, 322, 174, 348, WCFBX02, WCBBX02, 23,  1},	/*  2 */
+	{176, 322, 230, 348, WCFBX03, WCBBX03, 23, 23},	/*  3 */
+	{232, 322, 398, 348, WCFBX04, WCBBX04, 23, 30},	/*  4 */
+	{400, 322, 510, 348, WCFBX05, WCBBX05, 23, 51}	/*  5 */
+};
+
+char	*wdbxlb0[] = {	/* display box labels -- row 0 */
+
+	"",			/*  0 */
+
+	"\320\301  \320\303  \320\305  \320\307  \320\311  \
+\321\301  \321\303  \321\305  \321\307  \321\311  \
+\322\301  \322\303  \322\305  \322\307  \322\311  \323\301  ",	/*  1 */
+
+	"Waveshpe    Voice",	/*  2 */
+	"Store",		/*  3 */
+	"Pnt     Offst",	/*  4 */
+	"Harmonic #"		/*  5 */
+};
+
+char	*wdbxlb1[] = {	/* display box labels -- row 1 */
+
+	"",			/*  0 */
+	"",			/*  1 */
+	"Instrument    Slot",	/*  2 */
+	"Fetch",		/*  3 */
+	"        Final",	/*  4 */
+	"Value"			/*  5 */
+};
+
+/* 
+
+*/
+
+struct curpak wd_flds = {
+
+	stdctp1,	/* curtype */
+	nokey,		/* premove */
+	nokey,		/* pstmove */
+	cxkstd,		/* cx_key */
+	cykstd,		/* cy_key */
+	wdcxupd,	/* cx_upd */
+	wdcyupd,	/* cy_upd */
+	wdykup,		/* xy_up */
+	wdykdn,		/* xy_dn */
+	wdxkey,		/* x_key */
+	select,		/* e_key */
+	stdmkey,	/* m_key */
+	stddkey,	/* d_key */
+	wdnfld,		/* not_fld */
+	wd_fet1,	/* curfet */
+	wdboxes,	/* csbp */
+	crate1,		/* cratex */
+	crate1,		/* cratey */
+	CT_GRAF,	/* cmtype */
+	WCURX,		/* cxval */
+	WCURY		/* cyval */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	updfpu() -- update the FPU with a new waveshape
+   =============================================================================
+*/
+
+updfpu()
+{
+	register short i;
+	register short *wsp1, *wsp2;
+
+	/* calculate instrument source and FPU destination pointers */
+	
+	wsp1 = io_fpu + FPU_OWST + (curvce << 9) + (curwslt ? 0 : 0x0100) + 1;
+	wsp2 = curwslt ? vbufs[curvce].idhwvbf : vbufs[curvce].idhwvaf;
+
+	memcpyw(wsp1, wsp2, NUMWPNT);
+
+	/* make endpoints track */
+
+	*(wsp1 - 1) = *(wsp2 - 1);			/* lowest point */
+	*(wsp1 + NUMWPNT) = *(wsp2 + NUMWPNT - 1);	/* highest point */
+
+#if	DOUBLED
+
+	/* do outputs again to get around hardware bug */
+
+	memcpyw(wsp1, wsp2, NUMWPNT);
+
+	*(wsp1 - 1) = *(wsp2 - 1);			/* lowest point */
+	*(wsp1 + NUMWPNT) = *(wsp2 + NUMWPNT - 1);	/* highest point */
+#endif
+
+	curwfnl = wsp2[curwpnt] >> 5;			/* udpate final value */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wsupd() -- update the instrument definition and FPU for new WS offsets
+   =============================================================================
+*/
+
+wsupd()
+{
+	register short i;
+	register short *wsp1, *wsp2;
+
+	/* update the offsets[] array from the instrument definition */
+
+	wsp2 = curwslt ? vbufs[curvce].idhwvbo : vbufs[curvce].idhwvao;
+
+	for (i = 0; i < NUMWPNT; i++)
+		offsets[i + 1] = wsp2[i] >> 5;
+
+	offsets[0] = offsets[1];
+
+	wscalc();		/* calculate the final values */
+
+	/* update the final values in the instrument definition */
+
+	wsp1 = curwslt ? vbufs[curvce].idhwvbf : vbufs[curvce].idhwvaf;
+
+	for (i = 0; i < NUMWPNT; i++)
+		wsp1[i] = wsbuf[1 + i] << 5;
+
+	updfpu();
+	wsnmod[curvce][curwslt] = TRUE;			/* tag WS as modified */
+}
+
+/*
+   =============================================================================
+	whupd() -- update the FPU for new WS harmonics
+   =============================================================================
+*/
+
+whupd()
+{
+	register short i;
+	register short *wsp1;
+
+	/* update the final values in the instrument definition */
+
+	wsp1 = curwslt ? vbufs[curvce].idhwvbf : vbufs[curvce].idhwvaf;
+
+	for (i = 0; i < NUMWPNT; i++)
+		wsp1[i] = wsbuf[i + 1] << 5;
+
+	updfpu();	/* update the FPU */
+	wsnmod[curvce][curwslt] = TRUE;			/* tag WS as modified */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	pntsup() -- update waveshape points with the cursor 'brush'
+   =============================================================================
+*/
+
+pntsup()
+{
+	register struct instdef *ip;
+	short *ov;
+	register short i, j, k, tv, curdif;
+	short cwnp, cwin;
+
+	ip = &vbufs[curvce];			/* instrument definition */
+
+	ov = curwslt	? &ip->idhwvbo		/* offsets in definition */
+			: &ip->idhwvao;
+
+	cwnp   = wdcurct[curwdth][0];		/* number of points effected */
+
+	cwin   = wdcurct[curwdth][1];		/* table increment */
+
+	curdif = lstwoff - curwoff;		/* calculate the difference */
+
+/* 
+
+*/
+	for (i = 0 , k = 0; i < cwnp; i++ , k += cwin) {
+
+		if (i EQ 0) {			/* first point */
+
+			ov[curwpnt] = curwoff << 5;
+
+		} else {			/* subsequent points */
+
+			j = curwpnt + i;	/* update point on the right */
+
+			if (j < NUMWPNT) {	/* ... if it exists */
+
+				tv = (ov[j] >> 5) -
+					((((long)curdif * wdcurtb[k])
+					  + WCROUND) / WCSCALE);
+
+				if (tv GT 1023)
+					tv = 1023;
+				else if (tv LT -1023)
+					tv = -1023;
+
+				ov[j] = tv << 5;
+			}
+
+			j = curwpnt - i;	/* update point on the left */
+
+			if (j GE 0) {		/* ... if it exists */
+
+				tv = (ov[j] >> 5) -
+					((((long)curdif * wdcurtb[k])
+					  + WCROUND) / WCSCALE);
+
+				if (tv GT 1023)
+					tv = 1023;
+				else if (tv LT -1023)
+					tv = -1023;
+
+				ov[j] = tv << 5;
+			}
+		}
+	}
+
+	wsupd();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdintp() -- interpolate between waveshape points
+   =============================================================================
+*/
+
+wdintp()
+{
+	register struct instdef *ip;
+	register short *ov;
+	register short i, j, k, n;
+	register long t;
+	short to, from;
+
+	to   = curwpnt;
+	from = wplast;
+
+	ip   = &vbufs[curvce];
+	ov   = curwslt ? &ip->idhwvbo : &ip->idhwvao;
+
+	ov[curwpnt] = curwoff << 5;	/* force current point value */
+
+	if (from > to) {	/* make 'from' the leftmost point number */
+
+		i = from;
+		from = to;
+		to = i;
+	}
+
+	n = to - from;		/* number of points */
+
+	if (n > 1) {		/* have to have at least 1 point difference */
+
+		k = ov[from] >> 5;
+		t = ((long)((long)(ov[to] >> 5) - (long)k) << 16) / n;
+		j = 1 + from;
+		--n;
+
+		for (i = 0; i < n; i++)
+			ov[j++] = ((short)((t * (1 + i)) >> 16) + k) << 5;
+	}
+
+	wplast = curwpnt;
+	wvlast = curwoff;
+
+	wsupd();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdykdn() -- cursor y finger down processing
+   =============================================================================
+*/
+
+wdykdn()
+{
+	if (wpntsv EQ 0)
+		return;
+
+	lstwpnt = curwpnt;
+	lstwoff = curwoff;
+}
+
+/*
+   =============================================================================
+	wdykup() -- cursor y finger up processing
+   =============================================================================
+*/
+
+wdykup()
+{
+	if ((wpntsv EQ 0) OR (wdupdfl EQ FALSE))
+		return;
+
+	if (wpntsv EQ 1) {			/* offsets */
+
+		if (curwdth EQ NUMWIDS)
+			wdintp();	/* interpolate mode */
+		else
+			pntsup();	/* brush mode */
+
+	} else {				/* harmonics */
+
+		adj(curwhrm);	/* adjust vknm[curwhrm][] */
+		wscalc();	/* recalculate the waveshape */
+		whupd();	/* update the FPU */
+	}
+
+	wdswin(0);		/* display updated waveshape */
+	wdswin(2);
+	wdswin(4);
+
+	wdupdfl = FALSE;
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdcyupd() -- update cursor y location
+   =============================================================================
+*/
+
+wdcyupd()
+{
+	register struct instdef *ip;
+	register short *ov, *hv;
+	register short i, j, k, tv;
+	register char wsgn;
+	short wval, cwnp, cwin;
+
+	ip = &vbufs[curvce];
+
+	switch (wpntsv) {
+
+	case 0:		/* nothing selected -- just move cursor */
+
+		cyval += cyrate;
+
+		if (cyval GT (CYMAX - 1))
+			cyval = CYMAX - 1;
+		else if (cyval LT 1)
+			cyval = 1;
+
+		return;
+/* 
+
+*/
+	case 1:		/* offset selected */
+
+		curwoff -= cyrate;
+
+		if (curwoff GT 1023)
+			curwoff = 1023;
+		else if (curwoff LT -1023)
+			curwoff = -1023;
+
+		cyval = WPOFF - ((curwoff * WPSF1) / WPSF2);
+
+		if (curwoff < 0) {
+
+			wval = - curwoff;
+			wsgn = '-';
+
+		} else {
+
+			wval = curwoff;
+			wsgn = '+';
+		}
+
+		sprintf(bfs, "%c%04d", wsgn, wval);
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		vcputsv(waveob, 64, wdbox[4][4], wdbox[4][5], wdbox[4][6],
+			wdbox[4][7] + WOFF_OFF, bfs, 14);
+
+		wdupdfl = TRUE;
+		return;
+/* 
+
+*/
+	case 2:		/* harmonic selected */
+
+		hv = curwslt ? &ip->idhwvbh : &ip->idhwvah;
+
+		curwhrv = abs(hv[curwhrm]) - cyrate;
+
+		if (curwhrv > 100)
+			curwhrv = 100;
+		else if (curwhrv < 0)
+			curwhrv = 0;
+
+		curwhrv = (hv[curwhrm] < 0) ? -curwhrv : curwhrv;
+
+		hv[curwhrm] = curwhrv;
+		vmtab[curwhrm] = curwhrv;
+
+		if (curwhrv < 0) {
+
+			wval = -curwhrv;
+			wsgn = '-';
+
+		} else {
+
+			wval = curwhrv;
+			wsgn = '+';
+		}
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		sprintf(bfs, "%c%03d", wsgn, wval);
+
+		vcputsv(waveob, 64, wdbox[5][4], wdbox[5][5],
+			wdbox[5][6] + 1, wdbox[5][7] + WHRV_OFF, bfs, 14);
+
+		if (curwhrv < 0)
+			cyval = WBOFF - ((-curwhrv * WBSF1) / WBSF2);
+		else
+			cyval = WBOFF - ((curwhrv * WBSF1) / WBSF2);
+
+		wdupdfl = TRUE;
+		return;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdcxupd() -- update cursor x location
+   =============================================================================
+*/
+
+wdcxupd()
+{
+	switch (wpntsv) {
+
+	case 0:		/* nothing selected - just move cursor */
+
+		cxval += cxrate;
+
+		if (cxval GT (CXMAX - 1))
+			cxval = CXMAX - 1;
+		else if (cxval LT 1)
+			cxval = 1;
+
+		return;
+
+	case 1:		/* offset selected - maybe do interpolate move */
+
+		if (curwdth NE NUMWIDS)
+			return;
+
+		curwpnt += sign(cxrate, wxrate);
+
+		if (curwpnt GE NUMWPNT)
+			curwpnt = NUMWPNT - 1;
+		else if (curwpnt < 0)
+			curwpnt = 0;
+
+		cxval = (curwpnt << 1) + 2;
+
+		if (v_regs[5] & 0x0180)
+			vbank(0);
+
+		sprintf(bfs, "%03d", curwpnt);
+		vcputsv(waveob, 64, wdbox[4][4], wdbox[4][5],
+			wdbox[4][6], wdbox[4][7] + WPNT_OFF, bfs, 14);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdnfld() -- process not-in-field key entry
+   =============================================================================
+*/
+
+short
+wdnfld(k)
+short k;
+{
+	register short *hv;
+	register struct instdef *ip;
+
+	if (astat) {
+
+		if (whatbox()) {
+
+			ip = &vbufs[curvce];
+			hv = curwslt ? &ip->idhwvbh : &ip->idhwvah;
+
+			if (hitbox EQ 0) {	/* waveshape area */
+
+				switch (wpntsv) {
+
+				case 0:		/* nothing selected */
+
+					if (k EQ 8)  {		/* - */
+
+						if (--curwdth < 0)
+							curwdth = NUMWIDS;
+
+						wdswin(4);
+						return(SUCCESS);
+
+					} else if (k EQ 9) {	/* + */
+
+						if (++curwdth > NUMWIDS)
+							curwdth = 0;
+
+						wdswin(4);
+						return(SUCCESS);
+					}
+
+					return(FAILURE);
+/* 
+
+*/
+				case 1:		/* offset selected */
+
+					if (k EQ 8)  {		/* - */
+
+						if (curwdth EQ NUMWIDS)
+							return(FAILURE);
+
+						if (--curwdth LT 0)
+							curwdth = NUMWIDS - 1;
+
+						wdswin(4);
+						return(SUCCESS);
+
+					} else if (k EQ 9) {	/* + */
+
+						if (curwdth EQ NUMWIDS) {
+
+							wdintp();
+							wdswin(0);
+							wdswin(2);
+
+						} else if (++curwdth GE NUMWIDS)
+							curwdth = 0;
+
+						wdswin(4);
+						return(SUCCESS);
+					}
+
+					return(FAILURE);
+/* 
+
+*/
+				case 2:		/* harmonic selected */
+
+					if (k EQ 8)  {		/* - */
+
+						if (hv[curwhrm] > 0)
+							hv[curwhrm] = -hv[curwhrm];
+						else
+							return(FAILURE);
+
+					} else if (k EQ 9) {	/* + */
+
+						if (hv[curwhrm] < 0)
+							hv[curwhrm] = -hv[curwhrm];
+						else
+							return(FAILURE);
+
+					} else {
+
+						return(FAILURE);
+					}
+
+					curwhrv = hv[curwhrm];
+					vmtab[curwhrm] = curwhrv;
+					adj(curwhrm);
+					wscalc();
+					whupd();
+					wdswin(0);
+					wdswin(4);
+					wdswin(5);
+					return(SUCCESS);
+				}
+
+			} else 
+				return(FAILURE);
+/* 
+
+*/
+		} else if (hitbox EQ 1) {	/* harmonic legend */
+
+			if (k EQ 8)  {		/* - */
+
+				if (hv[curwhrm] > 0)
+					hv[curwhrm] = -hv[curwhrm];
+				else
+					return(FAILURE);
+
+			} else if (k EQ 9) {	/* + */
+
+				if (hv[curwhrm] < 0)
+					hv[curwhrm] = -hv[curwhrm];
+				else
+					return(FAILURE);
+
+			} else {
+
+				return(FAILURE);
+			}
+
+			curwhrv = hv[curwhrm];
+			vmtab[curwhrm] = curwhrv;
+			adj(curwhrm);
+			wscalc();
+			whupd();
+			wdswin(0);
+			wdswin(4);
+			wdswin(5);
+			return(SUCCESS);
+		}
+
+		return(FAILURE);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdxkey() -- process X key
+   =============================================================================
+*/
+
+short
+wdxkey()
+{
+	if (NOT astat)
+		return(FAILURE);
+
+	stcrow = cyval / 14;
+	stccol = cxval >> 3;
+
+	if (stcrow EQ 23) {
+
+		if ((stccol GE 2) OR (stccol LE 8)) {
+
+			clrws();
+
+		} else if ((stccol GE 38) AND (stccol LE 42)) {
+
+			memsetw(curwslt ? vbufs[curvce].idhwvbo
+					: vbufs[curvce].idhwvbo,
+				0, NUMWPNT);
+
+			curwoff = 0;
+			wsupd();
+
+		} else if ((stccol GE 51) AND (stccol LE 58)) {
+
+			memsetw(vmtab, 0, NUMHARM);
+			curwhrv = 0;
+			wadj();
+			wscalc();
+			whupd();
+
+		} else {
+
+			return(FAILURE);
+		}
+
+		wsnmod[curvce][curwslt] = TRUE;
+		wwins();
+		return(SUCCESS);
+	}
+
+	return(FAILURE);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdfield() -- setup field routines for the waveshape editor
+   =============================================================================
+*/
+
+wdfield()
+{
+	curslim = 307;
+
+	curset(&wd_flds);
+}
Index: ram/wdselbx.c
===================================================================
--- ram/wdselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/wdselbx.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,262 @@
+/*
+   =============================================================================
+	wdselbx.c -- waveshape editor box selection functions
+	Version 27 -- 1988-09-15 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#define	DEBUGIT		0
+
+#include "stddefs.h"
+#include "fields.h"
+#include "vsdd.h"
+#include "graphdef.h"
+#include "hwdefs.h"
+#include "fpu.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+extern	short	enterit(), wdswin();
+
+extern	short	curvce, curwdth, cursbox, hitbox, cxval, cyval, hitcx, hitcy;
+extern	short	curwave, curwfnl, curwpnt, curwoff, curwhrm, curwhrv, curwslt;
+extern	short	wdupdfl, wpntsv, wplast, wvlast, lstwoff, lstwpnt;
+
+extern	short	offsets[NUMWPCAL];
+extern	short	vmtab[NUMHARM];
+extern	short	wsbuf[NUMWPCAL];
+
+extern	long	vknm[NUMHARM][NUMWPCAL];
+
+extern	short	wdbox[][8];
+
+extern	short	wsnmod[12][2];
+
+extern	short	crate1[], crate2[], *cratex, *cratey;
+
+extern	struct	selbox	*csbp, *curboxp;
+
+extern	struct	instdef	vbufs[];
+
+extern	struct	wstbl	wslib[];
+
+/* forward references */
+
+short	bx_null(), wdfnbox();
+
+/* 
+
+*/
+
+struct	selbox	wdboxes[] = {
+
+	{  1,   1, 510, 307,      0, wdfnbox},	/*  0 */
+	{  1, 308, 510, 320,      1, wdfnbox},	/*  1 */
+	{  1, 322, 174, 348,      2, enterit},	/*  2 */
+	{176, 322, 230, 348,      3, wdfnbox},	/*  3 */
+	{232, 322, 398, 348,      4, enterit},	/*  4 */
+	{400, 322, 510, 348,      5, enterit},	/*  5 */
+
+	{  0,   0,   0,   0,	  0, FN_NULL}		/* end of table */
+};
+
+/*
+   =============================================================================
+	dsnewws() -- display a new waveshape
+   =============================================================================
+*/
+
+dsnewws()
+{
+	wdswin(0);
+	wdswin(2);
+	wdswin(4);
+	wdswin(5);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	newws() -- setup editing for a new waveshape
+   =============================================================================
+*/
+
+newws()
+{
+	register short i;
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];
+
+	if (curwslt) {
+
+		for (i = 0; i < NUMWPNT; i++) {
+
+			offsets[i + 1] = ip->idhwvbo[i] >> 5;
+			wsbuf[i + 1]   = ip->idhwvbf[i] >> 5;
+		}
+
+		memcpyw(vmtab, ip->idhwvbh, NUMHARM);
+
+	} else {
+
+		for (i = 0; i < NUMWPNT; i++) {
+
+			offsets[i + 1] = ip->idhwvao[i] >> 5;
+			wsbuf[i + 1]   = ip->idhwvaf[i] >> 5;
+		}
+
+		memcpyw(vmtab, ip->idhwvah, NUMHARM);
+	}
+
+	offsets[0] = offsets[1];
+	wsbuf[0]   = wsbuf[1];
+
+	curwhrv = vmtab[curwhrm];
+	lstwoff = wvlast = curwoff = offsets[1 + curwpnt];
+	curwfnl = wsbuf[curwpnt + 1];
+	lstwpnt = wplast = curwpnt;
+
+	memsetw(vknm, 0, (NUMHARM * NUMWPCAL) << 1);
+	wadj();
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdfnbox() -- waveshape display box hit processor
+   =============================================================================
+*/
+
+short
+wdfnbox(n)
+short n;
+{
+	register short wval;
+	register char wsgn;
+	register short *fpuws;
+
+	switch (n) {	/* switch off of window ID */
+
+	case 0:		/* process a hit in the main window */
+
+		switch (wpntsv) {
+
+		case 0:		/* nothing selected so far:  select a point */
+
+			wpntsv = 1;
+			curwpnt = (cxval - 2) / 2;
+
+			if (curwpnt GE NUMWPNT)
+				curwpnt = NUMWPNT - 1;
+			else if (curwpnt < 0)
+				curwpnt = 0;
+
+			cratex = crate2;
+			cratey = crate2;
+			newws();
+			cyval = WPOFF - ((curwoff * WPSF1) / WPSF2);
+			cxval = (curwpnt << 1) + 2;
+			arcurs(WS_GRAB);
+			gcurpos(cxval, cyval);
+			wplast = curwpnt;
+			wvlast = curwoff;
+			wdswin(4);
+			break;
+/* 
+
+*/
+		case 1:		/* point was selected:  unselect it */
+
+			wpntsv = 0;
+			cratex = crate1;
+			cratey = crate1;
+
+			arcurs(WDCURS);
+			gcurpos(cxval, cyval);
+			break;
+
+		case 2:		/* harmonic was selected:  unselect it */
+
+			wpntsv = 0;
+			cratex = crate1;
+			cratey = crate1;
+
+			arcurs(WDCURS);
+			settc(22, 1 + (curwhrm << 1));
+			break;
+		}
+
+		return(TRUE);
+
+	case 1:		/* process a hit in the harmonic legend */
+
+		wpntsv  = 2;
+		cratex  = crate1;
+		cratey  = crate1;
+
+		curwhrm = cxval >> 4;
+		curwhrv = vmtab[curwhrm];
+
+		cxval = (curwhrm << 4) + 8;
+
+		if (curwhrv < 0) {
+
+			cyval = WBOFF - ((-curwhrv * WBSF1) / WBSF2);
+
+		} else {
+
+			cyval = WBOFF - ((curwhrv * WBSF1) / WBSF2);
+		}
+
+		arcurs(WS_GRAB);
+		gcurpos(cxval, cyval);
+		wdswin(5);
+		return(TRUE);
+/* 
+
+*/
+	case 3:		/* process a hit in the store & fetch window */
+
+		wsnmod[curvce][curwslt] = FALSE;
+
+		if (cyval < 336) {		/* store ? */
+
+			memcpyw(&wslib[curwave],
+				curwslt ? vbufs[curvce].idhwvbf
+					: vbufs[curvce].idhwvaf,
+				NUMHARM + (2 * NUMWPNT));
+
+			wdswin(2);
+
+		} else {			/* retrieve */
+
+			memcpyw(curwslt ? vbufs[curvce].idhwvbf
+					: vbufs[curvce].idhwvaf,
+				&wslib[curwave],
+				NUMHARM + (2 * NUMWPNT));
+
+			updfpu();
+			newws();
+			dsnewws();
+		}
+
+		cratex = crate1;
+		cratey = crate1;
+		return(TRUE);
+
+	default:		/* anywhere else is an error */
+
+		cratex = crate1;
+		cratey = crate1;
+		return(FALSE);
+	}
+}
Index: ram/wheel.c
===================================================================
--- ram/wheel.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/wheel.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,1369 @@
+/*
+   =============================================================================
+	wheel.c -- MIDAS-VII -- scroll wheel, trackball and mouse functions
+	Version 47 -- 1989-12-19 -- D.N. Lynx Crowe
+
+	M8 Mouse driver -- uses 3 byte Microsoft format  (default).
+   =============================================================================
+*/
+
+#define	DEBUGMS		0
+#define	DEBUGTF		0
+#define	DEBUGTK		0
+
+#include "stddefs.h"
+#include "graphdef.h"
+#include "biosdefs.h"
+#include "uartio.h"
+#include "vsdd.h"
+#include "hwdefs.h"
+#include "fields.h"
+#include "macros.h"
+#include "sclock.h"
+#include "scwheel.h"
+#include "timers.h"
+#include "score.h"
+#include "curpak.h"
+
+#include "midas.h"
+
+extern	unsigned short	setipl();
+
+#define	M_FL_CT		1024			/* mouse flush count */
+
+#define	M_ST_TM		2
+#define	C_PER_S		500
+#define	MAXTRIES	10
+
+#define	MATIME		2000			/* mouse activity timeout -- ms*/
+
+#define	CFR0		(BR_1200|NSB_1)		/* UART CFR0  1200 baud, 1 stop bit */
+#define	CFR1		(P_NONE|NDB_7)		/* UART CFR1  7 data bits, no parity */
+
+#define	M_NONE		0		/* No errors detected */
+#define	M_FLUSH		1		/* Unable to flush mouse buffer */
+#define	M_SYNC		2		/* Mouse out of sync */
+#define	M_NORESP	3		/* No response from mouse */
+#define	M_RESPNG	4		/* Bad response from mouse */
+
+/* 
+
+*/
+
+#if	DEBUGMS
+short	debugms;
+#endif
+
+#if	DEBUGTF
+short	debugtf;
+
+long	txficnt;
+long	tyficnt;
+#endif
+
+#if	DEBUGTK
+short	debugtk;
+#endif
+
+short	M_error;		/* mouse I/F error code */
+short	M_state;		/* mouse state */
+short	M_oldbs;		/* previous mouse button state */
+
+char	M_strng[32];		/* mouse input string buffer */
+
+short	msctrl;			/* mouse control flag -- mouse update */
+short	msflag;			/* mouse control flag -- mouse movement */
+short	msrtag;			/* mouse control flag -- mouse reset */
+short	msxres;			/* mouse x residue */	
+short	msyres;			/* mouse y residue */
+short	msxmov;			/* mouse x movement */
+short	msymov;			/* mouse y movement */
+short	msxdiv;			/* mouse x divisor */
+short	msydiv;			/* mouse y divisor */
+
+short	tkboth;			/* both trackball axes went active */
+
+short	txdiv;			/* text cursor X divider */
+short	tydiv;			/* text cursor Y divider */
+
+short	tkxdvr = TKXDVR;	/* text cursor X divisor */
+short	tkydvr = TKYDVR;	/* text cursor Y divisor */
+
+short	tkhdvr = TKCDVR;	/* text cursor horizontal movement threshold */
+short	tkvdvr = TKCDVR;	/* text cursor vertical movement threshold */
+
+/* 
+
+*/
+
+short	msxgdv[13] = {		/* mouse x cursor divisor table */
+
+	1,	/* -1 -- Main menu */
+	1,	/*  0 -- Librarian */
+	1,	/*  1 -- Patch editor */
+	1,	/*  2 -- Score editor */
+	1,	/*  3 -- Sequence editor */
+	1,	/*  4 -- Instrument editor */
+	1,	/*  5 -- Initialize system */
+	1,	/*  6 -- Waveshape editor */
+	1,	/*  7 -- Write program to disk */
+	1,	/*  8 -- Tuning editor */
+	1,	/*  9 -- Format disk */
+	1,	/* 10 -- Assignment editor */
+	1	/* 11 -- Diagnostics */
+};
+
+short	msygdv[13] = {		/* mouse y cursor divisor table */
+
+	2,	/* -1 -- Main menu */
+	2,	/*  0 -- Librarian */
+	2,	/*  1 -- Patch editor */
+	2,	/*  2 -- Score editor */
+	2,	/*  3 -- Sequence editor */
+	2,	/*  4 -- Instrument editor */
+	2,	/*  5 -- Initialize system */
+	2,	/*  6 -- Waveshape editor */
+	2,	/*  7 -- Write program to disk */
+	2,	/*  8 -- Tuning editor */
+	2,	/*  9 -- Format disk */
+	2,	/* 10 -- Assignment editor */
+	2	/* 11 -- Diagnostics */
+};
+
+/* 
+
+*/
+
+extern	short	(*curmove)();
+extern	short	(*cx_upd)();
+extern	short	(*cy_upd)();
+extern	short	(*xy_dn)();
+extern	short	(*xy_up)();
+extern	short	(*e_key)();
+extern	short	(*m_key)();
+extern	short	(*x_key)();
+
+extern	short	asig;
+extern	short	astat;
+extern	short	aval;
+extern	short	chtime;
+extern	short	chwait;
+extern	short	clkctl;
+extern	short	clkrun;
+extern	short	cmfirst;
+extern	short	cmtype;
+extern	short	ctrsw;
+extern	short	curhold;
+extern	short	cvtime;
+extern	short	cvwait;
+extern	short	cxrate;
+extern	short	cxval;
+extern	short	cyrate;
+extern	short	cyval;
+extern	short	msctrl;
+extern	short	msflag;
+extern	short	msxdiv;
+extern	short	msydiv;
+extern	short	nchwait;
+extern	short	ncvwait;
+extern	short	ndisp;
+extern	short	ss_ptsw;
+extern	short	ss_sqsw;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	swback;
+extern	short	swctrl;
+extern	short	swdelta;
+extern	short	swdir;
+extern	short	swfiin;
+extern	short	swflag;
+extern	short	swlast;
+extern	short	swndx;
+extern	short	swstop;
+extern	short	swthr;
+extern	short	swtime;
+extern	short	swwait;
+
+/* 
+
+*/
+
+extern	short	tkback;
+extern	short	tkctrl;
+extern	short	tkrmin;
+extern	short	tkthr;
+extern	short	tktime;
+extern	short	tkwait;
+extern	short	trkball;
+extern	short	txfiin;
+extern	short	txflag;
+extern	short	txlast;
+extern	short	tyfiin;
+extern	short	tyflag;
+extern	short	tylast;
+extern	short	txstop;
+extern	short	tystop;
+extern	short	vtccol;
+extern	short	vtcrow;
+extern	short	vtpcol;
+extern	short	vtprow;
+extern	short	xkstat;
+extern	short	ykstat;
+
+extern	long	swcount;
+extern	long	swrate;
+extern	long	swrmin;
+extern	long	swtemp;
+
+extern	short	*cratex;
+extern	short	*cratey;
+
+extern	short	sigtab[][2];
+extern	short	swfifo[NSWFIFO];
+extern	short	txfifo[NTKFIFO];
+extern	short	tyfifo[NTKFIFO];
+
+#include "swrtab.h"		/* long swrtab[128]; */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MouseRT() -- reset the mouse activity timer
+   =============================================================================
+*/
+
+MouseRT(t)
+unsigned short t;
+{
+	unsigned short oldi;
+
+	oldi = setipl(TIM_DI);		/* disable interrupts */
+
+	timers[MUTIMER] = t;		/* set the mouse timer */
+
+	setipl(oldi);			/* enable interrupts */
+
+#if	DEBUGMS
+	if (debugms > 2)
+		printf("MouseRT(%d)\n", t);
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MouseRD() -- read a string from the mouse
+   =============================================================================
+*/
+
+MouseRD(str, nc, nt)
+char *str;
+short nc, nt;
+{
+	long tc;
+
+	tc = nt * (long)C_PER_S;
+
+	while (nc > 0) {
+
+		if (BIOS(B_RDAV, PRT_DEV)) {
+
+			*str++ = (char)BIOS(B_GETC, PRT_DEV);
+			*str = '\0';
+			--nc;
+
+		} else {
+
+			if (tc-- LE 0)
+				return(FAILURE);
+		}
+	}
+
+	return(SUCCESS);
+}
+
+/*
+   =============================================================================
+	MouseWR() -- write a string to the mouse
+   =============================================================================
+*/
+
+MouseWR(str)
+char *str;
+{
+	register unsigned short c;
+
+#if	DEBUGMS
+	if (debugms > 1)
+		printf("OUT \"%s\"\n", str);
+#endif
+
+	while (c = 0x00FF & *str++)		/* get a byte */
+		BIOS(B_PUTC, PRT_DEV, c);	/* output it */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MouseFL() -- flush the mouse input buffer
+   =============================================================================
+*/
+
+short
+MouseFL(tc)
+short tc;
+{
+	long flushed;
+
+	flushed = 0L;				/* reset the flush counter */
+
+	M_state = 0;				/* reset mouse state */
+	msflag  = FALSE;			/* reset mouse movement flag */
+	msctrl  = FALSE;			/* reset mouse update flag */
+
+	while (BIOS(B_RDAV, PRT_DEV)) {		/* check for data */
+
+		BIOS(B_GETC, PRT_DEV);		/* read a byte */
+		++flushed;			/* update flush count */
+
+		if (--tc LE 0) {		/* see if we've timed out */
+
+#if	DEBUGMS
+	if (debugms)
+		printf("FLUSH %d %ld FAILURE\n", M_state, flushed);
+#endif
+
+			return(FAILURE);	/* FAILED */
+		}
+	}
+
+#if	DEBUGMS
+	if (debugms)
+		printf("FLUSH %d %ld SUCCESS\n", M_state, flushed);
+#endif
+
+	return(SUCCESS);			/* SUCCEEDED */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MouseWK() -- wake up the mouse
+   =============================================================================
+*/
+
+short
+MouseWK()
+{
+	short tries;
+
+	M_error = M_NONE;		/* reset mouse error flag */
+	M_oldbs = 0;			/* reset mouse button state */
+	M_state = 0;			/* reset the mouse state machine */
+
+	/* set the UART to 1200 baud, 7 data bits, No parity, 1 stop bit */
+
+	XBIOS(X_SETPRT, PRT_DEV, L_NUL, -1, CFR0, CFR1);
+
+	if (MouseFL(M_FL_CT)) {		/* flush the FIFO */
+
+		M_error = M_FLUSH;	/* error -- can't flush */
+
+#if	DEBUGMS
+	if (debugms)
+		printf("MouseWK() -- FAILURE\n");
+#endif
+
+		return(FAILURE);	/* return -- we failed */
+	}
+
+	for (tries = 0; tries < MAXTRIES; tries++) {
+
+		MouseWR("t");			/* ask the mouse its mode */
+
+		if (MouseRD(M_strng, 2, M_ST_TM)) {
+
+			M_error = M_NORESP;
+
+		} else if (strcmp("VO", M_strng)) {
+
+			M_error = M_RESPNG;
+
+			if (MouseFL(M_FL_CT))
+				M_error = M_FLUSH;
+
+		} else {
+
+			M_error = M_NONE;
+			MouseRT(MATIME);
+
+#if	DEBUGMS
+	if (debugms)
+		printf("MouseWK() -- SUCCESS\n");
+#endif
+			return(SUCCESS);
+		}
+	}
+
+#if	DEBUGMS
+	if (debugms)
+		printf("MouseWK() -- FAILURE\n");
+#endif
+
+	return(FAILURE);
+}
+
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MouseEX() -- process a mouse report
+   =============================================================================
+*/
+
+MouseEX(str)
+char *str;
+{
+	unsigned short oldi, msc, mst;
+
+#if	DEBUGMS
+	if (debugms > 2)
+		printf("REPORT %02.2X %02.2X %02.2X\n",
+			str[0] & 0x00FF, str[1] & 0x00FF, str[2] & 0x00FF);
+#endif
+
+	M_error = M_NONE;			/* reset error code */
+
+	if ((str[0] & 0x0040) NE 0x0040) {
+
+		if (MouseFL(M_FL_CT))
+			M_error = M_FLUSH;
+		else
+			M_error = M_SYNC;
+
+		M_state = 0;
+		MouseRT(MATIME);
+
+#if	DEBUGMS
+	if (debugms)
+		printf("SYNC\n");
+#endif
+
+		return;
+	}
+
+	mst     = str[0] & 0x0030;		/* extract mouse buttons */
+	msc     = M_oldbs ^ mst;		/* see what changed */
+	M_oldbs = mst;				/* update button state */
+
+	if (msc) {			/* check for button status change */
+
+		if (msc & 0x0010) {		/* m key ?  (right mouse button) */
+
+			astat = (mst & 0x0010) >> 4;
+			(*m_key)();
+		}
+
+		if (msc & 0x0020) {		/* e key ?  (left mouse button) */
+
+			astat = (mst & 0x0020) >> 5;
+			(*e_key)();
+		}
+	}
+
+	if ((ss_ptsw NE 0) OR (ss_sqsw NE 0)) {
+
+		cxrate = 0;
+		cyrate = 0;
+		return;
+	}
+
+/* 
+
+*/
+
+	msxmov  =  str[1] | ((str[0] & 0x0003) << 6);
+
+	if (msxmov & 0x0080)
+		msxmov |= 0xFF80;
+
+	msxmov += msxres;
+
+	msymov =  str[2] + ((str[0] & 0x000C) << 4);
+
+	if (msymov & 0x0080)
+		msymov |= 0xFF80;
+
+	msymov += msyres;
+
+	msxdiv = msxgdv[ndisp + 1];
+	msydiv = msygdv[ndisp + 1];
+
+	/* calculate rates */
+
+	if (msxdiv > 1)
+		cxrate = msxmov / msxdiv;
+	else
+		cxrate = msxmov;
+
+	if (msydiv > 1)
+		cyrate = msymov / msydiv;
+	else
+		cyrate = msymov;
+
+	/* calculate residues */
+
+	if (msxdiv > 1)
+		msxres = msxmov % msxdiv;
+	else
+		msxres = 0;
+
+	if (msydiv > 1)
+		msyres = msymov % msydiv;
+	else
+		msyres = 0;
+
+/* 
+
+*/
+
+	if ((cxrate EQ 0) AND (cyrate EQ 0))	/* we're done if nothing changed */
+		return;
+
+	msctrl  = TRUE;				/* setup movement switches */
+	cmfirst = FALSE;
+	trkball = FALSE;
+
+	cvtime  = 0;				/* clear delays */
+	ncvwait = 0;
+	chtime  = 0;
+	nchwait = 0;
+	curhold = 0;
+
+	if (NOT msflag)			/* if mouse just started moving ... */
+		(*xy_dn)();		/* ... process key down */
+
+	oldi = setipl(TIM_DI);		/* set the mouse movement timer */
+	timers[MSTIMER] = MSTOVAL;
+	setipl(oldi);
+
+	msflag = TRUE;			/* indicate the mouse has started moving */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	MouseIN() -- process a byte from the mouse
+   =============================================================================
+*/
+
+MouseIN(c)
+short c;
+{
+	c &= 0x00FF;		/* mask off extraneous bits from mouse input */
+
+#if	DEBUGMS
+	if (debugms > 2)
+		printf("IN %d %02.2X\n", M_state, c);
+#endif
+
+	if ((M_state GE 0) AND (M_state < 3)) {
+
+		M_strng[M_state] = c;
+
+		if (M_state EQ 2) {
+
+			MouseEX(M_strng);
+			M_state = 0;
+
+		} else {
+
+			++M_state;
+		}
+	}
+}
+
+/* 
+
+*/
+
+#if	DEBUGTF
+/*
+   =============================================================================
+	tfdump() -- dump a trackball FIFO
+   =============================================================================
+*/
+
+tfdump(msg, fifo, ndx, fin, cnt)
+char *msg;
+register short *fifo, ndx, fin;
+long cnt;
+{
+	register short nol = 0, i = fin, j = fin - 1;
+
+	printf("Dump of %s FIFO\n", msg);
+	printf("  ndx=%d  fin=%d  cnt=%ld\n", ndx, fin, cnt);
+
+	if (j < 0)
+		j = NTKFIFO - 1;
+
+	do {
+
+		if (nol EQ 0)
+			printf("    ");
+
+		if (i EQ ndx)
+			printf("<%2d  ", fifo[i]);
+		else if (i EQ j)
+			printf(" %2d> ", fifo[i]);
+		else
+			printf(" %2d  ", fifo[i]);
+
+		if (++nol GE 15) {
+
+			printf("\n");
+			nol = 0;
+		}
+
+		if (++i GE NTKFIFO)
+			i = 0; 
+
+	} while (i NE fin);
+
+	if (nol)
+		printf("\n");
+
+	printf("\n");
+}
+#endif
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wheel() -- process inputs from the scroll wheel
+   =============================================================================
+*/
+
+wheel()
+{
+	register short i, oldi;
+
+	if (astat) {	/* if it's touched ... */
+
+		if (NOT swflag) {
+
+			/* GOING DOWN */
+
+			swflag  = TRUE;
+			swctrl  = FALSE;
+			swfiin  = 0;
+			swlast  = aval;
+			swstop  = swwait;
+			swcount = 0;
+
+			for (i = 0; i < NSWFIFO; i++)
+				swfifo[i] = aval;
+/* 
+
+*/
+		} else {		/* finger moved */
+
+			if (0 EQ swstop) {
+
+				swdelta = swlast - aval;
+
+				if (swdelta GE swthr) {
+
+					if ((clkctl EQ CK_STEP) OR
+					     ((clkctl NE CK_STEP) AND
+					      (NOT clkrun))) {
+
+						/* FINGER MOVED LEFT */
+
+						swtemp  = swdelta / swthr;
+						oldi    = setipl(TIM_DI);
+						fc_val += swtemp;
+
+						if (fc_val GE 0x00FFFFFFL)
+							fc_val = 0x00FFFFFFL;
+
+						setipl(oldi);
+						swlast = aval;
+					}
+
+				} else if ((swdelta = abs(swdelta)) GE swthr) {
+
+					if ((clkctl EQ CK_STEP) OR
+					     ((clkctl NE CK_STEP) AND
+					      (NOT clkrun))) {
+
+						/* FINGER MOVED RIGHT */
+
+						swtemp = swdelta / swthr;
+						oldi = setipl(TIM_DI);
+						fc_val -= swtemp;
+
+						if (fc_val LT 0L)
+							fc_val = 0L;
+
+						setipl(oldi);
+						swlast = aval;
+					}
+				}
+
+			} else {
+
+				swlast = aval;
+				--swstop;
+			}
+		}
+/* 
+
+*/
+	} else {	/* FINGER UP */
+
+		swlast = aval;
+		swflag = FALSE;
+		swctrl = FALSE;
+
+		if ((clkctl EQ CK_STEP) OR
+		    ((clkctl NE CK_STEP) AND
+		     (NOT clkrun))) {
+
+			swndx = swfiin - swback;
+
+			if (swndx < 0)
+				swndx += NSWFIFO;
+
+			swrate = swfifo[swndx] - swlast;
+
+			if (swrate > swrmin) {
+
+				swdir  = D_FWD;		/* SCROLL FORWARD */
+				swrate = swrtab[swrate - swrmin];
+				swctrl = TRUE;
+
+			} else if ((swrate = abs(swrate)) > swrmin) {
+
+				swdir  = D_BAK;		/* SCROLL BACKWARD */
+				swrate = swrtab[swrate - swrmin];
+				swctrl = TRUE;
+
+			} else {
+
+				swrate = 0L;		/* STOP SCROLLING */
+			}
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	txyup() -- process trackball -- both axes inactive
+   =============================================================================
+*/
+
+txyup()
+{
+	register short txndx, tyndx, txrate, tyrate;
+
+#if	DEBUGTF
+	if (debugtf)
+		printf("txyup():  both inactive\n");
+#endif
+
+	tkboth = FALSE;				/* both axes inactive now */
+
+	txdiv  = 0;				/* reset text cursor dividers */
+	tydiv  = 0;
+
+	if ((txndx = txfiin - tkback) < 0)	/* get fifo index */
+		txndx += NTKFIFO;		/* adjust index */
+
+	txrate = txfifo[txndx] - txlast;	/* get movement */
+
+#if	DEBUGTF
+	if (debugtf)
+		tfdump("X", txfifo, txndx, txfiin, txficnt);
+#endif
+
+	if (txrate GE tkrmin)
+		cxrate = -cratex[txrate - tkrmin];	/* tracking left */
+	else if ((txrate = abs(txrate)) GE tkrmin)
+		cxrate =  cratex[txrate - tkrmin];	/* tracking right */
+	else
+		cxrate = 0;				/* X inactive */
+
+/* 
+
+*/
+	if ((tyndx = tyfiin - tkback) < 0)	/* get fifo index */
+		tyndx += NTKFIFO;		/* adjust index */
+
+	tyrate = tyfifo[tyndx] - tylast;	/* get movement */
+
+#if	DEBUGTF
+	if (debugtf)
+		tfdump("Y", tyfifo, tyndx, tyfiin, tyficnt);
+#endif
+
+	if (tyrate GE tkrmin)
+		cyrate =  cratey[tyrate - tkrmin];	/* tracking down */
+	else if ((tyrate = abs(tyrate)) GE tkrmin)
+		cyrate = -cratey[tyrate - tkrmin];	/* tracking up */
+	else
+		cyrate = 0;				/* Y inactive */
+
+	if ((cxrate EQ 0) AND (cyrate EQ 0)) {
+
+		tkctrl = FALSE;		/* STOP -- both rates are zero */
+		(*xy_up)();
+
+	} else {
+
+		tkctrl = TRUE;		/* ROLL -- some rate is non-zero  */
+	}
+
+#if	DEBUGTK
+	if (debugtk)
+		printf("txyup():  %s  rmin=%d  txr=%d cxr=%d  tyr=%d cyr=%d\n",
+			tkctrl ? "ROLL" : "STOP", tkrmin, txrate, cxrate, tyrate, cyrate);
+#endif
+
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	txydn() -- process trackball -- both axes active
+   =============================================================================
+*/
+
+txydn()
+{
+	register short i;
+
+#if	DEBUGTK
+	if (debugtk)
+		printf("txydn():  both active  txlast=%d  tylast=%d\n",
+			txlast, tylast);
+#endif
+
+	tkboth = TRUE;			/* both down now */
+	(*xy_dn)();
+
+	tkctrl  = FALSE;		/* stop rolling */
+	cxrate  = 0;
+	cyrate  = 0;
+
+	txfiin  = 0;			/* preset the FIFOs */
+	tyfiin  = 0;
+
+	for (i = 0; i < NTKFIFO; i++) {
+
+		txfifo[i] = txlast;
+		tyfifo[i] = tylast;
+	}
+
+#if	DEBUGTF
+	txficnt = 0;
+	tyficnt = 0;
+#endif
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	txstd() -- process inputs from the trackball X axis
+   =============================================================================
+*/
+
+txstd()
+{
+	register short i, oldcx, oldi, txdelta, txcdvr;
+
+	trkball = TRUE;				/* set trackball mode */
+	cmfirst = FALSE;
+	chtime  = tktime;
+	nchwait = tktime;
+	chwait  = tktime;
+
+
+	/* get rate divisor */
+
+	txcdvr  = (cmtype EQ CT_GRAF) ? tkthr : tkhdvr;
+
+	if (astat) {				/* is axis active ? */
+
+		if (NOT txflag) {
+
+			/* GOING ACTIVE */
+
+			txflag  = TRUE;
+			txstop  = tkwait;
+			txlast  = aval;
+
+			if (tyflag AND (NOT tkboth))
+				txydn();	/* both active now */
+
+/* 
+
+*/
+		} else {			/* finger moved ? */
+
+			if (txstop LE 0) {	/* debounced ? */
+
+				txdelta = txlast - aval;
+				oldcx   = cxval;
+
+				if (txdelta GE txcdvr) {
+
+					/* FINGER MOVED LEFT */
+
+					cxrate  = -(txdelta / txcdvr);
+
+					(*cx_upd)();	/* update cxval */
+
+					if (oldcx NE cxval)	/* new cxval ? */
+						(*curmove)();	/* move cursor */
+
+					txlast = aval;
+					cxrate = 0;
+
+				} else if ((txdelta = abs(txdelta)) GE txcdvr) {
+
+					/* FINGER MOVED RIGHT */
+
+					cxrate = txdelta / txcdvr;
+
+					(*cx_upd)();	/* update cxval */
+
+					if (oldcx NE cxval)	/* new cxval ? */
+						(*curmove)();	/* move cursor */
+
+					txlast = aval;
+					cxrate = 0;
+				}
+
+			} else {		/* debounce data */
+
+				txlast = aval;
+				--txstop;
+			}
+		}
+/* 
+
+*/
+	} else {				/* AXIS GOING INACTIVE */
+
+		txlast = aval;			/* get current value */
+		txflag = FALSE;			/* X axis inactive */
+
+		if (NOT tyflag)			/* check other axis */
+			txyup();		/* both inactive now */
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tystd() -- process inputs from the trackball Y axis
+   =============================================================================
+*/
+
+tystd()
+{
+	register short i, oldcy, oldi, tydelta, tycdvr;
+
+	trkball = TRUE;				/* set trackball mode */
+	cmfirst = FALSE;
+	cvtime  = tktime;
+	ncvwait = tktime;
+	cvwait  = tktime;
+
+	/* get rate divisor */
+
+	tycdvr  = (cmtype EQ CT_GRAF) ? tkthr : tkvdvr;
+
+	if (astat) {				/* if axis active ? */
+
+		if (NOT tyflag) {
+
+			/* GOING ACTIVE */
+
+			tyflag  = TRUE;
+			tystop  = tkwait;
+			tylast  = aval;
+
+			if (txflag AND (NOT tkboth))
+				txydn();	/* both active now */
+/* 
+
+*/
+		} else {			/* finger moved ? */
+
+			if (tystop LE 0) {	/* debounced ? */
+
+				tydelta = tylast - aval;
+				oldcy   = cyval;
+
+				if (tydelta GE tycdvr) {
+
+					/* FINGER MOVED DOWN */
+
+					cyrate  = tydelta / tycdvr;
+
+					(*cy_upd)();	/* update cyval */
+
+					if (oldcy NE cyval)	/* new cyval ? */
+						(*curmove)();	/* move cursor */
+
+					tylast = aval;
+					cyrate = 0;
+
+				} else if ((tydelta = abs(tydelta)) GE tycdvr) {
+
+					/* FINGER MOVED UP */
+
+					cyrate = -(tydelta / tycdvr);
+
+					(*cy_upd)();	/* udpate cyval */
+
+					if (oldcy NE cyval)	/* new cyval ? */
+						(*curmove)();	/* move cursor */
+
+					tylast = aval;
+					cyrate = 0;
+				}
+
+			} else {		/* debounce data */
+
+				tylast = aval;
+				--tystop;
+			}
+		}
+/* 
+
+*/
+	} else {				/* AXIS GOING INACTIVE */
+
+		tylast = aval;			/* get current value */
+		tyflag = FALSE;			/* Y axis inactive */
+
+		if (NOT txflag)			/* check other axis */
+			txyup();		/* both inactive now */
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	curproc() -- process cursor trackball and scroll wheel updates
+   =============================================================================
+*/
+
+curproc()
+{
+	register short i, cxprev, cyprev;
+	short oldcx, oldcy;
+	register unsigned short oldi;
+
+	/* SET CURRENT WAIT COUNTS FROM TIMERS */
+
+	chwait = timers[TXTIMER];
+	cvwait = timers[TYTIMER];
+
+	if (trkball) {		/* are we tracking ? */
+
+		if (txflag AND (chwait LE 0)) {
+
+			/* SAMPLE THE TRACKBALL X AXIS */
+
+			txfifo[txfiin] = sigtab[55][0];
+
+#if	DEBUGTF
+	++txficnt;
+#endif
+
+			if (++txfiin GE NTKFIFO)
+				txfiin = 0;
+		}
+
+		if (tyflag AND (cvwait LE 0)) {
+
+			/* SAMPLE THE TRACKBALL Y AXIS */
+
+			tyfifo[tyfiin] = sigtab[56][0];
+
+#if	DEBUGTF
+	++tyficnt;
+#endif
+
+			if (++tyfiin GE NTKFIFO)
+				tyfiin = 0;
+		}
+	}
+/* 
+
+*/
+	/* PROCESS MOUSE INPUTS */
+
+	if (BIOS(B_RDAV, PRT_DEV)) {
+
+		MouseIN((short)BIOS(B_GETC, PRT_DEV));
+
+		MouseRT(MATIME);	/* reset mouse activity timer */
+	}
+
+	/* PROCESS THE CURSORS */
+
+	if (cvwait LE 0) {		/* has the vertical timer run out ? */
+
+		if (ss_ptsw)			/* see if the patches need scrolled */
+			smy_up(ss_ptsw);	/* scroll the patch display */
+
+		if (ss_sqsw)			/* see if the sequences need scrolled */
+			sqy_up(ss_sqsw);	/* scroll the sequence display */
+	}
+
+	if (msctrl OR					/* is the mouse moving ? */
+		(cvwait LE 0) OR (chwait LE 0)) {	/* has X or Y timer runout ? */
+
+		if (msctrl OR tkctrl OR (xkstat AND ykstat)) {	/* cursor moving ? */
+
+			oldcx   = cxrate;	/* save old cxrate, cyrate */
+			oldcy   = cyrate;
+			cxprev  = cxval;	/* save old cxval, cyval */
+			cyprev  = cyval;
+			vtprow  = vtcrow;	/* save old vtrow, vtcol */
+			vtpcol  = vtccol;
+
+			if (NOT msctrl)		/* if it's not the mouse ... */
+				cmfix();	/* ... adjust the rates */
+
+/* 
+
+*/
+			if ((cxrate NE 0) AND (msctrl OR (chwait LE 0)))	/* UPDATE X VALUES */
+				(*cx_upd)();
+
+			if ((cyrate NE 0) AND (msctrl OR (cvwait LE 0)))	/* UPDATE Y VALUES */
+				(*cy_upd)();
+
+			cxrate = oldcx;
+			cyrate = oldcy;
+
+			/* see if cursor should be moved */
+
+			if ( (cxprev NE cxval)  OR (cyprev NE cyval) OR
+			     (vtprow NE vtcrow) OR (vtpcol NE vtccol) ) {
+
+				(*curmove)();	/* MOVE CURSOR */
+
+				if (ebflag) {	/* FIXUP EDIT BUFFER */
+
+					if ((struct fet *)NULL NE curfet) {
+
+						if (infield(stcrow, stccol, curfet)) {
+
+							if ((cfetp NE NULL) AND
+							    (cfetp NE infetp)) {
+
+								(*cfetp->redisp)(cfetp->ftags);
+								ebflag = FALSE;
+							}
+
+						} else {	/* isn't in a field */
+
+							if (cfetp NE NULL)
+								(*cfetp->redisp)(cfetp->ftags);
+
+							ebflag = FALSE;
+						}
+
+					} else {	/* no fet, no field */
+
+						ebflag = FALSE;
+					}
+				}
+			}
+		}
+	}
+/* 
+
+*/
+	/* CHECK THE MOUSE MOTION TIMER */
+
+	if (msflag AND (0 EQ timers[MSTIMER])) {
+
+		(*xy_up)();		/* indicate key up */
+
+		msflag = FALSE;		/* indicate mouse stopped */
+	}
+
+	msctrl = FALSE;		/* indicate mouse movement processed */
+
+
+	/* CHECK THE MOUSE ACTIVITY TIMER */
+
+	if (0 EQ timers[MUTIMER]) {
+
+		if (M_state)
+			if (MouseFL(M_FL_CT))
+				M_error = M_FLUSH;
+
+		M_state = 0;
+		MouseRT(MATIME);
+
+#if	DEBUGMS
+	if (debugms > 1)
+		printf("MRESET\n");
+#endif
+	}
+
+/* 
+
+*/
+	/* UPDATE THE CURSOR TIMERS */
+
+	if (cvwait LE 0) {	/* reset vertical timer */
+
+		cvwait  = ncvwait;
+		ncvwait = cvtime;
+
+		oldi = setipl(TIM_DI);
+		timers[TYTIMER] = cvwait;
+		setipl(oldi);
+	}
+
+
+	if (chwait LE 0) {	/* reset horizontal timer */
+
+		chwait  = nchwait;
+		nchwait = chtime;
+
+		oldi = setipl(TIM_DI);
+		timers[TXTIMER] = chwait;
+		setipl(oldi);
+	}
+/* 
+
+*/
+	/* PROCESS THE SCROLL WHEEL */
+
+	if (0 EQ timers[SWTIMER]) {		/* is it time ? */
+
+		if (swflag) {			/* SAMPLE THE SCROLL WHEEL */
+
+			swfifo[swfiin] = sigtab[59][0];
+
+			if (++swfiin GE NSWFIFO)
+				swfiin = 0;
+		}
+
+		if (swctrl) {			/* SCROLL ... */
+
+			swtemp   = swcount + swrate;
+			swcount  = swtemp & 0x0000FFFFL;
+			swtemp >>= 16;
+
+			if (swdir EQ D_FWD) {	/* ... FORWARD */
+
+				oldi = setipl(TIM_DI);
+				fc_val += swtemp;
+
+				if (fc_val GE 0x00FFFFFFL) {
+
+					swctrl = FALSE;
+					fc_val = 0x00FFFFFFL;
+				}
+
+				setipl(oldi);
+
+			} else {		/* ... BACKWARD */
+
+				oldi = setipl(TIM_DI);
+				fc_val -= swtemp;
+
+				if (fc_val < 0) {
+
+					swctrl = FALSE;
+					fc_val = 0L;
+				}
+
+				setipl(oldi);
+			}
+		}
+/* 
+
+*/
+		if (swflag OR swctrl) {		/* RESET THE SCROLL TIMER */
+
+			oldi = setipl(TIM_DI);
+			timers[SWTIMER] = swtime;
+			setipl(oldi);
+		}
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	tkinit() -- initialize trackball variables
+   =============================================================================
+*/
+
+tkinit()
+{
+	trkball = FALSE;		/* stop the trackball */
+	txflag  = FALSE;		/* ... */
+	tyflag  = FALSE;		/* ... */
+	tkctrl  = FALSE;		/* ... */
+	tkboth  = FALSE;		/* ... */
+
+	memsetw(txfifo, 0, NTKFIFO);	/* clear trackball X fifo */
+	txfiin = 0;			/* ... */
+
+	memsetw(tyfifo, 0, NTKFIFO);	/* clear trackball Y fifo */
+	tyfiin = 0;			/* ... */
+}
Index: ram/wscalc.c
===================================================================
--- ram/wscalc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/wscalc.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,141 @@
+/*
+   =============================================================================
+	wscalc.c -- MIDAS-VII waveshape editor harmonic functions
+	Version 9 -- 1988-09-09 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "hwdefs.h"
+#include "graphdef.h"
+#include "vsdd.h"
+#include "macros.h"
+
+#include "midas.h"
+#include "wsdsp.h"
+
+#define	WAVESMAX	1023
+#define	WAVESMIN	1023
+
+extern	short	curwhrm;
+
+extern	long	hwave[NUMWPCAL];
+
+extern	short	offsets[NUMWPCAL];
+extern	short	vmtab[NUMHARM];
+extern	short	wsbuf[NUMWPCAL];
+
+extern	long	vknm[NUMHARM][NUMWPCAL];
+
+#include "knmtab.h"		/* short knmtab[NUMHARM][NUMWPCAL]; */
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	adj() -- adjust the coefficients in vknm[wshar][] for a new value
+   =============================================================================
+*/
+
+adj(wshar)
+register short wshar;
+{
+	register short wspnt;
+	register long harval;
+	register short *kp;
+	register long *vp;
+
+	vp = &vknm[wshar][0];
+
+	harval = vmtab[wshar];
+
+	if (harval) {
+
+		kp = &knmtab[wshar][0];
+
+		for (wspnt = 0; wspnt < NUMWPCAL; wspnt++)
+			*vp++ = *kp++ * harval;
+
+	} else {
+
+		for (wspnt = 0; wspnt < NUMWPCAL; wspnt++)
+			*vp++ = 0;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wadj() -- adjust the coefficients for all harmonics
+   =============================================================================
+*/
+
+wadj()
+{
+	register short wshar;
+
+	for (wshar = 0; wshar < NUMHARM; wshar++)
+		adj(wshar);
+}
+
+/*
+   =============================================================================
+	clrwsa() -- clear waveshape table harmonic work areas
+   =============================================================================
+*/
+
+clrwsa()
+{
+	memsetw(offsets, 0, NUMWPCAL);
+	memsetw(vknm,    0, (NUMHARM * NUMWPCAL) << 1);
+	memsetw(vmtab,   0, NUMHARM);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wscalc() -- calculate a waveshape from its harmonics and offsets
+   =============================================================================
+*/
+
+wscalc()
+{
+	register short wspnt, wshar;
+	register long hfac, hmax, temp;
+
+	hmax = WAVESMIN;	/* set minimum scaling value */
+
+	for (wspnt = 0; wspnt < NUMWPCAL; wspnt++) {
+
+		temp = 0;	/* sum up the harmonics */
+
+		for (wshar = 0; wshar < NUMHARM; wshar++)
+			temp += vknm[wshar][wspnt];
+
+		/* add in the offsets */
+
+		hwave[wspnt] = (temp / 100) + offsets[wspnt];
+
+		/* adjust the maximum value seen */
+
+		if ((temp = abs(hwave[wspnt])) > hmax)
+			hmax = temp;
+	}
+
+	/* calculate the scale factor */
+
+	hfac = ((long)WAVESMAX << 16) / hmax;
+
+	/* scale the waveshape */
+
+	for (wspnt = 0; wspnt < NUMWPCAL; wspnt++)
+		wsbuf[wspnt] = (hwave[wspnt] * hfac) >> 16;
+}
Index: ram/wsdsp.c
===================================================================
--- ram/wsdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
+++ ram/wsdsp.c	(revision c65a0e28c4af16f9b2db6a1bd72e49e1d5951558)
@@ -0,0 +1,537 @@
+/*
+   =============================================================================
+	wsdsp.c -- MIDAS waveshape editor display driver
+	Version 35 -- 1988-09-09 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+#include "stddefs.h"
+#include "memory.h"
+
+#include "fpu.h"
+#include "hwdefs.h"
+#include "vsdd.h"
+#include "vsddsw.h"
+#include "vsddvars.h"
+#include "graphdef.h"
+#include "charset.h"
+#include "fields.h"
+
+#include "midas.h"
+#include "instdsp.h"
+#include "wsdsp.h"
+
+/* things defined elsewhere */
+
+extern	unsigned	exp_c();
+
+extern	int	(*point)();
+
+extern	unsigned	*obj0;
+
+extern	char	bfs[];
+
+extern	char	*wdbxlb0[];
+extern	char	*wdbxlb1[];
+
+extern	short	wdbox[][8];
+
+extern	struct	instdef	vbufs[];
+
+/* 
+
+*/
+
+extern	short	curinst;
+extern	short	curvce;
+extern	short	curwave;	/* current waveshape library slot */
+extern	short	curwdth;	/* current waveshape cursor width */
+extern	short	curwfnl;	/* current waveshape final value */
+extern	short	curwhrm;	/* current waveshape harmonic number */
+extern	short	curwhrv;	/* current waveshape harmonic value */
+extern	short	curwpnt;	/* current waveshape point number */
+extern	short	curwoff;	/* current waveshape offset value */
+extern	short	curwslt;	/* current waveshape instrument slot */
+extern	short	cxval;
+extern	short	cyval;
+extern	short	lstwoff;
+extern	short	lstwpnt;
+extern	short	stccol;
+extern	short	stcrow;
+extern	short	wpntsv;		/* waveshape point selection state variable */
+extern	short	wplast;
+extern	short	wvlast;
+
+extern	short	vmtab[NUMHARM];		/* harmonic table */
+extern	short	wsbuf[NUMWPCAL];	/* waveshape generation buffer */
+
+extern	long	vknm[NUMHARM][NUMWPCAL];	/* scaled harmonics */
+
+extern	unsigned *waveob;		/* waveshape display object pointer */
+
+extern	short	wsnmod[12][2];		/* waveshape number or data modified */
+
+extern	struct	wstbl	wslib[NUMWAVS];	/* waveshape library */
+
+extern	struct	octent	*wdoct;		/* object control table pointer */
+
+/* forward references */
+
+short	wdpoint();
+
+/* 
+
+*/
+
+short	wavpal[16][3] = {	/* waveshape display color palette */
+
+	{0, 0, 0},	/* 0 */
+	{3, 3, 3},	/* 1 */
+	{2, 2, 2},	/* 2 */
+	{0, 1, 1},	/* 3 (was 0, 1, 0) */
+	{1, 0, 1},	/* 4 */
+	{0, 1, 1},	/* 5 (was 0, 1, 0) */
+	{2, 1, 2},	/* 6 */
+	{0, 3, 0},	/* 7 */
+	{2, 0, 0},	/* 8 */
+	{2, 0, 2},	/* 9 */
+	{0, 0, 0},	/* 10 */
+	{2, 3, 3},	/* 11 */
+	{3, 3, 0},	/* 12 */
+	{3, 0, 0},	/* 13 */
+	{0, 0, 1},	/* 14 (was 0, 0, 2) */
+	{0, 0, 3}	/* 15 */
+};
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	advwcur() -- advance the waveshape display text cursor
+   =============================================================================
+*/
+
+advwcur()
+{
+	register short newcol;
+
+	newcol = stccol + 1;
+
+	if (newcol LE cfetp->frcol)
+		itcpos(stcrow, newcol);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	hdraw(h) -- draw harmonic 'h' for the current waveshape
+   =============================================================================
+*/
+
+hdraw(hv, h)
+register short *hv;
+short h;
+{
+	register short  bc, bx, by, j;
+
+	bx = (h << 4) + 4;
+
+	if (hv[h] < 0) {
+
+		by = WBOFF - ((-hv[h] * WBSF1) / WBSF2);
+		bc = WBCN;
+
+	} else {
+
+		by = WBOFF - ((hv[h] * WBSF1) / WBSF2);
+		bc = WBCP;
+	}
+
+	for (j = 0; j < 8; j++) {
+
+		lseg(bx, WBOFF, bx, by, bc);
+		++bx;
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	dsws() -- display the current waveshape
+   =============================================================================
+*/
+
+dsws(how)
+short how;
+{
+	register struct instdef *ip;
+	register short *fv, *hv, *ov;
+	register short i;
+	short cx;
+
+	cx = exp_c(wdbox[0][0]);
+
+	ip = &vbufs[curvce];
+	fv = curwslt ? &ip->idhwvbf : &ip->idhwvaf;
+	ov = curwslt ? &ip->idhwvbo : &ip->idhwvao;
+	hv = curwslt ? &ip->idhwvbh : &ip->idhwvah;
+
+	point = wdpoint;
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	if (how)
+		vbfill4(waveob, 128, wdbox[0][0], wdbox[0][1],
+			wdbox[0][2], wdbox[0][3], cx);
+
+	lseg(1, 133, 510, 133, WZBC);		/* draw the zero line and ... */
+	lseg(1, (WPOFF << 1), 510, (WPOFF << 1), WZBC);	/* ... bottom limit */
+
+	for (i = 0; i < NUMHARM; i++)		/* draw the harmonics */
+		hdraw(hv, i);
+
+	for (i = 0; i < NUMWPNT; i++) {		/* draw the values */
+
+		/* offset values */
+
+		wdpoint(((2 * i) + 2),
+			(WPOFF - (((ov[i] >> 5) * WPSF1) / WPSF2)), WOVC);
+
+		/* final values */
+
+		wdpoint(((2 * i) + 2),
+			(WPOFF - (((fv[i] >> 5) * WPSF1) / WPSF2)), WFVC);
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdswin() -- display a window
+   =============================================================================
+*/
+
+wdswin(n)
+register short n;
+{
+	register short cx, wval;
+	register char wsgn;
+
+	cx = wdbox[n][5];
+	cx |= cx << 4;
+	cx |= cx << 8;
+
+	/* first, fill the box with the background color */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vbfill4(waveob, 128, wdbox[n][0], wdbox[n][1], wdbox[n][2],
+		wdbox[n][3], cx);
+
+	/* put in the box label */
+
+	tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6], wdbox[n][7],
+		wdbxlb0[n], 14);
+
+	tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1, wdbox[n][7],
+		wdbxlb1[n], 14);
+
+/* 
+
+*/
+	switch (n) {	/* final text - overlays above stuff */
+
+	case 0:		/* points and bars */
+
+		dsws(0);
+		return;
+
+	case 2:		/* waveshape - voice - instrument - slot */
+
+		sprintf(bfs, "%02d", curwave + 1);
+		tsplot4(waveob, 64,
+			exp_c(wsnmod[curvce][curwslt] ? WS_CHGC : wdbox[n][4]),
+			wdbox[n][6], wdbox[n][7] + WAVE_OFF, bfs, 14);
+
+		sprintf(bfs, "%02d", curvce + 1);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6],
+			wdbox[n][7] + WVCE_OFF, bfs, 14);
+
+		sprintf(bfs, "%02d", curinst);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+			wdbox[n][7] + WINS_OFF, bfs, 14);
+
+		sprintf(bfs, "%c", curwslt + 'A');
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+			wdbox[n][7] + WSLT_OFF, bfs, 14);
+
+		return;
+
+/* 
+
+*/
+	case 4:		/* point - offset - width - final */
+
+		sprintf(bfs, "%03d", curwpnt);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6],
+			wdbox[n][7] + WPNT_OFF, bfs, 14);
+
+		if (curwoff < 0) {
+
+			wval = - curwoff;
+			wsgn = '-';
+
+		} else {
+
+			wval = curwoff;
+			wsgn = '+';
+		}
+
+		sprintf(bfs, "%c%04d", wsgn, wval);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6],
+			wdbox[n][7] + WOFF_OFF, bfs, 14);
+
+		if (curwdth EQ NUMWIDS) {
+
+			tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+				wdbox[n][7], "Interp", 14);
+
+		} else {
+
+			tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+				wdbox[n][7], "Width", 14);
+
+			sprintf(bfs, "%01d", curwdth);
+			tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+				wdbox[n][7] + WDTH_OFF, bfs, 14);
+		}
+
+		if (curwfnl < 0) {
+
+			wval = - curwfnl;
+			wsgn = '-';
+
+		} else {
+
+			wval = curwfnl;
+			wsgn = '+';
+		}
+
+		sprintf(bfs, "%c%04d", wsgn, wval);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+			wdbox[n][7] + WFNL_OFF, bfs, 14);
+
+		return;
+/* 
+
+*/
+	case 5:		/* harmonic - value */
+
+		sprintf(bfs, "%02d", curwhrm + 1);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6],
+			wdbox[n][7] + WHRM_OFF, bfs, 14);
+
+		if (curwhrv < 0) {
+
+			wval = - curwhrv;
+			wsgn = '-';
+
+		} else {
+
+			wval = curwhrv;
+			wsgn = '+';
+		}
+
+		sprintf(bfs, "%c%03d", wsgn, wval);
+		tsplot4(waveob, 64, wdbox[n][4], wdbox[n][6] + 1,
+			wdbox[n][7] + WHRV_OFF, bfs, 14);
+
+		return;
+
+	}
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wwins() -- display all waveshape editor windows
+   =============================================================================
+*/
+
+wwins()
+{
+	register short i;
+
+	for (i = 0; i < 6; i++)
+		wdswin(i);
+}
+
+/*
+   =============================================================================
+	wdpoint() -- plot a point for the lseg function
+   =============================================================================
+*/
+
+wdpoint(x, y, pen)
+short x, y, pen;
+{
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	vputp(wdoct, x, y, pen);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wdbord() -- draw the border for the waveshape display
+   =============================================================================
+*/
+
+wdbord()
+{
+	point = wdpoint;
+
+	lseg(  0,   0, 511,   0, WBORD);	/* outer border */
+	lseg(511,   0, 511, 349, WBORD);
+	lseg(511, 349,   0, 349, WBORD);
+	lseg(  0, 349,   0,   0, WBORD);
+
+	lseg(  0, 308, 511, 308, WBORD);	/* windows - H lines */
+	lseg(511, 321,   0, 321, WBORD);
+
+	lseg(175, 322, 175, 349, WBORD);	/* windows - V lines */
+	lseg(231, 322, 231, 349, WBORD);
+	lseg(399, 322, 399, 349, WBORD);
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	clrws() -- initialize waveshape to null values
+   =============================================================================
+*/
+
+clrws()
+{
+	register struct instdef *ip;
+
+	ip = &vbufs[curvce];
+
+	if (curwslt) {
+
+		memsetw(ip->idhwvbh, 0, NUMHARM);
+		memsetw(ip->idhwvbo, 0, NUMWPNT);
+		memsetw(ip->idhwvbf, 0, NUMWPNT);
+
+	} else {
+
+		memsetw(ip->idhwvah, 0, NUMHARM);
+		memsetw(ip->idhwvao, 0, NUMWPNT);
+		memsetw(ip->idhwvaf, 0, NUMWPNT);
+	}
+
+	clrwsa();
+
+	lstwpnt = wplast  = curwpnt;
+
+	lstwoff = wvlast  = curwfnl = curwoff = 0;
+
+	curwhrv = 0;
+
+	updfpu();				/* update the FPU */
+	wsnmod[curvce][curwslt] = TRUE;		/* tag WS as modified */
+}
+
+/* 
+
+*/
+
+/*
+   =============================================================================
+	iniwslb() -- initialize waveshape library
+   =============================================================================
+*/
+
+iniwslb()
+{
+	register short i, j;
+
+	memsetw(wsnmod, FALSE, (sizeof wsnmod) / 2);
+
+	for (i = 0; i < NUMWAVS; i++) {
+
+		for (j = 0; j < NUMWPNT; j++) {
+
+			wslib[i].final[j]  = ((j + 1) << 8) ^ 0x8000;
+			wslib[i].offset[j] = ((j + 1) << 8) ^ 0x8000;
+		}
+
+		memsetw(wslib[i].harmon, 0, NUMHARM);	/* zero harmonics */
+	}
+}
+			
+/* 
+
+*/
+
+/*
+   =============================================================================
+	wsdsp() -- put up the waveshape display
+   =============================================================================
+*/
+
+wsdsp()
+{
+	waveob = &v_score[0];		/* setup object pointer */
+	obj0   = &v_curs0[0];		/* setup cursor object pointer */
+	wdoct  = &v_obtab[WAVEOBJ];	/* setup object control table pointer */
+
+	wpntsv = 0;			/* point selection state = unselected */
+	newws();			/* set editing variables */
+
+	dswap();			/* initialize display */
+
+	if (v_regs[5] & 0x0180)
+		vbank(0);
+
+	memsetw(waveob, 0, 32767);
+	memsetw(waveob+32767L, 0, 12033);
+
+	SetObj(WAVEOBJ, 0, 0, waveob, 512, 350,     0,     0,  WAVEFL, -1);
+	SetObj(      0, 0, 1,   obj0,  16,  16, WCURX, WCURY, OBFL_00, -1);
+
+	arcurs(WDCURS);			/* setup arrow cursor object */
+	itcini(WDCURS);			/* setup text cursor object */
+
+	wdbord();			/* draw the border */
+	wwins();
+
+	SetPri(WAVEOBJ, WAVEPRI);
+	SetPri(0, GCPRI);
+	setgc(WCURX, WCURY);		/* display the graphic cursor */
+
+	vsndpal(wavpal);		/* send the palette */
+}
