/*************************************************************** main.c ====== ***************************************************************/ #include #include #include #include #include "pad.h" #define ORDERING_TABLE_LENGTH (12) #define MAX_NO_PACKETS (248000) #define SCREEN_WIDTH (320) #define SCREEN_HEIGHT (240) #define CAR_MEM_ADDR (0x80090000) #define CAR_TEX_MEM_ADDR (0x800923A0) #define SQUARE1_MEM_ADDR (0x800927E0) #define SQUARE1_TEX_MEM_ADDR (0x80093020) #define SQUARE2_MEM_ADDR (0x80093090) #define SQUARE2_TEX_MEM_ADDR (0x800938D0) #define SQUARE3_MEM_ADDR (0x80093940) #define SQUARE3_TEX_MEM_ADDR (0x80094180) #define SQUARE4_MEM_ADDR (0x800941F0) #define SQUARE4_TEX_MEM_ADDR (0x80094A30) #define SQUARE5_MEM_ADDR (0x80094AA0) #define SQUARE5_TEX_MEM_ADDR (0x800952E0) #define SQUARE6_MEM_ADDR (0x80095350) #define SQUARE6_TEX_MEM_ADDR (0x80095B90) #define SQUARE0_MEM_ADDR (0x80095C00) #define SQUARE0_TEX_MEM_ADDR (0x80096440) #define SOUNDVH_ADDR (0x80096c80) #define SOUNDVB_ADDR (0x800978a0) #define SEPERATION (1200) int VAB=0; int clunksound=-1; int SPEEDP1 = 0; int SKID=0; // car coordinate in realation to the worldGroundData arry int CarInWorld[2]; int TURN=0; int TIMER=0; #define MAX_X (30) #define MAX_Z (30) #define MAX_WORLD_OBJECTS (MAX_X * MAX_Z) char worldGroundData[MAX_Z][MAX_X] ={ {'6','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','2'}, {'4','6','1','1','4','4','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','2','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','1','2','3','0','0','0','0','0','0','0','4','4','4'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','4','5','6','0','0','0','0','0','0','0','4','4','0'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','4','0','0','4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','1','1','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','1','1','1','1','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','0'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','4','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','4','4'}, {'4','5','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','3','4'}, {'5','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','3'}, }; // chase flag, to see if the car is being tracked. u_long CHASE=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,4,//14 - 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() { // This variable keeps track of the current buffer for double buffering int currentBuffer; u_long vsyncInterval=0; //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 world DrawWorld(&theWorld, &othWorld[currentBuffer]); // draw the player DrawPlayer(&theCar, &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); // FntPrint("%d X,%d Y,%d Z\n",view.vpx,view.vpy,view.vpz); // FntPrint("%d X,%d Y,%d Z\n",theCar.gsObjectCoord.coord.t[0],theCar.gsObjectCoord.coord.t[1],theCar.gsObjectCoord.coord.t[2]); // FntPrint("%d X, %d Z\n",CarInWorld[0],CarInWorld[1]); vsyncInterval=VSync(0); // print the vsync interval FntPrint("\n\n\n\n\n\n\n\n\n\n\nVSync Inerval: %d. \n",vsyncInterval); FntPrint("\nVAB = %d",VAB); //force text FntFlush(-1); // 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,SVECTOR *rotateVector, int nRX, int nRY, int nRZ) { MATRIX matTmp; //SVECTOR svRotate; 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; } //********************************************************************************************* // 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; } //********************************************************************************************* // InitialiseStaticView //********************************************************************************************* void InitialiseStaticView(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); } //********************************************************************************************* // InitialiseTrackerView //********************************************************************************************* void InitialiseTrackerView(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 = &theCar.gsObjectCoord ; // Activate view GsSetRefView2(view); } void InitialisePlayer(PlayerStructType1 *thePlayer, int nX, int nY, int nZ, unsigned long * lModelAddress) { // initialise the players rotation vector to 0 thePlayer->rotation.vx=0;thePlayer->rotation.vy=0; thePlayer->rotation.vz=0; thePlayer->facing.vx=0;thePlayer->facing.vy=0; thePlayer->facing.vz=0; // initialise other player variables and link in tmd AddModelToPlayer(thePlayer, 0, 0,0, (unsigned long *)CAR_MEM_ADDR); //-200 } //********************************************************************************************* // Reset Model //********************************************************************************************* 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; } //********************************************************************************************* // 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 } //********************************************************************************************* // Skid Model //********************************************************************************************* void SkidModel (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 = ONE; startVector.vy = 0; startVector.vz = 0 ; // 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 } //********************************************************************************************* // LoadTexture //********************************************************************************************* // load up from conventional memory into video memory int LoadTexture(long addr) { RECT rect; GsIMAGE tim1; // get tim info/header, again a little bit of magic is needed the // pointer // is incremented past the first 4 positions to get to this! GsGetTimInfo((u_long *)(addr+4),&tim1); // set the rect struct to contain the images x and y offset, width // and height rect.x=tim1.px; rect.y=tim1.py; rect.w=tim1.pw; rect.h=tim1.ph; //load image from main memory to video memory LoadImage(&rect,tim1.pixel); // if image has clut we need to load it too, //pmode =8 for 4 bit and 9 for 8 bit colour if((tim1.pmode>>3)&0x01) { // set the rect struct to contain the clut's x and y offset, width // and height rect.x=tim1.cx; rect.y=tim1.cy; rect.w=tim1.cw; rect.h=tim1.ch; // load the clut into video memory LoadImage(&rect,tim1.clut); } // wait for load to finish by calling drawsync. DrawSync(0); return(0); } //********************************************************************************************* // AddModelToWorld //********************************************************************************************* void AddModelToWorld(WorldStructType0 *theWorld, int nX, int nY, int nZ,unsigned long *lModelAddress) { theWorld->lObjectPointer[theWorld->nTotalModels] = (unsigned long*)lModelAddress; //increment the pointer to move past the model id. (weird huh?) theWorld->lObjectPointer[theWorld->nTotalModels]++; // map tmd data to its actual address GsMapModelingData(theWorld->lObjectPointer[theWorld->nTotalModels]); //initialise the objects coordinate system - set to be that of the WORLD GsInitCoordinate2(WORLD, &theWorld->gsObjectCoord [theWorld->nTotalModels]); //increment pointer twice more-to point to top of model data (beats me!) theWorld->lObjectPointer[theWorld->nTotalModels]++; theWorld->lObjectPointer[theWorld->nTotalModels]++; // link the model (tmd) with the players object handler GsLinkObject4((unsigned long)theWorld->lObjectPointer [theWorld->nTotalModels], &theWorld->gsObjectHandler [theWorld->nTotalModels], 0); // set the amount of polygon subdivision that will be done at runtime theWorld->gsObjectHandler[theWorld->nTotalModels].attribute = GsDIV1; // Assign the coordinates of the object model to the Object Handler theWorld->gsObjectHandler[theWorld->nTotalModels].coord2 = &theWorld->gsObjectCoord[theWorld->nTotalModels]; // Set The Position of the Object theWorld->gsObjectCoord[theWorld->nTotalModels].coord.t[0]=nX; // X theWorld->gsObjectCoord[theWorld->nTotalModels].coord.t[1]=nY; // Y theWorld->gsObjectCoord[theWorld->nTotalModels].coord.t[2]=nZ; // Z // Increment the object counter theWorld->nTotalModels++; // flag the object as needing to be drawn theWorld->gsObjectCoord[theWorld->nTotalModels].flg = 0; } //********************************************************************************************* // InitialiseWorld //********************************************************************************************* void InitialiseWorld () { int tmpx,tmpz; char c; //initialise total number of models to zero theWorld.nTotalModels=0; // then for each element of the worldGroundData array if we find a 1 // then place an instance of square1.tmd at the appropriate position // in the world. // load up the square1 texture to video memeory LoadTexture(SQUARE1_TEX_MEM_ADDR); // load up the square1 texture to video memeory LoadTexture(SQUARE2_TEX_MEM_ADDR); LoadTexture(SQUARE3_TEX_MEM_ADDR); LoadTexture(SQUARE4_TEX_MEM_ADDR); LoadTexture(SQUARE5_TEX_MEM_ADDR); LoadTexture(SQUARE6_TEX_MEM_ADDR); LoadTexture(SQUARE0_TEX_MEM_ADDR); for (tmpz = 0; tmpz < MAX_Z; tmpz++ ) { for (tmpx = 0; tmpx < MAX_X; tmpx++ ) { c= worldGroundData[tmpz][tmpx]; if(c== '0') { // AddModelToWorld(&theWorld, (tmpz* SEPERATION), (0), // (tmpx * SEPERATION), // (u_long *) SQUARE1_MEM_ADDR); // // theWorld.gsObjectHandler[theWorld.nTotalModels-1].attribute += (1<<31); AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE0_MEM_ADDR); } if(c == '1') { AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE1_MEM_ADDR); } //end if if(c == '2') { AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE2_MEM_ADDR); } //end if if(c == '3') { AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE3_MEM_ADDR); } //end if if(c == '4') { AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE4_MEM_ADDR); } //end if if(c == '5') { AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE5_MEM_ADDR); } //end if if(c == '6') { AddModelToWorld(&theWorld, (tmpz * SEPERATION),(0), (tmpx * SEPERATION), (unsigned long *)SQUARE6_MEM_ADDR); } //end if } // ) end for tmpx } //end for tmpz } //********************************************************************************************* // Draw world //********************************************************************************************* void DrawWorld(WorldStructType0 *theWorld, GsOT *othWorld) { MATRIX tmpls, tmplw; // int nCurrentModel; int i=0,j=0; // int tilex, tilez; int XCLIP=5, ZCLIP=5; int XCLIPM=11,ZCLIPM=11; u_long tTemp1, tTemp2, tTemp3, tTemp4, tFlag; // for (nCurrentModel = 0; nCurrentModel < theWorld->nTotalModels; nCurrentModel++) // { for (tTemp1 = 0; tTemp1= MAX_X) tFlag = 1; if (tFlag == 0) { for (tTemp2 = 0; tTemp2 < ZCLIPM; tTemp2++) { tFlag=0; tTemp4 = tTemp2 -ZCLIP + CarInWorld[1]; if (tTemp4 < 0) tFlag=1; if (tTemp4 >= MAX_Z) tFlag = 1; if (tFlag == 0) { //Get the local world and screen coordinates, needed for light //calculations GsGetLws(theWorld->gsObjectHandler[tTemp3 * MAX_X + tTemp4].coord2, &tmplw, &tmpls); // Set the resulting light source matrix GsSetLightMatrix(&tmplw); // Set the local screen matrix for the GTE (so it works out // perspective etc) GsSetLsMatrix(&tmpls); // Send Object To Ordering Table GsSortObject4( &theWorld->gsObjectHandler[tTemp3 * MAX_X + tTemp4], othWorld, 14 - ORDERING_TABLE_LENGTH,(u_long *)getScratchAddr(0)); } } } } // } } //added from step 5 // //void MoveCar(GsCOORDINATE2 *gsObjectCoord,SVECTOR *rotateVector, int nRX, int nRY, int nRZ, int nD) // //********************************************************************************************* // process user input //********************************************************************************************* void ProcessUserInput() { PADstatus=PadRead(); if(PADstatus & PADselect && PADstatus & PADstart )PLAYING=0; if(PADstatus & PADLright && PADstatus & PADLleft)TURN=0; if(PADstatus & PADLleft) { // FntPrint("\nLeft Arrow:Rotate Left\n"); // RotateModel(&theCar.gsObjectCoord,&theCar.rotation,0,-20,0); if(TURN>-60)TURN=TURN-2; } if(PADstatus & PADLright) { // FntPrint("\nRight Arrow:Rotate Right\n"); // RotateModel(&theCar.gsObjectCoord,&theCar.rotation,0,20,0); if(TURN<60)TURN=TURN+2; } //doesnt seem to work if(!PADstatus & PADLright && !PADstatus & PADLleft) { if (TURN>0)TURN=TURN-1; if (TURN<0)TURN=TURN+1; // FntPrint("\nPAD Start\n"); } if(PADstatus & PADstart) { // FntPrint("\nPAD Start\n"); } if(PADstatus & PADcross) { // FntPrint("\nPAD cross:Move Forward\n"); // MoveModel(&theCar.gsObjectCoord,0,0,10); if (SPEEDP1<120)SPEEDP1=SPEEDP1+2; // AdvanceModel(&theCar.gsObjectCoord,&theCar.rotation,15); } if(PADstatus & PADsquare) { // FntPrint("\nPAD square:Move Breaks\n"); // MoveModel(&theCar.gsObjectCoord,0,0,-10); // AdvanceModel(&theCar.gsObjectCoord,&theCar.rotation,-10); if(SPEEDP1>0)SPEEDP1=SPEEDP1-4; if(SPEEDP1<0)SPEEDP1=SPEEDP1+1; } if (PADstatus & PADL1) { // FntPrint ( "\nPAD padL1:STATIC_VIEW\n"); InitialiseStaticView(&view, 250, 0, 1000,-500, 0, 0, 0, 0 ); CHASE=0; } if (PADstatus & PADL2) { // FntPrint ( "\nPAD padL1:STATIC_VIEW\n"); clunksound=SsUtKeyOn(VAB,0,0,42,0,127,127); } if (PADstatus & PADR1) { // FntPrint ( "\nPAD padR1:TRACKER_VIEW\n"); // InitialiseTrackerView(&view, 250, 0, 0, -1000, -1000, 0,500,-100); CHASE=1; } if (PADstatus & PADR2) { // FntPrint ( "\nPAD padR1:TRACKER_VIEW\n"); // InitialiseTrackerView(&view, 250, 0, 0, -1000, -1000, 0,500,-100); CHASE=2; } if (PADstatus & PADtriangle) { SsUtKeyOff(0,VAB,0,42,0); clunksound=SsUtKeyOn(VAB,0,0,42,0,127,127); } if (PADstatus & PADstart) { // FntPrint ("PAD start\n"); theCar.gsObjectCoord.coord=GsIDMATRIX; // theCar.speed=0; theCar.rotation.vx=0; theCar.rotation.vy=0; theCar.rotation.vy=0; theCar.gsObjectCoord.flg=0; CHASE=0;SPEEDP1=0;TURN=0; // FntPrint ( "\nPAD padL1:STATIC_VIEW\n"); InitialiseStaticView(&view, 250, 0, 1000, -500, 0, 0, 0, 0 ); } } //********************************************************************************************* // gamestuff //********************************************************************************************* void GameStuff() { if (TURN>0)TURN=TURN-1; if (TURN<0)TURN=TURN+1; //dump speed FntPrint("%d SPEED",SPEEDP1); //keep tracking if(CHASE==1)InitialiseTrackerView(&view, 250, 0, 0, -1000, -3000, 0,500,-100); //keep tracking if(CHASE==2)InitialiseTrackerView(&view, 250, 0, 0, -10000, -0, 0,0,-0); //friction if (SPEEDP1>0)(SPEEDP1=SPEEDP1-1); if (SPEEDP1==0)TURN=0; //car turning by value turn //keep moving it moving if(SPEEDP1>0||SPEEDP1<0) { if(SPEEDP1>0 && SPEEDP1<100) { MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,0,0,SPEEDP1); MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,TURN,0,0); } //AdvanceModel(&theCar.gsObjectCoord,&theCar.rotation, SPEEDP1); //work out car coordinate in the world arry CarInWorld[0]= (int)(theCar.gsObjectCoord.coord.t[0]/SEPERATION); CarInWorld[1]= (int)(theCar.gsObjectCoord.coord.t[2]/SEPERATION); // keep car in world if(theCar.gsObjectCoord.coord.t[0]<-SEPERATION)theCar.gsObjectCoord.coord.t[0]=theCar.gsObjectCoord.coord.t[0]+100; if(theCar.gsObjectCoord.coord.t[0]>SEPERATION*MAX_X)theCar.gsObjectCoord.coord.t[0]=theCar.gsObjectCoord.coord.t[0]-100; if(theCar.gsObjectCoord.coord.t[2]<-SEPERATION)theCar.gsObjectCoord.coord.t[2]=theCar.gsObjectCoord.coord.t[2]+100; if(theCar.gsObjectCoord.coord.t[2]>SEPERATION*MAX_Z)theCar.gsObjectCoord.coord.t[2]=theCar.gsObjectCoord.coord.t[2]-100; // FntPrint("CHAR=%c",worldGroundData[CarInWorld[0]][CarInWorld[1]]); // FntPrint(" INT=%d",worldGroundData[CarInWorld[0]][CarInWorld[1]]); if(SPEEDP1>=100) { if(TIMER==0 && (PADstatus & PADLright || PADstatus & PADLleft)) { TIMER=25; SsUtKeyOff(0,VAB,0,42,0); clunksound=SsUtKeyOn(VAB,0,0,42,0,127,127); } if(TIMER>0)TIMER=TIMER-1; // if(SPEEDP1>0 && SPEEDP1<100)MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,30,0,0); MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,TURN,0,SPEEDP1); if (SPEEDP1>=100 && PADstatus & PADcross) { // if(SKID==0){SKID=20;} // if(SKID>0){SKID=SKID-1;} // if(SKID>0) { SkidModel(&theCar.gsObjectCoord,&theCar.rotation,-TURN*2); // MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,TURN,0,SPEEDP1); } // if(SPEEDP1>60)MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,30,0,0); } if (SPEEDP1>=100 && ! PADstatus & PADcross) { // if(SKID==0){SKID=20;} // if(SKID>0){SKID=SKID-1;} // if(SKID>0) { SkidModel(&theCar.gsObjectCoord,&theCar.rotation,-TURN); } // if(SPEEDP1>60)MoveCar(&theCar.gsObjectCoord,&theCar.rotation,0,30,0,0); } } } if(worldGroundData[CarInWorld[0]][CarInWorld[1]]=='0')FntPrint("\n\n\n Get back on!\n"); //force text FntFlush(-1); } //********************************************************************************************* // move car //********************************************************************************************* void MoveCar(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; /* if (SKID>0) { gsObjectCoord->coord.t[0] +=(oldDirection.vx * nD)/4096; gsObjectCoord->coord.t[1] +=(oldDirection.vy * nD)/4096; gsObjectCoord->coord.t[2] +=(oldDirection.vz * nD)/4096; } */ // Because it has changed set flg to redraw object gsObjectCoord->flg = 0; } //end if } //********************************************************************************************* // main //********************************************************************************************* int main() { // 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 SsVabTransfer (SOUNDVH_ADDR, SOUNDVB_ADDR,-1,1); 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 *)CAR_MEM_ADDR); // new function InitialisePlayer(&theCar,0, -200,0, (unsigned long *)CAR_MEM_ADDR); LoadTexture(CAR_TEX_MEM_ADDR); InitialiseWorld(); while(PLAYING) // while(1) { // RotateModel(&theCar.gsObjectCoord,&theCar.rotation,0,10,0); // if (PADstatus & PADselect) break; GameStuff(); ProcessUserInput(); // currentBuffer=GsGetActiveBuff(); RenderWorld(&theCar); // FntPrint("Code Warrior Rulez!\n"); FntFlush(-1); } // clean up ResetGraph(0); return 0; }