aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2009-02-15 13:29:48 +0000
committerFilippos Karapetis2009-02-15 13:29:48 +0000
commit781d7da6b1f0ff9ad7dd4b28b51ed1e3064d222b (patch)
tree91569e4d8abee185ba91875718afee94dc20a0f4
parent47a1cd754586a8f61381db7ac7147987bbaa27dc (diff)
downloadscummvm-rg350-781d7da6b1f0ff9ad7dd4b28b51ed1e3064d222b.tar.gz
scummvm-rg350-781d7da6b1f0ff9ad7dd4b28b51ed1e3064d222b.tar.bz2
scummvm-rg350-781d7da6b1f0ff9ad7dd4b28b51ed1e3064d222b.zip
Applied my patch for the BS1/2 video player
- Support for the MPEG2 videos in BS1/2 has been dropped. The MPEG2 videos were lossy, and support for them complicated the code a lot. - Support for the non-existing enhanced MPEG cutscene packs for BS1 has been dropped. As a consequence, the credits player and the splitted audio stream players used for these packs has been removed - The original Smacker videos for both games are now supported, using our Smacker player (which is based off publically available specs and FFMPEG) - The animations now use the common video player code. Both the Smacker videos and our DXA video packs are supported svn-id: r38236
-rw-r--r--engines/sword1/animation.cpp544
-rw-r--r--engines/sword1/animation.h153
-rw-r--r--engines/sword1/credits.cpp349
-rw-r--r--engines/sword1/credits.h75
-rw-r--r--engines/sword1/logic.cpp17
-rw-r--r--engines/sword1/module.mk1
-rw-r--r--engines/sword1/sword1.cpp8
-rw-r--r--engines/sword1/sword1.h2
-rw-r--r--engines/sword2/animation.cpp281
-rw-r--r--engines/sword2/animation.h49
-rw-r--r--engines/sword2/sword2.cpp2
-rw-r--r--graphics/video/video_player.h6
12 files changed, 184 insertions, 1303 deletions
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 04344a9b3f..f6e6e4d1db 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -27,7 +27,6 @@
#include "common/file.h"
#include "sword1/sword1.h"
#include "sword1/animation.h"
-#include "sword1/credits.h"
#include "sword1/text.h"
#include "sound/vorbis.h"
@@ -36,8 +35,11 @@
#include "common/str.h"
#include "common/events.h"
#include "common/system.h"
+#include "common/list.h"
#include "graphics/surface.h"
+#include "gui/message.h"
+
namespace Sword1 {
static const char *sequenceList[20] = {
@@ -67,107 +69,14 @@ static const char *sequenceList[20] = {
// Basic movie player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer::MoviePlayer(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system)
- : _vm(vm), _screen(screen), _textMan(textMan), _snd(snd), _system(system) {
+MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType)
+ : _vm(vm), _textMan(textMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system), VideoPlayer(decoder) {
_bgSoundStream = NULL;
- _ticks = 0;
- _black = 1;
- _white = 255;
- _currentFrame = 0;
- _forceFrame = false;
- _framesSkipped = 0;
+ _decoderType = decoderType;
}
MoviePlayer::~MoviePlayer(void) {
-}
-
-void MoviePlayer::updatePalette(byte *pal, bool packed) {
- byte palette[4 * 256];
- byte *p = palette;
-
- uint32 maxWeight = 0;
- uint32 minWeight = 0xFFFFFFFF;
-
- for (int i = 0; i < 256; i++) {
- int r = *pal++;
- int g = *pal++;
- int b = *pal++;
-
- if (!packed)
- pal++;
-
- uint32 weight = 3 * r * r + 6 * g * g + 2 * b * b;
-
- if (weight >= maxWeight) {
- _white = i;
- maxWeight = weight;
- }
-
- if (weight <= minWeight) {
- _black = i;
- minWeight = i;
- }
-
- *p++ = r;
- *p++ = g;
- *p++ = b;
- *p++ = 0;
- }
-
- _system->setPalette(palette, 0, 256);
- _forceFrame = true;
-}
-
-void MoviePlayer::handleScreenChanged(void) {
-}
-
-bool MoviePlayer::initOverlays(uint32 id) {
- return true;
-}
-
-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 (_system->getMillis() <= _ticks)
- return false;
- }
- _framesSkipped++;
- return true;
-}
-
-bool MoviePlayer::syncFrame(void) {
- _ticks += 83;
- if (checkSkipFrame()) {
- warning("Skipped frame %d", _currentFrame);
- return false;
- }
- if (_bgSoundStream) {
- while (_snd->isSoundHandleActive(_bgSoundHandle) && (_snd->getSoundElapsedTime(_bgSoundHandle) * 12) / 1000 < _currentFrame) {
- _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 = _system->getMillis();
- } else {
- while (_system->getMillis() < _ticks) {
- _system->delayMillis(10);
- }
- }
- return true;
+ delete(_decoder);
}
/**
@@ -178,8 +87,11 @@ bool MoviePlayer::load(uint32 id) {
Common::File f;
char fileName[20];
- _id = id;
- _bgSoundStream = NULL;
+ if (_decoderType == kVideoDecoderDXA) {
+ _bgSoundStream = Audio::AudioStream::openStreamFile(sequenceList[id]);
+ } else {
+ _bgSoundStream = NULL;
+ }
if (SwordEngine::_systemVars.showText) {
sprintf(fileName, "%s.txt", sequenceList[id]);
@@ -221,98 +133,51 @@ bool MoviePlayer::load(uint32 id) {
}
}
- 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
- sprintf(fileName, "%s.snd", sequenceList[id]);
- Common::File *oggSource = new Common::File();
- if (oggSource->open(fileName)) {
- SplittedAudioStream *sStream = new SplittedAudioStream();
- uint32 numSegs = oggSource->readUint32LE(); // number of audio segments, either 1 or 2.
- // for each segment and each of the 7 languages, we've got fileoffset and size
- uint32 *header = (uint32*)malloc(numSegs * 7 * 2 * 4);
- for (uint32 cnt = 0; cnt < numSegs * 7 * 2; cnt++)
- header[cnt] = oggSource->readUint32LE();
- for (uint32 segCnt = 0; segCnt < numSegs; segCnt++) {
- oggSource->seek( header[SwordEngine::_systemVars.language * 2 + 0 + segCnt * 14]);
- uint32 segSize = header[SwordEngine::_systemVars.language * 2 + 1 + segCnt * 14];
- Common::MemoryReadStream *stream = oggSource->readStream(segSize);
- Audio::AudioStream *apStream = Audio::makeVorbisStream(stream, true);
- if (!apStream)
- error("Can't create Vorbis Stream from file %s", fileName);
- sStream->appendStream(apStream);
- }
- free(header);
- _bgSoundStream = sStream;
- } else
- warning("Sound file \"%s\" not found", fileName);
- delete oggSource;
-#endif
- initOverlays(id);
- }
+ char filename[20];
+ switch (_decoderType) {
+ case kVideoDecoderDXA:
+ snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]);
+ break;
+ case kVideoDecoderSMK:
+ snprintf(filename, sizeof(filename), "%s.smk", sequenceList[id]);
+ break;
+ }
+
+ if (_decoder->loadFile(filename)) {
+ // The Broken Sword games always use external audio tracks.
+ if (_decoder->readSoundHeader() != MKID_BE('NULL'))
+ return false;
+ } else {
+ return false;
}
+
return true;
}
void MoviePlayer::play(void) {
- _screen->clearScreen();
- _framesSkipped = 0;
- _ticks = _system->getMillis();
- _bgSoundStream = Audio::AudioStream::openStreamFile(sequenceList[_id]);
if (_bgSoundStream) {
- _snd->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSoundHandle, _bgSoundStream);
+ _snd->playInputStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
}
- _currentFrame = 0;
bool terminated = false;
- Common::EventManager *eventMan = _system->getEventManager();
- while (!terminated && decodeFrame()) {
- if (!_movieTexts.empty()) {
- if (_currentFrame == _movieTexts[0]->_startFrame) {
- _textMan->makeTextSprite(2, (uint8 *)_movieTexts[0]->_text, 600, LETTER_COL);
-
- FrameHeader *frame = _textMan->giveSpriteData(2);
- _textWidth = frame->width;
- _textHeight = frame->height;
- _textX = 320 - _textWidth / 2;
- _textY = 420 - _textHeight;
- }
- if (_currentFrame == _movieTexts[0]->_endFrame) {
- _textMan->releaseText(2, false);
- delete _movieTexts.remove_at(0);
- }
- }
- processFrame();
- if (syncFrame())
- updateScreen();
- _currentFrame++;
- Common::Event event;
- while (eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_SCREEN_CHANGED:
- handleScreenChanged();
- break;
- case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
- terminated = true;
- break;
- default:
- break;
- }
- }
- if (_vm->shouldQuit())
- terminated = true;
- }
+
+ Common::List<Common::Event> stopEvents;
+ Common::Event stopEvent;
+ stopEvents.clear();
+ stopEvent.type = Common::EVENT_KEYDOWN;
+ stopEvent.kbd = Common::KEYCODE_ESCAPE;
+ stopEvents.push_back(stopEvent);
+
+ terminated = !playVideo(&stopEvents);
if (terminated)
- _snd->stopHandle(_bgSoundHandle);
+ _snd->stopHandle(*_bgSoundHandle);
_textMan->releaseText(2, false);
while (!_movieTexts.empty())
delete _movieTexts.remove_at(_movieTexts.size() - 1);
- while (_snd->isSoundHandleActive(_bgSoundHandle))
+ while (_snd->isSoundHandleActive(*_bgSoundHandle))
_system->delayMillis(100);
// It's tempting to call _screen->fullRefresh() here to restore the old
@@ -322,324 +187,105 @@ void MoviePlayer::play(void) {
byte pal[3 * 256];
memset(pal, 0, sizeof(pal));
- updatePalette(pal, true);
-}
-
-SplittedAudioStream::SplittedAudioStream(void) {
- _queue = NULL;
-}
-
-SplittedAudioStream::~SplittedAudioStream(void) {
- while (_queue) {
- delete _queue->stream;
- FileQueue *que = _queue->next;
- delete _queue;
- _queue = que;
- }
-}
-
-int SplittedAudioStream::getRate(void) const {
- if (_queue)
- return _queue->stream->getRate();
- else
- return 22050;
+ _system->setPalette(pal, 0, 255);
}
-void SplittedAudioStream::appendStream(Audio::AudioStream *stream) {
- FileQueue **que = &_queue;
- while (*que)
- que = &((*que)->next);
- *que = new FileQueue;
- (*que)->stream = stream;
- (*que)->next = NULL;
-}
-
-bool SplittedAudioStream::endOfData(void) const {
- if (_queue)
- return _queue->stream->endOfData();
- else
- return true;
-}
-
-bool SplittedAudioStream::isStereo(void) const {
- if (_queue)
- return _queue->stream->isStereo();
- else
- return false; // all the BS1 files are mono, anyways.
-}
+void MoviePlayer::performPostProcessing(byte *screen) {
+ if (!_movieTexts.empty()) {
+ if (_decoder->getCurFrame() == _movieTexts[0]->_startFrame) {
+ _textMan->makeTextSprite(2, (uint8 *)_movieTexts[0]->_text, 600, LETTER_COL);
-int SplittedAudioStream::readBuffer(int16 *buffer, const int numSamples) {
- int retVal = 0;
- int needSamples = numSamples;
- while (needSamples && _queue) {
- int retSmp = _queue->stream->readBuffer(buffer, needSamples);
- needSamples -= retSmp;
- retVal += retSmp;
- buffer += retSmp;
- if (_queue->stream->endOfData()) {
- delete _queue->stream;
- FileQueue *que = _queue->next;
- delete _queue;
- _queue = que;
+ FrameHeader *frame = _textMan->giveSpriteData(2);
+ _textWidth = frame->width;
+ _textHeight = frame->height;
+ _textX = 320 - _textWidth / 2;
+ _textY = 420 - _textHeight;
+ }
+ if (_decoder->getCurFrame() == _movieTexts[0]->_endFrame) {
+ _textMan->releaseText(2, false);
+ delete _movieTexts.remove_at(0);
}
}
- return retVal;
-}
-
-#ifdef USE_ZLIB
-
-///////////////////////////////////////////////////////////////////////////////
-// Movie player for the new DXA movies
-///////////////////////////////////////////////////////////////////////////////
-
-MoviePlayerDXA::MoviePlayerDXA(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system)
- : MoviePlayer(vm, screen, textMan, snd, system) {
- debug(0, "Creating DXA cutscene player");
-}
-
-MoviePlayerDXA::~MoviePlayerDXA(void) {
- closeFile();
-}
-
-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 (_fileStream->readUint32BE() != MKID_BE('NULL'))
- return false;
- _frameWidth = getWidth();
- _frameHeight = getHeight();
- _frameX = (640 - _frameWidth) / 2;
- _frameY = (480 - _frameHeight) / 2;
- 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 ((uint32)_currentFrame < (uint32)getFrameCount()) {
- decodeNextFrame();
- return true;
- }
- return false;
-}
-
-void MoviePlayerDXA::processFrame(void) {
-}
-
-void MoviePlayerDXA::updateScreen(void) {
- Graphics::Surface *frameBuffer = _system->lockScreen();
- copyFrameToBuffer((byte *)frameBuffer->pixels, _frameX, _frameY, 640);
-
- // TODO: Handle the advanced cutscene packs. Do they really exist?
-
- // We cannot draw the text to _drawBuffer, since that's one of the
- // decoder's internal buffers, and besides it may be much smaller than
- // the screen, so it's possible that the subtitles don't fit on it.
- // Instead, we get the frame buffer from the backend, after copying the
- // frame to it, and draw on that.
if (_textMan->giveSpriteData(2)) {
byte *src = (byte *)_textMan->giveSpriteData(2) + sizeof(FrameHeader);
- byte *dst = (byte *)frameBuffer->getBasePtr(_textX, _textY);
+ byte *dst = screen + _textY * _decoder->getWidth() + _textX * 1;
for (int y = 0; y < _textHeight; y++) {
for (int x = 0; x < _textWidth; x++) {
switch (src[x]) {
case BORDER_COL:
- dst[x] = _black;
+ dst[x] = _decoder->getBlack();
break;
case LETTER_COL:
- dst[x] = _white;
+ dst[x] = _decoder->getWhite();
break;
}
}
src += _textWidth;
- dst += frameBuffer->pitch;
+ dst += _decoder->getWidth();
}
-
}
-
- _system->unlockScreen();
-
- _system->updateScreen();
}
-#endif
-
-#ifdef USE_MPEG2
-
-///////////////////////////////////////////////////////////////////////////////
-// Movie player for the old MPEG movies
-///////////////////////////////////////////////////////////////////////////////
-
-MoviePlayerMPEG::MoviePlayerMPEG(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system)
- : MoviePlayer(vm, screen, textMan, snd, system) {
-#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;
+DXAPlayerWithSound::DXAPlayerWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
+ : _mixer(mixer), _bgSoundHandle(bgSoundHandle) {
}
-MoviePlayerMPEG::~MoviePlayerMPEG(void) {
- free(_introPal);
- for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++)
- free(_logoOvls[cnt]);
- delete _anim;
-}
+int32 DXAPlayerWithSound::getAudioLag() {
+ if (!_fileStream)
+ return 0;
-void MoviePlayerMPEG::handleScreenChanged(void) {
- _anim->handleScreenChanged();
-}
+ int32 frameDelay = getFrameDelay();
+ int32 videoTime = _videoInfo.currentFrame * frameDelay;
+ int32 audioTime;
-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]];
-}
+ audioTime = (((int32) _mixer->getSoundElapsedTime(*_bgSoundHandle)) * 100);
-bool MoviePlayerMPEG::load(uint32 id) {
- if (MoviePlayer::load(id)) {
- _anim = new AnimationState(this, _screen, _system);
- return _anim->init(sequenceList[id]);
- }
- return false;
+ return videoTime - audioTime;
}
-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));
- Graphics::PixelFormat format = _system->getOverlayFormat();
- for (uint16 cnt = 0; cnt < 256; cnt++)
- _introPal[cnt] = format.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
-}
-
-AnimationState::AnimationState(MoviePlayer *player, Screen *screen, OSystem *system)
- : BaseAnimationState(system, 640, 400), _player(player), _screen(screen) {
-}
-
-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
- _screen->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, SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system) {
-#if defined(USE_ZLIB) || defined(USE_MPEG2)
+MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system) {
char filename[20];
-#endif
+ char buf[60];
+ Audio::SoundHandle bgSoundHandle;
-#ifdef USE_ZLIB
- snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]);
+ snprintf(filename, sizeof(filename), "%s.smk", sequenceList[id]);
if (Common::File::exists(filename)) {
- return new MoviePlayerDXA(vm, screen, textMan, snd, system);
+ Graphics::SMKPlayer *smkDecoder = new Graphics::SMKPlayer(snd);
+ return new MoviePlayer(vm, textMan, snd, system, &bgSoundHandle, smkDecoder, kVideoDecoderSMK);
}
+
+ snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]);
+
+ if (Common::File::exists(filename)) {
+#ifdef USE_ZLIB
+ DXAPlayerWithSound *dxaDecoder = new DXAPlayerWithSound(snd, &bgSoundHandle);
+ return new MoviePlayer(vm, textMan, snd, system, &bgSoundHandle, dxaDecoder, kVideoDecoderDXA);
+#else
+ GUI::MessageDialog dialog("DXA cutscenes found but ScummVM has been built without zlib support", "OK");
+ dialog.runModal();
+ return NULL;
#endif
+ }
-#ifdef USE_MPEG2
+ // Old MPEG2 cutscenes
snprintf(filename, sizeof(filename), "%s.mp2", sequenceList[id]);
if (Common::File::exists(filename)) {
- return new MoviePlayerMPEG(vm, screen, textMan, snd, system);
+ GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK");
+ dialog.runModal();
+ return NULL;
}
-#endif
+
+ sprintf(buf, "Cutscene '%s' not found", sequenceList[id]);
+ GUI::MessageDialog dialog(buf, "OK");
+ dialog.runModal();
return NULL;
}
diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h
index 3c6bf0fc1a..a221221546 100644
--- a/engines/sword1/animation.h
+++ b/engines/sword1/animation.h
@@ -27,7 +27,8 @@
#define SWORD1_ANIMATION_H
#include "graphics/video/dxa_player.h"
-#include "graphics/video/mpeg_player.h"
+#include "graphics/video/smk_player.h"
+#include "graphics/video/video_player.h"
#include "sword1/screen.h"
#include "sword1/sound.h"
@@ -35,32 +36,11 @@
namespace Sword1 {
-enum {
- SEQ_FERRARI = 0,
- SEQ_LADDER,
- SEQ_STEPS,
- SEQ_SEWER,
- SEQ_INTRO,
- SEQ_RIVER,
- SEQ_TRUCK,
- SEQ_GRAVE,
- SEQ_MONTFCON,
- SEQ_TAPESTRY,
- SEQ_IRELAND,
- SEQ_FINALE,
- SEQ_HISTORY,
- SEQ_SPANISH,
- SEQ_WELL,
- SEQ_CANDLE,
- SEQ_GEODROP,
- SEQ_VULTURE,
- SEQ_ENDDEMO,
- SEQ_CREDITS
+enum DecoderType {
+ kVideoDecoderDXA = 0,
+ kVideoDecoderSMK = 1
};
-#define INTRO_LOGO_OVLS 12
-#define INTRO_TEXT_OVLS 8
-
class MovieText {
public:
uint16 _startFrame;
@@ -76,126 +56,39 @@ public:
}
};
-class MoviePlayer {
+class DXAPlayerWithSound : public Graphics::DXAPlayer {
+public:
+ DXAPlayerWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
+ ~DXAPlayerWithSound() {}
+
+ int32 getAudioLag();
+private:
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle *_bgSoundHandle;
+};
+
+class MoviePlayer : public Graphics::VideoPlayer {
public:
- MoviePlayer(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
+ MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType);
virtual ~MoviePlayer(void);
- virtual bool load(uint32 id);
+ bool load(uint32 id);
void play(void);
- void updatePalette(byte *pal, bool packed = true);
-private:
- bool checkSkipFrame(void);
protected:
SwordEngine *_vm;
- Screen *_screen;
Text *_textMan;
Audio::Mixer *_snd;
OSystem *_system;
Common::Array<MovieText *> _movieTexts;
int _textX, _textY, _textWidth, _textHeight;
- byte _black, _white;
-
- uint32 _id;
-
- uint _currentFrame;
- int _framesSkipped;
- bool _forceFrame;
-
- int _frameWidth, _frameHeight;
- int _frameX, _frameY;
+ DecoderType _decoderType;
- Audio::SoundHandle _bgSoundHandle;
+ 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 bool syncFrame(void);
- virtual void updateScreen(void) = 0;
-};
-
-#ifdef USE_ZLIB
-
-class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXAPlayer {
-protected:
- virtual void setPalette(byte *pal);
-public:
- MoviePlayerDXA(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
- 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 *_screen;
-
-public:
- AnimationState(MoviePlayer *player, Screen *screen, OSystem *system);
- ~AnimationState(void);
- OverlayColor *giveRgbBuffer(void);
-
-private:
- void drawYUV(int width, int height, byte *const *dat);
-
-#ifdef BACKEND_8BIT
- void setPalette(byte *pal);
-#endif
-
-protected:
- virtual Audio::AudioStream *createAudioStream(const char *name, void *arg);
-};
-
-class MoviePlayerMPEG : public MoviePlayer {
-public:
- MoviePlayerMPEG(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
- virtual ~MoviePlayerMPEG(void);
- bool load(uint32 id);
-protected:
- void insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal);
- AnimationState *_anim;
- OverlayColor *_introPal;
- uint8 *_logoOvls[INTRO_LOGO_OVLS];
-
- bool initOverlays(uint32 id);
- bool decodeFrame(void);
- void processFrame(void);
- void updateScreen(void);
- void handleScreenChanged(void);
-};
-
-#endif
-
-struct FileQueue {
- Audio::AudioStream *stream;
- FileQueue *next;
-};
-
-class SplittedAudioStream : public Audio::AudioStream {
-public:
- SplittedAudioStream(void);
- ~SplittedAudioStream(void);
- void appendStream(Audio::AudioStream *stream);
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo(void) const;
- virtual bool endOfData(void) const;
- virtual int getRate(void) const;
-private:
- FileQueue *_queue;
+ void performPostProcessing(byte *screen);
};
-MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
+MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system);
} // End of namespace Sword1
diff --git a/engines/sword1/credits.cpp b/engines/sword1/credits.cpp
deleted file mode 100644
index 986f751f8a..0000000000
--- a/engines/sword1/credits.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-/* 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.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/endian.h"
-
-#include "sword1/credits.h"
-#include "sword1/screen.h"
-#include "sword1/sword1.h"
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-
-#include "common/file.h"
-#include "common/util.h"
-#include "common/events.h"
-#include "common/system.h"
-
-
-#define CREDITS_X 480
-#define CREDITS_Y 300
-#define BUFSIZE_Y 640
-
-#define START_X ((640 - CREDITS_X) / 2)
-#define START_Y ((480 - CREDITS_Y) / 2)
-
-#define SCROLL_TIMING (2000 / 59) // 29.5 frames per second
-
-#define LOGO_FADEUP_TIME (133 * 1000)
-#define LOGO_FADEDOWN_TIME (163 * 1000)
-
-namespace Sword1 {
-
-enum {
- FONT_PAL = 0,
- FONT,
- TEXT,
- REVO_PAL,
- REVO_LOGO,
- F_EOF
-};
-
-enum {
- FNT_LFT = 0, // left column
- FNT_RGT, // right column
- FNT_CEN, // centered
- FNT_BIG = 64, // big font
- FNT_EOL = 128, // linebreak
- FNT_EOB = 255 // end of textblock
-};
-
-
-CreditsPlayer::CreditsPlayer(OSystem *pSystem, Audio::Mixer *pMixer) {
- _system = pSystem;
- _mixer = pMixer;
- _smlFont = _bigFont = NULL;
-}
-
-bool spaceInBuf(uint16 blitSta, uint16 blitEnd, uint16 renderDest) {
- if (blitEnd > blitSta) {
- if ((renderDest > blitEnd) || (renderDest + 15 < blitSta))
- return true;
- } else {
- if ((renderDest > blitEnd) && (renderDest + 15 < blitSta))
- return true;
- }
- return false;
-}
-
-void CreditsPlayer::play(void) {
- Audio::AudioStream *bgSoundStream = Audio::AudioStream::openStreamFile("credits");
- if (bgSoundStream == NULL) {
- warning("\"credits.ogg\" not found, skipping credits sequence");
- return;
- }
- ArcFile credFile;
- if (!credFile.open("credits.dat")) {
- warning("\"credits.dat\" not found, skipping credits sequence");
- return;
- }
-
- uint8 *palSrc = credFile.fetchFile(FONT_PAL, &_palLen);
- for (uint32 cnt = 0; cnt < _palLen; cnt++)
- _palette[(cnt / 3) * 4 + cnt % 3] = palSrc[cnt];
- _palLen /= 3;
-
- generateFonts(&credFile);
-
- uint8 *textData = credFile.fetchFile(TEXT);
- textData += READ_LE_UINT32(textData + SwordEngine::_systemVars.language * 4);
-
- uint8 *screenBuf = (uint8*)malloc(CREDITS_X * BUFSIZE_Y);
- memset(screenBuf, 0, CREDITS_X * BUFSIZE_Y);
- _system->copyRectToScreen(screenBuf, 640, 0, 0, 640, 480);
- _system->setPalette(_palette, 0, _palLen);
-
- // everything's initialized, time to render and show the credits.
- Audio::SoundHandle bgSound;
- _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &bgSound, bgSoundStream, 0);
-
- int relDelay = 0;
- uint16 scrollY = 0;
- uint16 renderY = BUFSIZE_Y / 2;
- uint16 clearY = 0xFFFF;
- bool clearLine = false;
- while (((*textData != FNT_EOB) || (scrollY != renderY)) && !Engine::shouldQuit()) {
- if ((int32)_mixer->getSoundElapsedTime(bgSound) - relDelay < (SCROLL_TIMING * 2)) { // sync to audio
- if (scrollY < BUFSIZE_Y - CREDITS_Y)
- _system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, CREDITS_Y);
- else {
- _system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, BUFSIZE_Y - scrollY);
- _system->copyRectToScreen(screenBuf, CREDITS_X, START_X, START_Y + BUFSIZE_Y - scrollY, CREDITS_X, CREDITS_Y - (BUFSIZE_Y - scrollY));
- }
- _system->updateScreen();
- } else
- warning("frame skipped");
-
- while (spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, renderY) && (*textData != FNT_EOB)) {
- if (*textData & FNT_EOL) {
- renderY = (renderY + 16) % BUFSIZE_Y; // linebreak
- clearLine = true;
- *textData &= ~FNT_EOL;
- }
- if (spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, renderY)) {
- if (clearLine)
- memset(screenBuf + renderY * CREDITS_X, 0, 16 * CREDITS_X);
- clearLine = false;
- renderLine(screenBuf, textData + 1, renderY, *textData);
- if (*textData & FNT_BIG)
- renderY += 16;
- while (*++textData != 0) // search for the start of next string
- ;
- textData++;
- }
- if (*textData == FNT_EOB)
- clearY = renderY;
- }
- if ((*textData == FNT_EOB) && spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, clearY)) {
- memset(screenBuf + clearY * CREDITS_X, 0, 16 * CREDITS_X);
- clearY = (clearY + 16) % BUFSIZE_Y;
- }
-
- relDelay += SCROLL_TIMING;
- delay(relDelay - (int32)_mixer->getSoundElapsedTime(bgSound));
- scrollY = (scrollY + 1) % BUFSIZE_Y;
- }
- free(_smlFont);
- free(_bigFont);
- _smlFont = _bigFont = NULL;
- free(screenBuf);
-
- // credits done, now show the revolution logo
- uint8 *revoBuf = credFile.decompressFile(REVO_LOGO);
- uint8 *revoPal = credFile.fetchFile(REVO_PAL, &_palLen);
- _palLen /= 3;
- while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEUP_TIME) && !Engine::shouldQuit()) {
- delay(100);
- }
- memset(_palette, 0, 256 * 4);
- _system->setPalette(_palette, 0, 256);
- _system->copyRectToScreen(revoBuf, 480, START_X, START_Y, CREDITS_X, CREDITS_Y);
- _system->updateScreen();
-
- fadePalette(revoPal, true, _palLen);
- while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEDOWN_TIME) && !Engine::shouldQuit()) {
- delay(100);
- }
- fadePalette(revoPal, false, _palLen);
- delay(3000);
-
- if (Engine::shouldQuit())
- _mixer->stopAll();
- free(revoBuf);
-}
-
-void CreditsPlayer::fadePalette(uint8 *srcPal, bool fadeup, uint16 len) {
- int8 fadeDir = fadeup ? 1 : -1;
- int fadeStart = fadeup ? 0 : 12;
-
- int relDelay = _system->getMillis();
- for (int fadeStep = fadeStart; (fadeStep >= 0) && (fadeStep <= 12) && !Engine::shouldQuit(); fadeStep += fadeDir) {
- for (uint16 cnt = 0; cnt < len * 3; cnt++)
- _palette[(cnt / 3) * 4 + (cnt % 3)] = (srcPal[cnt] * fadeStep) / 12;
- _system->setPalette(_palette, 0, 256);
- relDelay += 1000 / 12;
- delay(relDelay - _system->getMillis());
- }
-}
-
-void CreditsPlayer::renderLine(uint8 *screenBuf, uint8 *line, uint16 yBufPos, uint8 flags) {
- uint8 *font;
- uint16 fntSize = 16;
- if (flags & FNT_BIG) {
- font = _bigFont;
- fntSize = 32;
- flags &= ~FNT_BIG;
- } else
- font = _smlFont;
-
- uint16 width = getWidth(font, line);
- uint16 xBufPos = (flags == FNT_CEN) ? (CREDITS_X - width) / 2 : ((flags == FNT_LFT) ? (234 - width) : 255);
- uint8 *bufDest = screenBuf + yBufPos * CREDITS_X + xBufPos;
- while (*line) {
- uint8 *chrSrc = font + _numChars + (*line - 1) * fntSize * fntSize;
- for (uint16 cnty = 0; cnty < fntSize; cnty++) {
- for (uint16 cntx = 0; cntx < fntSize; cntx++)
- bufDest[cnty * CREDITS_X + cntx] = chrSrc[cntx];
- chrSrc += fntSize;
- }
- bufDest += font[*line++ - 1];
- }
-}
-
-uint16 CreditsPlayer::getWidth(uint8 *font, uint8 *line) {
- uint16 width = 0;
- while (*line)
- width += font[*line++ - 1];
- return width;
-}
-
-void CreditsPlayer::generateFonts(ArcFile *arcFile) {
- _bigFont = arcFile->decompressFile(FONT);
- _numChars = *_bigFont;
- memmove(_bigFont, _bigFont + 1, _numChars * (32 * 32 + 1));
- _smlFont = (uint8*)malloc(_numChars * (32 * 32 + 1));
- uint8 *src = _bigFont + _numChars;
- uint8 *dst = _smlFont + _numChars;
- for (uint16 cnt = 0; cnt < _numChars; cnt++) {
- _smlFont[cnt] = (_bigFont[cnt]++ + 1) / 2; // width table
- for (uint16 cnty = 0; cnty < 16; cnty++) {
- for (uint16 cntx = 0; cntx < 16; cntx++) {
- uint8 resR = (uint8)((_palette[src[0] * 4 + 0] + _palette[src[1] * 4 + 0] + _palette[src[32] * 4 + 0] + _palette[src[33] * 4 + 0]) >> 2);
- uint8 resG = (uint8)((_palette[src[0] * 4 + 1] + _palette[src[1] * 4 + 1] + _palette[src[32] * 4 + 1] + _palette[src[33] * 4 + 1]) >> 2);
- uint8 resB = (uint8)((_palette[src[0] * 4 + 2] + _palette[src[1] * 4 + 2] + _palette[src[32] * 4 + 2] + _palette[src[33] * 4 + 2]) >> 2);
- *dst++ = getPalIdx(resR, resG, resB);
- src += 2;
- }
- src += 32;
- }
- }
-}
-
-uint8 CreditsPlayer::getPalIdx(uint8 r, uint8 g, uint8 b) {
- for (uint16 cnt = 0; cnt < _palLen; cnt++)
- if ((_palette[cnt * 4 + 0] == r) && (_palette[cnt * 4 + 1] == g) && (_palette[cnt * 4 + 2] == b))
- return (uint8)cnt;
- assert(_palLen < 256);
- _palette[_palLen * 4 + 0] = r;
- _palette[_palLen * 4 + 1] = g;
- _palette[_palLen * 4 + 2] = b;
- return (uint8)_palLen++;
-}
-
-void CreditsPlayer::delay(int msecs) {
-
- Common::Event event;
- uint32 start = _system->getMillis();
- do {
- Common::EventManager *eventMan = _system->getEventManager();
- while (eventMan->pollEvent(event)) {
-#if 0
- switch (event.type) {
- default:
- break;
- }
-#endif
- }
-
- _system->updateScreen();
-
- if (msecs > 0)
- _system->delayMillis(10);
-
- } while ((_system->getMillis() < start + msecs) && !Engine::shouldQuit());
-}
-
-ArcFile::ArcFile(void) {
- _buf = NULL;
-}
-
-ArcFile::~ArcFile(void) {
- if (_buf)
- free(_buf);
-}
-
-bool ArcFile::open(const char *name) {
- Common::File arc;
- if (!arc.open(name))
- return false;
- _bufPos = _buf = (uint8*)malloc(arc.size());
- arc.read(_buf, arc.size());
- arc.close();
- return true;
-}
-
-void ArcFile::enterPath(uint32 id) {
- _bufPos += READ_LE_UINT32(_bufPos + id * 4);
-}
-
-uint8 *ArcFile::fetchFile(uint32 fileId, uint32 *size) {
- if (size)
- *size = READ_LE_UINT32(_bufPos + (fileId + 1) * 4) - READ_LE_UINT32(_bufPos + fileId * 4);
- return _bufPos + READ_LE_UINT32(_bufPos + fileId * 4);
-}
-
-uint8 *ArcFile::decompressFile(uint32 fileId) {
- uint32 size;
- uint8 *srcBuf = fetchFile(fileId, &size);
- uint8 *dstBuf = (uint8*)malloc(READ_LE_UINT32(srcBuf));
- uint8 *srcPos = srcBuf + 4;
- uint8 *dstPos = dstBuf;
- while (srcPos < srcBuf + size) {
- uint16 len = READ_LE_UINT16(srcPos);
- memset(dstPos, 0, len);
- dstPos += len;
- srcPos += 2;
- if (srcPos < srcBuf + size) {
- len = *srcPos++;
- memcpy(dstPos, srcPos, len);
- dstPos += len;
- srcPos += len;
- }
- }
- return dstBuf;
-}
-
-} // end of namespace Sword1
diff --git a/engines/sword1/credits.h b/engines/sword1/credits.h
deleted file mode 100644
index 1b4864709b..0000000000
--- a/engines/sword1/credits.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* 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.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef SWORD1_CREDITS_H
-#define SWORD1_CREDITS_H
-
-#include "common/util.h"
-
-namespace Audio {
- class Mixer;
-}
-class OSystem;
-
-namespace Sword1 {
-
-class ArcFile {
-public:
- ArcFile(void);
- ~ArcFile(void);
- bool open(const char *name);
- uint8 *fetchFile(uint32 fileId, uint32 *size = NULL);
- uint8 *decompressFile(uint32 fileId);
- void enterPath(uint32 id);
- void backToRoot(void) { _bufPos = _buf; }
-private:
- uint8 *_bufPos;
- uint8 *_buf;
-};
-
-class CreditsPlayer {
-public:
- CreditsPlayer(OSystem *pSystem, Audio::Mixer *pMixer);
- void play(void);
-private:
- void generateFonts(ArcFile *arcFile);
- void renderLine(uint8 *screenBuf, uint8 *line, uint16 yBufPos, uint8 flags);
- void fadePalette(uint8 *srcPal, bool fadeup, uint16 len);
- void delay(int msecs);
- uint16 getWidth(uint8 *font, uint8 *line);
- uint8 getPalIdx(uint8 r, uint8 g, uint8 b);
- uint8 _palette[256 * 4];
- uint32 _palLen;
- uint8 _numChars;
-
- OSystem *_system;
- Audio::Mixer *_mixer;
-
- uint8 *_smlFont, *_bigFont;
-};
-
-} // end of namespace Sword1
-
-#endif // BS1CREDITS_H
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 2b24e4ba54..bd35e774a0 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -41,7 +41,6 @@
#include "sword1/music.h"
#include "sword1/swordres.h"
#include "sword1/animation.h"
-#include "sword1/credits.h"
#include "sword1/debug.h"
@@ -960,16 +959,12 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3
// meantime, we don't want any looping sound effects still playing.
_sound->quitScreen();
- if ((SwordEngine::_systemVars.cutscenePackVersion == 1) && (sequenceId == SEQ_CREDITS)) {
- CreditsPlayer player(_system, _mixer);
- player.play();
- } else {
- MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _screen, _textMan, _mixer, _system);
- if (player) {
- if (player->load(sequenceId))
- player->play();
- delete player;
- }
+ MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _mixer, _system);
+ if (player) {
+ _screen->clearScreen();
+ if (player->load(sequenceId))
+ player->play();
+ delete player;
}
return SCRIPT_CONT;
}
diff --git a/engines/sword1/module.mk b/engines/sword1/module.mk
index f101be6cef..6e48069dd0 100644
--- a/engines/sword1/module.mk
+++ b/engines/sword1/module.mk
@@ -3,7 +3,6 @@ MODULE := engines/sword1
MODULE_OBJS := \
animation.o \
control.o \
- credits.o \
debug.o \
detection.o \
eventman.o \
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 86c8bf1676..e0228b4c33 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -58,10 +58,12 @@ SwordEngine::SwordEngine(OSystem *syst)
Common::File::addDefaultDirectory(_gameDataDir.getChild("MUSIC"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("SPEECH"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("SMACKSHI"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("music"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("speech"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("video"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("smackshi"));
}
SwordEngine::~SwordEngine() {
@@ -475,12 +477,6 @@ void SwordEngine::checkCdFiles(void) { // check if we're running from cd, hdd or
*/
// make the demo flag depend on the Gamesettings for now, and not on what the datafiles look like
_systemVars.isDemo = (_features & GF_DEMO) != 0;
- _systemVars.cutscenePackVersion = 0;
-#ifdef USE_MPEG2
- if (Common::File::exists("intro.snd")) {
- _systemVars.cutscenePackVersion = 1;
- }
-#endif
}
Common::Error SwordEngine::go() {
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index 2cbf19d436..ca5c958bf8 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -67,8 +67,6 @@ struct SystemVars {
uint8 language;
bool isDemo;
bool isMac;
-
- uint8 cutscenePackVersion;
};
class SwordEngine : public Engine {
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 9375896f81..a6925e9ade 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -42,6 +42,8 @@
#include "sword2/sound.h"
#include "sword2/animation.h"
+#include "gui/message.h"
+
namespace Sword2 {
///////////////////////////////////////////////////////////////////////////////
@@ -91,7 +93,6 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm, const char *name) {
_leadOutFrame = (uint)-1;
_seamless = false;
_framesSkipped = 0;
- _forceFrame = false;
_currentText = 0;
}
@@ -103,43 +104,6 @@ uint32 MoviePlayer::getTick() {
return _system->getMillis() - _pauseTicks;
}
-void MoviePlayer::updatePalette(byte *pal, bool packed) {
- byte palette[4 * 256];
- byte *p = palette;
-
- uint32 maxWeight = 0;
- uint32 minWeight = 0xFFFFFFFF;
-
- for (int i = 0; i < 256; i++) {
- int r = *pal++;
- int g = *pal++;
- int b = *pal++;
-
- if (!packed)
- pal++;
-
- uint32 weight = 3 * r * r + 6 * g * g + 2 * b * b;
-
- if (weight >= maxWeight) {
- _white = i;
- maxWeight = weight;
- }
-
- if (weight <= minWeight) {
- _black = i;
- minWeight = i;
- }
-
- *p++ = r;
- *p++ = g;
- *p++ = b;
- *p++ = 0;
- }
-
- _vm->_screen->setPalette(0, 256, palette, RDPAL_INSTANT);
- _forceFrame = true;
-}
-
void MoviePlayer::savePalette() {
memcpy(_originalPalette, _vm->_screen->getPalette(), sizeof(_originalPalette));
}
@@ -157,11 +121,6 @@ void MoviePlayer::updateScreen() {
}
bool MoviePlayer::checkSkipFrame() {
- if (_forceFrame) {
- _forceFrame = false;
- return false;
- }
-
if (_framesSkipped > 10) {
warning("Forced frame %d to be displayed", _currentFrame);
_framesSkipped = 0;
@@ -512,44 +471,34 @@ void MoviePlayer::pauseMovie(bool pause) {
}
}
-#ifdef USE_ZLIB
-
///////////////////////////////////////////////////////////////////////////////
-// Movie player for the new DXA movies
+// Movie player for the original SMK movies
///////////////////////////////////////////////////////////////////////////////
-MoviePlayerDXA::MoviePlayerDXA(Sword2Engine *vm, const char *name)
- : MoviePlayer(vm, name) {
- debug(0, "Creating DXA cutscene player");
+MoviePlayerSMK::MoviePlayerSMK(Sword2Engine *vm, const char *name)
+ : MoviePlayer(vm, name), SMKPlayer(vm->_mixer) {
+ debug(0, "Creating SMK cutscene player");
}
-MoviePlayerDXA::~MoviePlayerDXA() {
+MoviePlayerSMK::~MoviePlayerSMK() {
closeFile();
}
-void MoviePlayerDXA::setPalette(byte *pal) {
- updatePalette(pal);
-}
-
-bool MoviePlayerDXA::decodeFrame() {
+bool MoviePlayerSMK::decodeFrame() {
decodeNextFrame();
copyFrameToBuffer(_frameBuffer, _frameX, _frameY, _vm->_screen->getScreenWide());
return true;
}
-bool MoviePlayerDXA::load() {
+bool MoviePlayerSMK::load() {
if (!MoviePlayer::load())
return false;
char filename[20];
- snprintf(filename, sizeof(filename), "%s.dxa", _name);
+ snprintf(filename, sizeof(filename), "%s.smk", _name);
if (loadFile(filename)) {
- // The Broken Sword games always use external audio tracks.
- if (_fileStream->readUint32BE() != MKID_BE('NULL'))
- return false;
-
_frameBuffer = _vm->_screen->getScreen();
_frameWidth = getWidth();
@@ -564,197 +513,52 @@ bool MoviePlayerDXA::load() {
return false;
}
-#endif
-
-#ifdef USE_MPEG2
+#ifdef USE_ZLIB
///////////////////////////////////////////////////////////////////////////////
-// Movie player for the old MPEG movies
+// Movie player for the new DXA movies
///////////////////////////////////////////////////////////////////////////////
-MoviePlayerMPEG::MoviePlayerMPEG(Sword2Engine *vm, const char *name)
+MoviePlayerDXA::MoviePlayerDXA(Sword2Engine *vm, const char *name)
: MoviePlayer(vm, name) {
-#ifdef BACKEND_8BIT
- debug(0, "Creating MPEG cutscene player (8-bit)");
-#else
- debug(0, "Creating MPEG cutscene player (16-bit)");
-#endif
+ debug(0, "Creating DXA cutscene player");
}
-MoviePlayerMPEG::~MoviePlayerMPEG() {
- delete _anim;
- _anim = NULL;
+MoviePlayerDXA::~MoviePlayerDXA() {
+ closeFile();
}
-bool MoviePlayerMPEG::load() {
- if (!MoviePlayer::load())
- return false;
-
- _anim = new AnimationState(_vm, this);
-
- if (!_anim->init(_name)) {
- delete _anim;
- _anim = NULL;
- return false;
- }
-
-#ifdef BACKEND_8BIT
- _frameBuffer = _vm->_screen->getScreen();
-#endif
-
+bool MoviePlayerDXA::decodeFrame() {
+ decodeNextFrame();
+ copyFrameToBuffer(_frameBuffer, _frameX, _frameY, _vm->_screen->getScreenWide());
return true;
}
-bool MoviePlayerMPEG::decodeFrame() {
- bool result = _anim->decodeFrame();
-
-#ifdef BACKEND_8BIT
- _frameWidth = _anim->getFrameWidth();
- _frameHeight = _anim->getFrameHeight();
-
- _frameX = (_vm->_screen->getScreenWide() - _frameWidth) / 2;
- _frameY = (_vm->_screen->getScreenDeep() - _frameHeight) / 2;
-#endif
-
- return result;
-}
-
-AnimationState::AnimationState(Sword2Engine *vm, MoviePlayer *player)
- : BaseAnimationState(vm->_system, 640, 480) {
- _vm = vm;
- _player = player;
-}
-
-AnimationState::~AnimationState() {
-}
-
-#ifdef BACKEND_8BIT
-
-void AnimationState::setPalette(byte *pal) {
- _player->updatePalette(pal, false);
-}
-
-#else
-
-void MoviePlayerMPEG::handleScreenChanged() {
- _anim->handleScreenChanged();
-}
-
-void MoviePlayerMPEG::clearFrame() {
- _anim->clearFrame();
-}
-
-void MoviePlayerMPEG::drawFrame() {
-}
-
-void MoviePlayerMPEG::updateScreen() {
- _anim->updateScreen();
-}
-
-void MoviePlayerMPEG::drawTextObject() {
- if (_textObject.textMem && _textSurface) {
- _anim->drawTextObject(&_textObject.textSprite, _textSurface);
- }
-}
-
-void MoviePlayerMPEG::undrawTextObject() {
- // As long as we only have subtitles for full-sized cutscenes, we don't
- // really need to implement this function.
-}
-
-void AnimationState::drawTextObject(SpriteInfo *s, byte *src) {
- int moviePitch = _movieScale * _movieWidth;
- int textX = _movieScale * s->x;
- int textY = _movieScale * (_frameHeight - s->h - 12);
+bool MoviePlayerDXA::load() {
+ if (!MoviePlayer::load())
+ return false;
- OverlayColor *dst = _overlay + textY * moviePitch + textX;
+ char filename[20];
- Graphics::PixelFormat format = _sys->getOverlayFormat();
- OverlayColor pen = format.RGBToColor(255, 255, 255);
- OverlayColor border = format.RGBToColor(0, 0, 0);
+ snprintf(filename, sizeof(filename), "%s.dxa", _name);
- // TODO: Use the AdvMame scalers for the text? Pre-scale it?
+ if (loadFile(filename)) {
+ // The Broken Sword games always use external audio tracks.
+ if (_fileStream->readUint32BE() != MKID_BE('NULL'))
+ return false;
- for (int y = 0; y < s->h; y++) {
- OverlayColor *ptr = dst;
+ _frameBuffer = _vm->_screen->getScreen();
- for (int x = 0; x < s->w; x++) {
- switch (src[x]) {
- case 1:
- *ptr++ = border;
- if (_movieScale > 1) {
- *ptr++ = border;
- if (_movieScale > 2)
- *ptr++ = border;
- }
- break;
- case 255:
- *ptr++ = pen;
- if (_movieScale > 1) {
- *ptr++ = pen;
- if (_movieScale > 2)
- *ptr++ = pen;
- }
- break;
- default:
- ptr += _movieScale;
- break;
- }
- }
+ _frameWidth = getWidth();
+ _frameHeight = getHeight();
- if (_movieScale > 1) {
- memcpy(dst + moviePitch, dst, _movieScale * s->w * sizeof(OverlayColor));
- if (_movieScale > 2)
- memcpy(dst + 2 * moviePitch, dst, _movieScale * s->w * sizeof(OverlayColor));
- }
+ _frameX = (_vm->_screen->getScreenWide() - _frameWidth) / 2;
+ _frameY = (_vm->_screen->getScreenDeep() - _frameHeight) / 2;
- dst += _movieScale * moviePitch;
- src += s->w;
+ return true;
}
-}
-#endif
-
-void AnimationState::clearFrame() {
-#ifdef BACKEND_8BIT
- memset(_vm->_screen->getScreen(), 0, _movieWidth * _movieHeight);
-#else
- Graphics::PixelFormat format = _sys->getOverlayFormat();
- OverlayColor black = format.RGBToColor(0, 0, 0);
-
- for (int i = 0; i < _movieScale * _movieWidth * _movieScale * _movieHeight; i++)
- _overlay[i] = black;
-#endif
-}
-
-void AnimationState::drawYUV(int width, int height, byte *const *dat) {
- _frameWidth = width;
- _frameHeight = height;
-
-#ifdef BACKEND_8BIT
- byte *buf = _vm->_screen->getScreen() + ((480 - height) / 2) * RENDERWIDE + (640 - width) / 2;
-
- int x, y;
- int ypos = 0;
- int cpos = 0;
- int linepos = 0;
-
- for (y = 0; y < height; y += 2) {
- for (x = 0; x < width; x += 2) {
- int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH + 1)) + ((dat[1][cpos] + ROUNDADD) >> SHIFT)) * (BITDEPTH + 1);
- cpos++;
-
- buf[linepos ] = _lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
- buf[RENDERWIDE + linepos++] = _lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
- buf[linepos ] = _lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
- buf[RENDERWIDE + linepos++] = _lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
- }
- linepos += (2 * RENDERWIDE - width);
- ypos += width;
- }
-#else
- plotYUV(width, height, dat);
-#endif
+ return false;
}
#endif
@@ -802,10 +606,10 @@ bool MoviePlayerDummy::decodeFrame() {
byte msgNoCutscenesRU[] = "Po\344uk - to\344\345ko pev\345: hagmute k\344abuwy Ucke\343n, u\344u nocetute ca\343t npoekta u ckava\343te budeo po\344uku";
-#if defined(USE_MPEG2) || defined(USE_ZLIB)
+#if defined(USE_ZLIB)
byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or visit www.scummvm.org to download cutscene videos";
#else
- byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with MPEG2 or ZLib support";
+ byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with ZLib support";
#endif
byte *msg;
@@ -885,6 +689,12 @@ void MoviePlayerDummy::undrawTextObject() {
MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) {
static char filename[20];
+ snprintf(filename, sizeof(filename), "%s.smk", name);
+
+ if (Common::File::exists(filename)) {
+ return new MoviePlayerSMK(vm, name);
+ }
+
#ifdef USE_ZLIB
snprintf(filename, sizeof(filename), "%s.dxa", name);
@@ -893,13 +703,12 @@ MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) {
}
#endif
-#ifdef USE_MPEG2
snprintf(filename, sizeof(filename), "%s.mp2", name);
if (Common::File::exists(filename)) {
- return new MoviePlayerMPEG(vm, name);
+ GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK");
+ dialog.runModal();
}
-#endif
return new MoviePlayerDummy(vm, name);
}
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index da59a4c509..8b6a015037 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -29,7 +29,7 @@
#define SWORD2_ANIMATION_H
#include "graphics/video/dxa_player.h"
-#include "graphics/video/mpeg_player.h"
+#include "graphics/video/smk_player.h"
#include "sound/mixer.h"
#include "sword2/screen.h"
@@ -97,7 +97,6 @@ protected:
bool _seamless;
int _framesSkipped;
- bool _forceFrame;
static const MovieInfo _movies[];
@@ -126,7 +125,6 @@ public:
MoviePlayer(Sword2Engine *vm, const char *name);
virtual ~MoviePlayer();
- void updatePalette(byte *pal, bool packed = true);
virtual bool load();
bool userInterrupt();
void play(SequenceTextInfo *textList, uint32 numLines, int32 leadIn, int32 leadOut);
@@ -148,57 +146,20 @@ public:
bool load();
};
-#ifdef USE_MPEG2
-class AnimationState : public ::Graphics::BaseAnimationState {
-private:
- Sword2Engine *_vm;
- MoviePlayer *_player;
-
-public:
- AnimationState(Sword2Engine *vm, MoviePlayer *player);
- ~AnimationState();
-
-#ifndef BACKEND_8BIT
- void drawTextObject(SpriteInfo *s, byte *src);
-#endif
-
- void clearFrame();
-
-private:
- void drawYUV(int width, int height, byte *const *dat);
-
-#ifdef BACKEND_8BIT
- void setPalette(byte *pal);
-#endif
-};
-
-class MoviePlayerMPEG : public MoviePlayer {
+class MoviePlayerSMK : public MoviePlayer, ::Graphics::SMKPlayer {
protected:
- AnimationState *_anim;
-
- virtual bool decodeFrame();
-
-#ifndef BACKEND_8BIT
- void handleScreenChanged();
- void clearFrame();
- void drawFrame();
- void updateScreen();
- void drawTextObject();
- void undrawTextObject();
-#endif
+ bool decodeFrame();
public:
- MoviePlayerMPEG(Sword2Engine *vm, const char *name);
- ~MoviePlayerMPEG();
+ MoviePlayerSMK(Sword2Engine *vm, const char *name);
+ ~MoviePlayerSMK();
bool load();
};
-#endif
#ifdef USE_ZLIB
class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXAPlayer {
protected:
- void setPalette(byte *pal);
bool decodeFrame();
public:
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 9fdc10123d..71a949fe88 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -252,9 +252,11 @@ Sword2Engine::Sword2Engine(OSystem *syst) : Engine(syst) {
Common::File::addDefaultDirectory(_gameDataDir.getChild("CLUSTERS"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("SWORD2"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("SMACKS"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("sword2"));
Common::File::addDefaultDirectory(_gameDataDir.getChild("video"));
+ Common::File::addDefaultDirectory(_gameDataDir.getChild("smacks"));
if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword2demo"))
_features = GF_DEMO;
diff --git a/graphics/video/video_player.h b/graphics/video/video_player.h
index 3073538cab..2fe90210cd 100644
--- a/graphics/video/video_player.h
+++ b/graphics/video/video_player.h
@@ -141,6 +141,12 @@ public:
*/
virtual bool decodeNextFrame() = 0;
+ /**
+ * Used to read the sound header from DXA files. It's not pretty,
+ * but it's slightly better than exposing _fileStream
+ */
+ uint32 readSoundHeader() { return _fileStream->readUint32BE(); }
+
protected:
struct {
uint32 width;