[Scummvm-git-logs] scummvm master -> 2de359f23de43db2ab3e46f55c0bb5a880ea8441

bgK bastien.bouclet at gmail.com
Wed Jun 13 08:02:07 CEST 2018


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
13b3371f1a MOHAWK: MYST: Extract a Card class out of the main engine class
ea60aef8a8 MOHAWK: MYST: Simplify memory management of the active stack
47ddd9c214 MOHAWK: MYST: Move the current stack id to ScriptParser
2de359f23d MOHAWK: MYST: Make the scripts time accounting pause safe


Commit: 13b3371f1af143a319656bf476712abf41ee613b
    https://github.com/scummvm/scummvm/commit/13b3371f1af143a319656bf476712abf41ee613b
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2018-06-13T07:55:55+02:00

Commit Message:
MOHAWK: MYST: Extract a Card class out of the main engine class

This is to allow having multiple cards loaded at the same time in the
future.

Changed paths:
  A engines/mohawk/myst_card.cpp
  A engines/mohawk/myst_card.h
    engines/mohawk/console.cpp
    engines/mohawk/module.mk
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/myst_areas.cpp
    engines/mohawk/myst_scripts.cpp
    engines/mohawk/myst_scripts.h
    engines/mohawk/myst_stacks/channelwood.cpp
    engines/mohawk/myst_stacks/credits.cpp
    engines/mohawk/myst_stacks/mechanical.cpp
    engines/mohawk/myst_stacks/myst.cpp
    engines/mohawk/myst_stacks/selenitic.cpp
    engines/mohawk/myst_stacks/stoneship.cpp


diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index f24df96..2251ce0 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -36,6 +36,7 @@
 #ifdef ENABLE_MYST
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_scripts.h"
 #include "mohawk/myst_sound.h"
@@ -88,7 +89,7 @@ bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) {
 }
 
 bool MystConsole::Cmd_CurCard(int argc, const char **argv) {
-	debugPrintf("Current Card: %d\n", _vm->getCurCard());
+	debugPrintf("Current Card: %d\n", _vm->getCard()->getId());
 	return true;
 }
 
@@ -210,8 +211,8 @@ bool MystConsole::Cmd_DrawRect(int argc, const char **argv) {
 		_vm->_gfx->drawRect(Common::Rect((uint16)atoi(argv[1]), (uint16)atoi(argv[2]), (uint16)atoi(argv[3]), (uint16)atoi(argv[4])), kRectEnabled);
 	} else if (argc == 2) {
 		uint16 resourceId = (uint16)atoi(argv[1]);
-		if (resourceId < _vm->_resources.size())
-			_vm->_resources[resourceId]->drawBoundingRect();
+		if (resourceId < _vm->getCard()->_resources.size())
+			_vm->getCard()->_resources[resourceId]->drawBoundingRect();
 	}
 
 	return false;
@@ -223,7 +224,7 @@ bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) {
 		return true;
 	}
 
-	_vm->setResourceEnabled((uint16)atoi(argv[1]), atoi(argv[2]) == 1);
+	_vm->getCard()->setResourceEnabled((uint16)atoi(argv[1]), atoi(argv[2]) == 1);
 	return true;
 }
 
@@ -316,10 +317,10 @@ bool MystConsole::Cmd_Cache(int argc, const char **argv) {
 }
 
 bool MystConsole::Cmd_Resources(int argc, const char **argv) {
-	debugPrintf("Resources in card %d:\n", _vm->getCurCard());
+	debugPrintf("Resources in card %d:\n", _vm->getCard()->getId());
 
-	for (uint i = 0; i < _vm->_resources.size(); i++) {
-		debugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str());
+	for (uint i = 0; i < _vm->getCard()->_resources.size(); i++) {
+		debugPrintf("#%2d %s\n", i, _vm->getCard()->_resources[i]->describe().c_str());
 	}
 
 	return true;
@@ -343,10 +344,13 @@ bool MystConsole::Cmd_QuickTest(int argc, const char **argv) {
 
 			_vm->doFrame();
 
-			int16 resIndex = _vm->_rnd->getRandomNumber(_vm->_resources.size()) - 1;
-			if (resIndex >= 0 && _vm->_resources[resIndex]->isEnabled()) {
-				_vm->_resources[resIndex]->handleMouseDown();
-				_vm->_resources[resIndex]->handleMouseUp();
+			{
+				MystCardPtr card = _vm->getCardPtr();
+				int16 resIndex = _vm->_rnd->getRandomNumber(card->_resources.size()) - 1;
+				if (resIndex >= 0 && _vm->getCard()->_resources[resIndex]->isEnabled()) {
+					card->_resources[resIndex]->handleMouseDown();
+					card->_resources[resIndex]->handleMouseUp();
+				}
 			}
 
 			_vm->doFrame();
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index e20638f..4957ff3 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -32,6 +32,7 @@ ifdef ENABLE_MYST
 MODULE_OBJS += \
 	myst.o \
 	myst_areas.o \
+	myst_card.o \
 	myst_graphics.o \
 	myst_scripts.o \
 	myst_sound.o \
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 4ff1df2..d0d3a3c 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -29,6 +29,7 @@
 #include "mohawk/cursors.h"
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_scripts.h"
 #include "mohawk/myst_sound.h"
@@ -71,13 +72,8 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
 	_mainCursor = kDefaultMystCursor;
 	_showResourceRects = false;
 	_curStack = 0;
-	_curCard = 0;
 	_lastSaveTime = 0;
 
-	_hoverResource = nullptr;
-	_activeResource = nullptr;
-	_clickedResource = nullptr;
-
 	_sound = nullptr;
 	_video = nullptr;
 	_gfx = nullptr;
@@ -93,7 +89,6 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
 	_mouseMoved = false;
 	_escapePressed = false;
 	_waitingOnBlockingOperation = false;
-	_runExitScript = true;
 
 	_needsPageDrop = false;
 	_needsShowCredits = false;
@@ -113,9 +108,6 @@ MohawkEngine_Myst::~MohawkEngine_Myst() {
 	delete _optionsDialog;
 	delete _prevStack;
 	delete _rnd;
-
-	for (uint32 i = 0; i < _resources.size(); i++)
-		delete _resources[i];
 }
 
 // Uses cached data objects in preference to disk access
@@ -133,7 +125,6 @@ Common::SeekableReadStream *MohawkEngine_Myst::getResource(uint32 tag, uint16 id
 		}
 
 	error("Could not find a \'%s\' resource with ID %04x", tag2str(tag), id);
-	return nullptr;
 }
 
 Common::Array<uint16> MohawkEngine_Myst::getResourceIDList(uint32 type) const {
@@ -499,8 +490,16 @@ void MohawkEngine_Myst::doFrame() {
 	}
 
 	if (isInteractive()) {
-		updateActiveResource();
-		checkCurrentResource();
+		Common::Point mousePos = _system->getEventManager()->getMousePos();
+
+		// Keep a reference to the card so it is not freed if a script switches to another card
+		MystCardPtr card = _card;
+		card->updateActiveResource(mousePos);
+		card->updateResourcesForInput(mousePos, _mouseClicked, _mouseMoved);
+
+		refreshCursor();
+
+		_mouseMoved = false;
 	}
 
 	_system->updateScreen();
@@ -566,6 +565,9 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 	if (linkSrcSound)
 		playSoundBlocking(linkSrcSound);
 
+	_card->leave();
+	_card.reset();
+
 	// Delete the previous stack and move the current stack to the previous one
 	// There's probably a better way to do this, but the script classes shouldn't
 	// take up much memory.
@@ -635,8 +637,6 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 	if (!_mhk[0]->openFile(mystFiles[_curStack]))
 		error("Could not open %s", mystFiles[_curStack]);
 
-	_runExitScript = false;
-
 	// Clear the resource cache and the image cache
 	_cache.clear();
 	_gfx->clearCache();
@@ -647,26 +647,6 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 		playSoundBlocking(linkDstSound);
 }
 
-uint16 MohawkEngine_Myst::getCardBackgroundId() {
-	uint16 imageToDraw = 0;
-
-	if (_view.conditionalImages.size() == 0)
-		imageToDraw = _view.mainImage;
-	else {
-		for (uint16 i = 0; i < _view.conditionalImages.size(); i++) {
-			uint16 varValue = _scriptParser->getVar(_view.conditionalImages[i].var);
-			if (varValue < _view.conditionalImages[i].values.size())
-				imageToDraw = _view.conditionalImages[i].values[varValue];
-		}
-	}
-
-	return imageToDraw;
-}
-
-void MohawkEngine_Myst::drawCardBackground() {
-	_gfx->copyImageToBackBuffer(getCardBackgroundId(), Common::Rect(0, 0, 544, 332));
-}
-
 void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
 	debug(2, "changeToCard(%d)", card);
 
@@ -674,14 +654,6 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
 
 	_video->stopVideos();
 
-	// Run exit script from last card (if present)
-	if (_runExitScript)
-		runExitScript();
-
-	_runExitScript = true;
-
-	unloadCard();
-
 	// Clear the resource cache and image cache
 	_cache.clear();
 	_gfx->clearCache();
@@ -689,30 +661,13 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
 	_mouseClicked = false;
 	_mouseMoved = false;
 	_escapePressed = false;
-	_curCard = card;
-
-	// Load a bunch of stuff
-	loadCard();
-	loadResources();
-	loadCursorHints();
 
-	// Handle images
-	drawCardBackground();
-
-	// Handle sound
-	applySoundBlock(_view.soundBlock);
-
-	if (_view.flags & kMystZipDestination)
-		_gameState->addZipDest(_curStack, card);
-
-	// Run the entrance script (if present)
-	runInitScript();
-
-	// Update the images of each area too
-	drawResourceImages();
+	if (_card) {
+		_card->leave();
+	}
 
-	for (uint16 i = 0; i < _resources.size(); i++)
-		_resources[i]->handleCardChange();
+	_card = MystCardPtr(new MystCard(this, card));
+	_card->enter();
 
 	// The demo resets the cursor at each card change except when in the library
 	if (getFeatures() & GF_DEMO
@@ -731,310 +686,7 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
 
 	// Debug: Show resource rects
 	if (_showResourceRects)
-		drawResourceRects();
-}
-
-void MohawkEngine_Myst::drawResourceRects() {
-	for (uint16 i = 0; i < _resources.size(); i++) {
-		_resources[i]->getRect().debugPrint(0);
-		_resources[i]->drawBoundingRect();
-	}
-}
-
-void MohawkEngine_Myst::updateActiveResource() {
-	const Common::Point &mouse = _system->getEventManager()->getMousePos();
-
-	_activeResource = nullptr;
-	for (uint16 i = 0; i < _resources.size(); i++) {
-		if (_resources[i]->contains(mouse) && _resources[i]->canBecomeActive()) {
-			_activeResource = _resources[i];
-			break;
-		}
-	}
-}
-
-void MohawkEngine_Myst::checkCurrentResource() {
-	const Common::Point &mouse = _system->getEventManager()->getMousePos();
-
-	// Tell previous resource the mouse is no longer hovering it
-	if (_hoverResource && !_hoverResource->contains(mouse)) {
-		_hoverResource->handleMouseLeave();
-		_hoverResource = nullptr;
-	}
-
-	for (uint16 i = 0; i < _resources.size(); i++) {
-		if (_resources[i]->contains(mouse) && _resources[i]->hasType(kMystAreaHover)
-			&& _hoverResource != _resources[i]) {
-			_hoverResource = static_cast<MystAreaHover *>(_resources[i]);
-			_hoverResource->handleMouseEnter();
-		}
-	}
-
-	if (!_mouseClicked && _clickedResource) {
-		if (_clickedResource->isEnabled()) {
-			_clickedResource->handleMouseUp();
-		}
-		_clickedResource = nullptr;
-	} else if (_mouseMoved && _clickedResource) {
-		if (_clickedResource->isEnabled()) {
-			_clickedResource->handleMouseDrag();
-		}
-	} else if (_mouseClicked && !_clickedResource) {
-		if (_activeResource && _activeResource->isEnabled()) {
-			_clickedResource = _activeResource;
-			_clickedResource->handleMouseDown();
-		}
-	}
-
-	_mouseMoved = false;
-
-	checkCursorHints();
-}
-
-MystArea *MohawkEngine_Myst::forceUpdateClickedResource() {
-	updateActiveResource();
-
-	_clickedResource = _activeResource;
-
-	return _clickedResource;
-}
-
-void MohawkEngine_Myst::loadCard() {
-	debugC(kDebugView, "Loading Card View: %d", _curCard);
-
-	Common::SeekableReadStream *viewStream = getResource(ID_VIEW, _curCard);
-
-	// Card Flags
-	_view.flags = viewStream->readUint16LE();
-	debugC(kDebugView, "Flags: 0x%04X", _view.flags);
-
-	// The Image Block (Reminiscent of Riven PLST resources)
-	uint16 conditionalImageCount = viewStream->readUint16LE();
-	debugC(kDebugView, "Conditional Image Count: %d", conditionalImageCount);
-	if (conditionalImageCount != 0) {
-		for (uint16 i = 0; i < conditionalImageCount; i++) {
-			MystCondition conditionalImage;
-
-			debugC(kDebugView, "\tImage %d:", i);
-			conditionalImage.var = viewStream->readUint16LE();
-			debugC(kDebugView, "\t\tVar: %d", conditionalImage.var);
-			uint16 numStates = viewStream->readUint16LE();
-			debugC(kDebugView, "\t\tNumber of States: %d", numStates);
-			for (uint16 j = 0; j < numStates; j++) {
-				conditionalImage.values.push_back(viewStream->readUint16LE());
-				debugC(kDebugView, "\t\tState %d -> Value %d", j, conditionalImage.values[j]);
-			}
-
-			_view.conditionalImages.push_back(conditionalImage);
-		}
-		_view.mainImage = 0;
-	} else {
-		_view.mainImage = viewStream->readUint16LE();
-		debugC(kDebugView, "Main Image: %d", _view.mainImage);
-	}
-
-	// The Sound Block (Reminiscent of Riven SLST resources)
-	_view.soundBlock = readSoundBlock(viewStream);
-
-	// Resources that scripts can call upon
-	uint16 scriptResCount = viewStream->readUint16LE();
-	debugC(kDebugView, "Script Resource Count: %d", scriptResCount);
-	for (uint16 i = 0; i < scriptResCount; i++) {
-		MystView::ScriptResource scriptResource;
-
-		debugC(kDebugView, "\tResource %d:", i);
-		scriptResource.type = (MystView::ScriptResourceType) viewStream->readUint16LE();
-		debugC(kDebugView, "\t\t Type: %d", scriptResource.type);
-
-		switch (scriptResource.type) {
-		case MystView::kResourceImage:
-			debugC(kDebugView, "\t\t\t\t= Image");
-			break;
-		case MystView::kResourceSound:
-			debugC(kDebugView, "\t\t\t\t= Sound");
-			break;
-		case MystView::kResourceSwitch:
-			debugC(kDebugView, "\t\t\t\t= Resource Switch");
-			break;
-		case MystView::kResourceImageNoCache:
-			debugC(kDebugView, "\t\t\t\t= Image - Caching disabled");
-			break;
-		case MystView::kResourceSoundNoCache:
-			debugC(kDebugView, "\t\t\t\t= Sound - Caching disabled");
-			break;
-		default:
-			debugC(kDebugView, "\t\t\t\t= Unknown");
-			warning("Unknown script resource type '%d' in card '%d'", scriptResource.type, _curCard);
-			break;
-		}
-
-		if (scriptResource.type == MystView::kResourceSwitch) {
-			scriptResource.switchVar = viewStream->readUint16LE();
-			debugC(kDebugView, "\t\t Var: %d", scriptResource.switchVar);
-			uint16 count = viewStream->readUint16LE();
-			debugC(kDebugView, "\t\t Resource List Count: %d", count);
-			scriptResource.switchResourceType = (MystView::ScriptResourceType) viewStream->readUint16LE();
-			debugC(kDebugView, "\t\t u0: %d", scriptResource.switchResourceType);
-
-			for (uint16 j = 0; j < count; j++) {
-				scriptResource.switchResourceIds.push_back(viewStream->readSint16LE());
-				debugC(kDebugView, "\t\t Resource List %d: %d", j, scriptResource.switchResourceIds[j]);
-			}
-		} else {
-			scriptResource.id = viewStream->readUint16LE();
-			debugC(kDebugView, "\t\t Id: %d", scriptResource.id);
-		}
-
-		_view.scriptResources.push_back(scriptResource);
-	}
-
-	// Identifiers for other resources. 0 if non existent. There is always an RLST.
-	_view.rlst = viewStream->readUint16LE();
-	if (!_view.rlst)
-		error("RLST Index missing");
-
-	_view.hint = viewStream->readUint16LE();
-	_view.init = viewStream->readUint16LE();
-	_view.exit = viewStream->readUint16LE();
-
-	delete viewStream;
-
-	// Precache Card Resources
-	uint32 cacheImageType;
-	if (getFeatures() & GF_ME)
-		cacheImageType = ID_PICT;
-	else
-		cacheImageType = ID_WDIB;
-
-	// Precache Image Block data
-	if (_view.conditionalImages.size() != 0) {
-		for (uint16 i = 0; i < _view.conditionalImages.size(); i++) {
-			uint16 value = _scriptParser->getVar(_view.conditionalImages[i].var);
-			cachePreload(cacheImageType, _view.conditionalImages[i].values[value]);
-		}
-	} else {
-		cachePreload(cacheImageType, _view.mainImage);
-	}
-
-	// Precache Sound Block data
-	if (_view.soundBlock.sound > 0)
-		cachePreload(ID_MSND, _view.soundBlock.sound);
-	else if (_view.soundBlock.sound == kMystSoundActionConditional) {
-		uint16 value = _scriptParser->getVar(_view.soundBlock.soundVar);
-		if (_view.soundBlock.soundList[value].action > 0) {
-			cachePreload(ID_MSND, _view.soundBlock.soundList[value].action);
-		}
-	}
-
-	// Precache Script Resources
-	for (uint16 i = 0; i < _view.scriptResources.size(); i++) {
-		MystView::ScriptResourceType type;
-		int16 id;
-		if (_view.scriptResources[i].type == MystView::kResourceSwitch) {
-			type = _view.scriptResources[i].switchResourceType;
-			uint16 value = _scriptParser->getVar(_view.scriptResources[i].switchVar);
-			id = _view.scriptResources[i].switchResourceIds[value];
-		} else {
-			type = _view.scriptResources[i].type;
-			id = _view.scriptResources[i].id;
-		}
-
-		if (id < 0) continue;
-
-		switch (type) {
-		case MystView::kResourceImage:
-			cachePreload(cacheImageType, id);
-			break;
-		case MystView::kResourceSound:
-			cachePreload(ID_MSND, id);
-			break;
-		default:
-			// The other resource types should not be cached
-			break;
-		}
-	}
-}
-
-void MohawkEngine_Myst::unloadCard() {
-	_view.conditionalImages.clear();
-	_view.soundBlock.soundList.clear();
-	_view.scriptResources.clear();
-	_hoverResource = nullptr;
-	_activeResource = nullptr;
-	_clickedResource = nullptr;
-}
-
-void MohawkEngine_Myst::runInitScript() {
-	if (!_view.init) {
-		debugC(kDebugINIT, "No INIT Present");
-		return;
-	}
-
-	debugC(kDebugINIT, "Running INIT script");
-
-	Common::SeekableReadStream *initStream = getResource(ID_INIT, _view.init);
-	MystScript script = _scriptParser->readScript(initStream, kMystScriptInit);
-	delete initStream;
-
-	_scriptParser->runScript(script);
-}
-
-void MohawkEngine_Myst::runExitScript() {
-	if (!_view.exit) {
-		debugC(kDebugEXIT, "No EXIT Present");
-		return;
-	}
-
-	debugC(kDebugEXIT, "Running EXIT script");
-
-	Common::SeekableReadStream *exitStream = getResource(ID_EXIT, _view.exit);
-	MystScript script = _scriptParser->readScript(exitStream, kMystScriptExit);
-	delete exitStream;
-
-	_scriptParser->runScript(script);
-}
-
-void MohawkEngine_Myst::loadCursorHints() {
-	_cursorHints.clear();
-
-	if (!_view.hint) {
-		debugC(kDebugHint, "No HINT Present");
-		return;
-	}
-
-	debugC(kDebugHint, "Loading Cursor Hints:");
-
-	Common::SeekableReadStream *hintStream = getResource(ID_HINT, _curCard);
-	uint16 cursorHintCount = hintStream->readUint16LE();
-	debugC(kDebugHint, "Cursor Hint Count: %d", cursorHintCount);
-
-	for (uint16 i = 0; i < cursorHintCount; i++) {
-		MystCursorHint hint;
-
-		debugC(kDebugHint, "Cursor Hint %d:", i);
-		hint.id = hintStream->readUint16LE();
-		debugC(kDebugHint, "\tId: %d", hint.id);
-		hint.cursor = hintStream->readSint16LE();
-		debugC(kDebugHint, "\tCursor: %d", hint.cursor);
-
-		if (hint.cursor == -1) {
-			debugC(kDebugHint, "\tConditional Cursor Hints:");
-			hint.variableHint.var = hintStream->readUint16LE();
-			debugC(kDebugHint, "\tVar: %d", hint.variableHint.var);
-			uint16 numStates = hintStream->readUint16LE();
-			debugC(kDebugHint, "\tNumber of States: %d", numStates);
-			for (uint16 j = 0; j < numStates; j++) {
-				hint.variableHint.values.push_back(hintStream->readUint16LE());
-				debugC(kDebugHint, "\t\t State %d: Cursor %d", j, hint.variableHint.values[j]);
-			}
-		} else {
-			hint.variableHint.var = 0;
-		}
-
-		_cursorHints.push_back(hint);
-	}
-
-	delete hintStream;
+		_card->drawResourceRects();
 }
 
 void MohawkEngine_Myst::setMainCursor(uint16 cursor) {
@@ -1042,70 +694,22 @@ void MohawkEngine_Myst::setMainCursor(uint16 cursor) {
 	_cursor->setCursor(_currentCursor);
 }
 
-void MohawkEngine_Myst::checkCursorHints() {
-	if (!_view.hint) {
-		// Default to the main cursor when no hints are present
-		if (_currentCursor != _mainCursor) {
-			_currentCursor = _mainCursor;
-			_cursor->setCursor(_currentCursor);
-		}
-		return;
+void MohawkEngine_Myst::refreshCursor() {
+	int16 cursor = _card->getActiveResourceCursor();
+	if (cursor == -1) {
+		cursor = _mainCursor;
 	}
 
-	// Check all the cursor hints to see if we're in a hotspot that contains a hint.
-	for (uint16 i = 0; i < _cursorHints.size(); i++)
-		if (_activeResource && _resources[_cursorHints[i].id] == _activeResource && _activeResource->isEnabled()) {
-			if (_cursorHints[i].cursor == -1) {
-				uint16 var_value = _scriptParser->getVar(_cursorHints[i].variableHint.var);
-
-				if (var_value >= _cursorHints[i].variableHint.values.size())
-					warning("Variable %d Out of Range in variable HINT Resource %d", _cursorHints[i].variableHint.var, i);
-				else {
-					_currentCursor = _cursorHints[i].variableHint.values[var_value];
-					if (_currentCursor == 0)
-						_currentCursor = _mainCursor;
-					_cursor->setCursor(_currentCursor);
-				}
-			} else if (_currentCursor != _cursorHints[i].cursor) {
-				if (_cursorHints[i].cursor == 0)
-					_currentCursor = _mainCursor;
-				else
-					_currentCursor = _cursorHints[i].cursor;
-
-				_cursor->setCursor(_currentCursor);
-			}
-			return;
-		}
-
-	if (_currentCursor != _mainCursor) {
-		_currentCursor = _mainCursor;
-		_cursor->setCursor(_currentCursor);
+	if (cursor != _currentCursor) {
+		_currentCursor = cursor;
+		_cursor->setCursor(cursor);
 	}
 }
 
-void MohawkEngine_Myst::setResourceEnabled(uint16 resourceId, bool enable) {
-	if (resourceId < _resources.size()) {
-		_resources[resourceId]->setEnabled(enable);
-	} else
-		warning("Attempt to change unknown resource enable state");
-}
-
-void MohawkEngine_Myst::drawResourceImages() {
-	for (uint16 i = 0; i < _resources.size(); i++)
-		if (_resources[i]->isDrawSubimages())
-			_resources[i]->drawDataToScreen();
-}
-
 void MohawkEngine_Myst::redrawResource(MystAreaImageSwitch *resource, bool update) {
 	resource->drawConditionalDataToScreen(_scriptParser->getVar(resource->getImageSwitchVar()), update);
 }
 
-void MohawkEngine_Myst::redrawArea(uint16 var, bool update) {
-	for (uint16 i = 0; i < _resources.size(); i++)
-		if (_resources[i]->hasType(kMystAreaImageSwitch) && _resources[i]->getImageSwitchVar() == var)
-			redrawResource(static_cast<MystAreaImageSwitch *>(_resources[i]), update);
-}
-
 MystArea *MohawkEngine_Myst::loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent) {
 	MystArea *resource = nullptr;
 	ResourceType type = static_cast<ResourceType>(rlstStream->readUint16LE());
@@ -1146,29 +750,6 @@ MystArea *MohawkEngine_Myst::loadResource(Common::SeekableReadStream *rlstStream
 	return resource;
 }
 
-void MohawkEngine_Myst::loadResources() {
-	for (uint32 i = 0; i < _resources.size(); i++)
-		delete _resources[i];
-
-	_resources.clear();
-
-	if (!_view.rlst) {
-		debugC(kDebugResource, "No RLST present");
-		return;
-	}
-
-	Common::SeekableReadStream *rlstStream = getResource(ID_RLST, _view.rlst);
-	uint16 resourceCount = rlstStream->readUint16LE();
-	debugC(kDebugResource, "RLST Resource Count: %d", resourceCount);
-
-	for (uint16 i = 0; i < resourceCount; i++) {
-		debugC(kDebugResource, "Resource #%d:", i);
-		_resources.push_back(loadResource(rlstStream, nullptr));
-	}
-
-	delete rlstStream;
-}
-
 Common::Error MohawkEngine_Myst::loadGameState(int slot) {
 	if (_gameState->load(slot))
 		return Common::kNoError;
@@ -1208,8 +789,7 @@ bool MohawkEngine_Myst::canLoadGameStateCurrently() {
 		return false;
 	}
 
-	if (_clickedResource) {
-		// Can't save while dragging resources
+	if (_card->isDraggingResource()) {
 		return false;
 	}
 
@@ -1255,28 +835,28 @@ void MohawkEngine_Myst::dropPage() {
 	// Redraw page area
 	if (whitePage && _gameState->_globals.currentAge == kMystLibrary) {
 		_scriptParser->toggleVar(41);
-		redrawArea(41);
+		_card->redrawArea(41);
 	} else if (bluePage) {
 		if (page == kBlueFirePlacePage) {
 			if (_gameState->_globals.currentAge == kMystLibrary)
-				redrawArea(24);
+				_card->redrawArea(24);
 		} else {
-			redrawArea(103);
+			_card->redrawArea(103);
 		}
 	} else if (redPage) {
 		if (page == kRedFirePlacePage) {
 			if (_gameState->_globals.currentAge == kMystLibrary)
-				redrawArea(25);
+				_card->redrawArea(25);
 		} else if (page == kRedStoneshipPage) {
 			if (_gameState->_globals.currentAge == kStoneship)
-				redrawArea(35);
+				_card->redrawArea(35);
 		} else {
-			redrawArea(102);
+			_card->redrawArea(102);
 		}
 	}
 
 	setMainCursor(kDefaultMystCursor);
-	checkCursorHints();
+	refreshCursor();
 }
 
 MystSoundBlock MohawkEngine_Myst::readSoundBlock(Common::ReadStream *stream) const {
@@ -1317,7 +897,7 @@ MystSoundBlock MohawkEngine_Myst::readSoundBlock(Common::ReadStream *stream) con
 			soundBlock.soundList.push_back(sound);
 		}
 	} else {
-		error("Unknown sound control value '%d' in card '%d'", soundBlock.sound, _curCard);
+		error("Unknown sound control value '%d' in card '%d'", soundBlock.sound, _card->getId());
 	}
 
 	return soundBlock;
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 64fee10..867131a 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -47,6 +47,7 @@ class MystSound;
 class MystArea;
 class MystAreaImageSwitch;
 class MystAreaHover;
+class MystCard;
 
 // Engine Debug Flags
 enum {
@@ -121,52 +122,7 @@ enum {
 	// Other positive values are PlayNewSound of that id
 };
 
-// View flags
-enum {
-	kMystZipDestination = (1 << 0)
-};
-
-struct MystView {
-	uint16 flags;
-
-	// Image Data
-	Common::Array<MystCondition> conditionalImages;
-	uint16 mainImage;
-
-	// Sound Data
-	MystSoundBlock soundBlock;
-
-	// Script Resources
-	enum ScriptResourceType {
-		kResourceImage = 1,
-		kResourceSound = 2,
-		kResourceSwitch = 3,
-		kResourceImageNoCache = 4,
-		kResourceSoundNoCache = 5
-	};
-
-	struct ScriptResource {
-		ScriptResourceType type;
-		uint16 id;
-		uint16 switchVar;
-		ScriptResourceType switchResourceType;
-		Common::Array<int16> switchResourceIds;
-	};
-	Common::Array<ScriptResource> scriptResources;
-
-	// Resource ID's
-	uint16 rlst;
-	uint16 hint;
-	uint16 init;
-	uint16 exit;
-};
-
-struct MystCursorHint {
-	uint16 id;
-	int16 cursor;
-
-	MystCondition variableHint;
-};
+typedef Common::SharedPtr<MystCard> MystCardPtr;
 
 class MohawkEngine_Myst : public MohawkEngine {
 protected:
@@ -178,15 +134,16 @@ public:
 
 	Common::SeekableReadStream *getResource(uint32 tag, uint16 id) override;
 	Common::Array<uint16> getResourceIDList(uint32 type) const;
+	void cachePreload(uint32 tag, uint16 id);
 
 	void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound);
 	void changeToCard(uint16 card, TransitionType transition);
-	uint16 getCurCard() { return _curCard; }
+	MystCard *getCard() { return _card.get(); };
+	MystCardPtr getCardPtr() { return _card; };
 	uint16 getCurStack() { return _curStack; }
 	void setMainCursor(uint16 cursor);
 	uint16 getMainCursor() { return _mainCursor; }
-	void checkCursorHints();
-	MystArea *forceUpdateClickedResource();
+	void refreshCursor();
 	bool wait(uint32 duration, bool skippable = false);
 
 	/** Update the game state according to events and update the screen */
@@ -207,19 +164,10 @@ public:
 	MystGraphics *_gfx;
 	MystGameState *_gameState;
 	MystScriptParser *_scriptParser;
-	Common::Array<MystArea *> _resources;
 	Common::RandomSource *_rnd;
 
 	MystArea *loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent);
-	void setResourceEnabled(uint16 resourceId, bool enable);
-	void redrawArea(uint16 var, bool update = true);
 	void redrawResource(MystAreaImageSwitch *resource, bool update = true);
-	void drawResourceImages();
-	void drawCardBackground();
-	uint16 getCardBackgroundId();
-
-	template<class T>
-	T *getViewResource(uint index);
 
 	void setCacheState(bool state) { _cache.enabled = state; }
 	bool getCacheState() { return _cache.enabled; }
@@ -253,65 +201,29 @@ private:
 	MystOptionsDialog *_optionsDialog;
 	MystScriptParser *_prevStack;
 	ResourceCache _cache;
-	void cachePreload(uint32 tag, uint16 id);
 
 	uint16 _curStack;
-	uint16 _curCard;
+	MystCardPtr _card;
 	uint32 _lastSaveTime;
-	MystView _view;
-
-	bool _runExitScript;
 
 	bool hasGameSaveSupport() const;
 
 	void dropPage();
 
-	void loadCard();
-	void unloadCard();
-	void runInitScript();
-	void runExitScript();
-
-	void loadResources();
-	void drawResourceRects();
-	void checkCurrentResource();
-	void updateActiveResource();
-
 	Common::String wrapMovieFilename(const Common::String &movieName, uint16 stack);
 
-	/** Area of type kMystAreaHover being hovered by the mouse, if any */
-	MystAreaHover *_hoverResource;
-
-	/** Active area being hovered by the mouse, if any */
-	MystArea *_activeResource;
-
-	/** Active area being clicked on / dragged, if any */
-	MystArea *_clickedResource;
-
 	// Input
 	bool _mouseClicked;
 	bool _mouseMoved;
 	bool _escapePressed;
 	bool _waitingOnBlockingOperation;
 
-	Common::Array<MystCursorHint> _cursorHints;
-	void loadCursorHints();
 	uint16 _currentCursor;
 	uint16 _mainCursor; // Also defines the current page being held (white, blue, red, or none)
 
-	void pauseEngineIntern(bool) override;
+	void pauseEngineIntern(bool pause) override;
 };
 
-template<class T>
-T *MohawkEngine_Myst::getViewResource(uint index) {
-	T *resource = dynamic_cast<T *>(_resources[index]);
-
-	if (!resource) {
-		error("View resource '%d' has unexpected type", index);
-	}
-
-	return resource;
-}
-
 } // End of namespace Mohawk
 
 #endif
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index eff51bf..2d2d346 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_scripts.h"
 #include "mohawk/myst_sound.h"
@@ -152,11 +153,11 @@ void MystAreaAction::handleMouseUp() {
 const Common::String MystAreaAction::describe() {
 	Common::String desc = MystArea::describe();
 
-	if (_script->size() != 0) {
+	if (!_script.empty()) {
 		desc += " ops:";
 
-		for (uint i = 0; i < _script->size(); i++)
-			desc += " " + _vm->_scriptParser->getOpcodeDesc((*_script)[i].opcode);
+		for (uint i = 0; i < _script.size(); i++)
+			desc += " " + _vm->_scriptParser->getOpcodeDesc(_script[i].opcode);
 	}
 
 	return desc;
@@ -419,7 +420,7 @@ void MystAreaImageSwitch::drawDataToScreen() {
 
 		// This special case means redraw background
 		if (imageToDraw == 0xFFFF)
-			imageToDraw = _vm->getCardBackgroundId();
+			imageToDraw = _vm->getCard()->getBackgroundImageId();
 
 		_vm->_gfx->copyImageSectionToBackBuffer(imageToDraw, _subImages[subImageId].rect, _rect);
 	}
@@ -448,7 +449,7 @@ void MystAreaImageSwitch::drawConditionalDataToScreen(uint16 state, bool update)
 
 		// This special case means redraw background
 		if (imageToDraw == 0xFFFF)
-			imageToDraw = _vm->getCardBackgroundId();
+			imageToDraw = _vm->getCard()->getBackgroundImageId();
 
 		// Draw to screen
 		if (update) {
@@ -542,7 +543,7 @@ void MystAreaSlider::restoreBackground() {
 	Common::Rect dest = boundingBox();
 	src.top = 332 - dest.bottom;
 	src.bottom = 332 - dest.top;
-	_vm->_gfx->copyImageSectionToScreen(_vm->getCardBackgroundId(), src, dest);
+	_vm->_gfx->copyImageSectionToScreen(_vm->getCard()->getBackgroundImageId(), src, dest);
 }
 
 void MystAreaSlider::handleMouseDown() {
diff --git a/engines/mohawk/myst_card.cpp b/engines/mohawk/myst_card.cpp
new file mode 100644
index 0000000..71b546c
--- /dev/null
+++ b/engines/mohawk/myst_card.cpp
@@ -0,0 +1,456 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mohawk/myst_card.h"
+
+#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
+
+#include "mohawk/resource.h"
+
+namespace Mohawk {
+
+MystCard::MystCard(MohawkEngine_Myst *vm, uint16 id) :
+		_vm(vm),
+		_id(id),
+		_hoverResource(nullptr),
+		_activeResource(nullptr),
+		_clickedResource(nullptr) {
+
+	loadView();
+	loadResources();
+	loadCursorHints();
+}
+
+void MystCard::enter() {
+	// Handle images
+	drawBackground();
+
+	// Handle sound
+	_vm->applySoundBlock(_soundBlock);
+
+	if (_flags & kMystZipDestination)
+		_vm->_gameState->addZipDest(_vm->getCurStack(), _id);
+
+	// Run the entrance script (if present)
+	runInitScript();
+
+	// Update the images of each area too
+	drawResourceImages();
+
+	for (uint16 i = 0; i < _resources.size(); i++)
+		_resources[i]->handleCardChange();
+}
+
+void MystCard::leave() {
+	runExitScript();
+}
+
+MystCard::~MystCard() {
+	for (uint32 i = 0; i < _resources.size(); i++)
+		delete _resources[i];
+}
+
+uint16 MystCard::getId() const {
+	return _id;
+}
+
+void MystCard::loadView() {
+	debugC(kDebugView, "Loading Card View: %d", _id);
+
+	Common::SeekableReadStream *viewStream = _vm->getResource(ID_VIEW, _id);
+
+	// Card Flags
+	_flags = viewStream->readUint16LE();
+	debugC(kDebugView, "Flags: 0x%04X", _flags);
+
+	// The Image Block (Reminiscent of Riven PLST resources)
+	uint16 conditionalImageCount = viewStream->readUint16LE();
+	debugC(kDebugView, "Conditional Image Count: %d", conditionalImageCount);
+	if (conditionalImageCount != 0) {
+		for (uint16 i = 0; i < conditionalImageCount; i++) {
+			MystCondition conditionalImage;
+
+			debugC(kDebugView, "\tImage %d:", i);
+			conditionalImage.var = viewStream->readUint16LE();
+			debugC(kDebugView, "\t\tVar: %d", conditionalImage.var);
+			uint16 numStates = viewStream->readUint16LE();
+			debugC(kDebugView, "\t\tNumber of States: %d", numStates);
+			for (uint16 j = 0; j < numStates; j++) {
+				conditionalImage.values.push_back(viewStream->readUint16LE());
+				debugC(kDebugView, "\t\tState %d -> Value %d", j, conditionalImage.values[j]);
+			}
+
+			_conditionalImages.push_back(conditionalImage);
+		}
+		_mainImage = 0;
+	} else {
+		_mainImage = viewStream->readUint16LE();
+		debugC(kDebugView, "Main Image: %d", _mainImage);
+	}
+
+	// The Sound Block (Reminiscent of Riven SLST resources)
+	_soundBlock = _vm->readSoundBlock(viewStream);
+
+	// Resources that scripts can call upon
+	uint16 scriptResCount = viewStream->readUint16LE();
+	debugC(kDebugView, "Script Resource Count: %d", scriptResCount);
+	for (uint16 i = 0; i < scriptResCount; i++) {
+		ScriptResource scriptResource;
+
+		debugC(kDebugView, "\tResource %d:", i);
+		scriptResource.type = (ScriptResourceType) viewStream->readUint16LE();
+		debugC(kDebugView, "\t\t Type: %d", scriptResource.type);
+
+		switch (scriptResource.type) {
+			case kResourceImage:
+				debugC(kDebugView, "\t\t\t\t= Image");
+				break;
+			case kResourceSound:
+				debugC(kDebugView, "\t\t\t\t= Sound");
+				break;
+			case kResourceSwitch:
+				debugC(kDebugView, "\t\t\t\t= Resource Switch");
+				break;
+			case kResourceImageNoCache:
+				debugC(kDebugView, "\t\t\t\t= Image - Caching disabled");
+				break;
+			case kResourceSoundNoCache:
+				debugC(kDebugView, "\t\t\t\t= Sound - Caching disabled");
+				break;
+			default:
+				debugC(kDebugView, "\t\t\t\t= Unknown");
+				warning("Unknown script resource type '%d' in card '%d'", scriptResource.type, _id);
+				break;
+		}
+
+		if (scriptResource.type == kResourceSwitch) {
+			scriptResource.switchVar = viewStream->readUint16LE();
+			debugC(kDebugView, "\t\t Var: %d", scriptResource.switchVar);
+			uint16 count = viewStream->readUint16LE();
+			debugC(kDebugView, "\t\t Resource List Count: %d", count);
+			scriptResource.switchResourceType = (ScriptResourceType) viewStream->readUint16LE();
+			debugC(kDebugView, "\t\t u0: %d", scriptResource.switchResourceType);
+
+			for (uint16 j = 0; j < count; j++) {
+				scriptResource.switchResourceIds.push_back(viewStream->readSint16LE());
+				debugC(kDebugView, "\t\t Resource List %d: %d", j, scriptResource.switchResourceIds[j]);
+			}
+		} else {
+			scriptResource.id = viewStream->readUint16LE();
+			debugC(kDebugView, "\t\t Id: %d", scriptResource.id);
+		}
+
+		_scriptResources.push_back(scriptResource);
+	}
+
+	// Identifiers for other resources. 0 if non existent. There is always an RLST.
+	_resourceListId = viewStream->readUint16LE();
+	if (!_resourceListId)
+		error("RLST Index missing");
+
+	_hintResourceId = viewStream->readUint16LE();
+	_initScriptId = viewStream->readUint16LE();
+	_exitScriptId = viewStream->readUint16LE();
+
+	delete viewStream;
+
+	// Precache Card Resources
+	uint32 cacheImageType;
+	if (_vm->getFeatures() & GF_ME)
+		cacheImageType = ID_PICT;
+	else
+		cacheImageType = ID_WDIB;
+
+	// Precache Image Block data
+	if (!_conditionalImages.empty()) {
+		for (uint16 i = 0; i < _conditionalImages.size(); i++) {
+			uint16 value = _vm->_scriptParser->getVar(_conditionalImages[i].var);
+			_vm->cachePreload(cacheImageType, _conditionalImages[i].values[value]);
+		}
+	} else {
+		_vm->cachePreload(cacheImageType, _mainImage);
+	}
+
+	// Precache Sound Block data
+	if (_soundBlock.sound > 0)
+		_vm->cachePreload(ID_MSND, _soundBlock.sound);
+	else if (_soundBlock.sound == kMystSoundActionConditional) {
+		uint16 value = _vm->_scriptParser->getVar(_soundBlock.soundVar);
+		if (_soundBlock.soundList[value].action > 0) {
+			_vm->cachePreload(ID_MSND, _soundBlock.soundList[value].action);
+		}
+	}
+
+	// Precache Script Resources
+	for (uint16 i = 0; i < _scriptResources.size(); i++) {
+		ScriptResourceType type;
+		int16 id;
+		if (_scriptResources[i].type == kResourceSwitch) {
+			type = _scriptResources[i].switchResourceType;
+			uint16 value = _vm->_scriptParser->getVar(_scriptResources[i].switchVar);
+			id = _scriptResources[i].switchResourceIds[value];
+		} else {
+			type = _scriptResources[i].type;
+			id = _scriptResources[i].id;
+		}
+
+		if (id < 0) continue;
+
+		switch (type) {
+			case kResourceImage:
+				_vm->cachePreload(cacheImageType, id);
+				break;
+			case kResourceSound:
+				_vm->cachePreload(ID_MSND, id);
+				break;
+			default:
+				// The other resource types should not be cached
+				break;
+		}
+	}
+}
+
+void MystCard::loadCursorHints() {
+	if (!_hintResourceId) {
+		debugC(kDebugHint, "No HINT Present");
+		return;
+	}
+
+	debugC(kDebugHint, "Loading Cursor Hints:");
+
+	Common::SeekableReadStream *hintStream = _vm->getResource(ID_HINT, _id);
+	uint16 cursorHintCount = hintStream->readUint16LE();
+	debugC(kDebugHint, "Cursor Hint Count: %d", cursorHintCount);
+
+	for (uint16 i = 0; i < cursorHintCount; i++) {
+		MystCursorHint hint;
+
+		debugC(kDebugHint, "Cursor Hint %d:", i);
+		hint.id = hintStream->readUint16LE();
+		debugC(kDebugHint, "\tId: %d", hint.id);
+		hint.cursor = hintStream->readSint16LE();
+		debugC(kDebugHint, "\tCursor: %d", hint.cursor);
+
+		if (hint.cursor == -1) {
+			debugC(kDebugHint, "\tConditional Cursor Hints:");
+			hint.variableHint.var = hintStream->readUint16LE();
+			debugC(kDebugHint, "\tVar: %d", hint.variableHint.var);
+			uint16 numStates = hintStream->readUint16LE();
+			debugC(kDebugHint, "\tNumber of States: %d", numStates);
+			for (uint16 j = 0; j < numStates; j++) {
+				hint.variableHint.values.push_back(hintStream->readUint16LE());
+				debugC(kDebugHint, "\t\t State %d: Cursor %d", j, hint.variableHint.values[j]);
+			}
+		} else {
+			hint.variableHint.var = 0;
+		}
+
+		_cursorHints.push_back(hint);
+	}
+
+	delete hintStream;
+}
+
+void MystCard::loadResources() {
+	if (!_resourceListId) {
+		debugC(kDebugResource, "No RLST present");
+		return;
+	}
+
+	Common::SeekableReadStream *rlstStream = _vm->getResource(ID_RLST, _resourceListId);
+	uint16 resourceCount = rlstStream->readUint16LE();
+	debugC(kDebugResource, "RLST Resource Count: %d", resourceCount);
+
+	for (uint16 i = 0; i < resourceCount; i++) {
+		debugC(kDebugResource, "Resource #%d:", i);
+		_resources.push_back(_vm->loadResource(rlstStream, nullptr));
+	}
+
+	delete rlstStream;
+}
+
+uint16 MystCard::getBackgroundImageId() {
+	uint16 imageToDraw = 0;
+
+	if (_conditionalImages.empty())
+		imageToDraw = _mainImage;
+	else {
+		for (uint16 i = 0; i < _conditionalImages.size(); i++) {
+			uint16 varValue = _vm->_scriptParser->getVar(_conditionalImages[i].var);
+			if (varValue < _conditionalImages[i].values.size())
+				imageToDraw = _conditionalImages[i].values[varValue];
+		}
+	}
+
+	return imageToDraw;
+}
+
+void MystCard::drawBackground() {
+	_vm->_gfx->copyImageToBackBuffer(getBackgroundImageId(), Common::Rect(0, 0, 544, 332));
+}
+
+void MystCard::runInitScript() {
+	if (!_initScriptId) {
+		debugC(kDebugINIT, "No INIT Present");
+		return;
+	}
+
+	debugC(kDebugINIT, "Running INIT script");
+
+	Common::SeekableReadStream *initStream = _vm->getResource(ID_INIT, _initScriptId);
+	MystScript script = _vm->_scriptParser->readScript(initStream, kMystScriptInit);
+	delete initStream;
+
+	_vm->_scriptParser->runScript(script);
+}
+
+void MystCard::runExitScript() {
+	if (!_exitScriptId) {
+		debugC(kDebugEXIT, "No EXIT Present");
+		return;
+	}
+
+	debugC(kDebugEXIT, "Running EXIT script");
+
+	Common::SeekableReadStream *exitStream = _vm->getResource(ID_EXIT, _exitScriptId);
+	MystScript script = _vm->_scriptParser->readScript(exitStream, kMystScriptExit);
+	delete exitStream;
+
+	_vm->_scriptParser->runScript(script);
+}
+
+void MystCard::drawResourceRects() {
+	for (uint16 i = 0; i < _resources.size(); i++) {
+		_resources[i]->getRect().debugPrint(0);
+		_resources[i]->drawBoundingRect();
+	}
+}
+
+void MystCard::updateActiveResource(const Common::Point &mouse) {
+	_activeResource = nullptr;
+	for (uint16 i = 0; i < _resources.size(); i++) {
+		if (_resources[i]->contains(mouse) && _resources[i]->canBecomeActive()) {
+			_activeResource = _resources[i];
+			break;
+		}
+	}
+}
+
+MystArea *MystCard::forceUpdateClickedResource(const Common::Point &mouse) {
+	updateActiveResource(mouse);
+
+	_clickedResource = _activeResource;
+
+	return _clickedResource;
+}
+
+void MystCard::updateResourcesForInput(const Common::Point &mouse, bool mouseClicked, bool mouseMoved) {
+	// Tell previous resource the mouse is no longer hovering it
+	if (_hoverResource && !_hoverResource->contains(mouse)) {
+		_hoverResource->handleMouseLeave();
+		_hoverResource = nullptr;
+	}
+
+	for (uint16 i = 0; i < _resources.size(); i++) {
+		if (_resources[i]->contains(mouse) && _resources[i]->hasType(kMystAreaHover)
+		    && _hoverResource != _resources[i]) {
+			_hoverResource = static_cast<MystAreaHover *>(_resources[i]);
+			_hoverResource->handleMouseEnter();
+		}
+	}
+
+	if (!mouseClicked && _clickedResource) {
+		if (_clickedResource->isEnabled()) {
+			_clickedResource->handleMouseUp();
+		}
+		_clickedResource = nullptr;
+	} else if (mouseMoved && _clickedResource) {
+		if (_clickedResource->isEnabled()) {
+			_clickedResource->handleMouseDrag();
+		}
+	} else if (mouseClicked && !_clickedResource) {
+		if (_activeResource && _activeResource->isEnabled()) {
+			_clickedResource = _activeResource;
+			_clickedResource->handleMouseDown();
+		}
+	}
+}
+
+int16 MystCard::getActiveResourceCursor() {
+	if (!_hintResourceId) {
+		// Default to the main cursor when no hints are present
+		return -1;
+	}
+
+	// Check all the cursor hints to see if we're in a hotspot that contains a hint.
+	for (uint16 i = 0; i < _cursorHints.size(); i++) {
+		if (_activeResource && _resources[_cursorHints[i].id] == _activeResource && _activeResource->isEnabled()) {
+			if (_cursorHints[i].cursor == -1) {
+				uint16 var_value = _vm->_scriptParser->getVar(_cursorHints[i].variableHint.var);
+
+				if (var_value >= _cursorHints[i].variableHint.values.size())
+					warning("Variable %d Out of Range in variable HINT Resource %d", _cursorHints[i].variableHint.var,
+					        i);
+				else {
+					uint16 cursor = _cursorHints[i].variableHint.values[var_value];
+					if (cursor == 0)
+						return -1;
+					else
+						return cursor;
+				}
+			} else {
+				if (_cursorHints[i].cursor == 0)
+					return -1;
+				else
+					return _cursorHints[i].cursor;
+			}
+		}
+	}
+
+	return -1;
+}
+
+void MystCard::setResourceEnabled(uint16 resourceIndex, bool enable) {
+	if (resourceIndex < _resources.size()) {
+		_resources[resourceIndex]->setEnabled(enable);
+	} else
+		warning("Attempt to change unknown resource enable state");
+}
+
+void MystCard::drawResourceImages() {
+	for (uint16 i = 0; i < _resources.size(); i++)
+		if (_resources[i]->isDrawSubimages())
+			_resources[i]->drawDataToScreen();
+}
+
+void MystCard::redrawArea(uint16 var, bool updateScreen) {
+	for (uint16 i = 0; i < _resources.size(); i++)
+		if (_resources[i]->hasType(kMystAreaImageSwitch) && _resources[i]->getImageSwitchVar() == var)
+			_vm->redrawResource(static_cast<MystAreaImageSwitch *>(_resources[i]), updateScreen);
+}
+
+bool MystCard::isDraggingResource() const {
+	return _clickedResource != nullptr;
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_card.h b/engines/mohawk/myst_card.h
new file mode 100644
index 0000000..056d211
--- /dev/null
+++ b/engines/mohawk/myst_card.h
@@ -0,0 +1,185 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MYST_CARD_H
+#define MYST_CARD_H
+
+#include "common/rect.h"
+
+#include "mohawk/myst.h"
+
+namespace Mohawk {
+
+/**
+ * A game view
+ *
+ * The names Card and Stack are legacy from the HyperCard engine used in
+ * the original mac version.
+ *
+ * Cards contain resources (hotspots), images, sounds, and cursor hints.
+ */
+class MystCard {
+public:
+	MystCard(MohawkEngine_Myst *vm, uint16 id);
+	~MystCard();
+
+	/** Get the id of the card */
+	uint16 getId() const;
+
+	/** Initialization routine used to draw a card for the first time */
+	void enter();
+
+	/** Run the card's leave scripts */
+	void leave();
+
+	/** Get a card resource (hotspot) by its index in the resource list */
+	template<class T>
+	T *getResource(uint index);
+
+	/** The list of resources in the card */
+	Common::Array<MystArea *> _resources;
+
+	/** Enable or disable a card resource */
+	void setResourceEnabled(uint16 resourceIndex, bool enable);
+
+	/** Update the card's active resource according to the mouse position */
+	void updateActiveResource(const Common::Point &mouse);
+
+	/** Set the card's currently clicked resource to the currently active resource */
+	MystArea *forceUpdateClickedResource(const Common::Point &mouse);
+
+	/**
+	 * Get the mouse cursor that should be used when hovering the currently active resource
+	 *
+	 * -1 means that no specific cursor is defined for the active resource, or that there is no
+	 * currently active resource. In that case the default main cursor should be used by the caller.
+	 */
+	int16 getActiveResourceCursor();
+
+	/**
+	 * Call the resource event handlers to account for the new specified input
+	 *
+	 * For example call the mouse down event handler for the currently active resource
+	 * if the mouse is clicked and there was no clicked resource previously.
+	 */
+	void updateResourcesForInput(const Common::Point &mouse, bool mouseClicked, bool mouseMoved);
+
+	/** Is there a currently clicked resource */
+	bool isDraggingResource() const;
+
+	/** Retrieve the id of the background image to use when drawing the card */
+	uint16 getBackgroundImageId();
+
+	/** Draw the card's background image to the backbuffer */
+	void drawBackground();
+
+	/** Draw the card's image resources to the backbuffer */
+	void drawResourceImages();
+
+	/** Draw debug rectangles around the card's resources */
+	void drawResourceRects();
+
+	/** Redraw the card's resources that are affected by the specified variable */
+	void redrawArea(uint16 var, bool updateScreen = true);
+
+private:
+	// View flags
+	enum {
+		kMystZipDestination = (1 << 0)
+	};
+
+	struct MystCursorHint {
+		uint16 id;
+		int16 cursor;
+
+		MystCondition variableHint;
+	};
+
+	MohawkEngine_Myst *_vm;
+
+	// General card data
+	uint16 _id;
+	uint16 _flags;
+
+	// Image Data
+	Common::Array<MystCondition> _conditionalImages;
+	uint16 _mainImage;
+
+	// Sound Data
+	MystSoundBlock _soundBlock;
+
+	// Script Resources
+	enum ScriptResourceType {
+		kResourceImage = 1,
+		kResourceSound = 2,
+		kResourceSwitch = 3,
+		kResourceImageNoCache = 4,
+		kResourceSoundNoCache = 5
+	};
+
+	struct ScriptResource {
+		ScriptResourceType type;
+		uint16 id;
+		uint16 switchVar;
+		ScriptResourceType switchResourceType;
+		Common::Array<int16> switchResourceIds;
+	};
+	Common::Array<ScriptResource> _scriptResources;
+
+	uint16 _resourceListId;
+	uint16 _hintResourceId;
+	uint16 _initScriptId;
+	uint16 _exitScriptId;
+
+	Common::Array<MystCursorHint> _cursorHints;
+
+	/** Area of type kMystAreaHover being hovered by the mouse, if any */
+	MystAreaHover *_hoverResource;
+
+	/** Active area being hovered by the mouse, if any */
+	MystArea *_activeResource;
+
+	/** Active area being clicked on / dragged, if any */
+	MystArea *_clickedResource;
+
+	void loadView();
+	void loadResources();
+	void loadCursorHints();
+
+	void runInitScript();
+	void runExitScript();
+};
+
+template<class T>
+T *MystCard::getResource(uint index) {
+	T *resource = dynamic_cast<T *>(_resources[index]);
+
+	if (!resource) {
+		error("View resource '%d' has unexpected type", index);
+	}
+
+	return resource;
+}
+
+} // End of namespace Mohawk
+
+#endif
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index c1a593b..9403beb 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -23,6 +23,7 @@
 #include "mohawk/cursors.h"
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_scripts.h"
 #include "mohawk/myst_sound.h"
@@ -163,16 +164,16 @@ void MystScriptParser::overrideOpcode(uint16 op, const char *name, MystScriptPar
 	warning("Unable to find opcode %d to override with '%s'", op, name);
 }
 
-void MystScriptParser::runScript(MystScript script, MystArea *invokingResource) {
+void MystScriptParser::runScript(const MystScript &script, MystArea *invokingResource) {
 	_scriptNestingLevel++;
 
-	for (uint16 i = 0; i < script->size(); i++) {
-		MystScriptEntry &entry = (*script)[i];
+	for (uint16 i = 0; i < script.size(); i++) {
+		const MystScriptEntry &entry = script[i];
 
 		if (entry.type == kMystScriptNormal)
 			_invokingResource = invokingResource;
 		else
-			_invokingResource = _vm->_resources[entry.resourceId];
+			_invokingResource = _vm->getCard()->getResource<MystArea>(entry.resourceId);
 
 		runOpcode(entry.opcode, entry.var, entry.args);
 	}
@@ -233,13 +234,12 @@ MystScript MystScriptParser::readScript(Common::SeekableReadStream *stream, Myst
 	assert(stream);
 	assert(type != kMystScriptNone);
 
-	MystScript script = MystScript(new Common::Array<MystScriptEntry>());
-
 	uint16 opcodeCount = stream->readUint16LE();
-	script->resize(opcodeCount);
+
+	MystScript script(opcodeCount);
 
 	for (uint16 i = 0; i < opcodeCount; i++) {
-		MystScriptEntry &entry = (*script)[i];
+		MystScriptEntry &entry = script[i];
 		entry.type = type;
 
 		// Resource ID only exists in INIT and EXIT scripts
@@ -316,12 +316,12 @@ void MystScriptParser::NOP(uint16 var, const ArgumentsArray &args) {
 
 void MystScriptParser::o_toggleVar(uint16 var, const ArgumentsArray &args) {
 	toggleVar(var);
-	_vm->redrawArea(var);
+	_vm->getCard()->redrawArea(var);
 }
 
 void MystScriptParser::o_setVar(uint16 var, const ArgumentsArray &args) {
 	if (setVarValue(var, args[0]))
-		_vm->redrawArea(var);
+		_vm->getCard()->redrawArea(var);
 }
 
 void MystScriptParser::o_changeCardSwitch4(uint16 var, const ArgumentsArray &args) {
@@ -385,7 +385,7 @@ void MystScriptParser::o_takePage(uint16 var, const ArgumentsArray &args) {
 
 	if (oldPage != _globals.heldPage) {
 		_vm->_cursor->hideCursor();
-		_vm->redrawArea(var);
+		_vm->getCard()->redrawArea(var);
 
 		// Set new cursor
 		if (_globals.heldPage != kNoPage)
@@ -398,8 +398,8 @@ void MystScriptParser::o_takePage(uint16 var, const ArgumentsArray &args) {
 }
 
 void MystScriptParser::o_redrawCard(uint16 var, const ArgumentsArray &args) {
-	_vm->drawCardBackground();
-	_vm->drawResourceImages();
+	_vm->getCard()->drawBackground();
+	_vm->getCard()->drawResourceImages();
 	_vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333));
 }
 
@@ -464,7 +464,7 @@ void MystScriptParser::o_drawAreaState(uint16 var, const ArgumentsArray &args) {
 }
 
 void MystScriptParser::o_redrawAreaForVar(uint16 var, const ArgumentsArray &args) {
-	_vm->redrawArea(var);
+	_vm->getCard()->redrawArea(var);
 }
 
 void MystScriptParser::o_changeCardDirectional(uint16 var, const ArgumentsArray &args) {
@@ -483,7 +483,7 @@ void MystScriptParser::o_changeCardDirectional(uint16 var, const ArgumentsArray
 // Opcode 18 then "pops" this stored CardId and returns to that card.
 
 void MystScriptParser::o_changeCardPush(uint16 var, const ArgumentsArray &args) {
-	_savedCardId = _vm->getCurCard();
+	_savedCardId = _vm->getCard()->getId();
 
 	uint16 cardId = args[0];
 	TransitionType transition = static_cast<TransitionType>(args[1]);
@@ -510,7 +510,7 @@ void MystScriptParser::o_enableAreas(uint16 var, const ArgumentsArray &args) {
 		if (args[i + 1] == 0xFFFF)
 			resource = _invokingResource;
 		else
-			resource = _vm->_resources[args[i + 1]];
+			resource = _vm->getCard()->getResource<MystArea>(args[i + 1]);
 
 		if (resource)
 			resource->setEnabled(true);
@@ -527,7 +527,7 @@ void MystScriptParser::o_disableAreas(uint16 var, const ArgumentsArray &args) {
 		if (args[i + 1] == 0xFFFF)
 			resource = _invokingResource;
 		else
-			resource = _vm->_resources[args[i + 1]];
+			resource = _vm->getCard()->getResource<MystArea>(args[i + 1]);
 
 		if (resource)
 			resource->setEnabled(false);
@@ -548,7 +548,7 @@ void MystScriptParser::o_toggleAreasActivation(uint16 var, const ArgumentsArray
 		if (args[i + 1] == 0xFFFF)
 			resource = _invokingResource;
 		else
-			resource = _vm->_resources[args[i + 1]];
+			resource = _vm->getCard()->getResource<MystArea>(args[i + 1]);
 
 		if (resource)
 			resource->setEnabled(!resource->isEnabled());
@@ -804,8 +804,8 @@ void MystScriptParser::o_quit(uint16 var, const ArgumentsArray &args) {
 }
 
 void MystScriptParser::showMap() {
-	if (_vm->getCurCard() != getMap()) {
-		_savedMapCardId = _vm->getCurCard();
+	if (_vm->getCard()->getId() != getMap()) {
+		_savedMapCardId = _vm->getCard()->getId();
 		_vm->changeToCard(getMap(), kTransitionCopy);
 	}
 }
diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h
index a7a840b..f89a76e 100644
--- a/engines/mohawk/myst_scripts.h
+++ b/engines/mohawk/myst_scripts.h
@@ -56,14 +56,14 @@ struct MystScriptEntry {
 	uint16 u1;
 };
 
-typedef Common::SharedPtr<Common::Array<MystScriptEntry> > MystScript;
+typedef Common::Array<MystScriptEntry> MystScript;
 
 class MystScriptParser {
 public:
 	explicit MystScriptParser(MohawkEngine_Myst *vm);
 	virtual ~MystScriptParser();
 
-	void runScript(MystScript script, MystArea *invokingResource = nullptr);
+	void runScript(const MystScript &script, MystArea *invokingResource = nullptr);
 	void runOpcode(uint16 op, uint16 var = 0, const ArgumentsArray &args = ArgumentsArray());
 	const Common::String getOpcodeDesc(uint16 op);
 	MystScript readScript(Common::SeekableReadStream *stream, MystScriptType type);
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index 726b3d6..d1281fa 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -23,6 +23,7 @@
 #include "mohawk/cursors.h"
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_state.h"
 #include "mohawk/myst_sound.h"
@@ -409,7 +410,7 @@ void Channelwood::o_leverEndMove(uint16 var, const ArgumentsArray &args) {
 	if (soundId)
 		_vm->_sound->playEffect(soundId);
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Channelwood::o_leverEndMoveResumeBackground(uint16 var, const ArgumentsArray &args) {
@@ -513,10 +514,10 @@ void Channelwood::o_valveHandleMoveStop(uint16 var, const ArgumentsArray &args)
 		_vm->_sound->playEffect(soundId);
 
 	// Redraw valve
-	_vm->redrawArea(_valveVar);
+	_vm->getCard()->redrawArea(_valveVar);
 
 	// Restore cursor
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Channelwood::o_valveHandleMove2(uint16 var, const ArgumentsArray &args) {
@@ -573,7 +574,7 @@ void Channelwood::o_hologramMonitor(uint16 var, const ArgumentsArray &args) {
 
 	if (_state.holoprojectorSelection != button || !_vm->_video->isVideoPlaying()) {
 		_state.holoprojectorSelection = button;
-		_vm->redrawArea(17);
+		_vm->getCard()->redrawArea(17);
 
 		_vm->_video->stopVideos();
 
@@ -605,8 +606,8 @@ void Channelwood::o_hologramMonitor(uint16 var, const ArgumentsArray &args) {
 
 void Channelwood::o_drawerOpen(uint16 var, const ArgumentsArray &args) {
 	_siriusDrawerState = 1;
-	_vm->redrawArea(18, false);
-	_vm->redrawArea(102, false);
+	_vm->getCard()->redrawArea(18, false);
+	_vm->getCard()->redrawArea(102, false);
 }
 
 void Channelwood::o_hologramTemple(uint16 var, const ArgumentsArray &args) {
@@ -635,7 +636,7 @@ void Channelwood::o_hologramTemple(uint16 var, const ArgumentsArray &args) {
 }
 
 void Channelwood::o_executeMouseUp(uint16 var, const ArgumentsArray &args) {
-	MystArea *resource = _vm->getViewResource<MystArea>(args[0]);
+	MystArea *resource = _vm->getCard()->getResource<MystArea>(args[0]);
 	resource->handleMouseUp();
 }
 
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index 80ccf7f..135aded 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -22,6 +22,7 @@
 
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/cursors.h"
 #include "mohawk/sound.h"
@@ -71,7 +72,7 @@ void Credits::runPersistentScripts() {
 		}
 
 		// Draw next image
-		_vm->drawCardBackground();
+		_vm->getCard()->drawBackground();
 		_vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333));
 
 		_startTime = _vm->_system->getMillis();
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index a58e278..495f40b 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -23,6 +23,7 @@
 #include "mohawk/cursors.h"
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_state.h"
 #include "mohawk/myst_sound.h"
@@ -298,7 +299,7 @@ bool Mechanical::setVarValue(uint16 var, uint16 value) {
 }
 
 void Mechanical::o_throneEnablePassage(uint16 var, const ArgumentsArray &args) {
-	_vm->_resources[args[0]]->setEnabled(getVar(var));
+	_vm->getCard()->getResource<MystArea>(args[0])->setEnabled(getVar(var));
 }
 
 void Mechanical::o_birdCrankStart(uint16 var, const ArgumentsArray &args) {
@@ -407,7 +408,7 @@ void Mechanical::o_elevatorRotationStop(uint16 var, const ArgumentsArray &args)
 			if (_elevatorRotationGearPosition > 12)
 				break;
 
-			_vm->redrawArea(12);
+			_vm->getCard()->redrawArea(12);
 			_vm->wait(100);
 		}
 
@@ -415,10 +416,10 @@ void Mechanical::o_elevatorRotationStop(uint16 var, const ArgumentsArray &args)
 		_state.elevatorRotation = (_state.elevatorRotation + 1) % 10;
 
 		_vm->_sound->playEffect(_elevatorRotationSoundId);
-		_vm->redrawArea(11);
+		_vm->getCard()->redrawArea(11);
 	}
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Mechanical::o_fortressRotationSpeedStart(uint16 var, const ArgumentsArray &args) {
@@ -455,7 +456,7 @@ void Mechanical::o_fortressRotationSpeedStop(uint16 var, const ArgumentsArray &a
 
 	_fortressRotationSpeed = 0;
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Mechanical::o_fortressRotationBrakeStart(uint16 var, const ArgumentsArray &args) {
@@ -485,7 +486,7 @@ void Mechanical::o_fortressRotationBrakeStop(uint16 var, const ArgumentsArray &a
 	MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
 	lever->drawFrame(_fortressRotationBrake);
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Mechanical::o_fortressSimulationSpeedStart(uint16 var, const ArgumentsArray &args) {
@@ -522,7 +523,7 @@ void Mechanical::o_fortressSimulationSpeedStop(uint16 var, const ArgumentsArray
 
 	_fortressSimulationSpeed = 0;
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Mechanical::o_fortressSimulationBrakeStart(uint16 var, const ArgumentsArray &args) {
@@ -552,7 +553,7 @@ void Mechanical::o_fortressSimulationBrakeStop(uint16 var, const ArgumentsArray
 	MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
 	lever->drawFrame(_fortressSimulationBrake);
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Mechanical::o_elevatorWindowMovie(uint16 var, const ArgumentsArray &args) {
@@ -664,32 +665,32 @@ void Mechanical::o_elevatorWaitTimeout(uint16 var, const ArgumentsArray &args) {
 
 void Mechanical::o_crystalEnterYellow(uint16 var, const ArgumentsArray &args) {
 	_crystalLit = 3;
-	_vm->redrawArea(20);
+	_vm->getCard()->redrawArea(20);
 }
 
 void Mechanical::o_crystalEnterGreen(uint16 var, const ArgumentsArray &args) {
 	_crystalLit = 1;
-	_vm->redrawArea(21);
+	_vm->getCard()->redrawArea(21);
 }
 
 void Mechanical::o_crystalEnterRed(uint16 var, const ArgumentsArray &args) {
 	_crystalLit = 2;
-	_vm->redrawArea(22);
+	_vm->getCard()->redrawArea(22);
 }
 
 void Mechanical::o_crystalLeaveYellow(uint16 var, const ArgumentsArray &args) {
 	_crystalLit = 0;
-	_vm->redrawArea(20);
+	_vm->getCard()->redrawArea(20);
 }
 
 void Mechanical::o_crystalLeaveGreen(uint16 var, const ArgumentsArray &args) {
 	_crystalLit = 0;
-	_vm->redrawArea(21);
+	_vm->getCard()->redrawArea(21);
 }
 
 void Mechanical::o_crystalLeaveRed(uint16 var, const ArgumentsArray &args) {
 	_crystalLit = 0;
-	_vm->redrawArea(22);
+	_vm->getCard()->redrawArea(22);
 }
 
 void Mechanical::o_throne_init(uint16 var, const ArgumentsArray &args) {
@@ -698,9 +699,9 @@ void Mechanical::o_throne_init(uint16 var, const ArgumentsArray &args) {
 }
 
 void Mechanical::o_fortressStaircase_init(uint16 var, const ArgumentsArray &args) {
-	_vm->_resources[args[0]]->setEnabled(!_state.staircaseState);
-	_vm->_resources[args[1]]->setEnabled(!_state.staircaseState);
-	_vm->_resources[args[2]]->setEnabled(_state.staircaseState);
+	_vm->getCard()->getResource<MystArea>(args[0])->setEnabled(!_state.staircaseState);
+	_vm->getCard()->getResource<MystArea>(args[1])->setEnabled(!_state.staircaseState);
+	_vm->getCard()->getResource<MystArea>(args[2])->setEnabled(_state.staircaseState);
 }
 
 void Mechanical::birdSing_run() {
@@ -724,7 +725,7 @@ void Mechanical::o_snakeBox_init(uint16 var, const ArgumentsArray &args) {
 }
 
 void Mechanical::elevatorRotation_run() {
-	_vm->redrawArea(12);
+	_vm->getCard()->redrawArea(12);
 
 	_elevatorRotationGearPosition += _elevatorRotationSpeed;
 
@@ -735,7 +736,7 @@ void Mechanical::elevatorRotation_run() {
 		_state.elevatorRotation = (_state.elevatorRotation + 1) % 10;
 
 		_vm->_sound->playEffect(_elevatorRotationSoundId);
-		_vm->redrawArea(11);
+		_vm->getCard()->redrawArea(11);
 		_vm->wait(100);
 	}
 }
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index 4adee5f..a3e5685 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -23,6 +23,7 @@
 #include "mohawk/cursors.h"
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_state.h"
 #include "mohawk/myst_sound.h"
@@ -1077,7 +1078,7 @@ void Myst::o_imagerChangeSelection(uint16 var, const ArgumentsArray &args) {
 		_state.imagerSelection = 10 * d1 + d2;
 		_state.imagerActive = 0;
 
-		_vm->redrawArea(var);
+		_vm->getCard()->redrawArea(var);
 	}
 }
 
@@ -1101,7 +1102,7 @@ void Myst::o_dockVaultOpen(uint16 var, const ArgumentsArray &args) {
 			_dockVaultState = 1;
 
 		_vm->_sound->playEffect(soundId);
-		_vm->redrawArea(41, false);
+		_vm->getCard()->redrawArea(41, false);
 		animatedUpdate(ArgumentsArray(args.begin() + 3, directionalUpdateDataSize), delay);
 	}
 }
@@ -1124,7 +1125,7 @@ void Myst::o_dockVaultClose(uint16 var, const ArgumentsArray &args) {
 			_dockVaultState = 0;
 
 		_vm->_sound->playEffect(soundId);
-		_vm->redrawArea(41, false);
+		_vm->getCard()->redrawArea(41, false);
 		animatedUpdate(ArgumentsArray(args.begin() + 3, directionalUpdateDataSize), delay);
 	}
 }
@@ -1238,7 +1239,7 @@ void Myst::o_clockWheelsExecute(uint16 var, const ArgumentsArray &args) {
 		_vm->waitUntilMovieEnds(gears);
 
 		_state.clockTowerBridgeOpen = 1;
-		_vm->redrawArea(12);
+		_vm->getCard()->redrawArea(12);
 	} else if (_state.clockTowerBridgeOpen && !correctTime) {
 		_vm->_sound->playEffect(soundId);
 		_vm->wait(500);
@@ -1251,7 +1252,7 @@ void Myst::o_clockWheelsExecute(uint16 var, const ArgumentsArray &args) {
 		_vm->waitUntilMovieEnds(gears);
 
 		_state.clockTowerBridgeOpen = 0;
-		_vm->redrawArea(12);
+		_vm->getCard()->redrawArea(12);
 	}
 }
 
@@ -1464,7 +1465,7 @@ void Myst::o_generatorButtonPressed(uint16 var, const ArgumentsArray &args) {
 	}
 
 	// Redraw button
-	_vm->redrawArea(button->getImageSwitchVar());
+	_vm->getCard()->redrawArea(button->getImageSwitchVar());
 
 	// Blow breaker
 	if (_state.generatorVoltage > 59)
@@ -1472,9 +1473,9 @@ void Myst::o_generatorButtonPressed(uint16 var, const ArgumentsArray &args) {
 }
 
 void Myst::generatorRedrawRocket() {
-	_vm->redrawArea(64);
-	_vm->redrawArea(65);
-	_vm->redrawArea(97);
+	_vm->getCard()->redrawArea(64);
+	_vm->getCard()->redrawArea(65);
+	_vm->getCard()->redrawArea(97);
 }
 
 void Myst::generatorButtonValue(MystArea *button, uint16 &mask, uint16 &value) {
@@ -1536,7 +1537,7 @@ void Myst::o_cabinSafeChangeDigit(uint16 var, const ArgumentsArray &args) {
 
 	_state.cabinSafeCombination = 100 * d1 + 10 * d2 + d3;
 
-	_vm->redrawArea(var);
+	_vm->getCard()->redrawArea(var);
 }
 
 void Myst::o_cabinSafeHandleStartMove(uint16 var, const ArgumentsArray &args) {
@@ -1579,7 +1580,7 @@ void Myst::o_cabinSafeHandleEndMove(uint16 var, const ArgumentsArray &args) {
 	// Used on Card 4100
 	MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
 	handle->drawFrame(0);
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Myst::o_observatoryMonthChangeStartIncrease(uint16 var, const ArgumentsArray &args) {
@@ -1630,7 +1631,7 @@ void Myst::observatoryIncrementMonth(int16 increment) {
 		_state.observatoryMonthSetting = newMonth;
 
 		// Redraw digits
-		_vm->redrawArea(73);
+		_vm->getCard()->redrawArea(73);
 
 		// Update slider
 		_observatoryMonthSlider->setPosition(94 + 94 * _state.observatoryMonthSetting / 11);
@@ -1696,8 +1697,8 @@ void Myst::observatoryIncrementDay(int16 increment) {
 		_state.observatoryDaySetting = newDay;
 
 		// Redraw digits
-		_vm->redrawArea(75);
-		_vm->redrawArea(74);
+		_vm->getCard()->redrawArea(75);
+		_vm->getCard()->redrawArea(74);
 
 		// Update slider
 		_observatoryDaySlider->setPosition(91 + 3 * _state.observatoryDaySetting);
@@ -1755,10 +1756,10 @@ void Myst::observatoryIncrementYear(int16 increment) {
 		_state.observatoryYearSetting = newYear;
 
 		// Redraw digits
-		_vm->redrawArea(79);
-		_vm->redrawArea(78);
-		_vm->redrawArea(77);
-		_vm->redrawArea(76);
+		_vm->getCard()->redrawArea(79);
+		_vm->getCard()->redrawArea(78);
+		_vm->getCard()->redrawArea(77);
+		_vm->getCard()->redrawArea(76);
 
 		// Update slider
 		_observatoryYearSlider->setPosition(94 + 94 * _state.observatoryYearSetting / 9999);
@@ -1816,14 +1817,14 @@ void Myst::observatoryIncrementTime(int16 increment) {
 		_state.observatoryTimeSetting = newTime;
 
 		// Redraw digits
-		_vm->redrawArea(80);
-		_vm->redrawArea(81);
-		_vm->redrawArea(82);
-		_vm->redrawArea(83);
+		_vm->getCard()->redrawArea(80);
+		_vm->getCard()->redrawArea(81);
+		_vm->getCard()->redrawArea(82);
+		_vm->getCard()->redrawArea(83);
 
 		// Draw AM/PM
 		if (!observatoryIsDDMMYYYY2400()) {
-			_vm->redrawArea(88);
+			_vm->getCard()->redrawArea(88);
 		}
 
 		// Update slider
@@ -1870,7 +1871,7 @@ void Myst::o_observatoryGoButton(uint16 var, const ArgumentsArray &args) {
 
 		// Redraw button
 		_tempVar = 0;
-		_vm->redrawArea(105);
+		_vm->getCard()->redrawArea(105);
 	}
 }
 
@@ -1948,8 +1949,8 @@ void Myst::o_circuitBreakerMove(uint16 var, const ArgumentsArray &args) {
 
 void Myst::o_circuitBreakerEndMove(uint16 var, const ArgumentsArray &args) {
 	MystVideoInfo *breaker = getInvokingResource<MystVideoInfo>();
-	_vm->redrawArea(breaker->getImageSwitchVar());
-	_vm->checkCursorHints();
+	_vm->getCard()->redrawArea(breaker->getImageSwitchVar());
+	_vm->refreshCursor();
 }
 
 void Myst::o_boilerIncreasePressureStart(uint16 var, const ArgumentsArray &args) {
@@ -1964,7 +1965,7 @@ void Myst::o_boilerLightPilot(uint16 var, const ArgumentsArray &args) {
 	// Match is lit
 	if (_cabinMatchState == 1) {
 		_state.cabinPilotLightLit = 1;
-		_vm->redrawArea(98);
+		_vm->getCard()->redrawArea(98);
 
 		boilerFireUpdate(false);
 
@@ -1995,7 +1996,7 @@ Common::Rational Myst::boilerComputeGaugeRate(uint16 pressure, uint32 delay) {
 
 void Myst::boilerResetGauge(const Common::Rational &rate) {
 	if (!_cabinGaugeMovie || _cabinGaugeMovie->endOfVideo()) {
-		if (_vm->getCurCard() == 4098) {
+		if (_vm->getCard()->getId() == 4098) {
 			_cabinGaugeMovie = _vm->playMovie("cabingau", kMystStack);
 			_cabinGaugeMovie->moveTo(243, 96);
 		} else {
@@ -2042,7 +2043,7 @@ void Myst::boilerPressureIncrease_run() {
 			boilerFireUpdate(false);
 
 			// Draw fire
-			_vm->redrawArea(305);
+			_vm->getCard()->redrawArea(305);
 		} else if (_state.cabinValvePosition == 25) {
 			if (_state.cabinPilotLightLit == 1)
 				_vm->_sound->playBackground(8098, 49152);
@@ -2054,7 +2055,7 @@ void Myst::boilerPressureIncrease_run() {
 		_vm->_sound->playEffect(5098);
 
 		// Redraw wheel
-		_vm->redrawArea(99);
+		_vm->getCard()->redrawArea(99);
 	}
 }
 
@@ -2067,14 +2068,14 @@ void Myst::boilerPressureDecrease_run() {
 			boilerFireUpdate(false);
 
 			// Draw fire
-			_vm->redrawArea(305);
+			_vm->getCard()->redrawArea(305);
 		}
 
 		// Pressure increasing sound
 		_vm->_sound->playEffect(5098);
 
 		// Redraw wheel
-		_vm->redrawArea(99);
+		_vm->getCard()->redrawArea(99);
 	}
 }
 
@@ -2126,7 +2127,7 @@ void Myst::basementPressureIncrease_run() {
 		_vm->_sound->playEffect(4642);
 
 		// Redraw wheel
-		_vm->redrawArea(99);
+		_vm->getCard()->redrawArea(99);
 	}
 }
 
@@ -2139,7 +2140,7 @@ void Myst::basementPressureDecrease_run() {
 		_vm->_sound->playEffect(4642);
 
 		// Redraw wheel
-		_vm->redrawArea(99);
+		_vm->getCard()->redrawArea(99);
 	}
 }
 
@@ -2184,7 +2185,7 @@ void Myst::tree_run() {
 				}
 
 				// Stop background music if going up from book room
-				if (_vm->getCurCard() == 4630) {
+				if (_vm->getCard()->getId() == 4630) {
 					if (_state.treePosition > 0)
 						_vm->_sound->stopBackground();
 					else
@@ -2192,7 +2193,7 @@ void Myst::tree_run() {
 				}
 
 				// Redraw tree
-				_vm->redrawArea(72);
+				_vm->getCard()->redrawArea(72);
 
 				// Check if alcove is accessible
 				treeSetAlcoveAccessible();
@@ -2235,7 +2236,7 @@ void Myst::o_rocketSoundSliderMove(uint16 var, const ArgumentsArray &args) {
 }
 
 void Myst::o_rocketSoundSliderEndMove(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 
 	if (_state.generatorVoltage == 59 && !_state.generatorBreakers && _rocketSliderSound)
 		_vm->_sound->stopEffect();
@@ -2382,7 +2383,7 @@ void Myst::o_rocketPianoMove(uint16 var, const ArgumentsArray &args) {
 	_vm->_gfx->copyImageSectionToScreen(key->getSubImage(0).wdib, src, dest);
 
 	if (piano.contains(mouse)) {
-		MystArea *resource = _vm->forceUpdateClickedResource();
+		MystArea *resource = _vm->getCard()->forceUpdateClickedResource(mouse);
 		if (resource && resource->hasType(kMystAreaDrag)) {
 			// Press new key
 			key = static_cast<MystAreaDrag *>(resource);
@@ -2472,7 +2473,7 @@ void Myst::o_rocketLeverMove(uint16 var, const ArgumentsArray &args) {
 void Myst::o_rocketLeverEndMove(uint16 var, const ArgumentsArray &args) {
 	MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 	_rocketLeverPosition = 0;
 	lever->drawFrame(0);
 }
@@ -2517,7 +2518,7 @@ void Myst::o_observatoryMonthSliderStartMove(uint16 var, const ArgumentsArray &a
 }
 
 void Myst::o_observatoryMonthSliderEndMove(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 	_vm->_sound->resumeBackground();
 
 	observatoryUpdateMonth();
@@ -2533,7 +2534,7 @@ void Myst::observatoryUpdateMonth() {
 		_vm->wait(20);
 
 		// Redraw digits
-		_vm->redrawArea(73);
+		_vm->getCard()->redrawArea(73);
 	}
 }
 
@@ -2545,7 +2546,7 @@ void Myst::o_observatoryDaySliderStartMove(uint16 var, const ArgumentsArray &arg
 }
 
 void Myst::o_observatoryDaySliderEndMove(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 	_vm->_sound->resumeBackground();
 
 	observatoryUpdateDay();
@@ -2561,8 +2562,8 @@ void Myst::observatoryUpdateDay() {
 		_vm->wait(20);
 
 		// Redraw digits
-		_vm->redrawArea(75);
-		_vm->redrawArea(74);
+		_vm->getCard()->redrawArea(75);
+		_vm->getCard()->redrawArea(74);
 	}
 }
 
@@ -2574,7 +2575,7 @@ void Myst::o_observatoryYearSliderStartMove(uint16 var, const ArgumentsArray &ar
 }
 
 void Myst::o_observatoryYearSliderEndMove(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 	_vm->_sound->resumeBackground();
 
 	observatoryUpdateYear();
@@ -2590,10 +2591,10 @@ void Myst::observatoryUpdateYear() {
 		_vm->wait(20);
 
 		// Redraw digits
-		_vm->redrawArea(79);
-		_vm->redrawArea(78);
-		_vm->redrawArea(77);
-		_vm->redrawArea(76);
+		_vm->getCard()->redrawArea(79);
+		_vm->getCard()->redrawArea(78);
+		_vm->getCard()->redrawArea(77);
+		_vm->getCard()->redrawArea(76);
 	}
 }
 
@@ -2605,7 +2606,7 @@ void Myst::o_observatoryTimeSliderStartMove(uint16 var, const ArgumentsArray &ar
 }
 
 void Myst::o_observatoryTimeSliderEndMove(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 	_vm->_sound->resumeBackground();
 
 	observatoryUpdateTime();
@@ -2621,14 +2622,14 @@ void Myst::observatoryUpdateTime() {
 		_vm->wait(20);
 
 		// Redraw digits
-		_vm->redrawArea(80);
-		_vm->redrawArea(81);
-		_vm->redrawArea(82);
-		_vm->redrawArea(83);
+		_vm->getCard()->redrawArea(80);
+		_vm->getCard()->redrawArea(81);
+		_vm->getCard()->redrawArea(82);
+		_vm->getCard()->redrawArea(83);
 
 		// Draw AM/PM
 		if (!observatoryIsDDMMYYYY2400())
-			_vm->redrawArea(88);
+			_vm->getCard()->redrawArea(88);
 	}
 }
 
@@ -2706,12 +2707,12 @@ void Myst::matchBurn_run() {
 void Myst::o_courtyardBoxEnter(uint16 var, const ArgumentsArray &args) {
 	_tempVar = 1;
 	_vm->_sound->playEffect(_courtyardBoxSound);
-	_vm->redrawArea(var);
+	_vm->getCard()->redrawArea(var);
 }
 
 void Myst::o_courtyardBoxLeave(uint16 var, const ArgumentsArray &args) {
 	_tempVar = 0;
-	_vm->redrawArea(var);
+	_vm->getCard()->redrawArea(var);
 }
 
 void Myst::o_clockMinuteWheelStartTurn(uint16 var, const ArgumentsArray &args) {
@@ -2741,7 +2742,7 @@ void Myst::clockWheel_run() {
 		else
 			clockWheelTurn(38);
 
-		_vm->redrawArea(37);
+		_vm->getCard()->redrawArea(37);
 	}
 }
 
@@ -2758,7 +2759,7 @@ void Myst::clockWheelStartTurn(uint16 wheel) {
 	else
 		clockWheelTurn(38);
 
-	_vm->redrawArea(37);
+	_vm->getCard()->redrawArea(37);
 
 	// Continue turning wheel until mouse button is released
 	_clockTurningWheel = wheel;
@@ -2877,12 +2878,12 @@ void Myst::o_dockVaultForceClose(uint16 var, const ArgumentsArray &args) {
 		// Open switch
 		_state.dockMarkerSwitch = 1;
 		_vm->_sound->playEffect(4143);
-		_vm->redrawArea(4);
+		_vm->getCard()->redrawArea(4);
 
 		// Close vault
 		_dockVaultState = 0;
 		_vm->_sound->playEffect(soundId);
-		_vm->redrawArea(41, false);
+		_vm->getCard()->redrawArea(41, false);
 		animatedUpdate(ArgumentsArray(args.begin() + 3, directionalUpdateDataSize), delay);
 	}
 }
@@ -3027,7 +3028,7 @@ void Myst::clockGearsCheckSolution() {
 		// Gear opening video
 		_vm->playMovieBlocking("cl1wggat", kMystStack, 195, 225);
 		_state.gearsOpen = 1;
-		_vm->redrawArea(40);
+		_vm->getCard()->redrawArea(40);
 
 		_vm->_sound->playBackground(4113, 16384);
 	}
@@ -3085,7 +3086,7 @@ void Myst::clockReset() {
 
 		// Redraw gear
 		_state.gearsOpen = 0;
-		_vm->redrawArea(40);
+		_vm->getCard()->redrawArea(40);
 	}
 
 	_vm->_cursor->showCursor();
@@ -3131,7 +3132,7 @@ void Myst::o_clockResetLeverEndMove(uint16 var, const ArgumentsArray &args) {
 
 	lever->releaseLeverV();
 
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Myst::o_libraryBook_init(uint16 var, const ArgumentsArray &args) {
@@ -3189,7 +3190,7 @@ void Myst::towerRotationMap_run() {
 void Myst::o_towerRotationMap_init(uint16 var, const ArgumentsArray &args) {
 	_towerRotationMapRunning = true;
 	_towerRotationMapTower = getInvokingResource<MystAreaImageSwitch>();
-	_towerRotationMapLabel = _vm->getViewResource<MystAreaImageSwitch>(args[0]);
+	_towerRotationMapLabel = _vm->getCard()->getResource<MystAreaImageSwitch>(args[0]);
 	_tempVar = 0;
 	_startTime = 0;
 	_towerRotationMapClicked = false;
@@ -3197,11 +3198,11 @@ void Myst::o_towerRotationMap_init(uint16 var, const ArgumentsArray &args) {
 
 void Myst::towerRotationDrawBuildings() {
 	// Draw library
-	_vm->redrawArea(304, false);
+	_vm->getCard()->redrawArea(304, false);
 
 	// Draw other resources
 	for (uint i = 1; i <= 10; i++) {
-		MystAreaImageSwitch *resource = _vm->getViewResource<MystAreaImageSwitch>(i);
+		MystAreaImageSwitch *resource = _vm->getCard()->getResource<MystAreaImageSwitch>(i);
 		_vm->redrawResource(resource, false);
 	}
 }
@@ -3279,7 +3280,7 @@ void Myst::towerRotationMapDrawLine(const Common::Point &end, bool rotationLabel
 	src.bottom = 332 - rect.top;
 
 	// Redraw background
-	_vm->_gfx->copyImageSectionToBackBuffer(_vm->getCardBackgroundId(), src, rect);
+	_vm->_gfx->copyImageSectionToBackBuffer(_vm->getCard()->getBackgroundImageId(), src, rect);
 
 	// Draw buildings
 	towerRotationDrawBuildings();
@@ -3392,9 +3393,9 @@ void Myst::generatorControlRoom_run(void) {
 			_generatorVoltage++;
 
 		// Redraw generator gauge
-		_vm->redrawArea(62);
-		_vm->redrawArea(63);
-		_vm->redrawArea(96);
+		_vm->getCard()->redrawArea(62);
+		_vm->getCard()->redrawArea(63);
+		_vm->getCard()->redrawArea(96);
 	}
 }
 
@@ -3457,16 +3458,16 @@ void Myst::o_observatory_init(uint16 var, const ArgumentsArray &args) {
 	_tempVar = 0;
 	_observatoryNotInitialized = true;
 	_observatoryVisualizer = getInvokingResource<MystAreaImageSwitch>();
-	_observatoryGoButton = _vm->getViewResource<MystAreaImageSwitch>(args[0]);
+	_observatoryGoButton = _vm->getCard()->getResource<MystAreaImageSwitch>(args[0]);
 	if (observatoryIsDDMMYYYY2400()) {
-		_observatoryDaySlider = _vm->getViewResource<MystAreaSlider>(args[1]);
-		_observatoryMonthSlider = _vm->getViewResource<MystAreaSlider>(args[2]);
+		_observatoryDaySlider = _vm->getCard()->getResource<MystAreaSlider>(args[1]);
+		_observatoryMonthSlider = _vm->getCard()->getResource<MystAreaSlider>(args[2]);
 	} else {
-		_observatoryMonthSlider = _vm->getViewResource<MystAreaSlider>(args[1]);
-		_observatoryDaySlider = _vm->getViewResource<MystAreaSlider>(args[2]);
+		_observatoryMonthSlider = _vm->getCard()->getResource<MystAreaSlider>(args[1]);
+		_observatoryDaySlider = _vm->getCard()->getResource<MystAreaSlider>(args[2]);
 	}
-	_observatoryYearSlider = _vm->getViewResource<MystAreaSlider>(args[3]);
-	_observatoryTimeSlider = _vm->getViewResource<MystAreaSlider>(args[4]);
+	_observatoryYearSlider = _vm->getCard()->getResource<MystAreaSlider>(args[3]);
+	_observatoryTimeSlider = _vm->getCard()->getResource<MystAreaSlider>(args[4]);
 
 	// Set date selection sliders position
 	_observatoryDaySlider->setPosition(_state.observatoryDaySlider);
@@ -3610,13 +3611,13 @@ void Myst::o_boilerMovies_init(uint16 var, const ArgumentsArray &args) {
 }
 
 void Myst::boilerFireInit() {
-	if (_vm->getCurCard() == 4098) {
+	if (_vm->getCard()->getId() == 4098) {
 		_cabinFireMovie = _vm->playMovie("cabfire", kMystStack);
 		_cabinFireMovie->moveTo(240, 279);
 		_cabinFireMovie->setLooping(true);
 		_cabinFireMovie->pause(true);
 
-		_vm->redrawArea(305);
+		_vm->getCard()->redrawArea(305);
 		boilerFireUpdate(true);
 	} else {
 		if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition >= 1) {
@@ -3646,7 +3647,7 @@ void Myst::boilerFireUpdate(bool init) {
 }
 
 void Myst::boilerGaugeInit() {
-	if (_vm->getCurCard() == 4098) {
+	if (_vm->getCard()->getId() == 4098) {
 		_cabinGaugeMovie = _vm->playMovie("cabingau", kMystStack);
 		_cabinGaugeMovie->moveTo(243, 96);
 	} else {
@@ -3668,11 +3669,11 @@ void Myst::boilerGaugeInit() {
 
 void Myst::o_rocketSliders_init(uint16 var, const ArgumentsArray &args) {
 	_rocketLinkBook.reset();
-	_rocketSlider1 = _vm->getViewResource<MystAreaSlider>(args[0]);
-	_rocketSlider2 = _vm->getViewResource<MystAreaSlider>(args[1]);
-	_rocketSlider3 = _vm->getViewResource<MystAreaSlider>(args[2]);
-	_rocketSlider4 = _vm->getViewResource<MystAreaSlider>(args[3]);
-	_rocketSlider5 = _vm->getViewResource<MystAreaSlider>(args[4]);
+	_rocketSlider1 = _vm->getCard()->getResource<MystAreaSlider>(args[0]);
+	_rocketSlider2 = _vm->getCard()->getResource<MystAreaSlider>(args[1]);
+	_rocketSlider3 = _vm->getCard()->getResource<MystAreaSlider>(args[2]);
+	_rocketSlider4 = _vm->getCard()->getResource<MystAreaSlider>(args[3]);
+	_rocketSlider5 = _vm->getCard()->getResource<MystAreaSlider>(args[4]);
 
 	// Initialize sliders position
 	for (uint i = 0; i < 5; i++)
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index 2390306..8d95cb5 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -24,6 +24,7 @@
 #include "mohawk/myst.h"
 #include "mohawk/graphics.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_state.h"
 #include "mohawk/myst_sound.h"
 #include "mohawk/video.h"
@@ -1086,19 +1087,19 @@ void Selenitic::o_soundReceiver_init(uint16 var, const ArgumentsArray &args) {
 	// Used for Card 1245 (Sound Receiver)
 	_soundReceiverRunning = true;
 
-	_soundReceiverRightButton = _vm->getViewResource<MystAreaImageSwitch>(0);
-	_soundReceiverLeftButton = _vm->getViewResource<MystAreaImageSwitch>(1);
-	_soundReceiverSigmaButton = _vm->getViewResource<MystAreaImageSwitch>(2);
-	_soundReceiverSources[4] = _vm->getViewResource<MystAreaImageSwitch>(3);
-	_soundReceiverSources[3] = _vm->getViewResource<MystAreaImageSwitch>(4);
-	_soundReceiverSources[2] = _vm->getViewResource<MystAreaImageSwitch>(5);
-	_soundReceiverSources[1] = _vm->getViewResource<MystAreaImageSwitch>(6);
-	_soundReceiverSources[0] = _vm->getViewResource<MystAreaImageSwitch>(7);
-	_soundReceiverViewer = _vm->getViewResource<MystAreaImageSwitch>(8);
-	_soundReceiverAngle1 = _vm->getViewResource<MystAreaImageSwitch>(10);
-	_soundReceiverAngle2 = _vm->getViewResource<MystAreaImageSwitch>(11);
-	_soundReceiverAngle3 = _vm->getViewResource<MystAreaImageSwitch>(12);
-	_soundReceiverAngle4 = _vm->getViewResource<MystAreaImageSwitch>(13);
+	_soundReceiverRightButton = _vm->getCard()->getResource<MystAreaImageSwitch>(0);
+	_soundReceiverLeftButton = _vm->getCard()->getResource<MystAreaImageSwitch>(1);
+	_soundReceiverSigmaButton = _vm->getCard()->getResource<MystAreaImageSwitch>(2);
+	_soundReceiverSources[4] = _vm->getCard()->getResource<MystAreaImageSwitch>(3);
+	_soundReceiverSources[3] = _vm->getCard()->getResource<MystAreaImageSwitch>(4);
+	_soundReceiverSources[2] = _vm->getCard()->getResource<MystAreaImageSwitch>(5);
+	_soundReceiverSources[1] = _vm->getCard()->getResource<MystAreaImageSwitch>(6);
+	_soundReceiverSources[0] = _vm->getCard()->getResource<MystAreaImageSwitch>(7);
+	_soundReceiverViewer = _vm->getCard()->getResource<MystAreaImageSwitch>(8);
+	_soundReceiverAngle1 = _vm->getCard()->getResource<MystAreaImageSwitch>(10);
+	_soundReceiverAngle2 = _vm->getCard()->getResource<MystAreaImageSwitch>(11);
+	_soundReceiverAngle3 = _vm->getCard()->getResource<MystAreaImageSwitch>(12);
+	_soundReceiverAngle4 = _vm->getCard()->getResource<MystAreaImageSwitch>(13);
 
 	uint16 currentSource = _state.soundReceiverCurrentSource;
 	_soundReceiverPosition = &_state.soundReceiverPositions[currentSource];
@@ -1111,32 +1112,33 @@ void Selenitic::o_soundReceiver_init(uint16 var, const ArgumentsArray &args) {
 }
 
 void Selenitic::o_soundLock_init(uint16 var, const ArgumentsArray &args) {
-	for (uint i = 0; i < _vm->_resources.size(); i++) {
-		if (_vm->_resources[i]->hasType(kMystAreaSlider)) {
-			switch (_vm->_resources[i]->getImageSwitchVar()) {
+	for (uint i = 0; i < _vm->getCard()->_resources.size(); i++) {
+		if (_vm->getCard()->_resources[i]->hasType(kMystAreaSlider)) {
+			switch (_vm->getCard()->_resources[i]->getImageSwitchVar()) {
 			case 20:
-				_soundLockSlider1 = _vm->getViewResource<MystAreaSlider>(i);
+				_soundLockSlider1 = _vm->getCard()->getResource<MystAreaSlider>(i);
 				_soundLockSlider1->setStep(_state.soundLockSliderPositions[0]);
 				break;
 			case 21:
-				_soundLockSlider2 = _vm->getViewResource<MystAreaSlider>(i);
+				_soundLockSlider2 = _vm->getCard()->getResource<MystAreaSlider>(i);
 				_soundLockSlider2->setStep(_state.soundLockSliderPositions[1]);
 				break;
 			case 22:
-				_soundLockSlider3 = _vm->getViewResource<MystAreaSlider>(i);
+				_soundLockSlider3 = _vm->getCard()->getResource<MystAreaSlider>(i);
 				_soundLockSlider3->setStep(_state.soundLockSliderPositions[2]);
 				break;
 			case 23:
-				_soundLockSlider4 = _vm->getViewResource<MystAreaSlider>(i);
+				_soundLockSlider4 = _vm->getCard()->getResource<MystAreaSlider>(i);
 				_soundLockSlider4->setStep(_state.soundLockSliderPositions[3]);
 				break;
 			case 24:
-				_soundLockSlider5 = _vm->getViewResource<MystAreaSlider>(i);
+				_soundLockSlider5 = _vm->getCard()->getResource<MystAreaSlider>(i);
 				_soundLockSlider5->setStep(_state.soundLockSliderPositions[4]);
 				break;
 			}
-		} else if (_vm->_resources[i]->hasType(kMystAreaImageSwitch) && _vm->_resources[i]->getImageSwitchVar() == 28) {
-			_soundLockButton = _vm->getViewResource<MystAreaImageSwitch>(i);
+		} else if (_vm->getCard()->_resources[i]->hasType(kMystAreaImageSwitch)
+		           && _vm->getCard()->_resources[i]->getImageSwitchVar() == 28) {
+			_soundLockButton = _vm->getCard()->getResource<MystAreaImageSwitch>(i);
 		}
 	}
 
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index cd1db68..0ae78c1 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -23,6 +23,7 @@
 #include "mohawk/cursors.h"
 #include "mohawk/myst.h"
 #include "mohawk/myst_areas.h"
+#include "mohawk/myst_card.h"
 #include "mohawk/myst_graphics.h"
 #include "mohawk/myst_state.h"
 #include "mohawk/myst_sound.h"
@@ -426,8 +427,8 @@ void Stoneship::o_pumpTurnOff(uint16 var, const ArgumentsArray &args) {
 			warning("Incorrect pump state");
 		}
 
-		for (uint i = 0; i < _vm->_resources.size(); i++) {
-			MystArea *resource = _vm->_resources[i];
+		for (uint i = 0; i < _vm->getCard()->_resources.size(); i++) {
+			MystArea *resource = _vm->getCard()->_resources[i];
 			if (resource->hasType(kMystAreaImageSwitch) && resource->getImageSwitchVar() == buttonVar) {
 				static_cast<MystAreaImageSwitch *>(resource)->drawConditionalDataToScreen(0, true);
 				break;
@@ -438,7 +439,7 @@ void Stoneship::o_pumpTurnOff(uint16 var, const ArgumentsArray &args) {
 
 void Stoneship::o_brotherDoorOpen(uint16 var, const ArgumentsArray &args) {
 	_brotherDoorOpen = 1;
-	_vm->redrawArea(19, 0);
+	_vm->getCard()->redrawArea(19, 0);
 	animatedUpdate(args, 5);
 }
 
@@ -454,7 +455,7 @@ void Stoneship::o_cabinBookMovie(uint16 var, const ArgumentsArray &args) {
 }
 
 void Stoneship::o_drawerOpenSirius(uint16 var, const ArgumentsArray &args) {
-	MystAreaImageSwitch *drawer = _vm->getViewResource<MystAreaImageSwitch>(args[0]);
+	MystAreaImageSwitch *drawer = _vm->getCard()->getResource<MystAreaImageSwitch>(args[0]);
 
 	if (drawer->getImageSwitchVar() == 35) {
 		drawer->drawConditionalDataToScreen(getVar(102), 0);
@@ -496,7 +497,7 @@ void Stoneship::o_telescopeMove(uint16 var, const ArgumentsArray &args) {
 }
 
 void Stoneship::o_telescopeStop(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Stoneship::o_generatorStart(uint16 var, const ArgumentsArray &args) {
@@ -589,7 +590,7 @@ void Stoneship::batteryDeplete_run() {
 }
 
 void Stoneship::o_drawerOpenAchenar(uint16 var, const ArgumentsArray &args) {
-	MystAreaImageSwitch *drawer = _vm->getViewResource<MystAreaImageSwitch>(args[0]);
+	MystAreaImageSwitch *drawer = _vm->getCard()->getResource<MystAreaImageSwitch>(args[0]);
 	drawer->drawConditionalDataToScreen(0, 0);
 	_vm->_gfx->runTransition(kTransitionTopToBottom, drawer->getRect(), 25, 5);
 }
@@ -644,7 +645,7 @@ void Stoneship::o_hologramSelectionMove(uint16 var, const ArgumentsArray &args)
 }
 
 void Stoneship::o_hologramSelectionStop(uint16 var, const ArgumentsArray &args) {
-	_vm->checkCursorHints();
+	_vm->refreshCursor();
 }
 
 void Stoneship::o_compassButton(uint16 var, const ArgumentsArray &args) {
@@ -785,10 +786,10 @@ void Stoneship::o_drawerCloseOpened(uint16 var, const ArgumentsArray &args) {
 
 void Stoneship::drawerClose(uint16 drawer) {
 	_chestDrawersOpen = 0;
-	_vm->drawCardBackground();
-	_vm->drawResourceImages();
+	_vm->getCard()->drawBackground();
+	_vm->getCard()->drawResourceImages();
 
-	MystArea *res = _vm->_resources[drawer];
+	MystArea *res = _vm->getCard()->getResource<MystArea>(drawer);
 	_vm->_gfx->runTransition(kTransitionBottomToTop, res->getRect(), 25, 5);
 }
 
@@ -844,8 +845,8 @@ void Stoneship::batteryGauge_run() {
 		_batteryLastCharge = batteryCharge;
 
 		// Redraw card
-		_vm->drawCardBackground();
-		_vm->drawResourceImages();
+		_vm->getCard()->drawBackground();
+		_vm->getCard()->drawResourceImages();
 		_vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333));
 	}
 }
@@ -946,12 +947,12 @@ void Stoneship::o_achenarDrawers_init(uint16 var, const ArgumentsArray &args) {
 		uint16 count1 = args[0];
 		for (uint16 i = 0; i < count1; i++) {
 			debugC(kDebugScript, "Disable hotspot index %d", args[i + 1]);
-			_vm->setResourceEnabled(args[i + 1], false);
+			_vm->getCard()->setResourceEnabled(args[i + 1], false);
 		}
 		uint16 count2 = args[count1 + 1];
 		for (uint16 i = 0; i < count2; i++) {
 			debugC(kDebugScript, "Enable hotspot index %d", args[i + count1 + 2]);
-			_vm->setResourceEnabled(args[i + count1 + 2], true);
+			_vm->getCard()->setResourceEnabled(args[i + count1 + 2], true);
 		}
 	}
 }


Commit: ea60aef8a8018ac75ea9a5b507f4140eafe2d660
    https://github.com/scummvm/scummvm/commit/ea60aef8a8018ac75ea9a5b507f4140eafe2d660
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2018-06-13T07:55:55+02:00

Commit Message:
MOHAWK: MYST: Simplify memory management of the active stack

Changed paths:
    engines/mohawk/dialogs.cpp
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/myst_areas.cpp
    engines/mohawk/myst_areas.h


diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index 5700a46..b9575ce 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -32,6 +32,7 @@
 
 #ifdef ENABLE_MYST
 #include "mohawk/myst.h"
+#include "mohawk/myst_scripts.h"
 #endif
 
 #ifdef ENABLE_RIVEN
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index d0d3a3c..3f72647 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -78,13 +78,10 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
 	_video = nullptr;
 	_gfx = nullptr;
 	_console = nullptr;
-	_scriptParser = nullptr;
 	_gameState = nullptr;
 	_optionsDialog = nullptr;
 	_rnd = nullptr;
 
-	_prevStack = nullptr;
-
 	_mouseClicked = false;
 	_mouseMoved = false;
 	_escapePressed = false;
@@ -103,10 +100,8 @@ MohawkEngine_Myst::~MohawkEngine_Myst() {
 	delete _video;
 	delete _sound;
 	delete _console;
-	delete _scriptParser;
 	delete _gameState;
 	delete _optionsDialog;
-	delete _prevStack;
 	delete _rnd;
 }
 
@@ -565,64 +560,60 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 	if (linkSrcSound)
 		playSoundBlocking(linkSrcSound);
 
-	_card->leave();
-	_card.reset();
-
-	// Delete the previous stack and move the current stack to the previous one
-	// There's probably a better way to do this, but the script classes shouldn't
-	// take up much memory.
-	delete _prevStack;
-	_prevStack = _scriptParser;
+	if (_card) {
+		_card->leave();
+		_card.reset();
+	}
 
 	_curStack = stack;
 
 	switch (_curStack) {
 	case kChannelwoodStack:
 		_gameState->_globals.currentAge = kChannelwood;
-		_scriptParser = new MystStacks::Channelwood(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Channelwood(this));
 		break;
 	case kCreditsStack:
-		_scriptParser = new MystStacks::Credits(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Credits(this));
 		break;
 	case kDemoStack:
 		_gameState->_globals.currentAge = kSelenitic;
-		_scriptParser = new MystStacks::Demo(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Demo(this));
 		break;
 	case kDniStack:
 		_gameState->_globals.currentAge = kDni;
-		_scriptParser = new MystStacks::Dni(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Dni(this));
 		break;
 	case kIntroStack:
-		_scriptParser = new MystStacks::Intro(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Intro(this));
 		break;
 	case kMakingOfStack:
-		_scriptParser = new MystStacks::MakingOf(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::MakingOf(this));
 		break;
 	case kMechanicalStack:
 		_gameState->_globals.currentAge = kMechanical;
-		_scriptParser = new MystStacks::Mechanical(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Mechanical(this));
 		break;
 	case kMystStack:
 		_gameState->_globals.currentAge = kMystLibrary;
-		_scriptParser = new MystStacks::Myst(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Myst(this));
 		break;
 	case kDemoPreviewStack:
-		_scriptParser = new MystStacks::Preview(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Preview(this));
 		break;
 	case kSeleniticStack:
 		_gameState->_globals.currentAge = kSelenitic;
-		_scriptParser = new MystStacks::Selenitic(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Selenitic(this));
 		break;
 	case kDemoSlidesStack:
 		_gameState->_globals.currentAge = kStoneship;
-		_scriptParser = new MystStacks::Slides(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Slides(this));
 		break;
 	case kStoneshipStack:
 		_gameState->_globals.currentAge = kStoneship;
-		_scriptParser = new MystStacks::Stoneship(this);
+		_scriptParser = MystScriptParserPtr(new MystStacks::Stoneship(this));
 		break;
 	default:
-		error("Unknown Myst stack");
+		error("Unknown Myst stack %d", _curStack);
 	}
 
 	// If the array is empty, add a new one. Otherwise, delete the first
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 867131a..1bd51e8 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -26,7 +26,6 @@
 #include "mohawk/console.h"
 #include "mohawk/mohawk.h"
 #include "mohawk/resource_cache.h"
-#include "mohawk/myst_scripts.h"
 #include "mohawk/video.h"
 
 #include "audio/mixer.h"
@@ -123,6 +122,7 @@ enum {
 };
 
 typedef Common::SharedPtr<MystCard> MystCardPtr;
+typedef Common::SharedPtr<MystScriptParser> MystScriptParserPtr;
 
 class MohawkEngine_Myst : public MohawkEngine {
 protected:
@@ -163,7 +163,7 @@ public:
 	MystSound *_sound;
 	MystGraphics *_gfx;
 	MystGameState *_gameState;
-	MystScriptParser *_scriptParser;
+	MystScriptParserPtr _scriptParser;
 	Common::RandomSource *_rnd;
 
 	MystArea *loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent);
@@ -199,7 +199,6 @@ public:
 private:
 	MystConsole *_console;
 	MystOptionsDialog *_optionsDialog;
-	MystScriptParser *_prevStack;
 	ResourceCache _cache;
 
 	uint16 _curStack;
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 2d2d346..5fc6cbe 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -147,7 +147,10 @@ MystAreaAction::MystAreaAction(MohawkEngine_Myst *vm, ResourceType type, Common:
 }
 
 void MystAreaAction::handleMouseUp() {
-	_vm->_scriptParser->runScript(_script, this);
+	// Keep a reference to the stack so it is not freed if a script switches to another stack
+	MystScriptParserPtr parser = _vm->_scriptParser;
+
+	parser->runScript(_script, this);
 }
 
 const Common::String MystAreaAction::describe() {
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index b389f32..dd6605b 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -24,6 +24,7 @@
 #define MYST_AREAS_H
 
 #include "mohawk/myst.h"
+#include "mohawk/myst_scripts.h"
 #include "mohawk/video.h"
 
 #include "common/rect.h"


Commit: 47ddd9c2144c236e2b3bc0dd0f8349ae8657efb7
    https://github.com/scummvm/scummvm/commit/47ddd9c2144c236e2b3bc0dd0f8349ae8657efb7
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2018-06-13T07:55:55+02:00

Commit Message:
MOHAWK: MYST: Move the current stack id to ScriptParser

Changed paths:
    engines/mohawk/console.cpp
    engines/mohawk/dialogs.cpp
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/myst_areas.cpp
    engines/mohawk/myst_card.cpp
    engines/mohawk/myst_scripts.cpp
    engines/mohawk/myst_scripts.h
    engines/mohawk/myst_stacks/channelwood.cpp
    engines/mohawk/myst_stacks/credits.cpp
    engines/mohawk/myst_stacks/demo.cpp
    engines/mohawk/myst_stacks/dni.cpp
    engines/mohawk/myst_stacks/intro.cpp
    engines/mohawk/myst_stacks/intro.h
    engines/mohawk/myst_stacks/makingof.cpp
    engines/mohawk/myst_stacks/mechanical.cpp
    engines/mohawk/myst_stacks/myst.cpp
    engines/mohawk/myst_stacks/myst.h
    engines/mohawk/myst_stacks/preview.cpp
    engines/mohawk/myst_stacks/selenitic.cpp
    engines/mohawk/myst_stacks/slides.cpp
    engines/mohawk/myst_stacks/stoneship.cpp
    engines/mohawk/myst_state.cpp
    engines/mohawk/myst_state.h


diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 2251ce0..bd0e5c7 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -100,9 +100,9 @@ bool MystConsole::Cmd_Var(int argc, const char **argv) {
 	}
 
 	if (argc > 2)
-		_vm->_scriptParser->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2]));
+		_vm->_stack->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2]));
 
-	debugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1])));
+	debugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_stack->getVar((uint16)atoi(argv[1])));
 
 	return true;
 }
@@ -138,7 +138,7 @@ static const uint16 default_start_card[12] = {
 };
 
 bool MystConsole::Cmd_CurStack(int argc, const char **argv) {
-	debugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]);
+	debugPrintf("Current Stack: %s\n", mystStackNames[_vm->_stack->getStackId()]);
 	return true;
 }
 
@@ -178,7 +178,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) {
 	else
 		card = default_start_card[stackNum - 1];
 
-	_vm->changeToStack(stackNum - 1, card, 0, 0);
+	_vm->changeToStack(static_cast<MystStack>(stackNum - 1), card, 0, 0);
 
 	return false;
 }
@@ -290,7 +290,7 @@ bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) {
 		return true;
 	}
 
-	_vm->_scriptParser->disablePersistentScripts();
+	_vm->_stack->disablePersistentScripts();
 
 	return true;
 }
@@ -331,9 +331,12 @@ bool MystConsole::Cmd_QuickTest(int argc, const char **argv) {
 
 	// Go through all the ages, all the views and click random stuff
 	for (uint i = 0; i < ARRAYSIZE(mystStackNames); i++) {
-		if (i == 2 || i == 5 || i == 9 || i == 10) continue;
-		debug("Loading stack %s", mystStackNames[i]);
-		_vm->changeToStack(i, default_start_card[i], 0, 0);
+		MystStack stackId = static_cast<MystStack>(i);
+		if (stackId == kDemoStack || stackId == kMakingOfStack
+		    || stackId == kDemoSlidesStack || stackId == kDemoPreviewStack) continue;
+
+		debug("Loading stack %s", mystStackNames[stackId]);
+		_vm->changeToStack(stackId, default_start_card[stackId], 0, 0);
 
 		Common::Array<uint16> ids = _vm->getResourceIDList(ID_VIEW);
 		for (uint j = 0; j < ids.size(); j++) {
@@ -355,9 +358,9 @@ bool MystConsole::Cmd_QuickTest(int argc, const char **argv) {
 
 			_vm->doFrame();
 
-			if (_vm->getCurStack() != i) {
+			if (_vm->_stack->getStackId() != stackId) {
 				// Clicking may have linked us to another age
-				_vm->changeToStack(i, default_start_card[i], 0, 0);
+				_vm->changeToStack(stackId, default_start_card[stackId], 0, 0);
 			}
 		}
 	}
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index b9575ce..f443315 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -209,13 +209,13 @@ void MystOptionsDialog::open() {
 	_dropPageButton->setEnabled(canDropPage);
 
 	if (_showMapButton) {
-		bool canShowMap = _vm->isInteractive() && _vm->_scriptParser->getMap();
+		bool canShowMap = _vm->isInteractive() && _vm->_stack->getMap();
 		_showMapButton->setEnabled(canShowMap);
 	}
 
 	if (_returnToMenuButton) {
 		// Return to menu button is not enabled on the menu
-		bool canReturnToMenu = _vm->isInteractive() && _vm->getCurStack() != kDemoStack;
+		bool canReturnToMenu = _vm->isInteractive() && _vm->_stack->getStackId() != kDemoStack;
 		_returnToMenuButton->setEnabled(canReturnToMenu);
 	}
 
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 3f72647..eda9da5 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -71,7 +71,6 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
 	_currentCursor = 0;
 	_mainCursor = kDefaultMystCursor;
 	_showResourceRects = false;
-	_curStack = 0;
 	_lastSaveTime = 0;
 
 	_sound = nullptr;
@@ -249,7 +248,7 @@ void MohawkEngine_Myst::playMovieBlocking(const Common::String &name, MystStack
 	waitUntilMovieEnds(video);
 }
 
-void MohawkEngine_Myst::playFlybyMovie(uint16 stack, uint16 card) {
+void MohawkEngine_Myst::playFlybyMovie(MystStack stack, uint16 card) {
 	static const uint16 kMasterpieceOnly = 0xFFFF;
 
 	// Play Flyby Entry Movie on Masterpiece Edition.
@@ -384,7 +383,7 @@ void MohawkEngine_Myst::doFrame() {
 	_video->updateMovies();
 	if (isInteractive()) {
 		_waitingOnBlockingOperation = true;
-		_scriptParser->runPersistentScripts();
+		_stack->runPersistentScripts();
 		_waitingOnBlockingOperation = false;
 	}
 
@@ -433,7 +432,7 @@ void MohawkEngine_Myst::doFrame() {
 						}
 
 						if (_needsShowMap) {
-							_scriptParser->showMap();
+							_stack->showMap();
 							_needsShowMap = false;
 						}
 
@@ -533,8 +532,8 @@ void MohawkEngine_Myst::pauseEngineIntern(bool pause) {
 	}
 }
 
-void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound) {
-	debug(2, "changeToStack(%d)", stack);
+void MohawkEngine_Myst::changeToStack(MystStack stackId, uint16 card, uint16 linkSrcSound, uint16 linkDstSound) {
+	debug(2, "changeToStack(%d)", stackId);
 
 	// Fill screen with black and empty cursor
 	_cursor->setCursor(0);
@@ -546,8 +545,8 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 	// In Myst ME, play a fullscreen flyby movie, except when loading saves.
 	// Also play a flyby when first linking to Myst.
 	if (getFeatures() & GF_ME
-			&& (_curStack != kIntroStack || (stack == kMystStack && card == 4134))) {
-		playFlybyMovie(stack, card);
+			&& ((_stack && _stack->getStackId() != kIntroStack) || (stackId == kMystStack && card == 4134))) {
+		playFlybyMovie(stackId, card);
 	}
 
 	_sound->stopBackground();
@@ -565,55 +564,53 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 		_card.reset();
 	}
 
-	_curStack = stack;
-
-	switch (_curStack) {
+	switch (stackId) {
 	case kChannelwoodStack:
 		_gameState->_globals.currentAge = kChannelwood;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Channelwood(this));
+		_stack = MystScriptParserPtr(new MystStacks::Channelwood(this));
 		break;
 	case kCreditsStack:
-		_scriptParser = MystScriptParserPtr(new MystStacks::Credits(this));
+		_stack = MystScriptParserPtr(new MystStacks::Credits(this));
 		break;
 	case kDemoStack:
 		_gameState->_globals.currentAge = kSelenitic;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Demo(this));
+		_stack = MystScriptParserPtr(new MystStacks::Demo(this));
 		break;
 	case kDniStack:
 		_gameState->_globals.currentAge = kDni;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Dni(this));
+		_stack = MystScriptParserPtr(new MystStacks::Dni(this));
 		break;
 	case kIntroStack:
-		_scriptParser = MystScriptParserPtr(new MystStacks::Intro(this));
+		_stack = MystScriptParserPtr(new MystStacks::Intro(this));
 		break;
 	case kMakingOfStack:
-		_scriptParser = MystScriptParserPtr(new MystStacks::MakingOf(this));
+		_stack = MystScriptParserPtr(new MystStacks::MakingOf(this));
 		break;
 	case kMechanicalStack:
 		_gameState->_globals.currentAge = kMechanical;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Mechanical(this));
+		_stack = MystScriptParserPtr(new MystStacks::Mechanical(this));
 		break;
 	case kMystStack:
 		_gameState->_globals.currentAge = kMystLibrary;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Myst(this));
+		_stack = MystScriptParserPtr(new MystStacks::Myst(this));
 		break;
 	case kDemoPreviewStack:
-		_scriptParser = MystScriptParserPtr(new MystStacks::Preview(this));
+		_stack = MystScriptParserPtr(new MystStacks::Preview(this));
 		break;
 	case kSeleniticStack:
 		_gameState->_globals.currentAge = kSelenitic;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Selenitic(this));
+		_stack = MystScriptParserPtr(new MystStacks::Selenitic(this));
 		break;
 	case kDemoSlidesStack:
 		_gameState->_globals.currentAge = kStoneship;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Slides(this));
+		_stack = MystScriptParserPtr(new MystStacks::Slides(this));
 		break;
 	case kStoneshipStack:
 		_gameState->_globals.currentAge = kStoneship;
-		_scriptParser = MystScriptParserPtr(new MystStacks::Stoneship(this));
+		_stack = MystScriptParserPtr(new MystStacks::Stoneship(this));
 		break;
 	default:
-		error("Unknown Myst stack %d", _curStack);
+		error("Unknown Myst stack %d", stackId);
 	}
 
 	// If the array is empty, add a new one. Otherwise, delete the first
@@ -625,8 +622,8 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 		_mhk[0] = new MohawkArchive();
 	}
 
-	if (!_mhk[0]->openFile(mystFiles[_curStack]))
-		error("Could not open %s", mystFiles[_curStack]);
+	if (!_mhk[0]->openFile(mystFiles[stackId]))
+		error("Could not open %s", mystFiles[stackId]);
 
 	// Clear the resource cache and the image cache
 	_cache.clear();
@@ -641,7 +638,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
 void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
 	debug(2, "changeToCard(%d)", card);
 
-	_scriptParser->disablePersistentScripts();
+	_stack->disablePersistentScripts();
 
 	_video->stopVideos();
 
@@ -698,7 +695,7 @@ void MohawkEngine_Myst::refreshCursor() {
 }
 
 void MohawkEngine_Myst::redrawResource(MystAreaImageSwitch *resource, bool update) {
-	resource->drawConditionalDataToScreen(_scriptParser->getVar(resource->getImageSwitchVar()), update);
+	resource->drawConditionalDataToScreen(_stack->getVar(resource->getImageSwitchVar()), update);
 }
 
 MystArea *MohawkEngine_Myst::loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent) {
@@ -772,7 +769,7 @@ bool MohawkEngine_Myst::hasGameSaveSupport() const {
 }
 
 bool MohawkEngine_Myst::isInteractive() {
-	return !_scriptParser->isScriptRunning() && !_waitingOnBlockingOperation;
+	return !_stack->isScriptRunning() && !_waitingOnBlockingOperation;
 }
 
 bool MohawkEngine_Myst::canLoadGameStateCurrently() {
@@ -798,7 +795,7 @@ bool MohawkEngine_Myst::canSaveGameStateCurrently() {
 	}
 
 	// There's a limited number of stacks the game can save in
-	switch (_curStack) {
+	switch (_stack->getStackId()) {
 	case kChannelwoodStack:
 	case kDniStack:
 	case kMechanicalStack:
@@ -806,9 +803,9 @@ bool MohawkEngine_Myst::canSaveGameStateCurrently() {
 	case kSeleniticStack:
 	case kStoneshipStack:
 		return true;
+	default:
+		return false;
 	}
-
-	return false;
 }
 
 void MohawkEngine_Myst::dropPage() {
@@ -825,7 +822,7 @@ void MohawkEngine_Myst::dropPage() {
 
 	// Redraw page area
 	if (whitePage && _gameState->_globals.currentAge == kMystLibrary) {
-		_scriptParser->toggleVar(41);
+		_stack->toggleVar(41);
 		_card->redrawArea(41);
 	} else if (bluePage) {
 		if (page == kBlueFirePlacePage) {
@@ -899,7 +896,7 @@ void MohawkEngine_Myst::applySoundBlock(const MystSoundBlock &block) {
 	uint16 soundActionVolume = 0;
 
 	if (block.sound == kMystSoundActionConditional) {
-		uint16 soundVarValue = _scriptParser->getVar(block.soundVar);
+		uint16 soundVarValue = _stack->getVar(block.soundVar);
 		if (soundVarValue >= block.soundList.size())
 			warning("Conditional sound variable outside range");
 		else {
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 1bd51e8..d626221 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -136,11 +136,10 @@ public:
 	Common::Array<uint16> getResourceIDList(uint32 type) const;
 	void cachePreload(uint32 tag, uint16 id);
 
-	void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound);
+	void changeToStack(MystStack stackId, uint16 card, uint16 linkSrcSound, uint16 linkDstSound);
 	void changeToCard(uint16 card, TransitionType transition);
 	MystCard *getCard() { return _card.get(); };
 	MystCardPtr getCardPtr() { return _card; };
-	uint16 getCurStack() { return _curStack; }
 	void setMainCursor(uint16 cursor);
 	uint16 getMainCursor() { return _mainCursor; }
 	void refreshCursor();
@@ -163,7 +162,7 @@ public:
 	MystSound *_sound;
 	MystGraphics *_gfx;
 	MystGameState *_gameState;
-	MystScriptParserPtr _scriptParser;
+	MystScriptParserPtr _stack;
 	Common::RandomSource *_rnd;
 
 	MystArea *loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent);
@@ -175,7 +174,7 @@ public:
 	VideoEntryPtr playMovie(const Common::String &name, MystStack stack);
 	VideoEntryPtr findVideo(const Common::String &name, MystStack stack);
 	void playMovieBlocking(const Common::String &name, MystStack stack, uint16 x, uint16 y);
-	void playFlybyMovie(uint16 stack, uint16 card);
+	void playFlybyMovie(MystStack stack, uint16 card);
 	void waitUntilMovieEnds(const VideoEntryPtr &video);
 
 	void playSoundBlocking(uint16 id);
@@ -201,7 +200,6 @@ private:
 	MystOptionsDialog *_optionsDialog;
 	ResourceCache _cache;
 
-	uint16 _curStack;
 	MystCardPtr _card;
 	uint32 _lastSaveTime;
 
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 5fc6cbe..d03c78a 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -94,8 +94,8 @@ void MystArea::handleMouseUp() {
 		break;
 	}
 
-	_vm->_scriptParser->setInvokingResource(this);
-	_vm->_scriptParser->runOpcode(opcode, 0);
+	_vm->_stack->setInvokingResource(this);
+	_vm->_stack->runOpcode(opcode, 0);
 }
 
 bool MystArea::canBecomeActive() {
@@ -104,7 +104,7 @@ bool MystArea::canBecomeActive() {
 
 bool MystArea::unreachableZipDest() {
 	return (_flags & kMystZipModeEnableFlag)
-			&& !_vm->_gameState->isReachableZipDest(_vm->getCurStack() , _dest);
+			&& !_vm->_gameState->isReachableZipDest(_vm->_stack->getStackId() , _dest);
 }
 
 bool MystArea::isEnabled() {
@@ -143,14 +143,14 @@ MystAreaAction::MystAreaAction(MohawkEngine_Myst *vm, ResourceType type, Common:
 		MystArea(vm, type, rlstStream, parent) {
 	debugC(kDebugResource, "\tResource Type 5 Script:");
 
-	_script = vm->_scriptParser->readScript(rlstStream, kMystScriptNormal);
+	_script = vm->_stack->readScript(rlstStream, kMystScriptNormal);
 }
 
 void MystAreaAction::handleMouseUp() {
 	// Keep a reference to the stack so it is not freed if a script switches to another stack
-	MystScriptParserPtr parser = _vm->_scriptParser;
+	MystScriptParserPtr stack = _vm->_stack;
 
-	parser->runScript(_script, this);
+	stack->runScript(_script, this);
 }
 
 const Common::String MystAreaAction::describe() {
@@ -160,7 +160,7 @@ const Common::String MystAreaAction::describe() {
 		desc += " ops:";
 
 		for (uint i = 0; i < _script.size(); i++)
-			desc += " " + _vm->_scriptParser->getOpcodeDesc(_script[i].opcode);
+			desc += " " + _vm->_stack->getOpcodeDesc(_script[i].opcode);
 	}
 
 	return desc;
@@ -320,7 +320,7 @@ void MystAreaActionSwitch::doSwitch(AreaHandler handler) {
 		else if (_subResources.size() != 0)
 			warning("Action switch resource with _numSubResources of %d, but no control variable", _subResources.size());
 	} else {
-		uint16 varValue = _vm->_scriptParser->getVar(_actionSwitchVar);
+		uint16 varValue = _vm->_stack->getVar(_actionSwitchVar);
 
 		if (_subResources.size() == 1 && varValue != 0)
 			(_subResources[0]->*handler)();
@@ -404,7 +404,7 @@ void MystAreaImageSwitch::drawDataToScreen() {
 		} else if (_subImages.size() != 0)
 			warning("Image Switch resource with _numSubImages of %d, but no control variable", _subImages.size());
 	} else {
-		uint16 varValue = _vm->_scriptParser->getVar(_imageSwitchVar);
+		uint16 varValue = _vm->_stack->getVar(_imageSwitchVar);
 
 		if (_subImages.size() == 1 && varValue != 0) {
 			subImageId = 0;
@@ -586,7 +586,7 @@ void MystAreaSlider::handleMouseUp() {
 			value = _pos.x;
 	}
 
-	_vm->_scriptParser->setVarValue(_imageSwitchVar, value);
+	_vm->_stack->setVarValue(_imageSwitchVar, value);
 
 	MystAreaDrag::handleMouseUp();
 }
@@ -714,32 +714,32 @@ void MystAreaDrag::handleMouseDown() {
 	const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
 	setPositionClipping(mouse, _pos);
 
-	_vm->_scriptParser->setInvokingResource(this);
-	_vm->_scriptParser->runOpcode(_mouseDownOpcode, _imageSwitchVar);
+	_vm->_stack->setInvokingResource(this);
+	_vm->_stack->runOpcode(_mouseDownOpcode, _imageSwitchVar);
 }
 
 void MystAreaDrag::handleMouseUp() {
 	const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
 	setPositionClipping(mouse, _pos);
 
-	_vm->_scriptParser->setInvokingResource(this);
-	_vm->_scriptParser->runOpcode(_mouseUpOpcode, _imageSwitchVar);
+	_vm->_stack->setInvokingResource(this);
+	_vm->_stack->runOpcode(_mouseUpOpcode, _imageSwitchVar);
 }
 
 void MystAreaDrag::handleMouseDrag() {
 	const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
 	setPositionClipping(mouse, _pos);
 
-	_vm->_scriptParser->setInvokingResource(this);
-	_vm->_scriptParser->runOpcode(_mouseDragOpcode, _imageSwitchVar);
+	_vm->_stack->setInvokingResource(this);
+	_vm->_stack->runOpcode(_mouseDragOpcode, _imageSwitchVar);
 }
 
 const Common::String MystAreaDrag::describe() {
 	return Common::String::format("%s down: %s drag: %s up: %s",
 			MystAreaImageSwitch::describe().c_str(),
-			_vm->_scriptParser->getOpcodeDesc(_mouseDownOpcode).c_str(),
-			_vm->_scriptParser->getOpcodeDesc(_mouseDragOpcode).c_str(),
-			_vm->_scriptParser->getOpcodeDesc(_mouseUpOpcode).c_str());
+			_vm->_stack->getOpcodeDesc(_mouseDownOpcode).c_str(),
+			_vm->_stack->getOpcodeDesc(_mouseDragOpcode).c_str(),
+			_vm->_stack->getOpcodeDesc(_mouseUpOpcode).c_str());
 }
 
 void MystAreaDrag::setPositionClipping(const Common::Point &mouse, Common::Point &dest) {
@@ -836,13 +836,13 @@ MystAreaHover::MystAreaHover(MohawkEngine_Myst *vm, ResourceType type, Common::S
 void MystAreaHover::handleMouseEnter() {
 	// Pass along the enter opcode to the script parser
 	// The variable to use is stored in the dest field
-	_vm->_scriptParser->runOpcode(_enterOpcode, _dest);
+	_vm->_stack->runOpcode(_enterOpcode, _dest);
 }
 
 void MystAreaHover::handleMouseLeave() {
 	// Pass along the leave opcode (with no parameters) to the script parser
 	// The variable to use is stored in the dest field
-	_vm->_scriptParser->runOpcode(_leaveOpcode, _dest);
+	_vm->_stack->runOpcode(_leaveOpcode, _dest);
 }
 
 void MystAreaHover::handleMouseUp() {
@@ -854,8 +854,8 @@ void MystAreaHover::handleMouseUp() {
 const Common::String MystAreaHover::describe() {
 	return Common::String::format("%s enter: %s leave: %s",
 			MystArea::describe().c_str(),
-			_vm->_scriptParser->getOpcodeDesc(_enterOpcode).c_str(),
-			_vm->_scriptParser->getOpcodeDesc(_leaveOpcode).c_str());
+			_vm->_stack->getOpcodeDesc(_enterOpcode).c_str(),
+			_vm->_stack->getOpcodeDesc(_leaveOpcode).c_str());
 }
 
 } // End of namespace Mohawk
diff --git a/engines/mohawk/myst_card.cpp b/engines/mohawk/myst_card.cpp
index 71b546c..a587202 100644
--- a/engines/mohawk/myst_card.cpp
+++ b/engines/mohawk/myst_card.cpp
@@ -49,7 +49,7 @@ void MystCard::enter() {
 	_vm->applySoundBlock(_soundBlock);
 
 	if (_flags & kMystZipDestination)
-		_vm->_gameState->addZipDest(_vm->getCurStack(), _id);
+		_vm->_gameState->addZipDest(_vm->_stack->getStackId(), _id);
 
 	// Run the entrance script (if present)
 	runInitScript();
@@ -184,7 +184,7 @@ void MystCard::loadView() {
 	// Precache Image Block data
 	if (!_conditionalImages.empty()) {
 		for (uint16 i = 0; i < _conditionalImages.size(); i++) {
-			uint16 value = _vm->_scriptParser->getVar(_conditionalImages[i].var);
+			uint16 value = _vm->_stack->getVar(_conditionalImages[i].var);
 			_vm->cachePreload(cacheImageType, _conditionalImages[i].values[value]);
 		}
 	} else {
@@ -195,7 +195,7 @@ void MystCard::loadView() {
 	if (_soundBlock.sound > 0)
 		_vm->cachePreload(ID_MSND, _soundBlock.sound);
 	else if (_soundBlock.sound == kMystSoundActionConditional) {
-		uint16 value = _vm->_scriptParser->getVar(_soundBlock.soundVar);
+		uint16 value = _vm->_stack->getVar(_soundBlock.soundVar);
 		if (_soundBlock.soundList[value].action > 0) {
 			_vm->cachePreload(ID_MSND, _soundBlock.soundList[value].action);
 		}
@@ -207,7 +207,7 @@ void MystCard::loadView() {
 		int16 id;
 		if (_scriptResources[i].type == kResourceSwitch) {
 			type = _scriptResources[i].switchResourceType;
-			uint16 value = _vm->_scriptParser->getVar(_scriptResources[i].switchVar);
+			uint16 value = _vm->_stack->getVar(_scriptResources[i].switchVar);
 			id = _scriptResources[i].switchResourceIds[value];
 		} else {
 			type = _scriptResources[i].type;
@@ -296,7 +296,7 @@ uint16 MystCard::getBackgroundImageId() {
 		imageToDraw = _mainImage;
 	else {
 		for (uint16 i = 0; i < _conditionalImages.size(); i++) {
-			uint16 varValue = _vm->_scriptParser->getVar(_conditionalImages[i].var);
+			uint16 varValue = _vm->_stack->getVar(_conditionalImages[i].var);
 			if (varValue < _conditionalImages[i].values.size())
 				imageToDraw = _conditionalImages[i].values[varValue];
 		}
@@ -318,10 +318,10 @@ void MystCard::runInitScript() {
 	debugC(kDebugINIT, "Running INIT script");
 
 	Common::SeekableReadStream *initStream = _vm->getResource(ID_INIT, _initScriptId);
-	MystScript script = _vm->_scriptParser->readScript(initStream, kMystScriptInit);
+	MystScript script = _vm->_stack->readScript(initStream, kMystScriptInit);
 	delete initStream;
 
-	_vm->_scriptParser->runScript(script);
+	_vm->_stack->runScript(script);
 }
 
 void MystCard::runExitScript() {
@@ -333,10 +333,10 @@ void MystCard::runExitScript() {
 	debugC(kDebugEXIT, "Running EXIT script");
 
 	Common::SeekableReadStream *exitStream = _vm->getResource(ID_EXIT, _exitScriptId);
-	MystScript script = _vm->_scriptParser->readScript(exitStream, kMystScriptExit);
+	MystScript script = _vm->_stack->readScript(exitStream, kMystScriptExit);
 	delete exitStream;
 
-	_vm->_scriptParser->runScript(script);
+	_vm->_stack->runScript(script);
 }
 
 void MystCard::drawResourceRects() {
@@ -406,7 +406,7 @@ int16 MystCard::getActiveResourceCursor() {
 	for (uint16 i = 0; i < _cursorHints.size(); i++) {
 		if (_activeResource && _resources[_cursorHints[i].id] == _activeResource && _activeResource->isEnabled()) {
 			if (_cursorHints[i].cursor == -1) {
-				uint16 var_value = _vm->_scriptParser->getVar(_cursorHints[i].variableHint.var);
+				uint16 var_value = _vm->_stack->getVar(_cursorHints[i].variableHint.var);
 
 				if (var_value >= _cursorHints[i].variableHint.values.size())
 					warning("Variable %d Out of Range in variable HINT Resource %d", _cursorHints[i].variableHint.var,
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index 9403beb..a2a0c5e 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -44,7 +44,7 @@ MystScriptEntry::MystScriptEntry() {
 	opcode = 0;
 }
 
-const uint8 MystScriptParser::_stackMap[11] = {
+const MystStack MystScriptParser::_stackMap[11] = {
 	kSeleniticStack,
 	kStoneshipStack,
 	kMystStack,
@@ -74,8 +74,9 @@ const uint16 MystScriptParser::_startCard[11] = {
 
 // NOTE: Credits Start Card is 10000
 
-MystScriptParser::MystScriptParser(MohawkEngine_Myst *vm) :
+MystScriptParser::MystScriptParser(MohawkEngine_Myst *vm, MystStack stackId) :
 		_vm(vm),
+		_stackId(stackId),
 		_globals(vm->_gameState->_globals) {
 	setupCommonOpcodes();
 	_invokingResource = nullptr;
diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h
index f89a76e..38be09c 100644
--- a/engines/mohawk/myst_scripts.h
+++ b/engines/mohawk/myst_scripts.h
@@ -60,7 +60,7 @@ typedef Common::Array<MystScriptEntry> MystScript;
 
 class MystScriptParser {
 public:
-	explicit MystScriptParser(MohawkEngine_Myst *vm);
+	MystScriptParser(MohawkEngine_Myst *vm, MystStack stackId);
 	virtual ~MystScriptParser();
 
 	void runScript(const MystScript &script, MystArea *invokingResource = nullptr);
@@ -83,6 +83,7 @@ public:
 	virtual void toggleVar(uint16 var);
 	virtual bool setVarValue(uint16 var, uint16 value);
 
+	MystStack getStackId() const { return _stackId; }
 	virtual uint16 getMap() { return 0; }
 	void showMap();
 
@@ -166,7 +167,7 @@ protected:
 	int16 _tempVar; // Generic temp var used by the scripts
 	uint32 _startTime; // Generic start time used by the scripts
 
-	static const uint8 _stackMap[];
+	static const MystStack _stackMap[];
 	static const uint16 _startCard[];
 
 	void setupCommonOpcodes();
@@ -188,6 +189,8 @@ private:
 	MystArea *_invokingResource;
 	int32 _scriptNestingLevel;
 
+	const MystStack _stackId;
+
 	Common::String describeCommand(const MystOpcode &command, uint16 var, const ArgumentsArray &args);
 };
 
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index d1281fa..7e4e5e1 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -38,7 +38,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Channelwood::Channelwood(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+		MystScriptParser(vm, kChannelwoodStack),
 		_state(vm->_gameState->_channelwood),
 		_valveVar(0),
 		_siriusDrawerState(0),
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index 135aded..423dc9c 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -37,7 +37,7 @@ namespace MystStacks {
 // NOTE: Credits Start Card is 10000
 
 Credits::Credits(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+		MystScriptParser(vm, kCreditsStack),
 		_creditsRunning(false),
 		_curImage(0) {
 	setupOpcodes();
diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp
index d2ba70c..b98a16d 100644
--- a/engines/mohawk/myst_stacks/demo.cpp
+++ b/engines/mohawk/myst_stacks/demo.cpp
@@ -31,7 +31,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Demo::Demo(MohawkEngine_Myst *vm) :
-		Intro(vm),
+		Intro(vm, kDemoStack),
 		_returnToMenuRunning(false),
 		_returnToMenuStep(0),
 		_returnToMenuNextTime(0) {
@@ -86,7 +86,7 @@ void Demo::returnToMenu_run() {
 	if (time < _returnToMenuNextTime)
 		return;
 
-	switch (_returnToMenuStep){
+	switch (_returnToMenuStep) {
 	case 0:
 		_vm->_gfx->fadeToBlack();
 		_vm->changeToCard(2003, kNoTransition);
diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp
index a38b5d3..bb1adf2 100644
--- a/engines/mohawk/myst_stacks/dni.cpp
+++ b/engines/mohawk/myst_stacks/dni.cpp
@@ -34,7 +34,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Dni::Dni(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+		MystScriptParser(vm, kDniStack),
 		_notSeenAtrus(true),
 		_atrusRunning(false),
 		_waitForLoop(false),
diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp
index 9e03713..f6a7987 100644
--- a/engines/mohawk/myst_stacks/intro.cpp
+++ b/engines/mohawk/myst_stacks/intro.cpp
@@ -31,8 +31,8 @@
 namespace Mohawk {
 namespace MystStacks {
 
-Intro::Intro(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+Intro::Intro(MohawkEngine_Myst *vm, MystStack stackId) :
+		MystScriptParser(vm, stackId),
 		_introMoviesRunning(false),
 		_introStep(0),
 		_linkBookRunning(false),
diff --git a/engines/mohawk/myst_stacks/intro.h b/engines/mohawk/myst_stacks/intro.h
index ec78199..06a1e03 100644
--- a/engines/mohawk/myst_stacks/intro.h
+++ b/engines/mohawk/myst_stacks/intro.h
@@ -38,7 +38,7 @@ namespace MystStacks {
 
 class Intro : public MystScriptParser {
 public:
-	explicit Intro(MohawkEngine_Myst *vm);
+	explicit Intro(MohawkEngine_Myst *vm, MystStack stackId = kIntroStack);
 	~Intro() override;
 
 	void disablePersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/makingof.cpp b/engines/mohawk/myst_stacks/makingof.cpp
index 4e0ce51..7e57f98 100644
--- a/engines/mohawk/myst_stacks/makingof.cpp
+++ b/engines/mohawk/myst_stacks/makingof.cpp
@@ -31,7 +31,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 MakingOf::MakingOf(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm) {
+		MystScriptParser(vm, kMakingOfStack) {
 	setupOpcodes();
 }
 
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index 495f40b..5c0e273 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -37,7 +37,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Mechanical::Mechanical(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+		MystScriptParser(vm, kMechanicalStack),
 		_state(vm->_gameState->_mechanical) {
 	setupOpcodes();
 
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index a3e5685..03f4a3f 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -37,8 +37,8 @@
 namespace Mohawk {
 namespace MystStacks {
 
-Myst::Myst(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+Myst::Myst(MohawkEngine_Myst *vm, MystStack stackId) :
+		MystScriptParser(vm, stackId),
 		_state(_vm->_gameState->_myst),
 		_towerRotationCenter(Common::Point(383, 124)) {
 	setupOpcodes();
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
index ee89af1..3739630 100644
--- a/engines/mohawk/myst_stacks/myst.h
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -37,7 +37,7 @@ namespace MystStacks {
 
 class Myst : public MystScriptParser {
 public:
-	explicit Myst(MohawkEngine_Myst *vm);
+	explicit Myst(MohawkEngine_Myst *vm, MystStack stackId = kMystStack);
 	~Myst() override;
 
 	void disablePersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index 348a195..8348c45 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -35,7 +35,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Preview::Preview(MohawkEngine_Myst *vm) :
-		Myst(vm) {
+		Myst(vm, kDemoPreviewStack) {
 	setupOpcodes();
 	_vm->_cursor->hideCursor();
 
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index 8d95cb5..4ef7828 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -37,7 +37,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Selenitic::Selenitic(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+		MystScriptParser(vm, kSeleniticStack),
 		_state(vm->_gameState->_selenitic) {
 	setupOpcodes();
 
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index 25d5cf4..7524dde 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -34,7 +34,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Slides::Slides(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm) {
+		MystScriptParser(vm, kDemoSlidesStack) {
 	setupOpcodes();
 
 	_vm->_cursor->hideCursor();
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 0ae78c1..3791972 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -38,7 +38,7 @@ namespace Mohawk {
 namespace MystStacks {
 
 Stoneship::Stoneship(MohawkEngine_Myst *vm) :
-		MystScriptParser(vm),
+		MystScriptParser(vm, kStoneshipStack),
 		_state(vm->_gameState->_stoneship) {
 	setupOpcodes();
 
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index c65ece5..a0df54f 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -532,7 +532,7 @@ void MystGameState::deleteSave(int slot) {
 	g_system->getSavefileManager()->removeSavefile(metadataFilename);
 }
 
-void MystGameState::addZipDest(uint16 stack, uint16 view) {
+void MystGameState::addZipDest(MystStack stack, uint16 view) {
 	ZipDests *zipDests = nullptr;
 
 	// The demo has no zip dest storage
@@ -576,7 +576,7 @@ void MystGameState::addZipDest(uint16 stack, uint16 view) {
 		(*zipDests)[firstEmpty] = view;
 }
 
-bool MystGameState::isReachableZipDest(uint16 stack, uint16 view) {
+bool MystGameState::isReachableZipDest(MystStack stack, uint16 view) {
 	// Zip mode enabled
 	if (!_globals.zipMode)
 		return false;
diff --git a/engines/mohawk/myst_state.h b/engines/mohawk/myst_state.h
index 28bbf60..7dc75c7 100644
--- a/engines/mohawk/myst_state.h
+++ b/engines/mohawk/myst_state.h
@@ -113,8 +113,8 @@ public:
 	bool isAutoSaveAllowed();
 	static void deleteSave(int slot);
 
-	void addZipDest(uint16 stack, uint16 view);
-	bool isReachableZipDest(uint16 stack, uint16 view);
+	void addZipDest(MystStack stack, uint16 view);
+	bool isReachableZipDest(MystStack stack, uint16 view);
 
 	/* 8 Game Global Variables :
 	   0 = Unknown - Fixed at 2


Commit: 2de359f23de43db2ab3e46f55c0bb5a880ea8441
    https://github.com/scummvm/scummvm/commit/2de359f23de43db2ab3e46f55c0bb5a880ea8441
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2018-06-13T08:00:29+02:00

Commit Message:
MOHAWK: MYST: Make the scripts time accounting pause safe

Changed paths:
    engines/mohawk/myst_stacks/credits.cpp
    engines/mohawk/myst_stacks/demo.cpp
    engines/mohawk/myst_stacks/dni.cpp
    engines/mohawk/myst_stacks/mechanical.cpp
    engines/mohawk/myst_stacks/myst.cpp
    engines/mohawk/myst_stacks/preview.cpp
    engines/mohawk/myst_stacks/selenitic.cpp
    engines/mohawk/myst_stacks/slides.cpp
    engines/mohawk/myst_stacks/stoneship.cpp


diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index 423dc9c..2b8cbd0 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -62,7 +62,7 @@ void Credits::runPersistentScripts() {
 	if (!_creditsRunning)
 		return;
 
-	if (_vm->_system->getMillis() - _startTime >= 7 * 1000) {
+	if (_vm->getTotalPlayTime() - _startTime >= 7 * 1000) {
 		_curImage++;
 
 		// After the 6th image has shown, it's time to quit
@@ -75,7 +75,7 @@ void Credits::runPersistentScripts() {
 		_vm->getCard()->drawBackground();
 		_vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333));
 
-		_startTime = _vm->_system->getMillis();
+		_startTime = _vm->getTotalPlayTime();
 	}
 }
 
@@ -98,7 +98,7 @@ void Credits::o_runCredits(uint16 var, const ArgumentsArray &args) {
 	// Activate the credits
 	_creditsRunning = true;
 	_curImage = 0;
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 }
 
 } // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp
index b98a16d..400ab13 100644
--- a/engines/mohawk/myst_stacks/demo.cpp
+++ b/engines/mohawk/myst_stacks/demo.cpp
@@ -81,7 +81,7 @@ void Demo::o_fadeToBlack(uint16 var, const ArgumentsArray &args) {
 }
 
 void Demo::returnToMenu_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time < _returnToMenuNextTime)
 		return;
@@ -109,7 +109,7 @@ void Demo::returnToMenu_run() {
 
 void Demo::o_returnToMenu_init(uint16 var, const ArgumentsArray &args) {
 	// Used on Card 2001, 2002 and 2003
-	_returnToMenuNextTime = _vm->_system->getMillis() + 5000;
+	_returnToMenuNextTime = _vm->getTotalPlayTime() + 5000;
 	_returnToMenuRunning = true;
 }
 
diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp
index bb1adf2..0678f20 100644
--- a/engines/mohawk/myst_stacks/dni.cpp
+++ b/engines/mohawk/myst_stacks/dni.cpp
@@ -115,12 +115,12 @@ void Dni::o_handPage(uint16 var, const ArgumentsArray &args) {
 
 		_atrusLeft = true;
 		_waitForLoop = false;
-		_atrusLeftTime = _vm->_system->getMillis();
+		_atrusLeftTime = _vm->getTotalPlayTime();
 	}
 }
 
 void Dni::atrusLeft_run() {
-	if (_vm->_system->getMillis() > _atrusLeftTime + 63333) {
+	if (_vm->getTotalPlayTime() > _atrusLeftTime + 63333) {
 		_video = "atrus2";
 		_videoPos = Common::Point(215, 77);
 		VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index 5c0e273..2481ca6 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -309,7 +309,7 @@ void Mechanical::o_birdCrankStart(uint16 var, const ArgumentsArray &args) {
 	_vm->_sound->playEffect(crankSoundId, true);
 
 	_birdSingEndTime = 0;
-	_birdCrankStartTime = _vm->_system->getMillis();
+	_birdCrankStartTime = _vm->getTotalPlayTime();
 
 	MystAreaVideo *crankMovie = static_cast<MystAreaVideo *>(crank->getSubResource(0));
 	crankMovie->playMovie();
@@ -324,7 +324,7 @@ void Mechanical::o_birdCrankStop(uint16 var, const ArgumentsArray &args) {
 	uint16 crankSoundId = crank->getList2(1);
 	_vm->_sound->playEffect(crankSoundId);
 
-	_birdSingEndTime = 2 * _vm->_system->getMillis() - _birdCrankStartTime;
+	_birdSingEndTime = 2 * _vm->getTotalPlayTime() - _birdCrankStartTime;
 	_birdSinging = true;
 
 	_bird->playMovie();
@@ -572,11 +572,11 @@ void Mechanical::o_elevatorGoMiddle(uint16 var, const ArgumentsArray &args) {
 	_elevatorTopCounter = 5;
 	_elevatorGoingMiddle = true;
 	_elevatorInCabin = true;
-	_elevatorNextTime = _vm->_system->getMillis() + 1000;
+	_elevatorNextTime = _vm->getTotalPlayTime() + 1000;
 }
 
 void Mechanical::elevatorGoMiddle_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 	if (_elevatorNextTime < time) {
 		_elevatorNextTime = time + 1000;
 		_elevatorTopCounter--;
@@ -706,7 +706,7 @@ void Mechanical::o_fortressStaircase_init(uint16 var, const ArgumentsArray &args
 
 void Mechanical::birdSing_run() {
 	// Used for Card 6220 (Sirrus' Mechanical Bird)
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 	if (_birdSingEndTime < time) {
 		_bird->pauseMovie(true);
 		_vm->_sound->stopEffect();
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index 03f4a3f..5a64b8f 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -108,7 +108,7 @@ Myst::Myst(MohawkEngine_Myst *vm, MystStack stackId) :
 	}
 
 	_butterfliesMoviePlayed = false;
-	_state.treeLastMoveTime = _vm->_system->getMillis();
+	_state.treeLastMoveTime = _vm->getTotalPlayTime();
 
 	_rocketPianoSound = 0;
 	_rocketSlider1 = nullptr;
@@ -1342,7 +1342,7 @@ void Myst::o_imagerEraseButton(uint16 var, const ArgumentsArray &args) {
 
 	if (_imagerValidationStep == 0) {
 		// Validation script is not running, run it
-		_startTime = _vm->_system->getMillis() + 100;
+		_startTime = _vm->getTotalPlayTime() + 100;
 		_imagerValidationRunning = true;
 		return;
 	} else if (_imagerValidationStep < 7) {
@@ -1380,7 +1380,7 @@ void Myst::o_imagerEraseButton(uint16 var, const ArgumentsArray &args) {
 }
 
 void Myst::imagerValidation_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _startTime) {
 		_imagerRedButton->drawConditionalDataToScreen(1);
@@ -1620,7 +1620,7 @@ void Myst::observatoryMonthChangeStart(bool increase) {
 	observatoryIncrementMonth(_observatoryIncrement);
 
 	// Start persistent script
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_observatoryMonthChanging = true;
 }
 
@@ -1645,7 +1645,7 @@ void Myst::observatoryIncrementMonth(int16 increment) {
 }
 
 void Myst::observatoryMonthChange_run() {
-	if (_startTime + 500 < _vm->_system->getMillis())
+	if (_startTime + 500 < _vm->getTotalPlayTime())
 		observatoryIncrementMonth(_observatoryIncrement);
 }
 
@@ -1686,7 +1686,7 @@ void Myst::observatoryDayChangeStart(bool increase) {
 	observatoryIncrementDay(_observatoryIncrement);
 
 	// Start persistent script
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_observatoryDayChanging = true;
 }
 
@@ -1712,7 +1712,7 @@ void Myst::observatoryIncrementDay(int16 increment) {
 }
 
 void Myst::observatoryDayChange_run() {
-	if (_startTime + 500 < _vm->_system->getMillis())
+	if (_startTime + 500 < _vm->getTotalPlayTime())
 		observatoryIncrementDay(_observatoryIncrement);
 }
 
@@ -1745,7 +1745,7 @@ void Myst::observatoryYearChangeStart(bool increase) {
 	observatoryIncrementYear(_observatoryIncrement);
 
 	// Start persistent script
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_observatoryYearChanging = true;
 }
 
@@ -1773,7 +1773,7 @@ void Myst::observatoryIncrementYear(int16 increment) {
 }
 
 void Myst::observatoryYearChange_run() {
-	if (_startTime + 500 < _vm->_system->getMillis())
+	if (_startTime + 500 < _vm->getTotalPlayTime())
 		observatoryIncrementYear(_observatoryIncrement);
 }
 
@@ -1806,7 +1806,7 @@ void Myst::observatoryTimeChangeStart(bool increase) {
 	observatoryIncrementTime(_observatoryIncrement);
 
 	// Start persistent script
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_observatoryTimeChanging = true;
 }
 
@@ -1839,7 +1839,7 @@ void Myst::observatoryIncrementTime(int16 increment) {
 }
 
 void Myst::observatoryTimeChange_run() {
-	if (_startTime + 500 < _vm->_system->getMillis())
+	if (_startTime + 500 < _vm->getTotalPlayTime())
 		observatoryIncrementTime(_observatoryIncrement);
 }
 
@@ -1853,9 +1853,9 @@ void Myst::o_observatoryGoButton(uint16 var, const ArgumentsArray &args) {
 		_vm->_sound->playEffect(soundId);
 
 		int16 distance = _state.observatoryYearTarget - _state.observatoryYearSetting;
-		uint32 end = _vm->_system->getMillis() + 32 * ABS(distance) / 50 + 800;
+		uint32 end = _vm->getTotalPlayTime() + 32 * ABS(distance) / 50 + 800;
 
-		while (end > _vm->_system->getMillis()) {
+		while (end > _vm->getTotalPlayTime()) {
 			_vm->wait(50);
 
 			observatoryUpdateVisualizer(_vm->_rnd->getRandomNumber(409), _vm->_rnd->getRandomNumber(409));
@@ -1970,7 +1970,7 @@ void Myst::o_boilerLightPilot(uint16 var, const ArgumentsArray &args) {
 		boilerFireUpdate(false);
 
 		// Put out match
-		_matchGoOutTime = _vm->_system->getMillis();
+		_matchGoOutTime = _vm->getTotalPlayTime();
 
 		if (_state.cabinValvePosition > 0)
 			_vm->_sound->playBackground(8098, 49152);
@@ -1981,7 +1981,7 @@ void Myst::o_boilerLightPilot(uint16 var, const ArgumentsArray &args) {
 			Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay);
 			boilerResetGauge(rate);
 
-			_state.treeLastMoveTime = _vm->_system->getMillis();
+			_state.treeLastMoveTime = _vm->getTotalPlayTime();
 		}
 	}
 }
@@ -2018,7 +2018,7 @@ void Myst::boilerResetGauge(const Common::Rational &rate) {
 void Myst::o_boilerIncreasePressureStop(uint16 var, const ArgumentsArray &args) {
 	_treeStopped = false;
 	_boilerPressureIncreasing = false;
-	_state.treeLastMoveTime = _vm->_system->getMillis();
+	_state.treeLastMoveTime = _vm->getTotalPlayTime();
 
 	if (_state.cabinPilotLightLit == 1) {
 		if (_state.cabinValvePosition > 0)
@@ -2089,7 +2089,7 @@ void Myst::o_boilerDecreasePressureStart(uint16 var, const ArgumentsArray &args)
 void Myst::o_boilerDecreasePressureStop(uint16 var, const ArgumentsArray &args) {
 	_treeStopped = false;
 	_boilerPressureDecreasing = false;
-	_state.treeLastMoveTime = _vm->_system->getMillis();
+	_state.treeLastMoveTime = _vm->getTotalPlayTime();
 
 	if (_state.cabinPilotLightLit == 1) {
 		if (_state.cabinValvePosition > 0)
@@ -2115,7 +2115,7 @@ void Myst::o_basementIncreasePressureStart(uint16 var, const ArgumentsArray &arg
 void Myst::o_basementIncreasePressureStop(uint16 var, const ArgumentsArray &args) {
 	_treeStopped = false;
 	_basementPressureIncreasing = false;
-	_state.treeLastMoveTime = _vm->_system->getMillis();
+	_state.treeLastMoveTime = _vm->getTotalPlayTime();
 }
 
 void Myst::basementPressureIncrease_run() {
@@ -2152,7 +2152,7 @@ void Myst::o_basementDecreasePressureStart(uint16 var, const ArgumentsArray &arg
 void Myst::o_basementDecreasePressureStop(uint16 var, const ArgumentsArray &args) {
 	_treeStopped = false;
 	_basementPressureDecreasing = false;
-	_state.treeLastMoveTime = _vm->_system->getMillis();
+	_state.treeLastMoveTime = _vm->getTotalPlayTime();
 }
 
 void Myst::tree_run() {
@@ -2172,7 +2172,7 @@ void Myst::tree_run() {
 		if ((_state.treePosition < 12 && !goingDown)
 				|| (_state.treePosition > _treeMinPosition && goingDown)) {
 			uint16 delay = treeNextMoveDelay(pressure);
-			uint32 time = _vm->_system->getMillis();
+			uint32 time = _vm->getTotalPlayTime();
 			if (delay < time - _state.treeLastMoveTime) {
 
 				// Tree movement
@@ -2481,7 +2481,7 @@ void Myst::o_rocketLeverEndMove(uint16 var, const ArgumentsArray &args) {
 void Myst::o_cabinLeave(uint16 var, const ArgumentsArray &args) {
 	// If match is lit, put out
 	if (_cabinMatchState == 1) {
-		_matchGoOutTime = _vm->_system->getMillis();
+		_matchGoOutTime = _vm->getTotalPlayTime();
 	} else if (_cabinMatchState == 0) {
 		_vm->setMainCursor(_savedCursorId);
 		_cabinMatchState = 2;
@@ -2636,19 +2636,19 @@ void Myst::observatoryUpdateTime() {
 void Myst::o_libraryBookPageTurnStartLeft(uint16 var, const ArgumentsArray &args) {
 	_tempVar = -1;
 	libraryBookPageTurnLeft();
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_libraryBookPagesTurning = true;
 }
 
 void Myst::o_libraryBookPageTurnStartRight(uint16 var, const ArgumentsArray &args) {
 	_tempVar = 1;
 	libraryBookPageTurnRight();
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_libraryBookPagesTurning = true;
 }
 
 void Myst::libraryBook_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 	if (time >= _startTime + 500) {
 		if (_tempVar > 0) {
 			libraryBookPageTurnRight();
@@ -2676,12 +2676,12 @@ void Myst::o_cabinMatchLight(uint16 var, const ArgumentsArray &args) {
 		_vm->setMainCursor(kLitMatchCursor);
 
 		// Match will stay lit for one minute
-		_matchGoOutTime = _vm->_system->getMillis() + 60 * 1000;
+		_matchGoOutTime = _vm->getTotalPlayTime() + 60 * 1000;
 	}
 }
 
 void Myst::matchBurn_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _matchGoOutTime) {
 		_matchGoOutTime = time + 150;
@@ -2732,7 +2732,7 @@ void Myst::o_clockHourWheelStartTurn(uint16 var, const ArgumentsArray &args) {
 
 void Myst::clockWheel_run() {
 	// Turn wheel one step each second
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _startTime + 1000) {
 		_startTime = time;
@@ -2763,7 +2763,7 @@ void Myst::clockWheelStartTurn(uint16 wheel) {
 
 	// Continue turning wheel until mouse button is released
 	_clockTurningWheel = wheel;
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 }
 
 void Myst::clockWheelTurn(uint16 var) {
@@ -2779,14 +2779,14 @@ void Myst::clockWheelTurn(uint16 var) {
 void Myst::o_libraryCombinationBookStartRight(uint16 var, const ArgumentsArray &args) {
 	_tempVar = 0;
 	libraryCombinationBookTurnRight();
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_libraryCombinationBookPagesTurning = true;
 }
 
 void Myst::o_libraryCombinationBookStartLeft(uint16 var, const ArgumentsArray &args) {
 	_tempVar = 0;
 	libraryCombinationBookTurnLeft();
-	_startTime = _vm->_system->getMillis();
+	_startTime = _vm->getTotalPlayTime();
 	_libraryCombinationBookPagesTurning = true;
 }
 
@@ -2839,7 +2839,7 @@ void Myst::libraryCombinationBookTurnRight() {
 }
 
 void Myst::libraryCombinationBook_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 	if (time >= _startTime + 500) {
 		if (_tempVar > 0) {
 			libraryCombinationBookTurnRight();
@@ -3158,7 +3158,7 @@ void Myst::towerRotationMap_run() {
 		_vm->_gfx->copyBackBufferToScreen(Common::Rect(106, 42, 459, 273));
 	}
 
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 	if (time > _startTime) {
 		if (_towerRotationMapClicked) {
 			towerRotationMapRotate();
@@ -3428,14 +3428,14 @@ void Myst::o_clockGears_init(uint16 var, const ArgumentsArray &args) {
 
 void Myst::o_gulls1_init(uint16 var, const ArgumentsArray &args) {
 	if (!_state.shipFloating) {
-		_gullsNextTime = _vm->_system->getMillis() + 2000;
+		_gullsNextTime = _vm->getTotalPlayTime() + 2000;
 		_gullsFlying1 = true;
 	}
 }
 
 void Myst::gullsFly1_run() {
 	static const char* gulls[] = { "birds1", "birds2", "birds3" };
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _gullsNextTime) {
 		uint16 video = _vm->_rnd->getRandomNumber(3);
@@ -3475,7 +3475,7 @@ void Myst::o_observatory_init(uint16 var, const ArgumentsArray &args) {
 	_observatoryYearSlider->setPosition(_state.observatoryYearSlider);
 	_observatoryTimeSlider->setPosition(_state.observatoryTimeSlider);
 
-	_observatoryLastTime = _vm->_system->getMillis();
+	_observatoryLastTime = _vm->getTotalPlayTime();
 
 	observatorySetTargetToSetting();
 
@@ -3562,7 +3562,7 @@ void Myst::observatory_run() {
 			|| _state.observatoryTimeTarget != _state.observatoryTimeSetting) {
 
 		// Blink the go button
-		uint32 time = _vm->_system->getMillis();
+		uint32 time = _vm->getTotalPlayTime();
 		if (time > _observatoryLastTime + 250) {
 			_tempVar = (_tempVar + 1) % 2;
 			_observatoryGoButton->drawConditionalDataToScreen(_tempVar);
@@ -3573,14 +3573,14 @@ void Myst::observatory_run() {
 
 void Myst::o_gulls2_init(uint16 var, const ArgumentsArray &args) {
 	if (!_state.shipFloating) {
-		_gullsNextTime = _vm->_system->getMillis() + 2000;
+		_gullsNextTime = _vm->getTotalPlayTime() + 2000;
 		_gullsFlying2 = true;
 	}
 }
 
 void Myst::gullsFly2_run() {
 	static const char* gulls[] = { "birds1", "birds2", "birds3" };
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _gullsNextTime) {
 		uint16 video = _vm->_rnd->getRandomNumber(3);
@@ -3738,14 +3738,14 @@ void Myst::greenBook_run() {
 
 void Myst::o_gulls3_init(uint16 var, const ArgumentsArray &args) {
 	if (!_state.shipFloating) {
-		_gullsNextTime = _vm->_system->getMillis() + 2000;
+		_gullsNextTime = _vm->getTotalPlayTime() + 2000;
 		_gullsFlying3 = true;
 	}
 }
 
 void Myst::gullsFly3_run() {
 	static const char* gulls[] = { "birds1", "birds2", "birds3" };
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _gullsNextTime) {
 		uint16 video = _vm->_rnd->getRandomNumber(3);
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index 8348c45..eaa311b 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -114,7 +114,7 @@ void Preview::speechUpdateCue() {
 }
 
 void Preview::speech_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	// Update current speech sound cue
 	speechUpdateCue();
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index 4ef7828..bcc16dc 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -671,7 +671,7 @@ void Selenitic::soundReceiverLeftRight(uint direction) {
 
 	_soundReceiverDirection = direction;
 	_soundReceiverSpeed = kSoundReceiverSpeedSlow;
-	_soundReceiverStartTime = _vm->_system->getMillis();
+	_soundReceiverStartTime = _vm->getTotalPlayTime();
 
 	soundReceiverUpdate();
 }
@@ -950,7 +950,7 @@ void Selenitic::o_mazeRunnerLight_init(uint16 var, const ArgumentsArray &args) {
 void Selenitic::soundReceiver_run() {
 	if (_soundReceiverStartTime) {
 		if (_soundReceiverDirection) {
-			uint32 currentTime = _vm->_system->getMillis();
+			uint32 currentTime = _vm->getTotalPlayTime();
 
 			if (_soundReceiverSpeed == kSoundReceiverSpeedFast && currentTime > _soundReceiverStartTime + 500) {
 				soundReceiverIncreaseSpeed();
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index 7524dde..aa339bd 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -62,7 +62,7 @@ void Slides::disablePersistentScripts() {
 void Slides::runPersistentScripts() {
 	if (_cardSwapEnabled) {
 		// Used on Cards...
-		if (_vm->_system->getMillis() > _nextCardTime) {
+		if (_vm->getTotalPlayTime() > _nextCardTime) {
 			_vm->_gfx->fadeToBlack();
 			_vm->changeToCard(_nextCardID, kNoTransition);
 			_vm->_gfx->fadeFromBlack();
@@ -78,7 +78,7 @@ void Slides::o_returnToMenu(uint16 var, const ArgumentsArray &args) {
 void Slides::o_setCardSwap(uint16 var, const ArgumentsArray &args) {
 	_nextCardID = args[0];
 
-	_nextCardTime = _vm->_system->getMillis() + 5000;
+	_nextCardTime = _vm->getTotalPlayTime() + 5000;
 	_cardSwapEnabled = true;
 }
 
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 3791972..e60090c 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -508,12 +508,12 @@ void Stoneship::o_generatorStart(uint16 var, const ArgumentsArray &args) {
 		_vm->_sound->playEffect(soundId);
 
 	if (_state.generatorDuration)
-		_state.generatorDuration -= _vm->_system->getMillis() - _state.generatorDepletionTime;
+		_state.generatorDuration -= _vm->getTotalPlayTime() - _state.generatorDepletionTime;
 
 	// Start charging the battery
 	_batteryDepleting = false;
 	_batteryCharging = true;
-	_batteryNextTime = _vm->_system->getMillis() + 1000;
+	_batteryNextTime = _vm->getTotalPlayTime() + 1000;
 
 	// Start handle movie
 	MystAreaVideo *movie = static_cast<MystAreaVideo *>(handle->getSubResource(0));
@@ -533,10 +533,10 @@ void Stoneship::o_generatorStop(uint16 var, const ArgumentsArray &args) {
 			_state.generatorDuration = 600000;
 
 		// Start depleting power
-		_state.generatorDepletionTime = _vm->_system->getMillis() + _state.generatorDuration;
+		_state.generatorDepletionTime = _vm->getTotalPlayTime() + _state.generatorDuration;
 		_state.generatorPowerAvailable = 1;
 		_batteryDepleting = true;
-		_batteryNextTime = _vm->_system->getMillis() + 60000;
+		_batteryNextTime = _vm->getTotalPlayTime() + 60000;
 	}
 
 	// Pause handle movie
@@ -550,7 +550,7 @@ void Stoneship::o_generatorStop(uint16 var, const ArgumentsArray &args) {
 }
 
 void Stoneship::chargeBattery_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _batteryNextTime) {
 		_batteryNextTime = time + 1000;
@@ -559,7 +559,7 @@ void Stoneship::chargeBattery_run() {
 }
 
 uint16 Stoneship::batteryRemainingCharge() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (_state.generatorDepletionTime > time) {
 		return (_state.generatorDepletionTime - time) / 7500;
@@ -569,7 +569,7 @@ uint16 Stoneship::batteryRemainingCharge() {
 }
 
 void Stoneship::batteryDeplete_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _batteryNextTime) {
 		if (_state.generatorDuration > 60000) {
@@ -828,7 +828,7 @@ void Stoneship::o_tunnelEnter_init(uint16 var, const ArgumentsArray &args) {
 	o_tunnel_init(var, args);
 
 	_tunnelRunning = true;
-	_tunnelNextTime = _vm->_system->getMillis() + 1500;
+	_tunnelNextTime = _vm->getTotalPlayTime() + 1500;
 }
 
 void Stoneship::o_batteryGauge_init(uint16 var, const ArgumentsArray &args) {
@@ -867,7 +867,7 @@ void Stoneship::o_tunnel_init(uint16 var, const ArgumentsArray &args) {
 }
 
 void Stoneship::tunnel_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _tunnelNextTime) {
 		_tunnelNextTime = time + 1500;
@@ -904,11 +904,11 @@ void Stoneship::o_telescope_init(uint16 var, const ArgumentsArray &args) {
 
 	_telescopeRunning = true;
 	_telescopeLighthouseState = false;
-	_telescopeNexTime = _vm->_system->getMillis() + 1000;
+	_telescopeNexTime = _vm->getTotalPlayTime() + 1000;
 }
 
 void Stoneship::telescope_run() {
-	uint32 time = _vm->_system->getMillis();
+	uint32 time = _vm->getTotalPlayTime();
 
 	if (time > _telescopeNexTime) {
 





More information about the Scummvm-git-logs mailing list