aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorbjörn Andersson2006-08-26 11:34:35 +0000
committerTorbjörn Andersson2006-08-26 11:34:35 +0000
commitca387f158537dad55d11725247c8224678108e2f (patch)
tree2fe95e9c4bc79b3ee1891ff1d5c2777fdf230bee
parent4de0c30ad1bdec5e37a4ebb5c3ea6ca5f07eff09 (diff)
downloadscummvm-rg350-ca387f158537dad55d11725247c8224678108e2f.tar.gz
scummvm-rg350-ca387f158537dad55d11725247c8224678108e2f.tar.bz2
scummvm-rg350-ca387f158537dad55d11725247c8224678108e2f.zip
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
-rw-r--r--engines/sword1/animation.cpp520
-rw-r--r--engines/sword1/animation.h94
-rw-r--r--engines/sword1/logic.cpp8
-rw-r--r--engines/sword1/screen.cpp8
-rw-r--r--engines/sword1/screen.h1
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);