/*
 *   This include file includes the defines for all the blitter functions.
 *   It only allows use of the `blit' operations; for area fills or line
 *   drawing, it will need to be extended.
 *
 *   Information gleaned from the Hardware Reference Manual.
 */
#define BLTADD (0xdff040L)
/*
 *   This structure contains everything we need to know.
 *   Do not do a structure copy into this!  Instead, assign
 *   each field.  The last field assigned must be bltsize; that
 *   starts up the blitter.  Also note that all of these are
 *   write only, and you can't read them.
 */
struct bltstruct {
   short con0 ;
   short con1 ;
   short afwm ;
   short alwm ;
   short *csource, *bsource, *asource, *dsource ;
   short bltsize ;
   short dmy1, dmy2, dmy3 ;
   short cmod, bmod, amod, dmod ;
} *blitter = BLTADD ;
/*
 *   We need an array which tells what to use for all 256 possible operations.
 */
#define USEA (0x8)
#define USEB (0x4)
#define USEC (0x2)
#define USED (0x1)
char touse[256] ;
char fwma[16] ;
char lwma[16] ;
/*
 *   Call initblitdata() once on startup before you ever call blit.
 */
initblitdata() {
   register int i ;
   register int s ;

   for (i=0; i<256; i++) {
      s = USED ;
      if ((i >> 4) != (i & 15))
         s += USEA ;
      if (((i >> 2) & 51) != (i & 51))
         s += USEB ;
      if (((i >> 1) & 85) != (i & 85))
         s += USEC ;
      touse[i] = s ;
   }
   s = 0xffff ;
   for (i=0; i<16; i++) {
      fwma[i] = s ;
      s = (s >> 1) & ~0x8000 ;
      lwma[i] = 0xffff - s ;
   }
}
/*
 *   This is the major user interface.  Takes addresses and offsets for
 *   all four locations, a modulo and sizes, and a function.
 *   Assumes the modulos for all sources and destination are the same.
 *   You might want to add some arguments or delete some.
 *
 *   All arguments are in pixels (except the addresses and function.)
 *
 *   Before you call this routine, call OwnBlitter(); after you have
 *   called it as many times as you need, call DisownBlitter().  Remember
 *   that you cannot do any printf's or anything else which requires the
 *   blitter when you own the blitter, so be careful with the debug code.
 *   The machine will lock but will not crash.
 */
blit(aaddress, ax, ay,
     baddress, bx, by,
     caddress, cx, cy,
     daddress, dx, dy,
     modulo, xsize, ysize, function)
short *aaddress, *baddress, *caddress, *daddress ;
int ax, ay, bx, by, cx, cy, dx, dy, modulo,
    xsize, ysize, function ;
{
   short *t ;

/*
 *   Divide the modulo by 16 because we need words.
 */
   modulo >>= 4 ;
/*
 *   Wait for the blitter to finish whatever it needs to do.
 */
   WaitBlit() ;
/*
 *   Calculate the real addresses for d and c.
 */
   blitter->dsource = daddress + modulo * dy + (dx >> 4) ;
   blitter->csource = caddress + modulo * cy + (cx >> 4) ;
/*
 *   Mask out the low order bits of dx; add these to the xsize.  (The
 *   first bits will be masked using the first word mask.)
 */
   dx &= 15 ;
   xsize += dx ;
   blitter->afwm = fwma[dx] ;
   blitter->alwm = lwma[(xsize - 1) & 15] ;
/*
 *   Now calculate the shifts for the a and b operands.  The barrel
 *   shifter counts appear to be to the left instead of the more
 *   intuitive to the right.  Note that I take dx into account.
 */
   t = aaddress + modulo * ay + (ax >> 4) ;
   ax = dx - (ax & 15) ;
   if (ax < 0) {
      t++ ;
      ax += 16 ;
   }
   blitter->asource = t ;
   t = baddress + modulo * by + (bx >> 4) ;
   bx = dx - (bx & 15) ;
   if (bx < 0) {
      t++ ;
      bx += 16 ;
   }
   blitter->bsource = t ;
/*
 *   Now calculate the two control words.  If you want to do
 *   the addresses in reverse order, set the appropriate bit in con1.
 */
   blitter->con0 = (ax << 12) + (touse[function] << 8) + function ;
   blitter->con1 = (bx << 12) ;
/*
 *   Calculate the final total xsize in words, and the modulos.  The
 *   modulos are in bytes when written from the 68000.
 */
   xsize = (xsize + 15) >> 4 ;
   blitter->amod = blitter->bmod = blitter->cmod = blitter->dmod =
      2 * (modulo - xsize) ;
/*
 *   This last assignment starts up the blitter.
 */
   blitter->bltsize = (ysize << 6) + xsize ;
}
