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. --*/ { int iDelay = 800 / (iSpeed == 0 ? 16 : iSpeed); uint8_t *rng = (uint8_t *)malloc(65000); uint8_t *buf = (uint8_t *)malloc(65000); FILE *fp = UTIL_OpenRequiredFile("rng.mkf"); for (; rng && buf && iStartFrame <= iEndFrame; iStartFrame++) { uint32_t iTime = SDL_GetTicks() + iDelay; // // Read, decompress and render the frame // if (PAL_RNGReadFrame(buf, 65000, iNumRNG, iStartFrame, fp) < 0 || PAL_RNGBlitToSurface(rng, Decompress(buf, rng, 65000), gpScreen) == -1) { // // Failed to get the frame, don't go further // break; } // // 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_DelayUntil(iTime); } fclose(fp); free(rng); free(buf); }