/*************************************************************** * * * Copyright (C) 1997 by Sony Computer Entertainment * * All rights Reserved * * * * S. Ashley 28th Feb 97 * * * ***************************************************************/ #include #include "pad.h" #include "tmd.h" #include "sincos.h" #include "arc.h" #include "usualdef.h" // GPU packet space #define PACKETMAX 2500 #define PACKETMAX2 (PACKETMAX*24) #define VHAddr (u_char *)0x80090000 #define VBAddr (u_char *)0x80092400 #define roadTIM (u_long *)0x800d0000 // 4-bit, size 0x840 #define wallTIM (u_long *)0x800d2000 // 4-bit #define floorTMD (u_long *)0x800d4000 #define carTMD (u_long *)0x800ca000 #define lengthOT1 12 #define lengthOT2 12 #define TRACK_SECTIONS 48 #define SPLINE_POINTS 6 long spline_points[6 * 3] = { 0,0,3333, 5000,0,10000, 10000,0,3333, 10000,0,-3333, 5000,0,-10000, 0,0,-3333 }; long spline_control[6 * 3] = { 0,0,10000, 10000,0,10000, 10000,0,0, 10000,0,-10000, 0,0,-10000, 0,0,0 }; long track[TRACK_SECTIONS * 6]; // the viewing system moves everything relative to the origin // this is so that errors associated with complex viewing angles do not occur typedef struct { GsCOORDINATE2 carA; // car moves to viewing position GsCOORDINATE2 carB; // car rotates to viewing angle GsCOORDINATE2 trackA; // track rotates to keep car square on GsCOORDINATE2 trackB; // track moves to where the viewing position is GsCOORDINATE2 trackC; // track moves to where the car is } viewSystem; typedef struct { VECTOR v0,v1,v2,v3; // 4 points making up section of track VECTOR u0,u1,u2,u3; // 4 points making the upright section of the track SVECTOR n; // normal of track section, up SVECTOR nl,nr; // normals of the left and right walls SVECTOR nf,nb; // normals for forwards and backwards of opposition GsDOBJ2 obj; } tracksec; typedef struct { VECTOR pos; VECTOR acc; VECTOR vel; VECTOR cuv; // catch up vector MATRIX rot; VECTOR vp; SVECTOR va; viewSystem vs; short section; } car; extern DRAWENV GsDRAWENV; extern DISPENV GsDISPENV; // ordering tables for floor & roof, (so floor & roof can be drawn first) GsOT OT1[2]; // Ordering Table header GsOT_TAG zTable1[2][1 << lengthOT1]; // actual Ordering Tables themselves // ordering tables for rest of world GsOT OT2[2]; // Ordering Table header GsOT_TAG zTable2[2][1 << lengthOT2]; // actual Ordering Tables themselves // ordering tables for floor & roof, (so floor & roof can be drawn first) GsOT OT1_b[2]; // Ordering Table header GsOT_TAG zTable1_b[2][1 << lengthOT1]; // actual Ordering Tables themselves // ordering tables for rest of world GsOT OT2_b[2]; // Ordering Table header GsOT_TAG zTable2_b[2][1 << lengthOT2]; // actual Ordering Tables themselves PACKET GpuOutputPacket[4][PACKETMAX2]; // GPU packet work area u_long PadStatus; // for the pad // the TMD object handles GsDOBJ2 carOBJ; GsDOBJ2 floorOBJ, roofOBJ, wallOBJ; GsDOBJ2 monster1OBJ, monster2OBJ, deadOBJ; GsDOBJ2 bulletOBJ, bloodOBJ, ricochetOBJ, bullet2OBJ; GsDOBJ2 healthOBJ,efloorOBJ,eroofOBJ,ewallOBJ,fwallOBJ; GsVIEW2 TheMainView; // viewing handle GsRVIEW2 refview; GsCOORDINATE2 carpos,tpos; GsCOORDINATE2 carrot,trot; GsCOORDINATE2 tt,tp; GsCOORDINATE2 scene; GsCOORDINATE2 present; // coordinate system for view from current position car player1,player2; car opposition; int buffIdx; // current output buffer short VAB; short heartvoice; // voice used by heart beat short levelvoice; int playVsync; char playingMusic; // is map being displayed char displayMap = 0; tracksec thetrack[TRACK_SECTIONS]; // stuff to change exit colours RECT exitFloorCLUTRect; RECT exitWallCLUTRect; RECT exitRoofCLUTRect; u_short exitFloorCLUT[16]; u_short exitWallCLUT[16]; u_short exitRoofCLUT[16]; char exitCLUTInc = 1; char exitCLUTVal = 0; GsSPRITE status; long fntPrintID1,fntPrintID2; MATRIX rotationMatrix; void drawObject(GsDOBJ2 *obj, MATRIX , GsCOORDINATE2 *, GsOT *ot); void initialiseTMD(u_long *tmdAddr, char objNum, GsDOBJ2 *obj); void makeSplitTMD_G_4T(u_long *addr, u_long *timAddr, u_short u0, u_short v0, u_short u1, u_short v1, u_short u2, u_short v2, u_short u3, u_short v3, TMD_NORM norm0, TMD_VERT vert0, TMD_VERT vert1, TMD_VERT vert2, TMD_VERT vert3, char trans); //***************************************************************************** inline SVECTOR normalise(SVECTOR v) { long l; // reduce numbers so they can be used in sqrt function while (fabs(v.vx) > 4096 || fabs(v.vy) > 4096 || fabs(v.vz) > 4096) { v.vx >>= 2; v.vy >>= 2; v.vz >>= 2; } l = SquareRoot(v.vx * v.vx + v.vy * v.vy + v.vz * v.vz); if (l == 0) { printf("cannot normalise 0 vector\n"); return v; } v.vx = (v.vx << 12) / l; v.vy = (v.vy << 12) / l; v.vz = (v.vz << 12) / l; return v; } //***************************************************************************** inline int length(SVECTOR *v) { int l = 0; // reduce numbers so they can be used in sqrt function // but sort out length so it works correctly while (fabs(v->vx) > 4096 || fabs(v->vy) > 4096 || fabs(v->vz) > 4096) { v->vx >>= 1; v->vy >>= 1; v->vz >>= 1; l++; } l = SquareRoot(v->vx * v->vx + v->vy * v->vy + v->vz * v->vz) << l; return l; } //***************************************************************************** inline int lengthLV(VECTOR *v) { int l = 0; // reduce numbers so they can be used in sqrt function // but sort out length so it works correctly while (fabs(v->vx) > 4096 || fabs(v->vy) > 4096 || fabs(v->vz) > 4096) { v->vx >>= 1; v->vy >>= 1; v->vz >>= 1; l++; } l = SquareRoot(v->vx * v->vx + v->vy * v->vy + v->vz * v->vz) << l; return l; } //***************************************************************************** inline void normaliseMatrix(MATRIX *m) { SVECTOR v; setVector(&v,m->m[0][0],m->m[0][1],m->m[0][2]); v = normalise(v); m->m[0][0] = v.vx; m->m[0][1] = v.vy; m->m[0][2] = v.vz; setVector(&v,m->m[1][0],m->m[1][1],m->m[1][2]); v = normalise(v); m->m[1][0] = v.vx; m->m[1][1] = v.vy; m->m[1][2] = v.vz; setVector(&v,m->m[2][0],m->m[2][1],m->m[2][2]); v = normalise(v); m->m[2][0] = v.vx; m->m[2][1] = v.vy; m->m[2][2] = v.vz; } //***************************************************************************** void fill_spline() { VECTOR v[TRACK_SECTIONS]; SVECTOR w; int s,t; int i,j; int sp = SPLINE_POINTS * 3; for (i = 0; i < SPLINE_POINTS; i++) for(j = 0; j < 8; j++) { s = 8 - j; t = j; v[i * 8 + j].vx = s * s * spline_points[i * 3] / 64; v[i * 8 + j].vx += 2 * s * t * spline_control[i * 3] / 64; v[i * 8 + j].vx += t * t * spline_points[(i * 3 + 3) % sp] / 64; v[i * 8 + j].vy = s * s * spline_points[(i * 3 + 1) % sp] / 64; v[i * 8 + j].vy += 2 * s * t * spline_control[(i * 3 + 1) % sp] / 64; v[i * 8 + j].vy += t * t * spline_points[(i * 3 + 4) % sp] / 64; v[i * 8 + j].vz = s * s * spline_points[(i * 3 + 2) % sp] / 64; v[i * 8 + j].vz += 2 * s * t * spline_control[(i * 3 + 2) % sp] / 64; v[i * 8 + j].vz += t * t * spline_points[(i * 3 + 5) % sp] / 64; } for (i = 0; i < SPLINE_POINTS; i++) for(j = 0; j < 8; j++) { w.vx = v[(i * 8 + j + 1) % TRACK_SECTIONS].vx - v[i * 8 + j].vx; w.vy = v[(i * 8 + j + 1) % TRACK_SECTIONS].vy - v[i * 8 + j].vy; w.vz = v[(i * 8 + j + 1) % TRACK_SECTIONS].vz - v[i * 8 + j].vz; w = normalise(w); track[i * 48 + j * 6] = v[(i * 8 + j + 1) % TRACK_SECTIONS].vx - w.vz / 4; track[i * 48 + j * 6 + 1] = 0; track[i * 48 + j * 6 + 2] = v[(i * 8 + j + 1) % TRACK_SECTIONS].vz + w.vx / 4; track[i * 48 + j * 6 + 3] = v[(i * 8 + j + 1) % TRACK_SECTIONS].vx + w.vz / 4; track[i * 48 + j * 6 + 4] = 0; track[i * 48 + j * 6 + 5] = v[(i * 8 + j + 1) % TRACK_SECTIONS].vz - w.vx / 4; } } //***************************************************************************** void createTrack(void) { int i; SVECTOR a,b,c; double s = 2; for (i = 0; i < TRACK_SECTIONS; i ++) { setVector(&thetrack[i].v0, s * track[((i + 1) % TRACK_SECTIONS) * 6], s * track[((i + 1) % TRACK_SECTIONS) * 6 + 1], s * track[((i + 1) % TRACK_SECTIONS) * 6 + 2]); setVector(&thetrack[i].v1, s * track[((i + 1) % TRACK_SECTIONS) * 6 + 3], s * track[((i + 1) % TRACK_SECTIONS) * 6 + 4], s * track[((i + 1) % TRACK_SECTIONS) * 6 + 5]); setVector(&thetrack[i].v2, s * track[i * 6], s * track[i * 6 + 1], s * track[i * 6 + 2]); setVector(&thetrack[i].v3, s * track[i * 6 + 3], s * track[i * 6 + 4], s * track[i * 6 + 5]); setVector(&thetrack[i].u0, thetrack[i].v0.vx, thetrack[i].v0.vy - 128, thetrack[i].v0.vz); setVector(&thetrack[i].u1, thetrack[i].v1.vx, thetrack[i].v1.vy - 128, thetrack[i].v1.vz); setVector(&thetrack[i].u2, thetrack[i].v2.vx, thetrack[i].v2.vy - 128, thetrack[i].v2.vz); setVector(&thetrack[i].u3, thetrack[i].v3.vx, thetrack[i].v3.vy - 128, thetrack[i].v3.vz); // floor copyVector(&thetrack[i].v0,&a); subVector(&a,&thetrack[i].v1); copyVector(&thetrack[i].v2,&b); subVector(&b,&thetrack[i].v0); crossProduct(&a, &b, &c); thetrack[i].n = normalise(c); // left copyVector(&thetrack[i].u2,&a); subVector(&a,&thetrack[i].u0); copyVector(&thetrack[i].v2,&b); subVector(&b,&thetrack[i].u2); crossProduct(&a, &b, &c); thetrack[i].nl = normalise(c); // right copyVector(&thetrack[i].u1,&a); subVector(&a,&thetrack[i].u3); copyVector(&thetrack[i].v1,&b); subVector(&b,&thetrack[i].u1); crossProduct(&a, &b, &c); thetrack[i].nr = normalise(c); // forward copyVector(&thetrack[i].u0,&a); subVector(&a,&thetrack[i].u1); copyVector(&thetrack[i].v0,&b); subVector(&b,&thetrack[i].u0); crossProduct(&a, &b, &c); thetrack[i].nf = normalise(c); // backward copyVector(&thetrack[i].u3,&a); subVector(&a,&thetrack[i].u2); copyVector(&thetrack[i].v3,&b); subVector(&b,&thetrack[i].u3); crossProduct(&a, &b, &c); thetrack[i].nb = normalise(c); } } //***************************************************************************** void drawTrack(MATRIX transform, GsCOORDINATE2 s, GsOT *road_ot, GsOT *rest_ot, car *p) { int i; TMD_VERT v0,v1,v2,v3; TMD_NORM nm; SVECTOR vec; MATRIX t = GsIDMATRIX; VECTOR ps,ps2; SVECTOR pv; SVECTOR va; MATRIX rm; SVECTOR n0,n1,n2,n3; for (i = 0; i < TRACK_SECTIONS; i++) { if ((i - p->section + TRACK_SECTIONS) % TRACK_SECTIONS > 5 && (p->section - i + TRACK_SECTIONS) % TRACK_SECTIONS > 5) continue; t.t[0] = transform.t[0] + thetrack[i].v0.vx; t.t[1] = transform.t[1] + thetrack[i].v0.vy; t.t[2] = transform.t[2] + thetrack[i].v0.vz; setVector(&v0, 0, 0, 0); // set up vectors for points setVector(&v1, thetrack[i].v1.vx - thetrack[i].v0.vx, thetrack[i].v1.vy - thetrack[i].v0.vy, thetrack[i].v1.vz - thetrack[i].v0.vz); setVector(&v2, thetrack[i].v2.vx - thetrack[i].v0.vx, thetrack[i].v2.vy - thetrack[i].v0.vy, thetrack[i].v2.vz - thetrack[i].v0.vz); setVector(&v3, thetrack[i].v3.vx - thetrack[i].v0.vx, thetrack[i].v3.vy - thetrack[i].v0.vy, thetrack[i].v3.vz - thetrack[i].v0.vz); setNormal(&nm, thetrack[i].n.vx, thetrack[i].n.vy, thetrack[i].n.vz); makeSplitTMD_G_4T(floorTMD, roadTIM, 0, 0, 63, 0, 0, 63, 63, 63, nm, v0, v1, v2, v3, -1); initialiseTMD(floorTMD, 0, &floorOBJ); drawObject(&floorOBJ, t, &s, road_ot); // make a left wall setVector(&v0, thetrack[i].u2.vx - thetrack[i].v0.vx, thetrack[i].u2.vy - thetrack[i].v0.vy, thetrack[i].u2.vz - thetrack[i].v0.vz); setVector(&v1, thetrack[i].u0.vx - thetrack[i].v0.vx, thetrack[i].u0.vy - thetrack[i].v0.vy, thetrack[i].u0.vz - thetrack[i].v0.vz); setVector(&v2, thetrack[i].v2.vx - thetrack[i].v0.vx, thetrack[i].v2.vy - thetrack[i].v0.vy, thetrack[i].v2.vz - thetrack[i].v0.vz); setVector(&v3, 0, 0, 0); setNormal(&nm, thetrack[i].nl.vx, thetrack[i].nl.vy, thetrack[i].nl.vz); makeSplitTMD_G_4T(floorTMD, wallTIM, 0, 0, 63, 0, 0, 63, 63, 63, nm, v0, v1, v2, v3, -1); initialiseTMD(floorTMD, 0, &floorOBJ); drawObject(&floorOBJ, t, &s, rest_ot); // make a right wall setVector(&v0, thetrack[i].u1.vx - thetrack[i].v0.vx, thetrack[i].u1.vy - thetrack[i].v0.vy, thetrack[i].u1.vz - thetrack[i].v0.vz); setVector(&v1, thetrack[i].u3.vx - thetrack[i].v0.vx, thetrack[i].u3.vy - thetrack[i].v0.vy, thetrack[i].u3.vz - thetrack[i].v0.vz); setVector(&v2, thetrack[i].v1.vx - thetrack[i].v0.vx, thetrack[i].v1.vy - thetrack[i].v0.vy, thetrack[i].v1.vz - thetrack[i].v0.vz); setVector(&v3, thetrack[i].v3.vx - thetrack[i].v0.vx, thetrack[i].v3.vy - thetrack[i].v0.vy, thetrack[i].v3.vz - thetrack[i].v0.vz); setNormal(&nm, thetrack[i].nr.vx, thetrack[i].nr.vy, thetrack[i].nr.vz); makeSplitTMD_G_4T(floorTMD, wallTIM, 0, 0, 63, 0, 0, 63, 63, 63, nm, v0, v1, v2, v3, -1); initialiseTMD(floorTMD, 0, &floorOBJ); drawObject(&floorOBJ, t, &s, rest_ot); } } //***************************************************************************** short updateSection(short s, VECTOR *pos) { VECTOR v; copyVector(&thetrack[s].v0,&v); subVector(&v,pos); if (dotProduct(&thetrack[s].nf,&v) > 0) return (s + 1) % TRACK_SECTIONS; copyVector(&thetrack[s].v3,&v); subVector(&v,pos); if (dotProduct(&thetrack[s].nb,&v) > 0) return (s - 1 + TRACK_SECTIONS) % TRACK_SECTIONS; return s; } //***************************************************************************** // tie a handler to a TMD void initialiseTMD(u_long *tmdAddr, char objNum, GsDOBJ2 *obj) { GsMapModelingData((u_long *)(tmdAddr + 1)); GsLinkObject4((u_long)(tmdAddr + 3), obj, objNum); obj->coord2 = WORLD; } //***************************************************************************** // initialise texture and clut void InitialiseTexture(u_long *timAddr) { GsIMAGE image; RECT t,c; GsGetTimInfo(++timAddr,&image); setRECT(&t,image.px,image.py,image.pw,image.ph); LoadImage(&t,image.pixel); DrawSync(0); // load CLUT as necessary if (image.pmode & 8) { setRECT(&c,image.cx,image.cy,image.cw,image.ch); LoadImage(&c,image.clut); DrawSync(0); } } //***************************************************************************** // initialise sprite void initialiseSprite(u_long *timAddr, GsSPRITE *sprite) { GsIMAGE image; RECT t,c; GsGetTimInfo(++timAddr,&image); setRECT(&t,image.px,image.py,image.pw,image.ph); LoadImage(&t,image.pixel); DrawSync(0); // load CLUT as necessary if (image.pmode & 8) { setRECT(&c,image.cx,image.cy,image.cw,image.ch); LoadImage(&c,image.clut); DrawSync(0); sprite->attribute |= (image.pmode & 3) << 24; } sprite->w = image.pw << (2 - (image.pmode & 3)); sprite->h = image.ph; sprite->u = 0; sprite->v = 0; sprite->cx = image.cx; sprite->cy = image.cy; setColor(sprite,100,100,100); sprite->tpage = (image.px >> 6) + (image.py >> 10); } //***************************************************************************** // make a gouraud shaded textured 4 sided polygon within a TMD // needs the address to put the TMD // the CBA (thats the clutx / 16 + cluty *64, 0 if in 16 bit mode) // the TSB (the texture page x / 64 + y / 256, plus info about // semi trans 0 32 64 or 96, plus colour mode 0 128 or 256) // u v coords within the texture (0,0 top left in the texture) for the vertices // the normal direction (TMD_NORM is basically a SVECTOR) // the vertices (TMD_VERT is again little more than a SVECTOR) // order of vertices, this goes for texture coords aswell // 0 +----+ 1 // | | // 2 +----+ 3 // this procedure actually divides the given polygon into 4 smaller polygons // the reason is there is less near clipping than with automatic sub division void makeSplitTMD_G_4T(u_long *addr, u_long *timAddr, u_short u0, u_short v0, u_short u1, u_short v1, u_short u2, u_short v2, u_short u3, u_short v3, TMD_NORM norm0, TMD_VERT vert0, TMD_VERT vert1, TMD_VERT vert2, TMD_VERT vert3, char trans) { TMD_OBJ *obj_table; // pointer to object table u_long *vert_table; // pointer to vertices table u_long *norm_table; // pointer to normals table u_long *prim_table; // pointer to primative table u_short CBA,TSB,pmode,pixScale; GsIMAGE image; RECT t,c; GsGetTimInfo(++timAddr,&image); pmode = (image.pmode & 3); CBA = (image.cy << 6) + (image.cx >> 4); TSB = (image.px >> 6) + (image.py >> 10) + (pmode << 7); if (trans > 0) TSB += trans << 5; // add on offset from start of texture page if (pmode == 0) pixScale = 4; else if (pmode == 1) pixScale = 2; else pixScale = 1; u0 += (image.px & 63) * pixScale; v0 += (image.py) & 511; u1 += (image.px & 63) * pixScale; v1 += (image.py) & 511; u2 += (image.px & 63) * pixScale; v2 += (image.py) & 511; u3 += (image.px & 63) * pixScale; v3 += (image.py) & 511; // ******** TMD header info ******** setTMD_HDR((TMD_HDR *)addr, 0x00000041, 1, 1); addr = (u_long *)((TMD_HDR *)addr + 1); // move to end of header // ******** skip object table, values setup later ******** obj_table = (TMD_OBJ *)addr; addr = (u_long *)((TMD_OBJ *)addr + 1); // ******** primative table ******** prim_table = addr; // primative info, specific to type of primative if (trans < 0) setPRIM_HDR((PRIM_HDR *)addr, G_4T, 0, 8, 12); else setPRIM_HDR((PRIM_HDR *)addr, G_4T | ABE, 0, 8, 12); addr = (u_long *)((PRIM_HDR *)addr + 1); // move to end of primative header // primative data setTMD_G_4T((TMD_G_4T *)addr,CBA,TSB,u0,v0,u0+(u1-u0)/2,v0+(v1-v0)/2,u0+(u2-u0)/2,v0+(v2-v0)/2,u0+(u3-u0)/2,v0+(v3-v0)/2,0,0,0,0,0,1,3,4); addr = (u_long *)((TMD_G_4T *)addr + 1); // move to end of primative data // primative info, specific to type of primative if (trans < 0) setPRIM_HDR((PRIM_HDR *)addr, G_4T, 0, 8, 12); else setPRIM_HDR((PRIM_HDR *)addr, G_4T | ABE, 0, 8, 12); addr = (u_long *)((PRIM_HDR *)addr + 1); // move to end of primative header // primative data setTMD_G_4T((TMD_G_4T *)addr,CBA,TSB,u0+(u1-u0)/2,v0+(v1-v0)/2,u1,v1,u0+(u3-u0)/2,v0+(v3-v0)/2,u1+(u3-u1)/2,v1+(v3-v1)/2,0,0,0,0,1,2,4,5); addr = (u_long *)((TMD_G_4T *)addr + 1); // move to end of primative data // primative info, specific to type of primative if (trans < 0) setPRIM_HDR((PRIM_HDR *)addr, G_4T, 0, 8, 12); else setPRIM_HDR((PRIM_HDR *)addr, G_4T | ABE, 0, 8, 12); addr = (u_long *)((PRIM_HDR *)addr + 1); // move to end of primative header // primative data setTMD_G_4T((TMD_G_4T *)addr,CBA,TSB,u0+(u2-u0)/2,v0+(v2-v0)/2,u0+(u3-u0)/2,v0+(v3-v0)/2,u2,v2,u2+(u3-u2)/2,v2+(v3-v2)/2,0,0,0,0,3,4,6,7); addr = (u_long *)((TMD_G_4T *)addr + 1); // move to end of primative data // primative info, specific to type of primative if (trans < 0) setPRIM_HDR((PRIM_HDR *)addr, G_4T, 0, 8, 12); else setPRIM_HDR((PRIM_HDR *)addr, G_4T | ABE, 0, 8, 12); addr = (u_long *)((PRIM_HDR *)addr + 1); // move to end of primative header // primative data setTMD_G_4T((TMD_G_4T *)addr,CBA,TSB,u0+(u3-u0)/2,v0+(v3-v0)/2,u1+(u3-u1)/2,v1+(v3-v1)/2,u2+(u3-u2)/2,v2+(v3-v2)/2,u3,v3,0,0,0,0,4,5,7,8); addr = (u_long *)((TMD_G_4T *)addr + 1); // move to end of primative data // ******** vertices table ******** vert_table = addr; // vertices and normal data setTMD_VERT((TMD_VERT *)addr, vert0.vx, vert0.vy, vert0.vz); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert0.vx + (vert1.vx - vert0.vx) / 2, vert0.vy + (vert1.vy - vert0.vy) / 2, vert0.vz + (vert1.vz - vert0.vz) / 2); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert1.vx, vert1.vy, vert1.vz); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert0.vx + (vert2.vx - vert0.vx) / 2, vert0.vy + (vert2.vy - vert0.vy) / 2, vert0.vz + (vert2.vz - vert0.vz) / 2); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert0.vx + (vert3.vx - vert0.vx) / 2, vert0.vy + (vert3.vy - vert0.vy) / 2, vert0.vz + (vert3.vz - vert0.vz) / 2); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert1.vx + (vert3.vx - vert1.vx) / 2, vert1.vy + (vert3.vy - vert1.vy) / 2, vert1.vz + (vert3.vz - vert1.vz) / 2); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert2.vx, vert2.vy, vert2.vz); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert2.vx + (vert3.vx - vert2.vx) / 2, vert2.vy + (vert3.vy - vert2.vy) / 2, vert2.vz + (vert3.vz - vert2.vz) / 2); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert3.vx, vert3.vy, vert3.vz); addr = (u_long *)((TMD_VERT *)addr + 1); // ******** normals table ******** norm_table = addr; setTMD_NORM((TMD_NORM *)addr, norm0.nx, norm0.ny, norm0.nz); // fill in object table details setTMD_OBJ(obj_table, vert_table, 9, norm_table, 1, prim_table, 4, 0); } // this does the same job as the above, but doesn't worry about dividing the polygon void makeTMD_G_4T(u_long *addr, u_long *timAddr, u_short u0, u_short v0, u_short u1, u_short v1, u_short u2, u_short v2, u_short u3, u_short v3, TMD_NORM norm0, TMD_VERT vert0, TMD_VERT vert1, TMD_VERT vert2, TMD_VERT vert3, char trans) { TMD_OBJ *obj_table; // pointer to object table u_long *vert_table; // pointer to vertices table u_long *norm_table; // pointer to normals table u_long *prim_table; // pointer to primative table u_short CBA,TSB,pmode,pixScale; GsIMAGE image; RECT t,c; GsGetTimInfo(++timAddr,&image); pmode = (image.pmode & 3); CBA = (image.cy << 6) + (image.cx >> 4); TSB = (image.px >> 6) + (image.py >> 10) + (pmode << 7); if (trans > 0) TSB += trans << 5; // add on offset from start of texture page if (pmode == 0) pixScale = 4; else if (pmode == 1) pixScale = 2; else pixScale = 1; u0 += (image.px & 63) * pixScale; v0 += (image.py) & 511; u1 += (image.px & 63) * pixScale; v1 += (image.py) & 511; u2 += (image.px & 63) * pixScale; v2 += (image.py) & 511; u3 += (image.px & 63) * pixScale; v3 += (image.py) & 511; // ******** TMD header info ******** setTMD_HDR((TMD_HDR *)addr, 0x00000041, 1, 1); addr = (u_long *)((TMD_HDR *)addr + 1); // move to end of header // ******** skip object table, values setup later ******** obj_table = (TMD_OBJ *)addr; addr = (u_long *)((TMD_OBJ *)addr + 1); // ******** primative table ******** prim_table = addr; // primative info, specific to type of primative if (trans < 0) setPRIM_HDR((PRIM_HDR *)addr, G_4T, 0, 8, 12); else setPRIM_HDR((PRIM_HDR *)addr, G_4T | ABE, 0, 8, 12); addr = (u_long *)((PRIM_HDR *)addr + 1); // move to end of primative header // primative data setTMD_G_4T((TMD_G_4T *)addr,CBA,TSB,u0,v0,u1,v1,u2,v2,u3,v3,0,0,0,0,0,1,2,3); addr = (u_long *)((TMD_G_4T *)addr + 1); // move to end of primative data // ******** vertices table ******** vert_table = addr; // vertices and normal data setTMD_VERT((TMD_VERT *)addr, vert0.vx, vert0.vy, vert0.vz); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert1.vx, vert1.vy, vert1.vz); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert2.vx, vert2.vy, vert2.vz); addr = (u_long *)((TMD_VERT *)addr + 1); setTMD_VERT((TMD_VERT *)addr, vert3.vx, vert3.vy, vert3.vz); addr = (u_long *)((TMD_VERT *)addr + 1); // ******** normals table ******** norm_table = addr; setTMD_NORM((TMD_NORM *)addr, norm0.nx, norm0.ny, norm0.nz); // fill in object table details setTMD_OBJ(obj_table, vert_table, 4, norm_table, 1, prim_table, 1, 0); } //***************************************************************************** // draw a TMD, obj, in the scene. perform translation, t, a rotation about Y // of ang, and add to ordering table, ot void drawObject(GsDOBJ2 *obj, MATRIX transformMatrix, GsCOORDINATE2 *super, GsOT *ot) { MATRIX coordMatrix; long adx, adz; // absolute difference between object and current position obj->coord2->coord = transformMatrix; // perform transformation on object obj->coord2->super = super; // move relative to coord system super obj->coord2->flg = 0; // flag object as moved GsGetLs(obj->coord2, &coordMatrix); // do local screen matrix (performs GsSetLsMatrix(&coordMatrix); // perspective, etc) // adx = fabs(transformMatrix.t[0] - goodguy.position.vx); // adz = fabs(transformMatrix.t[2] - goodguy.position.vz); // if (adx < 1024 && adz < 1024) // obj->attribute |= GsDIV2; // else if (adx < 2048 && adz < 2048) // obj->attribute |= GsDIV1; // add object to ordering table GsSortObject4(obj, ot, 14 - ot->length, (u_long *)getScratchAddr(0)); // obj->attribute &= ~GsDIV3; // reset sub division to none } //***************************************************************************** int detectcollision(car *p, VECTOR *vec) { int i; VECTOR v0,v1; VECTOR va = *vec; i = updateSection(p->section,vec); // left wall copyVector(&thetrack[i].v2,&v0); subVector(&v0,&va); // right wall copyVector(&thetrack[i].v1,&v1); subVector(&v1,&va); if (dotProduct(&thetrack[i].nl,&v0) > 0 || dotProduct(&thetrack[i].nr,&v1) > 0) return 1; return 0; } //***************************************************************************** int collision(car *p, VECTOR *vec) { int i; VECTOR v0,v1,v2,v3; SVECTOR n,v; VECTOR vc; VECTOR va = *vec; int d,e; i = updateSection(p->section,vec); // wall 1 copyVector(&thetrack[i].v2,&v2); subVector(&v2,&va); if (dotProduct(&thetrack[i].nl,&v2) > 0) { copyVector(&thetrack[i].nl,&v); setVector(&p->vel,v.vx << 2,v.vy << 2,v.vz << 2); copyVector(&p->vel,&p->cuv); return 1; } // wall 2 copyVector(&thetrack[i].v1,&v2); subVector(&v2,&va); if (dotProduct(&thetrack[i].nr,&v2) > 0) { copyVector(&thetrack[i].nr,&v); setVector(&p->vel,v.vx << 2,v.vy << 2,v.vz << 2); copyVector(&p->vel,&p->cuv); return 1; } // ground copyVector(&thetrack[i].v0,&v2); subVector(&v2,&va); if (dotProduct(&thetrack[i].n,&v2) > 0) { return 1; } return 0; } update_catch_up(car *play, int degree) { if (abs(play->cuv.vx - play->vel.vx) < degree) play->cuv.vx = play->vel.vx; else if (play->cuv.vx < play->vel.vx) play->cuv.vx += degree; else play->cuv.vx -= degree; if (abs(play->cuv.vy - play->vel.vy) < degree) play->cuv.vy = play->vel.vy; else if (play->cuv.vy < play->vel.vy) play->cuv.vy += degree; else play->cuv.vy -= degree; if (abs(play->cuv.vz - play->vel.vz) < degree) play->cuv.vz = play->vel.vz; else if (play->cuv.vz < play->vel.vz) play->cuv.vz += degree; else play->cuv.vz -= degree; } //***************************************************************************** // character controls void playerControl(char pad, car *play) { VECTOR increment={0,0,0}; VECTOR vt; VECTOR back; VECTOR cur; SVECTOR rotate; SVECTOR dir; int speed; MATRIX t,tmp,t1; static u_long oldPad; u_long padstat; int i; back = play->cuv; setVector(&cur,(50 * play->vel.vx + 50 * back.vx) / 100,(50 * play->vel.vy + 50 * back.vy) / 100,(50 * play->vel.vz + 50 * back.vz) / 100); speed = lengthLV(&cur); // slow down play->vel.vx = play->vel.vx * 98 / 100; play->vel.vy = play->vel.vy * 98 / 100; play->vel.vz = play->vel.vz * 98 / 100; if (pad == 1) padstat = PadStatus; else if (pad == 2) padstat = PadStatus >> 16; else return; TransposeMatrix(&play->rot,&t); if (padstat & PADL1) play->va.vx += 32; if (padstat & PADL2) play->va.vx -= 32; if (padstat & PADR1) play->vp.vz += 500; if (padstat & PADR2) play->vp.vz -= 500; if (padstat & PADLleft) { if (speed > 6000) { setVector(&rotate,0,30,0); RotMatrix(&rotate,&t1); tmp = play->rot; MulMatrix0(&t1,&tmp,&play->rot); normaliseMatrix(&play->rot); setVector(&dir,t.m[0][2],t.m[1][2],t.m[2][2]); play->vel.vx = speed * dir.vx / 4096; play->vel.vy = speed * dir.vy / 4096; play->vel.vz = speed * dir.vz / 4096; } } if (padstat & PADLright) { if (speed > 6000) { setVector(&rotate,0,-30,0); RotMatrix(&rotate,&t1); tmp = play->rot; MulMatrix0(&t1,&tmp,&play->rot); normaliseMatrix(&play->rot); setVector(&dir,t.m[0][2],t.m[1][2],t.m[2][2]); play->vel.vx = speed * dir.vx / 4096; play->vel.vy = speed * dir.vy / 4096; play->vel.vz = speed * dir.vz / 4096; } } addVector(&play->vel,&play->acc); if (padstat & PADRdown && !(padstat & PADRleft)) { setVector(&play->acc, t.m[0][2], t.m[1][2], t.m[2][2]); update_catch_up(play,6000); } else if (padstat & PADRright && !(padstat & PADRleft)) { setVector(&play->acc, -t.m[0][2], -t.m[1][2], -t.m[2][2]); update_catch_up(play,6000); } else if (!(padstat & PADRleft)) { setVector(&play->acc, 0, 0, 0); update_catch_up(play,24000); } else { setVector(&play->acc, 0, 0, 0); update_catch_up(play,4000); } if (padstat & PADRleft) { play->vel.vx = play->vel.vx * 85 / 100; play->vel.vy = play->vel.vy * 85 / 100; play->vel.vz = play->vel.vz * 85 / 100; } // addVector(&increment,&play->vel); setVector(&increment,(50 * play->vel.vx + 50 * back.vx) / 100,(50 * play->vel.vy + 50 * back.vy) / 100,(50 * play->vel.vz + 50 * back.vz) / 100); copyVector(&play->pos,&vt); applyVector(&increment, 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8, &=); applyVector(&vt,increment.vx >> 9,increment.vy >> 9,increment.vz >> 9,+=); if (!collision(play,&vt)) play->pos = vt; } //***************************************************************************** void oppositionControl(void) { VECTOR vt; VECTOR v0,v1,v2,v3; SVECTOR n,a,b,rotate; int i,j; MATRIX t,tmp,t1; i = (opposition.section + 1) % TRACK_SECTIONS; copyVector(&thetrack[i].nr, &a); subVector(&a, &thetrack[i].nl); setVector(&b,opposition.rot.m[0][2],opposition.rot.m[1][2],opposition.rot.m[2][2]); if (dotProduct(&a,&b) > 0) { setVector(&rotate,0,64,0); RotMatrix(&rotate,&t1); tmp = opposition.rot; MulMatrix0(&t1,&tmp,&opposition.rot); normaliseMatrix(&opposition.rot); } else if (dotProduct(&a,&b) < 0) { setVector(&rotate,0,-64,0); RotMatrix(&rotate,&t1); tmp = opposition.rot; MulMatrix0(&t1,&tmp,&opposition.rot); normaliseMatrix(&opposition.rot); } // check for upcoming crash copyVector(&opposition.pos,&v0); applyVector(&v0, opposition.vel.vx * 16, opposition.vel.vy * 16, opposition.vel.vz * 16, +=); if (!detectcollision(&opposition,&v0)) setVector(&opposition.acc, opposition.rot.m[0][2] / 256, opposition.rot.m[1][2] / 256, opposition.rot.m[2][2] / 256); else { // apply brakes setVector(&opposition.acc, 0, 0, 0); opposition.vel.vx = opposition.vel.vx * 90 / 100; opposition.vel.vy = opposition.vel.vy * 90 / 100; opposition.vel.vz = opposition.vel.vz * 90 / 100; } addVector(&opposition.vel,&opposition.acc); // try to keep to centre a bit, stops car jamming on walls copyVector(&thetrack[i].v0,&v0); subVector(&v0,&opposition.pos); copyVector(&v0,&a); copyVector(&thetrack[i].v1,&v1); subVector(&v1,&opposition.pos); copyVector(&v1,&b); if (length(&a) > length(&b) * 2) applyVector(&opposition.vel, thetrack[i].nr.vx / 1024, thetrack[i].nr.vy / 1024, thetrack[i].nr.vz / 1024, +=); else if (length(&b) > length(&a) * 2) applyVector(&opposition.vel, thetrack[i].nl.vx / 1024, thetrack[i].nl.vy / 1024, thetrack[i].nl.vz / 1024, +=); opposition.vel.vx = opposition.vel.vx * 95 / 100; opposition.vel.vy = opposition.vel.vy * 95 / 100; opposition.vel.vz = opposition.vel.vz * 95 / 100; copyVector(&opposition.pos,&vt); addVector(&vt,&opposition.vel); if (collision(&opposition,&vt)) { applyVector(&opposition.vel, 8, 8, 8,>>=); } else { opposition.pos = vt; } } //***************************************************************************** void setupTexturesAndTMDs(void) { InitialiseTexture(roadTIM); InitialiseTexture(wallTIM); initialiseTMD(carTMD, 0, &carOBJ); } //***************************************************************************** void updateViewSystem(car *c) { MATRIX transform; VECTOR translate; transform = GsIDMATRIX; // setVector(&translate,0,1800,0); // TransMatrix(&transform, &translate); c->vs.carA.coord = transform; c->vs.carA.super = WORLD; c->vs.carA.flg = 0; transform = GsIDMATRIX; // RotMatrix(va, &transform); c->vs.carB.coord = transform; c->vs.carB.super = &c->vs.carA; c->vs.carB.flg = 0; transform = GsIDMATRIX; c->vs.trackA.coord = c->rot; c->vs.trackA.super = &c->vs.carB; c->vs.trackA.flg = 0; transform = GsIDMATRIX; setVector(&translate, -c->pos.vx, -c->pos.vy, -c->pos.vz); TransMatrix(&transform, &translate); c->vs.trackB.coord = transform; c->vs.trackB.super = &c->vs.trackA; c->vs.trackB.flg = 0; transform = GsIDMATRIX; setVector(&translate, -c->vp.vx, -c->vp.vy, -c->vp.vz); // TransMatrix(&transform,&translate); c->vs.trackC.coord = transform; c->vs.trackC.super = &c->vs.trackB; c->vs.trackC.flg = 0; } int main(void) { MATRIX transformMatrix; int i; VECTOR translate; SVECTOR tv; SVECTOR rotate; VECTOR vp; MATRIX vr; MATRIX tm,cr; MATRIX delay[10]; long dx, dz; GsF_LIGHT flatLight; // light source GsFOGPARAM fogging = {-5000,20971520L,0,0,0}; // fogging int hsync; int maxHsync = 0; SVECTOR scale = {ONE, 3 * ONE / 4, ONE}; SVECTOR vec; RECT rect; GsCOORDINATE2 cc; ResetGraph(0); // reset the graphics PadStatus = 0; // set up controller pad PadInit(); if (GetVideoMode() == MODE_NTSC) GsInitGraph(320 ,240, GsOFSGPU|GsNONINTER, 1, 0); // screen 320x240 else GsInitGraph(320 ,256, GsOFSGPU|GsNONINTER, 1, 0); // screen 320x256 GsDefDispBuff(0, 0, 0, 256); // display buffer GsInit3D(); // 3D FntLoad(960, 256); // fonts fntPrintID1 = FntOpen(-30, 91, 128, 8, 0, 32); fntPrintID2 = FntOpen(-137, -60, 320, 240, 0, 256); for (i = 0; i < 2; i++) // setup ordering tables { OT1[i].length = lengthOT1; OT1[i].org = zTable1[i]; OT2[i].length = lengthOT2; OT2[i].org = zTable2[i]; OT1_b[i].length = lengthOT1; OT1_b[i].org = zTable1_b[i]; OT2_b[i].length = lengthOT2; OT2_b[i].org = zTable2_b[i]; } setupTexturesAndTMDs(); // create polygon stuff // VAB = SsVabTransfer(VHAddr, VBAddr, -1, 1); // open sound stuff // if (VAB < 0) // { // printf("VAB open failed\n"); // exit(1); // } // SsUtKeyOn(VAB, 10, 0, 60, 0, 100, 100); // background noise // heartvoice = SsUtKeyOn(VAB, 0, 0, 60, 0, 0, 0); // heartbeat noise // goodguy.level = 1; // start level, music // initMap(map1Addr); // levelvoice = SsUtKeyOn(VAB, 11, 0, 60, 0, 127, 127); // playVsync = VSync(-1); // playingMusic = 1; setColor(&flatLight, 128, 128, 128); // flat light set up to remove any setVector(&flatLight, 0, 4096, 0); GsSetFlatLight(0, &flatLight); // previous lighting effects GsSetFlatLight(1, &flatLight); GsSetFlatLight(2, &flatLight); GsSetLightMatrix(&GsIDMATRIX); GsSetLightMode(0); // normal lighting, fogging on GsSetFogParam(&fogging); // degree of fogging GsSetAmbient(ONE/2,ONE/2,ONE/2); // ambient light (RGB) GsSetProjection(1000); // perpsective rotationMatrix = GsIDMATRIX; vr = GsIDMATRIX; tm = GsIDMATRIX; player1.section = 6; player1.rot = GsIDMATRIX; setVector(&player1.pos,0,0,0); setVector(&player1.vp, 0, 0, 5500); setVector(&player1.va, 64, 0, 0); player2.section = 6; player2.rot = GsIDMATRIX; setVector(&player2.pos,0,0,0); setVector(&player2.vp, 0, 0, 5500); setVector(&player2.va, 64, 0, 0); opposition.section = 6; opposition.rot = GsIDMATRIX; setVector(&opposition.pos,0,0,0); fill_spline(); createTrack(); //setVector(&viewPoint,0,180,2000); do { GsSetOrign(160,100); updateViewSystem(&player1); // sort out stuff for ordering tables buffIdx = GsGetActiveBuff(); // where all the polygons are copied to make up a scene GsSetWorkBase((PACKET*)GpuOutputPacket[buffIdx]); // clear out ordering table GsClearOt(0, 0, &OT1[buffIdx]); GsClearOt(0, 0, &OT1_b[buffIdx]); // GsClearOt(0, 0, &OT2[buffIdx]); // scale the screen GsScaleScreen(&scale); // the game stuff tm = GsIDMATRIX; TransMatrix(&tm,&player1.vp); RotMatrix(&player1.va,&tm); TransposeMatrix(&player1.rot,&cr); TransMatrix(&cr,&player1.pos); for (i=0;i<9;i++) delay[i] = delay[i+1]; delay[9] = cr; cr = delay[0]; //setVector(&translate,cr.t[0]+player1.vs.trackB.coord.t[0],cr.t[1]+player1.vs.trackB.coord.t[1],cr.t[2]+player1.vs.trackB.coord.t[2]); setVector(&translate,0,0,0); TransMatrix(&cr,&translate); vr = player1.vs.trackA.coord; // printf("cr %5d %5d %5d %d\n",cr.m[0][0],cr.m[0][1],cr.m[0][2],cr.t[0]); // printf(" %5d %5d %5d %d\n",cr.m[1][0],cr.m[1][1],cr.m[1][2],cr.t[1]); // printf(" %5d %5d %5d %d\n",cr.m[2][0],cr.m[2][1],cr.m[2][2],cr.t[2]); // printf("vr %5d %5d %5d %d\n",vr.m[0][0],vr.m[0][1],vr.m[0][2],vr.t[0]); // printf(" %5d %5d %5d %d\n",vr.m[1][0],vr.m[1][1],vr.m[1][2],vr.t[1]); // printf(" %5d %5d %5d %d\n",vr.m[2][0],vr.m[2][1],vr.m[2][2],vr.t[2]); TransMatrix(&vr,&translate); MulMatrix0(&cr,&vr,&cr); //cr=vr; // printf("cr %5d %5d %5d %d\n",cr.m[0][0],cr.m[0][1],cr.m[0][2],cr.t[0]); // printf(" %5d %5d %5d %d\n",cr.m[1][0],cr.m[1][1],cr.m[1][2],cr.t[1]); // printf(" %5d %5d %5d %d\n",cr.m[2][0],cr.m[2][1],cr.m[2][2],cr.t[2]); cc.coord = cr; cc.super = WORLD; cc.flg = 0; // set view transformation TheMainView.view = tm; TheMainView.super = &cc; GsSetView2(&TheMainView); drawTrack(GsIDMATRIX, player1.vs.trackC, &OT1_b[buffIdx],&OT1[buffIdx],&player1); drawObject(&carOBJ, GsIDMATRIX, &player1.vs.carB, &OT1[buffIdx]); tm = opposition.rot; TransMatrix(&tm,&opposition.pos); drawObject(&carOBJ, tm, &player1.vs.trackB, &OT1[buffIdx]); tm = player2.rot; TransposeMatrix(&tm,&vr); TransMatrix(&vr,&player2.pos); drawObject(&carOBJ, vr, &player1.vs.trackB, &OT1[buffIdx]); setVector(&translate,0,180,0); tm = GsIDMATRIX; DrawSync(0); // finish any drawing hsync = VSync(1); // how long since last vsync VSync(0); GsSwapDispBuff(); // swap screens GsSortClear(0, 0, 0, &OT1_b[buffIdx]); // add cls to ordering table setRECT(&rect,0,0,320,120); GsSetClip(&rect); GsDrawOt(&OT1_b[buffIdx]); // draw floor roof GsDrawOt(&OT1[buffIdx]); // draw floor roof //////////////////////////////////////////////////// GsSetOrign(160,220); GsSwapDispBuff(); // swap screens GsSwapDispBuff(); // swap screens updateViewSystem(&player2); // where all the polygons are copied to make up a scene GsSetWorkBase((PACKET*)GpuOutputPacket[buffIdx + 2]); // clear out ordering table GsClearOt(0, 0, &OT2[buffIdx]); GsClearOt(0, 0, &OT2_b[buffIdx]); // scale the screen GsScaleScreen(&scale); // the game stuff tm = GsIDMATRIX; // copyVector(&player2.vel,&tv); // tv = normalise(tv); // copyVector(&tv,&translate); // addVector(&translate,&player2.vp); copyVector(&player2.vp,&translate); TransMatrix(&tm,&translate); RotMatrix(&player2.va,&tm); // set view transformation TheMainView.view = tm; TheMainView.super = WORLD; GsSetView2(&TheMainView); drawTrack(GsIDMATRIX, player2.vs.trackC, &OT2_b[buffIdx], &OT2[buffIdx],&player2); drawObject(&carOBJ, GsIDMATRIX, &player2.vs.carB, &OT2[buffIdx]); tm = opposition.rot; TransMatrix(&tm,&opposition.pos); drawObject(&carOBJ, tm, &player2.vs.trackB, &OT2[buffIdx]); tm = player1.rot; TransposeMatrix(&tm,&vr); TransMatrix(&vr,&player1.pos); drawObject(&carOBJ, vr, &player2.vs.trackB, &OT2[buffIdx]); setVector(&translate,0,180,0); tm = GsIDMATRIX; DrawSync(0); // finish any drawing setRECT(&rect,0,120,320,120); GsSetClip(&rect); GsDrawOt(&OT2_b[buffIdx]); // draw floor roof GsDrawOt(&OT2[buffIdx]); // draw floor roof //////////////////////////////////////////////////// PadStatus = PadRead(); // read the pad // info about draw speed FntPrint(fntPrintID2,"~cFFFhsync %d\n",hsync); // the hsync < 1000 is so the initialisation time is not included if (hsync > maxHsync && hsync < 1500) maxHsync = hsync; FntPrint(fntPrintID2,"max hsync %d\n",maxHsync); FntPrint(fntPrintID2,"pos %d %d %d\n",player1.pos.vx,player1.pos.vy,player1.pos.vz); FntPrint(fntPrintID2,"vel %d %d %d\n",player1.vel.vx,player1.vel.vy,player1.vel.vz); FntPrint(fntPrintID2,"cuv %d %d %d\n",player1.cuv.vx,player1.cuv.vy,player1.cuv.vz); //FntPrint(fntPrintID2,"current %d\n",player1.section); FntPrint(fntPrintID2,"vp %d %d %d\n",player1.vp.vx,player1.vp.vy,player1.vp.vz); FntPrint(fntPrintID2,"va %d %d %d\n",player1.va.vx,player1.va.vy,player1.va.vz); // FntPrint(fntPrintID2,"opos %d %d %d\n",opposition.pos.vx,opposition.pos.vy,opposition.pos.vz); // FntPrint(fntPrintID2,"ovel %d %d %d\n",opposition.vel.vx,opposition.vel.vy,opposition.vel.vz); // FntPrint(fntPrintID2,"oacc %d %d %d\n",opposition.acc.vx,opposition.acc.vy,opposition.acc.vz); // FntPrint(fntPrintID2,"osec %d\n",opposition.section); // FntPrint(fntPrintID2,"%5d %5d %5d %d\n",vr.m[0][0],vr.m[0][1],vr.m[0][2],vr.t[0]); // FntPrint(fntPrintID2,"%5d %5d %5d %d\n",vr.m[1][0],vr.m[1][1],vr.m[1][2],vr.t[1]); // FntPrint(fntPrintID2,"%5d %5d %5d %d\n",vr.m[2][0],vr.m[2][1],vr.m[2][2],vr.t[2]); playerControl(1,&player1); // do controls player1.section = updateSection(player1.section, &player1.pos); playerControl(2,&player2); // do controls player2.section = updateSection(player2.section, &player2.pos); oppositionControl(); opposition.section = updateSection(opposition.section, &opposition.pos); FntFlush(fntPrintID1); // write info FntFlush(fntPrintID2); // write info } while(!(PadStatus & PADselect) || !(PadStatus & PADstart)); SsUtAllKeyOff(0); // switch off sounds SsVabClose(VAB); // close sound ResetGraph(1); // cleanup return 0; }