From a2fe6448459003abb5eb81deba8045d5546a5a6a Mon Sep 17 00:00:00 2001
From: Strangerke <strangerke@scummvm.org>
Date: Tue, 4 Jul 2017 07:47:25 +0200
Subject: [PATCH] KINGDOM: Improve savegame support

---
 engines/kingdom/detection.cpp | 80 ++++++++++++++++++++++++++++++++++-
 engines/kingdom/kingdom.cpp   | 10 ++---
 engines/kingdom/kingdom.h     |  4 +-
 3 files changed, 86 insertions(+), 8 deletions(-)

diff --git a/engines/kingdom/detection.cpp b/engines/kingdom/detection.cpp
index 881645b9250..42c23603786 100644
--- a/engines/kingdom/detection.cpp
+++ b/engines/kingdom/detection.cpp
@@ -40,6 +40,8 @@ static const PlainGameDescriptor kingdomGames[] = {
 
 namespace Kingdom {
 
+#define MAX_SAVES 99
+
 static const ADGameDescription gameDescriptions[] = {
 	// Kingdom PC DOS Demo version, provided by Strangerke
 	{
@@ -84,10 +86,20 @@ public:
 
 	virtual bool hasFeature(MetaEngineFeature f) const;
 	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+	virtual int getMaximumSaveSlot() const;
+	virtual SaveStateList listSaves(const char *target) const;
+	virtual void removeSaveState(const char *target, int slot) const;
+	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
 };
 
 bool KingdomMetaEngine::hasFeature(MetaEngineFeature f) const {
-	return false;
+	return
+	    (f == kSupportsListSaves) ||
+	    (f == kSupportsLoadingDuringStartup) ||
+	    (f == kSupportsDeleteSave) ||
+	    (f == kSavesSupportMetaInfo) ||
+	    (f == kSavesSupportThumbnail) ||
+	    (f == kSavesSupportCreationDate);
 }
 
 bool KingdomMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
@@ -97,6 +109,72 @@ bool KingdomMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADG
 	return desc != nullptr;
 }
 
+int KingdomMetaEngine::getMaximumSaveSlot() const {
+	return MAX_SAVES;
+}
+
+SaveStateList KingdomMetaEngine::listSaves(const char *target) const {
+	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+	Common::StringArray filenames;
+	Common::String saveDesc;
+	Common::String pattern = Common::String::format("%s.0##", target);
+
+	filenames = saveFileMan->listSavefiles(pattern);
+
+	Kingdom::KingdomSavegameHeader header;
+
+	SaveStateList saveList;
+	for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+		const char *ext = strrchr(file->c_str(), '.');
+		int slot = ext ? atoi(ext + 1) : -1;
+
+		if (slot >= 0 && slot < MAX_SAVES) {
+			Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+			if (in) {
+				if (Kingdom::KingdomGame::readSavegameHeader(in, header)) {
+					saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+
+					header._thumbnail->free();
+					delete header._thumbnail;
+				}
+
+				delete in;
+			}
+		}
+	}
+
+	// Sort saves based on slot number.
+	Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+	return saveList;
+}
+
+void KingdomMetaEngine::removeSaveState(const char *target, int slot) const {
+	Common::String filename = Common::String::format("%s.%03d", target, slot);
+	g_system->getSavefileManager()->removeSavefile(filename);
+}
+
+SaveStateDescriptor KingdomMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+	Common::String filename = Common::String::format("%s.%03d", target, slot);
+	Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
+
+	if (f) {
+		Kingdom::KingdomSavegameHeader header;
+		Kingdom::KingdomGame::readSavegameHeader(f, header);
+		delete f;
+
+		// Create the return descriptor
+		SaveStateDescriptor desc(slot, header._saveName);
+		desc.setThumbnail(header._thumbnail);
+		desc.setSaveDate(header._year, header._month, header._day);
+		desc.setSaveTime(header._hour, header._minute);
+
+		return desc;
+	}
+
+	return SaveStateDescriptor();
+}
+
 #if PLUGIN_ENABLED_DYNAMIC(KINGDOM)
 REGISTER_PLUGIN_DYNAMIC(KINGDOM, PLUGIN_TYPE_ENGINE, KingdomMetaEngine);
 #else
diff --git a/engines/kingdom/kingdom.cpp b/engines/kingdom/kingdom.cpp
index 3fed5bba72e..16dc4ca873e 100644
--- a/engines/kingdom/kingdom.cpp
+++ b/engines/kingdom/kingdom.cpp
@@ -696,7 +696,7 @@ void KingdomGame::DrawInventory() {
 		DrawIcon(131, 39, 134 + _Inventory[3]);
 }
 
-Common::String KingdomGame::generateSaveName(int slot) {
+Common::String KingdomGame::getSavegameFilename(int slot) {
 	return Common::String::format("%s.%03d", _targetName.c_str(), slot);
 }
 
@@ -722,7 +722,7 @@ void KingdomGame::restoreGame() {
 }
 
 Common::Error KingdomGame::saveGameState(int slot, const Common::String &desc) {
-	Common::String savegameFile = generateSaveName(slot);
+	Common::String savegameFile = getSavegameFilename(slot);
 	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
 	Common::OutSaveFile *out = saveMan->openForSaving(savegameFile);
 
@@ -743,7 +743,7 @@ Common::Error KingdomGame::saveGameState(int slot, const Common::String &desc) {
 }
 
 Common::Error KingdomGame::loadGameState(int slot) {
-	Common::String savegameFile = generateSaveName(slot);
+	Common::String savegameFile = getSavegameFilename(slot);
 	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
 	Common::InSaveFile *inFile = saveMan->openForLoading(savegameFile);
 	if (!inFile)
@@ -1479,8 +1479,8 @@ void KingdomGame::DrawIcon(int x, int y, int index) {
 	int height = _kingartEntries[index].Height;
 
 	::Graphics::Surface *screen = g_system->lockScreen();
-	for (uint curX = 0; curX < width; curX++) {
-		for (uint curY = 0; curY < height; curY++) {
+	for (int curX = 0; curX < width; curX++) {
+		for (int curY = 0; curY < height; curY++) {
 			const byte *src = data + (curY * width) + curX;
 			byte *dst = (byte *)screen->getBasePtr(curX + x, curY + y);
 			if (*src != 0xFF)
diff --git a/engines/kingdom/kingdom.h b/engines/kingdom/kingdom.h
index 6da0a2b71f4..65ced52b214 100644
--- a/engines/kingdom/kingdom.h
+++ b/engines/kingdom/kingdom.h
@@ -102,6 +102,7 @@ namespace Kingdom {
 		const ADGameDescription *_gameDescription;
 		const char *getGameId() const;
 		Common::Platform getPlatform() const;
+		static bool readSavegameHeader(Common::InSaveFile *in, KingdomSavegameHeader &header);
 
 	private:
 		Console *_console;
@@ -275,8 +276,7 @@ namespace Kingdom {
 		void restoreGame();
 		virtual Common::Error loadGameState(int slot);
 		virtual Common::Error saveGameState(int slot, const Common::String &desc);
-		Common::String generateSaveName(int slot);
-		static bool readSavegameHeader(Common::InSaveFile *in, KingdomSavegameHeader &header);
+		Common::String getSavegameFilename(int slot);
 		void writeSavegameHeader(Common::OutSaveFile *out, KingdomSavegameHeader &header);
 		void synchronize(Common::Serializer &s);
 		void refreshScreen();