aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk')
-rw-r--r--engines/mohawk/console.cpp41
-rw-r--r--engines/mohawk/console.h1
-rw-r--r--engines/mohawk/dialogs.cpp8
-rw-r--r--engines/mohawk/graphics.cpp153
-rw-r--r--engines/mohawk/graphics.h7
-rw-r--r--engines/mohawk/myst.cpp5
-rw-r--r--engines/mohawk/myst_scripts.cpp9
-rw-r--r--engines/mohawk/riven.cpp306
-rw-r--r--engines/mohawk/riven.h32
-rw-r--r--engines/mohawk/riven_cursors.h296
-rw-r--r--engines/mohawk/riven_external.cpp941
-rw-r--r--engines/mohawk/riven_external.h14
-rw-r--r--engines/mohawk/riven_saveload.cpp8
-rw-r--r--engines/mohawk/riven_scripts.cpp25
-rw-r--r--engines/mohawk/riven_scripts.h6
-rw-r--r--engines/mohawk/riven_vars.cpp55
-rw-r--r--engines/mohawk/sound.cpp54
-rw-r--r--engines/mohawk/sound.h13
-rw-r--r--engines/mohawk/video.cpp18
-rw-r--r--engines/mohawk/video.h2
20 files changed, 1458 insertions, 536 deletions
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 5dcfff4f90..3eed08e3c1 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -309,6 +309,7 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards));
DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP));
DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos));
+ DCmd_Register("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState));
}
RivenConsole::~RivenConsole() {
@@ -349,7 +350,7 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) {
return true;
}
- uint32 *globalVar = _vm->matchVarToString(argv[1]);
+ uint32 *globalVar = _vm->getVar(argv[1]);
if (!globalVar) {
DebugPrintf("Unknown variable \'%s\'\n", argv[1]);
@@ -366,19 +367,13 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) {
bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) {
if (argc < 2) {
- DebugPrintf("Usage: playSound <value> (<use main sound file, default = true>)\n");
- DebugPrintf("The main sound file is default, but you can use the word \'false\' to make it use the current stack file.\n");
-
+ DebugPrintf("Usage: playSound <value>\n");
return true;
}
_vm->_sound->stopSound();
_vm->_sound->stopAllSLST();
-
- bool mainSoundFile = (argc < 3) || (scumm_stricmp(argv[2], "false") != 0);
-
- _vm->_sound->playSound((uint16)atoi(argv[1]), mainSoundFile);
-
+ _vm->_sound->playSound((uint16)atoi(argv[1]));
return false;
}
@@ -392,13 +387,9 @@ bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) {
_vm->_sound->stopSound();
_vm->_sound->stopAllSLST();
- uint16 card = _vm->getCurCard();
-
- if (argc == 3)
- card = (uint16)atoi(argv[2]);
+ uint16 card = (argc == 3) ? (uint16)atoi(argv[2]) : _vm->getCurCard();
_vm->_sound->playSLST((uint16)atoi(argv[1]), card);
-
return false;
}
@@ -407,7 +398,6 @@ bool RivenConsole::Cmd_StopSound(int argc, const char **argv) {
_vm->_sound->stopSound();
_vm->_sound->stopAllSLST();
-
return true;
}
@@ -466,10 +456,11 @@ bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
DebugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID);
if (_vm->_hotspots[i].enabled)
- DebugPrintf("enabled)\n");
+ DebugPrintf("enabled");
else
- DebugPrintf("disabled)\n");
+ DebugPrintf("disabled");
+ DebugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom);
DebugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str());
}
@@ -477,7 +468,7 @@ bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
}
bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) {
- uint32 *zipModeActive = _vm->matchVarToString("azip");
+ uint32 *zipModeActive = _vm->getVar("azip");
*zipModeActive = !(*zipModeActive);
DebugPrintf("Zip Mode is ");
@@ -620,9 +611,9 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
// You'll need to look up the Rebel Tunnel puzzle on your own; the
// solution is constant.
- uint32 teleCombo = *_vm->matchVarToString("tcorrectorder");
- uint32 prisonCombo = *_vm->matchVarToString("pcorrectorder");
- uint32 domeCombo = *_vm->matchVarToString("adomecombo");
+ uint32 teleCombo = *_vm->getVar("tcorrectorder");
+ uint32 prisonCombo = *_vm->getVar("pcorrectorder");
+ uint32 domeCombo = *_vm->getVar("adomecombo");
DebugPrintf("Telescope Combo:\n ");
for (int i = 0; i < 5; i++)
@@ -641,6 +632,14 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
return true;
}
+bool RivenConsole::Cmd_SliderState(int argc, const char **argv) {
+ if (argc > 1)
+ _vm->_externalScriptHandler->setDomeSliderState((uint32)atoi(argv[1]));
+
+ DebugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState());
+ return true;
+}
+
LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index 1806c61027..beba3f8852 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -89,6 +89,7 @@ private:
bool Cmd_ListZipCards(int argc, const char **argv);
bool Cmd_GetRMAP(int argc, const char **argv);
bool Cmd_Combos(int argc, const char **argv);
+ bool Cmd_SliderState(int argc, const char **argv);
};
class LivingBooksConsole : public GUI::Debugger {
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index c09763cbb3..a7369b4825 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -125,17 +125,17 @@ RivenOptionsDialog::~RivenOptionsDialog() {
void RivenOptionsDialog::open() {
Dialog::open();
- _zipModeCheckbox->setState(*_vm->matchVarToString("azip") != 0);
- _waterEffectCheckbox->setState(*_vm->matchVarToString("waterenabled") != 0);
+ _zipModeCheckbox->setState(*_vm->getVar("azip") != 0);
+ _waterEffectCheckbox->setState(*_vm->getVar("waterenabled") != 0);
}
void RivenOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kZipCmd:
- *_vm->matchVarToString("azip") = _zipModeCheckbox->getState() ? 1 : 0;
+ *_vm->getVar("azip") = _zipModeCheckbox->getState() ? 1 : 0;
break;
case kWaterCmd:
- *_vm->matchVarToString("waterenabled") = _waterEffectCheckbox->getState() ? 1 : 0;
+ *_vm->getVar("waterenabled") = _waterEffectCheckbox->getState() ? 1 : 0;
break;
case GUI::kCloseCmd:
close();
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index 1974aec9c2..f472a9d721 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -326,7 +326,7 @@ void RivenGraphics::drawPLST(uint16 x) {
// draw PLST 1 each time. This "hack" is here to catch any PLST attempting to draw
// twice. There should never be a problem with doing it this way.
if (index == x && !(Common::find(_activatedPLSTs.begin(), _activatedPLSTs.end(), x) != _activatedPLSTs.end())) {
- debug (0, "Drawing image %d", id);
+ debug(0, "Drawing image %d", id);
copyImageToScreen(id, left, top, right, bottom);
_activatedPLSTs.push_back(x);
break;
@@ -399,7 +399,7 @@ void RivenGraphics::clearWaterEffects() {
bool RivenGraphics::runScheduledWaterEffects() {
// Don't run the effect if it's disabled
- if (*_vm->matchVarToString("waterenabled") == 0)
+ if (*_vm->getVar("waterenabled") == 0)
return false;
Graphics::Surface *screen = NULL;
@@ -491,95 +491,106 @@ void RivenGraphics::runScheduledTransition() {
_scheduledTransition = -1; // Clear scheduled transition
}
-// TODO: Marble Cursors/Palettes
void RivenGraphics::changeCursor(uint16 num) {
// All of Riven's cursors are hardcoded. See riven_cursors.h for these definitions.
switch (num) {
case 1002:
// Zip Mode
- CursorMan.replaceCursor(zipModeCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(zipModeCursorPalette, 1, ARRAYSIZE(zipModeCursorPalette) / 4);
+ CursorMan.replaceCursor(s_zipModeCursor, 16, 16, 8, 8, 0);
+ CursorMan.replaceCursorPalette(s_zipModeCursorPalette, 1, ARRAYSIZE(s_zipModeCursorPalette) / 4);
break;
case 2003:
// Hand Over Object
- CursorMan.replaceCursor(objectHandCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_objectHandCursor, 16, 16, 8, 8, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 2004:
// Grabbing/Using Object
- CursorMan.replaceCursor(grabbingHandCursor, 13, 13, 6, 6, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_grabbingHandCursor, 13, 13, 6, 6, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3000:
// Standard Hand
- CursorMan.replaceCursor(standardHandCursor, 15, 16, 6, 0, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_standardHandCursor, 15, 16, 6, 0, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3001:
// Pointing Left
- CursorMan.replaceCursor(pointingLeftCursor, 15, 13, 0, 3, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingLeftCursor, 15, 13, 0, 3, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3002:
// Pointing Right
- CursorMan.replaceCursor(pointingRightCursor, 15, 13, 14, 3, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingRightCursor, 15, 13, 14, 3, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3003:
// Pointing Down (Palm Up)
- CursorMan.replaceCursor(pointingDownCursorPalmUp, 13, 16, 3, 15, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingDownCursorPalmUp, 13, 16, 3, 15, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3004:
// Pointing Up (Palm Up)
- CursorMan.replaceCursor(pointingUpCursorPalmUp, 13, 16, 3, 0, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingUpCursorPalmUp, 13, 16, 3, 0, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3005:
// Pointing Left (Curved)
- CursorMan.replaceCursor(pointingLeftCursorBent, 15, 13, 0, 5, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingLeftCursorBent, 15, 13, 0, 5, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3006:
// Pointing Right (Curved)
- CursorMan.replaceCursor(pointingRightCursorBent, 15, 13, 14, 5, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingRightCursorBent, 15, 13, 14, 5, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 3007:
// Pointing Down (Palm Down)
- CursorMan.replaceCursor(pointingDownCursorPalmDown, 15, 16, 7, 15, 0);
- CursorMan.replaceCursorPalette(handCursorPalette, 1, ARRAYSIZE(handCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pointingDownCursorPalmDown, 15, 16, 7, 15, 0);
+ CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
break;
case 4001:
// Red Marble
+ CursorMan.replaceCursor(s_redMarbleCursor, 12, 12, 5, 5, 0);
+ CursorMan.replaceCursorPalette(s_redMarbleCursorPalette, 1, ARRAYSIZE(s_redMarbleCursorPalette) / 4);
break;
case 4002:
// Orange Marble
+ CursorMan.replaceCursor(s_orangeMarbleCursor, 12, 12, 5, 5, 0);
+ CursorMan.replaceCursorPalette(s_orangeMarbleCursorPalette, 1, ARRAYSIZE(s_orangeMarbleCursorPalette) / 4);
break;
case 4003:
// Yellow Marble
+ CursorMan.replaceCursor(s_yellowMarbleCursor, 12, 12, 5, 5, 0);
+ CursorMan.replaceCursorPalette(s_yellowMarbleCursorPalette, 1, ARRAYSIZE(s_yellowMarbleCursorPalette) / 4);
break;
case 4004:
// Green Marble
+ CursorMan.replaceCursor(s_greenMarbleCursor, 12, 12, 5, 5, 0);
+ CursorMan.replaceCursorPalette(s_greenMarbleCursorPalette, 1, ARRAYSIZE(s_greenMarbleCursorPalette) / 4);
break;
case 4005:
// Blue Marble
+ CursorMan.replaceCursor(s_blueMarbleCursor, 12, 12, 5, 5, 0);
+ CursorMan.replaceCursorPalette(s_blueMarbleCursorPalette, 1, ARRAYSIZE(s_blueMarbleCursorPalette) / 4);
break;
case 4006:
- // Purple Marble
+ // Violet Marble
+ CursorMan.replaceCursor(s_violetMarbleCursor, 12, 12, 5, 5, 0);
+ CursorMan.replaceCursorPalette(s_violetMarbleCursorPalette, 1, ARRAYSIZE(s_violetMarbleCursorPalette) / 4);
break;
case 5000:
// Pellet
- CursorMan.replaceCursor(pelletCursor, 8, 8, 4, 4, 0);
- CursorMan.replaceCursorPalette(pelletCursorPalette, 1, ARRAYSIZE(pelletCursorPalette) / 4);
+ CursorMan.replaceCursor(s_pelletCursor, 8, 8, 4, 4, 0);
+ CursorMan.replaceCursorPalette(s_pelletCursorPalette, 1, ARRAYSIZE(s_pelletCursorPalette) / 4);
break;
case 9000:
// Hide Cursor
CursorMan.showMouse(false);
break;
default:
- error ("Cursor %d does not exist!", num);
+ error("Cursor %d does not exist!", num);
}
if (num != 9000) // Show Cursor
@@ -597,28 +608,35 @@ void RivenGraphics::showInventory() {
// Clear the inventory area
clearInventoryArea();
- // The demo doesn't have the inventory system and we don't want
- // to show the inventory on setup screens or in other journals.
- if (_vm->getFeatures() & GF_DEMO || _vm->getCurStack() == aspit)
- return;
-
- // There are three books and three vars. We have three different
- // combinations. At the start you have just Atrus' journal. Later,
- // you get Catherine's journal and the trap book. Near the end,
- // you lose the trap book and have just the two journals.
-
- bool hasCathBook = *_vm->matchVarToString("acathbook") != 0;
- bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0;
-
- if (!hasCathBook) {
- drawInventoryImage(101, g_atrusJournalRect1);
- } else if (!hasTrapBook) {
- drawInventoryImage(101, g_atrusJournalRect2);
- drawInventoryImage(102, g_cathJournalRect2);
+ // Draw the demo's exit button
+ if (_vm->getFeatures() & GF_DEMO) {
+ // extras.mhk tBMP 101 contains "EXIT" instead of Atrus' journal in the demo!
+ // The demo's extras.mhk contains all the other inventory/marble/credits image
+ // but has hacked tBMP 101 with "EXIT". *sigh*
+ drawInventoryImage(101, g_demoExitRect);
} else {
- drawInventoryImage(101, g_atrusJournalRect3);
- drawInventoryImage(102, g_cathJournalRect3);
- drawInventoryImage(100, g_trapBookRect3);
+ // We don't want to show the inventory on setup screens or in other journals.
+ if (_vm->getCurStack() == aspit)
+ return;
+
+ // There are three books and three vars. We have three different
+ // combinations. At the start you have just Atrus' journal. Later,
+ // you get Catherine's journal and the trap book. Near the end,
+ // you lose the trap book and have just the two journals.
+
+ bool hasCathBook = *_vm->getVar("acathbook") != 0;
+ bool hasTrapBook = *_vm->getVar("atrapbook") != 0;
+
+ if (!hasCathBook) {
+ drawInventoryImage(101, g_atrusJournalRect1);
+ } else if (!hasTrapBook) {
+ drawInventoryImage(101, g_atrusJournalRect2);
+ drawInventoryImage(102, g_cathJournalRect2);
+ } else {
+ drawInventoryImage(101, g_atrusJournalRect3);
+ drawInventoryImage(102, g_cathJournalRect3);
+ drawInventoryImage(100, g_trapBookRect3);
+ }
}
_vm->_system->updateScreen();
@@ -672,6 +690,39 @@ void RivenGraphics::drawRect(Common::Rect rect, bool active) {
_vm->_system->unlockScreen();
}
+void RivenGraphics::drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect dstRect) {
+ // Draw tBMP id from srcRect to dstRect
+ ImageData *imageData = _bitmapDecoder->decodeImage(_vm->getRawData(ID_TBMP, id));
+ Graphics::Surface *surface = imageData->getSurface();
+ delete imageData;
+
+ assert(srcRect.width() == dstRect.width() && srcRect.height() == dstRect.height());
+
+ for (uint16 i = 0; i < srcRect.height(); i++)
+ memcpy(_mainScreen->getBasePtr(dstRect.left, i + dstRect.top), surface->getBasePtr(srcRect.left, i + srcRect.top), srcRect.width() * surface->bytesPerPixel);
+
+ surface->free();
+ delete surface;
+
+ _dirtyScreen = true;
+}
+
+void RivenGraphics::drawExtrasImage(uint16 id, Common::Rect dstRect) {
+ ImageData *imageData = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, id));
+ Graphics::Surface *surface = imageData->getSurface();
+ delete imageData;
+
+ assert(dstRect.width() == surface->w);
+
+ for (uint16 i = 0; i < surface->h; i++)
+ memcpy(_mainScreen->getBasePtr(dstRect.left, i + dstRect.top), surface->getBasePtr(0, i), surface->pitch);
+
+ surface->free();
+ delete surface;
+
+ _dirtyScreen = true;
+}
+
LBGraphics::LBGraphics(MohawkEngine_LivingBooks *vm) : _vm(vm) {
_bmpDecoder = (_vm->getGameType() == GType_LIVINGBOOKSV1) ? new OldMohawkBitmap() : new MohawkBitmap();
_palette = new byte[256 * 4];
@@ -707,7 +758,7 @@ void LBGraphics::copyImageToScreen(uint16 image, uint16 left, uint16 right) {
}
void LBGraphics::setPalette(uint16 id) {
- // Old Living Books gamnes use the old CTBL-style palette format while newer
+ // Old Living Books games use the old CTBL-style palette format while newer
// games use the better tPAL format which can store partial palettes.
if (_vm->getGameType() == GType_LIVINGBOOKSV1) {
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index dd1764e6d6..9419aad277 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -41,6 +41,8 @@ class MohawkBitmap;
class MystBitmap;
enum {
+ kRivenOpenHandCursor = 2003,
+ kRivenClosedHandCursor = 2004,
kRivenMainCursor = 3000,
kRivenPelletCursor = 5000,
kRivenHideCursor = 9000
@@ -117,7 +119,7 @@ private:
uint16 type;
uint16 width;
uint16 height;
- } *entries;
+ } *entries;
Common::File picFile;
} _pictureFile;
@@ -147,6 +149,8 @@ public:
Common::Array<uint16> _activatedPLSTs;
void drawPLST(uint16 x);
void drawRect(Common::Rect rect, bool active);
+ void drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect dstRect);
+ void drawExtrasImage(uint16 id, Common::Rect dstRect);
// Water Effect
void scheduleWaterEffect(uint16);
@@ -181,7 +185,6 @@ private:
Graphics::Surface *_mainScreen;
bool _dirtyScreen;
Graphics::PixelFormat _pixelFormat;
- byte findBlackIndex();
};
class LBGraphics {
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 9ff301c129..6ed7a313a0 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -25,6 +25,7 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/translation.h"
#include "mohawk/graphics.h"
#include "mohawk/myst.h"
@@ -218,7 +219,7 @@ Common::Error MohawkEngine_Myst::run() {
_varStore = new MystVar(this);
_saveLoad = new MystSaveLoad(this, _saveFileMan);
_scriptParser = new MystScriptParser(this);
- _loadDialog = new GUI::SaveLoadChooser("Load Game:", "Load");
+ _loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"));
_loadDialog->setSaveMode(false);
_optionsDialog = new MystOptionsDialog(this);
@@ -427,7 +428,7 @@ void MohawkEngine_Myst::changeToCard(uint16 card) {
// NOTE: All sounds are looped when played via the sound section of the
// VIEW resources.
- _sound->playSound(soundAction, true, soundActionVolume, true);
+ _sound->playSound(soundAction, soundActionVolume, true);
} else {
error("Unknown sound action %d", soundAction);
}
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index 2f6d178da8..a8cd643e2c 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -709,10 +709,7 @@ void MystScriptParser::playSoundBlocking(uint16 op, uint16 var, uint16 argc, uin
debugC(kDebugScript, "Opcode %d: playSoundBlocking", op);
debugC(kDebugScript, "\tsoundId: %d", soundId);
- Audio::SoundHandle *handle = _vm->_sound->playSound(soundId);
-
- while (_vm->_mixer->isSoundHandleActive(*handle))
- _vm->_system->delayMillis(10);
+ _vm->_sound->playSoundBlocking(soundId);
} else
unknown(op, var, argc, argv);
}
@@ -870,7 +867,7 @@ void MystScriptParser::opcode_30(uint16 op, uint16 var, uint16 argc, uint16 *arg
_vm->_sound->stopSound();
// TODO: Need to keep sound handle and add function to change volume of
// looped running sound for kMystSoundActionChangeVolume type
- _vm->_sound->playSound(soundAction, true, soundVolume);
+ _vm->_sound->playSound(soundAction, soundVolume);
} else {
debugC(kDebugScript, "Unknown");
warning("Unknown sound control value in opcode %d", op);
@@ -2458,7 +2455,7 @@ void MystScriptParser::opcode_120(uint16 op, uint16 var, uint16 argc, uint16 *ar
if (var8 != 0xFFFF)
_vm->_varStore->setVar(var8, !_vm->_varStore->getVar(var8));
else
- warning("Opcode 120: No invoking Resource Var 8 found!");
+ warning("Opcode 120: No invoking Resource Var 8 found");
} else
unknown(op, var, argc, argv);
break;
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 07b08dc220..f2f4a42f0e 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -27,6 +27,7 @@
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/keyboard.h"
+#include "common/translation.h"
#include "mohawk/graphics.h"
#include "mohawk/resource.h"
@@ -44,6 +45,7 @@ Common::Rect *g_cathJournalRect2;
Common::Rect *g_atrusJournalRect3;
Common::Rect *g_cathJournalRect3;
Common::Rect *g_trapBookRect3;
+Common::Rect *g_demoExitRect;
MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
_showHotspots = false;
@@ -73,6 +75,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
g_atrusJournalRect3 = new Common::Rect(222, 402, 240, 426);
g_cathJournalRect3 = new Common::Rect(291, 408, 311, 419);
g_trapBookRect3 = new Common::Rect(363, 396, 386, 432);
+ g_demoExitRect = new Common::Rect(291, 408, 317, 419);
}
MohawkEngine_Riven::~MohawkEngine_Riven() {
@@ -92,13 +95,13 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete g_atrusJournalRect3;
delete g_cathJournalRect3;
delete g_trapBookRect3;
+ delete g_demoExitRect;
}
GUI::Debugger *MohawkEngine_Riven::getDebugger() {
return _console;
}
-
Common::Error MohawkEngine_Riven::run() {
MohawkEngine::run();
@@ -114,124 +117,133 @@ Common::Error MohawkEngine_Riven::run() {
initVars();
- // Open extras.mhk for common images (non-existant in the demo)
- if (!(getFeatures() & GF_DEMO)) {
- _extrasFile = new MohawkArchive();
- _extrasFile->open("extras.mhk");
- }
+ // Open extras.mhk for common images
+ _extrasFile = new MohawkArchive();
+ _extrasFile->open("extras.mhk");
// Start at main cursor
_gfx->changeCursor(kRivenMainCursor);
- // Load game from launcher/command line if requested
- if (ConfMan.hasKey("save_slot") && !(getFeatures() & GF_DEMO)) {
+ // Let's begin, shall we?
+ if (getFeatures() & GF_DEMO) {
+ // Start the demo off with the videos
+ changeToStack(aspit);
+ changeToCard(6);
+ } else if (ConfMan.hasKey("save_slot")) {
+ // Load game from launcher/command line if requested
uint32 gameToLoad = ConfMan.getInt("save_slot");
Common::StringArray savedGamesList = _saveLoad->generateSaveGameList();
if (gameToLoad > savedGamesList.size())
error ("Could not find saved game");
_saveLoad->loadGame(savedGamesList[gameToLoad]);
- } else { // Otherwise, start us off at aspit's card 1
+ } else {
+ // Otherwise, start us off at aspit's card 1 (the main menu)
changeToStack(aspit);
changeToCard(1);
}
+
+ while (!_gameOver && !shouldQuit())
+ handleEvents();
+
+ return Common::kNoError;
+}
+
+void MohawkEngine_Riven::handleEvents() {
Common::Event event;
- while (!_gameOver) {
- bool needsUpdate = _gfx->runScheduledWaterEffects();
- needsUpdate |= _video->updateBackgroundMovies();
- while (_eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- _mousePos = event.mouse;
- checkHotspotChange();
+ // Update background videos and the water effect
+ bool needsUpdate = _gfx->runScheduledWaterEffects();
+ needsUpdate |= _video->updateBackgroundMovies();
+
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ checkHotspotChange();
- // Check to show the inventory
- if (_mousePos.y >= 392)
+ if (!(getFeatures() & GF_DEMO)) {
+ // Check to show the inventory, but it is always "showing" in the demo
+ if (_eventMan->getMousePos().y >= 392)
_gfx->showInventory();
else
_gfx->hideInventory();
+ }
- needsUpdate = true;
- break;
- case Common::EVENT_LBUTTONDOWN:
+ needsUpdate = true;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ if (_curHotspot >= 0)
+ runHotspotScript(_curHotspot, kMouseDownScript);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ // See RivenScript::switchCard() for more information on why we sometimes
+ // disable the next up event.
+ if (!_ignoreNextMouseUp) {
if (_curHotspot >= 0)
- runHotspotScript(_curHotspot, kMouseDownScript);
+ runHotspotScript(_curHotspot, kMouseUpScript);
+ else
+ checkInventoryClick();
+ }
+ _ignoreNextMouseUp = false;
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_d:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ _console->attach();
+ _console->onFrame();
+ }
break;
- case Common::EVENT_LBUTTONUP:
- // See RivenScript::switchCard() for more information on why we sometimes
- // disable the next up event.
- if (!_ignoreNextMouseUp) {
- if (_curHotspot >= 0)
- runHotspotScript(_curHotspot, kMouseUpScript);
- else
- checkInventoryClick();
+ case Common::KEYCODE_SPACE:
+ pauseGame();
+ break;
+ case Common::KEYCODE_F4:
+ _showHotspots = !_showHotspots;
+ if (_showHotspots) {
+ for (uint16 i = 0; i < _hotspotCount; i++)
+ _gfx->drawRect(_hotspots[i].rect, _hotspots[i].enabled);
+ needsUpdate = true;
+ } else
+ refreshCard();
+ break;
+ case Common::KEYCODE_F5:
+ runDialog(*_optionsDialog);
+ updateZipMode();
+ break;
+ case Common::KEYCODE_r:
+ // Return to the main menu in the demo on ctrl+r
+ if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) {
+ if (_curStack != aspit)
+ changeToStack(aspit);
+ changeToCard(1);
}
- _ignoreNextMouseUp = false;
break;
- case Common::EVENT_KEYDOWN:
- switch (event.kbd.keycode) {
- case Common::KEYCODE_d:
- if (event.kbd.flags & Common::KBD_CTRL) {
- _console->attach();
- _console->onFrame();
- }
- break;
- case Common::KEYCODE_SPACE:
- pauseGame();
- break;
- case Common::KEYCODE_F4:
- _showHotspots = !_showHotspots;
- if (_showHotspots) {
- for (uint16 i = 0; i < _hotspotCount; i++)
- _gfx->drawRect(_hotspots[i].rect, _hotspots[i].enabled);
- needsUpdate = true;
- } else
- refreshCard();
- break;
- case Common::KEYCODE_F5:
- runDialog(*_optionsDialog);
- updateZipMode();
- break;
- case Common::KEYCODE_ESCAPE:
- if (getFeatures() & GF_DEMO) {
- if (_curStack != aspit)
- changeToStack(aspit);
- changeToCard(1);
- }
- break;
- default:
- break;
+ case Common::KEYCODE_p:
+ // Play the intro videos in the demo on ctrl+p
+ if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) {
+ if (_curStack != aspit)
+ changeToStack(aspit);
+ changeToCard(6);
}
break;
default:
break;
}
+ break;
+ default:
+ break;
}
+ }
- if (_curHotspot >= 0)
- runHotspotScript(_curHotspot, kMouseInsideScript);
-
- if (shouldQuit()) {
- if (_eventMan->shouldRTL() && (getFeatures() & GF_DEMO) && !(_curStack == aspit && _curCard == 12)) {
- if (_curStack != aspit)
- changeToStack(aspit);
- changeToCard(12);
- _eventMan->resetRTL();
- continue;
- }
- return Common::kNoError;
- }
-
- // Update the screen if we need to
- if (needsUpdate)
- _system->updateScreen();
+ if (_curHotspot >= 0)
+ runHotspotScript(_curHotspot, kMouseInsideScript);
- // Cut down on CPU usage
- _system->delayMillis(10);
- }
+ // Update the screen if we need to
+ if (needsUpdate)
+ _system->updateScreen();
- return Common::kNoError;
+ // Cut down on CPU usage
+ _system->delayMillis(10);
}
// Stack/Card-Related Functions
@@ -240,7 +252,7 @@ void MohawkEngine_Riven::changeToStack(uint16 n) {
// The endings are in reverse order because of the way the 1.02 patch works.
// The only "Data3" file is j_Data3.mhk from that patch. Patch files have higher
// priorities over the regular files and are therefore loaded and checked first.
- static const char *endings[] = { "_Data3.mhk", "_Data2.mhk", "_Data1.mhk", "_Data.mhk" };
+ static const char *endings[] = { "_Data3.mhk", "_Data2.mhk", "_Data1.mhk", "_Data.mhk", "_Sounds.mhk" };
// Don't change stack to the current stack (if the files are loaded)
if (_curStack == n && !_mhk.empty())
@@ -274,9 +286,8 @@ void MohawkEngine_Riven::changeToStack(uint16 n) {
if (_mhk.empty())
error("Could not load stack %s", getStackName(_curStack).c_str());
- // Stop any currently playing sounds and load the new sound file too
+ // Stop any currently playing sounds
_sound->stopAllSLST();
- _sound->loadRivenSounds(_curStack);
}
// Riven uses some hacks to change stacks for linking books
@@ -379,12 +390,11 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) {
// NOTE: The hotspot scripts are cleared by the RivenScriptManager automatically.
- Common::SeekableReadStream* inStream = getRawData(ID_HSPT, id);
+ Common::SeekableReadStream *inStream = getRawData(ID_HSPT, id);
_hotspotCount = inStream->readUint16BE();
_hotspots = new RivenHotspot[_hotspotCount];
-
for (uint16 i = 0; i < _hotspotCount; i++) {
_hotspots[i].enabled = true;
@@ -396,26 +406,21 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) {
int16 right = inStream->readSint16BE();
int16 bottom = inStream->readSint16BE();
- // Riven has some weird hotspots, disable them here
+ // Riven has some invalid rects, disable them here
+ // Known weird hotspots:
+ // - tspit 371 (DVD: 377), hotspot 4
if (left >= right || top >= bottom) {
- left = top = right = bottom = 0;
- _hotspots[i].enabled = 0;
+ warning("%s %d hotspot %d is invalid: (%d, %d, %d, %d)", getStackName(_curStack).c_str(), _curCard, i, left, top, right, bottom);
+ left = top = right = bottom = 0;
+ _hotspots[i].enabled = 0;
}
_hotspots[i].rect = Common::Rect(left, top, right, bottom);
_hotspots[i].u0 = inStream->readUint16BE();
-
- if (_hotspots[i].u0 != 0)
- warning("Hotspot %d u0 non-zero", i);
-
_hotspots[i].mouse_cursor = inStream->readUint16BE();
_hotspots[i].index = inStream->readUint16BE();
_hotspots[i].u1 = inStream->readSint16BE();
-
- if (_hotspots[i].u1 != -1)
- warning("Hotspot %d u1 not -1", i);
-
_hotspots[i].zipModeHotspot = inStream->readUint16BE();
// Read in the scripts now
@@ -431,7 +436,7 @@ void MohawkEngine_Riven::updateZipMode() {
for (uint32 i = 0; i < _hotspotCount; i++) {
if (_hotspots[i].zipModeHotspot) {
- if (*matchVarToString("azip") != 0) {
+ if (*getVar("azip") != 0) {
// Check if a zip mode hotspot is enabled by checking the name/id against the ZIPS records.
Common::String hotspotName = getName(HotspotNames, _hotspots[i].name_resource);
@@ -455,7 +460,7 @@ void MohawkEngine_Riven::checkHotspotChange() {
uint16 hotspotIndex = 0;
bool foundHotspot = false;
for (uint16 i = 0; i < _hotspotCount; i++)
- if (_hotspots[i].enabled && _hotspots[i].rect.contains(_mousePos)) {
+ if (_hotspots[i].enabled && _hotspots[i].rect.contains(_eventMan->getMousePos())) {
foundHotspot = true;
hotspotIndex = i;
}
@@ -481,50 +486,71 @@ Common::String MohawkEngine_Riven::getHotspotName(uint16 hotspot) {
}
void MohawkEngine_Riven::checkInventoryClick() {
+ Common::Point mousePos = _eventMan->getMousePos();
+
// Don't even bother. We're not in the inventory portion of the screen.
- if (_mousePos.y < 392)
+ if (mousePos.y < 392)
+ return;
+
+ // In the demo, check if we've clicked the exit button
+ if (getFeatures() & GF_DEMO) {
+ if (g_demoExitRect->contains(mousePos)) {
+ if (_curStack == aspit && _curCard == 1) {
+ // From the main menu, go to the "quit" screen
+ changeToCard(12);
+ } else if (_curStack == aspit && _curCard == 12) {
+ // From the "quit" screen, just quit
+ _gameOver = true;
+ } else {
+ // Otherwise, return to the main menu
+ if (_curStack != aspit)
+ changeToStack(aspit);
+ changeToCard(1);
+ }
+ }
return;
+ }
- // No inventory in the demo or opening screens.
- if (getFeatures() & GF_DEMO || _curStack == aspit)
+ // No inventory shown on aspit
+ if (_curStack == aspit)
return;
// Set the return stack/card id's.
- *matchVarToString("returnstackid") = _curStack;
- *matchVarToString("returncardid") = _curCard;
+ *getVar("returnstackid") = _curStack;
+ *getVar("returncardid") = _curCard;
// See RivenGraphics::showInventory() for an explanation
// of the variables' meanings.
- bool hasCathBook = *matchVarToString("acathbook") != 0;
- bool hasTrapBook = *matchVarToString("atrapbook") != 0;
+ bool hasCathBook = *getVar("acathbook") != 0;
+ bool hasTrapBook = *getVar("atrapbook") != 0;
// Go to the book if a hotspot contains the mouse
if (!hasCathBook) {
- if (g_atrusJournalRect1->contains(_mousePos)) {
+ if (g_atrusJournalRect1->contains(mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
}
} else if (!hasTrapBook) {
- if (g_atrusJournalRect2->contains(_mousePos)) {
+ if (g_atrusJournalRect2->contains(mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
- } else if (g_cathJournalRect2->contains(_mousePos)) {
+ } else if (g_cathJournalRect2->contains(mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(6);
}
} else {
- if (g_atrusJournalRect3->contains(_mousePos)) {
+ if (g_atrusJournalRect3->contains(mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(5);
- } else if (g_cathJournalRect3->contains(_mousePos)) {
+ } else if (g_cathJournalRect3->contains(mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(6);
- } else if (g_trapBookRect3->contains(_mousePos)) {
+ } else if (g_trapBookRect3->contains(mousePos)) {
_gfx->hideInventory();
changeToStack(aspit);
changeToCard(7);
@@ -607,8 +633,26 @@ void MohawkEngine_Riven::runHotspotScript(uint16 hotspot, uint16 scriptType) {
}
}
+void MohawkEngine_Riven::delayAndUpdate(uint32 ms) {
+ uint32 startTime = _system->getMillis();
+
+ while (_system->getMillis() < startTime + ms && !shouldQuit()) {
+ bool needsUpdate = _gfx->runScheduledWaterEffects();
+ needsUpdate |= _video->updateBackgroundMovies();
+
+ Common::Event event;
+ while (_system->getEventManager()->pollEvent(event))
+ ;
+
+ if (needsUpdate)
+ _system->updateScreen();
+
+ _system->delayMillis(10); // Ease off the CPU
+ }
+}
+
void MohawkEngine_Riven::runLoadDialog() {
- GUI::SaveLoadChooser slc("Load Game:", "Load");
+ GUI::SaveLoadChooser slc(_("Load game:"), _("Load"));
slc.setSaveMode(false);
Common::String gameId = ConfMan.get("gameid");
@@ -636,19 +680,19 @@ Common::Error MohawkEngine_Riven::saveGameState(int slot, const char *desc) {
return _saveLoad->saveGame(Common::String(desc)) ? Common::kNoError : Common::kUnknownError;
}
-static const char *rivenStackNames[] = {
- "aspit",
- "bspit",
- "gspit",
- "jspit",
- "ospit",
- "pspit",
- "rspit",
- "tspit"
-};
-
-Common::String MohawkEngine_Riven::getStackName(uint16 stack) {
- return Common::String(rivenStackNames[stack]);
+Common::String MohawkEngine_Riven::getStackName(uint16 stack) const {
+ static const char *rivenStackNames[] = {
+ "aspit",
+ "bspit",
+ "gspit",
+ "jspit",
+ "ospit",
+ "pspit",
+ "rspit",
+ "tspit"
+ };
+
+ return rivenStackNames[stack];
}
bool ZipMode::operator== (const ZipMode &z) const {
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 631285455e..251a0fc753 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -74,6 +74,7 @@ extern Common::Rect *g_cathJournalRect2;
extern Common::Rect *g_atrusJournalRect3;
extern Common::Rect *g_cathJournalRect3;
extern Common::Rect *g_trapBookRect3;
+extern Common::Rect *g_demoExitRect;
struct RivenHotspot {
uint16 blstID;
@@ -135,11 +136,11 @@ private:
uint16 _curCard;
uint16 _curStack;
void loadCard(uint16);
+ void handleEvents();
// Hotspot related functions and variables
uint16 _hotspotCount;
void loadHotspots(uint16);
- void checkHotspotChange();
void checkInventoryClick();
bool _showHotspots;
void updateZipMode();
@@ -153,41 +154,44 @@ private:
bool _ignoreNextMouseUp;
public:
- Common::SeekableReadStream *getExtrasResource(uint32 tag, uint16 id);
- bool _activatedSLST;
- void runLoadDialog();
-
+ // Stack/card/script funtions
void changeToCard(uint16 dest);
void changeToStack(uint16);
void refreshCard();
Common::String getName(uint16 nameResource, uint16 nameID);
- Common::String getStackName(uint16 stack);
+ Common::String getStackName(uint16 stack) const;
void runCardScript(uint16 scriptType);
void runUpdateScreenScript() { runCardScript(kCardUpdateScript); }
- uint16 getCurCard() { return _curCard; }
- uint16 getCurStack() { return _curStack; }
+ uint16 getCurCard() const { return _curCard; }
+ uint16 getCurStack() const { return _curStack; }
uint16 matchRMAPToCard(uint32);
uint32 getCurCardRMAP();
- Common::Point _mousePos;
+ // Hotspot functions/variables
RivenHotspot *_hotspots;
int32 _curHotspot;
Common::Array<ZipMode> _zipModeData;
- uint16 getHotspotCount() { return _hotspotCount; }
+ uint16 getHotspotCount() const { return _hotspotCount; }
void runHotspotScript(uint16 hotspot, uint16 scriptType);
- int32 getCurHotspot() { return _curHotspot; }
+ int32 getCurHotspot() const { return _curHotspot; }
Common::String getHotspotName(uint16 hotspot);
+ void checkHotspotChange();
+ // Variable functions
void initVars();
- uint32 getVarCount() { return _varCount; }
+ uint32 getVarCount() const { return _varCount; }
uint32 getGlobalVar(uint32 index);
Common::String getGlobalVarName(uint32 index);
uint32 *getLocalVar(uint32 index);
- uint32 *matchVarToString(Common::String varName);
- uint32 *matchVarToString(const char *varName);
+ uint32 *getVar(const Common::String &varName);
+ // Miscellaneous
void setGameOver() { _gameOver = true; }
void ignoreNextMouseUp() { _ignoreNextMouseUp = true; }
+ Common::SeekableReadStream *getExtrasResource(uint32 tag, uint16 id);
+ bool _activatedSLST;
+ void runLoadDialog();
+ void delayAndUpdate(uint32 ms);
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_cursors.h b/engines/mohawk/riven_cursors.h
index 7deaf9c33c..71cb8fd804 100644
--- a/engines/mohawk/riven_cursors.h
+++ b/engines/mohawk/riven_cursors.h
@@ -37,7 +37,7 @@ namespace Mohawk {
// 1 = Black (0x000000)
// 2 = Yellow (0xDCFF00)
////////////////////////////////////////
-static const byte zipModeCursor[] = {
+static const byte s_zipModeCursor[] = {
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -61,7 +61,7 @@ static const byte zipModeCursor[] = {
// Zip Mode Cursor Palette:
// Palette For The Zip Mode Cursor
////////////////////////////////////////
-static const byte zipModeCursorPalette[] = {
+static const byte s_zipModeCursorPalette[] = {
0x00, 0x00, 0x00, 0x00, // Black
0xDC, 0xFF, 0x00, 0x00, // Yellow
};
@@ -77,7 +77,7 @@ static const byte zipModeCursorPalette[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte objectHandCursor[] = {
+static const byte s_objectHandCursor[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 1, 2, 3, 1, 1, 1, 0, 0, 0, 0,
0, 0, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 0, 0, 0,
@@ -107,7 +107,7 @@ static const byte objectHandCursor[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte grabbingHandCursor[] = {
+static const byte s_grabbingHandCursor[] = {
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 2, 3, 1, 1, 1, 0, 0, 0,
0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 0,
@@ -134,7 +134,7 @@ static const byte grabbingHandCursor[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte standardHandCursor[] = {
+static const byte s_standardHandCursor[] = {
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 3, 1, 0, 0, 0, 0, 0, 0,
@@ -164,7 +164,7 @@ static const byte standardHandCursor[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingLeftCursor[] = {
+static const byte s_pointingLeftCursor[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1,
@@ -191,7 +191,7 @@ static const byte pointingLeftCursor[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingRightCursor[] = {
+static const byte s_pointingRightCursor[] = {
0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0,
1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
@@ -218,7 +218,7 @@ static const byte pointingRightCursor[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingDownCursorPalmUp[] = {
+static const byte s_pointingDownCursorPalmUp[] = {
0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0,
0, 0, 1, 4, 2, 2, 4, 2, 2, 2, 4, 1, 0,
0, 1, 3, 4, 2, 2, 4, 4, 4, 4, 4, 1, 0,
@@ -248,7 +248,7 @@ static const byte pointingDownCursorPalmUp[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingUpCursorPalmUp[] = {
+static const byte s_pointingUpCursorPalmUp[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0,
@@ -278,7 +278,7 @@ static const byte pointingUpCursorPalmUp[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingLeftCursorBent[] = {
+static const byte s_pointingLeftCursorBent[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1,
@@ -305,7 +305,7 @@ static const byte pointingLeftCursorBent[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingRightCursorBent[] = {
+static const byte s_pointingRightCursorBent[] = {
0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0,
1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
@@ -332,7 +332,7 @@ static const byte pointingRightCursorBent[] = {
// 3 = Brown (0x8A672F)
// 4 = Dark Peach (0xE89A62)
////////////////////////////////////////
-static const byte pointingDownCursorPalmDown[] = {
+static const byte s_pointingDownCursorPalmDown[] = {
0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
@@ -355,7 +355,7 @@ static const byte pointingDownCursorPalmDown[] = {
// Hand Cursor Palette:
// Palette For All Hand Cursors
////////////////////////////////////////
-static const byte handCursorPalette[] = {
+static const byte s_handCursorPalette[] = {
0x00, 0x00, 0x00, 0x00, // Black
0xED, 0xCD, 0x96, 0x00, // Light Peach
0x8A, 0x67, 0x2F, 0x00, // Brown
@@ -376,7 +376,7 @@ static const byte handCursorPalette[] = {
// 6 = Dark Green (0x2D3300)
// 7 = Darkest Gray (0x222222)
////////////////////////////////////////
-static const byte pelletCursor[] = {
+static const byte s_pelletCursor[] = {
0, 0, 1, 1, 2, 3, 0, 0,
0, 2, 1, 4, 1, 2, 5, 0,
4, 1, 4, 1, 2, 1, 5, 4,
@@ -391,7 +391,7 @@ static const byte pelletCursor[] = {
// Pellet Cursor Palette:
// Palette For The Pellet Cursor
////////////////////////////////////////
-static const byte pelletCursorPalette[] = {
+static const byte s_pelletCursorPalette[] = {
0x5D, 0x67, 0x30, 0x00,
0x5E, 0x33, 0x33, 0x00,
0x55, 0x55, 0x55, 0x00,
@@ -401,4 +401,270 @@ static const byte pelletCursorPalette[] = {
0x22, 0x22, 0x22, 0x00
};
+////////////////////////////////////////
+// Red Marble Cursor (12x12):
+// Cursor When Holding The Red Marble
+////////////////////////////////////////
+static const byte s_redMarbleCursor[] = {
+ 0, 0, 0, 0, 1, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 3, 4, 2, 5, 2, 2, 2, 2, 0, 0,
+ 0, 6, 1, 1, 2, 2, 5, 2, 2, 2, 2, 0,
+ 0, 6, 3, 4, 5, 2, 2, 7, 8, 5, 2, 0,
+ 9, 6, 10,11,2, 2, 2, 12,13,2, 2, 2,
+ 14,10,6, 4, 1, 2, 8, 2, 2, 5, 2, 2,
+ 15,16,6, 3, 1, 2, 2, 2, 2, 2, 2, 5,
+ 17,9,18, 3, 4, 4, 4, 5, 2, 5, 1, 2,
+ 0, 16,9, 6, 6, 19,1, 20,1, 4, 11,0,
+ 0, 17,15,18,9, 10,6, 10,3, 21,4, 0,
+ 0, 0, 18,15,9, 18,6, 22,10,23,0, 0,
+ 0, 0, 0, 0, 15,15,16,9, 0, 0, 0, 0
+};
+
+
+////////////////////////////////////////
+// Red Marble Cursor Palette:
+// Palette For The Red Marble Cursor
+////////////////////////////////////////
+static const byte s_redMarbleCursorPalette[] = {
+ 0xb8, 0x33, 0x32, 0x00,
+ 0xe5, 0x33, 0x31, 0x00,
+ 0x98, 0x06, 0x00, 0x00,
+ 0xb8, 0x00, 0x34, 0x00,
+ 0xe6, 0x00, 0x34, 0x00,
+ 0x7a, 0x04, 0x00, 0x00,
+ 0xe8, 0x9a, 0x62, 0x00,
+ 0xea, 0x31, 0x67, 0x00,
+ 0x6a, 0x03, 0x00, 0x00,
+ 0x8c, 0x00, 0x35, 0x00,
+ 0xb6, 0x36, 0x00, 0x00,
+ 0xed, 0xcd, 0x96, 0x00,
+ 0xe9, 0x66, 0x65, 0x00,
+ 0x5b, 0x35, 0x00, 0x00,
+ 0x5b, 0x02, 0x00, 0x00,
+ 0x5f, 0x00, 0x35, 0x00,
+ 0x4c, 0x01, 0x00, 0x00,
+ 0x5e, 0x33, 0x33, 0x00,
+ 0x89, 0x05, 0x00, 0x00,
+ 0xb6, 0x08, 0x00, 0x00,
+ 0xa7, 0x07, 0x00, 0x00,
+ 0x88, 0x36, 0x00, 0x00,
+ 0x8b, 0x33, 0x33, 0x00
+};
+
+////////////////////////////////////////
+// Orange Marble Cursor (12x12):
+// Cursor When Holding The Orange Marble
+////////////////////////////////////////
+static const byte s_orangeMarbleCursor[] = {
+ 0, 0, 0, 0, 1, 2, 2, 3, 0, 0, 0, 0,
+ 0, 0, 4, 5, 2, 2, 3, 3, 3, 3, 0, 0,
+ 0, 6, 7, 4, 2, 1, 2, 2, 3, 3, 3, 0,
+ 0, 6, 6, 7, 1, 2, 3, 8, 9, 2, 10,0,
+ 11,12,7, 4, 2, 3, 3, 13,9, 2, 2, 1,
+ 14,15,6, 4, 2, 16,3, 3, 2, 1, 1, 1,
+ 14,14,12,17,4, 2, 2, 1, 2, 1, 2, 1,
+ 14,18,12,6, 4, 4, 4, 19,2, 19,20,4,
+ 0, 14,14,15,6, 15,6, 4, 4, 4, 4, 0,
+ 0, 14,11,14,14,12,12,12,17,6, 17,0,
+ 0, 0, 14,14,17,14,17,6, 6, 17,0, 0,
+ 0, 0, 0, 0, 14,11,14,11,0, 0, 0, 0
+};
+
+////////////////////////////////////////
+// Orange Marble Cursor Palette:
+// Palette For The Orange Marble Cursor
+////////////////////////////////////////
+static const byte s_orangeMarbleCursorPalette[] = {
+ 0xe1, 0x9e, 0x00, 0x00,
+ 0xe3, 0x9b, 0x28, 0x00,
+ 0xe2, 0xcf, 0x20, 0x00,
+ 0xb5, 0x6a, 0x00, 0x00,
+ 0xb6, 0x9b, 0x29, 0x00,
+ 0x87, 0x69, 0x00, 0x00,
+ 0xb7, 0x67, 0x2f, 0x00,
+ 0xe9, 0xff, 0x93, 0x00,
+ 0xe1, 0xff, 0x5a, 0x00,
+ 0xe0, 0xd0, 0x00, 0x00,
+ 0x5e, 0x33, 0x33, 0x00,
+ 0x88, 0x36, 0x00, 0x00,
+ 0xf3, 0xff, 0xc9, 0x00,
+ 0x5b, 0x35, 0x00, 0x00,
+ 0x8b, 0x33, 0x33, 0x00,
+ 0xe6, 0xce, 0x5f, 0x00,
+ 0x8a, 0x67, 0x2f, 0x00,
+ 0x5d, 0x67, 0x30, 0x00,
+ 0xe2, 0x6a, 0x00, 0x00,
+ 0xb3, 0x9d, 0x00, 0x00
+};
+
+////////////////////////////////////////
+// Yellow Marble Cursor (12x12):
+// Cursor When Holding The Yellow Marble
+////////////////////////////////////////
+static const byte s_yellowMarbleCursor[] = {
+ 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0,
+ 0, 0, 3, 4, 1, 1, 1, 5, 6, 6, 0, 0,
+ 0, 3, 3, 7, 1, 1, 1, 1, 2, 1, 6, 0,
+ 0, 3, 3, 3, 3, 1, 1, 8, 6, 1, 6, 0,
+ 9, 9, 3, 3, 1, 1, 2, 10,8, 1, 1, 2,
+ 11,9, 3, 3, 1, 1, 1, 1, 1, 1, 5, 1,
+ 9, 9, 12,3, 3, 1, 1, 1, 1, 1, 1, 1,
+ 9, 9, 9, 3, 3, 3, 3, 3, 1, 1, 1, 1,
+ 0, 11,9, 9, 12,3, 3, 3, 3, 3, 3, 0,
+ 0, 9, 9, 13,9, 14,12,3, 3, 3, 3, 0,
+ 0, 0, 9, 9, 9, 12,14,3, 13,3, 0, 0,
+ 0, 0, 0, 0, 11,9, 11,9, 0, 0, 0, 0
+};
+
+////////////////////////////////////////
+// Yellow Marble Cursor Palette:
+// Palette For The Yellow Marble Cursor
+////////////////////////////////////////
+static const byte s_yellowMarbleCursorPalette[] = {
+ 0xb3, 0xd0, 0x00, 0x00,
+ 0xb0, 0xff, 0x00, 0x00,
+ 0x86, 0x9c, 0x00, 0x00,
+ 0x87, 0xd0, 0x00, 0x00,
+ 0xe0, 0xd0, 0x00, 0x00,
+ 0xdc, 0xff, 0x00, 0x00,
+ 0xb3, 0x9d, 0x00, 0x00,
+ 0xdc, 0xff, 0x11, 0x00,
+ 0x5a, 0x68, 0x00, 0x00,
+ 0xe1, 0xff, 0x5a, 0x00,
+ 0x5d, 0x67, 0x30, 0x00,
+ 0x87, 0x69, 0x00, 0x00,
+ 0x88, 0x9b, 0x2a, 0x00,
+ 0x5a, 0x9c, 0x00, 0x00
+};
+
+////////////////////////////////////////
+// Green Marble Cursor (12x12):
+// Cursor When Holding The Green Marble
+////////////////////////////////////////
+static const byte s_greenMarbleCursor[] = {
+ 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0,
+ 0, 0, 4, 5, 2, 1, 2, 3, 6, 6, 0, 0,
+ 0, 7, 5, 8, 8, 1, 1, 2, 3, 6, 6, 0,
+ 0, 7, 7, 4, 8, 1, 2, 9, 6, 2, 6, 0,
+ 10,7, 7, 4, 1, 2, 3, 11,12,2, 2, 3,
+ 13,13,7, 4, 1, 2, 3, 2, 1, 2, 2, 3,
+ 14,13,7, 7, 5, 1, 1, 8, 2, 1, 1, 2,
+ 15,16,13,7, 4, 4, 5, 5, 1, 8, 1, 1,
+ 0, 15,13,7, 7, 7, 4, 4, 4, 5, 8, 0,
+ 0, 14,16,15,13, 7, 7, 7, 4,17,5, 0,
+ 0, 0, 10,16,13,13,13,17,18,17,0, 0,
+ 0, 0, 0, 0, 15,10,19,10,0, 0, 0, 0
+};
+
+////////////////////////////////////////
+// Green Marble Cursor Palette:
+// Palette For The Green Marble Cursor
+////////////////////////////////////////
+static const byte s_greenMarbleCursorPalette[] = {
+ 0x0e, 0xd0, 0x00, 0x00,
+ 0x0f, 0xe1, 0x00, 0x00,
+ 0x10, 0xf2, 0x00, 0x00,
+ 0x0b, 0x9c, 0x00, 0x00,
+ 0x0c, 0xad, 0x00, 0x00,
+ 0x11, 0xff, 0x00, 0x00,
+ 0x09, 0x8a, 0x00, 0x00,
+ 0x0d, 0xbe, 0x00, 0x00,
+ 0x30, 0xff, 0x5a, 0x00,
+ 0x0d, 0x67, 0x30, 0x00,
+ 0x6b, 0xff, 0x92, 0x00,
+ 0x00, 0xff, 0x28, 0x00,
+ 0x08, 0x79, 0x00, 0x00,
+ 0x05, 0x57, 0x00, 0x00,
+ 0x30, 0x67, 0x30, 0x00,
+ 0x06, 0x68, 0x00, 0x00,
+ 0x00, 0x9b, 0x2c, 0x00,
+ 0x2e, 0x9c, 0x00, 0x00,
+ 0x2e, 0x68, 0x00, 0x00
+};
+
+////////////////////////////////////////
+// Blue Marble Cursor (12x12):
+// Cursor When Holding The Blue Marble
+////////////////////////////////////////
+static const byte s_blueMarbleCursor[] = {
+ 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0,
+ 0, 0, 4, 5, 2, 2, 6, 3, 7, 3, 0, 0,
+ 0, 8, 9, 5, 10,11,2, 6, 3, 3, 7, 0,
+ 0, 12,13,9, 10,11,6, 14,7, 6, 3, 0,
+ 15,8, 4, 13,2, 6, 3, 16,17,6, 6, 3,
+ 18,15,19,13,10,7, 3, 6, 2, 2, 6, 7,
+ 20,8, 18,4, 21,11,2, 10,6, 2, 2, 2,
+ 15,15,18,8, 13,9, 21,5, 11,10,2, 1,
+ 0, 8, 15,19,15,13,13,21,21,5, 9, 0,
+ 0, 22,20,15, 8,19,15,19,4, 9, 4, 0,
+ 0, 0, 15,20,15,15,19,15,9, 15,0, 0,
+ 0, 0, 0, 0, 20,15, 8,15,0, 0, 0, 0
+};
+
+////////////////////////////////////////
+// Blue Marble Cursor Palette:
+// Palette For The Blue Marble Cursor
+////////////////////////////////////////
+static const byte s_blueMarbleCursorPalette[] = {
+ 0x6b, 0x00, 0xd2, 0x00,
+ 0x66, 0x00, 0xe3, 0x00,
+ 0x72, 0x00, 0xff, 0x00,
+ 0x53, 0x2d, 0x9d, 0x00,
+ 0x4e, 0x00, 0xaf, 0x00,
+ 0x6d, 0x00, 0xf5, 0x00,
+ 0x7d, 0x00, 0xff, 0x00,
+ 0x44, 0x00, 0x69, 0x00,
+ 0x56, 0x00, 0x9d, 0x00,
+ 0x56, 0x00, 0xc0, 0x00,
+ 0x5e, 0x00, 0xd2, 0x00,
+ 0x2b, 0x31, 0x68, 0x00,
+ 0x3f, 0x00, 0x8c, 0x00,
+ 0x91, 0x22, 0xff, 0x00,
+ 0x41, 0x31, 0x68, 0x00,
+ 0xd7, 0x95, 0xff, 0x00,
+ 0x77, 0x22, 0xff, 0x00,
+ 0x2f, 0x00, 0x69, 0x00,
+ 0x37, 0x00, 0x7a, 0x00,
+ 0x27, 0x00, 0x58, 0x00,
+ 0x46, 0x00, 0x9d, 0x00,
+ 0x33, 0x33, 0x33, 0x00
+};
+
+////////////////////////////////////////
+// Violet Marble Cursor (12x12):
+// Cursor When Holding The Violet Marble
+////////////////////////////////////////
+static const byte s_violetMarbleCursor[] = {
+ 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0,
+ 0, 0, 3, 3, 1, 1, 1, 4, 2, 4, 0, 0,
+ 0, 3, 3, 3, 1, 5, 1, 1, 4, 2, 4, 0,
+ 0, 3, 3, 3, 3, 1, 1, 6, 4, 1, 2, 0,
+ 3, 7, 8, 3, 1, 1, 4, 9, 4, 1, 1, 4,
+ 8, 7, 8, 3, 10,4, 1, 1, 1, 1, 4, 1,
+ 8, 3, 8, 7, 3, 1, 1, 5, 1, 1, 1, 1,
+ 7, 7, 11,3, 3, 3, 3, 3, 1, 3, 1, 1,
+ 0, 8, 7, 7, 8, 8, 7, 3, 3, 3, 1, 0,
+ 0, 7, 8, 3, 11,7, 3, 11,3, 10,3, 0,
+ 0, 0, 8, 7, 3, 3, 7, 3, 3, 3, 0, 0,
+ 0, 0, 0, 0, 8, 7, 11,3, 0, 0, 0, 0
+};
+
+////////////////////////////////////////
+// Violet Marble Cursor Palette:
+// Palette For The Violet Marble Cursor
+////////////////////////////////////////
+static const byte s_violetMarbleCursorPalette[] = {
+ 0xaa, 0x00, 0xd1, 0x00,
+ 0xd8, 0x00, 0xff, 0x00,
+ 0x76, 0x00, 0x9d, 0x00,
+ 0xb5, 0x00, 0xff, 0x00,
+ 0x87, 0x00, 0xd2, 0x00,
+ 0xd7, 0x22, 0xff, 0x00,
+ 0x68, 0x00, 0x69, 0x00,
+ 0x44, 0x00, 0x69, 0x00,
+ 0xd7, 0x5e, 0xff, 0x00,
+ 0x9c, 0x00, 0x9d, 0x00,
+ 0x56, 0x00, 0x9d, 0x00
+};
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 67d621a54c..21464a6a48 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -34,8 +34,12 @@
namespace Mohawk {
+static const uint32 kDomeSliderDefaultState = 0x01F00000;
+static const uint32 kDomeSliderSlotCount = 25;
+
RivenExternal::RivenExternal(MohawkEngine_Riven *vm) : _vm(vm) {
setupCommands();
+ _sliderState = kDomeSliderDefaultState;
}
RivenExternal::~RivenExternal() {
@@ -64,6 +68,8 @@ void RivenExternal::setupCommands() {
COMMAND(xadisablemenureturn);
COMMAND(xaenablemenureturn);
COMMAND(xalaunchbrowser);
+ COMMAND(xadisablemenuintro);
+ COMMAND(xaenablemenuintro);
// bspit (Bookmaking Island) external commands
COMMAND(xblabopenbook);
@@ -200,16 +206,33 @@ void RivenExternal::runCommand(uint16 argc, uint16 *argv) {
}
void RivenExternal::runDemoBoundaryDialog() {
- GUI::MessageDialog dialog("This demo does not allow you\n"
- "to visit that part of Riven.");
+ GUI::MessageDialog dialog("Exploration beyond this point available only within the full version of\n"
+ "the game.");
dialog.runModal();
}
void RivenExternal::runEndGame(uint16 video) {
_vm->_sound->stopAllSLST();
- _vm->_video->playMovieBlocking(video);
+ _vm->_video->playMovie(video);
+ runCredits(video);
+}
+void RivenExternal::runCredits(uint16 video) {
// TODO: Play until the last frame and then run the credits
+
+ VideoHandle videoHandle = _vm->_video->findVideoHandle(video);
+
+ while (!_vm->_video->endOfVideo(videoHandle) && !_vm->shouldQuit()) {
+ if (_vm->_video->updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event))
+ ;
+
+ _vm->_system->delayMillis(10);
+ }
+
_vm->setGameOver();
}
@@ -231,7 +254,151 @@ void RivenExternal::runDomeCheck() {
// frame that is the magic one is the one with the golden symbol) but we
// give a 3 frame leeway in either direction.
if (frameCount - curFrame < 3 || curFrame < 3)
- *_vm->matchVarToString("domecheck") = 1;
+ *_vm->getVar("domecheck") = 1;
+}
+
+void RivenExternal::resetDomeSliders(uint16 bitmapId, uint16 soundId, uint16 startHotspot) {
+ // The rightmost slider should move left until it finds the next slider,
+ // then those two continue until they find the third slider. This continues
+ // until all five sliders have returned their starting slots.
+ byte slidersFound = 0;
+ for (uint32 i = 0; i < kDomeSliderSlotCount; i++) {
+ if (_sliderState & (1 << i)) {
+ // A slider occupies this spot. Increase the number of sliders we
+ // have found, but we're not doing any moving this iteration.
+ slidersFound++;
+ } else {
+ // Move all the sliders we have found over one slot
+ for (byte j = 0; j < slidersFound; j++) {
+ _sliderState &= ~(1 << (i - j - 1));
+ _sliderState |= 1 << (i - j);
+ }
+
+ // If we have at least one found slider, it has now moved
+ // so we should redraw and play a tick sound
+ if (slidersFound) {
+ _vm->_sound->playSound(soundId);
+ drawDomeSliders(bitmapId, startHotspot);
+ _vm->_system->delayMillis(10);
+ }
+ }
+ }
+
+ // Sanity checks - the slider count should always be 5 and we should end up at
+ // the default state after moving them all over.
+ assert(slidersFound == 5);
+ assert(_sliderState == kDomeSliderDefaultState);
+}
+
+void RivenExternal::checkDomeSliders(uint16 resetSlidersHotspot, uint16 openDomeHotspot) {
+ // Let's see if we're all matched up...
+ if (*_vm->getVar("adomecombo") == _sliderState) {
+ // Set the button hotspot to the open dome hotspot
+ _vm->_hotspots[resetSlidersHotspot].enabled = false;
+ _vm->_hotspots[openDomeHotspot].enabled = true;
+ } else {
+ // Set the button hotspot to the reset sliders hotspot
+ _vm->_hotspots[resetSlidersHotspot].enabled = true;
+ _vm->_hotspots[openDomeHotspot].enabled = false;
+ }
+}
+
+void RivenExternal::checkSliderCursorChange(uint16 startHotspot) {
+ // Set the cursor based on _sliderState and what hotspot we're over
+ for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
+ if (_vm->_hotspots[i + startHotspot].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
+ if (_sliderState & (1 << (24 - i)))
+ _vm->_gfx->changeCursor(kRivenOpenHandCursor);
+ else
+ _vm->_gfx->changeCursor(kRivenMainCursor);
+ break;
+ }
+ }
+}
+
+void RivenExternal::dragDomeSlider(uint16 bitmapId, uint16 soundId, uint16 resetSlidersHotspot, uint16 openDomeHotspot, uint16 startHotspot) {
+ int16 foundSlider = -1;
+
+ for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
+ if (_vm->_hotspots[i + startHotspot].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
+ // If the slider is not at this hotspot, we can't do anything else
+ if (!(_sliderState & (1 << (24 - i))))
+ return;
+
+ foundSlider = i;
+ break;
+ }
+ }
+
+ // We're not over any slider
+ if (foundSlider < 0)
+ return;
+
+ // We've clicked down, so show the closed hand cursor
+ _vm->_gfx->changeCursor(kRivenClosedHandCursor);
+
+ bool done = false;
+ while (!done) {
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ if (foundSlider < 24 && !(_sliderState & (1 << (23 - foundSlider))) && _vm->_hotspots[foundSlider + startHotspot + 1].rect.contains(event.mouse)) {
+ // We've moved the slider right one space
+ _sliderState &= ~(_sliderState & (1 << (24 - foundSlider)));
+ foundSlider++;
+ _sliderState |= 1 << (24 - foundSlider);
+
+ // Now play a click sound and redraw
+ _vm->_sound->playSound(soundId);
+ drawDomeSliders(bitmapId, startHotspot);
+ } else if (foundSlider > 0 && !(_sliderState & (1 << (25 - foundSlider))) && _vm->_hotspots[foundSlider + startHotspot - 1].rect.contains(event.mouse)) {
+ // We've moved the slider left one space
+ _sliderState &= ~(_sliderState & (1 << (24 - foundSlider)));
+ foundSlider--;
+ _sliderState |= 1 << (24 - foundSlider);
+
+ // Now play a click sound and redraw
+ _vm->_sound->playSound(soundId);
+ drawDomeSliders(bitmapId, startHotspot);
+ } else
+ _vm->_system->updateScreen(); // A normal update for the cursor
+ break;
+ case Common::EVENT_LBUTTONUP:
+ done = true;
+ break;
+ default:
+ break;
+ }
+ }
+ _vm->_system->delayMillis(10);
+ }
+
+ // Check to see if we have the right combination
+ checkDomeSliders(resetSlidersHotspot, openDomeHotspot);
+}
+
+void RivenExternal::drawDomeSliders(uint16 bitmapId, uint16 startHotspot) {
+ Common::Rect dstAreaRect = Common::Rect(200, 250, 420, 319);
+
+ // On pspit, the rect is different by two pixels
+ // (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this)
+ if (_vm->getCurStack() == pspit)
+ dstAreaRect.translate(-2, 0);
+
+ for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
+ Common::Rect srcRect = _vm->_hotspots[startHotspot + i].rect;
+ srcRect.translate(-dstAreaRect.left, -dstAreaRect.top); // Adjust the rect so it's in the destination area
+
+ Common::Rect dstRect = _vm->_hotspots[startHotspot + i].rect;
+
+ if (_sliderState & (1 << (24 - i)))
+ _vm->_gfx->drawImageRect(bitmapId, srcRect, dstRect);
+ else
+ _vm->_gfx->drawImageRect(bitmapId + 1, srcRect, dstRect);
+ }
+
+ _vm->_gfx->updateScreen();
}
// ------------------------------------------------------------------------------------
@@ -252,7 +419,7 @@ void RivenExternal::xasetupcomplete(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->matchVarToString("aatruspage");
+ uint32 page = *_vm->getVar("aatruspage");
// Set hotspots depending on the page
if (page == 1) {
@@ -271,13 +438,13 @@ void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- _vm->changeToStack(*_vm->matchVarToString("returnstackid"));
- _vm->changeToCard(*_vm->matchVarToString("returncardid"));
+ _vm->changeToStack(*_vm->getVar("returnstackid"));
+ _vm->changeToCard(*_vm->getVar("returncardid"));
}
void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->matchVarToString("aatruspage");
+ uint32 *page = _vm->getVar("aatruspage");
// Decrement the page if it's not the first page
if (*page == 1)
@@ -286,9 +453,9 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
// Play the page turning sound
if (_vm->getFeatures() & GF_DEMO)
- _vm->_sound->playSound(4, false);
+ _vm->_sound->playSound(4);
else
- _vm->_sound->playSound(3, false);
+ _vm->_sound->playSound(3);
// Now update the screen :)
_vm->_gfx->scheduleTransition(1);
@@ -297,7 +464,7 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->matchVarToString("aatruspage");
+ uint32 *page = _vm->getVar("aatruspage");
// Increment the page if it's not the last page
if (((_vm->getFeatures() & GF_DEMO) && *page == 6) || *page == 10)
@@ -306,9 +473,9 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
// Play the page turning sound
if (_vm->getFeatures() & GF_DEMO)
- _vm->_sound->playSound(5, false);
+ _vm->_sound->playSound(5);
else
- _vm->_sound->playSound(4, false);
+ _vm->_sound->playSound(4);
// Now update the screen :)
_vm->_gfx->scheduleTransition(0);
@@ -317,7 +484,7 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->matchVarToString("acathpage");
+ uint32 page = *_vm->getVar("acathpage");
// Set hotspots depending on the page
if (page == 1) {
@@ -340,19 +507,33 @@ void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
_vm->_gfx->drawPLST(51);
if (page == 28) {
- // TODO: Draw telescope combination
+ // Draw the telescope combination
+ // The images for the numbers are tBMP's 13 through 17.
+ // The start point is at (156, 247)
+ uint32 teleCombo = *_vm->getVar("tcorrectorder");
+ static const uint16 kNumberWidth = 32;
+ static const uint16 kNumberHeight = 25;
+ static const uint16 kDstX = 156;
+ static const uint16 kDstY = 247;
+
+ for (byte i = 0; i < 5; i++) {
+ uint16 offset = (getComboDigit(teleCombo, i) - 1) * kNumberWidth;
+ Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
+ Common::Rect dstRect = Common::Rect(i * kNumberWidth + kDstX, kDstY, (i + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
+ _vm->_gfx->drawImageRect(i + 13, srcRect, dstRect);
+ }
}
}
void RivenExternal::xacathbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- _vm->changeToStack(*_vm->matchVarToString("returnstackid"));
- _vm->changeToCard(*_vm->matchVarToString("returncardid"));
+ _vm->changeToStack(*_vm->getVar("returnstackid"));
+ _vm->changeToCard(*_vm->getVar("returncardid"));
}
void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 *page = _vm->matchVarToString("acathpage");
+ uint32 *page = _vm->getVar("acathpage");
// Increment the page if it's not the first page
if (*page == 1)
@@ -360,7 +541,7 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
(*page)--;
// Play the page turning sound
- _vm->_sound->playSound(5, false);
+ _vm->_sound->playSound(5);
// Now update the screen :)
_vm->_gfx->scheduleTransition(3);
@@ -369,7 +550,7 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 *page = _vm->matchVarToString("acathpage");
+ uint32 *page = _vm->getVar("acathpage");
// Increment the page if it's not the last page
if (*page == 49)
@@ -377,7 +558,7 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
(*page)++;
// Play the page turning sound
- _vm->_sound->playSound(6, false);
+ _vm->_sound->playSound(6);
// Now update the screen :)
_vm->_gfx->scheduleTransition(2);
@@ -386,27 +567,27 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) {
// Return to where we were before entering the book
- *_vm->matchVarToString("atrap") = 0;
- _vm->changeToStack(*_vm->matchVarToString("returnstackid"));
- _vm->changeToCard(*_vm->matchVarToString("returncardid"));
+ *_vm->getVar("atrap") = 0;
+ _vm->changeToStack(*_vm->getVar("returnstackid"));
+ _vm->changeToCard(*_vm->getVar("returncardid"));
}
void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
// Close the trap book
- *_vm->matchVarToString("atrap") = 0;
+ *_vm->getVar("atrap") = 0;
// Play the page turning sound
- _vm->_sound->playSound(8, false);
+ _vm->_sound->playSound(8);
_vm->refreshCard();
}
void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) {
// Open the trap book
- *_vm->matchVarToString("atrap") = 1;
+ *_vm->getVar("atrap") = 1;
// Play the page turning sound
- _vm->_sound->playSound(9, false);
+ _vm->_sound->playSound(9);
_vm->refreshCard();
}
@@ -417,42 +598,99 @@ void RivenExternal::xarestoregame(uint16 argc, uint16 *argv) {
}
void RivenExternal::xadisablemenureturn(uint16 argc, uint16 *argv) {
- // Dummy function -- implemented in Mohawk::go
+ // This function would normally enable the Windows menu item for
+ // returning to the main menu. Ctrl+r will do this instead.
+ // The original also had this shortcut.
}
void RivenExternal::xaenablemenureturn(uint16 argc, uint16 *argv) {
- // Dummy function -- implemented in Mohawk::go
+ // This function would normally enable the Windows menu item for
+ // returning to the main menu. Ctrl+r will do this instead.
+ // The original also had this shortcut.
}
void RivenExternal::xalaunchbrowser(uint16 argc, uint16 *argv) {
// Well, we can't launch a browser for obvious reasons ;)
+ // The original text is as follows (for reference):
+
+ // If you have an auto-dial configured connection to the Internet,
+ // please select YES below.
+ //
+ // America Online and CompuServe users may experience difficulty. If
+ // you find that you are unable to connect, please quit the Riven
+ // Demo, launch your browser and type in the following URL:
+ //
+ // www.redorb.com/buyriven
+ //
+ // Would you like to attempt to make the connection?
+ //
+ // [YES] [NO]
+
GUI::MessageDialog dialog("At this point, the Riven Demo would\n"
- "open up a web browser to bring you to\n"
- "the Riven website. ScummVM cannot do\n"
- "that. Visit the site on your own.");
+ "ask if you would like to open a web browser\n"
+ "to bring you to the Red Orb store to buy\n"
+ "the game. ScummVM cannot do that and\n"
+ "the site no longer exists.");
dialog.runModal();
}
+void RivenExternal::xadisablemenuintro(uint16 argc, uint16 *argv) {
+ // This function would normally enable the Windows menu item for
+ // playing the intro. Ctrl+p will play the intro movies instead.
+ // The original also had this shortcut.
+
+ // Hide the "exit" button here
+ _vm->_gfx->hideInventory();
+}
+
+void RivenExternal::xaenablemenuintro(uint16 argc, uint16 *argv) {
+ // This function would normally enable the Windows menu item for
+ // playing the intro. Ctrl+p will play the intro movies instead.
+ // The original also had this shortcut.
+
+ // Show the "exit" button here
+ _vm->_gfx->showInventory();
+}
+
// ------------------------------------------------------------------------------------
// bspit (Bookmaking Island) external commands
// ------------------------------------------------------------------------------------
void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
// Get the variable
- uint32 page = *_vm->matchVarToString("blabbook");
+ uint32 page = *_vm->getVar("blabbook");
// Draw the image of the page based on the blabbook variable
_vm->_gfx->drawPLST(page);
- // TODO: Draw the dome combo
if (page == 14) {
- warning ("Need to draw dome combo");
+ // Draw the dome combination
+ // The images for the numbers are tBMP's 364 through 368
+ // The start point is at (240, 82)
+ uint32 domeCombo = *_vm->getVar("adomecombo");
+ static const uint16 kNumberWidth = 32;
+ static const uint16 kNumberHeight = 24;
+ static const uint16 kDstX = 240;
+ static const uint16 kDstY = 82;
+ byte numCount = 0;
+
+ for (int bitPos = 24; bitPos >= 0; bitPos--) {
+ if (domeCombo & (1 << bitPos)) {
+ uint16 offset = (24 - bitPos) * kNumberWidth;
+ Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
+ Common::Rect dstRect = Common::Rect(numCount * kNumberWidth + kDstX, kDstY, (numCount + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
+ _vm->_gfx->drawImageRect(numCount + 364, srcRect, dstRect);
+ numCount++;
+ }
+ }
+
+ assert(numCount == 5); // Sanity check
}
}
void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->matchVarToString("blabbook");
+ uint32 *page = _vm->getVar("blabbook");
// Decrement the page if it's not the first page
if (*page == 1)
@@ -460,7 +698,7 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
(*page)--;
// Play the page turning sound
- _vm->_sound->playSound(22, false);
+ _vm->_sound->playSound(22);
// Now update the screen :)
_vm->_gfx->scheduleTransition(1);
@@ -469,7 +707,7 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->matchVarToString("blabbook");
+ uint32 *page = _vm->getVar("blabbook");
// Increment the page if it's not the last page
if (*page == 22)
@@ -477,7 +715,7 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
(*page)++;
// Play the page turning sound
- _vm->_sound->playSound(23, false);
+ _vm->_sound->playSound(23);
// Now update the screen :)
_vm->_gfx->scheduleTransition(0);
@@ -485,8 +723,8 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
}
void RivenExternal::xsoundplug(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->matchVarToString("bheat");
- uint32 boilerInactive = *_vm->matchVarToString("bcratergg");
+ uint32 heat = *_vm->getVar("bheat");
+ uint32 boilerInactive = *_vm->getVar("bcratergg");
if (heat != 0)
_vm->_sound->playSLST(1, _vm->getCurCard());
@@ -497,58 +735,64 @@ void RivenExternal::xsoundplug(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->matchVarToString("bheat");
- uint32 water = *_vm->matchVarToString("bblrwtr");
- uint32 platform = *_vm->matchVarToString("bblrgrt");
+ uint32 heat = *_vm->getVar("bheat");
+ uint32 water = *_vm->getVar("bblrwtr");
+ uint32 platform = *_vm->getVar("bblrgrt");
+
+ // Stop any background videos
+ _vm->_video->stopVideos();
if (argv[0] == 1) {
+ // Water is filling/draining from the boiler
if (water == 0) {
- if (platform == 0)
- _vm->_video->activateMLST(10, _vm->getCurCard());
- else
+ if (platform == 1)
_vm->_video->activateMLST(12, _vm->getCurCard());
- } else if (heat == 0) {
- if (platform == 0)
- _vm->_video->activateMLST(19, _vm->getCurCard());
else
+ _vm->_video->activateMLST(10, _vm->getCurCard());
+ } else if (heat == 1) {
+ if (platform == 1)
_vm->_video->activateMLST(22, _vm->getCurCard());
- } else {
- if (platform == 0)
- _vm->_video->activateMLST(13, _vm->getCurCard());
else
+ _vm->_video->activateMLST(19, _vm->getCurCard());
+ } else {
+ if (platform == 1)
_vm->_video->activateMLST(16, _vm->getCurCard());
+ else
+ _vm->_video->activateMLST(13, _vm->getCurCard());
}
} else if (argv[0] == 2 && water != 0) {
- if (heat == 0) {
- if (platform == 0)
- _vm->_video->activateMLST(20, _vm->getCurCard());
- else
+ if (heat == 1) {
+ // Turning on the heat
+ if (platform == 1)
_vm->_video->activateMLST(23, _vm->getCurCard());
+ else
+ _vm->_video->activateMLST(20, _vm->getCurCard());
} else {
- if (platform == 0)
+ // Turning off the heat
+ if (platform == 1)
_vm->_video->activateMLST(18, _vm->getCurCard());
else
_vm->_video->activateMLST(15, _vm->getCurCard());
}
} else if (argv[0] == 3) {
- if (platform == 0) {
- if (water == 0) {
- _vm->_video->activateMLST(11, _vm->getCurCard());
- } else {
- if (heat == 0)
- _vm->_video->activateMLST(17, _vm->getCurCard());
- else
+ if (platform == 1) {
+ // Lowering the platform
+ if (water == 1) {
+ if (heat == 1)
_vm->_video->activateMLST(24, _vm->getCurCard());
- }
- } else {
- if (water == 0) {
- _vm->_video->activateMLST(9, _vm->getCurCard());
- } else {
- if (heat == 0)
- _vm->_video->activateMLST(14, _vm->getCurCard());
else
+ _vm->_video->activateMLST(17, _vm->getCurCard());
+ } else
+ _vm->_video->activateMLST(11, _vm->getCurCard());
+ } else {
+ // Raising the platform
+ if (water == 1) {
+ if (heat == 1)
_vm->_video->activateMLST(21, _vm->getCurCard());
- }
+ else
+ _vm->_video->activateMLST(14, _vm->getCurCard());
+ } else
+ _vm->_video->activateMLST(9, _vm->getCurCard());
}
}
@@ -557,27 +801,26 @@ void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
else if (argv[0] == 2)
_vm->_sound->playSLST(1, _vm->getCurCard());
- _vm->_video->playMovie(11);
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(11);
}
void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
- uint32 heat = *_vm->matchVarToString("bheat");
- uint32 platform = *_vm->matchVarToString("bblrgrt");
+ uint32 heat = *_vm->getVar("bheat");
+ uint32 platform = *_vm->getVar("bblrgrt");
if (heat) {
if (platform == 0) {
- _vm->_video->activateMLST(7, _vm->getCurCard());
- _vm->_video->playMovie(7);
- } else {
_vm->_video->activateMLST(8, _vm->getCurCard());
_vm->_video->playMovie(8);
+ } else {
+ _vm->_video->activateMLST(7, _vm->getCurCard());
+ _vm->_video->playMovie(7);
}
} else {
- _vm->_video->stopMovie(7);
- _vm->_video->stopMovie(8);
+ _vm->_video->disableMovie(7);
+ _vm->_video->disableMovie(8);
}
-
- _vm->refreshCard();
}
void RivenExternal::xbsettrap(uint16 argc, uint16 *argv) {
@@ -613,7 +856,7 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) {
// Set the bait if we put it on the plate
if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *_vm->matchVarToString("bbait") = 1;
+ *_vm->getVar("bbait") = 1;
_vm->_gfx->drawPLST(4);
_vm->_gfx->updateScreen();
_vm->_hotspots[3].enabled = false; // Disable bait hotspot
@@ -652,32 +895,32 @@ void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) {
// Set the bait if we put it on the plate, remove otherwise
if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
- *_vm->matchVarToString("bbait") = 1;
+ *_vm->getVar("bbait") = 1;
_vm->_gfx->drawPLST(4);
_vm->_gfx->updateScreen();
_vm->_hotspots[3].enabled = false; // Disable bait hotspot
_vm->_hotspots[9].enabled = true; // Enable baitplate hotspot
} else {
- *_vm->matchVarToString("bbait") = 0;
+ *_vm->getVar("bbait") = 0;
_vm->_hotspots[3].enabled = true; // Enable bait hotspot
_vm->_hotspots[9].enabled = false; // Disable baitplate hotspot
}
}
void RivenExternal::xbisland190_opencard(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkDomeSliders(27, 28);
}
void RivenExternal::xbisland190_resetsliders(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ resetDomeSliders(701, 41, 2);
}
void RivenExternal::xbisland190_slidermd(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ dragDomeSlider(701, 41, 27, 28, 2);
}
void RivenExternal::xbisland190_slidermw(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkSliderCursorChange(2);
}
void RivenExternal::xbscpbtn(uint16 argc, uint16 *argv) {
@@ -689,15 +932,17 @@ void RivenExternal::xbisland_domecheck(uint16 argc, uint16 *argv) {
}
void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
+ Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
+
// Get the variable for the valve
- uint32 *valve = _vm->matchVarToString("bvalve");
+ uint32 *valve = _vm->getVar("bvalve");
int changeX = 0;
int changeY = 0;
bool done = false;
// Set the cursor to the closed position
- _vm->_gfx->changeCursor(2004);
+ _vm->_gfx->changeCursor(kRivenClosedHandCursor);
_vm->_system->updateScreen();
while (!done) {
@@ -706,8 +951,8 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
- changeX = event.mouse.x - _vm->_mousePos.x;
- changeY = _vm->_mousePos.y - event.mouse.y;
+ changeX = event.mouse.x - startPos.x;
+ changeY = startPos.y - event.mouse.y;
_vm->_system->updateScreen();
break;
case Common::EVENT_LBUTTONUP:
@@ -746,26 +991,26 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
// If we changed state and the new state is that the valve is flowing to
// the boiler, we need to update the boiler state.
if (*valve == 1) {
- if (*_vm->matchVarToString("bidvlv") == 1) { // Check which way the water is going at the boiler
- if (*_vm->matchVarToString("bblrarm") == 1) {
+ if (*_vm->getVar("bidvlv") == 1) { // Check which way the water is going at the boiler
+ if (*_vm->getVar("bblrarm") == 1) {
// If the pipe is open, make sure the water is drained out
- *_vm->matchVarToString("bheat") = 0;
- *_vm->matchVarToString("bblrwtr") = 0;
+ *_vm->getVar("bheat") = 0;
+ *_vm->getVar("bblrwtr") = 0;
} else {
// If the pipe is closed, fill the boiler again
- *_vm->matchVarToString("bheat") = *_vm->matchVarToString("bblrvalve");
- *_vm->matchVarToString("bblrwtr") = 1;
+ *_vm->getVar("bheat") = *_vm->getVar("bblrvalve");
+ *_vm->getVar("bblrwtr") = 1;
}
} else {
// Have the grating inside the boiler match the switch outside
- *_vm->matchVarToString("bblrgrt") = (*_vm->matchVarToString("bblrsw") == 1) ? 0 : 1;
+ *_vm->getVar("bblrgrt") = (*_vm->getVar("bblrsw") == 1) ? 0 : 1;
}
}
}
void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
// Why is this an external command....?
- if (*_vm->matchVarToString("bvalve") == 2)
+ if (*_vm->getVar("bvalve") == 2)
_vm->_video->playMovieBlocking(2);
}
@@ -786,19 +1031,19 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) {
}
void RivenExternal::xgisland25_opencard(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkDomeSliders(29, 30);
}
void RivenExternal::xgisland25_resetsliders(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ resetDomeSliders(161, 16, 2);
}
void RivenExternal::xgisland25_slidermd(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ dragDomeSlider(161, 16, 29, 30, 2);
}
void RivenExternal::xgisland25_slidermw(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkSliderCursorChange(2);
}
void RivenExternal::xgscpbtn(uint16 argc, uint16 *argv) {
@@ -810,18 +1055,20 @@ void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) {
}
void RivenExternal::xgplateau3160_dopools(uint16 argc, uint16 *argv) {
- // TODO: "Bubble" map related
+ // Play the deactivation of a pool if one is active and a different one is activated
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlocking(*_vm->getVar("glkbtns") * 2);
}
void RivenExternal::xgwt200_scribetime(uint16 argc, uint16 *argv) {
// Get the current time
- *_vm->matchVarToString("gscribetime") = _vm->_system->getMillis();
+ *_vm->getVar("gscribetime") = _vm->_system->getMillis();
}
void RivenExternal::xgwt900_scribe(uint16 argc, uint16 *argv) {
- uint32 *scribeVar = _vm->matchVarToString("gscribe");
+ uint32 *scribeVar = _vm->getVar("gscribe");
- if (*scribeVar == 1 && _vm->_system->getMillis() > *_vm->matchVarToString("gscribetime") + 40000)
+ if (*scribeVar == 1 && _vm->_system->getMillis() > *_vm->getVar("gscribetime") + 40000)
*scribeVar = 2;
}
@@ -863,9 +1110,9 @@ void RivenExternal::xglview_villageon(uint16 argc, uint16 *argv) {
void RivenExternal::xreseticons(uint16 argc, uint16 *argv) {
// Reset the icons when going to Tay (rspit)
- *_vm->matchVarToString("jicons") = 0;
- *_vm->matchVarToString("jiconorder") = 0;
- *_vm->matchVarToString("jrbook") = 0;
+ *_vm->getVar("jicons") = 0;
+ *_vm->getVar("jiconorder") = 0;
+ *_vm->getVar("jrbook") = 0;
}
// Count up how many icons are pressed
@@ -886,30 +1133,30 @@ static byte countDepressedIcons(uint32 iconOrderVar) {
void RivenExternal::xicon(uint16 argc, uint16 *argv) {
// Set atemp as the status of whether or not the icon can be depressed.
- if (*_vm->matchVarToString("jicons") & (1 << (argv[0] - 1))) {
+ if (*_vm->getVar("jicons") & (1 << (argv[0] - 1))) {
// This icon is depressed. Allow depression only if the last depressed icon was this one.
- if ((*_vm->matchVarToString("jiconorder") & 0x1f) == argv[0])
- *_vm->matchVarToString("atemp") = 1;
+ if ((*_vm->getVar("jiconorder") & 0x1f) == argv[0])
+ *_vm->getVar("atemp") = 1;
else
- *_vm->matchVarToString("atemp") = 2;
+ *_vm->getVar("atemp") = 2;
} else
- *_vm->matchVarToString("atemp") = 0;
+ *_vm->getVar("atemp") = 0;
}
void RivenExternal::xcheckicons(uint16 argc, uint16 *argv) {
// Reset the icons if this is the sixth icon
- uint32 *iconOrderVar = _vm->matchVarToString("jiconorder");
+ uint32 *iconOrderVar = _vm->getVar("jiconorder");
if (countDepressedIcons(*iconOrderVar) == 5) {
*iconOrderVar = 0;
- *_vm->matchVarToString("jicons") = 0;
- _vm->_sound->playSound(46, false);
+ *_vm->getVar("jicons") = 0;
+ _vm->_sound->playSound(46);
}
}
void RivenExternal::xtoggleicon(uint16 argc, uint16 *argv) {
// Get the variables
- uint32 *iconsDepressed = _vm->matchVarToString("jicons");
- uint32 *iconOrderVar = _vm->matchVarToString("jiconorder");
+ uint32 *iconsDepressed = _vm->getVar("jicons");
+ uint32 *iconOrderVar = _vm->getVar("jiconorder");
if (*iconsDepressed & (1 << (argv[0] - 1))) {
// The icon is depressed, now unpress it
@@ -922,13 +1169,13 @@ void RivenExternal::xtoggleicon(uint16 argc, uint16 *argv) {
}
// Check if the puzzle is complete now and assign 1 to jrbook if the puzzle is complete.
- if (*iconOrderVar == *_vm->matchVarToString("jiconcorrectorder"))
- *_vm->matchVarToString("jrbook") = 1;
+ if (*iconOrderVar == *_vm->getVar("jiconcorrectorder"))
+ *_vm->getVar("jrbook") = 1;
}
void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->matchVarToString("jicons");
+ uint32 iconsDepressed = *_vm->getVar("jicons");
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 0))
@@ -949,7 +1196,7 @@ void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->matchVarToString("jicons");
+ uint32 iconsDepressed = *_vm->getVar("jicons");
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 9))
@@ -972,7 +1219,7 @@ void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->matchVarToString("jicons");
+ uint32 iconsDepressed = *_vm->getVar("jicons");
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 3))
@@ -993,7 +1240,7 @@ void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
// Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = *_vm->matchVarToString("jicons");
+ uint32 iconsDepressed = *_vm->getVar("jicons");
// Now, draw which icons are depressed based on the bits of the variable
if (iconsDepressed & (1 << 16))
@@ -1027,7 +1274,7 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
_vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again
_vm->_video->playMovieBlocking(2);
- uint32 *gallows = _vm->matchVarToString("jgallows");
+ uint32 *gallows = _vm->getVar("jgallows");
if (*gallows == 1) {
// If the gallows is open, play the up movie and return
_vm->_video->playMovieBlocking(3);
@@ -1072,15 +1319,15 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
}
void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ resetDomeSliders(_vm->getFeatures() & GF_DVD ? 547 : 548, 81, 2);
}
void RivenExternal::xjdome25_slidermd(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ dragDomeSlider(_vm->getFeatures() & GF_DVD ? 547: 548, 81, 29, 28, 2);
}
void RivenExternal::xjdome25_slidermw(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkSliderCursorChange(2);
}
void RivenExternal::xjscpbtn(uint16 argc, uint16 *argv) {
@@ -1092,18 +1339,20 @@ void RivenExternal::xjisland3500_domecheck(uint16 argc, uint16 *argv) {
}
int RivenExternal::jspitElevatorLoop() {
+ Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
+
Common::Event event;
int changeLevel = 0;
- _vm->_gfx->changeCursor(2004);
+ _vm->_gfx->changeCursor(kRivenClosedHandCursor);
_vm->_system->updateScreen();
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
- if (event.mouse.y > (_vm->_mousePos.y + 10)) {
+ if (event.mouse.y > (startPos.y + 10)) {
changeLevel = -1;
- } else if (event.mouse.y < (_vm->_mousePos.y - 10)) {
+ } else if (event.mouse.y < (startPos.y - 10)) {
changeLevel = 1;
} else {
changeLevel = 0;
@@ -1157,7 +1406,7 @@ void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlocking(6);
// If the whark's mouth is open, close it
- uint32 *mouthVar = _vm->matchVarToString("jwmouth");
+ uint32 *mouthVar = _vm->getVar("jwmouth");
if (*mouthVar == 1) {
_vm->_video->playMovieBlocking(3);
_vm->_video->playMovieBlocking(8);
@@ -1176,27 +1425,27 @@ void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
void RivenExternal::xjplaybeetle_550(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->matchVarToString("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_600(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->matchVarToString("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_950(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->matchVarToString("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_1050(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time
- *_vm->matchVarToString("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+ *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
}
void RivenExternal::xjplaybeetle_1450(uint16 argc, uint16 *argv) {
// Play a beetle animation 25% of the time as long as the girl is not present
- *_vm->matchVarToString("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && *_vm->matchVarToString("jgirl") != 1) ? 1 : 0;
+ *_vm->getVar("jplaybeetle") = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && *_vm->getVar("jgirl") != 1) ? 1 : 0;
}
void RivenExternal::xjlagoon700_alert(uint16 argc, uint16 *argv) {
@@ -1209,7 +1458,7 @@ void RivenExternal::xjlagoon800_alert(uint16 argc, uint16 *argv) {
void RivenExternal::xjlagoon1500_alert(uint16 argc, uint16 *argv) {
// Have the sunners move a bit as you get closer ;)
- uint32 *sunners = _vm->matchVarToString("jsunners");
+ uint32 *sunners = _vm->getVar("jsunners");
if (*sunners == 0) {
_vm->_video->playMovieBlocking(3);
} else if (*sunners == 1) {
@@ -1234,14 +1483,14 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) {
// WORKAROUND: The special change stuff only handles one destination and it would
// be messy to modify the way that currently works. If we use the trap book on Tay,
// we should be using the Tay end game sequences.
- if (*_vm->matchVarToString("returnstackid") == rspit) {
+ if (*_vm->getVar("returnstackid") == rspit) {
_vm->changeToStack(rspit);
_vm->changeToCard(2);
return;
}
// You used the trap book... why? What were you thinking?
- uint32 *gehnState = _vm->matchVarToString("agehn");
+ uint32 *gehnState = _vm->getVar("agehn");
if (*gehnState == 0) // Gehn who?
runEndGame(1);
@@ -1252,16 +1501,127 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) {
}
void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
- // TODO: This fun external command is probably one of the most complex,
- // up there with the marble puzzle ones. It involves so much... Basically,
- // it's playing when Gehn holds the trap book up to you and you have to
- // click on the book (hence the name of the function). Yeah, not fun.
- // Lots of timing stuff needs to be done for a couple videos.
+ // Hide the cursor
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+
+ // Let's hook onto our video
+ VideoHandle video = _vm->_video->findVideoHandle(argv[0]);
+
+ // Convert from the standard QuickTime base time to milliseconds
+ // The values are in terms of 1/600 of a second.
+ // Have I said how much I just *love* QuickTime? </sarcasm>
+ uint32 startTime = argv[1] * 1000 / 600;
+ uint32 endTime = argv[2] * 1000 / 600;
+
+ // Track down our hotspot
+ // Of course, they're not in any sane order...
+ static const uint16 hotspotMap[] = { 1, 3, 2, 0 };
+ Common::Rect hotspotRect = _vm->_hotspots[hotspotMap[argv[3] - 1]].rect;
+
+ debug(0, "xbookclick:");
+ debug(0, "\tVideo Code = %d", argv[0]);
+ debug(0, "\tStart Time = %dms", startTime);
+ debug(0, "\tEnd Time = %dms", endTime);
+ debug(0, "\tHotspot = %d -> %d", argv[3], hotspotMap[argv[3] - 1]);
+
+ // Just let the video play while we wait until Gehn opens the trap book for us
+ while (_vm->_video->getElapsedTime(video) < startTime && !_vm->shouldQuit()) {
+ if (_vm->_video->updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event))
+ ;
+
+ _vm->_system->delayMillis(10);
+ }
+
+ // Break out if we're quitting
+ if (_vm->shouldQuit())
+ return;
+
+ // Update our hotspot stuff
+ if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos()))
+ _vm->_gfx->changeCursor(kRivenOpenHandCursor);
+ else
+ _vm->_gfx->changeCursor(kRivenMainCursor);
+
+ // OK, Gehn has opened the trap book and has asked us to go in. Let's watch
+ // and see what the player will do...
+ while (_vm->_video->getElapsedTime(video) < endTime && !_vm->shouldQuit()) {
+ bool updateScreen = _vm->_video->updateBackgroundMovies();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos()))
+ _vm->_gfx->changeCursor(kRivenOpenHandCursor);
+ else
+ _vm->_gfx->changeCursor(kRivenMainCursor);
+ updateScreen = false; // Don't update twice, changing the cursor already updates the screen
+ break;
+ case Common::EVENT_LBUTTONUP:
+ if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) {
+ // OK, we've used the trap book! We go for ride lady!
+ _vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage)
+ _vm->_video->stopVideos(); // Stop all videos
+ _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_gfx->drawPLST(3); // Black out the screen
+ _vm->_gfx->updateScreen(); // Update the screen
+ _vm->_sound->playSound(0); // Play the link sound
+ _vm->_video->activateMLST(7, _vm->getCurCard()); // Activate Gehn Link Video
+ _vm->_video->playMovieBlocking(1); // Play Gehn Link Video
+ *_vm->getVar("agehn") = 4; // Set Gehn to the trapped state
+ *_vm->getVar("atrapbook") = 1; // We've got the trap book again
+ _vm->_sound->playSound(0); // Play the link sound again
+ _vm->changeToCard(_vm->matchRMAPToCard(0x2885)); // Link out! (TODO: Shouldn't this card change?)
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (updateScreen && !_vm->shouldQuit())
+ _vm->_system->updateScreen();
+
+ _vm->_system->delayMillis(10);
+ }
+
+ // Break out if we're quitting
+ if (_vm->shouldQuit())
+ return;
+
+ // Hide the cursor again
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+
+ // If there was no click and this is the third time Gehn asks us to
+ // use the trap book, he will shoot the player. Dead on arrival.
+ // Run the credits from here.
+ if (*_vm->getVar("agehn") == 3) {
+ _vm->_scriptMan->stopAllScripts();
+ runCredits(argv[0]);
+ return;
+ }
+
+ // There was no click, so just play the rest of the video.
+ while (!_vm->_video->endOfVideo(video) && !_vm->shouldQuit()) {
+ if (_vm->_video->updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event))
+ ;
+
+ _vm->_system->delayMillis(10);
+ }
}
void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
// Close the blank linking book if it's open
- uint32 *book = _vm->matchVarToString("odeskbook");
+ uint32 *book = _vm->getVar("odeskbook");
if (*book != 1)
return;
@@ -1284,16 +1644,16 @@ void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
void RivenExternal::xobedroom5_closedrawer(uint16 argc, uint16 *argv) {
// Close the drawer if open when clicking on the journal.
_vm->_video->playMovieBlocking(2);
- *_vm->matchVarToString("ostanddrawer") = 0;
+ *_vm->getVar("ostanddrawer") = 0;
}
void RivenExternal::xogehnopenbook(uint16 argc, uint16 *argv) {
- _vm->_gfx->drawPLST(*_vm->matchVarToString("ogehnpage"));
+ _vm->_gfx->drawPLST(*_vm->getVar("ogehnpage"));
}
void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->matchVarToString("ogehnpage");
+ uint32 *page = _vm->getVar("ogehnpage");
// Decrement the page if it's not the first page
if (*page == 1)
@@ -1301,7 +1661,7 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
(*page)--;
// Play the page turning sound
- _vm->_sound->playSound(12, false);
+ _vm->_sound->playSound(12);
// Now update the screen :)
_vm->_gfx->scheduleTransition(1);
@@ -1310,7 +1670,7 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
// Get the page variable
- uint32 *page = _vm->matchVarToString("ogehnpage");
+ uint32 *page = _vm->getVar("ogehnpage");
// Increment the page if it's not the last page
if (*page == 13)
@@ -1318,7 +1678,7 @@ void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
(*page)++;
// Play the page turning sound
- _vm->_sound->playSound(13, false);
+ _vm->_sound->playSound(13);
// Now update the screen :)
_vm->_gfx->scheduleTransition(0);
@@ -1334,7 +1694,7 @@ void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
// Hide the cursor
_vm->_gfx->changeCursor(kRivenHideCursor);
- uint32 *prisonCombo = _vm->matchVarToString("pcorrectorder");
+ uint32 *prisonCombo = _vm->getVar("pcorrectorder");
uint32 soundTime = _vm->_system->getMillis() - 500; // Start the first sound instantly
byte curSound = 0;
@@ -1371,19 +1731,19 @@ void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
void RivenExternal::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
// Play button sound based on argv[0]
- _vm->_sound->playSound(argv[0] + 5, false);
+ _vm->_sound->playSound(argv[0] + 5);
// It is impossible to get here if Gehn is not trapped. However,
// the original also disallows brute forcing the ending if you have
// not yet trapped Gehn.
- if (*_vm->matchVarToString("agehn") != 4)
+ if (*_vm->getVar("agehn") != 4)
return;
- uint32 *correctDigits = _vm->matchVarToString("pelevcombo");
+ uint32 *correctDigits = _vm->getVar("pelevcombo");
// pelevcombo keeps count of how many buttons we have pressed in the correct order.
// When pelevcombo is 5, clicking the handle will show the video freeing Catherine.
- if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->matchVarToString("pcorrectorder"), *correctDigits))
+ if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->getVar("pcorrectorder"), *correctDigits))
*correctDigits += 1;
else
*correctDigits = 0;
@@ -1398,19 +1758,19 @@ void RivenExternal::xpisland290_domecheck(uint16 argc, uint16 *argv) {
}
void RivenExternal::xpisland25_opencard(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkDomeSliders(31, 5);
}
void RivenExternal::xpisland25_resetsliders(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ resetDomeSliders(58, 10, 6);
}
void RivenExternal::xpisland25_slidermd(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ dragDomeSlider(58, 10, 31, 5, 6);
}
void RivenExternal::xpisland25_slidermw(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkSliderCursorChange(6);
}
// ------------------------------------------------------------------------------------
@@ -1430,8 +1790,8 @@ void RivenExternal::xrcredittime(uint16 argc, uint16 *argv) {
void RivenExternal::xrshowinventory(uint16 argc, uint16 *argv) {
// Give the trap book and Catherine's journal to the player
- *_vm->matchVarToString("atrapbook") = 1;
- *_vm->matchVarToString("acathbook") = 1;
+ *_vm->getVar("atrapbook") = 1;
+ *_vm->getVar("acathbook") = 1;
_vm->_gfx->showInventory();
}
@@ -1452,29 +1812,29 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlocking(3);
// Don't do anything else if the telescope power is off
- if (*_vm->matchVarToString("ttelevalve") == 0)
+ if (*_vm->getVar("ttelevalve") == 0)
return;
- uint32 *telescopePos = _vm->matchVarToString("ttelescope");
- uint32 *telescopeCover = _vm->matchVarToString("ttelecover");
+ uint32 *telescopePos = _vm->getVar("ttelescope");
+ uint32 *telescopeCover = _vm->getVar("ttelecover");
if (*telescopePos == 1) {
// We're at the bottom, which means one of two things can happen...
- if (*telescopeCover == 1 && *_vm->matchVarToString("ttelepin") == 1) {
+ if (*telescopeCover == 1 && *_vm->getVar("ttelepin") == 1) {
// ...if the cover is open and the pin is up, the game is now over.
- if (*_vm->matchVarToString("pcage") == 2) {
+ if (*_vm->getVar("pcage") == 2) {
// The best ending: Catherine is free, Gehn is trapped, Atrus comes to rescue you.
// And now we fall back to Earth... all the way...
warning("xtexterior300_telescopedown: Good ending");
_vm->_video->activateMLST(8, _vm->getCurCard());
runEndGame(8);
- } else if (*_vm->matchVarToString("agehn") == 4) {
+ } else if (*_vm->getVar("agehn") == 4) {
// The ok ending: Catherine is still trapped, Gehn is trapped, Atrus comes to rescue you.
// Nice going! Catherine and the islanders are all dead now! Just go back to your home...
warning("xtexterior300_telescopedown: OK ending");
_vm->_video->activateMLST(9, _vm->getCurCard());
runEndGame(9);
- } else if (*_vm->matchVarToString("atrapbook") == 1) {
+ } else if (*_vm->getVar("atrapbook") == 1) {
// The bad ending: Catherine is trapped, Gehn is free, Atrus gets shot by Gehn,
// And then you get shot by Cho. Nice going! Catherine and the islanders are dead
// and you have just set Gehn free from Riven, not to mention you're dead.
@@ -1492,7 +1852,9 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
}
} else {
// ...the telescope can't move down anymore.
- // TODO: Play sound
+ // Play the sound of not being able to move
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_sound->playSoundBlocking(13);
}
} else {
// We're not at the bottom, and we can move down again
@@ -1510,14 +1872,16 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) {
_vm->_video->playMovieBlocking(3);
// Don't do anything else if the telescope power is off
- if (*_vm->matchVarToString("ttelevalve") == 0)
+ if (*_vm->getVar("ttelevalve") == 0)
return;
- uint32 *telescopePos = _vm->matchVarToString("ttelescope");
+ uint32 *telescopePos = _vm->getVar("ttelescope");
// Check if we can't move up anymore
if (*telescopePos == 5) {
- // TODO: Play sound
+ // Play the sound of not being able to move
+ _vm->_gfx->changeCursor(kRivenHideCursor);
+ _vm->_sound->playSoundBlocking(13);
return;
}
@@ -1530,9 +1894,9 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) {
void RivenExternal::xtisland390_covercombo(uint16 argc, uint16 *argv) {
// Called when clicking the telescope cover buttons. argv[0] is the button number (1...5).
- uint32 *correctDigits = _vm->matchVarToString("tcovercombo");
+ uint32 *correctDigits = _vm->getVar("tcovercombo");
- if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->matchVarToString("tcorrectorder"), *correctDigits))
+ if (*correctDigits < 5 && argv[0] == getComboDigit(*_vm->getVar("tcorrectorder"), *correctDigits))
*correctDigits += 1;
else
*correctDigits = 0;
@@ -1548,8 +1912,8 @@ void RivenExternal::xtisland390_covercombo(uint16 argc, uint16 *argv) {
// Atrus' Journal and Trap Book are added to inventory
void RivenExternal::xtatrusgivesbooks(uint16 argc, uint16 *argv) {
// Give the player Atrus' Journal and the Trap book
- *_vm->matchVarToString("aatrusbook") = 1;
- *_vm->matchVarToString("atrapbook") = 1;
+ *_vm->getVar("aatrusbook") = 1;
+ *_vm->getVar("atrapbook") = 1;
}
// Trap Book is removed from inventory
@@ -1557,35 +1921,216 @@ void RivenExternal::xtchotakesbook(uint16 argc, uint16 *argv) {
// And now Cho takes the trap book. Sure, this isn't strictly
// necessary to add and them remove the trap book... but it
// seems better to do this ;)
- *_vm->matchVarToString("atrapbook") = 0;
+ *_vm->getVar("atrapbook") = 0;
}
void RivenExternal::xthideinventory(uint16 argc, uint16 *argv) {
_vm->_gfx->hideInventory();
}
+// Marble Puzzle related constants
+static const uint32 kMarbleCount = 6;
+static const int kSmallMarbleWidth = 4;
+static const int kSmallMarbleHeight = 2;
+static const int kLargeMarbleSize = 8;
+static const int kMarbleHotspotSize = 13;
+static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "tblue", "tviolet" };
+
+// Marble Puzzle helper functions
+// The y portion takes the upper 16 bits, while the x portion takes the lower 16 bits
+static void setMarbleX(uint32 *var, byte x) {
+ *var = (*var & 0xff00) | (x + 1);
+}
+
+static void setMarbleY(uint32 *var, byte y) {
+ *var = ((y + 1) << 16) | (*var & 0xff);
+}
+
+static byte getMarbleX(uint32 *var) {
+ return (*var & 0xff) - 1;
+}
+
+static byte getMarbleY(uint32 *var) { // Give that that Y you old hag! </bad Seinfeld reference>
+ return ((*var >> 16) & 0xff) - 1;
+}
+
+static Common::Rect generateMarbleGridRect(uint16 x, uint16 y) {
+ // x/y in terms of 0!
+ static const int marbleGridOffsetX[] = { 134, 202, 270, 338, 406 };
+ static const int marbleGridOffsetY[] = { 24, 92, 159, 227, 295 };
+
+ uint16 offsetX = marbleGridOffsetX[x / 5] + (x % 5) * kMarbleHotspotSize;
+ uint16 offsetY = marbleGridOffsetY[y / 5] + (y % 5) * kMarbleHotspotSize;
+ return Common::Rect(offsetX, offsetY, offsetX + kMarbleHotspotSize, offsetY + kMarbleHotspotSize);
+}
+
void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
- // TODO: Lots of stuff to do here, eventually we have to check each individual
- // marble position and set apower based on that. The game handles the video playing
- // so we don't have to. For the purposes of making the game progress further, we'll
- // just turn the power on for now.
- *_vm->matchVarToString("apower") = 1;
+ // Set apower if the marbles are in their correct spot.
+
+ bool valid = true;
+ static const uint32 marbleFinalValues[] = { 1114121, 1441798, 0, 65552, 65558, 262146 };
+
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ if (*_vm->getVar(s_marbleNames[i]) != marbleFinalValues[i]) {
+ valid = false;
+ break;
+ }
+
+ // If we have the correct combo, activate the power and reset the marble positions
+ // Otherwise, make sure the power is off
+ if (valid) {
+ *_vm->getVar("apower") = 1;
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ *_vm->getVar(s_marbleNames[i]) = 0;
+ } else
+ *_vm->getVar("apower") = 0;
}
void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
- // TODO: Marble puzzle related
+ // Draw the small marbles when we're a step away from the waffle
+ uint16 baseBitmapId = (_vm->getFeatures() & GF_DVD) ? 539 : 526;
+ bool waffleDown = *_vm->getVar("twaffle") != 0;
+
+ // Note that each of the small marble images is exactly 4x2
+
+ for (uint16 i = 0; i < kMarbleCount; i++) {
+ uint32 *var = _vm->getVar(s_marbleNames[i]);
+
+ if (*var == 0) {
+ // The marble is still in its initial place
+ // (Note that this is still drawn even if the waffle is down)
+ int marbleX = 376 + i * 2;
+ int marbleY = 253 + i * 4;
+ _vm->_gfx->copyImageToScreen(baseBitmapId + i, marbleX, marbleY, marbleX + kSmallMarbleWidth, marbleY + kSmallMarbleHeight);
+ } else if (waffleDown) {
+ // The marble is on the grid and the waffle is down
+ // (Nothing to draw here)
+ } else {
+ // The marble is on the grid and the waffle is up
+ // TODO: Draw them onto the grid
+ }
+ }
+}
+
+void RivenExternal::setMarbleHotspots() {
+ // Set the hotspots
+ for (uint16 i = 0; i < kMarbleCount; i++) {
+ uint32 *marblePos = _vm->getVar(s_marbleNames[i]);
+
+ if (*marblePos == 0) // In the receptacle
+ _vm->_hotspots[i + 3].rect = _marbleBaseHotspots[i];
+ else // On the grid
+ _vm->_hotspots[i + 3].rect = generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos));
+ }
}
void RivenExternal::xt7800_setup(uint16 argc, uint16 *argv) {
- // TODO: Marble puzzle related
+ // First, let's store the base receptacle hotspots for the marbles
+ if (_marbleBaseHotspots.empty())
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ _marbleBaseHotspots.push_back(_vm->_hotspots[i + 3].rect);
+
+ // Move the marble hotspots based on their position variables
+ setMarbleHotspots();
+ *_vm->getVar("themarble") = 0;
+}
+
+void RivenExternal::drawMarbles() {
+ for (uint32 i = 0; i < kMarbleCount; i++) {
+ // Don't draw the marble if we're holding it
+ if (*_vm->getVar("themarble") - 1 == i)
+ continue;
+
+ Common::Rect rect = _vm->_hotspots[i + 3].rect;
+ // Trim the rect down a bit
+ rect.left += 3;
+ rect.top += 3;
+ rect.right -= 2;
+ rect.bottom -= 2;
+ _vm->_gfx->drawExtrasImage(i + 200, rect);
+ }
}
void RivenExternal::xdrawmarbles(uint16 argc, uint16 *argv) {
- // TODO: Marble puzzle related
+ // Draw marbles in the closeup
+ drawMarbles();
+
+ // We have to re-enable the updates here
+ // Would be really nice if the scripts did this for us, but alas...
+ _vm->_gfx->_updatesEnabled = true;
}
void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
- // TODO: Marble puzzle related
+ // Pick up and move a marble
+
+ // First, let's figure out what marble we're now holding
+ uint32 *marble = _vm->getVar("themarble");
+ *marble = 0;
+
+ for (uint32 i = 0; i < kMarbleCount; i++)
+ if (_vm->_hotspots[i + 3].rect.contains(_vm->_system->getEventManager()->getMousePos())) {
+ *marble = i + 1;
+ break;
+ }
+
+ // xtakeit() shouldn't be called if we're not on a marble hotspot
+ assert(*marble);
+
+ // Redraw the background
+ _vm->_gfx->drawPLST(1);
+ _vm->_gfx->updateScreen();
+
+ // Loop until the player lets go (or quits)
+ Common::Event event;
+ bool mouseDown = true;
+ while (mouseDown) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ if (event.type == Common::EVENT_LBUTTONUP)
+ mouseDown = false;
+ else if (event.type == Common::EVENT_MOUSEMOVE)
+ _vm->_system->updateScreen();
+ else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
+ return;
+ }
+
+ _vm->_system->delayMillis(10); // Take it easy on the CPU
+ }
+
+ // Check if we landed in a valid location and no other marble has that location
+ uint32 *marblePos = _vm->getVar(s_marbleNames[*marble - 1]);
+
+ bool foundMatch = false;
+ for (int y = 0; y < 25 && !foundMatch; y++) {
+ for (int x = 0; x < 25 && !foundMatch; x++) {
+ Common::Rect testHotspot = generateMarbleGridRect(x, y);
+
+ // Let's try to place the marble!
+ if (testHotspot.contains(_vm->_system->getEventManager()->getMousePos())) {
+ // Set this as the position
+ setMarbleX(marblePos, x);
+ setMarbleY(marblePos, y);
+
+ // Let's make sure no other marble is in this spot...
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ if (i != *marble - 1 && *_vm->getVar(s_marbleNames[i]) == *marblePos)
+ *marblePos = 0;
+
+ // We have a match
+ foundMatch = true;
+ }
+ }
+ }
+
+ // If we still don't have a match, reset it to the original location
+ if (!foundMatch)
+ *marblePos = 0;
+
+ // Check the new hotspots and refresh everything
+ *marble = 0;
+ setMarbleHotspots();
+ _vm->_curHotspot = -1;
+ _vm->checkHotspotChange();
+ _vm->_gfx->updateScreen();
}
void RivenExternal::xtscpbtn(uint16 argc, uint16 *argv) {
@@ -1597,19 +2142,19 @@ void RivenExternal::xtisland4990_domecheck(uint16 argc, uint16 *argv) {
}
void RivenExternal::xtisland5056_opencard(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkDomeSliders(29, 30);
}
void RivenExternal::xtisland5056_resetsliders(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ resetDomeSliders(_vm->getFeatures() & GF_DVD ? 813 : 798, 37, 3);
}
void RivenExternal::xtisland5056_slidermd(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ dragDomeSlider(_vm->getFeatures() & GF_DVD ? 813 : 798, 37, 29, 30, 3);
}
void RivenExternal::xtisland5056_slidermw(uint16 argc, uint16 *argv) {
- // TODO: Dome related
+ checkSliderCursorChange(3);
}
void RivenExternal::xtatboundary(uint16 argc, uint16 *argv) {
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index bdf3fa01bc..1f012c82d9 100644
--- a/engines/mohawk/riven_external.h
+++ b/engines/mohawk/riven_external.h
@@ -39,9 +39,13 @@ public:
void runCommand(uint16 argc, uint16 *argv);
uint16 getComboDigit(uint32 correctCombo, uint32 digit);
+ uint32 getDomeSliderState() { return _sliderState; }
+ void setDomeSliderState(uint32 state) { _sliderState = state; }
private:
MohawkEngine_Riven *_vm;
+ uint32 _sliderState;
+ Common::Array<Common::Rect> _marbleBaseHotspots;
typedef void (RivenExternal::*ExternalCmd)(uint16 argc, uint16 *argv);
@@ -58,8 +62,16 @@ private:
int jspitElevatorLoop();
void runDemoBoundaryDialog();
void runEndGame(uint16 video);
+ void runCredits(uint16 video);
void runDomeCheck();
void runDomeButtonMovie();
+ void resetDomeSliders(uint16 bitmapId, uint16 soundId, uint16 startHotspot);
+ void checkDomeSliders(uint16 resetSlidersHotspot, uint16 openDomeHotspot);
+ void checkSliderCursorChange(uint16 startHotspot);
+ void dragDomeSlider(uint16 bitmapId, uint16 soundId, uint16 resetSlidersHotspot, uint16 openDomeHotspot, uint16 startHotspot);
+ void drawDomeSliders(uint16 bitmapId, uint16 startHotspot);
+ void drawMarbles();
+ void setMarbleHotspots();
// -----------------------------------------------------
// aspit (Main Menu, Books, Setup) external commands
@@ -86,6 +98,8 @@ private:
void xadisablemenureturn(uint16 argc, uint16 *argv);
void xaenablemenureturn(uint16 argc, uint16 *argv);
void xalaunchbrowser(uint16 argc, uint16 *argv);
+ void xadisablemenuintro(uint16 argc, uint16 *argv);
+ void xaenablemenuintro(uint16 argc, uint16 *argv);
// -----------------------------------------------------
// bspit (Boiler Island) external commands
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index d73b4ec0dc..c63a3f98fb 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -110,7 +110,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
delete vers;
if ((saveGameVersion == kCDSaveGameVersion && (_vm->getFeatures() & GF_DVD))
|| (saveGameVersion == kDVDSaveGameVersion && !(_vm->getFeatures() & GF_DVD))) {
- warning("Incompatible saved game versions. No support for this yet.");
+ warning("Incompatible saved game versions. No support for this yet");
delete mhk;
return false;
}
@@ -161,7 +161,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
if (name == "dropLeftStart" || name == "dropRightStart")
continue;
- uint32 *var = _vm->matchVarToString(name);
+ uint32 *var = _vm->getVar(name);
*var = rawVariables[i];
@@ -272,8 +272,8 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
filename += ".rvn";
// Convert class variables to variable numbers
- *_vm->matchVarToString("currentstackid") = mapNewStackIDToOld(_vm->getCurStack());
- *_vm->matchVarToString("currentcardid") = _vm->getCurCard();
+ *_vm->getVar("currentstackid") = mapNewStackIDToOld(_vm->getCurStack());
+ *_vm->getVar("currentcardid") = _vm->getCurCard();
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
if (!saveFile)
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 1fcaba8ac0..30d1d727eb 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -38,7 +38,7 @@ namespace Mohawk {
RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard)
: _vm(vm), _stream(stream), _scriptType(scriptType), _parentStack(parentStack), _parentCard(parentCard) {
setupOpcodes();
- _isRunning = false;
+ _isRunning = _continueRunning = false;
}
RivenScript::~RivenScript() {
@@ -227,7 +227,7 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray
}
void RivenScript::runScript() {
- _isRunning = true;
+ _isRunning = _continueRunning = true;
if (_stream->pos() != 0)
_stream->seek(0);
@@ -242,7 +242,7 @@ void RivenScript::processCommands(bool runCommands) {
uint16 commandCount = _stream->readUint16BE();
- for (uint16 j = 0; j < commandCount && !_vm->shouldQuit() && _stream->pos() < _stream->size(); j++) {
+ for (uint16 j = 0; j < commandCount && !_vm->shouldQuit() && _stream->pos() < _stream->size() && _continueRunning; j++) {
uint16 command = _stream->readUint16BE();
if (command == 8) {
@@ -346,9 +346,14 @@ void RivenScript::playScriptSLST(uint16 op, uint16 argc, uint16 *argv) {
_vm->_activatedSLST = true;
}
-// Command 4: play local tWAV resource (twav_id, volume, u1)
+// Command 4: play local tWAV resource (twav_id, volume, block)
void RivenScript::playSound(uint16 op, uint16 argc, uint16 *argv) {
- _vm->_sound->playSound(argv[0], false);
+ byte volume = Sound::convertRivenVolume(argv[1]);
+
+ if (argv[2] == 1)
+ _vm->_sound->playSoundBlocking(argv[0], volume);
+ else
+ _vm->_sound->playSound(argv[0], volume);
}
// Command 7: set variable value (variable, value)
@@ -398,7 +403,7 @@ void RivenScript::changeCursor(uint16 op, uint16 argc, uint16 *argv) {
void RivenScript::delay(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Delay %dms", argv[0]);
if (argv[0] > 0)
- _vm->_system->delayMillis(argv[0]);
+ _vm->delayAndUpdate(argv[0]);
}
// Command 17: call external command
@@ -572,7 +577,8 @@ void RivenScript::activateFLST(uint16 op, uint16 argc, uint16 *argv) {
for (uint16 i = 0; i < recordCount; i++) {
uint16 index = flst->readUint16BE();
uint16 sfxeID = flst->readUint16BE();
- if(flst->readUint16BE() != 0)
+
+ if (flst->readUint16BE() != 0)
warning("FLST u0 non-zero");
if (index == argv[0]) {
@@ -632,6 +638,11 @@ RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stre
return scriptList;
}
+void RivenScriptManager::stopAllScripts() {
+ for (uint32 i = 0; i < _currentScripts.size(); i++)
+ _currentScripts[i]->stopRunning();
+}
+
void RivenScriptManager::unloadUnusedScripts() {
// Free any scripts that aren't part of the current card and aren't running
for (uint32 i = 0; i < _currentScripts.size(); i++) {
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index 5187bbde08..a85cde1702 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -62,6 +62,7 @@ public:
uint16 getParentStack() { return _parentStack; }
uint16 getParentCard() { return _parentCard; }
bool isRunning() { return _isRunning; }
+ void stopRunning() { _continueRunning = false; }
static uint32 calculateScriptSize(Common::SeekableReadStream *script);
@@ -76,8 +77,8 @@ private:
MohawkEngine_Riven *_vm;
Common::SeekableReadStream *_stream;
- uint16 _scriptType, _parentStack, _parentCard, _parentHotspot;
- bool _isRunning;
+ uint16 _scriptType, _parentStack, _parentCard;
+ bool _isRunning, _continueRunning;
void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
void processCommands(bool runCommands);
@@ -131,6 +132,7 @@ public:
~RivenScriptManager();
RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
+ void stopAllScripts();
private:
void unloadUnusedScripts();
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index b6d2dff315..ae06afef01 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -271,7 +271,7 @@ static const char *variableNames[] = {
};
uint32 *MohawkEngine_Riven::getLocalVar(uint32 index) {
- return matchVarToString(getName(VariableNames, index));
+ return getVar(getName(VariableNames, index));
}
uint32 MohawkEngine_Riven::getGlobalVar(uint32 index) {
@@ -279,18 +279,15 @@ uint32 MohawkEngine_Riven::getGlobalVar(uint32 index) {
}
Common::String MohawkEngine_Riven::getGlobalVarName(uint32 index) {
- return Common::String(variableNames[index]);
+ return variableNames[index];
}
-uint32 *MohawkEngine_Riven::matchVarToString(Common::String varName) {
- return matchVarToString(varName.c_str());
-}
-
-uint32 *MohawkEngine_Riven::matchVarToString(const char *varName) {
+uint32 *MohawkEngine_Riven::getVar(const Common::String &varName) {
for (uint32 i = 0; i < _varCount; i++)
- if (!scumm_stricmp(varName, variableNames[i]))
+ if (varName.equalsIgnoreCase(variableNames[i]))
return &_vars[i];
- error ("Unknown variable: \'%s\'", varName);
+
+ error ("Unknown variable: '%s'", varName.c_str());
return NULL;
}
@@ -304,33 +301,33 @@ void MohawkEngine_Riven::initVars() {
_vars[i] = 0;
// Init Variables to their correct starting state.
- *matchVarToString("ttelescope") = 5;
- *matchVarToString("tgatestate") = 1;
- *matchVarToString("jbridge1") = 1;
- *matchVarToString("jbridge4") = 1;
- *matchVarToString("jgallows") = 1;
- *matchVarToString("jiconcorrectorder") = 12068577;
- *matchVarToString("bblrvalve") = 1;
- *matchVarToString("bblrwtr") = 1;
- *matchVarToString("bfans") = 1;
- *matchVarToString("bytrap") = 2;
- *matchVarToString("aatruspage") = 1;
- *matchVarToString("acathpage") = 1;
- *matchVarToString("bheat") = 1;
- *matchVarToString("waterenabled") = 1;
- *matchVarToString("ogehnpage") = 1;
- *matchVarToString("bblrsw") = 1;
- *matchVarToString("ocage") = 1;
+ *getVar("ttelescope") = 5;
+ *getVar("tgatestate") = 1;
+ *getVar("jbridge1") = 1;
+ *getVar("jbridge4") = 1;
+ *getVar("jgallows") = 1;
+ *getVar("jiconcorrectorder") = 12068577;
+ *getVar("bblrvalve") = 1;
+ *getVar("bblrwtr") = 1;
+ *getVar("bfans") = 1;
+ *getVar("bytrap") = 2;
+ *getVar("aatruspage") = 1;
+ *getVar("acathpage") = 1;
+ *getVar("bheat") = 1;
+ *getVar("waterenabled") = 1;
+ *getVar("ogehnpage") = 1;
+ *getVar("bblrsw") = 1;
+ *getVar("ocage") = 1;
// Randomize the telescope combination
- uint32 *teleCombo = matchVarToString("tcorrectorder");
+ uint32 *teleCombo = getVar("tcorrectorder");
for (byte i = 0; i < 5; i++) {
*teleCombo *= 10;
*teleCombo += _rnd->getRandomNumberRng(1, 5); // 5 buttons
}
// Randomize the prison combination
- uint32 *prisonCombo = matchVarToString("pcorrectorder");
+ uint32 *prisonCombo = getVar("pcorrectorder");
for (byte i = 0; i < 5; i++) {
*prisonCombo *= 10;
*prisonCombo += _rnd->getRandomNumberRng(1, 3); // 3 buttons/sounds
@@ -338,7 +335,7 @@ void MohawkEngine_Riven::initVars() {
// Randomize the dome combination -- each bit represents a slider position,
// the highest bit (1 << 24) represents 1, (1 << 23) represents 2, etc.
- uint32 *domeCombo = matchVarToString("adomecombo");
+ uint32 *domeCombo = getVar("adomecombo");
for (byte bitsSet = 0; bitsSet < 5;) {
uint32 randomBit = 1 << (24 - _rnd->getRandomNumber(24));
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 091bd68021..4a8c923c01 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -36,7 +36,6 @@
namespace Mohawk {
Sound::Sound(MohawkEngine* vm) : _vm(vm) {
- _rivenSoundFile = NULL;
_midiDriver = NULL;
_midiParser = NULL;
@@ -51,7 +50,6 @@ Sound::Sound(MohawkEngine* vm) : _vm(vm) {
Sound::~Sound() {
stopSound();
stopAllSLST();
- delete _rivenSoundFile;
if (_midiDriver) {
_midiDriver->close();
@@ -64,15 +62,6 @@ Sound::~Sound() {
}
}
-void Sound::loadRivenSounds(uint16 stack) {
- static const char prefixes[] = { 'a', 'b', 'g', 'j', 'o', 'p', 'r', 't' };
-
- if (!_rivenSoundFile)
- _rivenSoundFile = new MohawkArchive();
-
- _rivenSoundFile->open(Common::String(prefixes[stack]) + "_Sounds.mhk");
-}
-
void Sound::initMidi() {
if (!(_vm->getFeatures() & GF_HASMIDI))
return;
@@ -87,7 +76,7 @@ void Sound::initMidi() {
_midiParser->setTimerRate(_midiDriver->getBaseTempo());
}
-Audio::SoundHandle *Sound::playSound(uint16 id, bool mainSoundFile, byte volume, bool loop) {
+Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop) {
debug (0, "Playing sound %d", id);
SndHandle *handle = getHandle();
@@ -113,21 +102,9 @@ Audio::SoundHandle *Sound::playSound(uint16 id, bool mainSoundFile, byte volume,
} else
audStream = makeMohawkWaveStream(_vm->getRawData(ID_MSND, id));
break;
- case GType_RIVEN:
- if (mainSoundFile)
- audStream = makeMohawkWaveStream(_rivenSoundFile->getRawData(ID_TWAV, id));
- else
- audStream = makeMohawkWaveStream(_vm->getRawData(ID_TWAV, id));
- break;
case GType_ZOOMBINI:
audStream = makeMohawkWaveStream(_vm->getRawData(ID_SND, id));
break;
- case GType_CSAMTRAK:
- if (mainSoundFile)
- audStream = makeMohawkWaveStream(_vm->getRawData(ID_TWAV, id));
- else
- audStream = getCSAmtrakMusic(id);
- break;
case GType_LIVINGBOOKSV1:
audStream = makeOldMohawkWaveStream(_vm->getRawData(ID_WAV, id));
break;
@@ -147,6 +124,13 @@ Audio::SoundHandle *Sound::playSound(uint16 id, bool mainSoundFile, byte volume,
return NULL;
}
+void Sound::playSoundBlocking(uint16 id, byte volume) {
+ Audio::SoundHandle *handle = playSound(id, volume);
+
+ while (_vm->_mixer->isSoundHandleActive(*handle))
+ _vm->_system->delayMillis(10);
+}
+
void Sound::playMidi(uint16 id) {
uint32 idTag;
if (!(_vm->getFeatures() & GF_HASMIDI)) {
@@ -188,6 +172,10 @@ void Sound::playMidi(uint16 id) {
_midiDriver->setTimerCallback(_midiParser, MidiParser::timerCallback);
}
+byte Sound::convertRivenVolume(uint16 volume) {
+ return (volume == 256) ? 255 : volume;
+}
+
void Sound::playSLST(uint16 index, uint16 card) {
Common::SeekableReadStream *slstStream = _vm->getRawData(ID_SLST, card);
SLSTRecord slstRecord;
@@ -304,19 +292,15 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16
sndHandle.id = id;
_currentSLSTSounds.push_back(sndHandle);
- Audio::AudioStream *audStream = makeMohawkWaveStream(_rivenSoundFile->getRawData(ID_TWAV, id));
+ Audio::AudioStream *audStream = makeMohawkWaveStream(_vm->getRawData(ID_TWAV, id));
// Loop here if necessary
if (loop)
audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
- // The max mixer volume is 255 and the max Riven volume is 256. Just change it to 255.
- if (volume == 256)
- volume = 255;
-
// TODO: Handle fading, possibly just raise the volume of the channel in increments?
- _vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, sndHandle.handle, audStream, -1, volume, convertBalance(balance));
+ _vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, sndHandle.handle, audStream, -1, convertRivenVolume(volume), convertBalance(balance));
}
void Sound::stopSLSTSound(uint16 index, bool fade) {
@@ -336,16 +320,6 @@ void Sound::resumeSLST() {
_vm->_mixer->pauseHandle(*_currentSLSTSounds[i].handle, false);
}
-Audio::AudioStream *Sound::getCSAmtrakMusic(uint16 id) {
- char filename[18];
- sprintf(filename, "MUSIC/MUSIC%02d.MHK", id);
- MohawkArchive *file = new MohawkArchive();
- file->open(filename);
- Audio::AudioStream *audStream = makeMohawkWaveStream(file->getRawData(ID_TWAV, 2000 + id));
- delete file;
- return audStream;
-}
-
Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stream) {
uint32 tag = 0;
ADPC_Chunk adpc;
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 0e3ecd3c51..f493130d35 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -115,28 +115,29 @@ class MohawkEngine;
class Sound {
public:
- Sound(MohawkEngine*);
+ Sound(MohawkEngine *vm);
~Sound();
- void loadRivenSounds(uint16 stack);
- Audio::SoundHandle *playSound(uint16 id, bool mainSoundFile = true, byte volume = Audio::Mixer::kMaxChannelVolume, bool loop = false);
+ Audio::SoundHandle *playSound(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume, bool loop = false);
+ void playSoundBlocking(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume);
void playMidi(uint16 id);
void stopSound();
void pauseSound();
void resumeSound();
+
+ // Riven-specific
void playSLST(uint16 index, uint16 card);
void playSLST(SLSTRecord slstRecord);
void pauseSLST();
void resumeSLST();
void stopAllSLST();
+ static byte convertRivenVolume(uint16 volume);
private:
MohawkEngine *_vm;
- MohawkArchive *_rivenSoundFile;
MidiDriver *_midiDriver;
MidiParser *_midiParser;
- static Audio::AudioStream *getCSAmtrakMusic(uint16 id);
static Audio::AudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream);
static Audio::AudioStream *makeOldMohawkWaveStream(Common::SeekableReadStream *stream);
void initMidi();
@@ -144,7 +145,7 @@ private:
Common::Array<SndHandle> _handles;
SndHandle *getHandle();
- // Riven specific
+ // Riven-specific
void playSLSTSound(uint16 index, bool fade, bool loop, uint16 volume, int16 balance);
void stopSLSTSound(uint16 id, bool fade);
Common::Array<SLSTSndHandle> _currentSLSTSounds;
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 17456b8ec3..b7ee4c8a2c 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -123,7 +123,7 @@ void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
delete _videoStreams[videoHandle].video;
_videoStreams[videoHandle].video = 0;
- _videoStreams[videoHandle].id = 0;
+ _videoStreams[videoHandle].id = 0xffff;
_videoStreams[videoHandle].filename.clear();
}
@@ -156,7 +156,7 @@ bool VideoManager::updateBackgroundMovies() {
} else {
delete _videoStreams[i].video;
_videoStreams[i].video = 0;
- _videoStreams[i].id = 0;
+ _videoStreams[i].id = 0xffff;
_videoStreams[i].filename.clear();
continue;
}
@@ -292,7 +292,7 @@ void VideoManager::stopMovie(uint16 id) {
if (_mlstRecords[i].movieID == _videoStreams[j].id) {
delete _videoStreams[j].video;
_videoStreams[j].video = 0;
- _videoStreams[j].id = 0;
+ _videoStreams[j].id = 0xffff;
_videoStreams[j].filename.clear();
return;
}
@@ -368,7 +368,7 @@ VideoHandle VideoManager::createVideoHandle(Common::String filename, uint16 x, u
entry.x = x;
entry.y = y;
entry.filename = filename;
- entry.id = 0;
+ entry.id = 0xffff;
entry.loop = loop;
entry.enabled = true;
@@ -412,4 +412,14 @@ uint32 VideoManager::getFrameCount(const VideoHandle &handle) {
return _videoStreams[handle]->getFrameCount();
}
+uint32 VideoManager::getElapsedTime(const VideoHandle &handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->getElapsedTime();
+}
+
+bool VideoManager::endOfVideo(const VideoHandle &handle) {
+ assert(handle != NULL_VID_HANDLE);
+ return _videoStreams[handle]->endOfVideo();
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 6aa553e26b..4c6ed05cef 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -94,6 +94,8 @@ public:
VideoHandle findVideoHandle(uint16 id);
int32 getCurFrame(const VideoHandle &handle);
uint32 getFrameCount(const VideoHandle &handle);
+ uint32 getElapsedTime(const VideoHandle &handle);
+ bool endOfVideo(const VideoHandle &handle);
private:
MohawkEngine *_vm;