From b20187a0e92a284deb62298a63017de6e63a3661 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 22 Aug 2004 23:38:00 +0000 Subject: Cursor code cleanup svn-id: r14690 --- scumm/cursor.cpp | 161 ++++++++++++++++++++++++++++-------------------- scumm/intern.h | 6 ++ scumm/object.cpp | 48 --------------- scumm/resource_v7he.cpp | 2 +- scumm/script_v5.cpp | 15 +++-- scumm/script_v6.cpp | 6 +- scumm/script_v7he.cpp | 2 +- scumm/script_v8.cpp | 4 +- scumm/scumm.cpp | 11 +++- scumm/scumm.h | 14 ++--- 10 files changed, 130 insertions(+), 139 deletions(-) (limited to 'scumm') diff --git a/scumm/cursor.cpp b/scumm/cursor.cpp index 5cf17bc66f..2b53c48da7 100644 --- a/scumm/cursor.cpp +++ b/scumm/cursor.cpp @@ -21,6 +21,8 @@ #include "stdafx.h" #include "scumm/bomp.h" +#include "scumm/intern.h" +#include "scumm/object.h" #include "scumm/scumm.h" @@ -66,16 +68,48 @@ static const byte default_cursor_hotspots[10] = { 8, 7, //zak256 }; - void ScummEngine::setupCursor() { _cursor.animate = 1; - if (_gameId == GID_TENTACLE && res.roomno[rtRoom][60]) { - // HACK: For DOTT we manually set the default cursor. See also bug #786994 - setCursorImg(697, 60, 1); - makeCursorColorTransparent(1); +} + +void ScummEngine::animateCursor() { + if (_cursor.animate) { + if (!(_cursor.animateIndex & 0x1)) { + setBuiltinCursor((_cursor.animateIndex >> 1) & 3); + } + _cursor.animateIndex++; } } +void ScummEngine::setCursor(int cursor) { + if (cursor >= 0 && cursor <= 3) + _currentCursor = cursor; + else + warning("setCursor(%d)", cursor); +} + +void ScummEngine::setCursorHotspot(int x, int y) { + _cursor.hotspotX = x; + _cursor.hotspotY = y; +} + +void ScummEngine::setCursorTransparency(int a) { + int i, size; + + size = _cursor.width * _cursor.height; + + for (i = 0; i < size; i++) + if (_grabbedCursor[i] == (byte)a) + _grabbedCursor[i] = 0xFF; + + updateCursor(); +} + +void ScummEngine::updateCursor() { + _system->setMouseCursor(_grabbedCursor, _cursor.width, _cursor.height, + _cursor.hotspotX, _cursor.hotspotY); +} + void ScummEngine::grabCursor(int x, int y, int w, int h) { VirtScreen *vs = findVirtScreen(y); @@ -84,11 +118,10 @@ void ScummEngine::grabCursor(int x, int y, int w, int h) { return; } - grabCursor((byte *)vs->pixels + (y - vs->topline) * vs->pitch + x, w, h); - + setCursorFromBuffer((byte *)vs->pixels + (y - vs->topline) * vs->pitch + x, w, h, vs->pitch); } -void ScummEngine::grabCursor(byte *ptr, int width, int height) { +void ScummEngine::setCursorFromBuffer(byte *ptr, int width, int height, int pitch) { uint size; byte *dst; @@ -110,7 +143,54 @@ void ScummEngine::grabCursor(byte *ptr, int width, int height) { updateCursor(); } -void ScummEngine::useIm01Cursor(const byte *im, int w, int h) { +void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) { + int w, h; + const byte *dataptr, *bomp; + uint32 size; + FindObjectInRoom foir; + + if (room == (uint) - 1) + room = getObjectRoom(img); + + findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room); + + if (_version == 8) { + setCursorHotspot(READ_LE_UINT32(&foir.imhd->v8.hotspot[0].x), + READ_LE_UINT32(&foir.imhd->v8.hotspot[0].y)); + w = READ_LE_UINT32(&foir.imhd->v8.width) / 8; + h = READ_LE_UINT32(&foir.imhd->v8.height) / 8; + } else if (_version == 7) { + setCursorHotspot(READ_LE_UINT16(&foir.imhd->v7.hotspot[0].x), + READ_LE_UINT16(&foir.imhd->v7.hotspot[0].y)); + w = READ_LE_UINT16(&foir.imhd->v7.width) / 8; + h = READ_LE_UINT16(&foir.imhd->v7.height) / 8; + } else { + if (!(_features & GF_HUMONGOUS)) + setCursorHotspot(READ_LE_UINT16(&foir.imhd->old.hotspot[0].x), + READ_LE_UINT16(&foir.imhd->old.hotspot[0].y)); + w = READ_LE_UINT16(&foir.cdhd->v6.w) / 8; + h = READ_LE_UINT16(&foir.cdhd->v6.h) / 8; + } + + dataptr = getObjectImage(foir.obim, imgindex); + assert(dataptr); + if (_version == 8) { + bomp = dataptr; + } else { + size = READ_BE_UINT32(dataptr + 4); + if (size > sizeof(_grabbedCursor)) + error("setCursorFromImg: Cursor image too large"); + + bomp = findResource(MKID('BOMP'), dataptr); + } + + if (bomp != NULL) + useBompCursor(bomp, w, h); + else + useIm01Cursor(dataptr, w, h); +} + +void ScummEngine_v6::useIm01Cursor(const byte *im, int w, int h) { VirtScreen *vs = &virtscr[0]; byte *buf, *dst; const byte *src; @@ -139,7 +219,7 @@ void ScummEngine::useIm01Cursor(const byte *im, int w, int h) { gdi.enableZBuffer(); // Grab the data we just drew and setup the cursor with it - grabCursor(vs->getPixels(0, 0), w, h); + setCursorFromBuffer(vs->getPixels(0, 0), w, h, vs->pitch); // Restore the screen content src = buf; @@ -154,33 +234,7 @@ void ScummEngine::useIm01Cursor(const byte *im, int w, int h) { free(buf); } -void ScummEngine::setCursor(int cursor) { - if (cursor >= 0 && cursor <= 3) - _currentCursor = cursor; - else - warning("setCursor(%d)", cursor); -} - -void ScummEngine::setCursorHotspot(int x, int y) { - _cursor.hotspotX = x; - _cursor.hotspotY = y; -} - -void ScummEngine::updateCursor() { - _system->setMouseCursor(_grabbedCursor, _cursor.width, _cursor.height, - _cursor.hotspotX, _cursor.hotspotY); -} - -void ScummEngine::animateCursor() { - if (_cursor.animate) { - if (!(_cursor.animateIndex & 0x1)) { - decompressDefaultCursor((_cursor.animateIndex >> 1) & 3); - } - _cursor.animateIndex++; - } -} - -void ScummEngine::useBompCursor(const byte *im, int width, int height) { +void ScummEngine_v6::useBompCursor(const byte *im, int width, int height) { uint size; width *= 8; @@ -205,7 +259,7 @@ void ScummEngine::useBompCursor(const byte *im, int width, int height) { updateCursor(); } -void ScummEngine::decompressDefaultCursor(int idx) { +void ScummEngine::setBuiltinCursor(int idx) { int i, j; byte color; @@ -217,6 +271,9 @@ void ScummEngine::decompressDefaultCursor(int idx) { color = default_cursor_colors[idx]; // FIXME: None of the stock cursors are right for Loom. Why is that? + // Fingolfing says: because it sets different cursor shapes -- + // check the SO_CURSOR_IMAGE opcode in script_v5.cpp; if we implement + // that, this problem should be gone... if (_gameId == GID_LOOM || _gameId == GID_LOOM256) { int w = 0; @@ -300,32 +357,4 @@ void ScummEngine::decompressDefaultCursor(int idx) { updateCursor(); } -void ScummEngine::makeCursorColorTransparent(int a) { - int i, size; - - size = _cursor.width * _cursor.height; - - for (i = 0; i < size; i++) - if (_grabbedCursor[i] == (byte)a) - _grabbedCursor[i] = 0xFF; - - updateCursor(); -} - -void ScummEngine::grabCursorFromBuffer(byte *ptr, int width, int height) { - uint size; - - size = width * height; - if (size > sizeof(_grabbedCursor)) - error("grabCursor: grabbed cursor too big"); - - _cursor.width = width; - _cursor.height = height; - _cursor.animate = 0; - - memcpy(_grabbedCursor, ptr, width * height); - - updateCursor(); -} - } // End of namespace Scumm diff --git a/scumm/intern.h b/scumm/intern.h index 2dbaafda18..97234f3da2 100644 --- a/scumm/intern.h +++ b/scumm/intern.h @@ -331,6 +331,8 @@ protected: public: ScummEngine_v6(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs); + virtual void scummInit(); + protected: virtual void setupOpcodes(); virtual void executeOpcode(byte i); @@ -354,6 +356,10 @@ protected: void shuffleArray(int num, int minIdx, int maxIdx); + void setCursorFromImg(uint img, uint room, uint imgindex); + void useIm01Cursor(const byte *im, int w, int h); + void useBompCursor(const byte *im, int w, int h); + /* Version 6 script opcodes */ void o6_setBlastObjectWindow(); void o6_pushByte(); diff --git a/scumm/object.cpp b/scumm/object.cpp index 8b0d6e65a5..18864ff899 100644 --- a/scumm/object.cpp +++ b/scumm/object.cpp @@ -1366,54 +1366,6 @@ int ScummEngine::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, return getDist(x, y, x2, y2) * 0xFF / ((i + j) / 2); } -void ScummEngine::setCursorImg(uint img, uint room, uint imgindex) { - int w, h; - const byte *dataptr, *bomp; - uint32 size; - FindObjectInRoom foir; - - if (room == (uint) - 1) - room = getObjectRoom(img); - - findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room); - - if (_version == 8) { - setCursorHotspot(READ_LE_UINT32(&foir.imhd->v8.hotspot[0].x), - READ_LE_UINT32(&foir.imhd->v8.hotspot[0].y)); - w = READ_LE_UINT32(&foir.imhd->v8.width) / 8; - h = READ_LE_UINT32(&foir.imhd->v8.height) / 8; - } else if (_version == 7) { - setCursorHotspot(READ_LE_UINT16(&foir.imhd->v7.hotspot[0].x), - READ_LE_UINT16(&foir.imhd->v7.hotspot[0].y)); - w = READ_LE_UINT16(&foir.imhd->v7.width) / 8; - h = READ_LE_UINT16(&foir.imhd->v7.height) / 8; - } else { - if (!(_features & GF_HUMONGOUS)) - setCursorHotspot(READ_LE_UINT16(&foir.imhd->old.hotspot[0].x), - READ_LE_UINT16(&foir.imhd->old.hotspot[0].y)); - w = READ_LE_UINT16(&foir.cdhd->v6.w) / 8; - h = READ_LE_UINT16(&foir.cdhd->v6.h) / 8; - } - - dataptr = getObjectImage(foir.obim, imgindex); - assert(dataptr); - if (_version == 8) { - bomp = dataptr; - } else { - size = READ_BE_UINT32(dataptr + 4); - if (size > sizeof(_grabbedCursor)) - error("setCursorImg: Cursor image too large"); - - bomp = findResource(MKID('BOMP'), dataptr); - } - - if (bomp != NULL) - useBompCursor(bomp, w, h); - else - useIm01Cursor(dataptr, w, h); - -} - void ScummEngine::nukeFlObjects(int min, int max) { ObjectData *od; int i; diff --git a/scumm/resource_v7he.cpp b/scumm/resource_v7he.cpp index a9f1442d40..1d597d581e 100644 --- a/scumm/resource_v7he.cpp +++ b/scumm/resource_v7he.cpp @@ -67,7 +67,7 @@ void Win32ResExtractor::setCursor(int id) { &keycolor); _vm->setCursorHotspot(hotspot_x, hotspot_y); - _vm->grabCursorFromBuffer(cursor, w, h); + _vm->setCursorFromBuffer(cursor, w, h, w); free(cursorRes); free(cursor); } diff --git a/scumm/script_v5.cpp b/scumm/script_v5.cpp index bffc56a2c0..41dcd6beab 100644 --- a/scumm/script_v5.cpp +++ b/scumm/script_v5.cpp @@ -675,15 +675,14 @@ void ScummEngine_v5::o5_cursorCommand() { _userPut--; break; case 10: // SO_CURSOR_IMAGE - i = getVarOrDirectByte(PARAM_1); - j = getVarOrDirectByte(PARAM_2); - // cursor image in both Looms is based on image from charset - // omit for now. - // FIXME: Actually: is this opcode ever called by a non-Loom game? - // Which V3-V5 game besides Loom makes use of custom cursors, ever? + i = getVarOrDirectByte(PARAM_1); // Cursor number + j = getVarOrDirectByte(PARAM_2); // Charset letter to use + // Cursor image in both Looms are based on images from charset. + // For now we don't handle them. if (_gameId != GID_LOOM && _gameId != GID_LOOM256) { - warning("setCursorImg called - tell Fingolfin where you saw this!"); - setCursorImg(i, j, 1); + // FIXME: Actually: is this opcode ever called by a non-Loom game? + // Which V3-V5 game besides Loom makes use of custom cursors, ever? + warning("V3--V5 SO_CURSOR_IMAGE(%d,%d) called - tell Fingolfin where you saw this!", i, j); } break; case 11: // SO_CURSOR_HOTSPOT diff --git a/scumm/script_v6.cpp b/scumm/script_v6.cpp index 21748811af..07d0235e56 100644 --- a/scumm/script_v6.cpp +++ b/scumm/script_v6.cpp @@ -976,7 +976,7 @@ void ScummEngine_v6::o6_cursorCommand() { case 0x99: // SO_CURSOR_IMAGE Set cursor image { int room, obj = popRoomAndObj(&room); - setCursorImg(obj, room, 1); + setCursorFromImg(obj, room, 1); break; } case 0x9A: // SO_CURSOR_HOTSPOT Set cursor hotspot @@ -992,7 +992,7 @@ void ScummEngine_v6::o6_cursorCommand() { _charsetColorMap[i] = _charsetData[_string[1]._default.charset][i] = (unsigned char)args[i]; break; case 0xD6: // SO_CURSOR_TRANSPARENT Set cursor transparent color - makeCursorColorTransparent(pop()); + setCursorTransparency(pop()); break; default: error("o6_cursorCommand: default case %x", subOp); @@ -2567,7 +2567,7 @@ void ScummEngine_v6::o6_kernelSetFunctions() { } break; case 12: - setCursorImg(args[1], (uint) - 1, args[2]); + setCursorFromImg(args[1], (uint) - 1, args[2]); break; case 13: derefActor(args[1], "o6_kernelSetFunctions:13")->remapActorPalette(args[2], args[3], args[4], -1); diff --git a/scumm/script_v7he.cpp b/scumm/script_v7he.cpp index 92429be9b2..28090ea287 100644 --- a/scumm/script_v7he.cpp +++ b/scumm/script_v7he.cpp @@ -749,7 +749,7 @@ void ScummEngine_v7he::o7_cursorCommand() { _charsetColorMap[i] = _charsetData[_string[1]._default.charset][i] = (unsigned char)args[i]; break; case 0xD6: // SO_CURSOR_TRANSPARENT Set cursor transparent color - makeCursorColorTransparent(pop()); + setCursorTransparency(pop()); break; default: error("o6_cursorCommand: default case %x", subOp); diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp index 3cbfa30d68..f68dfe344a 100644 --- a/scumm/script_v8.cpp +++ b/scumm/script_v8.cpp @@ -730,7 +730,7 @@ void ScummEngine_v8::o8_cursorCommand() { int idx = pop(); int room, obj; obj = popRoomAndObj(&room); - setCursorImg(obj, room, idx); + setCursorFromImg(obj, room, idx); } break; case 0xE5: // SO_CURSOR_HOTSPOT Set cursor hotspot @@ -738,7 +738,7 @@ void ScummEngine_v8::o8_cursorCommand() { setCursorHotspot(pop(), a); break; case 0xE6: // SO_CURSOR_TRANSPARENT Set cursor transparent color - makeCursorColorTransparent(pop()); + setCursorTransparency(pop()); break; case 0xE7: { // SO_CHARSET_SET int charset = pop(); diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index f77389df2d..71aa8a97db 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -1245,7 +1245,7 @@ void ScummEngine::scummInit() { _flashlight.buffer = NULL; } - // HACK curcor hotspot is wrong + // HACK cursor hotspot is wrong // Original games used // setCursorHotspot(8, 7); if (_gameId == GID_FUNPACK) @@ -1306,6 +1306,15 @@ void ScummEngine::scummInit() { _lastSaveTime = _system->get_msecs(); } +void ScummEngine_v6::scummInit() { + ScummEngine::scummInit(); + + if (_gameId == GID_TENTACLE && res.roomno[rtRoom][60]) { + // HACK: For DOTT we manually set the default cursor. See also bug #786994 + setCursorFromImg(697, 60, 1); + setCursorTransparency(1); + } +} void ScummEngine::initScummVars() { diff --git a/scumm/scumm.h b/scumm/scumm.h index cb4b187c7e..9573d41c37 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -374,7 +374,7 @@ public: virtual ~ScummEngine(); // Init functions - void scummInit(); + virtual void scummInit(); void initScummVars(); virtual void setupScummVars(); @@ -937,17 +937,13 @@ protected: void desaturatePalette(int hueScale, int satScale, int lightScale, int startColor, int endColor); void setCursor(int cursor); - void setCursorImg(uint img, uint room, uint imgindex); void setCursorHotspot(int x, int y); - void grabCursor(int x, int y, int w, int h); - void grabCursor(byte *ptr, int width, int height); - void grabCursorFromBuffer(byte *ptr, int width, int height); - void makeCursorColorTransparent(int a); + void setCursorTransparency(int a); void setupCursor(); - void decompressDefaultCursor(int index); - void useIm01Cursor(const byte *im, int w, int h); - void useBompCursor(const byte *im, int w, int h); + void setBuiltinCursor(int index); + void grabCursor(int x, int y, int w, int h); + void setCursorFromBuffer(byte *ptr, int width, int height, int pitch); public: void markRectAsDirty(VirtScreenNumber virt, int left, int right, int top, int bottom, int dirtybit = 0); -- cgit v1.2.3