From 25a303a52967220e8f838b4f185c2fc8f8092f47 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Thu, 17 May 2018 05:27:28 +1000 Subject: ILLUSIONS: BBDOU: Implement video player (cherry picked from commit aab0b29) --- engines/illusions/bbdou/bbdou_videoplayer.cpp | 109 ++++++++++++++++++++++++ engines/illusions/bbdou/bbdou_videoplayer.h | 52 +++++++++++ engines/illusions/bbdou/illusions_bbdou.cpp | 18 ++++ engines/illusions/bbdou/illusions_bbdou.h | 7 ++ engines/illusions/bbdou/scriptopcodes_bbdou.cpp | 7 +- engines/illusions/module.mk | 1 + 6 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 engines/illusions/bbdou/bbdou_videoplayer.cpp create mode 100644 engines/illusions/bbdou/bbdou_videoplayer.h diff --git a/engines/illusions/bbdou/bbdou_videoplayer.cpp b/engines/illusions/bbdou/bbdou_videoplayer.cpp new file mode 100644 index 0000000000..ba578904f2 --- /dev/null +++ b/engines/illusions/bbdou/bbdou_videoplayer.cpp @@ -0,0 +1,109 @@ +/* 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/bbdou/illusions_bbdou.h" +#include "illusions/bbdou/bbdou_videoplayer.h" +#include "illusions/actor.h" +#include "illusions/dictionary.h" +#include "illusions/input.h" +#include "illusions/screen.h" +#include "engines/util.h" + +namespace Illusions { + +// BBDOUVideoPlayer + +BBDOUVideoPlayer::BBDOUVideoPlayer(IllusionsEngine_BBDOU *vm) + : _vm(vm), _videoDecoder(0), _callingThreadId(0), _objectId(0) { +} + +BBDOUVideoPlayer::~BBDOUVideoPlayer() { + delete _videoDecoder; +} + +void BBDOUVideoPlayer::start(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId) { + debug(0, "BBDOUVideoPlayer::play(%08X, %08X, %d, %08X)", videoId, objectId, priority, callingThreadId); + notifyCallingThread(); + _objectId = objectId; + _callingThreadId = callingThreadId; + Control *videoControl = _vm->_dict->getObjectControl(objectId); + videoControl->_flags |= 0x0008; + _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()); + notifyCallingThread(); + return; + } + _videoDecoder->start(); +} + +void BBDOUVideoPlayer::stop() { + _vm->_input->discardAllEvents(); + delete _videoDecoder; + _videoDecoder = 0; + notifyCallingThread(); + _objectId = 0; +} + +void BBDOUVideoPlayer::update() { + if (_vm->_input->pollEvent(kEventAbort) || _videoDecoder->endOfVideo()) { + stop(); + } else if (_videoDecoder->needsUpdate()) { + Control *videoControl = _vm->_dict->getObjectControl(_objectId); + const Graphics::Surface *frame = _videoDecoder->decodeNextFrame(); + Graphics::Surface *backSurface = videoControl->_actor->_surface; + if (frame->format.bytesPerPixel == g_system->getScreenFormat().bytesPerPixel) { + const int width = MIN(frame->w, backSurface->w) * frame->format.bytesPerPixel; + 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; + } + } + ActorType *actorType = _vm->_dict->findActorType(videoControl->_actorTypeId); + videoControl->_actor->_frameIndex = 1; + videoControl->_actor->_surfInfo = actorType->_surfInfo; + videoControl->appearActor(); + videoControl->deactivateObject(); + videoControl->_actor->_flags &= ~0x2000; + } +} + +bool BBDOUVideoPlayer::isPlaying() const { + return _videoDecoder != 0; +} + +void BBDOUVideoPlayer::notifyCallingThread() { + if (_callingThreadId != 0) { + _vm->notifyThreadId(_callingThreadId); + _callingThreadId = 0; + } +} + +} // End of namespace Illusions diff --git a/engines/illusions/bbdou/bbdou_videoplayer.h b/engines/illusions/bbdou/bbdou_videoplayer.h new file mode 100644 index 0000000000..7ad149a5a1 --- /dev/null +++ b/engines/illusions/bbdou/bbdou_videoplayer.h @@ -0,0 +1,52 @@ +/* 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_BBDOU_VIDEOPLAYER_H +#define ILLUSIONS_BBDOU_VIDEOPLAYER_H + +#include "illusions/illusions.h" +#include "video/avi_decoder.h" + +namespace Illusions { + +class IllusionsEngine_BBDOU; + +class BBDOUVideoPlayer { +public: + BBDOUVideoPlayer(IllusionsEngine_BBDOU *vm); + ~BBDOUVideoPlayer(); + void start(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId); + void stop(); + void update(); + bool isPlaying() const; +public: + IllusionsEngine_BBDOU *_vm; + Video::VideoDecoder *_videoDecoder; + uint32 _objectId; + int _priority; + uint32 _callingThreadId; + void notifyCallingThread(); +}; + +} // End of namespace Illusions + +#endif // ILLUSIONS_BBDOU_VIDEOPLAYER_H diff --git a/engines/illusions/bbdou/illusions_bbdou.cpp b/engines/illusions/bbdou/illusions_bbdou.cpp index 0c16ad5959..52e41daede 100644 --- a/engines/illusions/bbdou/illusions_bbdou.cpp +++ b/engines/illusions/bbdou/illusions_bbdou.cpp @@ -21,6 +21,7 @@ */ #include "illusions/bbdou/illusions_bbdou.h" +#include "illusions/bbdou/bbdou_videoplayer.h" #include "illusions/actor.h" #include "illusions/camera.h" #include "illusions/cursor.h" @@ -166,6 +167,7 @@ Common::Error IllusionsEngine_BBDOU::run() { _threads = new ThreadList(this); _updateFunctions = new UpdateFunctions(); _soundMan = new SoundMan(this); + _videoPlayer = new BBDOUVideoPlayer(this); _screen->setColorKey1(0xF81F); @@ -215,6 +217,7 @@ Common::Error IllusionsEngine_BBDOU::run() { delete _stack; delete _scriptOpcodes; + delete _videoPlayer; delete _soundMan; delete _updateFunctions; delete _threads; @@ -279,6 +282,7 @@ void IllusionsEngine_BBDOU::initUpdateFunctions() { UPDATEFUNCTION(50, 0, updateActors); UPDATEFUNCTION(60, 0, updateSequences); UPDATEFUNCTION(70, 0, updateGraphics); + UPDATEFUNCTION(70, 0, updateVideoPlayer); UPDATEFUNCTION(90, 0, updateSprites); UPDATEFUNCTION(120, 0, updateSoundMan); } @@ -314,6 +318,20 @@ uint32 IllusionsEngine_BBDOU::causeTrigger(uint32 sceneId, uint32 verbId, uint32 return causeThreadId; } +int IllusionsEngine_BBDOU::updateVideoPlayer(uint flags) { + if (_videoPlayer->isPlaying()) + _videoPlayer->update(); + return kUFNext; +} + +void IllusionsEngine_BBDOU::playVideo(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId) { + _videoPlayer->start(videoId, objectId, priority, callingThreadId); +} + +bool IllusionsEngine_BBDOU::isVideoPlaying() { + return _videoPlayer->isPlaying(); +} + void IllusionsEngine_BBDOU::setDefaultTextCoords() { WidthHeight dimensions; dimensions._width = 480; diff --git a/engines/illusions/bbdou/illusions_bbdou.h b/engines/illusions/bbdou/illusions_bbdou.h index ddbb8278a4..f1843f716f 100644 --- a/engines/illusions/bbdou/illusions_bbdou.h +++ b/engines/illusions/bbdou/illusions_bbdou.h @@ -33,6 +33,7 @@ namespace Illusions { class Dictionary; class ScriptMan; class ScriptStack; +class BBDOUVideoPlayer; struct ActiveScene { uint32 _sceneId; @@ -72,6 +73,8 @@ public: uint32 _theThreadId; uint32 _globalSceneId; + BBDOUVideoPlayer *_videoPlayer; + bool _walkthroughStarted; void initInput(); @@ -83,6 +86,10 @@ public: void causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId); + int updateVideoPlayer(uint flags); + void playVideo(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId); + bool isVideoPlaying(); + void setDefaultTextCoords(); void loadSpecialCode(uint32 resId); diff --git a/engines/illusions/bbdou/scriptopcodes_bbdou.cpp b/engines/illusions/bbdou/scriptopcodes_bbdou.cpp index e6a3dd6c2c..3a1b2486c4 100644 --- a/engines/illusions/bbdou/scriptopcodes_bbdou.cpp +++ b/engines/illusions/bbdou/scriptopcodes_bbdou.cpp @@ -792,11 +792,12 @@ void ScriptOpcodes_BBDOU::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall ARG_UINT32(objectId); ARG_UINT32(videoId); ARG_UINT32(priority); - // TODO _vm->playVideo(videoId, objectId, value, opCall._threadId); - +#if 1 // TODO DEBUG Set to 0 to skip videos + _vm->playVideo(videoId, objectId, priority, opCall._threadId); +#else //DEBUG Resume calling thread, later done by the video player _vm->notifyThreadId(opCall._callerThreadId); - +#endif } void ScriptOpcodes_BBDOU::opStackPop(ScriptThread *scriptThread, OpCall &opCall) { diff --git a/engines/illusions/module.mk b/engines/illusions/module.mk index d1272f4417..dc915c3cb1 100644 --- a/engines/illusions/module.mk +++ b/engines/illusions/module.mk @@ -9,6 +9,7 @@ MODULE_OBJS := \ bbdou/bbdou_foodctl.o \ bbdou/bbdou_inventory.o \ bbdou/bbdou_specialcode.o \ + bbdou/bbdou_videoplayer.o \ bbdou/bbdou_triggerfunctions.o \ bbdou/illusions_bbdou.o \ bbdou/scriptopcodes_bbdou.o \ -- cgit v1.2.3