[Scummvm-cvs-logs] SF.net SVN: scummvm:[50761] scummvm/trunk/engines/mohawk

mthreepwood at users.sourceforge.net mthreepwood at users.sourceforge.net
Fri Jul 9 18:53:21 CEST 2010


Revision: 50761
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50761&view=rev
Author:   mthreepwood
Date:     2010-07-09 16:53:20 +0000 (Fri, 09 Jul 2010)

Log Message:
-----------
Introduce the RivenScriptManager to keep track of scripts and free them when required. The old way of using SharedPtr was quite hacky and didn't work properly when talking to Gehn in ospit.

Modified Paths:
--------------
    scummvm/trunk/engines/mohawk/console.cpp
    scummvm/trunk/engines/mohawk/riven.cpp
    scummvm/trunk/engines/mohawk/riven.h
    scummvm/trunk/engines/mohawk/riven_scripts.cpp
    scummvm/trunk/engines/mohawk/riven_scripts.h

Modified: scummvm/trunk/engines/mohawk/console.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/console.cpp	2010-07-09 16:05:47 UTC (rev 50760)
+++ scummvm/trunk/engines/mohawk/console.cpp	2010-07-09 16:53:20 UTC (rev 50761)
@@ -558,9 +558,11 @@
 		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 @@
 		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;

Modified: scummvm/trunk/engines/mohawk/riven.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven.cpp	2010-07-09 16:05:47 UTC (rev 50760)
+++ scummvm/trunk/engines/mohawk/riven.cpp	2010-07-09 16:53:20 UTC (rev 50761)
@@ -53,6 +53,7 @@
 	_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 @@
 	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 @@
 	_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::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::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 @@
 		_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 @@
 	return z.name == name && z.id == id;
 }
 
-}
+} // End of namespace Mohawk

Modified: scummvm/trunk/engines/mohawk/riven.h
===================================================================
--- scummvm/trunk/engines/mohawk/riven.h	2010-07-09 16:05:47 UTC (rev 50760)
+++ scummvm/trunk/engines/mohawk/riven.h	2010-07-09 16:53:20 UTC (rev 50761)
@@ -113,6 +113,7 @@
 	RivenGraphics *_gfx;
 	RivenExternal *_externalScriptHandler;
 	Common::RandomSource *_rnd;
+	RivenScriptManager *_scriptMan;
 
 	Card _cardData;
 

Modified: scummvm/trunk/engines/mohawk/riven_scripts.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven_scripts.cpp	2010-07-09 16:05:47 UTC (rev 50760)
+++ scummvm/trunk/engines/mohawk/riven_scripts.cpp	2010-07-09 16:53:20 UTC (rev 50761)
@@ -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 @@
 		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::runScript() {
+	_isRunning = true;
+
 	if (_stream->pos() != 0)
 		_stream->seek(0);
 
 	processCommands(true);
+	_isRunning = false;
 }
 
 void RivenScript::processCommands(bool runCommands) {
@@ -610,9 +601,46 @@
 	_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

Modified: scummvm/trunk/engines/mohawk/riven_scripts.h
===================================================================
--- scummvm/trunk/engines/mohawk/riven_scripts.h	2010-07-09 16:05:47 UTC (rev 50760)
+++ scummvm/trunk/engines/mohawk/riven_scripts.h	2010-07-09 16:53:20 UTC (rev 50761)
@@ -50,19 +50,20 @@
 };
 
 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 @@
 		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,9 +121,23 @@
 	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
 
 #undef DECLARE_OPCODE


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list