diff options
Diffstat (limited to 'engines/zvision/graphics/render_manager.cpp')
-rw-r--r-- | engines/zvision/graphics/render_manager.cpp | 873 |
1 files changed, 512 insertions, 361 deletions
diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index e2ad13a330..f978ef7844 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -39,71 +39,75 @@ namespace ZVision { -RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat) +RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat, bool doubleFPS) : _engine(engine), _system(engine->_system), - _wrkWidth(workingWindow.width()), - _wrkHeight(workingWindow.height()), - _screenCenterX(_wrkWidth / 2), - _screenCenterY(_wrkHeight / 2), + _screenCenterX(_workingWindow.width() / 2), + _screenCenterY(_workingWindow.height() / 2), _workingWindow(workingWindow), _pixelFormat(pixelFormat), - _bkgWidth(0), - _bkgHeight(0), - _bkgOff(0), - _renderTable(_wrkWidth, _wrkHeight) { + _backgroundWidth(0), + _backgroundHeight(0), + _backgroundOffset(0), + _renderTable(_workingWindow.width(), _workingWindow.height()), + _doubleFPS(doubleFPS), + _subid(0) { - _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); - _effectWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); - _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); - _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat); - _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); + _backgroundSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); + _effectSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); + _warpedSceneSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); + _menuSurface.create(windowWidth, workingWindow.top, _pixelFormat); - _menuWndRect = Common::Rect(0, 0, windowWidth, workingWindow.top); - _subWndRect = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); + _menuArea = Common::Rect(0, 0, windowWidth, workingWindow.top); - _subid = 0; + initSubArea(windowWidth, windowHeight, workingWindow); } RenderManager::~RenderManager() { - _curBkg.free(); - _wrkWnd.free(); - _effectWnd.free(); - _outWnd.free(); - _menuWnd.free(); - _subWnd.free(); + _currentBackgroundImage.free(); + _backgroundSurface.free(); + _effectSurface.free(); + _warpedSceneSurface.free(); + _menuSurface.free(); + _subtitleSurface.free(); } -void RenderManager::renderBackbufferToScreen() { - Graphics::Surface *out = &_outWnd; - Graphics::Surface *in = &_wrkWnd; +void RenderManager::renderSceneToScreen() { + Graphics::Surface *out = &_warpedSceneSurface; + Graphics::Surface *in = &_backgroundSurface; Common::Rect outWndDirtyRect; + // If we have graphical effects, we apply them using a temporary buffer if (!_effects.empty()) { bool copied = false; - Common::Rect windRect(_wrkWidth, _wrkHeight); - for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { + Common::Rect windowRect(_workingWindow.width(), _workingWindow.height()); + + for (EffectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { Common::Rect rect = (*it)->getRegion(); - Common::Rect scrPlace = rect; - if ((*it)->isPort()) - scrPlace = bkgRectToScreen(scrPlace); - if (windRect.intersects(scrPlace)) { + Common::Rect screenSpaceLocation = rect; + + if ((*it)->isPort()) { + screenSpaceLocation = transformBackgroundSpaceRectToScreenSpace(screenSpaceLocation); + } + + if (windowRect.intersects(screenSpaceLocation)) { if (!copied) { copied = true; - _effectWnd.copyFrom(_wrkWnd); - in = &_effectWnd; + _effectSurface.copyFrom(_backgroundSurface); + in = &_effectSurface; } const Graphics::Surface *post; if ((*it)->isPort()) - post = (*it)->draw(_curBkg.getSubArea(rect)); + post = (*it)->draw(_currentBackgroundImage.getSubArea(rect)); else - post = (*it)->draw(_effectWnd.getSubArea(rect)); - blitSurfaceToSurface(*post, _effectWnd, scrPlace.left, scrPlace.top); - scrPlace.clip(windRect); - if (_wrkWndDirtyRect .isEmpty()) { - _wrkWndDirtyRect = scrPlace; + post = (*it)->draw(_effectSurface.getSubArea(rect)); + Common::Rect empty; + blitSurfaceToSurface(*post, empty, _effectSurface, screenSpaceLocation.left, screenSpaceLocation.top); + screenSpaceLocation.clip(windowRect); + if (_backgroundSurfaceDirtyRect .isEmpty()) { + _backgroundSurfaceDirtyRect = screenSpaceLocation; } else { - _wrkWndDirtyRect.extend(scrPlace); + _backgroundSurfaceDirtyRect.extend(screenSpaceLocation); } } } @@ -111,25 +115,40 @@ void RenderManager::renderBackbufferToScreen() { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA || state == RenderTable::TILT) { - if (!_wrkWndDirtyRect.isEmpty()) { - _renderTable.mutateImage(&_outWnd, in); - out = &_outWnd; - outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight); + if (!_backgroundSurfaceDirtyRect.isEmpty()) { + _renderTable.mutateImage(&_warpedSceneSurface, in); + out = &_warpedSceneSurface; + outWndDirtyRect = Common::Rect(_workingWindow.width(), _workingWindow.height()); } } else { out = in; - outWndDirtyRect = _wrkWndDirtyRect; + outWndDirtyRect = _backgroundSurfaceDirtyRect; } if (!outWndDirtyRect.isEmpty()) { - _system->copyRectToScreen(out->getBasePtr(outWndDirtyRect.left, outWndDirtyRect.top), out->pitch, - outWndDirtyRect.left + _workingWindow.left, - outWndDirtyRect.top + _workingWindow.top, - outWndDirtyRect.width(), - outWndDirtyRect.height()); + Common::Rect rect( + outWndDirtyRect.left + _workingWindow.left, + outWndDirtyRect.top + _workingWindow.top, + outWndDirtyRect.left + _workingWindow.left + outWndDirtyRect.width(), + outWndDirtyRect.top + _workingWindow.top + outWndDirtyRect.height() + ); + copyToScreen(*out, rect, outWndDirtyRect.left, outWndDirtyRect.top); } } +void RenderManager::copyToScreen(const Graphics::Surface &surface, Common::Rect &rect, int16 srcLeft, int16 srcTop) { + // Convert the surface to RGB565, if needed + Graphics::Surface *outSurface = surface.convertTo(_engine->_screenPixelFormat); + _system->copyRectToScreen(outSurface->getBasePtr(srcLeft, srcTop), + outSurface->pitch, + rect.left, + rect.top, + rect.width(), + rect.height()); + outSurface->free(); + delete outSurface; +} + void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) { Graphics::Surface surface; readImageToSurface(fileName, surface); @@ -157,97 +176,8 @@ void RenderManager::renderImageToBackground(const Common::String &fileName, int1 } void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) { - Common::File file; - - if (!_engine->getSearchManager()->openFile(file, fileName)) { - warning("Could not open file %s", fileName.c_str()); - return; - } - - // Read the magic number - // Some files are true TGA, while others are TGZ - uint32 fileType = file.readUint32BE(); - - uint32 imageWidth; - uint32 imageHeight; - Image::TGADecoder tga; - uint16 *buffer; bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA; - // All ZVision images are in RGB 555 - Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); - destination.format = pixelFormat555; - - bool isTGZ; - - // Check for TGZ files - if (fileType == MKTAG('T', 'G', 'Z', '\0')) { - isTGZ = true; - - // TGZ files have a header and then Bitmap data that is compressed with LZSS - uint32 decompressedSize = file.readSint32LE(); - imageWidth = file.readSint32LE(); - imageHeight = file.readSint32LE(); - - LzssReadStream lzssStream(&file); - buffer = (uint16 *)(new uint16[decompressedSize]); - lzssStream.read(buffer, decompressedSize); - } else { - isTGZ = false; - - // Reset the cursor - file.seek(0); - - // Decode - if (!tga.loadStream(file)) { - warning("Error while reading TGA image"); - return; - } - - Graphics::Surface tgaSurface = *(tga.getSurface()); - imageWidth = tgaSurface.w; - imageHeight = tgaSurface.h; - - buffer = (uint16 *)tgaSurface.getPixels(); - } - - // Flip the width and height if transposed - if (isTransposed) { - uint16 temp = imageHeight; - imageHeight = imageWidth; - imageWidth = temp; - } - - // If the destination internal buffer is the same size as what we're copying into it, - // there is no need to free() and re-create - if (imageWidth != destination.w || imageHeight != destination.h) { - destination.create(imageWidth, imageHeight, pixelFormat555); - } - - // If transposed, 'un-transpose' the data while copying it to the destination - // Otherwise, just do a simple copy - if (isTransposed) { - uint16 *dest = (uint16 *)destination.getPixels(); - - for (uint32 y = 0; y < imageHeight; ++y) { - uint32 columnIndex = y * imageWidth; - - for (uint32 x = 0; x < imageWidth; ++x) { - dest[columnIndex + x] = buffer[x * imageHeight + y]; - } - } - } else { - memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel); - } - - // Cleanup - if (isTGZ) { - delete[] buffer; - } else { - tga.destroy(); - } - - // Convert in place to RGB 565 from RGB 555 - destination.convertToInPlace(_pixelFormat); + readImageToSurface(fileName, destination, isTransposed); } void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed) { @@ -266,9 +196,8 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: uint32 imageHeight; Image::TGADecoder tga; uint16 *buffer; - // All ZVision images are in RGB 555 - Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); - destination.format = pixelFormat555; + // All Z-Vision images are in RGB 555 + destination.format = _engine->_resourcePixelFormat; bool isTGZ; @@ -277,13 +206,17 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: isTGZ = true; // TGZ files have a header and then Bitmap data that is compressed with LZSS - uint32 decompressedSize = file.readSint32LE(); + uint32 decompressedSize = file.readSint32LE() / 2; imageWidth = file.readSint32LE(); imageHeight = file.readSint32LE(); LzssReadStream lzssStream(&file); buffer = (uint16 *)(new uint16[decompressedSize]); - lzssStream.read(buffer, decompressedSize); + lzssStream.read(buffer, 2 * decompressedSize); +#ifndef SCUMM_LITTLE_ENDIAN + for (uint32 i = 0; i < decompressedSize; ++i) + buffer[i] = FROM_LE_16(buffer[i]); +#endif } else { isTGZ = false; @@ -313,7 +246,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: // If the destination internal buffer is the same size as what we're copying into it, // there is no need to free() and re-create if (imageWidth != destination.w || imageHeight != destination.h) { - destination.create(imageWidth, imageHeight, pixelFormat555); + destination.create(imageWidth, imageHeight, _engine->_resourcePixelFormat); } // If transposed, 'un-transpose' the data while copying it to the destination @@ -329,7 +262,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: } } } else { - memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel); + memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * destination.format.bytesPerPixel); } // Cleanup @@ -338,9 +271,6 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: } else { tga.destroy(); } - - // Convert in place to RGB 565 from RGB 555 - destination.convertToInPlace(_pixelFormat); } const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) { @@ -354,20 +284,20 @@ const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point & } if (state == RenderTable::PANORAMA) { - newPoint += (Common::Point(_bkgOff - _screenCenterX, 0)); + newPoint += (Common::Point(_backgroundOffset - _screenCenterX, 0)); } else if (state == RenderTable::TILT) { - newPoint += (Common::Point(0, _bkgOff - _screenCenterY)); + newPoint += (Common::Point(0, _backgroundOffset - _screenCenterY)); } - if (_bkgWidth) - newPoint.x %= _bkgWidth; - if (_bkgHeight) - newPoint.y %= _bkgHeight; + if (_backgroundWidth) + newPoint.x %= _backgroundWidth; + if (_backgroundHeight) + newPoint.y %= _backgroundHeight; if (newPoint.x < 0) - newPoint.x += _bkgWidth; + newPoint.x += _backgroundWidth; if (newPoint.y < 0) - newPoint.y += _bkgHeight; + newPoint.y += _backgroundHeight; return newPoint; } else { @@ -380,18 +310,18 @@ RenderTable *RenderManager::getRenderTable() { } void RenderManager::setBackgroundImage(const Common::String &fileName) { - readImageToSurface(fileName, _curBkg); - _bkgWidth = _curBkg.w; - _bkgHeight = _curBkg.h; - _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); + readImageToSurface(fileName, _currentBackgroundImage); + _backgroundWidth = _currentBackgroundImage.w; + _backgroundHeight = _currentBackgroundImage.h; + _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); } void RenderManager::setBackgroundPosition(int offset) { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::TILT || state == RenderTable::PANORAMA) - if (_bkgOff != offset) - _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); - _bkgOff = offset; + if (_backgroundOffset != offset) + _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); + _backgroundOffset = offset; _engine->getScriptManager()->setStateValue(StateKey_ViewPos, offset); } @@ -400,9 +330,9 @@ uint32 RenderManager::getCurrentBackgroundOffset() { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - return _bkgOff; + return _backgroundOffset; } else if (state == RenderTable::TILT) { - return _bkgOff; + return _backgroundOffset; } else { return 0; } @@ -454,10 +384,6 @@ void RenderManager::scaleBuffer(const void *src, void *dst, uint32 srcWidth, uin } void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y) { - - if (src.format != dst.format) - return; - Common::Rect srcRect = _srcRect; if (srcRect.isEmpty()) srcRect = Common::Rect(src.w, src.h); @@ -468,8 +394,10 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (srcRect.isEmpty() || !srcRect.isValidRect()) return; + Graphics::Surface *srcAdapted = src.convertTo(dst.format); + // Copy srcRect from src surface to dst surface - const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top); + const byte *srcBuffer = (const byte *)srcAdapted->getBasePtr(srcRect.left, srcRect.top); int xx = _x; int yy = _y; @@ -479,8 +407,11 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (yy < 0) yy = 0; - if (_x >= dst.w || _y >= dst.h) + if (_x >= dst.w || _y >= dst.h) { + srcAdapted->free(); + delete srcAdapted; return; + } byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy); @@ -488,17 +419,16 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com int32 h = srcRect.height(); for (int32 y = 0; y < h; y++) { - memcpy(dstBuffer, srcBuffer, w * src.format.bytesPerPixel); - srcBuffer += src.pitch; + memcpy(dstBuffer, srcBuffer, w * srcAdapted->format.bytesPerPixel); + srcBuffer += srcAdapted->pitch; dstBuffer += dst.pitch; } + + srcAdapted->free(); + delete srcAdapted; } void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey) { - - if (src.format != dst.format) - return; - Common::Rect srcRect = _srcRect; if (srcRect.isEmpty()) srcRect = Common::Rect(src.w, src.h); @@ -509,10 +439,11 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (srcRect.isEmpty() || !srcRect.isValidRect()) return; - uint32 _keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1); + Graphics::Surface *srcAdapted = src.convertTo(dst.format); + uint32 keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1); // Copy srcRect from src surface to dst surface - const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top); + const byte *srcBuffer = (const byte *)srcAdapted->getBasePtr(srcRect.left, srcRect.top); int xx = _x; int yy = _y; @@ -522,8 +453,11 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (yy < 0) yy = 0; - if (_x >= dst.w || _y >= dst.h) + if (_x >= dst.w || _y >= dst.h) { + srcAdapted->free(); + delete srcAdapted; return; + } byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy); @@ -531,12 +465,12 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com int32 h = srcRect.height(); for (int32 y = 0; y < h; y++) { - switch (src.format.bytesPerPixel) { + switch (srcAdapted->format.bytesPerPixel) { case 1: { const uint *srcTemp = (const uint *)srcBuffer; uint *dstTemp = (uint *)dstBuffer; for (int32 x = 0; x < w; x++) { - if (*srcTemp != _keycolor) + if (*srcTemp != keycolor) *dstTemp = *srcTemp; srcTemp++; dstTemp++; @@ -548,7 +482,7 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com const uint16 *srcTemp = (const uint16 *)srcBuffer; uint16 *dstTemp = (uint16 *)dstBuffer; for (int32 x = 0; x < w; x++) { - if (*srcTemp != _keycolor) + if (*srcTemp != keycolor) *dstTemp = *srcTemp; srcTemp++; dstTemp++; @@ -560,7 +494,7 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com const uint32 *srcTemp = (const uint32 *)srcBuffer; uint32 *dstTemp = (uint32 *)dstBuffer; for (int32 x = 0; x < w; x++) { - if (*srcTemp != _keycolor) + if (*srcTemp != keycolor) *dstTemp = *srcTemp; srcTemp++; dstTemp++; @@ -571,60 +505,32 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com default: break; } - srcBuffer += src.pitch; + srcBuffer += srcAdapted->pitch; dstBuffer += dst.pitch; } -} -void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, dst, x, y); + srcAdapted->free(); + delete srcAdapted; } -void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) { +void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, int32 colorkey) { Common::Rect empt; - blitSurfaceToSurface(src, empt, dst, x, y, colorkey); -} - -void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, _curBkg, x, y); - Common::Rect dirty(src.w, src.h); - dirty.translate(x, y); - if (_bkgDirtyRect.isEmpty()) - _bkgDirtyRect = dirty; + if (colorkey >= 0) + blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y, colorkey); else - _bkgDirtyRect.extend(dirty); -} - -void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, _curBkg, x, y, colorkey); + blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); - if (_bkgDirtyRect.isEmpty()) - _bkgDirtyRect = dirty; + if (_backgroundDirtyRect.isEmpty()) + _backgroundDirtyRect = dirty; else - _bkgDirtyRect.extend(dirty); -} - -void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect) { - if (src.w == _dstRect.width() && src.h == _dstRect.height()) - blitSurfaceToBkg(src, _dstRect.left, _dstRect.top); - else { - Graphics::Surface *tmp = new Graphics::Surface; - tmp->create(_dstRect.width(), _dstRect.height(), src.format); - scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height()); - blitSurfaceToBkg(*tmp, _dstRect.left, _dstRect.top); - tmp->free(); - delete tmp; - } + _backgroundDirtyRect.extend(dirty); } -void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, uint32 colorkey) { - if (src.w == _dstRect.width() && src.h == _dstRect.height()) +void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, int32 colorkey) { + if (src.w == _dstRect.width() && src.h == _dstRect.height()) { blitSurfaceToBkg(src, _dstRect.left, _dstRect.top, colorkey); - else { + } else { Graphics::Surface *tmp = new Graphics::Surface; tmp->create(_dstRect.width(), _dstRect.height(), src.format); scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height()); @@ -634,160 +540,163 @@ void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const C } } -void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y) { +void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, int32 colorkey) { Common::Rect empt; - blitSurfaceToSurface(src, empt, _menuWnd, x, y); - Common::Rect dirty(src.w, src.h); - dirty.translate(x, y); - if (_menuWndDirtyRect.isEmpty()) - _menuWndDirtyRect = dirty; + if (colorkey >= 0) + blitSurfaceToSurface(src, empt, _menuSurface, x, y, colorkey); else - _menuWndDirtyRect.extend(dirty); -} - -void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, _menuWnd, x, y, colorkey); + blitSurfaceToSurface(src, empt, _menuSurface, x, y); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); - if (_menuWndDirtyRect.isEmpty()) - _menuWndDirtyRect = dirty; + if (_menuSurfaceDirtyRect.isEmpty()) + _menuSurfaceDirtyRect = dirty; else - _menuWndDirtyRect.extend(dirty); + _menuSurfaceDirtyRect.extend(dirty); } Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) { Common::Rect dst = rect; - dst.clip(_bkgWidth, _bkgHeight); + dst.clip(_backgroundWidth, _backgroundHeight); if (dst.isEmpty() || !dst.isValidRect()) return NULL; Graphics::Surface *srf = new Graphics::Surface; - srf->create(dst.width(), dst.height(), _curBkg.format); + srf->create(dst.width(), dst.height(), _currentBackgroundImage.format); - srf->copyRectToSurface(_curBkg, 0, 0, Common::Rect(dst)); + srf->copyRectToSurface(_currentBackgroundImage, 0, 0, Common::Rect(dst)); return srf; } -Graphics::Surface *RenderManager::loadImage(Common::String &file) { +Graphics::Surface *RenderManager::loadImage(Common::String file) { Graphics::Surface *tmp = new Graphics::Surface; readImageToSurface(file, *tmp); return tmp; } -Graphics::Surface *RenderManager::loadImage(const char *file) { - Common::String str = Common::String(file); - return loadImage(str); -} - -Graphics::Surface *RenderManager::loadImage(Common::String &file, bool transposed) { +Graphics::Surface *RenderManager::loadImage(Common::String file, bool transposed) { Graphics::Surface *tmp = new Graphics::Surface; readImageToSurface(file, *tmp, transposed); return tmp; } -Graphics::Surface *RenderManager::loadImage(const char *file, bool transposed) { - Common::String str = Common::String(file); - return loadImage(str, transposed); -} - -void RenderManager::prepareBkg() { - _bkgDirtyRect.clip(_bkgWidth, _bkgHeight); +void RenderManager::prepareBackground() { + _backgroundDirtyRect.clip(_backgroundWidth, _backgroundHeight); RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - Common::Rect viewPort(_wrkWidth, _wrkHeight); - viewPort.translate(-(_screenCenterX - _bkgOff), 0); - Common::Rect drawRect = _bkgDirtyRect; + // Calculate the visible portion of the background + Common::Rect viewPort(_workingWindow.width(), _workingWindow.height()); + viewPort.translate(-(_screenCenterX - _backgroundOffset), 0); + Common::Rect drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); - if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - _bkgOff + drawRect.left, drawRect.top); + // Render the visible portion + if (!drawRect.isEmpty()) { + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, _screenCenterX - _backgroundOffset + drawRect.left, drawRect.top); + } - _wrkWndDirtyRect = _bkgDirtyRect; - _wrkWndDirtyRect.translate(_screenCenterX - _bkgOff, 0); + // Mark the dirty portion of the surface + _backgroundSurfaceDirtyRect = _backgroundDirtyRect; + _backgroundSurfaceDirtyRect.translate(_screenCenterX - _backgroundOffset, 0); - if (_bkgOff < _screenCenterX) { - viewPort.moveTo(-(_screenCenterX - (_bkgOff + _bkgWidth)), 0); - drawRect = _bkgDirtyRect; + // Panorama mode allows the user to spin in circles. Therefore, we need to render + // the portion of the image that wrapped to the other side of the screen + if (_backgroundOffset < _screenCenterX) { + viewPort.moveTo(-(_screenCenterX - (_backgroundOffset + _backgroundWidth)), 0); + drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - (_bkgOff + _bkgWidth) + drawRect.left, drawRect.top); + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, _screenCenterX - (_backgroundOffset + _backgroundWidth) + drawRect.left, drawRect.top); - Common::Rect tmp = _bkgDirtyRect; - tmp.translate(_screenCenterX - (_bkgOff + _bkgWidth), 0); + Common::Rect tmp = _backgroundDirtyRect; + tmp.translate(_screenCenterX - (_backgroundOffset + _backgroundWidth), 0); if (!tmp.isEmpty()) - _wrkWndDirtyRect.extend(tmp); + _backgroundSurfaceDirtyRect.extend(tmp); - } else if (_bkgWidth - _bkgOff < _screenCenterX) { - viewPort.moveTo(-(_screenCenterX + _bkgWidth - _bkgOff), 0); - drawRect = _bkgDirtyRect; + } else if (_backgroundWidth - _backgroundOffset < _screenCenterX) { + viewPort.moveTo(-(_screenCenterX + _backgroundWidth - _backgroundOffset), 0); + drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX + _bkgWidth - _bkgOff + drawRect.left, drawRect.top); + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, _screenCenterX + _backgroundWidth - _backgroundOffset + drawRect.left, drawRect.top); - Common::Rect tmp = _bkgDirtyRect; - tmp.translate(_screenCenterX + _bkgWidth - _bkgOff, 0); + Common::Rect tmp = _backgroundDirtyRect; + tmp.translate(_screenCenterX + _backgroundWidth - _backgroundOffset, 0); if (!tmp.isEmpty()) - _wrkWndDirtyRect.extend(tmp); + _backgroundSurfaceDirtyRect.extend(tmp); } } else if (state == RenderTable::TILT) { - Common::Rect viewPort(_wrkWidth, _wrkHeight); - viewPort.translate(0, -(_screenCenterY - _bkgOff)); - Common::Rect drawRect = _bkgDirtyRect; + // Tilt doesn't allow wrapping, so we just do a simple clip + Common::Rect viewPort(_workingWindow.width(), _workingWindow.height()); + viewPort.translate(0, -(_screenCenterY - _backgroundOffset)); + Common::Rect drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, drawRect.left, _screenCenterY - _bkgOff + drawRect.top); + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, drawRect.left, _screenCenterY - _backgroundOffset + drawRect.top); - _wrkWndDirtyRect = _bkgDirtyRect; - _wrkWndDirtyRect.translate(0, _screenCenterY - _bkgOff); + // Mark the dirty portion of the surface + _backgroundSurfaceDirtyRect = _backgroundDirtyRect; + _backgroundSurfaceDirtyRect.translate(0, _screenCenterY - _backgroundOffset); } else { - if (!_bkgDirtyRect.isEmpty()) - blitSurfaceToSurface(_curBkg, _bkgDirtyRect, _wrkWnd, _bkgDirtyRect.left, _bkgDirtyRect.top); - _wrkWndDirtyRect = _bkgDirtyRect; + if (!_backgroundDirtyRect.isEmpty()) + blitSurfaceToSurface(_currentBackgroundImage, _backgroundDirtyRect, _backgroundSurface, _backgroundDirtyRect.left, _backgroundDirtyRect.top); + _backgroundSurfaceDirtyRect = _backgroundDirtyRect; } - _bkgDirtyRect = Common::Rect(); + // Clear the dirty rect since everything is clean now + _backgroundDirtyRect = Common::Rect(); - _wrkWndDirtyRect.clip(_wrkWidth, _wrkHeight); + _backgroundSurfaceDirtyRect.clip(_workingWindow.width(), _workingWindow.height()); } void RenderManager::clearMenuSurface() { - _menuWndDirtyRect = Common::Rect(0, 0, _menuWnd.w, _menuWnd.h); - _menuWnd.fillRect(_menuWndDirtyRect, 0); + _menuSurfaceDirtyRect = Common::Rect(0, 0, _menuSurface.w, _menuSurface.h); + _menuSurface.fillRect(_menuSurfaceDirtyRect, 0); } void RenderManager::clearMenuSurface(const Common::Rect &r) { - if (_menuWndDirtyRect.isEmpty()) - _menuWndDirtyRect = r; + if (_menuSurfaceDirtyRect.isEmpty()) + _menuSurfaceDirtyRect = r; else - _menuWndDirtyRect.extend(r); - _menuWnd.fillRect(r, 0); + _menuSurfaceDirtyRect.extend(r); + _menuSurface.fillRect(r, 0); } void RenderManager::renderMenuToScreen() { - if (!_menuWndDirtyRect.isEmpty()) { - _menuWndDirtyRect.clip(Common::Rect(_menuWnd.w, _menuWnd.h)); - if (!_menuWndDirtyRect.isEmpty()) - _system->copyRectToScreen(_menuWnd.getBasePtr(_menuWndDirtyRect.left, _menuWndDirtyRect.top), _menuWnd.pitch, - _menuWndDirtyRect.left + _menuWndRect.left, - _menuWndDirtyRect.top + _menuWndRect.top, - _menuWndDirtyRect.width(), - _menuWndDirtyRect.height()); - _menuWndDirtyRect = Common::Rect(); + if (!_menuSurfaceDirtyRect.isEmpty()) { + _menuSurfaceDirtyRect.clip(Common::Rect(_menuSurface.w, _menuSurface.h)); + if (!_menuSurfaceDirtyRect.isEmpty()) { + Common::Rect rect( + _menuSurfaceDirtyRect.left + _menuArea.left, + _menuSurfaceDirtyRect.top + _menuArea.top, + _menuSurfaceDirtyRect.left + _menuArea.left + _menuSurfaceDirtyRect.width(), + _menuSurfaceDirtyRect.top + _menuArea.top + _menuSurfaceDirtyRect.height() + ); + copyToScreen(_menuSurface, rect, _menuSurfaceDirtyRect.left, _menuSurfaceDirtyRect.top); + } + _menuSurfaceDirtyRect = Common::Rect(); } } +void RenderManager::initSubArea(uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow) { + _workingWindow = workingWindow; + + _subtitleSurface.free(); + + _subtitleSurface.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); + _subtitleArea = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); +} + uint16 RenderManager::createSubArea(const Common::Rect &area) { _subid++; - oneSub sub; + OneSubtitle sub; sub.redraw = false; sub.timer = -1; sub.todelete = false; @@ -799,18 +708,9 @@ uint16 RenderManager::createSubArea(const Common::Rect &area) { } uint16 RenderManager::createSubArea() { - _subid++; - - oneSub sub; - sub.redraw = false; - sub.timer = -1; - sub.todelete = false; - sub.r = Common::Rect(_subWndRect.left, _subWndRect.top, _subWndRect.right, _subWndRect.bottom); - sub.r.translate(-_workingWindow.left, -_workingWindow.top); - - _subsList[_subid] = sub; - - return _subid; + Common::Rect r(_subtitleArea.left, _subtitleArea.top, _subtitleArea.right, _subtitleArea.bottom); + r.translate(-_workingWindow.left, -_workingWindow.top); + return createSubArea(r); } void RenderManager::deleteSubArea(uint16 id) { @@ -825,7 +725,7 @@ void RenderManager::deleteSubArea(uint16 id, int16 delay) { void RenderManager::updateSubArea(uint16 id, const Common::String &txt) { if (_subsList.contains(id)) { - oneSub *sub = &_subsList[id]; + OneSubtitle *sub = &_subsList[id]; sub->txt = txt; sub->redraw = true; } @@ -833,7 +733,7 @@ void RenderManager::updateSubArea(uint16 id, const Common::String &txt) { void RenderManager::processSubs(uint16 deltatime) { bool redraw = false; - for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { if (it->_value.timer != -1) { it->_value.timer -= deltatime; if (it->_value.timer <= 0) @@ -848,39 +748,41 @@ void RenderManager::processSubs(uint16 deltatime) { } if (redraw) { - _subWnd.fillRect(Common::Rect(_subWnd.w, _subWnd.h), 0); + _subtitleSurface.fillRect(Common::Rect(_subtitleSurface.w, _subtitleSurface.h), 0); - for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { - oneSub *sub = &it->_value; + for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + OneSubtitle *sub = &it->_value; if (sub->txt.size()) { - Graphics::Surface *rndr = new Graphics::Surface(); - rndr->create(sub->r.width(), sub->r.height(), _pixelFormat); - _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr); - blitSurfaceToSurface(*rndr, _subWnd, sub->r.left - _subWndRect.left + _workingWindow.left, sub->r.top - _subWndRect.top + _workingWindow.top); - rndr->free(); - delete rndr; + Graphics::Surface subtitleSurface; + subtitleSurface.create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat); + _engine->getTextRenderer()->drawTextWithWordWrapping(sub->txt, subtitleSurface); + Common::Rect empty; + blitSurfaceToSurface(subtitleSurface, empty, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); + subtitleSurface.free(); } sub->redraw = false; } - _system->copyRectToScreen(_subWnd.getPixels(), _subWnd.pitch, - _subWndRect.left, - _subWndRect.top, - _subWnd.w, - _subWnd.h); + Common::Rect rect( + _subtitleArea.left, + _subtitleArea.top, + _subtitleArea.left + _subtitleSurface.w, + _subtitleArea.top + _subtitleSurface.h + ); + copyToScreen(_subtitleSurface, rect, 0, 0); } } Common::Point RenderManager::getBkgSize() { - return Common::Point(_bkgWidth, _bkgHeight); + return Common::Point(_backgroundWidth, _backgroundHeight); } -void RenderManager::addEffect(Effect *_effect) { +void RenderManager::addEffect(GraphicsEffect *_effect) { _effects.push_back(_effect); } void RenderManager::deleteEffect(uint32 ID) { - for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { + for (EffectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { if ((*it)->getKey() == ID) { delete *it; it = _effects.erase(it); @@ -888,54 +790,54 @@ void RenderManager::deleteEffect(uint32 ID) { } } -Common::Rect RenderManager::bkgRectToScreen(const Common::Rect &src) { +Common::Rect RenderManager::transformBackgroundSpaceRectToScreenSpace(const Common::Rect &src) { Common::Rect tmp = src; RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - if (_bkgOff < _screenCenterX) { - Common::Rect rScreen(_screenCenterX + _bkgOff, _wrkHeight); - Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight); - lScreen.translate(_bkgWidth - lScreen.width(), 0); + if (_backgroundOffset < _screenCenterX) { + Common::Rect rScreen(_screenCenterX + _backgroundOffset, _workingWindow.height()); + Common::Rect lScreen(_workingWindow.width() - rScreen.width(), _workingWindow.height()); + lScreen.translate(_backgroundWidth - lScreen.width(), 0); lScreen.clip(src); rScreen.clip(src); if (rScreen.width() < lScreen.width()) { - tmp.translate(_screenCenterX - _bkgOff - _bkgWidth, 0); + tmp.translate(_screenCenterX - _backgroundOffset - _backgroundWidth, 0); } else { - tmp.translate(_screenCenterX - _bkgOff, 0); + tmp.translate(_screenCenterX - _backgroundOffset, 0); } - } else if (_bkgWidth - _bkgOff < _screenCenterX) { - Common::Rect rScreen(_screenCenterX - (_bkgWidth - _bkgOff), _wrkHeight); - Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight); - lScreen.translate(_bkgWidth - lScreen.width(), 0); + } else if (_backgroundWidth - _backgroundOffset < _screenCenterX) { + Common::Rect rScreen(_screenCenterX - (_backgroundWidth - _backgroundOffset), _workingWindow.height()); + Common::Rect lScreen(_workingWindow.width() - rScreen.width(), _workingWindow.height()); + lScreen.translate(_backgroundWidth - lScreen.width(), 0); lScreen.clip(src); rScreen.clip(src); if (lScreen.width() < rScreen.width()) { - tmp.translate(_screenCenterX + (_bkgWidth - _bkgOff), 0); + tmp.translate(_screenCenterX + (_backgroundWidth - _backgroundOffset), 0); } else { - tmp.translate(_screenCenterX - _bkgOff, 0); + tmp.translate(_screenCenterX - _backgroundOffset, 0); } } else { - tmp.translate(_screenCenterX - _bkgOff, 0); + tmp.translate(_screenCenterX - _backgroundOffset, 0); } } else if (state == RenderTable::TILT) { - tmp.translate(0, (_screenCenterY - _bkgOff)); + tmp.translate(0, (_screenCenterY - _backgroundOffset)); } return tmp; } EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *_minComp, int8 *_maxComp) { - Common::Rect bkgRect(_bkgWidth, _bkgHeight); + Common::Rect bkgRect(_backgroundWidth, _backgroundHeight); if (!bkgRect.contains(xy)) return NULL; if (!bkgRect.intersects(rect)) return NULL; - uint16 color = *(uint16 *)_curBkg.getBasePtr(xy.x, xy.y); + uint16 color = *(uint16 *)_currentBackgroundImage.getBasePtr(xy.x, xy.y); uint8 stC1, stC2, stC3; - _curBkg.format.colorToRGB(color, stC1, stC2, stC3); + _currentBackgroundImage.format.colorToRGB(color, stC1, stC2, stC3); EffectMap *newMap = new EffectMap; EffectMapUnit unit; @@ -953,11 +855,11 @@ EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, co uint8 depth8 = depth << 3; for (int16 j = 0; j < h; j++) { - uint16 *pix = (uint16 *)_curBkg.getBasePtr(rect.left, rect.top + j); + uint16 *pix = (uint16 *)_currentBackgroundImage.getBasePtr(rect.left, rect.top + j); for (int16 i = 0; i < w; i++) { uint16 curClr = pix[i]; uint8 cC1, cC2, cC3; - _curBkg.format.colorToRGB(curClr, cC1, cC2, cC3); + _currentBackgroundImage.format.colorToRGB(curClr, cC1, cC2, cC3); bool use = false; @@ -1055,12 +957,261 @@ EffectMap *RenderManager::makeEffectMap(const Graphics::Surface &surf, uint16 tr } void RenderManager::markDirty() { - _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); + _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); } +#if 0 void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) { - _curBkg.fillRect(Common::Rect(_curBkg.w, _curBkg.h), _curBkg.format.RGBToColor(r, g, b)); + _currentBackgroundImage.fillRect(Common::Rect(_currentBackgroundImage.w, _currentBackgroundImage.h), _currentBackgroundImage.format.RGBToColor(r, g, b)); markDirty(); } +#endif + +void RenderManager::timedMessage(const Common::String &str, uint16 milsecs) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, str); + deleteSubArea(msgid, milsecs); +} + +bool RenderManager::askQuestion(const Common::String &str) { + Graphics::Surface textSurface; + textSurface.create(_subtitleArea.width(), _subtitleArea.height(), _engine->_resourcePixelFormat); + _engine->getTextRenderer()->drawTextWithWordWrapping(str, textSurface); + copyToScreen(textSurface, _subtitleArea, 0, 0); + + _engine->stopClock(); + + int result = 0; + + while (result == 0) { + Common::Event evnt; + while (_engine->getEventManager()->pollEvent(evnt)) { + if (evnt.type == Common::EVENT_KEYDOWN) { + // English: yes/no + // German: ja/nein + // Spanish: si/no + // French Nemesis: F4/any other key + // French ZGI: oui/non + switch (evnt.kbd.keycode) { + case Common::KEYCODE_y: + if (_engine->getLanguage() == Common::EN_ANY) + result = 2; + break; + case Common::KEYCODE_j: + if (_engine->getLanguage() == Common::DE_DEU) + result = 2; + break; + case Common::KEYCODE_s: + if (_engine->getLanguage() == Common::ES_ESP) + result = 2; + break; + case Common::KEYCODE_o: + if (_engine->getLanguage() == Common::FR_FRA && _engine->getGameId() == GID_GRANDINQUISITOR) + result = 2; + break; + case Common::KEYCODE_F4: + if (_engine->getLanguage() == Common::FR_FRA && _engine->getGameId() == GID_NEMESIS) + result = 2; + break; + case Common::KEYCODE_n: + result = 1; + break; + default: + if (_engine->getLanguage() == Common::FR_FRA && _engine->getGameId() == GID_NEMESIS) + result = 1; + break; + } + } + } + _system->updateScreen(); + if (_doubleFPS) + _system->delayMillis(33); + else + _system->delayMillis(66); + } + + // Draw over the text in order to clear it + textSurface.fillRect(Common::Rect(_subtitleArea.width(), _subtitleArea.height()), 0); + copyToScreen(textSurface, _subtitleArea, 0, 0); + + // Free the surface + textSurface.free(); + + _engine->startClock(); + return result == 2; +} + +void RenderManager::delayedMessage(const Common::String &str, uint16 milsecs) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, str); + processSubs(0); + renderSceneToScreen(); + _engine->stopClock(); + + uint32 stopTime = _system->getMillis() + milsecs; + while (_system->getMillis() < stopTime) { + Common::Event evnt; + while (_engine->getEventManager()->pollEvent(evnt)) { + if (evnt.type == Common::EVENT_KEYDOWN && + (evnt.kbd.keycode == Common::KEYCODE_SPACE || + evnt.kbd.keycode == Common::KEYCODE_RETURN || + evnt.kbd.keycode == Common::KEYCODE_ESCAPE)) + break; + } + _system->updateScreen(); + if (_doubleFPS) + _system->delayMillis(33); + else + _system->delayMillis(66); + } + deleteSubArea(msgid); + _engine->startClock(); +} + +void RenderManager::showDebugMsg(const Common::String &msg, int16 delay) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, msg); + deleteSubArea(msgid, delay); +} + +void RenderManager::updateRotation() { + int16 _velocity = _engine->getMouseVelocity() + _engine->getKeyboardVelocity(); + ScriptManager *scriptManager = _engine->getScriptManager(); + + if (_doubleFPS) + _velocity /= 2; + + if (_velocity) { + RenderTable::RenderState renderState = _renderTable.getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 startPosition = scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition + (_renderTable.getPanoramaReverse() ? -_velocity : _velocity); + + int16 zeroPoint = _renderTable.getPanoramaZeroPoint(); + if (startPosition >= zeroPoint && newPosition < zeroPoint) + scriptManager->setStateValue(StateKey_Rounds, scriptManager->getStateValue(StateKey_Rounds) - 1); + if (startPosition <= zeroPoint && newPosition > zeroPoint) + scriptManager->setStateValue(StateKey_Rounds, scriptManager->getStateValue(StateKey_Rounds) + 1); + + int16 screenWidth = getBkgSize().x; + if (screenWidth) + newPosition %= screenWidth; + + if (newPosition < 0) + newPosition += screenWidth; + + setBackgroundPosition(newPosition); + } else if (renderState == RenderTable::TILT) { + int16 startPosition = scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition + _velocity; + + int16 screenHeight = getBkgSize().y; + int16 tiltGap = (int16)_renderTable.getTiltGap(); + + if (newPosition >= (screenHeight - tiltGap)) + newPosition = screenHeight - tiltGap; + if (newPosition <= tiltGap) + newPosition = tiltGap; + + setBackgroundPosition(newPosition); + } + } +} + +void RenderManager::checkBorders() { + RenderTable::RenderState renderState = _renderTable.getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 startPosition = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition; + + int16 screenWidth = getBkgSize().x; + + if (screenWidth) + newPosition %= screenWidth; + + if (newPosition < 0) + newPosition += screenWidth; + + if (startPosition != newPosition) + setBackgroundPosition(newPosition); + } else if (renderState == RenderTable::TILT) { + int16 startPosition = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition; + + int16 screenHeight = getBkgSize().y; + int16 tiltGap = (int16)_renderTable.getTiltGap(); + + if (newPosition >= (screenHeight - tiltGap)) + newPosition = screenHeight - tiltGap; + if (newPosition <= tiltGap) + newPosition = tiltGap; + + if (startPosition != newPosition) + setBackgroundPosition(newPosition); + } +} + +void RenderManager::rotateTo(int16 _toPos, int16 _time) { + if (_renderTable.getRenderState() != RenderTable::PANORAMA) + return; + + if (_time == 0) + _time = 1; + + int32 maxX = getBkgSize().x; + int32 curX = getCurrentBackgroundOffset(); + int32 dx = 0; + + if (curX == _toPos) + return; + + if (curX > _toPos) { + if (curX - _toPos > maxX / 2) + dx = (_toPos + (maxX - curX)) / _time; + else + dx = -(curX - _toPos) / _time; + } else { + if (_toPos - curX > maxX / 2) + dx = -((maxX - _toPos) + curX) / _time; + else + dx = (_toPos - curX) / _time; + } + + _engine->stopClock(); + + for (int16 i = 0; i <= _time; i++) { + if (i == _time) + curX = _toPos; + else + curX += dx; + + if (curX < 0) + curX = maxX - curX; + else if (curX >= maxX) + curX %= maxX; + + setBackgroundPosition(curX); + + prepareBackground(); + renderSceneToScreen(); + + _system->updateScreen(); + + _system->delayMillis(500 / _time); + } + + _engine->startClock(); +} + +void RenderManager::upscaleRect(Common::Rect &rect) { + rect.top = rect.top * HIRES_WINDOW_HEIGHT / WINDOW_HEIGHT; + rect.left = rect.left * HIRES_WINDOW_WIDTH / WINDOW_WIDTH; + rect.bottom = rect.bottom * HIRES_WINDOW_HEIGHT / WINDOW_HEIGHT; + rect.right = rect.right * HIRES_WINDOW_WIDTH / WINDOW_WIDTH; +} } // End of namespace ZVision |