home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-02-27 | 13.3 KB | 470 lines | [TEXT/BROW] |
- //
- // File: sprite.c
- //
- // This file contains the routines to draw the sprites
- //
- // 2/19/95 -- Created by Mick
- //
-
- // include files
-
- #include "global.h"
-
- #include "sprite.h"
-
- #include "main.h"
-
- // defines for this file
-
- #define kEndShapeToken 0L // the end of shape maker
- #define kLineStartToken 1L // the line start marker
- #define kDrawPixelsToken 2L // the draw run marker
- #define kSkipPixelsToken 3L // the skip pixels marker
-
- // global function declarations
-
- tSpriteInfo *loadSprite( signed short inSpriteResID );
- void disposeSprite( tSpriteInfo *inSpriteInfo );
- void startSpriteDraw( Rect *inClipRect, PixMapHandle inDestPixMap );
- void endSpriteDraw( void );
- void drawSprite( tSpriteInfo *inSpriteInfo, Point inWhere );
-
- // global data owned by this file
-
- // local function declarations
-
- static void renderSpriteClipped( tSpriteInfo *inSpriteInfo, Rect *inDestRect );
- static void renderSpriteUnclipped( tSpriteInfo *inSpriteInfo, Rect *inDestRect );
-
- // static data
-
- Rect sClipRect; // the rectangle to clip to
- PixMapHandle sDestPixMap; // where we are going to draw this data
- unsigned char *sBaseAddr; // the base address of the pixmap
- unsigned long sRowBytes; // the row bytes of the pixmap
-
- // functions
-
- //
- // loadSprite -
- //
- // Loads/allocates all the data for a sprite.
- //
-
- tSpriteInfo *loadSprite( signed short inSpriteResID )
- {
- tSpriteInfo *newSprite; // the new sprite data
-
- // create the sprite info record
- newSprite = ( tSpriteInfo * )NewPtr( sizeof( tSpriteInfo ) );
-
- // load the sprite
- newSprite->fSpriteData = GetResource( kSpriteResType, inSpriteResID );
- HNoPurge( newSprite->fSpriteData );
- if ( newSprite->fSpriteData == ( Handle )kNil )
- {
- // if it did not load, drop into the debugger -- real programs would have error checking
- Debugger();
- }
-
- // copy its bounds rect
- newSprite->fSpriteRect = **( ( Rect ** )( newSprite->fSpriteData ) );
-
- // return the new sprite!
- return newSprite;
- }
-
-
- //
- // disposeSprite -
- //
- // Disposes/releases all the memory used in a sprite
- //
-
- void disposeSprite( tSpriteInfo *inSpriteInfo )
- {
- // dump the sprite resource
- ReleaseResource( inSpriteInfo->fSpriteData );
-
- // free the structure
- DisposePtr( ( Ptr )inSpriteInfo );
- }
-
-
- //
- // startSpriteDraw -
- //
- // Prepare the sprite draw. Assumes that the port is set to the destination port.
- //
-
- void startSpriteDraw( Rect *inClipRect, PixMapHandle inDestPixMap )
- {
- // set the clip region to be the passed in rect
- sClipRect = *inClipRect;
-
- // save the pix map info (so we can use it)
- sDestPixMap = inDestPixMap;
-
- // get info from the pix map
- sBaseAddr = ( unsigned char * )GetPixBaseAddr( sDestPixMap );
- sRowBytes = ( *sDestPixMap )->rowBytes & 0x3fff;
- }
-
-
- //
- // endSpriteDraw -
- //
- // End the sprite draw sequence.
- //
-
- void endSpriteDraw( void )
- {
- }
-
-
- //
- // drawSprite -
- //
- // Draw the sprite in the port.
- //
-
- void drawSprite( tSpriteInfo *inSpriteInfo, Point inWhere )
- {
- Rect destRect; // where we want to draw the sprite
-
- // calculate the destination rect
- destRect = inSpriteInfo->fSpriteRect;
- OffsetRect( &destRect, inWhere.h, inWhere.v );
-
- // determine if the spite needs to be drawn at all
- if( destRect.top >= sClipRect.bottom || destRect.bottom <= sClipRect.top ||
- destRect.left >= sClipRect.right || destRect.right <= sClipRect.left )
- {
- // no need to draw, goodbye
- return;
- }
-
- // determine if the sprite will be clipped
- if ( destRect.top < sClipRect.top || destRect.bottom > sClipRect.bottom ||
- destRect.left < sClipRect.left || destRect.right > sClipRect.right )
- {
- // handle the clipped case
- renderSpriteClipped( inSpriteInfo, &destRect );
- }
- else
- {
- // handle the unclipped case
- renderSpriteUnclipped( inSpriteInfo, &destRect );
- }
- }
-
-
- //
- // renderSpriteClipped -
- //
- // Draw the spite, deal with clipping.
- //
-
- void renderSpriteClipped( tSpriteInfo *inSpriteInfo, Rect *inDestRect )
- {
- Rect clipRect; // the rect that defines the clipped shape
- unsigned char *rowStart; // the pointer to the start of this row
- unsigned char *srcPtr; // the current position in the sprite data
- unsigned char *destPtr; // the current position in the destination pixmap
- unsigned long miscCounter; // a counter for various purposes
- unsigned long extraCounter; // a counter for right clippling purposes ( how much extra was there? )
- unsigned long tokenOp; // the op code from the token
- unsigned long tokenData; // the data from the token
- unsigned char exitFlag; // should we exit from the loop?
- unsigned long yCount; // how many lines down in the shape are we?
- unsigned long xCount; // where are we in this line?
-
- // create a clipped rect in the coordinates of the sprite
- clipRect.left = inDestRect->left < sClipRect.left ? sClipRect.left - inDestRect->left : 0;
- clipRect.right = inDestRect->right > sClipRect.right ? sClipRect.right - inDestRect->left : inDestRect->right - inDestRect->left;
- clipRect.top = inDestRect->top < sClipRect.top ? sClipRect.top - inDestRect->top : 0;
- clipRect.bottom = inDestRect->bottom > sClipRect.bottom ? sClipRect.bottom - inDestRect->top : inDestRect->bottom - inDestRect->top;
-
- // set up the counters
- yCount = 0;
-
- // determine characteristics about the pixmap
- rowStart = sBaseAddr + inDestRect->top * sRowBytes + inDestRect->left;
-
- // move to the right place in the shape ( just past the size rect )
- srcPtr = ( unsigned char * )( ( *( inSpriteInfo->fSpriteData ) ) + sizeof( Rect ) );
-
- // loop until we are done
- exitFlag = kFalse;
- while( !exitFlag )
- {
- // get a token
- tokenOp = ( *( ( unsigned long * )srcPtr ) ) >> 24;
- tokenData = ( *( ( unsigned long * )srcPtr ) ) & 0x00ffffff;
- srcPtr += sizeof( unsigned long );
-
- // depending on the token
- switch( tokenOp )
- {
- case kDrawPixelsToken:
- miscCounter = tokenData;
- extraCounter = 0;
-
- // if we need to, clip to the left
- if( xCount < clipRect.left )
- {
- // if this run does not appear at all, don't draw it
- if ( miscCounter < clipRect.left - xCount )
- {
- destPtr += miscCounter;
- srcPtr += miscCounter;
- srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) );
- xCount += miscCounter;
- break;
- }
- else
- {
- // if it does, skip to where we can draw
- miscCounter -= clipRect.left - xCount;
- destPtr += clipRect.left - xCount;
- srcPtr += clipRect.left - xCount;
- xCount += clipRect.left - xCount;
- }
- }
-
- // if we need to, clip to the right
- if ( xCount + miscCounter > clipRect.right )
- {
- // if this run does not appear at all, skip it
- if ( xCount > clipRect.right )
- {
- destPtr += miscCounter;
- srcPtr += miscCounter;
- srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) );
- xCount += miscCounter;
- break;
- }
- else
- {
- // if it does, setup to draw what we can
- extraCounter = miscCounter;
- miscCounter -= ( xCount + miscCounter ) - clipRect.right;
- extraCounter -= miscCounter;
- }
- }
-
- // adjust xCount for the run
- xCount += miscCounter;
-
- // move data in the biggest chunks we can find
- #ifdef powerc
- // move in doubles while we can
- while( miscCounter >= sizeof( double ) )
- {
- *( ( double * )destPtr ) = *( ( double * )srcPtr );
- destPtr += sizeof( double );
- srcPtr += sizeof( double );
- miscCounter -= sizeof( double );
- }
-
- // move a long if we can
- if ( miscCounter >= sizeof( unsigned long ) )
- {
- *( ( unsigned long * )destPtr ) = *( ( unsigned long * )srcPtr );
- destPtr += sizeof( unsigned long );
- srcPtr += sizeof( unsigned long );
- miscCounter -= sizeof( unsigned long );
- }
- #else
- // move in longs while we can
- while( miscCounter >= sizeof( unsigned long ) )
- {
- *( ( unsigned long * )destPtr ) = *( ( unsigned long * )srcPtr );
- destPtr += sizeof( unsigned long );
- srcPtr += sizeof( unsigned long );
- miscCounter -= sizeof( unsigned long );
- }
- #endif
-
- // move a short if we can
- if ( miscCounter >= sizeof( unsigned short ) )
- {
- *( ( unsigned short * )destPtr ) = *( ( unsigned short * )srcPtr );
- destPtr += sizeof( unsigned short );
- srcPtr += sizeof( unsigned short );
- miscCounter -= sizeof( unsigned short );
- }
-
- // move a char if we can
- if ( miscCounter >= sizeof( unsigned char ) )
- {
- *( ( unsigned char * )destPtr ) = *( ( unsigned char * )srcPtr );
- destPtr += sizeof( unsigned char );
- srcPtr += sizeof( unsigned char );
- miscCounter -= sizeof( unsigned char );
- }
-
- // adjust for right clipping
- destPtr += extraCounter;
- srcPtr += extraCounter;
- xCount += extraCounter;
-
- // adjust for the padding
- srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) );
- break;
-
- case kSkipPixelsToken:
- destPtr += tokenData;
- xCount += tokenData;
- break;
-
- case kLineStartToken:
- // if this line is above the clip rect, skip to the next line
- if( yCount < clipRect.top )
- {
- srcPtr += tokenData;
- }
-
- // set up the destination pointer
- destPtr = rowStart;
- rowStart += sRowBytes;
-
- // move the yCounter
- yCount++;
-
- // reset the xCounter
- xCount = 0;
-
- // if we have hit the bottom clip, exit the loop
- if ( yCount > clipRect.bottom )
- {
- exitFlag = kTrue;
- }
- break;
-
- case kEndShapeToken:
- // signal a loop exit
- exitFlag = kTrue;
- break;
-
- default:
- // we should never get here
- Debugger();
- break;
- }
- }
- }
-
-
- //
- // renderSpriteUnclipped -
- //
- // Draw the sprite, no clipping needed
- //
-
- void renderSpriteUnclipped( tSpriteInfo *inSpriteInfo, Rect *inDestRect )
- {
- unsigned char *rowStart; // the pointer to the start of this row
- unsigned char *srcPtr; // the current position in the sprite data
- unsigned char *destPtr; // the current position in the destination pixmap
- unsigned long miscCounter; // a counter for various purposes
- unsigned long tokenOp; // the op code from the token
- unsigned long tokenData; // the data from the token
- unsigned char exitFlag; // should we exit from the loop?
-
- // determine characteristics about the pixmap
- rowStart = sBaseAddr + inDestRect->top * sRowBytes + inDestRect->left;
-
- // move to the right place in the shape ( just past the size rect )
- srcPtr = ( unsigned char * )( ( *( inSpriteInfo->fSpriteData ) ) + sizeof( Rect ) );
-
- // loop until we are done
- exitFlag = kFalse;
- while( !exitFlag )
- {
- // get a token
- tokenOp = ( *( ( unsigned long * )srcPtr ) ) >> 24;
- tokenData = ( *( ( unsigned long * )srcPtr ) ) & 0x00ffffff;
- srcPtr += sizeof( unsigned long );
-
- // depending on the token
- switch( tokenOp )
- {
- case kDrawPixelsToken:
- miscCounter = tokenData;
-
- // move data in the biggest chunks we can find
- #ifdef powerc
- // move in doubles while we can
- while( miscCounter >= sizeof( double ) )
- {
- *( ( double * )destPtr ) = *( ( double * )srcPtr );
- destPtr += sizeof( double );
- srcPtr += sizeof( double );
- miscCounter -= sizeof( double );
- }
-
- // move a long if we can
- if ( miscCounter >= sizeof( unsigned long ) )
- {
- *( ( unsigned long * )destPtr ) = *( ( unsigned long * )srcPtr );
- destPtr += sizeof( unsigned long );
- srcPtr += sizeof( unsigned long );
- miscCounter -= sizeof( unsigned long );
- }
- #else
- // move in longs while we can
- while( miscCounter >= sizeof( unsigned long ) )
- {
- *( ( unsigned long * )destPtr ) = *( ( unsigned long * )srcPtr );
- destPtr += sizeof( unsigned long );
- srcPtr += sizeof( unsigned long );
- miscCounter -= sizeof( unsigned long );
- }
- #endif
-
- // move a short if we can
- if ( miscCounter >= sizeof( unsigned short ) )
- {
- *( ( unsigned short * )destPtr ) = *( ( unsigned short * )srcPtr );
- destPtr += sizeof( unsigned short );
- srcPtr += sizeof( unsigned short );
- miscCounter -= sizeof( unsigned short );
- }
-
- // move a char if we can
- if ( miscCounter >= sizeof( unsigned char ) )
- {
- *( ( unsigned char * )destPtr ) = *( ( unsigned char * )srcPtr );
- destPtr += sizeof( unsigned char );
- srcPtr += sizeof( unsigned char );
- miscCounter -= sizeof( unsigned char );
- }
-
- // adjust for the padding
- srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) );
- break;
-
- case kSkipPixelsToken:
- destPtr += tokenData;
- break;
-
- case kLineStartToken:
- // set up the destination pointer
- destPtr = rowStart;
- rowStart += sRowBytes;
- break;
-
- case kEndShapeToken:
- // signal a loop exit
- exitFlag = kTrue;
- break;
-
- default:
- // we should never get here
- Debugger();
- break;
- }
- }
- }
-