diff options
Diffstat (limited to 'engines/mohawk')
35 files changed, 1133 insertions, 263 deletions
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index a7a650d8ed..ce22132cee 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -75,7 +75,7 @@ bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) { } _vm->_sound->stopSound(); - _vm->changeToCard((uint16)atoi(argv[1]), true); + _vm->changeToCard((uint16)atoi(argv[1]), kTransitionCopy); return false; } @@ -531,6 +531,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { varNames.push_back(name); } delete nameStream; + delete[] stringOffsets; // Load in External Command Names nameStream = _vm->getResource(ID_NAME, ExternalCommandNames); @@ -552,6 +553,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { xNames.push_back(name); } delete nameStream; + delete[] stringOffsets; // Get CARD/HSPT data and dump their scripts if (!scumm_stricmp(argv[2], "CARD")) { diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index e73d4ed6a3..c7bd03678f 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -106,8 +106,8 @@ void MystCursorManager::hideCursor() { void MystCursorManager::setCursor(uint16 id) { // Zero means empty cursor if (id == 0) { - static const byte emptyCursor = 0; - CursorMan.replaceCursor(&emptyCursor, 1, 1, 0, 0, 0); + static const byte emptyCursor[4] = { 0, 0, 0, 0 }; + CursorMan.replaceCursor(&emptyCursor, 2, 2, 0, 0, 0); return; } @@ -160,6 +160,7 @@ void NECursorManager::setCursor(uint16 id) { Graphics::Cursor *cursor = cursorGroup->cursors[0].cursor; CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); + delete cursorGroup; return; } } diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 5664929948..ef07de0180 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -143,6 +143,7 @@ static const PlainGameDescriptor mohawkGames[] = { {"harryhh","Harry and the Haunted House"}, {"stellaluna", "Stellaluna"}, {"sheila", "Sheila Rae, the Brave"}, + {"rugratsps", "Rugrats Print Shop" }, {0, 0} }; diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 55814af1c3..3b925af5a9 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -239,6 +239,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0, }, + // Myst Masterpiece Edition + // Polish Windows + // From pykman (Included in "Myst: Antologia") + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "4a05771b60f4a69869838d01e85c9e80"), + Common::PL_POL, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_MYST, + GF_ME, + 0, + }, + // Riven: The Sequel to Myst // Version 1.0 (5CD) // From clone2727 @@ -348,6 +366,24 @@ static const MohawkGameDescription gameDescriptions[] = { }, // Riven: The Sequel to Myst + // Version 1.02 (DVD, From "Myst: Antologia") + // From pykman + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "733a710cf5f848b441ec72d988ab8a3d"), + Common::PL_POL, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst // Version ? (Demo, From "Prince of Persia Collector's Edition") // From Clone2727 { @@ -1325,6 +1361,23 @@ static const MohawkGameDescription gameDescriptions[] = { "GRANDMA.EXE" }, + // Just Grandma and Me 1.1 Mac + // From eisnerguy1 in bug#3610725 + { + { + "grandma", + "v1.1", + AD_ENTRY1("BookOutline", "76eb265ec5fe42bc5b07f2bb418bd871"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GType_LIVINGBOOKSV1, + GF_LB_10, + 0 + }, + // from jjnryan in bug #3389857 { { @@ -2096,6 +2149,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // Rugrats Adventure Game + // English Windows Demo + // From GeorgeQGreg (Rugrats Movie Soundtrack) + { + { + "rugrats", + "Demo", + AD_ENTRY1("outline", "adbd7ff6c5e1bdb7062c89879a4e39e6"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO | ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_LIVINGBOOKSV4, + 0, + 0 + }, + { { "lbsampler", @@ -2507,6 +2578,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // Rugrats Print Shop + // English Windows Demo + // From GeorgeQGreg (Rugrats Movie Soundtrack) + { + { + "rugratsps", + "Demo", + AD_ENTRY1("outline", "808d5ee8427180ddebdd5dd4199b47cb"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO | ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_LIVINGBOOKSV4, + 0, + 0 + }, + { AD_TABLE_END_MARKER, 0, 0, 0 } }; diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp index 4461a30ad4..5f5a3b3800 100644 --- a/engines/mohawk/dialogs.cpp +++ b/engines/mohawk/dialogs.cpp @@ -137,12 +137,6 @@ void MystOptionsDialog::open() { void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) { switch (cmd) { - case kZipCmd: - _vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState(); - break; - case kTransCmd: - _vm->_gameState->_globals.transitions = _transitionsCheckbox->getState(); - break; case kDropCmd: _vm->_needsPageDrop = true; close(); @@ -155,8 +149,10 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui _vm->_needsShowDemoMenu = true; close(); break; - case GUI::kCloseCmd: - close(); + case GUI::kOKCmd: + _vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState(); + _vm->_gameState->_globals.transitions = _transitionsCheckbox->getState(); + GUI::OptionsDialog::handleCommand(sender, cmd, data); break; default: GUI::OptionsDialog::handleCommand(sender, cmd, data); diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp index 636b7ae476..5af95f27e3 100644 --- a/engines/mohawk/installer_archive.cpp +++ b/engines/mohawk/installer_archive.cpp @@ -133,4 +133,4 @@ Common::SeekableReadStream *InstallerArchive::createReadStreamForMember(const Co return Common::decompressDCL(_stream, entry.compressedSize, entry.uncompressedSize); } -} // End of namespace Mohawk +} // End of namespace Mohawk diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp index a0671d18d5..efa0dd3fd3 100644 --- a/engines/mohawk/livingbooks.cpp +++ b/engines/mohawk/livingbooks.cpp @@ -40,6 +40,8 @@ #include "gui/message.h" +#include "graphics/cursorman.h" + namespace Mohawk { // read a null-terminated string from a stream @@ -146,16 +148,10 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa const Common::FSNode gameDataDir(ConfMan.get("path")); // Rugrats - const Common::FSNode ProgPath = gameDataDir.getChild("program"); - if (ProgPath.exists()) - SearchMan.addDirectory(ProgPath.getPath(), ProgPath, 0, 2); - const Common::FSNode RugPath = gameDataDir.getChild("Rugrats Adventure Game"); - if (RugPath.exists()) - SearchMan.addDirectory(RugPath.getPath(), RugPath, 0, 2); + SearchMan.addSubDirectoryMatching(gameDataDir, "program", 0, 2); + SearchMan.addSubDirectoryMatching(gameDataDir, "Rugrats Adventure Game", 0, 2); // CarmenTQ - const Common::FSNode CTQPath = gameDataDir.getChild("95instal"); - if (CTQPath.exists()) - SearchMan.addDirectory(CTQPath.getPath(), CTQPath, 0, 4); + SearchMan.addSubDirectoryMatching(gameDataDir, "95instal", 0, 4); } MohawkEngine_LivingBooks::~MohawkEngine_LivingBooks() { @@ -223,7 +219,7 @@ Common::Error MohawkEngine_LivingBooks::run() { } } - if (found) + if (found && CursorMan.isVisible()) found->handleMouseDown(event.mouse); break; @@ -243,6 +239,8 @@ Common::Error MohawkEngine_LivingBooks::run() { case Common::KEYCODE_ESCAPE: if (_curMode == kLBIntroMode) tryLoadPageStart(kLBControlMode, 1); + else + _video->stopVideos(); break; case Common::KEYCODE_LEFT: @@ -585,8 +583,8 @@ void MohawkEngine_LivingBooks::updatePage() { _items.remove_at(i); i--; _orderedItems.remove(delayedEvent.item); - delete delayedEvent.item; _page->itemDestroyed(delayedEvent.item); + delete delayedEvent.item; if (_focus == delayedEvent.item) _focus = NULL; break; @@ -1354,8 +1352,9 @@ void MohawkEngine_LivingBooks::handleNotify(NotifyEvent &event) { if (!loadPage((LBMode)event.newMode, event.newPage, event.newSubpage)) { if (event.newPage != 0 || !loadPage((LBMode)event.newMode, _curPage, event.newSubpage)) if (event.newSubpage != 0 || !loadPage((LBMode)event.newMode, event.newPage, 1)) - error("kLBNotifyChangeMode failed to move to mode %d, page %d.%d", - event.newMode, event.newPage, event.newSubpage); + if (event.newSubpage != 1 || !loadPage((LBMode)event.newMode, event.newPage, 0)) + error("kLBNotifyChangeMode failed to move to mode %d, page %d.%d", + event.newMode, event.newPage, event.newSubpage); } break; case 3: @@ -3773,7 +3772,7 @@ LBMovieItem::~LBMovieItem() { void LBMovieItem::update() { if (_playing) { VideoHandle videoHandle = _vm->_video->findVideoHandle(_resourceId); - if (_vm->_video->endOfVideo(videoHandle)) + if (videoHandle == NULL_VID_HANDLE || _vm->_video->endOfVideo(videoHandle)) done(true); } @@ -3783,6 +3782,7 @@ void LBMovieItem::update() { bool LBMovieItem::togglePlaying(bool playing, bool restart) { if (playing) { if ((_loaded && _enabled && _globalEnabled) || _phase == kLBPhaseNone) { + debug("toggled video for phase %d", _phase); _vm->_video->playMovie(_resourceId, _rect.left, _rect.top); return true; diff --git a/engines/mohawk/livingbooks_code.cpp b/engines/mohawk/livingbooks_code.cpp index bb8f7a0d05..c45efb2c39 100644 --- a/engines/mohawk/livingbooks_code.cpp +++ b/engines/mohawk/livingbooks_code.cpp @@ -519,9 +519,17 @@ void LBCode::parseMain() { *val = _stack.pop(); _stack.push(*val); } else - _stack.push(LBValue()); - } else if (_currToken == kTokenAndEquals) { - debugN(" &= "); + error("assignment failed, no dest"); +// _stack.push(LBValue()); + } else if (_currToken == kTokenPlusEquals || _currToken == kTokenMinusEquals || _currToken == kTokenAndEquals) { + // FIXME: do +=/-= belong here? + byte token = _currToken; + if (_currToken == kTokenPlusEquals) + debugN(" += "); + else if (_currToken == kTokenMinusEquals) + debugN(" -= "); + else if (_currToken == kTokenAndEquals) + debugN(" &= "); nextToken(); parseStatement(); if (!_stack.size()) @@ -532,9 +540,19 @@ void LBCode::parseMain() { else val = &_vm->_variables[varname]; if (val) { - if (val->type != kLBValueString) - error("operator &= used on non-string"); - val->string = val->string + _stack.pop().toString(); + if (token == kTokenAndEquals) { + if (val->type != kLBValueString) + error("operator &= used on non-string"); + val->string = val->string + _stack.pop().toString(); + } else { + // FIXME: non-integers + if (val->type != kLBValueInteger) + error("operator used on non-integer"); + if (token == kTokenPlusEquals) + val->integer = val->integer + _stack.pop().toInt(); + else + val->integer = val->integer - _stack.pop().toInt(); + } _stack.push(*val); } else _stack.push(LBValue()); @@ -581,6 +599,7 @@ void LBCode::parseMain() { debugN("--"); nextToken(); + // FIXME: do we need to handle indexing? if (_currToken != kTokenIdentifier) error("expected identifier"); assert(_currValue.type == kLBValueString); @@ -669,6 +688,24 @@ void LBCode::parseMain() { _stack.push(_stack.pop().isZero() ? 1 : 0); break; + case kTokenEval: + // FIXME: original token? + debugN(".."); + nextToken(); + parseStatement(); + if (!_stack.size()) + error("eval op failed"); + { + // FIXME: XXX + LBValue in = _stack.pop(); + if (in.type != kLBValueString) + error("eval op on non-string"); + Common::String varname = in.string; + LBValue &val = _vm->_variables[varname]; + _stack.push(val); + } + break; + case kTokenGeneralCommand: runGeneralCommand(); break; @@ -692,9 +729,7 @@ void LBCode::parseMain() { assert(val.isNumeric()); // FIXME if (prefix == kTokenMinus) - val.integer--; - else - val.integer++; + val.integer = -val.integer; _stack.push(val); } } @@ -1554,12 +1589,32 @@ uint LBCode::nextFreeString() { error("nextFreeString couldn't find a space"); } +static const char *const functionNameAliases[][2] = { + { "makerect", "getRect" }, + { "makepair", "makePt" }, + { "getframerect", "getFrameBounds" }, + { "dragbegin", "dragBeginFrom" }, + { "x", "xpos" }, + { "y", "ypos" } +}; + /* * Helper function for parseCode: * Given a name, appends the appropriate data to the provided code array and * returns true if it's a function, or false otherwise. */ -bool LBCode::parseCodeSymbol(const Common::String &name, uint &pos, Common::Array<byte> &code) { +bool LBCode::parseCodeSymbol(Common::String name, uint &pos, Common::Array<byte> &code, bool useAllAliases) { + // Check to see if we have one of the older function names + // and remap it to the newer function names + for (uint i = 0; i < ARRAYSIZE(functionNameAliases); i++) { + if (name.equalsIgnoreCase(functionNameAliases[i][0])) { + if (name.size() == 1 && !useAllAliases) + continue; + name = functionNameAliases[i][1]; + break; + } + } + // first, check whether the name matches a known function for (uint i = 0; i < 2; i++) { byte cmdToken; @@ -1770,7 +1825,7 @@ uint LBCode::parseCode(const Common::String &source) { break; tempString += source[pos++]; } - wasFunction = parseCodeSymbol(tempString, pos, code); + wasFunction = parseCodeSymbol(tempString, pos, code, true); if (!wasFunction) error("while parsing script '%s', encountered explicit function call to unknown function '%s'", source.c_str(), tempString.c_str()); @@ -1805,7 +1860,7 @@ uint LBCode::parseCode(const Common::String &source) { } else if (tempString.equalsIgnoreCase("false")) { code.push_back(kTokenFalse); } else { - wasFunction = parseCodeSymbol(tempString, pos, code); + wasFunction = parseCodeSymbol(tempString, pos, code, false); } } else { error("while parsing script '%s', couldn't parse '%c'", source.c_str(), token); diff --git a/engines/mohawk/livingbooks_code.h b/engines/mohawk/livingbooks_code.h index 47dd90f814..c9d9ae06e6 100644 --- a/engines/mohawk/livingbooks_code.h +++ b/engines/mohawk/livingbooks_code.h @@ -188,6 +188,7 @@ enum { kTokenConstEventId = 0x42, kTokenConstScriptOpcode = 0x43, // ?? kTokenConstScriptParam = 0x44, // ?? + kTokenEval = 0x4b, kTokenGeneralCommand = 0x4d, kTokenItemCommand = 0x4e, kTokenNotifyCommand = 0x4f, @@ -242,7 +243,7 @@ protected: void runNotifyCommand(); uint nextFreeString(); - bool parseCodeSymbol(const Common::String &name, uint &pos, Common::Array<byte> &code); + bool parseCodeSymbol(Common::String name, uint &pos, Common::Array<byte> &code, bool useAllAliases); public: void cmdUnimplemented(const Common::Array<LBValue> ¶ms); diff --git a/engines/mohawk/livingbooks_lbx.cpp b/engines/mohawk/livingbooks_lbx.cpp index 9628e06294..2b8b22ec81 100644 --- a/engines/mohawk/livingbooks_lbx.cpp +++ b/engines/mohawk/livingbooks_lbx.cpp @@ -48,8 +48,10 @@ LBXDataFile::~LBXDataFile() { enum { kLBXDataFileOpen = 1, + kLBXDataFileAddSection = 3, kLBXDataFileGetSectionList = 4, kLBXDataFileSetCurSection = 5, + kLBXDataFileSetKey = 7, kLBXDataFileLoadCurSectionVars = 8, kLBXDataFileDeleteCurSection = 10, kLBXDataFileSectionExists = 14 @@ -64,6 +66,14 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> ¶ms, LBValu open(params[0].toString()); return false; + case kLBXDataFileAddSection: + if (params.size() != 1) + error("incorrect number of parameters (%d) to LBXDataFile::addSection", params.size()); + + _dataFile.addSection(params[0].toString()); + _curSection = params[0].toString(); + return false; + case kLBXDataFileGetSectionList: { Common::SharedPtr<LBList> list = Common::SharedPtr<LBList>(new LBList); @@ -81,6 +91,13 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> ¶ms, LBValu _curSection = params[0].toString(); return false; + case kLBXDataFileSetKey: + if (params.size() != 2) + error("incorrect number of parameters (%d) to LBXDataFile::setKey", params.size()); + + _dataFile.setKey(params[0].toString(), _curSection, params[1].toString()); + return false; + case kLBXDataFileLoadCurSectionVars: if (params.size() != 0) error("incorrect number of parameters (%d) to LBXDataFile::loadCurSectionVars", params.size()); diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp index 9c0e642203..8140817eb3 100644 --- a/engines/mohawk/myst.cpp +++ b/engines/mohawk/myst.cpp @@ -523,7 +523,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS _video->playMovieBlockingCentered(wrapMovieFilename(flyby, kMasterpieceOnly)); } - changeToCard(card, true); + changeToCard(card, kTransitionCopy); if (linkDstSound) _sound->playSoundBlocking(linkDstSound); @@ -549,7 +549,7 @@ void MohawkEngine_Myst::drawCardBackground() { _gfx->copyImageToBackBuffer(getCardBackgroundId(), Common::Rect(0, 0, 544, 332)); } -void MohawkEngine_Myst::changeToCard(uint16 card, bool updateScreen) { +void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) { debug(2, "changeToCard(%d)", card); _scriptParser->disablePersistentScripts(); @@ -629,9 +629,11 @@ void MohawkEngine_Myst::changeToCard(uint16 card, bool updateScreen) { } // Make sure the screen is updated - if (updateScreen) { - _gfx->copyBackBufferToScreen(Common::Rect(544, 333)); - _system->updateScreen(); + if (transition != kNoTransition) { + if (!_gameState->_globals.transitions) + transition = kTransitionCopy; + + _gfx->runTransition(transition, Common::Rect(544, 333), 10, 0); } // Make sure we have the right cursor showing @@ -1179,41 +1181,41 @@ bool MohawkEngine_Myst::canSaveGameStateCurrently() { } void MohawkEngine_Myst::dropPage() { - uint16 page = _gameState->_globals.heldPage; + uint16 page = _gameState->_globals.heldPage; bool whitePage = page == 13; bool bluePage = page - 1 < 6; - bool redPage = page - 7 < 6; - - // Play drop page sound - _sound->replaceSoundMyst(800); - - // Drop page - _gameState->_globals.heldPage = 0; - - // Redraw page area - if (whitePage && _gameState->_globals.currentAge == 2) { - redrawArea(41); - } else if (bluePage) { - if (page == 6) { - if (_gameState->_globals.currentAge == 2) - redrawArea(24); - } else { - redrawArea(103); - } - } else if (redPage) { - if (page == 12) { - if (_gameState->_globals.currentAge == 2) - redrawArea(25); - } else if (page == 10) { - if (_gameState->_globals.currentAge == 1) - redrawArea(35); - } else { - redrawArea(102); - } - } - - setMainCursor(kDefaultMystCursor); - checkCursorHints(); + bool redPage = page - 7 < 6; + + // Play drop page sound + _sound->replaceSoundMyst(800); + + // Drop page + _gameState->_globals.heldPage = 0; + + // Redraw page area + if (whitePage && _gameState->_globals.currentAge == 2) { + redrawArea(41); + } else if (bluePage) { + if (page == 6) { + if (_gameState->_globals.currentAge == 2) + redrawArea(24); + } else { + redrawArea(103); + } + } else if (redPage) { + if (page == 12) { + if (_gameState->_globals.currentAge == 2) + redrawArea(25); + } else if (page == 10) { + if (_gameState->_globals.currentAge == 1) + redrawArea(35); + } else { + redrawArea(102); + } + } + + setMainCursor(kDefaultMystCursor); + checkCursorHints(); } } // End of namespace Mohawk diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h index 30770f7ec9..a268c19737 100644 --- a/engines/mohawk/myst.h +++ b/engines/mohawk/myst.h @@ -75,6 +75,23 @@ enum { kStoneshipStack // Stoneship Age }; +// Transitions +enum TransitionType { + kTransitionLeftToRight = 0, + kTransitionRightToLeft = 1, + kTransitionSlideToLeft = 2, + kTransitionSlideToRight = 3, + kTransitionDissolve = 4, + kTransitionTopToBottom = 5, + kTransitionBottomToTop = 6, + kTransitionSlideToTop = 7, + kTransitionSlideToBottom= 8, + kTransitionPartToRight = 9, + kTransitionPartToLeft = 10, + kTransitionCopy = 11, + kNoTransition = 999 +}; + const uint16 kMasterpieceOnly = 0xFFFF; struct MystCondition { @@ -154,7 +171,7 @@ public: void reloadSaveList(); void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound); - void changeToCard(uint16 card, bool updateScreen); + void changeToCard(uint16 card, TransitionType transition); uint16 getCurCard() { return _curCard; } uint16 getCurStack() { return _curStack; } void setMainCursor(uint16 cursor); diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp index a54b67bef4..12a2c7f44c 100644 --- a/engines/mohawk/myst_areas.cpp +++ b/engines/mohawk/myst_areas.cpp @@ -70,10 +70,30 @@ MystResource::~MystResource() { } void MystResource::handleMouseUp() { - if (_dest != 0) - _vm->changeToCard(_dest, true); - else + if (_dest == 0) { warning("Movement type resource with null destination at position (%d, %d), (%d, %d)", _rect.left, _rect.top, _rect.right, _rect.bottom); + return; + } + + uint16 opcode; + + switch (type) { + case kMystForwardArea: + opcode = 6; + break; + case kMystLeftArea: + opcode = 8; + break; + case kMystRightArea: + opcode = 7; + break; + default: + opcode = 48; + break; + } + + _vm->_scriptParser->setInvokingResource(this); + _vm->_scriptParser->runOpcode(opcode, 0); } bool MystResource::canBecomeActive() { @@ -202,22 +222,23 @@ VideoHandle MystResourceType6::playMovie() { // Check if the video is already running VideoHandle handle = _vm->_video->findVideoHandle(_videoFile); - if (_direction != 1) - warning("Playing QT movies backwards is not implemented"); - // If the video is not running, play it if (handle == NULL_VID_HANDLE || _vm->_video->endOfVideo(handle)) { - if (_playBlocking) { - _vm->_video->playMovieBlocking(_videoFile, _left, _top); - handle = NULL_VID_HANDLE; - } else { - handle = _vm->_video->playMovie(_videoFile, _left, _top, _loop); + handle = _vm->_video->playMovie(_videoFile, _left, _top, _loop); + if (_direction == -1) { + _vm->_video->seekToTime(handle, _vm->_video->getDuration(handle)); + _vm->_video->setVideoRate(handle, -1); } } else { // Resume the video _vm->_video->pauseMovie(handle, false); } + if (_playBlocking) { + _vm->_video->waitUntilMovieEnds(handle); + handle = NULL_VID_HANDLE; + } + return handle; } diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp index 2df0f7e6ba..6a292c66e2 100644 --- a/engines/mohawk/myst_graphics.cpp +++ b/engines/mohawk/myst_graphics.cpp @@ -209,15 +209,15 @@ void MystGraphics::copyBackBufferToScreen(Common::Rect r) { _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(r.left, r.top), _backBuffer->pitch, r.left, r.top, r.width(), r.height()); } -void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay) { +void MystGraphics::runTransition(TransitionType type, Common::Rect rect, uint16 steps, uint16 delay) { // Do not artificially delay during transitions int oldEnableDrawingTimeSimulation = _enableDrawingTimeSimulation; _enableDrawingTimeSimulation = 0; switch (type) { - case 0: { - debugC(kDebugScript, "Left to Right"); + case kTransitionLeftToRight: { + debugC(kDebugView, "Left to Right"); uint16 step = (rect.right - rect.left) / steps; Common::Rect area = rect; @@ -239,8 +239,8 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - case 1: { - debugC(kDebugScript, "Right to Left"); + case kTransitionRightToLeft: { + debugC(kDebugView, "Right to Left"); uint16 step = (rect.right - rect.left) / steps; Common::Rect area = rect; @@ -262,8 +262,25 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - case 5: { - debugC(kDebugScript, "Top to Bottom"); + case kTransitionSlideToLeft: + debugC(kDebugView, "Slide to left"); + transitionSlideToLeft(rect, steps, delay); + break; + case kTransitionSlideToRight: + debugC(kDebugView, "Slide to right"); + transitionSlideToRight(rect, steps, delay); + break; + case kTransitionDissolve: { + debugC(kDebugView, "Dissolve"); + + for (int16 step = 0; step < 8; step++) { + simulatePreviousDrawDelay(rect); + transitionDissolve(rect, step); + } + } + break; + case kTransitionTopToBottom: { + debugC(kDebugView, "Top to Bottom"); uint16 step = (rect.bottom - rect.top) / steps; Common::Rect area = rect; @@ -285,8 +302,8 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - case 6: { - debugC(kDebugScript, "Bottom to Top"); + case kTransitionBottomToTop: { + debugC(kDebugView, "Bottom to Top"); uint16 step = (rect.bottom - rect.top) / steps; Common::Rect area = rect; @@ -308,18 +325,260 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - default: - warning("Unknown Update Direction"); + case kTransitionSlideToTop: + debugC(kDebugView, "Slide to top"); + transitionSlideToTop(rect, steps, delay); + break; + case kTransitionSlideToBottom: + debugC(kDebugView, "Slide to bottom"); + transitionSlideToBottom(rect, steps, delay); + break; + case kTransitionPartToRight: { + debugC(kDebugView, "Partial left to right"); + + transitionPartialToRight(rect, 75, 3); + } + break; + case kTransitionPartToLeft: { + debugC(kDebugView, "Partial right to left"); - //TODO: Replace minimal implementation + transitionPartialToLeft(rect, 75, 3); + } + break; + case kTransitionCopy: copyBackBufferToScreen(rect); _vm->_system->updateScreen(); break; + default: + error("Unknown transition %d", type); } _enableDrawingTimeSimulation = oldEnableDrawingTimeSimulation; } +void MystGraphics::transitionDissolve(Common::Rect rect, uint step) { + static const bool pattern[][4][4] = { + { + { true, false, false, false }, + { false, false, false, false }, + { false, false, true, false }, + { false, false, false, false } + }, + { + { false, false, true, false }, + { false, false, false, false }, + { true, false, false, false }, + { false, false, false, false } + }, + { + { false, false, false, false }, + { false, true, false, false }, + { false, false, false, false }, + { false, false, false, true } + }, + { + { false, false, false, false }, + { false, false, false, true }, + { false, false, false, false }, + { false, true, false, false } + }, + { + { false, false, false, false }, + { false, false, true, false }, + { false, true, false, false }, + { false, false, false, false } + }, + { + { false, true, false, false }, + { false, false, false, false }, + { false, false, false, false }, + { false, false, true, false } + }, + { + { false, false, false, false }, + { true, false, false, false }, + { false, false, false, true }, + { false, false, false, false } + }, + { + { false, false, false, true }, + { false, false, false, false }, + { false, false, false, false }, + { true, false, false, false } + } + }; + + rect.clip(_viewport); + + Graphics::Surface *screen = _vm->_system->lockScreen(); + + for (uint16 y = rect.top; y < rect.bottom; y++) { + const bool *linePattern = pattern[step][y % 4]; + + if (!linePattern[0] && !linePattern[1] && !linePattern[2] && !linePattern[3]) + continue; + + for (uint16 x = rect.left; x < rect.right; x++) { + if (linePattern[x % 4]) { + if (_pixelFormat.bytesPerPixel == 2) { + uint16 *dst = (uint16 *)screen->getBasePtr(x, y); + *dst = *(const uint16 *)_backBuffer->getBasePtr(x, y); + } else { + uint32 *dst = (uint32 *)screen->getBasePtr(x, y); + *dst = *(const uint32 *)_backBuffer->getBasePtr(x, y); + } + } + } + } + + _vm->_system->unlockScreen(); + _vm->_system->updateScreen(); +} + +void MystGraphics::transitionSlideToLeft(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.right - rect.left) / steps; + Common::Rect srcRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.right = dstRect.left + step * stepWidth; + srcRect.left = srcRect.right - step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + if (dstRect.right != rect.right) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionSlideToRight(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.right - rect.left) / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.left = dstRect.right - step * stepWidth; + srcRect.right = srcRect.left + step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + if (dstRect.left != rect.left) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionSlideToTop(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.bottom - rect.top) / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.bottom, rect.right, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.left, rect.top, rect.right, rect.top); + + for (uint step = 1; step <= steps; step++) { + dstRect.bottom = dstRect.top + step * stepWidth; + srcRect.top = srcRect.bottom - step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + + if (dstRect.bottom < rect.bottom) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionSlideToBottom(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.bottom - rect.top) / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.top, rect.right, rect.top); + Common::Rect dstRect = Common::Rect(rect.left, rect.bottom, rect.right, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.top = dstRect.bottom - step * stepWidth; + srcRect.bottom = srcRect.top + step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + + if (dstRect.top > rect.top) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionPartialToRight(Common::Rect rect, uint32 width, uint32 steps) { + rect.clip(_viewport); + + uint32 stepWidth = width / steps; + Common::Rect srcRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.right = dstRect.left + step * stepWidth; + srcRect.left = srcRect.right - step * stepWidth; + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); +} + +void MystGraphics::transitionPartialToLeft(Common::Rect rect, uint32 width, uint32 steps) { + rect.clip(_viewport); + + uint32 stepWidth = width / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.left = dstRect.right - step * stepWidth; + srcRect.right = srcRect.left + step * stepWidth; + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); +} + void MystGraphics::drawRect(Common::Rect rect, RectState state) { rect.clip(_viewport); diff --git a/engines/mohawk/myst_graphics.h b/engines/mohawk/myst_graphics.h index de8fe521e6..4bbc8d5b8c 100644 --- a/engines/mohawk/myst_graphics.h +++ b/engines/mohawk/myst_graphics.h @@ -48,7 +48,7 @@ public: void copyImageToScreen(uint16 image, Common::Rect dest); void copyImageToBackBuffer(uint16 image, Common::Rect dest); void copyBackBufferToScreen(Common::Rect r); - void runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay); + void runTransition(TransitionType type, Common::Rect rect, uint16 steps, uint16 delay); void drawRect(Common::Rect rect, RectState state); void drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color); void enableDrawingTimeSimulation(bool enable); @@ -60,7 +60,13 @@ protected: MohawkEngine *getVM() { return (MohawkEngine *)_vm; } void simulatePreviousDrawDelay(const Common::Rect &dest); void copyBackBufferToScreenWithSaturation(int16 saturation); - + void transitionDissolve(Common::Rect rect, uint step); + void transitionSlideToLeft(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToRight(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToTop(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToBottom(Common::Rect rect, uint16 steps, uint16 delay); + void transitionPartialToRight(Common::Rect rect, uint32 width, uint32 steps); + void transitionPartialToLeft(Common::Rect rect, uint32 width, uint32 steps); private: MohawkEngine_Myst *_vm; MystBitmap *_bmpDecoder; diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp index 107a8b03e9..c1b75df4cf 100644 --- a/engines/mohawk/myst_scripts.cpp +++ b/engines/mohawk/myst_scripts.cpp @@ -100,18 +100,18 @@ void MystScriptParser::setupCommonOpcodes() { // "Standard" Opcodes OPCODE(0, o_toggleVar); OPCODE(1, o_setVar); - OPCODE(2, o_changeCardSwitch); + OPCODE(2, o_changeCardSwitch4); OPCODE(3, o_takePage); OPCODE(4, o_redrawCard); // Opcode 5 Not Present - OPCODE(6, o_goToDest); - OPCODE(7, o_goToDest); - OPCODE(8, o_goToDest); + OPCODE(6, o_goToDestForward); + OPCODE(7, o_goToDestLeft); + OPCODE(8, o_goToDestRight); OPCODE(9, o_triggerMovie); OPCODE(10, o_toggleVarNoRedraw); // Opcode 11 Not Present - OPCODE(12, o_changeCardSwitch); - OPCODE(13, o_changeCardSwitch); + OPCODE(12, o_changeCardSwitchLtR); + OPCODE(13, o_changeCardSwitchRtL); OPCODE(14, o_drawAreaState); OPCODE(15, o_redrawAreaForVar); OPCODE(16, o_changeCardDirectional); @@ -120,7 +120,7 @@ void MystScriptParser::setupCommonOpcodes() { OPCODE(19, o_enableAreas); OPCODE(20, o_disableAreas); OPCODE(21, o_directionalUpdate); - OPCODE(22, o_goToDest); + OPCODE(22, o_goToDestUp); OPCODE(23, o_toggleAreasActivation); OPCODE(24, o_playSound); // Opcode 25 is unused; original calls replaceSoundMyst @@ -145,6 +145,7 @@ void MystScriptParser::setupCommonOpcodes() { OPCODE(44, o_restoreMainCursor); // Opcode 45 Not Present OPCODE(46, o_soundWaitStop); + OPCODE(48, o_goToDest); OPCODE(51, o_exitMap); // Opcodes 47 to 99 Not Present @@ -273,7 +274,7 @@ void MystScriptParser::animatedUpdate(uint16 argc, uint16 *argv, uint16 delay) { while (argsRead < argc) { Common::Rect rect = Common::Rect(argv[argsRead], argv[argsRead + 1], argv[argsRead + 2], argv[argsRead + 3]); - uint16 kind = argv[argsRead + 4]; + TransitionType kind = static_cast<TransitionType>(argv[argsRead + 4]); uint16 steps = argv[argsRead + 5]; debugC(kDebugScript, "\trect.left: %d", rect.left); @@ -323,16 +324,41 @@ void MystScriptParser::o_setVar(uint16 op, uint16 var, uint16 argc, uint16 *argv _vm->redrawArea(var); } -void MystScriptParser::o_changeCardSwitch(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - // Opcodes 2, 12, and 13 are the same +void MystScriptParser::o_changeCardSwitch4(uint16 op, uint16 var, uint16 argc, uint16 *argv) { uint16 value = getVar(var); debugC(kDebugScript, "Opcode %d: changeCardSwitch var %d: %d", op, var, value); if (value) - _vm->changeToCard(argv[value -1 ], true); + _vm->changeToCard(argv[value -1 ], kTransitionDissolve); else if (_invokingResource != NULL) - _vm->changeToCard(_invokingResource->getDest(), true); + _vm->changeToCard(_invokingResource->getDest(), kTransitionDissolve); + else + warning("Missing invokingResource in altDest call"); +} + +void MystScriptParser::o_changeCardSwitchLtR(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + uint16 value = getVar(var); + + debugC(kDebugScript, "Opcode %d: changeCardSwitch var %d: %d", op, var, value); + + if (value) + _vm->changeToCard(argv[value -1 ], kTransitionLeftToRight); + else if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionLeftToRight); + else + warning("Missing invokingResource in altDest call"); +} + +void MystScriptParser::o_changeCardSwitchRtL(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + uint16 value = getVar(var); + + debugC(kDebugScript, "Opcode %d: changeCardSwitch var %d: %d", op, var, value); + + if (value) + _vm->changeToCard(argv[value -1 ], kTransitionRightToLeft); + else if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionRightToLeft); else warning("Missing invokingResource in altDest call"); } @@ -373,10 +399,47 @@ void MystScriptParser::o_goToDest(uint16 op, uint16 var, uint16 argc, uint16 *ar debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); if (_invokingResource != NULL) - _vm->changeToCard(_invokingResource->getDest(), true); + _vm->changeToCard(_invokingResource->getDest(), kTransitionCopy); + else + warning("Opcode %d: Missing invokingResource", op); +} + +void MystScriptParser::o_goToDestForward(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionDissolve); + else + warning("Opcode %d: Missing invokingResource", op); +} + +void MystScriptParser::o_goToDestLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionPartToRight); + else + warning("Opcode %d: Missing invokingResource", op); +} + +void MystScriptParser::o_goToDestRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionPartToLeft); else warning("Opcode %d: Missing invokingResource", op); } + +void MystScriptParser::o_goToDestUp(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionTopToBottom); + else + warning("Opcode %d: Missing invokingResource", op); +} + void MystScriptParser::o_triggerMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Trigger Type 6 Resource Movie..", op); // TODO: If movie has sound, pause background music @@ -427,7 +490,7 @@ void MystScriptParser::o_changeCardDirectional(uint16 op, uint16 var, uint16 arg debugC(kDebugScript, "\tcardId: %d", cardId); debugC(kDebugScript, "\tdirectonal update data size: %d", directionalUpdateDataSize); - _vm->changeToCard(cardId, false); + _vm->changeToCard(cardId, kNoTransition); animatedUpdate(directionalUpdateDataSize, &argv[2], 0); } @@ -440,23 +503,23 @@ void MystScriptParser::o_changeCardPush(uint16 op, uint16 var, uint16 argc, uint debugC(kDebugScript, "Opcode %d: Jump to Card Id, Storing Current Card Id", op); _savedCardId = _vm->getCurCard(); - uint16 cardId = argv[0]; - // argv[1] is not used in the original engine + uint16 cardId = argv[0]; + TransitionType transition = static_cast<TransitionType>(argv[1]); debugC(kDebugScript, "\tCurrent CardId: %d", _savedCardId); debugC(kDebugScript, "\tJump to CardId: %d", cardId); - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, transition); } void MystScriptParser::o_changeCardPop(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Return To Stored Card Id", op); debugC(kDebugScript, "\tCardId: %d", _savedCardId); - // argv[0] is not used in the original engine + TransitionType transition = static_cast<TransitionType>(argv[0]); - _vm->changeToCard(_savedCardId, true); + _vm->changeToCard(_savedCardId, transition); } void MystScriptParser::o_enableAreas(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -752,14 +815,11 @@ void MystScriptParser::o_changeCard(uint16 op, uint16 var, uint16 argc, uint16 * debugC(kDebugScript, "Opcode %d: Change Card", op); uint16 cardId = argv[0]; - - // Argument 1 if present is not used - // uint16 u0 = argv[1]; + TransitionType transition = static_cast<TransitionType>(argv[1]); debugC(kDebugScript, "\tTarget Card: %d", cardId); - //debugC(kDebugScript, "\tu0: %d", u0); // Unused data - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, transition); } void MystScriptParser::o_drawImageChangeCard(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -767,7 +827,7 @@ void MystScriptParser::o_drawImageChangeCard(uint16 op, uint16 var, uint16 argc, uint16 imageId = argv[0]; uint16 cardId = argv[1]; - // argv[2] is not used in the original engine + TransitionType transition = static_cast<TransitionType>(argv[2]); debugC(kDebugScript, "\timageId: %d", imageId); debugC(kDebugScript, "\tcardId: %d", cardId); @@ -775,7 +835,7 @@ void MystScriptParser::o_drawImageChangeCard(uint16 op, uint16 var, uint16 argc, _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333)); _vm->_system->updateScreen(); - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, transition); } void MystScriptParser::o_changeMainCursor(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -850,7 +910,7 @@ void MystScriptParser::o_changeCardPlaySoundDirectional(uint16 op, uint16 var, u if (soundId) _vm->_sound->replaceSoundMyst(soundId); - _vm->changeToCard(cardId, false); + _vm->changeToCard(cardId, kNoTransition); animatedUpdate(dataSize, &argv[4], delayBetweenSteps); } @@ -901,12 +961,12 @@ void MystScriptParser::o_quit(uint16 op, uint16 var, uint16 argc, uint16 *argv) void MystScriptParser::showMap() { if (_vm->getCurCard() != getMap()) { _savedMapCardId = _vm->getCurCard(); - _vm->changeToCard(getMap(), true); + _vm->changeToCard(getMap(), kTransitionCopy); } } void MystScriptParser::o_exitMap(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - _vm->changeToCard(_savedMapCardId, true); + _vm->changeToCard(_savedMapCardId, kTransitionCopy); } } // End of namespace Mohawk diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h index ccb76e0dc8..b75da0801a 100644 --- a/engines/mohawk/myst_scripts.h +++ b/engines/mohawk/myst_scripts.h @@ -86,10 +86,16 @@ public: // Common opcodes DECLARE_OPCODE(o_toggleVar); DECLARE_OPCODE(o_setVar); - DECLARE_OPCODE(o_changeCardSwitch); + DECLARE_OPCODE(o_changeCardSwitch4); + DECLARE_OPCODE(o_changeCardSwitchLtR); + DECLARE_OPCODE(o_changeCardSwitchRtL); DECLARE_OPCODE(o_takePage); DECLARE_OPCODE(o_redrawCard); DECLARE_OPCODE(o_goToDest); + DECLARE_OPCODE(o_goToDestForward); + DECLARE_OPCODE(o_goToDestLeft); + DECLARE_OPCODE(o_goToDestRight); + DECLARE_OPCODE(o_goToDestUp); DECLARE_OPCODE(o_triggerMovie); DECLARE_OPCODE(o_toggleVarNoRedraw); DECLARE_OPCODE(o_drawAreaState); diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp index 069281f5dc..63ba5f7c85 100644 --- a/engines/mohawk/myst_stacks/channelwood.cpp +++ b/engines/mohawk/myst_stacks/channelwood.cpp @@ -341,7 +341,7 @@ void Channelwood::o_drawImageChangeCardAndVolume(uint16 op, uint16 var, uint16 a _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333)); _vm->_system->updateScreen(); - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, kTransitionPartToLeft); if (argc == 3) { uint16 volume = argv[2]; @@ -476,9 +476,12 @@ void Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uint16 argc, uint16 MystResourceType6 *movie = static_cast<MystResourceType6 *>(_invokingResource); if (_state.stairsUpperDoorState) { - // TODO: Play backwards + // Close door, play the open movie backwards + movie->setDirection(-1); movie->playMovie(); } else { + // Open door + movie->setDirection(1); movie->playMovie(); } } diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp index 29a12571fd..9f393ea401 100644 --- a/engines/mohawk/myst_stacks/demo.cpp +++ b/engines/mohawk/myst_stacks/demo.cpp @@ -104,14 +104,14 @@ void Demo::returnToMenu_run() { switch (_returnToMenuStep){ case 0: _vm->_gfx->fadeToBlack(); - _vm->changeToCard(2003, false); + _vm->changeToCard(2003, kNoTransition); _vm->_gfx->fadeFromBlack(); _returnToMenuStep++; break; case 1: _vm->_gfx->fadeToBlack(); - _vm->changeToCard(2001, false); + _vm->changeToCard(2001, kNoTransition); _vm->_gfx->fadeFromBlack(); _vm->_cursor->showCursor(); diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp index 545b97d956..71733227ac 100644 --- a/engines/mohawk/myst_stacks/intro.cpp +++ b/engines/mohawk/myst_stacks/intro.cpp @@ -127,9 +127,9 @@ void Intro::introMovies_run() { break; default: if (_vm->getFeatures() & GF_DEMO) - _vm->changeToCard(2001, true); + _vm->changeToCard(2001, kTransitionRightToLeft); else - _vm->changeToCard(2, true); + _vm->changeToCard(2, kTransitionRightToLeft); } } @@ -148,7 +148,7 @@ void Intro::mystLinkBook_run() { _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); } } else if (!_linkBookMovie->isPlaying()) { - _vm->changeToCard(5, true); + _vm->changeToCard(5, kTransitionRightToLeft); } } diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp index 79de03308c..43e9bcfed5 100644 --- a/engines/mohawk/myst_stacks/mechanical.cpp +++ b/engines/mohawk/myst_stacks/mechanical.cpp @@ -39,8 +39,17 @@ Mechanical::Mechanical(MohawkEngine_Myst *vm) : MystScriptParser(vm), _state(vm->_gameState->_mechanical) { setupOpcodes(); + _elevatorGoingMiddle = false; + _mystStaircaseState = false; _fortressPosition = 0; + _fortressRotationSpeed = 0; + _fortressSimulationSpeed = 0; + _gearsWereRunning = false; + + _fortressRotationShortMovieWorkaround = false; + _fortressRotationShortMovieCount = 0; + _fortressRotationShortMovieLast = 0; } Mechanical::~Mechanical() { @@ -74,9 +83,9 @@ void Mechanical::setupOpcodes() { OPCODE(121, o_elevatorWindowMovie); OPCODE(122, o_elevatorGoMiddle); OPCODE(123, o_elevatorTopMovie); - OPCODE(124, opcode_124); + OPCODE(124, o_fortressRotationSetPosition); OPCODE(125, o_mystStaircaseMovie); - OPCODE(126, opcode_126); + OPCODE(126, o_elevatorWaitTimeout); OPCODE(127, o_crystalEnterYellow); OPCODE(128, o_crystalLeaveYellow); OPCODE(129, o_crystalEnterGreen); @@ -103,7 +112,6 @@ void Mechanical::setupOpcodes() { void Mechanical::disablePersistentScripts() { _fortressSimulationRunning = false; _elevatorRotationLeverMoving = false; - _elevatorGoingMiddle = false; _birdSinging = false; _fortressRotationRunning = false; } @@ -599,30 +607,33 @@ void Mechanical::elevatorGoMiddle_run() { _vm->_gfx->copyBackBufferToScreen(Common::Rect(10, 137, 61, 165)); _vm->_system->updateScreen(); } - } else if (_elevatorInCabin) { + } else { _elevatorTooLate = true; - - // Elevator going to middle animation - _vm->_cursor->hideCursor(); - _vm->_sound->playSoundBlocking(11120); - _vm->_gfx->copyImageToBackBuffer(6118, Common::Rect(544, 333)); - _vm->_sound->replaceSoundMyst(12120); - _vm->_gfx->runTransition(2, Common::Rect(177, 0, 370, 333), 25, 0); - _vm->_sound->playSoundBlocking(13120); - _vm->_sound->replaceSoundMyst(8120); - _vm->_gfx->copyImageToBackBuffer(6327, Common::Rect(544, 333)); - _vm->_system->delayMillis(500); - _vm->_sound->replaceSoundMyst(9120); - static uint16 moviePos[2] = { 3540, 5380 }; - o_elevatorWindowMovie(121, 0, 2, moviePos); - _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); - _vm->_sound->replaceSoundMyst(10120); - _vm->_cursor->showCursor(); - _elevatorGoingMiddle = false; - _elevatorPosition = 1; - _vm->changeToCard(6327, true); + if (_elevatorInCabin) { + + // Elevator going to middle animation + _vm->_cursor->hideCursor(); + _vm->_sound->playSoundBlocking(11120); + _vm->_gfx->copyImageToBackBuffer(6118, Common::Rect(544, 333)); + _vm->_sound->replaceSoundMyst(12120); + _vm->_gfx->runTransition(kTransitionSlideToLeft, Common::Rect(177, 0, 370, 333), 25, 0); + _vm->_sound->playSoundBlocking(13120); + _vm->_sound->replaceSoundMyst(8120); + _vm->_gfx->copyImageToBackBuffer(6327, Common::Rect(544, 333)); + _vm->_system->delayMillis(500); + _vm->_sound->replaceSoundMyst(9120); + static uint16 moviePos[2] = { 3540, 5380 }; + o_elevatorWindowMovie(121, 0, 2, moviePos); + _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); + _vm->_sound->replaceSoundMyst(10120); + _vm->_cursor->showCursor(); + + _elevatorPosition = 1; + + _vm->changeToCard(6327, kTransitionRightToLeft); + } } } } @@ -638,16 +649,18 @@ void Mechanical::o_elevatorTopMovie(uint16 op, uint16 var, uint16 argc, uint16 * _vm->_video->waitUntilMovieEnds(window); } -void Mechanical::opcode_124(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Mechanical::o_fortressRotationSetPosition(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Set fortress position", op); - if (argc == 0) { - // Used by Card 6156 (Fortress Rotation Controls) - // Called when Red Exit Button Pressed to raise Elevator + VideoHandle gears = _fortressRotationGears->playMovie(); + uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames(); + + // Myst ME short movie workaround, explained in o_fortressRotation_init + if (_fortressRotationShortMovieWorkaround) { + moviePosition += 3600 * _fortressRotationShortMovieCount; + } - // TODO: Fill in Code... - } else - unknown(op, var, argc, argv); + _fortressPosition = (moviePosition + 900) / 1800 % 4; } void Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -656,17 +669,14 @@ void Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("sstairs", kMechanicalStack), 199, 108); } -void Mechanical::opcode_126(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Mechanical::o_elevatorWaitTimeout(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Wait for the elevator to go middle", op); - 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); + // Wait while the elevator times out + while (_elevatorGoingMiddle) { + runPersistentScripts(); + _vm->skippableWait(10); + } } void Mechanical::o_crystalEnterYellow(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -776,8 +786,76 @@ void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uin } void Mechanical::fortressRotation_run() { - // Used for Card 6156 (Fortress Rotation Controls) - // TODO: Fill in function... + VideoHandle gears = _fortressRotationGears->playMovie(); + + double oldRate = _vm->_video->getVideoRate(gears).toDouble(); + + uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames(); + + // Myst ME short movie workaround, explained in o_fortressRotation_init + if (_fortressRotationShortMovieWorkaround) { + // Detect if we just looped + if (ABS<int32>(_fortressRotationShortMovieLast - 3680) < 50 + && ABS<int32>(moviePosition) < 50) { + _fortressRotationShortMovieCount++; + } + + _fortressRotationShortMovieLast = moviePosition; + + // Simulate longer movie + moviePosition += 3600 * _fortressRotationShortMovieCount; + } + + int32 positionInQuarter = 900 - (moviePosition + 900) % 1800; + + // Are the gears moving? + if (oldRate >= 0.1 || ABS<int32>(positionInQuarter) >= 30 || _fortressRotationBrake) { + + double newRate = oldRate; + if (_fortressRotationBrake && (double)_fortressRotationBrake * 0.2 > oldRate) { + newRate += 0.1; + } + + // Don't let the gears get stuck between two fortress positions + if (ABS<double>(oldRate) <= 0.05) { + if (oldRate <= 0.0) { + newRate += oldRate; + } else { + newRate -= oldRate; + } + } else { + if (oldRate <= 0.0) { + newRate += 0.05; + } else { + newRate -= 0.05; + } + } + + // Adjust speed accordingly to acceleration lever + newRate += (double) (positionInQuarter / 1500.0) + * (double) (9 - _fortressRotationSpeed) / 9.0; + + newRate = CLIP<double>(newRate, -2.5, 2.5); + + _vm->_video->setVideoRate(gears, Common::Rational((int)(newRate * 1000.0), 1000)); + + _gearsWereRunning = true; + } else if (_gearsWereRunning) { + // The fortress has stopped. Set its new position + _fortressPosition = (moviePosition + 900) / 1800 % 4; + + _vm->_video->setVideoRate(gears, 0); + + if (!_fortressRotationShortMovieWorkaround) { + _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600)); + } else { + _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * (_fortressPosition % 2), 600)); + } + + _vm->_sound->playSoundBlocking(_fortressRotationSounds[_fortressPosition]); + + _gearsWereRunning = false; + } } void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -785,6 +863,11 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin _fortressRotationGears = static_cast<MystResourceType6 *>(_invokingResource); + VideoHandle gears = _fortressRotationGears->playMovie(); + _vm->_video->setVideoLooping(gears, true); + _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600)); + _vm->_video->setVideoRate(gears, 0); + _fortressRotationSounds[0] = argv[0]; _fortressRotationSounds[1] = argv[1]; _fortressRotationSounds[2] = argv[2]; @@ -792,12 +875,113 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin _fortressRotationBrake = 0; + // WORKAROUND for the tower rotation bug in Myst ME. + // The original engine only allowed to visit two out of the three small islands, + // preventing the game from being fully completable. + // The fortress rotation is computed from the current position in the movie + // hcgears.mov. The version of this movie that shipped with the ME edition is + // too short to allow to visit all the islands. + // ScummVM simulates a longer movie by counting the number of times the movie + // looped and adding that time to the current movie position. + // Hence allowing the fortress position to be properly computed. + uint32 movieDuration = _vm->_video->getDuration(gears).convertToFramerate(600).totalNumberOfFrames(); + if (movieDuration == 3680) { + _fortressRotationShortMovieWorkaround = true; + _fortressRotationShortMovieCount = 0; + _fortressRotationShortMovieLast = 0; + } + _fortressRotationRunning = true; + _gearsWereRunning = false; } void Mechanical::fortressSimulation_run() { - // Used for Card 6044 (Fortress Rotation Simulator) - // TODO: Fill in function... + if (_fortressSimulationInit) { + // Init sequence + _vm->_sound->replaceBackgroundMyst(_fortressSimulationStartSound1, 65535); + _vm->skippableWait(5000); + _vm->_sound->replaceSoundMyst(_fortressSimulationStartSound2); + + // Update movie while the sound is playing + VideoHandle startup = _fortressSimulationStartup->playMovie(); + while (_vm->_sound->isPlaying(_fortressSimulationStartSound2)) { + if (_vm->_video->updateMovies()) + _vm->_system->updateScreen(); + + _vm->_system->delayMillis(10); + } + _vm->_sound->replaceBackgroundMyst(_fortressSimulationStartSound1, 65535); + _vm->_video->waitUntilMovieEnds(startup); + _vm->_sound->stopBackgroundMyst(); + _vm->_sound->replaceSoundMyst(_fortressSimulationStartSound2); + + + Common::Rect src = Common::Rect(0, 0, 176, 176); + Common::Rect dst = Common::Rect(187, 3, 363, 179); + _vm->_gfx->copyImageSectionToBackBuffer(6046, src, dst); + _vm->_gfx->copyBackBufferToScreen(dst); + _vm->_system->updateScreen(); + + _fortressSimulationStartup->pauseMovie(true); + VideoHandle holo = _fortressSimulationHolo->playMovie(); + _vm->_video->setVideoLooping(holo, true); + _vm->_video->setVideoRate(holo, 0); + + _vm->_cursor->showCursor(); + + _fortressSimulationInit = false; + } else { + VideoHandle holo = _fortressSimulationHolo->playMovie(); + + double oldRate = _vm->_video->getVideoRate(holo).toDouble(); + + uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(holo), 600).totalNumberOfFrames(); + + int32 positionInQuarter = 900 - (moviePosition + 900) % 1800; + + // Are the gears moving? + if (oldRate >= 0.1 || ABS<int32>(positionInQuarter) >= 30 || _fortressSimulationBrake) { + + double newRate = oldRate; + if (_fortressSimulationBrake && (double)_fortressSimulationBrake * 0.2 > oldRate) { + newRate += 0.1; + } + + // Don't let the gears get stuck between two fortress positions + if (ABS<double>(oldRate) <= 0.05) { + if (oldRate <= 0.0) { + newRate += oldRate; + } else { + newRate -= oldRate; + } + } else { + if (oldRate <= 0.0) { + newRate += 0.05; + } else { + newRate -= 0.05; + } + } + + // Adjust speed accordingly to acceleration lever + newRate += (double) (positionInQuarter / 1500.0) + * (double) (9 - _fortressSimulationSpeed) / 9.0; + + newRate = CLIP<double>(newRate, -2.5, 2.5); + + _vm->_video->setVideoRate(holo, Common::Rational((int)(newRate * 1000.0), 1000)); + + _gearsWereRunning = true; + } else if (_gearsWereRunning) { + // The fortress has stopped. Set its new position + uint16 simulationPosition = (moviePosition + 900) / 1800 % 4; + + _vm->_video->setVideoRate(holo, 0); + _vm->_video->seekToTime(holo, Audio::Timestamp(0, 1800 * simulationPosition, 600)); + _vm->_sound->playSoundBlocking( _fortressRotationSounds[simulationPosition]); + + _gearsWereRunning = false; + } + } } void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -816,6 +1000,10 @@ void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, u _fortressSimulationBrake = 0; _fortressSimulationRunning = true; + _gearsWereRunning = false; + _fortressSimulationInit = true; + + _vm->_cursor->hideCursor(); } void Mechanical::o_fortressSimulationStartup_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/myst_stacks/mechanical.h b/engines/mohawk/myst_stacks/mechanical.h index 3bd7f2d71b..7f3d5143e4 100644 --- a/engines/mohawk/myst_stacks/mechanical.h +++ b/engines/mohawk/myst_stacks/mechanical.h @@ -80,9 +80,9 @@ private: DECLARE_OPCODE(o_elevatorWindowMovie); DECLARE_OPCODE(o_elevatorGoMiddle); DECLARE_OPCODE(o_elevatorTopMovie); - DECLARE_OPCODE(opcode_124); + DECLARE_OPCODE(o_fortressRotationSetPosition); DECLARE_OPCODE(o_mystStaircaseMovie); - DECLARE_OPCODE(opcode_126); + DECLARE_OPCODE(o_elevatorWaitTimeout); DECLARE_OPCODE(o_crystalEnterYellow); DECLARE_OPCODE(o_crystalEnterGreen); DECLARE_OPCODE(o_crystalEnterRed); @@ -104,13 +104,19 @@ private: bool _mystStaircaseState; // 76 bool _fortressRotationRunning; + bool _gearsWereRunning; uint16 _fortressRotationSpeed; // 78 uint16 _fortressRotationBrake; // 80 uint16 _fortressPosition; // 82 uint16 _fortressRotationSounds[4]; // 86 to 92 MystResourceType6 *_fortressRotationGears; // 172 + bool _fortressRotationShortMovieWorkaround; + uint32 _fortressRotationShortMovieCount; + uint32 _fortressRotationShortMovieLast; + bool _fortressSimulationRunning; + bool _fortressSimulationInit; // 94 uint16 _fortressSimulationSpeed; // 96 uint16 _fortressSimulationBrake; // 98 uint16 _fortressSimulationStartSound1; // 102 diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index c1ddc74c82..f17d765c99 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -51,6 +51,8 @@ Myst::Myst(MohawkEngine_Myst *vm) : _dockVaultState = 0; _cabinDoorOpened = 0; _cabinMatchState = 2; + _cabinGaugeMovie = NULL_VID_HANDLE; + _cabinFireMovie = NULL_VID_HANDLE; _matchBurning = false; _tree = 0; _treeAlcove = 0; @@ -189,7 +191,7 @@ void Myst::setupOpcodes() { OPCODE(215, o_gulls2_init); OPCODE(216, o_treeCard_init); OPCODE(217, o_treeEntry_init); - OPCODE(218, opcode_218); + OPCODE(218, o_boilerMovies_init); OPCODE(219, o_rocketSliders_init); OPCODE(220, o_rocketLinkVideo_init); OPCODE(221, o_greenBook_init); @@ -202,7 +204,7 @@ void Myst::setupOpcodes() { OPCODE(303, NOP); OPCODE(304, o_treeCard_exit); OPCODE(305, o_treeEntry_exit); - OPCODE(306, NOP); + OPCODE(306, o_boiler_exit); OPCODE(307, o_generatorControlRoom_exit); OPCODE(308, NOP); OPCODE(309, NOP); @@ -608,6 +610,8 @@ uint16 Myst::getVar(uint16 var) { return 1; case 302: // Green Book Opened Before Flag return _state.greenBookOpenedBefore; + case 303: // Library Bookcase status changed + return _libraryBookcaseChanged; case 304: // Tower Rotation Map Initialized return _towerRotationMapInitialized; case 305: // Cabin Boiler Lit @@ -1041,7 +1045,7 @@ void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { // No page or white page if (!_globals.heldPage || _globals.heldPage == 13) { - _vm->changeToCard(cardIdBookCover, true); + _vm->changeToCard(cardIdBookCover, kTransitionDissolve); return; } @@ -1083,7 +1087,7 @@ void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { // Wrong book if (bookVar != var) { - _vm->changeToCard(cardIdBookCover, true); + _vm->changeToCard(cardIdBookCover, kTransitionDissolve); return; } @@ -1109,9 +1113,9 @@ void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { else _globals.currentAge = 10; - _vm->changeToCard(cardIdLose, true); + _vm->changeToCard(cardIdLose, kTransitionDissolve); } else { - _vm->changeToCard(cardIdBookCover, true); + _vm->changeToCard(cardIdBookCover, kTransitionDissolve); } } @@ -1298,7 +1302,7 @@ void Myst::imagerValidation_run() { if (_imagerValidationStep == 11) { _imagerValidationStep = 0; - _vm->changeToCard(_imagerValidationCard, true); + _vm->changeToCard(_imagerValidationCard, kTransitionBottomToTop); } else { _startTime = time + 100; } @@ -1473,10 +1477,10 @@ void Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16 argc, uint16 *arg if (soundId) _vm->_sound->replaceSoundMyst(soundId); - _vm->changeToCard(4103, false); + _vm->changeToCard(4103, kNoTransition); Common::Rect screenRect = Common::Rect(544, 333); - _vm->_gfx->runTransition(0, screenRect, 2, 5); + _vm->_gfx->runTransition(kTransitionLeftToRight, screenRect, 2, 5); } _tempVar = 1; } else { @@ -1869,17 +1873,50 @@ void Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 argc, uint16 *argv) _state.cabinPilotLightLit = 1; _vm->redrawArea(98); + boilerFireUpdate(false); + // Put out match _matchGoOutTime = _vm->_system->getMillis(); if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - if (_state.cabinValvePosition > 12) + if (_state.cabinValvePosition > 12) { + // Compute the speed of the gauge to synchronize it with the next tree move + uint32 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + boilerResetGauge(rate); + _state.treeLastMoveTime = _vm->_system->getMillis(); + } + } +} - // TODO: Complete. Play movies +Common::Rational Myst::boilerComputeGaugeRate(uint16 pressure, uint32 delay) { + Common::Rational rate = Common::Rational(2088, delay); + if (pressure < 12) + return -rate; + else + return rate; +} + +void Myst::boilerResetGauge(const Common::Rational &rate) { + if (_vm->_video->endOfVideo(_cabinGaugeMovie)) { + if (_vm->getCurCard() == 4098) { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); + } else { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136); + } } + + Audio::Timestamp goTo; + if (rate > 0) + goTo = Audio::Timestamp(0, 0, 600); + else + goTo = _vm->_video->getDuration(_cabinGaugeMovie); + + _vm->_video->seekToTime(_cabinGaugeMovie, goTo); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); } void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -1893,7 +1930,12 @@ void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - // TODO: Play movies + if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + } + } else if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10); } @@ -1903,7 +1945,8 @@ void Myst::boilerPressureIncrease_run() { if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition < 25) { _state.cabinValvePosition++; if (_state.cabinValvePosition == 1) { - // TODO: Play fire movie + // Set fire to high + boilerFireUpdate(false); // Draw fire _vm->redrawArea(305); @@ -1927,7 +1970,8 @@ void Myst::boilerPressureDecrease_run() { if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition > 0) { _state.cabinValvePosition--; if (_state.cabinValvePosition == 0) { - // TODO: Play fire movie + // Set fire to low + boilerFireUpdate(false); // Draw fire _vm->redrawArea(305); @@ -1961,7 +2005,12 @@ void Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - // TODO: Play movies + if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + } + } else { if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10); @@ -2067,6 +2116,11 @@ void Myst::tree_run() { // Check if alcove is accessible treeSetAlcoveAccessible(); + if (_cabinGaugeMovie != NULL_VID_HANDLE) { + Common::Rational rate = boilerComputeGaugeRate(pressure, delay); + boilerResetGauge(rate); + } + _state.treeLastMoveTime = time; } } @@ -2968,7 +3022,12 @@ void Myst::clockReset() { _vm->_system->delayMillis(1000); _vm->_sound->replaceSoundMyst(7113); - // TODO: Play cl1wggat backwards + // Gear closing movie + VideoHandle handle = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack) , 195, 225); + _vm->_video->seekToTime(handle, _vm->_video->getDuration(handle)); + _vm->_video->setVideoRate(handle, -1); + _vm->_video->waitUntilMovieEnds(handle); + // Redraw gear _state.gearsOpen = 0; _vm->redrawArea(40); @@ -2980,16 +3039,9 @@ void Myst::clockReset() { void Myst::clockResetWeight() { _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0); - if (!(_vm->getFeatures() & GF_ME)) { - // Set video bounds, weight going up - _vm->_video->setVideoBounds(_clockWeightVideo, - Audio::Timestamp(0, 2214 * 2 - _clockWeightPosition, 600), - Audio::Timestamp(0, 2214 * 2, 600)); - } else { - //FIXME: Needs QT backwards playing, for now just display the weight up - warning("Weight going back up not implemented"); - _vm->_video->drawVideoFrame(_clockWeightVideo, Audio::Timestamp(0, 0, 600)); - } + // Play the movie backwards, weight going up + _vm->_video->seekToTime(_clockWeightVideo, Audio::Timestamp(0, _clockWeightPosition, 600)); + _vm->_video->setVideoRate(_clockWeightVideo, -1); // Reset position _clockWeightPosition = 0; @@ -3246,7 +3298,7 @@ void Myst::libraryBookcaseTransform_run(void) { if (_state.libraryBookcaseDoor) { _vm->_gfx->copyImageSectionToBackBuffer(11179, Common::Rect(0, 0, 106, 81), Common::Rect(0, 72, 106, 153)); - _vm->_gfx->runTransition(6, Common::Rect(0, 72, 106, 153), 5, 10); + _vm->_gfx->runTransition(kTransitionBottomToTop, Common::Rect(0, 72, 106, 153), 5, 10); _vm->_sound->playSoundBlocking(7348); _vm->_sound->replaceBackgroundMyst(4348, 16384); } else { @@ -3510,22 +3562,60 @@ void Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { treeSetAlcoveAccessible(); } -void Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Myst::o_boilerMovies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Boiler movies init", op); - // Used for Card 4097 (Cabin Boiler) - // TODO: Fill in logic - if (false) { - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244); - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 138); + boilerFireInit(); + boilerGaugeInit(); +} + +void Myst::boilerFireInit() { + if (_vm->getCurCard() == 4098) { + _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279, true); + _vm->_video->pauseMovie(_cabinFireMovie, true); + + _vm->redrawArea(305); + boilerFireUpdate(true); + } else { + if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition >= 1) { + _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244, true); + } + } +} + +void Myst::boilerFireUpdate(bool init) { + uint position = _vm->_video->getTime(_cabinFireMovie); + + if (_state.cabinPilotLightLit == 1) { + if (_state.cabinValvePosition == 0) { + if (position > (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { + _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 100, 600)); + _vm->_video->pauseMovie(_cabinFireMovie, false); + } + } else { + if (position < (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { + _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 201, 600), Audio::Timestamp(0, 1900, 600)); + _vm->_video->pauseMovie(_cabinFireMovie, false); + } + } } +} - // Used for Card 4098 (Cabin Boiler) - // TODO: Fill in logic - if (false) { - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279); - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 97); +void Myst::boilerGaugeInit() { + if (_vm->getCurCard() == 4098) { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); + } else { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136); } + + Audio::Timestamp frame; + + if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12) + frame = _vm->_video->getDuration(_cabinGaugeMovie); + else + frame = Audio::Timestamp(0, 0, 600); + + _vm->_video->drawVideoFrame(_cabinGaugeMovie, frame); } void Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -3648,6 +3738,13 @@ void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { _treeAlcove = 0; } +void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Exit boiler card", op); + + _cabinGaugeMovie = NULL_VID_HANDLE; + _cabinFireMovie = NULL_VID_HANDLE; +} + void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Generator room exit", op); diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h index e9bff08cb4..de88843d59 100644 --- a/engines/mohawk/myst_stacks/myst.h +++ b/engines/mohawk/myst_stacks/myst.h @@ -43,7 +43,7 @@ public: virtual void disablePersistentScripts(); virtual void runPersistentScripts(); -private: +protected: void setupOpcodes(); uint16 getVar(uint16 var); void toggleVar(uint16 var); @@ -52,7 +52,7 @@ private: virtual uint16 getMap() { return 9934; } void towerRotationMap_run(); - void libraryBookcaseTransform_run(); + virtual void libraryBookcaseTransform_run(); void generatorControlRoom_run(); void opcode_212_run(); void libraryCombinationBook_run(); @@ -174,7 +174,7 @@ private: DECLARE_OPCODE(o_gulls2_init); DECLARE_OPCODE(o_treeCard_init); DECLARE_OPCODE(o_treeEntry_init); - DECLARE_OPCODE(opcode_218); + DECLARE_OPCODE(o_boilerMovies_init); DECLARE_OPCODE(o_rocketSliders_init); DECLARE_OPCODE(o_rocketLinkVideo_init); DECLARE_OPCODE(o_greenBook_init); @@ -183,6 +183,7 @@ private: DECLARE_OPCODE(o_bookAddSpecialPage_exit); DECLARE_OPCODE(o_treeCard_exit); DECLARE_OPCODE(o_treeEntry_exit); + DECLARE_OPCODE(o_boiler_exit); DECLARE_OPCODE(o_generatorControlRoom_exit); @@ -259,6 +260,9 @@ private: uint16 _cabinMatchState; // 60 uint32 _matchGoOutTime; // 144 + VideoHandle _cabinFireMovie; // 240 + VideoHandle _cabinGaugeMovie; // 244 + bool _boilerPressureIncreasing; bool _boilerPressureDecreasing; bool _basementPressureIncreasing; @@ -317,6 +321,12 @@ private: Common::Point towerRotationMapComputeCoords(const Common::Point ¢er, uint16 angle); void towerRotationMapDrawLine(const Common::Point ¢er, const Common::Point &end); + void boilerFireInit(); + void boilerFireUpdate(bool init); + void boilerGaugeInit(); + Common::Rational boilerComputeGaugeRate(uint16 pressure, uint32 delay); + void boilerResetGauge(const Common::Rational &rate); + void treeSetAlcoveAccessible(); uint32 treeNextMoveDelay(uint16 pressure); diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp index 0b8dcf897a..75e870281e 100644 --- a/engines/mohawk/myst_stacks/preview.cpp +++ b/engines/mohawk/myst_stacks/preview.cpp @@ -60,6 +60,7 @@ void Preview::setupOpcodes() { OVERRIDE_OPCODE(199, o_speechStop); // "Init" Opcodes + OVERRIDE_OPCODE(209, o_libraryBookcaseTransformDemo_init); OPCODE(298, o_speech_init); OPCODE(299, o_library_init); } @@ -139,7 +140,7 @@ void Preview::speech_run() { break; case 1: // Open book if (_currentCue >= 1) { - _vm->changeToCard(3001, true); + _vm->changeToCard(3001, kTransitionDissolve); _speechStep++; } @@ -147,7 +148,7 @@ void Preview::speech_run() { case 2: // Go to Myst if (_currentCue >= 2) { _vm->_gfx->fadeToBlack(); - _vm->changeToCard(3002, false); + _vm->changeToCard(3002, kNoTransition); _vm->_gfx->fadeFromBlack(); _speechStep++; @@ -164,7 +165,7 @@ void Preview::speech_run() { if (_currentCue >= 4) { _library->drawConditionalDataToScreen(0); - _vm->changeToCard(3003, true); + _vm->changeToCard(3003, kTransitionDissolve); _speechNextTime = time + 2000; _speechStep++; @@ -181,7 +182,7 @@ void Preview::speech_run() { if (time < _speechNextTime) break; - _vm->changeToCard(3004, true); + _vm->changeToCard(3004, kTransitionDissolve); _speechNextTime = time + 2000; _speechStep++; break; @@ -190,7 +191,7 @@ void Preview::speech_run() { break; _vm->_gfx->fadeToBlack(); - _vm->changeToCard(3005, false); + _vm->changeToCard(3005, kNoTransition); _vm->_gfx->fadeFromBlack(); _speechNextTime = time + 1000; _speechStep++; @@ -205,7 +206,7 @@ void Preview::speech_run() { if (time < _speechNextTime) break; - _vm->changeToCard(3006 + _speechStep - 7, true); + _vm->changeToCard(3006 + _speechStep - 7, kTransitionDissolve); _speechNextTime = time + 2000; _speechStep++; break; @@ -213,7 +214,7 @@ void Preview::speech_run() { if (time < _speechNextTime) break; - _vm->changeToCard(4329, true); + _vm->changeToCard(4329, kTransitionDissolve); _speechRunning = false; _globals.currentAge = 2; @@ -241,5 +242,22 @@ void Preview::o_library_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { _library = static_cast<MystResourceType8 *>(_invokingResource); } +void Preview::o_libraryBookcaseTransformDemo_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + if (_libraryBookcaseChanged) { + MystResourceType7 *resource = static_cast<MystResourceType7 *>(_invokingResource); + _libraryBookcaseMovie = static_cast<MystResourceType6 *>(resource->getSubResource(getVar(303))); + _libraryBookcaseSoundId = argv[0]; + _libraryBookcaseMoving = true; + } +} + +void Preview::libraryBookcaseTransform_run() { + if (_libraryBookcaseChanged) + _state.libraryBookcaseDoor = !_state.libraryBookcaseDoor; + + Myst::libraryBookcaseTransform_run(); +} + + } // End of namespace MystStacks } // End of namespace Mohawk diff --git a/engines/mohawk/myst_stacks/preview.h b/engines/mohawk/myst_stacks/preview.h index 1e4ff3efb4..706220e8ed 100644 --- a/engines/mohawk/myst_stacks/preview.h +++ b/engines/mohawk/myst_stacks/preview.h @@ -51,6 +51,7 @@ private: DECLARE_OPCODE(o_stayHere); DECLARE_OPCODE(o_speechStop); + DECLARE_OPCODE(o_libraryBookcaseTransformDemo_init); DECLARE_OPCODE(o_speech_init); DECLARE_OPCODE(o_library_init); @@ -65,6 +66,8 @@ private: void speech_run(); void speechUpdateCue(); + + void libraryBookcaseTransform_run(); }; } // End of namespace MystStacks diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp index 1473742259..a941b14eaa 100644 --- a/engines/mohawk/myst_stacks/selenitic.cpp +++ b/engines/mohawk/myst_stacks/selenitic.cpp @@ -729,11 +729,11 @@ void Selenitic::o_mazeRunnerDoorButton(uint16 op, uint16 var, uint16 argc, uint1 uint16 cardIdEntry = argv[1]; if (_mazeRunnerPosition == 288) { - _vm->changeToCard(cardIdEntry, false); + _vm->changeToCard(cardIdEntry, kNoTransition); _vm->_sound->replaceSoundMyst(cardIdEntry); animatedUpdate(argv[2], &argv[3], 10); } else if (_mazeRunnerPosition == 289) { - _vm->changeToCard(cardIdExit, false); + _vm->changeToCard(cardIdExit, kNoTransition); _vm->_sound->replaceSoundMyst(cardIdExit); animatedUpdate(argv[2], &argv[3], 10); } @@ -895,9 +895,9 @@ void Selenitic::o_soundLockButton(uint16 op, uint16 var, uint16 argc, uint16 *ar uint16 cardIdClosed = argv[0]; uint16 cardIdOpen = argv[1]; - _vm->changeToCard(cardIdClosed, true); + _vm->changeToCard(cardIdClosed, kTransitionDissolve); - _vm->changeToCard(cardIdOpen, false); + _vm->changeToCard(cardIdOpen, kNoTransition); _vm->_sound->replaceSoundMyst(argv[2]); animatedUpdate(argv[4], &argv[5], argv[3]); diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp index c0bb400db1..720926904a 100644 --- a/engines/mohawk/myst_stacks/slides.cpp +++ b/engines/mohawk/myst_stacks/slides.cpp @@ -63,7 +63,7 @@ void Slides::runPersistentScripts() { // Used on Cards... if (_vm->_system->getMillis() > _nextCardTime) { _vm->_gfx->fadeToBlack(); - _vm->changeToCard(_nextCardID, false); + _vm->changeToCard(_nextCardID, kNoTransition); _vm->_gfx->fadeFromBlack(); } } diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp index ef228e62f3..1359685302 100644 --- a/engines/mohawk/myst_stacks/stoneship.cpp +++ b/engines/mohawk/myst_stacks/stoneship.cpp @@ -440,9 +440,9 @@ void Stoneship::o_drawerOpenSirius(uint16 op, uint16 var, uint16 argc, uint16 *a drawer->drawConditionalDataToScreen(0, 0); } - uint16 transition = 5; + TransitionType transition = kTransitionTopToBottom; if (argc == 2 && argv[1]) - transition = 11; + transition = kTransitionCopy; _vm->_gfx->runTransition(transition, drawer->getRect(), 25, 5); } @@ -579,7 +579,7 @@ void Stoneship::o_drawerOpenAchenar(uint16 op, uint16 var, uint16 argc, uint16 * MystResourceType8 *drawer = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]); drawer->drawConditionalDataToScreen(0, 0); - _vm->_gfx->runTransition(5, drawer->getRect(), 25, 5); + _vm->_gfx->runTransition(kTransitionTopToBottom, drawer->getRect(), 25, 5); } void Stoneship::o_hologramPlayback(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -692,9 +692,9 @@ void Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint16 argc, uint16 *a _vm->_sound->resumeBackgroundMyst(); } else { // Valve opening - // TODO: Play backwards VideoHandle valve = _vm->_video->playMovie(movie, 97, 267); - _vm->_video->setVideoBounds(valve, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 350, 600)); + _vm->_video->seekToTime(valve, Audio::Timestamp(0, 350, 600)); + _vm->_video->setVideoRate(valve, -1); _vm->_video->waitUntilMovieEnds(valve); } } @@ -777,7 +777,7 @@ void Stoneship::o_cloudOrbLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv _cloudOrbMovie->pauseMovie(true); _vm->_sound->replaceSoundMyst(_cloudOrbStopSound); - _vm->_gfx->runTransition(5, _invokingResource->getRect(), 4, 0); + _vm->_gfx->runTransition(kTransitionTopToBottom, _invokingResource->getRect(), 4, 0); } void Stoneship::o_drawerCloseOpened(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -794,7 +794,7 @@ void Stoneship::drawerClose(uint16 drawer) { _vm->drawResourceImages(); MystResource *res = _vm->_resources[drawer]; - _vm->_gfx->runTransition(6, res->getRect(), 25, 5); + _vm->_gfx->runTransition(kTransitionBottomToTop, res->getRect(), 25, 5); } void Stoneship::o_hologramDisplay_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp index f01375bacf..d7e829118a 100644 --- a/engines/mohawk/resource.cpp +++ b/engines/mohawk/resource.cpp @@ -464,4 +464,4 @@ bool DOSArchive_v2::openStream(Common::SeekableReadStream *stream) { return true; } -} // End of namespace Mohawk +} // End of namespace Mohawk diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 32613c6185..71aa371073 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -177,7 +177,7 @@ Common::Error MohawkEngine_Riven::run() { } } else { // Otherwise, start us off at aspit's card 1 (the main menu) - changeToStack(aspit); + changeToStack(aspit); changeToCard(1); } @@ -830,7 +830,7 @@ static void sunnersTopStairsTimer(MohawkEngine_Riven *vm) { } else if (sunnerTime < vm->getTotalPlayTime()) { VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(1, 3)); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(2, 15) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(2, 15) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -868,7 +868,7 @@ static void sunnersMidStairsTimer(MohawkEngine_Riven *vm) { VideoHandle handle = vm->_video->playMovieRiven(movie); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 10) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 10) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -898,7 +898,7 @@ static void sunnersLowerStairsTimer(MohawkEngine_Riven *vm) { } else if (sunnerTime < vm->getTotalPlayTime()) { VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(3, 5)); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 30) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -932,7 +932,7 @@ static void sunnersBeachTimer(MohawkEngine_Riven *vm) { vm->_video->activateMLST(mlstID, vm->getCurCard()); VideoHandle handle = vm->_video->playMovieRiven(mlstID); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 30) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 337a57e3e1..384e89a4cf 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -1467,7 +1467,7 @@ static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) { VideoHandle videoHandle = vm->_video->playMovieRiven(30); // Reset the timer - vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle) + vm->_rnd->getRandomNumber(60) * 1000); + vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle).msecs() + vm->_rnd->getRandomNumber(60) * 1000); } void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { @@ -1507,7 +1507,7 @@ void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { _vm->_video->activateMLST(cathMovie, _vm->getCurCard()); VideoHandle videoHandle = _vm->_video->playMovieRiven(30); - timeUntilNextMovie = _vm->_video->getDuration(videoHandle) + _vm->_rnd->getRandomNumber(60) * 1000; + timeUntilNextMovie = _vm->_video->getDuration(videoHandle).msecs() + _vm->_rnd->getRandomNumber(60) * 1000; } else { // Otherwise, just redraw the imager timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000; @@ -2335,7 +2335,7 @@ static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) { VideoHandle handle = vm->_video->playMovieRiven(movie); // Ensure the next video starts after this one ends - uint32 timeUntilNextVideo = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(38, 58) * 1000; + uint32 timeUntilNextVideo = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(38, 58) * 1000; // Save the time in case we leave the card and return vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime(); diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index b1b99722d5..8b0130d711 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -493,9 +493,9 @@ uint32 VideoManager::getTime(VideoHandle handle) { return _videoStreams[handle]->getTime(); } -uint32 VideoManager::getDuration(VideoHandle handle) { +Audio::Timestamp VideoManager::getDuration(VideoHandle handle) { assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getDuration().msecs(); + return _videoStreams[handle]->getDuration(); } bool VideoManager::endOfVideo(VideoHandle handle) { @@ -536,6 +536,16 @@ void VideoManager::setVideoLooping(VideoHandle handle, bool loop) { _videoStreams[handle].loop = loop; } +Common::Rational VideoManager::getVideoRate(VideoHandle handle) const { + assert(handle != NULL_VID_HANDLE); + return _videoStreams[handle]->getRate(); +} + +void VideoManager::setVideoRate(VideoHandle handle, const Common::Rational &rate) { + assert(handle != NULL_VID_HANDLE); + _videoStreams[handle]->setRate(rate); +} + void VideoManager::pauseMovie(VideoHandle handle, bool pause) { assert(handle != NULL_VID_HANDLE); _videoStreams[handle]->pauseVideo(pause); diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h index 6d2783936d..2c4c827aa8 100644 --- a/engines/mohawk/video.h +++ b/engines/mohawk/video.h @@ -101,12 +101,14 @@ public: int getCurFrame(VideoHandle handle); uint32 getFrameCount(VideoHandle handle); uint32 getTime(VideoHandle handle); - uint32 getDuration(VideoHandle videoHandle); + Audio::Timestamp getDuration(VideoHandle videoHandle); bool endOfVideo(VideoHandle handle); void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end); void drawVideoFrame(VideoHandle handle, Audio::Timestamp time); void seekToTime(VideoHandle handle, Audio::Timestamp time); void setVideoLooping(VideoHandle handle, bool loop); + Common::Rational getVideoRate(VideoHandle handle) const; + void setVideoRate(VideoHandle handle, const Common::Rational &rate); void waitUntilMovieEnds(VideoHandle videoHandle); void delayUntilMovieEnds(VideoHandle videoHandle); void pauseMovie(VideoHandle videoHandle, bool pause); diff --git a/engines/mohawk/view.cpp b/engines/mohawk/view.cpp index 36e8f8466e..719c288af5 100644 --- a/engines/mohawk/view.cpp +++ b/engines/mohawk/view.cpp @@ -361,8 +361,8 @@ void View::idleView() { void View::setModule(Module *module) { if (_currentModule) { - module->shutdown(); - delete module; + _currentModule->shutdown(); + delete _currentModule; } _currentModule = NULL; |