#define library(X) (X) #ifdef COMPUTE_VELTABLE #include #endif #include #include #include "Maelstrom_Globals.h" #include "load.h" #include "colortable.h" #include "fastrand.h" // Global variables set in this file... Sound *sound = NULL; FontServ *fontserv = NULL; FrameBuf *screen = NULL; Sint32 gLastHigh; Uint32 gLastDrawn; int gNumSprites; Rect gScrnRect; SDL_Rect gClipRect; int gStatusLine; int gTop, gLeft, gBottom, gRight; MPoint gShotOrigins[SHIP_FRAMES]; MPoint gThrustOrigins[SHIP_FRAMES]; MPoint gVelocityTable[SHIP_FRAMES]; StarPtr gTheStars[MAX_STARS]; Uint32 gStarColors[20]; /* -- The blit'ers we use */ BlitPtr gRock1R, gRock2R, gRock3R, gDamagedShip; BlitPtr gRock1L, gRock2L, gRock3L, gShipExplosion; BlitPtr gPlayerShip, gExplosion, gNova, gEnemyShip, gEnemyShip2; BlitPtr gMult[4], gSteelRoidL; BlitPtr gSteelRoidR, gPrize, gBonusBlit, gPointBlit; BlitPtr gVortexBlit, gMineBlitL, gMineBlitR, gShieldBlit; BlitPtr gThrust1, gThrust2, gShrapnel1, gShrapnel2; /* -- The prize CICN's */ SDL_Surface *gAutoFireIcon, *gAirBrakesIcon, *gMult2Icon, *gMult3Icon; SDL_Surface *gMult4Icon, *gMult5Icon, *gLuckOfTheIrishIcon, *gLongFireIcon; SDL_Surface *gTripleFireIcon, *gKeyIcon, *gShieldIcon; // Local functions used in this file. static void DrawLoadBar(int first); static int InitSprites(void); static int LoadBlits(Mac_Resource *spriteres); static int LoadCICNS(void); static void BackwardsSprite(BlitPtr *theBlit, BlitPtr oldBlit); static int LoadSprite(Mac_Resource *spriteres, BlitPtr *theBlit, int baseID, int numFrames); static int LoadSmallSprite(Mac_Resource *spriteres, BlitPtr *theBlit, int baseID, int numFrames); /* Put up an Ambrosia Software splash screen */ void DoSplash(void) { SDL_Surface *splash; splash = Load_Title(screen, 999); if ( splash == NULL ) { error("Can't load Ambrosia splash title! (ID=%d)\n", 999); return; } screen->QueueBlit(SCREEN_WIDTH/2-splash->w/2, SCREEN_HEIGHT/2-splash->h/2, splash, NOCLIP); screen->Update(); screen->FreeImage(splash); } /* ----------------------------------------------------------------- */ /* -- Put up our intro splash screen */ void DoIntroScreen(void) { MFont *geneva; SDL_Surface *intro, *text; Uint16 Yoff, Xoff; Uint32 clr, ltClr, ltrClr; intro = Load_Title(screen, 130); if ( intro == NULL ) { error("Can't load intro title! (ID=%d)\n", 130); return; } // -- Draw a border clr = screen->MapRGB(30000>>8, 30000>>8, 0xFF); ltClr = screen->MapRGB(40000>>8, 40000>>8, 0xFF); ltrClr = screen->MapRGB(50000>>8, 50000>>8, 0xFF); screen->Clear(); Xoff = (SCREEN_WIDTH-intro->w)/2; Yoff = (SCREEN_HEIGHT-intro->h)/2; screen->DrawRect(Xoff-1, Yoff-1, intro->w+2, intro->h+2, clr); screen->DrawRect(Xoff-2, Yoff-2, intro->w+4, intro->h+4, clr); screen->DrawRect(Xoff-3, Yoff-3, intro->w+6, intro->h+6, ltClr); screen->DrawRect(Xoff-4, Yoff-4, intro->w+8, intro->h+8, ltClr); screen->DrawRect(Xoff-5, Yoff-5, intro->w+10, intro->h+10, ltrClr); screen->DrawRect(Xoff-6, Yoff-6, intro->w+12, intro->h+12, ltClr); screen->DrawRect(Xoff-7, Yoff-7, intro->w+14, intro->h+14, clr); Yoff += intro->h; screen->QueueBlit(SCREEN_WIDTH/2-intro->w/2, SCREEN_HEIGHT/2-intro->h/2, intro, NOCLIP); screen->FreeImage(intro); /* -- Draw the loading message */ geneva = fontserv->NewFont("Geneva", 9); if ( geneva == NULL ) { error("Warning: %s\n", fontserv->Error()); return; } text = fontserv->TextImage("Loading...", geneva, STYLE_BOLD, 0xFF, 0xFF, 0x00); if ( text ) { screen->QueueBlit(SCREEN_WIDTH/2-text->w/2, Yoff+20-text->h/2, text, NOCLIP); fontserv->FreeText(text); } delete geneva; screen->Update(); } // -- DoIntroScreen /* ----------------------------------------------------------------- */ /* -- Draw a loading status bar */ #define MAX_BAR 26 static void DrawLoadBar(int first) { static int stage; Uint32 black, clr; int fact; DropEvents(); if (first) { stage = 1; black = screen->MapRGB(0x00, 0x00, 0x00); screen->DrawRect((SCREEN_WIDTH-200)/2, ((SCREEN_HEIGHT-10)/2)+185, 200, 10, black); clr = screen->MapRGB(0xFF, 0xFF, 0xFF); screen->DrawRect(((SCREEN_WIDTH-200)/2)+1, ((SCREEN_HEIGHT-10)/2)+185+1, 200-2, 10-2, clr); clr = screen->MapRGB(0x8F, 0x8F, 0xFF); screen->FillRect(((SCREEN_WIDTH-200)/2)+1+1, ((SCREEN_HEIGHT-10)/2)+185+1+1, 200-2-2, 10-2-2, clr); } clr = screen->MapRGB(0x6F, 0x6F, 0xFF); fact = ((200-2-2) * stage) / MAX_BAR; screen->FillRect(((SCREEN_WIDTH-200)/2)+1+1, ((SCREEN_HEIGHT-10)/2)+185+1+1, fact, 10-2-2, clr); screen->Update(); stage++; } /* -- DrawLoadBar */ /* ----------------------------------------------------------------- */ /* -- Set a star */ void SetStar(int which) { gTheStars[which]->xCoord = gClipRect.x+FastRandom(gClipRect.w); gTheStars[which]->yCoord = gClipRect.y+FastRandom(gClipRect.h); gTheStars[which]->color = gStarColors[FastRandom(20)]; } /* -- SetStar */ /* ----------------------------------------------------------------- */ /* -- Initialize the stars */ static void InitStars(void) { int index; /* Map star pixel colors to new colormap */ gStarColors[0] = screen->MapRGB(colors[gGammaCorrect][0xEB].r, colors[gGammaCorrect][0xEB].g, colors[gGammaCorrect][0xEB].b); gStarColors[1] = screen->MapRGB(colors[gGammaCorrect][0xEC].r, colors[gGammaCorrect][0xEC].g, colors[gGammaCorrect][0xEC].b); gStarColors[2] = screen->MapRGB(colors[gGammaCorrect][0xED].r, colors[gGammaCorrect][0xED].g, colors[gGammaCorrect][0xED].b); gStarColors[3] = screen->MapRGB(colors[gGammaCorrect][0xEE].r, colors[gGammaCorrect][0xEE].g, colors[gGammaCorrect][0xEE].b); gStarColors[4] = screen->MapRGB(colors[gGammaCorrect][0xEF].r, colors[gGammaCorrect][0xEF].g, colors[gGammaCorrect][0xEF].b); gStarColors[5] = screen->MapRGB(colors[gGammaCorrect][0xD9].r, colors[gGammaCorrect][0xD9].g, colors[gGammaCorrect][0xD9].b); gStarColors[6] = screen->MapRGB(colors[gGammaCorrect][0xDA].r, colors[gGammaCorrect][0xDA].g, colors[gGammaCorrect][0xDA].b); gStarColors[7] = screen->MapRGB(colors[gGammaCorrect][0xDB].r, colors[gGammaCorrect][0xDB].g, colors[gGammaCorrect][0xDB].b); gStarColors[8] = screen->MapRGB(colors[gGammaCorrect][0xDC].r, colors[gGammaCorrect][0xDC].g, colors[gGammaCorrect][0xDC].b); gStarColors[9] = screen->MapRGB(colors[gGammaCorrect][0xDD].r, colors[gGammaCorrect][0xDD].g, colors[gGammaCorrect][0xDD].b); gStarColors[10] = screen->MapRGB(colors[gGammaCorrect][0xE4].r, colors[gGammaCorrect][0xE4].g, colors[gGammaCorrect][0xE4].b); gStarColors[11] = screen->MapRGB(colors[gGammaCorrect][0xE5].r, colors[gGammaCorrect][0xE5].g, colors[gGammaCorrect][0xE5].b); gStarColors[12] = screen->MapRGB(colors[gGammaCorrect][0xE6].r, colors[gGammaCorrect][0xE6].g, colors[gGammaCorrect][0xE6].b); gStarColors[13] = screen->MapRGB(colors[gGammaCorrect][0xE7].r, colors[gGammaCorrect][0xE7].g, colors[gGammaCorrect][0xE7].b); gStarColors[14] = screen->MapRGB(colors[gGammaCorrect][0xE8].r, colors[gGammaCorrect][0xE8].g, colors[gGammaCorrect][0xE8].b); gStarColors[15] = screen->MapRGB(colors[gGammaCorrect][0xF7].r, colors[gGammaCorrect][0xF7].g, colors[gGammaCorrect][0xF7].b); gStarColors[16] = screen->MapRGB(colors[gGammaCorrect][0xF8].r, colors[gGammaCorrect][0xF8].g, colors[gGammaCorrect][0xF8].b); gStarColors[17] = screen->MapRGB(colors[gGammaCorrect][0xF9].r, colors[gGammaCorrect][0xF9].g, colors[gGammaCorrect][0xF9].b); gStarColors[18] = screen->MapRGB(colors[gGammaCorrect][0xFA].r, colors[gGammaCorrect][0xFA].g, colors[gGammaCorrect][0xFA].b); gStarColors[19] = screen->MapRGB(colors[gGammaCorrect][0xFB].r, colors[gGammaCorrect][0xFB].g, colors[gGammaCorrect][0xFB].b); for (index = 0; index < MAX_STARS; index++) { gTheStars[index] = new Star; gTheStars[index]->color = 0L; SetStar(index); } } /* -- InitStars */ /* ----------------------------------------------------------------- */ /* -- Build the ship's velocity table */ static void InitShots(void) { int xx = 30; /* Load the shot images */ gPlayerShot = screen->LoadImage(SHOT_SIZE,SHOT_SIZE,gPlayerShotColors); gEnemyShot = screen->LoadImage(SHOT_SIZE, SHOT_SIZE, gEnemyShotColors); /* Now setup the shot origin table */ gShotOrigins[0].h = 15 * SCALE_FACTOR; gShotOrigins[0].v = 12 * SCALE_FACTOR; gShotOrigins[1].h = 16 * SCALE_FACTOR; gShotOrigins[1].v = 12 * SCALE_FACTOR; gShotOrigins[2].h = 18 * SCALE_FACTOR; gShotOrigins[2].v = 12 * SCALE_FACTOR; gShotOrigins[3].h = 21 * SCALE_FACTOR; gShotOrigins[3].v = 12 * SCALE_FACTOR; gShotOrigins[4].h = xx * SCALE_FACTOR; gShotOrigins[4].v = xx * SCALE_FACTOR; gShotOrigins[5].h = xx * SCALE_FACTOR; gShotOrigins[5].v = xx * SCALE_FACTOR; gShotOrigins[6].h = xx * SCALE_FACTOR; gShotOrigins[6].v = xx * SCALE_FACTOR; gShotOrigins[7].h = xx * SCALE_FACTOR; gShotOrigins[7].v = xx * SCALE_FACTOR; gShotOrigins[8].h = xx * SCALE_FACTOR; gShotOrigins[8].v = xx * SCALE_FACTOR; gShotOrigins[9].h = xx * SCALE_FACTOR; gShotOrigins[9].v = xx * SCALE_FACTOR; gShotOrigins[10].h = xx * SCALE_FACTOR; gShotOrigins[10].v = xx * SCALE_FACTOR; gShotOrigins[11].h = xx * SCALE_FACTOR; gShotOrigins[11].v = xx * SCALE_FACTOR; gShotOrigins[12].h = xx * SCALE_FACTOR; gShotOrigins[12].v = xx * SCALE_FACTOR; gShotOrigins[13].h = xx * SCALE_FACTOR; gShotOrigins[13].v = xx * SCALE_FACTOR; gShotOrigins[14].h = xx * SCALE_FACTOR; gShotOrigins[14].v = xx * SCALE_FACTOR; gShotOrigins[15].h = xx * SCALE_FACTOR; gShotOrigins[15].v = xx * SCALE_FACTOR; gShotOrigins[16].h = xx * SCALE_FACTOR; gShotOrigins[16].v = xx * SCALE_FACTOR; gShotOrigins[17].h = xx * SCALE_FACTOR; gShotOrigins[17].v = xx * SCALE_FACTOR; gShotOrigins[18].h = xx * SCALE_FACTOR; gShotOrigins[18].v = xx * SCALE_FACTOR; gShotOrigins[19].h = xx * SCALE_FACTOR; gShotOrigins[19].v = xx * SCALE_FACTOR; gShotOrigins[20].h = xx * SCALE_FACTOR; gShotOrigins[20].v = xx * SCALE_FACTOR; gShotOrigins[21].h = xx * SCALE_FACTOR; gShotOrigins[21].v = xx * SCALE_FACTOR; gShotOrigins[22].h = xx * SCALE_FACTOR; gShotOrigins[22].v = xx * SCALE_FACTOR; gShotOrigins[23].h = xx * SCALE_FACTOR; gShotOrigins[23].v = xx * SCALE_FACTOR; gShotOrigins[24].h = xx * SCALE_FACTOR; gShotOrigins[24].v = xx * SCALE_FACTOR; gShotOrigins[25].h = xx * SCALE_FACTOR; gShotOrigins[25].v = xx * SCALE_FACTOR; gShotOrigins[26].h = xx * SCALE_FACTOR; gShotOrigins[26].v = xx * SCALE_FACTOR; gShotOrigins[27].h = xx * SCALE_FACTOR; gShotOrigins[27].v = xx * SCALE_FACTOR; gShotOrigins[28].h = xx * SCALE_FACTOR; gShotOrigins[28].v = xx * SCALE_FACTOR; gShotOrigins[29].h = xx * SCALE_FACTOR; gShotOrigins[29].v = xx * SCALE_FACTOR; gShotOrigins[30].h = xx * SCALE_FACTOR; gShotOrigins[30].v = xx * SCALE_FACTOR; gShotOrigins[31].h = xx * SCALE_FACTOR; gShotOrigins[31].v = xx * SCALE_FACTOR; gShotOrigins[32].h = xx * SCALE_FACTOR; gShotOrigins[32].v = xx * SCALE_FACTOR; gShotOrigins[33].h = xx * SCALE_FACTOR; gShotOrigins[33].v = xx * SCALE_FACTOR; gShotOrigins[34].h = xx * SCALE_FACTOR; gShotOrigins[34].v = xx * SCALE_FACTOR; gShotOrigins[35].h = xx * SCALE_FACTOR; gShotOrigins[35].v = xx * SCALE_FACTOR; gShotOrigins[36].h = xx * SCALE_FACTOR; gShotOrigins[36].v = xx * SCALE_FACTOR; gShotOrigins[37].h = xx * SCALE_FACTOR; gShotOrigins[37].v = xx * SCALE_FACTOR; gShotOrigins[38].h = xx * SCALE_FACTOR; gShotOrigins[38].v = xx * SCALE_FACTOR; gShotOrigins[39].h = xx * SCALE_FACTOR; gShotOrigins[39].v = xx * SCALE_FACTOR; gShotOrigins[40].h = xx * SCALE_FACTOR; gShotOrigins[40].v = xx * SCALE_FACTOR; gShotOrigins[41].h = xx * SCALE_FACTOR; gShotOrigins[41].v = xx * SCALE_FACTOR; gShotOrigins[42].h = xx * SCALE_FACTOR; gShotOrigins[42].v = xx * SCALE_FACTOR; gShotOrigins[43].h = xx * SCALE_FACTOR; gShotOrigins[43].v = xx * SCALE_FACTOR; gShotOrigins[44].h = xx * SCALE_FACTOR; gShotOrigins[44].v = xx * SCALE_FACTOR; gShotOrigins[45].h = xx * SCALE_FACTOR; gShotOrigins[45].v = xx * SCALE_FACTOR; gShotOrigins[46].h = xx * SCALE_FACTOR; gShotOrigins[46].v = xx * SCALE_FACTOR; gShotOrigins[47].h = xx * SCALE_FACTOR; gShotOrigins[47].v = xx * SCALE_FACTOR; /* -- Now setup the thruster origin table */ gThrustOrigins[0].h = 8 * SCALE_FACTOR; gThrustOrigins[0].v = 22 * SCALE_FACTOR; gThrustOrigins[1].h = 6 * SCALE_FACTOR; gThrustOrigins[1].v = 22 * SCALE_FACTOR; gThrustOrigins[2].h = 4 * SCALE_FACTOR; gThrustOrigins[2].v = 21 * SCALE_FACTOR; gThrustOrigins[3].h = 1 * SCALE_FACTOR; gThrustOrigins[3].v = 20 * SCALE_FACTOR; gThrustOrigins[4].h = 0 * SCALE_FACTOR; gThrustOrigins[4].v = 19 * SCALE_FACTOR; gThrustOrigins[5].h = -1 * SCALE_FACTOR; gThrustOrigins[5].v = 19 * SCALE_FACTOR; gThrustOrigins[6].h = -3 * SCALE_FACTOR; gThrustOrigins[6].v = 16 * SCALE_FACTOR; gThrustOrigins[7].h = -5 * SCALE_FACTOR; gThrustOrigins[7].v = 15 * SCALE_FACTOR; gThrustOrigins[8].h = -6 * SCALE_FACTOR; gThrustOrigins[8].v = 13 * SCALE_FACTOR; gThrustOrigins[9].h = -9 * SCALE_FACTOR; gThrustOrigins[9].v = 11 * SCALE_FACTOR; gThrustOrigins[10].h = -10 * SCALE_FACTOR; gThrustOrigins[10].v = 10 * SCALE_FACTOR; gThrustOrigins[11].h = -11 * SCALE_FACTOR; gThrustOrigins[11].v = 7 * SCALE_FACTOR; gThrustOrigins[12].h = -9 * SCALE_FACTOR; gThrustOrigins[12].v = 7 * SCALE_FACTOR; gThrustOrigins[13].h = -9 * SCALE_FACTOR; gThrustOrigins[13].v = 4 * SCALE_FACTOR; gThrustOrigins[14].h = -7 * SCALE_FACTOR; gThrustOrigins[14].v = 2 * SCALE_FACTOR; gThrustOrigins[15].h = -6 * SCALE_FACTOR; gThrustOrigins[15].v = 0 * SCALE_FACTOR; gThrustOrigins[16].h = -9 * SCALE_FACTOR; gThrustOrigins[16].v = 1 * SCALE_FACTOR; gThrustOrigins[17].h = -3 * SCALE_FACTOR; gThrustOrigins[17].v = -3 * SCALE_FACTOR; gThrustOrigins[18].h = -1 * SCALE_FACTOR; gThrustOrigins[18].v = -2 * SCALE_FACTOR; gThrustOrigins[19].h = 0 * SCALE_FACTOR; gThrustOrigins[19].v = -4 * SCALE_FACTOR; gThrustOrigins[20].h = 4 * SCALE_FACTOR; gThrustOrigins[20].v = -6 * SCALE_FACTOR; gThrustOrigins[21].h = 5 * SCALE_FACTOR; gThrustOrigins[21].v = -8 * SCALE_FACTOR; gThrustOrigins[22].h = 5 * SCALE_FACTOR; gThrustOrigins[22].v = -6 * SCALE_FACTOR; gThrustOrigins[23].h = 8 * SCALE_FACTOR; gThrustOrigins[23].v = -7 * SCALE_FACTOR; gThrustOrigins[24].h = 9 * SCALE_FACTOR; gThrustOrigins[24].v = -7 * SCALE_FACTOR; gThrustOrigins[25].h = 12 * SCALE_FACTOR; gThrustOrigins[25].v = -6 * SCALE_FACTOR; gThrustOrigins[26].h = 13 * SCALE_FACTOR; gThrustOrigins[26].v = -6 * SCALE_FACTOR; gThrustOrigins[27].h = 15 * SCALE_FACTOR; gThrustOrigins[27].v = -7 * SCALE_FACTOR; gThrustOrigins[28].h = 17 * SCALE_FACTOR; gThrustOrigins[28].v = -6 * SCALE_FACTOR; gThrustOrigins[29].h = 18 * SCALE_FACTOR; gThrustOrigins[29].v = -4 * SCALE_FACTOR; gThrustOrigins[30].h = 20 * SCALE_FACTOR; gThrustOrigins[30].v = -2 * SCALE_FACTOR; gThrustOrigins[31].h = 19 * SCALE_FACTOR; gThrustOrigins[31].v = -1 * SCALE_FACTOR; gThrustOrigins[32].h = 21 * SCALE_FACTOR; gThrustOrigins[32].v = 0 * SCALE_FACTOR; gThrustOrigins[33].h = 22 * SCALE_FACTOR; gThrustOrigins[33].v = 2 * SCALE_FACTOR; gThrustOrigins[34].h = 24 * SCALE_FACTOR; gThrustOrigins[34].v = 3 * SCALE_FACTOR; gThrustOrigins[35].h = 25 * SCALE_FACTOR; gThrustOrigins[35].v = 5 * SCALE_FACTOR; gThrustOrigins[36].h = 26 * SCALE_FACTOR; gThrustOrigins[36].v = 7 * SCALE_FACTOR; gThrustOrigins[37].h = 25 * SCALE_FACTOR; gThrustOrigins[37].v = 7 * SCALE_FACTOR; gThrustOrigins[38].h = 24 * SCALE_FACTOR; gThrustOrigins[38].v = 10 * SCALE_FACTOR; gThrustOrigins[39].h = 23 * SCALE_FACTOR; gThrustOrigins[39].v = 11 * SCALE_FACTOR; gThrustOrigins[40].h = 23 * SCALE_FACTOR; gThrustOrigins[40].v = 12 * SCALE_FACTOR; gThrustOrigins[41].h = 20 * SCALE_FACTOR; gThrustOrigins[41].v = 14 * SCALE_FACTOR; gThrustOrigins[42].h = 20 * SCALE_FACTOR; gThrustOrigins[42].v = 16 * SCALE_FACTOR; gThrustOrigins[43].h = 18 * SCALE_FACTOR; gThrustOrigins[43].v = 18 * SCALE_FACTOR; gThrustOrigins[44].h = 15 * SCALE_FACTOR; gThrustOrigins[44].v = 18 * SCALE_FACTOR; gThrustOrigins[45].h = 15 * SCALE_FACTOR; gThrustOrigins[45].v = 20 * SCALE_FACTOR; gThrustOrigins[46].h = 12 * SCALE_FACTOR; gThrustOrigins[46].v = 21 * SCALE_FACTOR; gThrustOrigins[47].h = 9 * SCALE_FACTOR; gThrustOrigins[47].v = 22 * SCALE_FACTOR; } /* -- InitShots */ /* ----------------------------------------------------------------- */ /* -- Build the ship's velocity table */ static void BuildVelocityTable(void) { #ifdef COMPUTE_VELTABLE /* Calculate the appropriate values */ int index; double factor; double ss; ss = SHIP_FRAMES; factor = (360.0 / ss); for (index = 0; index < SHIP_FRAMES; index++) { ss = index; ss = -(((ss * factor) * PI) / 180.0); gVelocityTable[index].h = (int)(sin(ss) * -8.0); gVelocityTable[index].v = (int)(cos(ss) * -8.0); #ifdef PRINT_TABLE printf("\tgVelocityTable[%d].h = %d;\n", index, gVelocityTable[index].h); printf("\tgVelocityTable[%d].v = %d;\n", index, gVelocityTable[index].v); #endif } #else /* Because PI, sin() and cos() return _slightly_ different values across architectures, we need to precompute our velocity table -- make it standard across compilations. :) */ gVelocityTable[0].h = 0; gVelocityTable[0].v = -8; gVelocityTable[1].h = 1; gVelocityTable[1].v = -7; gVelocityTable[2].h = 2; gVelocityTable[2].v = -7; gVelocityTable[3].h = 3; gVelocityTable[3].v = -7; gVelocityTable[4].h = 4; gVelocityTable[4].v = -6; gVelocityTable[5].h = 4; gVelocityTable[5].v = -6; gVelocityTable[6].h = 5; gVelocityTable[6].v = -5; gVelocityTable[7].h = 6; gVelocityTable[7].v = -4; gVelocityTable[8].h = 6; gVelocityTable[8].v = -4; gVelocityTable[9].h = 7; gVelocityTable[9].v = -3; gVelocityTable[10].h = 7; gVelocityTable[10].v = -2; gVelocityTable[11].h = 7; gVelocityTable[11].v = -1; gVelocityTable[12].h = 8; gVelocityTable[12].v = 0; gVelocityTable[13].h = 7; gVelocityTable[13].v = 1; gVelocityTable[14].h = 7; gVelocityTable[14].v = 2; gVelocityTable[15].h = 7; gVelocityTable[15].v = 3; gVelocityTable[16].h = 6; gVelocityTable[16].v = 3; gVelocityTable[17].h = 6; gVelocityTable[17].v = 4; gVelocityTable[18].h = 5; gVelocityTable[18].v = 5; gVelocityTable[19].h = 4; gVelocityTable[19].v = 6; gVelocityTable[20].h = 3; gVelocityTable[20].v = 6; gVelocityTable[21].h = 3; gVelocityTable[21].v = 7; gVelocityTable[22].h = 2; gVelocityTable[22].v = 7; gVelocityTable[23].h = 1; gVelocityTable[23].v = 7; gVelocityTable[24].h = 0; gVelocityTable[24].v = 8; gVelocityTable[25].h = -1; gVelocityTable[25].v = 7; gVelocityTable[26].h = -2; gVelocityTable[26].v = 7; gVelocityTable[27].h = -3; gVelocityTable[27].v = 7; gVelocityTable[28].h = -4; gVelocityTable[28].v = 6; gVelocityTable[29].h = -4; gVelocityTable[29].v = 6; gVelocityTable[30].h = -5; gVelocityTable[30].v = 5; gVelocityTable[31].h = -6; gVelocityTable[31].v = 4; gVelocityTable[32].h = -6; gVelocityTable[32].v = 4; gVelocityTable[33].h = -7; gVelocityTable[33].v = 3; gVelocityTable[34].h = -7; gVelocityTable[34].v = 2; gVelocityTable[35].h = -7; gVelocityTable[35].v = 1; gVelocityTable[36].h = -8; gVelocityTable[36].v = 0; gVelocityTable[37].h = -7; gVelocityTable[37].v = -1; gVelocityTable[38].h = -7; gVelocityTable[38].v = -2; gVelocityTable[39].h = -7; gVelocityTable[39].v = -3; gVelocityTable[40].h = -6; gVelocityTable[40].v = -4; gVelocityTable[41].h = -6; gVelocityTable[41].v = -4; gVelocityTable[42].h = -5; gVelocityTable[42].v = -5; gVelocityTable[43].h = -4; gVelocityTable[43].v = -6; gVelocityTable[44].h = -4; gVelocityTable[44].v = -6; gVelocityTable[45].h = -3; gVelocityTable[45].v = -7; gVelocityTable[46].h = -2; gVelocityTable[46].v = -7; gVelocityTable[47].h = -1; gVelocityTable[47].v = -7; #endif /* COMPUTE_VELTABLE */ } /* -- BuildVelocityTable */ /* This function needs to be able to properly clean up from any stage of the program at any time, including itself if interrupted during cleanup. *sigh* reentrant multi-threading can be a pain. :) */ extern "C" void CleanUp(void) { HaltLogic(); if ( fontserv ) { delete fontserv; fontserv = NULL; } if ( sound ) { delete sound; sound = NULL; } if ( screen ) { delete screen; screen = NULL; } SaveControls(); SDL_Quit(); } /* ----------------------------------------------------------------- */ /* -- Perform some initializations and report failure if we choke */ int DoInitializations(Uint32 video_flags) { LibPath library; int i; SDL_Surface *icon; /* Make sure we clean up properly at exit */ Uint32 init_flags = (SDL_INIT_VIDEO|SDL_INIT_AUDIO); #ifdef SDL_INIT_JOYSTICK init_flags |= SDL_INIT_JOYSTICK; #endif if ( SDL_Init(init_flags) < 0 ) { init_flags &= ~SDL_INIT_JOYSTICK; if ( SDL_Init(init_flags) < 0 ) { error("Couldn't initialize SDL: %s\n", SDL_GetError()); return(-1); } } atexit(CleanUp); signal(SIGSEGV, exit); // -- Initialize some variables gLastHigh = -1; // -- Create our scores file LoadScores(); #ifdef SDL_INIT_JOYSTICK /* Initialize the first joystick */ if ( SDL_NumJoysticks() > 0 ) { if ( SDL_JoystickOpen(0) == NULL ) { error("Warning: Couldn't open joystick '%s' : %s\n", SDL_JoystickName(0), SDL_GetError()); } } #endif /* Load the Font Server */ fontserv = new FontServ(library.Path("Maelstrom Fonts")); if ( fontserv->Error() ) { error("Fatal: %s\n", fontserv->Error()); return(-1); } /* Load the Sound Server and initialize sound */ sound = new Sound(library.Path("Maelstrom Sounds"), gSoundLevel); if ( sound->Error() ) { error("Fatal: %s\n", sound->Error()); return(-1); } /* Load the Maelstrom icon */ icon = SDL_LoadBMP(library.Path("icon.bmp")); if ( icon == NULL ) { error("Fatal: Couldn't load icon: %s\n", SDL_GetError()); return(-1); } /* Initialize the screen */ screen = new FrameBuf; if (screen->Init(SCREEN_WIDTH, SCREEN_HEIGHT, video_flags, colors[gGammaCorrect], icon) < 0){ error("Fatal: %s\n", screen->Error()); return(-1); } screen->SetCaption("Maelstrom"); atexit(CleanUp); // Need to reset this under X11 DGA SDL_FreeSurface(icon); /* -- We want to access the FULL screen! */ SetRect(&gScrnRect, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); gStatusLine = (gScrnRect.bottom - gScrnRect.top - STATUS_HEIGHT); gScrnRect.bottom -= STATUS_HEIGHT; gTop = 0; gLeft = 0; gBottom = gScrnRect.bottom - gScrnRect.top; gRight = gScrnRect.right - gScrnRect.left; gClipRect.x = gLeft+SPRITES_WIDTH; gClipRect.y = gTop+SPRITES_WIDTH; gClipRect.w = gRight-gLeft-2*SPRITES_WIDTH; gClipRect.h = gBottom-gTop-2*SPRITES_WIDTH+STATUS_HEIGHT; screen->ClipBlit(&gClipRect); /* Do the Ambrosia Splash screen */ screen->Clear(); screen->Update(); screen->Fade(); DoSplash(); screen->Fade(); for ( i=0; i<5; ++i ) { if ( DropEvents() ) { break; } Delay(60); } /* -- Throw up our intro screen */ screen->Fade(); DoIntroScreen(); sound->PlaySound(gPrizeAppears, 1); screen->Fade(); /* -- Load in our sprites and other needed resources */ { Mac_Resource spriteres(library.Path("Maelstrom Sprites")); if ( spriteres.Error() ) { error("%s\n", spriteres.Error()); return(-1); } if ( LoadBlits(&spriteres) < 0 ) { return(-1); } } /* -- Create the shots array */ InitShots(); /* -- Initialize the sprite manager - after we load blits and shots! */ if ( InitSprites() < 0 ) return(-1); /* -- Load in the prize CICN's */ if ( LoadCICNS() < 0 ) return(-1); /* -- Create the stars array */ InitStars(); /* -- Set up the velocity tables */ BuildVelocityTable(); return(0); } /* -- DoInitializations */ /* ----------------------------------------------------------------- */ /* -- Load in the blits */ static int LoadBlits(Mac_Resource *spriteres) { DrawLoadBar(1); /* -- Load in the thrusters */ if ( LoadSmallSprite(spriteres, &gThrust1, 400, SHIP_FRAMES) < 0 ) return(-1); DrawLoadBar(0); if ( LoadSmallSprite(spriteres, &gThrust2, 500, SHIP_FRAMES) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the player's ship */ if ( LoadSprite(spriteres, &gPlayerShip, 200, SHIP_FRAMES) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the large rock */ if ( LoadSprite(spriteres, &gRock1R, 500, 60) < 0 ) return(-1); BackwardsSprite(&gRock1L, gRock1R); DrawLoadBar(0); /* -- Load in the medium rock */ if ( LoadSprite(spriteres, &gRock2R, 400, 40) < 0 ) return(-1); BackwardsSprite(&gRock2L, gRock2R); DrawLoadBar(0); /* -- Load in the small rock */ if ( LoadSmallSprite(spriteres, &gRock3R, 300, 20) < 0 ) return(-1); BackwardsSprite(&gRock3L, gRock3R); DrawLoadBar(0); /* -- Load in the explosion */ if ( LoadSprite(spriteres, &gExplosion, 600, 12) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the 2x multiplier */ if ( LoadSprite(spriteres, &gMult[0], 2000, 1) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the 3x multiplier */ if ( LoadSprite(spriteres, &gMult[1], 2002, 1) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the 4x multiplier */ if ( LoadSprite(spriteres, &gMult[2], 2004, 1) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the 5x multiplier */ if ( LoadSprite(spriteres, &gMult[3], 2006, 1) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the steel asteroid */ if ( LoadSprite(spriteres, &gSteelRoidL, 700, 40) < 0 ) return(-1); BackwardsSprite(&gSteelRoidR, gSteelRoidL); DrawLoadBar(0); /* -- Load in the prize */ if ( LoadSprite(spriteres, &gPrize, 800, 30) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the bonus */ if ( LoadSprite(spriteres, &gBonusBlit, 900, 10) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the bonus */ if ( LoadSprite(spriteres, &gPointBlit, 1000, 6) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the vortex */ if ( LoadSprite(spriteres, &gVortexBlit, 1100, 10) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the homing mine */ if ( LoadSprite(spriteres, &gMineBlitR, 1200, 40) < 0 ) return(-1); BackwardsSprite(&gMineBlitL, gMineBlitR); DrawLoadBar(0); /* -- Load in the shield */ if ( LoadSprite(spriteres, &gShieldBlit, 1300, 2) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the nova */ if ( LoadSprite(spriteres, &gNova, 1400, 18) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the ship explosion */ if ( LoadSprite(spriteres, &gShipExplosion, 1500, 21) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the shrapnel */ if ( LoadSprite(spriteres, &gShrapnel1, 1800, 50) < 0 ) return(-1); DrawLoadBar(0); if ( LoadSprite(spriteres, &gShrapnel2, 1900, 42) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the damaged ship */ if ( LoadSprite(spriteres, &gDamagedShip, 1600, 10) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the enemy ship */ if ( LoadSprite(spriteres, &gEnemyShip, 1700, 40) < 0 ) return(-1); DrawLoadBar(0); /* -- Load in the enemy ship */ if ( LoadSprite(spriteres, &gEnemyShip2, 2100, 40) < 0 ) return(-1); DrawLoadBar(0); return(0); } /* -- LoadBlits */ /* -- Initialize our sprites */ int InitSprites(void) { /* Initialize sprite variables */ gNumSprites = 0; gLastDrawn = 0L; /* Initialize player sprites */ return(InitPlayerSprites()); } /* -- InitSprites */ /* ----------------------------------------------------------------- */ /* -- Load in the sprites we use */ static void BackwardsSprite(BlitPtr *theBlit, BlitPtr oldBlit) { BlitPtr aBlit; int index, nFrames; aBlit = new Blit; nFrames = oldBlit->numFrames; aBlit->numFrames = nFrames; aBlit->hitRect.left = oldBlit->hitRect.left; aBlit->hitRect.right = oldBlit->hitRect.right; aBlit->hitRect.top = oldBlit->hitRect.top; aBlit->hitRect.bottom = oldBlit->hitRect.bottom; aBlit->isSmall = oldBlit->isSmall; /* -- Reverse the sprite images */ for (index = 0; index < aBlit->numFrames; index++) { aBlit->sprite[index] = oldBlit->sprite[nFrames - index - 1]; aBlit->mask[index] = oldBlit->mask[nFrames - index - 1]; } (*theBlit) = aBlit; } /* -- BackwardsSprite */ /* ----------------------------------------------------------------- */ /* -- Load in the sprites we use */ static int LoadSprite(Mac_Resource *spriteres, BlitPtr *theBlit, int baseID, int numFrames) { Mac_ResData *S, *M; int index; BlitPtr aBlit; Uint32 offset; int top, left, bottom, right; int row, col; Uint8 *mask; aBlit = new Blit; aBlit->numFrames = numFrames; aBlit->isSmall = 0; left = 32; right = 0; top = 32; bottom = 0; /* -- Load in the image data */ for (index = 0; index < numFrames; index++) { M = spriteres->Resource("ICN#", baseID+index); if ( M== NULL ) { error( "LoadSprite(%d+%d): Couldn't load ICN# resource!\n", baseID, index); return(-1); } mask = M->data+128; S = spriteres->Resource("icl8", baseID+index); if ( S == NULL ) { error( "LoadSprite(%d+%d): Couldn't load icl8 resource!\n", baseID, index); return(-1); } /* -- Figure out the hit rectangle */ /* -- Do the top/left first */ for ( row=0; row<32; ++row ) { for ( col=0; col<32; ++col ) { offset = (row*32)+col; if ((mask[offset/8]>>(7-(offset%8))) & 0x01){ if ( row < top ) top = row; if ( col < left ) left = col; } } } for ( row=31; row>top; --row ) { for ( col=31; col>left; --col ) { offset = (row*32)+col; if ((mask[offset/8]>>(7-(offset%8))) & 0x01){ if ( row > bottom ) bottom = row; if ( col > right ) right = col; } } } SetRect(&aBlit->hitRect, left, top, right, bottom); /* Load the image */ aBlit->sprite[index] = screen->LoadImage(32, 32, S->data, mask); if ( aBlit->sprite[index] == NULL ) { error( "LoadSprite(%d+%d): Couldn't convert sprite image!\n", baseID, index); return(-1); } /* Create the bytemask */ M->length = (M->length-128)*8; aBlit->mask[index] = new Uint8[M->length]; for ( offset=0; offsetlength; ++offset ) { aBlit->mask[index][offset] = ((mask[offset/8]>>(7-(offset%8)))&0x01); } } (*theBlit) = aBlit; return(0); } /* -- LoadSprite */ /* ----------------------------------------------------------------- */ /* -- Load in the prize CICN's */ static int LoadCICNS(void) { if ( (gAutoFireIcon = GetCIcon(screen, 128)) == NULL ) return(-1); if ( (gAirBrakesIcon = GetCIcon(screen, 129)) == NULL ) return(-1); if ( (gMult2Icon = GetCIcon(screen, 130)) == NULL ) return(-1); if ( (gMult3Icon = GetCIcon(screen, 131)) == NULL ) return(-1); if ( (gMult4Icon = GetCIcon(screen, 132)) == NULL ) return(-1); if ( (gMult5Icon = GetCIcon(screen, 134)) == NULL ) return(-1); if ( (gLuckOfTheIrishIcon = GetCIcon(screen, 133)) == NULL ) return(-1); if ( (gTripleFireIcon = GetCIcon(screen, 135)) == NULL ) return(-1); if ( (gLongFireIcon = GetCIcon(screen, 136)) == NULL ) return(-1); if ( (gShieldIcon = GetCIcon(screen, 137)) == NULL ) return(-1); if ( (gKeyIcon = GetCIcon(screen, 100)) == NULL ) return(-1); return(0); } /* -- LoadCICNS */ /* ----------------------------------------------------------------- */ /* -- Load in the sprites we use */ static int LoadSmallSprite(Mac_Resource *spriteres, BlitPtr *theBlit, int baseID, int numFrames) { Mac_ResData *S, *M; int index; BlitPtr aBlit; Uint32 offset; int top, left, bottom, right; int row, col; Uint8 *mask; aBlit = new Blit; aBlit->numFrames = numFrames; aBlit->isSmall = 1; left = 16; right = 0; top = 16; bottom = 0; /* -- Load in the image data */ for (index = 0; index < numFrames; index++) { M = spriteres->Resource("ics#", baseID+index); if ( M == NULL ) { error( "LoadSmallSprite(%d+%d): Couldn't load ics# resource!\n", baseID,index); return(-1); } mask = M->data+32; S = spriteres->Resource("ics8", baseID+index); if ( S == NULL ) { error( "LoadSmallSprite(%d+%d): Couldn't load ics8 resource!\n", baseID,index); return(-1); } /* -- Figure out the hit rectangle */ /* -- Do the top/left first */ for ( row=0; row<16; ++row ) { for ( col=0; col<16; ++col ) { offset = (row*16)+col; if ((mask[offset/8]>>(7-(offset%8))) & 0x01){ if ( row < top ) top = row; if ( col < left ) left = col; } } } for ( row=15; row>top; --row ) { for ( col=15; col>left; --col ) { offset = (row*16)+col; if ((mask[offset/8]>>(7-(offset%8))) & 0x01){ if ( row > bottom ) bottom = row; if ( col > right ) right = col; } } } SetRect(&aBlit->hitRect, left, top, right, bottom); /* Load the image */ aBlit->sprite[index] = screen->LoadImage(16, 16, S->data, mask); if ( aBlit->sprite[index] == NULL ) { error( "LoadSprite(%d+%d): Couldn't convert sprite image!\n", baseID, index); return(-1); } /* Create the bytemask */ M->length = (M->length-32)*8; aBlit->mask[index] = new Uint8[M->length]; for ( offset=0; offsetlength; ++offset ) { aBlit->mask[index][offset] = ((mask[offset/8]>>(7-(offset%8)))&0x01); } } (*theBlit) = aBlit; return(0); } /* -- LoadSmallSprite */