/**************************************************** * * * TEXTURE PAGE ANIMATION TEST CODE * * ================================== * * * * Written by Steven Lewis * * * * Downloaded from: * * Steve's Yaroze Site * * http://www.netyaroze-europe.com/~slewis/ * * * * e-mail: * * stevenlewis@birminghamhome.freeserve.co.uk * * * * This code loads in one TIM file and, by * * changing the U and V values of the image, * * creates an amazing(!) two-framed animation. * * Pressing left on the joyapd in port 1 reveals * * this epic piece of coding. The reason behind * * this code is just to highlight the * * techniques involved in using this process * * to create an animation. Alterations can * * easily be made to this code to produce more * * advanced animations consisting of many more * * frames, but I could only be bothered to put * * in two. Please note that if you decide to * * use this code with an image of your own, you * * will need to make a note of the width of your * * TIM file. The one used in this example (which * * took a whole minute to draw) is 100 pixels * * wide, and in the code below you will see * * reference to this value being halved when left * * is pressed on the joypad. You will need to * * alter this value to suit whatever width your * * image is. Also of note is that as far as I am * * aware every sprite needs to be taken from an * * area of exactly the same size. For example, in * * this code the images are located in TIM file * * areas of 50 pixels by 200 pixels. If another * * frame was added, it would need to be in another * * area of this size. This is due to the way the * * this animation method works, the TIM file is * * broken up into sections of a certain size and * * whatever is contained within that section is * * displayed. Got that? Good! And can I once * * again apologise for the quality of the sprites. * * I will try harder next time :) * * * ****************************************************/ // -------------- // HEADER FILES // -------------- #include #include // ------------- // DEFINITIONS // ------------- #define SPRITE_COUNT (2) // Set the total number of sprites #define TIM_ADDRESS (0x80094000) // Memory location of the single TIM file #define SCREEN_WIDTH (320) // Sets the width of the screen #define SCREEN_HEIGHT (256) // Sets the height of the screen #define SPRITETPAGEX (100) // Sets the width of the TIM file #define SPRITETPAGEY (200) // Sets the height of the TIM file // ------------------------- // SPRITE STRUCTURE POINTER // ------------------------- GsSPRITE sprite; // Sets a structure to load the TIM into // ------------------------- // ORDERING TABLE VARIABLES // ------------------------- #define OT_LENGTH (1) // Sets the length of the Ordering Table GsOT WorldOT[2]; // Sets two OT headers GsOT_TAG OTTags[2][1<(100/2)) // Keeps the texture page value at 50 while left is pressed. sprite.u=(100/2); } if(!(padCheck & PADLleft)) sprite.u=0; /* If left is not pressed then the original image is displayed on screen. This is the image that starts at the pixels value 0. */ activeBuffer = GsGetActiveBuff(); // Finds out which buffer is active GsSetWorkBase((PACKET *)GpuPacketArea[activeBuffer]); // Initialises the drawing environment for the OT's GsClearOt(0,0,&WorldOT[activeBuffer]); // Clears the OT GsSortFastSprite(&sprite,&WorldOT[activeBuffer],0); // Draws tim image into the OT DrawSync(0); // Waits for the above to finish before continuing VSync(0); // Waits for Vertical retrace to finish before continuing GsSwapDispBuff(); // Swaps the display buffers - active becomes inactive etc. GsSortClear(0,0,0,&WorldOT[activeBuffer]); // Sorts the OT GsDrawOt(&WorldOT[activeBuffer]); // Draws the OT } } // ------------------------------------------ // FUNCTION TO LOAD THE TIM FILE INTO MEMORY // ------------------------------------------ void InitSprites() { RECT rect; // Creates a rectangular structure to put around the sprite GsIMAGE tim_info; // Creates a structure for holding all relevant TIM file info GsGetTimInfo((u_long *)(TIM_ADDRESS+4),&tim_info); // Gets all relevant TIM file info // Load image into the frame buffer rect.x = tim_info.px; // x position of image rect.y = tim_info.py; // y position of image rect.w = tim_info.pw; // width of image rect.h = tim_info.ph; // height of image LoadImage(&rect,tim_info.pixel); // Loads all of the above into the frame buffer // Load the CLUT into the Frame Buffer - If there is one if((tim_info.pmode>>3) & 0x01) { 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 the frame buffer } // Switch statement to load the structure of the image switch(tim_info.pmode) { // If the image is 4-bit case 0x08: sprite.attribute = 0x00000000; // Sets the sprites properties sprite.w = (tim_info.pw*4)/2; /* Sets the width of the visible image. Note the fact that it is divided by two. This is because there are two seperate sprites contained within TIM file and only one is required to be displayed at once. Subsequently the width of the sprite is set as being half of the total TIM file width. */ sprite.tpage = GetTPage(0,0,tim_info.px,tim_info.py); // Texture page info break; // Leaves the switch statement // If the image is 8-bit case 0x09: sprite.attribute = 0x01000000; sprite.w = (tim_info.pw*2)/2; sprite.tpage = GetTPage(1,0,tim_info.px,tim_info.py); break; // If the image is 16-bit default: sprite.attribute = 0x02000000; sprite.w = tim_info.pw/2; sprite.tpage = GetTPage(2,0,tim_info.px,tim_info.py); break; } sprite.x = screenPositionx; // x screen position of sprite sprite.y = screenPositiony; // y screen position of sprite sprite.h = tim_info.ph; // width of the sprite sprite.u = 0; // x texture page value sprite.v = 0; // y texture page value sprite.cx = tim_info.cx; // CLUT x position for sprite sprite.cy = tim_info.cy; // CLUT y position for sprite sprite.r = 128; // Applies a red tint to the sprite - 128 is normal sprite.g = 128; // Applies a green tint to the sprite - 128 is normal sprite.b = 128; // Applies a blue tint to the sprite - 128 is normal sprite.mx = (sprite.w/2); // Sets x value for the center of the sprite sprite.my = (sprite.h/2); // Sets y value for the center of the sprite sprite.scalex = ONE; // Sets x axis scale ratio - ONE = a 1:1 ratio sprite.scaley = ONE; // Sets y axis scale ratio - ONE = a 1:1 ratio sprite.rotate = 0; // Sets the rotation of the sprite to 'off' } // --------------------- // PAD READING FUNCTION // --------------------- static u_long ReadPad(long) { return(~(*(padBuffer+3)|*(padBuffer+2)<<8)); // Pad reading information } // ------------------------------------ // FUNCTION TO INITIATE THE PSX JOYPAD // ------------------------------------ static long InitPad() { padCheck = ReadPad(1); // If the pad is used the previous function is called if(padCheck & PADselect) // If statement to see if 'Select' is pressed on the joypad return(99); }