aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorColin Snover2016-03-10 14:05:27 -0600
committerColin Snover2016-03-10 14:16:56 -0600
commit4a16ebc970bfe1eae948b5d59accc321b092db8c (patch)
treee686fe900fe88ddd914cfaba18bbc49edd87c19b /engines/sci
parenteac416f480ca5d08a6117b15e78ef906a0135c91 (diff)
downloadscummvm-rg350-4a16ebc970bfe1eae948b5d59accc321b092db8c.tar.gz
scummvm-rg350-4a16ebc970bfe1eae948b5d59accc321b092db8c.tar.bz2
scummvm-rg350-4a16ebc970bfe1eae948b5d59accc321b092db8c.zip
SCI32: Implement kSetNowSeen
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/kernel.h1
-rw-r--r--engines/sci/engine/kernel_tables.h5
-rw-r--r--engines/sci/engine/kgraphics.cpp14
-rw-r--r--engines/sci/graphics/compare.cpp21
-rw-r--r--engines/sci/graphics/frameout.cpp20
-rw-r--r--engines/sci/graphics/frameout.h1
-rw-r--r--engines/sci/graphics/screen_item32.cpp103
-rw-r--r--engines/sci/graphics/screen_item32.h7
8 files changed, 146 insertions, 26 deletions
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index d521d4f057..6feaeb865b 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -452,7 +452,6 @@ reg_t kScrollWindowShow(EngineState *s, int argc, reg_t *argv);
reg_t kScrollWindowDestroy(EngineState *s, int argc, reg_t *argv);
reg_t kMulDiv(EngineState *s, int argc, reg_t *argv);
-reg_t kSetNowSeen32(EngineState *s, int argc, reg_t *argv);
reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv);
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index ad07072aea..1cb02d4e33 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -568,7 +568,10 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL },
{ MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL },
{ MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
- { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
+ { MAP_CALL(SetNowSeen), SIG_SCI16, SIGFOR_ALL, "o(i)", NULL, NULL },
+#ifdef ENABLE_SCI32
+ { MAP_CALL(SetNowSeen), SIG_SCI32, SIGFOR_ALL, "o", NULL, NULL },
+#endif
{ MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iiiii)(i)", NULL, kSetPort_workarounds },
{ MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL },
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 93d0d91b65..c79ffa9dd5 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -572,9 +572,17 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) {
}
reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gfxCompare->kernelSetNowSeen(argv[0]);
-
- return s->r_acc;
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ g_sci->_gfxFrameout->kernelSetNowSeen(argv[0]);
+ return NULL_REG;
+ } else {
+#endif
+ g_sci->_gfxCompare->kernelSetNowSeen(argv[0]);
+ return s->r_acc;
+#ifdef ENABLE_SCI32
+ }
+#endif
}
reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp
index 698ad1baf1..2f83017915 100644
--- a/engines/sci/graphics/compare.cpp
+++ b/engines/sci/graphics/compare.cpp
@@ -122,9 +122,6 @@ uint16 GfxCompare::kernelOnControl(byte screenMask, const Common::Rect &rect) {
void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
GfxView *view = NULL;
Common::Rect celRect(0, 0);
- // TODO/FIXME: Torin's menu code tries to draw special views with an ID of 0xFFFF, which
- // are not currently handled properly and cause a crash. These might be text views that
- // are not properly implemented.
GuiResourceId viewId = (GuiResourceId)readSelectorValue(_segMan, objectReference, SELECTOR(view));
int16 loopNo = readSelectorValue(_segMan, objectReference, SELECTOR(loop));
int16 celNo = readSelectorValue(_segMan, objectReference, SELECTOR(cel));
@@ -135,26 +132,8 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z));
view = _cache->getView(viewId);
-
-#ifdef ENABLE_SCI32
- if (view->isSci2Hires())
- view->adjustToUpscaledCoordinates(y, x);
- else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE))
- _coordAdjuster->fromScriptToDisplay(y, x);
-#endif
-
view->getCelRect(loopNo, celNo, x, y, z, celRect);
-#ifdef ENABLE_SCI32
- if (view->isSci2Hires()) {
- view->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
- view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
- } else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) {
- _coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
- _coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
- }
-#endif
-
if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) {
setNSRect(objectReference, celRect);
}
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 655e59de00..78e61b9e34 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -2028,6 +2028,26 @@ bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const
return true;
}
+void GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const {
+ const reg_t planeObject = readSelector(_segMan, screenItemObject, SELECTOR(plane));
+
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("Plane %04x:%04x not found", PRINT_REG(planeObject));
+ }
+
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject);
+ if (screenItem == nullptr) {
+ error("Screen item %04x:%04x not found", PRINT_REG(screenItemObject));
+ }
+
+ Common::Rect result = screenItem->getNowSeenRect(*plane);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsLeft), result.left);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), result.top);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), result.right - 1);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), result.bottom - 1);
+}
+
#pragma mark -
#pragma mark Debugging
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index f864abc5bc..969123f4d3 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -245,6 +245,7 @@ public:
void kernelAddScreenItem(const reg_t object);
void kernelUpdateScreenItem(const reg_t object);
void kernelDeleteScreenItem(const reg_t object);
+ void kernelSetNowSeen(const reg_t screenItemObject) const;
#pragma mark -
#pragma mark Planes
diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp
index 4a42221875..9f6dc7a2a2 100644
--- a/engines/sci/graphics/screen_item32.cpp
+++ b/engines/sci/graphics/screen_item32.cpp
@@ -495,6 +495,109 @@ void ScreenItem::update(const reg_t object) {
_deleted = 0;
}
+// TODO: This code is quite similar to calcRects, so try to deduplicate
+// if possible
+Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
+ CelObj &celObj = getCelObj();
+
+ Common::Rect celObjRect(celObj._width, celObj._height);
+ Common::Rect nsRect;
+
+ if (_useInsetRect) {
+ // TODO: This is weird. Checking to see if the inset rect is
+ // fully inside the bounds of the celObjRect, and then
+ // clipping to the celObjRect, is pretty useless.
+ if (_insetRect.right > 0 && _insetRect.bottom > 0 && _insetRect.left < celObj._width && _insetRect.top < celObj._height) {
+ nsRect = _insetRect;
+ nsRect.clip(celObjRect);
+ } else {
+ nsRect = Common::Rect();
+ }
+ } else {
+ nsRect = celObjRect;
+ }
+
+ const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ Ratio scaleX, scaleY;
+ if (_scale.signal & kScaleSignalDoScaling32) {
+ if (_scale.signal & kScaleSignalUseVanishingPoint) {
+ int num = _scale.max * (_position.y - plane._vanishingPoint.y) / (scriptWidth - plane._vanishingPoint.y);
+ scaleX = Ratio(num, 128);
+ scaleY = Ratio(num, 128);
+ } else {
+ scaleX = Ratio(_scale.x, 128);
+ scaleY = Ratio(_scale.y, 128);
+ }
+ }
+
+ if (scaleX.getNumerator() == 0 || scaleY.getNumerator() == 0) {
+ return Common::Rect();
+ }
+
+ int16 displaceX = celObj._displace.x;
+ int16 displaceY = celObj._displace.y;
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
+ displaceX = celObj._width - displaceX - 1;
+ }
+
+ if (celObj._scaledWidth != scriptWidth || celObj._scaledHeight != scriptHeight) {
+ if (_useInsetRect) {
+ Ratio scriptToScaledX(celObj._scaledWidth, scriptWidth);
+ Ratio scriptToScaledY(celObj._scaledHeight, scriptHeight);
+ mulru(nsRect, scriptToScaledX, scriptToScaledY, 0);
+
+ // TODO: This is weird. Checking to see if the inset rect is
+ // fully inside the bounds of the celObjRect, and then
+ // clipping to the celObjRect, is pretty useless.
+ if (nsRect.right > 0 && nsRect.bottom > 0 && nsRect.left < celObj._width && nsRect.top < celObj._height) {
+ nsRect.clip(celObjRect);
+ } else {
+ nsRect = Common::Rect();
+ }
+ }
+
+ if (!scaleX.isOne() || !scaleY.isOne()) {
+ mulinc(nsRect, scaleX, scaleY);
+ // TODO: This was in the original code, baked into the
+ // multiplication though it is not immediately clear
+ // why this is the only one that reduces the BR corner
+ nsRect.right -= 1;
+ nsRect.bottom -= 1;
+ }
+
+ Ratio scaledToScriptX(scriptWidth, celObj._scaledWidth);
+ Ratio scaledToScriptY(scriptHeight, celObj._scaledHeight);
+
+ displaceX = (displaceX * scaleX * scaledToScriptX).toInt();
+ displaceY = (displaceY * scaleY * scaledToScriptY).toInt();
+
+ mulinc(nsRect, scaledToScriptX, scaledToScriptY);
+ nsRect.translate(_position.x - displaceX, _position.y - displaceY);
+ } else {
+ if (!scaleX.isOne() || !scaleY.isOne()) {
+ mulinc(nsRect, scaleX, scaleY);
+ // TODO: This was in the original code, baked into the
+ // multiplication though it is not immediately clear
+ // why this is the only one that reduces the BR corner
+ nsRect.right -= 1;
+ nsRect.bottom -= 1;
+ }
+
+ displaceX = (displaceX * scaleX).toInt();
+ displaceY = (displaceY * scaleY).toInt();
+ nsRect.translate(_position.x - displaceX, _position.y - displaceY);
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
+ nsRect.translate(plane._gameRect.width() - nsRect.width(), 0);
+ }
+ }
+
+ return nsRect;
+}
+
#pragma mark -
#pragma mark ScreenItemList
ScreenItem *ScreenItemList::findByObject(const reg_t object) const {
diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h
index 52782acc56..977d80ebad 100644
--- a/engines/sci/graphics/screen_item32.h
+++ b/engines/sci/graphics/screen_item32.h
@@ -259,6 +259,13 @@ public:
* VM object.
*/
void update(const reg_t object);
+
+ /**
+ * Gets the "now seen" rect for the screen item, which
+ * represents the current size and position of the
+ * screen item on the screen in script coordinates.
+ */
+ Common::Rect getNowSeenRect(const Plane &plane) const;
};
#pragma mark -