[Scummvm-cvs-logs] SF.net SVN: scummvm: [30786] scummvm/trunk

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Mon Feb 4 11:15:21 CET 2008


Revision: 30786
          http://scummvm.svn.sourceforge.net/scummvm/?rev=30786&view=rev
Author:   fingolfin
Date:     2008-02-04 02:15:21 -0800 (Mon, 04 Feb 2008)

Log Message:
-----------
Commited updated version of my own patch #1868402: Basic savestate plugin API

Modified Paths:
--------------
    scummvm/trunk/backends/plugins/dynamic-plugin.h
    scummvm/trunk/base/commandLine.cpp
    scummvm/trunk/base/game.cpp
    scummvm/trunk/base/game.h
    scummvm/trunk/base/plugins.cpp
    scummvm/trunk/base/plugins.h
    scummvm/trunk/engines/metaengine.h
    scummvm/trunk/engines/scumm/detection.cpp
    scummvm/trunk/engines/scumm/dialogs.cpp
    scummvm/trunk/engines/scumm/saveload.cpp
    scummvm/trunk/engines/scumm/script_v5.cpp
    scummvm/trunk/engines/scumm/script_v8.cpp
    scummvm/trunk/engines/scumm/scumm.h

Modified: scummvm/trunk/backends/plugins/dynamic-plugin.h
===================================================================
--- scummvm/trunk/backends/plugins/dynamic-plugin.h	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/backends/plugins/dynamic-plugin.h	2008-02-04 10:15:21 UTC (rev 30786)
@@ -67,6 +67,10 @@
 		return _metaengine->detectGames(fslist);
 	}
 
+	SaveStateList listSaves(const char *target) const {
+		return _metaengine->listSaves(target);
+	}
+
 	virtual bool loadPlugin() {
 		// Query the plugin's name
 		MetaAllocFunc metaAlloc = (MetaAllocFunc)findSymbol("PLUGIN_MetaEngine_alloc");

Modified: scummvm/trunk/base/commandLine.cpp
===================================================================
--- scummvm/trunk/base/commandLine.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/base/commandLine.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -350,6 +350,12 @@
 			DO_LONG_COMMAND("test-detector")
 			END_OPTION
 
+			DO_LONG_OPTION("list-saves")
+				// FIXME: Need to document this.
+				// TODO: Make the argument optional. If no argument is given, list all savegames
+				// for all configured targets.
+				return "list-saves";
+			END_OPTION
 
 			DO_OPTION('c', "config")
 			END_OPTION
@@ -571,7 +577,7 @@
 
 	using namespace Common;
 	const ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
-	ConfigManager::DomainMap::const_iterator iter = domains.begin();
+	ConfigManager::DomainMap::const_iterator iter;
 	for (iter = domains.begin(); iter != domains.end(); ++iter) {
 		Common::String name(iter->_key);
 		Common::String description(iter->_value.get("description"));
@@ -587,9 +593,50 @@
 		}
 
 		printf("%-20s %s\n", name.c_str(), description.c_str());
+
 	}
 }
 
+/** List all saves states for the given target. */
+static void listSaves(const char *target) {
+	// FIXME HACK
+	g_system->initBackend();
+
+	// Grab the "target" domain, if any
+	const Common::ConfigManager::Domain *domain = ConfMan.getDomain(target);
+
+	// Grab the gameid from the domain resp. use the target as gameid
+	Common::String gameid;
+	if (domain)
+		gameid = domain->get("gameid");
+	if (gameid.empty())
+		gameid = target;
+	gameid.toLowercase();	// Normalize it to lower case
+
+	// Find the plugin that will handle the specified gameid
+	const Plugin *plugin = 0;
+	GameDescriptor game = Base::findGame(gameid, &plugin);
+
+	if (!plugin) {
+		error("Could not find any plugin to handle gameid '%s' (target '%s')", gameid.c_str(), target);
+		return;
+	}
+
+	// Query the plugin for a list of savegames
+	SaveStateList saveList = plugin->listSaves(target);
+
+	// TODO: Include more info about the target (desc, engine name, ...) ???
+	printf("Saves for target '%s':\n", target);
+	printf("  Slot Description                                           \n"
+	       "  ---- ------------------------------------------------------\n");
+
+	for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
+		printf("  %-4s %s\n", x->save_slot().c_str(), x->description().c_str());
+		// TODO: Could also iterate over the full hashmap, printing all key-value pairs
+	}
+}
+
+
 #ifdef DETECTOR_TESTING_HACK
 static void runDetectorTest() {
 	// HACK: The following code can be used to test the detection code of our
@@ -671,6 +718,9 @@
 	} else if (command == "list-games") {
 		listGames();
 		return false;
+	} else if (command == "list-saves") {
+		listSaves(settings["list-saves"].c_str());
+		return false;
 	} else if (command == "version") {
 		printf("%s\n", gScummVMFullVersion);
 		printf("Features compiled in: %s\n", gScummVMFeatures);

Modified: scummvm/trunk/base/game.cpp
===================================================================
--- scummvm/trunk/base/game.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/base/game.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -25,7 +25,9 @@
 
 #include "base/game.h"
 #include "base/plugins.h"
+#include "graphics/surface.h"
 
+
 const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) {
 	const PlainGameDescriptor *g = list;
 	while (g->gameid) {
@@ -66,6 +68,15 @@
 	}
 }
 
+void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
+	if (_thumbnail && _thumbnail != t) {
+		_thumbnail->free();
+		delete _thumbnail;
+	}
+	_thumbnail = t;
+}
+
+
 namespace Base {
 
 // TODO: Find a better name & place for this function.

Modified: scummvm/trunk/base/game.h
===================================================================
--- scummvm/trunk/base/game.h	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/base/game.h	2008-02-04 10:15:21 UTC (rev 30786)
@@ -30,6 +30,10 @@
 #include "common/array.h"
 #include "common/hash-str.h"
 
+namespace Graphics {
+	class Surface;
+}
+
 /**
  * A simple structure used to map gameids (like "monkey", "sword1", ...) to
  * nice human readable and descriptive game titles (like "The Secret of Monkey Island").
@@ -67,7 +71,7 @@
 		setVal("description", pgd.description);
 	}
 
-	GameDescriptor(Common::String g, Common::String d, Common::Language l  = Common::UNK_LANG,
+	GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l  = Common::UNK_LANG,
 	             Common::Platform p = Common::kPlatformUnknown) {
 		setVal("gameid", g);
 		setVal("description", d);
@@ -103,8 +107,79 @@
 	}
 };
 
+/**
+ * A hashmap describing details about a given save state.
+ * TODO
+ * Guaranteed to contain save_slot, filename and description values.
+ * Additional ideas: Playtime, creation date, thumbnail, ...
+ */
+class SaveStateDescriptor : public Common::StringMap {
+protected:
+	Graphics::Surface	*_thumbnail;	// can be NULL
+public:
+	SaveStateDescriptor() : _thumbnail(0) {
+		setVal("save_slot", "-1");	// FIXME: default to 0 (first slot) or to -1 (invalid slot) ?
+		setVal("description", "");
+		setVal("filename", "");
+	}
 
+	SaveStateDescriptor(int s, const Common::String &d, const Common::String &f) : _thumbnail(0) {
+		char buf[16];
+		sprintf(buf, "%d", s);
+		setVal("save_slot", buf);
+		setVal("description", d);
+		setVal("filename", f);
+	}
 
+	SaveStateDescriptor(const Common::String &s, const Common::String &d, const Common::String &f) : _thumbnail(0) {
+		setVal("save_slot", s);
+		setVal("description", d);
+		setVal("filename", f);
+	}
+
+	~SaveStateDescriptor() {
+		setThumbnail(0);
+	}
+
+	/** The saveslot id, as it would be passed to the "-x" command line switch. */
+	Common::String &save_slot() { return getVal("save_slot"); }
+
+	/** The saveslot id, as it would be passed to the "-x" command line switch (read-only variant). */
+	const Common::String &save_slot() const { return getVal("save_slot"); }
+
+	/** A human readable description of the save state. */
+	Common::String &description() { return getVal("description"); }
+
+	/** A human readable description of the save state (read-only variant). */
+	const Common::String &description() const { return getVal("description"); }
+
+	/** The filename of the savestate, for use with the SaveFileManager API. */
+	Common::String &filename() { return getVal("filename"); }
+
+	/** The filename of the savestate, for use with the SaveFileManager API (read-only variant). */
+	const Common::String &filename() const { return getVal("filename"); }
+
+	/**
+	 * Return a thumbnail graphics surface representing the savestate visually
+	 * This is usually a scaled down version of the game graphics. The size
+	 * should be either 160x100 or 160x120 pixels, depending on the aspect
+	 * ratio of the game. If another ratio is required, contact the core team.
+	 *
+	 * TODO: it is probably a bad idea to read this for *all* games at once,
+	 * at least on low-end devices. So this info should probably normally only
+	 * be included optionally. I.e. only upon a query for a specific savegame...
+	 * To this end, add a getFullSaveStateInfo(target, slot) to the plugin API.
+	 */
+	const Graphics::Surface *getThumbnail() const { return _thumbnail; }
+
+	
+	void setThumbnail(Graphics::Surface *t);
+};
+
+/** List of savestates. */
+typedef Common::Array<SaveStateDescriptor> SaveStateList;
+
+
 class Plugin;
 
 namespace Base {

Modified: scummvm/trunk/base/plugins.cpp
===================================================================
--- scummvm/trunk/base/plugins.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/base/plugins.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -67,6 +67,10 @@
 	GameList detectGames(const FSList &fslist) const {
 		return _metaengine->detectGames(fslist);
 	}
+
+	SaveStateList listSaves(const char *target) const {
+		return _metaengine->listSaves(target);
+	}
 };
 
 class StaticPluginProvider : public PluginProvider {

Modified: scummvm/trunk/base/plugins.h
===================================================================
--- scummvm/trunk/base/plugins.h	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/base/plugins.h	2008-02-04 10:15:21 UTC (rev 30786)
@@ -47,6 +47,7 @@
 public:
 	virtual ~Plugin() {}
 
+//	virtual bool isLoaded() const = 0;	// TODO
 	virtual bool loadPlugin() = 0;
 	virtual void unloadPlugin() = 0;
 
@@ -58,6 +59,8 @@
 	virtual GameDescriptor findGame(const char *gameid) const = 0;
 	virtual GameList detectGames(const FSList &fslist) const = 0;
 
+	virtual SaveStateList listSaves(const char *target) const = 0;
+
 	virtual PluginError createInstance(OSystem *syst, Engine **engine) const = 0;
 };
 

Modified: scummvm/trunk/engines/metaengine.h
===================================================================
--- scummvm/trunk/engines/metaengine.h	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/metaengine.h	2008-02-04 10:15:21 UTC (rev 30786)
@@ -46,15 +46,54 @@
 public:
 	virtual ~MetaEngine() {}
 
+	/** Returns the name of the engine. */
 	virtual const char *getName() const = 0;
+
+	/** Returns some copyright information about the engine. */
 	virtual const char *getCopyright() const = 0;
+
 //	virtual int getVersion() const = 0;	// TODO!
 
+	/** Returns a list of games supported by this engine. */
 	virtual GameList getSupportedGames() const = 0;
+
+	/** Query the engine for a GameDescriptor for the specified gameid, if any. */
 	virtual GameDescriptor findGame(const char *gameid) const = 0;
+
+	/**
+	 * Runs the engine's game detector on the given list of files, and returns a
+	 * (possibly empty) list of games supported by the engine which it was able
+	 * to detect amongst the given files.
+	 */
 	virtual GameList detectGames(const FSList &fslist) const = 0;
 
+	/**
+	 * Tries to instantiate an engine instance based on the settings of
+	 * the currently active ConfMan target. That is, the MetaEngine should
+	 * query the ConfMan singleton for the target, gameid, path etc. data.
+	 *
+	 * @param syst	Pointer to the global OSystem object
+	 * @param engine	Pointer to a pointer which the MetaEngine sets to
+	 *					the newly create Engine, or 0 in case of an error
+	 * @return		a PluginError describing the error which occurred, or kNoError
+	 */
 	virtual PluginError createInstance(OSystem *syst, Engine **engine) const = 0;
+
+	/**
+	 * Return a list of all save states associated with the given target.
+	 *
+	 * In general, the caller will already have ensured that this (Meta)Engine
+	 * is responsible for the specified target by using findGame on it resp.
+	 * on the associated gameid from the relevant ConfMan entry, if present.
+	 *
+	 * The default implementation returns an empty list.
+	 *
+	 * @param target	name of a config manager target
+	 * @return			a list of save state descriptors
+	 */
+	virtual SaveStateList listSaves(const char *target) const {
+		return SaveStateList();
+	}
 };
 
 #endif

Modified: scummvm/trunk/engines/scumm/detection.cpp
===================================================================
--- scummvm/trunk/engines/scumm/detection.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/scumm/detection.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -29,6 +29,8 @@
 #include "common/fs.h"
 #include "common/list.h"
 #include "common/md5.h"
+#include "common/savefile.h"
+#include "common/system.h"
 
 #include "scumm/detection.h"
 #include "scumm/detection_tables.h"
@@ -675,6 +677,8 @@
 	virtual GameList detectGames(const FSList &fslist) const;
 
 	virtual PluginError createInstance(OSystem *syst, Engine **engine) const;
+
+	virtual SaveStateList listSaves(const char *target) const;
 };
 
 GameList ScummMetaEngine::getSupportedGames() const {
@@ -928,4 +932,36 @@
 	       "Humongous SCUMM Games (C) Humongous";
 }
 
+namespace Scumm {
+	extern bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion);
+}
+
+SaveStateList ScummMetaEngine::listSaves(const char *target) const {
+	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+	Common::StringList filenames;
+	Common::String saveDesc;
+	Common::String pattern = target;
+	pattern += ".s??";
+
+	filenames = saveFileMan->listSavefiles(pattern.c_str());
+	sort(filenames.begin(), filenames.end());	// Sort (hopefully ensuring we are sorted numerically..)
+
+	SaveStateList saveList;
+	for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){
+		// Obtain the last 2 digits of the filename, since they correspond to the save slot
+		int slotNum = atoi(file->c_str() + file->size() - 2);
+		
+		if (slotNum >= 0 && slotNum <= 99) {
+			Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+			if (in) {
+				Scumm::getSavegameName(in, saveDesc, 0);	// FIXME: heversion?!?
+				saveList.push_back(SaveStateDescriptor(slotNum, saveDesc, *file));
+				delete in;
+			}
+		}
+	}
+
+	return saveList;
+}
+
 REGISTER_PLUGIN(SCUMM, ScummMetaEngine);

Modified: scummvm/trunk/engines/scumm/dialogs.cpp
===================================================================
--- scummvm/trunk/engines/scumm/dialogs.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/scumm/dialogs.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -421,16 +421,14 @@
 Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) {
 	// Get savegame descriptions
 	Common::StringList descriptions;
-	char name[32];
 	uint i = saveMode ? 1 : 0;		//the autosave is on slot #0
 	bool avail_saves[81];
 
 	scumm->listSavegames(avail_saves, ARRAYSIZE(avail_saves));
 	for (; i < ARRAYSIZE(avail_saves); i++) {
+		Common::String name;
 		if (avail_saves[i])
 			scumm->getSavegameName(i, name);
-		else
-			name[0] = 0;
 		descriptions.push_back(name);
 	}
 

Modified: scummvm/trunk/engines/scumm/saveload.cpp
===================================================================
--- scummvm/trunk/engines/scumm/saveload.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/scumm/saveload.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -431,39 +431,46 @@
 	}
 }
 
-bool ScummEngine::getSavegameName(int slot, char *desc) {
+bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion);
+
+bool ScummEngine::getSavegameName(int slot, Common::String &desc) {
+	Common::InSaveFile *in = 0;
+	bool result = false;
 	char filename[256];
-	Common::SeekableReadStream *in;
-	SaveGameHeader hdr;
 
+	desc.clear();
 	makeSavegameName(filename, slot, false);
-	if (!(in = _saveFileMan->openForLoading(filename))) {
-		strcpy(desc, "");
-		return false;
+	in = _saveFileMan->openForLoading(filename);
+	if (in) {
+		result = Scumm::getSavegameName(in, desc, _game.heversion);
+		delete in;
 	}
+	return result;
+}
 
+bool getSavegameName(Common::InSaveFile *in, Common::String &desc, int heversion) {
+	SaveGameHeader hdr;
+
 	if (!loadSaveGameHeader(in, hdr)) {
-		delete in;
-		strcpy(desc, "Invalid savegame");
+		desc = "Invalid savegame";
 		return false;
 	}
-	delete in;
 
 	if (hdr.ver > CURRENT_VER)
 		hdr.ver = TO_LE_32(hdr.ver);
 	if (hdr.ver < VER(7) || hdr.ver > CURRENT_VER) {
-		strcpy(desc, "Invalid version");
+		desc = "Invalid version";
 		return false;
 	}
 
 	// We (deliberately) broke HE savegame compatibility at some point.
-	if (hdr.ver < VER(57) && _game.heversion >= 60) {
-		strcpy(desc, "Unsupported version");
+	if (hdr.ver < VER(57) && heversion >= 60) {
+		desc = "Unsupported version";
 		return false;
 	}
 
-	memcpy(desc, hdr.name, sizeof(hdr.name));
-	desc[sizeof(hdr.name) - 1] = 0;
+	hdr.name[sizeof(hdr.name) - 1] = 0;
+	desc = hdr.name;
 	return true;
 }
 

Modified: scummvm/trunk/engines/scumm/script_v5.cpp
===================================================================
--- scummvm/trunk/engines/scumm/script_v5.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/scumm/script_v5.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -942,7 +942,6 @@
 			int slotSize;
 			byte* slotContent;
 			int savegameId;
-			char name[32];
 			bool avail_saves[100];
 
 			if (a == STRINGID_IQ_SERIES && b == STRINGID_IQ_SERIES) {
@@ -960,9 +959,10 @@
 
 				// load savegame names
 				savegameId = slot - a + 1;
+				Common::String name;
 				if (avail_saves[savegameId] && getSavegameName(savegameId, name)) {
 					int pos;
-					char *ptr = name;
+					const char *ptr = name.c_str();
 					// slotContent ends with {'\0','@'} -> max. length = slotSize-2
 					for (pos = 0; pos < slotSize - 2; ++pos) {
 						if (!ptr[pos])

Modified: scummvm/trunk/engines/scumm/script_v8.cpp
===================================================================
--- scummvm/trunk/engines/scumm/script_v8.cpp	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/scumm/script_v8.cpp	2008-02-04 10:15:21 UTC (rev 30786)
@@ -1235,9 +1235,9 @@
 		removeBlastTexts();
 		break;
 	case 25: {	// saveGameReadName
-		char name[30];
+		Common::String name;
 		if (getSavegameName(args[1], name)) {
-			int size = resStrLen((const byte *)name) + 1;
+			int size = name.size() + 1;
 			_res->nukeResource(rtString, args[2]);
 
 			ArrayHeader *ah = (ArrayHeader *)_res->createResource(rtString, args[2], size + sizeof(ArrayHeader));
@@ -1245,7 +1245,7 @@
 			ah->dim1 = TO_LE_16(size + 1);
 			ah->dim2 = TO_LE_16(1);
 
-			memcpy(getStringAddress(args[2]), name, size);
+			memcpy(getStringAddress(args[2]), name.c_str(), size);
 		}
 		break;
 	}

Modified: scummvm/trunk/engines/scumm/scumm.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm.h	2008-02-04 07:38:42 UTC (rev 30785)
+++ scummvm/trunk/engines/scumm/scumm.h	2008-02-04 10:15:21 UTC (rev 30786)
@@ -623,7 +623,7 @@
 	int getKeyState(int key);
 
 public:
-	bool getSavegameName(int slot, char *desc);
+	bool getSavegameName(int slot, Common::String &desc);
 	void listSavegames(bool *marks, int num);
 
 	void requestSave(int slot, const char *name, bool temporary = false);


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