2009-12-29 23:18:24 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2014-02-18 02:34:22 +01:00
|
|
|
*
|
2009-12-29 23:18:24 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2014-02-18 02:34:22 +01:00
|
|
|
*
|
2009-12-29 23:18:24 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-11-25 04:49:11 +00:00
|
|
|
#include "mohawk/cursors.h"
|
2009-12-29 23:18:24 +00:00
|
|
|
#include "mohawk/riven.h"
|
2016-08-03 20:07:13 +02:00
|
|
|
#include "mohawk/riven_card.h"
|
2012-03-10 13:50:27 -05:00
|
|
|
#include "mohawk/riven_graphics.h"
|
2009-12-29 23:18:24 +00:00
|
|
|
#include "mohawk/riven_scripts.h"
|
2016-08-08 07:35:55 +02:00
|
|
|
#include "mohawk/riven_sound.h"
|
2016-08-07 09:22:40 +02:00
|
|
|
#include "mohawk/riven_stack.h"
|
2010-05-23 18:33:55 +00:00
|
|
|
#include "mohawk/video.h"
|
2011-03-22 20:31:54 -04:00
|
|
|
#include "common/memstream.h"
|
2017-01-28 14:55:24 +01:00
|
|
|
|
|
|
|
#include "common/debug-channels.h"
|
2009-12-29 23:18:24 +00:00
|
|
|
#include "common/stream.h"
|
2011-04-24 11:34:27 +03:00
|
|
|
#include "common/system.h"
|
2009-12-29 23:18:24 +00:00
|
|
|
|
|
|
|
namespace Mohawk {
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
static void printTabs(byte tabs) {
|
|
|
|
for (byte i = 0; i < tabs; i++)
|
|
|
|
debugN("\t");
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-04 14:34:45 +01:00
|
|
|
RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) :
|
|
|
|
_vm(vm),
|
|
|
|
_runningQueuedScripts(false) {
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
_storedMovieOpcode.time = 0;
|
|
|
|
_storedMovieOpcode.id = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RivenScriptManager::~RivenScriptManager() {
|
|
|
|
clearStoredMovieOpcode();
|
|
|
|
}
|
|
|
|
|
2016-08-02 19:43:15 +02:00
|
|
|
RivenScriptPtr RivenScriptManager::readScript(Common::ReadStream *stream) {
|
2016-08-02 21:04:34 +02:00
|
|
|
RivenScriptPtr script = RivenScriptPtr(new RivenScript());
|
2016-08-02 18:56:55 +02:00
|
|
|
|
|
|
|
uint16 commandCount = stream->readUint16BE();
|
|
|
|
|
|
|
|
for (uint16 i = 0; i < commandCount; i++) {
|
2017-01-28 14:02:12 +01:00
|
|
|
RivenCommandPtr command = readCommand(stream);
|
2016-08-02 18:56:55 +02:00
|
|
|
script->addCommand(command);
|
|
|
|
}
|
|
|
|
|
|
|
|
return script;
|
|
|
|
}
|
|
|
|
|
2017-01-28 14:02:12 +01:00
|
|
|
RivenCommandPtr RivenScriptManager::readCommand(Common::ReadStream *stream) {
|
2017-02-11 12:31:13 +01:00
|
|
|
RivenCommandType type = (RivenCommandType) stream->readUint16BE();
|
2016-08-02 18:56:55 +02:00
|
|
|
|
2016-11-05 08:35:03 +01:00
|
|
|
switch (type) {
|
2017-02-11 12:31:13 +01:00
|
|
|
case kRivenCommandSwitch:
|
|
|
|
return RivenCommandPtr(RivenSwitchCommand::createFromStream(_vm, stream));
|
|
|
|
case kRivenCommandChangeStack:
|
|
|
|
return RivenCommandPtr(RivenStackChangeCommand::createFromStream(_vm, stream));
|
2016-11-05 08:35:03 +01:00
|
|
|
default:
|
2017-01-28 14:02:12 +01:00
|
|
|
return RivenCommandPtr(RivenSimpleCommand::createFromStream(_vm, type, stream));
|
2016-08-02 18:56:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RivenScriptList RivenScriptManager::readScripts(Common::ReadStream *stream) {
|
|
|
|
RivenScriptList scriptList;
|
|
|
|
|
|
|
|
uint16 scriptCount = stream->readUint16BE();
|
|
|
|
for (uint16 i = 0; i < scriptCount; i++) {
|
2016-08-02 19:43:15 +02:00
|
|
|
RivenTypedScript script;
|
|
|
|
script.type = stream->readUint16BE();
|
|
|
|
script.script = readScript(stream);
|
2016-08-02 18:56:55 +02:00
|
|
|
scriptList.push_back(script);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
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) {
|
2016-08-02 21:43:22 +02:00
|
|
|
runScript(_storedMovieOpcode.script, false);
|
2016-08-02 18:56:55 +02:00
|
|
|
clearStoredMovieOpcode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RivenScriptManager::clearStoredMovieOpcode() {
|
|
|
|
_storedMovieOpcode.script = RivenScriptPtr();
|
|
|
|
_storedMovieOpcode.time = 0;
|
|
|
|
_storedMovieOpcode.id = 0;
|
|
|
|
}
|
|
|
|
|
2016-08-02 21:43:22 +02:00
|
|
|
void RivenScriptManager::runScript(const RivenScriptPtr &script, bool queue) {
|
|
|
|
if (!queue) {
|
|
|
|
script->run();
|
|
|
|
} else {
|
|
|
|
_queue.push_back(script);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-28 14:04:12 +01:00
|
|
|
bool RivenScriptManager::hasQueuedScripts() const {
|
|
|
|
return !_queue.empty();
|
|
|
|
}
|
|
|
|
|
2017-02-04 14:34:45 +01:00
|
|
|
void RivenScriptManager::runQueuedScripts() {
|
|
|
|
_runningQueuedScripts = true;
|
|
|
|
|
|
|
|
for (uint i = 0; i < _queue.size(); i++) {
|
|
|
|
_queue[i]->run();
|
|
|
|
}
|
|
|
|
|
|
|
|
_queue.clear();
|
|
|
|
|
|
|
|
_runningQueuedScripts = false;
|
|
|
|
}
|
|
|
|
|
2016-08-04 06:28:04 +02:00
|
|
|
RivenScriptPtr RivenScriptManager::createScriptFromData(uint16 commandCount, ...) {
|
|
|
|
va_list args;
|
|
|
|
va_start(args, commandCount);
|
|
|
|
|
|
|
|
// Build a script from the variadic arguments
|
|
|
|
Common::MemoryWriteStreamDynamic writeStream = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
|
|
|
|
writeStream.writeUint16BE(commandCount);
|
|
|
|
|
|
|
|
for (uint i = 0; i < commandCount; i++) {
|
|
|
|
uint16 command = va_arg(args, int);
|
|
|
|
writeStream.writeUint16BE(command);
|
|
|
|
|
2017-02-11 12:31:13 +01:00
|
|
|
if (command == kRivenCommandSwitch) {
|
2016-08-04 06:28:04 +02:00
|
|
|
// The switch command has a different format that is not implemented
|
|
|
|
error("Cannot create a Switch command from data");
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 argumentCount = va_arg(args, int);
|
|
|
|
writeStream.writeUint16BE(argumentCount);
|
|
|
|
|
|
|
|
for (uint j = 0; j < commandCount; j++) {
|
|
|
|
uint16 argument = va_arg(args, int);
|
|
|
|
writeStream.writeUint16BE(argument);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
Common::MemoryReadStream readStream = Common::MemoryReadStream(writeStream.getData(), writeStream.size());
|
|
|
|
return readScript(&readStream);
|
|
|
|
}
|
|
|
|
|
2016-11-05 08:33:34 +01:00
|
|
|
RivenScriptPtr RivenScriptManager::createScriptWithCommand(RivenCommand *command) {
|
|
|
|
assert(command);
|
|
|
|
|
|
|
|
RivenScriptPtr script = RivenScriptPtr(new RivenScript());
|
2017-01-28 14:02:12 +01:00
|
|
|
script->addCommand(RivenCommandPtr(command));
|
2016-11-05 08:33:34 +01:00
|
|
|
return script;
|
|
|
|
}
|
|
|
|
|
2017-02-04 14:34:45 +01:00
|
|
|
bool RivenScriptManager::runningQueuedScripts() const {
|
|
|
|
return _runningQueuedScripts;
|
|
|
|
}
|
|
|
|
|
2016-08-02 21:04:34 +02:00
|
|
|
RivenScript::RivenScript() {
|
2016-08-02 18:56:55 +02:00
|
|
|
_continueRunning = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
RivenScript::~RivenScript() {
|
|
|
|
}
|
|
|
|
|
2016-08-06 14:36:41 +02:00
|
|
|
void RivenScript::dumpScript(byte tabs) {
|
2016-08-02 18:56:55 +02:00
|
|
|
for (uint16 i = 0; i < _commands.size(); i++) {
|
2016-08-06 14:36:41 +02:00
|
|
|
_commands[i]->dump(tabs);
|
2016-08-02 18:56:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-02 21:43:22 +02:00
|
|
|
void RivenScript::run() {
|
2017-01-28 14:02:12 +01:00
|
|
|
for (uint i = 0; i < _commands.size() && _continueRunning; i++) {
|
2016-08-02 18:56:55 +02:00
|
|
|
_commands[i]->execute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-28 14:02:12 +01:00
|
|
|
void RivenScript::addCommand(RivenCommandPtr command) {
|
2016-08-02 18:56:55 +02:00
|
|
|
_commands.push_back(command);
|
|
|
|
}
|
|
|
|
|
2016-08-06 19:22:12 +02:00
|
|
|
bool RivenScript::empty() const {
|
|
|
|
return _commands.empty();
|
|
|
|
}
|
|
|
|
|
2016-08-07 07:47:18 +02:00
|
|
|
RivenScript &RivenScript::operator+=(const RivenScript &other) {
|
|
|
|
_commands.push_back(other._commands);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-08-13 08:57:06 +02:00
|
|
|
const char *RivenScript::getTypeName(uint16 type) {
|
|
|
|
static const char *names[] = {
|
|
|
|
"MouseDown",
|
|
|
|
"MouseDrag",
|
|
|
|
"MouseUp",
|
|
|
|
"MouseEnter",
|
|
|
|
"MouseInside",
|
|
|
|
"MouseLeave",
|
|
|
|
"CardLoad",
|
|
|
|
"CardLeave",
|
|
|
|
"CardUnknown",
|
2016-08-13 09:02:28 +02:00
|
|
|
"CardEnter",
|
2016-08-13 08:57:06 +02:00
|
|
|
"CardUpdate"
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(type < ARRAYSIZE(names));
|
|
|
|
return names[type];
|
|
|
|
}
|
|
|
|
|
2016-08-07 07:47:18 +02:00
|
|
|
RivenScriptPtr &operator+=(RivenScriptPtr &lhs, const RivenScriptPtr &rhs) {
|
|
|
|
*lhs += *rhs;
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
RivenCommand::RivenCommand(MohawkEngine_Riven *vm) :
|
|
|
|
_vm(vm) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
RivenCommand::~RivenCommand() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-02-11 12:31:13 +01:00
|
|
|
RivenSimpleCommand::RivenSimpleCommand(MohawkEngine_Riven *vm, RivenCommandType type, const ArgumentArray &arguments) :
|
2016-08-02 18:56:55 +02:00
|
|
|
RivenCommand(vm),
|
|
|
|
_type(type),
|
|
|
|
_arguments(arguments) {
|
|
|
|
setupOpcodes();
|
|
|
|
}
|
|
|
|
|
|
|
|
RivenSimpleCommand::~RivenSimpleCommand() {
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-11 12:31:13 +01:00
|
|
|
RivenSimpleCommand *RivenSimpleCommand::createFromStream(MohawkEngine_Riven *vm, RivenCommandType type, Common::ReadStream *stream) {
|
2016-08-02 18:56:55 +02:00
|
|
|
uint16 argCount = stream->readUint16BE();
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
Common::Array<uint16> arguments;
|
|
|
|
arguments.resize(argCount);
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
for (uint16 i = 0; i < argCount; i++) {
|
|
|
|
arguments[i] = stream->readUint16BE();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new RivenSimpleCommand(vm, type, arguments);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
#define OPCODE(x) { &RivenSimpleCommand::x, #x }
|
2009-12-29 23:18:24 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::setupOpcodes() {
|
2009-12-29 23:18:24 +00:00
|
|
|
static const RivenOpcode riven_opcodes[] = {
|
|
|
|
// 0x00 (0 decimal)
|
|
|
|
OPCODE(empty),
|
|
|
|
OPCODE(drawBitmap),
|
|
|
|
OPCODE(switchCard),
|
|
|
|
OPCODE(playScriptSLST),
|
|
|
|
// 0x04 (4 decimal)
|
|
|
|
OPCODE(playSound),
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
OPCODE(empty), // Complex animation (not used)
|
|
|
|
OPCODE(setVariable),
|
|
|
|
// 0x08 (8 decimal)
|
2016-11-05 08:35:03 +01:00
|
|
|
OPCODE(empty), // Not a SimpleCommand
|
2009-12-29 23:18:24 +00:00
|
|
|
OPCODE(enableHotspot),
|
|
|
|
OPCODE(disableHotspot),
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
// 0x0C (12 decimal)
|
2011-01-23 05:12:50 +00:00
|
|
|
OPCODE(stopSound),
|
2009-12-29 23:18:24 +00:00
|
|
|
OPCODE(changeCursor),
|
|
|
|
OPCODE(delay),
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
// 0x10 (16 decimal)
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
OPCODE(runExternalCommand),
|
|
|
|
OPCODE(transition),
|
|
|
|
OPCODE(refreshCard),
|
|
|
|
// 0x14 (20 decimal)
|
2016-08-04 07:19:51 +02:00
|
|
|
OPCODE(beginScreenUpdate),
|
|
|
|
OPCODE(applyScreenUpdate),
|
2009-12-29 23:18:24 +00:00
|
|
|
OPCODE(empty), // Empty
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
// 0x18 (24 decimal)
|
|
|
|
OPCODE(incrementVariable),
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
OPCODE(empty), // Empty
|
2016-11-05 08:35:03 +01:00
|
|
|
OPCODE(empty), // Not a SimpleCommand
|
2009-12-29 23:18:24 +00:00
|
|
|
// 0x1C (28 decimal)
|
|
|
|
OPCODE(disableMovie),
|
|
|
|
OPCODE(disableAllMovies),
|
|
|
|
OPCODE(empty), // Set movie rate (not used)
|
|
|
|
OPCODE(enableMovie),
|
|
|
|
// 0x20 (32 decimal)
|
2011-01-18 20:30:16 +00:00
|
|
|
OPCODE(playMovieBlocking),
|
2009-12-29 23:18:24 +00:00
|
|
|
OPCODE(playMovie),
|
|
|
|
OPCODE(stopMovie),
|
|
|
|
OPCODE(empty), // Start a water effect (not used)
|
|
|
|
// 0x24 (36 decimal)
|
|
|
|
OPCODE(unk_36), // Unknown
|
|
|
|
OPCODE(fadeAmbientSounds),
|
2011-03-22 20:31:54 -04:00
|
|
|
OPCODE(storeMovieOpcode),
|
2009-12-29 23:18:24 +00:00
|
|
|
OPCODE(activatePLST),
|
|
|
|
// 0x28 (40 decimal)
|
|
|
|
OPCODE(activateSLST),
|
|
|
|
OPCODE(activateMLSTAndPlay),
|
|
|
|
OPCODE(empty), // Empty
|
|
|
|
OPCODE(activateBLST),
|
|
|
|
// 0x2C (44 decimal)
|
|
|
|
OPCODE(activateFLST),
|
|
|
|
OPCODE(zipMode),
|
|
|
|
OPCODE(activateMLST),
|
2010-07-09 16:53:20 +00:00
|
|
|
OPCODE(empty) // Activate an SLST with a volume parameter (not used)
|
2009-12-29 23:18:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
_opcodes = riven_opcodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// Opcodes
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
// Command 1: draw tBMP resource (tbmp_id, left, top, right, bottom, u0, u1, u2, u3)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::drawBitmap(uint16 op, uint16 argc, uint16 *argv) {
|
2010-06-02 15:26:35 +00:00
|
|
|
if (argc < 5) // Copy the image to the whole screen, ignoring the rest of the parameters
|
2009-12-29 23:18:24 +00:00
|
|
|
_vm->_gfx->copyImageToScreen(argv[0], 0, 0, 608, 392);
|
2011-01-19 15:22:39 +00:00
|
|
|
else // Copy the image to a certain part of the screen
|
2009-12-29 23:18:24 +00:00
|
|
|
_vm->_gfx->copyImageToScreen(argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Command 2: go to card (card id)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::switchCard(uint16 op, uint16 argc, uint16 *argv) {
|
2009-12-29 23:18:24 +00:00
|
|
|
_vm->changeToCard(argv[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Command 3: play an SLST from the script
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::playScriptSLST(uint16 op, uint16 argc, uint16 *argv) {
|
2009-12-29 23:18:24 +00:00
|
|
|
int offset = 0, j = 0;
|
2016-08-08 07:35:55 +02:00
|
|
|
uint16 soundCount = argv[offset++];
|
2009-12-29 23:18:24 +00:00
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
SLSTRecord slstRecord;
|
2009-12-29 23:18:24 +00:00
|
|
|
slstRecord.index = 0; // not set by the scripts, so we set it to 0
|
2016-08-08 07:35:55 +02:00
|
|
|
slstRecord.soundIds.resize(soundCount);
|
2009-12-29 23:18:24 +00:00
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
for (j = 0; j < soundCount; j++)
|
|
|
|
slstRecord.soundIds[j] = argv[offset++];
|
|
|
|
slstRecord.fadeFlags = argv[offset++];
|
2009-12-29 23:18:24 +00:00
|
|
|
slstRecord.loop = argv[offset++];
|
2016-08-08 07:35:55 +02:00
|
|
|
slstRecord.globalVolume = argv[offset++];
|
2010-01-25 01:39:44 +00:00
|
|
|
slstRecord.u0 = argv[offset++];
|
2016-08-08 07:35:55 +02:00
|
|
|
slstRecord.suspend = argv[offset++];
|
2009-12-29 23:18:24 +00:00
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
slstRecord.volumes.resize(soundCount);
|
|
|
|
slstRecord.balances.resize(soundCount);
|
|
|
|
slstRecord.u2.resize(soundCount);
|
2009-12-29 23:18:24 +00:00
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
for (j = 0; j < soundCount; j++)
|
2009-12-29 23:18:24 +00:00
|
|
|
slstRecord.volumes[j] = argv[offset++];
|
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
for (j = 0; j < soundCount; j++)
|
2009-12-29 23:18:24 +00:00
|
|
|
slstRecord.balances[j] = argv[offset++]; // negative = left, 0 = center, positive = right
|
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
for (j = 0; j < soundCount; j++)
|
2009-12-29 23:18:24 +00:00
|
|
|
slstRecord.u2[j] = argv[offset++]; // Unknown
|
|
|
|
|
|
|
|
// Play the requested sound list
|
|
|
|
_vm->_sound->playSLST(slstRecord);
|
|
|
|
}
|
|
|
|
|
2010-09-08 20:50:56 +00:00
|
|
|
// Command 4: play local tWAV resource (twav_id, volume, block)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::playSound(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-08 07:35:55 +02:00
|
|
|
uint16 volume = argv[1];
|
|
|
|
bool playOnDraw = argv[2] == 1;
|
2010-09-08 20:50:56 +00:00
|
|
|
|
2016-08-08 07:35:55 +02:00
|
|
|
_vm->_sound->playSound(argv[0], volume, playOnDraw);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 7: set variable value (variable, value)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::setVariable(uint16 op, uint16 argc, uint16 *argv) {
|
2011-03-23 23:14:59 -04:00
|
|
|
_vm->getStackVar(argv[0]) = argv[1];
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 9: enable hotspot (blst_id)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::enableHotspot(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-07 11:26:43 +02:00
|
|
|
RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(argv[0]);
|
2016-08-06 06:41:04 +02:00
|
|
|
if (hotspot) {
|
|
|
|
hotspot->enable(true);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
2011-01-24 02:43:07 +00:00
|
|
|
|
|
|
|
// Recheck our current hotspot because it may have now changed
|
|
|
|
_vm->updateCurrentHotspot();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 10: disable hotspot (blst_id)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::disableHotspot(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-07 11:26:43 +02:00
|
|
|
RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(argv[0]);
|
2016-08-06 06:41:04 +02:00
|
|
|
if (hotspot) {
|
|
|
|
hotspot->enable(false);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
2011-01-24 02:43:07 +00:00
|
|
|
|
|
|
|
// Recheck our current hotspot because it may have now changed
|
|
|
|
_vm->updateCurrentHotspot();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2011-01-23 05:12:50 +00:00
|
|
|
// Command 12: stop sounds (flags)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::stopSound(uint16 op, uint16 argc, uint16 *argv) {
|
2011-01-23 07:02:49 +00:00
|
|
|
// 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
|
|
|
|
// would cause all ambient sounds not to play. An alternative
|
|
|
|
// fix would be to stop all scripts on a stack change, but this
|
|
|
|
// does fine for now.
|
2016-08-07 11:26:43 +02:00
|
|
|
if (_vm->getStack()->getId() == kStackTspit && (_vm->getStack()->getCurrentCardGlobalId() == 0x6e9a ||
|
|
|
|
_vm->getStack()->getCurrentCardGlobalId() == 0xfeeb))
|
2011-01-23 07:02:49 +00:00
|
|
|
return;
|
|
|
|
|
2011-01-23 05:12:50 +00:00
|
|
|
// The argument is a bitflag for the setting.
|
2011-06-14 10:46:48 -04:00
|
|
|
// bit 0 is normal sound stopping
|
2011-01-23 05:12:50 +00:00
|
|
|
// bit 1 is ambient sound stopping
|
|
|
|
// Having no flags set means clear all
|
2011-01-23 07:02:49 +00:00
|
|
|
if (argv[0] & 2 || argv[0] == 0)
|
|
|
|
_vm->_sound->stopAllSLST();
|
2011-01-23 05:12:50 +00:00
|
|
|
|
2011-06-14 10:46:48 -04:00
|
|
|
if (argv[0] & 1 || argv[0] == 0)
|
|
|
|
_vm->_sound->stopSound();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 13: set mouse cursor (cursor_id)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::changeCursor(uint16 op, uint16 argc, uint16 *argv) {
|
2010-11-25 04:49:11 +00:00
|
|
|
_vm->_cursor->setCursor(argv[0]);
|
2011-03-07 01:07:53 -05:00
|
|
|
_vm->_system->updateScreen();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 14: pause script execution (delay in ms, u1)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::delay(uint16 op, uint16 argc, uint16 *argv) {
|
2009-12-29 23:18:24 +00:00
|
|
|
if (argv[0] > 0)
|
2010-09-01 23:39:25 +00:00
|
|
|
_vm->delayAndUpdate(argv[0]);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 17: call external command
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::runExternalCommand(uint16 op, uint16 argc, uint16 *argv) {
|
2016-11-01 19:19:26 +01:00
|
|
|
_vm->getStack()->runCommand(argc, argv);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 18: transition
|
2011-01-19 15:22:39 +00:00
|
|
|
// Note that this opcode has 1 or 5 parameters, depending on argc
|
2009-12-29 23:18:24 +00:00
|
|
|
// Parameter 0: transition type
|
|
|
|
// Parameters 1-4: transition rectangle
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::transition(uint16 op, uint16 argc, uint16 *argv) {
|
2010-02-26 08:14:33 +00:00
|
|
|
if (argc == 1)
|
2017-02-11 12:05:43 +01:00
|
|
|
_vm->_gfx->scheduleTransition((RivenTransition) argv[0]);
|
2010-02-26 08:14:33 +00:00
|
|
|
else
|
2017-02-11 12:05:43 +01:00
|
|
|
_vm->_gfx->scheduleTransition((RivenTransition) argv[0], Common::Rect(argv[1], argv[2], argv[3], argv[4]));
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 19: reload card
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::refreshCard(uint16 op, uint16 argc, uint16 *argv) {
|
2010-02-26 08:14:33 +00:00
|
|
|
_vm->refreshCard();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-04 07:19:51 +02:00
|
|
|
// Command 20: begin screen update
|
|
|
|
void RivenSimpleCommand::beginScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
|
|
|
|
_vm->_gfx->beginScreenUpdate();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-04 07:19:51 +02:00
|
|
|
// Command 21: apply screen update
|
|
|
|
void RivenSimpleCommand::applyScreenUpdate(uint16 op, uint16 argc, uint16 *argv) {
|
|
|
|
_vm->_gfx->applyScreenUpdate();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 24: increment variable (variable, value)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::incrementVariable(uint16 op, uint16 argc, uint16 *argv) {
|
2011-03-23 23:14:59 -04:00
|
|
|
_vm->getStackVar(argv[0]) += argv[1];
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 28: disable a movie
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::disableMovie(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-13 14:02:29 +02:00
|
|
|
VideoEntryPtr video = _vm->_video->findVideoRiven(argv[0]);
|
|
|
|
if (video)
|
|
|
|
video->setEnabled(false);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 29: disable all movies
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::disableAllMovies(uint16 op, uint16 argc, uint16 *argv) {
|
2009-12-29 23:18:24 +00:00
|
|
|
_vm->_video->disableAllMovies();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Command 31: enable a movie
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::enableMovie(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-13 14:02:29 +02:00
|
|
|
VideoEntryPtr video = _vm->_video->findVideoRiven(argv[0]);
|
|
|
|
if (video)
|
|
|
|
video->setEnabled(true);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 32: play foreground movie - blocking (movie_id)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::playMovieBlocking(uint16 op, uint16 argc, uint16 *argv) {
|
2011-03-22 20:13:01 -04:00
|
|
|
_vm->_cursor->hideCursor();
|
2011-01-18 20:30:16 +00:00
|
|
|
_vm->_video->playMovieBlockingRiven(argv[0]);
|
2011-03-22 20:13:01 -04:00
|
|
|
_vm->_cursor->showCursor();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 33: play background movie - nonblocking (movie_id)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::playMovie(uint16 op, uint16 argc, uint16 *argv) {
|
2011-01-18 20:30:16 +00:00
|
|
|
_vm->_video->playMovieRiven(argv[0]);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 34: stop a movie
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::stopMovie(uint16 op, uint16 argc, uint16 *argv) {
|
2011-01-18 20:30:16 +00:00
|
|
|
_vm->_video->stopMovieRiven(argv[0]);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 36: unknown
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::unk_36(uint16 op, uint16 argc, uint16 *argv) {
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 37: fade ambient sounds
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::fadeAmbientSounds(uint16 op, uint16 argc, uint16 *argv) {
|
2011-01-23 07:02:49 +00:00
|
|
|
// Similar to stopSound(), but does fading
|
|
|
|
_vm->_sound->stopAllSLST(true);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2011-03-22 20:31:54 -04:00
|
|
|
// Command 38: Store an opcode for use when playing a movie (movie id, time high, time low, opcode, arguments...)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) {
|
2011-06-14 10:35:58 -04:00
|
|
|
// 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.
|
|
|
|
|
2011-03-22 20:31:54 -04:00
|
|
|
uint32 scriptSize = 6 + (argc - 4) * 2;
|
2011-01-19 15:22:39 +00:00
|
|
|
|
2011-03-22 20:31:54 -04:00
|
|
|
// Create our dummy script
|
|
|
|
byte *scriptBuf = (byte *)malloc(scriptSize);
|
|
|
|
WRITE_BE_UINT16(scriptBuf, 1); // One command
|
|
|
|
WRITE_BE_UINT16(scriptBuf + 2, argv[3]); // One opcode
|
2011-06-20 00:59:48 +02:00
|
|
|
WRITE_BE_UINT16(scriptBuf + 4, argc - 4); // argc - 4 args
|
2011-03-22 20:31:54 -04:00
|
|
|
|
|
|
|
for (int i = 0; i < argc - 4; i++)
|
|
|
|
WRITE_BE_UINT16(scriptBuf + 6 + (i * 2), argv[i + 4]);
|
|
|
|
|
|
|
|
// Build a script out of 'er
|
|
|
|
Common::SeekableReadStream *scriptStream = new Common::MemoryReadStream(scriptBuf, scriptSize, DisposeAfterUse::YES);
|
2016-08-02 19:43:15 +02:00
|
|
|
RivenScriptPtr script = _vm->_scriptMan->readScript(scriptStream);
|
2011-03-22 20:31:54 -04:00
|
|
|
|
|
|
|
uint32 delayTime = (argv[1] << 16) + argv[2];
|
|
|
|
|
|
|
|
if (delayTime > 0) {
|
|
|
|
// Store the script
|
|
|
|
RivenScriptManager::StoredMovieOpcode storedOp;
|
|
|
|
storedOp.script = script;
|
2011-06-14 10:35:58 -04:00
|
|
|
storedOp.time = delayTime;
|
2011-03-22 20:31:54 -04:00
|
|
|
storedOp.id = argv[0];
|
|
|
|
|
2011-06-14 10:35:58 -04:00
|
|
|
// Store the opcode for later
|
|
|
|
_vm->_scriptMan->setStoredMovieOpcode(storedOp);
|
2011-03-22 20:31:54 -04:00
|
|
|
} else {
|
|
|
|
// Run immediately if we have no delay
|
2016-08-02 21:43:22 +02:00
|
|
|
_vm->_scriptMan->runScript(script, false);
|
2011-03-22 20:31:54 -04:00
|
|
|
}
|
2016-08-02 18:56:55 +02:00
|
|
|
|
|
|
|
delete scriptStream;
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 39: activate PLST record (card picture lists)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::activatePLST(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-04 06:28:04 +02:00
|
|
|
_vm->_activatedPLST = true;
|
|
|
|
|
2016-08-07 11:26:43 +02:00
|
|
|
RivenCard::Picture picture = _vm->getCard()->getPicture(argv[0]);
|
2016-08-04 06:28:04 +02:00
|
|
|
_vm->_gfx->copyImageToScreen(picture.id, picture.rect.left, picture.rect.top, picture.rect.right, picture.rect.bottom);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 40: activate SLST record (card ambient sound lists)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::activateSLST(uint16 op, uint16 argc, uint16 *argv) {
|
2009-12-29 23:18:24 +00:00
|
|
|
_vm->_activatedSLST = true;
|
2017-02-04 14:32:59 +01:00
|
|
|
|
2016-08-07 11:26:43 +02:00
|
|
|
SLSTRecord slstRecord = _vm->getCard()->getSound(argv[0]);
|
2016-08-06 17:54:45 +02:00
|
|
|
_vm->_sound->playSLST(slstRecord);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 41: activate MLST record and play
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::activateMLSTAndPlay(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-13 17:59:47 +02:00
|
|
|
_vm->_video->activateMLST(_vm->getCard()->getMovie(argv[0]));
|
2011-01-18 20:30:16 +00:00
|
|
|
_vm->_video->playMovieRiven(argv[0]);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 43: activate BLST record (card hotspot enabling lists)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::activateBLST(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-07 11:26:43 +02:00
|
|
|
_vm->getCard()->activateHotspotEnableRecord(argv[0]);
|
2011-01-24 02:43:07 +00:00
|
|
|
|
|
|
|
// Recheck our current hotspot because it may have now changed
|
|
|
|
_vm->updateCurrentHotspot();
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 44: activate FLST record (information on which SFXE resource this card should use)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::activateFLST(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-07 11:26:43 +02:00
|
|
|
_vm->getCard()->activateWaterEffect(argv[0]);
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Command 45: do zip mode
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::zipMode(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-07 11:26:43 +02:00
|
|
|
assert(_vm->getCard() && _vm->getCard()->getCurHotspot());
|
2016-08-05 20:24:59 +02:00
|
|
|
|
2009-12-29 23:18:24 +00:00
|
|
|
// Check the ZIPS records to see if we have a match to the hotspot name
|
2016-08-07 11:26:43 +02:00
|
|
|
Common::String hotspotName = _vm->getCard()->getCurHotspot()->getName();
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-12-29 23:18:24 +00:00
|
|
|
for (uint16 i = 0; i < _vm->_zipModeData.size(); i++)
|
|
|
|
if (_vm->_zipModeData[i].name == hotspotName) {
|
|
|
|
_vm->changeToCard(_vm->_zipModeData[i].id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Command 46: activate MLST record (movie lists)
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
|
2016-08-13 17:59:47 +02:00
|
|
|
_vm->_video->activateMLST(_vm->getCard()->getMovie(argv[0]));
|
2009-12-29 23:18:24 +00:00
|
|
|
}
|
|
|
|
|
2017-01-28 14:55:24 +01:00
|
|
|
Common::String RivenSimpleCommand::describe() const {
|
|
|
|
Common::String desc;
|
2016-08-02 18:56:55 +02:00
|
|
|
|
2017-02-11 12:31:13 +01:00
|
|
|
if (_type == kRivenCommandSwitch) { // Use the variable name
|
2016-08-07 11:26:43 +02:00
|
|
|
Common::String varName = _vm->getStack()->getName(kVariableNames, _arguments[0]);
|
2017-01-28 14:55:24 +01:00
|
|
|
desc = Common::String::format("%s = %d", varName.c_str(), _arguments[1]);
|
2017-02-11 12:31:13 +01:00
|
|
|
} else if (_type == kRivenCommandRunExternal) { // Use the external command name
|
2016-08-07 11:26:43 +02:00
|
|
|
Common::String externalCommandName = _vm->getStack()->getName(kExternalCommandNames, _arguments[0]);
|
2017-01-28 14:55:24 +01:00
|
|
|
desc = Common::String::format("%s(", externalCommandName.c_str());
|
2016-08-02 18:56:55 +02:00
|
|
|
uint16 varCount = _arguments[1];
|
|
|
|
for (uint16 j = 0; j < varCount; j++) {
|
2017-01-28 14:55:24 +01:00
|
|
|
desc += Common::String::format("%d", _arguments[2 + j]);
|
2016-08-02 18:56:55 +02:00
|
|
|
if (j != varCount - 1)
|
2017-01-28 14:55:24 +01:00
|
|
|
desc += ", ";
|
2016-08-02 18:56:55 +02:00
|
|
|
}
|
2017-01-28 14:55:24 +01:00
|
|
|
desc += ")";
|
2017-02-11 12:31:13 +01:00
|
|
|
} else if (_type == kRivenCommandIncrementVariable) { // Use the variable name
|
2016-08-07 11:26:43 +02:00
|
|
|
Common::String varName = _vm->getStack()->getName(kVariableNames, _arguments[0]);
|
2017-01-28 14:55:24 +01:00
|
|
|
desc = Common::String::format("%s += %d", varName.c_str(), _arguments[1]);
|
2016-08-02 18:56:55 +02:00
|
|
|
} else {
|
2017-01-28 14:55:24 +01:00
|
|
|
desc = Common::String::format("%s(", _opcodes[_type].desc);
|
2016-08-02 18:56:55 +02:00
|
|
|
for (uint16 j = 0; j < _arguments.size(); j++) {
|
2017-01-28 14:55:24 +01:00
|
|
|
desc += Common::String::format("%d", _arguments[j]);
|
2016-08-02 18:56:55 +02:00
|
|
|
if (j != _arguments.size() - 1)
|
2017-01-28 14:55:24 +01:00
|
|
|
desc += ", ";
|
2016-08-02 18:56:55 +02:00
|
|
|
}
|
2017-01-28 14:55:24 +01:00
|
|
|
desc += ")";
|
2016-08-02 18:56:55 +02:00
|
|
|
}
|
2017-01-28 14:55:24 +01:00
|
|
|
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RivenSimpleCommand::dump(byte tabs) {
|
|
|
|
printTabs(tabs);
|
|
|
|
debugN("%s;\n", describe().c_str());
|
2010-07-09 16:53:20 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSimpleCommand::execute() {
|
2017-01-28 14:55:24 +01:00
|
|
|
if (DebugMan.isDebugChannelEnabled(kRivenDebugScript)) {
|
|
|
|
debugC(kRivenDebugScript, "Running opcode: %s", describe().c_str());
|
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
uint16 *argValues = new uint16[_arguments.size()];
|
2011-03-22 20:31:54 -04:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
for (uint16 k = 0; k < _arguments.size(); k++)
|
|
|
|
argValues[k] = _arguments[k];
|
|
|
|
|
|
|
|
(this->*(_opcodes[_type].proc)) (_type, _arguments.size(), argValues);
|
|
|
|
|
|
|
|
delete[] argValues;
|
2010-07-09 16:53:20 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
RivenSwitchCommand::RivenSwitchCommand(MohawkEngine_Riven *vm) :
|
|
|
|
RivenCommand(vm),
|
|
|
|
_variableId(0) {
|
2010-07-09 16:53:20 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
}
|
2010-07-09 16:53:20 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
RivenSwitchCommand::~RivenSwitchCommand() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-02-11 12:31:13 +01:00
|
|
|
RivenSwitchCommand *RivenSwitchCommand::createFromStream(MohawkEngine_Riven *vm, Common::ReadStream *stream) {
|
2016-08-02 18:56:55 +02:00
|
|
|
RivenSwitchCommand *command = new RivenSwitchCommand(vm);
|
2010-07-09 16:53:20 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
if (stream->readUint16BE() != 2) {
|
|
|
|
// This value is not used in the original engine
|
|
|
|
warning("if-then-else unknown value is not 2");
|
2010-07-09 16:53:20 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
// variable to check against
|
|
|
|
command->_variableId = stream->readUint16BE();
|
2010-07-09 16:53:20 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
// number of logic blocks
|
|
|
|
uint16 logicBlockCount = stream->readUint16BE();
|
|
|
|
command->_branches.resize(logicBlockCount);
|
2010-09-01 13:28:12 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
for (uint16 i = 0; i < logicBlockCount; i++) {
|
|
|
|
Branch &branch = command->_branches[i];
|
|
|
|
|
|
|
|
// Value for this logic block
|
|
|
|
branch.value = stream->readUint16BE();
|
2016-08-02 19:43:15 +02:00
|
|
|
branch.script = vm->_scriptMan->readScript(stream);
|
2010-07-09 16:53:20 +00:00
|
|
|
}
|
2009-12-29 23:18:24 +00:00
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
return command;
|
2011-03-22 20:31:54 -04:00
|
|
|
}
|
|
|
|
|
2016-08-06 14:36:41 +02:00
|
|
|
void RivenSwitchCommand::dump(byte tabs) {
|
2016-08-07 11:26:43 +02:00
|
|
|
Common::String varName = _vm->getStack()->getName(kVariableNames, _variableId);
|
2016-08-06 14:36:41 +02:00
|
|
|
printTabs(tabs); debugN("switch (%s) {\n", varName.c_str());
|
2016-08-02 18:56:55 +02:00
|
|
|
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);
|
2016-08-06 14:36:41 +02:00
|
|
|
_branches[j].script->dumpScript(tabs + 2);
|
2016-08-02 18:56:55 +02:00
|
|
|
printTabs(tabs + 2); debugN("break;\n");
|
2011-03-22 20:31:54 -04:00
|
|
|
}
|
2016-08-02 18:56:55 +02:00
|
|
|
printTabs(tabs); debugN("}\n");
|
2011-03-22 20:31:54 -04:00
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
void RivenSwitchCommand::execute() {
|
2017-01-28 14:55:24 +01:00
|
|
|
if (DebugMan.isDebugChannelEnabled(kRivenDebugScript)) {
|
|
|
|
Common::String varName = _vm->getStack()->getName(kVariableNames, _variableId);
|
|
|
|
debugC(kRivenDebugScript, "Running opcode: switch(%s)", varName.c_str());
|
|
|
|
}
|
|
|
|
|
2016-08-02 18:56:55 +02:00
|
|
|
// 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) {
|
2016-08-02 21:43:22 +02:00
|
|
|
_vm->_scriptMan->runScript(_branches[i].script, false);
|
2016-08-02 18:56:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for the default case if any
|
|
|
|
for (uint i = 0; i < _branches.size(); i++) {
|
|
|
|
if (_branches[i].value == 0Xffff) {
|
2016-08-02 21:43:22 +02:00
|
|
|
_vm->_scriptMan->runScript(_branches[i].script, false);
|
2016-08-02 18:56:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2011-03-22 20:31:54 -04:00
|
|
|
}
|
|
|
|
|
2016-11-05 08:35:03 +01:00
|
|
|
RivenStackChangeCommand::RivenStackChangeCommand(MohawkEngine_Riven *vm, uint16 stackId, uint32 globalCardId, bool byStackId) :
|
|
|
|
RivenCommand(vm),
|
|
|
|
_stackId(stackId),
|
|
|
|
_cardId(globalCardId),
|
|
|
|
_byStackId(byStackId) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
RivenStackChangeCommand::~RivenStackChangeCommand() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-02-11 12:31:13 +01:00
|
|
|
RivenStackChangeCommand *RivenStackChangeCommand::createFromStream(MohawkEngine_Riven *vm, Common::ReadStream *stream) {
|
2016-11-05 08:35:03 +01:00
|
|
|
/* argumentsSize = */ stream->readUint16BE();
|
|
|
|
uint16 stackId = stream->readUint16BE();
|
|
|
|
uint32 globalCardId = stream->readUint32BE();
|
|
|
|
|
|
|
|
return new RivenStackChangeCommand(vm, stackId, globalCardId, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RivenStackChangeCommand::execute() {
|
2017-01-28 14:55:24 +01:00
|
|
|
debugC(kRivenDebugScript, "Running opcode: changeStack(%d, %d)", _stackId, _cardId);
|
|
|
|
|
2016-11-05 12:39:51 +01:00
|
|
|
uint16 stackID;
|
2016-11-05 08:35:03 +01:00
|
|
|
if (_byStackId) {
|
|
|
|
stackID = _stackId;
|
|
|
|
} else {
|
|
|
|
Common::String stackName = _vm->getStack()->getName(kStackNames, _stackId);
|
|
|
|
|
2016-11-05 12:39:51 +01:00
|
|
|
stackID = RivenStacks::getId(stackName.c_str());
|
|
|
|
if (stackID == kStackUnknown) {
|
2016-11-05 08:35:03 +01:00
|
|
|
error ("'%s' is not a stack name!", stackName.c_str());
|
2016-11-05 12:39:51 +01:00
|
|
|
}
|
2016-11-05 08:35:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
_vm->changeToStack(stackID);
|
|
|
|
uint16 cardID = _vm->getStack()->getCardStackId(_cardId);
|
|
|
|
_vm->changeToCard(cardID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RivenStackChangeCommand::dump(byte tabs) {
|
|
|
|
printTabs(tabs);
|
|
|
|
debugN("changeStack(%d, %d);\n", _stackId, _cardId);
|
|
|
|
}
|
|
|
|
|
2009-12-29 23:18:24 +00:00
|
|
|
} // End of namespace Mohawk
|