diff options
Diffstat (limited to 'engines/sci/graphics/cursor32.cpp')
-rw-r--r-- | engines/sci/graphics/cursor32.cpp | 182 |
1 files changed, 81 insertions, 101 deletions
diff --git a/engines/sci/graphics/cursor32.cpp b/engines/sci/graphics/cursor32.cpp index 74fbafa2f0..ae8c01495c 100644 --- a/engines/sci/graphics/cursor32.cpp +++ b/engines/sci/graphics/cursor32.cpp @@ -34,22 +34,22 @@ namespace Sci { GfxCursor32::GfxCursor32() : _hideCount(0), _position(0, 0), - _writeToVMAP(false) { + _needsPaint(false) { } -void GfxCursor32::init(const Buffer &vmap) { - _vmap = vmap; - _vmapRegion.rect = Common::Rect(_vmap.screenWidth, _vmap.screenHeight); - _vmapRegion.data = (byte *)_vmap.getPixels(); - _restrictedArea = _vmapRegion.rect; +void GfxCursor32::init(const Buffer &outputBuffer) { + _screen = outputBuffer; + _screenRegion.rect = Common::Rect(_screen.screenWidth, _screen.screenHeight); + _screenRegion.data = static_cast<byte *>(_screen.getPixels()); + _restrictedArea = _screenRegion.rect; } GfxCursor32::~GfxCursor32() { free(_cursor.data); free(_cursorBack.data); - free(_drawBuff1.data); - free(_drawBuff2.data); - free(_savedVmapRegion.data); + free(_scratch1.data); + free(_scratch2.data); + free(_savedScreenRegion.data); } void GfxCursor32::hide() { @@ -58,25 +58,26 @@ void GfxCursor32::hide() { } if (!_cursorBack.rect.isEmpty()) { - drawToHardware(_cursorBack); + drawToScreen(_cursorBack); } } void GfxCursor32::revealCursor() { _cursorBack.rect = _cursor.rect; - _cursorBack.rect.clip(_vmapRegion.rect); + _cursorBack.rect.clip(_screenRegion.rect); if (_cursorBack.rect.isEmpty()) { return; } - readVideo(_cursorBack); - _drawBuff1.rect = _cursor.rect; - copy(_drawBuff1, _cursorBack); - paint(_drawBuff1, _cursor); - drawToHardware(_drawBuff1); + copyFromScreen(_cursorBack); + _scratch1.rect = _cursor.rect; + copy<false>(_scratch1, _cursorBack); + copy<true>(_scratch1, _cursor); + drawToScreen(_scratch1); } -void GfxCursor32::paint(DrawRegion &target, const DrawRegion &source) { +template <bool SKIP> +void GfxCursor32::copy(DrawRegion &target, const DrawRegion &source) { if (source.rect.isEmpty()) { return; } @@ -96,25 +97,33 @@ void GfxCursor32::paint(DrawRegion &target, const DrawRegion &source) { const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset; const uint8 skipColor = source.skipColor; - const int16 sourceStride = source.rect.width() - drawRectWidth; - const int16 targetStride = target.rect.width() - drawRectWidth; + int16 sourceStride = source.rect.width(); + int16 targetStride = target.rect.width(); + if (SKIP) { + sourceStride -= drawRectWidth; + targetStride -= drawRectWidth; + } for (int16 y = 0; y < drawRectHeight; ++y) { - for (int16 x = 0; x < drawRectWidth; ++x) { - if (*sourcePixel != skipColor) { - *targetPixel = *sourcePixel; + if (SKIP) { + for (int16 x = 0; x < drawRectWidth; ++x) { + if (*sourcePixel != skipColor) { + *targetPixel = *sourcePixel; + } + ++targetPixel; + ++sourcePixel; } - ++targetPixel; - ++sourcePixel; + } else { + memcpy(targetPixel, sourcePixel, drawRectWidth); } - sourcePixel += sourceStride; targetPixel += targetStride; + sourcePixel += sourceStride; } } -void GfxCursor32::drawToHardware(const DrawRegion &source) { +void GfxCursor32::drawToScreen(const DrawRegion &source) { Common::Rect drawRect(source.rect); - drawRect.clip(_vmapRegion.rect); + drawRect.clip(_screenRegion.rect); const int16 sourceXOffset = drawRect.left - source.rect.left; const int16 sourceYOffset = drawRect.top - source.rect.top; byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset; @@ -174,7 +183,7 @@ void GfxCursor32::setRestrictedArea(const Common::Rect &rect) { } void GfxCursor32::clearRestrictedArea() { - _restrictedArea = _vmapRegion.rect; + _restrictedArea = _screenRegion.rect; } void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) { @@ -279,58 +288,29 @@ void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const _cursor.rect = Common::Rect(_width, _height); *_cursor.data = _cursor.skipColor; _cursorBack.rect = _cursor.rect; - _cursorBack.rect.clip(_vmapRegion.rect); + _cursorBack.rect.clip(_screenRegion.rect); if (!_cursorBack.rect.isEmpty()) { - readVideo(_cursorBack); + copyFromScreen(_cursorBack); } } _cursorBack.data = (byte *)realloc(_cursorBack.data, _width * _height); memset(_cursorBack.data, 0, _width * _height); - _drawBuff1.data = (byte *)realloc(_drawBuff1.data, _width * _height); - _drawBuff2.data = (byte *)realloc(_drawBuff2.data, _width * _height * 4); - _savedVmapRegion.data = (byte *)realloc(_savedVmapRegion.data, _width * _height); + _scratch1.data = (byte *)realloc(_scratch1.data, _width * _height); + _scratch2.data = (byte *)realloc(_scratch2.data, _width * _height * 4); + _savedScreenRegion.data = (byte *)realloc(_savedScreenRegion.data, _width * _height); unhide(); } -void GfxCursor32::readVideo(DrawRegion &target) { - // NOTE: In SSCI, mouse events were received via hardware interrupt, so - // there was a separate branch here that would read from VRAM instead of - // from the game's back buffer when a mouse event was received while the - // back buffer was being updated. In ScummVM, mouse events are polled, which - // means it is not possible to receive a mouse event during a back buffer - // update, so the code responsible for handling that is removed. - copy(target, _vmapRegion); -} - -void GfxCursor32::copy(DrawRegion &target, const DrawRegion &source) { - if (source.rect.isEmpty()) { - return; - } - - Common::Rect drawRect(source.rect); - drawRect.clip(target.rect); - if (drawRect.isEmpty()) { - return; - } - - const int16 sourceXOffset = drawRect.left - source.rect.left; - const int16 sourceYOffset = drawRect.top - source.rect.top; - const int16 drawWidth = drawRect.width(); - const int16 drawHeight = drawRect.height(); - - byte *targetPixel = target.data + ((drawRect.top - target.rect.top) * target.rect.width()) + (drawRect.left - target.rect.left); - const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset; - - const int16 sourceStride = source.rect.width(); - const int16 targetStride = target.rect.width(); - - for (int y = 0; y < drawHeight; ++y) { - memcpy(targetPixel, sourcePixel, drawWidth); - targetPixel += targetStride; - sourcePixel += sourceStride; - } +void GfxCursor32::copyFromScreen(DrawRegion &target) { + // In SSCI, mouse events were received via hardware interrupt, so there was + // a separate branch here that would read from VRAM instead of from the + // game's back buffer when a mouse event was received while the back buffer + // was being updated. In ScummVM, mouse events are polled, which means it is + // not possible to receive a mouse event during a back buffer update, so the + // code responsible for handling that is removed. + copy<false>(target, _screenRegion); } void GfxCursor32::setPosition(const Common::Point &position) { @@ -349,32 +329,32 @@ void GfxCursor32::setPosition(const Common::Point &position) { } void GfxCursor32::gonnaPaint(Common::Rect paintRect) { - if (!_hideCount && !_writeToVMAP && !_cursorBack.rect.isEmpty()) { + if (!_hideCount && !_needsPaint && !_cursorBack.rect.isEmpty()) { paintRect.left &= ~3; paintRect.right |= 3; if (_cursorBack.rect.intersects(paintRect)) { - _writeToVMAP = true; + _needsPaint = true; } } } void GfxCursor32::paintStarting() { - if (_writeToVMAP) { - _savedVmapRegion.rect = _cursor.rect; - copy(_savedVmapRegion, _vmapRegion); - paint(_vmapRegion, _cursor); + if (_needsPaint) { + _savedScreenRegion.rect = _cursor.rect; + copy<false>(_savedScreenRegion, _screenRegion); + copy<true>(_screenRegion, _cursor); } } void GfxCursor32::donePainting() { - if (_writeToVMAP) { - copy(_vmapRegion, _savedVmapRegion); - _savedVmapRegion.rect = Common::Rect(); - _writeToVMAP = false; + if (_needsPaint) { + copy<false>(_screenRegion, _savedScreenRegion); + _savedScreenRegion.rect = Common::Rect(); + _needsPaint = false; } if (!_hideCount && !_cursorBack.rect.isEmpty()) { - copy(_cursorBack, _vmapRegion); + copy<false>(_cursorBack, _screenRegion); } } @@ -423,45 +403,45 @@ void GfxCursor32::move() { } // Cursor moved offscreen - if (!_cursor.rect.intersects(_vmapRegion.rect)) { - drawToHardware(_cursorBack); + if (!_cursor.rect.intersects(_screenRegion.rect)) { + drawToScreen(_cursorBack); return; } if (!_cursor.rect.intersects(_cursorBack.rect)) { // Cursor moved to a completely different part of the screen - _drawBuff1.rect = _cursor.rect; - _drawBuff1.rect.clip(_vmapRegion.rect); - readVideo(_drawBuff1); + _scratch1.rect = _cursor.rect; + _scratch1.rect.clip(_screenRegion.rect); + copyFromScreen(_scratch1); - _drawBuff2.rect = _drawBuff1.rect; - copy(_drawBuff2, _drawBuff1); + _scratch2.rect = _scratch1.rect; + copy<false>(_scratch2, _scratch1); - paint(_drawBuff1, _cursor); - drawToHardware(_drawBuff1); + copy<true>(_scratch1, _cursor); + drawToScreen(_scratch1); - drawToHardware(_cursorBack); + drawToScreen(_cursorBack); _cursorBack.rect = _cursor.rect; - _cursorBack.rect.clip(_vmapRegion.rect); - copy(_cursorBack, _drawBuff2); + _cursorBack.rect.clip(_screenRegion.rect); + copy<false>(_cursorBack, _scratch2); } else { // Cursor moved, but still overlaps the previous cursor location Common::Rect mergedRect(_cursorBack.rect); mergedRect.extend(_cursor.rect); - mergedRect.clip(_vmapRegion.rect); + mergedRect.clip(_screenRegion.rect); - _drawBuff2.rect = mergedRect; - readVideo(_drawBuff2); + _scratch2.rect = mergedRect; + copyFromScreen(_scratch2); - copy(_drawBuff2, _cursorBack); + copy<false>(_scratch2, _cursorBack); _cursorBack.rect = _cursor.rect; - _cursorBack.rect.clip(_vmapRegion.rect); - copy(_cursorBack, _drawBuff2); + _cursorBack.rect.clip(_screenRegion.rect); + copy<false>(_cursorBack, _scratch2); - paint(_drawBuff2, _cursor); - drawToHardware(_drawBuff2); + copy<true>(_scratch2, _cursor); + drawToScreen(_scratch2); } } |