From 6a4ff1a9b52c2dd31b951ad9e3362da5f29b37fc Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Mon, 29 Nov 2010 20:49:42 +0000 Subject: MOHAWK : Finished implementing Selenitic sound receiver svn-id: r54593 --- engines/mohawk/console.cpp | 4 +- engines/mohawk/mohawk.cpp | 10 + engines/mohawk/mohawk.h | 1 + engines/mohawk/myst.cpp | 119 +++-- engines/mohawk/myst.h | 19 +- engines/mohawk/myst_saveload.h | 3 +- engines/mohawk/myst_scripts.cpp | 74 ++-- engines/mohawk/myst_scripts.h | 5 + engines/mohawk/myst_scripts_myst.cpp | 31 +- engines/mohawk/myst_scripts_selenitic.cpp | 705 +++++++++++++++++++++--------- engines/mohawk/myst_scripts_selenitic.h | 53 ++- engines/mohawk/resource.cpp | 26 ++ engines/mohawk/resource.h | 1 + engines/mohawk/sound.cpp | 21 + engines/mohawk/sound.h | 2 + 15 files changed, 758 insertions(+), 316 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index e4fe9e0f8b..1e669c2b20 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -86,9 +86,9 @@ bool MystConsole::Cmd_Var(int argc, const char **argv) { } if (argc > 2) - _vm->_varStore->setVar((uint16)atoi(argv[1]), (uint32)atoi(argv[2])); + _vm->_scriptParser->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2])); - DebugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_varStore->getVar((uint16)atoi(argv[1]))); + DebugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1]))); return true; } diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp index 623f251e1a..fbe52da998 100644 --- a/engines/mohawk/mohawk.cpp +++ b/engines/mohawk/mohawk.cpp @@ -134,4 +134,14 @@ uint16 MohawkEngine::findResourceID(uint32 tag, const Common::String &resName) { return 0xFFFF; } +Common::String MohawkEngine::getResourceName(uint32 tag, uint16 id) { + for (uint32 i = 0; i < _mhk.size(); i++) + if (_mhk[i]->hasResource(tag, id)) { + return _mhk[i]->getName(tag, id); + } + + error("Could not find a \'%s\' resource with ID %04x", tag2str(tag), id); + return 0; +} + } // End of namespace Mohawk diff --git a/engines/mohawk/mohawk.h b/engines/mohawk/mohawk.h index e7d1902790..125296c03d 100644 --- a/engines/mohawk/mohawk.h +++ b/engines/mohawk/mohawk.h @@ -108,6 +108,7 @@ public: bool hasResource(uint32 tag, const Common::String &resName); uint32 getResourceOffset(uint32 tag, uint16 id); uint16 findResourceID(uint32 type, const Common::String &resName); + Common::String getResourceName(uint32 tag, uint16 id); void pauseGame(); diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp index 1a237db916..d8460e6201 100644 --- a/engines/mohawk/myst.cpp +++ b/engines/mohawk/myst.cpp @@ -247,12 +247,12 @@ Common::Error MohawkEngine_Myst::run() { else if (getFeatures() & GF_DEMO) changeToStack(kDemoStack); else - changeToStack(kIntroStack); + changeToStack(kSeleniticStack); if (getFeatures() & GF_DEMO) changeToCard(2000); else - changeToCard(1); + changeToCard(1282); // Load game from launcher/command line if requested if (ConfMan.hasKey("save_slot") && !(getFeatures() & GF_DEMO)) { @@ -416,10 +416,10 @@ void MohawkEngine_Myst::changeToCard(uint16 card) { // Handle images if (_view.conditionalImageCount != 0) { for (uint16 i = 0; i < _view.conditionalImageCount; i++) { - if (_varStore->getVar(_view.conditionalImages[i].var) < _view.conditionalImages[i].numStates) - _gfx->copyImageToScreen(_view.conditionalImages[i].values[_varStore->getVar(_view.conditionalImages[i].var)], Common::Rect(0, 0, 544, 333)); + if (_scriptParser->getVar(_view.conditionalImages[i].var) < _view.conditionalImages[i].numStates) + _gfx->copyImageToScreen(_view.conditionalImages[i].values[_scriptParser->getVar(_view.conditionalImages[i].var)], Common::Rect(0, 0, 544, 333)); else - warning("Conditional image %d variable %d: %d exceeds maximum state of %d", i, _view.conditionalImages[i].var, _varStore->getVar(_view.conditionalImages[i].var), _view.conditionalImages[i].numStates-1); + warning("Conditional image %d variable %d: %d exceeds maximum state of %d", i, _view.conditionalImages[i].var, _scriptParser->getVar(_view.conditionalImages[i].var), _view.conditionalImages[i].numStates-1); } } else if (_view.mainImage != 0) _gfx->copyImageToScreen(_view.mainImage, Common::Rect(0, 0, 544, 333)); @@ -429,7 +429,7 @@ void MohawkEngine_Myst::changeToCard(uint16 card) { uint16 soundActionVolume = 0; if (_view.sound == kMystSoundActionConditional) { - uint16 soundVarValue = _varStore->getVar(_view.soundVar); + uint16 soundVarValue = _scriptParser->getVar(_view.soundVar); if (soundVarValue >= _view.soundCount) warning("Conditional sound variable outside range"); else { @@ -846,7 +846,7 @@ void MohawkEngine_Myst::checkCursorHints() { for (uint16 i = 0; i < _cursorHintCount; i++) if (_cursorHints[i].id == _curResource && _resources[_cursorHints[i].id]->isEnabled()) { if (_cursorHints[i].cursor == -1) { - uint16 var_value = _varStore->getVar(_cursorHints[i].variableHint.var); + uint16 var_value = _scriptParser->getVar(_cursorHints[i].variableHint.var); if (var_value >= _cursorHints[i].variableHint.numStates) warning("Variable %d Out of Range in variable HINT Resource %d", _cursorHints[i].variableHint.var, i); @@ -1111,7 +1111,7 @@ void MystResourceType7::drawDataToScreen() { else if (_numSubResources != 0) warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources); } else { - uint16 varValue = _vm->_varStore->getVar(_var7); + uint16 varValue = _vm->_scriptParser->getVar(_var7); if (_numSubResources == 1 && varValue != 0) _subResources[0]->drawDataToScreen(); @@ -1131,7 +1131,7 @@ void MystResourceType7::handleAnimation() { else if (_numSubResources != 0) warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources); } else { - uint16 varValue = _vm->_varStore->getVar(_var7); + uint16 varValue = _vm->_scriptParser->getVar(_var7); if (_numSubResources == 1 && varValue != 0) _subResources[0]->handleAnimation(); @@ -1151,7 +1151,7 @@ void MystResourceType7::handleMouseUp() { else if (_numSubResources != 0) warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources); } else { - uint16 varValue = _vm->_varStore->getVar(_var7); + uint16 varValue = _vm->_scriptParser->getVar(_var7); if (_numSubResources == 1 && varValue != 0) _subResources[0]->handleMouseUp(); @@ -1171,7 +1171,7 @@ void MystResourceType7::handleMouseDown() { else if (_numSubResources != 0) warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources); } else { - uint16 varValue = _vm->_varStore->getVar(_var7); + uint16 varValue = _vm->_scriptParser->getVar(_var7); if (_numSubResources == 1 && varValue != 0) _subResources[0]->handleMouseDown(); @@ -1191,7 +1191,7 @@ void MystResourceType7::handleMouseEnter() { else if (_numSubResources != 0) warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources); } else { - uint16 varValue = _vm->_varStore->getVar(_var7); + uint16 varValue = _vm->_scriptParser->getVar(_var7); if (_numSubResources == 1 && varValue != 0) _subResources[0]->handleMouseEnter(); @@ -1211,7 +1211,7 @@ void MystResourceType7::handleMouseLeave() { else if (_numSubResources != 0) warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources); } else { - uint16 varValue = _vm->_varStore->getVar(_var7); + uint16 varValue = _vm->_scriptParser->getVar(_var7); if (_numSubResources == 1 && varValue != 0) _subResources[0]->handleMouseLeave(); @@ -1277,7 +1277,7 @@ void MystResourceType8::drawDataToScreen() { } else if (_numSubImages != 0) warning("Type 8 Resource with _numSubImages of %d, but no control variable", _numSubImages); } else { - uint16 varValue = _vm->_varStore->getVar(_var8); + uint16 varValue = _vm->_scriptParser->getVar(_var8); if (_numSubImages == 1 && varValue != 0) { subImageId = 0; @@ -1306,8 +1306,54 @@ void MystResourceType8::drawDataToScreen() { imageToDraw = _vm->_view.mainImage; else { for (uint16 i = 0; i < _vm->_view.conditionalImageCount; i++) - if (_vm->_varStore->getVar(_vm->_view.conditionalImages[i].var) < _vm->_view.conditionalImages[i].numStates) - imageToDraw = _vm->_view.conditionalImages[i].values[_vm->_varStore->getVar(_vm->_view.conditionalImages[i].var)]; + if (_vm->_scriptParser->getVar(_vm->_view.conditionalImages[i].var) < _vm->_view.conditionalImages[i].numStates) + imageToDraw = _vm->_view.conditionalImages[i].values[_vm->_scriptParser->getVar(_vm->_view.conditionalImages[i].var)]; + } + } else + imageToDraw = _subImages[subImageId].wdib; + + _vm->_gfx->copyImageSectionToScreen(imageToDraw, _subImages[subImageId].rect, _rect); + } +} + +void MystResourceType8::drawConditionalDataToScreen(uint16 state) { + // Need to call overidden Type 7 function to ensure + // switch section is processed correctly. + MystResourceType7::drawDataToScreen(); + + bool drawSubImage = false; + int16 subImageId = 0; + + + if (_numSubImages == 1 && state != 0) { + subImageId = 0; + drawSubImage = true; + } else if (_numSubImages != 0) { + if (state < _numSubImages) { + subImageId = state; + drawSubImage = true; + } else + warning("Type 8 Image Var %d: %d exceeds number of subImages %d", _var8, state, _numSubImages); + } + + + if (drawSubImage) { + uint16 imageToDraw = 0; + + if (_subImages[subImageId].wdib == 0xFFFF) { + // TODO: Think the reason for problematic screen updates in some rects is that they + // are these -1 cases. + // They need to be redrawn i.e. if the Myst marker switches are changed, but I don't think + // the rects are valid. This does not matter in the original engine as the screen update redraws + // the VIEW images, followed by the RLST resource images, and -1 for the WDIB is interpreted as + // "Do Not Draw Image" i.e so the VIEW image is shown through.. We need to fix screen update + // to do this same behaviour. + if (_vm->_view.conditionalImageCount == 0) + imageToDraw = _vm->_view.mainImage; + else { + for (uint16 i = 0; i < _vm->_view.conditionalImageCount; i++) + if (_vm->_scriptParser->getVar(_vm->_view.conditionalImages[i].var) < _vm->_view.conditionalImages[i].numStates) + imageToDraw = _vm->_view.conditionalImages[i].values[_vm->_scriptParser->getVar(_vm->_view.conditionalImages[i].var)]; } } else imageToDraw = _subImages[subImageId].wdib; @@ -1380,8 +1426,22 @@ MystResourceType10::~MystResourceType10() { delete[] _lists[i].list; } +void MystResourceType10::handleMouseDown() { + _mouseDown = true; + + _vm->_scriptParser->runOpcode(_mouseDownOpcode); +} + void MystResourceType10::handleMouseUp() { - // TODO + _mouseDown = false; + + _vm->_scriptParser->runOpcode(_mouseUpOpcode); +} + +void MystResourceType10::handleAnimation() { + if (_mouseDown) { + _vm->_scriptParser->runOpcode(_mouseDragOpcode); + } } MystResourceType11::MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResourceType8(vm, rlstStream, parent) { @@ -1433,7 +1493,7 @@ MystResourceType11::MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableRe } } - warning("TODO: Card contains Type 11 Resource - Function not yet implemented"); + _mouseDown = false; } MystResourceType11::~MystResourceType11() { @@ -1441,16 +1501,21 @@ MystResourceType11::~MystResourceType11() { delete[] _lists[i].list; } +void MystResourceType11::handleMouseDown() { + _mouseDown = true; + + _vm->_scriptParser->runOpcode(_mouseDownOpcode); +} + void MystResourceType11::handleMouseUp() { - // TODO - - // HACK: Myst Card 4059 (Fireplace Code Book) to usuable state - if (_mouseDownOpcode == 191) { - uint16 tmp = _vm->_varStore->getVar(0); - if (tmp > 0) - _vm->_varStore->setVar(0, tmp - 1); - } else if (_mouseDownOpcode == 190) { - _vm->_varStore->setVar(0, _vm->_varStore->getVar(0) + 1); + _mouseDown = false; + + _vm->_scriptParser->runOpcode(_mouseUpOpcode); +} + +void MystResourceType11::handleAnimation() { + if (_mouseDown) { + _vm->_scriptParser->runOpcode(_mouseDragOpcode); } } diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h index 3126fdd4fc..fcd9e709a3 100644 --- a/engines/mohawk/myst.h +++ b/engines/mohawk/myst.h @@ -157,6 +157,7 @@ public: bool contains(Common::Point point) { return _rect.contains(point); } virtual void drawDataToScreen() {} + virtual void drawConditionalDataToScreen(uint16 state) {} virtual void handleAnimation() {} virtual Common::Rect getRect() { return _rect; } bool isEnabled() { return _enabled; } @@ -232,15 +233,17 @@ public: MystResourceType8(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent); virtual ~MystResourceType8(); void drawDataToScreen(); + void drawConditionalDataToScreen(uint16 state); uint16 getType8Var(); -protected: - uint16 _var8; - uint16 _numSubImages; struct SubImage { uint16 wdib; Common::Rect rect; } *_subImages; + +protected: + uint16 _var8; + uint16 _numSubImages; }; // No MystResourceType9! @@ -249,6 +252,8 @@ class MystResourceType10 : public MystResourceType8 { public: MystResourceType10(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent); virtual ~MystResourceType10(); + void handleAnimation(); + void handleMouseDown(); void handleMouseUp(); protected: @@ -263,12 +268,16 @@ protected: uint16 listCount; uint16 *list; } _lists[4]; + + bool _mouseDown; }; class MystResourceType11 : public MystResourceType8 { public: MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent); virtual ~MystResourceType11(); + void handleAnimation(); + void handleMouseDown(); void handleMouseUp(); protected: @@ -283,6 +292,8 @@ protected: uint16 listCount; uint16 *list; } _lists[3]; + + bool _mouseDown; }; class MystResourceType12 : public MystResourceType8 { @@ -366,6 +377,7 @@ public: MystGraphics *_gfx; MystSaveLoad *_saveLoad; MystScriptParser *_scriptParser; + Common::Array _resources; bool _showResourceRects; void setResourceEnabled(uint16 resourceId, bool enable); @@ -400,7 +412,6 @@ private: void loadHelp(uint16 id); - Common::Array _resources; void loadResources(); void drawResourceRects(); void checkCurrentResource(); diff --git a/engines/mohawk/myst_saveload.h b/engines/mohawk/myst_saveload.h index 33dd9a7e07..f24d1addc3 100644 --- a/engines/mohawk/myst_saveload.h +++ b/engines/mohawk/myst_saveload.h @@ -201,10 +201,11 @@ public: void initMystVariables(MystVariables *_tv); void debug_printMystVariables(MystVariables *_tv); + + MystVariables *_v; private: MohawkEngine_Myst *_vm; Common::SaveFileManager *_saveFileMan; - MystVariables *_v; }; } // End of namespace Mohawk diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp index 976a6d50a6..fcc2680faa 100644 --- a/engines/mohawk/myst_scripts.cpp +++ b/engines/mohawk/myst_scripts.cpp @@ -97,7 +97,8 @@ void MystScriptParser::setupOpcodes() { OPCODE(7, opcode_7), OPCODE(8, opcode_8), OPCODE(9, opcode_9), - // Opcode 10 to 11 Not Present + OPCODE(10, opcode_10), + // Opcode 11 Not Present OPCODE(12, altDest), OPCODE(13, altDest), OPCODE(14, opcode_14), @@ -111,7 +112,7 @@ void MystScriptParser::setupOpcodes() { OPCODE(22, opcode_22), OPCODE(23, opcode_23), OPCODE(24, playSound), - // Opcode 25 Not Present + // Opcode 25 Not Present, original calls replaceSound OPCODE(26, opcode_26), OPCODE(27, playSoundBlocking), OPCODE(28, opcode_28), @@ -211,6 +212,22 @@ MystScript MystScriptParser::readScript(Common::SeekableReadStream *stream, Myst return script; } +uint16 MystScriptParser::getVar(uint16 var) { + warning("Unimplemented var getter 0x%02x (%d)", var, var); + return _vm->_varStore->getVar(var); +} + +void MystScriptParser::toggleVar(uint16 var) { + warning("Unimplemented var toggle 0x%02x (%d)", var, var); + _vm->_varStore->setVar(var, (_vm->_varStore->getVar(var) + 1) % 2); +} + +bool MystScriptParser::setVarValue(uint16 var, uint16 value) { + warning("Unimplemented var setter 0x%02x (%d)", var, var); + _vm->_varStore->setVar(var, value); + return false; +} + // NOTE: Check to be used on Opcodes where var is thought // not to be used. This emits a warning if var is nonzero. // It is possible that the opcode does use var 0 in this case, @@ -240,33 +257,19 @@ void MystScriptParser::NOP(uint16 op, uint16 var, uint16 argc, uint16 *argv) { } void MystScriptParser::toggleBoolean(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 0) { - debugC(kDebugScript, "Opcode %d: toggleBoolean() var %d", op, var); - // HACK: This Mech Card seems to be a special case... Are there others, - // or a more general definition of this opcode? - if (_vm->getCurStack() == kMechanicalStack && _vm->getCurCard() == 6267) - _vm->_varStore->setVar(var, (_vm->_varStore->getVar(var) + 1) % 10); - else - _vm->_varStore->setVar(var, !_vm->_varStore->getVar(var)); - } else - unknown(op, var, argc, argv); + toggleVar(var); } void MystScriptParser::setVar(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 1) { - debugC(kDebugScript, "Opcode %d: setVar var %d = %d", op, var, argv[0]); - - _vm->_varStore->setVar(var, argv[0]); - } else - unknown(op, var, argc, argv); + setVarValue(var, argv[0]); } void MystScriptParser::altDest(uint16 op, uint16 var, uint16 argc, uint16 *argv) { if (argc == 1) { // TODO: Work out any differences between opcode 2, 12 and 13.. - debugC(kDebugScript, "Opcode %d: altDest var %d: %d", op, var, _vm->_varStore->getVar(var)); + debugC(kDebugScript, "Opcode %d: altDest var %d: %d", op, var, getVar(var)); - if (_vm->_varStore->getVar(var)) + if (getVar(var)) _vm->changeToCard(argv[0]); else if (_invokingResource != NULL) _vm->changeToCard(_invokingResource->getDest()); @@ -282,17 +285,17 @@ void MystScriptParser::takePage(uint16 op, uint16 var, uint16 argc, uint16 *argv debugC(kDebugScript, "Opcode %d: takePage Var %d CursorId %d", op, var, cursorId); - if (_vm->_varStore->getVar(var)) { + if (getVar(var)) { _vm->setMainCursor(cursorId); - _vm->_varStore->setVar(var, 0); + setVarValue(var, 0); // Return pages that are already held if (var == 102) - _vm->_varStore->setVar(103, 1); + setVarValue(103, 1); if (var == 103) - _vm->_varStore->setVar(102, 1); + setVarValue(102, 1); } } else unknown(op, var, argc, argv); @@ -306,7 +309,7 @@ void MystScriptParser::opcode_4(uint16 op, uint16 var, uint16 argc, uint16 *argv // as it breaks Selenitic Card 1257, though this may be due to screen update. Also, // this may actually be a "Force Card Reload" or "VIEW conditional re-evaluation".. in // the general case, rather than this image blit... - uint16 var_value = _vm->_varStore->getVar(var); + uint16 var_value = getVar(var); if (var_value < _vm->_view.scriptResCount) { if (_vm->_view.scriptResources[var_value].type == 1) { // TODO: Add Symbols for Types _vm->_gfx->copyImageToScreen(_vm->_view.scriptResources[var_value].id, Common::Rect(0, 0, 544, 333)); @@ -389,15 +392,18 @@ void MystScriptParser::opcode_9(uint16 op, uint16 var, uint16 argc, uint16 *argv unknown(op, var, argc, argv); } +void MystScriptParser::opcode_10(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + varUnusedCheck(op, var); + + unknown(op, var, argc, argv); +} + void MystScriptParser::opcode_14(uint16 op, uint16 var, uint16 argc, uint16 *argv) { if (argc == 1) { debugC(kDebugScript, "Opcode %d: Unknown, 1 Argument: %d", op, argv[0]); debugC(kDebugScript, "\tVar: %d", var); - // TODO: Function Unknown... - // Function looks like it changes the Var8 of the invoking resource to argument value.. - // Most calls seem to have var = 0, but used in Myst Card 4500 (Execute Button) - // with Var 105.. + _invokingResource->drawConditionalDataToScreen(argv[0]); } else unknown(op, var, argc, argv); } @@ -408,7 +414,7 @@ void MystScriptParser::dropPage(uint16 op, uint16 var, uint16 argc, uint16 *argv debugC(kDebugScript, "\tvar: %d", var); // TODO: Need to check where this is used - _vm->_varStore->setVar(var, 1); + setVarValue(var, 1); } else unknown(op, var, argc, argv); } @@ -674,8 +680,8 @@ void MystScriptParser::opcode_28(uint16 op, uint16 var, uint16 argc, uint16 *arg imageToDraw = _vm->_view.mainImage; else { for (uint16 i = 0; i < _vm->_view.conditionalImageCount; i++) - if (_vm->_varStore->getVar(_vm->_view.conditionalImages[i].var) < _vm->_view.conditionalImages[i].numStates) - imageToDraw = _vm->_view.conditionalImages[i].values[_vm->_varStore->getVar(_vm->_view.conditionalImages[i].var)]; + if (getVar(_vm->_view.conditionalImages[i].var) < _vm->_view.conditionalImages[i].numStates) + imageToDraw = _vm->_view.conditionalImages[i].values[getVar(_vm->_view.conditionalImages[i].var)]; } _vm->_gfx->copyImageSectionToScreen(imageToDraw, rect, rect); } else @@ -747,7 +753,7 @@ void MystScriptParser::opcode_30(uint16 op, uint16 var, uint16 argc, uint16 *arg } else if (soundAction == kMystSoundActionConditional) { debugC(kDebugScript, "Conditional sound list"); uint16 condVar = argv[decodeIdx++]; - uint16 condVarValue = _vm->_varStore->getVar(condVar); + uint16 condVarValue = getVar(condVar); uint16 condCount = argv[decodeIdx++]; debugC(kDebugScript, "\tcondVar: %d = %d", condVar, condVarValue); @@ -820,7 +826,7 @@ void MystScriptParser::opcode_31(uint16 op, uint16 var, uint16 argc, uint16 *arg debugC(kDebugScript, "\tsoundId0: %d", soundId0); debugC(kDebugScript, "\tsoundId1: %d", soundId1); - if (_vm->_varStore->getVar(var)) { + if (getVar(var)) { if (soundId1) _vm->_sound->playSound(soundId1); } else { diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h index 59974d9003..ea8d8b92f6 100644 --- a/engines/mohawk/myst_scripts.h +++ b/engines/mohawk/myst_scripts.h @@ -72,6 +72,10 @@ public: virtual void disableInitOpcodes() = 0; virtual void runPersistentOpcodes() = 0; + virtual uint16 getVar(uint16 var); + virtual void toggleVar(uint16 var); + virtual bool setVarValue(uint16 var, uint16 value); + DECLARE_OPCODE(unknown); DECLARE_OPCODE(toggleBoolean); @@ -83,6 +87,7 @@ public: DECLARE_OPCODE(opcode_7); DECLARE_OPCODE(opcode_8); DECLARE_OPCODE(opcode_9); + DECLARE_OPCODE(opcode_10); DECLARE_OPCODE(opcode_14); DECLARE_OPCODE(dropPage); DECLARE_OPCODE(opcode_16); diff --git a/engines/mohawk/myst_scripts_myst.cpp b/engines/mohawk/myst_scripts_myst.cpp index 7cbef15c54..9dce227318 100644 --- a/engines/mohawk/myst_scripts_myst.cpp +++ b/engines/mohawk/myst_scripts_myst.cpp @@ -63,6 +63,7 @@ void MystScriptParser_Myst::setupOpcodes() { OPCODE(7, opcode_7), OPCODE(8, opcode_8), OPCODE(9, opcode_9), + OPCODE(10, opcode_10), // TODO: Opcode 10 to 11 Not Present OPCODE(12, altDest), OPCODE(13, altDest), @@ -2130,21 +2131,21 @@ void MystScriptParser_Myst::opcode_200(uint16 op, uint16 var, uint16 argc, uint1 // 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)); - } +// 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); break; diff --git a/engines/mohawk/myst_scripts_selenitic.cpp b/engines/mohawk/myst_scripts_selenitic.cpp index c2b42f844e..dc256f4226 100644 --- a/engines/mohawk/myst_scripts_selenitic.cpp +++ b/engines/mohawk/myst_scripts_selenitic.cpp @@ -23,9 +23,11 @@ * */ +#include "mohawk/cursors.h" #include "mohawk/myst.h" #include "mohawk/graphics.h" #include "mohawk/myst_scripts_selenitic.h" +#include "mohawk/myst_saveload.h" #include "mohawk/sound.h" #include "mohawk/video.h" @@ -50,8 +52,7 @@ void MystScriptParser_Selenitic::setupOpcodes() { static const MystOpcode myst_opcodes[] = { // "Standard" Opcodes - { 0, &MystScriptParser::toggleBoolean, "toggleBoolean" }, - //OPCODE(0, toggleBoolean), + OPCODE(0, toggleBoolean), OPCODE(1, setVar), OPCODE(2, altDest), OPCODE(3, takePage), @@ -61,6 +62,7 @@ void MystScriptParser_Selenitic::setupOpcodes() { OPCODE(7, opcode_7), OPCODE(8, opcode_8), OPCODE(9, opcode_9), + OPCODE(10, opcode_10), // TODO: Opcode 10 to 11 Not Present OPCODE(12, altDest), OPCODE(13, altDest), @@ -100,15 +102,21 @@ void MystScriptParser_Selenitic::setupOpcodes() { // TODO: Opcodes 47 to 99 Not Present // "Stack-Specific" Opcodes + SPECIFIC_OPCODE(100, opcode_100), SPECIFIC_OPCODE(101, opcode_101), - 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(102, opcode_102), + SPECIFIC_OPCODE(103, opcode_103), + SPECIFIC_OPCODE(104, opcode_104), + SPECIFIC_OPCODE(105, opcode_105_109), + SPECIFIC_OPCODE(106, opcode_105_109), + SPECIFIC_OPCODE(107, opcode_105_109), + SPECIFIC_OPCODE(108, opcode_105_109), + SPECIFIC_OPCODE(109, opcode_105_109), SPECIFIC_OPCODE(110, opcode_110), SPECIFIC_OPCODE(111, opcode_111), SPECIFIC_OPCODE(115, opcode_115), + SPECIFIC_OPCODE(116, NOP), + SPECIFIC_OPCODE(117, opcode_117), // "Init" Opcodes SPECIFIC_OPCODE(200, opcode_200), @@ -127,23 +135,148 @@ void MystScriptParser_Selenitic::setupOpcodes() { } void MystScriptParser_Selenitic::disableInitOpcodes() { - opcode_200_disable(); - opcode_201_disable(); - opcode_202_disable(); opcode_203_disable(); - opcode_204_disable(); - opcode_205_disable(); - opcode_206_disable(); } void MystScriptParser_Selenitic::runPersistentOpcodes() { - opcode_200_run(); - opcode_201_run(); - opcode_202_run(); opcode_203_run(); - opcode_204_run(); - opcode_205_run(); - opcode_206_run(); +} + +uint16 MystScriptParser_Selenitic::getVar(uint16 var) { + 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 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 (*_sound_receiver_position) / 1000; + case 15: + return ((*_sound_receiver_position) / 100) % 10; + case 16: + return ((*_sound_receiver_position) / 10) % 10; + case 17: + return (*_sound_receiver_position) % 10; + case 26: + return _sound_receiver_sigma_pressed; + default: + return MystScriptParser::getVar(var); + } +} + +void MystScriptParser_Selenitic::toggleVar(uint16 var) { + 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; + 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; + default: + refresh = MystScriptParser::setVarValue(var, value); + break; + } + + return refresh; +} + +void MystScriptParser_Selenitic::opcode_100(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + varUnusedCheck(op, var); + + unknown(op, var, argc, argv); } void MystScriptParser_Selenitic::opcode_101(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -161,69 +294,162 @@ void MystScriptParser_Selenitic::opcode_101(uint16 op, uint16 var, uint16 argc, unknown(op, var, argc, argv); } -void MystScriptParser_Selenitic::opcode_105(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 1) { - uint16 soundId = argv[0]; +/** + * Sound receiver sigma button + */ +void MystScriptParser_Selenitic::opcode_102(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars; + + _vm->_cursor->hideCursor(); + + _sound_receiver_current_source->drawConditionalDataToScreen(0); + + uint16 *oldPosition = _sound_receiver_position; + 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; + } - debugC(kDebugScript, "Opcode %d: Sound Receiver Water Button", op); - debugC(kDebugScript, "\tvar: %d", var); + _sound_receiver_position = &selenitic_vars[8 + source]; + _vm->_sound->stopSound(); + _vm->_sound->playSound(2287); + sound_receiver_draw_view(); + uint16 soundId = sound_receiver_current_sound(source, *_sound_receiver_position); + _vm->_sound->replaceSound(soundId); + _vm->_system->delayMillis(1000); + } - // TODO: Complete Function including Var Change? - _vm->_sound->playSound(soundId); - } else - unknown(op, var, argc, argv); + _sound_receiver_position = oldPosition; + _sound_receiver_sigma_pressed = true; + _vm->_sound->stopSound(); + + _sound_receiver_sources[selenitic_vars[7]]->drawConditionalDataToScreen(1); + + sound_receiver_draw_view(); + + _vm->_cursor->showCursor(); } -void MystScriptParser_Selenitic::opcode_106(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 1) { - uint16 soundId = argv[0]; +/** + * Sound receiver right button + */ +void MystScriptParser_Selenitic::opcode_103(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + varUnusedCheck(op, var); - debugC(kDebugScript, "Opcode %d: Sound Receiver Volcanic Crack Button", op); - debugC(kDebugScript, "\tvar: %d", var); + sound_receiver_left_right(1); +} - // TODO: Complete Function including Var Change? - _vm->_sound->playSound(soundId); - } else - unknown(op, var, argc, argv); +/** + * Sound receiver left button + */ +void MystScriptParser_Selenitic::opcode_104(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + varUnusedCheck(op, var); + + sound_receiver_left_right(2); } -void MystScriptParser_Selenitic::opcode_107(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 1) { - uint16 soundId = argv[0]; +void MystScriptParser_Selenitic::sound_receiver_left_right(uint direction) { - debugC(kDebugScript, "Opcode %d: Sound Receiver Clock Button", op); - debugC(kDebugScript, "\tvar: %d", var); + if (_sound_receiver_sigma_pressed) { + _sound_receiver_sigma_button->drawConditionalDataToScreen(0); + _sound_receiver_sigma_pressed = false; + } - // TODO: Complete Function including Var Change? - _vm->_sound->playSound(soundId); - } else - unknown(op, var, argc, argv); + if (direction == 1) { + _sound_receiver_right_button->drawConditionalDataToScreen(1); + } else { + _sound_receiver_left_button->drawConditionalDataToScreen(1); + } + + _vm->_sound->stopSound(); + + _sound_receiver_direction = direction; + _sound_receiver_speed = 1; + _sound_receiver_start_time = _vm->_system->getMillis(); + + sound_receiver_update(); } -void MystScriptParser_Selenitic::opcode_108(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 1) { - uint16 soundId = argv[0]; +void MystScriptParser_Selenitic::sound_receiver_update() { + if (_sound_receiver_direction == 1) { + *_sound_receiver_position = ((*_sound_receiver_position) + _sound_receiver_speed) % 3600; + } else if (_sound_receiver_direction == 2) { + *_sound_receiver_position = ((*_sound_receiver_position) - _sound_receiver_speed) % 3600; + } - debugC(kDebugScript, "Opcode %d: Sound Receiver Crystal Rocks Button", op); - debugC(kDebugScript, "\tvar: %d", var); + sound_receiver_draw_view(); +} - // TODO: Complete Function including Var Change? - _vm->_sound->playSound(soundId); - } else - unknown(op, var, argc, argv); +void MystScriptParser_Selenitic::sound_receiver_draw_view() { + uint32 left = ((*_sound_receiver_position) * 1800) / 3600; + + _sound_receiver_viewer->_subImages->rect.left = left; + _sound_receiver_viewer->_subImages->rect.right = left + 136; + + _sound_receiver_viewer->drawConditionalDataToScreen(0); + + sound_receiver_draw_angle(); +} + +void MystScriptParser_Selenitic::sound_receiver_draw_angle() { + draw_digit(_sound_receiver_angle_1); + draw_digit(_sound_receiver_angle_2); + draw_digit(_sound_receiver_angle_3); + draw_digit(_sound_receiver_angle_4); } -void MystScriptParser_Selenitic::opcode_109(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - if (argc == 1) { - uint16 soundId = argv[0]; +void MystScriptParser_Selenitic::draw_digit(MystResource *_resource) { + _resource->drawConditionalDataToScreen(getVar(_resource->getType8Var())); +} - debugC(kDebugScript, "Opcode %d: Sound Receiver Wind Button", op); - debugC(kDebugScript, "\tvar: %d", var); +/** + * Sound receiver source selection buttons + */ +void MystScriptParser_Selenitic::opcode_105_109(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars; - // TODO: Complete Function including Var Change? - _vm->_sound->playSound(soundId); - } else - unknown(op, var, argc, argv); + if (_sound_receiver_sigma_pressed) { + _sound_receiver_sigma_button->drawConditionalDataToScreen(0); + _sound_receiver_sigma_pressed = false; + } + + _vm->_cursor->hideCursor(); + + uint pressed_button = var - 9; + + if (selenitic_vars[7] != pressed_button) { + selenitic_vars[7] = pressed_button; + + _sound_receiver_position = &selenitic_vars[8 + pressed_button]; + _sound_receiver_current_source = _sound_receiver_sources[pressed_button]; + + _vm->_sound->stopSound(); + + uint16 sound_id = argv[0]; + _vm->_sound->playSound(sound_id); + + _sound_receiver_current_source->drawConditionalDataToScreen(1); + + sound_receiver_draw_view(); + } + + _vm->_cursor->showCursor(); } void MystScriptParser_Selenitic::opcode_110(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -268,16 +494,7 @@ void MystScriptParser_Selenitic::opcode_110(uint16 op, uint16 var, uint16 argc, } void MystScriptParser_Selenitic::opcode_111(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); - - 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); + sound_receiver_update_sound(); } void MystScriptParser_Selenitic::opcode_115(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -317,125 +534,92 @@ void MystScriptParser_Selenitic::opcode_115(uint16 op, uint16 var, uint16 argc, unknown(op, var, argc, argv); } -// 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" -}; +void MystScriptParser_Selenitic::opcode_117(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + varUnusedCheck(op, var); -static struct { - bool enabled; -} g_opcode200Parameters; + uint16 old_direction = _sound_receiver_direction; -void MystScriptParser_Selenitic::opcode_200_run() { - if (g_opcode200Parameters.enabled) { - // Used on Card 1191 (Maze Runner) + if (_sound_receiver_direction) { + _sound_receiver_direction = 0; + + sound_receiver_update_sound(); - // TODO: Implementation Movie Function.. - if (false) { - _vm->_video->playMovie(_vm->wrapMovieFilename(kHCMovPathSelenitic[0], kSeleniticStack), 201, 26); + if (old_direction == 1) { + _sound_receiver_right_button->drawConditionalDataToScreen(0); + } else { + _sound_receiver_left_button->drawConditionalDataToScreen(0); } + } } -void MystScriptParser_Selenitic::opcode_200_disable() { - g_opcode200Parameters.enabled = false; -} +// 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" +//}; void MystScriptParser_Selenitic::opcode_200(uint16 op, uint16 var, uint16 argc, uint16 *argv) { varUnusedCheck(op, var); // Used for Card 1191 (Maze Runner) if (argc == 0) { - g_opcode200Parameters.enabled = true; + } else unknown(op, var, argc, argv); } -static struct { - bool enabled; -} g_opcode201Parameters; - -void MystScriptParser_Selenitic::opcode_201_run() { - - if (g_opcode201Parameters.enabled) { - // Used for Card 1191 (Maze Runner) - - // TODO: Fill in Function... - } -} - -void MystScriptParser_Selenitic::opcode_201_disable() { - g_opcode201Parameters.enabled = false; -} - void MystScriptParser_Selenitic::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *argv) { varUnusedCheck(op, var); // Used for Card 1191 (Maze Runner) if (argc == 0) { - g_opcode201Parameters.enabled = true; + } else unknown(op, var, argc, argv); } -static struct { - bool enabled; -} g_opcode202Parameters; - -void MystScriptParser_Selenitic::opcode_202_run(void) { - if (g_opcode202Parameters.enabled) { - // Used for Card 1191 (Maze Runner) - - // TODO: Fill in function... - } -} - -void MystScriptParser_Selenitic::opcode_202_disable(void) { - g_opcode202Parameters.enabled = false; -} - void MystScriptParser_Selenitic::opcode_202(uint16 op, uint16 var, uint16 argc, uint16 *argv) { varUnusedCheck(op, var); // Used for Card 1191 (Maze Runner) if (argc == 0) { - g_opcode202Parameters.enabled = true; + } else unknown(op, var, argc, argv); } @@ -446,8 +630,125 @@ static struct { void MystScriptParser_Selenitic::opcode_203_run(void) { if (g_opcode203Parameters.enabled) { - // Used for Card 1245 (Sound Receiver) - // TODO: Fill in Logic to Change Viewer Display etc.? + if (_sound_receiver_start_time) { + if (_sound_receiver_direction) { + uint32 current_time = _vm->_system->getMillis(); + + if (_sound_receiver_speed == 50) { + if (current_time > _sound_receiver_start_time + 500) { + sound_receiver_increase_speed(); + } + } else { + if (current_time > _sound_receiver_start_time + 1000) { + sound_receiver_increase_speed(); + } + } + + if (current_time > _sound_receiver_start_time + 100) { + sound_receiver_update(); + } + + } else if (!_sound_receiver_sigma_pressed) { + sound_receiver_update_sound(); + } + } + } +} + +void MystScriptParser_Selenitic::sound_receiver_increase_speed() { + switch (_sound_receiver_speed) { + case 1: + _sound_receiver_speed = 10; + break; + case 10: + _sound_receiver_speed = 50; + break; + case 50: + _sound_receiver_speed = 100; + break; + } +} + +void MystScriptParser_Selenitic::sound_receiver_update_sound() { + uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars; + + uint16 soundId = sound_receiver_current_sound(selenitic_vars[7], *_sound_receiver_position); + _vm->_sound->replaceSound(soundId); +} + +uint16 MystScriptParser_Selenitic::sound_receiver_current_sound(uint16 source, uint16 position) { + uint16 solution; + bool sourceEnabled; + sound_receiver_solution(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) { + _sound_receiver_left_button->drawConditionalDataToScreen(2); + _sound_receiver_left_button->drawConditionalDataToScreen(0); + soundId = soundIdNear; + } else if (position < solution && position >= solution - 50) { + _sound_receiver_right_button->drawConditionalDataToScreen(2); + _sound_receiver_right_button->drawConditionalDataToScreen(0); + soundId = soundIdNear; + } + } + + return soundId; +} + +void MystScriptParser_Selenitic::sound_receiver_solution(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; } } @@ -459,25 +760,28 @@ void MystScriptParser_Selenitic::opcode_203(uint16 op, uint16 var, uint16 argc, varUnusedCheck(op, var); // Used for Card 1245 (Sound Receiver) - if (argc == 0) { - g_opcode203Parameters.enabled = true; - } else - unknown(op, var, argc, argv); -} - -static struct { - bool enabled; -} g_opcode204Parameters; - -void MystScriptParser_Selenitic::opcode_204_run(void) { - if (g_opcode204Parameters.enabled) { - // Used for Card 1147 (Sound Code Lock) - // TODO: Fill in code for Sound Lock... - } -} - -void MystScriptParser_Selenitic::opcode_204_disable(void) { - g_opcode204Parameters.enabled = false; + g_opcode203Parameters.enabled = true; + uint16 *selenitic_vars = _vm->_saveLoad->_v->selenitic_vars; + + _sound_receiver_right_button = _vm->_resources[0]; + _sound_receiver_left_button = _vm->_resources[1]; + _sound_receiver_sigma_button = _vm->_resources[2]; + _sound_receiver_sources[4] = _vm->_resources[3]; + _sound_receiver_sources[3] = _vm->_resources[4]; + _sound_receiver_sources[2] = _vm->_resources[5]; + _sound_receiver_sources[1] = _vm->_resources[6]; + _sound_receiver_sources[0] = _vm->_resources[7]; + _sound_receiver_viewer = static_cast(_vm->_resources[8]); + _sound_receiver_angle_1 = _vm->_resources[10]; + _sound_receiver_angle_2 = _vm->_resources[11]; + _sound_receiver_angle_3 = _vm->_resources[12]; + _sound_receiver_angle_4 = _vm->_resources[13]; + + uint16 current_source = selenitic_vars[7]; + _sound_receiver_position = &selenitic_vars[8 + current_source]; + _sound_receiver_current_source = _sound_receiver_sources[current_source]; + + _sound_receiver_sigma_pressed = false; } void MystScriptParser_Selenitic::opcode_204(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -485,58 +789,27 @@ void MystScriptParser_Selenitic::opcode_204(uint16 op, uint16 var, uint16 argc, // Used for Card 1147 (Sound Code Lock) if (argc == 0) { - g_opcode204Parameters.enabled = true; + } else unknown(op, var, argc, argv); } -static struct { - bool enabled; -} g_opcode205Parameters; - -void MystScriptParser_Selenitic::opcode_205_run(void) { - if (g_opcode205Parameters.enabled) { - // Used for Card 1191 (Maze Runner) - // TODO: Fill in function... - } -} - -void MystScriptParser_Selenitic::opcode_205_disable(void) { - g_opcode205Parameters.enabled = false; -} - void MystScriptParser_Selenitic::opcode_205(uint16 op, uint16 var, uint16 argc, uint16 *argv) { varUnusedCheck(op, var); // Used for Card 1191 (Maze Runner) if (argc == 0) { - g_opcode205Parameters.enabled = true; + } else unknown(op, var, argc, argv); } -static struct { - bool enabled; -} g_opcode206Parameters; - -void MystScriptParser_Selenitic::opcode_206_run(void) { - if (g_opcode206Parameters.enabled) { - // Used for Card 1191 (Maze Runner) - // TODO: Fill in function... - } -} - -void MystScriptParser_Selenitic::opcode_206_disable(void) { - g_opcode206Parameters.enabled = false; -} - void MystScriptParser_Selenitic::opcode_206(uint16 op, uint16 var, uint16 argc, uint16 *argv) { varUnusedCheck(op, var); // Used for Card 1191 (Maze Runner) - if (argc == 0) { - g_opcode206Parameters.enabled = true; + } else unknown(op, var, argc, argv); } diff --git a/engines/mohawk/myst_scripts_selenitic.h b/engines/mohawk/myst_scripts_selenitic.h index 6295d6b913..ea6e0e31f1 100644 --- a/engines/mohawk/myst_scripts_selenitic.h +++ b/engines/mohawk/myst_scripts_selenitic.h @@ -47,31 +47,23 @@ public: private: void setupOpcodes(); + uint16 getVar(uint16 var); + void toggleVar(uint16 var); + bool setVarValue(uint16 var, uint16 value); - 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(); + DECLARE_OPCODE(opcode_100); DECLARE_OPCODE(opcode_101); - DECLARE_OPCODE(opcode_105); - DECLARE_OPCODE(opcode_106); - DECLARE_OPCODE(opcode_107); - DECLARE_OPCODE(opcode_108); - DECLARE_OPCODE(opcode_109); + DECLARE_OPCODE(opcode_102); + DECLARE_OPCODE(opcode_103); + DECLARE_OPCODE(opcode_104); + DECLARE_OPCODE(opcode_105_109); DECLARE_OPCODE(opcode_110); DECLARE_OPCODE(opcode_111); DECLARE_OPCODE(opcode_115); + DECLARE_OPCODE(opcode_117); DECLARE_OPCODE(opcode_200); DECLARE_OPCODE(opcode_201); @@ -80,6 +72,33 @@ private: DECLARE_OPCODE(opcode_204); DECLARE_OPCODE(opcode_205); DECLARE_OPCODE(opcode_206); + + bool _sound_receiver_sigma_pressed; // 6 + MystResource *_sound_receiver_sources[5]; // 92 -> 108 + MystResource *_sound_receiver_current_source; // 112 + uint16 *_sound_receiver_position; // 116 + uint16 _sound_receiver_direction; // 120 + uint16 _sound_receiver_speed; // 122 + uint32 _sound_receiver_start_time; //124 + MystResourceType8 *_sound_receiver_viewer; // 128 + MystResource *_sound_receiver_right_button; // 132 + MystResource *_sound_receiver_left_button; // 136 + MystResource *_sound_receiver_angle_1; // 140 + MystResource *_sound_receiver_angle_2; // 144 + MystResource *_sound_receiver_angle_3; // 148 + MystResource *_sound_receiver_angle_4; // 152 + MystResource *_sound_receiver_sigma_button; // 156 + + void sound_receiver_left_right(uint direction); + void sound_receiver_update(); + void sound_receiver_draw_view(); + void sound_receiver_draw_angle(); + void sound_receiver_increase_speed(); + void sound_receiver_update_sound(); + uint16 sound_receiver_current_sound(uint16 source, uint16 position); + void sound_receiver_solution(uint16 source, uint16 &solution, bool &enabled); + + void draw_digit(MystResource *_resource); }; } diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp index ee82bb4cea..abade641eb 100644 --- a/engines/mohawk/resource.cpp +++ b/engines/mohawk/resource.cpp @@ -260,6 +260,32 @@ bool MohawkArchive::hasResource(uint32 tag, const Common::String &resName) { return getIDIndex(typeIndex, resName) >= 0; } +Common::String MohawkArchive::getName(uint32 tag, uint16 id) { + if (!_mhk) + return 0; + + int16 typeIndex = getTypeIndex(tag); + + if (typeIndex < 0) + return 0; + + int16 idIndex = -1; + + for (uint16 i = 0; i < _types[typeIndex].resTable.resources; i++) + if (_types[typeIndex].resTable.entries[i].id == id) { + idIndex = _types[typeIndex].resTable.entries[i].index; + break; + } + + assert(idIndex >= 0); + + for (uint16 i = 0; i < _types[typeIndex].nameTable.num; i++) + if (_types[typeIndex].nameTable.entries[i].index == idIndex) + return _types[typeIndex].nameTable.entries[i].name; + + return 0; // not found +} + uint32 MohawkArchive::getOffset(uint32 tag, uint16 id) { assert(_mhk); diff --git a/engines/mohawk/resource.h b/engines/mohawk/resource.h index 675c8f3f8c..8aa186b54a 100644 --- a/engines/mohawk/resource.h +++ b/engines/mohawk/resource.h @@ -186,6 +186,7 @@ public: virtual Common::SeekableReadStream *getResource(uint32 tag, uint16 id); virtual uint32 getOffset(uint32 tag, uint16 id); virtual uint16 findResourceID(uint32 type, const Common::String &resName); + Common::String getName(uint32 tag, uint16 id); protected: Common::SeekableReadStream *_mhk; diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index d801907bd0..41d7000ad8 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -96,6 +96,8 @@ Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop) { audStream = Audio::makeWAVStream(_vm->getResource(ID_MSND, id), DisposeAfterUse::YES); } else audStream = makeMohawkWaveStream(_vm->getResource(ID_MSND, id)); + + handle->name = _vm->getResourceName(ID_MSND, id); break; case GType_ZOOMBINI: audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id)); @@ -119,6 +121,25 @@ Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop) { return NULL; } +Audio::SoundHandle *Sound::replaceSound(uint16 id, byte volume, bool loop) { + debug (0, "Replacing sound %d", id); + + //TODO: The original engine does fading + + Common::String name = _vm->getResourceName(ID_MSND, id); + + // Check if sound is already playing + for (uint32 i = 0; i < _handles.size(); i++) { + if (_vm->_mixer->isSoundHandleActive(_handles[i].handle) + && name.equals(_handles[i].name)) { + return &_handles[i].handle; + } + } + + stopSound(); + return playSound(id, volume, loop); +} + void Sound::playSoundBlocking(uint16 id, byte volume) { Audio::SoundHandle *handle = playSound(id, volume); diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h index e0674500fa..386eb78991 100644 --- a/engines/mohawk/sound.h +++ b/engines/mohawk/sound.h @@ -66,6 +66,7 @@ struct SndHandle { Audio::SoundHandle handle; SndHandleType type; uint16 id; + Common::String name; }; struct SLSTSndHandle { @@ -120,6 +121,7 @@ public: ~Sound(); Audio::SoundHandle *playSound(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume, bool loop = false); + Audio::SoundHandle *replaceSound(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume, bool loop = false); void playSoundBlocking(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume); void playMidi(uint16 id); void stopSound(); -- cgit v1.2.3