mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-01 15:09:47 +00:00
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
This commit is contained in:
parent
dffabdfed0
commit
ce8a2fbbbc
@ -129,8 +129,7 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
|
|||||||
g_sci->_gfxCursor->kernelHide();
|
g_sci->_gfxCursor->kernelHide();
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
// TODO: Special case at least in kq6, check disassembly
|
g_sci->_gfxCursor->kernelClearZoomZone();
|
||||||
// Does something with magCursor, which is set on argc = 10, which we don't support
|
|
||||||
break;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
g_sci->_gfxCursor->kernelResetMoveZone();
|
g_sci->_gfxCursor->kernelResetMoveZone();
|
||||||
@ -184,15 +183,10 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
|
|||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
// Freddy pharkas, when using the whiskey glass to read the prescription (bug #3034973)
|
// Freddy pharkas, when using the whiskey glass to read the prescription (bug #3034973)
|
||||||
// magnifier support, disabled using argc == 1, argv == -1
|
g_sci->_gfxCursor->kernelSetZoomZone(argv[0].toUint16(),
|
||||||
warning("kSetCursor: unsupported magnifier");
|
Common::Rect(argv[1].toUint16(), argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16()),
|
||||||
// we just set the view cursor currently
|
argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(),
|
||||||
g_sci->_gfxCursor->kernelSetView(argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(), hotspot);
|
argv[8].toUint16(), argv[9].toUint16());
|
||||||
// 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
|
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
error("kSetCursor: Unhandled case: %d arguments given", argc);
|
error("kSetCursor: Unhandled case: %d arguments given", argc);
|
||||||
|
@ -49,6 +49,15 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc
|
|||||||
// center mouse cursor
|
// center mouse cursor
|
||||||
setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2));
|
setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2));
|
||||||
_moveZoneActive = false;
|
_moveZoneActive = false;
|
||||||
|
|
||||||
|
_zoomZoneActive = false;
|
||||||
|
_zoomZone = Common::Rect();
|
||||||
|
_zoomColor = 0;
|
||||||
|
_zoomCursorView = 0;
|
||||||
|
_zoomCursorLoop = 0;
|
||||||
|
_zoomCursorCel = 0;
|
||||||
|
_zoomPicView = 0;
|
||||||
|
_zoomMultiplier = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GfxCursor::~GfxCursor() {
|
GfxCursor::~GfxCursor() {
|
||||||
@ -329,9 +338,10 @@ Common::Point GfxCursor::getPosition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GfxCursor::refreshPosition() {
|
void GfxCursor::refreshPosition() {
|
||||||
|
Common::Point mousePoint = getPosition();
|
||||||
|
|
||||||
if (_moveZoneActive) {
|
if (_moveZoneActive) {
|
||||||
bool clipped = false;
|
bool clipped = false;
|
||||||
Common::Point mousePoint = getPosition();
|
|
||||||
|
|
||||||
if (mousePoint.x < _moveZone.left) {
|
if (mousePoint.x < _moveZone.left) {
|
||||||
mousePoint.x = _moveZone.left;
|
mousePoint.x = _moveZone.left;
|
||||||
@ -353,6 +363,47 @@ void GfxCursor::refreshPosition() {
|
|||||||
if (clipped)
|
if (clipped)
|
||||||
setPosition(mousePoint);
|
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() {
|
void GfxCursor::kernelResetMoveZone() {
|
||||||
@ -364,6 +415,55 @@ void GfxCursor::kernelSetMoveZone(Common::Rect zone) {
|
|||||||
_moveZoneActive = true;
|
_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) {
|
void GfxCursor::kernelSetPos(Common::Point pos) {
|
||||||
_coordAdjuster->setCursorPos(pos);
|
_coordAdjuster->setCursorPos(pos);
|
||||||
kernelMoveCursor(pos);
|
kernelMoveCursor(pos);
|
||||||
|
@ -79,6 +79,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void kernelSetMoveZone(Common::Rect zone);
|
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 kernelSetPos(Common::Point pos);
|
||||||
void kernelMoveCursor(Common::Point pos);
|
void kernelMoveCursor(Common::Point pos);
|
||||||
|
|
||||||
@ -96,6 +99,16 @@ private:
|
|||||||
bool _moveZoneActive;
|
bool _moveZoneActive;
|
||||||
Common::Rect _moveZone; // Rectangle in which the pointer can move
|
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;
|
CursorCache _cachedCursors;
|
||||||
|
|
||||||
bool _isVisible;
|
bool _isVisible;
|
||||||
|
Loading…
Reference in New Issue
Block a user