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

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Tue Sep 16 16:10:56 CEST 2008


Revision: 34581
          http://scummvm.svn.sourceforge.net/scummvm/?rev=34581&view=rev
Author:   lordhoto
Date:     2008-09-16 14:10:55 +0000 (Tue, 16 Sep 2008)

Log Message:
-----------
Added "querySaveMetaInfos" to MetaEngine.
 -> Allows easy addition of save state specific infos like playtime, save date atc.
 -> Removed MetaEngine::loadThumbnailFromSlot, superseded by meta infos
 -> Changed SCUMM / KYRA to implement the newly added functionallity
 -> Removed hack in KYRAs listSavefiles, which is now handled via meta infos

Modified Paths:
--------------
    scummvm/trunk/base/game.cpp
    scummvm/trunk/base/game.h
    scummvm/trunk/engines/kyra/detection.cpp
    scummvm/trunk/engines/metaengine.h
    scummvm/trunk/engines/scumm/detection.cpp
    scummvm/trunk/graphics/surface.cpp
    scummvm/trunk/graphics/surface.h
    scummvm/trunk/gui/launcher.cpp
    scummvm/trunk/gui/widget.cpp

Modified: scummvm/trunk/base/game.cpp
===================================================================
--- scummvm/trunk/base/game.cpp	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/base/game.cpp	2008-09-16 14:10:55 UTC (rev 34581)
@@ -69,9 +69,30 @@
 }
 
 void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
-	if (_thumbnail && _thumbnail != t) {
-		_thumbnail->free();
-		delete _thumbnail;
+	if (_thumbnail.get() == t)
+		return;
+
+	_thumbnail = Common::SharedPtr<Graphics::Surface>(t, Graphics::SharedPtrSurfaceDeleter());
+}
+
+bool SaveStateDescriptor::getBool(const Common::String &key) const {
+	if (contains(key)) {
+		Common::String value = getVal(key);
+		if (value.equalsIgnoreCase("true") ||
+			value.equalsIgnoreCase("yes") || 
+			value.equals("1"))
+			return true;
+		if (value.equalsIgnoreCase("false") ||
+			value.equalsIgnoreCase("no") || 
+			value.equals("0"))
+			return false;
+		error("SaveStateDescriptor: %s '%s' has unknown value '%s' for boolean '%s'",
+				save_slot().c_str(), description().c_str(), value.c_str(), key.c_str());
 	}
-	_thumbnail = t;
+	return false;
 }
+
+void SaveStateDescriptor::setDeletableFlag(bool state) {
+	setVal("is_deletable", state ? "true" : "false");
+}
+

Modified: scummvm/trunk/base/game.h
===================================================================
--- scummvm/trunk/base/game.h	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/base/game.h	2008-09-16 14:10:55 UTC (rev 34581)
@@ -29,6 +29,7 @@
 #include "common/str.h"
 #include "common/array.h"
 #include "common/hash-str.h"
+#include "common/ptr.h"
 
 namespace Graphics {
 	struct Surface;
@@ -119,15 +120,16 @@
  */
 class SaveStateDescriptor : public Common::StringMap {
 protected:
-	Graphics::Surface	*_thumbnail;	// can be NULL
+	Common::SharedPtr<Graphics::Surface> _thumbnail; // can be 0
+
 public:
-	SaveStateDescriptor() : _thumbnail(0) {
+	SaveStateDescriptor() : _thumbnail() {
 		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) {
+	SaveStateDescriptor(int s, const Common::String &d, const Common::String &f) : _thumbnail() {
 		char buf[16];
 		sprintf(buf, "%d", s);
 		setVal("save_slot", buf);
@@ -135,16 +137,12 @@
 		setVal("filename", f);
 	}
 
-	SaveStateDescriptor(const Common::String &s, const Common::String &d, const Common::String &f) : _thumbnail(0) {
+	SaveStateDescriptor(const Common::String &s, const Common::String &d, const Common::String &f) : _thumbnail() {
 		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"); }
 
@@ -163,19 +161,30 @@
 	/** The filename of the savestate, for use with the SaveFileManager API (read-only variant). */
 	const Common::String &filename() const { return getVal("filename"); }
 
+	/** Optional entries only included when querying via MetaEngine::querySaveMetaInfo */
+
 	/**
+	 * Returns the value of a given key as boolean.
+	 * It accepts 'true', 'yes' and '1' for true and
+	 * 'false', 'no' and '0' for false.
+	 * (FIXME:) On unknown value it errors out ScummVM.
+	 * On unknown key it returns false as default.
+	 */
+	bool getBool(const Common::String &key) const;
+
+	/**
+	 * Sets the 'is_deletable' key, which indicates, if the
+	 * given savestate is safe for deletion.
+	 */
+	void setDeletableFlag(bool state);
+
+	/**
 	 * 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; }
-
+	const Graphics::Surface *getThumbnail() const { return _thumbnail.get(); }
 	
 	void setThumbnail(Graphics::Surface *t);
 };

Modified: scummvm/trunk/engines/kyra/detection.cpp
===================================================================
--- scummvm/trunk/engines/kyra/detection.cpp	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/engines/kyra/detection.cpp	2008-09-16 14:10:55 UTC (rev 34581)
@@ -1068,7 +1068,7 @@
 	bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
 	SaveStateList listSaves(const char *target) const;
 	void removeSaveState(const char *target, int slot) const;
-	Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot) const;
+	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
 };
 
 bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -1077,6 +1077,7 @@
 		(f == kSupportsListSaves) ||
 		(f == kSupportsDirectLoad) ||
 		(f == kSupportsDeleteSave) ||
+	   	(f == kSupportsMetaInfos) ||
 		(f == kSupportsThumbnails);
 }
 
@@ -1137,10 +1138,7 @@
 		// Obtain the last 3 digits of the filename, since they correspond to the save slot
 		int slotNum = atoi(file->c_str() + file->size() - 3);
 		
-		// HACK: Until we have a way to check whether a save is deletable in our launcher delete savegame dialog.
-		// We do not list slot 0 here, since it's for restarting the game and it should never be deleted.
-		// The downside of it is of course we can not load it via the menu and it isn't listed via --list-saves.
-		if (slotNum > 0 && slotNum <= 999) {
+		if (slotNum >= 0 && slotNum <= 999) {
 			Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
 			if (in) {
 				if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) {
@@ -1194,16 +1192,28 @@
 
 }
 
-Graphics::Surface *KyraMetaEngine::loadThumbnailFromSlot(const char *target, int slot) const {
+SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
 	Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot);
-
 	Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
-	Kyra::KyraEngine_v1::SaveHeader header;
 
-	if (in && Kyra::KyraEngine_v1::readSaveHeader(in, true, header) == Kyra::KyraEngine_v1::kRSHENoError)
-		return header.thumbnail;
+	if (in) {
+		Kyra::KyraEngine_v1::SaveHeader header;
+		Kyra::KyraEngine_v1::kReadSaveHeaderError error;
+
+		error = Kyra::KyraEngine_v1::readSaveHeader(in, true, header);
+		delete in;
+		
+		if (error == Kyra::KyraEngine_v1::kRSHENoError) {
+			SaveStateDescriptor desc(slot, header.description, filename);
+
+			desc.setDeletableFlag(slot != 0);
+			desc.setThumbnail(header.thumbnail);
+
+			return desc;
+		}
+	}
 	
-	return 0;
+	return SaveStateDescriptor();
 }
 
 #if PLUGIN_ENABLED_DYNAMIC(KYRA)

Modified: scummvm/trunk/engines/metaengine.h
===================================================================
--- scummvm/trunk/engines/metaengine.h	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/engines/metaengine.h	2008-09-16 14:10:55 UTC (rev 34581)
@@ -107,18 +107,16 @@
 	virtual void removeSaveState(const char *target, int slot) const {};
 
 	/**
-	 * Loads a thumbnail from the specified save state.
+	 * Returns meta infos from the specified save state.
 	 *
-	 * This can return '0' to indicate that no thumbnail was found.
-	 * If it returns a valid Graphics::Surface object, it must be the same
-	 * format as the overlay.
+	 * Depending on the MetaEngineFeatures set this can include
+	 * thumbnails, save date / time, play time.
 	 *
 	 * @param target	name of a config manager target
 	 * @param slot		slot number of the save state
 	 */
-	virtual Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot) const { return 0; }
+	virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const { return SaveStateDescriptor(); }
 
-	
 	/** @name MetaEngineFeature flags */
 	//@{
 	
@@ -146,10 +144,17 @@
 		kSupportsDeleteSave     = 3,
 
 		/**
-		 * Features a thumbnail in savegames (i.e. implements the
-		 * loadThumbnailFromSlot method)
+		 * Features meta infos for savestates (i.e. implements the
+		 * querySaveMetaInfos method properly)
 		 */
-		kSupportsThumbnails		= 4
+		kSupportsMetaInfos		= 4,
+
+		/**
+		 * Features a thumbnail in savegames (i.e. includes a thumbnail
+		 * in savestates returned via querySaveMetaInfo). This flag may 
+		 * only be set when 'kSupportsMetaInfos' is set.
+		 */
+		kSupportsThumbnails		= 5
 	};	
 
 	/**

Modified: scummvm/trunk/engines/scumm/detection.cpp
===================================================================
--- scummvm/trunk/engines/scumm/detection.cpp	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/engines/scumm/detection.cpp	2008-09-16 14:10:55 UTC (rev 34581)
@@ -683,7 +683,7 @@
 
 	virtual SaveStateList listSaves(const char *target) const;
 	virtual void removeSaveState(const char *target, int slot) const;
-	virtual Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot) const;
+	virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
 };
 
 bool ScummMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -692,6 +692,7 @@
 		(f == kSupportsListSaves) ||
 		(f == kSupportsDirectLoad) ||
 		(f == kSupportsDeleteSave) ||
+		(f == kSupportsMetaInfos) ||
 		(f == kSupportsThumbnails);
 }
 
@@ -983,8 +984,25 @@
 	g_system->getSavefileManager()->removeSavefile(filename.c_str());
 }
 
-Graphics::Surface *ScummMetaEngine::loadThumbnailFromSlot(const char *target, int slot) const {
-	return ScummEngine::loadThumbnailFromSlot(target, slot);
+SaveStateDescriptor ScummMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+	Common::String filename = ScummEngine::makeSavegameName(target, slot, false);
+	Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
+
+	if (!in)
+		return SaveStateDescriptor();
+
+	Common::String saveDesc;
+	Scumm::getSavegameName(in, saveDesc, 0);	// FIXME: heversion?!?
+	delete in;
+
+	// TODO: Cleanup
+	Graphics::Surface *thumbnail = ScummEngine::loadThumbnailFromSlot(target, slot);
+	
+	SaveStateDescriptor desc(slot, saveDesc, filename);
+	desc.setDeletableFlag(true);
+	desc.setThumbnail(thumbnail);
+
+	return desc;
 }
 
 #if PLUGIN_ENABLED_DYNAMIC(SCUMM)

Modified: scummvm/trunk/graphics/surface.cpp
===================================================================
--- scummvm/trunk/graphics/surface.cpp	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/graphics/surface.cpp	2008-09-16 14:10:55 UTC (rev 34581)
@@ -66,6 +66,11 @@
 	bytesPerPixel = 0;
 }
 
+void Surface::copyFrom(const Surface &surf) {
+	create(surf.w, surf.h, surf.bytesPerPixel);
+	memcpy(pixels, surf.pixels, h * pitch);
+}
+
 void Surface::hLine(int x, int y, int x2, uint32 color) {
 	// Clipping
 	if (y < 0 || y >= h)

Modified: scummvm/trunk/graphics/surface.h
===================================================================
--- scummvm/trunk/graphics/surface.h	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/graphics/surface.h	2008-09-16 14:10:55 UTC (rev 34581)
@@ -30,7 +30,6 @@
 
 namespace Graphics {
 
-
 /**
  * An arbitrary graphics surface, which can be the target (or source) of blit
  * operations, font rendering, etc.
@@ -67,6 +66,12 @@
 	 */
 	void free();
 
+	/**
+	 * Copies data from another Surface, this calls *free* on the current surface, to assure
+	 * it being clean.
+	 */
+	void copyFrom(const Surface &surf);
+
 	void drawLine(int x0, int y0, int x1, int y1, uint32 color);
 	void hLine(int x, int y, int x2, uint32 color);
 	void vLine(int x, int y, int y2, uint32 color);
@@ -76,7 +81,19 @@
 	void move(int dx, int dy, int height);
 };
 
+/**
+ * For safe deletion of surface with SharedPtr.
+ * The deleter assures Surface::free is called on
+ * deletion.
+ */
+struct SharedPtrSurfaceDeleter {
+	void operator()(Surface *ptr) {
+		ptr->free();
+		delete ptr;
+	}
+};
 
+
 } // End of namespace Graphics
 
 

Modified: scummvm/trunk/gui/launcher.cpp
===================================================================
--- scummvm/trunk/gui/launcher.cpp	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/gui/launcher.cpp	2008-09-16 14:10:55 UTC (rev 34581)
@@ -477,7 +477,6 @@
 	typedef Common::String String;
 	typedef Common::StringList StringList;
 protected:
-	bool			_delSupport;
 	GUI::ListWidget		*_list;
 	GUI::ButtonWidget	*_chooseButton;
 	GUI::ButtonWidget	*_deleteButton;
@@ -485,13 +484,16 @@
 	GUI::ContainerWidget	*_container;
 
 	const EnginePlugin		*_plugin;
+	bool					_delSupport;
+	bool					_metaInfoSupport;
+	bool					_thumbnailSupport;
 	String					_target;
 	SaveStateList			_saveList;
 
 	uint8 _fillR, _fillG, _fillB;
 
 	void updateSaveList();
-	void updateInfos(bool redraw);
+	void updateSelection(bool redraw);
 public:
 	SaveLoadChooser(const String &title, const String &buttonLabel);
 	~SaveLoadChooser();
@@ -528,6 +530,8 @@
 
 	_deleteButton = new GUI::ButtonWidget(this, "scummsaveload_delete", "Delete", kDelCmd, 0);
 	_deleteButton->setEnabled(false);
+
+	_delSupport = _metaInfoSupport = _thumbnailSupport = false;
 }
 
 SaveLoadChooser::~SaveLoadChooser() {
@@ -540,6 +544,8 @@
 	_plugin = plugin;
 	_target = target;
 	_delSupport = (*_plugin)->hasFeature(MetaEngine::kSupportsDeleteSave);
+	_metaInfoSupport = (*_plugin)->hasFeature(MetaEngine::kSupportsMetaInfos);
+	_thumbnailSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSupportsThumbnails);
 	reflowLayout();
 	updateSaveList();
 
@@ -566,16 +572,7 @@
 		close();
 		break;
 	case GUI::kListSelectionChangedCmd: {
-		if (_gfxWidget)
-			updateInfos(true);
-
-		// Disable these buttons if nothing is selected, or if an empty
-		// list item is selected.
-		_chooseButton->setEnabled(selItem >= 0 && (!_list->getSelectedString().empty()));
-		_chooseButton->draw();
-		// Delete will always be disabled if the engine doesn't support it.
-		_deleteButton->setEnabled(_delSupport && (selItem >= 0) && (!_list->getSelectedString().empty()));
-		_deleteButton->draw();
+		updateSelection(true);
 	} break;
 	case kDelCmd:
 		if (selItem >= 0 && _delSupport) {
@@ -588,10 +585,7 @@
 				_list->setSelected(-1);
 
 				updateSaveList();
-
-				// Disable these buttons again after deleteing a selection
-				_chooseButton->setEnabled(false);
-				_deleteButton->setEnabled(false);
+				updateSelection(true);
 			}
 		}
 		break;
@@ -603,7 +597,7 @@
 }
 
 void SaveLoadChooser::reflowLayout() {
-	if (g_gui.evaluator()->getVar("scummsaveload_extinfo.visible") == 1 && (_plugin && (*_plugin)->hasFeature(MetaEngine::kSupportsThumbnails))) {
+	if (g_gui.evaluator()->getVar("scummsaveload_extinfo.visible") == 1 && _thumbnailSupport) {
 		int thumbX = g_gui.evaluator()->getVar("scummsaveload_thumbnail.x");
 		int thumbY = g_gui.evaluator()->getVar("scummsaveload_thumbnail.y");
 		int hPad = g_gui.evaluator()->getVar("scummsaveload_thumbnail.hPad");
@@ -621,7 +615,7 @@
 		_fillR = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR");
 		_fillG = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG");
 		_fillB = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB");
-		updateInfos(false);
+		updateSelection(false);
 	} else {
 		_container->setFlags(GUI::WIDGET_INVISIBLE);
 		_gfxWidget->setFlags(GUI::WIDGET_INVISIBLE);
@@ -630,23 +624,39 @@
 	Dialog::reflowLayout();
 }
 
-void SaveLoadChooser::updateInfos(bool redraw) {
+void SaveLoadChooser::updateSelection(bool redraw) {
 	int selItem = _list->getSelected();
-	Graphics::Surface *thumb = 0;
-	if (selItem >= 0 && !_list->getSelectedString().empty())
-		thumb = (*_plugin)->loadThumbnailFromSlot(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str()));
 
-	if (thumb) {
-		_gfxWidget->setGfx(thumb);
-		_gfxWidget->useAlpha(256);
-		thumb->free();
-		delete thumb;
-	} else {
-		_gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
+	bool isDeletable = _delSupport;
+
+	if (selItem >= 0 && !_list->getSelectedString().empty() && _metaInfoSupport) {
+		SaveStateDescriptor desc = (*_plugin)->querySaveMetaInfos(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str()));
+
+		isDeletable = desc.getBool("is_deletable") && _delSupport;
+
+		if (_thumbnailSupport) {
+			const Graphics::Surface *thumb = desc.getThumbnail();
+			if (thumb) {
+				_gfxWidget->setGfx(thumb);
+				_gfxWidget->useAlpha(256);
+			} else {
+				_gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
+			}
+		}
 	}
 
-	if (redraw)
+
+	// Disable these buttons if nothing is selected, or if an empty
+	// list item is selected.
+	_chooseButton->setEnabled(selItem >= 0 && (!_list->getSelectedString().empty()));
+	// Delete will always be disabled if the engine doesn't support it.
+	_deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty()));
+
+	if (redraw) {
 		_gfxWidget->draw();
+		_chooseButton->draw();
+		_deleteButton->draw();
+	}
 }
 
 void SaveLoadChooser::close() {

Modified: scummvm/trunk/gui/widget.cpp
===================================================================
--- scummvm/trunk/gui/widget.cpp	2008-09-16 11:57:45 UTC (rev 34580)
+++ scummvm/trunk/gui/widget.cpp	2008-09-16 14:10:55 UTC (rev 34581)
@@ -363,8 +363,7 @@
 		return;
 
 	// TODO: add conversion to OverlayColor
-	_gfx.create(gfx->w, gfx->h, gfx->bytesPerPixel);
-	memcpy(_gfx.pixels, gfx->pixels, gfx->h * gfx->pitch);
+	_gfx.copyFrom(*gfx);
 }
 
 void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {


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