From cc9bf88ed56a4c5fbb14c05d30395b1688f5ebe7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 9 Jul 2016 11:32:15 -0400 Subject: TITANIC: Major implementation of OSMovie and AVISurface classes --- engines/titanic/core/game_object.cpp | 112 ++++++------ engines/titanic/core/game_object.h | 30 ++-- engines/titanic/events.cpp | 23 +++ engines/titanic/events.h | 7 +- engines/titanic/game/computer.cpp | 2 +- engines/titanic/game_manager.cpp | 68 +++++--- engines/titanic/messages/messages.h | 4 +- engines/titanic/sound/sound_manager.cpp | 4 +- engines/titanic/sound/sound_manager.h | 15 +- engines/titanic/support/avi_surface.cpp | 185 ++++++++++++++++++++ engines/titanic/support/avi_surface.h | 110 ++++++++++-- engines/titanic/support/mouse_cursor.cpp | 12 +- engines/titanic/support/mouse_cursor.h | 2 +- engines/titanic/support/movie.cpp | 245 ++++++++++++++------------- engines/titanic/support/movie.h | 132 ++++++++------- engines/titanic/support/movie_event.cpp | 33 ++-- engines/titanic/support/movie_event.h | 18 +- engines/titanic/support/movie_range_info.cpp | 42 ++--- engines/titanic/support/movie_range_info.h | 20 ++- engines/titanic/support/video_surface.cpp | 23 +-- engines/titanic/support/video_surface.h | 58 +++++-- 21 files changed, 759 insertions(+), 386 deletions(-) (limited to 'engines') diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp index dcc66f569d..78b91c3375 100644 --- a/engines/titanic/core/game_object.cpp +++ b/engines/titanic/core/game_object.cpp @@ -85,12 +85,14 @@ void CGameObject::save(SimpleFile *file, int indent) { _movieRangeInfoList.destroyContents(); if (_surface) { - Common::List rangeList = _surface->getMovieRangeInfo(); + const CMovieRangeInfoList *rangeList = _surface->getMovieRangeInfo(); - for (Common::List::const_iterator i = rangeList.begin(); - i != rangeList.end(); ++i) { - CMovieRangeInfo *rangeInfo = new CMovieRangeInfo(*i); - rangeInfo->_frameNumber = (i == rangeList.begin()) ? getMovieFrame() : -1; + if (rangeList) { + for (CMovieRangeInfoList::const_iterator i = rangeList->begin(); + i != rangeList->end(); ++i) { + CMovieRangeInfo *rangeInfo = new CMovieRangeInfo(*i); + rangeInfo->_initialFrame = (i == rangeList->begin()) ? getMovieFrame() : -1; + } } } @@ -403,21 +405,6 @@ void CGameObject::loadFrame(int frameNumber) { makeDirty(); } -void CGameObject::playMovie(int v1, int v2) { - if (_surface && !_resource.empty()) { - loadResource(_resource); - _resource.clear(); - } - - if (_surface && _surface->loadIfReady()) { - if (_surface->_movie) { - disableMouse(); - _surface->_movie->play(_bounds, v1, v2); - enableMouse(); - } - } -} - void CGameObject::processMoveRangeInfo() { for (CMovieRangeInfoList::iterator i = _movieRangeInfoList.begin(); i != _movieRangeInfoList.end(); ++i) (*i)->process(this); @@ -518,23 +505,53 @@ void CGameObject::petSetRemoteTarget() { pet->setRemoteTarget(this); } -void CGameObject::playMovie(uint startFrame, uint endFrame, uint flags) { +void CGameObject::playMovie(uint flags) { _frameNumber = -1; + + if (_surface && !_resource.empty()) { + loadResource(_resource); + _resource.clear(); + } + + CGameObject *obj = (flags & MOVIE_NO_OBJECT) ? nullptr : this; + if (_surface) { + _surface->playMovie(flags, obj); + if (flags & MOVIE_GAMESTATE) + getGameManager()->_gameState.addMovie(_surface->_movie); + } +} + +void CGameObject::playMovie(int startFrame, int endFrame, uint flags) { + _frameNumber = -1; + if (!_surface) { if (!_resource.empty()) loadResource(_resource); _resource.clear(); } + CGameObject *obj = (flags & MOVIE_NO_OBJECT) ? nullptr : this; if (_surface) { - // TODO: Figure out where to do this legitimately - OSMovie *movie = static_cast(_surface->_movie); - if (movie) - movie->_gameObject = this; + _surface->playMovie(startFrame, endFrame, flags, obj); + if (flags & MOVIE_GAMESTATE) + getGameManager()->_gameState.addMovie(_surface->_movie); + } +} + - _surface->playMovie(startFrame, endFrame, flags, flags != 0); +void CGameObject::playMovie(int startFrame, int endFrame, int initialFrame, uint flags) { + _frameNumber = -1; - if (flags & 0x10) + if (!_surface) { + if (!_resource.empty()) + loadResource(_resource); + _resource.clear(); + } + + CGameObject *obj = (flags & MOVIE_NO_OBJECT) ? nullptr : this; + if (_surface) { + _surface->playMovie(startFrame, endFrame, initialFrame, flags, obj); + if (flags & MOVIE_GAMESTATE) getGameManager()->_gameState.addMovie(_surface->_movie); } } @@ -565,28 +582,6 @@ void CGameObject::playRandomClip(const char **names, uint flags) { playClip(name, flags); } -void CGameObject::playMovie(uint flags) { - _frameNumber = -1; - if (!_surface && !_resource.empty()) { - loadResource(_resource); - _resource.clear(); - } - - CVideoSurface *surface = (flags & 4) ? _surface : nullptr; - if (_surface) { - _surface->playMovie(flags, surface); - - // TODO: Figure out where to do this legitimately - OSMovie *movie = static_cast(_surface->_movie); - if (movie) - movie->_gameObject = this; - - if (flags & 0x10) { - getGameManager()->_gameState.addMovie(_surface->_movie); - } - } -} - void CGameObject::savePosition() { _savedPos = _bounds; } @@ -1109,17 +1104,6 @@ bool CGameObject::clipExistsByEnd(const CString &name, int endFrame) const { return _movieClips.existsByEnd(name, endFrame); } -void CGameObject::checkPlayMovie(int fieldC, int field10, int frameNumber, int flags) { - if (!_surface && !_resource.empty()) - loadResource(_resource); - - if (_surface ) { - _surface->proc35(fieldC, field10, frameNumber, flags, (flags & CLIPFLAG_4) ? this : nullptr); - if (flags & CLIPFLAG_PLAY) - getGameManager()->_gameState.addMovie(_surface->_movie); - } -} - void CGameObject::petClear() const { CPetControl *petControl = getPetControl(); if (petControl) @@ -1235,14 +1219,14 @@ void CGameObject::setMovie14(int v) { _surface->_movie->_field14 = v; } -void CGameObject::surface38(int v1, int v2) { +void CGameObject::movieEvent(int frameNumber) { if (_surface) - _surface->proc38(v1, v2); + _surface->addMovieEvent(frameNumber, this); } -void CGameObject::surface38(int v1) { +void CGameObject::movieEvent() { if (_surface) - _surface->proc38(-1, v1); + _surface->addMovieEvent(-1, this); } int CGameObject::getClipDuration(const CString &name, int frameRate) const { diff --git a/engines/titanic/core/game_object.h b/engines/titanic/core/game_object.h index 20059539d9..58ae4c6123 100644 --- a/engines/titanic/core/game_object.h +++ b/engines/titanic/core/game_object.h @@ -293,11 +293,6 @@ protected: */ Point getControid() const; - /** - * Plays a movie - */ - void playMovie(int v1, int v2); - /** * Play an arbitrary clip */ @@ -560,11 +555,6 @@ public: */ virtual bool isPet() const; - /** - * Play the movie specified in _resource - */ - void playMovie(uint startFrame, uint endFrame, uint flags); - /** * Checks the passed point is validly in the object, * with extra checking of object flags status @@ -582,9 +572,14 @@ public: void playMovie(uint flags); /** - * Checks and plays a pending clip + * Play the movie specified in _resource + */ + void playMovie(int startFrame, int endFrame, uint flags); + + /** + * Play the movie specified in _resource */ - void checkPlayMovie(int fieldC, int field10, int frameNumber, int flags); + void playMovie(int startFrame, int endFrame, int initialFrame, uint flags); /** * Returns true if the object has a currently active movie @@ -842,9 +837,16 @@ public: /*--- CVideoSurface Methods ---*/ - void surface38(int v1, int v2); + /** + * Signal a movie event for the given frame + */ + void movieEvent(int frameNumber); - void surface38(int v1); + /** + * Signal a movie event at the end of all currently + * playing ranges + */ + void movieEvent(); }; } // End of namespace Titanic diff --git a/engines/titanic/events.cpp b/engines/titanic/events.cpp index 590107336c..ff425abcde 100644 --- a/engines/titanic/events.cpp +++ b/engines/titanic/events.cpp @@ -235,4 +235,27 @@ void Events::sleep(uint time) { } } +bool Events::waitForPress(uint expiry) { + uint32 delayEnd = g_system->getMillis() + expiry; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { + g_system->delayMillis(10); + checkForNextFrameCounter(); + + Common::Event event; + if (g_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_MBUTTONDOWN: + case Common::EVENT_KEYDOWN: + return true; + default: + break; + } + } + } + + return false; +} + } // End of namespace Titanic diff --git a/engines/titanic/events.h b/engines/titanic/events.h index 4638056e8c..ab3d755535 100644 --- a/engines/titanic/events.h +++ b/engines/titanic/events.h @@ -104,12 +104,17 @@ public: */ bool isSpecialPressed(SpecialButtons btn) const { return _specialButtons; } + uint getSpecialButtons() const { return _specialButtons; } + /** * Sleep for a specified period of time */ void sleep(uint time); - uint getSpecialButtons() const { return _specialButtons; } + /** + * Wait for a mouse or keypress + */ + bool waitForPress(uint expiry); }; } // End of namespace Titanic diff --git a/engines/titanic/game/computer.cpp b/engines/titanic/game/computer.cpp index e3f9430f3e..90574997b1 100644 --- a/engines/titanic/game/computer.cpp +++ b/engines/titanic/game/computer.cpp @@ -91,7 +91,7 @@ bool CComputer::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { } bool CComputer::MovieEndMsg(CMovieEndMsg *msg) { - if (msg->_value2 == 90) { + if (msg->_endFrame == 90) { playSound("a#32.wav", 100, 0, 0); playSound("a#33.wav", 100, 0, 0); playSound("a#31.wav", 100, 0, 0); diff --git a/engines/titanic/game_manager.cpp b/engines/titanic/game_manager.cpp index 7e8531fe68..84306b42e3 100644 --- a/engines/titanic/game_manager.cpp +++ b/engines/titanic/game_manager.cpp @@ -192,36 +192,48 @@ void CGameManager::update() { } void CGameManager::updateMovies() { - // TODO: Make this more like the original, if I can figuring out - // what's it doing with temporary lists and the OSMovie methods - for (CMovieList::iterator i = CMovie::_activeMovies->begin(); - i != CMovie::_activeMovies->end(); ) { - OSMovie *movie = static_cast(*i); - assert(movie && movie->_gameObject); - - movie->update(); - switch (movie->getState()) { - case MOVIE_FINISHED: { - CMovieEndMsg endMsg; - endMsg.execute(movie->_gameObject); - - i = CMovie::_activeMovies->erase(i); - delete movie; - continue; - } - - case MOVIE_FRAME: { - CMovieFrameMsg frameMsg; - frameMsg.execute(movie->_gameObject); + bool repeatFlag; + do { + repeatFlag = false; + + for (CMovieList::iterator i = CMovie::_playingMovies->begin(); + i != CMovie::_playingMovies->end(); ) { + CMovie *movie = *i; + if (movie->_state) + continue; + + CMovieEventList eventsList; + if (!movie->handleEvents(eventsList)) + movie->removeFromPlayingMovies(); + + while (!eventsList.empty()) { + CMovieEvent *movieEvent = eventsList.front(); + + switch (movieEvent->_type) { + case MET_MOVIE_END: { + CMovieEndMsg endMsg(movieEvent->_startFrame, movieEvent->_endFrame); + endMsg.execute(movieEvent->_gameObject); + break; + } + + case MET_FRAME: { + CMovieFrameMsg frameMsg(movieEvent->_initialFrame, 0); + frameMsg.execute(movieEvent->_gameObject); + break; + } + + default: + break; + } + + eventsList.remove(movieEvent); + } + + repeatFlag = true; + movie->_state = MSTATE_1; break; } - - default: - break; - } - - ++i; - } + } while (repeatFlag); } void CGameManager::updateDiskTicksCount() { diff --git a/engines/titanic/messages/messages.h b/engines/titanic/messages/messages.h index 278fac1fbd..de5d0bdcc0 100644 --- a/engines/titanic/messages/messages.h +++ b/engines/titanic/messages/messages.h @@ -264,8 +264,8 @@ MESSAGE0(CMaitreDDefeatedMsg); MESSAGE0(CMaitreDHappyMsg); MESSAGE1(CMissiveOMatActionMsg, int, value, 0); MESSAGE0(CMoveToStartPosMsg); -MESSAGE2(CMovieEndMsg, int, value1, 0, int, value2, 0); -MESSAGE2(CMovieFrameMsg, int, value1, 0, int, value2, 0); +MESSAGE2(CMovieEndMsg, int, startFrame, 0, int, endFrame, 0); +MESSAGE2(CMovieFrameMsg, int, frameNumber, 0, int, value2, 0); MESSAGE0(CMusicHasStartedMsg); MESSAGE0(CMusicHasStoppedMsg); MESSAGE0(CMusicSettingChangedMsg); diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp index 05a924f352..440d74ade5 100644 --- a/engines/titanic/sound/sound_manager.cpp +++ b/engines/titanic/sound/sound_manager.cpp @@ -100,8 +100,8 @@ void QSoundManager::WaveMixPump() { warning("TODO"); } -int QSoundManager::proc18() const { - warning("TODO"); +bool QSoundManager::movieStarted() const { + // TODO return 0; } diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h index ac4ac1ef9f..942124e796 100644 --- a/engines/titanic/sound/sound_manager.h +++ b/engines/titanic/sound/sound_manager.h @@ -59,7 +59,12 @@ public: virtual bool isActive(int handle) const { return false; } virtual int proc16() const { return 0; } virtual void WaveMixPump() {} - virtual int proc18() const { return 0; } + + /** + * Called when a movie with audio is started + */ + virtual bool movieStarted() const { return false; } + virtual void setMusicPercent(double percent) { _musicPercent = percent; } virtual void setSpeechPercent(double percent) { _speechPercent = percent; } virtual void setMasterPercent(double percent) { _masterPercent = percent; } @@ -128,7 +133,13 @@ public: virtual bool isActive(int handle) const; virtual int proc16(); virtual void WaveMixPump(); - virtual int proc18() const; + + + /** + * Called when a movie with audio is started + */ + virtual bool movieStarted() const; + virtual void proc19(int v); virtual void proc20(int v); virtual void proc21(int v); diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp index f6f63a7f1d..47127fe83b 100644 --- a/engines/titanic/support/avi_surface.cpp +++ b/engines/titanic/support/avi_surface.cpp @@ -21,12 +21,197 @@ */ #include "titanic/support/avi_surface.h" +#include "titanic/support/video_surface.h" #include "video/avi_decoder.h" namespace Titanic { AVISurface::AVISurface(const CResourceKey &key) { + // TODO +/* +Video::AVIDecoder *decoder = new Video::AVIDecoder(); +decoder->ignoreSecondaryVideoTracks(); +_video = decoder; +_field14 = 1; + +if (!_video->loadFile(name.getString())) +error("Could not open video - %s", name.getString().c_str()); +*/ +} + +AVISurface::~AVISurface() { + if (_videoSurface) + _videoSurface->_blitStyleFlag = false; + delete _frameInfo; +} + +bool AVISurface::play(uint flags, CGameObject *obj) { + if (flags & MOVIE_REVERSE) + return play(_decoder->getFrameCount() - 1, 0, flags, obj); + else + return play(0, _decoder->getFrameCount() - 1, flags, obj); +} + +bool AVISurface::play(int startFrame, int endFrame, uint flags, CGameObject *obj) { + if (flags & MOVIE_STOP_PREVIOUS) + stop(); + + return play(startFrame, endFrame, -1, flags, obj); +} + +bool AVISurface::play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj) { + CMovieRangeInfo *info = new CMovieRangeInfo(); + info->_startFrame = startFrame; + info->_endFrame = endFrame; + info->_isReversed = endFrame < startFrame; + info->_isFlag1 = flags & MOVIE_1; + + if (obj) { + CMovieEvent *me = new CMovieEvent(); + me->_type = MET_MOVIE_END; + me->_startFrame = startFrame; + me->_endFrame = endFrame; + me->_initialFrame = 0; + me->_gameObject = obj; + + info->addEvent(me); + } + + _movieRangeInfo.push_back(info); + + if (_movieRangeInfo.size() == 1) { + changeFrame(initialFrame); + } else { + return true; + } +} + +void AVISurface::stop() { + _isPlaying = false; + _decoder->stop(); + _movieRangeInfo.destroyContents(); +} + +bool AVISurface::changeFrame(int frameNumber) { + if (_isPlaying) + return false; + + if (frameNumber == -1) + // Default to starting frame of first movie range + frameNumber = _movieRangeInfo.front()->_startFrame; + + seekToFrame(frameNumber); + renderFrame(); + + _isPlaying = true; + return true; +} + +void AVISurface::seekToFrame(uint frameNumber) { + _decoder->seekToFrame(frameNumber); + _priorFrame = frameNumber; +} + +bool AVISurface::handleEvents(CMovieEventList &events) { + if (!_isPlaying) + return true; + + CMovieRangeInfo *info = _movieRangeInfo.front(); + _currentPos += info->_isReversed ? -1 : 1; + if ((info->_isReversed && _currentPos < info->_endFrame) || + (!info->_isReversed && _currentPos > info->_endFrame)) { + if (info->_isFlag1) { + info->getMovieEnd(events); + _movieRangeInfo.remove(info); + delete info; + + if (_movieRangeInfo.empty()) { + // NO more ranges, so stop playback + stop(); + } else { + // Not empty, so move onto new first one + info = _movieRangeInfo.front(); + _currentPos = info->_startFrame; + } + } else { + _currentPos = info->_startFrame; + } + } + + if (_isPlaying) { + // SInce movie ranges can change the position in the movie, + // ensure the decoder is kept in sync + seekToFrame(_currentPos); + + info->getMovieFrame(events, _currentPos); + return renderFrame(); + } else { + return false; + } +} + +void AVISurface::setVideoSurface(CVideoSurface *surface) { + _videoSurface = surface; + + warning("TODO: Get video track list from video decoder"); +} + +uint AVISurface::getWidth() const { + return _decoder->getWidth(); +} + +uint AVISurface::getHeight() const { + return _decoder->getHeight(); +} + +void AVISurface::setFrame(int frameNumber) { + // If playback was in process, stop it + if (_isPlaying) + stop(); + + // Ensure the frame number is valid + if (frameNumber >= _decoder->getFrameCount()) + frameNumber = _decoder->getFrameCount() - 1; + + seekToFrame(frameNumber); + renderFrame(); +} + +int AVISurface::getFrame() const { + return _decoder->getCurFrame(); +} + +bool AVISurface::renderFrame() { + // Check there's a frame ready for + assert(_videoSurface); + if (!_decoder->needsUpdate()) + return false; + + // Get the frame to render, and draw it on the surface + const Graphics::Surface *frame = _decoder->decodeNextFrame(); + _videoSurface->blitFrom(Point(0, 0), frame); + return false; +} + +bool AVISurface::addEvent(int frameNumber, CGameObject *obj) { + if (!_movieRangeInfo.empty()) { + CMovieRangeInfo *tail = _movieRangeInfo.back(); + if (frameNumber == -1) + frameNumber = tail->_startFrame; + + CMovieEvent *me = new CMovieEvent(); + me->_type = MET_FRAME; + me->_startFrame = 0; + me->_endFrame = 0; + me->_initialFrame = frameNumber; + me->_gameObject = obj; + tail->addEvent(me); + + return _movieRangeInfo.size() == 1 && frameNumber == _priorFrame; + } + + return false; } } // End of namespace Titanic diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h index 248f2c5ab3..48c8169e78 100644 --- a/engines/titanic/support/avi_surface.h +++ b/engines/titanic/support/avi_surface.h @@ -23,33 +23,121 @@ #ifndef TITANIC_AVI_SURFACE_H #define TITANIC_AVI_SURFACE_H -#include "video/video_decoder.h" +#include "video/avi_decoder.h" #include "titanic/core/resource_key.h" #include "titanic/support/movie_range_info.h" namespace Titanic { class CSoundManager; +class CVideoSurface; + +enum MovieFlag { + MOVIE_1 = 1, MOVIE_STOP_PREVIOUS = 2, MOVIE_NO_OBJECT = 4, + MOVIE_REVERSE = 8, MOVIE_GAMESTATE = 0x10 +}; class AVISurface { private: + Video::AVIDecoder *_decoder; + CVideoSurface *_videoSurface; int _field4; int _field8; - int _fieldC; - int _field10; - int _frame; + int _currentPos; + int _priorFrame; CMovieRangeInfoList _movieRangeInfo; - int _field28; - int _field2C; - int _field30; - int _field34; - int _field38; + int _streamCount; + void *_frameInfo; +private: + /** + * Render a frame to the video surface + */ + bool renderFrame(); +protected: + /** + * Change the frame with ??? checking + */ + virtual bool changeFrame(int frameNumber); + + /** + * Seeks to a given frame number in the video + */ + virtual void seekToFrame(uint frameNumber); +public: CSoundManager *_soundManager; - // TODO: Lots more fields + bool _hasAudio; + bool _isPlaying; + double _frameRate; public: AVISurface(const CResourceKey &key); + ~AVISurface(); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(uint flags, CGameObject *obj); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(int startFrame, int endFrame, uint flags, CGameObject *obj); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj); + + /** + * Stop the currently playing video + */ + virtual void stop(); + + /** + * Handle any movie events relevent for the frame + */ + virtual bool handleEvents(CMovieEventList &events); + + /** + * Set the video surface the AVI Surface will render on + */ + void setVideoSurface(CVideoSurface *surface); + + /** + * Get the width of the video + */ + uint getWidth() const; + + /** + * Get the height of the video + */ + uint getHeight() const; + + /** + * Set the current frame + */ + void setFrame(int frameNumber); + + /** + * Gets the current frame + */ + int getFrame() const; + + /** + * Add a movie event + */ + bool addEvent(int frameNumber, CGameObject *obj); + + const void *getFrameInfo() const { + return _streamCount <= 1 ? nullptr : _frameInfo; + } + + /** + * Get a reference to the movie range info list + */ + const CMovieRangeInfoList *getMovieRangeInfo() const { + return &_movieRangeInfo; + } - }; } // End of namespace Titanic diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp index d87e7a499b..721088f086 100644 --- a/engines/titanic/support/mouse_cursor.cpp +++ b/engines/titanic/support/mouse_cursor.cpp @@ -91,15 +91,17 @@ void CMouseCursor::loadCursorImages() { // Create the surface CVideoSurface *surface = _screenManager->createSurface(64, 64); _cursors[idx]._videoSurface = surface; - +/* Common::SeekableReadStream *stream = new Common::MemoryReadStream( movieData, f.size(), DisposeAfterUse::NO); OSMovie movie(stream, surface); movie.setFrame(idx); - - _cursors[idx]._ptrUnknown = movie.proc21(); - surface->set40(_cursors[idx]._ptrUnknown); - } + + int frameNum = movie.proc21(); + _cursors[idx]._frameNumber = frameNum; + surface->setMovieFrame(frameNum); +*/ + } } void CMouseCursor::show() { diff --git a/engines/titanic/support/mouse_cursor.h b/engines/titanic/support/mouse_cursor.h index 55e0cb4da5..168a7be539 100644 --- a/engines/titanic/support/mouse_cursor.h +++ b/engines/titanic/support/mouse_cursor.h @@ -54,7 +54,7 @@ class CVideoSurface; class CMouseCursor { struct CursorEntry { CVideoSurface *_videoSurface; - void *_ptrUnknown; + int _frameNumber; Common::Point _centroid; }; private: diff --git a/engines/titanic/support/movie.cpp b/engines/titanic/support/movie.cpp index 6a79c02a3e..338396ff96 100644 --- a/engines/titanic/support/movie.cpp +++ b/engines/titanic/support/movie.cpp @@ -20,42 +20,51 @@ * */ -#include "video/avi_decoder.h" -#include "titanic/sound/sound_manager.h" #include "titanic/support/movie.h" +#include "titanic/support/avi_surface.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/messages/messages.h" #include "titanic/titanic.h" namespace Titanic { -CMovieList *CMovie::_activeMovies; +#define CLIP_WIDTH 600 +#define CLIP_WIDTH_REDUCED (CLIP_WIDTH / 2) +#define CLIP_HEIGHT 340 +#define CLIP_HEIGHT_REDUCED (CLIP_HEIGHT / 2) + +CMovieList *CMovie::_playingMovies; +CVideoSurface *CMovie::_movieSurface; -CMovie::CMovie() : ListItem(), _state(MOVIE_STOPPED), _field10(0), +CMovie::CMovie() : ListItem(), _state(MSTATE_0), _field10(0), _field14(0) { } CMovie::~CMovie() { - removeFromActiveMovies(); + removeFromPlayingMovies(); } void CMovie::init() { - _activeMovies = new CMovieList(); + _playingMovies = new CMovieList(); + _movieSurface = nullptr; } void CMovie::deinit() { - delete _activeMovies; + delete _playingMovies; + delete _movieSurface; } -void CMovie::addToActiveMovies() { +void CMovie::addToPlayingMovies() { if (!isActive()) - _activeMovies->push_back(this); + _playingMovies->push_back(this); } -void CMovie::removeFromActiveMovies() { - _activeMovies->remove(this); +void CMovie::removeFromPlayingMovies() { + _playingMovies->remove(this); } bool CMovie::isActive() const { - return _activeMovies->contains(this); + return _playingMovies->contains(this); } bool CMovie::get10() { @@ -70,156 +79,148 @@ bool CMovie::get10() { /*------------------------------------------------------------------------*/ OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) : - _videoSurface(surface), _gameObject(nullptr), _endFrame(-1) { - Video::AVIDecoder *decoder = new Video::AVIDecoder(); - _video = decoder; - _field14 = 1; - - if (!_video->loadFile(name.getString())) - error("Could not open video - %s", name.getString().c_str()); -} + _aviSurface(name), _videoSurface(surface) { + _field18 = 0; + _field24 = 0; + _field28 = 0; + _field2C = 0; + _ticksStart = 0; + _frameTime1 = 0; + _frameTime2 = 17066; -OSMovie::OSMovie(Common::SeekableReadStream *stream, CVideoSurface *surface) : - _videoSurface(surface), _gameObject(nullptr), _endFrame(-1) { - _video = new Video::AVIDecoder(); - if (!_video->loadStream(stream)) - error("Could not parse movie stream"); + surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight()); + _aviSurface.setVideoSurface(surface); } OSMovie::~OSMovie() { - delete _video; } -void OSMovie::play(uint flags, CVideoSurface *surface) { - uint endFrame = _video->getFrameCount(); - play(0, endFrame, 0, 0); -} +void OSMovie::play(uint flags, CGameObject *obj) { + _aviSurface.play(flags, obj); -void OSMovie::play(uint startFrame, uint endFrame, int v3, bool v4) { - warning("TODO: OSMovie::play properly"); + if (_aviSurface._isPlaying) + movieStarted(); +} - _video->start(); - _video->seekToFrame(startFrame); - _endFrame = endFrame; +void OSMovie::play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) { + _aviSurface.play(startFrame, endFrame, flags, obj); - addToActiveMovies(); - _state = MOVIE_NONE; + if (_aviSurface._isPlaying) + movieStarted(); } -void OSMovie::play(const Rect &rect, int v1, int v2) { - warning("TODO: OSMovie::play 3"); -} +void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) { + _aviSurface.play(startFrame, endFrame, initialFrame, flags, obj); -void OSMovie::playClip(const Rect &rect, uint startFrame, uint endFrame) { - warning("TODO: OSMovie::playClip"); + if (_aviSurface._isPlaying) + movieStarted(); } -void OSMovie::proc11() { - warning("TODO: OSMovie::proc11"); -} +void OSMovie::playClip(const Point &drawPos, uint startFrame, uint endFrame) { + if (!_movieSurface) + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); + + bool widthLess = _videoSurface->getWidth() < 600; + bool heightLess = _videoSurface->getHeight() < 340; + Rect r(drawPos.x, drawPos.y, + drawPos.x + widthLess ? CLIP_WIDTH_REDUCED : CLIP_WIDTH, + drawPos.y + heightLess ? CLIP_HEIGHT_REDUCED : CLIP_HEIGHT + ); -void OSMovie::proc12(int v1, int v2, int frameNumber, int flags, CGameObject *obj) { - warning("TODO: OSMovie::proc12"); + uint timePerFrame = 1000 / _aviSurface._frameRate; + + for (; endFrame >= startFrame; ++startFrame) { + // Set the frame + _aviSurface.setFrame(startFrame); + + // TODO: See if we need to do anything further here. The original had a bunch + // of calls and using of the _movieSurface; perhaps to allow scaling down + // videos to half-size + if (widthLess || heightLess) + warning("Not properly reducing clip size: %d %d", r.width(), r.height()); + + // Wait for the next frame, unless the user interrupts the clip + if (g_vm->_events->waitForPress(timePerFrame)) + break; + } } void OSMovie::stop() { - _video->stop(); - _state = MOVIE_STOPPED; + _aviSurface.stop(); + removeFromPlayingMovies(); } -void OSMovie::proc14() { - warning("TODO: OSMovie::proc14"); +void OSMovie::addEvent(int frameNumber, CGameObject *obj) { + if (_aviSurface.addEvent(frameNumber, obj)) { + CMovieFrameMsg frameMsg(frameNumber, 0); + frameMsg.execute(obj); + } } void OSMovie::setFrame(uint frameNumber) { - _video->seekToFrame(frameNumber); - decodeFrame(); + _aviSurface.setFrame(frameNumber); + _videoSurface->setMovieFrame(frameNumber); } -void OSMovie::proc16() { - warning("TODO: OSMovie::proc16"); -} +bool OSMovie::handleEvents(CMovieEventList &events) { + if (!_aviSurface._isPlaying) + return false; -const Common::List OSMovie::getMovieRangeInfo() const { - warning("TODO: OSMovie::getMovieRangeInfo"); - return Common::List(); -} + int time = (g_vm->_events->getTicksCount() + ((_ticksStart << 24) - _ticksStart)) << 8; + if (time < _frameTime1) + return _aviSurface._isPlaying; -void OSMovie::setSoundManager(CSoundManager *soundManager) { -// if (_aviSurface) -// _aviSurface->_field3C = soundManager; + if (!_field14 && (time - _frameTime1) > (_frameTime2 * 2)) + _frameTime1 = time; - warning("TODO: OSMovie::proc18"); -} + _frameTime1 += _frameTime2; + _aviSurface.handleEvents(events); + _videoSurface->setMovieFrameInfo(_aviSurface.getFrameInfo()); -int OSMovie::getFrame() { - assert(_video); - return _video->getCurFrame(); -} + if (_field14) { + while (_frameTime1 >= time && events.empty()) { + _aviSurface.handleEvents(events); + _videoSurface->setMovieFrameInfo(_aviSurface.getFrameInfo()); -void OSMovie::proc20() { - warning("TODO: OSMovie::proc20"); -} - -void *OSMovie::proc21() { - warning("TODO: OSMovie::proc21"); - return nullptr; -} - -MovieState OSMovie::getState() { - if (!_video) - _state = MOVIE_STOPPED; - return _state; -} - -void OSMovie::update() { - if (_state != MOVIE_STOPPED) { - if (_video->isPlaying()) { - if (_video->getCurFrame() >= _endFrame) { - _video->stop(); - _state = MOVIE_FINISHED; - } else if (_video->needsUpdate()) { - decodeFrame(); - _state = MOVIE_FRAME; - } else { - _state = MOVIE_NONE; - } - } else { - _state = MOVIE_STOPPED; + _frameTime1 += _frameTime2; } } + + return _aviSurface._isPlaying; +} + +const CMovieRangeInfoList *OSMovie::getMovieRangeInfo() const { + return _aviSurface.getMovieRangeInfo(); } -void OSMovie::decodeFrame() { - const Graphics::Surface *frame = _video->decodeNextFrame(); - OSVideoSurface *videoSurface = static_cast(_videoSurface); - assert(videoSurface); +void OSMovie::setSoundManager(CSoundManager *soundManager) { + _aviSurface._soundManager = soundManager; +} - // If the video surface doesn't yet have an underlying surface, create it - if (!videoSurface->hasSurface()) - videoSurface->recreate(frame->w, frame->h); +int OSMovie::getFrame() const { + return _aviSurface.getFrame(); +} - // Lock access to the surface - videoSurface->lock(); - assert(videoSurface->_rawSurface); +void OSMovie::movieStarted() { + _frameTime1 = _frameTime2 = 256000.0 / _aviSurface._frameRate; + _ticksStart = g_vm->_events->getTicksCount(); - if (frame->format == videoSurface->_rawSurface->format) { - // Matching format, so we can copy straight from the video frame - videoSurface->_rawSurface->blitFrom(*frame); - } else { - // Different formats so we have to convert it first - Graphics::Surface *s = frame->convertTo(videoSurface->_rawSurface->format); - videoSurface->_rawSurface->blitFrom(*s); + if (_aviSurface._hasAudio) + _aviSurface._soundManager->movieStarted(); - s->free(); - delete s; - } + // Register the movie in the playing list + addToPlayingMovies(); + _field10 = 1; +} - // Unlock the surface - videoSurface->unlock(); +void OSMovie::proc20() { + // TODO +} - if (_gameObject) - _gameObject->makeDirty(); +int OSMovie::proc21() { + // TODO + return 0; } + } // End of namespace Titanic diff --git a/engines/titanic/support/movie.h b/engines/titanic/support/movie.h index 7abca6bbc0..c839c882ca 100644 --- a/engines/titanic/support/movie.h +++ b/engines/titanic/support/movie.h @@ -27,12 +27,13 @@ #include "video/video_decoder.h" #include "titanic/core/list.h" #include "titanic/core/resource_key.h" +#include "titanic/support/avi_surface.h" #include "titanic/support/movie_range_info.h" namespace Titanic { enum MovieState { - MOVIE_STOPPED = -1, MOVIE_NONE = 0, MOVIE_FINISHED = 1, MOVIE_FRAME = 2 + MSTATE_0 = 0, MSTATE_1 = 1 }; class CGameObject; @@ -46,22 +47,17 @@ public: class CMovie : public ListItem { protected: - MovieState _state; - int _field10; -protected: - /** - * Adds the movie to the active movies list - */ - void addToActiveMovies(); - /** - * Removes the movie from the active movies list + * Adds the movie to the list of currently playing movies */ - void removeFromActiveMovies(); + void addToPlayingMovies(); public: + MovieState _state; + int _field10; int _field14; public: - static CMovieList *_activeMovies; + static CMovieList *_playingMovies; + static CVideoSurface *_movieSurface; /** * Initializes statics @@ -77,41 +73,49 @@ public: virtual ~CMovie(); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint flags, CVideoSurface *surface) = 0; + virtual void play(uint flags, CGameObject *obj) = 0; /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint startFrame, uint endFrame, int v3, bool v4) = 0; + virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0; /** - * Plays the movie + * Starts playing the movie */ - virtual void play(const Rect &rect, int v1, int v2) = 0; + virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0; /** * Plays a sub-section of a movie */ - virtual void playClip(const Rect &rect, uint startFrame, uint endFrame) = 0; + virtual void playClip(const Point &drawPos, uint startFrame, uint endFrame) = 0; - virtual void proc11() = 0; - virtual void proc12(int v1, int v2, int frameNumber, int flags, CGameObject *obj) = 0; - /** * Stops the movie */ virtual void stop() = 0; - virtual void proc14() = 0; + /** + * Add a playback event + */ + virtual void addEvent(int frameNumber, CGameObject *obj) = 0; + + /** + * Set the current frame number + */ virtual void setFrame(uint frameNumber) = 0; - virtual void proc16() = 0; + + /** + * Handle any pending movie events + */ + virtual bool handleEvents(CMovieEventList &events) = 0; /** * Return any movie range info associated with the movie */ - virtual const Common::List getMovieRangeInfo() const = 0; + virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0; /** * Set the sound manager reference @@ -121,94 +125,102 @@ public: /** * Get the current movie frame */ - virtual int getFrame() = 0; + virtual int getFrame() const = 0; virtual void proc20() = 0; - virtual void *proc21() = 0; + virtual int proc21() = 0; + + /** + * Removes the movie from the list of currently playing movies + */ + void removeFromPlayingMovies(); + /** + * Returns true if the movie is currently active + */ bool isActive() const; bool get10(); - - virtual MovieState getState() = 0; - virtual void update() = 0; }; class OSMovie : public CMovie { private: - Video::VideoDecoder *_video; + AVISurface _aviSurface; CVideoSurface *_videoSurface; - int _endFrame; - + int _field18; + int _field24; + int _field28; + int _field2C; + int _ticksStart; + int _frameTime1; + int _frameTime2; +private: /** - * Decodes the next frame + * Called when a movie is started playing */ - void decodeFrame(); -public: - CGameObject *_gameObject; + void movieStarted(); public: OSMovie(const CResourceKey &name, CVideoSurface *surface); - OSMovie(Common::SeekableReadStream *stream, CVideoSurface *surface); virtual ~OSMovie(); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint flags, CVideoSurface *surface); + virtual void play(uint flags, CGameObject *obj); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint startFrame, uint endFrame, int v3, bool v4); + virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(const Rect &rect, int v1, int v2); + virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj); /** * Plays a sub-section of a movie */ - virtual void playClip(const Rect &rect, uint startFrame, uint endFrame); - - virtual void proc11(); - virtual void proc12(int v1, int v2, int frameNumber, int flags, CGameObject *obj); + virtual void playClip(const Point &drawPos, uint startFrame, uint endFrame); /** * Stops the movie */ virtual void stop(); - virtual void proc14(); + /** + * Add a playback event + */ + virtual void addEvent(int eventId, CGameObject *obj); /** * Set the current frame number */ virtual void setFrame(uint frameNumber); - virtual void proc16(); + /** + * Handle any pending movie events + */ + virtual bool handleEvents(CMovieEventList &events); /** - * Return any movie range info associated with the movie + * Get the current frame number */ - virtual const Common::List getMovieRangeInfo() const; + virtual int getFrame() const; /** - * Set the sound manager reference + * Return any movie range info associated with the movie */ - virtual void setSoundManager(CSoundManager *soundManager); + virtual const CMovieRangeInfoList *getMovieRangeInfo() const; /** - * Get the current movie frame + * Set the sound manager reference */ - virtual int getFrame(); + virtual void setSoundManager(CSoundManager *soundManager); virtual void proc20(); - virtual void *proc21(); - + virtual int proc21(); - virtual MovieState getState(); - virtual void update(); }; } // End of namespace Titanic diff --git a/engines/titanic/support/movie_event.cpp b/engines/titanic/support/movie_event.cpp index 870a06fe6f..5f8a6da019 100644 --- a/engines/titanic/support/movie_event.cpp +++ b/engines/titanic/support/movie_event.cpp @@ -21,27 +21,29 @@ */ #include "titanic/support/movie_event.h" +#include "titanic/core/game_object.h" namespace Titanic { -CMovieEvent::CMovieEvent() : ListItem(), _fieldC(0), _field10(0), - _field14(0), _field1C(0) { +CMovieEvent::CMovieEvent() : ListItem(), _type(MET_PLAY), _startFrame(0), + _endFrame(0), _initialFrame(0), _gameObject(nullptr) { } CMovieEvent::CMovieEvent(const CMovieEvent *src) { - _fieldC = src->_fieldC; - _field10 = src->_field10; - _field14 = src->_field14; - _field18 = src->_field18; - _field1C = src->_field1C; + _type = src->_type; + _startFrame = src->_startFrame; + _endFrame = src->_endFrame; + _initialFrame = src->_initialFrame; + _gameObject = src->_gameObject; } void CMovieEvent::save(SimpleFile *file, int indent) { file->writeNumberLine(0, indent); - file->writeNumberLine(_fieldC, indent + 1); - file->writeNumberLine(_field10, indent + 1); - file->writeNumberLine(_field14, indent + 1); - file->writeNumberLine(_field1C, indent + 1); + file->writeNumberLine(_startFrame, indent + 1); + file->writeNumberLine(_endFrame, indent + 1); + error("FIXME: Original save/loaded object pointer"); + // file->writeNumberLine(_gameObject, indent + 1); + file->writeNumberLine(_initialFrame, indent + 1); ListItem::save(file, indent); } @@ -49,10 +51,11 @@ void CMovieEvent::save(SimpleFile *file, int indent) { void CMovieEvent::load(SimpleFile *file) { int val = file->readNumber(); if (!val) { - _fieldC = file->readNumber(); - _field10 = file->readNumber(); - _field14 = file->readNumber(); - _field1C = file->readNumber(); + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + file->readNumber(); + error("FIXME: Original save/loaded object pointer"); + _initialFrame = file->readNumber(); } ListItem::load(file); diff --git a/engines/titanic/support/movie_event.h b/engines/titanic/support/movie_event.h index ed72e2d349..af93c76a31 100644 --- a/engines/titanic/support/movie_event.h +++ b/engines/titanic/support/movie_event.h @@ -27,13 +27,17 @@ namespace Titanic { +enum MovieEventType { MET_PLAY = 0, MET_MOVIE_END = 1, MET_FRAME = 2 }; + +class CGameObject; + class CMovieEvent : public ListItem { public: - int _fieldC; - int _field10; - int _field14; - int _field18; - int _field1C; + MovieEventType _type; + int _startFrame; + int _endFrame; + CGameObject *_gameObject; + int _initialFrame; public: CMovieEvent(); CMovieEvent(const CMovieEvent *src); @@ -53,6 +57,10 @@ public: class CMovieEventList : public List { }; +class CSharedMovieEventList : public Common::List { +}; + + } // End of namespace Titanic #endif /* TITANIC_MOVIE_EVENT_H */ diff --git a/engines/titanic/support/movie_range_info.cpp b/engines/titanic/support/movie_range_info.cpp index e6b28ce4e8..4c62539864 100644 --- a/engines/titanic/support/movie_range_info.cpp +++ b/engines/titanic/support/movie_range_info.cpp @@ -34,11 +34,11 @@ CMovieRangeInfo::~CMovieRangeInfo() { } CMovieRangeInfo::CMovieRangeInfo(const CMovieRangeInfo *src) : ListItem() { - _fieldC = src->_fieldC; - _field10 = src->_field10; - _frameNumber = src->_frameNumber; _startFrame = src->_startFrame; _endFrame = src->_endFrame; + _initialFrame = src->_initialFrame; + _isReversed = src->_isReversed; + _isFlag1 = src->_isFlag1; // Duplicate the events list for (CMovieEventList::const_iterator i = _events.begin(); @@ -49,38 +49,38 @@ CMovieRangeInfo::CMovieRangeInfo(const CMovieRangeInfo *src) : ListItem() { void CMovieRangeInfo::save(SimpleFile *file, int indent) { file->writeNumberLine(0, indent); - file->writeNumberLine(_fieldC, indent + 1); - file->writeNumberLine(_field10, indent + 1); - file->writeNumberLine(_frameNumber, indent + 1); - file->writeNumberLine(_endFrame, indent + 1); file->writeNumberLine(_startFrame, indent + 1); + file->writeNumberLine(_endFrame, indent + 1); + file->writeNumberLine(_initialFrame, indent + 1); + file->writeNumberLine(_isFlag1, indent + 1); + file->writeNumberLine(_isReversed, indent + 1); _events.save(file, indent + 1); } void CMovieRangeInfo::load(SimpleFile *file) { int val = file->readNumber(); if (!val) { - _fieldC = file->readNumber(); - _field10 = file->readNumber(); - _frameNumber = file->readNumber(); - _endFrame = file->readNumber(); _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + _initialFrame = file->readNumber(); + _isFlag1 = file->readNumber(); + _isReversed = file->readNumber(); _events.load(file); } } -void CMovieRangeInfo::get1(CMovieEventList &list) { +void CMovieRangeInfo::getMovieEnd(CMovieEventList &list) { for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (movieEvent->_fieldC == 1) + if (movieEvent->_type == MET_MOVIE_END) list.push_back(new CMovieEvent(movieEvent)); } } -void CMovieRangeInfo::get2(CMovieEventList &list, int val) { +void CMovieRangeInfo::getMovieFrame(CMovieEventList &list, int frameNumber) { for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (movieEvent->_fieldC == 2 && movieEvent->_field1C == val) + if (movieEvent->_type == MET_FRAME && movieEvent->_initialFrame == frameNumber) list.push_back(new CMovieEvent(movieEvent)); } } @@ -88,24 +88,24 @@ void CMovieRangeInfo::get2(CMovieEventList &list, int val) { void CMovieRangeInfo::process(CGameObject *owner) { int flags = 0; if (_endFrame) - flags |= CLIPFLAG_HAS_END_FRAME; + flags |= MOVIE_1; if (_startFrame) - flags |= CLIPFLAG_HAS_START_FRAME; + flags |= MOVIE_REVERSE; for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (!movieEvent->_fieldC) { + if (!movieEvent->_type == MET_PLAY) { flags |= CLIPFLAG_PLAY; break; } } - owner->checkPlayMovie(_fieldC, _field10, _frameNumber, flags); + owner->playMovie(_startFrame, _endFrame, _initialFrame, flags); for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (!movieEvent->_fieldC) - owner->surface38(movieEvent->_field1C); + if (movieEvent->_type == MET_PLAY) + owner->movieEvent(movieEvent->_initialFrame); } } diff --git a/engines/titanic/support/movie_range_info.h b/engines/titanic/support/movie_range_info.h index be04975cbf..b8186e6f7e 100644 --- a/engines/titanic/support/movie_range_info.h +++ b/engines/titanic/support/movie_range_info.h @@ -34,11 +34,11 @@ class CGameObject; class CMovieRangeInfo : public ListItem { public: - int _fieldC; - int _field10; - int _frameNumber; - uint _startFrame; - uint _endFrame; + int _startFrame; + int _endFrame; + int _initialFrame; + bool _isReversed; + bool _isFlag1; CMovieEventList _events; public: CMovieRangeInfo(); @@ -60,9 +60,15 @@ public: */ void addEvent(CMovieEvent *movieEvent) { _events.push_back(movieEvent); } - void get1(CMovieEventList &list); + /** + * Get any movie end events for the range + */ + void getMovieEnd(CMovieEventList &list); - void get2(CMovieEventList &list, int val); + /** + * Get any movie frame events for a specified frame number + */ + void getMovieFrame(CMovieEventList &list, int frameNumber); void process(CGameObject *owner); }; diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp index 0335e7d9b1..fc7db30391 100644 --- a/engines/titanic/support/video_surface.cpp +++ b/engines/titanic/support/video_surface.cpp @@ -32,7 +32,7 @@ int CVideoSurface::_videoSurfaceCounter = 0; CVideoSurface::CVideoSurface(CScreenManager *screenManager) : _screenManager(screenManager), _rawSurface(nullptr), _movie(nullptr), _pendingLoad(false), _blitStyleFlag(false), _blitFlag(false), - _field40(nullptr), _field44(4), _field48(0), _field50(1) { + _movieFrameInfo(nullptr), _transparencyMode(TRANS_DEFAULT), _field48(0), _field50(1) { _videoSurfaceNum = _videoSurfaceCounter++; } @@ -427,22 +427,22 @@ void OSVideoSurface::clear() { } -void OSVideoSurface::playMovie(uint flags, CVideoSurface *surface) { +void OSVideoSurface::playMovie(uint flags, CGameObject *obj) { if (loadIfReady() && _movie) - _movie->play(flags, surface); + _movie->play(flags, obj); _ddSurface->fill(nullptr, 0); } -void OSVideoSurface::playMovie(uint startFrame, uint endFrame, int v3, bool v4) { +void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) { if (loadIfReady() && _movie) { - _movie->play(startFrame, endFrame, v3, v4); + _movie->play(startFrame, endFrame, flags, obj); } } -void OSVideoSurface::proc35(int v1, int v2, int frameNumber, int flags, CGameObject *owner) { +void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) { if (loadIfReady() && _movie) { - _movie->proc12(v1, v2, frameNumber, flags, owner); + _movie->play(startFrame, endFrame, initialFrame, flags, obj); } } @@ -456,16 +456,17 @@ void OSVideoSurface::setMovieFrame(uint frameNumber) { _movie->setFrame(frameNumber); } -void OSVideoSurface::proc38(int v1, int v2) { - warning("OSVideoSurface::proc38"); +void OSVideoSurface::addMovieEvent(int frameNumber, CGameObject *obj) { + if (_movie) + _movie->addEvent(frameNumber, obj); } void OSVideoSurface::proc39(int v1, int v2) { warning("OSVideoSurface::proc39"); } -const Common::List OSVideoSurface::getMovieRangeInfo() const { - return _movie ? _movie->getMovieRangeInfo() : Common::List(); +const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const { + return _movie ? _movie->getMovieRangeInfo() : nullptr; } bool OSVideoSurface::loadIfReady() { diff --git a/engines/titanic/support/video_surface.h b/engines/titanic/support/video_surface.h index 37afccf9e1..3521be6336 100644 --- a/engines/titanic/support/video_surface.h +++ b/engines/titanic/support/video_surface.h @@ -35,6 +35,11 @@ namespace Titanic { +enum TransparencyMode { + TRANS_MASK0 = 0, TRANS_MASK255 = 1, TRANS_ALPHA0 = 2, + TRANS_ALPHA255 = 3, TRANS_DEFAULT = 4 +}; + class CScreenManager; class CJPEGDecode; class CTargaDecode; @@ -57,8 +62,7 @@ protected: CScreenManager *_screenManager; Graphics::ManagedSurface *_rawSurface; bool _pendingLoad; - void *_field40; - int _field44; + const void *_movieFrameInfo; int _field48; int _videoSurfaceNum; int _field50; @@ -69,6 +73,7 @@ public: bool _blitFlag; bool _blitStyleFlag; CResourceKey _resourceKey; + TransparencyMode _transparencyMode; public: CVideoSurface(CScreenManager *screenManager); virtual ~CVideoSurface(); @@ -190,15 +195,19 @@ public: * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint flags, CVideoSurface *surface) = 0; + virtual void playMovie(uint flags, CGameObject *obj) = 0; /** * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint startFrame, uint endFrame, int v3, bool v4) = 0; + virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0; - virtual void proc35(int v1, int v2, int frameNumber, int flags, CGameObject *owner) = 0; + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0; /** * Stops any movie currently attached to the surface @@ -206,18 +215,21 @@ public: virtual void stopMovie() = 0; /** - * Sets the movie to the specified frame number + * Set the current movie frame number */ virtual void setMovieFrame(uint frameNumber) = 0; - virtual void proc38(int v1, int v2) = 0; + /** + * Adds a movie playback event + */ + virtual void addMovieEvent(int eventId, CGameObject *obj) = 0; virtual void proc39(int v1, int v2) = 0; /** * Return any movie range info associated with the surface's movie */ - virtual const Common::List getMovieRangeInfo() const = 0; + virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0; /** * Loads the surface's resource if there's one pending @@ -257,8 +269,19 @@ public: */ void blitFrom(const Point &destPos, const Graphics::Surface *src); - void set40(void *v) { _field40 = v; } + /** + * + */ + void setMovieFrameInfo(const void *frameInfo) { _movieFrameInfo = frameInfo; } + + /** + */ + const void *getMovieFrameInfo() const { return _movieFrameInfo; } + /** + * Get the pixels associated with the surface. Only valid when the + * surface has been locked for access + */ uint16 *getPixels() { return (uint16 *)_rawSurface->getPixels(); } /** @@ -400,15 +423,19 @@ public: * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint flags, CVideoSurface *surface); + virtual void playMovie(uint flags, CGameObject *obj); /** * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint startFrame, uint endFrame, int v3, bool v4); + virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj); - virtual void proc35(int v1, int v2, int frameNumber, int flags, CGameObject *owner); + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj); /** * Stops any movie currently attached to the surface @@ -420,14 +447,17 @@ public: */ virtual void setMovieFrame(uint frameNumber); - virtual void proc38(int v1, int v2); + /** + * Adds a movie playback event + */ + virtual void addMovieEvent(int frameNumber, CGameObject *obj); virtual void proc39(int v1, int v2); /** * Return any movie range info associated with the surface's movie */ - virtual const Common::List getMovieRangeInfo() const; + virtual const CMovieRangeInfoList *getMovieRangeInfo() const; /** * Loads the surface's resource if there's one pending -- cgit v1.2.3