home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
324.lha
/
BLITTER.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-30
|
15KB
|
691 lines
/*
* BLITTER.c
*
* PROGRAMMER : Gregg A. Tavares
* VERSION : 00.002
* CREATED : 08/22/89
* MODIFIED : 10/25/89
*
* DESCRIPTION
* various BLITTER routines for manipulating graphic images.
*
* NOTES
* Set ClipLeft, ClipTop, ClipWidth and ClipHeight to the
* maximum area you want effected in your destination BitMap.
*
* This code was written with Manx C68k 3.6a with the +l option
* (32 bit ints) I don't know what if anything you'll have to
* change to use it with out that option or with another compiler.
*
* You must also add -L100 to compile with Manx.
*
* COPYWRONG
* I hereby place this code IN THE PUBLIC DOMAIN. Use it, Sell it,
* burn it, frame it, worship it, whatever makes your pants smoke :-)
*
* DISCLAIMER
* If this code causes you or any one you know any problems don't
* come crying to me! ;-)
*
* HISTORY
* 9/6/89 Wednesday
* Made CopyBitMap work non-distructively when copying on the same
* BitMap.
*
*/
short ClipLeft = 0;
short ClipTop = 0;
short ClipHeight = 320;
short ClipWidth = 200;
#include <exec/types.h>
#include <hardware/blit.h>
#include <hardware/dmabits.h>
#include <hardware/custom.h>
#include <graphics/gfx.h>
/* remove the following macros if they are standard in your 'C' */
#ifndef OKAY
#define OKAY 1
#endif
#ifndef NULL
#define NULL 0L
#endif
#ifndef FALSE
#define FALSE 0L
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#ifndef abs
#define abs(value) (((value) < 0) ? -(value) : (value))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef sign
#define sign(value) (((value) > 0) - ((value) < 0))
#endif
#define WAITFORBLITTER while(custom.dmaconr & DMAF_BLTDONE);
/*
#define DEBUG 1
*/
#if DEBUG
typedef struct {
UWORD bltddat;
UWORD bltcon0;
UWORD bltcon1;
UWORD bltafwm;
UWORD bltalwm;
APTR bltcpt;
APTR bltbpt;
APTR bltapt;
APTR bltdpt;
UWORD bltsize;
UWORD bltcmod;
UWORD bltbmod;
UWORD bltamod;
UWORD bltdmod;
UWORD bltcdat;
UWORD bltbdat;
UWORD bltadat;
} BLITTER;
#else
typedef struct Custom BLITTER;
#endif
#if DEBUG
void dorealblit (hardware)
BLITTER *hardware;
{
OwnBlitter ();
WAITFORBLITTER
custom.bltddat = hardware->bltddat;
custom.bltcon0 = hardware->bltcon0;
custom.bltcon1 = hardware->bltcon1;
custom.bltafwm = hardware->bltafwm;
custom.bltalwm = hardware->bltalwm;
custom.bltcpt = hardware->bltcpt;
custom.bltbpt = hardware->bltbpt;
custom.bltapt = hardware->bltapt;
custom.bltdpt = hardware->bltdpt;
custom.bltcmod = hardware->bltcmod;
custom.bltbmod = hardware->bltbmod;
custom.bltamod = hardware->bltamod;
custom.bltdmod = hardware->bltdmod;
custom.bltcdat = hardware->bltcdat;
custom.bltbdat = hardware->bltbdat;
custom.bltadat = hardware->bltadat;
custom.bltsize = hardware->bltsize;
DisownBlitter ();
}
#endif
#if 0
if (!mask && !tsbit && !tebit && !fsbit && !febit) {
/*
* Use Special Quick Blit.
*/
} else if (!mask) {
} else {
#endif
/**************************************************************************
*
* CopyMaskBitMap
*
* SYNOPSIS
* void CopyMaskBitMap (
* struct BitMap *frombm,
* int fromleft,
* int fromtop,
* struct BitMap *tobm,
* int toleft,
* int totop,
* int width,
* int height,
* UBYTE planemask,
* UBYTE *mask
* );
*
* FUNCTION
* Use the blitter to copy from one bitmap to another using a mask
* for transparency. As far as I can tell if you are blitting from
* a one word source into a two word destination (example: pixels
* 10<->13 to 14<->17) you must use two blits (yech!) in the generic
* case. If are always blitting entire shape clipped to word boundries
* then use ShapeBlit().
*
* INPUTS
* frombm = pointer to bitmap to copy from
* fromleft = x position to start copying from
* fromtop = y position to start copying from
* tobm = pointer to bitmap to copy to
* toleft = x position to start copying to
* totop = y position to start copying to
* width = width in pixels of area to copy
* height = height in pixels of area to copy
* planemask = bitmask of planes to effect, bit0 = plane 0, bit1 = plane1...
* mask = optional pointer to a mask bitplane of same size as a
* bitplane in frombm->Planes[0].
*
* BUGS
* NOTE: If you copy from LEFT to RIGHT or TOP to BOTTOM from a bitmap
* to the SAME bitmap and the areas overlap the area will be trashed
* (or smeared)
*
* HISTORY
*
*
* SEE ALSO
* ShapeBlit (), CopyBitMap ()
*/
void CopyMaskBitMap (
frombm,
fromleft,
fromtop,
tobm,
toleft,
totop,
inwidth,
inheight,
planemask,
mask
)
struct BitMap *frombm;
int fromleft;
int fromtop;
struct BitMap *tobm;
int toleft;
int totop;
int inwidth;
int inheight;
UBYTE planemask;
UBYTE *mask;
{
register ULONG fromoffset;
register ULONG tooffset;
BLITTER h;
register BLITTER *hardware =
#if DEBUG
&h;
#else
(struct Custom *)0x0DFF000;
#endif
UWORD fsword;
UWORD tsword;
UWORD newwidth;
UWORD fend;
UWORD tend;
UWORD fsbit;
UWORD tsbit;
UWORD febit;
UWORD tebit;
UWORD frommod;
UWORD tomod;
UWORD shift;
UWORD bltshift;
UWORD fbwidth;
UWORD tbwidth;
UWORD bltwidth;
ULONG toptr;
UWORD size;
UWORD firstmask;
UWORD lastmask;
UWORD othermask;
UWORD ndx;
UWORD depth;
UWORD more;
UBYTE tempmask;
/* --------------------------------------------------------------------- */
int width = inwidth;
int height = inheight;
if (toleft < ClipLeft) {
width = inwidth - (ClipLeft - toleft);
toleft = ClipLeft;
fromleft += inwidth - width;
} else if (toleft > ClipLeft + ClipWidth - inwidth) {
width = (ClipLeft + ClipWidth) - toleft;
}
if (totop < ClipTop) {
height = inheight - (ClipTop - totop);
totop = ClipTop;
fromtop += inheight - height;
} else if (totop > ClipTop + ClipHeight - inheight) {
height = (ClipTop + ClipHeight) - totop;
}
if (width <= 0 || height <= 0) {
return;
}
/* --------------------------------------------------------------------- */
#ifndef DEBUG
OwnBlitter ();
#endif
more = FALSE;
othermask = 0xFFFF;
tempmask = planemask;
depth = min (frombm->Depth, tobm->Depth);
fsword = fromleft >> 4;
tsword = toleft >> 4;
newwidth = width - 1;
fend = fromleft + newwidth;
tend = toleft + newwidth;
fromoffset = fromtop * frombm->BytesPerRow + (fsword << 1);
tooffset = totop * tobm->BytesPerRow + (tsword << 1);
fsbit = fromleft & 0x0F;
tsbit = toleft & 0x0F;
febit = fend & 0x0F;
tebit = tend & 0x0F;
fbwidth = (fend >> 4) - fsword + 1;
tbwidth = (tend >> 4) - tsword + 1;
bltwidth = fbwidth;
shift = (tsbit - fsbit);
if (shift > 15) {
bltwidth += 1;
shift &= 0x0F;
tooffset -= 2;
othermask = 0x0000;
}
firstmask = 0xFFFF >> fsbit;
if (tbwidth > fbwidth) {
more = TRUE;
lastmask = 0xFFFF << shift;
} else {
lastmask = 0xFFFF << (15 - febit);
}
frommod = frombm->BytesPerRow - (bltwidth << 1);
tomod = tobm->BytesPerRow - (bltwidth << 1);
bltshift = shift << 12;
size = (height << 6) | bltwidth;
mask += fromoffset;
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltcon0 = bltshift | 0x0FCA;
hardware->bltcon1 = bltshift;
hardware->bltafwm = firstmask;
hardware->bltalwm = lastmask & othermask;
hardware->bltamod = frommod;
hardware->bltbmod = frommod;
hardware->bltcmod = tomod;
hardware->bltdmod = tomod;
for (ndx = 0; ndx < depth; ndx++) {
if (planemask & 0x01) {
toptr = (ULONG)tobm->Planes[ndx] + (ULONG)tooffset;
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltapt = (APTR)mask;
hardware->bltbpt = (APTR)((ULONG)frombm->Planes[ndx] + fromoffset);
hardware->bltcpt = (APTR)toptr;
hardware->bltdpt = (APTR)toptr;
hardware->bltsize = size;
#if DEBUG
dorealblit (hardware);
#endif
}
planemask >>= 1;
}
if (more) {
bltwidth <<= 1;
newwidth = bltwidth - 2;
fromoffset += newwidth;
mask += newwidth;
tooffset += newwidth;
frommod = frombm->BytesPerRow - (2 << 1);
tomod = tobm->BytesPerRow - (2 << 1);
size = (height << 6) | 2;
firstmask = 0xFFFF << (15 - febit);
lastmask = 0xFFFF >> (((15 - shift) + 1) & 0x0F);
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltafwm = lastmask & firstmask;
hardware->bltalwm = 0x0000;
hardware->bltbmod = frommod;
hardware->bltamod = frommod;
hardware->bltcmod = tomod;
hardware->bltdmod = tomod;
for (ndx = 0; ndx < depth; ndx++) {
if (tempmask & 0x01) {
toptr = (ULONG)tobm->Planes[ndx] + (ULONG)tooffset;
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltapt = (APTR)mask;
hardware->bltbpt = (APTR)((ULONG)frombm->Planes[ndx] + fromoffset);
hardware->bltcpt = (APTR)toptr;
hardware->bltdpt = (APTR)toptr;
hardware->bltsize = size;
#if DEBUG
dorealblit (hardware);
#endif
}
tempmask >>= 1;
}
}
#ifndef DEBUG
DisownBlitter ();
#endif
}
/**************************************************************************
*
* CopyBitMap
*
* SYNOPSIS
* void CopyBitMap (
* struct BitMap *frombm,
* int fromleft,
* int fromtop,
* struct BitMap *tobm,
* int toleft,
* int totop,
* int width,
* int height,
* UBYTE planemask,
* );
*
* FUNCTION
* Use the blitter to copy from one bitmap to another. If the blit
* is word aligned (ie. First pixel is the first bit of the first
* word and last pixel is last bit of the last word) and the same is
* true for both the source and the destination then this routine will
* use a special blit (D=A) which is twice as fast as the normal
* 'clipped' blit (D=AB+~AC).
*
* INPUTS
* frombm = pointer to bitmap to copy from
* fromleft = x position to start copying from
* fromtop = y position to start copying from
* tobm = pointer to bitmap to copy to
* toleft = x position to start copying to
* totop = y position to start copying to
* width = width in pixels of area to copy
* height = height in pixels of area to copy
* planemask = bitmask of planes to effect, bit0 = plane 0, bit1 = plane1...
*
* HISTORY
*
*
* SEE ALSO
* ShapeBlit (), CopyMaskBitMap ()
*/
void CopyBitMap (
frombm,
fromleft,
fromtop,
tobm,
toleft,
totop,
inwidth,
inheight,
planemask,
)
struct BitMap *frombm;
int fromleft;
int fromtop;
struct BitMap *tobm;
int toleft;
int totop;
int inwidth;
int inheight;
UBYTE planemask;
{
register ULONG fromoffset;
register ULONG tooffset;
BLITTER h;
register BLITTER *hardware =
#if DEBUG
&h;
#else
(struct Custom *)0x0DFF000;
#endif
register ULONG newoffset;
UWORD fsword;
UWORD tsword;
UWORD newwidth;
UWORD fend;
UWORD tend;
UWORD fsbit;
UWORD tsbit;
UWORD febit;
UWORD tebit;
UWORD frommod;
UWORD tomod;
UWORD shift;
UWORD bltshift;
UWORD fbwidth;
UWORD tbwidth;
UWORD bltwidth;
ULONG toptr;
UWORD size;
UWORD firstmask;
UWORD lastmask;
UWORD othermask;
UWORD ndx;
UWORD depth;
UWORD control;
/* --------------------------------------------------------------------- */
int width = inwidth;
int height = inheight;
if (toleft < ClipLeft) {
width = inwidth - (ClipLeft - toleft);
toleft = ClipLeft;
fromleft += inwidth - width;
} else if (toleft > ClipLeft + ClipWidth - inwidth) {
width = (ClipLeft + ClipWidth) - toleft;
}
if (totop < ClipTop) {
height = inheight - (ClipTop - totop);
totop = ClipTop;
fromtop += inheight - height;
} else if (totop > ClipTop + ClipHeight - inheight) {
height = (ClipTop + ClipHeight) - totop;
}
if (width <= 0 || height <= 0) {
return;
}
/* --------------------------------------------------------------------- */
depth = min (frombm->Depth, tobm->Depth);
fsword = fromleft >> 4;
tsword = toleft >> 4;
newwidth = width - 1;
fend = fromleft + newwidth;
tend = toleft + newwidth;
fromoffset = fromtop * frombm->BytesPerRow + (fsword << 1);
tooffset = totop * tobm->BytesPerRow + (tsword << 1);
fsbit = fromleft & 0x0F;
tsbit = toleft & 0x0F;
febit = fend & 0x0F;
tebit = tend & 0x0F;
fbwidth = (fend >> 4) - fsword + 1;
tbwidth = (tend >> 4) - tsword + 1;
bltwidth = fbwidth;
if (!fsbit && !tsbit && febit == 15 && tebit == 15) {
frommod = frombm->BytesPerRow - (bltwidth << 1);
tomod = tobm->BytesPerRow - (bltwidth << 1);
size = (height << 6) | bltwidth;
if (fromoffset < tooffset) {
control = 0x0002;
newoffset = (bltwidth - 1) << 1;
fromoffset += frombm->BytesPerRow * (height - 1) + newoffset;
tooffset += tobm->BytesPerRow * (height - 1) + newoffset;
} else {
control = 0x0000;
}
#ifndef DEBUG
OwnBlitter ();
WAITFORBLITTER
#endif
hardware->bltcon0 = 0x09F0;
hardware->bltcon1 = control;
hardware->bltafwm = 0xFFFF;
hardware->bltalwm = 0xFFFF;
hardware->bltamod = frommod;
hardware->bltdmod = tomod;
for (ndx = 0; ndx < depth; ndx++) {
if (planemask & 0x01) {
toptr = (ULONG)tobm->Planes[ndx] + (ULONG)tooffset;
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltapt = (APTR)((ULONG)frombm->Planes[ndx] + fromoffset);
hardware->bltdpt = (APTR)toptr;
hardware->bltsize = size;
#if DEBUG
dorealblit (hardware);
#endif
}
planemask >>= 1;
}
#ifndef DEBUG
DisownBlitter ();
#endif
} else {
BltBitMap (frombm, fromleft, fromtop,
tobm, toleft, totop,
width, height, 0xC0, 0xFF, NULL);
#if 0
shift = (tsbit - fsbit);
if (shift > 15) {
bltwidth += 1;
shift &= 0x0F;
tooffset -= 2;
othermask = 0x0000;
}
firstmask = 0xFFFF >> fsbit;
if (tbwidth > fbwidth) {
more = TRUE;
lastmask = 0xFFFF << shift;
} else {
lastmask = 0xFFFF << (15 - febit);
}
frommod = frombm->BytesPerRow - (bltwidth << 1);
tomod = tobm->BytesPerRow - (bltwidth << 1);
bltshift = shift << 12;
size = (height << 6) | bltwidth;
mask += fromoffset;
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltcon0 = bltshift | 0x0FCA;
hardware->bltcon1 = bltshift;
hardware->bltafwm = firstmask;
hardware->bltalwm = lastmask & othermask;
hardware->bltamod = frommod;
hardware->bltbmod = frommod;
hardware->bltcmod = tomod;
hardware->bltdmod = tomod;
for (ndx = 0; ndx < depth; ndx++) {
if (planemask & 0x01) {
toptr = (ULONG)tobm->Planes[ndx] + (ULONG)tooffset;
#ifndef DEBUG
WAITFORBLITTER
#endif
hardware->bltapt = (APTR)mask;
hardware->bltbpt = (APTR)((ULONG)frombm->Planes[ndx] + fromoffset);
hardware->bltcpt = (APTR)toptr;
hardware->bltdpt = (APTR)toptr;
hardware->bltsize = size;
#if DEBUG
dorealblit (hardware);
#endif
}
planemask >>= 1;
}
#endif
}
}