123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */
- //
- // Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
- // All rights reserved.
- //
- // Portions based on PalLibrary by Lou Yihua <louyihua@21cn.com>.
- // Copyright (c) 2006-2007, Lou Yihua.
- //
- // 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 <http://www.gnu.org/licenses/>.
- //
- #include "main.h"
- static INT
- PAL_RNGReadFrame(
- LPBYTE lpBuffer,
- UINT uiBufferSize,
- UINT uiRngNum,
- UINT uiFrameNum,
- FILE *fpRngMKF
- )
- /*++
- Purpose:
- Read a frame from a RNG animation.
- Parameters:
- [OUT] lpBuffer - pointer to the destination buffer.
- [IN] uiBufferSize - size of the destination buffer.
- [IN] uiRngNum - the number of the RNG animation in the MKF archive.
- [IN] uiFrameNum - frame number in the RNG animation.
- [IN] fpRngMKF - pointer to the fopen'ed MKF file.
- Return value:
- Integer value which indicates the size of the chunk.
- -1 if there are error in parameters.
- -2 if buffer size is not enough.
- --*/
- {
- UINT uiOffset = 0;
- UINT uiSubOffset = 0;
- UINT uiNextOffset = 0;
- UINT uiChunkCount = 0;
- INT iChunkLen = 0;
- if (lpBuffer == NULL || fpRngMKF == NULL || uiBufferSize == 0)
- {
- return -1;
- }
- //
- // Get the total number of chunks.
- //
- uiChunkCount = PAL_MKFGetChunkCount(fpRngMKF);
- if (uiRngNum >= uiChunkCount)
- {
- return -1;
- }
- //
- // Get the offset of the chunk.
- //
- fseek(fpRngMKF, 4 * uiRngNum, SEEK_SET);
- fread(&uiOffset, sizeof(UINT), 1, fpRngMKF);
- fread(&uiNextOffset, sizeof(UINT), 1, fpRngMKF);
- uiOffset = SDL_SwapLE32(uiOffset);
- uiNextOffset = SDL_SwapLE32(uiNextOffset);
- //
- // Get the length of the chunk.
- //
- iChunkLen = uiNextOffset - uiOffset;
- if (iChunkLen != 0)
- {
- fseek(fpRngMKF, uiOffset, SEEK_SET);
- }
- else
- {
- return -1;
- }
- //
- // Get the number of sub chunks.
- //
- fread(&uiChunkCount, sizeof(UINT), 1, fpRngMKF);
- uiChunkCount = (SDL_SwapLE32(uiChunkCount) - 4) / 4;
- if (uiFrameNum >= uiChunkCount)
- {
- return -1;
- }
- //
- // Get the offset of the sub chunk.
- //
- fseek(fpRngMKF, uiOffset + 4 * uiFrameNum, SEEK_SET);
- fread(&uiSubOffset, sizeof(UINT), 1, fpRngMKF);
- fread(&uiNextOffset, sizeof(UINT), 1, fpRngMKF);
- uiSubOffset = SDL_SwapLE32(uiSubOffset);
- uiNextOffset = SDL_SwapLE32(uiNextOffset);
- //
- // Get the length of the sub chunk.
- //
- iChunkLen = uiNextOffset - uiSubOffset;
- if ((UINT)iChunkLen > uiBufferSize)
- {
- return -2;
- }
- if (iChunkLen != 0)
- {
- fseek(fpRngMKF, uiOffset + uiSubOffset, SEEK_SET);
- fread(lpBuffer, iChunkLen, 1, fpRngMKF);
- }
- else
- {
- return -1;
- }
- return iChunkLen;
- }
- static INT
- PAL_RNGBlitToSurface(
- INT iNumRNG,
- INT iNumFrame,
- SDL_Surface *lpDstSurface,
- FILE *fpRngMKF
- )
- /*++
- Purpose:
- Blit one frame in an RNG animation to an SDL surface.
- The surface should contain the last frame of the RNG, or blank if it's the first
- frame.
- NOTE: Assume the surface is already locked, and the surface is a 320x200 8-bit one.
- Parameters:
- [IN] iNumRNG - The number of the animation in the MKF archive.
- [IN] iNumFrame - The number of the frame in the animation.
- [OUT] lpDstSurface - pointer to the destination SDL surface.
- [IN] fpRngMKF - Pointer to the fopen'ed rng.mkf file.
- Return value:
- 0 = success, -1 = error.
- --*/
- {
- INT ptr = 0;
- INT dst_ptr = 0;
- BYTE data = 0;
- WORD wdata = 0;
- INT x, y, i, n;
- LPBYTE rng = NULL;
- LPBYTE buf = NULL;
- //
- // Check for invalid parameters.
- //
- if (lpDstSurface == NULL || iNumRNG < 0 || iNumFrame < 0)
- {
- return -1;
- }
- buf = (LPBYTE)calloc(1, 65000);
- if (buf == NULL)
- {
- return -1;
- }
- //
- // Read the frame.
- //
- if (PAL_RNGReadFrame(buf, 65000, iNumRNG, iNumFrame, fpRngMKF) < 0)
- {
- free(buf);
- return -1;
- }
- //
- // Decompress the frame.
- //
- rng = (LPBYTE)calloc(1, 65000);
- if (rng == NULL)
- {
- free(buf);
- return -1;
- }
- Decompress(buf, rng, 65000);
- free(buf);
- //
- // Draw the frame to the surface.
- // FIXME: Dirty and ineffective code, needs to be cleaned up
- //
- while (TRUE)
- {
- data = rng[ptr++];
- switch (data)
- {
- case 0x00:
- case 0x13:
- //
- // End
- //
- goto end;
- case 0x02:
- dst_ptr += 2;
- break;
- case 0x03:
- data = rng[ptr++];
- dst_ptr += (data + 1) * 2;
- break;
- case 0x04:
- wdata = rng[ptr] | (rng[ptr + 1] << 8);
- ptr += 2;
- dst_ptr += ((unsigned int)wdata + 1) * 2;
- break;
- case 0x0a:
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- case 0x09:
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- case 0x08:
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- case 0x07:
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- case 0x06:
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- break;
- case 0x0b:
- data = *(rng + ptr++);
- for (i = 0; i <= data; i++)
- {
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- }
- break;
- case 0x0c:
- wdata = rng[ptr] | (rng[ptr + 1] << 8);
- ptr += 2;
- for (i = 0; i <= wdata; i++)
- {
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr++];
- dst_ptr += 2;
- }
- break;
- case 0x0d:
- case 0x0e:
- case 0x0f:
- case 0x10:
- for (i = 0; i < data - (0x0d - 2); i++)
- {
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr + 1];
- dst_ptr += 2;
- }
- ptr += 2;
- break;
- case 0x11:
- data = *(rng + ptr++);
- for (i = 0; i <= data; i++)
- {
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr + 1];
- dst_ptr += 2;
- }
- ptr += 2;
- break;
- case 0x12:
- n = (rng[ptr] | (rng[ptr + 1] << 8)) + 1;
- ptr += 2;
- for (i = 0; i < n; i++)
- {
- x = dst_ptr % 320;
- y = dst_ptr / 320;
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr];
- if (++x >= 320)
- {
- x = 0;
- ++y;
- }
- ((LPBYTE)(lpDstSurface->pixels))[y * lpDstSurface->pitch + x] = rng[ptr + 1];
- dst_ptr += 2;
- }
- ptr += 2;
- break;
- }
- }
- end:
- free(rng);
- return 0;
- }
- VOID
- PAL_RNGPlay(
- INT iNumRNG,
- INT iStartFrame,
- INT iEndFrame,
- INT iSpeed
- )
- /*++
- Purpose:
- Play a RNG movie.
- Parameters:
- [IN] iNumRNG - number of the RNG movie.
- [IN] iStartFrame - start frame number.
- [IN] iEndFrame - end frame number.
- [IN] iSpeed - speed of playing.
- Return value:
- None.
- --*/
- {
- UINT iTime;
- int iDelay = 800 / (iSpeed == 0 ? 16 : iSpeed);
- FILE *fp;
- fp = UTIL_OpenRequiredFile("rng.mkf");
- for (; iStartFrame <= iEndFrame; iStartFrame++)
- {
- iTime = SDL_GetTicks() + iDelay;
- if (PAL_RNGBlitToSurface(iNumRNG, iStartFrame, gpScreen, fp) == -1)
- {
- //
- // Failed to get the frame, don't go further
- //
- fclose(fp);
- return;
- }
- //
- // Update the screen
- //
- VIDEO_UpdateScreen(NULL);
- //
- // Fade in the screen if needed
- //
- if (gpGlobals->fNeedToFadeIn)
- {
- PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1);
- gpGlobals->fNeedToFadeIn = FALSE;
- }
- //
- // Delay for a while
- //
- PAL_ProcessEvent();
- while (SDL_GetTicks() <= iTime)
- {
- PAL_ProcessEvent();
- SDL_Delay(1);
- }
- }
- fclose(fp);
- }
|