From 63ec47e62f23e310786168cd596667015b2d2523 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 26 Nov 2016 10:53:47 -0500 Subject: TITANIC: Add support for 32-bit surfaces Some of the game videos have alpha levels, which are lost if the surfaces are converted to 16-bit. This adds better support for creating 32-bit video surfaces, so the information won't be lost --- engines/titanic/game_manager.cpp | 4 +- .../titanic/star_control/surface_fader_base.cpp | 2 +- engines/titanic/support/avi_surface.cpp | 8 +++- engines/titanic/support/avi_surface.h | 6 +++ engines/titanic/support/direct_draw.cpp | 8 ++-- engines/titanic/support/direct_draw.h | 2 +- engines/titanic/support/direct_draw_surface.cpp | 8 +++- engines/titanic/support/direct_draw_surface.h | 6 ++- engines/titanic/support/image_decoders.cpp | 4 +- engines/titanic/support/mouse_cursor.cpp | 2 +- engines/titanic/support/movie.cpp | 5 +- engines/titanic/support/screen_manager.cpp | 8 ++-- engines/titanic/support/screen_manager.h | 8 ++-- engines/titanic/support/text_cursor.cpp | 2 +- engines/titanic/support/video_surface.cpp | 55 +++++++--------------- engines/titanic/support/video_surface.h | 8 ++-- 16 files changed, 66 insertions(+), 70 deletions(-) (limited to 'engines') diff --git a/engines/titanic/game_manager.cpp b/engines/titanic/game_manager.cpp index 9e107c92b9..d554067717 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); + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16); _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); + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16); _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 fb17fb1f31..57754c1ba4 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); + _videoSurface = screenManager->createSurface(width, height, 16); return true; } diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp index 2a671156e0..8ed87a2340 100644 --- a/engines/titanic/support/avi_surface.cpp +++ b/engines/titanic/support/avi_surface.cpp @@ -36,7 +36,7 @@ Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack(uint idx) { return *track; } -AVISurface::AVISurface(const CResourceKey &key) { +AVISurface::AVISurface(const CResourceKey &key) : _movieName(key.getString()) { _videoSurface = nullptr; _streamCount = 0; _movieFrameSurface[0] = _movieFrameSurface[1] = nullptr; @@ -51,7 +51,7 @@ AVISurface::AVISurface(const CResourceKey &key) { // Create a decoder _decoder = new AVIDecoder(Audio::Mixer::kPlainSoundType); - if (!_decoder->loadFile(key.getString())) + if (!_decoder->loadFile(_movieName)) error("Could not open video - %s", key.getString().c_str()); _streamCount = _decoder->videoTrackCount(); @@ -437,4 +437,8 @@ void AVISurface::playCutscene(const Rect &r, uint startFrame, uint endFrame) { stop(); } +uint AVISurface::getBitDepth() const { + return _decoder->getVideoTrack(0).getBitCount(); +} + } // End of namespace Titanic diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h index 2a4b321f0f..855732f5cb 100644 --- a/engines/titanic/support/avi_surface.h +++ b/engines/titanic/support/avi_surface.h @@ -67,6 +67,7 @@ private: bool _isReversed; int _currentFrame; uint32 _priorFrameTime; + Common::String _movieName; private: /** * Render a frame to the video surface @@ -203,6 +204,11 @@ public: * Plays an interruptable cutscene */ void playCutscene(const Rect &r, uint startFrame, uint endFrame); + + /** + * Returns the pixel depth of the movie in bits + */ + uint getBitDepth() const; }; } // End of namespace Titanic diff --git a/engines/titanic/support/direct_draw.cpp b/engines/titanic/support/direct_draw.cpp index 8e510861ae..faed140ea7 100644 --- a/engines/titanic/support/direct_draw.cpp +++ b/engines/titanic/support/direct_draw.cpp @@ -47,7 +47,7 @@ void DirectDraw::diagnostics() { DirectDrawSurface *DirectDraw::createSurfaceFromDesc(const DDSurfaceDesc &desc) { DirectDrawSurface *surface = new DirectDrawSurface(); - surface->create(desc._w, desc._h); + surface->create(desc._w, desc._h, desc._bpp); return surface; } @@ -82,15 +82,15 @@ void DirectDrawManager::initFullScreen() { _mainSurface = new DirectDrawSurface(); _mainSurface->create(g_vm->_screen); _backSurfaces[0] = new DirectDrawSurface(); - _backSurfaces[0]->create(_directDraw._width, _directDraw._height); + _backSurfaces[0]->create(_directDraw._width, _directDraw._height, 32); } -DirectDrawSurface *DirectDrawManager::createSurface(int w, int h, int surfaceNum) { +DirectDrawSurface *DirectDrawManager::createSurface(int w, int h, int bpp, int surfaceNum) { if (surfaceNum) return nullptr; assert(_mainSurface); - return _directDraw.createSurfaceFromDesc(DDSurfaceDesc(w, h)); + return _directDraw.createSurfaceFromDesc(DDSurfaceDesc(w, h, bpp)); } } // End of namespace Titanic diff --git a/engines/titanic/support/direct_draw.h b/engines/titanic/support/direct_draw.h index 08ead6d798..8370191648 100644 --- a/engines/titanic/support/direct_draw.h +++ b/engines/titanic/support/direct_draw.h @@ -87,7 +87,7 @@ public: /** * Create a surface */ - DirectDrawSurface *createSurface(int w, int h, int surfaceNum); + DirectDrawSurface *createSurface(int w, int h, int bpp, int surfaceNum); }; } // End of namespace Titanic diff --git a/engines/titanic/support/direct_draw_surface.cpp b/engines/titanic/support/direct_draw_surface.cpp index 9ebda15b0e..126cebfaeb 100644 --- a/engines/titanic/support/direct_draw_surface.cpp +++ b/engines/titanic/support/direct_draw_surface.cpp @@ -38,8 +38,12 @@ void DirectDrawSurface::create(Graphics::ManagedSurface *surface) { _disposeAfterUse = DisposeAfterUse::NO; } -void DirectDrawSurface::create(int w, int h) { - Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); +void DirectDrawSurface::create(int w, int h, int bpp) { + assert(bpp == 16 || bpp == 32); + Graphics::PixelFormat pixelFormat = (bpp == 32) ? + Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0) : + Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); + _surface = new Graphics::ManagedSurface(w, h, pixelFormat); _disposeAfterUse = DisposeAfterUse::YES; } diff --git a/engines/titanic/support/direct_draw_surface.h b/engines/titanic/support/direct_draw_surface.h index af19e369d2..82749afffa 100644 --- a/engines/titanic/support/direct_draw_surface.h +++ b/engines/titanic/support/direct_draw_surface.h @@ -35,10 +35,12 @@ class TitanicEngine; struct DDSurfaceDesc { int _w; int _h; + int _bpp; int _flags; int _caps; - DDSurfaceDesc(int w, int h) : _w(w), _h(h), _flags(0x1006), _caps(64) {} + DDSurfaceDesc(int w, int h, int bpp) : _w(w), _h(h), _bpp(bpp), + _flags(0x1006), _caps(64) {} }; class DirectDrawSurface { @@ -52,7 +54,7 @@ public: /** * Create a surface */ - void create(int w, int h); + void create(int w, int h, int bpp); /** * Create a surface based on a passed surface diff --git a/engines/titanic/support/image_decoders.cpp b/engines/titanic/support/image_decoders.cpp index 2dba66fbb3..3819b85116 100644 --- a/engines/titanic/support/image_decoders.cpp +++ b/engines/titanic/support/image_decoders.cpp @@ -36,7 +36,7 @@ void CJPEGDecode::decode(OSVideoSurface &surface, const CString &name) { // Resize the surface if necessary if (!surface.hasSurface() || surface.getWidth() != srcSurf->w || surface.getHeight() != srcSurf->h) - surface.recreate(srcSurf->w, srcSurf->h); + surface.recreate(srcSurf->w, srcSurf->h, 16); // Convert the decoded surface to the correct pixel format, and then copy it over surface.lock(); @@ -64,7 +64,7 @@ void CTargaDecode::decode(OSVideoSurface &surface, const CString &name) { // Resize the surface if necessary if (!surface.hasSurface() || surface.getWidth() != srcSurf->w || surface.getHeight() != srcSurf->h) - surface.recreate(srcSurf->w, srcSurf->h); + surface.recreate(srcSurf->w, srcSurf->h, 16); // Convert the decoded surface to the correct pixel format, and then copy it over surface.lock(); diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp index 6300f65a3b..e72e928e67 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); + CVideoSurface *surface = _screenManager->createSurface(CURSOR_SIZE, CURSOR_SIZE, 16); _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 c26e4eb3c4..5e59ed747b 100644 --- a/engines/titanic/support/movie.cpp +++ b/engines/titanic/support/movie.cpp @@ -88,7 +88,8 @@ OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) : _field28 = 0; _field2C = 0; - surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight()); + surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight(), + _aviSurface.getBitDepth() == 32 ? 32 : 16); _aviSurface.setVideoSurface(surface); } @@ -118,7 +119,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); + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16); // 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.cpp b/engines/titanic/support/screen_manager.cpp index 2a675394b5..553486d094 100644 --- a/engines/titanic/support/screen_manager.cpp +++ b/engines/titanic/support/screen_manager.cpp @@ -293,13 +293,13 @@ void OSScreenManager::clearSurface(SurfaceNum surfaceNum, Rect *bounds) { _directDrawManager._backSurfaces[surfaceNum]->fill(bounds, 0); } -void OSScreenManager::resizeSurface(CVideoSurface *surface, int width, int height) { - DirectDrawSurface *ddSurface = _directDrawManager.createSurface(width, height, 0); +void OSScreenManager::resizeSurface(CVideoSurface *surface, int width, int height, int bpp) { + DirectDrawSurface *ddSurface = _directDrawManager.createSurface(width, height, bpp, 0); surface->setSurface(this, ddSurface); } -CVideoSurface *OSScreenManager::createSurface(int w, int h) { - DirectDrawSurface *ddSurface = _directDrawManager.createSurface(w, h, 0); +CVideoSurface *OSScreenManager::createSurface(int w, int h, int bpp) { + DirectDrawSurface *ddSurface = _directDrawManager.createSurface(w, h, bpp, 0); return new OSVideoSurface(this, ddSurface); } diff --git a/engines/titanic/support/screen_manager.h b/engines/titanic/support/screen_manager.h index f88928af8b..0da8e0daf3 100644 --- a/engines/titanic/support/screen_manager.h +++ b/engines/titanic/support/screen_manager.h @@ -185,12 +185,12 @@ public: /** * Resize the passed surface */ - virtual void resizeSurface(CVideoSurface *surface, int width, int height) = 0; + virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp) = 0; /** * Creates a surface of a given size */ - virtual CVideoSurface *createSurface(int w, int h) = 0; + virtual CVideoSurface *createSurface(int w, int h, int bpp) = 0; /** * Creates a surface from a specified resource @@ -367,12 +367,12 @@ public: /** * Resize the passed surface */ - virtual void resizeSurface(CVideoSurface *surface, int width, int height); + virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp); /** * Creates a surface of a given size */ - virtual CVideoSurface *createSurface(int w, int h); + virtual CVideoSurface *createSurface(int w, int h, int bpp); /** * Creates a surface from a specified resource diff --git a/engines/titanic/support/text_cursor.cpp b/engines/titanic/support/text_cursor.cpp index 5c7593ba68..1da98c1cf7 100644 --- a/engines/titanic/support/text_cursor.cpp +++ b/engines/titanic/support/text_cursor.cpp @@ -32,7 +32,7 @@ CTextCursor::CTextCursor(CScreenManager *screenManager) : _backRenderSurface(nullptr), _frontRenderSurface(nullptr), _blinkDelay(300), _size(2, 10), _priorBlinkTime(0), _cursorR(0), _cursorG(0), _cursorB(0), _mode(-1) { - _surface = screenManager->createSurface(10, 10); + _surface = screenManager->createSurface(10, 10, 16); } CTextCursor::~CTextCursor() { diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp index 7455e8cfef..e24063188d 100644 --- a/engines/titanic/support/video_surface.cpp +++ b/engines/titanic/support/video_surface.cpp @@ -158,25 +158,9 @@ void CVideoSurface::blitRect(const Rect &srcRect, const Rect &destRect, CVideoSu if (src->lock()) { const Graphics::ManagedSurface *srcSurface = src->_rawSurface; Graphics::ManagedSurface *destSurface = _rawSurface; - Graphics::Surface destArea = destSurface->getSubArea(destRect); const uint transColor = src->getTransparencyColor(); - const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr( - srcRect.left, srcRect.top); - uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, 0); - - for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr, - srcPtr += src->getPitch() / 2, - destPtr += destArea.pitch / 2) { - // Prepare for copying the line - const uint16 *lineSrcP = srcPtr; - uint16 *lineDestP = destPtr; - - for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX, ++lineSrcP, ++lineDestP) { - if (*lineSrcP != transColor) - *lineDestP = *lineSrcP; - } - } + destSurface->transBlitFrom(*srcSurface, srcRect, destRect, transColor); src->unlock(); } @@ -190,28 +174,22 @@ void CVideoSurface::flippedBlitRect(const Rect &srcRect, const Rect &destRect, C transBlitRect(srcRect, destRect, src, true); } else if (lock()) { if (src->lock()) { - const Graphics::ManagedSurface *srcSurface = src->_rawSurface; + Graphics::ManagedSurface *srcSurface = src->_rawSurface; Graphics::ManagedSurface *destSurface = _rawSurface; - Graphics::Surface destArea = destSurface->getSubArea(destRect); + const Graphics::Surface srcArea = srcSurface->getSubArea(srcRect); const uint transColor = src->getTransparencyColor(); - const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr( - srcRect.left, srcRect.top); - uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, destArea.h - 1); - - for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr, - srcPtr += src->getPitch() / 2, - destPtr -= destArea.pitch / 2) { - // Prepare for copying the line - const uint16 *lineSrcP = srcPtr; - uint16 *lineDestP = destPtr; - - for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX, ++lineSrcP, ++lineDestP) { - if (*lineSrcP != transColor) - *lineDestP = *lineSrcP; - } + // Vertically flip the source area + Graphics::ManagedSurface flippedArea(srcArea.w, srcArea.h, srcArea.format); + for (int y = 0; y < srcArea.h; ++y) { + const byte *pSrc = (const byte *)srcArea.getBasePtr(0, y); + byte *pDest = (byte *)flippedArea.getBasePtr(0, flippedArea.h - y - 1); + Common::copy(pSrc, pSrc + srcArea.pitch, pDest); } + destSurface->transBlitFrom(flippedArea, + Common::Point(destRect.left, destRect.top), transColor); + src->unlock(); } @@ -221,6 +199,7 @@ void CVideoSurface::flippedBlitRect(const Rect &srcRect, const Rect &destRect, C void CVideoSurface::transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src, bool flipFlag) { assert(srcRect.width() == destRect.width() && srcRect.height() == destRect.height()); + assert(src->getPixelDepth() == 2); if (lock()) { if (src->lock()) { @@ -442,18 +421,18 @@ int OSVideoSurface::getBpp() { return getPixelDepth(); } -void OSVideoSurface::recreate(int width, int height) { +void OSVideoSurface::recreate(int width, int height, int bpp) { freeSurface(); - _screenManager->resizeSurface(this, width, height); + _screenManager->resizeSurface(this, width, height, bpp); if (_ddSurface) _videoSurfaceCounter += _ddSurface->getSize(); } -void OSVideoSurface::resize(int width, int height) { +void OSVideoSurface::resize(int width, int height, int bpp) { if (!_ddSurface || _ddSurface->getWidth() != width || _ddSurface->getHeight() != height) - recreate(width, height); + recreate(width, height, bpp); } void OSVideoSurface::detachSurface() { diff --git a/engines/titanic/support/video_surface.h b/engines/titanic/support/video_surface.h index 390e70bc33..77b9e61ad7 100644 --- a/engines/titanic/support/video_surface.h +++ b/engines/titanic/support/video_surface.h @@ -176,12 +176,12 @@ public: /** * Recreates the surface */ - virtual void recreate(int width, int height) = 0; + virtual void recreate(int width, int height, int bpp = 16) = 0; /** * Resizes the surface */ - virtual void resize(int width, int height) = 0; + virtual void resize(int width, int height, int bpp = 16) = 0; /** * Detachs the underlying raw surface @@ -423,12 +423,12 @@ public: /** * Recreates the surface with the designated size */ - virtual void recreate(int width, int height); + virtual void recreate(int width, int height, int bpp = 16); /** * Resizes the surface */ - virtual void resize(int width, int height); + virtual void resize(int width, int height, int bpp = 16); /** * Detachs the underlying raw surface -- cgit v1.2.3