/*
 * Glib - Generic LIBrarian and editor
 *
 * Machine dependent stuff for MIDI programs.
 *
 * This is for MS-DOS machines.  The screen operations should
 * work okay, but the MIDI I/O needs to be worked on.  It may
 * or may not be fast enough on some machines. 
 */

#include "dos.h"
#include "glib.h"

#define C86
#ifdef C86
#define inp inportb
#define outp outportb
#endif

int Rows = 24;
int Cols = 80;

flushmidi()
{
	while ( statmidi() )
		getmidi();
}

/* getmouse - get currect row and column of mouse */
getmouse(amr,amc)
int *amr;
int *amc;
{
	*amr = -1;
	*amc = -1;
}

/* statmouse - return mouse button state (0=nothing pressed,1=left,2=right) */
statmouse()
{
	return(-1);
}

/* Return when either a console key or mouse button is pressed. */
mouseorkey()
{
	return(getconsole());
}

flushconsole()
{
}

statconsole()
{
	struct regval sreg, rreg;
	sreg.ax = 0x0100;
	sysint(0x16, &sreg, &rreg);
	if ( rreg.ax != 0 )
		return(1);
	else
		return(0);
}

getconsole()
{
	struct regval sreg, rreg;
	sreg.ax = 0x0000;
	sysint(0x16, &sreg, &rreg);
	return(rreg.ax & 0x7f);
}

long milliclock()
{
	static int hour1 = -1, min1, sec1, hund1;
	struct regval sreg, rreg;
	int hours, mins, secs, hunds;
	long mills;

	sreg.ax = 0x2c00;
	sysint(0x21, &sreg, &rreg);
	hours = (rreg.cx >> 8) & 0x7f;
	mins = rreg.cx & 0x7f;
	secs = (rreg.dx >> 8) & 0x7f;
	hunds = rreg.dx & 0x7f ;
	if ( hour1 < 0 ) {
		mills = 0L;
		hour1 = hours;
		min1 = mins;
		sec1 = secs;
		hund1 = hunds;
	}
	else {
		mills = 10L*(hunds-hund1)+1000L*(secs-sec1)
			+60000L*(mins-min1)+360000L*(hours-hour1);
	}
	return( mills );
}

char *
alloc(n)
{
	char *p;

	if ( (p=malloc((unsigned)n)) == (char *)NULL ) {
		printf("*** Whoops *** alloc has failed?!?  No more memory!\n");
		fflush(stdout);
		bye();
	}
	return(p);
}

windinit()
{
}

windgoto(r,c)
int r,c;
{
	struct regval sreg, rreg;
	sreg.ax = 0x200;
	sreg.bx = 0;
	sreg.dx = (r<<8) | c ;
	sysint(0x10, &sreg, &rreg);
}

winderaserow(r)
{
	struct regval sreg, rreg;
	sreg.ax = 0x0600;
	sreg.bx = 0;
	sreg.cx = (r<<8);	/* urow, lcol */
	sreg.dx = (r<<8) | 79;
	sysint(0x10, &sreg, &rreg);
}

windexit(r)
int r;
{
	/* windgoto(23,0);
	windrefresh();
	nocbreak();
	nl();
	echo();
	endwin(); */
}

windclear()
{
	struct regval sreg, rreg;
	sreg.ax = 0x0600;
	sreg.bx = 0;
	sreg.cx = 0;	/* urow, lcol */
	sreg.dx = (24<<8) | 79;
	sysint(0x10, &sreg, &rreg);
}

/* windgets - get a line of input from the console, handling backspaces */
windgets(s)
char *s;
{
	char *origs = s;
	int c;

	while ( (c=getconsole()) != '\n' && c!='\r' && c!= EOF ) {
		if ( c == '\b' ) {
			if ( s > origs ) {
				windstr("\b \b");
				s--;
			}
		}
		else {
			windputc(c);
			*s++ = c;
		}
		windrefresh();
	}
	*s = '\0';
}

windstr(s)
char *s;
{
	int c;

	while ( (c=(*s++)) != '\0' )
		windputc(c);
}

windputc(c)
int c;
{
	putchar(c);
}

windrefresh()
{
}

beep()
{
	putchar('\007');
}

windhigh()
{
}

windnorm()
{
}

/****************
 * openls(), nextls(), and closels() are used to scan the current directory.
 ***************/

openls()
{
}
char *
nextls()
{
	return(NULL);
}
closels()
{
}

/*
 * The following MPU code has been provided by Steve Frysinger (moss!spf).
 */

#define	STATUS_PORT	0x0331
#define	COMMAND_PORT	0x0331
#define	DATA_PORT	0x0330
#define	DATA_READY_MASK	0x40
#define	DATA_AVAIL_MASK	0x80

int send_command_4001(val)	/* Patterned after Voyetra's reset_4001() */
unsigned val;
{
	unsigned x = 0;
	int flag;
	int ack_count,time_count;
	int retval=1; /* Assume success */
	inp(DATA_PORT);
	for (time_count=5000,flag=1;time_count&&flag;time_count--)
	{
		if (!(inp(STATUS_PORT)&DATA_READY_MASK)) flag=0;
	}
	if (flag)
	{
		fprintf(stderr,"Command timeout waiting for port!\n");
		retval = -1;
	}
	else
	{
		outp(COMMAND_PORT,val);
		for (time_count=10000,ack_count=5,flag=0;!flag;)
		{
			if ((inp(STATUS_PORT)&DATA_AVAIL_MASK))
			{
				time_count--;
				if (!time_count)
				{
					flag++;
					fprintf(stderr,"Command timeout waiting for ACK.\n");
					retval = -1;
				}
			}
			else
			{
				x = (unsigned)inp(DATA_PORT);
				if (x == 0xfe)
				{
					flag++;
					fprintf(stderr,"Got command acknowledgement\n");
				}
				else
				{
					ack_count--;
					if (!ack_count)
					{
						printf("Too many data bytes without ACK\n");
						retval = -1;
					}
				}
			}
		}
	}
	return(retval);
} /* send_command_4001 */

getmidi()
{
	while (inp(STATUS_PORT) & DATA_AVAIL_MASK)
		; /* Wait for data available */
	return(inp(DATA_PORT));
}

statmidi()
{
	if ( inp(STATUS_PORT) & DATA_AVAIL_MASK) /* data available ? */
		return(0);
	else
		return(1);
}

sendmidi(val)
int val;
{
	int timeout = 10000;

	unsigned status;
	status=inp(STATUS_PORT);
	while (status & DATA_READY_MASK)
		printf("Busy; read %d ",getmidi());
	/*
	This printf lets me know what's holding up the transfer; I usually get
	254 back, unless I press a synth key, when I get the key press parameters.
	*/
	outp(DATA_PORT,val);
}

hello()
{
	send_command_4001(0xff);	/* reset */
	send_command_4001(0x96);	/* kill RT? */
	send_command_4001(0x94);	/* ?? */
	send_command_4001(0x90);	/* ?? */
	send_command_4001(0x3f);	/* go into uart mode */
}

bye()
{
	send_command_4001(0xff);	/* reset */
	windexit(0);
}

