/* myblit.c - definition of my blitter code */
/*	It will blit from a source through a mask to a destination bitmap */
/*      The mask must have the word before and after it clear */

#include <exec/types.h>
#ifdef BLTDEBUG
#include <stdio.h>
#endif
#include <hardware/custom.h>
#include <hardware/blit.h>
#include <graphics/gfx.h>

#define BLTADD (0xdff040)

/*
 *   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 {
	WORD con0;
	WORD con1;
	WORD afwm;
	WORD alwm;
	WORD *csource, *bsource, *asource, *dsource;
	WORD bltsize;
	WORD dmy1, dmy2, dmy3;
	WORD cmod, bmod, amod, dmod;
};
static struct BltStruct *Blitter = (struct BltStruct *)BLTADD;

static UBYTE boffset[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

void
BltBitMask(sbm,sx,sy,dbm,dx,dy,mbm,mx,my,mpno,xsize,ysize)
struct BitMap *sbm, *dbm, *mbm;
int sx,sy,dx,dy,mx,my,mpno,xsize,ysize;
{
	WORD *splane, *dplane, *mplane;
	WORD *aaddr,*baddr,*daddr;
	int ashft, bshft;
	UWORD afwm,alwm;
	int smodulo, dmodulo, mmodulo;
	int i;

	smodulo = ((sbm->BytesPerRow) + 1) >> 1;
	dmodulo = ((dbm->BytesPerRow) + 1) >> 1;
	mmodulo = ((mbm->BytesPerRow) + 1) >> 1;

	splane = (WORD *) (sbm->Planes[0]);
	dplane = (WORD *) (dbm->Planes[0]);
	mplane = (WORD *) (mbm->Planes[mpno]);

	daddr = dplane + dmodulo * dy + (dx >> 4);
	dx &= 15;
	aaddr = mplane + mmodulo * my + (mx >> 4);
	mx &= 15;
	baddr = splane + smodulo * sy + (sx >> 4);
	sx &= 15;
#ifdef BLTDEBUG
printf("new - spl = %x, dpl = %x, mpl = %x\n",splane,dplane,mplane);
printf("smod = %x, dmod = %x, mmod = %x\n",smodulo,dmodulo,mmodulo);
printf("aa=%x, ba=%x, da=%x, (a)mx=%d, (b)sx=%d, dx=%d, xs=%d\n",
	(aaddr - mplane - mmodulo * my),
	(baddr - splane - smodulo * sy),
	(daddr - dplane - dmodulo * dy),mx,sx,dx,xsize);
#endif
	ashft = dx - mx;
	bshft = dx - sx;
	afwm = ((unsigned) 0xffff) >> mx;
	alwm = 0xffff << (16 - ((mx + xsize) & 15));
	xsize = (xsize + dx + 15) >> 4;
	if ((ashft < 0) || (bshft < 0)) {
		daddr--;
		xsize++;
		if (ashft < 0) ashft += 16;
		else aaddr--;
		if (bshft < 0) bshft += 16;
		else baddr--;
	}
#ifdef BLTDEBUG
printf("aaddr = %x, baddr = %x, daddr = %x\n",aaddr,baddr,daddr);
printf("aa=%x, ba=%x, da=%x, fw=%x, lw=%x, as=%d, bs=%d, xs=%d\n",
	(aaddr - mplane - mmodulo * my),
	(baddr - splane - smodulo * sy),
	(daddr - dplane - dmodulo * dy),afwm,alwm,ashft,bshft,xsize);
#endif
	OwnBlitter();

	WaitBlit();
	Blitter->asource = aaddr;
	Blitter->bsource = baddr;
	Blitter->csource = Blitter->dsource = daddr;
	Blitter->amod = (mmodulo - xsize) << 1;
	Blitter->bmod = (smodulo - xsize) << 1;
	Blitter->cmod = Blitter->dmod = (dmodulo - xsize) << 1;
	Blitter->afwm = afwm;
	Blitter->alwm = alwm;
	Blitter->con0 = (ashft << 12) | (0xf << 8) | 0xca;
	Blitter->con1 = (bshft << 12);
	Blitter->bltsize = (ysize << 6) | xsize;

	for (i = 1; i < dbm->Depth; i++) {
		WaitBlit();
		Blitter->asource = aaddr;
		Blitter->bsource = baddr +
			(((WORD *)sbm->Planes[i]) - ((WORD *)sbm->Planes[0]));
		Blitter->csource = Blitter->dsource = daddr +
			(((WORD *)dbm->Planes[i]) - ((WORD *)dbm->Planes[0]));
		Blitter->bltsize = (ysize << 6) | xsize;
	}

	DisownBlitter();
}

void
mywritepixel1(bm,x,y)
struct BitMap *bm;
int x,y;
{
	register int offset;
	register UBYTE bits;

	offset = y * bm->BytesPerRow + (x >> 3);
	bits = boffset[x & 7];

	bm->Planes[0][offset] |= bits;
}

void
mywritepixel(bm,x,y,color)
struct BitMap *bm;
int x,y;
{
	register int offset;
	register int i;
	UBYTE bits,nbits;

	offset = y * bm->BytesPerRow + (x >> 3);
	bits = boffset[x & 7];
	nbits = ~bits;

	for (i=0; i < bm->Depth; i++) {
		if (color & 0x01) bm->Planes[i][offset] |= bits;
		else bm->Planes[i][offset] &= nbits;
		color >>= 1;
	}
}

void
myblank(bm,y1,y2)
struct BitMap *bm;
int y1,y2;
{
	register int offset, bytes;
	register int i;

	offset = y1 * bm->BytesPerRow;
	bytes = (y2 - y1) * bm->BytesPerRow;

	for (i=0; i < bm->Depth; i++)
		BltClear(&(bm->Planes[i][offset]),bytes,0);
}

void
mylinecopy(bm,starty,len,delta)
struct BitMap *bm;
int starty, len, delta;
{
	UBYTE *loc1, *loc2, *stop;
	int i;

	for(i=0; i < bm->Depth; i++) {
		loc1 = &(bm->Planes[i][starty*bm->BytesPerRow]);
		stop = loc1 + len*bm->BytesPerRow;
		loc2 = loc1 + delta*bm->BytesPerRow;
		while (loc1 < stop) *(loc2++) = *(loc1++);
	}
}

void
myblankc(bm,y1,y2,color)
struct BitMap *bm;
int y1,y2,color;
{
	register int i;
	WORD *daddr;
	int dmodulo;
	
	dmodulo = ((bm->BytesPerRow) + 1) >> 1;

	daddr = (WORD *) (bm->Planes[0]);
	daddr += dmodulo * y1;

	OwnBlitter();
	WaitBlit();

	Blitter->dsource = daddr;
	Blitter->dmod = 0;
	if (color & 1)
		Blitter->con0 = (1 << 8) | (0xff);
	else	Blitter->con0 = (1 << 8);
	Blitter->bltsize = ((y2-y1) << 6) | dmodulo;
	color >>= 1;
	
	for (i = 1; i < bm->Depth; i++) {
		WaitBlit();
		Blitter->dsource = daddr +
			(((WORD *)bm->Planes[i]) - ((WORD *)bm->Planes[0]));
		if (color & 1)
			Blitter->con0 = (1 << 8) | (0xff);
		else	Blitter->con0 = (1 << 8);
		color >>= 1;
		Blitter->bltsize = ((y2 - y1) << 6) | dmodulo;
	}
	
	DisownBlitter();
}
