/*  SpriteWiz modification routines  -  By David A. Visage  */

#include <stdio.h>
#include <exec/types.h>
#include <intuition/intuition.h>

#define BOX_WIDTH  15
#define BOX_HEIGHT 10

#define GRID_WIDTH  (16 * BOX_WIDTH)
#define GRID_HEIGHT (16 * BOX_HEIGHT)

#define SPRITE_SIZE  36              /*  In words  */

#define ALL_BITS  0xffff

/*  The world famous Sprite structure  */
struct Sprite
 {
 UWORD SpriteData [SPRITE_SIZE];
 UWORD SprColor1,SprColor2,SprColor3;
 UWORD SpriteNumber;
 };


/*  Scroll up routine for grid and sprite data  */
ScrollUp(Rp,VertRast,SpritePtr,BoxPtr)
struct RastPort *Rp;
struct RastPort *VertRast;
struct Sprite *SpritePtr;
struct Rectangle *BoxPtr;
{
struct Rectangle *RectPtr1,*RectPtr2;
UWORD *SpriteDataPtr;
LONG SrcX,SrcY,DestX,DestY;
int i;
LONG BoxIndex;
LONG WordIndex1,WordIndex2;
UWORD SaveHigh,SaveLow;
UWORD HighWord,LowWord;

SpriteDataPtr = &SpritePtr->SpriteData[0];

/*  Save first row of grid data  */
SrcX = BoxPtr->MinX;
SrcY = BoxPtr->MinY;
ClipBlit(Rp,SrcX,SrcY,VertRast,0,0,GRID_WIDTH,BOX_HEIGHT,0xc0);

/*  Save first row of sprite data  */
WordIndex1 = 2;
SaveHigh = *(SpriteDataPtr + WordIndex1);
SaveLow = *(SpriteDataPtr + WordIndex1 + 1);

for ( i = 1; i <= 15; i++ )
    {
    /*  Scroll grid row to next higher row  */
    RectPtr1 = BoxPtr + (i * 16);
    RectPtr2 = RectPtr1 - 16;         /*  Rectangle row about current  */
    SrcX = RectPtr1->MinX;
    SrcY = RectPtr1->MinY;
    DestX = RectPtr2->MinX;
    DestY = RectPtr2->MinY;
    ClipBlit(Rp,SrcX,SrcY,Rp,DestX,DestY,GRID_WIDTH,BOX_HEIGHT,0xc0);

    /*  Scroll sprite row to next higher row  */
    WordIndex1 = 2 + (2 * i);
    WordIndex2 = 2 * i;
    HighWord = *(SpriteDataPtr + WordIndex1);
    LowWord = *(SpriteDataPtr + WordIndex1 + 1);
    *(SpriteDataPtr + WordIndex2) = HighWord;
    *(SpriteDataPtr + WordIndex2 + 1) = LowWord;
    };

/*  Restore last row of grid data  */
BoxIndex = 16 * 15;
RectPtr1 = BoxPtr + BoxIndex;        /*  Auto scaled by argument size  */
DestX = RectPtr1->MinX;
DestY = RectPtr1->MinY;
ClipBlit(VertRast,0,0,Rp,DestX,DestY,GRID_WIDTH,BOX_HEIGHT,0xc0);

/*  Restore last row of sprite  */
WordIndex1 = 2 + (15 * 2);
*(SpriteDataPtr + WordIndex1) = SaveHigh;
*(SpriteDataPtr + WordIndex1 + 1) = SaveLow;
}


/*  Scroll down routine for grid and sprite data  */
ScrollDown(Rp,VertRast,SpritePtr,BoxPtr)
struct RastPort *Rp;
struct RastPort *VertRast;
struct Sprite *SpritePtr;
struct Rectangle *BoxPtr;
{
struct Rectangle *RectPtr1,*RectPtr2;
UWORD *SpriteDataPtr;
LONG SrcX,SrcY,DestX,DestY;
int i;
LONG BoxIndex;
LONG WordIndex1,WordIndex2;
UWORD SaveHigh,SaveLow;
UWORD HighWord,LowWord;

SpriteDataPtr = &SpritePtr->SpriteData[0];

/*  Save last row of grid data  */
BoxIndex = 16 * 15;
RectPtr1 = BoxPtr + BoxIndex;
SrcX = RectPtr1->MinX;
SrcY = RectPtr1->MinY;
ClipBlit(Rp,SrcX,SrcY,VertRast,0,0,GRID_WIDTH,BOX_HEIGHT,0xc0);

/*  Save last row of sprite data  */
WordIndex1 = 2 + (15 * 2);
SaveHigh = *(SpriteDataPtr + WordIndex1);
SaveLow = *(SpriteDataPtr + WordIndex1 + 1);

for ( i = 15; i > 0 ; i-- )
    {
    /*  Scroll row of grid data to next lower row  */
    BoxIndex = i * 16;
    RectPtr1 = BoxPtr + BoxIndex;          /*  Row below current  */
    RectPtr2 = RectPtr1 - 16;
    SrcX = RectPtr2->MinX;
    SrcY = RectPtr2->MinY;
    DestX = RectPtr1->MinX;
    DestY = RectPtr1->MinY;
    ClipBlit(Rp,SrcX,SrcY,Rp,DestX,DestY,GRID_WIDTH,BOX_HEIGHT,0xc0);

    /*  Scroll sprite row to next lower row  */
    WordIndex1 = 2 * i;
    WordIndex2 = 2 + (2 * i);
    HighWord = *(SpriteDataPtr + WordIndex1);
    LowWord = *(SpriteDataPtr + WordIndex1 + 1);
    *(SpriteDataPtr + WordIndex2) = HighWord;
    *(SpriteDataPtr + WordIndex2 + 1) = LowWord;
    };

/*  Restore first row of grid data  */
DestX = BoxPtr->MinX;
DestY = BoxPtr->MinY;
ClipBlit(VertRast,0,0,Rp,DestX,DestY,GRID_WIDTH,BOX_HEIGHT,0xc0);

/*  Restore first row of sprite  */
WordIndex1 = 2;
*(SpriteDataPtr + WordIndex1) = SaveHigh;
*(SpriteDataPtr + WordIndex1 + 1) = SaveLow;
}


/*  Scroll left routine for grid and sprite data  */
ScrollLeft(Rp,HorizRast,SpritePtr,BoxPtr)
struct RastPort *Rp;
struct RastPort *HorizRast;
struct Sprite *SpritePtr;
struct Rectangle *BoxPtr;
{
struct Rectangle *RectPtr1,*RectPtr2;
UWORD *SpriteDataPtr;
LONG SrcX,SrcY,DestX,DestY;
int i;
LONG BoxIndex;
LONG WordIndex;
UWORD *HighWordPtr,*LowWordPtr;

SpriteDataPtr = &SpritePtr->SpriteData[0];

/*  Save first column of grid data  */
SrcX = BoxPtr->MinX;
SrcY = BoxPtr->MinY;
ClipBlit(Rp,SrcX,SrcY,HorizRast,0,0,BOX_WIDTH,GRID_HEIGHT,0xc0);

/*  Shift first line of sprite data to the left  */
WordIndex = 2;
HighWordPtr = SpriteDataPtr + WordIndex;
LowWordPtr = SpriteDataPtr + WordIndex + 1;
ShiftLeft(HighWordPtr,LowWordPtr);

for ( i = 1; i <= 15 ; i++ )
    {
    /*  Move next grid column to the left  */
    RectPtr1 = BoxPtr + i;
    RectPtr2 = RectPtr1 - 1;       /*  Column to left of current  */
    SrcX = RectPtr1->MinX;
    SrcY = RectPtr1->MinY;
    DestX = RectPtr2->MinX;
    DestY = RectPtr2->MinY;
    ClipBlit(Rp,SrcX,SrcY,Rp,DestX,DestY,BOX_WIDTH,GRID_HEIGHT,0xc0);

    /*  Shift next line of sprite data to the left  */
    WordIndex = 2 + (2 * i);
    HighWordPtr = SpriteDataPtr + WordIndex;
    LowWordPtr = SpriteDataPtr + WordIndex + 1;
    ShiftLeft(HighWordPtr,LowWordPtr);
    };

/*  Restore last column of grid data  */
BoxIndex = 15;
RectPtr1 = BoxPtr + BoxIndex;        /*  Auto scaled by argument size  */
DestX = RectPtr1->MinX;
DestY = RectPtr1->MinY;
ClipBlit(HorizRast,0,0,Rp,DestX,DestY,BOX_WIDTH,GRID_HEIGHT,0xc0);
}


/*  Scroll right routine for grid and sprite data  */
ScrollRight(Rp,HorizRast,SpritePtr,BoxPtr)
struct RastPort *Rp;
struct RastPort *HorizRast;
struct Sprite *SpritePtr;
struct Rectangle *BoxPtr;
{
struct Rectangle *RectPtr1,*RectPtr2;
UWORD *SpriteDataPtr;
LONG SrcX,SrcY,DestX,DestY;
int i;
LONG BoxIndex,WordIndex;
UWORD *HighWordPtr,*LowWordPtr;

SpriteDataPtr = &SpritePtr->SpriteData[0];

/*  Save last column of grid data  */
BoxIndex = 15;
RectPtr1 = BoxPtr + BoxIndex;
SrcX = RectPtr1->MinX;
SrcY = RectPtr1->MinY;
ClipBlit(Rp,SrcX,SrcY,HorizRast,0,0,BOX_WIDTH,GRID_HEIGHT,0xc0);

/*  Shift first line of sprite data to the right  */
WordIndex = 2;
HighWordPtr = SpriteDataPtr + WordIndex;
LowWordPtr = SpriteDataPtr + WordIndex + 1;
ShiftRight(HighWordPtr,LowWordPtr);

for ( i = 15; i > 0; i-- )
    {
    /*  Move next column of grid data to the right  */
    RectPtr1 = BoxPtr + i;      /*  Column right of current  */
    RectPtr2 = RectPtr1 - 1;
    SrcX = RectPtr2->MinX;
    SrcY = RectPtr2->MinY;
    DestX = RectPtr1->MinX;
    DestY = RectPtr1->MinY;
    ClipBlit(Rp,SrcX,SrcY,Rp,DestX,DestY,BOX_WIDTH,GRID_HEIGHT,0xc0);

    /*  Shift next line of sprite data to the right  */
    WordIndex = 2 + (2 * i);
    HighWordPtr = SpriteDataPtr + WordIndex;
    LowWordPtr = SpriteDataPtr + WordIndex + 1;
    ShiftRight(HighWordPtr,LowWordPtr);
    };

/*  Restore first column of grid data  */
DestX = BoxPtr->MinX;
DestY = BoxPtr->MinY;
ClipBlit(HorizRast,0,0,Rp,DestX,DestY,BOX_WIDTH,GRID_HEIGHT,0xc0);
}


/*  Rotate right for grid and sprite data  */
RotateRight(Rp,GRast,SpritePtr,BoxPtr)
struct RastPort *Rp;
struct RastPort *GRast;                      /*  Pointer to GRast  */
struct Sprite *SpritePtr;
struct Rectangle *BoxPtr;
{
struct Rectangle *RectPtr;
UWORD *SpriteDataPtr;
UWORD TempSprite[SPRITE_SIZE];
UWORD HighWord,LowWord;
ULONG HighBit,LowBit;
LONG WordIndex1,WordIndex2;
LONG SrcX,SrcY;
LONG DestX,DestY;
LONG BoxIndex,BitMask;
int i,j;

SpriteDataPtr = &SpritePtr->SpriteData[0];

ClearSprData(&TempSprite[0]);           /*  Clear temporary sprite     */

DestX = GRID_WIDTH - BOX_WIDTH;        /*  Last column in GridRast    */
for ( i = 0; i <= 15; i++ )
    {
    /*  Get next row of sprite data  */
    WordIndex1 = 2 + (2 * i);
    HighWord = *(SpriteDataPtr + WordIndex1);
    LowWord = *(SpriteDataPtr + WordIndex1 + 1);

    DestY = 0;                       /*  DestY starts at mimimum  */
    for ( j = 0; j <= 15; j++ )
        {
        /*  Calculate new sprite image  */
        BitMask = 1 << (15 - j);
        HighBit = HighWord & BitMask;
        LowBit = LowWord & BitMask;
        WordIndex2 = 2 + (2 * j);             /*  Start at top  */
        if ( HighBit != 0 )
           TempSprite[WordIndex2] |= (1 << i);
        if ( LowBit != 0 )
           TempSprite[WordIndex2 + 1] |= (1 << i);

        /*  Save current box data in backup raster  */
        BoxIndex = j + (16 * i);
        RectPtr = BoxPtr + BoxIndex;  /*  Auto scaled by argument size  */
        SrcX = RectPtr->MinX;
        SrcY = RectPtr->MinY;
        ClipBlit(Rp,SrcX,SrcY,GRast,DestX,DestY,BOX_WIDTH,BOX_HEIGHT,0xc0);
        DestY += BOX_HEIGHT;   /*  Next Y position in grid raster    */
        };

    DestX -= BOX_WIDTH;        /*  Next X position in grid raster  */
    };

/*  Copy temporary sprite data to real sprite data  */
CopySprData(&TempSprite[0],SpriteDataPtr);

/*  Copy GRast to drawing grid  */
DestX = BoxPtr->MinX;
DestY = BoxPtr->MinY;
ClipBlit(GRast,0,0,Rp,DestX,DestY,GRID_WIDTH,GRID_HEIGHT,0xc0);
}


/*  Rotate left for grid and sprite data  */
RotateLeft(Rp,GRast,SpritePtr,BoxPtr)
struct RastPort *Rp;
struct RastPort *GRast;                      /*  Pointer to GRast  */
struct Sprite *SpritePtr;
struct Rectangle *BoxPtr;
{
struct Rectangle *RectPtr;
UWORD *SpriteDataPtr;
UWORD TempSprite[SPRITE_SIZE];
UWORD HighWord,LowWord;
ULONG HighBit,LowBit;
LONG WordIndex1,WordIndex2;
LONG SrcX,SrcY;
LONG DestX,DestY;
LONG BoxIndex,BitMask;
int i,j;

SpriteDataPtr = &SpritePtr->SpriteData[0]; 

ClearSprData(&TempSprite[0]);     /*  Clear temporary sprite  */

DestX = 0;                       /*  First column in GridRast  */
for ( i = 0; i <= 15; i++ )
    {
    /*  Get next row of sprite data  */
    WordIndex1 = 2 + (2 * i);
    HighWord = *(SpriteDataPtr + WordIndex1);
    LowWord = *(SpriteDataPtr + WordIndex1 + 1);

    DestY = GRID_HEIGHT - BOX_HEIGHT;     /*  Initial grid Y coordinate  */
    for ( j = 0; j <= 15; j++ )
        {
        /*  Calculate new sprite image  */
        BitMask = 1 << (15 - j);
        HighBit = HighWord & BitMask;
        LowBit = LowWord & BitMask;
        WordIndex2 = 32 - (2 * j);             /*  Start at bottom  */
        if ( HighBit != 0 )
           TempSprite[WordIndex2] |= (1 << (15 - i));
        if ( LowBit != 0 )
           TempSprite[WordIndex2 + 1] |= (1 << (15 - i));

        /*  Save current box data in backup raster  */
        BoxIndex = j + (16 * i);
        RectPtr = BoxPtr + BoxIndex;  /*  Auto scaled by argument size  */
        SrcX = RectPtr->MinX;
        SrcY = RectPtr->MinY;
        ClipBlit(Rp,SrcX,SrcY,GRast,DestX,DestY,BOX_WIDTH,BOX_HEIGHT,0xc0);
        DestY -= BOX_HEIGHT;     /*  Next Y position in grid raster  */
        };

    DestX += BOX_WIDTH;        /*  Next X position in grid raster  */
    };

/*  Copy temporary sprite data to real sprite data  */
CopySprData(&TempSprite[0],SpriteDataPtr);

/*  Copy GRast to drawing grid  */
DestX = BoxPtr->MinX;
DestY = BoxPtr->MinY;
ClipBlit(GRast,0,0,Rp,DestX,DestY,GRID_WIDTH,GRID_HEIGHT,0xc0);
}


/*  Flip sprite on the Y Axis  */
FlipY(SpritePtr)
struct Sprite *SpritePtr;
{
UWORD *SpriteDataPtr;
UWORD TempSprite[SPRITE_SIZE];
UWORD HighWord,LowWord;
UWORD BitMask;
LONG WordIndex;
int i,j;

SpriteDataPtr = &SpritePtr->SpriteData[0];

ClearSprData(&TempSprite[0]);            /*  Clear temporary sprite  */
for ( i = 0; i <= 15; i++ )
    {
    WordIndex = 2 + ( 2 * i);
    HighWord = *(SpriteDataPtr + WordIndex);
    LowWord = *(SpriteDataPtr + WordIndex + 1);
    for ( j = 0; j <= 15; j++ )
        {
        BitMask = 1 << (15 - j);
        if ( (HighWord & BitMask) != 0 )
           TempSprite[WordIndex] |= (1 << j);
        if ( (LowWord & BitMask) != 0 )
           TempSprite[WordIndex + 1] |= (1 << j);
        };
    };

/*  Copy TempSprite data to edit sprite image  */
CopySprData(&TempSprite[0],SpriteDataPtr);
}


/*  Flip sprite on the X Axis  */
FlipX(SpritePtr)
struct Sprite *SpritePtr;
{
UWORD *SpriteDataPtr;
UWORD TempSprite[SPRITE_SIZE];
UWORD HighWord,LowWord;
LONG WordIndex1,WordIndex2;
int i;

SpriteDataPtr = &SpritePtr->SpriteData[0];

ClearSprData(&TempSprite[0]);            /*  Clear temporary sprite  */
for ( i = 0; i <= 15; i++ )
    {
    /*  Get next line of sprite data from top  */
    WordIndex1 = 2 + ( 2 * i);
    HighWord = *(SpriteDataPtr + WordIndex1);
    LowWord = *(SpriteDataPtr + WordIndex1 + 1);
    /*  Move to next line of temporary sprite from bottom  */
    WordIndex2 = 2 + (2 * (15 - i));
    TempSprite[WordIndex2] = HighWord;
    TempSprite[WordIndex2 + 1] = LowWord;
    };

/*  Copy TempSprite data to edit sprite image  */
CopySprData(&TempSprite[0],SpriteDataPtr);
}


/*  Negate image of sprite by using XOR  */
Negate(SpritePtr)
struct Sprite *SpritePtr;
{
UWORD *SpriteDataPtr;
UWORD HighWord,LowWord;
LONG WordIndex;
int i;

SpriteDataPtr = &SpritePtr->SpriteData[0];

for ( i = 0; i <= 15; i++ )
    {
    /*  Get next line of sprite  */
    WordIndex = 2 + (2 * i);
    HighWord = *(SpriteDataPtr + WordIndex);
    LowWord = *(SpriteDataPtr + WordIndex + 1);
    /*  Negate sense of all bits  */
    HighWord ^= ALL_BITS;
    LowWord ^= ALL_BITS;
    /*  Assign back to sprite  */
    *(SpriteDataPtr + WordIndex) = HighWord;
    *(SpriteDataPtr + WordIndex + 1) = LowWord;
    };
}


