diff options
-rw-r--r-- | engines/mohawk/console.cpp | 12 | ||||
-rw-r--r-- | engines/mohawk/riven.cpp | 18 | ||||
-rw-r--r-- | engines/mohawk/riven.h | 1 | ||||
-rw-r--r-- | engines/mohawk/riven_scripts.cpp | 66 | ||||
-rw-r--r-- | engines/mohawk/riven_scripts.h | 33 |
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 |