home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat 1999 Spring
/
macformat-077.iso
/
Shareware Plus
/
Development
/
SpriteWorld 2.2
/
SpriteWorld files
/
Sources
/
BlitPixie8Bit.c
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1999-01-14
|
37.8 KB
|
1,403 lines
|
[
TEXT/CWIE
]
///--------------------------------------------------------------------------------------
// BlitPixie8Bit.c
//
// Ideas and code snippets contributed by:
// Ben Sharpe, Brigham Stevens, Sean Callahan, Joe Britt and Tim Collins
//
// Portions are copyright: © 1991-94 Tony Myles
//
// Description: Implementation of BlitPixie8Bit - a fast 8-bit blitter
///--------------------------------------------------------------------------------------
#ifndef __SWCOMMON__
#include "SWCommonHeaders.h"
#endif
#ifndef __SPRITEWORLDUTILS__
#include "SpriteWorldUtils.h"
#endif
#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
#ifndef __OSUTILS__
#include <OSUtils.h>
#endif
#ifndef __QUICKDRAW__
#include <Quickdraw.h>
#endif
#ifndef __QDOFFSCREEN__
#include <QDOffscreen.h>
#endif
#ifndef __SPRITEWORLD__
#include "SpriteWorld.h"
#endif
#ifndef __SPRITEFRAME__
#include "SpriteFrame.h"
#endif
#ifndef __BLITPIXIE__
#include "BlitPixie.h"
#endif
#ifndef __SPRITECOMPILER__
#include "SpriteCompiler.h"
#endif
extern SInt8 gSWmmuMode;
///--------------------------------------------------------------------------------------
// BlitPixie8BitRectDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void BlitPixie8BitRectDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect* srcRect,
Rect* dstRect)
{
Rect srcBlitRect = *srcRect;
Rect dstBlitRect = *dstRect;
unsigned long numBytesPerRow;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
START_32_BIT_MODE
// calculate the number of bytes in each row to be copied
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixie8Bit(
// calculate the address of the first byte of the source
(PixelChunkPtr)(srcFrameP->frameBaseAddr +
(srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) +
srcBlitRect.left),
// calculate the address of the first byte of the destination
(PixelChunkPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// calculate the number of rows to blit
dstBlitRect.bottom - dstBlitRect.top,
// number of bytes in a row (also the number of pixels to be copied)
numBytesPerRow,
srcFrameP->frameRowBytes,
dstFrameP->frameRowBytes);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// BP8BitInterlacedRectDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void BP8BitInterlacedRectDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect* srcRect,
Rect* dstRect)
{
Rect srcBlitRect = *srcRect;
Rect dstBlitRect = *dstRect;
unsigned long numBytesPerRow, numRowsToCopy;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
BP_CLIP_RECT_INTERLACED(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
numRowsToCopy = dstBlitRect.bottom - dstBlitRect.top;
numRowsToCopy = (numRowsToCopy >> 1) + (numRowsToCopy & 1);
if (numRowsToCopy < 1)
return;
START_32_BIT_MODE
// calculate the number of bytes in a row
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixie8Bit(
// calculate the address of the first byte of the source
(PixelChunkPtr)(srcFrameP->frameBaseAddr +
(srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) +
srcBlitRect.left),
// calculate the address of the first byte of the destination
(PixelChunkPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// number of rows to copy, already calculated for Interlaced mode
numRowsToCopy,
// number of bytes in a row (duh!)
numBytesPerRow,
srcFrameP->frameRowBytes<<1,
dstFrameP->frameRowBytes<<1);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// BlitPixie8BitMaskDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void BlitPixie8BitMaskDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect *srcRect,
Rect *dstRect)
{
Rect dstBlitRect = *dstRect;
Rect srcBlitRect = *srcRect;
unsigned long numBytesPerRow, srcBaseOffset;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT(srcFrameP->maskPort != NULL);
BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
START_32_BIT_MODE
// calculate the offset to the first byte of the source
srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top -
srcFrameP->frameRect.top] + srcBlitRect.left;
// calculate the number of bytes in a row
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixieMask8Bit(
// calculate the address of the first byte of the source
(PixelPtr)(srcFrameP->frameBaseAddr + srcBaseOffset),
// calculate the address of the first byte of the destination
(PixelPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// calculate the address of the first byte of the mask
(PixelPtr)(srcFrameP->maskBaseAddr + srcBaseOffset),
// calculate the number of rows to blit
dstBlitRect.bottom - dstBlitRect.top,
// number of bytes in a row (duh!)
numBytesPerRow,
srcFrameP->frameRowBytes,
dstFrameP->frameRowBytes);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// BlitPixie8BitPartialMaskDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void BlitPixie8BitPartialMaskDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect *srcRect,
Rect *dstRect)
{
Rect dstBlitRect = *dstRect;
Rect srcBlitRect = *srcRect;
unsigned long numBytesPerRow, srcBaseOffset;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT(srcFrameP->maskPort != NULL);
BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
START_32_BIT_MODE
// calculate the offset to the first byte of the source
srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top] +
srcBlitRect.left;
// calculate the number of bytes in a row
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixiePartialMask8Bit(
// calculate the address of the first byte of the source
(PixelPtr)(srcFrameP->frameBaseAddr + srcBaseOffset),
// calculate the address of the first byte of the destination
(PixelPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// calculate the address of the first byte of the mask
(PixelPtr)(srcFrameP->maskBaseAddr + srcBaseOffset),
// calculate the number of rows to blit
dstBlitRect.bottom - dstBlitRect.top,
// number of bytes in a row (duh!)
numBytesPerRow,
srcFrameP->frameRowBytes,
dstFrameP->frameRowBytes);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// BP8BitInterlacedMaskDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void BP8BitInterlacedMaskDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect* srcRect,
Rect* dstRect)
{
Rect srcBlitRect = *srcRect;
Rect dstBlitRect = *dstRect;
unsigned long numBytesPerRow, numRowsToCopy, srcBaseOffset;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT(srcFrameP->maskPort != NULL);
BP_CLIP_RECT_INTERLACED(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
numRowsToCopy = dstBlitRect.bottom - dstBlitRect.top;
numRowsToCopy = (numRowsToCopy >> 1) + (numRowsToCopy & 1);
if (numRowsToCopy < 1)
return;
START_32_BIT_MODE
// calculate the offset to the first byte of the source
srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top] +
srcBlitRect.left;
// calculate the number of bytes in a row
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixieMask8Bit(
// calculate the address of the first byte of the source
(PixelPtr)(srcFrameP->frameBaseAddr + srcBaseOffset),
// calculate the address of the first byte of the destination
(PixelPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// calculate the address of the first byte of the mask
(PixelPtr)(srcFrameP->maskBaseAddr + srcBaseOffset),
// number of rows to copy, already calculated for Interlaced mode
numRowsToCopy,
// number of bytes in a row (duh!)
numBytesPerRow,
srcFrameP->frameRowBytes<<1,
dstFrameP->frameRowBytes<<1);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// BP8BitInterlacedPartialMaskDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void BP8BitInterlacedPartialMaskDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect* srcRect,
Rect* dstRect)
{
Rect srcBlitRect = *srcRect;
Rect dstBlitRect = *dstRect;
unsigned long numBytesPerRow, numRowsToCopy, srcBaseOffset;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT(srcFrameP->maskPort != NULL);
BP_CLIP_RECT_INTERLACED(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
numRowsToCopy = dstBlitRect.bottom - dstBlitRect.top;
numRowsToCopy = (numRowsToCopy >> 1) + (numRowsToCopy & 1);
if (numRowsToCopy < 1)
return;
START_32_BIT_MODE
// calculate the offset to the first byte of the source
srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top] +
srcBlitRect.left;
// calculate the number of bytes in a row
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixiePartialMask8Bit(
// calculate the address of the first byte of the source
(PixelPtr)(srcFrameP->frameBaseAddr + srcBaseOffset),
// calculate the address of the first byte of the destination
(PixelPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// calculate the address of the first byte of the mask
(PixelPtr)(srcFrameP->maskBaseAddr + srcBaseOffset),
// number of rows to copy, already calculated for Interlaced mode
numRowsToCopy,
// number of bytes in a row (duh!)
numBytesPerRow,
srcFrameP->frameRowBytes<<1,
dstFrameP->frameRowBytes<<1);
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// CompiledSprite8BitDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void CompiledSprite8BitDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect *srcRect,
Rect *dstRect)
{
#if SW_PPC
#pragma unused(srcFrameP, dstFrameP, srcRect, dstRect)
#else
Rect dstBlitRect = *dstRect;
Rect srcBlitRect = *srcRect;
SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
SW_ASSERT(srcFrameP->frameBlitterP != NULL);
// we first check to see if any clipping will be necessary, then
// we determine whether or not we can use the compiled blitter. we must
// do this since the compiled blitter cannot handle clipping.
BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
START_32_BIT_MODE
// If we didn't have to clip the sprite, we can call the compiled blitter.
// Hopefully this will be the most common case (i.e. the sprites will be entirely
// on the screen more often than not)
if (srcBlitRect.top == srcFrameP->frameRect.top &&
srcBlitRect.bottom == srcFrameP->frameRect.bottom &&
srcBlitRect.left == srcFrameP->frameRect.left &&
srcBlitRect.right == srcFrameP->frameRect.right)
{
(*srcFrameP->frameBlitterP)(
srcFrameP->frameRowBytes,
dstFrameP->frameRowBytes,
srcFrameP->frameBaseAddr +
srcFrameP->scanLinePtrArray[0] + srcRect->left, // 0 'cause it always starts at top
dstFrameP->frameBaseAddr +
dstFrameP->scanLinePtrArray[dstRect->top] + dstRect->left);
}
else
{
unsigned long numBytesPerRow;
unsigned long srcBaseOffset;
// calculate the offset to the first byte of the source
srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top-srcFrameP->frameRect.top] +
srcBlitRect.left;
// calculate the number of bytes in a row
numBytesPerRow = (dstBlitRect.right - dstBlitRect.left);
BlitPixieMask8Bit(
// calculate the address of the first byte of the source
(PixelPtr)(srcFrameP->frameBaseAddr + srcBaseOffset),
// calculate the address of the first byte of the destination
(PixelPtr)(dstFrameP->frameBaseAddr +
(dstFrameP->scanLinePtrArray[dstBlitRect.top]) + dstBlitRect.left),
// calculate the address of the first byte of the mask
(PixelPtr)(srcFrameP->maskBaseAddr + srcBaseOffset),
// calculate the number of rows to blit
dstBlitRect.bottom - dstBlitRect.top,
// number of bytes in a row (duh!)
numBytesPerRow,
srcFrameP->frameRowBytes,
dstFrameP->frameRowBytes);
}
END_32_BIT_MODE
#endif
}
#pragma mark -
#pragma mark *** Misc Routines:
///--------------------------------------------------------------------------------------
// BlitPixie8BitGetPixel
///--------------------------------------------------------------------------------------
SW_FUNC unsigned char BlitPixie8BitGetPixel(
FramePtr srcFrameP,
Point thePoint )
{
unsigned long srcBaseOffset;
unsigned char theColor;
SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
START_32_BIT_MODE
srcBaseOffset = srcFrameP->scanLinePtrArray[thePoint.v] +
thePoint.h+srcFrameP->frameRect.left;
theColor = *((unsigned char*)(srcFrameP->frameBaseAddr + srcBaseOffset));
END_32_BIT_MODE
return theColor;
}
///--------------------------------------------------------------------------------------
// BlitPixie8BitSetPixel
///--------------------------------------------------------------------------------------
SW_FUNC void BlitPixie8BitSetPixel(
FramePtr srcFrameP,
Point thePoint,
unsigned char theColor)
{
unsigned long srcBaseOffset;
SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
if ((thePoint.h >= 0) &&
(thePoint.h < srcFrameP->frameRect.right-srcFrameP->frameRect.left) &&
(thePoint.v >= 0) &&
(thePoint.v < srcFrameP->frameRect.bottom-srcFrameP->frameRect.top) )
{
START_32_BIT_MODE
srcBaseOffset = srcFrameP->scanLinePtrArray[thePoint.v] +
thePoint.h + srcFrameP->frameRect.left;
*((unsigned char*)(srcFrameP->frameBaseAddr + srcBaseOffset)) = theColor;
END_32_BIT_MODE
}
}
///--------------------------------------------------------------------------------------
// SWAnimate8BitStarField
///--------------------------------------------------------------------------------------
SW_FUNC void SWAnimate8BitStarField(
SpriteWorldPtr spriteWorldP,
StarArray *starArray,
short numStars,
unsigned short backColor)
{
short curStar;
short horizOffset, vertOffset; // Offset from window to work area
FramePtr windFrameP = spriteWorldP->windowFrameP;
FramePtr workFrameP = spriteWorldP->workFrameP;
unsigned long srcBaseOffset;
SW_ASSERT(windFrameP->isFrameLocked && workFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->pixelDepth == 8);
START_32_BIT_MODE
// Stores offset if spriteWorld is smaller than window
horizOffset = windFrameP->frameRect.left;
vertOffset = windFrameP->frameRect.top;
for (curStar = 0; curStar < numStars; curStar++)
{
// Make sure we aren't erasing part of a sprite
if (starArray[curStar].needsToBeErased)
{
srcBaseOffset = windFrameP->scanLinePtrArray[starArray[curStar].oldVertLoc] +
starArray[curStar].oldHorizLoc;
*((unsigned char*)(windFrameP->frameBaseAddr + srcBaseOffset)) = backColor;
}
// Make sure we aren't going to draw over a sprite
srcBaseOffset = workFrameP->scanLinePtrArray[starArray[curStar].vertLoc - vertOffset] +
starArray[curStar].horizLoc - horizOffset;
if ( *((unsigned char*)(workFrameP->frameBaseAddr + srcBaseOffset)) == backColor)
{
// Draw the new star position
srcBaseOffset = windFrameP->scanLinePtrArray[starArray[curStar].vertLoc] +
starArray[curStar].horizLoc;
*((unsigned char*)(windFrameP->frameBaseAddr + srcBaseOffset)) =
starArray[curStar].color;
starArray[curStar].needsToBeErased = true;
}
else
{
starArray[curStar].needsToBeErased = false;
}
}
END_32_BIT_MODE
}
///--------------------------------------------------------------------------------------
// BlitPixie8BitFlipSprite
///--------------------------------------------------------------------------------------
SW_FUNC void BlitPixie8BitFlipSprite(
SpritePtr srcSpriteP )
{
FramePtr curFrameP;
unsigned char holdPixel;
short frameCounter,
scanLineCounter,
halfWidth,
leftPixel,
rightPixel,
frameLeft;
GDHandle currentGDH;
GWorldPtr currentGWorld;
frameCounter = srcSpriteP->numFrames;
while (frameCounter--)
{
START_32_BIT_MODE
curFrameP = srcSpriteP->frameArray[frameCounter];
SW_ASSERT(curFrameP->isFrameLocked);
SW_ASSERT((*curFrameP->framePort->portPixMap)->pixelSize == 8);
frameLeft = curFrameP->frameRect.left;
halfWidth = (curFrameP->frameRect.right - curFrameP->frameRect.left)/2;
scanLineCounter = curFrameP->numScanLines;
while (scanLineCounter--)
{
rightPixel = leftPixel = halfWidth;
while (leftPixel--)
{
holdPixel = *((unsigned char*)(curFrameP->frameBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + leftPixel+frameLeft));
if ( holdPixel != *((unsigned char*)(curFrameP->frameBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + rightPixel+frameLeft)) )
{
*((unsigned char*)(curFrameP->frameBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + leftPixel+frameLeft)) =
*((unsigned char*)(curFrameP->frameBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + rightPixel+frameLeft));
*((unsigned char*)(curFrameP->frameBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + rightPixel+frameLeft)) =
holdPixel;
}
rightPixel++;
}
}
if ( curFrameP->maskPort != NULL )
{
scanLineCounter = curFrameP->numScanLines;
while (scanLineCounter--)
{
rightPixel = leftPixel = halfWidth;
while (leftPixel--)
{
holdPixel = *((unsigned char*)(curFrameP->maskBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + leftPixel+frameLeft));
if ( holdPixel != *((unsigned char*)(curFrameP->maskBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] + rightPixel+frameLeft)) )
{
*((unsigned char*)(curFrameP->maskBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] +
leftPixel+frameLeft)) =
*((unsigned char*)(curFrameP->maskBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] +
rightPixel+frameLeft));
*((unsigned char*)(curFrameP->maskBaseAddr +
curFrameP->scanLinePtrArray[scanLineCounter] +
rightPixel+frameLeft)) = holdPixel;
}
rightPixel++;
}
}
}
END_32_BIT_MODE
if ( curFrameP->maskRgn != NULL && curFrameP->maskPort != NULL )
{
GetGWorld( ¤tGWorld, ¤tGDH );
SetGWorld( curFrameP->maskPort, NULL );
InvertRect( &(curFrameP->frameRect) );
(void)SWCreateRegionFromGWorldAndRect( &(curFrameP->maskRgn),
curFrameP->maskPort, &(curFrameP->frameRect) );
SWSetFrameMaskRgn(curFrameP, curFrameP->maskRgn);
InvertRect( &(curFrameP->frameRect) );
SetGWorld( currentGWorld, currentGDH );
}
}
}
#pragma mark -
#pragma mark *** PowerPC:
#if SW_PPC
///--------------------------------------------------------------------------------------
// BlitPixie8Bit
///--------------------------------------------------------------------------------------
// Since this blit routine just does straight copying and requires no boolean operations,
// we can make use of the floating point registers on the Power PC. This means we
// can blit a double, 8 bytes at a time, rather than a long. This makes the blitter
// almost twice as fast when this is done. We could speed this up even more by unrolling
// the loop for big blits, but it would make the code much less readable.
// Note that we only use doubles to copy only when we are 4-byte aligned for both
// source and destination. Otherwise PPC 603, 604 and laters will run slower.
// (Yes, you can use doubles as long as you're aligned to a 4-byte boundary, even if it's
// not an 8-byte boundary!)
void BlitPixie8Bit(
PixelChunkPtr srcPixelPTemp,
PixelChunkPtr dstPixelPTemp,
register unsigned long rowsToCopy,
register unsigned long numBytesPerRow,
register unsigned long srcOffset,
register unsigned long dstOffset)
{
if (((unsigned long)srcPixelPTemp & 3) || ((unsigned long)dstPixelPTemp & 3))
{
register long index;
register PixelChunkPtr srcPixelP = srcPixelPTemp;
register PixelChunkPtr dstPixelP = dstPixelPTemp;
register PixelChunkPtr startSrcPixelP;
register PixelChunkPtr startDstPixelP;
startSrcPixelP = srcPixelP;
startDstPixelP = dstPixelP;
while (rowsToCopy--)
{
register fourblits = (numBytesPerRow >> 2);
srcPixelP = startSrcPixelP;
dstPixelP = startDstPixelP;
for (index = 0; index < fourblits; index++)
{
register unsigned long temp1;
temp1 = srcPixelP[index];
dstPixelP[index] = temp1;
}
srcPixelP += fourblits;
dstPixelP += fourblits;
if (numBytesPerRow & 0x2)
*((unsigned short *) dstPixelP)++ = *((unsigned short *) srcPixelP)++;
if (numBytesPerRow & 0x1)
*((unsigned char *)dstPixelP)++ = *((unsigned char *)srcPixelP)++;
// bump to next row
(char *)startSrcPixelP += srcOffset;
(char *)startDstPixelP += dstOffset;
}
}
else
{
register long index;
register double *startSrcPixelP;
register double *startDstPixelP;
register double *srcPixelP = (double *)srcPixelPTemp;
register double *dstPixelP = (double *)dstPixelPTemp;
startSrcPixelP = srcPixelP;
startDstPixelP = dstPixelP;
while (rowsToCopy--)
{
register eightblits = (numBytesPerRow >> 3);
srcPixelP = startSrcPixelP;
dstPixelP = startDstPixelP;
for (index = 0; index < eightblits; index++)
{
dstPixelP[index] = srcPixelP[index];
}
srcPixelP += eightblits;
dstPixelP += eightblits;
if (numBytesPerRow & 0x4)
*((unsigned long *) dstPixelP)++ = *((unsigned long *) srcPixelP)++;
if (numBytesPerRow & 0x2)
*((unsigned short *) dstPixelP)++ = *((unsigned short *) srcPixelP)++;
if (numBytesPerRow & 0x1)
*((unsigned char *)dstPixelP)++ = *((unsigned char *)srcPixelP)++;
// bump to next row
(char *)startSrcPixelP += srcOffset;
(char *)startDstPixelP += dstOffset;
}
}
}
///--------------------------------------------------------------------------------------
// BlitPixieMask8Bit
///--------------------------------------------------------------------------------------
void BlitPixieMask8Bit(
register PixelPtr srcPixelP,
register PixelPtr dstPixelP,
register PixelPtr maskPixelP,
register unsigned long rowsToCopy,
register unsigned long numBytesPerRow,
register unsigned long srcOffset,
register unsigned long dstOffset)
{
register long index;
register PixelPtr startSrcPixelP;
register PixelPtr startDstPixelP;
register PixelPtr startMaskPixelP;
startSrcPixelP = srcPixelP;
startDstPixelP = dstPixelP;
startMaskPixelP = maskPixelP;
while (rowsToCopy--)
{
register fourblits = (numBytesPerRow >> 2);
srcPixelP = startSrcPixelP;
dstPixelP = startDstPixelP;
maskPixelP = startMaskPixelP;
for (index = 0; index < fourblits; index++)
{
register unsigned long temp1;
temp1 = dstPixelP[index] & maskPixelP[index] | srcPixelP[index];
dstPixelP[index] = temp1;
}
srcPixelP += fourblits;
dstPixelP += fourblits;
maskPixelP += fourblits;
if (numBytesPerRow & 0x2)
{
register unsigned short temp1;
temp1 = (*((unsigned short *) dstPixelP)) & (*((unsigned short *) maskPixelP)++) |
*((unsigned short *) srcPixelP)++;
(*((unsigned short *) dstPixelP)++) = temp1;
}
if (numBytesPerRow & 0x1)
{
register unsigned char temp1;
temp1 = (*((unsigned char *) dstPixelP)) & (*((unsigned char *) maskPixelP)++) |
*((unsigned char *) srcPixelP)++;
(*((unsigned char *) dstPixelP)++) = temp1;
}
// bump to next row
startSrcPixelP = (PixelPtr)(((char*)startSrcPixelP) + srcOffset);
startDstPixelP = (PixelPtr)(((char*)startDstPixelP) + dstOffset);
startMaskPixelP = (PixelPtr)(((char*)startMaskPixelP) + srcOffset);
}
}
///--------------------------------------------------------------------------------------
// BlitPixiePartialMask8Bit
///--------------------------------------------------------------------------------------
void BlitPixiePartialMask8Bit(
register PixelPtr srcPixelP,
register PixelPtr dstPixelP,
register PixelPtr maskPixelP,
register unsigned long rowsToCopy,
register unsigned long numBytesPerRow,
register unsigned long srcOffset,
register unsigned long dstOffset)
{
register long index;
register PixelPtr startSrcPixelP;
register PixelPtr startDstPixelP;
register PixelPtr startMaskPixelP;
startSrcPixelP = srcPixelP;
startDstPixelP = dstPixelP;
startMaskPixelP = maskPixelP;
while (rowsToCopy--)
{
register fourblits = (numBytesPerRow >> 2);
srcPixelP = startSrcPixelP;
dstPixelP = startDstPixelP;
maskPixelP = startMaskPixelP;
for (index = 0; index < fourblits; index++)
{
register unsigned long temp1;
temp1 = dstPixelP[index] & maskPixelP[index] |
( (~maskPixelP[index])&srcPixelP[index]);
dstPixelP[index] = temp1;
}
srcPixelP += fourblits;
dstPixelP += fourblits;
maskPixelP += fourblits;
if (numBytesPerRow & 0x2)
{
register unsigned short temp1;
temp1 = (*((unsigned short *) dstPixelP)) & (*((unsigned short *) maskPixelP)) |
(~(*((unsigned short *) maskPixelP)++) &
*((unsigned short *) srcPixelP)++);
(*((unsigned short *) dstPixelP)++) = temp1;
}
if (numBytesPerRow & 0x1)
{
register unsigned char temp1;
temp1 = (*((unsigned char *) dstPixelP)) & (*((unsigned char *) maskPixelP)) |
(~(*((unsigned char *) maskPixelP)++) &
*((unsigned char *) srcPixelP)++);
(*((unsigned char *) dstPixelP)++) = temp1;
}
// bump to next row
startSrcPixelP = (PixelPtr)(((char*)startSrcPixelP) + srcOffset);
startDstPixelP = (PixelPtr)(((char*)startDstPixelP) + dstOffset);
startMaskPixelP = (PixelPtr)(((char*)startMaskPixelP) + srcOffset);
}
}
#pragma mark *** 68k:
#else /* SW_PPC */
///--------------------------------------------------------------------------------------
// BlitPixie8Bit
///--------------------------------------------------------------------------------------
SW_ASM_FUNC void BlitPixie8Bit(
register PixelPtr srcPixelP, // address of source pixel
register PixelPtr dstPixelP, // address of destination pixel
register unsigned long rowsToCopy, // number of rows to copy
register unsigned long numBytesPerRow, // number of pixels to copy in each row
register unsigned long srcRowStride, // frameRowBytes when passed to this function
register unsigned long dstRowStride) // frameRowBytes when passed to this function
{
register unsigned long loopsPerRow;
SW_ASM_BEGIN
#if __MWERKS__
fralloc +
#endif
// srcRowStride = distance from end of a row to beginning of next
sub.l numBytesPerRow, srcRowStride
sub.l numBytesPerRow, dstRowStride
// longWordsPerRow = numBytesPerRow >> 2;
move.l numBytesPerRow, d0
lsr.l #2, d0
// numBytesPerRow -= longWordsPerRow << 2;
move.l d0, d1
lsl.l #2, d1
sub.l d1, numBytesPerRow
// loopsPerRow = longWordsPerRow >> 4;
move.l d0, loopsPerRow
lsr.l #4, loopsPerRow
moveq #0xF, d1
and.l d1, d0
add.l d0, d0 // multiply longWordsPerRow by 2 (size of move.l (srcPixelP)+,(dstPixelP)+)
lea @loopEnd, a0 // get address of the end of the loop
suba.l d0, a0 // calculate where to jmp in the loop
@forEachRow:
move.l loopsPerRow, d0
jmp (a0)
@loopBase:
move.l (srcPixelP)+, (dstPixelP)+ // 16
move.l (srcPixelP)+, (dstPixelP)+ // 15
move.l (srcPixelP)+, (dstPixelP)+ // 14
move.l (srcPixelP)+, (dstPixelP)+ // 13
move.l (srcPixelP)+, (dstPixelP)+ // 12
move.l (srcPixelP)+, (dstPixelP)+ // 11
move.l (srcPixelP)+, (dstPixelP)+ // 10
move.l (srcPixelP)+, (dstPixelP)+ // 9
move.l (srcPixelP)+, (dstPixelP)+ // 8
move.l (srcPixelP)+, (dstPixelP)+ // 7
move.l (srcPixelP)+, (dstPixelP)+ // 6
move.l (srcPixelP)+, (dstPixelP)+ // 5
move.l (srcPixelP)+, (dstPixelP)+ // 4
move.l (srcPixelP)+, (dstPixelP)+ // 3
move.l (srcPixelP)+, (dstPixelP)+ // 2
move.l (srcPixelP)+, (dstPixelP)+ // 1
@loopEnd:
subq.l #1,d0
bpl @loopBase
// now do any leftover bits
move.l numBytesPerRow, d0
beq @nextRow
subq.l #2, d0
bmi @moveByte
move.w (srcPixelP)+, (dstPixelP)+
tst d0
beq @nextRow
@moveByte:
move.b (srcPixelP)+, (dstPixelP)+
@nextRow:
adda.l srcRowStride, srcPixelP
adda.l dstRowStride, dstPixelP
subq.l #1, rowsToCopy
bne @forEachRow
#if __MWERKS__
frfree
#endif
SW_ASM_END
}
///--------------------------------------------------------------------------------------
// BlitPixieMask8Bit
///--------------------------------------------------------------------------------------
SW_ASM_FUNC void BlitPixieMask8Bit(
register PixelPtr srcPixelP,
register PixelPtr dstPixelP,
register PixelPtr maskPixelP,
register unsigned long rowsToCopy,
register unsigned long numBytesPerRow,
register unsigned long srcRowStride,
register unsigned long dstRowStride)
{
register unsigned long loopsPerRow;
SW_ASM_BEGIN
#if __MWERKS__
fralloc +
#endif
sub.l numBytesPerRow, srcRowStride
sub.l numBytesPerRow, dstRowStride
// longWordsPerRow = numBytesPerRow >> 2;
move.l numBytesPerRow, d0
lsr.l #2, d0
// numBytesPerRow -= longWordsPerRow << 2;
move.l d0, d1
lsl.l #2, d1
sub.l d1, numBytesPerRow
// loopsPerRow = longWordsPerRow >> 4;
move.l d0, loopsPerRow
lsr.l #4, loopsPerRow
moveq #0xF, d1
and.l d1, d0
lsl.l #3, d0 // longWordsPerRow *= 8;
lea @loopEnd, a0 // get address of the end of the loop
sub.l d0, a0 // calculate where to jmp in the loop
@forEachRow:
move.l loopsPerRow, d2
jmp (a0)
@loopBase:
// 16
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 15
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 14
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 13
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 12
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 11
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 10
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 9
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 8
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 7
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 6
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 5
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 4
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 3
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 2
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
// 1
move.l (dstPixelP), d0
and.l (maskPixelP)+, d0
or.l (srcPixelP)+, d0
move.l d0, (dstPixelP)+
@loopEnd:
subq.l #1, d2
bpl @loopBase
// now do any leftover bits
move.l numBytesPerRow, d2
beq @nextRow
subq.l #2, d2
bmi @moveByte
move.w (dstPixelP), d0
and.w (maskPixelP)+, d0
or.w (srcPixelP)+, d0
move.w d0, (dstPixelP)+
tst d2
beq @nextRow
@moveByte:
move.b (dstPixelP), d0
and.b (maskPixelP)+, d0
or.b (srcPixelP)+, d0
move.b d0, (dstPixelP)+
@nextRow:
adda.l srcRowStride, srcPixelP
adda.l srcRowStride, maskPixelP
adda.l dstRowStride, dstPixelP
subq.l #1, rowsToCopy
bne @forEachRow
#if __MWERKS__
frfree
#endif
SW_ASM_END
}
///--------------------------------------------------------------------------------------
// BlitPixiePartialMask8Bit
///--------------------------------------------------------------------------------------
SW_ASM_FUNC void BlitPixiePartialMask8Bit(
register PixelPtr srcPixelP,
register PixelPtr dstPixelP,
register PixelPtr maskPixelP,
register unsigned long rowsToCopy,
register unsigned long numBytesPerRow,
register unsigned long srcRowStride,
register unsigned long dstRowStride)
{
register unsigned long loopsPerRow;
SW_ASM_BEGIN
#if __MWERKS__
fralloc +
#endif
sub.l numBytesPerRow, srcRowStride
sub.l numBytesPerRow, dstRowStride
// longWordsPerRow = numBytesPerRow >> 2;
move.l numBytesPerRow, d0
lsr.l #2, d0
// numBytesPerRow -= longWordsPerRow << 2;
move.l d0, d1
lsl.l #2, d1
sub.l d1, numBytesPerRow
// loopsPerRow = longWordsPerRow >> 4;
move.l d0, loopsPerRow
lsr.l #4, loopsPerRow
moveq #0xF, d1
and.l d1, d0
mulu #14, d0 // longWordsPerRow *= 14 (bytes in segment of loop)
lea @loopEnd, a0 // get address of the end of the loop
sub.l d0, a0 // calculate where to jmp in the loop
@forEachRow:
move.l loopsPerRow, d2
jmp (a0)
@loopBase:
// 16
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 15
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 14
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 13
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 12
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 11
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 10
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 9
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 8
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 7
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 6
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 5
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 4
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 3
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 2
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
// 1
move.l (dstPixelP), d0
and.l (maskPixelP), d0
move.l (maskPixelP)+, d1
not.l d1
and.l (srcPixelP)+, d1
or.l d1, d0
move.l d0, (dstPixelP)+
@loopEnd:
subq.l #1, d2
bpl @loopBase
// now do any leftover bits
move.l numBytesPerRow, d2
beq @nextRow
subq.l #2, d2
bmi @moveByte
move.w (dstPixelP), d0
and.w (maskPixelP), d0
move.w (maskPixelP)+, d1
not.w d1
and.w (srcPixelP)+, d1
or.w d1, d0
move.w d0, (dstPixelP)+
tst d2
beq @nextRow
@moveByte:
move.b (dstPixelP), d0
and.b (maskPixelP), d0
move.b (maskPixelP)+, d1
not.b d1
and.b (srcPixelP)+, d1
or.b d1, d0
move.b d0, (dstPixelP)+
@nextRow:
adda.l srcRowStride, srcPixelP
adda.l srcRowStride, maskPixelP
adda.l dstRowStride, dstPixelP
subq.l #1, rowsToCopy
bne @forEachRow
#if __MWERKS__
frfree
#endif
SW_ASM_END
}
#endif /* SW_PPC */