aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-08-04 18:53:00 -0500
committerColin Snover2017-09-03 20:58:07 -0500
commit43a07abb46cc55d09f7415090f9f53c068c856aa (patch)
treebf31cbe8d30dadce8706e9484d519e71b73afc9e
parentd2b4e16ab2bd28ce8b39a6330683228bd48950c2 (diff)
downloadscummvm-rg350-43a07abb46cc55d09f7415090f9f53c068c856aa.tar.gz
scummvm-rg350-43a07abb46cc55d09f7415090f9f53c068c856aa.tar.bz2
scummvm-rg350-43a07abb46cc55d09f7415090f9f53c068c856aa.zip
SCI32: Implement kCelLink
kCelLink exists in SSCI since 2.1mid, but it is only known to be used in Lighthouse, during the weapon creation puzzle near the end of the game.
-rw-r--r--engines/sci/engine/kernel.h3
-rw-r--r--engines/sci/engine/kernel_tables.h12
-rw-r--r--engines/sci/engine/kgraphics32.cpp17
-rw-r--r--engines/sci/graphics/celobj32.cpp32
-rw-r--r--engines/sci/graphics/celobj32.h2
5 files changed, 65 insertions, 1 deletions
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index d1dce37e48..baa891650e 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -636,6 +636,9 @@ reg_t kCelInfo(EngineState *s, int argc, reg_t *argv);
reg_t kCelInfoGetOriginX(EngineState *s, int argc, reg_t *argv);
reg_t kCelInfoGetOriginY(EngineState *s, int argc, reg_t *argv);
reg_t kCelInfoGetPixel(EngineState *s, int argc, reg_t *argv);
+reg_t kCelLink(EngineState *s, int argc, reg_t *argv);
+reg_t kCelLinkGetX(EngineState *s, int argc, reg_t *argv);
+reg_t kCelLinkGetY(EngineState *s, int argc, reg_t *argv);
reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv);
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index c65356470a..ac932199d3 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -575,6 +575,16 @@ static const SciKernelMapSubEntry kCelInfo_subops[] = {
};
// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kCelLink_subops[] = {
+ { SIG_SINCE_SCI21MID, 0, MAP_DUMMY(CelLink0), "", NULL },
+ { SIG_SINCE_SCI21MID, 1, MAP_DUMMY(CelLink1), "", NULL },
+ { SIG_SINCE_SCI21MID, 2, MAP_CALL(CelLinkGetX), "iiii", NULL },
+ { SIG_SINCE_SCI21MID, 3, MAP_CALL(CelLinkGetY), "iiii", NULL },
+ { SIG_SINCE_SCI21MID, 4, MAP_DUMMY(CelLink4), "", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kScrollWindow_subops[] = {
{ SIG_SCI32, 0, MAP_CALL(ScrollWindowCreate), "oi", NULL },
{ SIG_SCI32, 1, MAP_CALL(ScrollWindowAdd), "iriii(i)", kScrollWindowAdd_workarounds },
@@ -988,7 +998,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_DUMMY(FindClass), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(CelRect), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(BaseLineSpan), SIG_EVERYWHERE, "(.*)", NULL, NULL },
- { MAP_DUMMY(CelLink), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(CelLink), SIG_SINCE_SCI21MID, SIGFOR_ALL, "(.*)", kCelLink_subops, NULL },
{ MAP_DUMMY(AddPolygon), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(DeletePolygon), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(UpdatePolygon), SIG_EVERYWHERE, "(.*)", NULL, NULL },
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 44a3517458..c07282f53e 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -449,6 +449,23 @@ reg_t kCelInfoGetPixel(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, view.readPixel(argv[3].toSint16(), argv[4].toSint16(), view._mirrorX));
}
+// Used by Lighthouse, room 800, script 16, when in the weapon-building puzzle
+reg_t kCelLink(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
+reg_t kCelLinkGetX(EngineState *s, int argc, reg_t *argv) {
+ CelObjView view(argv[0].toUint16(), argv[1].toSint16(), argv[2].toSint16());
+ return make_reg(0, view.getLinkPosition(argv[3].toSint16()).x);
+}
+
+reg_t kCelLinkGetY(EngineState *s, int argc, reg_t *argv) {
+ CelObjView view(argv[0].toUint16(), argv[1].toSint16(), argv[2].toSint16());
+ return make_reg(0, view.getLinkPosition(argv[3].toSint16()).y);
+}
+
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
if (!s)
return make_reg(0, getSciVersion());
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index 49b3b0053b..687ecd64f3 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -1081,6 +1081,38 @@ const SciSpan<const byte> CelObjView::getResPointer() const {
return *resource;
}
+Common::Point CelObjView::getLinkPosition(const int16 linkId) const {
+ const SciSpan<const byte> resource = getResPointer();
+
+ if (resource[18] < 0x84) {
+ error("%s unsupported version %u for Links", _info.toString().c_str(), resource[18]);
+ }
+
+ const SciSpan<const byte> celHeader = resource.subspan(_celHeaderOffset);
+ const int16 numLinks = celHeader.getInt16SEAt(40);
+
+ if (numLinks) {
+ const int recordSize = 6;
+ SciSpan<const byte> linkTable = resource.subspan(celHeader.getInt32SEAt(36), recordSize * numLinks);
+ for (int16 i = 0; i < numLinks; ++i) {
+ if (linkTable[4] == linkId) {
+ Common::Point point;
+ point.x = linkTable.getInt16SEAt(0);
+ if (_mirrorX) {
+ // NOTE: SSCI had an off-by-one error here (missing -1)
+ point.x = _width - point.x - 1;
+ }
+ point.y = linkTable.getInt16SEAt(2);
+ return point;
+ }
+
+ linkTable += recordSize;
+ }
+ }
+
+ return Common::Point(-1, -1);
+}
+
#pragma mark -
#pragma mark CelObjPic
diff --git a/engines/sci/graphics/celobj32.h b/engines/sci/graphics/celobj32.h
index d51913473c..6e50f7232e 100644
--- a/engines/sci/graphics/celobj32.h
+++ b/engines/sci/graphics/celobj32.h
@@ -540,6 +540,8 @@ public:
virtual CelObjView *duplicate() const override;
virtual const SciSpan<const byte> getResPointer() const override;
+
+ Common::Point getLinkPosition(const int16 linkId) const;
};
#pragma mark -