mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 09:49:11 +00:00
431 lines
10 KiB
C++
431 lines
10 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "twine/flamovies.h"
|
|
#include "common/file.h"
|
|
#include "common/system.h"
|
|
#include "twine/grid.h"
|
|
#include "twine/input.h"
|
|
#include "twine/music.h"
|
|
#include "twine/screens.h"
|
|
#include "twine/sound.h"
|
|
#include "twine/twine.h"
|
|
|
|
namespace TwinE {
|
|
|
|
/** FLA movie extension */
|
|
#define FLA_EXT ".fla"
|
|
|
|
void FlaMovies::drawKeyFrame(uint8 *ptr, int32 width, int32 height) {
|
|
uint8 *destPtr = (uint8 *)flaBuffer;
|
|
uint8 *startOfLine = destPtr;
|
|
|
|
do {
|
|
int8 flag1 = *(ptr++);
|
|
|
|
for (int8 a = 0; a < flag1; a++) {
|
|
int8 flag2 = *(ptr++);
|
|
|
|
if (flag2 < 0) {
|
|
flag2 = -flag2;
|
|
for (int8 b = 0; b < flag2; b++) {
|
|
*(destPtr++) = *(ptr++);
|
|
}
|
|
} else {
|
|
char colorFill = *(ptr++);
|
|
|
|
for (int8 b = 0; b < flag2; b++) {
|
|
*(destPtr++) = colorFill;
|
|
}
|
|
}
|
|
}
|
|
|
|
startOfLine = destPtr = startOfLine + width;
|
|
} while (--height);
|
|
}
|
|
|
|
void FlaMovies::drawDeltaFrame(uint8 *ptr, int32 width) {
|
|
int32 a, b;
|
|
uint16 skip;
|
|
uint8 *destPtr;
|
|
uint8 *startOfLine;
|
|
int32 height;
|
|
|
|
int8 flag1;
|
|
int8 flag2;
|
|
|
|
skip = *((uint16 *)ptr);
|
|
ptr += 2;
|
|
skip *= width;
|
|
startOfLine = destPtr = (uint8 *)flaBuffer + skip;
|
|
height = *((int16 *)ptr);
|
|
ptr += 2;
|
|
|
|
do {
|
|
flag1 = *(ptr++);
|
|
|
|
for (a = 0; a < flag1; a++) {
|
|
destPtr += (unsigned char)*(ptr++);
|
|
flag2 = *(ptr++);
|
|
|
|
if (flag2 > 0) {
|
|
for (b = 0; b < flag2; b++) {
|
|
*(destPtr++) = *(ptr++);
|
|
}
|
|
} else {
|
|
char colorFill;
|
|
flag2 = -flag2;
|
|
|
|
colorFill = *(ptr++);
|
|
|
|
for (b = 0; b < flag2; b++) {
|
|
*(destPtr++) = colorFill;
|
|
}
|
|
}
|
|
}
|
|
|
|
startOfLine = destPtr = startOfLine + width;
|
|
} while (--height);
|
|
}
|
|
|
|
void FlaMovies::scaleFla2x() {
|
|
int32 i, j;
|
|
uint8 *source = (uint8 *)flaBuffer;
|
|
uint8 *dest = (uint8 *)_engine->workVideoBuffer.getPixels();
|
|
|
|
if (_engine->cfgfile.Movie == CONF_MOVIE_FLAWIDE) {
|
|
for (i = 0; i < SCREEN_WIDTH / SCALE * 40; i++) {
|
|
*(dest++) = 0x00;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < FLASCREEN_HEIGHT; i++) {
|
|
for (j = 0; j < FLASCREEN_WIDTH; j++) {
|
|
*(dest++) = *(source);
|
|
*(dest++) = *(source++);
|
|
}
|
|
if (_engine->cfgfile.Movie == CONF_MOVIE_FLAWIDE) { // include wide bars
|
|
memcpy(dest, dest - SCREEN_WIDTH / SCALE, FLASCREEN_WIDTH * 2);
|
|
dest += FLASCREEN_WIDTH * 2;
|
|
} else { // stretch the movie like original game.
|
|
if (i % (2)) {
|
|
memcpy(dest, dest - SCREEN_WIDTH / SCALE, FLASCREEN_WIDTH * 2);
|
|
dest += FLASCREEN_WIDTH * 2;
|
|
}
|
|
if (i % 10) {
|
|
memcpy(dest, dest - SCREEN_WIDTH / SCALE, FLASCREEN_WIDTH * 2);
|
|
dest += FLASCREEN_WIDTH * 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_engine->cfgfile.Movie == CONF_MOVIE_FLAWIDE) {
|
|
for (i = 0; i < SCREEN_WIDTH / SCALE * 40; i++) {
|
|
*(dest++) = 0x00;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FlaMovies::processFrame() {
|
|
FLASampleStruct sample;
|
|
uint32 opcodeBlockSize;
|
|
uint8 opcode;
|
|
int32 aux = 0;
|
|
|
|
file.read(&frameData.videoSize, 1);
|
|
file.read(&frameData.dummy, 1);
|
|
file.read(&frameData.frameVar0, 4);
|
|
if (frameData.frameVar0 > _engine->workVideoBuffer.w * _engine->workVideoBuffer.h) {
|
|
warning("Skipping video frame - it would exceed the screen buffer: %i", frameData.frameVar0);
|
|
return;
|
|
}
|
|
|
|
uint8 *ptr = (uint8*)_engine->workVideoBuffer.getPixels();
|
|
file.read(ptr, frameData.frameVar0);
|
|
|
|
if ((int32)frameData.videoSize <= 0)
|
|
return;
|
|
|
|
do {
|
|
opcode = *((uint8 *)ptr);
|
|
ptr += 2;
|
|
opcodeBlockSize = *((uint16 *)ptr);
|
|
ptr += 2;
|
|
|
|
switch (opcode - 1) {
|
|
case kLoadPalette: {
|
|
int16 numOfColor = *((int16 *)ptr);
|
|
int16 startColor = *((int16 *)(ptr + 2));
|
|
memcpy((_engine->_screens->palette + (startColor * 3)), (ptr + 4), numOfColor * 3);
|
|
break;
|
|
}
|
|
case kFade: {
|
|
// FLA movies don't use cross fade
|
|
// fade out tricky
|
|
if (_fadeOut != 1) {
|
|
_engine->_screens->convertPalToRGBA(_engine->_screens->palette, _engine->_screens->paletteRGBACustom);
|
|
_engine->_screens->fadeToBlack(_engine->_screens->paletteRGBACustom);
|
|
_fadeOut = 1;
|
|
}
|
|
break;
|
|
}
|
|
case kPlaySample: {
|
|
memcpy(&sample, ptr, sizeof(FLASampleStruct));
|
|
_engine->_sound->playFlaSample(sample.sampleNum, sample.freq, sample.repeat, sample.x, sample.y);
|
|
break;
|
|
}
|
|
case kStopSample: {
|
|
_engine->_sound->stopSample(sample.sampleNum);
|
|
break;
|
|
}
|
|
case kDeltaFrame: {
|
|
drawDeltaFrame(ptr, FLASCREEN_WIDTH);
|
|
if (_fadeOut == 1)
|
|
fadeOutFrames++;
|
|
break;
|
|
}
|
|
case kKeyFrame: {
|
|
drawKeyFrame(ptr, FLASCREEN_WIDTH, FLASCREEN_HEIGHT);
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
aux++;
|
|
ptr += opcodeBlockSize;
|
|
|
|
} while (aux < (int32)frameData.videoSize);
|
|
//free(workVideoBufferCopy);
|
|
}
|
|
|
|
/** Play FLA PCX Screens
|
|
@param flaName FLA movie name */
|
|
static void fla_pcxList(const char *flaName) {
|
|
// TODO if is using FLA PCX than show the images instead
|
|
}
|
|
|
|
FlaMovies::FlaMovies(TwinEEngine *engine) : _engine(engine) {}
|
|
|
|
void FlaMovies::playFlaMovie(const char *flaName) {
|
|
_engine->_sound->stopSamples();
|
|
|
|
// Play FLA PCX instead of movies
|
|
if (_engine->cfgfile.Movie == CONF_MOVIE_FLAPCX) {
|
|
fla_pcxList(flaName);
|
|
return;
|
|
}
|
|
|
|
_engine->_music->stopMusic();
|
|
|
|
Common::String fileNamePath = Common::String::format("%s", flaName);
|
|
const size_t n = fileNamePath.findLastOf(".");
|
|
if (n != Common::String::npos) {
|
|
fileNamePath.erase(n);
|
|
}
|
|
fileNamePath += FLA_EXT;
|
|
|
|
_fadeOut = -1;
|
|
fadeOutFrames = 0;
|
|
|
|
file.close();
|
|
if (!file.open(FLA_DIR + fileNamePath)) {
|
|
if (!file.open(fileNamePath)) {
|
|
warning("Failed to open fla movie '%s'", fileNamePath.c_str());
|
|
return;
|
|
}
|
|
}
|
|
|
|
file.read(&flaHeaderData.version, 6);
|
|
flaHeaderData.numOfFrames = file.readUint32LE();
|
|
flaHeaderData.speed = file.readByte();
|
|
flaHeaderData.var1 = file.readByte();
|
|
flaHeaderData.xsize = file.readUint16LE();
|
|
flaHeaderData.ysize = file.readUint16LE();
|
|
|
|
samplesInFla = file.readUint16LE();
|
|
file.skip(2);
|
|
|
|
for (int32 i = 0; i < samplesInFla; i++) {
|
|
flaSampleTable[i] = file.readSint16LE();
|
|
file.skip(2);
|
|
}
|
|
|
|
if (!strcmp((const char *)flaHeaderData.version, "V1.3")) {
|
|
int32 currentFrame = 0;
|
|
|
|
debug("Play fla: %s", flaName);
|
|
|
|
ScopedKeyMap scopedKeyMap(_engine, cutsceneKeyMapId);
|
|
|
|
do {
|
|
_engine->readKeys();
|
|
if (_engine->shouldQuit()) {
|
|
break;
|
|
}
|
|
if (currentFrame == flaHeaderData.numOfFrames) {
|
|
break;
|
|
}
|
|
processFrame();
|
|
scaleFla2x();
|
|
_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
|
|
|
|
// Only blit to screen if isn't a fade
|
|
if (_fadeOut == -1) {
|
|
_engine->_screens->convertPalToRGBA(_engine->_screens->palette, _engine->_screens->paletteRGBACustom);
|
|
if (!currentFrame) // fade in the first frame
|
|
_engine->_screens->fadeIn(_engine->_screens->paletteRGBACustom);
|
|
else
|
|
_engine->setPalette(_engine->_screens->paletteRGBACustom);
|
|
}
|
|
|
|
// TRICKY: fade in tricky
|
|
if (fadeOutFrames >= 2) {
|
|
_engine->flip();
|
|
_engine->_screens->convertPalToRGBA(_engine->_screens->palette, _engine->_screens->paletteRGBACustom);
|
|
_engine->_screens->fadeToPal(_engine->_screens->paletteRGBACustom);
|
|
_fadeOut = -1;
|
|
fadeOutFrames = 0;
|
|
}
|
|
|
|
currentFrame++;
|
|
|
|
_engine->_system->delayMillis(1000 / flaHeaderData.speed + 1);
|
|
} while (!_engine->_input->isActionActive(TwinEActionType::CutsceneAbort));
|
|
}
|
|
|
|
if (_engine->cfgfile.CrossFade) {
|
|
_engine->crossFade(_engine->frontVideoBuffer, _engine->_screens->paletteRGBACustom);
|
|
} else {
|
|
_engine->_screens->fadeToBlack(_engine->_screens->paletteRGBACustom);
|
|
}
|
|
|
|
_engine->_sound->stopSamples();
|
|
}
|
|
|
|
/*
|
|
void fla_pcxList(char *flaName)
|
|
{
|
|
// check if FLAPCX file exist
|
|
// if(!checkIfFileExist("FLA_PCX.HQR") || !checkIfFileExist("FLA_GIF.HQR")){
|
|
// printf("FLA_PCX file doesn't exist!");
|
|
//return;
|
|
//}
|
|
|
|
// TODO: done this with the HQR 23th entry (movies informations)
|
|
if(!strcmp(flaName,"INTROD"))
|
|
{
|
|
prepareFlaPCX(1);
|
|
WaitTime(5000);
|
|
prepareFlaPCX(2);
|
|
WaitTime(5000);
|
|
prepareFlaPCX(3);
|
|
WaitTime(5000);
|
|
prepareFlaPCX(4);
|
|
WaitTime(5000);
|
|
prepareFlaPCX(5);
|
|
WaitTime(5000);
|
|
|
|
}
|
|
else if(!strcmp(flaName,"BAFFE") || !strcmp(flaName,"BAFFE2") || !strcmp(flaName,"BAFFE3") || !strcmp(flaName,"BAFFE4"))
|
|
{
|
|
prepareFlaPCX(6);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"bateau") || !strcmp(flaName,"bateau2"))
|
|
{
|
|
prepareFlaPCX(7);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"flute2"))
|
|
{
|
|
prepareFlaPCX(8);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"navette"))
|
|
{
|
|
prepareFlaPCX(15);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"templebu"))
|
|
{
|
|
prepareFlaPCX(12);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"glass2"))
|
|
{
|
|
prepareFlaPCX(8);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"surf"))
|
|
{
|
|
prepareFlaPCX(9);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"verser") || !strcmp(flaName,"verser2"))
|
|
{
|
|
prepareFlaPCX(10);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"capture"))
|
|
{
|
|
prepareFlaPCX(14);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"neige2"))
|
|
{
|
|
prepareFlaPCX(11);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"sendel"))
|
|
{
|
|
prepareFlaPCX(14);
|
|
WaitTime(5000);
|
|
}
|
|
else if(!strcmp(flaName,"sendel2"))
|
|
{
|
|
prepareFlaPCX(17);
|
|
WaitTime(5000);
|
|
}
|
|
}
|
|
|
|
void prepareFlaPCX(int index)
|
|
{
|
|
int i;
|
|
SDL_Surface *image;
|
|
|
|
// TODO: Done this without SDL_Image Library
|
|
if(checkIfFileExist("FLA_PCX.HQR"))
|
|
image = IMG_LoadPCX_RW(SDL_RWFromMem(HQR_Get(HQR_FlaPCX,index), Size_HQR("FLA_PCX.HQR", index))); // rwop
|
|
else if(checkIfFileExist("FLA_GIF.HQR"))
|
|
image = IMG_LoadGIF_RW(SDL_RWFromMem(HQR_Get(HQR_FlaGIF,index), Size_HQR("fla_gif.hqr", index))); // rwop
|
|
|
|
if(!image) {
|
|
printf("Can't load FLA PCX: %s\n", IMG_GetError());
|
|
}
|
|
|
|
osystem_FlaPCXCrossFade(image);
|
|
}*/
|
|
|
|
} // namespace TwinE
|