diff --git a/engines/titanic/game_manager.cpp b/engines/titanic/game_manager.cpp index d55406771783..9e107c92b9d5 100644 --- a/engines/titanic/game_manager.cpp +++ b/engines/titanic/game_manager.cpp @@ -39,7 +39,7 @@ CGameManager::CGameManager(CProjectItem *project, CGameView *gameView, Audio::Mi CTimeEventInfo::_nextId = 0; _movie = nullptr; - _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16); + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); _project->setGameManager(this); g_vm->_filesManager->setGameManager(this); } @@ -264,7 +264,7 @@ void CGameManager::viewChange() { delete _movieSurface; _movie = nullptr; - _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16); + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); _trueTalkManager.clear(); for (CTreeItem *treeItem = _project; treeItem; treeItem = treeItem->scan(_project)) diff --git a/engines/titanic/star_control/surface_fader_base.cpp b/engines/titanic/star_control/surface_fader_base.cpp index 57754c1ba418..fb17fb1f3149 100644 --- a/engines/titanic/star_control/surface_fader_base.cpp +++ b/engines/titanic/star_control/surface_fader_base.cpp @@ -49,7 +49,7 @@ bool CSurfaceFaderBase::setupSurface(CScreenManager *screenManager, CVideoSurfac delete _videoSurface; } - _videoSurface = screenManager->createSurface(width, height, 16); + _videoSurface = screenManager->createSurface(width, height); return true; } diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp index 8ed87a234001..d05ad64e8c33 100644 --- a/engines/titanic/support/avi_surface.cpp +++ b/engines/titanic/support/avi_surface.cpp @@ -265,6 +265,33 @@ void AVISurface::setupDecompressor() { } } +void AVISurface::copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedSurface &dest) { + assert(src.w == dest.w && src.h == dest.h); + + if (src.format.bytesPerPixel == 1) { + Graphics::Surface *s = src.convertTo(dest.format, _decoder->getPalette()); + dest.blitFrom(*s); + s->free(); + delete s; + } else { + byte a, r, g, b; + assert(src.format.bytesPerPixel == 4 && dest.format.bytesPerPixel == 2); + uint16 transPixel = _videoSurface->getTransparencyColor(); + + for (uint y = 0; y < src.h; ++y) { + const uint32 *pSrc = (const uint32 *)src.getBasePtr(0, y); + uint16 *pDest = (uint16 *)dest.getBasePtr(0, y); + + for (uint x = 0; x < src.w; ++x, ++pSrc, ++pDest) { + src.format.colorToARGB(*pSrc, a, r, g, b); + assert(a == 0 || a == 0xff); + + *pDest = (a == 0) ? transPixel : dest.format.RGBToColor(r, g, b); + } + } + } +} + uint AVISurface::getWidth() const { return _decoder->getWidth(); } @@ -309,23 +336,22 @@ bool AVISurface::renderFrame() { // Make a copy of each decoder's video frame for (int idx = 0; idx < _streamCount; ++idx) { - const Graphics::Surface *frame = (idx == 0) ? - _decoder->decodeNextFrame() : _decoder->decodeNextTransparency(); + const Graphics::Surface *frame; - if (!_movieFrameSurface[idx]) { - // Setup frame surface - _movieFrameSurface[idx] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(), - _decoder->getVideoTrack(idx).getPixelFormat()); - } + if (idx == 0) { + frame = _decoder->decodeNextFrame(); + if (!_movieFrameSurface[0]) + _movieFrameSurface[0] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(), + g_system->getScreenFormat()); - if (_movieFrameSurface[idx]->format == frame->format) { - _movieFrameSurface[idx]->blitFrom(*frame); + copyMovieFrame(*frame, *_movieFrameSurface[0]); } else { - Graphics::Surface *s = frame->convertTo(_movieFrameSurface[idx]->format, - _decoder->getPalette()); - _movieFrameSurface[idx]->blitFrom(*s); - s->free(); - delete s; + frame = _decoder->decodeNextTransparency(); + if (!_movieFrameSurface[1]) + _movieFrameSurface[1] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(), + Graphics::PixelFormat::createFormatCLUT8()); + + _movieFrameSurface[1]->blitFrom(*frame); } } @@ -397,7 +423,7 @@ Graphics::ManagedSurface *AVISurface::duplicateTransparency() const { return nullptr; } else { Graphics::ManagedSurface *dest = new Graphics::ManagedSurface(_movieFrameSurface[1]->w, - _movieFrameSurface[1]->h, _movieFrameSurface[1]->format); + _movieFrameSurface[1]->h, Graphics::PixelFormat::createFormatCLUT8()); dest->blitFrom(*_movieFrameSurface[1]); return dest; } diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h index 855732f5cb52..4ee6cc6e0b57 100644 --- a/engines/titanic/support/avi_surface.h +++ b/engines/titanic/support/avi_surface.h @@ -78,6 +78,16 @@ class AVISurface { * Sets up for video decompression */ void setupDecompressor(); + + /** + * Copys a movie frame into a local 16-bit frame surface + * @param src Source raw movie frame + * @param dest Destination 16-bit copy of the frame + * @remarks The important thing this methods different from a straight + * copy is that any pixels marked as fully transparent are replaced with + * the special transparent color value. + */ + void copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedSurface &dest); protected: /** * Start playback at the specified frame diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp index e72e928e671e..6300f65a3b4f 100644 --- a/engines/titanic/support/mouse_cursor.cpp +++ b/engines/titanic/support/mouse_cursor.cpp @@ -74,7 +74,7 @@ void CMouseCursor::loadCursorImages() { CURSOR_DATA[idx][3]); // Create the surface - CVideoSurface *surface = _screenManager->createSurface(CURSOR_SIZE, CURSOR_SIZE, 16); + CVideoSurface *surface = _screenManager->createSurface(CURSOR_SIZE, CURSOR_SIZE); _cursors[idx]._videoSurface = surface; // Open the cursors video and move to the given frame diff --git a/engines/titanic/support/movie.cpp b/engines/titanic/support/movie.cpp index 5e59ed747b6b..8863e94e1458 100644 --- a/engines/titanic/support/movie.cpp +++ b/engines/titanic/support/movie.cpp @@ -88,8 +88,7 @@ OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) : _field28 = 0; _field2C = 0; - surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight(), - _aviSurface.getBitDepth() == 32 ? 32 : 16); + surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight()); _aviSurface.setVideoSurface(surface); } @@ -119,7 +118,7 @@ void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags void OSMovie::playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) { if (!_movieSurface) - _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16); + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 32); // Set a new event target whilst the clip plays, so standard scene drawing isn't called CEventTarget eventTarget; diff --git a/engines/titanic/support/screen_manager.h b/engines/titanic/support/screen_manager.h index 0da8e0daf323..a7c929fb5f7e 100644 --- a/engines/titanic/support/screen_manager.h +++ b/engines/titanic/support/screen_manager.h @@ -185,12 +185,12 @@ class CScreenManager { /** * Resize the passed surface */ - virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp) = 0; + virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp = 16) = 0; /** * Creates a surface of a given size */ - virtual CVideoSurface *createSurface(int w, int h, int bpp) = 0; + virtual CVideoSurface *createSurface(int w, int h, int bpp = 16) = 0; /** * Creates a surface from a specified resource @@ -367,12 +367,12 @@ class OSScreenManager: CScreenManager { /** * Resize the passed surface */ - virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp); + virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp = 16); /** * Creates a surface of a given size */ - virtual CVideoSurface *createSurface(int w, int h, int bpp); + virtual CVideoSurface *createSurface(int w, int h, int bpp = 16); /** * Creates a surface from a specified resource