/*************************************************************** main.c ====== ***************************************************************/ #include #include #include #include #include "pad.h" #define ORDERING_TABLE_LENGTH (14) #define MAX_NO_PACKETS (248000) #define SCREEN_WIDTH (320) #define SCREEN_HEIGHT (240) //#define CAR_MEM_ADDR (0x80090000) #define F1_A 0x80090000 #define F2_A 0x80093C2C #define F3_A 0x80097858 #define F4_A 0x8009B484 #define F5_A 0x8009F0B0 #define F6_A 0x800A2CDC #define F7_A 0x800A6908 #define F8_A 0x800AA534 #define F9_A 0x800AE160 #define BOTTOP_A 0x800C4428 #define CUBE_A 0x800C7034 // frame number int FRAME=0; // we need a variable to store the status of the joypad u_long PADstatus=0; // We need two Ordering Table Headers, one for each buffer GsOT othWorld[2]; // And we need Two Ordering Tables, one for each buffer GsOT_TAG otWorld[2][1<gsObjectCoord); // increment pointer twice more - to point to top of model data // (beats me!) lModelAddress++; lModelAddress++; // link the model (tmd) with the players object handler // change unsigned long * to unsigned long GsLinkObject4((unsigned long )lModelAddress, &thePlayer->gsObjectHandler,0); // Assign the coordinates of the object model to the Object Handler thePlayer->gsObjectHandler.coord2 = &thePlayer->gsObjectCoord; // Set the initial position of the object thePlayer->gsObjectCoord.coord.t[0]=nX; // X thePlayer->gsObjectCoord.coord.t[1]=nY; // Y thePlayer->gsObjectCoord.coord.t[2]=nZ; // Z // setting the players gsObjectCoord.flg to 0 indicates it is to be // drawn thePlayer->gsObjectCoord.flg = 0; } // This function deals with setting up matrices needed for rendering // and sends the object to the ordering table so it is drawn //********************************************************************************************* // DrawPlayer //********************************************************************************************* void DrawPlayer(PlayerStructType1 *thePlayer, GsOT *othWorld) { MATRIX tmpls, tmplw; GsDOBJ2 *tmpPtr; // Set The Local World/Screen MATRIX GsGetLws(thePlayer->gsObjectHandler.coord2, &tmplw, &tmpls); GsSetLightMatrix(&tmplw); GsSetLsMatrix(&tmpls); tmpPtr = &thePlayer->gsObjectHandler; // Send Object To Ordering Table GsSortObject4( tmpPtr,othWorld,2,//16 - ORDERING_TABLE_LENGTH, (u_long *)getScratchAddr(0)); } //********************************************************************************************* // InitialiseLight //********************************************************************************************* void InitialiseLight(GsF_LIGHT *flLight, int nLight, int nX, int nY, int nZ, int nRed, int nGreen, int nBlue) { // Set the direction in which light travels flLight->vx = nX;flLight->vy = nY; flLight->vz = nZ; // Set the colour flLight->r = nRed; flLight->g = nGreen; flLight->b = nBlue; // Activate light GsSetFlatLight(nLight, flLight); } //********************************************************************************************* // InitialiseAllLights //********************************************************************************************* void InitialiseAllLights() { InitialiseLight(&flLights[0], 0, -1, -1, -1, 255,255,255); InitialiseLight(&flLights[1], 1, 1, 1, 1, 255,255,255); GsSetAmbient(0,0,0); GsSetLightMode(0); } //********************************************************************************************* // InitialiseView //********************************************************************************************* void InitialiseView(GsRVIEW2 *view, int nProjDist, int nRZ, int nVPX, int nVPY, int nVPZ, int nVRX, int nVRY, int nVRZ) { // This is the distance between the eye // and the imaginary projection screen GsSetProjection(nProjDist); // Set the eye position or center of projection view->vpx = nVPX; view->vpy = nVPY; view->vpz = nVPZ; // Set the look at position view->vrx = nVRX; view->vry = nVRY; view->vrz = nVRZ; // Set which way is up view->rz=-nRZ; // Set the origin of the coord system in this case the car view->super = WORLD; //&theCar.gsObjectCoord ; // Activate view GsSetRefView2(view); } //********************************************************************************************* // InitialiseGraphics //********************************************************************************************* // this function initialises the graphics system void InitialiseGraphics() { // Initialise The Graphics System to PAL as opposed to NTSC SetVideoMode(MODE_PAL); // Set the Actual Size of the Video memory GsInitGraph(SCREEN_WIDTH, SCREEN_HEIGHT, GsINTER|GsOFSGPU, 1, 0); // Set the Top Left Coordinates Of The Two Buffers in video memory GsDefDispBuff(0, 0, 0, SCREEN_HEIGHT); // Initialise the 3D Graphics... GsInit3D(); // Before we can use the ordering table headers, // we need to... // 1. Set them to the right length othWorld[0].length = ORDERING_TABLE_LENGTH; othWorld[1].length = ORDERING_TABLE_LENGTH; // 2. Associate them with an actual ordering table othWorld[0].org = otWorld[0]; othWorld[1].org = otWorld[1]; // 3. initialise the World Ordering Table Headers and Arrays GsClearOt(0,0,&othWorld[0]); GsClearOt(0,0,&othWorld[1]); } //********************************************************************************************* // RenderWorld //********************************************************************************************* // This function deals with double buffering and drawing of 3D objects void RenderWorld(PlayerStructType1 *thePlayer) { // This variable keeps track of the current buffer for double buffering int currentBuffer; //get the current buffer currentBuffer=GsGetActiveBuff(); // set address for GPU scratchpad area GsSetWorkBase((PACKET*)out_packet[currentBuffer]); // clear the ordering table GsClearOt(0, 0, &othWorld[currentBuffer]); // draw the player DrawPlayer(thePlayer, &othWorld[currentBuffer]); //print your elegant message // FntPrint("Code Warrior Rules!\n"); // force text output to the PSX screen FntFlush(-1); // wait for end of drawing DrawSync(0); // wait for V_BLANK interrupt VSync(0); // swap double buffers GsSwapDispBuff(); // register clear-command: clear ordering table to black GsSortClear(0, 0, 0,&othWorld[currentBuffer]); // register request to draw ordering table GsDrawOt(&othWorld[currentBuffer]); } //********************************************************************************************* // RenderGAMEWorld //********************************************************************************************* // This function deals with double buffering and drawing of 3D objects void RenderGAMEWorld(PlayerStructType1 *thePlayer) { // This variable keeps track of the current buffer for double buffering int currentBuffer; //get the current buffer currentBuffer=GsGetActiveBuff(); // set address for GPU scratchpad area GsSetWorkBase((PACKET*)out_packet[currentBuffer]); // clear the ordering table GsClearOt(0, 0, &othWorld[currentBuffer]); // draw the player DrawPlayer(thePlayer, &othWorld[currentBuffer]); // DrawPlayer(&cube, &othWorld[currentBuffer]); DrawPlayer(&bottop, &othWorld[currentBuffer]); // force text output to the PSX screen FntFlush(-1); // wait for end of drawing DrawSync(0); // wait for V_BLANK interrupt VSync(0); // swap double buffers GsSwapDispBuff(); // register clear-command: clear ordering table to black GsSortClear(0, 0, 0,&othWorld[currentBuffer]); // register request to draw ordering table GsDrawOt(&othWorld[currentBuffer]); } //********************************************************************************************* // RotateModel //********************************************************************************************* // added in for step 4 void RotateModel(GsCOORDINATE2 *gsObjectCoord,int nRX, int nRY, int nRZ) { MATRIX matTmp; SVECTOR svRotate; // rotation vector svRotate.vx = nRX; svRotate.vy = nRY; svRotate.vz = nRZ; //RotMatrix sets up the matix coefficients for rotation RotMatrix(&svRotate, &matTmp); //concatenate the existing objects with the rotation matrix MulMatrix0(&gsObjectCoord->coord, &matTmp,&gsObjectCoord->coord); gsObjectCoord->flg=0; } //********************************************************************************************* // MoveModel //********************************************************************************************* void MoveModel (GsCOORDINATE2 *gsObjectCoord, int nX, int nY, int nZ) { gsObjectCoord->coord.t[0]=gsObjectCoord->coord.t[0]+nX; gsObjectCoord->coord.t[1]=gsObjectCoord->coord.t[1]+nY; gsObjectCoord->coord.t[2]=gsObjectCoord->coord.t[2]+nZ; gsObjectCoord->flg=0; } //********************************************************************************************* // Advance model //********************************************************************************************* // move the model nD steps in the direction it is pointing void AdvanceModel (GsCOORDINATE2 *gsObjectCoord, SVECTOR *rotateVector, int nD) { // Moves the model nD units in the direction of its rotation vector MATRIX matTmp; SVECTOR startVector; SVECTOR currentDirection; // if nD = 0 there is no movement and we need to avoid the // main body of the function which will cause a divide by zero error if(nD!=0){ // set up original vector, pointing down the positive z axis startVector.vx = 0; startVector.vy = 0; startVector.vz = ONE; // RotMatrix sets up the matrix coefficients for rotation RotMatrix(rotateVector, &matTmp); // multiply startVector by mattmp and put the result in // currentDirection which is the vector defining the direction // the player is pointing ApplyMatrixSV(&matTmp, &startVector, ¤tDirection); // set the translation based on the currentDirection, note // currentDirection components have been scaled by 4096 so we // divide by 4096 to scale them back gsObjectCoord->coord.t[0] +=(currentDirection.vx * nD)/4096; gsObjectCoord->coord.t[1] +=(currentDirection.vy * nD)/4096; gsObjectCoord->coord.t[2] +=(currentDirection.vz * nD)/4096; // Because it has changed set flg to redraw object gsObjectCoord->flg = 0; } //end if } //********************************************************************************************* // reset the matrix //********************************************************************************************* void ResetMatrix (short m[3][3]) { m[0][0]=m[1][1]=m[2][2]=ONE; m[0][1]=m[0][2]=m[1][0]=m[1][2]=m[2][0]=m[2][1]=0; } //********************************************************************************************* // move object //********************************************************************************************* void MoveObject(GsCOORDINATE2 *gsObjectCoord,SVECTOR *rotateVector, int nRX, int nRY, int nRZ, int nD) { MATRIX matTmp; //SVECTOR svRotate; ///////////////////// SVECTOR startVector; SVECTOR currentDirection; // SVECTOR oldDirection; ////////////////////////////////////////////////////////////////////////////////// // Moves the model nD units in the direction of its rotation vector // MATRIX matTmp; ///////////////// ResetMatrix(gsObjectCoord->coord.m); // rotation vector rotateVector->vx = (rotateVector->vx+nRX)%ONE; rotateVector->vy = (rotateVector->vy+nRY)%ONE; rotateVector->vz = (rotateVector->vz+nRZ)%ONE; //RotMatrix sets up the matix coefficients for rotation RotMatrix(rotateVector, &matTmp); //concatenate the existing objects with the rotation matrix MulMatrix0(&gsObjectCoord->coord, &matTmp,&gsObjectCoord->coord); // gsObjectCoord->flg=0; ////////////////////////////// // if nD = 0 there is no movement and we need to avoid the // main body of the function which will cause a divide by zero error if(nD!=0){ // set up original vector, pointing down the positive z axis startVector.vx = 0; startVector.vy = 0; startVector.vz = ONE; // RotMatrix sets up the matrix coefficients for rotation RotMatrix(rotateVector, &matTmp); // multiply startVector by mattmp and put the result in // currentDirection which is the vector defining the direction // the player is pointing ApplyMatrixSV(&matTmp, &startVector, ¤tDirection); // set the translation based on the currentDirection, note // currentDirection components have been scaled by 4096 so we // divide by 4096 to scale them back gsObjectCoord->coord.t[0] +=(currentDirection.vx * nD)/4096; gsObjectCoord->coord.t[1] +=(currentDirection.vy * nD)/4096; gsObjectCoord->coord.t[2] +=(currentDirection.vz * nD)/4096; // gsObjectCoord->flg = 0; } //end if gsObjectCoord->flg = 0; } ///////////////////////////////////////////////////////////////////// // process user input ///////////////////////////////////////////////////////////////////// void ProcessUserInput() { //read pad PADstatus=PadRead(); if (PADstatus & PADselect && PADstatus & PADstart) PLAYING=0; if (PADstatus & PADLright ) { MoveObject(&bot[0].gsObjectCoord,&bot[0].rotation,0,50,0,0); } if (PADstatus & PADLleft ) { MoveObject(&bot[0].gsObjectCoord,&bot[0].rotation,0,-50,0,0); } if (PADstatus & PADR1 ) { MoveObject(&bottop.gsObjectCoord,&bottop.rotation,0,50,0,0); // bottop.rotation = bot[0].rotation; } if (PADstatus & PADL1 ) { MoveObject(&bottop.gsObjectCoord,&bottop.rotation,0,-50,0,0); // bottop.rotation = bot[0].rotation; } if (PADstatus & PADLup ) { bottop.rotation = bot[0].rotation; FRAME = (FRAME+1) % (9<<4); MoveObject(&bot[0].gsObjectCoord,&bot[0].rotation,0,0,0,-2); MoveObject(&bottop.gsObjectCoord,&bottop.rotation,0,0,0,-2); } if (PADstatus & PADLdown ) { bottop.rotation = bot[0].rotation; FRAME = (FRAME-1) % (9<<4); if(FRAME<0)FRAME=1000; MoveObject(&bot[0].gsObjectCoord,&bot[0].rotation,0,0,0,2); MoveObject(&bottop.gsObjectCoord,&bottop.rotation,0,0,0,2); } } // //******************************************************************** // main //******************************************************************** int main() { int tempi; // set up print-to-screen font, the parameters are where the font is // loaded into the frame buffer FntLoad(960, 256); //specify where to write on the PSX screen FntOpen(-96, -96, 192, 192, 0, 512); // initialise the joypad PadInit(); // initialise graphics InitialiseGraphics(); // Setup view to view the car from the side InitialiseView(&view, 250, 0, 1000, -500, 0, 0, 0, 0 ); InitialiseAllLights(); // The car's initial xyz is set to 0,-200,0 // changed long* to unsigned long * // AddModelToPlayer(&theCar, 0, -200,0, (unsigned long *)F1_A); AddModelToPlayer(&bot[0], 0, 0,0, (unsigned long *)F1_A); AddModelToPlayer(&bot[1], 0, 0,0, (unsigned long *)F2_A); AddModelToPlayer(&bot[2], 0, 0,0, (unsigned long *)F3_A); AddModelToPlayer(&bot[3], 0, 0,0, (unsigned long *)F4_A); AddModelToPlayer(&bot[4], 0, 0,0, (unsigned long *)F5_A); AddModelToPlayer(&bot[5], 0, 0,0, (unsigned long *)F6_A); AddModelToPlayer(&bot[6], 0, 0,0, (unsigned long *)F7_A); AddModelToPlayer(&bot[7], 0, 0,0, (unsigned long *)F8_A); AddModelToPlayer(&bot[8], 0, 0,0, (unsigned long *)F9_A); AddModelToPlayer(&cube, 0, 0,0, (unsigned long *)CUBE_A); AddModelToPlayer(&bottop, 0, -200,0, (unsigned long *)BOTTOP_A); for (tempi=1;tempi<9;tempi++) { bot[tempi].gsObjectHandler.coord2 = &bot[0].gsObjectCoord; } bottop.rotation = bot[0].rotation; while(PLAYING) { ProcessUserInput(); RenderGAMEWorld(&bot[FRAME>>4]); // RenderWorld(&bottop); } // clean up ResetGraph(0); return 0; }