diff options
author | Filippos Karapetis | 2010-10-03 22:41:35 +0000 |
---|---|---|
committer | Filippos Karapetis | 2010-10-03 22:41:35 +0000 |
commit | ce8a2fbbbc658ee31d8621687119b3e1c295560f (patch) | |
tree | 612b590ac15966a5088b8a4d1d38b80ba903fa48 | |
parent | dffabdfed08f75ed040c087abc090f75c3ad5eb9 (diff) | |
download | scummvm-rg350-ce8a2fbbbc658ee31d8621687119b3e1c295560f.tar.gz scummvm-rg350-ce8a2fbbbc658ee31d8621687119b3e1c295560f.tar.bz2 scummvm-rg350-ce8a2fbbbc658ee31d8621687119b3e1c295560f.zip |
SCI: Added support for SCI1.1+ magnifier cursors (bug #3034973).
These are special cursors which zoom parts of a view dynamically. Examples
are Freddy Pharkas, when reading the prescription with the whiskey and LB2,
when using the magnifying glass on the Rosetta Stone
svn-id: r53003
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 16 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.cpp | 102 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.h | 13 |
3 files changed, 119 insertions, 12 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index c68dbb9b90..07385fd3f9 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -129,8 +129,7 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelHide(); break; case -1: - // TODO: Special case at least in kq6, check disassembly - // Does something with magCursor, which is set on argc = 10, which we don't support + g_sci->_gfxCursor->kernelClearZoomZone(); break; case -2: g_sci->_gfxCursor->kernelResetMoveZone(); @@ -184,15 +183,10 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { break; case 10: // Freddy pharkas, when using the whiskey glass to read the prescription (bug #3034973) - // magnifier support, disabled using argc == 1, argv == -1 - warning("kSetCursor: unsupported magnifier"); - // we just set the view cursor currently - g_sci->_gfxCursor->kernelSetView(argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(), hotspot); - // argv[0] -> 1, 2, 4 -> maybe magnification multiplier - // argv[1-4] -> rect for magnification - // argv[5, 6, 7] -> view resource for cursor - // argv[8] -> picture resource for mag - // argv[9] -> color for magnifier replacement + g_sci->_gfxCursor->kernelSetZoomZone(argv[0].toUint16(), + Common::Rect(argv[1].toUint16(), argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16()), + argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(), + argv[8].toUint16(), argv[9].toUint16()); break; default : error("kSetCursor: Unhandled case: %d arguments given", argc); diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 8e69d034c8..dde6f1df00 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -49,6 +49,15 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc // center mouse cursor setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2)); _moveZoneActive = false; + + _zoomZoneActive = false; + _zoomZone = Common::Rect(); + _zoomColor = 0; + _zoomCursorView = 0; + _zoomCursorLoop = 0; + _zoomCursorCel = 0; + _zoomPicView = 0; + _zoomMultiplier = 0; } GfxCursor::~GfxCursor() { @@ -329,9 +338,10 @@ Common::Point GfxCursor::getPosition() { } void GfxCursor::refreshPosition() { + Common::Point mousePoint = getPosition(); + if (_moveZoneActive) { bool clipped = false; - Common::Point mousePoint = getPosition(); if (mousePoint.x < _moveZone.left) { mousePoint.x = _moveZone.left; @@ -353,6 +363,47 @@ void GfxCursor::refreshPosition() { if (clipped) setPosition(mousePoint); } + + if (_zoomZoneActive) { + // Cursor + const CelInfo *cursorCelInfo = _zoomCursorView->getCelInfo(_zoomCursorLoop, _zoomCursorCel); + const byte *cursorBitmap = _zoomCursorView->getBitmap(_zoomCursorLoop, _zoomCursorCel); + int16 cursorWidth = cursorCelInfo->width * (_upscaledHires ? 2 : 1); + int16 cursorHeight = cursorCelInfo->height * (_upscaledHires ? 2 : 1); + byte *finalBitmap = new byte[cursorWidth * cursorHeight]; + // Pic + const CelInfo *picCelInfo = _zoomPicView->getCelInfo(0, 0); + int16 picWidth = picCelInfo->width * _zoomMultiplier; + //int16 picHeight = picCelInfo->height * _zoomMultiplier; + // Compute hotspot from xoffset/yoffset + Common::Point cursorHotspot = Common::Point((cursorCelInfo->width >> 1) - cursorCelInfo->displaceX, cursorCelInfo->height - cursorCelInfo->displaceY - 1); + + if (!_upscaledHires) { + memcpy(finalBitmap, cursorBitmap, cursorCelInfo->width * cursorCelInfo->height); + } else { + // Scale cursor by 2x - note: sierra didn't do this, but it looks much better + cursorHotspot.x *= 2; + cursorHotspot.y *= 2; + _screen->scale2x(cursorBitmap, finalBitmap, cursorCelInfo->width, cursorCelInfo->height); + } + + uint16 targetX = mousePoint.x * _zoomMultiplier - _zoomZone.left; + uint16 targetY = mousePoint.y * _zoomMultiplier - _zoomZone.top; + + // Replace the special magnifier color with the associated magnified pixels + for (int x = 0; x < cursorCelInfo->width; x++) { + for (int y = 0; y < cursorCelInfo->height; y++) { + int curPos = cursorCelInfo->width * y + x; + if (finalBitmap[curPos] == _zoomColor) { + finalBitmap[curPos] = _zoomBitmap[picWidth * (targetY + y) + (targetX + x)]; + } + } + } + + CursorMan.replaceCursor((const byte *)finalBitmap, cursorCelInfo->width, cursorCelInfo->height, cursorHotspot.x, cursorHotspot.y, cursorCelInfo->clearKey); + + delete[] finalBitmap; + } } void GfxCursor::kernelResetMoveZone() { @@ -364,6 +415,55 @@ void GfxCursor::kernelSetMoveZone(Common::Rect zone) { _moveZoneActive = true; } +void GfxCursor::kernelClearZoomZone() { + delete[] _zoomBitmap; + kernelResetMoveZone(); + _zoomZone = Common::Rect(); + _zoomColor = 0; + _zoomMultiplier = 0; + _zoomZoneActive = false; +} + +void GfxCursor::kernelSetZoomZone(byte multiplier, Common::Rect zone, GuiResourceId viewNum, int loopNum, int celNum, GuiResourceId picNum, byte zoomColor) { + if (multiplier != 1 && multiplier != 2) { + warning("kernelSetZoomZone: Unsupported magnifier %d", multiplier); + return; + } + + _zoomMultiplier = multiplier; + + if (_cachedCursors.size() >= MAX_CACHED_CURSORS) + purgeCache(); + + if (!_cachedCursors.contains(viewNum)) + _cachedCursors[viewNum] = new GfxView(_resMan, _screen, _palette, viewNum); + if (!_cachedCursors.contains(picNum)) + _cachedCursors[picNum] = new GfxView(_resMan, _screen, _palette, picNum); + + _zoomCursorView = _cachedCursors[viewNum]; + _zoomCursorLoop = (byte)loopNum; + _zoomCursorCel = (byte)celNum; + _zoomPicView = _cachedCursors[picNum]; + + kernelSetView(viewNum, loopNum, celNum, NULL); + + GfxView *zoomPicView = _cachedCursors[picNum]; + const byte *rawPicBitmap = zoomPicView->getBitmap(0, 0); + const CelInfo *celInfo = zoomPicView->getCelInfo(0, 0); + _zoomBitmap = new byte[(celInfo->width * _zoomMultiplier) * (celInfo->height * _zoomMultiplier)]; + + if (_zoomMultiplier == 1) + memcpy(_zoomBitmap, rawPicBitmap, celInfo->width * celInfo->height); + else if (_zoomMultiplier == 2) + _screen->scale2x(rawPicBitmap, _zoomBitmap, celInfo->width, celInfo->height); + + _zoomZone = zone; + kernelSetMoveZone(_zoomZone); + + _zoomColor = zoomColor; + _zoomZoneActive = true; +} + void GfxCursor::kernelSetPos(Common::Point pos) { _coordAdjuster->setCursorPos(pos); kernelMoveCursor(pos); diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index 10cd5d8a85..f9d886f321 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -79,6 +79,9 @@ public: */ void kernelSetMoveZone(Common::Rect zone); + void kernelClearZoomZone(); + void kernelSetZoomZone(byte multiplier, Common::Rect zone, GuiResourceId viewNum, int loopNum, int celNum, GuiResourceId picNum, byte zoomColor); + void kernelSetPos(Common::Point pos); void kernelMoveCursor(Common::Point pos); @@ -96,6 +99,16 @@ private: bool _moveZoneActive; Common::Rect _moveZone; // Rectangle in which the pointer can move + bool _zoomZoneActive; + Common::Rect _zoomZone; + GfxView *_zoomCursorView; + byte _zoomCursorLoop; + byte _zoomCursorCel; + GfxView *_zoomPicView; + byte *_zoomBitmap; + byte _zoomColor; + byte _zoomMultiplier; + CursorCache _cachedCursors; bool _isVisible; |