aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk/myst_stacks
diff options
context:
space:
mode:
authorMatthew Hoops2010-11-29 21:34:59 +0000
committerMatthew Hoops2010-11-29 21:34:59 +0000
commit2bd16f9e84e3480e7bda65b89089c684a2eaa639 (patch)
tree93ebb08a8041785f7ccd71f16df8d8555fddf6b7 /engines/mohawk/myst_stacks
parentd3c78b8a3d4d1692f7db0d9391f76f3ba0092199 (diff)
downloadscummvm-rg350-2bd16f9e84e3480e7bda65b89089c684a2eaa639.tar.gz
scummvm-rg350-2bd16f9e84e3480e7bda65b89089c684a2eaa639.tar.bz2
scummvm-rg350-2bd16f9e84e3480e7bda65b89089c684a2eaa639.zip
MOHAWK: Move Myst stack-specific code to its own directory
svn-id: r54648
Diffstat (limited to 'engines/mohawk/myst_stacks')
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp3817
-rw-r--r--engines/mohawk/myst_stacks/myst.h164
-rw-r--r--engines/mohawk/myst_stacks/selenitic.cpp1766
-rw-r--r--engines/mohawk/myst_stacks/selenitic.h139
4 files changed, 5886 insertions, 0 deletions
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
new file mode 100644
index 0000000000..cd6e375fd5
--- /dev/null
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -0,0 +1,3817 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "mohawk/myst.h"
+#include "mohawk/graphics.h"
+#include "mohawk/myst_areas.h"
+#include "mohawk/sound.h"
+#include "mohawk/video.h"
+#include "mohawk/myst_stacks/myst.h"
+
+#include "gui/message.h"
+
+namespace Mohawk {
+
+// NOTE: Credits Start Card is 10000
+
+#define OPCODE(op, x) { op, &MystScriptParser::x, #x }
+#define SPECIFIC_OPCODE(op, x) { op, (OpcodeProcMyst) &MystScriptParser_Myst::x, #x }
+
+MystScriptParser_Myst::MystScriptParser_Myst(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+ setupOpcodes();
+ _invokingResource = NULL;
+
+ // Card ID preinitialized by the engine for use by opcode 18
+ // when linking back to Myst in the library
+ if (_vm->getCurStack() == kMystStack)
+ _savedCardId = 4329;
+}
+
+MystScriptParser_Myst::~MystScriptParser_Myst() {
+}
+
+void MystScriptParser_Myst::setupOpcodes() {
+ // "invalid" opcodes do not exist or have not been observed
+ // "unknown" opcodes exist, but their meaning is unknown
+
+ static const MystOpcode myst_opcodes[] = {
+ // "Standard" Opcodes
+ OPCODE(0, o_toggleVar),
+ OPCODE(1, o_setVar),
+ OPCODE(2, o_changeCardSwitch),
+ OPCODE(3, o_takePage),
+ OPCODE(4, o_redrawCard),
+ // TODO: Opcode 5 Not Present
+ OPCODE(6, o_goToDest),
+ OPCODE(7, o_goToDest),
+ OPCODE(8, o_goToDest),
+ OPCODE(9, o_triggerMovie),
+ OPCODE(10, o_toggleVarNoRedraw),
+ // TODO: Opcode 10 to 11 Not Present
+ OPCODE(12, o_changeCardSwitch),
+ OPCODE(13, o_changeCardSwitch),
+ OPCODE(14, o_drawAreaState),
+ OPCODE(15, o_redrawAreaForVar),
+ OPCODE(16, o_changeCardDirectional),
+ OPCODE(17, o_changeCardPush),
+ OPCODE(18, o_changeCardPop),
+ OPCODE(19, o_enableAreas),
+ OPCODE(20, o_disableAreas),
+ OPCODE(21, o_directionalUpdate),
+ OPCODE(22, o_goToDest),
+ OPCODE(23, o_toggleAreasActivation),
+ OPCODE(24, o_playSound),
+ // TODO: Opcode 25 Not Present
+ OPCODE(26, o_stopSoundBackground),
+ OPCODE(27, o_playSoundBlocking),
+ OPCODE(28, o_restoreDefaultRect),
+ OPCODE(29, o_blitRect),
+ OPCODE(30, o_changeSound),
+ OPCODE(31, o_soundPlaySwitch),
+ OPCODE(32, o_soundResumeBackground),
+ OPCODE(33, o_blitRect),
+ OPCODE(34, o_changeCard),
+ OPCODE(35, o_drawImageChangeCard),
+ OPCODE(36, o_changeMainCursor),
+ OPCODE(37, o_hideCursor),
+ OPCODE(38, o_showCursor),
+ OPCODE(39, o_delay),
+ OPCODE(40, o_changeStack),
+ OPCODE(41, o_changeCardPlaySoundDirectional),
+ OPCODE(42, o_directionalUpdatePlaySound),
+ OPCODE(43, o_saveMainCursor),
+ OPCODE(44, o_restoreMainCursor),
+ // TODO: Opcode 45 Not Present
+ OPCODE(46, o_soundWaitStop),
+ // TODO: Opcodes 47 to 99 Not Present
+
+ // "Stack-Specific" Opcodes
+ SPECIFIC_OPCODE(100, opcode_100),
+ SPECIFIC_OPCODE(101, opcode_101),
+ SPECIFIC_OPCODE(102, opcode_102),
+ SPECIFIC_OPCODE(103, opcode_103),
+ SPECIFIC_OPCODE(104, opcode_104),
+ SPECIFIC_OPCODE(105, opcode_105),
+ SPECIFIC_OPCODE(106, opcode_106),
+ SPECIFIC_OPCODE(107, opcode_107),
+ SPECIFIC_OPCODE(108, opcode_108),
+ SPECIFIC_OPCODE(109, opcode_109),
+ SPECIFIC_OPCODE(110, opcode_110),
+ SPECIFIC_OPCODE(111, opcode_111),
+ SPECIFIC_OPCODE(112, opcode_112),
+ SPECIFIC_OPCODE(113, opcode_113),
+ SPECIFIC_OPCODE(114, opcode_114),
+ SPECIFIC_OPCODE(115, opcode_115),
+ SPECIFIC_OPCODE(116, opcode_116),
+ SPECIFIC_OPCODE(117, opcode_117),
+ SPECIFIC_OPCODE(118, opcode_118),
+ SPECIFIC_OPCODE(119, opcode_119),
+ SPECIFIC_OPCODE(120, opcode_120),
+ SPECIFIC_OPCODE(121, opcode_121),
+ SPECIFIC_OPCODE(122, opcode_122),
+ SPECIFIC_OPCODE(123, opcode_123),
+ SPECIFIC_OPCODE(124, opcode_124),
+ SPECIFIC_OPCODE(125, opcode_125),
+ SPECIFIC_OPCODE(126, opcode_126),
+ SPECIFIC_OPCODE(127, opcode_127),
+ SPECIFIC_OPCODE(128, opcode_128),
+ SPECIFIC_OPCODE(129, opcode_129),
+ SPECIFIC_OPCODE(130, opcode_130),
+ SPECIFIC_OPCODE(131, opcode_131),
+ SPECIFIC_OPCODE(132, opcode_132),
+ SPECIFIC_OPCODE(133, opcode_133),
+ // TODO: Opcodes 134 to 146 Not Present
+ SPECIFIC_OPCODE(147, opcode_147),
+ // TODO: Opcodes 148 to 163 Not Present
+ SPECIFIC_OPCODE(164, opcode_164),
+ // TODO: Opcodes 165 to 168 Not Present
+ SPECIFIC_OPCODE(169, opcode_169),
+ // TODO: Opcodes 170 to 181 Not Present
+ SPECIFIC_OPCODE(182, opcode_182),
+ SPECIFIC_OPCODE(183, opcode_183),
+ SPECIFIC_OPCODE(184, opcode_184),
+ SPECIFIC_OPCODE(185, opcode_185),
+ // TODO: Opcodes 186 to 195 Not Present
+ SPECIFIC_OPCODE(196, opcode_196), // Demo only
+ SPECIFIC_OPCODE(197, opcode_197), // Demo only
+ SPECIFIC_OPCODE(198, opcode_198),
+ SPECIFIC_OPCODE(199, opcode_199),
+
+ // "Init" Opcodes
+ SPECIFIC_OPCODE(200, opcode_200),
+ SPECIFIC_OPCODE(201, opcode_201),
+ SPECIFIC_OPCODE(202, opcode_202),
+ SPECIFIC_OPCODE(203, opcode_203),
+ SPECIFIC_OPCODE(204, opcode_204),
+ SPECIFIC_OPCODE(205, opcode_205),
+ SPECIFIC_OPCODE(206, opcode_206),
+ SPECIFIC_OPCODE(207, opcode_207),
+ SPECIFIC_OPCODE(208, opcode_208),
+ SPECIFIC_OPCODE(209, opcode_209),
+ SPECIFIC_OPCODE(210, opcode_210),
+ SPECIFIC_OPCODE(211, opcode_211),
+ SPECIFIC_OPCODE(212, opcode_212),
+ SPECIFIC_OPCODE(213, opcode_213),
+ SPECIFIC_OPCODE(214, opcode_214),
+ SPECIFIC_OPCODE(215, opcode_215),
+ SPECIFIC_OPCODE(216, opcode_216),
+ SPECIFIC_OPCODE(217, opcode_217),
+ SPECIFIC_OPCODE(218, opcode_218),
+ SPECIFIC_OPCODE(219, opcode_219),
+ SPECIFIC_OPCODE(220, opcode_220),
+ SPECIFIC_OPCODE(221, opcode_221),
+ SPECIFIC_OPCODE(222, opcode_222),
+ // TODO: Opcodes 223 to 297 Not Present
+ SPECIFIC_OPCODE(298, opcode_298), // Demo only
+ SPECIFIC_OPCODE(299, opcode_299), // Demo only
+
+ // "Exit" Opcodes
+ SPECIFIC_OPCODE(300, opcode_300),
+ SPECIFIC_OPCODE(301, opcode_301),
+ SPECIFIC_OPCODE(302, opcode_302),
+ SPECIFIC_OPCODE(303, opcode_303),
+ SPECIFIC_OPCODE(304, opcode_304),
+ SPECIFIC_OPCODE(305, opcode_305),
+ SPECIFIC_OPCODE(306, opcode_306),
+ SPECIFIC_OPCODE(307, opcode_307),
+ SPECIFIC_OPCODE(308, opcode_308),
+ SPECIFIC_OPCODE(309, opcode_309),
+ // TODO: Opcodes 310 to 311 Not Present
+ SPECIFIC_OPCODE(312, opcode_312),
+ // TODO: Opcodes 313 and greater Not Present
+
+ OPCODE(0xFFFF, NOP)
+ };
+
+ _opcodes = myst_opcodes;
+ _opcodeCount = ARRAYSIZE(myst_opcodes);
+}
+
+void MystScriptParser_Myst::disablePersistentScripts() {
+ opcode_200_disable();
+ opcode_201_disable();
+ opcode_202_disable();
+ opcode_203_disable();
+ opcode_204_disable();
+ opcode_205_disable();
+ opcode_206_disable();
+ opcode_209_disable();
+ opcode_210_disable();
+ opcode_211_disable();
+ opcode_212_disable();
+}
+
+void MystScriptParser_Myst::runPersistentScripts() {
+ opcode_200_run();
+ opcode_201_run();
+ opcode_202_run();
+ opcode_203_run();
+ opcode_204_run();
+ opcode_205_run();
+ opcode_206_run();
+ opcode_209_run();
+ opcode_210_run();
+ opcode_211_run();
+ opcode_212_run();
+}
+
+void MystScriptParser_Myst::opcode_100(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ // Hard coded SoundId valid only for Intro Stack.
+ // Other stacks use Opcode 40, which takes SoundId values as arguments.
+ const uint16 soundIdLinkSrc = 5;
+
+ switch (_vm->getCurStack()) {
+ case kIntroStack:
+ debugC(kDebugScript, "Opcode %d: ChangeStack", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // TODO: Merge with changeStack (Opcode 40) Implementation?
+ if (_vm->_varStore->getVar(var) == 5 || _vm->_varStore->getVar(var) > 7) {
+ // TODO: Dead Book i.e. Released Sirrus/Achenar
+ } else {
+ // Play Linking Sound, blocking...
+ _vm->_sound->stopSound();
+ Audio::SoundHandle *handle = _vm->_sound->playSound(soundIdLinkSrc);
+ while (_vm->_mixer->isSoundHandleActive(*handle))
+ _vm->_system->delayMillis(10);
+
+ // Play Flyby Entry Movie on Masterpiece Edition. The Macintosh version is currently hooked
+ // up to the Cinepak versions of the video (the 'c' suffix) until the SVQ1 decoder is completed.
+ if ((_vm->getFeatures() & GF_ME)) {
+ switch (stack_map[_vm->_varStore->getVar(var)]) {
+ case kSeleniticStack:
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("FLY_SEc", kMasterpieceOnly));
+ else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("selenitic flyby", kMasterpieceOnly));
+ break;
+ case kStoneshipStack:
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("FLY_STc", kMasterpieceOnly));
+ else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("stoneship flyby", kMasterpieceOnly));
+ break;
+ // Myst Flyby Movie not used in Original Masterpiece Edition Engine
+ case kMystStack:
+ if (_vm->_tweaksEnabled) {
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("FLY_MYc", kMasterpieceOnly));
+ else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("myst flyby", kMasterpieceOnly));
+ }
+ break;
+ case kMechanicalStack:
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("FLY_MEc", kMasterpieceOnly));
+ else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("mech age flyby", kMasterpieceOnly));
+ break;
+ case kChannelwoodStack:
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("FLY_CHc", kMasterpieceOnly));
+ else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("channelwood flyby", kMasterpieceOnly));
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint16 varValue = _vm->_varStore->getVar(var);
+ _vm->changeToStack(stack_map[varValue]);
+ _vm->changeToCard(start_card[varValue], true);
+
+ // TODO: No soundIdLinkDst for Opcode 100 link? Check Original.
+ }
+ break;
+ case kStoneshipStack:
+ // Used for Cards 2185 (Water Pump)
+ varUnusedCheck(op, var);
+
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Unknown Function", op);
+
+ // TODO: Called when Water Pump Button is pressed? Animation?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDniStack:
+ // Used in Card 5022 (Rocks)
+ varUnusedCheck(op, var);
+
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Unknown Function", op);
+
+ // TODO: Fill in Logic.
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kCreditsStack:
+ case kMakingOfStack:
+ _vm->_system->quit();
+ break;
+ case kDemoSlidesStack:
+ // TODO: Change to changeStack call?
+ _vm->changeToStack(kDemoStack);
+ _vm->changeToCard(2001, true);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_101(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 0) {
+ // Used on Card 1191 (Maze Runner)
+ // Called when Red Warning Button is pushed
+
+ debugC(kDebugScript, "Opcode %d: Repeat Buzzer Sound?", op);
+
+ // TODO: Fill in logic...
+ // Repeat buzzer sound
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 6) {
+ // Used by Door Buttons to Brothers' Rooms
+ // Cards 2294, 2255
+ Common::Rect u0_rect = Common::Rect(argv[0], argv[1], argv[2], argv[3]);
+ uint16 u1 = argv[3];
+ uint16 u2 = argv[2];
+
+ debugC(kDebugScript, "Opcode %d: Unknown", op);
+ debugC(kDebugScript, "u0_rect.left: %d", u0_rect.left);
+ debugC(kDebugScript, "u0_rect.top: %d", u0_rect.top);
+ debugC(kDebugScript, "u0_rect.right: %d", u0_rect.right);
+ debugC(kDebugScript, "u0_rect.bottom: %d", u0_rect.bottom);
+ debugC(kDebugScript, "u1: %d", u1);
+ debugC(kDebugScript, "u2: %d", u2);
+
+ // TODO: Fill in logic...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ debugC(kDebugScript, "Opcode %d: Decrement Variable", op);
+ if (argc == 0) {
+ debugC(kDebugScript, "\tvar: %d", var);
+ uint16 varValue = _vm->_varStore->getVar(var);
+ // Logic to prevent decrement to negative
+ if (varValue != 0)
+ _vm->_varStore->setVar(var, varValue - 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 1) {
+ debugC(kDebugScript, "Opcode %d: Play Pipe Movie and Sound", op);
+
+ uint16 soundId = argv[0];
+ debugC(kDebugScript, "\tsoundId: %d", soundId);
+
+ _vm->_sound->playSound(soundId);
+
+ // TODO: Get Movie Location from Invoking Resource Rect, rather than
+ // hardcoded 267, 170 ?
+
+ // TODO: Need version of playMovie blocking which allows selection
+ // of start and finish points.
+ if (!_vm->_varStore->getVar(6)) {
+ // Play Pipe Extending i.e. 0 to 1/2 way through file
+ _vm->_video->playMovie(_vm->wrapMovieFilename("pipebrid", kChannelwoodStack), 267, 170);
+ } else {
+ // Play Pipe Retracting i.e. 1/2 way to end of file
+ _vm->_video->playMovie(_vm->wrapMovieFilename("pipebrid", kChannelwoodStack), 267, 170);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDniStack:
+ // Used in Card 5014 (Atrus)
+ // Hotspot Resource Used to hand Page to Atrus...
+ varUnusedCheck(op, var);
+ // TODO: Fill in Logic.
+ break;
+ case kDemoStack:
+ varUnusedCheck(op, var);
+
+ // Used on Card 2000, 2002 and 2003
+ // Triggered by Click
+ if (argc == 0) {
+ // TODO: Fill in Logic.. Fade in?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_102(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 2) {
+ debugC(kDebugScript, "Opcode %d: Play Book Room Movie", op);
+
+ uint16 startTime = argv[0];
+ uint16 endTime = argv[1];
+
+ debugC(kDebugScript, "\tstartTime: %d", startTime);
+ debugC(kDebugScript, "\tendTime: %d", endTime);
+
+ warning("TODO: Opcode %d Movie Time Index %d to %d", op, startTime, endTime);
+ // TODO: Need version of playMovie blocking which allows selection
+ // of start and finish points.
+ _vm->_video->playMovie(_vm->wrapMovieFilename("bkroom", kStoneshipStack), 159, 99);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Increment Variable", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // AFAIK no logic to put ceiling on increment at least in this opcode
+ _vm->_varStore->setVar(var, _vm->_varStore->getVar(var) + 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 2 || argc == 3) {
+ debugC(kDebugScript, "Opcode %d: Draw Full Screen Image, Optional Delay and Change Card", op);
+
+ uint16 imageId = argv[0];
+ uint16 cardId = argv[1];
+ uint16 delay = 0;
+
+ if (argc == 3)
+ delay = argv[2]; // TODO: Not sure about purpose of this parameter...
+
+ debugC(kDebugScript, "\timageId: %d", imageId);
+ debugC(kDebugScript, "\tcardId: %d", cardId);
+ debugC(kDebugScript, "\tdelay: %d", delay);
+
+ _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333));
+ _vm->_system->delayMillis(delay / 100);
+ _vm->changeToCard(cardId, true);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoStack:
+ varUnusedCheck(op, var);
+
+ // Used on Card 2002 and 2003
+ // Triggered by Click
+ if (argc == 0) {
+ // TODO: Fill in Logic.. Fade out?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_103(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 1) {
+ // Used on Card 2197 (Sirrus' Room Drawers)
+ debugC(kDebugScript, "Opcode %d: Unknown", op);
+
+ uint16 u0 = argv[0];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ // TODO: Fill in Logic...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used on Myst Card 4162 (Fireplace Grid)
+ if (argc == 1) {
+ debugC(kDebugScript, "Opcode %d: Toggle Variable with Bitmask", op);
+
+ uint16 bitmask = argv[0];
+ uint16 varValue = _vm->_varStore->getVar(var);
+
+ debugC(kDebugScript, "\tvar: %d", var);
+ debugC(kDebugScript, "\tbitmask: 0x%02X", bitmask);
+
+ if (varValue & bitmask)
+ _vm->_varStore->setVar(var, varValue & ~bitmask);
+ else
+ _vm->_varStore->setVar(var, varValue | bitmask);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_104(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 2004 (Achenar's Room Drawers)
+ // Used for Closeup of Torn Note?
+ if (argc == 1) {
+ debugC(kDebugScript, "Opcode %d: Unknown Function", op);
+
+ uint16 u0 = argv[0];
+ debugC(kDebugScript, "\tu0: %d", u0);
+
+ // TODO: Fill in Function...
+ // Does u0 correspond to a resource Id? Enable? Disable?
+ // Similar to Opcode 111 (Stoneship Version).. But does this also
+ // draw closeup image of note / change to closeup card?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ varUnusedCheck(op, var);
+
+ // Used on Myst Card 4162 and 4166 (Fireplace Puzzle Rotation Movies)
+ if (argc == 1) {
+ debugC(kDebugScript, "Opcode %d: Play Fireplace Puzzle Rotation Movies", op);
+
+ uint16 movieNum = argv[0];
+ debugC(kDebugScript, "\tmovieNum: %d", movieNum);
+
+ if (movieNum == 0)
+ _vm->_video->playMovie(_vm->wrapMovieFilename("fpin", kMystStack), 167, 5);
+ if (movieNum == 1)
+ _vm->_video->playMovie(_vm->wrapMovieFilename("fpout", kMystStack), 167, 5);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ varUnusedCheck(op, var);
+
+ // Used on Mechanical Card 6043 (Weapons Rack with Snake Box)
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Trigger Playing Of Snake Movie", op);
+
+ // TODO: Trigger Type 6 To Play Snake Movie.. Resource #3 on card.
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ varUnusedCheck(op, var);
+
+ // Used on Channelwood Card 3280
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Do Water Tank Valve Open Animation", op);
+ Common::Rect rect = _invokingResource->getRect();
+
+ // TODO: Need to load the image ids from Script Resources structure of VIEW
+ for (uint16 imageId = 3595; imageId <= 3601; imageId++) {
+ _vm->_gfx->copyImageToScreen(imageId, rect);
+ _vm->_system->delayMillis(50);
+ }
+
+ // TODO: Is 8 gotten from var7 of calling hotspot, rather than hardcoded?
+ _vm->_varStore->setVar(8, 1);
+ _vm->_varStore->setVar(19, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_105(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 1) {
+ uint16 soundId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Sound Receiver Water Button", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // TODO: Complete Function including Var Change?
+ _vm->_sound->playSound(soundId);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ if (argc == 1) {
+ varUnusedCheck(op, var);
+
+ uint16 soundId = argv[0];
+ uint16 boxValue = 0;
+ Audio::SoundHandle *handle;
+
+ debugC(kDebugScript, "Opcode %d: Ship Puzzle Logic", op);
+ debugC(kDebugScript, "\tsoundId: %d", soundId);
+
+ // Logic for Myst Ship Box Puzzle Solution
+ for (byte i = 0; i < 8; i++)
+ boxValue |= _vm->_varStore->getVar(i + 26) ? (1 << i) : 0;
+
+ uint16 var10 = _vm->_varStore->getVar(10);
+
+ if (boxValue == 0x32 && var10 == 0) {
+ handle = _vm->_sound->playSound(soundId);
+
+ while (_vm->_mixer->isSoundHandleActive(*handle))
+ _vm->_system->delayMillis(10);
+
+ _vm->_varStore->setVar(10, 1);
+ } else if (boxValue != 0x32 && var10 == 1) {
+ handle = _vm->_sound->playSound(soundId);
+
+ while (_vm->_mixer->isSoundHandleActive(*handle))
+ _vm->_system->delayMillis(10);
+
+ _vm->_varStore->setVar(10, 0);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Play Stairs Movement Movie", op);
+
+ if (_vm->_varStore->getVar(10)) {
+ // TODO: Play Movie from 0 to 1/2 way...
+ _vm->_video->playMovie(_vm->wrapMovieFilename("hhstairs", kMechanicalStack), 174, 222);
+ } else {
+ // TODO: Play Movie from 1/2 way to end...
+ _vm->_video->playMovie(_vm->wrapMovieFilename("hhstairs", kMechanicalStack), 174, 222);
+ }
+ }
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_106(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 1) {
+ uint16 soundId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Sound Receiver Volcanic Crack Button", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // TODO: Complete Function including Var Change?
+ _vm->_sound->playSound(soundId);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_107(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 1) {
+ uint16 soundId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Sound Receiver Clock Button", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // TODO: Complete Function including Var Change?
+ _vm->_sound->playSound(soundId);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_108(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 1) {
+ uint16 soundId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Sound Receiver Crystal Rocks Button", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // TODO: Complete Function including Var Change?
+ _vm->_sound->playSound(soundId);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_109(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 1) {
+ uint16 soundId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Sound Receiver Wind Button", op);
+ debugC(kDebugScript, "\tvar: %d", var);
+
+ // TODO: Complete Function including Var Change?
+ _vm->_sound->playSound(soundId);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ if (argc == 1) {
+ int16 signedValue = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Add Signed Value to Var", op);
+ debugC(kDebugScript, "\tVar: %d", var);
+ debugC(kDebugScript, "\tsignedValue: %d", signedValue);
+
+ _vm->_varStore->setVar(var, _vm->_varStore->getVar(var) + signedValue);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_110(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 15) {
+ // Used for Selenitic Maze Runner Exit Logic
+ uint16 CardIdEntry = argv[0];
+ uint16 CardIdExit = argv[1];
+ uint16 u0 = argv[2];
+ Common::Rect rect1 = Common::Rect(argv[3], argv[4], argv[5], argv[6]);
+ uint16 rect1UpdateDirection = argv[7];
+ uint16 u1 = argv[8];
+ Common::Rect rect2 = Common::Rect(argv[9], argv[10], argv[11], argv[12]);
+ uint16 rect2UpdateDirection = argv[13];
+ uint16 u2 = argv[14];
+
+ debugC(kDebugScript, "Opcode %d: Maze Runner Exit Logic and Door Open Animation", op);
+ debugC(kDebugScript, "\tExit Card: %d", CardIdEntry);
+ debugC(kDebugScript, "\tEntry Card: %d", CardIdExit);
+ debugC(kDebugScript, "\tu0 (Exit Var?): %d", u0);
+
+ debugC(kDebugScript, "\trect1.left: %d", rect1.left);
+ debugC(kDebugScript, "\trect1.top: %d", rect1.top);
+ debugC(kDebugScript, "\trect1.right: %d", rect1.right);
+ debugC(kDebugScript, "\trect1.bottom: %d", rect1.bottom);
+ debugC(kDebugScript, "\trect1 updateDirection: %d", rect1UpdateDirection);
+ debugC(kDebugScript, "\tu1: %d", u1);
+
+ debugC(kDebugScript, "\trect2.left: %d", rect2.left);
+ debugC(kDebugScript, "\trect2.top: %d", rect2.top);
+ debugC(kDebugScript, "\trect2.right: %d", rect2.right);
+ debugC(kDebugScript, "\trect2.bottom: %d", rect2.bottom);
+ debugC(kDebugScript, "\trect2 updateDirection: %d", rect2UpdateDirection);
+ debugC(kDebugScript, "\tu2: %d", u2);
+
+ // TODO: Finish Implementing Logic...
+ // HACK: Bypass Higher Logic for now...
+ _vm->changeToCard(argv[1], true);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_111(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ if (argc == 0) {
+ // Used on Card 1245 (Sound Receiver)
+ // Used by Source Selection Buttons...
+
+ debugC(kDebugScript, "Opcode %d: Unknown", op);
+ // TODO: Fill in Function...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ if (argc == 1) {
+ // Used for Card 2004 (Achenar's Room Drawers)
+ // Used by Drawers Hotspots...
+
+ debugC(kDebugScript, "Opcode %d: Unknown Function", op);
+
+ uint16 u0 = argv[0];
+ debugC(kDebugScript, "\tu0: %d", u0);
+
+ // TODO: Fill in Function...
+ // Does u0 correspond to a resource Id? Enable? Disable?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_112(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ // Used for Card 2013 (Achenar's Rose-Skull Hologram)
+ if (argc == 3) {
+ debugC(kDebugScript, "Opcode %d: Rose-Skull Hologram Playback", op);
+
+ uint16 varValue = _vm->_varStore->getVar(var);
+
+ debugC(kDebugScript, "\tVar: %d = %d", var, varValue);
+
+ uint16 startPoint = argv[0];
+ uint16 endPoint = argv[1];
+ uint16 u0 = argv[2];
+
+ debugC(kDebugScript, "\tstartPoint: %d", startPoint);
+ debugC(kDebugScript, "\tendPoint: %d", endPoint);
+ debugC(kDebugScript, "\tu0: %d", u0);
+
+ // TODO: Fill in Function...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_113(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used on Myst 4143 (Dock near Marker Switch)
+ if (argc == 9) {
+ uint16 soundId = argv[0];
+
+ uint16 u0 = argv[1];
+ uint16 u1 = argv[2];
+
+ Common::Rect rect = Common::Rect(argv[3], argv[4], argv[5], argv[6]);
+
+ uint16 updateDirection = argv[7];
+ uint16 u2 = argv[8];
+
+ debugC(kDebugScript, "Opcode %d: Vault Open Logic", op);
+ debugC(kDebugScript, "\tsoundId: %d", soundId);
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+
+ debugC(kDebugScript, "\trect.left: %d", rect.left);
+ debugC(kDebugScript, "\trect.top: %d", rect.top);
+ debugC(kDebugScript, "\trect.right: %d", rect.right);
+ debugC(kDebugScript, "\trect.bottom: %d", rect.bottom);
+ debugC(kDebugScript, "\trect updateDirection: %d", updateDirection);
+ debugC(kDebugScript, "\tu2: %d", u2);
+
+ if ((_vm->_varStore->getVar(2) == 1) &&
+ (_vm->_varStore->getVar(3) == 1) &&
+ (_vm->_varStore->getVar(4) == 0) &&
+ (_vm->_varStore->getVar(5) == 1) &&
+ (_vm->_varStore->getVar(6) == 1) &&
+ (_vm->_varStore->getVar(7) == 1) &&
+ (_vm->_varStore->getVar(8) == 1) &&
+ (_vm->_varStore->getVar(9) == 1)) {
+ // TODO: Implement correct function...
+ // Blit Image in Left to Right Vertical stripes i.e. transistion
+ // like door opening
+ _vm->_sound->playSound(soundId);
+ // TODO: Set 41 to 1 if page already present in hand.
+ _vm->_varStore->setVar(41, 2);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_114(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used on Myst 4143 (Dock near Marker Switch)
+ if (argc == 9) {
+ uint16 soundId = argv[0];
+
+ uint16 u0 = argv[1];
+ uint16 u1 = argv[2];
+
+ Common::Rect rect = Common::Rect(argv[3], argv[4], argv[5], argv[6]);
+
+ uint16 updateDirection = argv[7];
+ uint16 u2 = argv[8];
+
+ debugC(kDebugScript, "Opcode %d: Vault Close Logic", op);
+ debugC(kDebugScript, "\tsoundId: %d", soundId);
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+
+ debugC(kDebugScript, "\trect.left: %d", rect.left);
+ debugC(kDebugScript, "\trect.top: %d", rect.top);
+ debugC(kDebugScript, "\trect.right: %d", rect.right);
+ debugC(kDebugScript, "\trect.bottom: %d", rect.bottom);
+ debugC(kDebugScript, "\tupdateDirection: %d", updateDirection);
+ debugC(kDebugScript, "\tu2: %d", u2);
+
+ if ((_vm->_varStore->getVar(2) == 1) &&
+ (_vm->_varStore->getVar(3) == 1) &&
+ (_vm->_varStore->getVar(4) == 1) &&
+ (_vm->_varStore->getVar(5) == 1) &&
+ (_vm->_varStore->getVar(6) == 1) &&
+ (_vm->_varStore->getVar(7) == 1) &&
+ (_vm->_varStore->getVar(8) == 1) &&
+ (_vm->_varStore->getVar(9) == 1)) {
+ // TODO: Implement correct function...
+ // Blit Image in Right to Left Vertical stripes i.e. transistion
+ // like door closing
+ _vm->_sound->playSound(soundId);
+ _vm->_varStore->setVar(41, 0);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_115(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 11) {
+ // Used for Selenitic Card 1147 (Musical Door Lock Button)
+ uint16 imageIdClose = argv[0]; // TODO: Sound Id?
+ uint16 imageIdOpen = argv[1]; // TODO: Sound Id?
+
+ uint16 cardIdOpen = argv[2];
+
+ uint16 u0 = argv[3];
+ uint16 u1 = argv[4];
+
+ Common::Rect rect = Common::Rect(argv[5], argv[6], argv[7], argv[8]);
+
+ uint16 updateDirection = argv[9];
+ uint16 u2 = argv[10];
+
+ debugC(kDebugScript, "Music Door Lock Logic...");
+ debugC(kDebugScript, "\timageId (Close): %d", imageIdClose);
+ debugC(kDebugScript, "\timageId (Open): %d", imageIdOpen);
+ debugC(kDebugScript, "\tcardId (Open): %d", cardIdOpen);
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+
+ debugC(kDebugScript, "\trect.left: %d", rect.left);
+ debugC(kDebugScript, "\trect.top: %d", rect.top);
+ debugC(kDebugScript, "\trect.right: %d", rect.right);
+ debugC(kDebugScript, "\trect.bottom: %d", rect.bottom);
+ debugC(kDebugScript, "\trect updateDirection: %d", updateDirection);
+ debugC(kDebugScript, "\tu2: %d", u2);
+
+ // TODO: Fix Logic...
+ // HACK: Bypass Door Lock For Now
+ _vm->changeToCard(cardIdOpen, true);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ if (argc == 3) {
+ uint16 cardIdLose = argv[0];
+ uint16 cardIdBookCover = argv[1];
+ uint16 soundIdAddPage = argv[2];
+
+ debugC(kDebugScript, "Opcode %d: Red and Blue Book/Page Interaction", op);
+ debugC(kDebugScript, "Var: %d", var);
+ debugC(kDebugScript, "Card Id (Lose): %d", cardIdLose);
+ debugC(kDebugScript, "Card Id (Book Cover): %d", cardIdBookCover);
+ debugC(kDebugScript, "SoundId (Add Page): %d", soundIdAddPage);
+
+ // TODO: if holding page for this book, play SoundIdAddPage
+ if (false) { // TODO: Should be access to mainCursor...
+ _vm->_sound->playSound(soundIdAddPage);
+ // TODO: Code for updating variables based on adding page
+ }
+
+ // TODO: Add Tweak to improve original logic by denying
+ // lose until all red / blue pages collected, rather
+ // than allowing shortcut based on 1 fireplace page?
+
+ // If holding last page for this book i.e. var 24/25
+ // Then trigger Trapped in Book Losing Ending
+ if ((var == 100 && !_vm->_varStore->getVar(25)) ||
+ (var == 101 && !_vm->_varStore->getVar(24))) {
+ // TODO: Clear mainCursor back to nominal..
+ _vm->changeToCard(cardIdLose, true);
+ } else
+ _vm->changeToCard(cardIdBookCover, true);
+
+ // TODO: Is this logic here?
+ // i.e. If was holding page, wait then auto open and play book...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ varUnusedCheck(op, var);
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_116(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 1) {
+ // Used on Card 2111 (Compass Rose)
+ // Called when Button Clicked.
+ uint16 correctButton = argv[0];
+
+ if (correctButton) {
+ // Correct Button -> Light On Logic
+ // TODO: Deal with if main power on?
+ _vm->_varStore->setVar(16, 1);
+ _vm->_varStore->setVar(30, 0);
+ } else {
+ // Wrong Button -> Power Failure Logic
+ // TODO: Fill in Alarm
+ _vm->_varStore->setVar(16, 0);
+ _vm->_varStore->setVar(30, 2);
+ _vm->_varStore->setVar(33, 0);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ if (argc == 1) {
+ // Used on Card 4006 (Clock Tower Time Controls)
+ uint16 soundId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Clock Tower Bridge Puzzle Execute Button", op);
+
+ uint16 bridgeState = _vm->_varStore->getVar(12);
+ uint16 currentTime = _vm->_varStore->getVar(43);
+
+ const uint16 correctTime = 32; // 2:40 i.e. From 12 Noon in 5 min increments
+
+ if (!bridgeState && currentTime == correctTime) {
+ _vm->_sound->playSound(soundId);
+
+ // TODO: Play only 1st half of movie i.e. gears rise up
+ _vm->_video->playMovie(_vm->wrapMovieFilename("gears", kMystStack), 305, 36);
+
+ bridgeState = 1;
+ _vm->_varStore->setVar(12, bridgeState);
+ } else if (bridgeState && currentTime != correctTime) {
+ _vm->_sound->playSound(soundId);
+
+ // TODO: Play only 2nd half of movie i.e. gears sink down
+ _vm->_video->playMovie(_vm->wrapMovieFilename("gears", kMystStack), 305, 36);
+
+ bridgeState = 0;
+ _vm->_varStore->setVar(12, bridgeState);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_117(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 0) {
+ // Used on Card 2132 (Chest at Bottom of Lighthouse)
+ // Called when Valve Hotspot Clicked.
+ // TODO: Fill in Function to play right section of movie
+ // based on valve state and water in chest..
+ _vm->_video->playMovie(_vm->wrapMovieFilename("ligspig", kStoneshipStack), 97, 267);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ if (argc == 2) {
+ // Used by Myst Imager Control Button
+ uint16 varValue = _vm->_varStore->getVar(var);
+
+ if (varValue)
+ _vm->_sound->playSound(argv[1]);
+ else
+ _vm->_sound->playSound(argv[0]);
+
+ _vm->_varStore->setVar(var, !varValue);
+ // TODO: Change Var 45 "Dock Forechamber Imager Water Effect Enabled" here?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 1) {
+ // Used on Card 3012 (Temple Hologram Monitor)
+ uint16 button = argv[0]; // 0 to 3
+ _vm->_varStore->setVar(17, button);
+ switch (button) {
+ case 0:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("monalgh", kChannelwoodStack), 227, 71);
+ break;
+ case 1:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("monamth", kChannelwoodStack), 227, 71);
+ break;
+ case 2:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("monasirs", kChannelwoodStack), 227, 71);
+ break;
+ case 3:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("monsmsg", kChannelwoodStack), 227, 71);
+ break;
+ default:
+ warning("Opcode %d Control Variable Out of Range", op);
+ break;
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_118(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ if (argc == 0) {
+ // Used on Card 2126 (Lighthouse Looking Along Plank)
+ // Called when Exit Resource is clicked
+
+ // TODO: Implement Function...
+ // If holding Key to Lamp Room Trapdoor, drop to bottom of
+ // Lighthouse...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 5) {
+ // Used by Card 4709 (Myst Imager Control Panel Red Button)
+
+ debugC(kDebugScript, "Opcode %d: Imager Change Value", op);
+
+ uint16 soundIdBeepLo = argv[0];
+ uint16 soundIdBeepHi = argv[1];
+ uint16 soundIdBwapp = argv[2];
+ uint16 soundIdBeepTune = argv[3]; // 5 tones..
+ uint16 soundIdPanelSlam = argv[4];
+
+ debugC(kDebugScript, "\tsoundIdBeepLo: %d", soundIdBeepLo);
+ debugC(kDebugScript, "\tsoundIdBeepHi: %d", soundIdBeepHi);
+ debugC(kDebugScript, "\tsoundIdBwapp: %d", soundIdBwapp);
+ debugC(kDebugScript, "\tsoundIdBeepTune: %d", soundIdBeepTune);
+ debugC(kDebugScript, "\tsoundIdPanelSlam: %d", soundIdPanelSlam);
+
+ _vm->_sound->playSound(soundIdBeepLo);
+
+ // TODO: Complete Logic...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 0) {
+ // Used on Card 3318 (Sirrus' Room Nightstand Drawer)
+ // Triggered when clicked on drawer
+ // TODO: Implement function...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_119(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ if (argc == 0) {
+ // Used on Card 2143 (Lighthouse Trapdoor)
+ // Called when Lock Hotspot Clicked while holding key.
+ _vm->_video->playMovie(_vm->wrapMovieFilename("openloc", kStoneshipStack), 187, 72);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ if (argc == 1) {
+ // Used on Card 4383 and 4451 (Tower Elevator)
+ switch (argv[0]) {
+ case 0:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("libdown", kMystStack), 216, 78);
+ break;
+ case 1:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("libup", kMystStack), 214, 75);
+ break;
+ default:
+ break;
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ if (argc == 0) {
+ // Used on Card 3333 (Temple Hologram)
+ // TODO: Not 100% sure about movie position...
+ switch (_vm->_varStore->getVar(17)) {
+ case 0:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("holoalgh", kChannelwoodStack), 126, 74);
+ break;
+ case 1:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("holoamth", kChannelwoodStack), 126, 74);
+ break;
+ case 2:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("holoasir", kChannelwoodStack), 126, 74);
+ break;
+ case 3:
+ _vm->_video->playMovie(_vm->wrapMovieFilename("holosmsg", kChannelwoodStack), 126, 74);
+ break;
+ default:
+ warning("Opcode %d Control Variable Out of Range", op);
+ break;
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_120(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ MystResource *_top;
+
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ if (argc == 1) {
+ // Used for Cards 2285, 2289, 2247, 2251 (Side Doors in Tunnels Down To Brothers Rooms)
+ uint16 movieId = argv[0];
+
+ debugC(kDebugScript, "Opcode %d: Play Side Door Movies", op);
+ debugC(kDebugScript, "\tmovieId: %d", movieId);
+
+ switch (movieId) {
+ case 0:
+ // Card 2251
+ _vm->_video->playMovie(_vm->wrapMovieFilename("tunaup", kStoneshipStack), 149, 161);
+ break;
+ case 1:
+ // Card 2247
+ _vm->_video->playMovie(_vm->wrapMovieFilename("tunadown", kStoneshipStack), 218, 150);
+ break;
+ case 2:
+ // Card 2289
+ _vm->_video->playMovie(_vm->wrapMovieFilename("tuncup", kStoneshipStack), 259, 161);
+ break;
+ case 3:
+ // Card 2285
+ _vm->_video->playMovie(_vm->wrapMovieFilename("tuncdown", kStoneshipStack), 166, 150);
+ break;
+ default:
+ warning("Opcode 120 MovieId Out Of Range");
+ break;
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Card 4297 (Generator Puzzle Buttons)
+ debugC(kDebugScript, "Opcode %d: Toggle Var8 of Invoking Resource", op);
+ _top = _invokingResource;
+
+ while(_top->_parent != NULL)
+ _top = _top->_parent;
+
+ if (argc == 0) {
+ uint16 var8 = _top->getType8Var();
+ if (var8 != 0xFFFF)
+ _vm->_varStore->setVar(var8, !_vm->_varStore->getVar(var8));
+ else
+ warning("Opcode 120: No invoking Resource Var 8 found");
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_121(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used on Card 4100 (Cabin Safe Buttons)
+ // Correct Solution (724) -> Var 67=2, 68=7, 69=5
+ // Jump to Card 4103 when solution correct and handle pulled...
+ if (argc == 0) {
+ uint16 varValue = _vm->_varStore->getVar(var);
+ if (varValue == 0)
+ varValue = 9;
+ else
+ varValue--;
+ _vm->_varStore->setVar(var, varValue);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ varUnusedCheck(op, var);
+
+ if (argc == 2) {
+ uint16 startTime = argv[0];
+ uint16 endTime = argv[1];
+
+ warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, startTime, endTime);
+ // TODO: Need version of playMovie blocking which allows selection
+ // of start and finish points.
+ _vm->_video->playMovie(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ varUnusedCheck(op, var);
+
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_122(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kChannelwoodStack:
+ // Used on Channelwood Card 3280
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Do Water Tank Valve Close Animation", op);
+ Common::Rect rect = _invokingResource->getRect();
+
+ // TODO: Need to load the image ids from Script Resources structure of VIEW
+ for (uint16 imageId = 3601; imageId >= 3595; imageId--) {
+ _vm->_gfx->copyImageToScreen(imageId, rect);
+ _vm->_system->delayMillis(50);
+ }
+
+ // TODO: Is 8 gotten from var7 of calling hotspot, rather than hard-coded?
+ _vm->_varStore->setVar(8, 0);
+ _vm->_varStore->setVar(19, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used on Card 6120 (Elevator)
+ // Called when Exit Midde Button Pressed
+
+ // TODO: hcelev? Movie of Elevator?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_123(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 2) {
+ // Used on Card 6154
+ uint16 start_time = argv[0];
+ uint16 end_time = argv[1];
+
+ warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, start_time, end_time);
+ // TODO: Need version of playMovie blocking which allows selection
+ // of start and finish points.
+ // TODO: Not 100% sure about movie position
+ _vm->_video->playMovie(_vm->wrapMovieFilename("hcelev", kMechanicalStack), 205, 40);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_124(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used by Card 6156 (Fortress Rotation Controls)
+ // Called when Red Exit Button Pressed to raise Elevator
+
+ // TODO: Fill in Code...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_125(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ if (argc == 1) {
+ // Used on Card 2197 (Sirrus' Room Drawers)
+ debugC(kDebugScript, "Opcode %d: Unknown uses Var %d", op, var);
+
+ uint16 u0 = argv[0];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ // TODO: Fill in Logic...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used on Card 6267 (Code Lock)
+ // Called by Red Execute Button...
+ debugC(kDebugScript, "Opcode %d: Code Lock Execute...", op);
+
+ // TODO: Fill in Logic For Code Lock...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_126(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used by Card 6120 (Fortress Elevator)
+ // Called when Red Exit Button Pressed to raise Elevator and
+ // exit is clicked...
+
+ // TODO: Fill in Code...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_127(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kChannelwoodStack:
+ if (argc == 2) {
+ // Used by Card 3262 (Elevator)
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+
+ uint16 u0 = argv[0];
+ uint16 u1 = argv[1];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+
+ // TODO: Fill in Code...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used for Mech Card 6226 (3 Crystals)
+ _vm->_varStore->setVar(20, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_128(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used for Mech Card 6226 (3 Crystals)
+ _vm->_varStore->setVar(20, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_129(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kChannelwoodStack:
+ if (argc == 1) {
+ // Used by Card 3262 (Elevator)
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+
+ uint16 cardId = argv[0];
+
+ debugC(kDebugScript, "\tcardId: %d", cardId);
+
+ // TODO: Fill in Code...
+ _vm->changeToCard(cardId, true);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used for Mech Card 6226 (3 Crystals)
+ _vm->_varStore->setVar(21, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_130(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used for Mech Card 6226 (3 Crystals)
+ _vm->_varStore->setVar(21, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_131(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used for Mech Card 6226 (3 Crystals)
+ _vm->_varStore->setVar(22, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_132(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMechanicalStack:
+ if (argc == 0) {
+ // Used for Mech Card 6226 (3 Crystals)
+ _vm->_varStore->setVar(22, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_133(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used on Card 4500 (Stellar Observatory Controls)
+ if (argc == 1) {
+ // Called by Telescope Slew Button
+ uint16 soundId = argv[0];
+
+ // TODO: Function to change variables controlling telescope view
+ // etc.
+
+ // TODO: Sound seems to be stuck looping?
+ _vm->_sound->playSound(soundId);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_147(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ // TODO: Extra Logic to do this in INIT process watching cursor and var 98?
+ _vm->_varStore->setVar(98, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_164(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used on Card 4530 (Rocketship Music Slider Controls)
+ // TODO: Finish Implementation...
+ // Var 105 is used to set between 0 to 2 = No Function, Movie Playback and Linkable...
+ // This is called when Var 105 = 1 i.e. this plays back Movie...
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_169(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used on Card 4099 (In Cabin, Looking Out Door)
+ // TODO: Finish Implementation...
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_181(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ // TODO: Logic for lighting the match
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_182(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ // TODO: Logic for lighting the match
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_183(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ // Used for Myst Cards 4257, 4260, 4263, 4266, 4269, 4272, 4275 and 4278 (Ship Puzzle Boxes)
+ _vm->_varStore->setVar(105, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_184(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ // Used for Myst Cards 4257, 4260, 4263, 4266, 4269, 4272, 4275 and 4278 (Ship Puzzle Boxes)
+ _vm->_varStore->setVar(105, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_185(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ // Used for Myst Card 4098 (Cabin Boiler Pilot Light)
+ // TODO: Extra Logic to do this in INIT process watching cursor and var 98?
+ _vm->_varStore->setVar(98, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_196(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ // Used on Card ...
+ // TODO: Finish Implementation...
+ // Voice Over and Card Advance?
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_197(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ // Used on Card ...
+ // TODO: Finish Implementation...
+ // Voice Over and Card Advance?
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+// TODO: Merge with Opcode 42?
+void MystScriptParser_Myst::opcode_198(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ if (argc == 0) {
+ // Nuh-uh! No leaving the library in the demo!
+ GUI::MessageDialog dialog("You can't leave the library in the demo.");
+ dialog.runModal();
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used on Card 4143 (Dock near Marker Switch, facing Cogs)
+ if (argc == 9) {
+ uint16 soundId = argv[0];
+ uint16 u0 = argv[1];
+ uint16 u1 = argv[2];
+ Common::Rect rect = Common::Rect(argv[3], argv[4], argv[5], argv[6]);
+ uint16 updateDirection = argv[7];
+ uint16 u2 = argv[8];
+
+ debugC(kDebugScript, "Opcode %d: Close Dock Marker Switch Vault", op);
+ debugC(kDebugScript, "\tsoundId: %d", soundId);
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+
+ debugC(kDebugScript, "\trect.left: %d", rect.left);
+ debugC(kDebugScript, "\trect.top: %d", rect.top);
+ debugC(kDebugScript, "\trect.right: %d", rect.right);
+ debugC(kDebugScript, "\trect.bottom: %d", rect.bottom);
+ debugC(kDebugScript, "\tupdateDirection: %d", updateDirection);
+ debugC(kDebugScript, "\tu2: %d", u2);
+
+ Audio::SoundHandle *handle;
+ if (_vm->_varStore->getVar(41) != 0) {
+ handle = _vm->_sound->playSound(soundId);
+
+ while (_vm->_mixer->isSoundHandleActive(*handle))
+ _vm->_system->delayMillis(10);
+ // TODO: Do Image Blit
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_199(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Myst Imager Control Execute Button Logic", op);
+
+ uint16 numericSelection = (_vm->_varStore->getVar(36) + 1) % 10;
+ numericSelection += ((_vm->_varStore->getVar(35) + 1) % 10) * 10;
+
+ debugC(kDebugScript, "\tImager Selection: %d", numericSelection);
+
+ switch (numericSelection) {
+ case 40:
+ _vm->_varStore->setVar(51, 1); // Mountain
+ break;
+ case 67:
+ _vm->_varStore->setVar(51, 2); // Water
+ break;
+ case 47:
+ _vm->_varStore->setVar(51, 4); // Marker Switch
+ break;
+ case 8:
+ _vm->_varStore->setVar(51, 3); // Atrus
+ break;
+ default:
+ _vm->_varStore->setVar(51, 0); // Blank
+ break;
+ }
+
+ // TODO: Fill in Logic
+ //{ 34, 2, "Dock Forechamber Imager State" }, // 0 to 2 = Off, Mountain, Water
+ //{ 310, 0, "Dock Forechamber Imager Control Temp Value?" }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ // Used on Card ...
+ // TODO: Finish Implementation...
+ // Voice Over and Card Advance?
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+// Selenitic Stack Movies For Maze Runner (Card 1191)
+static const char* kHCMovPathSelenitic[36] = {
+ "backa1",
+ "backe1",
+ "backf0",
+ "backf1",
+ "backl0",
+ "backl1",
+ "backo0",
+ "backo1",
+ "backp0",
+ "backp1",
+ "backr0",
+ "backr1",
+ "backs0",
+ "backs1",
+ "forwa1",
+ "forwe0",
+ "forwf0",
+ "forwf1",
+ "forwl0",
+ "forwl1",
+ "forwo0",
+ "forwo1",
+ "forwp0",
+ "forwp1",
+ "forwr0",
+ "forwr1",
+ "forws0",
+ "forws1",
+ "left00",
+ "left01",
+ "left10",
+ "left11",
+ "right00",
+ "right01",
+ "right10",
+ "right11"
+};
+
+static struct {
+ bool enabled;
+
+ uint16 var;
+ uint16 imageCount;
+ uint16 imageBaseId;
+ uint16 soundDecrement;
+ uint16 soundIncrement;
+
+ // Myst Demo slideshow variables
+ uint16 cardId;
+ uint32 lastCardTime;
+} g_opcode200Parameters;
+
+void MystScriptParser_Myst::opcode_200_run() {
+ static uint16 lastImageIndex = 0;
+ uint16 curImageIndex;
+ Common::Rect rect;
+
+ if (g_opcode200Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kIntroStack: // Used on Card 1
+ case kDemoStack: // Used on Card 2000
+ // TODO : Implement function here to play though intro movies and change card?
+ break;
+ case kSeleniticStack:
+ // Used on Card 1191 (Maze Runner)
+
+ // TODO: Implementation Movie Function..
+ if (false) {
+ _vm->_video->playMovie(_vm->wrapMovieFilename(kHCMovPathSelenitic[0], kSeleniticStack), 201, 26);
+ }
+ break;
+ case kStoneshipStack:
+ // Used for Card 2013 (Achenar's Rose-Skull Hologram)
+
+ // TODO: Implement Function...
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ curImageIndex = _vm->_varStore->getVar(g_opcode200Parameters.var);
+
+ if (curImageIndex >= g_opcode200Parameters.imageCount) {
+ curImageIndex = g_opcode200Parameters.imageCount - 1;
+ _vm->_varStore->setVar(g_opcode200Parameters.var, curImageIndex);
+ }
+
+ // HACK: Think these images are centered on screen (when smaller than full screen),
+ // and since no _gfx call for image size, hack this to deal with this case for now...
+ if (_vm->getCurCard() == 4059)
+ rect = Common::Rect(157, 115, 544, 333);
+ else
+ rect = Common::Rect(0, 0, 544, 333);
+
+ if (curImageIndex != lastImageIndex)
+ _vm->_gfx->copyImageToScreen(g_opcode200Parameters.imageBaseId + curImageIndex, rect);
+
+ // TODO: Comparison with original engine shows that this simple solution
+ // may not be the correct one and the choice of which sound
+ // may be more complicated or even random..
+ if (curImageIndex < lastImageIndex && g_opcode200Parameters.soundDecrement != 0)
+ _vm->_sound->playSound(g_opcode200Parameters.soundDecrement);
+ else if (curImageIndex > lastImageIndex && g_opcode200Parameters.soundIncrement != 0)
+ _vm->_sound->playSound(g_opcode200Parameters.soundIncrement);
+
+ lastImageIndex = curImageIndex;
+ break;
+ case kCreditsStack:
+ curImageIndex = _vm->_varStore->getVar(g_opcode200Parameters.var);
+
+ if (_vm->_system->getMillis() - g_opcode200Parameters.lastCardTime >= 7 * 1000) {
+ // After the 6th image has shown, it's time to quit
+ if (curImageIndex == 7)
+ _vm->_system->quit();
+
+ // Note: The modulus by 6 is because the 6th image is the one at imageBaseId
+ _vm->_gfx->copyImageToScreen(g_opcode200Parameters.imageBaseId + curImageIndex % 6, Common::Rect(0, 0, 544, 333));
+
+ _vm->_varStore->setVar(g_opcode200Parameters.var, curImageIndex + 1);
+ g_opcode200Parameters.lastCardTime = _vm->_system->getMillis();
+ }
+ break;
+ case kMechanicalStack:
+ // Used on Card 6238 (Sirrus' Throne) and Card 6027 (Achenar's Throne)
+ // g_opcode200Parameters.var == 0 for Achenar
+ // g_opcode200Parameters.var == 1 for Sirrus
+
+ // TODO: Fill in Function...
+ // Variable indicates that this is related to Secret Panel State
+ break;
+ case kDemoSlidesStack:
+ // Used on Cards...
+ if (_vm->_system->getMillis() - g_opcode200Parameters.lastCardTime >= 2 * 1000)
+ _vm->changeToCard(g_opcode200Parameters.cardId, true);
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_200_disable() {
+ g_opcode200Parameters.enabled = false;
+ g_opcode200Parameters.var = 0;
+ g_opcode200Parameters.imageCount = 0;
+ g_opcode200Parameters.imageBaseId = 0;
+ g_opcode200Parameters.soundDecrement = 0;
+ g_opcode200Parameters.soundIncrement = 0;
+}
+
+void MystScriptParser_Myst::opcode_200(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kIntroStack: // Used on Card 1
+ case kDemoStack: // Used on Card 2000
+ varUnusedCheck(op, var);
+
+ // TODO : Clicking during the intro movies does not stop them and change to Card 5.
+ // This is due to the movies playing blocking, but making them non-blocking causes
+ // the card change here to prevent them playing. Need to move the following to the
+ // opcode_200_run process and wait for all movies to finish playing before the card
+ // change is performed.
+
+ // Play Intro Movies..
+ if ((_vm->getFeatures() & GF_ME) && _vm->getPlatform() == Common::kPlatformMacintosh) {
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("mattel", kIntroStack));
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("presto", kIntroStack));
+ } else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("broder", kIntroStack));
+
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("cyanlogo", kIntroStack));
+
+ if (!(_vm->getFeatures() & GF_DEMO)) { // The demo doesn't have the intro video
+ if ((_vm->getFeatures() & GF_ME) && _vm->getPlatform() == Common::kPlatformMacintosh)
+ // intro.mov uses Sorenson, introc uses Cinepak. Otherwise, they're the same.
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("introc", kIntroStack));
+ else
+ _vm->_video->playMovieCentered(_vm->wrapMovieFilename("intro", kIntroStack));
+ }
+
+ _vm->changeToCard(_vm->getCurCard()+1, true);
+ break;
+ case kSeleniticStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 1191 (Maze Runner)
+ if (argc == 0) {
+ g_opcode200Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 2013 (Achenar's Rose-Skull Hologram)
+ if (argc == 0) {
+ g_opcode200Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ if (argc == 4) {
+ g_opcode200Parameters.var = var;
+ g_opcode200Parameters.imageCount = argv[0];
+ g_opcode200Parameters.imageBaseId = argv[1];
+ g_opcode200Parameters.soundDecrement = argv[2];
+ g_opcode200Parameters.soundIncrement = argv[3];
+ g_opcode200Parameters.enabled = true;
+
+ _vm->_varStore->setVar(var, 0);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ // Used on Card 6238 (Sirrus' Throne) and Card 6027 (Achenar's Throne)
+ if (argc == 0) {
+ g_opcode200Parameters.var = var;
+ g_opcode200Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDniStack:
+ varUnusedCheck(op, var);
+ // Used on Card 5014
+
+ // TODO: Logic for Atrus Reactions and Movies
+ if (false) {
+ // Var 0 used for Atrus Gone (from across room) 0 = Present, 1 = Not Present
+ // Var 1 used for Myst Book Status 0 = Not Usuable
+ // 1 = Openable, but not linkable (Atrus Gone?)
+ // 2 = Linkable
+ // Var 2 used for Music Type 0 to 2..
+ // Var 106 used for Atrus Static Image State 0 = Initial State
+ // 1 = Holding Out Hand for Page
+ // 2 = Gone, Book Open
+ // 3 = Back #1
+ // 4 = Back #2
+ _vm->_video->playMovie(_vm->wrapMovieFilename("atr1nopg", kDniStack), 215, 77);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("atr1page", kDniStack), 215, 77);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("atrus2", kDniStack), 215, 77);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("atrwrite", kDniStack), 215, 77);
+ }
+ break;
+ case kCreditsStack:
+ if (argc == 0) {
+ g_opcode200Parameters.var = var;
+ // TODO: Pass ImageCount, rather than hardcoded in run process?
+ g_opcode200Parameters.imageBaseId = _vm->getCurCard();
+ g_opcode200Parameters.lastCardTime = _vm->_system->getMillis();
+ g_opcode200Parameters.enabled = true;
+
+ _vm->_varStore->setVar(var, 1);
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoSlidesStack:
+ // Used on Cards...
+ if (argc == 1) {
+ g_opcode200Parameters.cardId = argv[0];
+ g_opcode200Parameters.lastCardTime = _vm->_system->getMillis();
+ g_opcode200Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ uint16 u0;
+ uint16 u1;
+ uint16 u2;
+
+ uint16 lastVar105;
+ uint16 soundId;
+
+ bool enabled;
+} g_opcode201Parameters;
+
+void MystScriptParser_Myst::opcode_201_run() {
+ uint16 var105;
+
+ if (g_opcode201Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+
+ // TODO: Fill in Function...
+ break;
+ case kStoneshipStack:
+ // Used for Card 2013 (Achenar's Rose-Skull Hologram)
+
+ // TODO: Fill in Function...
+ break;
+ case kMystStack:
+ var105 = _vm->_varStore->getVar(105);
+ if (var105 && !g_opcode201Parameters.lastVar105)
+ _vm->_sound->playSound(g_opcode201Parameters.soundId);
+ g_opcode201Parameters.lastVar105 = var105;
+ break;
+ case kMechanicalStack:
+ // Used for Card 6159 (Facing Corridor to Fortress Elevator)
+
+ // g_opcode201Parameters.u0
+ // g_opcode201Parameters.u1
+ // g_opcode201Parameters.u2
+
+ // TODO: Fill in Function...
+ break;
+ case kDemoStack:
+ // Used on Card 2001, 2002 and 2003
+
+ // TODO: Fill in Function...
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_201_disable() {
+ g_opcode201Parameters.enabled = false;
+ g_opcode201Parameters.soundId = 0;
+ g_opcode201Parameters.lastVar105 = 0;
+}
+
+void MystScriptParser_Myst::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kIntroStack:
+ _vm->_system->delayMillis(4 * 1000);
+ _vm->_gfx->copyImageToScreen(4, Common::Rect(0, 0, 544, 333));
+ // TODO : Wait until video ends, then change to card 5
+ break;
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+
+ if (argc == 0) {
+ g_opcode201Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 2013 (Achenar's Rose-Skull Hologram)
+ if (argc == 0) {
+ g_opcode201Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Cards 4257, 4260, 4263, 4266, 4269, 4272, 4275 and 4278 (Ship Puzzle Boxes)
+ if (argc == 1) {
+ g_opcode201Parameters.soundId = argv[0];
+ g_opcode201Parameters.lastVar105 = 0;
+ g_opcode201Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ // Used for Card 6159 (Facing Corridor to Fortress Elevator)
+ if (argc == 3) {
+ g_opcode201Parameters.u0 = argv[0];
+ g_opcode201Parameters.u1 = argv[1];
+ g_opcode201Parameters.u2 = argv[2];
+
+ g_opcode201Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ // Used for Card 3247 (Elevator #1 Movement), 3161 (Bridge Movement), 3259 (Elevator #3 Movement) and 3252 (Elevator #2 Movement)
+ if (argc == 0) {
+ // TODO: Fill in Function. Video Playback? Rect from invoking hotspot resource...
+ if (false) {
+ // Card 3161
+ _vm->_video->playMovie(_vm->wrapMovieFilename("bridge", kChannelwoodStack), 292, 204);
+
+ // Card 3247
+ _vm->_video->playMovie(_vm->wrapMovieFilename("welev1dn", kChannelwoodStack), 214, 107);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("welev1up", kChannelwoodStack), 214, 107);
+
+ // Card 3252
+ _vm->_video->playMovie(_vm->wrapMovieFilename("welev2dn", kChannelwoodStack), 215, 118);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("welev2up", kChannelwoodStack), 215, 118);
+
+ // Card 3259
+ _vm->_video->playMovie(_vm->wrapMovieFilename("welev3dn", kChannelwoodStack), 213, 99);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("welev3up", kChannelwoodStack), 213, 99);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoStack:
+ // Used on Card 2001, 2002 and 2003
+ if (argc == 0) {
+ g_opcode201Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ bool enabled;
+ uint16 var;
+} g_opcode202Parameters;
+
+void MystScriptParser_Myst::opcode_202_run(void) {
+ if (g_opcode202Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+
+ // TODO: Fill in function...
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used for Card 4378 (Library Tower Rotation Map)
+ // TODO: Fill in.. Code for Tower Rotation Angle etc..
+ // Var 0, 3, 4, 5, 6, 7, 8, 9 used for Type 8 Image Display
+ // Type 11 Hotspot for control..
+ // Var 304 controls presence of Myst Library Image
+ break;
+ case kMechanicalStack:
+ // Used for Card 6220 (Sirrus' Mechanical Bird)
+ // TODO: Fill in Function
+ break;
+ case kChannelwoodStack:
+ // Used for Cards 3328, 3691, 3731, 3809, 3846 etc. (Water Valves)
+
+ // Code for Water Flow Logic
+ // Var 8 = "Water Tank Valve State"
+ // Controls
+ // Var 19 = "Water Flowing to First Water Valve"
+ // Code for this in Opcode 104 / 122
+
+ // Var 19 = "Water Flowing to First Water Valve"
+ // and
+ // Var 9 = "First Water Valve State"
+ // Controls
+ // Var 20 = "Water Flowing to Second (L) Water Valve"
+ // Var 3 = "Water Flowing (R) to Pump for Upper Walkway to Temple Elevator"
+ uint16 var9 = _vm->_varStore->getVar(9);
+ if (_vm->_varStore->getVar(19)) {
+ _vm->_varStore->setVar(20, !var9);
+ _vm->_varStore->setVar(3, var9);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(20, 0);
+ _vm->_varStore->setVar(3, 0);
+ }
+
+ // Var 20 = "Water Flowing to Second (L) Water Valve"
+ // and
+ // Var 10 = "Second (L) Water Valve State"
+ // Controls
+ // Var 24 = "Water Flowing to Third (L, L) Water Valve"
+ // Var 21 = "Water Flowing to Third (L, R) Water Valve"
+ uint16 var10 = _vm->_varStore->getVar(10);
+ if (_vm->_varStore->getVar(20)) {
+ _vm->_varStore->setVar(24, !var10);
+ _vm->_varStore->setVar(21, var10);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(24, 0);
+ _vm->_varStore->setVar(21, 0);
+ }
+
+ // Var 21 = "Water Flowing to Third (L, R) Water Valve"
+ // and
+ // Var 11 = "Third (L, R) Water Valve State"
+ // Controls
+ // Var 23 = "Water Flowing to Fourth (L, R, L) Water Valve"
+ // Var 22 = "Water Flowing to Fourth (L, R, R) Water Valve"
+ uint16 var11 = _vm->_varStore->getVar(11);
+ if (_vm->_varStore->getVar(21)) {
+ _vm->_varStore->setVar(23, !var11);
+ _vm->_varStore->setVar(22, var11);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(23, 0);
+ _vm->_varStore->setVar(22, 0);
+ }
+
+ // Var 24 = "Water Flowing to Third (L, L) Water Valve"
+ // and
+ // Var 14 = "Third (L, L) Water Valve State"
+ // Controls
+ // Var 29 = "Water Flowing to Pipe In Water (L, L, L)"
+ // Var 28 = "Water Flowing to Join and Pump Bridge (L, L, R)"
+ uint16 var14 = _vm->_varStore->getVar(14);
+ if (_vm->_varStore->getVar(24)) {
+ _vm->_varStore->setVar(29, !var14);
+ _vm->_varStore->setVar(28, var14);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(29, 0);
+ _vm->_varStore->setVar(28, 0);
+ }
+
+ // Var 22 = "Water Flowing to Fourth (L, R, R) Water Valve"
+ // and
+ // Var 12 = "Fourth (L, R, R) Water Valve State"
+ // Controls
+ // Var 25 = "Water Flowing to Pipe Bridge (L, R, R, L)"
+ // Var 15 = "Water Flowing (L, R, R, R) to Pump for Lower Walkway to Upper Walkway Elevator"
+ uint16 var12 = _vm->_varStore->getVar(12);
+ if (_vm->_varStore->getVar(22)) {
+ _vm->_varStore->setVar(25, !var12);
+ _vm->_varStore->setVar(15, var12);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(25, 0);
+ _vm->_varStore->setVar(15, 0);
+ }
+
+ // Var 23 = "Water Flowing to Fourth (L, R, L) Water Valve"
+ // and
+ // Var 13 = "Fourth (L, R, L) Water Valve State"
+ // Controls
+ // Var 27 = "Water Flowing to Join and Pump Bridge (L, R, L, L)"
+ // Var 26 = "Water Flowing to Pipe At Entry Point (L, R, L, R)"
+ uint16 var13 = _vm->_varStore->getVar(13);
+ if (_vm->_varStore->getVar(23)) {
+ _vm->_varStore->setVar(27, !var13);
+ _vm->_varStore->setVar(26, var13);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(27, 0);
+ _vm->_varStore->setVar(26, 0);
+ }
+
+ // TODO: Not sure that original had OR logic for water flow at Join...
+ // Var 27 = "Water Flowing to Join and Pump Bridge (L, R, L, L)"
+ // Or
+ // Var 28 = "Water Flowing to Join and Pump Bridge (L, L, R)"
+ // Controls
+ // Var 31 = "Water Flowing to Join (L, L, R)" // 0 to 2 = Stop Sound, Background, Background with Water Flow
+ // Var 7 = "Bridge Pump Running"
+ // TODO: Not sure about control of Var 31 which is tristate...
+ if (_vm->_varStore->getVar(27) || _vm->_varStore->getVar(28)) {
+ _vm->_varStore->setVar(31, 2); // Background with Water Flow
+ _vm->_varStore->setVar(7, 1);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(31, 1); // Background
+ _vm->_varStore->setVar(7, 0);
+ }
+
+ // TODO: Code for this shouldn't be here...
+ // Move to Opcodes called by Pipe Extension...
+ // Var 25 = "Water Flowing to Pipe Bridge (L, R, R, L)"
+ // and
+ // Var 6 = "Pipe Bridge Extended"
+ // Controls
+ // Var 32 = "Water Flowing (L, R, R, L, Pipe) State" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow
+ // Var 4 = "Water Flowing (L, R, R, L, Pipe Extended) to Pump for Book Room Elevator"
+ // TODO: Not sure about control of Var 32 which is tristate...
+ if (_vm->_varStore->getVar(25) && _vm->_varStore->getVar(6)) {
+ _vm->_varStore->setVar(32, 2); // Background with Water Flow
+ _vm->_varStore->setVar(4, 1);
+ } else {
+ // No water into Valve
+ _vm->_varStore->setVar(32, 1); // Background
+ _vm->_varStore->setVar(4, 0);
+ }
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_202_disable(void) {
+ g_opcode202Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_202(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 1191 (Maze Runner)
+ if (argc == 0) {
+ g_opcode202Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 2160 (Lighthouse Battery Pack Closeup)
+ // TODO: Implement Code...
+ // Not Sure of Purpose - Update of Light / Discharge?
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ varUnusedCheck(op, var);
+
+ // Used for Card 4378 (Library Tower Rotation Map)
+ if (argc == 1) {
+ // TODO: Figure Out argv[0] purpose.. number of image resources?
+ g_opcode202Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ // Used for Card 6220 (Sirrus' Mechanical Bird)
+ if (argc == 0) {
+ g_opcode202Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ // Used for Cards 3328, 3691, 3731, 3809, 3846 etc. (Water Valves)
+ if (argc == 0) {
+ g_opcode202Parameters.var = var;
+ g_opcode202Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ varUnusedCheck(op, var);
+
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ bool enabled;
+} g_opcode203Parameters;
+
+void MystScriptParser_Myst::opcode_203_run(void) {
+ if (g_opcode203Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1245 (Sound Receiver)
+ // TODO: Fill in Logic to Change Viewer Display etc.?
+ break;
+ case kMystStack:
+ // Used for Card 4138 (Dock Forechamber Door)
+ // TODO: Fill in Logic. Slide for Dock Forechamber Door?
+ // Original has Left to Right Open Slide and Upon leaving card,
+ // Right to left Slide before card change.
+ //debugC(kDebugScript, "Opcode %d: Clear Dock Forechamber Door Variable", op);
+ //_vm->_varStore->setVar(105, 0);
+ break;
+ case kMechanicalStack:
+ // Used for Card 6043 (Weapons Rack with Snake Box)
+ // TODO: Fill in Logic for Snake Box...
+ break;
+ case kChannelwoodStack:
+ // Used for Card 3310 (Sirrus' Room Right Bed Drawer),
+ // Card 3307 (Sirrus' Room Left Bed Drawer)
+ // and Card 3318 (Sirrus' Room Nightstand Drawer)
+ // TODO: Fill in Logic...
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_203_disable(void) {
+ g_opcode203Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_203(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ uint16 imageIdDarkDoorOpen = 0;
+ uint16 imageIdDarkDoorClosed = 0;
+
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1245 (Sound Receiver)
+ if (argc == 0) {
+ g_opcode203Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ // Used for all/most Cards in Tunnels Down To Brothers Rooms
+
+ // TODO: Duplicate or similar function to Opcode 203?
+ if (argc == 2 || argc == 4) {
+ debugC(kDebugScript, "Opcode %d: %d Arguments", op, argc);
+
+ uint16 u0 = argv[0];
+ if (argc == 4) {
+ imageIdDarkDoorOpen = argv[1];
+ imageIdDarkDoorClosed = argv[2];
+ }
+ uint16 soundIdAlarm = argv[argc - 1];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ if (argc == 4) {
+ debugC(kDebugScript, "\timageIdDarkDoorOpen: %d", imageIdDarkDoorOpen);
+ debugC(kDebugScript, "\tsoundIdDarkDoorClosed: %d", imageIdDarkDoorClosed);
+ }
+ debugC(kDebugScript, "\tsoundIdAlarm: %d", soundIdAlarm);
+
+ // TODO: Fill in Correct Function for Lights
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Card 4138 (Dock Forechamber Door)
+ // Set forechamber door to closed
+ setVarValue(105, 0);
+ break;
+ case kMechanicalStack:
+ // Used for Card 6043 (Weapons Rack with Snake Box)
+ if (argc == 0) {
+ g_opcode203Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kChannelwoodStack:
+ // Used for Card 3310 (Sirrus' Room Right Bed Drawer),
+ // Card 3307 (Sirrus' Room Left Bed Drawer)
+ // and Card 3318 (Sirrus' Room Nightstand Drawer)
+ if (argc == 0) {
+ g_opcode203Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ bool enabled;
+ uint16 soundId;
+} g_opcode204Parameters;
+
+void MystScriptParser_Myst::opcode_204_run(void) {
+ if (g_opcode204Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1147 (Sound Code Lock)
+ // TODO: Fill in code for Sound Lock...
+ break;
+ case kMystStack:
+ // Used for Card 4134 and 4149 (Dock)
+ // TODO: Not sure of function. Not Gulls (at least directly). Fill in Logic.
+ break;
+ case kMechanicalStack:
+ // TODO: Fill in Logic.
+ // Var 12 holds Large Cog Position in range 0 to 5
+ // - For animation
+ // Var 11 holds C position in range 0 to 9
+ // - 4 for Correct Answer
+ // C Movement Sound
+ //_vm->_sound->playSound(g_opcode204Parameters.soundId);
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_204_disable(void) {
+ g_opcode204Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_204(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1147 (Sound Code Lock)
+ if (argc == 0) {
+ g_opcode204Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ // Used for Card 2160 (Lighthouse Battery Pack Closeup)
+ if (argc == 0) {
+ // TODO: Implement Code For Battery Meter Level
+ // Overwrite _vm->_resources[1]->_subImages[0].rect.bottom 1 to 80
+ // Add accessor functions for this...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Card 4134 and 4149 (Dock)
+ break;
+ case kMechanicalStack:
+ // Used for Card 6180 (Lower Elevator Puzzle)
+ if (argc == 1) {
+ g_opcode204Parameters.soundId = argv[0];
+ g_opcode204Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ uint16 soundIdPosition[4];
+
+ bool enabled;
+} g_opcode205Parameters;
+
+void MystScriptParser_Myst::opcode_205_run(void) {
+ if (g_opcode205Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+ // TODO: Fill in function...
+ break;
+ case kMystStack:
+ // Used for Card 4532 (Rocketship Piano)
+ // TODO: Fill in function...
+ break;
+ case kMechanicalStack:
+ // Used for Card 6156 (Fortress Rotation Controls)
+ // TODO: Fill in function...
+ // g_opcode205Parameters.soundIdPosition[4]
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_205_disable(void) {
+ g_opcode205Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_205(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ uint16 imageIdDoorOpen = 0;
+ uint16 imageIdDoorClosed = 0;
+
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+
+ if (argc == 0) {
+ g_opcode205Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ // Used on Cards 2322, 2285 (Tunnels Down To Brothers Rooms)
+
+ // TODO: Duplicate or similar function to Opcode 203?
+ if (argc == 2 || argc == 4) {
+ debugC(kDebugScript, "Opcode %d: %d Arguments", op, argc);
+
+ uint16 u0 = argv[0];
+ if (argc == 4) {
+ imageIdDoorOpen = argv[1];
+ imageIdDoorClosed = argv[2];
+ }
+ uint16 soundIdAlarm = argv[argc - 1];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ if (argc == 4) {
+ debugC(kDebugScript, "\timageIdDoorOpen: %d", imageIdDoorOpen);
+ debugC(kDebugScript, "\tsoundIdDoorClosed: %d", imageIdDoorClosed);
+ }
+ debugC(kDebugScript, "\tsoundIdAlarm: %d", soundIdAlarm);
+
+ // TODO: Fill in Correct Function for Lights
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Card 4532 (Rocketship Piano)
+
+ if (argc == 0) {
+ g_opcode205Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ // Used for Card 6156 (Fortress Rotation Controls)
+
+ if (argc == 4) {
+ g_opcode205Parameters.soundIdPosition[0] = argv[0];
+ g_opcode205Parameters.soundIdPosition[1] = argv[1];
+ g_opcode205Parameters.soundIdPosition[2] = argv[2];
+ g_opcode205Parameters.soundIdPosition[3] = argv[3];
+
+ g_opcode205Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ uint16 soundIdStart[2];
+ uint16 soundIdPosition[4];
+
+ bool enabled;
+} g_opcode206Parameters;
+
+void MystScriptParser_Myst::opcode_206_run(void) {
+ if (g_opcode206Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+ // TODO: Fill in function...
+ break;
+ case kMechanicalStack:
+ // Used for Card 6044 (Fortress Rotation Simulator)
+
+ // g_opcode206Parameters.soundIdStart[2]
+ // g_opcode206Parameters.soundIdPosition[4]
+
+ // TODO: Fill in function...
+ break;
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_206_disable(void) {
+ g_opcode206Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_206(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kSeleniticStack:
+ // Used for Card 1191 (Maze Runner)
+
+ if (argc == 0) {
+ g_opcode206Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kStoneshipStack:
+ // Used for Cards 2272 and 2234 (Facing Out of Door)
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Unknown, %d Arguments", op, argc);
+ // TODO: Function Unknown...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Card 4256 (Butterfly Movie Activation)
+ // TODO: Implement Logic...
+ break;
+ case kMechanicalStack:
+ // Used for Card 6044 (Fortress Rotation Simulator)
+ if (argc == 6) {
+ g_opcode206Parameters.soundIdStart[0] = argv[0];
+ g_opcode206Parameters.soundIdStart[1] = argv[1];
+ g_opcode206Parameters.soundIdPosition[0] = argv[2];
+ g_opcode206Parameters.soundIdPosition[1] = argv[3];
+ g_opcode206Parameters.soundIdPosition[2] = argv[4];
+ g_opcode206Parameters.soundIdPosition[3] = argv[5];
+
+ g_opcode206Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_207(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ // Used for Card 2138 (Lighthouse Key/Chest Animation Logic)
+ // TODO: Fill in function
+ warning("TODO: Opcode 207 Lighthouse Key/Chest Animation Logic");
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_208(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ // Used in Card 2218 (Telescope view)
+ if (argc == 3) {
+ debugC(kDebugScript, "Opcode %d: Telescope View", op);
+ uint16 imagePanorama = argv[0];
+ uint16 imageLighthouseOff = argv[1];
+ uint16 imageLighthouseOn = argv[2];
+
+ debugC(kDebugScript, "Image (Panorama): %d", imagePanorama);
+ debugC(kDebugScript, "Image (Lighthouse Off): %d", imageLighthouseOff);
+ debugC(kDebugScript, "Image (Lighthouse On): %d", imageLighthouseOn);
+
+ // TODO: Fill in Logic.
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Imager Function", op);
+ debugC(kDebugScript, "Var: %d", var);
+
+ // TODO: Fill in Correct Function
+ if (false) {
+ _vm->_video->playMovie(_vm->wrapMovieFilename("vltmntn", kMystStack), 159, 97);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ uint16 u0[5];
+ uint16 u1[5];
+ uint16 stateVar;
+
+ uint16 soundId;
+
+ bool enabled;
+} g_opcode209Parameters;
+
+void MystScriptParser_Myst::opcode_209_run(void) {
+ static bool enabledLast;
+
+ if (g_opcode209Parameters.enabled) {
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ // Used for Card 2004 (Achenar's Room Drawers)
+
+ // TODO: Implement Function...
+ // Swap Open Drawers?
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used for Card 4334 and 4348 (Myst Library Bookcase Door)
+ if (!enabledLast)
+ // TODO: If Variable changed...
+ _vm->_sound->playSound(g_opcode209Parameters.soundId);
+
+ // TODO: Code to trigger Type 6 to play movie...
+ break;
+ case kMechanicalStack:
+ // Used for Card 6044 (Fortress Rotation Simulator)
+
+ // TODO: Implement Function For Secret Panel State as
+ // per Opcode 200 function (Mechanical)
+ break;
+ default:
+ break;
+ }
+ }
+
+ enabledLast = g_opcode209Parameters.enabled;
+}
+
+void MystScriptParser_Myst::opcode_209_disable(void) {
+ g_opcode209Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_209(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ // Used for Card 2004 (Achenar's Room Drawers)
+ if (argc == 11) {
+ g_opcode209Parameters.u0[0] = argv[0];
+ g_opcode209Parameters.u0[1] = argv[1];
+ g_opcode209Parameters.u0[2] = argv[2];
+ g_opcode209Parameters.u0[3] = argv[3];
+ g_opcode209Parameters.u0[4] = argv[4];
+
+ g_opcode209Parameters.u1[0] = argv[5];
+ g_opcode209Parameters.u1[1] = argv[6];
+ g_opcode209Parameters.u1[2] = argv[7];
+ g_opcode209Parameters.u1[3] = argv[8];
+ g_opcode209Parameters.u1[4] = argv[9];
+
+ g_opcode209Parameters.stateVar = argv[10];
+
+ g_opcode209Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used for Card 4334 and 4348 (Myst Library Bookcase Door)
+ if (argc == 1) {
+ g_opcode209Parameters.soundId = argv[0];
+ g_opcode209Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMechanicalStack:
+ // Used for Card 6044 (Fortress Rotation Simulator)
+ if (argc == 0) {
+ g_opcode209Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ bool enabled;
+} g_opcode210Parameters;
+
+void MystScriptParser_Myst::opcode_210_run(void) {
+ if (g_opcode210Parameters.enabled) {
+ // Code for Generator Puzzle
+
+ // Var 52 to 61 Hold Button State for 10 generators
+ // Var 64, 65 - 2 8-Segments for Rocket Power Dial
+ // Var 62, 63 - 2 8-Segments for Power Dial
+ // Var 96, 97 - Needle for Power and Rocket Power Dials
+
+ // Var 44 Holds State for Rocketship
+ // 0 = No Power
+ // 1 = Insufficient Power
+ // 2 = Correct Power i.e. 59V
+
+ // Var 93 Holds Breaker nearest Generator State
+ // Var 94 Holds Breaker nearest Rocket Ship State
+ // 0 = Closed 1 = Open
+
+ const uint16 correctVoltage = 59;
+
+ // Correct Solution is 4, 7, 8, 9 i.e. 16 + 2 + 22 + 19 = 59
+ const uint16 genVoltages[10] = { 10, 7, 8, 16, 5, 1, 2, 22, 19, 9 };
+
+ uint16 powerVoltage = 0;
+ uint16 rocketPowerVoltage = 0;
+
+ // Calculate Power Voltage from Generator Contributions
+ for (byte i = 0; i < ARRAYSIZE(genVoltages); i++)
+ if (_vm->_varStore->getVar(52 + i))
+ powerVoltage += genVoltages[i];
+
+ // Logic for Var 49 - Generator Running Sound Control
+ if (powerVoltage == 0)
+ _vm->_varStore->setVar(49, 0);
+ else
+ _vm->_varStore->setVar(49, 1);
+
+ // TODO: Animation Code to Spin Up and Spin Down LED Dials?
+ // Code For Power Dial Var 62 and 63
+ _vm->_varStore->setVar(62, powerVoltage / 10);
+ _vm->_varStore->setVar(63, powerVoltage % 10);
+ // TODO: Var 96 - Power Needle Logic
+
+ // Code For Breaker Logic
+ if (_vm->_varStore->getVar(93) != 0 || _vm->_varStore->getVar(94) != 0)
+ rocketPowerVoltage = 0;
+ else {
+ if (powerVoltage <= correctVoltage)
+ rocketPowerVoltage = powerVoltage;
+ else {
+ // Blow Generator Room Breaker...
+ _vm->_varStore->setVar(93, 1);
+ // TODO: I think Logic For Blowing Other Breaker etc.
+ // is done in process on Breaker Cards.
+
+ rocketPowerVoltage = 0;
+ }
+ }
+
+ // TODO: Animation Code to Spin Up and Spin Down LED Dials?
+ // Code For Rocket Power Dial
+ _vm->_varStore->setVar(64, rocketPowerVoltage / 10);
+ _vm->_varStore->setVar(65, rocketPowerVoltage % 10);
+ // TODO: Var 97 - Rocket Power Needle Logic
+
+ // Set Rocket Ship Power Based on Power Level
+ if (rocketPowerVoltage == 0)
+ _vm->_varStore->setVar(44, 0);
+ else if (rocketPowerVoltage < correctVoltage)
+ _vm->_varStore->setVar(44, 1);
+ else if (rocketPowerVoltage == correctVoltage)
+ _vm->_varStore->setVar(44, 2);
+ else // Should Not Happen Case
+ _vm->_varStore->setVar(44, 0);
+ }
+}
+
+void MystScriptParser_Myst::opcode_210_disable(void) {
+ g_opcode210Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_210(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kStoneshipStack:
+ varUnusedCheck(op, var);
+
+ // Used in Cards 2205 and 2207 (Cloud Orbs in Sirrus' Room)
+ if (argc == 2) {
+ uint16 soundId = argv[0];
+ uint16 soundIdStopping = argv[1];
+
+ // TODO: Work Out Function i.e. control Var etc.
+ if (false) {
+ _vm->_sound->playSound(soundId);
+ _vm->_sound->playSound(soundIdStopping);
+ }
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ case kMystStack:
+ // Used for Card 4297 (Generator Puzzle)
+ if (argc == 2) {
+ // TODO: Work Out 2 parameters meaning... 16, 17
+ // Script Resources for Generator Spinup and Spindown Sounds?
+ g_opcode210Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ bool enabled;
+} g_opcode211Parameters;
+
+void MystScriptParser_Myst::opcode_211_run(void) {
+ const uint16 imageBaseId = 4779;
+ const uint16 gridBaseLeft = 173;
+ const uint16 gridBaseTop = 168;
+
+ static uint16 lastGridState[6];
+ uint16 gridState[6];
+ uint16 image;
+
+ if (g_opcode211Parameters.enabled) {
+ // Grid uses Var 17 to 22 as bitfields (8 horizontal cells x 6 vertical)
+ for (byte i = 0; i < 6; i++) {
+ gridState[i] = _vm->_varStore->getVar(i + 17);
+
+ if (gridState[i] != lastGridState[i]) {
+ for (byte j = 0; j < 8; j++) {
+ // TODO: Animation Code
+ if ((gridState[i] >> (7 - j)) & 1)
+ image = 16;
+ else
+ image = 0;
+
+ _vm->_gfx->copyImageToScreen(imageBaseId + image, Common::Rect(gridBaseLeft + (j * 26), gridBaseTop + (i * 26), gridBaseLeft + ((j + 1) * 26), gridBaseTop + ((i + 1) * 26)));
+ }
+ }
+
+ lastGridState[i] = gridState[i];
+ }
+
+ // Var 23 contains boolean for whether pattern matches correct book pattern i.e. Pattern 158
+ if (gridState[0] == 0xc3 && gridState[1] == 0x6b && gridState[2] == 0xa3 &&
+ gridState[3] == 0x93 && gridState[4] == 0xcc && gridState[5] == 0xfa)
+ _vm->_varStore->setVar(23, 1);
+ else
+ _vm->_varStore->setVar(23, 0);
+ }
+}
+
+void MystScriptParser_Myst::opcode_211_disable(void) {
+ g_opcode211Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_211(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used for Card 4059 (Fireplace Puzzle)
+ if (argc == 0) {
+ for (byte i = 0; i < 6; i++)
+ _vm->_varStore->setVar(i + 17, 0);
+
+ g_opcode211Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+static struct {
+ bool enabled;
+} g_opcode212Parameters;
+
+void MystScriptParser_Myst::opcode_212_run(void) {
+ if (g_opcode212Parameters.enabled) {
+ // TODO: Implement Correct Code for Myst Clock Tower Cog Puzzle
+ // Card 4113
+
+ if (false) {
+ // 3 videos to be played of Cog Movement
+ // TODO: Not 100% sure of movie positions.
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wg1", kMystStack), 220, 50);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wg2", kMystStack), 220, 80);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wg3", kMystStack), 220, 110);
+
+ // 1 video of weight descent
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack), 123, 0);
+
+ // Video of Cog Open on Success
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack), 195, 225);
+ // Var 40 set on success
+ _vm->_varStore->setVar(40, 1);
+ }
+ }
+}
+
+void MystScriptParser_Myst::opcode_212_disable(void) {
+ g_opcode212Parameters.enabled = false;
+}
+
+void MystScriptParser_Myst::opcode_212(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4113 (Clock Tower Cog Puzzle)
+ if (argc == 0) {
+ g_opcode212Parameters.enabled = true;
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_213(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4524 (Dockside Facing Towards Ship)
+ if (argc == 0) {
+ // TODO: Implement Code...
+ // Code for Gull Videos?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_214(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4500 (Stellar Observatory)
+ if (argc == 5) {
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+
+ uint16 u0 = argv[0];
+ uint16 u1 = argv[1];
+ uint16 u2 = argv[2];
+ uint16 u3 = argv[3];
+ uint16 u4 = argv[4];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+ debugC(kDebugScript, "\tu2: %d", u2);
+ debugC(kDebugScript, "\tu3: %d", u3);
+ debugC(kDebugScript, "\tu4: %d", u4);
+ // TODO: Complete Implementation...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_215(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4134 (Dock Facing Marker Switch)
+ // TODO: Fill in logic for Gull Videos.
+ // may be offset and overlap and need video update to all these
+ // to run in sequence with opcode215_run() process...
+ if (false) {
+ // All birds(x) videos are 120x48 and played in top right corner of card
+ _vm->_video->playMovie(_vm->wrapMovieFilename("birds1", kMystStack), 544-120-1, 0);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("birds2", kMystStack), 544-120-1, 0);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("birds3", kMystStack), 544-120-1, 0);
+ }
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_216(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Cards 4571 (Channelwood Tree), 4586 (Channelwood Tree),
+ // 4615 (Channelwood Tree) and 4601 (Channelwood Tree)
+ if (argc == 0) {
+ // TODO: Fill in logic for Channelwood Tree Position i.e. Var 72 update // 0 to 12, 4 for Alcove
+ // Based on Timer code and following variables :
+ // 98 "Cabin Boiler Pilot Light Lit"
+ // 99 "Cabin Boiler Gas Valve Position" }, // 0 to 5
+ // 305 "Cabin Boiler Lit" },
+ // 306 "Cabin Boiler Steam Sound Control" }, // 0 to 27
+ // 307 "Cabin Boiler Needle Position i.e. Fully Pressurised" }, // 0 to 1
+
+ // Note : Opcode 218 does boiler update code..
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_217(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4601 (Channelwood Tree)
+ if (argc == 2) {
+ // TODO: Fill in logic for Tree Position Close Up...
+ // 2 arguments: 4, 4
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4097 (Cabin Boiler)
+ // TODO: Fill in logic
+ if (false) {
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 138);
+ }
+
+ // Used for Card 4098 (Cabin Boiler)
+ // TODO: Fill in logic
+ if (false) {
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279);
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 97);
+ }
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_219(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4530 (Rocketship Music Puzzle)
+ if (argc == 5) {
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+
+ uint16 u0 = argv[0];
+ uint16 u1 = argv[1];
+ uint16 u2 = argv[2];
+ uint16 u3 = argv[3];
+ uint16 u4 = argv[4];
+
+ debugC(kDebugScript, "\tu0: %d", u0);
+ debugC(kDebugScript, "\tu1: %d", u1);
+ debugC(kDebugScript, "\tu2: %d", u2);
+ debugC(kDebugScript, "\tu3: %d", u3);
+ debugC(kDebugScript, "\tu4: %d", u4);
+ // TODO: Fill in logic...
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_220(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4530 (Rocketship Music Puzzle Video)
+ // TODO: Fill in logic.
+ if (false) {
+ // loop?
+ _vm->_video->playMovie(_vm->wrapMovieFilename("selenbok", kMystStack), 224, 41);
+ }
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_221(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4168 (Green Book Movies)
+ // Movie plays in resource #0 rect
+ // TODO: Not sure if subsection is looped...
+ if (!_vm->_varStore->getVar(302)) {
+ // HACK: Stop Wind Sounds.. Think this is a problem at library entrance.
+ _vm->_sound->stopSound();
+ _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename("atrusbk1", kMystStack), 314, 76);
+ _vm->_varStore->setVar(302, 1);
+ } else {
+ // HACK: Stop Wind Sounds.. Think this is a problem at library entrance.
+ _vm->_sound->stopSound();
+ _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename("atrusbk2", kMystStack), 314, 76);
+ }
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_222(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4141 (Myst Dock Facing Sea)
+ if (argc == 0) {
+ // TODO: Logic for Gull Videos?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_298(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ // Used for Card 3000 (Closed Myst Book)
+ // TODO: Fill in logic.
+ // Start Voice Over... which controls book opening
+ _vm->_sound->playSound(3001);
+
+ // then link to Myst - Trigger of Hotspot? then opcode 199/196/197 for voice over continue?
+ // TODO: Sync Voice and Actions to Original
+ // TODO: Flash Library Red
+ // TODO: Move to run process based delay to prevent
+ // blocking...
+ _vm->_system->delayMillis(20 * 1000);
+ for (uint16 imageId = 3001; imageId <= 3012; imageId++) {
+ _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333));
+ _vm->_system->delayMillis(5 * 1000);
+ }
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_299(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ // Used for Card 3002 (Myst Island Overview)
+ // TODO: Fill in logic.
+ // Zoom into Island?
+ // On this card is a Type 8 controlled by Var 0, which
+ // can change the Myst Library to Red..
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_300(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kIntroStack:
+ varUnusedCheck(op, var);
+ // In the original engine, this opcode stopped Intro Movies if playing,
+ // upon card change, but this behaviour is now default in this engine.
+ break;
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used in Card 4371 (Blue Book) Var = 101
+ // and Card 4363 (Red Book) Var = 100
+ debugC(kDebugScript, "Opcode %d: Book Exit Function...", op);
+ debugC(kDebugScript, "Var: %d", var);
+ // TODO: Fill in Logic
+ break;
+ case kStoneshipStack:
+ // Used in Card 2218 (Telescope view)
+ varUnusedCheck(op, var);
+ // TODO: Fill in Logic. Clearing Variable for View?
+ break;
+ case kMechanicalStack:
+ // Used in Card 6156 (Fortress Elevator View)
+ varUnusedCheck(op, var);
+ // TODO: Fill in Logic. Clearing Variable for View?
+ break;
+ case kChannelwoodStack:
+ // Used in Card 3012 (Achenar's Holoprojector Control)
+ varUnusedCheck(op, var);
+ // TODO: Fill in Logic. Clearing Variable for View?
+ break;
+ case kDniStack:
+ // Used in Card 5014 (Atrus Writing)
+ varUnusedCheck(op, var);
+ // TODO: Fill in Logic.
+ break;
+ case kDemoStack:
+ // Used on Card 2000
+ varUnusedCheck(op, var);
+
+ // TODO: Fill in Function...
+ break;
+ default:
+ varUnusedCheck(op, var);
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_301(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kDemoPreviewStack:
+ case kMystStack:
+ // Used in Cards 4047, 4059, 4060, 4068 and 4080 (Myst Library Books - Open)
+ // TODO: Fill in Logic. Clear Variable on Book exit.. or Copy from duplicate..
+ _vm->_varStore->setVar(0, 1);
+ break;
+ default:
+ varUnusedCheck(op, var);
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_302(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used in Card 4113 (Clock Tower Cog Puzzle)
+ // TODO: Fill in Logic
+ break;
+ default:
+ varUnusedCheck(op, var);
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_303(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4134 (Dock Facing Marker Switch)
+ // Used for Card 4141 (Myst Dock Facing Sea)
+ // In the original engine, this opcode stopped Gull Movies if playing,
+ // upon card change, but this behaviour is now default in this engine.
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_304(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4601 (Channelwood Tree)
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+ // TODO: Logic for clearing variable?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_305(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4601 (Channelwood Tree)
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+ // TODO: Logic for clearing variable?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_306(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4098 (Cabin Boiler Puzzle)
+ // In the original engine, this opcode stopped the Boiler Fire and Meter Needle videos
+ // if playing, upon card change, but this behaviour is now default in this engine.
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_307(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4297 (Generator Room Controls)
+ if (argc == 0) {
+ debugC(kDebugScript, "Opcode %d: Unknown...", op);
+ // TODO: Logic for clearing variable?
+ } else
+ unknown(op, var, argc, argv);
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_308(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4530 (Rocketship Music Sliders)
+ // In the original engine, this opcode stopped the Selenitic Book Movie if playing,
+ // upon card change, but this behaviour is now default in this engine.
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_309(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4168 (Green D'ni Book Open)
+ // In the original engine, this opcode stopped the Green Book Atrus Movies if playing,
+ // upon card change, but this behaviour is now default in this engine.
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+void MystScriptParser_Myst::opcode_312(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ varUnusedCheck(op, var);
+
+ switch (_vm->getCurStack()) {
+ case kMystStack:
+ // Used for Card 4698 (Dock Forechamber Imager)
+ // In the original engine, this opcode stopped the Imager Movie if playing,
+ // especially the hardcoded Topological Extrusion (Mountain) video,
+ // upon card change, but this behaviour is now default in this engine.
+ break;
+ default:
+ unknown(op, var, argc, argv);
+ break;
+ }
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
new file mode 100644
index 0000000000..ccdeb89860
--- /dev/null
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -0,0 +1,164 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MYST_SCRIPTS_MYST_H
+#define MYST_SCRIPTS_MYST_H
+
+#include "common/scummsys.h"
+#include "common/util.h"
+#include "mohawk/myst_scripts.h"
+
+namespace Mohawk {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class MohawkEngine_Myst;
+struct MystScriptEntry;
+
+class MystScriptParser_Myst : public MystScriptParser {
+public:
+ MystScriptParser_Myst(MohawkEngine_Myst *vm);
+ ~MystScriptParser_Myst();
+
+ void disablePersistentScripts();
+ void runPersistentScripts();
+
+private:
+ void setupOpcodes();
+
+ void opcode_200_run();
+ void opcode_200_disable();
+ void opcode_201_run();
+ void opcode_201_disable();
+ void opcode_202_run();
+ void opcode_202_disable();
+ void opcode_203_run();
+ void opcode_203_disable();
+ void opcode_204_run();
+ void opcode_204_disable();
+ void opcode_205_run();
+ void opcode_205_disable();
+ void opcode_206_run();
+ void opcode_206_disable();
+ void opcode_209_run();
+ void opcode_209_disable();
+ void opcode_210_run();
+ void opcode_210_disable();
+ void opcode_211_run();
+ void opcode_211_disable();
+ void opcode_212_run();
+ void opcode_212_disable();
+
+ DECLARE_OPCODE(opcode_100);
+ DECLARE_OPCODE(opcode_101);
+ DECLARE_OPCODE(opcode_102);
+ DECLARE_OPCODE(opcode_103);
+ DECLARE_OPCODE(opcode_104);
+ DECLARE_OPCODE(opcode_105);
+ DECLARE_OPCODE(opcode_106);
+ DECLARE_OPCODE(opcode_107);
+ DECLARE_OPCODE(opcode_108);
+ DECLARE_OPCODE(opcode_109);
+ DECLARE_OPCODE(opcode_110);
+ DECLARE_OPCODE(opcode_111);
+ DECLARE_OPCODE(opcode_112);
+ DECLARE_OPCODE(opcode_113);
+ DECLARE_OPCODE(opcode_114);
+ DECLARE_OPCODE(opcode_115);
+ DECLARE_OPCODE(opcode_116);
+ DECLARE_OPCODE(opcode_117);
+ DECLARE_OPCODE(opcode_118);
+ DECLARE_OPCODE(opcode_119);
+ DECLARE_OPCODE(opcode_120);
+ DECLARE_OPCODE(opcode_121);
+ DECLARE_OPCODE(opcode_122);
+ DECLARE_OPCODE(opcode_123);
+ DECLARE_OPCODE(opcode_124);
+ DECLARE_OPCODE(opcode_125);
+ DECLARE_OPCODE(opcode_126);
+ DECLARE_OPCODE(opcode_127);
+ DECLARE_OPCODE(opcode_128);
+ DECLARE_OPCODE(opcode_129);
+ DECLARE_OPCODE(opcode_130);
+ DECLARE_OPCODE(opcode_131);
+ DECLARE_OPCODE(opcode_132);
+ DECLARE_OPCODE(opcode_133);
+ DECLARE_OPCODE(opcode_147);
+ DECLARE_OPCODE(opcode_164);
+ DECLARE_OPCODE(opcode_169);
+ DECLARE_OPCODE(opcode_181);
+ DECLARE_OPCODE(opcode_182);
+ DECLARE_OPCODE(opcode_183);
+ DECLARE_OPCODE(opcode_184);
+ DECLARE_OPCODE(opcode_185);
+ DECLARE_OPCODE(opcode_196);
+ DECLARE_OPCODE(opcode_197);
+ DECLARE_OPCODE(opcode_198);
+ DECLARE_OPCODE(opcode_199);
+
+ DECLARE_OPCODE(opcode_200);
+ DECLARE_OPCODE(opcode_201);
+ DECLARE_OPCODE(opcode_202);
+ DECLARE_OPCODE(opcode_203);
+ DECLARE_OPCODE(opcode_204);
+ DECLARE_OPCODE(opcode_205);
+ DECLARE_OPCODE(opcode_206);
+ DECLARE_OPCODE(opcode_207);
+ DECLARE_OPCODE(opcode_208);
+ DECLARE_OPCODE(opcode_209);
+ DECLARE_OPCODE(opcode_210);
+ DECLARE_OPCODE(opcode_211);
+ DECLARE_OPCODE(opcode_212);
+ DECLARE_OPCODE(opcode_213);
+ DECLARE_OPCODE(opcode_214);
+ DECLARE_OPCODE(opcode_215);
+ DECLARE_OPCODE(opcode_216);
+ DECLARE_OPCODE(opcode_217);
+ DECLARE_OPCODE(opcode_218);
+ DECLARE_OPCODE(opcode_219);
+ DECLARE_OPCODE(opcode_220);
+ DECLARE_OPCODE(opcode_221);
+ DECLARE_OPCODE(opcode_222);
+ DECLARE_OPCODE(opcode_298);
+ DECLARE_OPCODE(opcode_299);
+
+ DECLARE_OPCODE(opcode_300);
+ DECLARE_OPCODE(opcode_301);
+ DECLARE_OPCODE(opcode_302);
+ DECLARE_OPCODE(opcode_303);
+ DECLARE_OPCODE(opcode_304);
+ DECLARE_OPCODE(opcode_305);
+ DECLARE_OPCODE(opcode_306);
+ DECLARE_OPCODE(opcode_307);
+ DECLARE_OPCODE(opcode_308);
+ DECLARE_OPCODE(opcode_309);
+ DECLARE_OPCODE(opcode_312);
+};
+
+}
+
+#undef DECLARE_OPCODE
+
+#endif
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
new file mode 100644
index 0000000000..fde037dbcd
--- /dev/null
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -0,0 +1,1766 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "mohawk/cursors.h"
+#include "mohawk/myst.h"
+#include "mohawk/graphics.h"
+#include "mohawk/myst_areas.h"
+#include "mohawk/myst_saveload.h"
+#include "mohawk/sound.h"
+#include "mohawk/video.h"
+#include "mohawk/myst_stacks/selenitic.h"
+
+#include "gui/message.h"
+
+namespace Mohawk {
+
+#define OPCODE(op, x) { op, &MystScriptParser::x, #x }
+#define SPECIFIC_OPCODE(op, x) { op, (OpcodeProcMyst) &MystScriptParser_Selenitic::x, #x }
+
+MystScriptParser_Selenitic::MystScriptParser_Selenitic(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+ setupOpcodes();
+ _invokingResource = NULL;
+ _mazeRunnerPosition = 288;
+}
+
+MystScriptParser_Selenitic::~MystScriptParser_Selenitic() {
+}
+
+void MystScriptParser_Selenitic::setupOpcodes() {
+ // "invalid" opcodes do not exist or have not been observed
+ // "unknown" opcodes exist, but their meaning is unknown
+
+ static const MystOpcode myst_opcodes[] = {
+ // "Standard" Opcodes
+ OPCODE(0, o_toggleVar),
+ OPCODE(1, o_setVar),
+ OPCODE(2, o_changeCardSwitch),
+ OPCODE(3, o_takePage),
+ OPCODE(4, o_redrawCard),
+ // TODO: Opcode 5 Not Present
+ OPCODE(6, o_goToDest),
+ OPCODE(7, o_goToDest),
+ OPCODE(8, o_goToDest),
+ OPCODE(9, o_triggerMovie),
+ OPCODE(10, o_toggleVarNoRedraw),
+ // TODO: Opcode 10 to 11 Not Present
+ OPCODE(12, o_changeCardSwitch),
+ OPCODE(13, o_changeCardSwitch),
+ OPCODE(14, o_drawAreaState),
+ OPCODE(15, o_redrawAreaForVar),
+ OPCODE(16, o_changeCardDirectional),
+ OPCODE(17, o_changeCardPush),
+ OPCODE(18, o_changeCardPop),
+ OPCODE(19, o_enableAreas),
+ OPCODE(20, o_disableAreas),
+ OPCODE(21, o_directionalUpdate),
+ OPCODE(22, o_goToDest),
+ OPCODE(23, o_toggleAreasActivation),
+ OPCODE(24, o_playSound),
+ // TODO: Opcode 25 Not Present
+ OPCODE(26, o_stopSoundBackground),
+ OPCODE(27, o_playSoundBlocking),
+ OPCODE(28, o_restoreDefaultRect),
+ OPCODE(29, o_blitRect),
+ OPCODE(30, o_changeSound),
+ OPCODE(31, o_soundPlaySwitch),
+ OPCODE(32, o_soundResumeBackground),
+ OPCODE(33, o_blitRect),
+ OPCODE(34, o_changeCard),
+ OPCODE(35, o_drawImageChangeCard),
+ OPCODE(36, o_changeMainCursor),
+ OPCODE(37, o_hideCursor),
+ OPCODE(38, o_showCursor),
+ OPCODE(39, o_delay),
+ OPCODE(40, o_changeStack),
+ OPCODE(41, o_changeCardPlaySoundDirectional),
+ OPCODE(42, o_directionalUpdatePlaySound),
+ OPCODE(43, o_saveMainCursor),
+ OPCODE(44, o_restoreMainCursor),
+ // TODO: Opcode 45 Not Present
+ OPCODE(46, o_soundWaitStop),
+ // TODO: Opcodes 47 to 99 Not Present
+
+ // "Stack-Specific" Opcodes
+ SPECIFIC_OPCODE(100, o_mazeRunnerMove),
+ SPECIFIC_OPCODE(101, o_mazeRunnerSoundRepeat),
+ SPECIFIC_OPCODE(102, o_soundReceiverSigma),
+ SPECIFIC_OPCODE(103, o_soundReceiverRight),
+ SPECIFIC_OPCODE(104, o_soundReceiverLeft),
+ SPECIFIC_OPCODE(105, o_soundReceiverSource),
+ SPECIFIC_OPCODE(106, o_soundReceiverSource),
+ SPECIFIC_OPCODE(107, o_soundReceiverSource),
+ SPECIFIC_OPCODE(108, o_soundReceiverSource),
+ SPECIFIC_OPCODE(109, o_soundReceiverSource),
+ SPECIFIC_OPCODE(110, o_mazeRunnerDoorButton),
+ SPECIFIC_OPCODE(111, o_soundReceiverUpdateSound),
+ SPECIFIC_OPCODE(112, o_soundLockMove),
+ SPECIFIC_OPCODE(113, o_soundLockStartMove),
+ SPECIFIC_OPCODE(114, o_soundLockEndMove),
+ SPECIFIC_OPCODE(115, o_soundLockButton),
+ SPECIFIC_OPCODE(116, NOP),
+ SPECIFIC_OPCODE(117, o_soundReceiverEndMove),
+
+ // "Init" Opcodes
+ SPECIFIC_OPCODE(200, o_mazeRunnerCompass_init),
+ SPECIFIC_OPCODE(201, o_mazeRunnerWindow_init),
+ SPECIFIC_OPCODE(202, o_mazeRunnerLight_init),
+ SPECIFIC_OPCODE(203, o_soundReceiver_init),
+ SPECIFIC_OPCODE(204, o_soundLock_init),
+ SPECIFIC_OPCODE(205, o_mazeRunnerRight_init),
+ SPECIFIC_OPCODE(206, o_mazeRunnerLeft_init),
+
+ OPCODE(0xFFFF, NOP)
+ };
+
+ _opcodes = myst_opcodes;
+ _opcodeCount = ARRAYSIZE(myst_opcodes);
+}
+
+void MystScriptParser_Selenitic::disablePersistentScripts() {
+ _soundReceiverRunning = false;
+}
+
+void MystScriptParser_Selenitic::runPersistentScripts() {
+ if (_soundReceiverRunning)
+ soundReceiver_run();
+}
+
+uint16 MystScriptParser_Selenitic::getVar(uint16 var) {
+ uint16 *game_globals = _vm->_saveLoad->_v->game_globals;
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ switch(var) {
+ case 0: // Sound receiver emitters enabled
+ return selenitic_vars[4];
+ case 1:
+ return selenitic_vars[1];
+ case 2:
+ return selenitic_vars[2];
+ case 3:
+ return selenitic_vars[0];
+ case 4:
+ return selenitic_vars[3];
+ case 5: // Sound receiver opened
+ return selenitic_vars[5];
+ case 6: // Tunnel lights
+ return selenitic_vars[6];
+ case 7:// Maze runner display
+ if (_mazeRunnerPosition == 288) {
+ return 0;
+ } else if (_mazeRunnerPosition == 289) {
+ return 1;
+ } else if (!mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ return 2;
+ } else {
+ return 3;
+ }
+ case 8: // Viewer
+ return 0;
+ case 9: // Sound receiver selected source
+ return selenitic_vars[7] == 0;
+ case 10:
+ return selenitic_vars[7] == 1;
+ case 11:
+ return selenitic_vars[7] == 2;
+ case 12:
+ return selenitic_vars[7] == 3;
+ case 13:
+ return selenitic_vars[7] == 4;
+ case 14: // Sound receiver position
+ return (*_soundReceiverPosition) / 1000;
+ case 15:
+ return ((*_soundReceiverPosition) / 100) % 10;
+ case 16:
+ return ((*_soundReceiverPosition) / 10) % 10;
+ case 17:
+ return (*_soundReceiverPosition) % 10;
+ case 20: // Sound lock sliders state
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ return 1;
+ case 25: // Maze runner direction
+ return _mazeRunnerDirection;
+ case 26:
+ return _soundReceiverSigmaPressed;
+ case 27:
+ case 29: // Maze runner door
+ return 0;
+ case 30:
+ return _mazeRunnerDoorOpened;
+ case 31: // Maze runner forward allowed
+ return mazeRunnerForwardAllowed(_mazeRunnerPosition) || _mazeRunnerPosition == 288;
+ case 32: // Maze runner exit allowed
+ return _mazeRunnerPosition != 288 && _mazeRunnerPosition != 289;
+ case 33: // Maze runner at entry
+ return _mazeRunnerPosition != 288;
+ case 102: // Red page
+ return !(game_globals[6] & 2) && (game_globals[2] != 8);
+ case 103: // Blue page
+ return !(game_globals[7] & 2) && (game_globals[2] != 2);
+ default:
+ return MystScriptParser::getVar(var);
+ }
+}
+
+void MystScriptParser_Selenitic::toggleVar(uint16 var) {
+ uint16 *game_globals = _vm->_saveLoad->_v->game_globals;
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ switch(var) {
+ case 0: // Sound receiver emitters enabled
+ selenitic_vars[4] = (selenitic_vars[4] + 1) % 2;
+ break;
+ case 1:
+ selenitic_vars[1] = (selenitic_vars[1] + 1) % 2;
+ break;
+ case 2:
+ selenitic_vars[2] = (selenitic_vars[2] + 1) % 2;
+ break;
+ case 3:
+ selenitic_vars[0] = (selenitic_vars[0] + 1) % 2;
+ break;
+ case 4:
+ selenitic_vars[3] = (selenitic_vars[3] + 1) % 2;
+ break;
+ case 5: // Sound receiver opened
+ selenitic_vars[5] = (selenitic_vars[5] + 1) % 2;
+ break;
+ case 6: // Tunnel lights
+ selenitic_vars[6] = (selenitic_vars[6] + 1) % 2;
+ break;
+ case 102: // Red page
+ if (!(game_globals[6] & 2)) {
+ if (game_globals[2] == 8)
+ game_globals[2] = 0;
+ else {
+ game_globals[2] = 8;
+ }
+ }
+ break;
+ case 103: // Blue page
+ if (!(game_globals[7] & 2)) {
+ if (game_globals[2] == 2)
+ game_globals[2] = 0;
+ else {
+ game_globals[2] = 2;
+ }
+ }
+ break;
+ default:
+ MystScriptParser::toggleVar(var);
+ break;
+ }
+}
+
+bool MystScriptParser_Selenitic::setVarValue(uint16 var, uint16 value) {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+ bool refresh = false;
+
+ switch (var) {
+ case 0: // Sound receiver emitters enabled
+ if (selenitic_vars[4] != value) {
+ selenitic_vars[4] = value;
+ refresh = true;
+ }
+ break;
+ case 1:
+ if (selenitic_vars[1] != value) {
+ selenitic_vars[1] = value;
+ refresh = true;
+ }
+ break;
+ case 2:
+ if (selenitic_vars[2] != value) {
+ selenitic_vars[2] = value;
+ refresh = true;
+ }
+ break;
+ case 3:
+ if (selenitic_vars[0] != value) {
+ selenitic_vars[0] = value;
+ refresh = true;
+ }
+ break;
+ case 4:
+ if (selenitic_vars[3] != value) {
+ selenitic_vars[3] = value;
+ refresh = true;
+ }
+ break;
+ case 5: // Sound receiver opened
+ if (selenitic_vars[5] != value) {
+ selenitic_vars[5] = value;
+ refresh = true;
+ }
+ break;
+ case 6: // Tunnel lights
+ if (selenitic_vars[6] != value) {
+ selenitic_vars[6] = value;
+ refresh = true;
+ }
+ break;
+ case 20: // Sound lock sliders
+ selenitic_vars[13] = value;
+ break;
+ case 21:
+ selenitic_vars[14] = value;
+ break;
+ case 22:
+ selenitic_vars[15] = value;
+ break;
+ case 23:
+ selenitic_vars[16] = value;
+ break;
+ case 24:
+ selenitic_vars[17] = value;
+ break;
+ case 30:
+ _mazeRunnerDoorOpened = value;
+ break;
+ default:
+ refresh = MystScriptParser::setVarValue(var, value);
+ break;
+ }
+
+ return refresh;
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 oldPosition = _mazeRunnerPosition;
+ uint16 move = var;
+
+ uint16 videoToNext = _mazeRunnerVideos[_mazeRunnerPosition][move];
+ _mazeRunnerPosition = _mazeRunnerMap[_mazeRunnerPosition][move];
+
+ if (videoToNext) {
+ _mazeRunnerCompass->drawConditionalDataToScreen(8);
+
+ mazeRunnerPlayVideo(videoToNext, oldPosition);
+ mazeRunnerUpdateCompass();
+
+ if (move == 0 || move == 3)
+ mazeRunnerPlaySoundHelp();
+ }
+}
+
+void MystScriptParser_Selenitic::mazeRunnerPlayVideo(uint16 video, uint16 pos) {
+ Common::String file;
+
+ switch (video) {
+ case 1:
+ file = _vm->wrapMovieFilename("forwa1", kSeleniticStack);
+ break;
+ case 2:
+ file = _vm->wrapMovieFilename("forwe0", kSeleniticStack);
+ break;
+ case 3:
+ if (mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ file = _vm->wrapMovieFilename("forwf1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("forwf0", kSeleniticStack);
+ }
+ break;
+ case 4:
+ file = _vm->wrapMovieFilename("left00", kSeleniticStack);
+ break;
+ case 5:
+ file = _vm->wrapMovieFilename("left01", kSeleniticStack);
+ break;
+ case 6:
+ file = _vm->wrapMovieFilename("left10", kSeleniticStack);
+ break;
+ case 7:
+ file = _vm->wrapMovieFilename("left11", kSeleniticStack);
+ break;
+ case 8:
+ file = _vm->wrapMovieFilename("right00", kSeleniticStack);
+ break;
+ case 9:
+ file = _vm->wrapMovieFilename("right01", kSeleniticStack);
+ break;
+ case 10:
+ file = _vm->wrapMovieFilename("right10", kSeleniticStack);
+ break;
+ case 11:
+ file = _vm->wrapMovieFilename("right11", kSeleniticStack);
+ break;
+ case 12:
+ if (mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ file = _vm->wrapMovieFilename("forwo1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("forwo0", kSeleniticStack);
+ }
+ break;
+ case 13:
+ if (mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ file = _vm->wrapMovieFilename("forwp1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("forwp0", kSeleniticStack);
+ }
+ break;
+ case 14:
+ if (mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ file = _vm->wrapMovieFilename("forws1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("forws0", kSeleniticStack);
+ }
+ break;
+ case 15:
+ if (mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ file = _vm->wrapMovieFilename("forwr1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("forwr0", kSeleniticStack);
+ }
+ break;
+ case 16:
+ if (mazeRunnerForwardAllowed(_mazeRunnerPosition)) {
+ file = _vm->wrapMovieFilename("forwl1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("forwl0", kSeleniticStack);
+ }
+ break;
+ case 17:
+ file = _vm->wrapMovieFilename("backa1", kSeleniticStack);
+ break;
+ case 18:
+ file = _vm->wrapMovieFilename("backe1", kSeleniticStack);
+ break;
+ case 19:
+ if (mazeRunnerForwardAllowed(pos)) {
+ file = _vm->wrapMovieFilename("backf1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("backf0", kSeleniticStack);
+ }
+ break;
+ case 20:
+ if (mazeRunnerForwardAllowed(pos)) {
+ file = _vm->wrapMovieFilename("backo1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("backo0", kSeleniticStack);
+ }
+ break;
+ case 21:
+ if (mazeRunnerForwardAllowed(pos)) {
+ file = _vm->wrapMovieFilename("backp1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("backp0", kSeleniticStack);
+ }
+ break;
+ case 22:
+ if (mazeRunnerForwardAllowed(pos)) {
+ file = _vm->wrapMovieFilename("backs1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("backs0", kSeleniticStack);
+ }
+ break;
+ case 23:
+ if (mazeRunnerForwardAllowed(pos)) {
+ file = _vm->wrapMovieFilename("backr1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("backr0", kSeleniticStack);
+ }
+ break;
+ case 24:
+ if (mazeRunnerForwardAllowed(pos)) {
+ file = _vm->wrapMovieFilename("backl1", kSeleniticStack);
+ } else {
+ file = _vm->wrapMovieFilename("backl0", kSeleniticStack);
+ }
+ break;
+ }
+
+ if (file != "") {
+ const Common::Rect &dest = _mazeRunnerWindow->getRect();
+ _vm->_video->playMovie(file, dest.left, dest.top, false);
+ }
+}
+
+void MystScriptParser_Selenitic::mazeRunnerUpdateCompass() {
+ if (_mazeRunnerPosition == 288 || _mazeRunnerPosition == 289) {
+ _mazeRunnerDirection = 8;
+ } else {
+ _mazeRunnerDirection = _mazeRunnerPosition % 8;
+ }
+ _mazeRunnerCompass->drawConditionalDataToScreen(_mazeRunnerDirection);
+}
+
+bool MystScriptParser_Selenitic::mazeRunnerForwardAllowed(uint16 position) {
+ uint16 move = _mazeRunnerVideos[position][1];
+ return move == 6 || move == 7;
+}
+
+void MystScriptParser_Selenitic::mazeRunnerPlaySoundHelp() {
+ uint16 soundId = 0;
+
+ _mazeRunnerLight->drawConditionalDataToScreen(1);
+
+ if (_mazeRunnerPosition >= 272)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 264)
+ soundId = 8191;
+ else if (_mazeRunnerPosition >= 256)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 248)
+ soundId = 5191;
+ else if (_mazeRunnerPosition >= 232)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 224)
+ soundId = 5191;
+ else if (_mazeRunnerPosition >= 216)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 208)
+ soundId = 5191;
+ else if (_mazeRunnerPosition >= 176)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 168)
+ soundId = 7191;
+ else if (_mazeRunnerPosition >= 152)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 144)
+ soundId = 7191;
+ else if (_mazeRunnerPosition >= 136)
+ soundId = 2191;
+ else if (_mazeRunnerPosition >= 112)
+ soundId = 0;
+ else if (_mazeRunnerPosition >= 104)
+ soundId = 6191;
+ else if (_mazeRunnerPosition >= 96)
+ soundId = 2191;
+ else if (_mazeRunnerPosition >= 88)
+ soundId = 3191;
+ else if (_mazeRunnerPosition >= 80)
+ soundId = 4191;
+ else if (_mazeRunnerPosition >= 72)
+ soundId = 8191;
+ else if (_mazeRunnerPosition >= 64)
+ soundId = 7191;
+ else if (_mazeRunnerPosition >= 56)
+ soundId = 8191;
+ else if (_mazeRunnerPosition >= 40)
+ soundId = 5191;
+ else if (_mazeRunnerPosition >= 24)
+ soundId = 1191;
+ else if (_mazeRunnerPosition >= 16)
+ soundId = 2191;
+ else if (_mazeRunnerPosition >= 8)
+ soundId = 8191;
+ else
+ soundId = 2191;
+
+ if (soundId)
+ _vm->_sound->playSound(soundId);
+
+ _mazeRunnerLight->drawConditionalDataToScreen(0);
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerSoundRepeat(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ mazeRunnerPlaySoundHelp();
+}
+
+/**
+ * Sound receiver sigma button
+ */
+void MystScriptParser_Selenitic::o_soundReceiverSigma(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ debugC(kDebugScript, "Opcode %d: Sound receiver sigma button", op);
+
+ _vm->_cursor->hideCursor();
+
+ _soundReceiverCurrentSource->drawConditionalDataToScreen(0);
+
+ uint16 *oldPosition = _soundReceiverPosition;
+ uint16 source = 0;
+
+ for (uint i = 0; i < 5; i++) {
+ switch (i) {
+ case 0:
+ source = 3;
+ break;
+ case 1:
+ source = 0;
+ break;
+ case 2:
+ source = 4;
+ break;
+ case 3:
+ source = 1;
+ break;
+ case 4:
+ source = 2;
+ break;
+ }
+
+ _soundReceiverPosition = &selenitic_vars[8 + source];
+ _vm->_sound->stopSound();
+ _vm->_sound->playSound(2287);
+ soundReceiverDrawView();
+ uint16 soundId = soundReceiverCurrentSound(source, *_soundReceiverPosition);
+ _vm->_sound->replaceSound(soundId);
+ _vm->_system->delayMillis(1000);
+ }
+
+ _soundReceiverPosition = oldPosition;
+ _soundReceiverSigmaPressed = true;
+ _vm->_sound->stopSound();
+
+ _soundReceiverSources[selenitic_vars[7]]->drawConditionalDataToScreen(1);
+
+ soundReceiverDrawView();
+
+ _vm->_cursor->showCursor();
+}
+
+/**
+ * Sound receiver right button
+ */
+void MystScriptParser_Selenitic::o_soundReceiverRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound receiver right", op);
+
+ soundReceiverLeftRight(1);
+}
+
+/**
+ * Sound receiver left button
+ */
+void MystScriptParser_Selenitic::o_soundReceiverLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound receiver left", op);
+
+ soundReceiverLeftRight(2);
+}
+
+void MystScriptParser_Selenitic::soundReceiverLeftRight(uint direction) {
+
+ if (_soundReceiverSigmaPressed) {
+ _soundReceiverSigmaButton->drawConditionalDataToScreen(0);
+ _soundReceiverSigmaPressed = false;
+ }
+
+ if (direction == 1) {
+ _soundReceiverRightButton->drawConditionalDataToScreen(1);
+ } else {
+ _soundReceiverLeftButton->drawConditionalDataToScreen(1);
+ }
+
+ _vm->_sound->stopSound();
+
+ _soundReceiverDirection = direction;
+ _soundReceiverSpeed = 1;
+ _soundReceiverStartTime = _vm->_system->getMillis();
+
+ soundReceiverUpdate();
+}
+
+void MystScriptParser_Selenitic::soundReceiverUpdate() {
+ if (_soundReceiverDirection == 1) {
+ *_soundReceiverPosition = ((*_soundReceiverPosition) + _soundReceiverSpeed) % 3600;
+ } else if (_soundReceiverDirection == 2) {
+ *_soundReceiverPosition = ((*_soundReceiverPosition) + 3600 - _soundReceiverSpeed) % 3600;
+ }
+
+ soundReceiverDrawView();
+}
+
+void MystScriptParser_Selenitic::soundReceiverDrawView() {
+ uint32 left = ((*_soundReceiverPosition) * 1800) / 3600;
+
+ _soundReceiverViewer->_subImages->rect.left = left;
+ _soundReceiverViewer->_subImages->rect.right = left + 136;
+
+ _soundReceiverViewer->drawConditionalDataToScreen(0);
+
+ soundReceiverDrawAngle();
+}
+
+void MystScriptParser_Selenitic::soundReceiverDrawAngle() {
+ _vm->redrawResource(_soundReceiverAngle1);
+ _vm->redrawResource(_soundReceiverAngle2);
+ _vm->redrawResource(_soundReceiverAngle3);
+ _vm->redrawResource(_soundReceiverAngle4);
+}
+
+/**
+ * Sound receiver source selection buttons
+ */
+void MystScriptParser_Selenitic::o_soundReceiverSource(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ debugC(kDebugScript, "Opcode %d: Sound receiver source", op);
+
+ if (_soundReceiverSigmaPressed) {
+ _soundReceiverSigmaButton->drawConditionalDataToScreen(0);
+ _soundReceiverSigmaPressed = false;
+ }
+
+ _vm->_cursor->hideCursor();
+
+ uint pressedButton = var - 9;
+
+ if (selenitic_vars[7] != pressedButton) {
+ selenitic_vars[7] = pressedButton;
+
+ _soundReceiverCurrentSource->drawConditionalDataToScreen(0);
+
+ _soundReceiverPosition = &selenitic_vars[8 + pressedButton];
+ _soundReceiverCurrentSource = _soundReceiverSources[pressedButton];
+
+ _vm->_sound->stopSound();
+
+ uint16 soundId = argv[0];
+ _vm->_sound->playSound(soundId);
+
+ _soundReceiverCurrentSource->drawConditionalDataToScreen(1);
+
+ soundReceiverDrawView();
+ }
+
+ _vm->_cursor->showCursor();
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerDoorButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ // Used for Selenitic Maze Runner Exit Logic
+ uint16 cardIdExit = argv[0];
+ uint16 cardIdEntry = argv[1];
+
+ if (_mazeRunnerPosition == 288) {
+ _vm->changeToCard(cardIdEntry, false);
+ _vm->_sound->playSound(cardIdEntry);
+ animatedUpdate(argv[2], &argv[3], 10);
+ } else if (_mazeRunnerPosition == 289) {
+ _vm->changeToCard(cardIdExit, false);
+ _vm->_sound->playSound(cardIdExit);
+ animatedUpdate(argv[2], &argv[3], 10);
+ }
+}
+
+void MystScriptParser_Selenitic::o_soundReceiverUpdateSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound receiver update sound", op);
+
+ soundReceiverUpdateSound();
+}
+
+uint16 MystScriptParser_Selenitic::soundLockCurrentSound(uint16 position, bool pixels) {
+ if ((pixels && position < 96) || (!pixels && position == 0)) {
+ return 289;
+ } else if ((pixels && position < 108) || (!pixels && position == 1)) {
+ return 1289;
+ } else if ((pixels && position < 120) || (!pixels && position == 2)) {
+ return 2289;
+ } else if ((pixels && position < 132) || (!pixels && position == 3)) {
+ return 3289;
+ } else if ((pixels && position < 144) || (!pixels && position == 4)) {
+ return 4289;
+ } else if ((pixels && position < 156) || (!pixels && position == 5)) {
+ return 5289;
+ } else if ((pixels && position < 168) || (!pixels && position == 6)) {
+ return 6289;
+ } else if ((pixels && position < 180) || (!pixels && position == 7)) {
+ return 7289;
+ } else if ((pixels && position < 192) || (!pixels && position == 8)) {
+ return 8289;
+ } else if (pixels || (!pixels && position == 9)) {
+ return 9289;
+ } else {
+ return 0;
+ }
+}
+
+MystResourceType10 *MystScriptParser_Selenitic::soundLockSliderFromVar(uint16 var) {
+ switch (var) {
+ case 20:
+ return _soundLockSlider1;
+ case 21:
+ return _soundLockSlider2;
+ case 22:
+ return _soundLockSlider3;
+ case 23:
+ return _soundLockSlider4;
+ case 24:
+ return _soundLockSlider5;
+ }
+
+ return 0;
+}
+
+void MystScriptParser_Selenitic::o_soundLockMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound lock move", op);
+
+ MystResourceType10 *slider = soundLockSliderFromVar(var);
+
+ uint16 soundId = soundLockCurrentSound(slider->_pos.y, true);
+ if (_soundLockSoundId != soundId) {
+ _soundLockSoundId = soundId;
+ _vm->_sound->replaceSound(soundId, Audio::Mixer::kMaxChannelVolume, true);
+ }
+}
+
+void MystScriptParser_Selenitic::o_soundLockStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound lock start move", op);
+
+ MystResourceType10 *slider = soundLockSliderFromVar(var);
+
+ _vm->_cursor->setCursor(700);
+ _vm->_sound->pauseBackground();
+
+ _soundLockSoundId = soundLockCurrentSound(slider->_pos.y, true);
+ _vm->_sound->replaceSound(_soundLockSoundId, Audio::Mixer::kMaxChannelVolume, true);
+}
+
+void MystScriptParser_Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound lock end move", op);
+
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+ MystResourceType10 *slider = soundLockSliderFromVar(var);
+ uint16 *value = 0;
+
+ switch (var) {
+ case 20: // Sound lock sliders
+ value = &selenitic_vars[13];
+ break;
+ case 21:
+ value = &selenitic_vars[14];
+ break;
+ case 22:
+ value = &selenitic_vars[15];
+ break;
+ case 23:
+ value = &selenitic_vars[16];
+ break;
+ case 24:
+ value = &selenitic_vars[17];
+ break;
+ }
+
+ uint16 stepped = 12 * (*value / 12) + 6;
+
+ if (stepped == 6)
+ stepped = 0;
+ if (stepped == 114)
+ stepped = 119;
+
+ *value = stepped;
+
+ slider->setStep(stepped);
+ slider->drawDataToScreen();
+ _vm->_gfx->updateScreen();
+
+ uint16 soundId = slider->getList3(0);
+ if (soundId)
+ _vm->_sound->playSoundBlocking(soundId);
+
+ _vm->_sound->stopSound();
+ _vm->_sound->resumeBackground();
+}
+
+void MystScriptParser_Selenitic::soundLockCheckSolution(MystResourceType10 *slider, uint16 value, uint16 solution, bool &solved) {
+ slider->drawConditionalDataToScreen(2);
+ _vm->_sound->playSound(soundLockCurrentSound(value / 12, false));
+ _vm->_system->delayMillis(1500);
+
+ if (value / 12 != solution) {
+ solved = false;
+ }
+
+ slider->drawConditionalDataToScreen(1);
+ _vm->_sound->stopSound();
+}
+
+void MystScriptParser_Selenitic::o_soundLockButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound lock button", op);
+
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+ bool solved = true;
+
+ _vm->_sound->pauseBackground();
+ _vm->_sound->playSound(1147);
+ _soundLockButton->drawConditionalDataToScreen(1);
+ _vm->_cursor->hideCursor();
+
+ soundLockCheckSolution(_soundLockSlider1, selenitic_vars[13], 5, solved);
+ soundLockCheckSolution(_soundLockSlider2, selenitic_vars[14], 9, solved);
+ soundLockCheckSolution(_soundLockSlider3, selenitic_vars[15], 0, solved);
+ soundLockCheckSolution(_soundLockSlider4, selenitic_vars[16], 6, solved);
+ soundLockCheckSolution(_soundLockSlider5, selenitic_vars[17], 7, solved);
+
+ _vm->_sound->playSound(1148);
+ _vm->_sound->resumeBackground();
+
+ if (solved) {
+ _soundLockButton->drawConditionalDataToScreen(2);
+
+ uint16 cardIdClosed = argv[0];
+ uint16 cardIdOpen = argv[1];
+
+ _vm->changeToCard(cardIdClosed, true);
+
+ _vm->changeToCard(cardIdOpen, false);
+ _vm->_sound->playSound(argv[2]);
+
+ animatedUpdate(argv[4], &argv[5], argv[3]);
+ } else {
+ _soundLockButton->drawConditionalDataToScreen(0);
+ }
+
+ _vm->_cursor->showCursor();
+}
+
+void MystScriptParser_Selenitic::o_soundReceiverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Sound receiver end move", op);
+
+ uint16 oldDirection = _soundReceiverDirection;
+
+ if (_soundReceiverDirection) {
+ _soundReceiverDirection = 0;
+
+ soundReceiverUpdateSound();
+
+ if (oldDirection == 1) {
+ _soundReceiverRightButton->drawConditionalDataToScreen(0);
+ } else {
+ _soundReceiverLeftButton->drawConditionalDataToScreen(0);
+ }
+
+ }
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerCompass_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ _mazeRunnerCompass = static_cast<MystResourceType8 *>(_invokingResource);
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerWindow_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ _mazeRunnerWindow = static_cast<MystResourceType8 *>(_invokingResource);
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerLight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ _mazeRunnerLight = static_cast<MystResourceType8 *>(_invokingResource);
+}
+
+void MystScriptParser_Selenitic::soundReceiver_run() {
+ if (_soundReceiverStartTime) {
+ if (_soundReceiverDirection) {
+ uint32 currentTime = _vm->_system->getMillis();
+
+ if (_soundReceiverSpeed == 50) {
+ if (currentTime > _soundReceiverStartTime + 500) {
+ soundReceiverIncreaseSpeed();
+ }
+ } else {
+ if (currentTime > _soundReceiverStartTime + 1000) {
+ soundReceiverIncreaseSpeed();
+ }
+ }
+
+ if (currentTime > _soundReceiverStartTime + 100) {
+ soundReceiverUpdate();
+ }
+
+ } else if (!_soundReceiverSigmaPressed) {
+ soundReceiverUpdateSound();
+ }
+ }
+}
+
+void MystScriptParser_Selenitic::soundReceiverIncreaseSpeed() {
+ switch (_soundReceiverSpeed) {
+ case 1:
+ _soundReceiverSpeed = 10;
+ break;
+ case 10:
+ _soundReceiverSpeed = 50;
+ break;
+ case 50:
+ _soundReceiverSpeed = 100;
+ break;
+ }
+}
+
+void MystScriptParser_Selenitic::soundReceiverUpdateSound() {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ uint16 soundId = soundReceiverCurrentSound(selenitic_vars[7], *_soundReceiverPosition);
+ _vm->_sound->replaceSound(soundId);
+}
+
+uint16 MystScriptParser_Selenitic::soundReceiverCurrentSound(uint16 source, uint16 position) {
+ uint16 solution;
+ bool sourceEnabled;
+ soundReceiverSolution(source, solution, sourceEnabled);
+
+ uint16 soundIdGood;
+ uint16 soundIdNear;
+ uint16 soundId = 1245;
+
+ switch (source) {
+ case 0:
+ soundIdNear = 3245;
+ soundIdGood = 3093;
+ break;
+ case 1:
+ soundIdNear = 5245;
+ soundIdGood = 5093;
+ break;
+ case 2:
+ soundIdNear = 6245;
+ soundIdGood = 6093;
+ break;
+ case 3:
+ soundIdNear = 2245;
+ soundIdGood = 2093;
+ break;
+ case 4:
+ soundIdNear = 4245;
+ soundIdGood = 4093;
+ break;
+ }
+
+ if (sourceEnabled) {
+ if (position == solution) {
+ soundId = soundIdGood;
+ } else if (position > solution && position <= solution + 50) {
+ _soundReceiverLeftButton->drawConditionalDataToScreen(2);
+ _soundReceiverLeftButton->drawConditionalDataToScreen(0);
+ soundId = soundIdNear;
+ } else if (position < solution && position >= solution - 50) {
+ _soundReceiverRightButton->drawConditionalDataToScreen(2);
+ _soundReceiverRightButton->drawConditionalDataToScreen(0);
+ soundId = soundIdNear;
+ }
+ }
+
+ return soundId;
+}
+
+void MystScriptParser_Selenitic::soundReceiverSolution(uint16 source, uint16 &solution, bool &enabled) {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ switch (source) {
+ case 0:
+ enabled = selenitic_vars[0];
+ solution = 1534;
+ break;
+ case 1:
+ enabled = selenitic_vars[1];
+ solution = 1303;
+ break;
+ case 2:
+ enabled = selenitic_vars[2];
+ solution = 556;
+ break;
+ case 3:
+ enabled = selenitic_vars[3];
+ solution = 150;
+ break;
+ case 4:
+ enabled = selenitic_vars[4];
+ solution = 2122;
+ break;
+ }
+}
+
+void MystScriptParser_Selenitic::o_soundReceiver_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ debugC(kDebugScript, "Opcode %d: Sound receiver init", op);
+
+ // Used for Card 1245 (Sound Receiver)
+ _soundReceiverRunning = true;
+
+ _soundReceiverRightButton = static_cast<MystResourceType8 *>(_vm->_resources[0]);
+ _soundReceiverLeftButton = static_cast<MystResourceType8 *>(_vm->_resources[1]);
+ _soundReceiverSigmaButton = static_cast<MystResourceType8 *>(_vm->_resources[2]);
+ _soundReceiverSources[4] = static_cast<MystResourceType8 *>(_vm->_resources[3]);
+ _soundReceiverSources[3] = static_cast<MystResourceType8 *>(_vm->_resources[4]);
+ _soundReceiverSources[2] = static_cast<MystResourceType8 *>(_vm->_resources[5]);
+ _soundReceiverSources[1] = static_cast<MystResourceType8 *>(_vm->_resources[6]);
+ _soundReceiverSources[0] = static_cast<MystResourceType8 *>(_vm->_resources[7]);
+ _soundReceiverViewer = static_cast<MystResourceType8 *>(_vm->_resources[8]);
+ _soundReceiverAngle1 = static_cast<MystResourceType8 *>(_vm->_resources[10]);
+ _soundReceiverAngle2 = static_cast<MystResourceType8 *>(_vm->_resources[11]);
+ _soundReceiverAngle3 = static_cast<MystResourceType8 *>(_vm->_resources[12]);
+ _soundReceiverAngle4 = static_cast<MystResourceType8 *>(_vm->_resources[13]);
+
+ uint16 currentSource = selenitic_vars[7];
+ _soundReceiverPosition = &selenitic_vars[8 + currentSource];
+ _soundReceiverCurrentSource = _soundReceiverSources[currentSource];
+
+ _soundReceiverSigmaPressed = false;
+}
+
+void MystScriptParser_Selenitic::o_soundLock_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars;
+
+ debugC(kDebugScript, "Opcode %d: Sound lock init", op);
+
+ for (uint i = 0; i < _vm->_resources.size(); i++) {
+ if (_vm->_resources[i]->type == kMystSlider) {
+ switch (_vm->_resources[i]->getType8Var()) {
+ case 20:
+ _soundLockSlider1 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider1->setStep(selenitic_vars[13]);
+ break;
+ case 21:
+ _soundLockSlider2 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider2->setStep(selenitic_vars[14]);
+ break;
+ case 22:
+ _soundLockSlider3 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider3->setStep(selenitic_vars[15]);
+ break;
+ case 23:
+ _soundLockSlider4 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider4->setStep(selenitic_vars[16]);
+ break;
+ case 24:
+ _soundLockSlider5 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider5->setStep(selenitic_vars[17]);
+ break;
+ }
+ } else if (_vm->_resources[i]->type == kMystConditionalImage) {
+ if (_vm->_resources[i]->getType8Var() == 28) {
+ _soundLockButton = static_cast<MystResourceType8 *>(_vm->_resources[i]);
+ }
+ }
+ }
+
+ _soundLockSoundId = 0;
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerRight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ _mazeRunnerRightButton = static_cast<MystResourceType8 *>(_invokingResource);
+}
+
+void MystScriptParser_Selenitic::o_mazeRunnerLeft_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ _mazeRunnerLeftButton = static_cast<MystResourceType8 *>(_invokingResource);
+}
+
+const uint16 MystScriptParser_Selenitic::_mazeRunnerMap[300][4] = {
+ {8, 7, 1, 288},
+ {1, 0, 2, 288},
+ {2, 1, 3, 288},
+ {3, 2, 4, 288},
+ {4, 3, 5, 288},
+ {5, 4, 6, 288},
+ {6, 5, 7, 288},
+ {7, 6, 0, 288},
+ {8, 15, 9, 0},
+ {9, 8, 10, 0},
+ {10, 9, 11, 0},
+ {11, 10, 12, 0},
+ {4, 11, 13, 0},
+ {13, 12, 14, 0},
+ {22, 13, 15, 0},
+ {15, 14, 8, 0},
+ {24, 23, 17, 14},
+ {17, 16, 18, 14},
+ {10, 17, 19, 14},
+ {19, 18, 20, 14},
+ {20, 19, 21, 14},
+ {21, 20, 22, 14},
+ {22, 21, 23, 14},
+ {23, 22, 16, 14},
+ {112, 31, 25, 16},
+ {25, 24, 26, 16},
+ {34, 25, 27, 16},
+ {27, 26, 28, 16},
+ {20, 27, 29, 16},
+ {29, 28, 30, 16},
+ {30, 29, 31, 16},
+ {31, 30, 24, 16},
+ {120, 39, 33, 26},
+ {33, 32, 34, 26},
+ {42, 33, 35, 26},
+ {35, 34, 36, 26},
+ {36, 35, 37, 26},
+ {37, 36, 38, 26},
+ {30, 37, 39, 26},
+ {39, 38, 32, 26},
+ {40, 47, 41, 34},
+ {143, 40, 42, 34},
+ {42, 41, 43, 34},
+ {43, 42, 44, 34},
+ {52, 43, 45, 34},
+ {45, 44, 46, 34},
+ {38, 45, 47, 34},
+ {47, 46, 40, 34},
+ {40, 55, 49, 44},
+ {49, 48, 50, 44},
+ {146, 49, 51, 44},
+ {51, 50, 52, 44},
+ {60, 51, 53, 44},
+ {53, 52, 54, 44},
+ {54, 53, 55, 44},
+ {55, 54, 48, 44},
+ {48, 63, 57, 52},
+ {57, 56, 58, 52},
+ {58, 57, 59, 52},
+ {171, 58, 60, 52},
+ {60, 59, 61, 52},
+ {61, 60, 62, 52},
+ {68, 61, 63, 52},
+ {63, 62, 56, 52},
+ {58, 71, 65, 62},
+ {65, 64, 66, 62},
+ {66, 65, 67, 62},
+ {67, 66, 68, 62},
+ {68, 67, 69, 62},
+ {77, 68, 70, 62},
+ {70, 69, 71, 62},
+ {71, 70, 64, 62},
+ {72, 79, 73, 69},
+ {65, 72, 74, 69},
+ {186, 73, 75, 69},
+ {75, 74, 76, 69},
+ {196, 75, 77, 69},
+ {77, 76, 78, 69},
+ {86, 77, 79, 69},
+ {79, 78, 72, 69},
+ {80, 87, 81, 78},
+ {81, 80, 82, 78},
+ {74, 81, 83, 78},
+ {83, 82, 84, 78},
+ {212, 83, 85, 78},
+ {229, 84, 86, 78},
+ {86, 85, 87, 78},
+ {95, 86, 80, 78},
+ {88, 95, 89, 87},
+ {97, 88, 90, 87},
+ {90, 89, 91, 87},
+ {83, 90, 92, 87},
+ {92, 91, 93, 87},
+ {93, 92, 94, 87},
+ {254, 93, 95, 87},
+ {95, 94, 88, 87},
+ {106, 103, 97, 89},
+ {97, 96, 98, 89},
+ {98, 97, 99, 89},
+ {99, 98, 100, 89},
+ {100, 99, 101, 89},
+ {93, 100, 102, 89},
+ {102, 101, 103, 89},
+ {271, 102, 96, 89},
+ {104, 111, 105, 96},
+ {105, 104, 106, 96},
+ {106, 105, 107, 96},
+ {289, 106, 108, 96},
+ {108, 107, 109, 96},
+ {109, 108, 110, 96},
+ {100, 109, 111, 96},
+ {111, 110, 104, 96},
+ {112, 119, 113, 24},
+ {113, 112, 114, 24},
+ {114, 113, 115, 24},
+ {115, 114, 116, 24},
+ {28, 115, 117, 24},
+ {117, 116, 118, 24},
+ {118, 117, 119, 24},
+ {119, 118, 112, 24},
+ {120, 127, 121, 32},
+ {121, 120, 122, 32},
+ {122, 121, 123, 32},
+ {123, 122, 124, 32},
+ {36, 123, 125, 32},
+ {125, 124, 126, 32},
+ {126, 125, 127, 32},
+ {127, 126, 120, 32},
+ {128, 135, 129, 136},
+ {129, 128, 130, 136},
+ {130, 129, 131, 136},
+ {131, 130, 132, 136},
+ {140, 131, 133, 136},
+ {133, 132, 134, 136},
+ {134, 133, 135, 136},
+ {135, 134, 128, 136},
+ {128, 143, 137, 41},
+ {137, 136, 138, 41},
+ {138, 137, 139, 41},
+ {45, 138, 140, 41},
+ {140, 139, 141, 41},
+ {141, 140, 142, 41},
+ {142, 141, 143, 41},
+ {143, 142, 136, 41},
+ {144, 151, 145, 50},
+ {145, 144, 146, 50},
+ {146, 145, 147, 50},
+ {147, 146, 148, 50},
+ {148, 147, 149, 50},
+ {157, 148, 150, 50},
+ {54, 149, 151, 50},
+ {151, 150, 144, 50},
+ {152, 159, 153, 149},
+ {145, 152, 154, 149},
+ {154, 153, 155, 149},
+ {155, 154, 156, 149},
+ {156, 155, 157, 149},
+ {157, 156, 158, 149},
+ {158, 157, 159, 149},
+ {159, 158, 152, 149},
+ {160, 167, 161, 168},
+ {161, 160, 162, 168},
+ {162, 161, 163, 168},
+ {163, 162, 164, 168},
+ {172, 163, 165, 168},
+ {165, 164, 166, 168},
+ {166, 165, 167, 168},
+ {167, 166, 160, 168},
+ {160, 175, 169, 59},
+ {169, 168, 170, 59},
+ {170, 169, 171, 59},
+ {171, 170, 172, 59},
+ {172, 171, 173, 59},
+ {181, 172, 174, 59},
+ {174, 173, 175, 59},
+ {63, 174, 168, 59},
+ {176, 183, 177, 173},
+ {169, 176, 178, 173},
+ {178, 177, 179, 173},
+ {179, 178, 180, 173},
+ {180, 179, 181, 173},
+ {181, 180, 182, 173},
+ {182, 181, 183, 173},
+ {183, 182, 176, 173},
+ {184, 191, 185, 74},
+ {185, 184, 186, 74},
+ {186, 185, 187, 74},
+ {187, 186, 188, 74},
+ {188, 187, 189, 74},
+ {189, 188, 190, 74},
+ {78, 189, 191, 74},
+ {191, 190, 184, 74},
+ {72, 199, 193, 76},
+ {193, 192, 194, 76},
+ {194, 193, 195, 76},
+ {195, 194, 196, 76},
+ {196, 195, 197, 76},
+ {197, 196, 198, 76},
+ {198, 197, 199, 76},
+ {199, 198, 192, 76},
+ {200, 207, 201, 212},
+ {201, 200, 202, 212},
+ {202, 201, 203, 212},
+ {203, 202, 204, 212},
+ {204, 203, 205, 212},
+ {205, 204, 206, 212},
+ {208, 205, 207, 212},
+ {207, 206, 200, 212},
+ {80, 215, 209, 84},
+ {209, 208, 210, 84},
+ {210, 209, 211, 84},
+ {211, 210, 212, 84},
+ {202, 211, 213, 84},
+ {213, 212, 214, 84},
+ {208, 213, 215, 84},
+ {215, 214, 208, 84},
+ {224, 223, 217, 228},
+ {217, 216, 218, 228},
+ {218, 217, 219, 228},
+ {219, 218, 220, 228},
+ {220, 219, 221, 228},
+ {221, 220, 222, 228},
+ {216, 221, 223, 228},
+ {223, 222, 216, 228},
+ {224, 231, 225, 85},
+ {81, 224, 226, 85},
+ {226, 225, 227, 85},
+ {227, 226, 228, 85},
+ {220, 227, 229, 85},
+ {229, 228, 230, 85},
+ {238, 229, 231, 85},
+ {231, 230, 224, 85},
+ {232, 239, 233, 230},
+ {233, 232, 234, 230},
+ {226, 233, 235, 230},
+ {235, 234, 236, 230},
+ {236, 235, 237, 230},
+ {237, 236, 238, 230},
+ {232, 237, 239, 230},
+ {239, 238, 232, 230},
+ {240, 247, 241, 252},
+ {241, 240, 242, 252},
+ {248, 241, 243, 252},
+ {243, 242, 244, 252},
+ {244, 243, 245, 252},
+ {245, 244, 246, 252},
+ {240, 245, 247, 252},
+ {247, 246, 240, 252},
+ {256, 255, 249, 94},
+ {249, 248, 250, 94},
+ {90, 249, 251, 94},
+ {251, 250, 252, 94},
+ {246, 251, 253, 94},
+ {253, 252, 254, 94},
+ {248, 253, 255, 94},
+ {255, 254, 248, 94},
+ {256, 263, 257, 248},
+ {257, 256, 258, 248},
+ {258, 257, 259, 248},
+ {259, 258, 260, 248},
+ {252, 259, 261, 248},
+ {261, 260, 262, 248},
+ {256, 261, 263, 248},
+ {263, 262, 256, 248},
+ {280, 271, 265, 103},
+ {265, 264, 266, 103},
+ {266, 265, 267, 103},
+ {99, 266, 268, 103},
+ {268, 267, 269, 103},
+ {269, 268, 270, 103},
+ {278, 269, 271, 103},
+ {271, 270, 264, 103},
+ {272, 279, 273, 270},
+ {273, 272, 274, 270},
+ {266, 273, 275, 270},
+ {275, 274, 276, 270},
+ {276, 275, 277, 270},
+ {277, 276, 278, 270},
+ {272, 277, 279, 270},
+ {279, 278, 272, 270},
+ {280, 287, 281, 264},
+ {281, 280, 282, 264},
+ {282, 281, 283, 264},
+ {283, 282, 284, 264},
+ {268, 283, 285, 264},
+ {285, 284, 286, 264},
+ {280, 285, 287, 264},
+ {287, 286, 280, 264},
+ {0, 288, 288, 288},
+ {289, 289, 289, 107},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0}
+ };
+
+const uint8 MystScriptParser_Selenitic::_mazeRunnerVideos[300][4] = {
+ {3, 6, 10, 17},
+ {0, 5, 8, 17},
+ {0, 4, 8, 17},
+ {0, 4, 8, 17},
+ {0, 4, 8, 17},
+ {0, 4, 8, 17},
+ {0, 4, 8, 17},
+ {0, 4, 9, 17},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {12, 6, 10, 19},
+ {0, 5, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {14, 6, 10, 20},
+ {0, 5, 9, 20},
+ {13, 6, 10, 20},
+ {0, 5, 9, 20},
+ {12, 6, 10, 20},
+ {0, 5, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 9, 20},
+ {12, 6, 10, 21},
+ {0, 5, 9, 21},
+ {3, 6, 10, 21},
+ {0, 5, 8, 21},
+ {12, 4, 8, 21},
+ {0, 4, 9, 21},
+ {13, 6, 10, 21},
+ {0, 5, 9, 21},
+ {0, 4, 9, 19},
+ {16, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 9, 19},
+ {12, 6, 10, 19},
+ {0, 5, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {3, 6, 10, 20},
+ {0, 5, 9, 20},
+ {13, 6, 10, 20},
+ {0, 5, 9, 20},
+ {14, 6, 10, 20},
+ {0, 5, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 9, 20},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 9, 22},
+ {3, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 9, 22},
+ {16, 6, 10, 22},
+ {0, 5, 9, 22},
+ {15, 6, 10, 24},
+ {0, 5, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 9, 24},
+ {14, 6, 10, 24},
+ {0, 5, 8, 24},
+ {0, 4, 9, 24},
+ {0, 4, 9, 22},
+ {14, 6, 11, 22},
+ {12, 7, 10, 22},
+ {0, 5, 9, 22},
+ {13, 6, 10, 22},
+ {0, 5, 9, 22},
+ {3, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 5, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 9, 19},
+ {14, 6, 11, 19},
+ {3, 7, 10, 19},
+ {0, 5, 9, 19},
+ {14, 6, 10, 19},
+ {0, 4, 9, 22},
+ {3, 6, 10, 22},
+ {0, 5, 9, 22},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 9, 22},
+ {3, 6, 10, 22},
+ {0, 5, 8, 22},
+ {15, 7, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 9, 19},
+ {14, 6, 11, 19},
+ {0, 4, 8, 23},
+ {0, 4, 8, 23},
+ {0, 4, 9, 23},
+ {2, 6, 10, 23},
+ {0, 5, 8, 23},
+ {0, 4, 9, 23},
+ {16, 6, 10, 23},
+ {0, 5, 8, 23},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 9, 22},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 9, 20},
+ {12, 6, 10, 20},
+ {0, 5, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {3, 6, 10, 24},
+ {0, 5, 8, 24},
+ {0, 4, 9, 24},
+ {15, 6, 10, 24},
+ {0, 5, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 9, 24},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 9, 21},
+ {3, 6, 11, 21},
+ {13, 7, 10, 21},
+ {0, 5, 8, 21},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 9, 22},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {14, 7, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 9, 19},
+ {3, 6, 11, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 9, 20},
+ {12, 6, 10, 20},
+ {0, 5, 8, 20},
+ {13, 6, 10, 21},
+ {0, 5, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 9, 21},
+ {0, 4, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 8, 24},
+ {0, 4, 9, 24},
+ {15, 6, 10, 24},
+ {0, 5, 8, 24},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 9, 22},
+ {16, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 9, 22},
+ {12, 6, 10, 20},
+ {0, 5, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 8, 20},
+ {0, 4, 9, 20},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 9, 19},
+ {12, 6, 10, 19},
+ {0, 5, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 23},
+ {0, 4, 9, 23},
+ {16, 6, 10, 23},
+ {0, 5, 8, 23},
+ {0, 4, 8, 23},
+ {0, 4, 8, 23},
+ {0, 4, 8, 23},
+ {0, 4, 8, 23},
+ {14, 6, 10, 19},
+ {0, 5, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 9, 19},
+ {15, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 9, 22},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 8, 22},
+ {0, 4, 8, 22},
+ {3, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 9, 22},
+ {14, 6, 10, 22},
+ {0, 5, 8, 22},
+ {0, 4, 9, 22},
+ {13, 6, 10, 22},
+ {0, 5, 9, 22},
+ {0, 4, 8, 21},
+ {0, 4, 9, 21},
+ {12, 6, 10, 21},
+ {0, 5, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 21},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 9, 19},
+ {3, 6, 10, 19},
+ {0, 5, 8, 19},
+ {0, 4, 8, 19},
+ {0, 4, 8, 19},
+ {1, 0, 0, 0},
+ {0, 0, 0, 18},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+ };
+} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_stacks/selenitic.h b/engines/mohawk/myst_stacks/selenitic.h
new file mode 100644
index 0000000000..8ea12012eb
--- /dev/null
+++ b/engines/mohawk/myst_stacks/selenitic.h
@@ -0,0 +1,139 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MYST_SCRIPTS_SELENITIC_H
+#define MYST_SCRIPTS_SELENITIC_H
+
+#include "common/scummsys.h"
+#include "common/util.h"
+#include "mohawk/myst_scripts.h"
+
+namespace Mohawk {
+
+#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
+
+class MohawkEngine_Myst;
+class MystResourceType8;
+struct MystScriptEntry;
+
+class MystScriptParser_Selenitic : public MystScriptParser {
+public:
+ MystScriptParser_Selenitic(MohawkEngine_Myst *vm);
+ ~MystScriptParser_Selenitic();
+
+ void disablePersistentScripts();
+ void runPersistentScripts();
+
+private:
+ void setupOpcodes();
+ uint16 getVar(uint16 var);
+ void toggleVar(uint16 var);
+ bool setVarValue(uint16 var, uint16 value);
+
+ DECLARE_OPCODE(o_mazeRunnerMove);
+ DECLARE_OPCODE(o_mazeRunnerSoundRepeat);
+ DECLARE_OPCODE(o_soundReceiverSigma);
+ DECLARE_OPCODE(o_soundReceiverRight);
+ DECLARE_OPCODE(o_soundReceiverLeft);
+ DECLARE_OPCODE(o_soundReceiverSource);
+ DECLARE_OPCODE(o_mazeRunnerDoorButton);
+ DECLARE_OPCODE(o_soundReceiverUpdateSound);
+ DECLARE_OPCODE(o_soundLockMove);
+ DECLARE_OPCODE(o_soundLockStartMove);
+ DECLARE_OPCODE(o_soundLockEndMove);
+ DECLARE_OPCODE(o_soundLockButton);
+ DECLARE_OPCODE(o_soundReceiverEndMove);
+
+ DECLARE_OPCODE(o_mazeRunnerCompass_init);
+ DECLARE_OPCODE(o_mazeRunnerWindow_init);
+ DECLARE_OPCODE(o_mazeRunnerLight_init);
+ DECLARE_OPCODE(o_soundReceiver_init);
+ DECLARE_OPCODE(o_soundLock_init);
+ DECLARE_OPCODE(o_mazeRunnerRight_init);
+ DECLARE_OPCODE(o_mazeRunnerLeft_init);
+
+ void soundReceiver_run();
+
+ bool _soundReceiverRunning;
+ bool _soundReceiverSigmaPressed; // 6
+ MystResourceType8 *_soundReceiverSources[5]; // 92 -> 108
+ MystResourceType8 *_soundReceiverCurrentSource; // 112
+ uint16 *_soundReceiverPosition; // 116
+ uint16 _soundReceiverDirection; // 120
+ uint16 _soundReceiverSpeed; // 122
+ uint32 _soundReceiverStartTime; //124
+ MystResourceType8 *_soundReceiverViewer; // 128
+ MystResourceType8 *_soundReceiverRightButton; // 132
+ MystResourceType8 *_soundReceiverLeftButton; // 136
+ MystResourceType8 *_soundReceiverAngle1; // 140
+ MystResourceType8 *_soundReceiverAngle2; // 144
+ MystResourceType8 *_soundReceiverAngle3; // 148
+ MystResourceType8 *_soundReceiverAngle4; // 152
+ MystResourceType8 *_soundReceiverSigmaButton; // 156
+
+ static const uint16 _mazeRunnerMap[300][4];
+ static const uint8 _mazeRunnerVideos[300][4];
+
+ uint16 _mazeRunnerPosition; // 56
+ uint16 _mazeRunnerDirection; // 58
+ MystResourceType8 *_mazeRunnerWindow; // 68
+ MystResourceType8 *_mazeRunnerCompass; // 72
+ MystResourceType8 *_mazeRunnerLight; // 76
+ MystResourceType8 *_mazeRunnerRightButton; // 80
+ MystResourceType8 *_mazeRunnerLeftButton; // 84
+ bool _mazeRunnerDoorOpened; // 160
+
+ uint16 _soundLockSoundId;
+ MystResourceType10 *_soundLockSlider1; // 164
+ MystResourceType10 *_soundLockSlider2; // 168
+ MystResourceType10 *_soundLockSlider3; // 172
+ MystResourceType10 *_soundLockSlider4; // 176
+ MystResourceType10 *_soundLockSlider5; // 180
+ MystResourceType8 *_soundLockButton; // 184
+
+ void soundReceiverLeftRight(uint direction);
+ void soundReceiverUpdate();
+ void soundReceiverDrawView();
+ void soundReceiverDrawAngle();
+ void soundReceiverIncreaseSpeed();
+ void soundReceiverUpdateSound();
+ uint16 soundReceiverCurrentSound(uint16 source, uint16 position);
+ void soundReceiverSolution(uint16 source, uint16 &solution, bool &enabled);
+
+ uint16 soundLockCurrentSound(uint16 position, bool pixels);
+ MystResourceType10 *soundLockSliderFromVar(uint16 var);
+ void soundLockCheckSolution(MystResourceType10 *slider, uint16 value, uint16 solution, bool &solved);
+
+ bool mazeRunnerForwardAllowed(uint16 position);
+ void mazeRunnerUpdateCompass();
+ void mazeRunnerPlaySoundHelp();
+ void mazeRunnerPlayVideo(uint16 video, uint16 pos);
+};
+
+}
+
+#undef DECLARE_OPCODE
+
+#endif