/*************************** Sandstorm GRAPHICS.C ****************************/ /**** INCLUDES ****/ #include #include "main.h" #include "graphics.h" #include "pad.h" #include "control.h" #include "debug.h" #include "sprite.h" #include "collide.h" #include "fire.h" #include "ai.h" #include "cdread.h" #include "sound.h" /**** GLOBALS ****/ int h_sync=0; int x; //for loops /**** EXTERNS ****/ extern short seq, vab; //from sound.c /**** DEFINES ****/ #define FAR_CLIP (1<<13) #define NEAR_CLIP (1<<1) /**** INIT GRAPHICS ****/ void InitGraphics( void ) { SetVideoMode(MODE_PAL); ResetGraph(0); FntLoad(960,256); FntOpen(15-(WIDTH_PAL/2),5-(HEIGHT_PAL/2), WIDTH_PAL, HEIGHT_PAL, 0, 512); GsInitGraph(WIDTH_PAL, HEIGHT_PAL, GsOFSGPU|GsINTER,0,0); #ifdef INTER GsDefDispBuff(0,0,0,0); #endif #ifndef INTER GsDefDispBuff(0,0,0,HEIGHT_PAL); #endif GsDISPENV.screen.x=6; GsDISPENV.screen.y=16; GsDISPENV.screen.w=255; GsDISPENV.screen.h=255; #ifdef INTER // set bg clear color and flag GsDRAWENV.r0 = 0x00; GsDRAWENV.g0 = 0x00; GsDRAWENV.b0 = 0x00; GsDRAWENV.isbg = 1; #endif GsInit3D(); //initialise OTs for(x=0; x<2; x++) { wot[x].length=OTLENGTH; wot[x].org=ot[x]; } GsClearOt(0,0,&wot[out_buf]); GsClearOt(0,0,&wot[out_buf+1]); GetPadBuf(&bb0,&bb1); }// end InitGraphics /**** DEINIT ****/ void DeInit( void ) { // stop SEQ data reading SsSeqStop( seq ); // turn the reverb off SsUtReverbOff(); // wait for vertical synchronisation VSync(0); VSync(0); // close SEQ data SsSeqClose( seq ); // close VAB data SsVabClose( vab ); ResetGraph(0); }// end DeInit /**** INITCOORDINATES ****/ void InitCoordinates( void ) { GsInitCoordinate2(WORLD,&sand.coord); GsInitCoordinate2(WORLD,&track.coord); for(x=0;xcoord2=coord; //set coordinates to 0 coord->coord.t[0]=0; coord->coord.t[1]=0; coord->coord.t[2]=0; //clear flag and attributes coord->flg=0; obj->attribute=0; }// end CREATETMD /**** INITVIEW ****/ void InitView( void ) { GsSetProjection(PROJ); // set view point coordinates view.vpx = -452; view.vpy = -128; view.vpz = 0; // set focus point coordinates view.vrx = 98; view.vry = -63; view.vrz = 0; // set the roll parameter of viewpoint view.rz = 0; // set origin to WORLD view.super = &truck[0].coord; GsSetRefView2(&view); }// end InitView /**** INITLIGHTS ****/ void InitLights( void ) { // parallel light source light[0].vx = 20; light[0].vy = -100; light[0].vz = -100; light[0].r = 128; light[0].g = 128; light[0].b = 128; GsSetFlatLight(0,&light[0]); // parallel light source light[1].vx = 20; light[1].vy = -100; light[1].vz = 100; light[1].r = 128; light[1].g = 128; light[1].b = 128; GsSetFlatLight(1,&light[1]); // parallel light source light[2].vx = -100; light[2].vy = -100; light[2].vz = 100; light[2].r = 128; light[2].g = 128; light[2].b = 128; GsSetFlatLight(2,&light[2]); //initialise fog parameters fog.dqa = (-FAR_CLIP * ONE) / 64 / PROJ; fog.dqb = (1.25 * ONE * ONE); fog.rfc = 255; fog.gfc = 255; fog.bfc = 255; GsSetFogParam(&fog); GsSetAmbient( 3072, 3072, 3072 ); GsSetLightMode(0); }//end InitLights /**** INITTEX ****/ GsIMAGE *InitTex( u_long *addr ) { static GsIMAGE tim; RECT rect; // skip id and initialize image structure addr ++; GsGetTimInfo(addr, &tim); // transfer pixel data to VRAM rect.x = tim.px; rect.y = tim.py; rect.w = tim.pw; rect.h = tim.ph; LoadImage(&rect, tim.pixel); DrawSync(0); // check if CLUT exists and transfer it to VRAM if( (tim.pmode >> 3) & 0x01 ) { rect.x = tim.cx; rect.y = tim.cy; rect.w = tim.cw; rect.h = tim.ch; LoadImage(&rect, tim.clut); } DrawSync(0); return(&tim); }// end InitTex /**** INITIMAGE ****/ void InitImage( u_long *addr, RECT *rect, GsIMAGE *tim ) { // skip id and initialize image structure addr ++; GsGetTimInfo(addr, tim); // transfer pixel data to VRAM rect->x = tim->px; rect->y = tim->py; rect->w = tim->pw; rect->h = tim->ph; LoadImage(rect, tim->pixel); DrawSync(0); // check if CLUT exists and transfer it to VRAM if( (tim->pmode >> 3) & 0x01 ) { rect->x = tim->cx; rect->y = tim->cy; rect->w = tim->cw; rect->h = tim->ch; LoadImage(rect, tim->clut); } DrawSync(0); }// end InitImage /**** UPDATECOORDINATES ****/ void UpdateCoordinates( SVECTOR *svec, GsCOORDINATE2 *coord ) { MATRIX tmp; // set translation tmp.t[0] = coord->coord.t[0]; tmp.t[1] = coord->coord.t[1]; tmp.t[2] = coord->coord.t[2]; // rotate Matrix RotMatrix(svec,&tmp); // set Matrix to Coordinate coord->coord = tmp; // clear flag because of changing parameter coord->flg = 0; }// end UpdateCoordinates /**** DRAWSCREEN ****/ void DrawScreen( void ) { int x; int sunx=(sun2.x+5); int suny=(sun2.y+5); GsSetRefView2(&view); out_buf = GsGetActiveBuff(); GsSetWorkBase((PACKET*)gpu_work_area[out_buf]); GsClearOt(0, 0, &wot[out_buf]); ScrollBG(); //draw cursor on gamemode 1 if(gamemode==1) GsSortBoxFill( &dot, &wot[out_buf], 0 ); if(gamemode==2) { //draw objects if game is in progress /******sort TMD objects into OT****/ SortObject(&sand.obj, &wot[out_buf], 3);//3 SortObject(&truck[0].obj, &wot[out_buf], 4); //4 if(cpu1destroyed==0) SortObject(&truck[1].obj, &wot[out_buf], 4); //4 if(cpu2destroyed==0) SortObject(&truck[2].obj, &wot[out_buf], 4); //4 SortObject(&pyramid.obj, &wot[out_buf], 4); SortObject(&pointer.obj, &wot[out_buf], 4); if(power_m_status==1) SortObject(&power_m.obj, &wot[out_buf], 4); if(homing_m_status==1) SortObject(&homing_m.obj, &wot[out_buf], 4); if(fire_m_status==1) SortObject(&fire_m.obj, &wot[out_buf], 4); if(power2_m_status==1) SortObject(&power2_m.obj, &wot[out_buf], 4); if(homing2_m_status==1) SortObject(&homing2_m.obj, &wot[out_buf], 4); if(fire2_m_status==1) SortObject(&fire2_m.obj, &wot[out_buf], 4); if(power3_m_status==1) SortObject(&power3_m.obj, &wot[out_buf], 4); if(fire3_m_status==1) SortObject(&fire3_m.obj, &wot[out_buf], 4); if(homing3_m_status==1) SortObject(&homing3_m.obj, &wot[out_buf], 4); /****sort 3d sprites into OT*******/ //registers the 2d tree sprite as 3d object in OT for(x=0; x<5; x++) draw_3dsprite(&tree[x], pos[x],10); draw_3dsprite(&sun2, sunpos, 1); //draw pick-up icons as 3D sprites if(spot[0]==1) draw_3dsprite(&upg_ico, upg_ico_pos, 10); if(spot[1]==1) draw_3dsprite(&mine_ico, mine_ico_pos, 10); if(spot[2]==1) draw_3dsprite(&fire_ico, fire_ico_pos, 10); if(spot[3]==1) draw_3dsprite(&hlt_ico, hlt_ico_pos, 10); if(spot[4]==1) draw_3dsprite(&hom_ico, hom_ico_pos, 10); if(spot[5]==1) draw_3dsprite(&pow_ico, pow_ico_pos, 10); if(spot[6]==1) draw_3dsprite(&rico_ico, rico_ico_pos, 10); if(spot[7]==1) draw_3dsprite(&tbo_ico, tbo_ico_pos, 10); if(spot[8]==1) draw_3dsprite(&time_ico, time_ico_pos, 10); if(rico_status==1) draw_3dsprite( &ricochet, rico_pos, 10 ); DrawFireCars(); //display onscreen items if screen is not fading if(blank.r<50) { if(p1items.pow>0 && sel_item==4) GsSortFastSprite( &os_pow, &wot[out_buf], 0 ); if(p1items.upg>0 && sel_item==0) GsSortFastSprite( &os_bullet, &wot[out_buf], 0); if(p1items.mine>0 && sel_item==1) GsSortFastSprite( &os_mine, &wot[out_buf], 0); if(p1items.fire>0 && sel_item==2) GsSortFastSprite( &os_fire, &wot[out_buf], 0); if(p1items.hom>0 && sel_item==3) GsSortFastSprite( &os_hom, &wot[out_buf], 0); if(p1items.rico>0 && sel_item==5) GsSortFastSprite( &os_rico, &wot[out_buf], 0); if(p1items.time>0 && sel_item==6) GsSortFastSprite( &os_time, &wot[out_buf], 0); } //send mine alert sprites to OT if(mine_status==1) { if(picksprite==1) draw_3dsprite( &mine_1, mine_1_pos, 10 ); if(picksprite==2) draw_3dsprite( &mine_2, mine_2_pos, 10 ); if(picksprite==3) draw_3dsprite( &mine_3, mine_3_pos, 10 ); } //send bullet sprites to OT for(x=0; x<21; x++) { if(bull_stat[x]==1) //if bullet is "alive" draw_3dsprite(&bullet[x], bullet_pos[x], 10); } if(expl_status==1){ if(firestatus==1) draw_3dsprite(&fire1, fire1_pos, 5 ); if(firestatus==2) draw_3dsprite(&fire2, fire2_pos, 5 ); } //register GsBOXFs into OT if(blank.r<50) { //draw only if not fading RenderFlare( &le1, sunx, suny, 0, 0, 1 ); RenderFlare( &le2, sunx, suny, 0, 0, 2 ); RenderFlare( &le3, sunx, suny, 0, 0, 3 ); } if(blank.r<50) { GsSortBoxFill( &turbo, &wot[out_buf], 0 ); GsSortBoxFill( &life, &wot[out_buf], 0 ); } GsSortBoxFill( &blank, &wot[out_buf], 0 ); if(blank.r<50) { DrawEnemyHealth( &truck[0].coord, &cpulife1, &truck[1].coord ); DrawEnemyHealth( &truck[0].coord, &cpulife2, &truck[2].coord ); } } //end if(gamemode==2) #ifndef INTER DrawSync(0); #endif h_sync=VSync(1); VSync(0); #ifdef INTER ResetGraph(1); #endif GsSwapDispBuff(); #ifndef INTER GsSortClear(0x0, 0x0, 0x0, &wot[out_buf]); #endif GsDrawOt(&wot[out_buf]); FntFlush(-1); }// end DrawScreen /**** SORTOBJECT ****/ void SortObject( GsDOBJ2 *obj, GsOT *wot, int shift ) { MATRIX local_world, local_screen; // calculate both local world and local screen matrices GsGetLws(obj->coord2, &local_world, &local_screen); // set LWMATRIX to GTE Lighting Registers GsSetLightMatrix(&local_world); // set LSMATRIX to GTE Registers GsSetLsMatrix(&local_screen); // set perspective and light calculations, Z sort and send to OT GsSortObject4(obj, wot, shift, (u_long*)getScratchAddr(0)); }// end SortObject