/************************************************ * * * SPRITE ANIMATION PROGRAM * * ========================== * * * * by Steven Lewis * * * * Downloaded from: * * http://www.netyaroze-europe.com/~slewis/ * * * * e-mail: * * stevenlewis@birminghamhome.freeserve.co.uk * * * * This code loads in four different TIM images * * and, using a loop, flips between them * * to create an animation * ************************************************/ // ----------------- // HEADER FILES // ----------------- #include #include // ----------------- // DEFINITIONS // ----------------- #define SPRITE_COUNT (1) // Sets the number of sprites on screen at one time #define SCREEN_WIDTH (320) // Sets the width of the screen #define SCREEN_HEIGHT (256) // Sets the height of the screen #define SPRITE_ADDRESS (0x80094000) // Memory location where the first TIM image is loaded #define SPRITE_ADDRESS2 (0x80096000) // Memory location where the second TIM image is loaded #define SPRITE_ADDRESS3 (0x80098000) // Memory location where the third TIM image is loaded #define SPRITE_ADDRESS4 (0x800a7000) // Memory location where the fourth TIM image is loaded #define TOTAL_FRAMES (4) // The number of frames used in the animation // --------------------------- // SPRITE STRUCTURE POINTER // --------------------------- GsSPRITE sprite[TOTAL_FRAMES]; /* Declares sprite structure to be an array because we are using four different sprites. The first sprite is called sprite[0], the second called sprite[1], etc. */ // -------------------------- // ORDERING TABLE VARIABLES // -------------------------- #define OT_LENGTH (1) /* Sets the length of the Ordering Table. As there is only one image on screen at a time our OT only needs to be 1 in length */ GsOT WorldOT[2]; // Sets two Ordering Table headers GsOT_TAG OTTags[2][1<>3)&0x01) { // Load CLUT into the Frame Buffer rect.x = tim_info.cx; // x position of CLUT rect.y = tim_info.cy; // y position of CLUT rect.w = tim_info.cw; // width of CLUT rect.h = tim_info.ch; // height of CLUT LoadImage (&rect,tim_info.clut); // Loads all of the above into memory } // Initialise the Sprite Structure. Switch statement enable 4, 8, or 16bit images to be used switch(tim_info.pmode) { // If the sprite is 4 bit case 0x08: sprite->attribute = 0x00000000; // Sets attribute of the sprite sprite->w = tim_info.pw*4; /* Because each pixel in the frame buffer is a 16 bit memory address, a 4 bit sprite can be stores in a fourth of its normal size. This means that it has to be multiplied by four to be displayed at its correct size */ sprite->tpage = GetTPage(0,0,tim_info.px,tim_info.py); /* Gets texture page info */ break; // leaves the switch statement // If the Sprite is 8 bit case 0x09: sprite->attribute = 0x01000000; // Sets sprites attribute sprite->w = tim_info.pw*2; /* An 8 bit image is stored at half of its normal size in the frame buffer. Thus it must be mulitiplied by two upon its display */ sprite->tpage = GetTPage(1,0,tim_info.px,tim_info.py); /* Gets texture page info */ break; // exits the switch statement // If the Sprite is 16 bit default: sprite->attribute = 0x02000000; // Sets the sprites attribute sprite->w = tim_info.pw; // Sets the width of the sprite sprite->tpage = GetTPage(2,0,tim_info.px,tim_info.py); /* Gets texture page info */ break; // exits the switch statement } sprite->x = (SCREEN_WIDTH/2)-(tim_info.pw); // x screen position of sprite sprite->y = (SCREEN_HEIGHT/2)-(tim_info.ph/2); // y screen position of sprite sprite->h = tim_info.ph; // sprite height sprite->u = 0; // Texture page offset x axis sprite->v = 0; // texture page offset y axis sprite->cx = tim_info.cx; // CLUT x axis position sprite->cy = tim_info.cy; // CLUT y axis position sprite->r = 128; // Sets brightness, 128=normal sprite->g = 128; // Sets brightness, 128=normal sprite->b = 128; // Sets brightness, 128=normal sprite->scalex = ONE; // Sets scale ratio to 1:1 on the x axis sprite->scaley = ONE; // Sets scale ratio to 1:1 on the y axis sprite->rotate = 0; // Sets sprite rotate to off DrawSync(0); // Waits for all the above to be completed before continuing printf("Sprite %d Loaded\n", currentSprite); /* Reports when each sprite is loaded to the PC screen */ currentSprite++; // Increments the current sprite value. Used in the next function } // ------------------ // MAIN FUNCTION // ------------------ void main() { int i; // Variable to set up the Ordering Tables unsigned long currentSpriteAddress; // Holds the memory address of the current sprite int framePerSecondCount; /* Variable which holds the number of each frame sent to the screen. This is to help run the animation at an approprite speed */ SetVideoMode(MODE_PAL); // Sets the Video Mode to PAL GsInitGraph(SCREEN_WIDTH,SCREEN_HEIGHT,4,0,0); // Initialises the graphics GsDefDispBuff(0,0,0,SCREEN_HEIGHT); /* Defines the double buffering area within the frame buffer */ FntLoad(960,0); // Loads a PlayStation font into the Frame buffer memory FntOpen(20,0,SCREEN_WIDTH,100,0,256); //Sets the attributes for the loaded font if(SCREEN_HEIGHT==256) GsDISPENV.screen.h = SCREEN_HEIGHT; /* Helps to slightly correct the PAL letterbox problems */ for(i=0;i<2;i++) // Initialises the Ordering Tables { WorldOT[i].length = OT_LENGTH; WorldOT[i].org = OTTags[i]; } printf("\nLoading Sprites:\n"); // Sends text to the PC screen // the following 'for' loop runs the InitSprite() function for each frame of the animation for(i=0;i<4;i++) { if(i==0) currentSpriteAddress=SPRITE_ADDRESS; // Loads frame 0 into memory if(i==1) currentSpriteAddress=SPRITE_ADDRESS2; // Loads frame 1 into memory if(i==2) currentSpriteAddress=SPRITE_ADDRESS3; // Loads frame 2 into memory if(i==3) currentSpriteAddress=SPRITE_ADDRESS4; // Loads frame 3 into memory InitSprite(&sprite[i],currentSpriteAddress); /* This is the actual call which runs InitSprite() for each of the above */ } currentSprite=0; // Sets the value of currentSprite to equal 0 framePerSecondCount=0; // Sets the stating value of the frames counter to equal 0 // Sets the address of the joypad buffers GetPadBuf(&pad1Buffer,&pad2Buffer); //Main Program Loop. Loops until Select is pressed on the joypad while((InitPads()) != 99) { framePerSecondCount++; // Increments the frames per second count if(framePerSecondCount>20) // Loop to slow down animation speed { currentSprite++; // Increments the current sprite number if(currentSprite>3) // Loops the sprite animation { currentSprite=0; } framePerSecondCount=1; //Resets the frames counter } FntPrint("Animation Frame: %d", currentSprite); /* Prints the animation frame number to the PlayStation screen */ activeBuffer = GsGetActiveBuff(); // Finds out which buffer is being used GsSetWorkBase((PACKET *)GpuPacketArea[activeBuffer]); /* Initialises the space to draw the OT to */ GsClearOt(0,0,&WorldOT[activeBuffer]); // Clears the OT ready to use FntFlush(-1); // Puts text into the Ordering Table GsSortSprite(&sprite[currentSprite],&WorldOT[activeBuffer],0); // Draws sprite into OT DrawSync(0); // Waits for the above to be finished before continuing VSync(0); // Waits for television vertical retrace to finish GsSwapDispBuff(); // Swaps the display buffers around GsSortClear(0,0,0,&WorldOT[activeBuffer]); // Sorts the Ordering Table GsDrawOt(&WorldOT[activeBuffer]); // Draws the Ordering table into the active buffer } } // ------------------------ // PAD READING FUNCTION // ------------------------ static u_long ReadPads(long) // Reads the input on the PlayStation joypads. { return(~(*(pad1Buffer+3)|*(pad1Buffer+2)<<8|*(pad2Buffer+3)<<16|*(pad2Buffer+2)<<24)); } // ---------------------------- // INITIATE THE PADS FUNCTION // ---------------------------- static long InitPads() { padCheck = ReadPads(1); if(padCheck & PADselect) return(99); // Sends the value 99 to the main loop in the main() function }