aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/mohawk/console.cpp12
-rw-r--r--engines/mohawk/riven.cpp18
-rw-r--r--engines/mohawk/riven.h1
-rw-r--r--engines/mohawk/riven_scripts.cpp66
-rw-r--r--engines/mohawk/riven_scripts.h33
5 files changed, 92 insertions, 38 deletions
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index abdcf42dc0..5dcfff4f90 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -558,9 +558,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
printf ("==================================\n\n");
Common::SeekableReadStream *cardStream = _vm->getRawData(MKID_BE('CARD'), (uint16)atoi(argv[3]));
cardStream->seek(4);
- RivenScriptList scriptList = RivenScript::readScripts(_vm, cardStream);
- for (uint32 i = 0; i < scriptList.size(); i++)
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false);
+ 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")) {
printf ("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3]));
@@ -573,9 +575,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
for (uint16 i = 0; i < hotspotCount; i++) {
printf ("Hotspot %d:\n", i);
hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff
- RivenScriptList scriptList = RivenScript::readScripts(_vm, hsptStream);
- for (uint32 j = 0; j < scriptList.size(); j++)
+ RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false);
+ for (uint32 j = 0; j < scriptList.size(); j++) {
scriptList[j]->dumpScript(varNames, xNames, 1);
+ delete scriptList[j];
+ }
}
delete hsptStream;
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 81e33d6513..07b08dc220 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -53,6 +53,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_ignoreNextMouseUp = false;
_extrasFile = NULL;
_curStack = aspit;
+ _hotspots = NULL;
// NOTE: We can never really support CD swapping. All of the music files
// (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
@@ -80,16 +81,17 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete _externalScriptHandler;
delete _extrasFile;
delete _saveLoad;
+ delete _scriptMan;
delete[] _vars;
delete _optionsDialog;
delete _rnd;
+ delete[] _hotspots;
delete g_atrusJournalRect1;
delete g_atrusJournalRect2;
delete g_cathJournalRect2;
delete g_atrusJournalRect3;
delete g_cathJournalRect3;
delete g_trapBookRect3;
- _cardData.scripts.clear();
}
GUI::Debugger *MohawkEngine_Riven::getDebugger() {
@@ -105,6 +107,7 @@ Common::Error MohawkEngine_Riven::run() {
_saveLoad = new RivenSaveLoad(this, _saveFileMan);
_externalScriptHandler = new RivenExternal(this);
_optionsDialog = new RivenOptionsDialog(this);
+ _scriptMan = new RivenScriptManager(this);
_rnd = new Common::RandomSource();
g_eventRec.registerRandomSource(*_rnd, "riven");
@@ -347,13 +350,13 @@ void MohawkEngine_Riven::refreshCard() {
}
void MohawkEngine_Riven::loadCard(uint16 id) {
- // NOTE: Do not clear the card scripts because it may delete a currently running script!
+ // NOTE: The card scripts are cleared by the RivenScriptManager automatically.
Common::SeekableReadStream* inStream = getRawData(ID_CARD, id);
_cardData.name = inStream->readSint16BE();
_cardData.zipModePlace = inStream->readUint16BE();
- _cardData.scripts = RivenScript::readScripts(this, inStream);
+ _cardData.scripts = _scriptMan->readScripts(inStream);
_cardData.hasData = true;
delete inStream;
@@ -371,7 +374,10 @@ void MohawkEngine_Riven::loadCard(uint16 id) {
}
void MohawkEngine_Riven::loadHotspots(uint16 id) {
- // NOTE: Do not clear the hotspots because it may delete a currently running script!
+ // Clear old hotspots
+ delete[] _hotspots;
+
+ // NOTE: The hotspot scripts are cleared by the RivenScriptManager automatically.
Common::SeekableReadStream* inStream = getRawData(ID_HSPT, id);
@@ -413,7 +419,7 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) {
_hotspots[i].zipModeHotspot = inStream->readUint16BE();
// Read in the scripts now
- _hotspots[i].scripts = RivenScript::readScripts(this, inStream);
+ _hotspots[i].scripts = _scriptMan->readScripts(inStream);
}
delete inStream;
@@ -649,4 +655,4 @@ bool ZipMode::operator== (const ZipMode &z) const {
return z.name == name && z.id == id;
}
-}
+} // End of namespace Mohawk
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 3e2ab59597..631285455e 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -113,6 +113,7 @@ public:
RivenGraphics *_gfx;
RivenExternal *_externalScriptHandler;
Common::RandomSource *_rnd;
+ RivenScriptManager *_scriptMan;
Card _cardData;
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index a23fd26b96..1fcaba8ac0 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -35,28 +35,16 @@
namespace Mohawk {
-RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType)
- : _vm(vm), _stream(stream), _scriptType(scriptType) {
+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;
}
RivenScript::~RivenScript() {
delete _stream;
}
-RivenScriptList RivenScript::readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream) {
- RivenScriptList scriptList;
-
- uint16 scriptCount = stream->readUint16BE();
- for (uint16 i = 0; i < scriptCount; i++) {
- uint16 scriptType = stream->readUint16BE();
- uint32 scriptSize = calculateScriptSize(stream);
- scriptList.push_back(Common::SharedPtr<RivenScript>(new RivenScript(vm, stream->readStream(scriptSize), scriptType)));
- }
-
- return scriptList;
-}
-
uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) {
uint16 command = script->readUint16BE();
uint32 commandSize = 2;
@@ -161,7 +149,7 @@ void RivenScript::setupOpcodes() {
OPCODE(activateFLST),
OPCODE(zipMode),
OPCODE(activateMLST),
- OPCODE(activateSLSTWithVolume)
+ OPCODE(empty) // Activate an SLST with a volume parameter (not used)
};
_opcodes = riven_opcodes;
@@ -239,10 +227,13 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray
}
void RivenScript::runScript() {
+ _isRunning = true;
+
if (_stream->pos() != 0)
_stream->seek(0);
processCommands(true);
+ _isRunning = false;
}
void RivenScript::processCommands(bool runCommands) {
@@ -610,9 +601,46 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) {
_vm->_video->activateMLST(argv[0], _vm->getCurCard());
}
-// Command 47: activate SLST record with a volume argument
-void RivenScript::activateSLSTWithVolume(uint16 op, uint16 argc, uint16 *argv) {
- warning("STUB: activateSLSTWithVolume()");
+RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) {
+ _vm = vm;
+}
+
+RivenScriptManager::~RivenScriptManager() {
+ for (uint32 i = 0; i < _currentScripts.size(); i++)
+ delete _currentScripts[i];
+}
+
+RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) {
+ if (garbageCollect)
+ unloadUnusedScripts(); // Garbage collect!
+
+ 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);
+
+ // 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);
+ }
+
+ return scriptList;
+}
+
+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--;
+ }
+ }
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index a1512af697..5187bbde08 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -50,19 +50,20 @@ enum {
};
class RivenScript;
-typedef Common::Array<Common::SharedPtr<RivenScript> > RivenScriptList;
class RivenScript {
public:
- RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType);
+ RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard);
~RivenScript();
void runScript();
void dumpScript(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
uint16 getScriptType() { return _scriptType; }
+ uint16 getParentStack() { return _parentStack; }
+ uint16 getParentCard() { return _parentCard; }
+ bool isRunning() { return _isRunning; }
- // Read in an array of script objects from a stream
- static RivenScriptList readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream);
+ static uint32 calculateScriptSize(Common::SeekableReadStream *script);
private:
typedef void (RivenScript::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv);
@@ -70,18 +71,18 @@ private:
OpcodeProcRiven proc;
const char *desc;
};
- const RivenOpcode* _opcodes;
+ const RivenOpcode *_opcodes;
void setupOpcodes();
MohawkEngine_Riven *_vm;
Common::SeekableReadStream *_stream;
- uint16 _scriptType;
+ uint16 _scriptType, _parentStack, _parentCard, _parentHotspot;
+ bool _isRunning;
void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs);
void processCommands(bool runCommands);
- static uint32 calculateCommandSize(Common::SeekableReadStream* script);
- static uint32 calculateScriptSize(Common::SeekableReadStream* script);
+ static uint32 calculateCommandSize(Common::SeekableReadStream *script);
DECLARE_OPCODE(empty) { warning ("Unknown Opcode %04x", op); }
@@ -120,7 +121,21 @@ private:
DECLARE_OPCODE(activateFLST);
DECLARE_OPCODE(zipMode);
DECLARE_OPCODE(activateMLST);
- DECLARE_OPCODE(activateSLSTWithVolume);
+};
+
+typedef Common::Array<RivenScript*> RivenScriptList;
+
+class RivenScriptManager {
+public:
+ RivenScriptManager(MohawkEngine_Riven *vm);
+ ~RivenScriptManager();
+
+ RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true);
+
+private:
+ void unloadUnusedScripts();
+ RivenScriptList _currentScripts;
+ MohawkEngine_Riven *_vm;
};
} // End of namespace Mohawk