/* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */ // // Copyright (c) 2009, Wei Mingzhi . // All rights reserved. // // This file is part of SDLPAL. // // SDLPAL is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include "main.h" static WORD g_wCurEffectSprite = 0; VOID PAL_EndingSetEffectSprite( WORD wSpriteNum ) /*++ Purpose: Set the effect sprite of the ending. Parameters: [IN] wSpriteNum - the number of the sprite. Return value: None. --*/ { g_wCurEffectSprite = wSpriteNum; } VOID PAL_ShowFBP( WORD wChunkNum, WORD wFade ) /*++ Purpose: Draw an FBP picture to the screen. Parameters: [IN] wChunkNum - number of chunk in fbp.mkf file. [IN] wFade - fading speed of showing the picture. Return value: None. --*/ { PAL_LARGE BYTE buf[320 * 200]; PAL_LARGE BYTE bufSprite[320 * 200]; const int rgIndex[6] = {0, 3, 1, 5, 2, 4}; SDL_Surface *p; int i, j, k; BYTE a, b; if (PAL_MKFDecompressChunk(buf, 320 * 200, wChunkNum, gpGlobals->f.fpFBP) <= 0) { memset(buf, 0, sizeof(buf)); } if (g_wCurEffectSprite != 0) { PAL_MKFDecompressChunk(bufSprite, 320 * 200, g_wCurEffectSprite, gpGlobals->f.fpMGO); } if (wFade) { wFade++; wFade *= 10; p = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8, gpScreen->format->Rmask, gpScreen->format->Gmask, gpScreen->format->Bmask, gpScreen->format->Amask); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetSurfacePalette(p, gpScreen->format->palette); #else SDL_SetPalette(p, SDL_PHYSPAL | SDL_LOGPAL, VIDEO_GetPalette(), 0, 256); #endif PAL_FBPBlitToSurface(buf, p); VIDEO_BackupScreen(); for (i = 0; i < 16; i++) { for (j = 0; j < 6; j++) { // // Blend the pixels in the 2 buffers, and put the result into the // backup buffer // for (k = rgIndex[j]; k < gpScreen->pitch * gpScreen->h; k += 6) { a = ((LPBYTE)(p->pixels))[k]; b = ((LPBYTE)(gpScreenBak->pixels))[k]; if (i > 0) { if ((a & 0x0F) > (b & 0x0F)) { b++; } else if ((a & 0x0F) < (b & 0x0F)) { b--; } } ((LPBYTE)(gpScreenBak->pixels))[k] = ((a & 0xF0) | (b & 0x0F)); } SDL_BlitSurface(gpScreenBak, NULL, gpScreen, NULL); if (g_wCurEffectSprite != 0) { int f = SDL_GetTicks() / 150; PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufSprite, f % PAL_SpriteGetNumFrames(bufSprite)), gpScreen, PAL_XY(0, 0)); } VIDEO_UpdateScreen(NULL); UTIL_Delay(wFade); } } SDL_FreeSurface(p); } // // HACKHACK: to make the ending show correctly // if (wChunkNum != (gpGlobals->fIsWIN95 ? 68 : 49)) { PAL_FBPBlitToSurface(buf, gpScreen); } VIDEO_UpdateScreen(NULL); } VOID PAL_ScrollFBP( WORD wChunkNum, WORD wScrollSpeed, BOOL fScrollDown ) /*++ Purpose: Scroll up an FBP picture to the screen. Parameters: [IN] wChunkNum - number of chunk in fbp.mkf file. [IN] wScrollSpeed - scrolling speed of showing the picture. [IN] fScrollDown - TRUE if scroll down, FALSE if scroll up. Return value: None. --*/ { SDL_Surface *p; PAL_LARGE BYTE buf[320 * 200]; PAL_LARGE BYTE bufSprite[320 * 200]; int i, l; SDL_Rect rect, dstrect; if (PAL_MKFDecompressChunk(buf, 320 * 200, wChunkNum, gpGlobals->f.fpFBP) <= 0) { return; } if (g_wCurEffectSprite != 0) { PAL_MKFDecompressChunk(bufSprite, 320 * 200, g_wCurEffectSprite, gpGlobals->f.fpMGO); } p = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8, gpScreen->format->Rmask, gpScreen->format->Gmask, gpScreen->format->Bmask, gpScreen->format->Amask); if (p == NULL) { return; } #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetSurfacePalette(p, gpScreen->format->palette); #else SDL_SetPalette(p, SDL_PHYSPAL | SDL_LOGPAL, VIDEO_GetPalette(), 0, 256); #endif VIDEO_BackupScreen(); PAL_FBPBlitToSurface(buf, p); if (wScrollSpeed == 0) { wScrollSpeed = 1; } rect.x = 0; rect.w = 320; dstrect.x = 0; dstrect.w = 320; for (l = 0; l < 220; l++) { i = l; if (i > 200) { i = 200; } if (fScrollDown) { rect.y = 0; dstrect.y = i; rect.h = 200 - i; dstrect.h = 200 - i; } else { rect.y = i; dstrect.y = 0; rect.h = 200 - i; dstrect.h = 200 - i; } SDL_BlitSurface(gpScreenBak, &rect, gpScreen, &dstrect); if (fScrollDown) { rect.y = 200 - i; dstrect.y = 0; rect.h = i; dstrect.h = i; } else { rect.y = 0; dstrect.y = 200 - i; rect.h = i; dstrect.h = i; } SDL_BlitSurface(p, &rect, gpScreen, &dstrect); PAL_ApplyWave(gpScreen); if (g_wCurEffectSprite != 0) { int f = SDL_GetTicks() / 150; PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufSprite, f % PAL_SpriteGetNumFrames(bufSprite)), gpScreen, PAL_XY(0, 0)); } VIDEO_UpdateScreen(NULL); if (gpGlobals->fNeedToFadeIn) { PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1); gpGlobals->fNeedToFadeIn = FALSE; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetSurfacePalette(p, gpScreen->format->palette); #else SDL_SetPalette(p, SDL_PHYSPAL | SDL_LOGPAL, VIDEO_GetPalette(), 0, 256); #endif } UTIL_Delay(800 / wScrollSpeed); } SDL_BlitSurface(p, NULL, gpScreen, NULL); SDL_FreeSurface(p); VIDEO_UpdateScreen(NULL); } VOID PAL_EndingAnimation( VOID ) /*++ Purpose: Show the ending animation. Parameters: None. Return value: None. --*/ { LPBYTE buf; LPBYTE bufGirl; SDL_Surface *pUpper; SDL_Surface *pLower; SDL_Rect srcrect, dstrect; int yPosGirl = 180; int i; buf = (LPBYTE)UTIL_calloc(1, 64000); bufGirl = (LPBYTE)UTIL_calloc(1, 6000); pUpper = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8, gpScreen->format->Rmask, gpScreen->format->Gmask, gpScreen->format->Bmask, gpScreen->format->Amask); pLower = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8, gpScreen->format->Rmask, gpScreen->format->Gmask, gpScreen->format->Bmask, gpScreen->format->Amask); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetSurfacePalette(pUpper, gpScreen->format->palette); SDL_SetSurfacePalette(pLower, gpScreen->format->palette); #else SDL_SetPalette(pUpper, SDL_PHYSPAL | SDL_LOGPAL, VIDEO_GetPalette(), 0, 256); SDL_SetPalette(pLower, SDL_PHYSPAL | SDL_LOGPAL, VIDEO_GetPalette(), 0, 256); #endif PAL_MKFDecompressChunk(buf, 64000, gpGlobals->fIsWIN95 ? 69 : 61, gpGlobals->f.fpFBP); PAL_FBPBlitToSurface(buf, pUpper); PAL_MKFDecompressChunk(buf, 64000, gpGlobals->fIsWIN95 ? 70 : 62, gpGlobals->f.fpFBP); PAL_FBPBlitToSurface(buf, pLower); PAL_MKFDecompressChunk(buf, 64000, 571, gpGlobals->f.fpMGO); PAL_MKFDecompressChunk(bufGirl, 6000, 572, gpGlobals->f.fpMGO); srcrect.x = 0; dstrect.x = 0; srcrect.w = 320; dstrect.w = 320; gpGlobals->wScreenWave = 2; for (i = 0; i < 400; i++) { // // Draw the background // srcrect.y = 0; srcrect.h = 200 - i / 2; dstrect.y = i / 2; dstrect.h = 200 - i / 2; SDL_BlitSurface(pLower, &srcrect, gpScreen, &dstrect); srcrect.y = 200 - i / 2; srcrect.h = i / 2; dstrect.y = 0; dstrect.h = i / 2; SDL_BlitSurface(pUpper, &srcrect, gpScreen, &dstrect); PAL_ApplyWave(gpScreen); // // Draw the beast // PAL_RLEBlitToSurface(PAL_SpriteGetFrame(buf, 0), gpScreen, PAL_XY(0, -400 + i)); PAL_RLEBlitToSurface(gpGlobals->fIsWIN95 ? buf + 0x8444 : PAL_SpriteGetFrame(buf, 1), gpScreen, PAL_XY(0, -200 + i)); // // Draw the girl // yPosGirl -= i & 1; if (yPosGirl < 80) { yPosGirl = 80; } PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufGirl, (SDL_GetTicks() / 50) % 4), gpScreen, PAL_XY(220, yPosGirl)); // // Update the screen // VIDEO_UpdateScreen(NULL); if (gpGlobals->fNeedToFadeIn) { PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1); gpGlobals->fNeedToFadeIn = FALSE; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetSurfacePalette(pUpper, gpScreen->format->palette); SDL_SetSurfacePalette(pLower, gpScreen->format->palette); #else SDL_SetPalette(pUpper, SDL_LOGPAL | SDL_PHYSPAL, VIDEO_GetPalette(), 0, 256); SDL_SetPalette(pLower, SDL_LOGPAL | SDL_PHYSPAL, VIDEO_GetPalette(), 0, 256); #endif } UTIL_Delay(50); } gpGlobals->wScreenWave = 0; SDL_FreeSurface(pUpper); SDL_FreeSurface(pLower); free(buf); free(bufGirl); } VOID PAL_EndingScreen( VOID ) { RIX_Play(0x1a, TRUE, 0); PAL_RNGPlay(gpGlobals->iCurPlayingRNG, 110, 150, 7); PAL_RNGPlay(gpGlobals->iCurPlayingRNG, 151, 999, 9); PAL_FadeOut(2); RIX_Play(0x19, TRUE, 0); PAL_ShowFBP(75, 0); PAL_FadeIn(5, FALSE, 1); PAL_ScrollFBP(74, 0xf, TRUE); PAL_FadeOut(1); SDL_FillRect(gpScreen, NULL, 0); gpGlobals->wNumPalette = 4; gpGlobals->fNeedToFadeIn = TRUE; PAL_EndingAnimation(); RIX_Play(0, FALSE, 2); PAL_ColorFade(7, 15, FALSE); if (!SOUND_PlayCDA(2)) { RIX_Play(0x11, TRUE, 0); } SDL_FillRect(gpScreen, NULL, 0); PAL_SetPalette(0, FALSE); PAL_RNGPlay(0xb, 0, 999, 7); PAL_FadeOut(2); SDL_FillRect(gpScreen, NULL, 0); gpGlobals->wNumPalette = 8; gpGlobals->fNeedToFadeIn = TRUE; PAL_RNGPlay(10, 0, 999, 6); PAL_EndingSetEffectSprite(0); PAL_ShowFBP(77, 10); VIDEO_BackupScreen(); PAL_EndingSetEffectSprite(0x27b); PAL_ShowFBP(76, 7); PAL_SetPalette(5, FALSE); PAL_ShowFBP(73, 7); PAL_ScrollFBP(72, 0xf, TRUE); PAL_ShowFBP(71, 7); PAL_ShowFBP(68, 7); PAL_EndingSetEffectSprite(0); PAL_ShowFBP(68, 6); PAL_WaitForKey(0); RIX_Play(0, FALSE, 1); UTIL_Delay(500); if (!SOUND_PlayCDA(13)) { RIX_Play(9, TRUE, 0); } PAL_ScrollFBP(67, 0xf, TRUE); PAL_ScrollFBP(66, 0xf, TRUE); PAL_ScrollFBP(65, 0xf, TRUE); PAL_ScrollFBP(64, 0xf, TRUE); PAL_ScrollFBP(63, 0xf, TRUE); PAL_ScrollFBP(62, 0xf, TRUE); PAL_ScrollFBP(61, 0xf, TRUE); PAL_ScrollFBP(60, 0xf, TRUE); PAL_ScrollFBP(59, 0xf, TRUE); RIX_Play(0, FALSE, 6); PAL_FadeOut(3); }