aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMatthew Hoops2011-02-06 00:05:27 +0000
committerMatthew Hoops2011-02-06 00:05:27 +0000
commit46404940b55dd07849548d185836b261c22dcf69 (patch)
tree28fe231e1fa7c90b6282cba0db839121558e3833 /engines/sci
parent36b6d961c202f4a6c06b362159f41b06a2d18248 (diff)
downloadscummvm-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/sci')
-rw-r--r--engines/sci/engine/kmisc.cpp78
-rw-r--r--engines/sci/graphics/cursor.cpp157
-rw-r--r--engines/sci/graphics/cursor.h6
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