[Scummvm-cvs-logs] scummvm master -> 7044996cd530d1e0efa6a521be85c07111eb76df

bgK bastien.bouclet at gmail.com
Mon Feb 22 08:45:46 CET 2016


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
c3c09a1c83 MOHAWK: MystOptionsDialog should not subclass GUI::OptionsDialog
524d7ec5ec MOHAWK: Center the options dialog
6f56f2efe1 MOHAWK: Add Save, Load and Quit buttons to the Myst Dialog
7044996cd5 MOHAWK: Add support for the ScummVM save metadata features


Commit: c3c09a1c83b24d9c0206d9cbb86a4d6d641232b1
    https://github.com/scummvm/scummvm/commit/c3c09a1c83b24d9c0206d9cbb86a4d6d641232b1
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2016-02-22T08:44:55+01:00

Commit Message:
MOHAWK: MystOptionsDialog should not subclass GUI::OptionsDialog

Changed paths:
    engines/mohawk/dialogs.cpp
    engines/mohawk/dialogs.h



diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index ffc4552..492e610 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -87,7 +87,7 @@ enum {
 
 #ifdef ENABLE_MYST
 
-MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
+MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::Dialog(120, 120, 360, 200), _vm(vm) {
 	// I18N: Option for fast scene switching
 	_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
 	_transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
@@ -144,18 +144,22 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
 	case kMapCmd:
 		_vm->_needsShowMap = true;
 		close();
-	break;
+		break;
 	case kMenuCmd:
 		_vm->_needsShowDemoMenu = true;
 		close();
-	break;
+		break;
 	case GUI::kOKCmd:
 		_vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState();
 		_vm->_gameState->_globals.transitions = _transitionsCheckbox->getState();
-		GUI::OptionsDialog::handleCommand(sender, cmd, data);
+		setResult(1);
+		close();
+		break;
+	case GUI::kCloseCmd:
+		close();
 		break;
 	default:
-		GUI::OptionsDialog::handleCommand(sender, cmd, data);
+		GUI::Dialog::handleCommand(sender, cmd, data);
 	}
 }
 
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index 7470cd3..c017cb2 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -70,7 +70,7 @@ public:
 
 class MohawkEngine_Myst;
 
-class MystOptionsDialog : public GUI::OptionsDialog {
+class MystOptionsDialog : public GUI::Dialog {
 public:
 	MystOptionsDialog(MohawkEngine_Myst *vm);
 	~MystOptionsDialog();


Commit: 524d7ec5ec4e8c88cc37bbb5125383b1e3014cd6
    https://github.com/scummvm/scummvm/commit/524d7ec5ec4e8c88cc37bbb5125383b1e3014cd6
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2016-02-22T08:44:55+01:00

Commit Message:
MOHAWK: Center the options dialog

Changed paths:
    engines/mohawk/dialogs.cpp
    engines/mohawk/dialogs.h



diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index 492e610..73b1a15 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -87,7 +87,7 @@ enum {
 
 #ifdef ENABLE_MYST
 
-MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::Dialog(120, 120, 360, 200), _vm(vm) {
+MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::Dialog(0, 0, 360, 200), _vm(vm) {
 	// I18N: Option for fast scene switching
 	_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
 	_transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
@@ -135,6 +135,17 @@ void MystOptionsDialog::open() {
 	_transitionsCheckbox->setState(_vm->_gameState->_globals.transitions);
 }
 
+void MystOptionsDialog::reflowLayout() {
+	const int screenW = g_system->getOverlayWidth();
+	const int screenH = g_system->getOverlayHeight();
+
+	// Center the dialog
+	_x = (screenW - getWidth()) / 2;
+	_y = (screenH - getHeight()) / 2;
+
+	Dialog::reflowLayout();
+}
+
 void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
 	switch (cmd) {
 	case kDropCmd:
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index c017cb2..da89090 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -76,6 +76,7 @@ public:
 	~MystOptionsDialog();
 	void open();
 
+	virtual void reflowLayout() override;
 	virtual void handleCommand(GUI::CommandSender*, uint32, uint32);
 private:
 	MohawkEngine_Myst *_vm;


Commit: 6f56f2efe129e55d7ac5cf35378dd385d3f0547b
    https://github.com/scummvm/scummvm/commit/6f56f2efe129e55d7ac5cf35378dd385d3f0547b
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2016-02-22T08:44:55+01:00

Commit Message:
MOHAWK: Add Save, Load and Quit buttons to the Myst Dialog

So that it is possible to play the game without knowing about the GMM

Changed paths:
    engines/mohawk/dialogs.cpp
    engines/mohawk/dialogs.h



diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index 73b1a15..f8aaf0f 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -24,6 +24,7 @@
 #include "mohawk/dialogs.h"
 
 #include "gui/gui-manager.h"
+#include "gui/saveload.h"
 #include "gui/ThemeEngine.h"
 #include "gui/widget.h"
 #include "common/system.h"
@@ -82,35 +83,47 @@ enum {
 	kWaterCmd = 'WATR',
 	kDropCmd = 'DROP',
 	kMapCmd = 'SMAP',
-	kMenuCmd = 'MENU'
+	kMenuCmd = 'MENU',
+	kSaveCmd = 'SAVE',
+	kLoadCmd = 'LOAD',
+	kQuitCmd = 'QUIT'
 };
 
 #ifdef ENABLE_MYST
 
 MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::Dialog(0, 0, 360, 200), _vm(vm) {
 	// I18N: Option for fast scene switching
-	_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
-	_transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
+	_zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 220, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
+	_transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 220, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
 	// I18N: Drop book page
 	_dropPageButton = new GUI::ButtonWidget(this, 15, 60, 100, 25, _("~D~rop Page"), 0, kDropCmd);
 
 	// Myst ME only has maps
 	if (_vm->getFeatures() & GF_ME)
-		_showMapButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("~S~how Map"), 0, kMapCmd);
+		_showMapButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Show ~M~ap"), 0, kMapCmd);
 	else
 		_showMapButton = 0;
 
 	// Myst demo only has a menu
 	if (_vm->getFeatures() & GF_DEMO)
-		_returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("~M~ain Menu"), 0, kMenuCmd);
+		_returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Main Men~u~"), 0, kMenuCmd);
 	else
 		_returnToMenuButton = 0;
 
+	_loadButton = new GUI::ButtonWidget(this, 245, 25, 100, 25, _("~L~oad"), 0, kLoadCmd);
+	_saveButton = new GUI::ButtonWidget(this, 245, 60, 100, 25, _("~S~ave"), 0, kSaveCmd);
+	new GUI::ButtonWidget(this, 245, 95, 100, 25, _("~Q~uit"), 0, kQuitCmd);
+
 	new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
 	new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
+
+	_loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
+	_saveDialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
 }
 
 MystOptionsDialog::~MystOptionsDialog() {
+	delete _loadDialog;
+	delete _saveDialog;
 }
 
 void MystOptionsDialog::open() {
@@ -133,6 +146,33 @@ void MystOptionsDialog::open() {
 
 	_zipModeCheckbox->setState(_vm->_gameState->_globals.zipMode);
 	_transitionsCheckbox->setState(_vm->_gameState->_globals.transitions);
+
+	_loadButton->setEnabled(_vm->canLoadGameStateCurrently());
+	_saveButton->setEnabled(_vm->canSaveGameStateCurrently());
+}
+
+void MystOptionsDialog::save() {
+	int slot = _saveDialog->runModalWithCurrentTarget();
+
+	if (slot >= 0) {
+		Common::String result(_saveDialog->getResultString());
+		if (result.empty()) {
+			// If the user was lazy and entered no save name, come up with a default name.
+			result = _saveDialog->createDefaultSaveDescription(slot);
+		}
+
+		_vm->saveGameState(slot, result);
+		close();
+	}
+}
+
+void MystOptionsDialog::load() {
+	int slot = _loadDialog->runModalWithCurrentTarget();
+
+	if (slot >= 0) {
+		_vm->loadGameState(slot);
+		close();
+	}
 }
 
 void MystOptionsDialog::reflowLayout() {
@@ -160,6 +200,19 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
 		_vm->_needsShowDemoMenu = true;
 		close();
 		break;
+	case kLoadCmd:
+		load();
+		break;
+	case kSaveCmd:
+		save();
+		break;
+	case kQuitCmd: {
+		Common::Event eventQ;
+		eventQ.type = Common::EVENT_QUIT;
+		g_system->getEventManager()->pushEvent(eventQ);
+		close();
+	}
+		break;
 	case GUI::kOKCmd:
 		_vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState();
 		_vm->_gameState->_globals.transitions = _transitionsCheckbox->getState();
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index da89090..bc25c72 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -32,6 +32,10 @@
 #include "gui/widget.h"
 #include "gui/widgets/list.h"
 
+namespace GUI {
+class SaveLoadChooser;
+}
+
 namespace Mohawk {
 
 class MohawkEngine;
@@ -80,11 +84,22 @@ public:
 	virtual void handleCommand(GUI::CommandSender*, uint32, uint32);
 private:
 	MohawkEngine_Myst *_vm;
+
 	GUI::CheckboxWidget *_zipModeCheckbox;
 	GUI::CheckboxWidget *_transitionsCheckbox;
+
 	GUI::ButtonWidget *_dropPageButton;
 	GUI::ButtonWidget *_showMapButton;
 	GUI::ButtonWidget *_returnToMenuButton;
+
+	GUI::ButtonWidget    *_loadButton;
+	GUI::ButtonWidget    *_saveButton;
+
+	GUI::SaveLoadChooser *_loadDialog;
+	GUI::SaveLoadChooser *_saveDialog;
+
+	void save();
+	void load();
 };
 
 #endif


Commit: 7044996cd530d1e0efa6a521be85c07111eb76df
    https://github.com/scummvm/scummvm/commit/7044996cd530d1e0efa6a521be85c07111eb76df
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2016-02-22T08:44:55+01:00

Commit Message:
MOHAWK: Add support for the ScummVM save metadata features

The metadata is saved in a separate file to keep compatibility with
the original engine saves.

Changed paths:
    engines/mohawk/detection.cpp
    engines/mohawk/myst.cpp
    engines/mohawk/myst_state.cpp
    engines/mohawk/myst_state.h



diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 926c296..986b35c 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -35,6 +35,7 @@
 
 #ifdef ENABLE_MYST
 #include "mohawk/myst.h"
+#include "mohawk/myst_state.h"
 #endif
 
 #ifdef ENABLE_RIVEN
@@ -184,13 +185,18 @@ public:
 	virtual SaveStateList listSaves(const char *target) const;
 	virtual int getMaximumSaveSlot() const { return 999; }
 	virtual void removeSaveState(const char *target, int slot) const;
+	virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
 };
 
 bool MohawkMetaEngine::hasFeature(MetaEngineFeature f) const {
 	return
 		(f == kSupportsListSaves)
 		|| (f == kSupportsLoadingDuringStartup)
-		|| (f == kSupportsDeleteSave);
+		|| (f == kSupportsDeleteSave)
+		|| (f == kSavesSupportMetaInfo)
+		|| (f == kSavesSupportThumbnail)
+		|| (f == kSavesSupportCreationDate)
+		|| (f == kSavesSupportPlayTime);
 }
 
 SaveStateList MohawkMetaEngine::listSaves(const char *target) const {
@@ -198,12 +204,15 @@ SaveStateList MohawkMetaEngine::listSaves(const char *target) const {
 	SaveStateList saveList;
 
 	// Loading games is only supported in Myst/Riven currently.
+#ifdef ENABLE_MYST
 	if (strstr(target, "myst")) {
-		filenames = g_system->getSavefileManager()->listSavefiles("*.mys");
+		filenames = Mohawk::MystGameState::generateSaveGameList();
 
 		for (uint32 i = 0; i < filenames.size(); i++)
 			saveList.push_back(SaveStateDescriptor(i, filenames[i]));
-	} else if (strstr(target, "riven")) {
+	} else
+#endif
+	if (strstr(target, "riven")) {
 		filenames = g_system->getSavefileManager()->listSavefiles("*.rvn");
 
 		for (uint32 i = 0; i < filenames.size(); i++)
@@ -215,15 +224,35 @@ SaveStateList MohawkMetaEngine::listSaves(const char *target) const {
 
 void MohawkMetaEngine::removeSaveState(const char *target, int slot) const {
 	// Removing saved games is only supported in Myst/Riven currently.
+#ifdef ENABLE_MYST
 	if (strstr(target, "myst")) {
-		Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("*.mys");
-		g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str());
-	} else if (strstr(target, "riven")) {
+		Common::StringArray filenames = Mohawk::MystGameState::generateSaveGameList();
+		Mohawk::MystGameState::deleteSave(filenames[slot]);
+	} else
+#endif
+	if (strstr(target, "riven")) {
 		Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("*.rvn");
 		g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str());
 	}
 }
 
+SaveStateDescriptor MohawkMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+#ifdef ENABLE_MYST
+	if (strstr(target, "myst")) {
+		Common::StringArray filenames = Mohawk::MystGameState::generateSaveGameList();
+
+		if (slot >= (int) filenames.size()) {
+			return SaveStateDescriptor();
+		}
+
+		return Mohawk::MystGameState::querySaveMetaInfos(filenames[slot]);
+	} else
+#endif
+	{
+		return SaveStateDescriptor();
+	}
+}
+
 bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
 	const Mohawk::MohawkGameDescription *gd = (const Mohawk::MohawkGameDescription *)desc;
 
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 852196e..5337a5e 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -236,7 +236,7 @@ Common::Error MohawkEngine_Myst::run() {
 	// Load game from launcher/command line if requested
 	if (ConfMan.hasKey("save_slot") && canLoadGameStateCurrently()) {
 		uint32 gameToLoad = ConfMan.getInt("save_slot");
-		Common::StringArray savedGamesList = _gameState->generateSaveGameList();
+		Common::StringArray savedGamesList = MystGameState::generateSaveGameList();
 		if (gameToLoad > savedGamesList.size())
 			error ("Could not find saved game");
 		_gameState->load(savedGamesList[gameToLoad]);
@@ -1066,19 +1066,19 @@ void MohawkEngine_Myst::loadResources() {
 }
 
 Common::Error MohawkEngine_Myst::loadGameState(int slot) {
-	if (_gameState->load(_gameState->generateSaveGameList()[slot]))
+	if (_gameState->load(MystGameState::generateSaveGameList()[slot]))
 		return Common::kNoError;
 
 	return Common::kUnknownError;
 }
 
 Common::Error MohawkEngine_Myst::saveGameState(int slot, const Common::String &desc) {
-	Common::StringArray saveList = _gameState->generateSaveGameList();
+	Common::StringArray saveList = MystGameState::generateSaveGameList();
 
 	if ((uint)slot < saveList.size())
-		_gameState->deleteSave(saveList[slot]);
+		MystGameState::deleteSave(saveList[slot]);
 
-	return _gameState->save(Common::String(desc)) ? Common::kNoError : Common::kUnknownError;
+	return _gameState->save(desc) ? Common::kNoError : Common::kUnknownError;
 }
 
 bool MohawkEngine_Myst::canLoadGameStateCurrently() {
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index 9bfbba6..06cd69b 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -26,11 +26,41 @@
 
 #include "common/debug.h"
 #include "common/serializer.h"
+#include "common/system.h"
 #include "common/textconsole.h"
 #include "common/util.h"
 
+#include "graphics/thumbnail.h"
+
 namespace Mohawk {
 
+MystSaveMetadata::MystSaveMetadata() {
+	saveDay = 0;
+	saveMonth = 0;
+	saveYear = 0;
+	saveHour = 0;
+	saveMinute = 0;
+	totalPlayTime = 0;
+}
+
+bool MystSaveMetadata::sync(Common::Serializer &s) {
+	static const Common::Serializer::Version kCurrentVersion = 1;
+
+	if (!s.syncVersion(kCurrentVersion)) {
+		return false;
+	}
+
+	s.syncAsByte(saveDay);
+	s.syncAsByte(saveMonth);
+	s.syncAsUint16LE(saveYear);
+	s.syncAsByte(saveHour);
+	s.syncAsByte(saveMinute);
+	s.syncString(saveDescription);
+	s.syncAsUint32LE(totalPlayTime);
+
+	return true;
+}
+
 MystGameState::MystGameState(MohawkEngine_Myst *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) {
 	// Most of the variables are zero at game start.
 	memset(&_globals, 0, sizeof(_globals));
@@ -77,28 +107,15 @@ MystGameState::~MystGameState() {
 }
 
 Common::StringArray MystGameState::generateSaveGameList() {
-	return _saveFileMan->listSavefiles("*.mys");
+	return g_system->getSavefileManager()->listSavefiles("*.mys");
 }
 
 bool MystGameState::load(const Common::String &filename) {
-	Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
-	if (!loadFile)
-		return false;
-
-	debugC(kDebugSaveLoad, "Loading game from '%s'", filename.c_str());
-
-	// First, let's make sure we're using a saved game file from this version of Myst
-	// By checking length of file...
-	int32 size = loadFile->size();
-	if (size != 664 && size != 601) {
-		warning("Incompatible saved game version");
-		delete loadFile;
+	if (!loadState(filename)) {
 		return false;
 	}
 
-	Common::Serializer s(loadFile, nullptr);
-	syncGameState(s, size == 664);
-	delete loadFile;
+	loadMetadata(filename);
 
 	// Set Channelwood elevator state to down, because we start on the lower level
 	_channelwood.elevatorState = 0;
@@ -119,15 +136,72 @@ bool MystGameState::load(const Common::String &filename) {
 	return true;
 }
 
-bool MystGameState::save(const Common::String &fname) {
-	Common::String filename(fname);
-	// Make sure we have the right extension
-	if (!filename.hasSuffix(".mys") && !filename.hasSuffix(".MYS"))
-		filename += ".mys";
+bool MystGameState::loadState(const Common::String &filename) {
+	Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
+	if (!loadFile) {
+		return false;
+	}
+
+	debugC(kDebugSaveLoad, "Loading game from '%s'", filename.c_str());
+
+	// First, let's make sure we're using a saved game file from this version of Myst
+	// By checking length of file...
+	int32 size = loadFile->size();
+	if (size != 664 && size != 601) {
+		warning("Incompatible saved game version");
+		delete loadFile;
+		return false;
+	}
+
+	Common::Serializer s(loadFile, nullptr);
+	syncGameState(s, size == 664);
+	delete loadFile;
+
+	return true;
+}
 
+void MystGameState::loadMetadata(const Common::String &filename) {
+	// Open the metadata file
+	Common::InSaveFile *metadataFile = openMetadataFile(filename);
+	if (!metadataFile) {
+		return;
+	}
+
+	debugC(kDebugSaveLoad, "Loading metadata from '%s'", filename.c_str());
+
+	Common::Serializer m(metadataFile, nullptr);
+
+	// Read the metadata file
+	if (_metadata.sync(m)) {
+		_vm->setTotalPlayTime(_metadata.totalPlayTime);
+	}
+
+	delete metadataFile;
+}
+
+bool MystGameState::save(const Common::String &filename) {
+	// Make sure the description does not have an extension
+	Common::String desc = filename;
+	if (filename.hasSuffix(".mys") || filename.hasSuffix(".MYS")) {
+		desc = removeExtension(filename);
+	}
+
+	if (!saveState(desc)) {
+		return false;
+	}
+
+	updateMetadateForSaving(desc);
+
+	return saveMetadata(desc);
+}
+
+bool MystGameState::saveState(const Common::String &desc) {
+	// Make sure we have the right extension
+	Common::String filename = desc + ".mys";
 	Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
-	if (!saveFile)
+	if (!saveFile) {
 		return false;
+	}
 
 	debugC(kDebugSaveLoad, "Saving game to '%s'", filename.c_str());
 
@@ -139,6 +213,88 @@ bool MystGameState::save(const Common::String &fname) {
 	return true;
 }
 
+void MystGameState::updateMetadateForSaving(const Common::String &desc) {
+	// Update save creation info
+	TimeDate t;
+	g_system->getTimeAndDate(t);
+	_metadata.saveYear = t.tm_year + 1900;
+	_metadata.saveMonth = t.tm_mon + 1;
+	_metadata.saveDay = t.tm_mday;
+	_metadata.saveHour = t.tm_hour;
+	_metadata.saveMinute = t.tm_min;
+	_metadata.saveDescription = desc;
+	_metadata.totalPlayTime = _vm->getTotalPlayTime();
+}
+
+bool MystGameState::saveMetadata(const Common::String &desc) {
+	// Write the metadata to a separate file so that the save files
+	// are still compatible with the original engine
+	Common::String metadataFilename = desc + ".mym";
+	Common::OutSaveFile *metadataFile = _saveFileMan->openForSaving(metadataFilename);
+	if (!metadataFile) {
+		return false;
+	}
+
+	// Save the metadata
+	Common::Serializer m(nullptr, metadataFile);
+	_metadata.sync(m);
+
+	// Append a thumbnail
+	Graphics::saveThumbnail(*metadataFile);
+
+	metadataFile->finalize();
+	delete metadataFile;
+
+	return true;
+}
+
+SaveStateDescriptor MystGameState::querySaveMetaInfos(const Common::String filename) {
+	SaveStateDescriptor desc;
+	desc.setDescription(filename);
+
+	// Open the metadata file
+	Common::InSaveFile *metadataFile = openMetadataFile(filename);
+	if (!metadataFile) {
+		return desc;
+	}
+
+	Common::Serializer m(metadataFile, nullptr);
+
+	// Read the metadata file
+	Mohawk::MystSaveMetadata metadata;
+	if (!metadata.sync(m)) {
+		delete metadataFile;
+		return desc;
+	}
+
+	// Set the save description
+	desc.setDescription(metadata.saveDescription);
+	desc.setSaveDate(metadata.saveYear, metadata.saveMonth, metadata.saveDay);
+	desc.setSaveTime(metadata.saveHour, metadata.saveMinute);
+	desc.setPlayTime(metadata.totalPlayTime);
+	desc.setThumbnail(Graphics::loadThumbnail(*metadataFile));
+
+	delete metadataFile;
+
+	return desc;
+}
+
+Common::InSaveFile *MystGameState::openMetadataFile(const Common::String &filename) {
+	// Remove the extension
+	Common::String baseName = removeExtension(filename);
+
+	// Open the metadata file
+	return g_system->getSavefileManager()->openForLoading(baseName + ".mym");
+}
+
+Common::String MystGameState::removeExtension(const Common::String &filename) {
+	Common::String baseName = filename;
+	for (uint i = 0; i < 4; i++) {
+		baseName.deleteLastChar();
+	}
+	return baseName;
+}
+
 void MystGameState::syncGameState(Common::Serializer &s, bool isME) {
 	// Globals first
 	s.syncAsUint16LE(_globals.u0);
@@ -317,7 +473,10 @@ void MystGameState::syncGameState(Common::Serializer &s, bool isME) {
 
 void MystGameState::deleteSave(const Common::String &saveName) {
 	debugC(kDebugSaveLoad, "Deleting save file \'%s\'", saveName.c_str());
-	_saveFileMan->removeSavefile(saveName.c_str());
+	Common::String basename = removeExtension(saveName);
+
+	g_system->getSavefileManager()->removeSavefile(saveName);
+	g_system->getSavefileManager()->removeSavefile(basename + ".mym");
 }
 
 void MystGameState::addZipDest(uint16 stack, uint16 view) {
diff --git a/engines/mohawk/myst_state.h b/engines/mohawk/myst_state.h
index b07a0f2..50359a5 100644
--- a/engines/mohawk/myst_state.h
+++ b/engines/mohawk/myst_state.h
@@ -27,6 +27,8 @@
 #include "common/file.h"
 #include "common/str.h"
 
+#include "engines/savestate.h"
+
 namespace Common {
 class Serializer;
 }
@@ -35,15 +37,33 @@ namespace Mohawk {
 
 class MohawkEngine_Myst;
 
+struct MystSaveMetadata {
+	uint8 saveDay;
+	uint8 saveMonth;
+	uint16 saveYear;
+
+	uint8 saveHour;
+	uint8 saveMinute;
+
+	uint32 totalPlayTime;
+
+	Common::String saveDescription;
+
+	MystSaveMetadata();
+	bool sync(Common::Serializer &s);
+};
+
 class MystGameState {
 public:
 	MystGameState(MohawkEngine_Myst*, Common::SaveFileManager*);
 	~MystGameState();
 
-	Common::StringArray generateSaveGameList();
-	bool load(const Common::String &);
-	bool save(const Common::String &);
-	void deleteSave(const Common::String &);
+	static Common::StringArray generateSaveGameList();
+	static SaveStateDescriptor querySaveMetaInfos(const Common::String filename);
+
+	bool load(const Common::String &filename);
+	bool save(const Common::String &filename);
+	static void deleteSave(const Common::String &saveName);
 
 	void addZipDest(uint16 stack, uint16 view);
 	bool isReachableZipDest(uint16 stack, uint16 view);
@@ -268,8 +288,17 @@ public:
 		uint32 generatorDepletionTime;
 	} _stoneship;
 
+	MystSaveMetadata _metadata;
+
 private:
 	void syncGameState(Common::Serializer &s, bool isME);
+	static Common::InSaveFile *openMetadataFile(const Common::String &filename);
+	bool loadState(const Common::String &filename);
+	void loadMetadata(const Common::String &filename);
+	bool saveState(const Common::String &desc);
+	void updateMetadateForSaving(const Common::String &desc);
+	bool saveMetadata(const Common::String &desc);
+	static Common::String removeExtension(const Common::String &filename);
 
 	// The values in these regions are lists of VIEW resources
 	// which correspond to visited zip destinations






More information about the Scummvm-git-logs mailing list