diff options
Diffstat (limited to 'engines/sword1/animation.cpp')
-rw-r--r-- | engines/sword1/animation.cpp | 147 |
1 files changed, 130 insertions, 17 deletions
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index e274e02cfd..1e2964054a 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -37,6 +37,11 @@ #include "gui/message.h" +#include "video/psx_decoder.h" +#include "video/smk_decoder.h" + +#include "engines/util.h" + namespace Sword1 { static const char *const sequenceList[20] = { @@ -62,6 +67,31 @@ static const char *const sequenceList[20] = { "credits", // 19 CD2 credits, to follow "finale" sequence }; +// This is the list of the names of the PlayStation videos +// TODO: fight.str, flashy.str, +static const char *const sequenceListPSX[20] = { + "e_ferr1", + "ladder1", + "steps1", + "sewer1", + "e_intro1", + "river1", + "truck1", + "grave1", + "montfcn1", + "tapesty1", + "ireland1", + "e_fin1", + "e_hist1", + "spanish1", + "well1", + "candle1", + "geodrop1", + "vulture1", + "", // demo video not present + "" // credits are not a video +}; + /////////////////////////////////////////////////////////////////////////////// // Basic movie player /////////////////////////////////////////////////////////////////////////////// @@ -150,6 +180,21 @@ bool MoviePlayer::load(uint32 id) { case kVideoDecoderSMK: filename = Common::String::format("%s.smk", sequenceList[id]); break; + case kVideoDecoderPSX: + filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]); + + // Need to switch to true color + initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0); + + // Need to load here in case it fails in which case we'd need + // to go back to paletted mode + if (_decoder->loadFile(filename)) { + return true; + } else { + initGraphics(g_system->getWidth(), g_system->getHeight(), true); + return false; + } + break; } return _decoder->loadFile(filename.c_str()); @@ -187,6 +232,11 @@ void MoviePlayer::play() { } void MoviePlayer::performPostProcessing(byte *screen) { + // TODO: We don't support the PSX stream videos yet + // nor using the PSX fonts to display subtitles. + if (_vm->isPsx()) + return; + if (!_movieTexts.empty()) { if (_decoder->getCurFrame() == _movieTexts.front()._startFrame) { _textMan->makeTextSprite(2, (const uint8 *)_movieTexts.front()._text.c_str(), 600, LETTER_COL); @@ -215,10 +265,10 @@ void MoviePlayer::performPostProcessing(byte *screen) { for (x = 0; x < _textWidth; x++) { switch (src[x]) { case BORDER_COL: - dst[x] = findBlackPalIndex(); + dst[x] = getBlackColor(); break; case LETTER_COL: - dst[x] = findTextColorPalIndex(); + dst[x] = findTextColor(); break; } } @@ -238,12 +288,12 @@ void MoviePlayer::performPostProcessing(byte *screen) { for (y = 0; y < _textHeight; y++) { if (_textY + y < frameY || _textY + y >= frameY + frameHeight) { - memset(dst + _textX, findBlackPalIndex(), _textWidth); + memset(dst + _textX, getBlackColor(), _textWidth); } else { if (frameX > _textX) - memset(dst + _textX, findBlackPalIndex(), frameX - _textX); + memset(dst + _textX, getBlackColor(), frameX - _textX); if (frameX + frameWidth < _textX + _textWidth) - memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + _textWidth - (frameX + frameWidth)); + memset(dst + frameX + frameWidth, getBlackColor(), _textX + _textWidth - (frameX + frameWidth)); } dst += _system->getWidth(); @@ -255,14 +305,19 @@ void MoviePlayer::performPostProcessing(byte *screen) { } bool MoviePlayer::playVideo() { + bool skipped = false; uint16 x = (g_system->getWidth() - _decoder->getWidth()) / 2; uint16 y = (g_system->getHeight() - _decoder->getHeight()) / 2; - while (!_vm->shouldQuit() && !_decoder->endOfVideo()) { + while (!_vm->shouldQuit() && !_decoder->endOfVideo() && !skipped) { if (_decoder->needsUpdate()) { const Graphics::Surface *frame = _decoder->decodeNextFrame(); - if (frame) - _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + if (frame) { + if (_decoderType == kVideoDecoderPSX) + drawFramePSX(frame); + else + _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + } if (_decoder->hasDirtyPalette()) { _decoder->setSystemPalette(); @@ -362,19 +417,40 @@ bool MoviePlayer::playVideo() { Common::Event event; while (_vm->_system->getEventManager()->pollEvent(event)) if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) - return false; + skipped = true; _vm->_system->delayMillis(10); } - return !_vm->shouldQuit(); + if (_decoderType == kVideoDecoderPSX) { + // Need to jump back to paletted color + initGraphics(g_system->getWidth(), g_system->getHeight(), true); + } + + return !_vm->shouldQuit() && !skipped; } -byte MoviePlayer::findBlackPalIndex() { - return _black; +uint32 MoviePlayer::getBlackColor() { + return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black; } - -byte MoviePlayer::findTextColorPalIndex() { + +uint32 MoviePlayer::findTextColor() { + if (_decoderType == kVideoDecoderPSX) { + // We're in true color mode, so return the actual colors + switch (_textColor) { + case 1: + return g_system->getScreenFormat().RGBToColor(248, 252, 248); + case 2: + return g_system->getScreenFormat().RGBToColor(184, 188, 184); + case 3: + return g_system->getScreenFormat().RGBToColor(200, 120, 184); + case 4: + return g_system->getScreenFormat().RGBToColor(80, 152, 184); + } + + return g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF); + } + switch (_textColor) { case 1: return _c1Color; @@ -413,6 +489,23 @@ void MoviePlayer::convertColor(byte r, byte g, byte b, float &h, float &s, float } } +void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) { + // The PSX videos have half resolution + + Graphics::Surface scaledFrame; + scaledFrame.create(frame->w, frame->h * 2, frame->format); + + for (int y = 0; y < scaledFrame.h; y++) + memcpy(scaledFrame.getBasePtr(0, y), frame->getBasePtr(0, y / 2), scaledFrame.w * scaledFrame.format.bytesPerPixel); + + uint16 x = (g_system->getWidth() - scaledFrame.w) / 2; + uint16 y = (g_system->getHeight() - scaledFrame.h) / 2; + + _vm->_system->copyRectToScreen((byte *)scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); + + scaledFrame.free(); +} + DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle) : _mixer(mixer), _bgSoundHandle(bgSoundHandle) { } @@ -432,6 +525,24 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan * Common::String filename; Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle; + // For the PSX version, we'll try the PlayStation stream files + if (vm->isPsx()) { + // The demo uses the normal file names + filename = ((vm->_systemVars.isDemo) ? Common::String(sequenceList[id]) : Common::String(sequenceListPSX[id])) + ".str"; + + if (Common::File::exists(filename)) { +#ifdef USE_RGB_COLOR + // All BS1 PSX videos run the videos at 2x speed + Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x); + return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, psxDecoder, kVideoDecoderPSX); +#else + GUI::MessageDialog dialog(Common::String::format(_("PSX stream cutscene '%s' cannot be played in paletted mode"), filename.c_str()), _("OK")); + dialog.runModal(); + return 0; +#endif + } + } + filename = Common::String::format("%s.smk", sequenceList[id]); if (Common::File::exists(filename)) { @@ -461,9 +572,11 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan * return NULL; } - Common::String buf = Common::String::format(_("Cutscene '%s' not found"), sequenceList[id]); - GUI::MessageDialog dialog(buf, _("OK")); - dialog.runModal(); + if (!vm->isPsx() || scumm_stricmp(sequenceList[id], "enddemo") != 0) { + Common::String buf = Common::String::format(_("Cutscene '%s' not found"), sequenceList[id]); + GUI::MessageDialog dialog(buf, _("OK")); + dialog.runModal(); + } return NULL; } |