From ca387f158537dad55d11725247c8224678108e2f Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 26 Aug 2006 11:34:35 +0000 Subject: Added support for DXA cutscenes. Still needs a bit of cleanup, and the DCA player does not support the (unreleased) multi-lingual cutscene pack, since I don't have one to test with. It needs to be cleaned up a bit, but the next step will be to clean up the MPEG decoder first. svn-id: r23753 --- engines/sword1/animation.cpp | 520 +++++++++++++++++++++++++++++++------------ engines/sword1/animation.h | 94 ++++++-- engines/sword1/logic.cpp | 8 +- engines/sword1/screen.cpp | 8 + engines/sword1/screen.h | 1 + 5 files changed, 465 insertions(+), 166 deletions(-) diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index dc0a4e8f8d..9c02c431c3 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -28,83 +28,132 @@ #include "sound/vorbis.h" #include "common/config-manager.h" +#include "common/endian.h" #include "common/str.h" #include "common/system.h" namespace Sword1 { -AnimationState::AnimationState(Screen *scr, Audio::Mixer *snd, OSystem *sys) - : BaseAnimationState(snd, sys, 640, 400), _scr(scr) { -} - -AnimationState::~AnimationState() { -} +static const char *sequenceList[20] = { + "ferrari", // 0 CD2 ferrari running down fitz in sc19 + "ladder", // 1 CD2 george walking down ladder to dig sc24->sc$ + "steps", // 2 CD2 george walking down steps sc23->sc24 + "sewer", // 3 CD1 george entering sewer sc2->sc6 + "intro", // 4 CD1 intro sequence ->sc1 + "river", // 5 CD1 george being thrown into river by flap & g$ + "truck", // 6 CD2 truck arriving at bull's head sc45->sc53/4 + "grave", // 7 BOTH george's grave in scotland, from sc73 + from sc38 $ + "montfcon", // 8 CD2 monfaucon clue in ireland dig, sc25 + "tapestry", // 9 CD2 tapestry room beyond spain well, sc61 + "ireland", // 10 CD2 ireland establishing shot europe_map->sc19 + "finale", // 11 CD2 grand finale at very end, from sc73 + "history", // 12 CD1 George's history lesson from Nico, in sc10 + "spanish", // 13 CD2 establishing shot for 1st visit to Spain, europe_m$ + "well", // 14 CD2 first time being lowered down well in Spai$ + "candle", // 15 CD2 Candle burning down in Spain mausoleum sc59 + "geodrop", // 16 CD2 from sc54, George jumping down onto truck + "vulture", // 17 CD2 from sc54, vultures circling George's dead body + "enddemo", // 18 --- for end of single CD demo + "credits", // 19 CD2 credits, to follow "finale" sequence +}; +/////////////////////////////////////////////////////////////////////////////// +// Basic movie player +/////////////////////////////////////////////////////////////////////////////// -#ifdef BACKEND_8BIT -void AnimationState::setPalette(byte *pal) { - _sys->setPalette(pal, 0, 256); +MoviePlayer::MoviePlayer(Screen *scr, Audio::Mixer *snd, OSystem *sys) + : _scr(scr), _snd(snd), _sys(sys) { + _bgSoundStream = NULL; + _ticks = 0; + _frameBuffer = NULL; + _currentFrame = 0; + _forceFrame = false; + _framesSkipped = 0; } -#endif - -void AnimationState::drawYUV(int width, int height, byte *const *dat) { - _frameWidth = width; - _frameHeight = height; -#ifdef BACKEND_8BIT - _scr->plotYUV(_lut, width, height, dat); -#else - plotYUV(width, height, dat); -#endif +MoviePlayer::~MoviePlayer(void) { } -OverlayColor *AnimationState::giveRgbBuffer(void) { -#ifdef BACKEND_8BIT - return NULL; -#else - return _overlay; -#endif +void MoviePlayer::updatePalette(byte *pal, bool packed) { + byte palette[4 * 256]; + byte *p = palette; + for (int i = 0; i < 256; i++) { + *p++ = *pal++; + *p++ = *pal++; + *p++ = *pal++; + if (!packed) + *p++ = *pal++; + else + *p++ = 0; + } + _sys->setPalette(palette, 0, 256); + _forceFrame = true; } -bool AnimationState::soundFinished(void) { - return !_snd->isSoundHandleActive(_bgSound); +void MoviePlayer::handleScreenChanged(void) { } -Audio::AudioStream *AnimationState::createAudioStream(const char *name, void *arg) { - if (arg) - return (Audio::AudioStream*)arg; - else - return Audio::AudioStream::openStreamFile(name); +bool MoviePlayer::initOverlays(uint32 id) { + return true; } -MoviePlayer::MoviePlayer(Screen *scr, Audio::Mixer *snd, OSystem *sys) - : _scr(scr), _snd(snd), _sys(sys) { - for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++) - _logoOvls[cnt] = NULL; - _introPal = NULL; +bool MoviePlayer::checkSkipFrame(void) { + if (_forceFrame) { + _forceFrame = false; + return false; + } + if (_framesSkipped > 10) { + warning("Forced frame %d to be displayed", _currentFrame); + _framesSkipped = 0; + return false; + } + if (_bgSoundStream) { + if ((_snd->getSoundElapsedTime(_bgSoundHandle) * 12) / 1000 < _currentFrame + 1) + return false; + } else { + if (_sys->getMillis() <= _ticks) + return false; + } + _framesSkipped++; + return true; } -MoviePlayer::~MoviePlayer(void) { - if (_introPal) - free(_introPal); - for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++) - if (_logoOvls[cnt]) - free(_logoOvls[cnt]); +void MoviePlayer::syncFrame(void) { + _ticks += 83; + if (checkSkipFrame()) { + warning("Skipped frame %d", _currentFrame); + return; + } + if (_bgSoundStream) { + while (_snd->isSoundHandleActive(_bgSoundHandle) && (_snd->getSoundElapsedTime(_bgSoundHandle) * 12) / 1000 < _currentFrame) { + _sys->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 = _sys->getMillis(); + } else { + while (_sys->getMillis() < _ticks) { + _sys->delayMillis(10); + } + } } /** * Plays an animated cutscene. * @param id the id of the file */ -void MoviePlayer::play(uint32 id) { -#if defined(USE_MPEG2) && defined(USE_VORBIS) - AnimationState *anim = new AnimationState(_scr, _snd, _sys); - Audio::AudioStream *stream = NULL; +bool MoviePlayer::load(uint32 id) { + _id = id; + _bgSoundStream = NULL; if (SwordEngine::_systemVars.cutscenePackVersion == 1) { if ((id == SEQ_INTRO) || (id == SEQ_FINALE) || (id == SEQ_HISTORY) || (id == SEQ_FERRARI)) { +#ifdef USE_VORBIS // these sequences are language specific char sndName[20]; - sprintf(sndName, "%s.snd", _sequenceList[id]); + sprintf(sndName, "%s.snd", sequenceList[id]); Common::File *oggSource = new Common::File(); if (oggSource->open(sndName)) { SplittedAudioStream *sStream = new SplittedAudioStream(); @@ -122,96 +171,61 @@ void MoviePlayer::play(uint32 id) { sStream->appendStream(apStream); } free(header); - stream = sStream; + _bgSoundStream = sStream; } else warning("Sound file \"%s\" not found", sndName); - initOverlays(id); oggSource->decRef(); +#endif + initOverlays(id); } } - bool initOK = anim->init(_sequenceList[id], stream); - - uint32 frameCount = 0; - if (initOK) { - while (anim->decodeFrame()) { - processFrame(id, anim, frameCount); - anim->updateScreen(); - frameCount++; - OSystem::Event event; - while (_sys->pollEvent(event)) { - switch (event.type) { - case OSystem::EVENT_SCREEN_CHANGED: - anim->handleScreenChanged(); - break; - case OSystem::EVENT_KEYDOWN: - if (event.kbd.keycode == 27) { - delete anim; - return; - } - break; - case OSystem::EVENT_QUIT: - _sys->quit(); - break; - default: - break; + return true; +} + +void MoviePlayer::play(void) { + _scr->clearScreen(); + _framesSkipped = 0; + _ticks = _sys->getMillis(); + if (_bgSoundStream) { + _snd->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSoundHandle, _bgSoundStream); + } + _currentFrame = 0; + while (decodeFrame()) { + processFrame(); + syncFrame(); + updateScreen(); + _currentFrame++; + OSystem::Event event; + while (_sys->pollEvent(event)) { + switch (event.type) { + case OSystem::EVENT_SCREEN_CHANGED: + handleScreenChanged(); + break; + case OSystem::EVENT_KEYDOWN: + if (event.kbd.keycode == 27) { + _snd->stopHandle(_bgSoundHandle); + return; } + break; + case OSystem::EVENT_QUIT: + _sys->quit(); + break; + default: + break; } } } - while (!anim->soundFinished()) + while (_snd->isSoundHandleActive(_bgSoundHandle)) _sys->delayMillis(100); - delete anim; -#endif // USE_MPEG2 && USE_VORBIS -} -void MoviePlayer::insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal) { - if (ovl != NULL) - for (uint32 cnt = 0; cnt < 640 * 400; cnt++) - if (ovl[cnt]) - buf[cnt] = pal[ovl[cnt]]; -} + // It's tempting to call _screen->fullRefresh() here to restore the old + // palette. However, that causes glitches with DXA movies, here the + // previous location would be momentarily drawn, before switching to + // the new one. Work around this by setting the palette to black. -void MoviePlayer::processFrame(uint32 animId, AnimationState *anim, uint32 frameNo) { -#if defined(USE_MPEG2) && !defined(BACKEND_8BIT) - if ((animId != 4) || (SwordEngine::_systemVars.cutscenePackVersion == 0)) - return; - OverlayColor *buf = anim->giveRgbBuffer(); - if ((frameNo > 397) && (frameNo < 444)) { // Broken Sword Logo - if (frameNo <= 403) - insertOverlay(buf, _logoOvls[frameNo - 398], _introPal); // fade up - else if (frameNo <= 437) - insertOverlay(buf, _logoOvls[(frameNo - 404) % 6 + 6], _introPal); // animation - else { - insertOverlay(buf, _logoOvls[5 - (frameNo - 438)], _introPal); // fade down - } - } -#endif -} - -bool MoviePlayer::initOverlays(uint32 id) { -#if defined(USE_MPEG2) && !defined(BACKEND_8BIT) - if (id == SEQ_INTRO) { - ArcFile ovlFile; - if (!ovlFile.open("intro.dat")) { - warning("\"intro.dat\" not found"); - return false; - } - ovlFile.enterPath(SwordEngine::_systemVars.language); - for (uint8 fcnt = 0; fcnt < 12; fcnt++) { - _logoOvls[fcnt] = ovlFile.decompressFile(fcnt); - if (fcnt > 0) - for (uint32 cnt = 0; cnt < 640 * 400; cnt++) - if (_logoOvls[fcnt - 1][cnt] && !_logoOvls[fcnt][cnt]) - _logoOvls[fcnt][cnt] = _logoOvls[fcnt - 1][cnt]; - } - uint8 *pal = ovlFile.fetchFile(12); - _introPal = (OverlayColor*)malloc(256 * sizeof(OverlayColor)); - for (uint16 cnt = 0; cnt < 256; cnt++) - _introPal[cnt] = _sys->RGBToColor(pal[cnt * 3 + 0], pal[cnt * 3 + 1], pal[cnt * 3 + 2]); - } -#endif - - return true; + byte pal[3 * 256]; + memset(pal, 0, sizeof(pal)); + updatePalette(pal, true); } SplittedAudioStream::SplittedAudioStream(void) { @@ -275,27 +289,237 @@ int SplittedAudioStream::readBuffer(int16 *buffer, const int numSamples) { return retVal; } -const char * MoviePlayer::_sequenceList[20] = { - "ferrari", // 0 CD2 ferrari running down fitz in sc19 - "ladder", // 1 CD2 george walking down ladder to dig sc24->sc$ - "steps", // 2 CD2 george walking down steps sc23->sc24 - "sewer", // 3 CD1 george entering sewer sc2->sc6 - "intro", // 4 CD1 intro sequence ->sc1 - "river", // 5 CD1 george being thrown into river by flap & g$ - "truck", // 6 CD2 truck arriving at bull's head sc45->sc53/4 - "grave", // 7 BOTH george's grave in scotland, from sc73 + from sc38 $ - "montfcon", // 8 CD2 monfaucon clue in ireland dig, sc25 - "tapestry", // 9 CD2 tapestry room beyond spain well, sc61 - "ireland", // 10 CD2 ireland establishing shot europe_map->sc19 - "finale", // 11 CD2 grand finale at very end, from sc73 - "history", // 12 CD1 George's history lesson from Nico, in sc10 - "spanish", // 13 CD2 establishing shot for 1st visit to Spain, europe_m$ - "well", // 14 CD2 first time being lowered down well in Spai$ - "candle", // 15 CD2 Candle burning down in Spain mausoleum sc59 - "geodrop", // 16 CD2 from sc54, George jumping down onto truck - "vulture", // 17 CD2 from sc54, vultures circling George's dead body - "enddemo", // 18 --- for end of single CD demo - "credits", // 19 CD2 credits, to follow "finale" sequence -}; +#ifdef USE_ZLIB + +/////////////////////////////////////////////////////////////////////////////// +// Movie player for the new DXA movies +/////////////////////////////////////////////////////////////////////////////// + +MoviePlayerDXA::MoviePlayerDXA(Screen *src, Audio::Mixer *snd, OSystem *sys) + : MoviePlayer(src, snd, sys) { + debug(0, "Creating DXA cutscene player"); +} + +MoviePlayerDXA::~MoviePlayerDXA(void) { + // free(_frameBuffer); +} + +bool MoviePlayerDXA::load(uint32 id) { + if (!MoviePlayer::load(id)) + return false; + + char filename[20]; + snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]); + if (loadFile(filename)) { + // The Broken Sword games always use external audio tracks. + if (_fd.readUint32BE() != MKID_BE('NULL')) + return false; + _frameWidth = getWidth(); + _frameHeight = getHeight(); + _frameX = (640 - _frameWidth) / 2; + _frameY = (480 - _frameHeight) / 2; + if (!_bgSoundStream) { + _bgSoundStream = Audio::AudioStream::openStreamFile(sequenceList[id]); + } + return true; + } + return false; +} + +bool MoviePlayerDXA::initOverlays(uint32 id) { + // TODO + return true; +} + +void MoviePlayerDXA::setPalette(byte *pal) { + updatePalette(pal, true); +} + +bool MoviePlayerDXA::decodeFrame(void) { + if (_currentFrame < _framesCount) { + decodeNextFrame(); + return true; + } + return false; +} + +void MoviePlayerDXA::processFrame(void) { + // TODO +} + +void MoviePlayerDXA::updateScreen(void) { + // Using _frameBuffer1 directly should work, as long as we don't do any + // post-processing of the frame. + _sys->copyRectToScreen(_frameBuffer1, _frameWidth, _frameX, _frameY, _frameWidth, _frameHeight); + _sys->updateScreen(); +} + +#endif + +#ifdef USE_MPEG2 + +/////////////////////////////////////////////////////////////////////////////// +// Movie player for the old MPEG movies +/////////////////////////////////////////////////////////////////////////////// + +MoviePlayerMPEG::MoviePlayerMPEG(Screen *src, Audio::Mixer *snd, OSystem *sys) + : MoviePlayer(src, snd, sys) { +#ifdef BACKEND_8BIT + debug(0, "Creating MPEG cutscene player (8-bit)"); +#else + debug(0, "Creating MPEG cutscene player (16-bit)"); +#endif + for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++) + _logoOvls[cnt] = NULL; + _introPal = NULL; + _anim = NULL; +} + +MoviePlayerMPEG::~MoviePlayerMPEG(void) { + free(_introPal); + for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++) + free(_logoOvls[cnt]); + delete _anim; +} + +void MoviePlayerMPEG::handleScreenChanged(void) { + _anim->handleScreenChanged(); +} + +void MoviePlayerMPEG::insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal) { + if (ovl != NULL) + for (uint32 cnt = 0; cnt < 640 * 400; cnt++) + if (ovl[cnt]) + buf[cnt] = pal[ovl[cnt]]; +} + +bool MoviePlayerMPEG::load(uint32 id) { + if (MoviePlayer::load(id)) { + _anim = new AnimationState(this, _scr, _snd, _sys); + return _anim->init(sequenceList[id], _bgSoundStream); + } + return false; +} + +bool MoviePlayerMPEG::initOverlays(uint32 id) { + if (id == SEQ_INTRO) { + ArcFile ovlFile; + if (!ovlFile.open("intro.dat")) { + warning("\"intro.dat\" not found"); + return false; + } + ovlFile.enterPath(SwordEngine::_systemVars.language); + for (uint8 fcnt = 0; fcnt < 12; fcnt++) { + _logoOvls[fcnt] = ovlFile.decompressFile(fcnt); + if (fcnt > 0) + for (uint32 cnt = 0; cnt < 640 * 400; cnt++) + if (_logoOvls[fcnt - 1][cnt] && !_logoOvls[fcnt][cnt]) + _logoOvls[fcnt][cnt] = _logoOvls[fcnt - 1][cnt]; + } + uint8 *pal = ovlFile.fetchFile(12); + _introPal = (OverlayColor*)malloc(256 * sizeof(OverlayColor)); + for (uint16 cnt = 0; cnt < 256; cnt++) + _introPal[cnt] = _sys->RGBToColor(pal[cnt * 3 + 0], pal[cnt * 3 + 1], pal[cnt * 3 + 2]); + } + + return true; +} + +bool MoviePlayerMPEG::decodeFrame(void) { + return _anim->decodeFrame(); +} + +void MoviePlayerMPEG::updateScreen(void) { + _anim->updateScreen(); +} + +void MoviePlayerMPEG::processFrame(void) { +#ifndef BACKEND_8BIT + if ((_id != 4) || (SwordEngine::_systemVars.cutscenePackVersion == 0)) + return; + OverlayColor *buf = _anim->giveRgbBuffer(); + if ((_currentFrame > 397) && (_currentFrame < 444)) { // Broken Sword Logo + if (_currentFrame <= 403) + insertOverlay(buf, _logoOvls[_currentFrame - 398], _introPal); // fade up + else if (_currentFrame <= 437) + insertOverlay(buf, _logoOvls[(_currentFrame - 404) % 6 + 6], _introPal); // animation + else { + insertOverlay(buf, _logoOvls[5 - (_currentFrame - 438)], _introPal); // fade down + } + } +#endif +} + +void MoviePlayerMPEG::syncFrame(void) { +} + +AnimationState::AnimationState(MoviePlayer *player, Screen *scr, Audio::Mixer *snd, OSystem *sys) + : BaseAnimationState(snd, sys, 640, 400), _player(player), _scr(scr) { +} + +AnimationState::~AnimationState(void) { +} + +#ifdef BACKEND_8BIT +void AnimationState::setPalette(byte *pal) { + _player->updatePalette(pal, false); +} +#endif + +void AnimationState::drawYUV(int width, int height, byte *const *dat) { + _frameWidth = width; + _frameHeight = height; + +#ifdef BACKEND_8BIT + _scr->plotYUV(_lut, width, height, dat); +#else + plotYUV(width, height, dat); +#endif +} + +OverlayColor *AnimationState::giveRgbBuffer(void) { +#ifdef BACKEND_8BIT + return NULL; +#else + return _overlay; +#endif +} + +Audio::AudioStream *AnimationState::createAudioStream(const char *name, void *arg) { + if (arg) + return (Audio::AudioStream*)arg; + else + return Audio::AudioStream::openStreamFile(name); +} + +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Factory function for creating the appropriate cutscene player +/////////////////////////////////////////////////////////////////////////////// + +MoviePlayer *makeMoviePlayer(uint32 id, Screen *scr, Audio::Mixer *snd, OSystem *sys) { +#if defined(USE_ZLIB) || defined(USE_MPEG2) + char filename[20]; +#endif + +#ifdef USE_ZLIB + snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]); + + if (Common::File::exists(filename)) { + return new MoviePlayerDXA(scr, snd, sys); + } +#endif + +#ifdef USE_MPEG2 + snprintf(filename, sizeof(filename), "%s.mp2", sequenceList[id]); + + if (Common::File::exists(filename)) { + return new MoviePlayerMPEG(scr, snd, sys); + } +#endif + + return NULL; +} } // End of namespace Sword1 diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h index f49245153b..1b484e9583 100644 --- a/engines/sword1/animation.h +++ b/engines/sword1/animation.h @@ -24,6 +24,7 @@ #define ANIMATION_H #include "graphics/animation.h" +#include "graphics/dxa_player.h" #include "sword1/screen.h" #include "sword1/sound.h" @@ -57,15 +58,71 @@ enum { #define INTRO_LOGO_OVLS 12 #define INTRO_TEXT_OVLS 8 +class MoviePlayer { +public: + MoviePlayer(Screen *scr, Audio::Mixer *snd, OSystem *sys); + virtual ~MoviePlayer(void); + virtual bool load(uint32 id); + void play(void); + void updatePalette(byte *pal, bool packed = true); +private: + bool checkSkipFrame(void); +protected: + Screen *_scr; + Audio::Mixer *_snd; + OSystem *_sys; + + uint32 _id; + + byte *_frameBuffer; + uint _currentFrame; + int _framesSkipped; + bool _forceFrame; + + int _frameWidth, _frameHeight; + int _frameX, _frameY; + + Audio::SoundHandle _bgSoundHandle; + Audio::AudioStream *_bgSoundStream; + uint32 _ticks; + + virtual void handleScreenChanged(void); + virtual bool initOverlays(uint32 id); + virtual bool decodeFrame(void) = 0; + virtual void processFrame(void) = 0; + virtual void syncFrame(void); + virtual void updateScreen(void) = 0; +}; + +#ifdef USE_ZLIB + +class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXAPlayer { +protected: + virtual void setPalette(byte *pal); +public: + MoviePlayerDXA(Screen *scr, Audio::Mixer *snd, OSystem *sys); + virtual ~MoviePlayerDXA(void); + bool load(uint32 id); +protected: + bool initOverlays(uint32 id); + bool decodeFrame(void); + void processFrame(void); + void updateScreen(void); +}; + +#endif + +#ifdef USE_MPEG2 + class AnimationState : public Graphics::BaseAnimationState { private: + MoviePlayer *_player; Screen *_scr; public: - AnimationState(Screen *scr, Audio::Mixer *snd, OSystem *sys); - ~AnimationState(); + AnimationState(MoviePlayer *player, Screen *scr, Audio::Mixer *snd, OSystem *sys); + ~AnimationState(void); OverlayColor *giveRgbBuffer(void); - bool soundFinished(); private: void drawYUV(int width, int height, byte *const *dat); @@ -78,24 +135,27 @@ protected: virtual Audio::AudioStream *createAudioStream(const char *name, void *arg); }; -class MoviePlayer { +class MoviePlayerMPEG : public MoviePlayer { public: - MoviePlayer(Screen *scr, Audio::Mixer *snd, OSystem *sys); - ~MoviePlayer(void); - void play(uint32 id); -private: + MoviePlayerMPEG(Screen *scr, Audio::Mixer *snd, OSystem *sys); + virtual ~MoviePlayerMPEG(void); + bool load(uint32 id); +protected: void insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal); - void processFrame(uint32 animId, AnimationState *anim, uint32 frameNo); - bool initOverlays(uint32 id); - Screen *_scr; - Audio::Mixer *_snd; - OSystem *_sys; - - static const char *_sequenceList[20]; - uint8 *_logoOvls[INTRO_LOGO_OVLS]; + AnimationState *_anim; OverlayColor *_introPal; + uint8 *_logoOvls[INTRO_LOGO_OVLS]; + + bool initOverlays(uint32 id); + bool decodeFrame(void); + void processFrame(void); + void syncFrame(void); + void updateScreen(void); + void handleScreenChanged(void); }; +#endif + struct FileQueue { Audio::AudioStream *stream; FileQueue *next; @@ -114,6 +174,8 @@ private: FileQueue *_queue; }; +MoviePlayer *makeMoviePlayer(uint32 id, Screen *scr, Audio::Mixer *snd, OSystem *sys); + } // End of namespace Sword1 #endif diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp index 2c619d6dc9..b6210edd63 100644 --- a/engines/sword1/logic.cpp +++ b/engines/sword1/logic.cpp @@ -951,8 +951,12 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3 CreditsPlayer player(_system, _mixer); player.play(); } else { - MoviePlayer player(_screen, _mixer, _system); - player.play(sequenceId); + MoviePlayer *player = makeMoviePlayer(sequenceId, _screen, _mixer, _system); + if (player) { + if (player->load(sequenceId)) + player->play(); + delete player; + } } return SCRIPT_CONT; } diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp index 26672b3a3c..57a9b6137c 100644 --- a/engines/sword1/screen.cpp +++ b/engines/sword1/screen.cpp @@ -64,6 +64,14 @@ Screen::~Screen(void) { quitScreen(); } +void Screen::clearScreen(void) { + if (_screenBuf) { + _fullRefresh = true; + memset(_screenBuf, 0, _scrnSizeX * _scrnSizeY); + _system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480); + } +} + void Screen::useTextManager(Text *pTextMan) { _textMan = pTextMan; } diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h index 43a0b74cab..44b22bd2cd 100644 --- a/engines/sword1/screen.h +++ b/engines/sword1/screen.h @@ -69,6 +69,7 @@ class Screen { public: Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan); ~Screen(void); + void clearScreen(void); void useTextManager(Text *pTextMan); void draw(void); -- cgit v1.2.3