aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorColin Snover2016-01-18 00:12:47 -0600
committerColin Snover2016-02-18 13:18:02 -0600
commit75ccabc325d56876dd34d4a55e2034ee66d33d0b (patch)
tree01961ae148804e0206aa8c7858ac879471da04dd /engines/sci/engine
parent4ba0ff8deb57aba3b034462c6c00ecf13ee281c9 (diff)
downloadscummvm-rg350-75ccabc325d56876dd34d4a55e2034ee66d33d0b.tar.gz
scummvm-rg350-75ccabc325d56876dd34d4a55e2034ee66d33d0b.tar.bz2
scummvm-rg350-75ccabc325d56876dd34d4a55e2034ee66d33d0b.zip
SCI: Implement accurate renderer architecture for SCI32
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/kgraphics32.cpp186
-rw-r--r--engines/sci/engine/object.h36
-rw-r--r--engines/sci/engine/selector.cpp11
-rw-r--r--engines/sci/engine/selector.h2
-rw-r--r--engines/sci/engine/vm_types.cpp14
-rw-r--r--engines/sci/engine/vm_types.h13
6 files changed, 148 insertions, 114 deletions
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 8d41393a9e..93e8b90ecc 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -80,21 +80,18 @@ reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) {
}
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->_gfxFrameout->findScreenItem(argv[0]) == NULL)
- g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
- else
- g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]);
- return s->r_acc;
+ g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
+ return NULL_REG;
}
reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]);
- return s->r_acc;
+ return NULL_REG;
}
reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxFrameout->kernelDeleteScreenItem(argv[0]);
- return s->r_acc;
+ return NULL_REG;
}
reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) {
@@ -115,11 +112,12 @@ reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) {
reg_t planeObj = argv[0];
GuiResourceId pictureId = argv[1].toUint16();
- int16 pictureX = argv[2].toSint16();
- int16 pictureY = argv[3].toSint16();
+ int16 x = argv[2].toSint16();
+ int16 y = argv[3].toSint16();
+ bool mirrorX = argc > 4 ? argv[4].toSint16() : false;
- g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, pictureX, pictureY);
- return s->r_acc;
+ g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, x, y, mirrorX);
+ return NULL_REG;
}
reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
@@ -127,43 +125,13 @@ reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
}
reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
-/* TODO: Transcribed from SCI engine disassembly.
- GraphicsMgr &graphicsMgr = g_sci->_graphicsMgr;
- if (graphicsMgr.palMorphNeeded) {
- graphicsMgr.PalMorphFrameOut(&g_PalStyleRanges, false);
- }
- else {
- // TODO: Not sure if this is a pointer or not yet.
- if (g_ScrollState != nullptr) {
- kFrameOutDoScroll();
- }
-
- bool showBits = true;
- if (argc == 1) {
- showBits = (bool) argv[0].toUint16();
- }
-
- rect SOL_Rect = { .left = 0, .top = 0, .right = UINT32_MAX, .bottom = UINT32_MAX };
- graphicsMgr.FrameOut(showBits, &rect);
- }
-*/
- g_sci->_gfxFrameout->kernelFrameout();
+ bool showBits = argc > 0 ? argv[0].toUint16() : true;
+ g_sci->_gfxFrameout->kernelFrameout(showBits);
return NULL_REG;
}
reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv) {
-/* TODO: Transcribed from SCI engine disassembly.
- uint16 start = argv[0].toUint16();
- uint16 end = argv[1].toUint16();
- if (end <= start) {
- uint16 index = start;
- while (index <= end) {
- g_PalStyleRanges[index] = 0;
- }
- }
-*/
-
- kStub(s, argc, argv);
+ g_sci->_gfxFrameout->kernelSetPalStyleRange(argv[0].toUint16(), argv[1].toUint16());
return NULL_REG;
}
@@ -266,72 +234,59 @@ reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) {
}
/**
- * Used for scene transitions, replacing (but reusing parts of) the old
- * transition code.
+ * Causes an immediate plane transition with an optional transition
+ * effect
*/
reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
- // Can be called with 7 or 8 parameters
- // The style defines which transition to perform. Related to the transition
- // tables inside graphics/transitions.cpp
- uint16 showStyle = argv[0].toUint16(); // 0 - 15
- reg_t planeObj = argv[1]; // the affected plane
- Common::String planeObjName = s->_segMan->getObjectName(planeObj);
- uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts
- uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff
- int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out
- uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts
- uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out
+ ShowStyleType type = (ShowStyleType)argv[0].toUint16();
+ reg_t planeObj = argv[1];
+ int16 seconds = argv[2].toSint16();
+ // NOTE: This value seems to indicate whether the transition is an
+ // “exit” transition (0) or an “enter” transition (-1) for fade
+ // transitions. For other types of transitions, it indicates a palette
+ // index value to use when filling the screen.
+ int16 back = argv[3].toSint16();
+ int16 priority = argv[4].toSint16();
+ int16 animate = argv[5].toSint16();
+ // TODO: Rename to frameOutNow?
+ int16 refFrame = argv[6].toSint16();
+ int16 blackScreen;
+ reg_t pFadeArray;
int16 divisions;
- // If the game has the pFadeArray selector, another parameter is used here,
- // before the optional last parameter
- bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0;
- if (hasFadeArray) {
- // argv[7]
- divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?)
- } else {
- divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?)
+ // SCI 2–2.1early
+ if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
+ blackScreen = 0;
+ pFadeArray = NULL_REG;
+ divisions = argc > 7 ? argv[7].toSint16() : -1;
}
-
- if (showStyle > 15) {
- warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj));
- return s->r_acc;
+ // SCI 2.1mid–2.1late
+ else if (getSciVersion() < SCI_VERSION_3) {
+ blackScreen = 0;
+ pFadeArray = argc > 7 ? argv[7] : NULL_REG;
+ divisions = argc > 8 ? argv[8].toSint16() : -1;
+ }
+ // SCI 3
+ else {
+ blackScreen = argv[7].toSint16();
+ pFadeArray = argc > 8 ? argv[8] : NULL_REG;
+ divisions = argc > 9 ? argv[9].toSint16() : -1;
}
- // GK1 calls fadeout (13) / fadein (14) with the following parameters:
- // seconds: 1
- // backColor: 0 / -1
- // fade: 200
- // animate: 0
- // refFrame: 0
- // divisions: 0 / 20
-
- // TODO: Check if the plane is in the list of planes to draw
-
- Common::String effectName = "unknown";
+// TODO: Reuse later for SCI2 and SCI3 implementation and then discard
+// warning("kSetShowStyle: effect %d, plane: %04x:%04x (%s), sec: %d, "
+// "dir: %d, prio: %d, animate: %d, ref frame: %d, black screen: %d, "
+// "pFadeArray: %04x:%04x (%s), divisions: %d",
+// type, PRINT_REG(planeObj), s->_segMan->getObjectName(planeObj), seconds,
+// back, priority, animate, refFrame, blackScreen,
+// PRINT_REG(pFadeArray), s->_segMan->getObjectName(pFadeArray), divisions);
- switch (showStyle) {
- case 0: // no transition / show
- effectName = "show";
- break;
- case 13: // fade out
- effectName = "fade out";
- // TODO
- break;
- case 14: // fade in
- effectName = "fade in";
- // TODO
- break;
- default:
- // TODO
- break;
- }
+ // NOTE: The order of planeObj and showStyle are reversed
+ // because this is how SCI3 called the corresponding method
+ // on the KernelMgr
+ g_sci->_gfxFrameout->kernelSetShowStyle(argc, planeObj, type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen);
- warning("kSetShowStyle: effect %d (%s) - plane: %04x:%04x (%s), sec: %d, "
- "back: %d, prio: %d, animate: %d, ref frame: %d, divisions: %d",
- showStyle, effectName.c_str(), PRINT_REG(planeObj), planeObjName.c_str(),
- seconds, backColor, priority, animate, refFrame, divisions);
- return s->r_acc;
+ return NULL_REG;
}
reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
@@ -359,6 +314,8 @@ reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
}
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+#if 0
// Used by SQ6 and LSL6 hires for the text area in the bottom of the
// screen. The relevant scripts also exist in Phantasmagoria 1, but they're
// unused. This is always called by scripts 64906 (ScrollerWindow) and
@@ -464,6 +421,7 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
}
return s->r_acc;
+#endif
}
reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) {
@@ -497,6 +455,8 @@ reg_t kFont(EngineState *s, int argc, reg_t *argv) {
// TODO: Eventually, all of the kBitmap operations should be put
// in a separate class
+// NOTE: This size is correct only for SCI2.1mid; the size for
+// SCI2/2.1early is 36
#define BITMAP_HEADER_SIZE 46
reg_t kBitmap(EngineState *s, int argc, reg_t *argv) {
@@ -673,6 +633,8 @@ reg_t kEditText(EngineState *s, int argc, reg_t *argv) {
}
reg_t kAddLine(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+#if 0
reg_t plane = argv[0];
Common::Point startPoint(argv[1].toUint16(), argv[2].toUint16());
Common::Point endPoint(argv[3].toUint16(), argv[4].toUint16());
@@ -681,10 +643,15 @@ reg_t kAddLine(EngineState *s, int argc, reg_t *argv) {
byte priority = (byte)argv[7].toUint16();
byte control = (byte)argv[8].toUint16();
// argv[9] is unknown (usually a small number, 1 or 2). Thickness, perhaps?
- return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, control);
+// return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, control);
+ return s->r_acc;
+#endif
}
reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+
+#if 0
reg_t hunkId = argv[0];
reg_t plane = argv[1];
Common::Point startPoint(argv[2].toUint16(), argv[3].toUint16());
@@ -694,14 +661,18 @@ reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) {
byte priority = (byte)argv[8].toUint16();
byte control = (byte)argv[9].toUint16();
// argv[10] is unknown (usually a small number, 1 or 2). Thickness, perhaps?
- g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control);
+// g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control);
return s->r_acc;
+#endif
}
reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+#if 0
reg_t hunkId = argv[0];
reg_t plane = argv[1];
- g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId);
+// g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId);
return s->r_acc;
+#endif
}
reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {
@@ -730,12 +701,7 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {
// Used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270)
reg_t kMorphOn(EngineState *s, int argc, reg_t *argv) {
- // TODO: g_sci->_gfxManager->palMorphIsOn = true
- // This function sets the palMorphIsOn flag which causes kFrameOut to use
- // an alternative FrameOut function (GraphicsMgr::PalMorphFrameOut instead
- // of GraphicsMgr::FrameOut). At the end of the frame, kFrameOut sets the
- // palMorphIsOn flag back to false.
- kStub(s, argc, argv);
+ g_sci->_gfxFrameout->_palMorphIsOn = true;
return NULL_REG;
}
diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h
index 0ae7ed2cab..cc9f5ebb52 100644
--- a/engines/sci/engine/object.h
+++ b/engines/sci/engine/object.h
@@ -41,8 +41,21 @@ enum {
};
enum infoSelectorFlags {
- kInfoFlagClone = 0x0001,
- kInfoFlagClass = 0x8000
+ kInfoFlagClone = 0x0001,
+#ifdef ENABLE_SCI32
+ /**
+ * When set, indicates to game scripts that a screen
+ * item can be updated.
+ */
+ kInfoFlagViewVisible = 0x0008, // TODO: "dirty" ?
+
+ /**
+ * When set, the object has an associated screen item in
+ * the rendering tree.
+ */
+ kInfoFlagViewInserted = 0x0010,
+#endif
+ kInfoFlagClass = 0x8000
};
enum ObjectOffsets {
@@ -120,7 +133,24 @@ public:
_infoSelectorSci3 = info;
}
- // No setter for the -info- selector
+#ifdef ENABLE_SCI32
+ void setInfoSelectorFlag(infoSelectorFlags flag) {
+ if (getSciVersion() < SCI_VERSION_3) {
+ _variables[_offset + 2] |= flag;
+ } else {
+ _infoSelectorSci3 |= flag;
+ }
+ }
+
+ // NOTE: In real engine, -info- is treated as byte size
+ void clearInfoSelectorFlag(infoSelectorFlags flag) {
+ if (getSciVersion() < SCI_VERSION_3) {
+ _variables[_offset + 2] &= ~flag;
+ } else {
+ _infoSelectorSci3 &= ~flag;
+ }
+ }
+#endif
reg_t getNameSelector() const {
if (getSciVersion() < SCI_VERSION_3)
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index 910f1f885f..05a9e6c980 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -187,6 +187,7 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(inLeft);
FIND_SELECTOR(inBottom);
FIND_SELECTOR(inRight);
+ FIND_SELECTOR(magnifier);
#endif
}
@@ -211,8 +212,16 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t
if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
error("Selector '%s' of object at %04x:%04x could not be"
" written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
- else
+ else {
*address.getPointer(segMan) = value;
+#ifdef ENABLE_SCI32
+ // TODO: Make this correct for all SCI versions
+ // Selectors 26 through 44 are selectors for View script objects
+ if (getSciVersion() >= SCI_VERSION_2 && selectorId >= 26 && selectorId <= 44) {
+ segMan->getObject(object)->setInfoSelectorFlag(kInfoFlagViewVisible);
+ }
+#endif
+ }
}
void invokeSelector(EngineState *s, reg_t object, int selectorId,
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index b3dd393708..a8b195f245 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -153,6 +153,8 @@ struct SelectorCache {
Selector useInsetRect;
Selector inTop, inLeft, inBottom, inRight;
+
+ Selector magnifier;
#endif
};
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
index cf008c45e1..53a5a5c507 100644
--- a/engines/sci/engine/vm_types.cpp
+++ b/engines/sci/engine/vm_types.cpp
@@ -210,6 +210,20 @@ reg_t reg_t::operator^(const reg_t right) const {
return lookForWorkaround(right, "bitwise XOR");
}
+#ifdef ENABLE_SCI32
+reg_t reg_t::operator&(int16 right) const {
+ return *this & make_reg(0, right);
+}
+
+reg_t reg_t::operator|(int16 right) const {
+ return *this | make_reg(0, right);
+}
+
+reg_t reg_t::operator^(int16 right) const {
+ return *this ^ make_reg(0, right);
+}
+#endif
+
int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
if (getSegment() == right.getSegment()) { // can compare things in the same segment
if (treatAsUnsigned || !isNumber())
diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h
index af78bd0b84..a646478a8e 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -136,6 +136,19 @@ struct reg_t {
reg_t operator|(const reg_t right) const;
reg_t operator^(const reg_t right) const;
+#ifdef ENABLE_SCI32
+ reg_t operator&(int16 right) const;
+ reg_t operator|(int16 right) const;
+ reg_t operator^(int16 right) const;
+
+ void operator&=(const reg_t &right) { *this = *this & right; }
+ void operator|=(const reg_t &right) { *this = *this | right; }
+ void operator^=(const reg_t &right) { *this = *this ^ right; }
+ void operator&=(int16 right) { *this = *this & right; }
+ void operator|=(int16 right) { *this = *this | right; }
+ void operator^=(int16 right) { *this = *this ^ right; }
+#endif
+
private:
/**
* Compares two reg_t's.