diff options
author | Matthew Hoops | 2011-02-06 00:05:27 +0000 |
---|---|---|
committer | Matthew Hoops | 2011-02-06 00:05:27 +0000 |
commit | 46404940b55dd07849548d185836b261c22dcf69 (patch) | |
tree | 28fe231e1fa7c90b6282cba0db839121558e3833 /engines | |
parent | 36b6d961c202f4a6c06b362159f41b06a2d18248 (diff) | |
download | scummvm-rg350-46404940b55dd07849548d185836b261c22dcf69.tar.gz scummvm-rg350-46404940b55dd07849548d185836b261c22dcf69.tar.bz2 scummvm-rg350-46404940b55dd07849548d185836b261c22dcf69.zip |
SCI: Improve Mac SCI1.1+ cursor support
The scripts can pass a list of view id's from the DOS version that get remapped to CURS/crsr id's. GK1 cursors now work and Phantasmagoria uses the correct ones.
svn-id: r55791
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/kmisc.cpp | 78 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.cpp | 157 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.h | 6 |
3 files changed, 158 insertions, 83 deletions
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index b6e1aad679..6e961f72f3 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -31,6 +31,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/gc.h" +#include "sci/graphics/cursor.h" #include "sci/graphics/maciconbar.h" #include "sci/console.h" @@ -338,38 +339,77 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -// kIconBar is really a subop of kPlatform for SCI1.1 Mac +#ifdef ENABLE_SCI32 +reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { + Common::String setting = s->_segMan->getString(argv[0]); + reg_t data = readSelector(s->_segMan, argv[1], SELECTOR(data)); + + warning("Get config setting %s", setting.c_str()); + s->_segMan->strcpy(data, ""); + return argv[1]; +} +#endif + +// kIconBar is really a subop of kMacPlatform for SCI1.1 Mac reg_t kIconBar(EngineState *s, int argc, reg_t *argv) { + // Mac versions use their own tertiary platform functions + // to handle the outside-of-the-screen icon bar. + // QFG1 Mac calls this function to load the Mac icon bar (of which // the resources do exist), but the game completely ignores it and // uses the standard icon bar for the game. We do the same. if (!g_sci->hasMacIconBar()) return NULL_REG; - // TODO... - - if (argv[0].toUint16() == 4 && argv[1].toUint16() == 0) { - for (int i = 0; i < argv[2].toUint16(); i++) - g_sci->_gfxMacIconBar->addIcon(argv[i + 3]); + switch (argv[0].toUint16()) { + case 0: + // Add the icons + for (int i = 0; i < argv[1].toUint16(); i++) + g_sci->_gfxMacIconBar->addIcon(argv[i + 2]); - g_sci->_gfxMacIconBar->drawIcons(); + g_sci->_gfxMacIconBar->drawIcons(); + break; + case 2: + case 3: + case 4: + // TODO: Other calls seem to handle selecting/deselecting them + break; + default: + warning("Unknown kIconBar subop %d", argv[0].toUint16()); } - // Other calls seem to handle selecting/deselecting them - return NULL_REG; } -#ifdef ENABLE_SCI32 -reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) { - Common::String setting = s->_segMan->getString(argv[0]); - reg_t data = readSelector(s->_segMan, argv[1], SELECTOR(data)); +// kMacPlatform is really a subop of kPlatform for SCI1.1+ Mac +reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) { + // Mac versions use their own secondary platform functions + // to do various things. Why didn't they just declare a new + // kernel function? - warning("Get config setting %s", setting.c_str()); - s->_segMan->strcpy(data, ""); - return argv[1]; + switch (argv[0].toUint16()) { + case 0: + // Set Mac cursor remap + g_sci->_gfxCursor->setMacCursorRemapList(argc - 1, argv + 1); + break; + case 1: + // Unknown + break; + case 2: + // Unknown + break; + case 3: + // Unknown + break; + case 4: + // Handle icon bar code + return kIconBar(s, argc - 1, argv + 1); + default: + warning("Unknown kMacPlatform subop %d", argv[0].toUint16()); + } + + return s->r_acc; } -#endif enum kSciPlatforms { kSciPlatformDOS = 1, @@ -415,8 +455,8 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { warning("STUB: kPlatform(CDCheck)"); break; case kPlatformUnk0: - if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1) - return kIconBar(s, argc - 1, argv + 1); + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1 && argc > 1) + return kMacPlatform(s, argc - 1, argv + 1); // Otherwise, fall through case kPlatformGetPlatform: return make_reg(0, (isWindows) ? kSciPlatformWindows : kSciPlatformDOS); diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 30fc7a0f3d..258900a3fb 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -223,70 +223,6 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co delete cursorHotspot; } -void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNum, Common::Point *hotspot) { - // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-402.html - // for more information. - - // View 998 seems to be a fake resource used to call for Mac cursor resources. - // For other resources, they're still in the views, so use them. - if (viewNum != 998) { - kernelSetView(viewNum, loopNum, celNum, hotspot); - return; - } - - // TODO: What about the 2000 resources? Inventory items? How to handle? - // Update: Perhaps these are handled like the Windows cursors in KQ6? - // TODO: 1000 + celNum won't work for GK1 - - Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, 1000 + celNum), false); - - if (!resource) { - warning("Mac cursor %d not found", 1000 + celNum); - return; - } - - assert(resource); - - if (resource->size == 32 * 2 + 4) { - // Mac CURS cursor - byte *cursorBitmap = new byte[16 * 16]; - byte *data = resource->data; - - // Get B&W data - for (byte i = 0; i < 32; i++) { - byte imageByte = *data++; - for (byte b = 0; b < 8; b++) - cursorBitmap[i * 8 + b] = (byte)((imageByte & (0x80 >> b)) > 0 ? 0x00 : 0xFF); - } - - // Apply mask data - for (byte i = 0; i < 32; i++) { - byte imageByte = *data++; - for (byte b = 0; b < 8; b++) - if ((imageByte & (0x80 >> b)) == 0) - cursorBitmap[i * 8 + b] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; // Doesn't matter, just is transparent - } - - uint16 hotspotX = READ_BE_UINT16(data); - uint16 hotspotY = READ_BE_UINT16(data + 2); - - CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, SCI_CURSOR_SCI0_TRANSPARENCYCOLOR); - - delete[] cursorBitmap; - } else { - // Mac crsr cursor - byte *cursorBitmap, *palette; - int width, height, hotspotX, hotspotY, palSize, keycolor; - Common::MacResManager::convertCrsrCursor(resource->data, resource->size, &cursorBitmap, &width, &height, &hotspotX, &hotspotY, &keycolor, true, &palette, &palSize); - CursorMan.replaceCursor(cursorBitmap, width, height, hotspotX, hotspotY, keycolor); - CursorMan.replaceCursorPalette(palette, 0, palSize); - free(cursorBitmap); - free(palette); - } - - kernelShow(); -} - // this list contains all mandatory set cursor changes, that need special handling // ffs. GfxCursor::setPosition (below) // Game, newPosition, validRect @@ -489,4 +425,97 @@ void GfxCursor::kernelMoveCursor(Common::Point pos) { _event->getSciEvent(SCI_EVENT_PEEK); } +void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNum, Common::Point *hotspot) { + // Here we try to map the view number onto the cursor. What they did was keep the + // kSetCursor calls the same, but perform remapping on the cursors. They also took + // it a step further and added a new kPlatform sub-subop that handles remapping + // automatically. + + if (_macCursorRemap.empty()) { + // The scripts have given us no remapping, so let's try to do this manually. + // First try and see if the view resource exists. If it does, we're just using + // that cursor (QFG1/Hoyle4 do not use Mac cursors, although they have them). + if (_resMan->testResource(ResourceId(kResourceTypeView, viewNum))) { + CursorMan.disableCursorPalette(true); + kernelSetView(viewNum, loopNum, celNum, hotspot); + return; + } + + // KQ6 seems to use this mapping for its cursors + viewNum = loopNum * 1000 + celNum; + } else { + // If we do have the list, we'll be using a remap based on what the + // scripts have given us. + for (uint32 i = 0; i < _macCursorRemap.size(); i++) { + if (viewNum == _macCursorRemap[i]) { + viewNum = (i + 1) * 0x100 + loopNum * 0x10 + celNum; + break; + } + + if (i == _macCursorRemap.size()) + error("Unmatched Mac cursor %d", viewNum); + } + } + + Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, viewNum), false); + + if (!resource) { + warning("Mac cursor %d not found", viewNum); + return; + } + + CursorMan.disableCursorPalette(false); + + assert(resource); + + if (resource->size == 32 * 2 + 4) { + // Mac CURS cursor + // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-402.html + // for more information. + byte *cursorBitmap = new byte[16 * 16]; + byte *data = resource->data; + + // Get B&W data + for (byte i = 0; i < 32; i++) { + byte imageByte = *data++; + for (byte b = 0; b < 8; b++) + cursorBitmap[i * 8 + b] = (byte)((imageByte & (0x80 >> b)) > 0 ? 1 : 2); + } + + // Apply mask data + for (byte i = 0; i < 32; i++) { + byte imageByte = *data++; + for (byte b = 0; b < 8; b++) + if ((imageByte & (0x80 >> b)) == 0) + cursorBitmap[i * 8 + b] = 0; // Doesn't matter, just is transparent + } + + uint16 hotspotX = READ_BE_UINT16(data); + uint16 hotspotY = READ_BE_UINT16(data + 2); + + static const byte cursorPalette[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00 }; + + CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0); + CursorMan.replaceCursorPalette(cursorPalette, 1, 2); + + delete[] cursorBitmap; + } else { + // Mac crsr cursor + byte *cursorBitmap, *palette; + int width, height, hotspotX, hotspotY, palSize, keycolor; + Common::MacResManager::convertCrsrCursor(resource->data, resource->size, &cursorBitmap, &width, &height, &hotspotX, &hotspotY, &keycolor, true, &palette, &palSize); + CursorMan.replaceCursor(cursorBitmap, width, height, hotspotX, hotspotY, keycolor); + CursorMan.replaceCursorPalette(palette, 0, palSize); + free(cursorBitmap); + free(palette); + } + + kernelShow(); +} + +void GfxCursor::setMacCursorRemapList(int cursorCount, reg_t *cursors) { + for (int i = 0; i < cursorCount; i++) + _macCursorRemap.push_back(cursors[i].toUint16()); +} + } // End of namespace Sci diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index cb65398f4b..271cf507e0 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -26,6 +26,7 @@ #ifndef SCI_GRAPHICS_CURSOR_H #define SCI_GRAPHICS_CURSOR_H +#include "common/array.h" #include "common/hashmap.h" namespace Sci { @@ -85,6 +86,8 @@ public: void kernelSetPos(Common::Point pos); void kernelMoveCursor(Common::Point pos); + void setMacCursorRemapList(int cursorCount, reg_t *cursors); + private: void purgeCache(); @@ -119,6 +122,9 @@ private: // graphics, like SSCI did. These look very ugly, which is why // they aren't enabled by default. bool _useOriginalKQ6WinCursors; + + // Mac versions of games use a remap list to remap their cursors + Common::Array<uint16> _macCursorRemap; }; } // End of namespace Sci |