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.
This commit is contained in:
Colin Snover 2017-08-04 18:53:00 -05:00
parent d2b4e16ab2
commit 43a07abb46
5 changed files with 65 additions and 1 deletions

View file

@ -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);

View file

@ -574,6 +574,16 @@ static const SciKernelMapSubEntry kCelInfo_subops[] = {
SCI_SUBOPENTRY_TERMINATOR
};
// 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 },
@ -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 },

View file

@ -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());

View file

@ -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

View file

@ -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 -