From c3bbc4b2794bb8afc1dd3adcd7015aa41231a02a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2008 11:26:29 +0000 Subject: Added Smacker support for the introduction and ending videos of FTA2 svn-id: r35482 --- engines/saga/introproc_fta2.cpp | 168 ++++++++++++++++++++++++++++++++++++---- engines/saga/scene.h | 10 +++ 2 files changed, 165 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/saga/introproc_fta2.cpp b/engines/saga/introproc_fta2.cpp index 2b7172594e..18d82be60f 100644 --- a/engines/saga/introproc_fta2.cpp +++ b/engines/saga/introproc_fta2.cpp @@ -27,43 +27,185 @@ #include "saga/saga.h" #include "saga/scene.h" +#include "saga/gfx.h" #include "sound/mixer.h" +#include "graphics/surface.h" #include "graphics/video/smk_player.h" +#include "common/events.h" +#include "common/system.h" + namespace Saga { class MoviePlayerSMK : Graphics::SMKPlayer { protected: virtual void setPalette(byte *pal); public: - MoviePlayerSMK(Audio::Mixer *mixer); - virtual ~MoviePlayerSMK(void); + MoviePlayerSMK(SagaEngine *vm): _vm(vm), SMKPlayer(vm->_mixer) { + _frameSkipped = 0; + _ticks = 0; + } + ~MoviePlayerSMK(void) { closeFile(); } + + bool load(const char *filename) { + _skipVideo = false; + return loadFile(filename); + } + void playVideo(); + void stopVideo() { closeFile(); } +private: + bool processFrame(); + PalEntry _smkPalette[256]; + uint32 _ticks; + uint16 _frameSkipped; + bool _skipVideo; + SagaEngine *_vm; + Common::Event _event; }; -MoviePlayerSMK::MoviePlayerSMK(Audio::Mixer *mixer) - : SMKPlayer(mixer) { - debug(0, "Creating SMK cutscene player"); +void MoviePlayerSMK::setPalette(byte *pal) { + for (int i = 0; i < 256; i++) { + _smkPalette[i].red = *pal++; + _smkPalette[i].green = *pal++; + _smkPalette[i].blue = *pal++; + } + + _vm->_gfx->setPalette(_smkPalette, true); } -MoviePlayerSMK::~MoviePlayerSMK(void) { - closeFile(); +void MoviePlayerSMK::playVideo() { + while (getCurFrame() < getFrameCount() && !_skipVideo && !_vm->shouldQuit()) { + Common::EventManager *eventMan = _vm->_system->getEventManager(); + // process events, and skip video if esc is pressed + while (eventMan->pollEvent(_event)) { + switch (_event.type) { + case Common::EVENT_KEYDOWN: + if (_event.kbd.keycode == Common::KEYCODE_ESCAPE) + _skipVideo = true; + break; + case Common::EVENT_RTL: + case Common::EVENT_QUIT: + _skipVideo = true; + break; + default: + break; + } + } + decodeNextFrame(); + if (processFrame()) + _vm->_system->updateScreen(); + } } -void MoviePlayerSMK::setPalette(byte *pal) { - // TODO +bool MoviePlayerSMK::processFrame() { + Graphics::Surface *screen = _vm->_system->lockScreen(); + copyFrameToBuffer((byte *)screen->pixels, + (_vm->getDisplayInfo().logicalWidth - getWidth()) / 2, + (_vm->getDisplayInfo().logicalHeight - getHeight()) / 2, + _vm->getDisplayInfo().logicalWidth); + _vm->_system->unlockScreen(); + + if (!getAudioLag() || getFrameWaitTime() || _frameSkipped > getFrameRate()) { + if (_frameSkipped > getFrameRate()) { + warning("force frame %i redraw", getCurFrame()); + _frameSkipped = 0; + } + + if (getAudioLag() > 0) { + while (getAudioLag() > 0) { + _vm->_system->delayMillis(10); + } + // In case the background sound ends prematurely, update + // _ticks so that we can still fall back on the no-sound + // sync case for the subsequent frames. + _ticks = _vm->_system->getMillis(); + } else { + _ticks += getFrameDelay(); + //while (_vm->_system->getMillis() < _ticks) // FIXME + _vm->_system->delayMillis(10); + } + + return true; + } + + warning("dropped frame %i", getCurFrame()); + _frameSkipped++; + return false; } int Scene::FTA2StartProc() { - // STUB + MoviePlayerSMK *smkPlayer = new MoviePlayerSMK(_vm); + + _vm->_gfx->showCursor(false); + + // Show Ignite logo + if (smkPlayer->load("trimark.smk")) { + debug(0, "Playing video trimark.smk"); + smkPlayer->playVideo(); + smkPlayer->stopVideo(); + } else { + warning("Failed to load video file trimark.smk"); + } - MoviePlayerSMK *smkPlayer = new MoviePlayerSMK(_vm->_mixer); - + // Play introduction + if (smkPlayer->load("intro.smk")) { + debug(0, "Playing video intro.smk"); + smkPlayer->playVideo(); + smkPlayer->stopVideo(); + } else { + warning("Failed to load video file intro.smk"); + } + + // Cleanup delete smkPlayer; + // HACK: Forcibly quit here _vm->quitGame(); - return !SUCCESS; + return SUCCESS; +} + +int Scene::FTA2EndProc(FTA2Endings whichEnding) { + char videoName[20]; + + switch (whichEnding) { + case kFta2BadEndingLaw: + strcpy(videoName, "end_1.smk"); + break; + case kFta2BadEndingChaos: + strcpy(videoName, "end_2.smk"); + break; + case kFta2GoodEnding1: + strcpy(videoName, "end_3a.smk"); + break; + case kFta2GoodEnding2: + strcpy(videoName, "end_3b.smk"); + break; + case kFta2BadEndingDeath: + strcpy(videoName, "end_4.smk"); + break; + default: + error("Unknown FTA2 ending"); + } + + MoviePlayerSMK *smkPlayer = new MoviePlayerSMK(_vm); + + _vm->_gfx->showCursor(false); + + // Play introduction + if (smkPlayer->load(videoName)) { + debug(0, "Playing video %s", videoName); + smkPlayer->playVideo(); + smkPlayer->stopVideo(); + } else { + warning("Failed to load video file %s", videoName); + } + + // Cleanup + delete smkPlayer; + + return SUCCESS; } } // End of namespace Saga diff --git a/engines/saga/scene.h b/engines/saga/scene.h index 96f88c3789..10ec6f4b6f 100644 --- a/engines/saga/scene.h +++ b/engines/saga/scene.h @@ -62,6 +62,15 @@ enum SceneFlags { kSceneFlagShowCursor = 2 }; +// FTA2 possible endings +enum FTA2Endings { + kFta2BadEndingLaw = 0, + kFta2BadEndingChaos = 1, + kFta2GoodEnding1 = 2, + kFta2GoodEnding2 = 3, + kFta2BadEndingDeath = 4 +}; + struct BGInfo { Rect bounds; byte *buffer; @@ -412,6 +421,7 @@ class Scene { int IHNMStartProc(); int IHNMCreditsProc(); int FTA2StartProc(); + int FTA2EndProc(FTA2Endings whichEnding); void IHNMLoadCutaways(); bool checkKey(); -- cgit v1.2.3