aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorBastien Bouclet2016-08-02 18:56:55 +0200
committerEugene Sandulenko2017-07-03 08:50:10 +0200
commit9b9fa7e0a5f92c1b3b3a1252af5ed82a5911505d (patch)
tree87bfbe4cecf49fb3881ddfa62155473d3b0d7df2 /engines
parent834be40ffa299896fef46e84368de2f371ff2a09 (diff)
downloadscummvm-rg350-9b9fa7e0a5f92c1b3b3a1252af5ed82a5911505d.tar.gz
scummvm-rg350-9b9fa7e0a5f92c1b3b3a1252af5ed82a5911505d.tar.bz2
scummvm-rg350-9b9fa7e0a5f92c1b3b3a1252af5ed82a5911505d.zip
MOHAWK: Refactor the script manager to read data to Command classes
Diffstat (limited to 'engines')
-rw-r--r--engines/mohawk/console.cpp6
-rw-r--r--engines/mohawk/riven.cpp6
-rw-r--r--engines/mohawk/riven_scripts.cpp526
-rw-r--r--engines/mohawk/riven_scripts.h129
4 files changed, 361 insertions, 306 deletions
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index f08eee9677..82173c2670 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -617,10 +617,9 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
debugN("==================================\n\n");
Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3]));
cardStream->seek(4);
- RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false);
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream);
for (uint32 i = 0; i < scriptList.size(); i++) {
scriptList[i]->dumpScript(varNames, xNames, 0);
- delete scriptList[i];
}
delete cardStream;
} else if (!scumm_stricmp(argv[2], "HSPT")) {
@@ -635,10 +634,9 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
for (uint16 i = 0; i < hotspotCount; i++) {
debugN("Hotspot %d:\n", i);
hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff
- RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false);
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream);
for (uint32 j = 0; j < scriptList.size(); j++) {
scriptList[j]->dumpScript(varNames, xNames, 1);
- delete scriptList[j];
}
}
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 12b4851a9c..61ceb4130c 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -697,7 +697,8 @@ void MohawkEngine_Riven::runCardScript(uint16 scriptType) {
assert(_cardData.hasData);
for (uint16 i = 0; i < _cardData.scripts.size(); i++)
if (_cardData.scripts[i]->getScriptType() == scriptType) {
- _cardData.scripts[i]->runScript();
+ RivenScriptPtr script = _cardData.scripts[i];
+ script->runScript();
break;
}
}
@@ -706,7 +707,8 @@ void MohawkEngine_Riven::runHotspotScript(uint16 hotspot, uint16 scriptType) {
assert(hotspot < _hotspotCount);
for (uint16 i = 0; i < _hotspots[hotspot].scripts.size(); i++)
if (_hotspots[hotspot].scripts[i]->getScriptType() == scriptType) {
- _hotspots[hotspot].scripts[i]->runScript();
+ RivenScriptPtr script = _hotspots[hotspot].scripts[i];
+ script->runScript();
break;
}
}
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 3655452603..8e5207f90e 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -34,60 +34,151 @@
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 = _continueRunning = false;
+static void printTabs(byte tabs) {
+ for (byte i = 0; i < tabs; i++)
+ debugN("\t");
}
-RivenScript::~RivenScript() {
- delete _stream;
-}
-
-uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) {
- uint16 command = script->readUint16BE();
- uint32 commandSize = 2;
- if (command == 8) {
- if (script->readUint16BE() != 2) // Arg count?
- warning ("if-then-else unknown value is not 2");
- script->readUint16BE(); // variable to check against
- uint16 logicBlockCount = script->readUint16BE(); // number of logic blocks
- commandSize += 6; // 2 + variable + logicBlocks
-
- for (uint16 i = 0; i < logicBlockCount; i++) {
- script->readUint16BE(); // Block variable
- uint16 logicBlockLength = script->readUint16BE();
- commandSize += 4;
- for (uint16 j = 0; j < logicBlockLength; j++)
- commandSize += calculateCommandSize(script);
- }
+RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
+ _vm = vm;
+ _storedMovieOpcode.time = 0;
+ _storedMovieOpcode.id = 0;
+}
+
+RivenScriptManager::~RivenScriptManager() {
+ clearStoredMovieOpcode();
+}
+
+RivenScriptPtr RivenScriptManager::readScript(Common::ReadStream *stream, uint16 scriptType) {
+ RivenScriptPtr script = RivenScriptPtr(new RivenScript(_vm, scriptType));
+
+ uint16 commandCount = stream->readUint16BE();
+
+ for (uint16 i = 0; i < commandCount; i++) {
+ RivenCommand *command = readCommand(stream);
+ script->addCommand(command);
+ }
+
+ return script;
+}
+
+RivenCommand *RivenScriptManager::readCommand(Common::ReadStream *stream) {
+ uint16 type = stream->readUint16BE();
+
+ if (type == 8) {
+ return RivenSwitchCommand::createFromStream(_vm, type, stream);
} else {
- uint16 argCount = script->readUint16BE();
- commandSize += 2;
- for (uint16 i = 0; i < argCount; i++) {
- script->readUint16BE();
- commandSize += 2;
- }
+ return RivenSimpleCommand::createFromStream(_vm, type, stream);
+ }
+}
+
+RivenScriptList RivenScriptManager::readScripts(Common::ReadStream *stream) {
+ RivenScriptList scriptList;
+
+ uint16 scriptCount = stream->readUint16BE();
+ for (uint16 i = 0; i < scriptCount; i++) {
+ uint16 scriptType = stream->readUint16BE();
+ RivenScriptPtr script = readScript(stream, scriptType);
+ scriptList.push_back(script);
}
- return commandSize;
+ return scriptList;
+}
+
+void RivenScriptManager::stopAllScripts() {
+// TODO: Restore
+// for (uint32 i = 0; i < _currentScripts.size(); i++)
+// _currentScripts[i]->stopRunning();
+}
+
+void RivenScriptManager::setStoredMovieOpcode(const StoredMovieOpcode &op) {
+ clearStoredMovieOpcode();
+ _storedMovieOpcode.script = op.script;
+ _storedMovieOpcode.id = op.id;
+ _storedMovieOpcode.time = op.time;
+}
+
+void RivenScriptManager::runStoredMovieOpcode() {
+ if (_storedMovieOpcode.script) {
+ _storedMovieOpcode.script->runScript();
+ clearStoredMovieOpcode();
+ }
+}
+
+void RivenScriptManager::clearStoredMovieOpcode() {
+ _storedMovieOpcode.script = RivenScriptPtr();
+ _storedMovieOpcode.time = 0;
+ _storedMovieOpcode.id = 0;
+}
+
+RivenScript::RivenScript(MohawkEngine_Riven *vm, uint16 scriptType) :
+ _vm(vm),
+ _scriptType(scriptType) {
+ _continueRunning = true;
+}
+
+RivenScript::~RivenScript() {
+ for (uint i = 0; i < _commands.size(); i ++) {
+ delete _commands[i];
+ }
+}
+
+void RivenScript::dumpScript(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) {
+ printTabs(tabs); debugN("Stream Type %d:\n", _scriptType);
+ dumpCommands(varNames, xNames, tabs + 1);
+}
+
+void RivenScript::dumpCommands(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) {
+ for (uint16 i = 0; i < _commands.size(); i++) {
+ _commands[i]->dump(varNames, xNames, tabs);
+ }
+}
+
+void RivenScript::runScript() {
+ for (uint16 i = 0; i < _commands.size() && _continueRunning; i++) {
+ _commands[i]->execute();
+ }
+}
+
+void RivenScript::addCommand(RivenCommand *command) {
+ _commands.push_back(command);
+}
+
+RivenCommand::RivenCommand(MohawkEngine_Riven *vm) :
+ _vm(vm) {
+
+}
+
+RivenCommand::~RivenCommand() {
+
+}
+
+RivenSimpleCommand::RivenSimpleCommand(MohawkEngine_Riven *vm, int type, const ArgumentArray &arguments) :
+ RivenCommand(vm),
+ _type(type),
+ _arguments(arguments) {
+ setupOpcodes();
+}
+
+RivenSimpleCommand::~RivenSimpleCommand() {
}
-uint32 RivenScript::calculateScriptSize(Common::SeekableReadStream* script) {
- uint32 oldPos = script->pos();
- uint16 commandCount = script->readUint16BE();
- uint16 scriptSize = 2; // 2 for command count
+RivenSimpleCommand *RivenSimpleCommand::createFromStream(MohawkEngine_Riven *vm, int type, Common::ReadStream *stream) {
+ uint16 argCount = stream->readUint16BE();
- for (uint16 i = 0; i < commandCount; i++)
- scriptSize += calculateCommandSize(script);
+ Common::Array<uint16> arguments;
+ arguments.resize(argCount);
- script->seek(oldPos);
- return scriptSize;
+ for (uint16 i = 0; i < argCount; i++) {
+ arguments[i] = stream->readUint16BE();
+ }
+
+ return new RivenSimpleCommand(vm, type, arguments);
}
-#define OPCODE(x) { &RivenScript::x, #x }
+#define OPCODE(x) { &RivenSimpleCommand::x, #x }
-void RivenScript::setupOpcodes() {
+void RivenSimpleCommand::setupOpcodes() {
static const RivenOpcode riven_opcodes[] = {
// 0x00 (0 decimal)
OPCODE(empty),
@@ -154,139 +245,12 @@ void RivenScript::setupOpcodes() {
_opcodes = riven_opcodes;
}
-static void printTabs(byte tabs) {
- for (byte i = 0; i < tabs; i++)
- debugN("\t");
-}
-
-void RivenScript::dumpScript(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) {
- if (_stream->pos() != 0)
- _stream->seek(0);
-
- printTabs(tabs); debugN("Stream Type %d:\n", _scriptType);
- dumpCommands(varNames, xNames, tabs + 1);
-}
-
-void RivenScript::dumpCommands(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) {
- uint16 commandCount = _stream->readUint16BE();
-
- for (uint16 i = 0; i < commandCount; i++) {
- uint16 command = _stream->readUint16BE();
-
- if (command == 8) { // "Switch" Statement
- if (_stream->readUint16BE() != 2)
- warning ("if-then-else unknown value is not 2");
- uint16 var = _stream->readUint16BE();
- printTabs(tabs); debugN("switch (%s) {\n", varNames[var].c_str());
- uint16 logicBlockCount = _stream->readUint16BE();
- for (uint16 j = 0; j < logicBlockCount; j++) {
- uint16 varCheck = _stream->readUint16BE();
- printTabs(tabs + 1);
- if (varCheck == 0xFFFF)
- debugN("default:\n");
- else
- debugN("case %d:\n", varCheck);
- dumpCommands(varNames, xNames, tabs + 2);
- printTabs(tabs + 2); debugN("break;\n");
- }
- printTabs(tabs); debugN("}\n");
- } else if (command == 7) { // Use the variable name
- _stream->readUint16BE(); // Skip the opcode var count
- printTabs(tabs);
- uint16 var = _stream->readUint16BE();
- debugN("%s = %d;\n", varNames[var].c_str(), _stream->readUint16BE());
- } else if (command == 17) { // Use the external command name
- _stream->readUint16BE(); // Skip the opcode var count
- printTabs(tabs);
- debugN("%s(", xNames[_stream->readUint16BE()].c_str());
- uint16 varCount = _stream->readUint16BE();
- for (uint16 j = 0; j < varCount; j++) {
- debugN("%d", _stream->readUint16BE());
- if (j != varCount - 1)
- debugN(", ");
- }
- debugN(");\n");
- } else if (command == 24) { // Use the variable name
- _stream->readUint16BE(); // Skip the opcode var count
- printTabs(tabs);
- uint16 var = _stream->readUint16BE();
- debugN("%s += %d;\n", varNames[var].c_str(), _stream->readUint16BE());
- } else {
- printTabs(tabs);
- uint16 varCount = _stream->readUint16BE();
- debugN("%s(", _opcodes[command].desc);
- for (uint16 j = 0; j < varCount; j++) {
- debugN("%d", _stream->readUint16BE());
- if (j != varCount - 1)
- debugN(", ");
- }
- debugN(");\n");
- }
- }
-}
-
-void RivenScript::runScript() {
- _isRunning = _continueRunning = true;
-
- if (_stream->pos() != 0)
- _stream->seek(0);
-
- processCommands(true);
- _isRunning = false;
-}
-
-void RivenScript::processCommands(bool runCommands) {
- bool runBlock = true;
-
- uint16 commandCount = _stream->readUint16BE();
-
- for (uint16 j = 0; j < commandCount && !_vm->shouldQuit() && _stream->pos() < _stream->size() && _continueRunning; j++) {
- uint16 command = _stream->readUint16BE();
-
- if (command == 8) {
- // Command 8 contains a conditional branch, similar to switch statements
- if (_stream->readUint16BE() != 2)
- warning("if-then-else unknown value is not 2");
-
- uint16 var = _stream->readUint16BE(); // variable to check against
- uint16 logicBlockCount = _stream->readUint16BE(); // number of logic blocks
- bool anotherBlockEvaluated = false;
-
- for (uint16 k = 0; k < logicBlockCount; k++) {
- uint16 checkValue = _stream->readUint16BE(); // variable for this logic block
-
- // Run the following block if the block's variable is equal to the variable to check against
- // Don't run it if the parent block is not executed
- // And don't run it if another block has already evaluated to true (needed for the default case)
- runBlock = (_vm->getStackVar(var) == checkValue || checkValue == 0xffff) && runCommands && !anotherBlockEvaluated;
- processCommands(runBlock);
-
- if (runBlock)
- anotherBlockEvaluated = true;
- }
- } else {
- uint16 argCount = _stream->readUint16BE();
- uint16 *argValues = new uint16[argCount];
-
- for (uint16 k = 0; k < argCount; k++)
- argValues[k] = _stream->readUint16BE();
-
- if (runCommands) {
- debug (4, "Running opcode %04x, argument count %d", command, argCount);
- (this->*(_opcodes[command].proc)) (command, argCount, argValues);
- }
-
- delete[] argValues;
- }
- }
-}
-
////////////////////////////////
// Opcodes
////////////////////////////////
// Command 1: draw tBMP resource (tbmp_id, left, top, right, bottom, u0, u1, u2, u3)
-void RivenScript::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
if (argc < 5) // Copy the image to the whole screen, ignoring the rest of the parameters
_vm->_gfx->copyImageToScreen(argv[0], 0, 0, 608, 392);
else // Copy the image to a certain part of the screen
@@ -297,18 +261,19 @@ void RivenScript::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 2: go to card (card id)
-void RivenScript::switchCard(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::switchCard(uint16 op, uint16 argc, uint16 *argv) {
_vm->changeToCard(argv[0]);
// WORKAROUND: If we changed card on a mouse down event,
// we want to ignore the next mouse up event so we don't
// change card when lifting the mouse on the next card.
- if (_scriptType == kMouseDownScript)
- _vm->ignoreNextMouseUp();
+// TODO: Restore
+// if (_scriptType == kMouseDownScript)
+// _vm->ignoreNextMouseUp();
}
// Command 3: play an SLST from the script
-void RivenScript::playScriptSLST(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::playScriptSLST(uint16 op, uint16 argc, uint16 *argv) {
int offset = 0, j = 0;
uint16 soundCount = argv[offset++];
@@ -342,7 +307,7 @@ void RivenScript::playScriptSLST(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 4: play local tWAV resource (twav_id, volume, block)
-void RivenScript::playSound(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::playSound(uint16 op, uint16 argc, uint16 *argv) {
uint16 volume = argv[1];
bool playOnDraw = argv[2] == 1;
@@ -350,17 +315,17 @@ void RivenScript::playSound(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 7: set variable value (variable, value)
-void RivenScript::setVariable(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::setVariable(uint16 op, uint16 argc, uint16 *argv) {
_vm->getStackVar(argv[0]) = argv[1];
}
// Command 8: conditional branch
-void RivenScript::mohawkSwitch(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::mohawkSwitch(uint16 op, uint16 argc, uint16 *argv) {
// dummy function, this opcode does logic checking in processCommands()
}
// Command 9: enable hotspot (blst_id)
-void RivenScript::enableHotspot(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::enableHotspot(uint16 op, uint16 argc, uint16 *argv) {
for (uint16 i = 0; i < _vm->getHotspotCount(); i++) {
if (_vm->_hotspots[i].blstID == argv[0]) {
debug(2, "Enabling hotspot with BLST ID %d", argv[0]);
@@ -373,7 +338,7 @@ void RivenScript::enableHotspot(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 10: disable hotspot (blst_id)
-void RivenScript::disableHotspot(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::disableHotspot(uint16 op, uint16 argc, uint16 *argv) {
for (uint16 i = 0; i < _vm->getHotspotCount(); i++) {
if (_vm->_hotspots[i].blstID == argv[0]) {
debug(2, "Disabling hotspot with BLST ID %d", argv[0]);
@@ -386,7 +351,7 @@ void RivenScript::disableHotspot(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 12: stop sounds (flags)
-void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::stopSound(uint16 op, uint16 argc, uint16 *argv) {
// WORKAROUND: The Play Riven/Visit Riven/Start New Game buttons
// in the main menu call this function to stop ambient sounds
// after the change stack call to Temple Island. However, this
@@ -408,21 +373,21 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 13: set mouse cursor (cursor_id)
-void RivenScript::changeCursor(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::changeCursor(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Change to cursor %d", argv[0]);
_vm->_cursor->setCursor(argv[0]);
_vm->_system->updateScreen();
}
// Command 14: pause script execution (delay in ms, u1)
-void RivenScript::delay(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::delay(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Delay %dms", argv[0]);
if (argv[0] > 0)
_vm->delayAndUpdate(argv[0]);
}
// Command 17: call external command
-void RivenScript::runExternalCommand(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::runExternalCommand(uint16 op, uint16 argc, uint16 *argv) {
_vm->_externalScriptHandler->runCommand(argc, argv);
}
@@ -430,7 +395,7 @@ void RivenScript::runExternalCommand(uint16 op, uint16 argc, uint16 *argv) {
// Note that this opcode has 1 or 5 parameters, depending on argc
// Parameter 0: transition type
// Parameters 1-4: transition rectangle
-void RivenScript::transition(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::transition(uint16 op, uint16 argc, uint16 *argv) {
if (argc == 1)
_vm->_gfx->scheduleTransition(argv[0]);
else
@@ -438,31 +403,31 @@ void RivenScript::transition(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 19: reload card
-void RivenScript::refreshCard(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::refreshCard(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Refreshing card");
_vm->refreshCard();
}
// Command 20: disable screen update
-void RivenScript::disableScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::disableScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Screen update disabled");
_vm->_gfx->_updatesEnabled = false;
}
// Command 21: enable screen update
-void RivenScript::enableScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::enableScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
debug(2, "Screen update enabled");
_vm->_gfx->_updatesEnabled = true;
_vm->_gfx->updateScreen();
}
// Command 24: increment variable (variable, value)
-void RivenScript::incrementVariable(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::incrementVariable(uint16 op, uint16 argc, uint16 *argv) {
_vm->getStackVar(argv[0]) += argv[1];
}
// Command 27: go to stack (stack name, code high, code low)
-void RivenScript::changeStack(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::changeStack(uint16 op, uint16 argc, uint16 *argv) {
Common::String stackName = _vm->getName(StackNames, argv[0]);
int8 index = -1;
@@ -482,54 +447,54 @@ void RivenScript::changeStack(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 28: disable a movie
-void RivenScript::disableMovie(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::disableMovie(uint16 op, uint16 argc, uint16 *argv) {
VideoHandle handle = _vm->_video->findVideoHandleRiven(argv[0]);
if (handle)
handle->setEnabled(false);
}
// Command 29: disable all movies
-void RivenScript::disableAllMovies(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::disableAllMovies(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->disableAllMovies();
}
// Command 31: enable a movie
-void RivenScript::enableMovie(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::enableMovie(uint16 op, uint16 argc, uint16 *argv) {
VideoHandle handle = _vm->_video->findVideoHandleRiven(argv[0]);
if (handle)
handle->setEnabled(true);
}
// Command 32: play foreground movie - blocking (movie_id)
-void RivenScript::playMovieBlocking(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::playMovieBlocking(uint16 op, uint16 argc, uint16 *argv) {
_vm->_cursor->hideCursor();
_vm->_video->playMovieBlockingRiven(argv[0]);
_vm->_cursor->showCursor();
}
// Command 33: play background movie - nonblocking (movie_id)
-void RivenScript::playMovie(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::playMovie(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->playMovieRiven(argv[0]);
}
// Command 34: stop a movie
-void RivenScript::stopMovie(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::stopMovie(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->stopMovieRiven(argv[0]);
}
// Command 36: unknown
-void RivenScript::unk_36(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::unk_36(uint16 op, uint16 argc, uint16 *argv) {
debug(0, "unk_36: Ignoring");
}
// Command 37: fade ambient sounds
-void RivenScript::fadeAmbientSounds(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::fadeAmbientSounds(uint16 op, uint16 argc, uint16 *argv) {
// Similar to stopSound(), but does fading
_vm->_sound->stopAllSLST(true);
}
// Command 38: Store an opcode for use when playing a movie (movie id, time high, time low, opcode, arguments...)
-void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
// This opcode is used to delay an opcode's usage based on the elapsed
// time of a specified movie. However, every use in the game is for
// delaying an activateSLST opcode.
@@ -547,7 +512,7 @@ void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
// Build a script out of 'er
Common::SeekableReadStream *scriptStream = new Common::MemoryReadStream(scriptBuf, scriptSize, DisposeAfterUse::YES);
- RivenScript *script = new RivenScript(_vm, scriptStream, kStoredOpcodeScript, getParentStack(), getParentCard());
+ RivenScriptPtr script = _vm->_scriptMan->readScript(scriptStream, kStoredOpcodeScript);
uint32 delayTime = (argv[1] << 16) + argv[2];
@@ -563,21 +528,23 @@ void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
} else {
// Run immediately if we have no delay
script->runScript();
- delete script;
}
+
+ delete scriptStream;
}
// Command 39: activate PLST record (card picture lists)
-void RivenScript::activatePLST(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::activatePLST(uint16 op, uint16 argc, uint16 *argv) {
_vm->_gfx->drawPLST(argv[0]);
// An update is automatically sent here as long as it's not a load or update script and updates are enabled.
- if (_scriptType != kCardLoadScript && _scriptType != kCardUpdateScript)
+ // TODO: Fix the graphics manager
+ //if (_scriptType != kCardLoadScript && _scriptType != kCardUpdateScript)
_vm->_gfx->updateScreen();
}
// Command 40: activate SLST record (card ambient sound lists)
-void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
// WORKAROUND: Disable the SLST that is played during Riven's intro.
// Riven X does this too (spoke this over with Jeff)
if (_vm->getCurStack() == kStackTspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2)
@@ -588,13 +555,13 @@ void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 41: activate MLST record and play
-void RivenScript::activateMLSTAndPlay(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::activateMLSTAndPlay(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
_vm->_video->playMovieRiven(argv[0]);
}
// Command 43: activate BLST record (card hotspot enabling lists)
-void RivenScript::activateBLST(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::activateBLST(uint16 op, uint16 argc, uint16 *argv) {
Common::SeekableReadStream* blst = _vm->getResource(ID_BLST, _vm->getCurCard());
uint16 recordCount = blst->readUint16BE();
@@ -616,7 +583,7 @@ void RivenScript::activateBLST(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 44: activate FLST record (information on which SFXE resource this card should use)
-void RivenScript::activateFLST(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::activateFLST(uint16 op, uint16 argc, uint16 *argv) {
Common::SeekableReadStream* flst = _vm->getResource(ID_FLST, _vm->getCurCard());
uint16 recordCount = flst->readUint16BE();
@@ -637,7 +604,7 @@ void RivenScript::activateFLST(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 45: do zip mode
-void RivenScript::zipMode(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::zipMode(uint16 op, uint16 argc, uint16 *argv) {
// Check the ZIPS records to see if we have a match to the hotspot name
Common::String hotspotName = _vm->getHotspotName(_vm->getCurHotspot());
@@ -649,81 +616,120 @@ void RivenScript::zipMode(uint16 op, uint16 argc, uint16 *argv) {
}
// Command 46: activate MLST record (movie lists)
-void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
+void RivenSimpleCommand::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
}
-RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
- _vm = vm;
- _storedMovieOpcode.script = 0;
- _storedMovieOpcode.time = 0;
- _storedMovieOpcode.id = 0;
+void RivenSimpleCommand::dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) {
+ printTabs(tabs);
+
+ if (_type == 7) { // Use the variable name
+ uint16 var = _arguments[0];
+ debugN("%s = %d;\n", varNames[var].c_str(), _arguments[1]);
+ } else if (_type == 17) { // Use the external command name
+ debugN("%s(", xNames[_arguments[0]].c_str());
+ uint16 varCount = _arguments[1];
+ for (uint16 j = 0; j < varCount; j++) {
+ debugN("%d", _arguments[1 + j]);
+ if (j != varCount - 1)
+ debugN(", ");
+ }
+ debugN(");\n");
+ } else if (_type == 24) { // Use the variable name
+ uint16 var = _arguments[0];
+ debugN("%s += %d;\n", varNames[var].c_str(), _arguments[1]);
+ } else {
+ debugN("%s(", _opcodes[_type].desc);
+ for (uint16 j = 0; j < _arguments.size(); j++) {
+ debugN("%d", _arguments[j]);
+ if (j != _arguments.size() - 1)
+ debugN(", ");
+ }
+ debugN(");\n");
+ }
}
-RivenScriptManager::~RivenScriptManager() {
- for (uint32 i = 0; i < _currentScripts.size(); i++)
- delete _currentScripts[i];
+void RivenSimpleCommand::execute() {
+ uint16 *argValues = new uint16[_arguments.size()];
- clearStoredMovieOpcode();
+ for (uint16 k = 0; k < _arguments.size(); k++)
+ argValues[k] = _arguments[k];
+
+ debug (4, "Running opcode %04x, argument count %d", _type, _arguments.size());
+ (this->*(_opcodes[_type].proc)) (_type, _arguments.size(), argValues);
+
+ delete[] argValues;
}
-RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) {
- if (garbageCollect)
- unloadUnusedScripts(); // Garbage collect!
+RivenSwitchCommand::RivenSwitchCommand(MohawkEngine_Riven *vm) :
+ RivenCommand(vm),
+ _variableId(0) {
- RivenScriptList scriptList;
+}
- uint16 scriptCount = stream->readUint16BE();
- for (uint16 i = 0; i < scriptCount; i++) {
- uint16 scriptType = stream->readUint16BE();
- uint32 scriptSize = RivenScript::calculateScriptSize(stream);
- RivenScript *script = new RivenScript(_vm, stream->readStream(scriptSize), scriptType, _vm->getCurStack(), _vm->getCurCard());
- scriptList.push_back(script);
+RivenSwitchCommand::~RivenSwitchCommand() {
+
+}
+
+RivenSwitchCommand *RivenSwitchCommand::createFromStream(MohawkEngine_Riven *vm, int type, Common::ReadStream *stream) {
+ RivenSwitchCommand *command = new RivenSwitchCommand(vm);
- // Only add it to the scripts that we will free later if it is requested.
- // (ie. we don't want to store scripts from the dumpScript console command)
- if (garbageCollect)
- _currentScripts.push_back(script);
+ if (stream->readUint16BE() != 2) {
+ // This value is not used in the original engine
+ warning("if-then-else unknown value is not 2");
}
- return scriptList;
-}
+ // variable to check against
+ command->_variableId = stream->readUint16BE();
-void RivenScriptManager::stopAllScripts() {
- for (uint32 i = 0; i < _currentScripts.size(); i++)
- _currentScripts[i]->stopRunning();
-}
+ // number of logic blocks
+ uint16 logicBlockCount = stream->readUint16BE();
+ command->_branches.resize(logicBlockCount);
-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++) {
- if ((_vm->getCurStack() != _currentScripts[i]->getParentStack() || _vm->getCurCard() != _currentScripts[i]->getParentCard()) && !_currentScripts[i]->isRunning()) {
- delete _currentScripts[i];
- _currentScripts.remove_at(i);
- i--;
- }
+ for (uint16 i = 0; i < logicBlockCount; i++) {
+ Branch &branch = command->_branches[i];
+
+ // Value for this logic block
+ branch.value = stream->readUint16BE();
+ branch.script = vm->_scriptMan->readScript(stream, kStoredOpcodeScript);
}
-}
-void RivenScriptManager::setStoredMovieOpcode(const StoredMovieOpcode &op) {
- clearStoredMovieOpcode();
- _storedMovieOpcode.script = op.script;
- _storedMovieOpcode.id = op.id;
- _storedMovieOpcode.time = op.time;
+ return command;
}
-void RivenScriptManager::runStoredMovieOpcode() {
- if (_storedMovieOpcode.script) {
- _storedMovieOpcode.script->runScript();
- clearStoredMovieOpcode();
+void RivenSwitchCommand::dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) {
+ printTabs(tabs); debugN("switch (%s) {\n", varNames[_variableId].c_str());
+ for (uint16 j = 0; j < _branches.size(); j++) {
+ printTabs(tabs + 1);
+ if (_branches[j].value == 0xFFFF)
+ debugN("default:\n");
+ else
+ debugN("case %d:\n", _branches[j].value);
+ _branches[j].script->dumpScript(varNames, xNames, tabs + 2);
+ printTabs(tabs + 2); debugN("break;\n");
}
+ printTabs(tabs); debugN("}\n");
}
-void RivenScriptManager::clearStoredMovieOpcode() {
- delete _storedMovieOpcode.script;
- _storedMovieOpcode.script = 0;
- _storedMovieOpcode.time = 0;
- _storedMovieOpcode.id = 0;
+void RivenSwitchCommand::execute() {
+ // Get the switch variable value
+ uint32 value = _vm->getStackVar(_variableId);
+
+ // Look for a case matching the value
+ for (uint i = 0; i < _branches.size(); i++) {
+ if (_branches[i].value == value) {
+ _branches[i].script->runScript();
+ return;
+ }
+ }
+
+ // Look for the default case if any
+ for (uint i = 0; i < _branches.size(); i++) {
+ if (_branches[i].value == 0Xffff) {
+ _branches[i].script->runScript();
+ return;
+ }
+ }
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index b669cd5081..9163345a64 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -49,25 +49,93 @@ enum {
};
class MohawkEngine_Riven;
-class RivenScript;
+class RivenCommand;
class RivenScript {
public:
- RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard);
+ RivenScript(MohawkEngine_Riven *vm, uint16 scriptType);
~RivenScript();
+ void addCommand(RivenCommand *command);
+
void runScript();
void dumpScript(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs);
uint16 getScriptType() { return _scriptType; }
- uint16 getParentStack() { return _parentStack; }
- uint16 getParentCard() { return _parentCard; }
- bool isRunning() { return _isRunning; }
void stopRunning() { _continueRunning = false; }
- static uint32 calculateScriptSize(Common::SeekableReadStream *script);
+private:
+ MohawkEngine_Riven *_vm;
+
+ Common::Array<RivenCommand *> _commands;
+ uint16 _scriptType;
+ bool _continueRunning;
+
+ void dumpCommands(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs);
+};
+
+typedef Common::SharedPtr<RivenScript> RivenScriptPtr;
+typedef Common::Array<RivenScriptPtr> RivenScriptList;
+
+class RivenScriptManager {
+public:
+ RivenScriptManager(MohawkEngine_Riven *vm);
+ ~RivenScriptManager();
+
+ RivenScriptPtr readScript(Common::ReadStream *stream, uint16 scriptType);
+ RivenScriptList readScripts(Common::ReadStream *stream);
+ void stopAllScripts();
+
+ struct StoredMovieOpcode {
+ RivenScriptPtr script;
+ uint32 time;
+ uint16 id;
+ };
+
+ uint16 getStoredMovieOpcodeID() { return _storedMovieOpcode.id; }
+ uint32 getStoredMovieOpcodeTime() { return _storedMovieOpcode.time; }
+ void setStoredMovieOpcode(const StoredMovieOpcode &op);
+ void runStoredMovieOpcode();
+ void clearStoredMovieOpcode();
private:
- typedef void (RivenScript::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv);
+ MohawkEngine_Riven *_vm;
+
+ StoredMovieOpcode _storedMovieOpcode;
+
+ RivenCommand *readCommand(Common::ReadStream *stream);
+};
+
+class RivenCommand {
+public:
+ RivenCommand(MohawkEngine_Riven *vm);
+ virtual ~RivenCommand();
+
+ virtual void dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) = 0;
+
+ virtual void execute() = 0;
+
+protected:
+ MohawkEngine_Riven *_vm;
+};
+
+class RivenSimpleCommand : public RivenCommand {
+public:
+ static RivenSimpleCommand *createFromStream(MohawkEngine_Riven *vm, int type, Common::ReadStream *stream);
+ virtual ~RivenSimpleCommand();
+
+ // RivenCommand API
+ virtual void dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) override;
+ virtual void execute() override;
+
+private:
+ typedef Common::Array<uint16> ArgumentArray;
+
+ RivenSimpleCommand(MohawkEngine_Riven *vm, int type, const ArgumentArray &arguments);
+
+ int _type;
+ ArgumentArray _arguments;
+
+ typedef void (RivenSimpleCommand::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv);
struct RivenOpcode {
OpcodeProcRiven proc;
const char *desc;
@@ -75,16 +143,6 @@ private:
const RivenOpcode *_opcodes;
void setupOpcodes();
- MohawkEngine_Riven *_vm;
- Common::SeekableReadStream *_stream;
- uint16 _scriptType, _parentStack, _parentCard;
- bool _isRunning, _continueRunning;
-
- void dumpCommands(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs);
- void processCommands(bool runCommands);
-
- static uint32 calculateCommandSize(Common::SeekableReadStream *script);
-
DECLARE_OPCODE(empty) { warning ("Unknown Opcode %04x", op); }
//Opcodes
@@ -124,34 +182,25 @@ private:
DECLARE_OPCODE(activateMLST);
};
-typedef Common::Array<RivenScript *> RivenScriptList;
-
-class RivenScriptManager {
+class RivenSwitchCommand : public RivenCommand {
public:
- RivenScriptManager(MohawkEngine_Riven *vm);
- ~RivenScriptManager();
+ static RivenSwitchCommand *createFromStream(MohawkEngine_Riven *vm, int type, Common::ReadStream *stream);
+ virtual ~RivenSwitchCommand();
- RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
- void stopAllScripts();
-
- struct StoredMovieOpcode {
- RivenScript *script;
- uint32 time;
- uint16 id;
- };
-
- uint16 getStoredMovieOpcodeID() { return _storedMovieOpcode.id; }
- uint32 getStoredMovieOpcodeTime() { return _storedMovieOpcode.time; }
- void setStoredMovieOpcode(const StoredMovieOpcode &op);
- void runStoredMovieOpcode();
- void clearStoredMovieOpcode();
+ // RivenCommand API
+ virtual void dump(const Common::StringArray &varNames, const Common::StringArray &xNames, byte tabs) override;
+ virtual void execute() override;
private:
- void unloadUnusedScripts();
- RivenScriptList _currentScripts;
- MohawkEngine_Riven *_vm;
+ RivenSwitchCommand(MohawkEngine_Riven *vm);
- StoredMovieOpcode _storedMovieOpcode;
+ struct Branch {
+ uint16 value;
+ RivenScriptPtr script;
+ };
+
+ uint16 _variableId;
+ Common::Array<Branch> _branches;
};
} // End of namespace Mohawk