aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk')
-rw-r--r--engines/mohawk/console.cpp4
-rw-r--r--engines/mohawk/cursors.cpp5
-rw-r--r--engines/mohawk/detection.cpp1
-rw-r--r--engines/mohawk/detection_tables.h89
-rw-r--r--engines/mohawk/dialogs.cpp12
-rw-r--r--engines/mohawk/installer_archive.cpp2
-rw-r--r--engines/mohawk/livingbooks.cpp28
-rw-r--r--engines/mohawk/livingbooks_code.cpp79
-rw-r--r--engines/mohawk/livingbooks_code.h3
-rw-r--r--engines/mohawk/livingbooks_lbx.cpp17
-rw-r--r--engines/mohawk/myst.cpp78
-rw-r--r--engines/mohawk/myst.h19
-rw-r--r--engines/mohawk/myst_areas.cpp43
-rw-r--r--engines/mohawk/myst_graphics.cpp283
-rw-r--r--engines/mohawk/myst_graphics.h10
-rw-r--r--engines/mohawk/myst_scripts.cpp118
-rw-r--r--engines/mohawk/myst_scripts.h8
-rw-r--r--engines/mohawk/myst_stacks/channelwood.cpp7
-rw-r--r--engines/mohawk/myst_stacks/demo.cpp4
-rw-r--r--engines/mohawk/myst_stacks/intro.cpp6
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp280
-rw-r--r--engines/mohawk/myst_stacks/mechanical.h10
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp175
-rw-r--r--engines/mohawk/myst_stacks/myst.h16
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp32
-rw-r--r--engines/mohawk/myst_stacks/preview.h3
-rw-r--r--engines/mohawk/myst_stacks/selenitic.cpp8
-rw-r--r--engines/mohawk/myst_stacks/slides.cpp2
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp14
-rw-r--r--engines/mohawk/resource.cpp2
-rw-r--r--engines/mohawk/riven.cpp10
-rw-r--r--engines/mohawk/riven_external.cpp6
-rw-r--r--engines/mohawk/video.cpp14
-rw-r--r--engines/mohawk/video.h4
-rw-r--r--engines/mohawk/view.cpp4
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> &params);
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> &params, 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> &params, 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 &center, uint16 angle);
void towerRotationMapDrawLine(const Common::Point &center, 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;