From 960d79ed5acde4d1dda7c123e224b551c7df7260 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Thu, 17 May 2018 01:28:06 +1000 Subject: ILLUSIONS: DUCKMAN: Implement video player (cherry picked from commit 62577c8) --- engines/illusions/duckman/duckman_videoplayer.cpp | 100 +++++++++++++++++++++ engines/illusions/duckman/duckman_videoplayer.h | 49 ++++++++++ engines/illusions/duckman/illusions_duckman.cpp | 18 ++++ engines/illusions/duckman/illusions_duckman.h | 6 ++ .../illusions/duckman/scriptopcodes_duckman.cpp | 14 +-- engines/illusions/illusions.h | 1 + engines/illusions/module.mk | 1 + engines/illusions/screen.cpp | 2 +- engines/illusions/screen.h | 1 + 9 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 engines/illusions/duckman/duckman_videoplayer.cpp create mode 100644 engines/illusions/duckman/duckman_videoplayer.h (limited to 'engines') diff --git a/engines/illusions/duckman/duckman_videoplayer.cpp b/engines/illusions/duckman/duckman_videoplayer.cpp new file mode 100644 index 0000000000..ae17d32381 --- /dev/null +++ b/engines/illusions/duckman/duckman_videoplayer.cpp @@ -0,0 +1,100 @@ +/* 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. + * + */ + +#include "illusions/duckman/illusions_duckman.h" +#include "illusions/duckman/duckman_videoplayer.h" +#include "illusions/input.h" +#include "illusions/screen.h" +#include "engines/util.h" + +namespace Illusions { + +// DuckmanVideoPlayer + +DuckmanVideoPlayer::DuckmanVideoPlayer(IllusionsEngine_Duckman *vm) + : _vm(vm), _videoDecoder(0) { +} + +DuckmanVideoPlayer::~DuckmanVideoPlayer() { + delete _videoDecoder; +} + +void DuckmanVideoPlayer::start(uint32 videoId, uint32 callingThreadId) { + debug(0, "DuckmanVideoPlayer::play(%08X, %08X)", videoId, callingThreadId); + _callingThreadId = callingThreadId; + _vm->_input->discardAllEvents(); + Common::String filename = Common::String::format("%08x.avi", videoId); + _videoDecoder = new Video::AVIDecoder(); + if (!_videoDecoder->loadFile(filename)) { + delete _videoDecoder; + _videoDecoder = 0; + warning("Unable to open video %s", filename.c_str()); + return; + } + _videoDecoder->start(); +} + +void DuckmanVideoPlayer::stop() { + _vm->_input->discardAllEvents(); + delete _videoDecoder; + _videoDecoder = 0; + if (_callingThreadId != 0) { + _vm->notifyThreadId(_callingThreadId); + _callingThreadId = 0; + } +} + +void DuckmanVideoPlayer::update() { + if (_vm->_input->pollEvent(kEventSkip) || _videoDecoder->endOfVideo()) { + stop(); + } else if (_videoDecoder->needsUpdate()) { + const Graphics::Surface *frame = _videoDecoder->decodeNextFrame(); + Graphics::Surface *backSurface = _vm->_screen->getBackSurface(); + if (frame->format.bytesPerPixel == g_system->getScreenFormat().bytesPerPixel) { + const int width = MIN(frame->w, backSurface->w); + const int height = MIN(frame->h, backSurface->h); + const byte *src = (const byte*)frame->getPixels(); + byte *dest = (byte*)backSurface->getPixels(); + for (int yc = 0; yc < height; ++yc) { + memcpy(dest, src, width); + src += frame->pitch; + dest += backSurface->pitch; + } + } + if (_videoDecoder->hasDirtyPalette()) { + const byte *palette = _videoDecoder->getPalette(); + byte palette4[1024]; + for (uint i = 0; i < 256; ++i) { + palette4[i * 4 + 0] = palette[i * 3 + 0]; + palette4[i * 4 + 1] = palette[i * 3 + 1]; + palette4[i * 4 + 2] = palette[i * 3 + 2]; + } + _vm->_screenPalette->setPalette(palette4, 1, 256); + } + } +} + +bool DuckmanVideoPlayer::isPlaying() const { + return _videoDecoder != 0; +} + +} // End of namespace Illusions diff --git a/engines/illusions/duckman/duckman_videoplayer.h b/engines/illusions/duckman/duckman_videoplayer.h new file mode 100644 index 0000000000..d2d7f1fc23 --- /dev/null +++ b/engines/illusions/duckman/duckman_videoplayer.h @@ -0,0 +1,49 @@ +/* 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. + * + */ + +#ifndef ILLUSIONS_DUCKMAN_VIDEOPLAYER_H +#define ILLUSIONS_DUCKMAN_VIDEOPLAYER_H + +#include "illusions/illusions.h" +#include "video/avi_decoder.h" + +namespace Illusions { + +class IllusionsEngine_Duckman; + +class DuckmanVideoPlayer { +public: + DuckmanVideoPlayer(IllusionsEngine_Duckman *vm); + ~DuckmanVideoPlayer(); + void start(uint32 videoId, uint32 callingThreadId); + void stop(); + void update(); + bool isPlaying() const; +public: + IllusionsEngine_Duckman *_vm; + Video::VideoDecoder *_videoDecoder; + uint32 _callingThreadId; +}; + +} // End of namespace Illusions + +#endif // ILLUSIONS_DUCKMAN_VIDEOPLAYER_H diff --git a/engines/illusions/duckman/illusions_duckman.cpp b/engines/illusions/duckman/illusions_duckman.cpp index 9eae7a5514..d22b947731 100644 --- a/engines/illusions/duckman/illusions_duckman.cpp +++ b/engines/illusions/duckman/illusions_duckman.cpp @@ -26,6 +26,7 @@ #include "illusions/duckman/gamestate_duckman.h" #include "illusions/duckman/menusystem_duckman.h" #include "illusions/duckman/scriptopcodes_duckman.h" +#include "illusions/duckman/duckman_videoplayer.h" #include "illusions/actor.h" #include "illusions/camera.h" #include "illusions/cursor.h" @@ -116,6 +117,7 @@ Common::Error IllusionsEngine_Duckman::run() { _updateFunctions = new UpdateFunctions(); _soundMan = new SoundMan(this); _menuSystem = new DuckmanMenuSystem(this); + _videoPlayer = new DuckmanVideoPlayer(this); _gameState = new Duckman_GameState(this); _fader = new Fader(); @@ -215,6 +217,7 @@ Common::Error IllusionsEngine_Duckman::run() { delete _gameState; delete _menuSystem; + delete _videoPlayer; delete _soundMan; delete _updateFunctions; delete _threads; @@ -273,6 +276,7 @@ void IllusionsEngine_Duckman::initInput() { (this, &IllusionsEngine_Duckman::callback)); void IllusionsEngine_Duckman::initUpdateFunctions() { + UPDATEFUNCTION(25, 0, updateVideoPlayer); UPDATEFUNCTION(30, 0, updateScript); UPDATEFUNCTION(50, 0, updateActors); UPDATEFUNCTION(60, 0, updateSequences); @@ -412,6 +416,20 @@ void IllusionsEngine_Duckman::unpauseFader() { _fader->_paused = false; } +int IllusionsEngine_Duckman::updateVideoPlayer(uint flags) { + if (_videoPlayer->isPlaying()) + _videoPlayer->update(); + return kUFNext; +} + +void IllusionsEngine_Duckman::playVideo(uint32 videoId, uint32 callingThreadId) { + _videoPlayer->start(videoId, callingThreadId); +} + +bool IllusionsEngine_Duckman::isVideoPlaying() { + return _videoPlayer->isPlaying(); +} + void IllusionsEngine_Duckman::setDefaultTextCoords() { WidthHeight dimensions; dimensions._width = 300; diff --git a/engines/illusions/duckman/illusions_duckman.h b/engines/illusions/duckman/illusions_duckman.h index 46bf15e3d8..d4583bccef 100644 --- a/engines/illusions/duckman/illusions_duckman.h +++ b/engines/illusions/duckman/illusions_duckman.h @@ -33,6 +33,7 @@ class Dictionary; class ScriptStack; class DuckmanDialogSystem; class DuckmanMenuSystem; +class DuckmanVideoPlayer; struct Cursor_Duckman { int _gameState; @@ -101,6 +102,7 @@ public: ScreenShaker *_screenShaker; DuckmanMenuSystem *_menuSystem; + DuckmanVideoPlayer *_videoPlayer; void initInput(); @@ -117,6 +119,10 @@ public: void pauseFader(); void unpauseFader(); + int updateVideoPlayer(uint flags); + void playVideo(uint32 videoId, uint32 callingThreadId); + bool isVideoPlaying(); + void setDefaultTextCoords(); void loadSpecialCode(uint32 resId); diff --git a/engines/illusions/duckman/scriptopcodes_duckman.cpp b/engines/illusions/duckman/scriptopcodes_duckman.cpp index 8764f9277f..01a9c962e5 100644 --- a/engines/illusions/duckman/scriptopcodes_duckman.cpp +++ b/engines/illusions/duckman/scriptopcodes_duckman.cpp @@ -583,13 +583,13 @@ void ScriptOpcodes_Duckman::opStartCursorHoldingObject(ScriptThread *scriptThrea void ScriptOpcodes_Duckman::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall) { ARG_SKIP(2); - ARG_UINT32(objectId); - // NOTE This has no attached objectId or priority - _vm->playVideo(0, objectId, 0, opCall._threadId); - + ARG_UINT32(videoId); +#if 1 // TODO DEBUG Set to 0 to skip videos + _vm->playVideo(videoId, opCall._threadId); +#else //DEBUG Resume calling thread, later done by the video player _vm->notifyThreadId(opCall._threadId); - +#endif } void ScriptOpcodes_Duckman::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) { @@ -640,7 +640,7 @@ void ScriptOpcodes_Duckman::opStopMidiMusic(ScriptThread *scriptThread, OpCall & void ScriptOpcodes_Duckman::opFadeMidiMusic(ScriptThread *scriptThread, OpCall &opCall) { ARG_INT16(duration); ARG_INT16(finalVolume); - //FIXME _vm->_soundMan->fadeMidiMusic(finalVolume, duration); + // TODO _vm->fadeMidiMusic(2, finalVolume, duration, opCall._threadId); } void ScriptOpcodes_Duckman::opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall) { @@ -684,7 +684,7 @@ void ScriptOpcodes_Duckman::opQuitGame(ScriptThread *scriptThread, OpCall &opCal void ScriptOpcodes_Duckman::opResetGame(ScriptThread *scriptThread, OpCall &opCall) { _vm->reset(); _vm->_input->activateButton(0xFFFF); - _vm->_soundMan->stopMidiMusic(); + // TODO _vm->stopMusic(); // TODO _vm->_gameStates->clear(); } diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h index 438ab04e34..a6f9ac752e 100644 --- a/engines/illusions/illusions.h +++ b/engines/illusions/illusions.h @@ -176,6 +176,7 @@ public: virtual void clearFader() {}; virtual void pauseFader() {}; virtual void unpauseFader() {}; + virtual bool isVideoPlaying() { return false; } void setCurrFontId(uint32 fontId); bool checkActiveTalkThreads(); diff --git a/engines/illusions/module.mk b/engines/illusions/module.mk index 1f164cdff9..d1272f4417 100644 --- a/engines/illusions/module.mk +++ b/engines/illusions/module.mk @@ -21,6 +21,7 @@ MODULE_OBJS := \ duckman/duckman_inventory.o \ duckman/duckman_screenshakereffects.o \ duckman/duckman_specialcode.o \ + duckman/duckman_videoplayer.o \ duckman/gamestate_duckman.o \ duckman/illusions_duckman.o \ duckman/menusystem_duckman.o \ diff --git a/engines/illusions/screen.cpp b/engines/illusions/screen.cpp index 6a991cd782..9979cd1fa8 100644 --- a/engines/illusions/screen.cpp +++ b/engines/illusions/screen.cpp @@ -423,7 +423,7 @@ void Screen::updateSprites() { _drawQueue->drawAll(); if (_isScreenOffsetActive) clearScreenOffsetAreas(); - if (!_displayOn) // TODO Check if a video is playing then don't do it + if (!_displayOn && !_vm->isVideoPlaying()) _backSurface->fillRect(Common::Rect(_backSurface->w, _backSurface->h), 0); g_system->copyRectToScreen((byte*)_backSurface->getBasePtr(0, 0), _backSurface->pitch, 0, 0, _backSurface->w, _backSurface->h); } diff --git a/engines/illusions/screen.h b/engines/illusions/screen.h index 4a89c790a4..63750ce635 100644 --- a/engines/illusions/screen.h +++ b/engines/illusions/screen.h @@ -168,6 +168,7 @@ public: uint16 getColorKey2() const { return _colorKey2; } int16 getScreenWidth() const { return _backSurface->w; } int16 getScreenHeight() const { return _backSurface->h; } + Graphics::Surface *getBackSurface() const { return _backSurface; } virtual void decompressSprite(SpriteDecompressQueueItem *item) = 0; virtual void drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) = 0; virtual void drawText(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 *text, uint count) = 0; -- cgit v1.2.3