/*
 * 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);
}

