[comp.sources.misc] v06i107: glib part 6 of 15

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

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

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 15)."
# Contents:  PORTING k1multi.mnu pc-ints.asm pc-mach.c
# Wrapped by lee@uhccux on Sun May  7 00:40:13 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'PORTING' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'PORTING'\"
else
echo shar: Extracting \"'PORTING'\" \(12157 characters\)
sed "s/^X//" >'PORTING' <<'END_OF_FILE'
X$Id: PORTING,v 1.6 89/05/06 17:13:07 lee Exp $
X[Lee:]
X
XThe C source code for the various synth modules is generated by
Xa program 'menutoc'.  Although C source for 'menutoc' is included,
Xrevising the program would require flex, the freely distributed "fast
Xlex" to compile.  But if you happen not to have flex, lex will serve --
Xsee the note in the Makefile and notes at the beginning of file
Xmakemenu.l.
X
X	---------------------------------
X[Kesti:]
X
XIn order to adapt it to the D-10's rather large data set, I have used glib's
Xability to service multiple synths to instead service sub-sections of a single
XD-10.  These subsections are:
X
X	Performance mode patches
X	Multi-timbral mode timbres
X
X	Tone waveform generators
X	Tone time variant filters
X	Tone time variant amplifiers
X
X	Rhythm setup
X	Rhythm patterns
X	Rhythm track
X
XBecause the memory requirement of a single program to service this much data
Xis large enough to be cumbersome, I have broken the subsections into three
Xseparate programs.  These are d10patch, d10tone, and d10drum.
X
XThe tone services also require a separate program because, unlike all other
Xservices, they must operate on a single common data set.  This required
Xchanges to the data memory allocation and other functions in glib.c.  When
Xcompiling d10tone, be sure to #define SINGLEDATA in glib.c to enable these
Xchanges.
X
XI believe that I have maintained glib's ability to be compiled for Un*x
X(using SysV curses), DOS, and the Atari ST.  The sources supplied have
Xbeen succesfully compiled and run on an AT&T 3b1, running v3.51 software;
Xand an AT&T 6300 (with a V30 in the cpu socket), running AT&T's version of
XDOS v3.20.  Borland Turbo C v1.0 was used to produce the executables and the
Xmachine was fitted with a CMS-401 interface.
X
XThe Makefile provided was used on the 3b1, and produces a single executable
Xnamed glib that combines all services, but does not tie the tone data
Xtogether as discussed above.  This is presumably no problem, as the Un*x
Xversion is intended to be for demo purposes.  If your Un*x machine has a
Xmidi interface, I'd like hear from you!
X
XThe Turbo C project files (*.prj) are used by the integrated environment to
Xproduce glib.exe, d10patch.exe, d10tone.exe, and d10drum.exe.  Be sure to
Xuse the large memory model.  It is not recommended that glib.exe be used, as
Xit requires almost all the available memory of a 640K machine, and again,
Xwould not tie the tone data together (SINGLEDATA should not be #defined
Xwhen compiling for glib.exe.).
X
X[Lee:]
X
XI did not include the .prj files mentioned above.  So many files
Xalready!  But below are the contents of those files.  The file machdep.c
Xis a copy of pc-mach.c (and pc-mach.h should be copied to machdep.h);
Xthe d10*.c files except d10ton.c) must be constructed from the
Xcorresponding d10*.mnu files by the menutoc program; and the files
Xlistdrum.c, listpat.c, and listton.c are the same as file list.c, but
Xwith '#defines' removed for the unused modules.  That is to say, for the
XD10 '#defines', keep only
X	#define D10urp
X	#define D10rsu
X	#define D10tra
Xfor listdrum.c, keep only
X	#define D10pat
X	#define D10tim
Xfor listpat.c, and keep only
X	#define D10wfg
X	#define D10tvf
X	#define D10tva
Xfor listton.c.
X::::::::::::::
Xcontents of file d10drum.prj
X::::::::::::::
Xd10urp.c
Xd10rsu.c
Xd10tra.c
Xglib.c
Xlistdrum.c
Xvis.c
Xmachdep.c
X::::::::::::::
Xcontents of file d10patch.prj
X::::::::::::::
Xd10pat.c
Xd10tim.c
Xglib.c
Xlistpat.c
Xvis.c
Xmachdep.c
X::::::::::::::
Xcontents of file d10tone.prj
X::::::::::::::
Xd10ton.c
Xd10wfg.c
Xd10tvf.c
Xd10tva.c
Xglib.c
Xlisttone.c
Xvis.c
Xmachdep.c
X::::::::::::::
Xcontents of file glib.prj
X::::::::::::::
Xd10pat.c
Xd10tim.c
Xd10wfg.c
Xd10ton.c
Xd10tvf.c
Xd10tva.c
Xd10urp.c
Xd10rsu.c
Xd10tra.c
Xglib.c
Xlist.c
Xvis.c
Xmachdep.c
X----------------------
X
X
X[Thompson:]
X
XCompiling
X---------
Xmachdep.c and machdep.h are machine-dependent parts.  The *-mach.h and
X*-mach.c files are the versions of these files for different machines,
Xe.g. unix-mach.[ch] is for UNIX, st-mach.[ch] is for the Atari ST.
XCopy the proper files to machdep.c and machdep.h before compiling
Xfor a particular machine.   For example, on UNIX, do the following:
X
X	cp unix-mach.c machdep.c
X	cp unix-mach.h machdep.h
X	make glib
X
XThe contents of list.c control which synths are supported; modify
Xthe defines at the beginning of that file appropriately.  When
Xcompiling, you need to include glib.c and the appropriate synth
Xfiles (e.g. if you define DW8000 in list.c, then you need to compile
Xwith dw8000.c).  A single version of glib can support as many synths
Xas you want, although some compilers may have size limitations or
Xoverlay schemes that get in the way.
X
X
XHacking glib - Internals
X------------------------
XThe program is written so that support for a new synth can be added by
Xadding an entry to the array in list.c, describing the various attributes
Xof the synthesizer and the C functions to be called to control it.  And, of
Xcourse, you have to write those C functions.  Adding a new synth, for a
Xreasonable C programmer, might be described as mostly straightforward but
Xtedious.  People other than the original author HAVE done it, with no help.
XGlib allows you to re-use the front-end interface of the librarian and
Xeditor, but it does not relieve you of having to write C code which
Xinteracts with the synth (which, depending on the synth, can of course be
Xeasy or maddening) and with the raw data formats.  Naturally, using one of
Xthe existing synth files as an example of how to do things is the best way
Xto start on a new one.
X
XThe 'E' array in list.c has the following structure:
X
Xstruct editinfo {
X	char *ed_name;		/* Synth name */
X	struct paraminfo *ed_params;	/* list of parameters */
X	struct labelinfo *ed_labels;	/* screen labels in edit mode */
X	int ed_nvoices;		/* number of voices */
X	int ed_vsize;		/* size of each voice data, in bytes */
X	int ed_nsize;		/* name size */
X	int ed_dataid;		/* data ID */
X	int (*ed_din)();	/* copy voice data into paraminfo array */
X	int (*ed_dout)();	/* copy voice data out of paraminfo array */
X	int (*ed_sedit)();	/* send 1 voice to synth edit buffer */
X	int (*ed_sone)();	/* send 1 voice to a synth (permanent) patch*/
X	int (*ed_sbulk)();	/* send bulk voice data */
X	int (*ed_gbulk)();	/* get bulk voice data */
X	char *(*ed_nof)();	/* get name of a voice out of data */
X	int (*ed_snof)();	/* set name of a voice in data */
X	char *(*ed_numof)();	/* convert voice number to on-screen text */
X	int (*ed_cvtnum)();	/* convert visable voice number to std. format */
X};
X
XIn glib, there are several relatively independent representations of the
Xsynth voice data.  First, there is the data that is stored in the
Xlibrary and synth banks (ie.  the data used and manipulated via the
Xlibrarian screen).  This is the format of the data that is written to
Xand read from files (a single byte, given as 'ed_dataid' above, is added
Xto the beginning of the file, to identify it).  The size of a single
Xvoice in this data is 'ed_vsize'.  The number of voices in a bank is
X'ed_nvoices', so the amount of space taken up by a library bank is
Xed_vsize * ed_nvoices.
X
XWhen a voice is edited, the voice data is copied into the parameter
Xarray (see below), in p_val.  The 'ed_din' function is called to do this.
XAfter a voice is edited, 'ed_dout' takes the updated parameter values 
Xand puts them back into the original data format.  Note that this means
Xthat the bytes in the 'raw' voice data and the values in the parameter
Xarray (ie. the values manipulated by the editor) need not be the same.
XThere are utility functions 'getval' and 'setval' which should be used
Xfor getting and setting the values in the parameter array.  See dx100.c
Xfor usage.
X
XThe ed_sedit, ed_sone, ed_sbulk, and ed_gbulk functions are called to
Xsend voices to and get voices from the synthesizer.  Only one of ed_sone
Xand ed_sbulk need be defined, although ed_sone should be preferred.
X(I had trouble getting the DX100 to accept a single permanent voice
Xchange, so it always does a bulk voice transfer.)  The data passed to
Xthese functions is in the library bank format.  The ed_gbulk function is
Xoptional, so that write-only MIDI devices (like the DEP-5) are allowed.
X
XThe ed_nof function is called to pull the voice name out of the raw
Xvoice data (as stored in the library banks), and it should return a
XC string containing the name.  The ed_snof function is called to
Xstick a voice name into the raw voice data.  Note that the 'raw'
Xlibrary bank voice data does NOT have to match the data that is
Xreally sent to the synthesizer (by the ed_sedit and ed_sone functions).
XFor example, the DEP-5 does not have names as part of the voice data,
Xbut that does not prevent glib from maintaining and storing (in the files)
Xvoice names.  This holds for the DW-8000 as well.
X
XThe ed_numof function is called to convert the voice number to the
Xtext that is displayed on the librarian screen.  This can handle
Xthe odd numbering convention of the DW-8000.  If ed_numof==NULL, the
Xnumber is used as-is.  Otherwise, ed_numof is called with the voice
Xnumber MINUS 1 (i.e. 0-based); ed_numof should return a string
Xcontaining the desired display.  Likewise, the ed_cvtnum function is
Xused to convert user input from an odd numbering system to the standard
Xsequential internal representation (0 to whatever).
X
XThe editor screen is controlled by two arrays, ed_labels and ed_params.
Xed_labels contains arbitrary screen labels, in the following structure:
X
Xstruct labelinfo {
X	int l_row;	/* 0-based */
X	int l_col;	/* 0-based */
X	char *l_text;
X};
X
XThe ed_params array is used to specify the parameters that the user can peruse
Xand change in the edit screen, and looks like this (one for each parameter):
X
Xstruct paraminfo {
X	char *p_name;		/* the parameter name */
X	char *p_label;		/* on-screen label (possibly NULL) */
X	int p_lrow;		/* position for printing label */
X	int p_lcol;
X	int p_vrow;		/* position for printing value */
X	int p_vcol;
X	char *((*p_tovis)());	/* function converts value to on-screen text*/
X	int p_min;		/* minimum parameter value */
X	int p_max;		/* maximum parameter value */
X	int p_val;		/* parameter value */
X	int p_flags;		/* flag to enable/disable parameter */
X};
X
XThe editor calls p_tovis with a parameter value, and expects that function
Xto pass back a string which contains what should be displayed on the
Xscreen for that value.  Often, this is just an 'sprintf' of the value,
Xor perhaps the value offset by something.  Or, it could be some text
Xthat represents the value (e.g. "on" for 1 and "off" for 0).  Or, it could
Xbe something more interesting, e.g. a picture of the voice algorithm.
XThe parameter value strings can make use of cursor motion, by including the
Xsequences ~d,~u,~l,~r to go down,up,left,right.  The dx100 and dep5 editors
Xuse this to handle the display of the algorithm drawings.
X
XA parameter can be 'disabled' by setting p_flags to non-zero.  The p_tovis
Xfunction can set the external variable 'Redraw' to 1 if it wants to force
Xthe entire editor screen to be redrawn (e.g. after a parameter has been
Xdisabled).
X
XSupport for a mouse has been added, although it is currently disabled
Xfor the Atari, since I was having various hassles getting it under control.
XIt did work, but had various quirks.
X
XMouse support for the Amiga was added, and appears to work after fixing
Xa few problems in glib.c, so it may be possible to enable the Atari mouse
Xsupport now.
X
X                             ...Tim Thompson...twitch!glimmer!tjt...
X
X[notes from Ed Wilts, ewilts%Janus.MtRoyal.AB.CA@Ucnet.UCalgary.CA,
X on the Amiga version for the D-10]
X
X...  The problem I had in getting it
Xgoing was more in the execution than the compilation.  Without a sufficiently
Xlarge stack, you will get highly intermittent results, and depending on the
Xstate of the moon and the time of day, gurus.  I was getting frequent timeouts
Xreading from the D-10 and sometimes the data would be all read but not in the
Xproper order.  I was getting quite frustrated for a while...
X
XMy stack was originally 4000 - the default.  I boosted it to 8192 with no
Xgreater results, and finally went to 32768 and now it seems to work.  At least
XI can read from the D-10 consistently. ...
END_OF_FILE
if test 12157 -ne `wc -c <'PORTING'`; then
    echo shar: \"'PORTING'\" unpacked with wrong size!
fi
# end of 'PORTING'
fi
if test -f 'k1multi.mnu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'k1multi.mnu'\"
else
echo shar: Extracting \"'k1multi.mnu'\" \(10993 characters\)
sed "s/^X//" >'k1multi.mnu' <<'END_OF_FILE'
X/* $Id: k1multi.mnu,v 1.6 89/05/06 17:13:27 lee Exp $
X * GLIB - a Generic LIBrarian and editor for synths
X *
X * K1 Patch Librarian
X *
X * Adapted for K1 from Kesti's D10 version by Greg Lee
X * $Log:	k1multi.mnu,v $
X * Revision 1.6  89/05/06  17:13:27  lee
X * rel. to comp.sources.misc
X * 
X */
X
X#include "glib.h"
X#include "k1vis.h"
X
X#define K1MULTISIZE 75
X#define K1SINGLESIZE 87
X#define RESERVESIZE 0
X
Xextern char sngnames[64][11];
X
X/* This array contains arbitrary screen labels */
Xstruct labelinfo Lk1m[] = {
X
X#MENU for multi
X			volume %
X
X
X
X
X   A.........   B................  C.............  D.....................
X   single       zn lo zn hi vel sw poly mode rcvch trnsps tune level output
X |-------------|-----|-----|------|----|----|-----|------|----|-----|------|
X
X1  %	          %     %     %     %    %     %     %     %     %     %
X2  %	          %     %     %     %    %     %     %     %     %     %
X3  %	          %     %     %     %    %     %     %     %     %     %
X4  %	          %     %     %     %    %     %     %     %     %     %
X5  %	          %     %     %     %    %     %     %     %     %     %
X6  %	          %     %     %     %    %     %     %     %     %     %
X7  %	          %     %     %     %    %     %     %     %     %     %
X8  %	          %     %     %     %    %     %     %     %     %     %
X
X
X
X
X
X Press SPACE BAR to sound note %   at volume %   for duration %  on channel % .
X#END
X
X-1,-1,NULL
X};
X
Xchar *vismltnum();
X
Xstruct paraminfo Pk1m[] = {
X
X/*NAME		TYPE		POS	MAX	OFFSET	MASK	SHIFT	ADHOC*/
X
X#O volume	pnum		%%	99	10
X
X#O single1	mltnum		%%	63	11
X#O zonelo1	cpitch		%%	127	19
X#O zonehi1	cpitch		%%	127	27
X#O velosw1	velosw		%%	2	43	0x30	4
X#O poly1	poly		%%	9	35	0x0F
X#O modem1	mode		%%	2	35	0x40	6	*1
X/* 2nd bit below goes above */
X#O moden1	num		--	1	43	0x40	6	*2
X#O rcvch1	pnum		%%	15	43	0x0F
X#O trnsps1	keyshift	%%	48	51
X#O tune1	finetune	%%	100	59
X#O level1	num		%%	100	67
X#O output1	pan		%%	2	35	0x30	4
X
X#O single2	mltnum		%%	63	12
X#O zonelo2	cpitch		%%	127	20
X#O zonehi2	cpitch		%%	127	28
X#O velosw2	velosw		%%	2	44	0x30	4
X#O poly2	poly		%%	9	36	0x0F
X#O modem2	mode		%%	2	36	0x40	6	*1
X#O moden2	num		--	1	44	0x40	6	*2
X#O rcvch2	pnum		%%	15	44	0x0F
X#O trnsps2	keyshift	%%	48	52
X#O tune2	finetune	%%	100	60
X#O level2	num		%%	100	68
X#O output2	pan		%%	2	36	0x30	4
X
X#O single3	mltnum		%%	63	13
X#O zonelo3	cpitch		%%	127	21
X#O zonehi3	cpitch		%%	127	29
X#O velosw3	velosw		%%	2	45	0x30	4
X#O poly3	poly		%%	9	37	0x0F
X#O modem3	mode		%%	2	37	0x40	6	*1
X#O moden3	num		--	1	45	0x40	6	*2
X#O rcvch3	pnum		%%	15	45	0x0F
X#O trnsps3	keyshift	%%	48	53
X#O tune3	finetune	%%	100	61
X#O level3	num		%%	100	69
X#O output3	pan		%%	2	37	0x30	4
X
X#O single4	mltnum		%%	63	14
X#O zonelo4	cpitch		%%	127	22
X#O zonehi4	cpitch		%%	127	30
X#O velosw4	velosw		%%	2	46	0x30	4
X#O poly4	poly		%%	9	38	0x0F
X#O modem4	mode		%%	2	38	0x40	6	*1
X#O moden4	num		--	1	46	0x40	6	*2
X#O rcvch4	pnum		%%	15	46	0x0F
X#O trnsps4	keyshift	%%	48	54
X#O tune4	finetune	%%	100	62
X#O level4	num		%%	100	70
X#O output4	pan		%%	2	38	0x30	4
X
X#O single5	mltnum		%%	63	15
X#O zonelo5	cpitch		%%	127	23
X#O zonehi5	cpitch		%%	127	31
X#O velosw5	velosw		%%	2	47	0x30	4
X#O poly5	poly		%%	9	39	0x0F
X#O modem5	mode		%%	2	39	0x40	6	*1
X#O moden5	num		--	1	47	0x40	6	*2
X#O rcvch5	pnum		%%	15	47	0x0F
X#O trnsps5	keyshift	%%	48	55
X#O tune5	finetune	%%	100	63
X#O level5	num		%%	100	71
X#O output5	pan		%%	2	39	0x30	4
X
X#O single6	mltnum		%%	63	16
X#O zonelo6	cpitch		%%	127	24
X#O zonehi6	cpitch		%%	127	32
X#O velosw6	velosw		%%	2	48	0x30	4
X#O poly6	poly		%%	9	40	0x0F
X#O modem6	mode		%%	2	40	0x40	6	*1
X#O moden6	num		--	1	48	0x40	6	*2
X#O rcvch6	pnum		%%	15	48	0x0F
X#O trnsps6	keyshift	%%	48	56
X#O tune6	finetune	%%	100	64
X#O level6	num		%%	100	72
X#O output6	pan		%%	2	40	0x30	4
X
X#O single7	mltnum		%%	63	17
X#O zonelo7	cpitch		%%	127	25
X#O zonehi7	cpitch		%%	127	33
X#O velosw7	velosw		%%	2	49	0x30	4
X#O poly7	poly		%%	9	41	0x0F
X#O modem7	mode		%%	2	41	0x40	6	*1
X#O moden7	num		--	1	49	0x40	6	*2
X#O rcvch7	pnum		%%	15	49	0x0F
X#O trnsps7	keyshift	%%	48	57
X#O tune7	finetune	%%	100	65
X#O level7	num		%%	100	73
X#O output7	pan		%%	2	41	0x30	4
X
X#O single8	mltnum		%%	63	18
X#O zonelo8	cpitch		%%	127	26
X#O zonehi8	cpitch		%%	127	34
X#O velosw8	velosw		%%	2	50	0x30	4
X#O poly8	poly		%%	9	42	0x0F
X#O modem8	mode		%%	2	42	0x40	6	*1
X#O moden8	num		--	1	50	0x40	6	*2
X#O rcvch8	pnum		%%	15	50	0x0F
X#O trnsps8	keyshift	%%	48	58
X#O tune8	finetune	%%	100	66
X#O level8	num		%%	100	74
X#O output8	pan		%%	2	42	0x30	4
X
X"autopitch",	NULL,	-1,-1, %%, visnum, 		0, 127, 60, 0,
X"autovol",	NULL,	-1,-1, %%, visnum, 		0, 127, 63, 0,
X"autodur",	NULL,	-1,-1, %%, visnum, 		1,  20,  5, 0,
X"autochan",	NULL,	-1,-1, %%, visnum, 		1,  16,  1, 0,
X
XNULL,		NULL,	-1,-1, -1, -1, visnum, 		0,   0, 0, 0
X};
X
X/*
X * k1mnum
X *
X * Convert a voice number (0 to 127) to the string displayed in the
X * librarian (ie. A1 to D8 for multi, to d8 for singles).
X */
X
Xchar *
Xk1mnum(n)
X{
X	static char v[4];
X
X	if ( n < 0 || n > 63 )
X		return("???");
X
X	v[0] = 'A' + (n >> 3);
X	if (v[0] > 'D') v[0] += ' ' - 4;
X
X	(void)sprintf(v+1, "%d", (n % 8) + 1);
X
X	return(v);
X}
X
Xchar *
Xvismltnum(n)
X{	static char numnam[15];
X
X	strcpy(numnam, k1mnum(n));
X	if (sngnames[n][0] > ' ') {
X		strcat(numnam, " ");
X		strcat(numnam, sngnames[n]);
X	}
X	return(numnam);
X}
X
X/*
X * k1nummlt
X *
X * Convert a display-style voice number (A1 to d8) to internal
X * format (0 to 127).
X */
X
Xk1nummlt(s)
Xchar *s;
X{
X
X	int ld, rd;
X
X	rd = s[0] - 'A';
X	if (rd > 3) rd -= ' ' - 4;
X	if (rd < 0 || rd > 7) return(-1);
X
X	(void)sscanf(s+1, "%d", &ld);
X	if (ld < 1 || ld > 8) return(-1);
X
X	return((rd << 3) + ld - 1);
X
X}
X
X/*
X * k1mdin
X *
X * Take library bank 'data' and stuff values in the P array, by using
X * the setval function.
X */
X
Xk1mdin(data)
Xchar *data;
X{
X	/* The first RESERVESIZE bytes are reserved (arbitrarily) for the voice name */
X#SETVAL
X}
X
X/*
X * k1mdout
X *
X * Take (possibly changed) parameters values out of the P array and
X * put them back into the library bank 'data'.
X */
X
Xk1mdout(data)
Xchar *data;
X{
X#GETVAL
X}
X
Xk1send1(function, voice)
X{
X	if (Nvoices == 32) voice += 64;
X
X	sendmidi(0xf0);
X	sendmidi(0x40);		/* Kawai id */
X	sendmidi(Channel - 1);	/* channel = 1 to 16 */
X	sendmidi(function);	/* function */
X	sendmidi(0x00);		/* group */
X	sendmidi(0x03);		/* machine id number of K1 */
X	sendmidi(0x00);		/* subcommand 1 = internal */
X	sendmidi(voice);	/* subcommand 2 = voice 1 */
X}
X
X/*
X * k1msedit
X *
X * Send a single voice to the edit buffer of the K1.  This will be whatever
X * voice is currently selected.
X * (So far as I know, one can't do this;  this is here pro forma. -- gl)
X */
X
Xk1msedit(data)
Xchar *data;
X{
X/*
X	int cksum;
X	int n, dumpsize;
X
X	k1send1(0x20, 0);
X	cksum = 0xa5;
X
X	if (Nvoices == 32) dumpsize = K1MULTISIZE;
X	else dumpsize = K1SINGLESIZE;
X
X	for(n = 0; n < dumpsize; n++) {
X		sendmidi(data[n] & 0x7f);
X		cksum += data[n] & 0x7f;
X	}
X	sendmidi(cksum & 0x7f);
X	sendmidi(EOX);
X*/
X}
X
X/*
X * k1mnof
X *
X * Return a pointer to the voice name buried in library bank data.
X */
Xchar *
Xk1mnof(data)
Xchar *data;
X{
X	static char currbuff[11];
X	char *p;
X	int m;
X
X	p = currbuff;
X	for ( m = 0 ; m < 10 ; m++ )
X		*p++ = data[m];
X	*p = '\0';
X	return(currbuff);
X}
X
X/*
X * k1msnof
X *
X * Set the voice name buried in data to name.
X */
Xk1msnof(data,name)
Xchar *data;
Xchar *name;
X{
X	char *p;
X	int m;
X
X	for ( p = name, m = 0 ; *p != '\0' && m < 10 ; p++, m++ )
X		data[m] = *p;
X	for ( ; m < 10 ; m++ )
X		data[m] = ' ';
X}
X
X/* k1msone - send a single voice to the K1 */
Xk1msone(iv, data)
Xint iv;
Xchar *data;
X{
X	int cksum;
X	int n, dumpsize;
X
X	k1send1(0x20, iv);
X	cksum = 0xa5;
X
X	if (Nvoices == 32) dumpsize = K1MULTISIZE;
X	else dumpsize = K1SINGLESIZE;
X
X	for(n = 0; n < dumpsize; n++) {
X		sendmidi(data[n] & 0x7f);
X		cksum += data[n] & 0x7f;
X	}
X	sendmidi(cksum & 0x7f);	/* checksum */
X	sendmidi(EOX);
X
X	return(0);
X}
X
X/* k1mgbulk - Request and read a bulk dump from the K1 */
Xk1mgbulk(data)
Xchar *data;
X{
X	static	char Buff[BUFSIZ];
X	int n, v, b2, ret = 1;
X	long begin, toolong;
X	int dumpsize;
X	
X	(void)sprintf(Buff,"\nA: ");
X	windstr(Buff);
X
X	if (Nvoices == 32) dumpsize = K1MULTISIZE;
X	else dumpsize = K1SINGLESIZE;
X
X	for(v = 0; v < Nvoices; v++) {
X
X		flushmidi();
X
X		if(v == 64) {
X			(void)sprintf(Buff,"\nB: ");
X			windstr(Buff);
X		}
X		if((((v > 63) ? (v - 64) : v) % 10) != 0) {
X			(void)sprintf(Buff, ".");
X		} else {
X			(void)sprintf(Buff,"%d", (((v > 63) ? (v - 64) : v) / 10));
X		}
X		windstr(Buff);
X
X	/* request the dump */
X		if (!synthinfileflag) {
X			k1send1(0, v);
X			sendmidi(EOX);
X		}
X	
X	/* set up timeout */
X		begin = milliclock();
X		toolong = begin + (1000 * TIMEOUT);
X	
X	/* read header */
X		for(n = 0; n < 8; ) {
X			if ( STATMIDI ) {
X				b2 = (getmidi() & 0xff);
X				/* burn active sensing and timing clock */
X				if((b2 != 0xfe) && (b2 != 0xf8))
X					n++;
X			} else {
X				if ( milliclock() > toolong ) {
X					Reason = "Timeout waiting for header";
X					goto getout;
X				}
X			}
X		}
X
X	/* read data */
X		for(n = 0; n < dumpsize; ) {
X			if ( STATMIDI ) {
X				b2 = (getmidi() & 0xff);
X				/* burn active sensing and timing clock */
X				if((b2 != 0xfe) && (b2 != 0xf8)) {
X					VOICEBYTE(data,v,n) = b2;
X					n++;
X				}
X			} else {
X				if ( milliclock() > toolong ) {
X					Reason = "Timeout reading data";
X					goto timeout;
X				}
X			}
X		}
X
X	timeout:
X		if ( n != dumpsize ) {
X			Reason = "Timeout reading data!";
X			goto getout;
X		}
X
X	/* read checksum */
X		for(n = 0; n < 1; ) {
X			if ( STATMIDI ) {
X				b2 = (getmidi() & 0xff);
X				/* burn active sensing and timing clock */
X				if((b2 != 0xfe) && (b2 != 0xf8))
X					n++;
X			} else {
X				if ( milliclock() > toolong ) {
X					Reason = "Timeout reading checksum";
X					goto getout;
X				}
X			}
X		}
X
X	/* read EOX */
X		for(n = 0; n < 1; ) {
X			if ( STATMIDI ) {
X				b2 = (getmidi() & 0xff);
X				/* burn active sensing and timing clock */
X				if((b2 != 0xfe) && (b2 != 0xf8))
X					if ( b2 != EOX ) {
X						(void)sprintf(Buff,"EOX not received (%X)\n", b2);
X						Reason = Buff;
X						goto getout;
X					}
X					n++;
X			} else {
X				if ( milliclock() > toolong ) {
X					Reason = "Timeout reading EOX";
X					goto getout;
X				}
X			}
X		}
X
X	} /* go back for another voice */
X
X	Reason = "";
X	ret = 0;	/* all's well */
X
Xgetout:
X	return(ret);
X}
X
X/* k1msbulk - send a bulk dump to the K1 */
Xk1msbulk(data)
Xchar *data;
X{
X	static char Buff[BUFSIZ];
X	int v, n, databyte, curoff, dumpsize;
X	int cksum;
X
X	(void)sprintf(Buff,"\nA: ");
X	windstr(Buff);
X
X	if (Nvoices == 32) dumpsize = K1MULTISIZE;
X	else dumpsize = K1SINGLESIZE;
X
X	curoff = 0;
X	for(v = 0; v < Nvoices ; v++) {
X		if(v == 64) {
X			(void)sprintf(Buff,"\nB: ");
X			windstr(Buff);
X		}
X		if((((v > 63) ? (v - 64) : v) % 10) != 0) {
X			(void)sprintf(Buff, ".");
X		} else {
X			(void)sprintf(Buff,"%d", (((v > 63) ? (v - 64) : v) / 10));
X		}
X
X		windstr(Buff);
X		k1send1(0x20, v);
X		cksum = 0xa5;
X
X		for(n = 0; n < dumpsize; n++) {
X			databyte = data[n + curoff] & 0x7f;
X			sendmidi(databyte);
X			cksum += databyte;
X		}
X		sendmidi(cksum & 0x7f);	/* checksum */
X		sendmidi(EOX);
X		curoff += Voicesize;
X	}
X	return(0);
X}
X
X/* end */
END_OF_FILE
if test 10993 -ne `wc -c <'k1multi.mnu'`; then
    echo shar: \"'k1multi.mnu'\" unpacked with wrong size!
fi
# end of 'k1multi.mnu'
fi
if test -f 'pc-ints.asm' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pc-ints.asm'\"
else
echo shar: Extracting \"'pc-ints.asm'\" \(12452 characters\)
sed "s/^X//" >'pc-ints.asm' <<'END_OF_FILE'
X@ab	equ 6		;use big model
X; $Id: pc-ints.asm,v 1.6 89/05/06 17:13:38 lee Exp $
X;
X; the following constants are hardware specific to the MPU401 & OP4000
X; MIDI interface controllers
X; $Log:	pc-ints.asm,v $
X; Revision 1.6  89/05/06  17:13:38  lee
X; rel. to comp.sources.misc
X; 
X; 
X;
XBASE_ADDRESS_MPU 	equ 330h
XSTATUS_PORT_MPU 	equ BASE_ADDRESS_MPU  + 1
XCOMMAND_PORT_MPU 	equ BASE_ADDRESS_MPU  + 1
XDATA_PORT_MPU 		equ BASE_ADDRESS_MPU  + 0
XTx_EMT 			equ 40h	;midi transmitter ready for more data
XRx_NEMT			equ 80h	;midi receiver has data ready
XMPU_INT			equ 2
XMPU_INT_MASK		equ 4
X;
X; the remaining constants are for the AT&T PC6300 and compatible PC's
X;
XTIMER_INT		equ 0
XTIMER_INT_MASK		equ 1
XHW_INT_MASK		equ MPU_INT_MASK OR TIMER_INT_MASK
XINT_CTLR_PORT		equ 20h	;port to send EOI command to
XINT_CTLR_IMR 		equ 21h	;port to mask interrupts
XEOI_CODE		equ 20h	;EOI command
XT_55MS	   equ	0000h		; 8253 value for 55 ms
XT_5MS	   equ	174dh		; 8253 value for 5 ms
XTIC_55MS   equ	11		; Number of timer tics to equal 55 ms
XPIT_MODE   equ	36h	; 8253 mode: 00 11 011 0 -> cntr0,LSB/MSB,mode 3,binary
XPIT_CNT0   equ	40h		; Counter 0 port for 8253 PIT
XPIT_CTRL   equ	43h		; Control port for 8253 PIT
XUSER_TMR   equ	1ch		; User Timer (55 ms) Int. Vector
X;
X
X;********************
X;**   macros       **
X;********************
X;
Xc_in	macro			;this macro sets up a stack frame
X    push	bp		;must save bp reg for 'c' progs
X    mov	bp, sp			;set up frame pointer
X    push di
X    push si			;save register vars
X    endm
X;
Xc_out	macro			;This macro cleans up for return to 'C'
X    pop si
X    pop di
X    mov sp, bp
X    pop	bp			;restore caller's frame pointer
X    cld				;clear direction flag 
X    ret				;and return
X    endm
X;
Xpush_all_regs	macro
X    push	es
X    push	ds
X    push	dx
X    push	cx
X    push	bx
X    push	si
X    push	di
X    push	ax
X    push	bp
X    endm
X;
Xpop_all_regs	macro
X    pop	bp
X    pop	ax
X    pop	di
X    pop	si
X    pop	bx
X    pop	cx
X    pop	dx
X    pop	ds
X    pop	es
X    endm
X;
Xenable_IMR	macro num		;this macro clears (enables)
X					;interrupts in the interrupt mask reg
X    in		al, INT_CTLR_IMR	;read in current int mask
X    and		al, 0ffh - num		;clear the requested IMR bit
X    out		INT_CTLR_IMR, al	;and write it back out
X    endm
X;
Xdisable_IMR	macro num		;disable interrupts in the IMR
X    in		al, INT_CTLR_IMR	;read in current int mask
X    or		al, num			;set the requested IMR bit
X    out		INT_CTLR_IMR, al	;and write it out
X    endm
X;
Xack_int	macro				;this macro sends non-specific EOI
X    					;to the int controller chip in the PC
X    mov al, EOI_CODE
X    out INT_CTLR_PORT, al
X    sti
X    endm
X;
X
X;************************************************************
X;**                                                        **
X;** DATA GROUP DECLARATION                                 **
X;**                                                        **
X;************************************************************
X;
X	
Xdgroup	group	data
Xdata	segment	word public 'data'
X	assume	ds:dgroup
X;
X; --- The following vars are used to manage a very small stack
X;     that is used for interrupt enable/disable stacking
X;
XINT_STACK_SIZE		equ	8 * 1
Xint_stack		db	(INT_STACK_SIZE/8) dup ('intstack')
Xint_stack_pointer 	dw	0
X;
X; --- The following provide a circular character buffer used to
X;     store data received from the MIDI interface
X;
XBUFFER_SIZE		equ	512
X_wrt_index		dw	0
X_rd_index		dw	0
X_midi_buffer		db	BUFFER_SIZE dup (0)
Xpublic _wrt_index
Xpublic _rd_index
Xpublic _midi_buffer
X;
X; --- The following vars are used to keep a running tally of the
X;     programmable timer ticks.
X;
X_hzcount		dd	0
Xint_cnt			dw 	0
Xpublic	_hzcount
X;
Xdata	ends
X;
X
X;************************************************************
X;**                                                        **
X;** CODE SEGMENT                                           **
X;**                                                        **
X;**                                                        **
X;************************************************************
X;
X;
X    extrn _fatal_dos_handler:far	;'C' routine to handle DOS errors
X    extrn _bye:far			; exit routine for Ctl-brk
X
X_code segment byte public 'code'
X    assume cs:_code
X    public     _ctl_brk
X    public     _asm_fatal_dos_handler
X    public     _disable_ints
X    public     _enable_ints
X    public     _init_enable_MPU
X    public     _init_enable_TIMER
X    public     _reset_TIMER
X    public     _write_data_MPU
X    public     _read_MPU
X    public     _midi_isr
X    public     _tick_isr
X
X;
X;************************************************************
X;**                                                        **
X;** INTERRUPT HANDLERS                                     **
X;**                                                        **
X;**                                                        **
X;************************************************************
X_ctl_brk	proc	far
X;
X;	Control-Break Interrupt Service Routine
X;
Xctl_st: cli			; make sure no interrupts
X	mov	ax,ds
X	mov	ss,ax		; ss = ds :: so chkstk() doesn't fail in quit()
X	mov	sp,0fffeh	;  and sp = hi mem
X	mov	ax,1		; exit code
X	sti			; turn interrupts back on
X	push	ax
X	call    _bye
X	pop	bp		; not needed, never returns here
X	iret			;  or here
X_ctl_brk	endp
X;
X;	Fatal Dos Error Interrupt Service Routine
X;
X_asm_fatal_dos_handler proc far
X	push_all_regs		;save machine state
X	push	di
X	push	ax		;push args for function
X	mov	ax, dgroup
X	mov	ds, ax		;address data segment
X	mov	es, ax		;and extra segmant
X	call	_fatal_dos_handler ;handler(ax, di)
X	pop	ax
X	pop	ax
X	pop_all_regs
X	mov	al,0		;tell DOS to ignore error
X	iret
X_asm_fatal_dos_handler endp
X;
X;
X;************************************************************
X;** MIDI_ISR                                               **
X;** This is the MPU int service routine             	   **
X;** It reads data from MPU data port until there is no more** 
X;** and stores in a circular buffer			   **
X;************************************************************
X;
X_midi_isr	proc	far
X	push_all_regs				;save machine state
X	mov	ax, dgroup
X	mov	ds, ax
X	disable_IMR MPU_INT_MASK
X	sti
Xdo_another:
X	mov	dx, DATA_PORT_MPU
X	in	al, dx		;read in the interrupt data from MPU
X
X        inc	_wrt_index			;bump up write pointer
X        cmp	_wrt_index, 01ffh		;is index at top of buff?
X        jle	wrt_index_ok
X        mov	_wrt_index, 0			;if yes, wraparound to bottom
Xwrt_index_ok:					;of buffer 
X        mov	bx, _wrt_index
X        mov	_midi_buffer[bx], al		;move data into buffer
X
X        mov dx, STATUS_PORT_MPU			;DX = &status port
X        in	al, dx				;read status port
X        and al, Rx_NEMT				;is there data to read?
X	jz	do_another			;go back if so
X;isr return
X	cli					;turn off system ints
X	enable_IMR MPU_INT_MASK
X	ack_int					;and acknowlege interrupt
X	pop_all_regs				;restore machine state
X	iret					;and leave
X_midi_isr	endp
X;
X;********************************************************************
X;*	TICK_ISR
X;*	The interrupt service routine for the programmable timer.
X;*	Timer is currently set at 5 ms. intervals.
X;********************************************************************
X;
X_tick_isr 	proc far
X;
Xtmr_st:	push	ds
X	push	ax
X	mov	ax, dgroup
X	mov	ds, ax		;must have our data segment
X	disable_IMR TIMER_INT_MASK
X	sti
X	add	word ptr _hzcount, 1
X	adc	word ptr _hzcount + 2, 0
X	inc	int_cnt
X	cmp	int_cnt,TIC_55MS
X	jge	tm1
X	cli
X	enable_IMR TIMER_INT_MASK
X	ack_int
X	pop	ax
X	pop	ds
X	iret
X
Xtm1:	mov	int_cnt,0
X	int	USER_TMR
X	cli
X	enable_IMR TIMER_INT_MASK
X	ack_int
X	pop	ax
X	pop	ds
X	iret
X_tick_isr endp
X
X
X;
X;************************************************************
X;** DISABLE_INTS()                                         **
X;** Called to disable interrupts.  stacks old int          **
X;** status before disabling, so that nesting is            **
X;** preserved.                                             **
X;************************************************************
X;
X_disable_ints proc far
X	cli
X    	in	al, INT_CTLR_IMR	;read in current int mask
X	mov	dl, al			;move it to dl
X	and	dl, HW_INT_MASK		;extract the bit for MPU ints
X	mov	bx, int_stack_pointer	;get current stack pointer
X	mov	int_stack[bx], dl	;store out int status there
X	inc	bx
X	mov	int_stack_pointer, bx	;write back new stack pointer value
X	or	al, HW_INT_MASK		;mask off int
X    	out	INT_CTLR_IMR, al	;and write it out
X	sti
X	ret
X_disable_ints endp
X;
X;************************************************************
X;** ENABLE_INTS()                                          **
X;** Restores whatever the int status was before            **
X;** DISABLE_INTS() was called.                             **
X;** Note that calls to enable and disable must be matched  **
X;** or chaos will occur                                    **
X;************************************************************
X;
X_enable_ints proc far
X	cli
X    	in	al, INT_CTLR_IMR	;read in current int mask
X	and	al, 0ffh - HW_INT_MASK 	; get all the bits except the ones
X					; for out ints
X	mov	bx, int_stack_pointer	;get int stack pointer
X	dec	bx			;move it down
X	mov	int_stack_pointer, bx	;store it
X	or	al, int_stack[bx]	;or in int status with old one
X    	out	INT_CTLR_IMR, al	;and write it out
X	sti				;turn ints on now
X	ret
X_enable_ints endp
X;
X;************************************************************
X;** INIT_ENABLE_MPU()                                  **
X;** Starts up the MPU ints.                               **
X;**                                                        **
X;************************************************************
X;
X_init_enable_MPU proc far
X	cli
X	enable_IMR MPU_INT_MASK
X	sti
X	ret
X_init_enable_MPU endp
X;;
X;************************************************************
X;** INIT_ENABLE_TIMER()                                  **
X;** Starts up the TIMER ints.                               **
X;**                                                        **
X;************************************************************
X;
X_init_enable_TIMER proc far
X	cli
X; Set 8253 PIT for different timing
X;
X	mov	al,PIT_MODE
X	out	PIT_CTRL,al	; Set 8253 mode
X	mov	ax,T_5MS
X	out	PIT_CNT0,al
X	mov	al,ah
X	out	PIT_CNT0,al	; Set new timing
X	enable_IMR TIMER_INT_MASK
X	sti
X	ret
X_init_enable_TIMER endp 
X;
X;
X;************************************************************
X;** RESET_TIMER()                                          **
X;** Sets timer values back to what they were               **
X;**                                                        **
X;************************************************************
X_reset_TIMER	proc far
X
X	disable_IMR TIMER_INT_MASK
X	mov	al,PIT_MODE
X	out	PIT_CTRL,al	; Set 8253 mode
X	mov	ax,T_55MS
X	out	PIT_CNT0,al
X	mov	al,ah
X	out	PIT_CNT0,al	; Reset timing
X	enable_IMR TIMER_INT_MASK
X	ret
X_reset_TIMER	endp
X;
X
X;************************************************************
X;** WRITE_DATA_MPU(DATA)                                   **
X;** sends a byte to the MPU data port                      **
X;** waits for handshake                                    **
X;**                                                        **
X;************************************************************
X;
X;
X_write_data_MPU proc far
X	c_in
X	mov bx, @ab[bp]			;get data byte in bl reg
X	call write_sub			;and call fast sub
X	c_out				;leave
X_write_data_MPU endp
X;
X;************************************************************
X;**                                                        **
X;**   write_sub                                            **
X;**   Writes data to MPU. on entry, byte in bl            **
X;**   ax, cx, cx destroyed                                 **
X;************************************************************
X;
Xwrite_sub proc near
X	mov dx, STATUS_PORT_MPU	;set up pointer to MPU port
Xwrite_clear_loop:
X	in	al, dx
X	and al, Tx_EMT
X	jnz write_clear_loop
X	dec	dx			;point to data reg
X	mov	al, bl
X	out	dx, al			;send out the data
X	ret
Xwrite_sub endp
X;
X;************************************************************
X;** read_MPU()                                            **
X;** reads a byte from the MPU	eata port                   **
X;** waits for handshake                                    **
X;**                                                        **
X;************************************************************
X;
X_read_MPU proc far
X	c_in
Xread_clear_loop:
X	mov dx, STATUS_PORT_MPU	;DX = &status port
X	in	al, dx
X	and al, Rx_NEMT
X	jnz read_clear_loop
X	dec	dx			;point to data reg
X	in	al, dx
X	xor	ah, ah
X	c_out
X_read_MPU endp
X
X;
X
X_code	ends
X	end
X
END_OF_FILE
if test 12452 -ne `wc -c <'pc-ints.asm'`; then
    echo shar: \"'pc-ints.asm'\" unpacked with wrong size!
fi
# end of 'pc-ints.asm'
fi
if test -f 'pc-mach.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pc-mach.c'\"
else
echo shar: Extracting \"'pc-mach.c'\" \(11518 characters\)
sed "s/^X//" >'pc-mach.c' <<'END_OF_FILE'
X/* $Id: pc-mach.c,v 1.6 89/05/06 17:13:39 lee Exp $
X *
X * Glib - Generic LIBrarian and editor
X *
X * Machine dependent stuff for MIDI programs.
X * Time Thompson
X *
X * This is for MS-DOS machines.  The screen operations should
X * work okay, but the MIDI I/O needs to be worked on.  It may
X * or may not be fast enough on some machines. 
X * $Log:	pc-mach.c,v $
X * Revision 1.6  89/05/06  17:13:39  lee
X * rel. to comp.sources.misc
X * 
X */
X
X#include "glib.h"
X
Xint Rows = 24;
Xint Cols = 80;
X
Xchar *
Xalloc(n)
X{
X	char *p;
X
X	if ( (p=malloc((unsigned)n)) == (char *)NULL ) {
X		printf("*** Whoops *** alloc has failed?!?  No more memory!\n");
X		fflush(stdout);
X		bye();
X	}
X	return(p);
X}
X
Xflushmidi()
X{
X	while ( STATMIDI )
X		getmidi();
X}
X
X/* getmouse - get currect row and column of mouse */
Xgetmouse(amr,amc)
Xint *amr;
Xint *amc;
X{
X	*amr = -1;
X	*amc = -1;
X}
X
X/* statmouse - return mouse button state (0=nothing pressed,1=left,2=right) */
Xstatmouse()
X{
X	return(-1);
X}
X
X/* Return when either a console key or mouse button is pressed. */
Xmouseorkey()
X{
X	return(getconsole());
X}
X
X#ifdef C86
Xgetch()
X{
X	struct regval sreg, rreg;
X	sreg.ax = 0x0000;
X	sysint(0x16, &sreg, &rreg);
X	return(rreg.ax & 0x7f);
X}
X#endif
X
Xwindinit()
X{
X}
X
Xwindgoto(r,c)
Xint r,c;
X{
X#ifdef C86
X	struct regval sreg, rreg;
X	sreg.ax = 0x200;
X	sreg.bx = 0;
X	sreg.dx = (r<<8) | c ;
X	sysint(0x10, &sreg, &rreg);
X#endif
X#ifdef TURBOC
X	gotoxy(1+c,1+r);
X#endif
X}
X
Xwinderaserow(r)
X{
X#ifdef C86
X	struct regval sreg, rreg;
X	sreg.ax = 0x0600;
X	sreg.bx = 0;
X	sreg.cx = (r<<8);	/* urow, lcol */
X	sreg.dx = (r<<8) | 79;
X	sysint(0x10, &sreg, &rreg);
X#endif
X#ifdef TURBOC
X	gotoxy(1,r+1);
X	clreol();
X#endif
X}
X
Xwindexit()
X{
X	/* windgoto(23,0);
X	windrefresh();
X	nocbreak();
X	nl();
X	echo();
X	endwin(); */
X}
X
Xwindclear()
X{
X#ifdef C86
X	struct regval sreg, rreg;
X	sreg.ax = 0x0600;
X	sreg.bx = 0;
X	sreg.cx = 0;	/* urow, lcol */
X	sreg.dx = (24<<8) | 79;
X	sysint(0x10, &sreg, &rreg);
X#endif
X#ifdef TURBOC
X	clrscr();
X#endif
X}
X
X/* windgets - get a line of input from the console, handling backspaces */
Xwindgets(s)
Xchar *s;
X{
X	char *origs = s;
X	int c;
X
X	while ( (c=getconsole()) != '\n' && c!='\r' && c!= EOF ) {
X		if ( c == '\b' ) {
X			if ( s > origs ) {
X				windstr("\b \b");
X				s--;
X			}
X		}
X		else {
X			windputc(c);
X			*s++ = c;
X		}
X		windrefresh();
X	}
X	*s = '\0';
X}
X
Xwindstr(s)
Xchar *s;
X{
X	int c;
X
X	while ( (c=(*s++)) != '\0' )
X		windputc(c);
X}
X
Xwindputc(c)
Xint c;
X{
X	putchar(c);
X}
X
Xwindrefresh()
X{
X}
X
Xbeep()
X{
X	putchar('\007');
X}
X
Xwindhigh()
X{
X}
X
Xwindnorm()
X{
X}
X
X/****************
X * openls(), nextls(), and closels() are used to scan the current directory.
X ***************/
X
Xint first = 1;
Xopenls()
X{
X	first = 1;
X}
Xchar *
Xnextls()
X{
X	static struct ffblk ffblk;
X	int n;
X
X	if ( first ) {
X		n = findfirst("*.*",&ffblk,0);
X		first = 0;
X	}
X	else
X		n = findnext(&ffblk);
X
X	if ( n == 0 )
X		return(ffblk.ff_name);
X	else
X		return((char *)NULL);
X}
Xclosels()
X{
X}
X
X#ifdef OLDSTUFF
X/*
X * The following MPU code has been provided by Steve Frysinger (moss!spf).
X */
X
X#define	STATUS_PORT	0x0331
X#define	COMMAND_PORT	0x0331
X#define	DATA_PORT	0x0330
X#define	DATA_READY_MASK	0x40
X#define	DATA_AVAIL_MASK	0x80
X
Xint send_command_4001(val)	/* Patterned after Voyetra's reset_4001() */
Xunsigned val;
X{
X	unsigned x = 0;
X	int flag;
X	int ack_count,time_count;
X	int retval=1; /* Assume success */
X	inportb(DATA_PORT);
X	for (time_count=5000,flag=1;time_count&&flag;time_count--)
X	{
X		if (!(inportb(STATUS_PORT)&DATA_READY_MASK)) flag=0;
X	}
X	if (flag)
X	{
X		fprintf(stderr,"Command timeout waiting for port!\n");
X		retval = -1;
X	}
X	else
X	{
X		outportb(COMMAND_PORT,val);
X		for (time_count=10000,ack_count=5,flag=0;!flag;)
X		{
X			if ((inportb(STATUS_PORT)&DATA_AVAIL_MASK))
X			{
X				time_count--;
X				if (!time_count)
X				{
X					flag++;
X					fprintf(stderr,"Command timeout waiting for ACK.\n");
X					retval = -1;
X				}
X			}
X			else
X			{
X				x = (unsigned)inportb(DATA_PORT);
X				if (x == 0xfe)
X				{
X					flag++;
X					fprintf(stderr,"Got command acknowledgement\n");
X				}
X				else
X				{
X					ack_count--;
X					if (!ack_count)
X					{
X						printf("Too many data bytes without ACK\n");
X						retval = -1;
X					}
X				}
X			}
X		}
X	}
X	return(retval);
X} /* send_command_4001 */
X#endif
X
X/*
X * Acknowledgements to John Helton for additions to support ATT PC6300 w/
X * MPU401 and OP4000 MIDI Interface Controllers.
X * PC6300 support uses Borland TurboC 'C' compiler, large model
X *
X */
X#define QUIT 1
X#define NOQUIT 0
X
Xvoid interrupt (*oldint0)();
Xvoid interrupt (*oldint2)();
Xvoid interrupt (*oldint1b)();
Xvoid interrupt (*oldint23)();
Xvoid interrupt (*oldint24)();
Xvoid interrupt ctr_brk_handler();
Xvoid interrupt fatal_err_hndlr();
X
Xvoid interrupt far tick_isr();
Xvoid interrupt far midi_isr();
Xextern unsigned long hzcount;
Xextern char midi_buffer[];
Xextern int wrt_index, rd_index;
X
Xextern unsigned _stklen;	/* Turbo C specific */ 
X
Xint Nextpcchar = EOF;
Xint Fakemidi = 0;
Xint (*Intfunc)() = NULL;
X
Xhello()
X{
X    _stklen = 50000;
X    hzcount = 0L;			/* init timer & buffer globals */
X    wrt_index = rd_index = 0;
X    if (!setup_MIC())			/* Set up the Midi Interface Ctrl */
X    {
X	if ( fisatty(stdout) )
X	    printf("Can't initialize midi interface\n");
X	Fakemidi = 1;
X	reset_ints(NOQUIT);		/* restore interrupts to a suitable
X					   condition to keep running without
X					   the Midi Interface (for testing) */
X	return;
X    }
X    send_msg(UART, COMMAND_MSG);	/* run the MIC in dumb mode */
X    return;
X}
X
Xrtend()
X{
X    reset_MIC();
X}
X
Xbye()
X{
X	system_exit();
X}
X
Xflushconsole()
X{ return; }
X
Xgetconsole()
X{
X    int c;
X
X    if ( Nextpcchar != EOF ) {
X    	c = Nextpcchar;
X    	Nextpcchar = EOF;
X    }
X    else {
X    	c = getch();
X    }
X    return(c);
X}
X
Xputconsole(c)
X{
X	putch(c);
X}
X
X/* getmidi reads data out of the circular midi buffer */
Xgetmidi()
X{
X	static char mbuff[1];
X	unsigned char *p;
X
X	while ( wrt_index == rd_index)
X		;
X	rd_index++;
X	if (rd_index > 511) rd_index = 0;
X	mbuff[0] = midi_buffer[rd_index];
X	return (mbuff[0] & 0xff);
X}
X
Xsendmidi(val)
Xint val;
X{
X	unsigned char p[1];
X	p[0] = val;
X	putnmidi(1,p);
X}
X
Xputnmidi(n,p)
Xchar *p;
X{
X    while ( n-- > 0 ) {
X	    int c = (*p++) & 0xff;
X	    if ( Fakemidi )
X		printf("putmidi(d=%d x=%x o=%o)\n",c,c,c);
X	    else
X		write_data_MPU(c);
X    }
X}
X
Xresetclock()
X{
X	hzcount = 0L;
X}
X
Xlong
Xmilliclock()
X{
X	return (hzcount*5L);
X}
X
X/* filetime - Return the modification time of a file in seconds. */
Xlong
Xfiletime(fn)
Xchar *fn;	/* file name */
X{
X	struct stat s;
X
X	if ( stat(fn,&s) == -1 )
X		return(-1);
X	return(s.st_mtime);
X}
X
X/* currtime - Return current time in seconds (consistent with filetime()) */
Xlong
Xcurrtime()
X{
X	long time();
X	return ( time((long *)0) );
X}
X
Xfisatty(f)
XFILE* f;
X{
X	return(isatty(fileno(f)));
X}
X
X/*
X * send_msg(COM, TYPE, PTR, LENGTH)
X * will send command to Midi Interface Controller (MIC) Command port, 
X * then either return, wait for data or send data
X */
X
Xsend_msg(com, type, ptr, length)
Xint com, type, length;
Xchar *ptr;
X{
X    int acked;
X    int x;
X
X    while ( NOT_READY_FOR_DATA_MIC());
X    disable_ints();
X    COMMAND_OUT_MIC((char) com);	/* send the command to the MIC */
X    for(acked=0; !acked; ) {		/* wait until our command is acked */
X        x = read_MPU();			/* get a byte back from the MIC */
X        if (x == ACK) acked++;		/* done if ACK received */
X        else write_rcv_buff(x);		/* deal with this input stream first */
X    }
X    if (type == WRITE_MSG)		/* if write request... */
X        for (; length; ptr++, length--) write_data_MPU(*ptr);
X					/* write all the bytes to the MIC */
X    enable_ints();			/* ints restored to where they were
X					   before we shut them off */
X}
X
X
X/* WRITE_RCV_BUFF(INPUT)
X * part of the command handshake sequence.  Input read from the
X * midi data port is saved in wraparound FIFO
X*/
X
Xwrite_rcv_buff(val)
Xint val;
X{
X    wrt_index++;
X    if (wrt_index > 511) wrt_index = 0;
X    midi_buffer[wrt_index] = (char) val;
X}
X
X/*
X * SETUP_MIC()
X * resets MIC, sets up int vectors and enables int system
X * Returns - true if MIC set ok
X */
X
Xstatic setup_MIC()
X{
X    int retval;
X
X    set_ints();			/* set the new interrupt vectors */
X    init_enable_MPU();		 /* turn on interrupt system for first time */
X    retval = reset_MIC();		/* try to reset MIC */
X    if (!retval) retval = reset_MIC(); /* if no good, try again */
X    init_enable_TIMER();	/* turn on timer interrupt if reset ok*/
X    return(retval);
X}
X
X/*
X * RESET_MIC()
X * attempts to do a low level software reset on the MIC
X * returns - true if success
X */
X
Xreset_MIC()
X{
X    unsigned x = 0;
X    int flag;
X    int ack_count, time_count;
X    int retval=1;		/* assume success */
X    
X    disable_ints();		/* disable interrupts */
X    READ_DATA_MIC();		/* Clear out any data in receiver */
X    /* Here we will loop until ready for data, or we give up 	*/
X    for (time_count=5000, flag=1; time_count && flag; time_count--) {
X	/* if MIC ready for data, we can quit loop */
X        if (!(NOT_READY_FOR_DATA_MIC())) flag=0;
X    }
X    /* if timed out before we got ready for data, return flag couldn't reset */
X    if (flag){	
X	retval = 0;
X    }
X    else {
X        COMMAND_OUT_MIC(RESET); /* Send the reset command */
X	/* loop here till time out, or ack recvd */
X        for (time_count=10000, ack_count=5, flag=0; !flag;) {
X	    if ((NOT_DATA_AVAILABLE_MIC())) { /* if no data from MIC */
X	        time_count--;		/* count one more wait */
X	        if (!time_count) {
XBAD_RESET:
X		    flag++;		/* if time out, note it */
X		    retval=0;		/* and note failure */
X		}
X	    }
X	    else {		/* If there is data coming back form MIC */
X	        x = (unsigned) READ_DATA_MIC(); /* ...read it */
X	        if (x == ACK) { /* If data is the ACK message */
X		    flag++;		/* note we are done, and no failure */
X		}
X	        else {		/* if data back from MIC wasn't ack */
X		    ack_count--;/* note that we got something that isn't ack */
X		    if (!ack_count) goto BAD_RESET;
X				/* If we get too many data bytes back from
X				   MIC with no ack, give up */
X		}
X	    }
X	}
X    }
X    enable_ints();			 /* turn ints back on */
X    return(retval);
X}
X
X/*
X * SYSTEM_EXIT()
X * called to leave program.  resets ints and exits
X */
Xsystem_exit()
X{
X    reset_MIC();
X    disable_ints();
X    reset_ints(QUIT);	/* put all the int vectors back where they were */
X    reset_TIMER();
X    enable_ints();
X    windexit(0);
X    exit();
X}
X
X/*
X * hi level interrupt routines
X */
X
Xvoid interrupt
Xctr_brk_handler()
X{
X    if ( Intfunc != NULL )
X	(*Intfunc)();
X    printf("interrupts reset; BYE!\n");
X    system_exit();
X}
X
Xvoid interrupt
Xfatal_err_hndlr()
X{
X    fatal_dos_handler();
X}
X
Xfatal_dos_handler()	/* called by fatal error handler ISR */
X{
X    printf("got fatal error; BYE!\n");
X    system_exit();
X}
X
Xset_ints()
X{
X    oldint0 = getvect(0x08);	/* timer interrupt on irq0 */
X    setvect(0x08, tick_isr);
X    oldint2 = getvect(0x0a);	/* midi interrupt on irq2 */
X    setvect(0x0a, midi_isr);
X    oldint1b = getvect(0x1b);	/* the rest of these are dos & bios ints */
X    setvect(0x1b, ctr_brk_handler);
X    oldint23 = getvect(0x23);
X    setvect(0x23, ctr_brk_handler);
X    oldint24 = getvect(0x24);
X    setvect(0x24, fatal_err_hndlr);
X}
X
Xreset_ints(reset_type)
X{
X    if (reset_type == QUIT) {
X        setvect(0x08, oldint0);
X        setvect(0x1b, oldint1b);
X        setvect(0x23, oldint23);
X        setvect(0x24, oldint24);
X    }
X    setvect(0x0a, oldint2);	/* only need to reset one hardware interrupt
X				   if we're not going to quit */
X}
X
Xsignal(type,func)
Xint (*func)();
X{
X	if ( type == SIGINT ) {
X		if ( func == SIG_IGN )
X			Intfunc = NULL;
X		else
X			Intfunc = func;
X	}
X}
END_OF_FILE
if test 11518 -ne `wc -c <'pc-mach.c'`; then
    echo shar: \"'pc-mach.c'\" unpacked with wrong size!
fi
# end of 'pc-mach.c'
fi
echo shar: End of archive 6 \(of 15\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 15 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0