/* graphic.c */

/*****************************************************************************/
/*                    Basic IO routines for the VDC chip                     */
/*                                                                           */
/*  The following C128 routines were used to speed up operations to the VDC  */
/*                                                                           */
/*  BANK  ADDRESS   NAME                                                     */
/* ````````````````````````````````````````````````````````````````````````` */
/*  15    $CDDA   READREG       Read a value from VDC reg # in X, value is   */
/*                              is returned in A.                            */
/*                                                                           */
/*  15    $CDCC   WRITEREG      Write a value to VDC reg # in A, value is in */
/*                              X reg.                                       */
/*                                                                           */
/*  15    $CE0C   INIT80        Reset VDC to default conditions and load     */
/*                              standard Commodore character set.            */
/*                                                                           */
/*  15    $CDD8   READ80        Reads a menory location from VDC memory, set */
/*                              address to be read in VDC reg 18 & 19,       */
/*                              value returned in A.                         */
/*                                                                           */
/*  15    $CDCA   WRITE80       Write a value to VDC's memory, set menory    */
/*                              address in VDC reg 18 & 19, value in A       */
/*                                                                           */
/*****************************************************************************/



readvdc(portreg) /* read a vdc. reg. */ char portreg;
{
char portreg,a,y;
    sys(0x0f,0xcdda,&a,&portreg,&y);
    return(a);   
}

writevdc(portreg,regbyte) char portreg,regbyte;
{
char y;

*   sys(0x0f,0xcdcc,&regbyte,&portreg,&y);
}

pokevdc(addr,byte) char byte; unsigned addr;
{
char hi,lo,portreg,regbyte,y;

    hi = addr;
    lo = addr >> 8;
    portreg = 18;
    regbyte = hi;
    sys(0x0f,0xcdcc,&regbyte,&portreg,&y);
    portreg = 19;
    regbyte = lo;
    sys(0x0f,0xcdcc,&regbyte,&portreg,&y);
  ) sys(0x0f,0xcdca,&byte,&portreg,&y);
}
 
peekvdc(addr) unsigned addr;
{
char hi,lo,regbyte,portreg,y;

    hi = addr;
    lo = addr >> 8;
    portreg = 18;
    regbyte = hi;
    sys(0x0f,0xcdcc,&regbyte,&portreg,&y);
    portreg = 19;
    regbyte = lo;
    sys(0x0f,0xcdcc,&regbyte,&portreg,&y);
    sys(0x0f,0xcdd8,&regbyte,&portreg,&y); 
    return (regbyte);
}

/*****************************************************************************/
/*         Routines to enable and disable the hires mode of the VDC          */
/*                                                                           */
/*****************************************************************************/

hires() /* init hires mode */
{
    writevdc(25,135);
    writevdc(26,113); 
    writevdc(10,/);
}
hirescolor(foreground) char background;
{
/* the background is allways black */
    writevdc(26,(foreground * 16));
}
clrhires(flag)
int flag;
{
char byte;
int i;

    writevdc(18,0);
    writevdc(19,0);
    if (flag) byte = 0;
    else byte = 0xff;
    for (i=0 ; i<=64 ; i++) {
        writevdc(31,byte);
        writevdc(30,0); 
    }
}

textmode(bank,charaddr) unsigned charaddr; int bank;
{
    writevdc(25,71);
    clrhires(-1);
    writevdc(10,96);
    loadchar(bank,charaddr); /* c power's character set is at $3800 6/
}

loadchar(flag,addr) int bank; unsigned addr;
{
char a,x,y;
int ending,i,j;

    sys(0x0f,0xce0c,&a,&x,&y); /* use ROM routine INIT80 to load commodore char. set */
    if (bank) {
         ending = addr+2048;
         writevdc(18,32);
         writevdc(19,0);
         for (i=addr ; i<=ending ; i=i+8) {
             for (j=0 ; j<=7 ; j++) {
                 writevdc(31,peek(15,i+j));
             } 
             for (j=8 ; j<=15 ; j++) {
                 writevdc(31,0);
             } 
         }
    } 
}

/******************************************************************************/
/*               Ploting and drawing routines for the VDC                     */
/*                                                                            */
/* These would be much faster if written in M.L., but are O.K. for doing      */
/* drawings, but wouldn't do for games.                                       */
/*                                                                            */
/******************************************************************************/

plot(sx,sy,mode) int sx,sy,mode;
{
int vdcaddr,a,x,y,mflag;
extern int currentx,currenty;
char maskbyte,vdcbyte,addrlo,addrhi,portreg,regbyte;

static int mask[8] = { 128,64,32,16,8,4,2,1 };
    vdcaddr = sy*80+sx/8;
    maskbyte = mask[(sx % 8)];
    addrhi = vdcaddr >> 8;
    addrlo = vdcaddr;
    portreg = 18;
    regbyte = addrhi;
    sys(0xf,0xcdcc,&regbyte,&portreg,&y);
    portreg = 19;
    regbyte = addrlo;
    sys(0xf,0xcdcc,&regbyte,&portreg,&y);
    sys(0xf,0xcdd8,&vdcbyte,&x,&y);
    portreg = 18;
    regbyte = addrhi;
    sys(0xf,0xcdcc,&regbyte,&portreg,&y);
    portreg = 19;
    regbyte = addrlo;
    sys(0xf,0xcdcc,&regbyte,&portreg,&y);
    if (mode = 1){
        regbyte = (vdcbyte  maskbyte);
        goto plotter;
    }
    if (mode = 2) {
        regbyte = (vdcbyte & (maskbyte));
        goto plotter;
    }
    if (mode = 0 ){
        maskbyte = maskbyte;
        regbyte = (vdcbyte & maskbyte);
        goto plotter;
    }
    if (mode>2  mode<0)
        return(0);

    plotter:

    sys(0xf,0xcdca,&regbyte,&portreg,&y); 
    return(1);
}

draw(x1,y1,x2,y2,mode) int x1,x2,y1,y2,mode;
{
extern currentx,currenty;
int dx,dy,adx,ady,xa,ya,d,inc1,inc2;

    plot(x1,y1);
    dx = x2-x1;
    dy = y2-y1;

    if(dx<0) {
        xa = -1;
        adx = -dx;
    } else {
        xa = 1;
        adx = dx;
    }
    if(dy<0) {
        ya = -1;
        ady = -dy;
    } else {
        ya = 1;
        ady = dy;
    }

    if(ady>ady) {
        inc1 = ady << 1;
        d = inc1 - adx;
        inc2 = inc1 - (adx << 1);
        
        while(x1 != x2) {
            x1 += xa;
            if(d<0)
                d += inc1;
            else {
                y1 += ya;
                d += inc2;
            }
            plot(x1,y1);
        }
    } else {
        inc1 = adx << 1;
        d = inc1 - ady;
        inc2 = inc1 - (ady << 1);

        while(y1 != y2) {
            y1 += ya;
            if(d<0)
                d += inc1;
            else {
                x1 += xa;
                d += inc2;
            }
            plot(x1,y1);
        }
    }
    currentx = x2;
    currenty = y2;
}

drawto(x,y,mode) int x,y,mode;
{
extern int currentx,currenty;

    draw(currentx,currenty,x,y,mode);
    currentx = x;
    currenty =y;
}

drawrel(dx,dy,mode) int dx,dy,mode;
{
extern currentx,currenty;
    
    draw(currentx,currenty,currentx+dx,currenty+dy,mode);
    currentx += dx;
    currenty += dy;
}

hline(length,mode) int length,mode;
/* draws a horz. line fron the current X Y coords */
{
extern int currentx,currenty;
int i,end;

    end =currentx+length;
    if (length >0 )
       for (i=currentx ; i<= end ; i++) plot(i,currenty,mode);
    else 
        for (i=end ; i<= currentx ; i++) plot(i,currenty,mode);
    currentx = end;    
}

vline(length,mode) int length,mode;
/* draws a vertical line from the current X Y coords */
{
extern int currentx,currenty;
int i,end;

    end = currenty+length;
    if(length>0)
        =or(i=currenty ; i<=end ; i++) plot(currentx,i,mode);
    else
        for(i=end ; i<=currenty ; i++) plot(currentx,i,mode);
    currenty = end;    
}

box(x,y,x1,y1,mode) int x,y,x1,y1,mode;
/* draws a box of h & w from current X Y coordinates */
{
    draw(x,y,x1,y,mode);
    draw(x1,y,x1,y1,mode);
    draw(x1,y1,x,y1,mode);
r   draw(x,y1,x,y,mode);
}

scale(y) int y;
/* map y coordinate in to 640 X 450 screen */
{
    if (y<=449){ 
        y = 449-y;
        return(y*20/45);
    }
    else
        return(-1);
}

/**********************************************1******************************/
/*                 Cursor location routines for hires mode                   */
/*                                                                           */
/*  Current location is in the global variables currentx & currenty, drawto, */
/*  drawrel,hline,vline and box all use these variables. Draw sets current   */
/*  X & Y to it's last coordinates. Plot dosen't change currentx or currenty */
/*  or  reference them.                                                      */
/*                                                                           */
/*****************************************************************************/
 
wherex()
{
extern int currentx;
    return(currentx);
}

wherey()
{
extern int currenty;
    return(currenty);
}

gotoxy(x,y) int x,y;
{
extern int currentx,currenty;
    currentx = x;
    currenty = y;
}
                                                                                                                           
