#define VESA8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <mem.h>
#include <dos.h>
#include "vidlib.h"
#include "vesa.h"

int VESAfill256(unsigned dx, unsigned dy, unsigned sdx, unsigned sdy,
                unsigned color)
{
   char *dest;
   int  tempdx;

   VESAsetpage(VESAwhat_page(dy, dx));
   dest=(char *)normalize(_screen_start + VESAwhat_offset(dy,dx));
   if (vgadebug) {
       fprintf(vgadebug,"\nVESAfill256(dx=%u, %u, sdx=%u, sdy=%u, color=%u)\n",
                        dx,dy,sdx,sdy,color);
       fflush(vgadebug);
   }
   while (sdy>0) {
       while ((Vnext_break_row != dy) && (sdy>0)){
          setmem(dest, sdx, color);
          dy++; sdy--;
          dest=(char *)normalize(dest+_screen_width);
       }
       if ((sdy>0) && (Vnext_break_row == dy)) {
	 tempdx=Vnext_break_col - dx; /* number of bytes */
	 if ( tempdx < 1 ) { /* no bytes to output on this page */
	    VESAsetpage(vesapage+1);
	    dest=(char *)normalize (_screen_start + VESAwhat_offset(dy,dx) );
            setmem(dest, sdx, color);
            dy++; sdy--;
            continue;
         }
         if ( sdx > tempdx ) {    /* split page */
            setmem(dest, tempdx, color);
            VESAsetpage(vesapage+1);
            dest=(char *)normalize
			(_screen_start + VESAwhat_offset(dy,dx+tempdx) );
            setmem(dest, (sdx-tempdx), color);
	 } else { /* then all on this page */
	    setmem(dest, sdx, color);
	    VESAsetpage(vesapage+1);
	 }
	 dy++; sdy--;
	 dest=(char *)normalize(_screen_start + VESAwhat_offset(dy,dx));
       }
   }
   return(1);

}

/* Currently, we assume the worst and perform all copies through system */
/* memory.								*/
int VESAcopy256(unsigned dx, unsigned dy,
             unsigned sx, unsigned sy,
             unsigned sdx, unsigned sdy)
{
   char *temp;
   int i,g, b, direction;
   long t;

   /* determine if the source is less than the destination, and overlaps */
   if ( (sy < dy) && (sy+sdy > dy) && (sx+sdx > dx) && (dx+sdx > sx) )
        direction=-1;
   else
        direction=1;
   t=(long)sdx*sdy;
   if (t < 16385) {
      g=sdy;
   } else {
      g=16384/sdx;
      t=g*sdx;
   }
   if ( (temp=(char *)malloc((unsigned)t)) == NULL) {
      return(0);
   }
   if (vgadebug) {
      fprintf(vgadebug,
              "\nVESAcopy256(dx=%u, dy=%u,  sx=%u, sy=%u,  sdx=%u, sdy=%u)\n",
                           dx,dy,sx,sy,sdx,sdy);
      fprintf(vgadebug,"   temp=%Fp, _s_s=%Fp, _s_w=%u, g=%u, direction=%i"
                       ", core=%lu\n",
              temp, _screen_start, _screen_width, g, direction,coreleft());
      fflush(vgadebug);
   }
   if ( direction > 0 ) {
      for (i=sy; i<sy+sdy; i+=g, dy+=g) {
         b=(( (sy+sdy-i) < g ) ? (sy+sdy-i) : g );
         VESAcapt256(temp, sdx, g, 0, 0, sx, i, sdx, b, 1);
         VESAdisp256(dx, dy, temp, sdx, g, 0, 0, sdx, b, 1);
      }
   } else {
      i=(sy+sdy); b=g; dy+=sdy;
      while ( i > sy ) {
         if ( sy+b > i ) {
            b=i-sy; i=sy; dy-=b;
         } else {
            i-=g; dy-=g;
         }
         VESAcapt256(temp, sdx, g, 0, 0, sx, i, sdx, b, -1);
         VESAdisp256(dx, dy, temp, sdx, g, 0, 0, sdx, b, -1);
      }
   }
   free(temp);
   return(1);
}

/* System memory to video copy */
int VESAdisp256(unsigned dx, unsigned dy,
	     char *s, unsigned sw, unsigned sl,
             unsigned sx, unsigned sy,
             unsigned sdx, unsigned sdy, int direction)
{
   char *src;
   char *dest;
   int  tempdx;

   src=(char *)normalize(s + sy*sw + sx);
   VESAsetpage(VESAwhat_page(dy, dx));
   dest=(char *)normalize(_screen_start + VESAwhat_offset(dy,dx));
   if (vgadebug) {
       fprintf(vgadebug,"\nVESAdisp256(dx=%u, %u, s=%Fp,"
                        " sw=%u, %u, sx=%u, %u,  sdx=%u, sdy=%u, "
                        "direction=%u)\n",
                        dx,dy,s,sw,sl,sx,sy,sdx,sdy,direction);
       fflush(vgadebug);
   }
   while (sdy>0) {
       while ((Vnext_break_row != dy) && (sdy>0)){
	  /* while we're not on a break row and we've still got work ... */
	  memcpy(dest, src, sdx);
	  dy++; sdy--;
	  dest=dest+_screen_width; /* don't need to normalize dest */
	  src=(char *)normalize(src+sw);
       }
       if ((sdy>0) && (Vnext_break_row == dy)) {
	 /* if we've still got lines to do and we're on a break row ... */
	 /* Vnext_break_col is the first byte in the next page */
	 tempdx=Vnext_break_col - dx; /* number of bytes on this page */
	 if ( tempdx < 1 ) { /* no bytes to output on this page */
	    VESAsetpage(vesapage+1);
	    dest=(char *)normalize (_screen_start + VESAwhat_offset(dy,dx) );
            memcpy(dest, src, sdx);
            dy++; sdy--;
            if (sdy) src=(char *)normalize(src + sw);
            continue;
         }
         if ( sdx > tempdx ) {    /* split page */
            memcpy(dest, src, tempdx);
            VESAsetpage(vesapage+1);
            dest=(char *)normalize
			(_screen_start + VESAwhat_offset(dy,dx+tempdx) );
            memcpy(dest, src+tempdx, (sdx-tempdx));
         } else { /* then sdx <= tempdx */
            memcpy(dest, src, sdx);
            VESAsetpage(vesapage+1);
         }
         dy++; sdy--;
	 dest=(char *)normalize(_screen_start + VESAwhat_offset(dy,dx));
       }
       if (sdy) src=(char *)normalize(src + sw);
   }
   return(1);
}
/* Video to System memory copy */
int VESAcapt256(char *d, unsigned dw, unsigned dl,
                      unsigned dx, unsigned dy,
                      unsigned sx, unsigned sy,
                      unsigned sdx, unsigned sdy, int direction)
{
   char *src;
   char *dest;
   int  tempdx;

   dest=(char *)normalize(d + dy*dw + dx);
   VESAsetpage(VESAwhat_page(sy, sx));
   src=(char *)normalize(_screen_start + VESAwhat_offset(sy,sx));
   if (vgadebug) {
      fprintf(vgadebug,"\nVESAcapt256(d=%Fp, dw=%u, %u, dx=%u, %u, sx=%u, %u,"
                       "  sdx=%u, sdy=%u, direction=%u)\n",
                       d, dw, dl, dx,dy,sx,sy,sdx,sdy,direction);
   }
   while (sdy) {
       while ((Vnext_break_row != sy)&&(sdy>0)) {
          memcpy(dest, src, sdx);
          sy++; sdy--;
          src=(char *)normalize(src+_screen_width);
          dest=(char *)normalize(dest+dw);
       }
       if ( (sdy>0) && (Vnext_break_row == sy)) {
	 tempdx=Vnext_break_col - sx; /* number of bytes on this page */
	 if ( tempdx < 1 ) {  /* if no bytes on this page */
	    VESAsetpage(vesapage+1);
	    src=(char *)normalize
			(_screen_start + VESAwhat_offset(sy,sx) );
            memcpy(dest, src, sdx);
            sy++; sdy--;
            src=(char *)normalize(src+_screen_width);
            if (sdy) dest=(char *)normalize(dest + dw);
            continue;
         }
         if ( sdx > tempdx ) { /* split page */
            memcpy(dest, src, tempdx);
            VESAsetpage(vesapage+1);
            src=(char *)normalize
			(_screen_start + VESAwhat_offset(sy,sx+tempdx) );
            memcpy((dest+tempdx), src, (sdx-tempdx));
         } else { /* all on this page */
            memcpy(dest, src, sdx);
            VESAsetpage(vesapage+1);
         }
         sy++; sdy--;
	 src=(char *)normalize(_screen_start + VESAwhat_offset(sy,sx));
       }
       if (sdy) dest=(char *)normalize(dest + dw);
   }
   return(1);
}
