aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/cursor32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics/cursor32.cpp')
-rw-r--r--engines/sci/graphics/cursor32.cpp182
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);
}
}