[Scummvm-cvs-logs] SF.net SVN: scummvm:[39438] scummvm/trunk/engines/scumm

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Mon Mar 16 05:45:13 CET 2009


Revision: 39438
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39438&view=rev
Author:   fingolfin
Date:     2009-03-16 04:45:12 +0000 (Mon, 16 Mar 2009)

Log Message:
-----------
SCUMM: Modified version of patch #1687041 (Scumm: Load-/Save-support for the original save-dialog)

Modified Paths:
--------------
    scummvm/trunk/engines/scumm/input.cpp
    scummvm/trunk/engines/scumm/intern.h
    scummvm/trunk/engines/scumm/saveload.cpp
    scummvm/trunk/engines/scumm/script_v5.cpp
    scummvm/trunk/engines/scumm/scumm.cpp
    scummvm/trunk/engines/scumm/scumm.h

Modified: scummvm/trunk/engines/scumm/input.cpp
===================================================================
--- scummvm/trunk/engines/scumm/input.cpp	2009-03-16 04:15:03 UTC (rev 39437)
+++ scummvm/trunk/engines/scumm/input.cpp	2009-03-16 04:45:12 UTC (rev 39438)
@@ -410,6 +410,11 @@
 	// Fall back to default behavior
 	ScummEngine::processKeyboard(lastKeyHit);
 
+	// On Alt-F5 prepare savegame for the original save/load dialog.
+	if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == Common::KBD_ALT) {
+		prepareSavegame();
+	}
+
 	if (VAR_KEYPRESS != 0xFF && _mouseAndKeyboardStat) {		// Key Input
 		if (315 <= _mouseAndKeyboardStat && _mouseAndKeyboardStat <= 323) {
 			// Convert F-Keys for V1/V2 games (they start at 1)
@@ -424,8 +429,13 @@
 	// Fall back to default behavior
 	ScummEngine::processKeyboard(lastKeyHit);
 
-	// 'i' brings up an IQ dialog in Indy3
-	if (lastKeyHit.ascii == 'i' && _game.id == GID_INDY3) {
+	// On Alt-F5 prepare savegame for the original save/load dialog.
+	if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == Common::KBD_ALT) {
+		prepareSavegame();
+	}
+
+	// 'i' brings up an IQ dialog in Indy3 (disabled in save/load dialog for input)
+	if (lastKeyHit.ascii == 'i' && _game.id == GID_INDY3 && _currentRoom != 14) {
 		// SCUMM var 244 is the episode score
 		// and var 245 is the series score
 		char text[50];
@@ -496,7 +506,7 @@
 			messageDialog("Snap scroll on");
 		} else {
 			messageDialog("Snap scroll off");
-		}	
+		}
 
 		if (VAR_CAMERA_FAST_X != 0xFF)
 			VAR(VAR_CAMERA_FAST_X) = _snapScroll;

Modified: scummvm/trunk/engines/scumm/intern.h
===================================================================
--- scummvm/trunk/engines/scumm/intern.h	2009-03-16 04:15:03 UTC (rev 39437)
+++ scummvm/trunk/engines/scumm/intern.h	2009-03-16 04:45:12 UTC (rev 39438)
@@ -238,8 +238,26 @@
  */
 class ScummEngine_v3 : public ScummEngine_v4 {
 public:
+
+	/**
+	 * Prepared savegame used by the orginal save/load dialog.
+	 * Must be valid as long as the savescreen is active. As we are not
+	 * notified when the savescreen is closed, memory is only freed on a game
+	 * reset, at the destruction of the engine or when the original save/load
+	 * dialog is entered the next time.
+	 */
+	Common::SeekableReadStream *_savePreparedSavegame;
+
+	void prepareSavegame();
+	bool savePreparedSavegame(int slot, char *desc);
+
+
+public:
 	ScummEngine_v3(OSystem *syst, const DetectorResult &dr);
+	~ScummEngine_v3();
 
+	virtual void resetScumm();
+
 protected:
 	virtual void readRoomsOffsets();
 	virtual void loadCharset(int no);

Modified: scummvm/trunk/engines/scumm/saveload.cpp
===================================================================
--- scummvm/trunk/engines/scumm/saveload.cpp	2009-03-16 04:15:03 UTC (rev 39437)
+++ scummvm/trunk/engines/scumm/saveload.cpp	2009-03-16 04:45:12 UTC (rev 39438)
@@ -28,6 +28,7 @@
 #include "common/config-manager.h"
 #include "common/savefile.h"
 #include "common/system.h"
+#include "common/zlib.h"
 
 #include "scumm/actor.h"
 #include "scumm/charset.h"
@@ -129,10 +130,27 @@
 	return true;
 }
 
+bool ScummEngine::saveState(Common::OutSaveFile *out, bool writeHeader) {
+	SaveGameHeader hdr;
+
+	if (writeHeader) {
+		memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
+		saveSaveGameHeader(out, hdr);
+	}
+#if !defined(__DS__)
+	Graphics::saveThumbnail(*out);
+#endif
+	saveInfos(out);
+
+	Serializer ser(0, out, CURRENT_VER);
+	saveOrLoad(&ser);
+	return true;
+}
+
 bool ScummEngine::saveState(int slot, bool compat) {
+	bool saveFailed;
 	Common::String filename;
 	Common::OutSaveFile *out;
-	SaveGameHeader hdr;
 
 	if (_saveLoadSlot == 255) {
 		// Allow custom filenames for save game system in HE Games
@@ -143,26 +161,108 @@
 	if (!(out = _saveFileMan->openForSaving(filename.c_str())))
 		return false;
 
-	memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
-	saveSaveGameHeader(out, hdr);
-#if !defined(__DS__)
-	Graphics::saveThumbnail(*out);
-#endif
-	saveInfos(out);
+	saveFailed = false;
+	if (!saveState(out))
+		saveFailed = true;
 
-	Serializer ser(0, out, CURRENT_VER);
-	saveOrLoad(&ser);
 	out->finalize();
-	if (out->err()) {
-		delete out;
+	if (out->err())
+		saveFailed = true;
+	delete out;
+
+	if (saveFailed) {
 		debug(1, "State save as '%s' FAILED", filename.c_str());
 		return false;
 	}
-	delete out;
 	debug(1, "State saved as '%s'", filename.c_str());
 	return true;
 }
 
+
+void ScummEngine_v3::prepareSavegame() {
+	Common::MemoryWriteStreamDynamic *memStream;
+	Common::WriteStream *writeStream;
+
+	// free memory of the last prepared savegame
+	delete _savePreparedSavegame;
+	_savePreparedSavegame = NULL;
+
+	// store headerless savegame in a compressed memory stream
+	memStream = new Common::MemoryWriteStreamDynamic();
+	writeStream = Common::wrapCompressedWriteStream(memStream);
+	if (saveState(writeStream, false)) {
+		// we have to finalize the compression-stream first, otherwise the internal
+		// memory-stream pointer will be zero (Important: flush() does not work here!).
+		writeStream->finalize();
+		if (!writeStream->err()) {
+			// wrap uncompressing MemoryReadStream around the savegame data
+			_savePreparedSavegame = Common::wrapCompressedReadStream(
+				new Common::MemoryReadStream(memStream->getData(), memStream->size(), true));
+		}
+	}
+	// free the CompressedWriteStream and MemoryWriteStreamDynamic
+	// but not the memory stream's internal buffer
+	delete writeStream;
+}
+
+bool ScummEngine_v3::savePreparedSavegame(int slot, char *desc) {
+	bool success;
+	Common::String filename;
+	Common::OutSaveFile *out;
+	SaveGameHeader hdr;
+	uint32 nread, nwritten;
+
+	out = 0;
+	success = true;
+
+	// check if savegame was successfully stored in memory
+	if (!_savePreparedSavegame)
+		success = false;
+
+	// open savegame file
+	if (success) {
+		filename = makeSavegameName(slot, false);
+		if (!(out = _saveFileMan->openForSaving(filename.c_str()))) {
+			success = false;
+		}
+	}
+
+	// write header to file
+	if (success) {
+		memset(hdr.name, 0, sizeof(hdr.name));
+		strncpy(hdr.name, desc, sizeof(hdr.name)-1);
+		success = saveSaveGameHeader(out, hdr);
+	}
+
+	// copy savegame from memory-stream to file
+	if (success) {
+		_savePreparedSavegame->seek(0, SEEK_SET);
+		byte buffer[1024];
+		while ((nread = _savePreparedSavegame->read(buffer, sizeof(buffer)))) {
+			nwritten = out->write(buffer, nread);
+			if (nwritten < nread) {
+				success = false;
+				break;
+			}
+		}
+	}
+
+	if (out) {
+		out->finalize();
+		if (out->err())
+			success = false;
+		delete out;
+	}
+
+	if (!success) {
+		debug(1, "State save as '%s' FAILED", filename.c_str());
+		return false;
+	} else {
+		debug(1, "State saved as '%s'", filename.c_str());
+		return true;
+	}
+}
+
 static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &hdr) {
 	hdr.type = in->readUint32BE();
 	hdr.size = in->readUint32LE();

Modified: scummvm/trunk/engines/scumm/script_v5.cpp
===================================================================
--- scummvm/trunk/engines/scumm/script_v5.cpp	2009-03-16 04:15:03 UTC (rev 39437)
+++ scummvm/trunk/engines/scumm/script_v5.cpp	2009-03-16 04:45:12 UTC (rev 39438)
@@ -869,7 +869,12 @@
 	// which matches the original Indy3 save/load code. See also the notes
 	// on Feature Request #1666521.
 	STRINGID_IQ_EPISODE = 7,
-	STRINGID_IQ_SERIES = 9
+	STRINGID_IQ_SERIES = 9,
+	// The string IDs of the first savegame name, used as an offset to determine
+	// the IDs of all savenames.
+	// Loom is the only game whose savenames start with a different ID.
+	STRINGID_SAVENAME1 = 10,
+	STRINGID_SAVENAME1_LOOM = 9
 };
 
 void ScummEngine_v5::o5_saveLoadVars() {
@@ -1235,26 +1240,43 @@
 		result = 100;
 		break;
 	case 0x20: // drive
-		if (_game.id == GID_INDY3) {
-			// 0 = hard drive
-			// 1 = disk drive
-			result = 0;
+		if (_game.version <= 3) {
+			// 0 = ???
+			// [1,2] = disk drive [A:,B:]
+			// 3 = hard drive
+			result = 3;
 		} else {
 			// set current drive
 			result = 1;
 		}
 		break;
 	case 0x40: // load
-		if (loadState(slot, _saveTemporaryState))
+		if (loadState(slot, false))
 			result = 3; // sucess
 		else
 			result = 5; // failed to load
 		break;
 	case 0x80: // save
-		//if (saveState(slot, _saveTemporaryState))
-		//	result = 0; // sucess
-		//else
+		if (_game.version <= 3) {
+			char name[32];
+			if (_game.version <= 2) {
+				// use generic name
+				sprintf(name, "Game %c", 'A'+slot-1);
+			} else {
+				// use name entered by the user
+				char* ptr;
+				int firstSlot = (_game.id == GID_LOOM) ? STRINGID_SAVENAME1_LOOM : STRINGID_SAVENAME1;
+				ptr = (char*)getStringAddress(slot + firstSlot - 1);
+				strncpy(name, ptr, sizeof(name));
+			}
+
+			if (((ScummEngine_v3 *)this)->savePreparedSavegame(slot, name))
+				result = 0;
+			else
+				result = 2;
+		} else {
 			result = 2; // failed to save
+		}
 		break;
 	case 0xC0: // test if save exists
 		{

Modified: scummvm/trunk/engines/scumm/scumm.cpp
===================================================================
--- scummvm/trunk/engines/scumm/scumm.cpp	2009-03-16 04:15:03 UTC (rev 39437)
+++ scummvm/trunk/engines/scumm/scumm.cpp	2009-03-16 04:45:12 UTC (rev 39438)
@@ -631,8 +631,14 @@
 	// All v3 and older games only used 16 colors with exception of the GF_OLD256 games.
 	if (!(_game.features & GF_OLD256))
 		_game.features |= GF_16COLOR;
+
+	_savePreparedSavegame = NULL;
 }
 
+ScummEngine_v3::~ScummEngine_v3() {
+	delete _savePreparedSavegame;
+}
+
 ScummEngine_v3old::ScummEngine_v3old(OSystem *syst, const DetectorResult &dr)
 	: ScummEngine_v3(syst, dr) {
 	_resourceHeaderSize = 4;
@@ -1426,7 +1432,7 @@
 }
 
 void ScummEngine_v2::resetScumm() {
-	ScummEngine::resetScumm();
+	ScummEngine_v3::resetScumm();
 
 	if (_game.platform == Common::kPlatformNES) {
 		initNESMouseOver();
@@ -1442,6 +1448,13 @@
 	_inventoryOffset = 0;
 }
 
+void ScummEngine_v3::resetScumm() {
+	ScummEngine_v4::resetScumm();
+
+	delete _savePreparedSavegame;
+	_savePreparedSavegame = NULL;
+}
+
 void ScummEngine_v4::resetScumm() {
 	ScummEngine::resetScumm();
 

Modified: scummvm/trunk/engines/scumm/scumm.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm.h	2009-03-16 04:15:03 UTC (rev 39437)
+++ scummvm/trunk/engines/scumm/scumm.h	2009-03-16 04:45:12 UTC (rev 39438)
@@ -29,6 +29,7 @@
 #include "engines/engine.h"
 #include "common/endian.h"
 #include "common/file.h"
+#include "common/savefile.h"
 #include "common/keyboard.h"
 #include "common/rect.h"
 #include "common/str.h"
@@ -628,6 +629,7 @@
 	char _saveLoadFileName[32];
 	char _saveLoadName[32];
 
+	bool saveState(Common::OutSaveFile *out, bool writeHeader = true);
 	bool saveState(int slot, bool compat);
 	bool loadState(int slot, bool compat);
 	virtual void saveOrLoad(Serializer *s);


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