#include "GraphicPrim.h" // Indicates the actual frame, where one can insert geometry static short ActiveBuffer; // The ordering table for the background static GsOT BackGround[2]; // The ordering table for the mid ground static GsOT MidGround[2]; // The ordering table for the foreground static GsOT ForeGround[2]; // The ordering table for the box gound static GsOT BoxGround[2]; // The packet base fo the two buffers static PACKET *WorkBase[2]; // The final Combination of all ordering tables static GsOT AllTogether[2]; // The three lights used static GsF_LIGHT Lights[3]; // The geometry static unsigned long *ModelData; // The pause screen static GsIMAGE *pauseScreen; // The main title screen static GsIMAGE *mainScreen; // The level names volatile GsSPRITE *LevelNames[30]; // The black rectangle is used for shading static GsBOXF BlackBox; // The counter contains the fading status static int FadingStatus; GsOT *getForeGround() { return (&ForeGround[ActiveBuffer]); } GsOT *getBackGround() { return (&BackGround[ActiveBuffer]); } GsOT *getMidGround() { return (&MidGround[ActiveBuffer]); } GsOT *getBoxGround() { return (&BoxGround[ActiveBuffer]); } // Loads an image into the memory, copies it into the VRAM (incl. CLUT) // and returns an iname structure. The image has to be deleted when not used // any more static GsIMAGE *getImage(char *filename) { void *data; RECT bounds; GsIMAGE *image; int clut; image=(GsIMAGE *)malloc(sizeof(GsIMAGE)); data =(void *)LoadFile(filename); GsGetTimInfo(((unsigned long*)data)+1,image); // Transfer to the default location in VRAM bounds.x = image->px; bounds.y = image->py; bounds.w = image->pw; bounds.h = image->ph; LoadImage(&bounds, (unsigned long *)image->pixel); // Load the associated CLUT if it exists. if (image->pmode & 0x8) { bounds.x = image->cx; bounds.y = image->cy; bounds.w = image->cw; bounds.h = image->ch; LoadImage(&bounds, (unsigned long *)image->clut); clut = GetClut(image->cx, image->cy); } free(data); // Not used any more return image; } // Loads the file into memory static void LoadModelData(char *filename) { void *data; data=(void *)LoadFile(filename); ModelData=(unsigned long *)data; ModelData++; GsMapModelingData(ModelData); ModelData++; // printf("Es sind %d Objekte gefunden worden \n",(*ModelData)); ModelData++; } // Initializes the Graphics system void InitializeGraphic() { // SetVideoMode(MODE_NTSC); SetVideoMode(MODE_PAL); // We want to generate a PAL signal GsInitGraph(320,240,4,0,0); // 320*240 no Interlacing but double buffering 16 bit Farbtiefe GsDefDispBuff(0,240,0,0); // two pages in VRAM for double buffering GsInit3D(); ActiveBuffer=GsGetActiveBuff(); // We start drawing with this buffer Lights[0].vx=-70; Lights[0].vy=30; Lights[0].vz=70; // We will create three lights Lights[0].r=Lights[0].g=Lights[0].b=180; GsSetFlatLight(0,&Lights[0]); Lights[1].vx=0; Lights[1].vy=40; Lights[1].vz=-100; // We will create three lights Lights[1].r=Lights[1].g=Lights[1].b=80; GsSetFlatLight(1,&Lights[1]); Lights[2].vx=100; Lights[2].vy=40; Lights[2].vz=0; // We will create three lights Lights[2].r=Lights[2].g=Lights[2].b=80; GsSetFlatLight(2,&Lights[2]); GsSetAmbient(70,40,40); GsSetProjection(200); // Needed later on BlackBox.x=-160; BlackBox.y=-120; BlackBox.w=320; BlackBox.h=240; BlackBox.r=BlackBox.g=BlackBox.b=0; BlackBox.attribute=(2<<28)|(1<<30); FadingStatus=0; DrawSync(0); } void InitializeSpaces() { int i; int small=2<<3; int large=2<<14; WorkBase[0]=(PACKET *)malloc(24*10000); WorkBase[1]=(PACKET *)malloc(24*10000); for(i=0;i<2;i++) { ForeGround[i].org=(GsOT_TAG *)malloc(sizeof(GsOT_TAG)*small); ForeGround[i].length=3; BackGround[i].org=(GsOT_TAG *)malloc(sizeof(GsOT_TAG)*small); BackGround[i].length=3; MidGround[i].org=(GsOT_TAG *)malloc(sizeof(GsOT_TAG)*large); MidGround[i].length=14; BoxGround[i].org=(GsOT_TAG *)malloc(sizeof(GsOT_TAG)*(2<<13)); BoxGround[i].length=13; AllTogether[i].org=(GsOT_TAG *)malloc(sizeof(GsOT_TAG)*small); AllTogether[i].length=3; } GsClearOt(0,0,&ForeGround[ActiveBuffer]); // Odertable perpaing for drawing GsClearOt(0,1,&BoxGround[ActiveBuffer]); GsClearOt(0,2,&MidGround[ActiveBuffer]); GsClearOt(0,3,&BackGround[ActiveBuffer]); GsClearOt(0,0,&AllTogether[ActiveBuffer]); GsSetWorkBase(WorkBase[ActiveBuffer]); // Als Arbeistraum fuer den aktuellen Buffer verwenden } void LoadObjects() { char filename[100]; int i; GsIMAGE *dummy; dummy=getImage("ImageData/Stone02.tim"); free(dummy); // Load textures dummy=getImage("ImageData/Stone03.tim"); free(dummy); dummy=getImage("ImageData/Wall01.tim"); free(dummy); dummy=getImage("ImageData/Mybox.tim"); free(dummy); LoadModelData("Geometry/Geo.tmd"); // The geometry data pauseScreen=getImage("ImageData/Pause.tim"); for(i=14;i>=0;i--) // Generate the sprites for the titles { if (i<9) sprintf(filename,"ImageData/L0%dr.tim",(i+1)); else sprintf(filename,"ImageData/L%dr.tim",(i+1)); LevelNames[2*i]=loadSprite(filename); if (i<9) sprintf(filename,"ImageData/L0%dg.tim",(i+1)); else sprintf(filename,"ImageData/L%dg.tim",(i+1)); LevelNames[2*i+1]=loadSprite(filename); } mainScreen=getImage("ImageData/Screen.tim"); } // This method generates a sprite structure GsSPRITE *loadSprite(char *filename) { GsIMAGE *image; GsSPRITE *sprite; int pixelsPerWord; sprite=(GsSPRITE *)malloc(sizeof(GsSPRITE)); image=getImage(filename); switch (image->pmode & 0x7) { case 0: pixelsPerWord = 4; break; case 1: pixelsPerWord = 2; break; case 2: pixelsPerWord = 1; break; default: // Unexpected image.pmode value pixelsPerWord = 0; break; } // Load up the GsSPRITE with reasonable default values. sprite->attribute = 0 + ((image->pmode & 0x7) << 24); sprite->x = sprite->y = 3; sprite->w = image->pw * pixelsPerWord; sprite->h = image->ph; sprite->tpage =GetTPage(image->pmode & 0x7, 0, image->px, image->py);; sprite->u = image->px & (64-1); sprite->v = image->py & (256-1); sprite->cx = image->cx; sprite->cy = image->cy; // Colour shading sprite->r = sprite->g = sprite->b = 128; sprite->mx = 0; sprite->my = 0; sprite->scalex = ONE; sprite->scaley = ONE; sprite->rotate = 0; sprite->x=-90; sprite->y=65; // Used for the level names free(image); return sprite; } // Retruns a box, has to be deleted by its own, // The index refers to the part of the box. The box is splitted into // the top and its four sides GsDOBJ2 getBox(int index,GsCOORDINATE2 *coordinate) { GsDOBJ2 box; GsLinkObject4((unsigned long)ModelData,&box,2+index); box.coord2=coordinate; box.attribute=0; return box; } GsDOBJ2 getFloor(GsCOORDINATE2 *coordinate) { GsDOBJ2 floor; GsLinkObject4((unsigned long)ModelData,&floor,0); floor.coord2=coordinate; floor.attribute=0; return floor; } GsDOBJ2 getTarget(GsCOORDINATE2 *coordinate) { GsDOBJ2 target; GsLinkObject4((unsigned long)ModelData,&target,1); target.coord2=coordinate; target.attribute=0; return target; } // The Wall elements are also splitted into 5 segments GsDOBJ2 getWall(int index,GsCOORDINATE2 *coordinate) { GsDOBJ2 wall; GsLinkObject4((unsigned long)ModelData,&wall,7+index); wall.coord2=coordinate; wall.attribute=0; return wall; } // Simply displays the startscreen directly) void DisplayStartScreen(char *filename) { void *data; RECT bounds; GsIMAGE *image; int c; image=(GsIMAGE *)malloc(sizeof(GsIMAGE)); data =(void *)LoadFile(filename); GsGetTimInfo(((unsigned long*)data)+1,image); if (GsGetActiveBuff()==1) bounds.y=0; else bounds.y=240; bounds.x = 0; bounds.w = image->pw; bounds.h = image->ph; DrawSync(0); LoadImage(&bounds, (unsigned long *)image->pixel); DrawSync(0); VSync(0); GsSwapDispBuff(); for(c=0;c<250;c++) VSync(0); free(data); free(image); } // Draws everything and switches the buffer void SwitchFrames() { if (FadingStatus==1) GsSortBoxFill(&BlackBox,&ForeGround[ActiveBuffer],0); // Fading box GsSortOt(&BackGround[ActiveBuffer],&AllTogether[ActiveBuffer]); // Compose the ordering tables GsSortOt(&MidGround[ActiveBuffer],&AllTogether[ActiveBuffer]); GsSortOt(&BoxGround[ActiveBuffer],&AllTogether[ActiveBuffer]); GsSortOt(&ForeGround[ActiveBuffer],&AllTogether[ActiveBuffer]); DrawSync(0); // Wait for GPU finishing last frame if (VSync(0)<340) VSync(0); // Wait for interrupt, force two frames GsSwapDispBuff(); // Show result of last drawing command GsSortClear(0,0,0,&AllTogether[ActiveBuffer]); // Dummy order GsDrawOt(&AllTogether[ActiveBuffer]); // Draw ! ActiveBuffer=1-ActiveBuffer; // Let us change context GsSetWorkBase(WorkBase[ActiveBuffer]); // Clear context GsClearOt(0,0,&ForeGround[ActiveBuffer]); // Prepare order tables GsClearOt(0,1,&BoxGround[ActiveBuffer]); GsClearOt(0,2,&MidGround[ActiveBuffer]); GsClearOt(0,3,&BackGround[ActiveBuffer]); GsClearOt(0,0,&AllTogether[ActiveBuffer]); } // Shows pause screen. Do not mess up double buffer switching! void DisplayPause() { int x,y; RECT source; source.x=pauseScreen->px; source.y=pauseScreen->py; source.w=pauseScreen->pw; source.h=pauseScreen->ph; x=0; if (GsGetActiveBuff()==1) y=0; else y=240; DrawSync(0); MoveImage(&source,x,y); DrawSync(0); VSync(0); GsSwapDispBuff(); } void DisplayMain(int level,int won) { int x,y; RECT source; source.x=mainScreen->px; source.y=mainScreen->py; source.w=mainScreen->pw; source.h=mainScreen->ph; x=0; if (GsGetActiveBuff()==1) y=0; else y=240; DrawSync(0); MoveImage(&source,x,y); DrawSync(0); // Main Screen painted GsSetWorkBase(WorkBase[0]); GsClearOt(0,0,&ForeGround[0]); GsSortSprite(LevelNames[2*level+won],&ForeGround[0],1); if (FadingStatus==1) GsSortBoxFill(&BlackBox,&ForeGround[0],0); GsDrawOt(&ForeGround[0]); DrawSync(0); VSync(0); GsSwapDispBuff(); GsClearOt(0,0,&ForeGround[0]); GsSetWorkBase(WorkBase[ActiveBuffer]); } void RedrawAll() { DrawSetting(); DrawBackground(); DrawBoxes(); SwitchFrames(); } void setFadingValue(int param) { if (param==0) FadingStatus=0; else { FadingStatus=1; BlackBox.r=BlackBox.g=BlackBox.b=5*param; } }