Copy Link
Add to Bookmark
Report
Sprite editor for the GP32
sprite editor for GP32
sprite editor for GP32 with an image loaded
source code
//////////////////////////////////////////////////////////////////////////////
//
// GPMain.c
//
// Author: Jung-Man Park ( sysop@doyongid.com )
//
// - Example code about sprite reading and drawing
//
// - Any modifications for optimize or bug-fix are welcomed.
//
// - When you modified this code, please notify to the author
// about the modification by the e-mail.
//
//////////////////////////////////////////////////////////////////////////////
#include "gpdef.h"
#include "gpstdlib.h"
#include "gpgraphic.h"
#include "gpstdio.h"
#include "gpmem.h"
#include "gpmain.h"
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
GPDRAWSURFACE gpDraw[2]; // Primary / Back Surface
int nflip; // Flip
#define MAX_ALPHA 8 // Alpha Level (1 - 8)
unsigned char AlphaTable[256][256][8]; // Alpha Table
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Minimum image area of one sprite
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
typedef struct
{
unsigned short Left;
unsigned short Top;
unsigned short Width;
unsigned short Height;
} _MINAREA;
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// GPF Header
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
typedef struct
{
int FileKind; // Identifier
int ColorMode; // Color Mode (Always 1 = 8 Bit)
int Size; // Size of sprite (seldom used)
int Col, Row; // Column and row blocks of sprite
int Width, Height; // Width and height of sprite
int TileNumber; // Number of sprites
int ColorKey; // Color key
} GPFHEADER;
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Information of one sprite
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
typedef struct
{
_MINAREA *Area; // Minimum image area of one sprite
int *SaveSize; // the compressed size of sprite when saved
} GPFDATA;
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// GPF Structure
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
typedef struct
{
// CompressMode = 1 : Load compressed image to memory (with color-key-compression)
// CompressMode = 0 : Load decompressed image to memory (expand color-key-compression)
int CompressMode;
GPFHEADER stHeader;
GPFDATA stData;
// 'Bitmap' is used when CompressMode == 1, (compressed)
// otherwise 'Surface' is used. (decompressed)
unsigned char **Bitmap;
GPDRAWSURFACE *Surface;
} _GPF;
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Load GPF
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
int GPF_Load(_GPF *pGpf, char *pFileName, int pCompressMode)
{
int i, j, l;
ulong ReadCount, TotalCount;
unsigned char *ReadBuffer, *PutPtr, *TempBuffer;
int ReadBufferSize = 0;
F_HANDLE fp;
// Open file
if(GpFileOpen(pFileName, OPEN_R, &fp) != SM_OK)
return 0;
// Read header info
GpFileRead(fp, &pGpf->stHeader, sizeof(GPFHEADER), &ReadCount);
// Is it a valid GPF file? (Identifier is always 0x7839)
if(pGpf->stHeader.FileKind != 0x7839)
return 0;
// Is it an 8-Bit image?
if(pGpf->stHeader.ColorMode != 1)
return 0;
// 4-byte width arrangement
while(pGpf->stHeader.Width % 4)
pGpf->stHeader.Width++;
// Set compression mode
pGpf->CompressMode = pCompressMode;
// Allocate memory for a minimum-image-area-structure (_MINAREA)
pGpf->stData.Area = (_MINAREA *)gp_mem_func.malloc(pGpf->stHeader.TileNumber * sizeof(_MINAREA));
// Allocate memory using the compressed size in the GPF file
pGpf->stData.SaveSize = (int *)gp_mem_func.malloc(pGpf->stHeader.TileNumber * sizeof(int));
// Read the minimum image area for every sprite
GpFileRead(fp, pGpf->stData.Area, sizeof(_MINAREA) * pGpf->stHeader.TileNumber, &ReadCount);
// Read the compressed size for every sprite
GpFileRead(fp, pGpf->stData.SaveSize, sizeof(int) * pGpf->stHeader.TileNumber, &ReadCount);
// If there is any key-color(transparent color), load sprite data, leave it compressed
if(pGpf->CompressMode)
{
// Create image containers (Bitmap) as the amount of sprites
pGpf->Bitmap = (unsigned char **)gp_mem_func.malloc(pGpf->stHeader.TileNumber * sizeof(int));
// Load compressed sprite data
for(l = 0; l < pGpf->stHeader.TileNumber; l++)
{
pGpf->Bitmap[l] = (unsigned char *)gp_mem_func.malloc(pGpf->stData.SaveSize[l]);
// Load compressed tile data
GpFileRead(fp, pGpf->Bitmap[l], pGpf->stData.SaveSize[l], &ReadCount);
}
}
// Else if there is no key-color, load sprite data, and decompress it
else
{
// Create Surfaces as the amount of sprites
pGpf->Surface = (GPDRAWSURFACE *)gp_mem_func.malloc(pGpf->stHeader.TileNumber * sizeof(GPDRAWSURFACE));
// Check compressed size, and calculate the decompressed size
for(l = 0; l < pGpf->stHeader.TileNumber; l++)
{
if(ReadBufferSize < pGpf->stData.SaveSize[l])
ReadBufferSize = pGpf->stData.SaveSize[l];
}
// Allocate memory for a temporary read buffer
ReadBuffer = (unsigned char *)gp_mem_func.malloc(ReadBufferSize);
// Load sprite data to Surface, and decompress it
for(l = 0; l < pGpf->stHeader.TileNumber; l++)
{
// Skip empty sprite
if(pGpf->stData.Area[l].Width == 0) continue;
// Create Surface
pGpf->Surface[l].bpp = 8;
pGpf->Surface[l].buf_w = pGpf->stData.Area[l].Width;
pGpf->Surface[l].buf_h = pGpf->stData.Area[l].Height;
GpMemSurfaceGet(&pGpf->Surface[l]);
// Load an image data of every sprite to Surface
GpFileRead(fp, ReadBuffer, pGpf->stData.SaveSize[l], &ReadCount);
i = 0;
j = 0;
// Decompress it
while(i < pGpf->stData.SaveSize[l])
{
// Fill key-color by the amount of key-color
if(ReadBuffer[i + 1] == pGpf->stHeader.ColorKey)
{
gm_memset(&pGpf->Surface[l].o_buffer[j], pGpf->stHeader.ColorKey, ReadBuffer[i]);
j += ReadBuffer[i];
i += 2;
}
// Otherwise, just copy it
else
{
gm_memcpy(&pGpf->Surface[l].o_buffer[j], &ReadBuffer[i + 1], ReadBuffer[i]);
j += ReadBuffer[i];
i += (ReadBuffer[i] + 1);
}
}
}
gp_mem_func.free(ReadBuffer);
}
GpFileClose(fp);
return 1;
}
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Delete GPF
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
void GPF_Delete(_GPF *pGpf)
{
int i;
if(pGpf->CompressMode)
{
for(i = 0; i < pGpf->stHeader.TileNumber; i++)
{
if(pGpf->Bitmap[i]) gp_mem_func.free(pGpf->Bitmap[i]);
}
}
else
{
for(i = 0; i < pGpf->stHeader.TileNumber; i++)
{
// Release Surface, if exists (Width > 0)
if(pGpf->stData.Area[i].Width)
{
gp_mem_func.free(pGpf->Surface[i].o_buffer);
}
}
}
gp_mem_func.free(pGpf->stData.Area);
gp_mem_func.free(pGpf->stData.SaveSize);
gm_memset(pGpf, 0, sizeof(_GPF));
}
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Load Palette
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
int Palette_Load(char *pFileName)
{
int i;
unsigned char PalOk;
unsigned char PalEntry[768];
ulong ReadCount;
GP_HPALETTE GpPalette;
GP_LOGPALENTRY GpPalEntry[256];
F_HANDLE fp;
if(GpFileOpen(pFileName, OPEN_R, &fp) != SM_OK)
return 0;
// Read header info
GpFileRead(fp, &PalOk, 1, &ReadCount);
// Check Identifier
if(PalOk != 1)
{
GpFileClose(fp);
return 0;
}
// Read palette data
GpFileRead(fp, PalEntry, 768, &ReadCount);
// Read alpha table
GpFileRead(fp, AlphaTable, sizeof(AlphaTable), &ReadCount);
GpFileClose(fp);
// Set palette data to GP32 palette
for(i = 0; i < 256; i++)
{
GpPalEntry[i].peRed = PalEntry[i * 3];
GpPalEntry[i].peGreen = PalEntry[i * 3 + 1];
GpPalEntry[i].peBlue = PalEntry[i * 3 + 2];
GpPalEntry[i].peFlags = 0;
}
// Apply palette
GpPalette = GpPaletteCreateEx(256, GpPalEntry);
GpPaletteSelect(GpPalette);
GpPaletteRealize();
return 1;
}
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Copy memory. (pPutBuffer = output surface buffer, pLineBuffer = source image)
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
void SprCopyMemory(unsigned char *pPutBuffer, unsigned char *pLineBuffer, int pSize, unsigned short pAlphaDepth)
{
int i, j = 0;
// If there is no alpha depth, just copy them
if(pAlphaDepth == 0)
{
gm_memcpy(pPutBuffer, pLineBuffer, pSize);
}
// Else, apply alpha blend
else if(pAlphaDepth <= MAX_ALPHA)
{
for(i = 0; i < pSize; i++)
{
// Set the alpha-blended color using alpha table
pPutBuffer[i] = AlphaTable[pPutBuffer[i]][pLineBuffer[j++]][pAlphaDepth - 1];
}
}
}
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Draw specified frame. (pFrame = frame number, pRotateMode = horizontal flip, pAlphaDepth = alpha depth)
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
void GPF_ShowFrame(GPDRAWSURFACE *pSurface, int pLeft, int pTop, _GPF *pGpf, int pFrame, int pRotateMode, int pAlphaDepth)
{
int i, j, w, h;
int PutLoc, LineCount, LineStart, LineWidth, BlockStart;
int PutSurfaceWidth, PutSurfaceHeight;
int RealLeft, RealTop;
int SprWidth, SprHeight;
unsigned char *SprPtr;
unsigned char *PutPtr;
GPRECT stMinRect, stGpRect;
GPFHEADER *GpfHeader;
GPFDATA *GpfData;
// Get sprite info
GpfHeader = &pGpf->stHeader;
GpfData = &pGpf->stData;
// If sprite was decompressed (No alpha blend)
if(pGpf->CompressMode == 0)
{
GpBitBlt(NULL,
pSurface,
pLeft, pTop,
pGpf->Surface[pFrame].buf_w, pGpf->Surface[pFrame].buf_h,
pGpf->Surface[pFrame].o_buffer,
0, 0,
pGpf->Surface[pFrame].buf_w, pGpf->Surface[pFrame].buf_h);
}
else
{
// Set the sprite's start address
SprPtr = pGpf->Bitmap[pFrame];
// Convert to the GP32 coordinates (Note that X-Editor does not convert the sprite coordinates to GP32's)
stGpRect.left = GpfHeader->Height - (GpfData->Area[pFrame].Top + GpfData->Area[pFrame].Height);
stGpRect.top = GpfData->Area[pFrame].Left;
stGpRect.right = GpfHeader->Height - GpfData->Area[pFrame].Top;
stGpRect.bottom = GpfData->Area[pFrame].Left + GpfData->Area[pFrame].Width;
// Get minimum-image-area-info. (Exchange width and height, according to the GP32 coordinates)
SprWidth = GpfData->Area[pFrame].Height;
SprHeight = GpfData->Area[pFrame].Width;
// Reset the minimum-image-area (This value will be changed when clipped)
stMinRect.left = 0;
stMinRect.top = 0;
stMinRect.right = SprWidth;
stMinRect.bottom = SprHeight;
// Set output surface size (Exchange, as the GP32 coord.)
PutSurfaceWidth = pSurface->buf_h;
PutSurfaceHeight = pSurface->buf_w;
// Calculate the output position (as the GP32 coord.)
RealLeft = PutSurfaceWidth - pTop - GpfHeader->Height + stGpRect.left;
if(pRotateMode)
{
RealTop = pLeft + GpfHeader->Width - stGpRect.top - SprHeight;
LineCount = SprHeight;
}
else
{
RealTop = pLeft + stGpRect.top;
LineCount = 0;
}
// Skip the out-of-screen drawing
if(RealLeft <= -SprWidth || RealLeft >= PutSurfaceWidth || RealTop <= -SprHeight || RealTop >= PutSurfaceHeight)
return;
// Apply clipping to the output area
if(RealLeft < 0 && RealLeft > -SprWidth)
stMinRect.left = -RealLeft;
if(RealLeft + SprWidth >= PutSurfaceWidth)
stMinRect.right = stMinRect.left + PutSurfaceWidth - RealLeft;
if(RealTop < 0 && RealTop > -SprHeight)
stMinRect.top = -RealTop;
if(RealTop + SprHeight >= PutSurfaceHeight)
stMinRect.bottom = PutSurfaceHeight - RealTop;
// Get the address of output surface
PutPtr = pSurface->ptbuffer;
// Calculate the output position
PutLoc = RealTop * PutSurfaceWidth + RealLeft;
i = 0;
j = 0;
// Loop around the sprite
while(i < GpfData->SaveSize[pFrame])
{
// Color Key check
if(SprPtr[i + 1] == GpfHeader->ColorKey)
{
j += SprPtr[i];
i += 2;
}
// Else it's not a key-color
else
{
// Y-axis clipping
if((RealTop + LineCount) >= 0 && (RealTop + LineCount) < PutSurfaceHeight)
{
BlockStart = j;
// Left-side clipping
if(stMinRect.left > 0)
{
// If across the border
if(stMinRect.left > BlockStart && stMinRect.left < BlockStart + SprPtr[i])
{
LineWidth = (BlockStart + SprPtr[i]) - stMinRect.left;
LineStart = stMinRect.left;
if(PutLoc + LineStart >= 0)
{
SprCopyMemory(&PutPtr[PutLoc + LineStart], &SprPtr[i + stMinRect.left - j + 1], LineWidth, pAlphaDepth);
}
}
// else, lay inside of the output area
else if(stMinRect.left <= BlockStart)
{
LineWidth = SprPtr[i];
LineStart = BlockStart;
if(PutLoc + LineStart >= 0)
SprCopyMemory(&PutPtr[PutLoc + LineStart], &SprPtr[i + 1], LineWidth, pAlphaDepth);
}
}
// Right-side clipping
else if(stMinRect.right < SprWidth)
{
// If across the border
if(stMinRect.right > BlockStart && stMinRect.right < BlockStart + SprPtr[i])
{
LineWidth = stMinRect.right - BlockStart;
LineStart = BlockStart;
if(PutLoc + LineStart >= 0)
SprCopyMemory(&PutPtr[PutLoc + LineStart], &SprPtr[i + 1], LineWidth, pAlphaDepth);
}
// else, lay inside of the output area
else if(stMinRect.right >= BlockStart + SprPtr[i])
{
LineWidth = SprPtr[i];
LineStart = BlockStart;
if(PutLoc + LineStart >= 0)
SprCopyMemory(&PutPtr[PutLoc + LineStart], &SprPtr[i + 1], LineWidth, pAlphaDepth);
}
}
// inside of the output area
else
{
if(PutLoc + BlockStart >= 0)
SprCopyMemory(&PutPtr[PutLoc + BlockStart], &SprPtr[i + 1], SprPtr[i], pAlphaDepth);
}
}
j += SprPtr[i];
i += (SprPtr[i] + 1);
}
// When finished decompressing one line
if(j == SprWidth)
{
if(pRotateMode)
{
// Decrease amount of lines to draw
LineCount--;
// Recalculate the next line position
PutLoc -= PutSurfaceWidth;
}
else
{
// Increase amount of lines to draw
LineCount++;
// Recalculate the next line position
PutLoc += PutSurfaceWidth;
}
j = 0;
}
}
}
}
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
// Main Program
//¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨¶¨
int Frame = 0;
int GpMain(void *arg)
{
int n_tick, i, j;
_GPF stGpf;
GpFatInit();
GpRelativePathSet("gp:\\gpmm\\XEditor");
GpLcdSurfaceGet(&gpDraw[0], 0);
GpLcdSurfaceGet(&gpDraw[1], 1);
GpRectFill(NULL, &gpDraw[0], 0, 0, 320, 240, 0);
GpRectFill(NULL, &gpDraw[1], 0, 0, 320, 240, 0);
GpSurfaceSet(&gpDraw[0]);
nflip = 1;
// Load palette
if(Palette_Load("Palette.Pal") == 0) return 0;
// Initialize GPF structure
gm_memset(&stGpf, 0, sizeof(_GPF));
// Load GPF to memory, with color key (set 1 at the third parameter)
if(GPF_Load(&stGpf, "Sample.Gpf", 1) == 0) return 0;
// Load GPF to memory, without color key (set 0 at the third parameter)
//if(GPF_Load(&stGpf, "Sample2.Gpf", 0) == 0) return 0;
while(1)
{
GpKeyInit();
// Finish program
if(GpKeyGet() == GPC_VK_FA)
{
// Delete GPF
GPF_Delete(&stGpf);
GpAppExit();
return 0;
}
// Set to 25 frame-per-second
if(GpTickCountGet() - n_tick > 1000 / 25)
{
n_tick = GpTickCountGet();
// Fill the screen with black
GpRectFill(NULL, &gpDraw[nflip], 0, 0, 320, 240, 0);
// Draw sprite
GPF_ShowFrame( &gpDraw[nflip], // Target surface
0, 0, // Target Coordinate (x, y)
&stGpf, // GPF structure
Frame++, // Frame number to draw
0, // Apply horizontal flip?
0 // Alpha depth(1 - 8)
);
// Note: To use alpha depth,
// you must set the third parameter as integer '1' when you call GPF_Load()
// If passed last frame, return to first frame
if(Frame == stGpf.stHeader.TileNumber)
Frame = 0;
// Flip Surface.
GpSurfaceFlip(&gpDraw[nflip++]);
nflip %= 2;
}
}
return 0;
}