[Scummvm-git-logs] scummvm branch-2-8 -> 9355c6693bfb11ce4003e6acb8667568155139b8

sev- noreply at scummvm.org
Fri Dec 8 11:27:42 UTC 2023


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

Summary:
0edbea4ba9 ENGINES: Added optional parameter to canSave/LoadGameStateCurrently() for indicating the reason
735a6693d7 ENGINES: Show pop-up message for save/load in GMM and explain the reason
8a9fa51846 SCUMM: Explain to HE games players that the save/loading is not supported from GMM
b4b529df89 GLK: MAGNETIC: Explain that magnetic games save/load is not available from the GMM
65dad3186b AGI: Explain that preAGI games cannot be load or saved
f4f0ac39d0 ASYLUM: Explain that demo does not support save/load
e2fd89bc2a BURIED: Explain that demo does not support save/load
0b4d19ddfd DREAMWEB: Removing redundant methods: the game does not allow save/load from GMM
e8692001c4 MOHAWK: Riven demo does not support save/load. Message this to the user
9355c6693b PETKA: Demo does not allow save/load. Message to the user


Commit: 0edbea4ba9cb74737f2d300726cfa83fd4d0fb55
    https://github.com/scummvm/scummvm/commit/0edbea4ba9cb74737f2d300726cfa83fd4d0fb55
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:24:25+01:00

Commit Message:
ENGINES: Added optional parameter to canSave/LoadGameStateCurrently() for indicating the reason

Changed paths:
    devtools/create_engine/files/xyzzy.h
    devtools/create_engine/files_events/xyzzy.h
    engines/access/access.cpp
    engines/access/access.h
    engines/adl/adl.cpp
    engines/adl/adl.h
    engines/adl/adl_v2.cpp
    engines/adl/adl_v2.h
    engines/adl/hires6.cpp
    engines/agi/agi.h
    engines/agi/metaengine.cpp
    engines/ags/ags.cpp
    engines/ags/ags.h
    engines/asylum/asylum.cpp
    engines/asylum/asylum.h
    engines/avalanche/avalanche.cpp
    engines/avalanche/avalanche.h
    engines/bbvs/bbvs.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/buried/buried.h
    engines/buried/saveload.cpp
    engines/cge/cge.cpp
    engines/cge/cge.h
    engines/cge2/cge2.h
    engines/cge2/saveload.cpp
    engines/chamber/chamber.h
    engines/chewy/chewy.h
    engines/cine/cine.h
    engines/cine/metaengine.cpp
    engines/composer/composer.h
    engines/crab/crab.cpp
    engines/crab/crab.h
    engines/cruise/cruise.cpp
    engines/cruise/cruise.h
    engines/cryomni3d/cryomni3d.h
    engines/dm/dm.cpp
    engines/dm/dm.h
    engines/draci/draci.cpp
    engines/draci/draci.h
    engines/dragons/dragons.cpp
    engines/dragons/dragons.h
    engines/drascula/drascula.h
    engines/drascula/saveload.cpp
    engines/dreamweb/dreamweb.h
    engines/dreamweb/metaengine.cpp
    engines/efh/efh.h
    engines/efh/savegames.cpp
    engines/engine.cpp
    engines/engine.h
    engines/freescape/freescape.h
    engines/glk/comprehend/comprehend.h
    engines/glk/glk.cpp
    engines/glk/glk.h
    engines/glk/magnetic/magnetic.h
    engines/glk/quest/quest.h
    engines/griffon/griffon.h
    engines/grim/grim.h
    engines/groovie/groovie.cpp
    engines/groovie/groovie.h
    engines/hadesch/hadesch.h
    engines/hdb/hdb.h
    engines/hdb/saveload.cpp
    engines/hopkins/hopkins.cpp
    engines/hopkins/hopkins.h
    engines/hpl1/hpl1.h
    engines/hugo/hugo.cpp
    engines/hugo/hugo.h
    engines/hypno/hypno.h
    engines/illusions/illusions.h
    engines/immortal/immortal.h
    engines/kyra/kyra_v1.h
    engines/lab/lab.cpp
    engines/lab/lab.h
    engines/lure/lure.h
    engines/macventure/macventure.h
    engines/macventure/saveload.cpp
    engines/mads/mads.cpp
    engines/mads/mads.h
    engines/mm/mm1/mm1.cpp
    engines/mm/mm1/mm1.h
    engines/mm/xeen/xeen.cpp
    engines/mm/xeen/xeen.h
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/riven.cpp
    engines/mohawk/riven.h
    engines/mortevielle/mortevielle.cpp
    engines/mortevielle/mortevielle.h
    engines/mtropolis/mtropolis.h
    engines/mtropolis/saveload.cpp
    engines/mutationofjb/mutationofjb.cpp
    engines/mutationofjb/mutationofjb.h
    engines/myst3/myst3.cpp
    engines/myst3/myst3.h
    engines/nancy/nancy.cpp
    engines/nancy/nancy.h
    engines/neverhood/neverhood.h
    engines/ngi/ngi.h
    engines/pegasus/pegasus.cpp
    engines/pegasus/pegasus.h
    engines/petka/petka.h
    engines/petka/saveload.cpp
    engines/pink/pink.cpp
    engines/pink/pink.h
    engines/prince/prince.h
    engines/prince/saveload.cpp
    engines/private/private.h
    engines/queen/queen.cpp
    engines/queen/queen.h
    engines/saga/metaengine.cpp
    engines/saga/saga.h
    engines/saga2/saga2.h
    engines/sci/metaengine.cpp
    engines/sci/sci.h
    engines/scumm/saveload.cpp
    engines/scumm/scumm.h
    engines/sherlock/sherlock.cpp
    engines/sherlock/sherlock.h
    engines/sherlock/tattoo/tattoo.cpp
    engines/sherlock/tattoo/tattoo.h
    engines/sky/metaengine.cpp
    engines/sky/sky.h
    engines/stark/stark.cpp
    engines/stark/stark.h
    engines/supernova/supernova.cpp
    engines/supernova/supernova.h
    engines/sword1/metaengine.cpp
    engines/sword1/sword1.h
    engines/sword2/sword2.cpp
    engines/sword2/sword2.h
    engines/teenagent/teenagent.h
    engines/tetraedge/tetraedge.cpp
    engines/tetraedge/tetraedge.h
    engines/tinsel/metaengine.cpp
    engines/tinsel/tinsel.h
    engines/titanic/titanic.cpp
    engines/titanic/titanic.h
    engines/toltecs/toltecs.h
    engines/tony/tony.cpp
    engines/tony/tony.h
    engines/toon/toon.cpp
    engines/toon/toon.h
    engines/touche/touche.cpp
    engines/touche/touche.h
    engines/trecision/trecision.h
    engines/tsage/tsage.cpp
    engines/tsage/tsage.h
    engines/tucker/saveload.cpp
    engines/tucker/tucker.h
    engines/twine/twine.cpp
    engines/twine/twine.h
    engines/ultima/shared/engine/ultima.h
    engines/ultima/ultima8/ultima8.cpp
    engines/ultima/ultima8/ultima8.h
    engines/vcruise/vcruise.cpp
    engines/vcruise/vcruise.h
    engines/voyeur/voyeur.cpp
    engines/voyeur/voyeur.h
    engines/wage/metaengine.cpp
    engines/wage/wage.h
    engines/wintermute/wintermute.cpp
    engines/wintermute/wintermute.h
    engines/zvision/metaengine.cpp
    engines/zvision/zvision.h


diff --git a/devtools/create_engine/files/xyzzy.h b/devtools/create_engine/files/xyzzy.h
index e7bf3157932..25a2d134ea8 100644
--- a/devtools/create_engine/files/xyzzy.h
+++ b/devtools/create_engine/files/xyzzy.h
@@ -74,10 +74,10 @@ public:
 		    (f == kSupportsReturnToLauncher);
 	};
 
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 
diff --git a/devtools/create_engine/files_events/xyzzy.h b/devtools/create_engine/files_events/xyzzy.h
index fc19010ab8c..eb2cac31841 100644
--- a/devtools/create_engine/files_events/xyzzy.h
+++ b/devtools/create_engine/files_events/xyzzy.h
@@ -81,10 +81,10 @@ public:
 		    (f == kSupportsReturnToLauncher);
 	};
 
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 
diff --git a/engines/access/access.cpp b/engines/access/access.cpp
index ecc401e0a9e..29c34ea3091 100644
--- a/engines/access/access.cpp
+++ b/engines/access/access.cpp
@@ -497,11 +497,11 @@ Common::Error AccessEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool AccessEngine::canLoadGameStateCurrently() {
+bool AccessEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _canSaveLoad;
 }
 
-bool AccessEngine::canSaveGameStateCurrently() {
+bool AccessEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _canSaveLoad;
 }
 
diff --git a/engines/access/access.h b/engines/access/access.h
index a6cf8ea0861..a77a4f4ac98 100644
--- a/engines/access/access.h
+++ b/engines/access/access.h
@@ -283,12 +283,12 @@ public:
 	/**
 	 * Returns true if a savegame can currently be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	* Returns true if the game can currently be saved
 	*/
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Read in a savegame header
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 503bed68310..db900c8301c 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -929,7 +929,7 @@ Common::Error AdlEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool AdlEngine::canLoadGameStateCurrently() {
+bool AdlEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _canRestoreNow;
 }
 
@@ -1016,7 +1016,7 @@ Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc, boo
 	return Common::kNoError;
 }
 
-bool AdlEngine::canSaveGameStateCurrently() {
+bool AdlEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!_canSaveNow)
 		return false;
 
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 6ec3357fd6d..bd886d681e4 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -263,7 +263,7 @@ protected:
 	// Engine
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override;
 	int getAutosaveSlot() const override { return 15; }
 
@@ -466,7 +466,7 @@ private:
 	// Engine
 	Common::Error run() override;
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	// Text input
 	byte convertKey(uint16 ascii) const;
diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp
index 380e3bd4b24..faf4d61a465 100644
--- a/engines/adl/adl_v2.cpp
+++ b/engines/adl/adl_v2.cpp
@@ -623,13 +623,13 @@ int AdlEngine_v2::o_initDisk(ScriptEnv &e) {
 	return 0;
 }
 
-bool AdlEngine_v2::canSaveGameStateCurrently() {
+bool AdlEngine_v2::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!_canSaveNow)
 		return false;
 
 	// Back up first visit flag as it may be changed by this test
 	const bool isFirstTime = getCurRoom().isFirstTime;
-	const bool retval = AdlEngine::canSaveGameStateCurrently();
+	const bool retval = AdlEngine::canSaveGameStateCurrently(msg);
 
 	getCurRoom().isFirstTime = isFirstTime;
 
diff --git a/engines/adl/adl_v2.h b/engines/adl/adl_v2.h
index 412971e8752..04fdf39787b 100644
--- a/engines/adl/adl_v2.h
+++ b/engines/adl/adl_v2.h
@@ -47,7 +47,7 @@ protected:
 	void takeItem(byte noun) override;
 
 	// Engine
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	void mapExeStrings(const Common::StringArray &strings);
 	void insertDisk(byte volume);
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index cf317288616..7c623e1e264 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -59,7 +59,7 @@ private:
 	void printString(const Common::String &str) override;
 
 	// Engine
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	int o_fluteSound(ScriptEnv &e);
 
@@ -139,7 +139,7 @@ int HiRes6Engine::o_fluteSound(ScriptEnv &e) {
 	return 0;
 }
 
-bool HiRes6Engine::canSaveGameStateCurrently() {
+bool HiRes6Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!_canSaveNow)
 		return false;
 
@@ -148,7 +148,7 @@ bool HiRes6Engine::canSaveGameStateCurrently() {
 	const byte var24 = getVar(24);
 	const bool abortScript = _abortScript;
 
-	const bool retval = AdlEngine_v5::canSaveGameStateCurrently();
+	const bool retval = AdlEngine_v5::canSaveGameStateCurrently(msg);
 
 	setVar(2, var2);
 	setVar(24, var24);
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 3fe4c988b6a..33f2f90cb42 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -793,8 +793,8 @@ public:
 
 	const char *getDiskName(uint16 id);
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	const byte *getFontData();
 
diff --git a/engines/agi/metaengine.cpp b/engines/agi/metaengine.cpp
index dac4bc678a4..ff1a8e44f25 100644
--- a/engines/agi/metaengine.cpp
+++ b/engines/agi/metaengine.cpp
@@ -399,7 +399,7 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
 
 namespace Agi {
 
-bool AgiBase::canLoadGameStateCurrently() {
+bool AgiBase::canLoadGameStateCurrently(Common::U32String *msg) {
 	if (!(getGameType() == GType_PreAGI)) {
 		if (getFlag(VM_FLAG_MENUS_ACCESSIBLE)) {
 			if (!_noSaveLoadAllowed) {
@@ -417,7 +417,7 @@ bool AgiBase::canLoadGameStateCurrently() {
 	return false;
 }
 
-bool AgiBase::canSaveGameStateCurrently() {
+bool AgiBase::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (getGameID() == GID_BC) // Technically in Black Cauldron we may save anytime
 		return true;
 
diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index 362a1becf67..49fba50c960 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -288,12 +288,12 @@ Common::FSNode AGSEngine::getGameFolder() {
 	return Common::FSNode(ConfMan.get("path"));
 }
 
-bool AGSEngine::canLoadGameStateCurrently() {
+bool AGSEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_GP(thisroom).Options.SaveLoadDisabled &&
 	       !_G(inside_script) && !_GP(play).fast_forward && !_G(no_blocking_functions);
 }
 
-bool AGSEngine::canSaveGameStateCurrently() {
+bool AGSEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !_GP(thisroom).Options.SaveLoadDisabled &&
 	       !_G(inside_script) && !_GP(play).fast_forward && !_G(no_blocking_functions);
 }
diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index bd786b958a7..edd915381e3 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -145,12 +145,12 @@ public:
 	/**
 	 * Indicate whether a game state can be loaded.
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Indicate whether a game state can be saved.
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Load a savegame
diff --git a/engines/asylum/asylum.cpp b/engines/asylum/asylum.cpp
index efeedb6a1fd..6d37c6b7e46 100644
--- a/engines/asylum/asylum.cpp
+++ b/engines/asylum/asylum.cpp
@@ -668,13 +668,13 @@ void AsylumEngine::checkAchievements() {
 //////////////////////////////////////////////////////////////////////////
 // Save/Load
 //////////////////////////////////////////////////////////////////////////
-bool AsylumEngine::canLoadGameStateCurrently() {
+bool AsylumEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (!checkGameVersion("Demo")
 		&& (_handler == _scene || _handler == _menu)
 		&& !speech()->getSoundResourceId());
 }
 
-bool AsylumEngine::canSaveGameStateCurrently() {
+bool AsylumEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (!checkGameVersion("Demo")
 		&& (_handler == _scene)
 		&& !speech()->getSoundResourceId());
diff --git a/engines/asylum/asylum.h b/engines/asylum/asylum.h
index 733c83480c3..b5a5678c12a 100644
--- a/engines/asylum/asylum.h
+++ b/engines/asylum/asylum.h
@@ -70,8 +70,8 @@ class VideoPlayer;
 class AsylumEngine: public Engine, public Common::Serializable {
 protected:
 	// Engine APIs
-	virtual Common::Error run();
-	virtual bool hasFeature(EngineFeature f) const;
+	virtual Common::Error run() override;
+	virtual bool hasFeature(EngineFeature f) const override;
 
 public:
 	enum StartGameType {
@@ -187,7 +187,7 @@ public:
 	void updateReverseStereo();
 
 	// Serializable
-	void saveLoadWithSerializer(Common::Serializer &s);
+	void saveLoadWithSerializer(Common::Serializer &s) override;
 
 	bool checkGameVersion(const char *version) { return !strcmp(_gameDescription->extra, version); }
 	bool isAltDemo() { return Common::File::exists("asylum.dat"); }
@@ -198,12 +198,12 @@ public:
 	EventHandler *getEventHandler() { return _handler; }
 
 	// Save/Load
-	int getAutosaveSlot() const { return getMetaEngine()->getAutosaveSlot(); }
-	bool canLoadGameStateCurrently();
-	Common::Error loadGameState(int slot);
-	bool canSaveGameStateCurrently();
-	bool canSaveAutosaveCurrently();
-	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false);
+	int getAutosaveSlot() const override { return getMetaEngine()->getAutosaveSlot(); }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	Common::Error loadGameState(int slot) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveAutosaveCurrently() override;
+	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
 private:
 	const ADGameDescription *_gameDescription;
diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp
index 9851a7ec00b..2607d418ac0 100644
--- a/engines/avalanche/avalanche.cpp
+++ b/engines/avalanche/avalanche.cpp
@@ -325,7 +325,7 @@ void AvalancheEngine::synchronize(Common::Serializer &sz) {
 
 }
 
-bool AvalancheEngine::canSaveGameStateCurrently() {
+bool AvalancheEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (_animationsEnabled && _alive);
 }
 
@@ -366,7 +366,7 @@ bool AvalancheEngine::saveGame(const int16 slot, const Common::String &desc) {
 	return true;
 }
 
-bool AvalancheEngine::canLoadGameStateCurrently() {
+bool AvalancheEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (_animationsEnabled);
 }
 
diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h
index a6e9e34d603..e22f7a38cd5 100644
--- a/engines/avalanche/avalanche.h
+++ b/engines/avalanche/avalanche.h
@@ -106,10 +106,10 @@ public:
 	const char *getCopyrightString() const;
 
 	void synchronize(Common::Serializer &sz);
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	bool saveGame(const int16 slot, const Common::String &desc);
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	bool loadGame(const int16 slot);
 	Common::String expandDate(int d, int m, int y);
diff --git a/engines/bbvs/bbvs.h b/engines/bbvs/bbvs.h
index 9a78eda655f..468fa76c8e1 100644
--- a/engines/bbvs/bbvs.h
+++ b/engines/bbvs/bbvs.h
@@ -435,8 +435,8 @@ public:
 
 	bool _isSaveAllowed;
 
-	bool canLoadGameStateCurrently() override { return _isSaveAllowed; }
-	bool canSaveGameStateCurrently() override { return _isSaveAllowed; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &description, bool isAutosave = false) override;
 	void savegame(const char *filename, const char *description);
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 8fece8e1ec9..a62c825da23 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -267,7 +267,7 @@ bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
 		f == kSupportsSavingDuringRuntime;
 }
 
-bool BladeRunnerEngine::canLoadGameStateCurrently() {
+bool BladeRunnerEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return
 		playerHasControl() &&
 		_gameIsRunning &&
@@ -307,7 +307,7 @@ Common::Error BladeRunnerEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool BladeRunnerEngine::canSaveGameStateCurrently() {
+bool BladeRunnerEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return
 		playerHasControl() &&
 		_gameIsRunning &&
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index cd217d6c7ec..e713f33a13a 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -349,9 +349,9 @@ public:
 	~BladeRunnerEngine() override;
 
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	/**
 	* NOTE: Disable support for external autosave (ScummVM's feature).
diff --git a/engines/buried/buried.h b/engines/buried/buried.h
index 2443b7010b8..52296a21774 100644
--- a/engines/buried/buried.h
+++ b/engines/buried/buried.h
@@ -142,8 +142,8 @@ public:
 	void showPoints();
 
 	// Save/Load
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override {
 		return Common::String::format("buried.%03d", slot);
 	}
diff --git a/engines/buried/saveload.cpp b/engines/buried/saveload.cpp
index 9f732a5c26d..71101f523d7 100644
--- a/engines/buried/saveload.cpp
+++ b/engines/buried/saveload.cpp
@@ -47,11 +47,11 @@ namespace Buried {
 
 #define SAVEGAME_CURRENT_VERSION 1
 
-bool BuriedEngine::canLoadGameStateCurrently() {
+bool BuriedEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !isDemo() && _mainWindow && !_yielding;
 }
 
-bool BuriedEngine::canSaveGameStateCurrently() {
+bool BuriedEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !isDemo() && _mainWindow && !_yielding && ((FrameWindow *)_mainWindow)->isGameInProgress();
 }
 
diff --git a/engines/cge/cge.cpp b/engines/cge/cge.cpp
index 21a14f36ac9..b5f2b7592a3 100644
--- a/engines/cge/cge.cpp
+++ b/engines/cge/cge.cpp
@@ -246,11 +246,11 @@ bool CGEEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-bool CGEEngine::canLoadGameStateCurrently() {
+bool CGEEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (_startupMode == 0) && _mouse->_active;
 }
 
-bool CGEEngine::canSaveGameStateCurrently() {
+bool CGEEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (_startupMode == 0) && _mouse->_active &&
 				_commandHandler->idle() && !_hero->_flags._hide;
 }
diff --git a/engines/cge/cge.h b/engines/cge/cge.h
index de538c923ad..985cffc1ae9 100644
--- a/engines/cge/cge.h
+++ b/engines/cge/cge.h
@@ -136,8 +136,8 @@ public:
 	CGEEngine(OSystem *syst, const ADGameDescription *gameDescription);
 	~CGEEngine() override;
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
index 0d7742f0237..672feb532e9 100644
--- a/engines/cge2/cge2.h
+++ b/engines/cge2/cge2.h
@@ -154,8 +154,8 @@ private:
 public:
 	CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription);
 	bool hasFeature(EngineFeature f) const override;
-	bool canSaveGameStateCurrently() override;
-	bool canLoadGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Language getLanguage() const;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error loadGameState(int slot) override;
diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp
index 53409640e11..ffaddde0286 100644
--- a/engines/cge2/saveload.cpp
+++ b/engines/cge2/saveload.cpp
@@ -41,7 +41,7 @@ namespace CGE2 {
 #define kSavegameCheckSum (1997 + _now + _sex + kWorldHeight)
 #define kBadSVG           99
 
-bool CGE2Engine::canSaveGameStateCurrently() {
+bool CGE2Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (_gamePhase == kPhaseInGame) && _mouse->_active &&
 		_commandHandler->idle() && (_soundStat._wait == nullptr);
 }
@@ -73,7 +73,7 @@ void CGE2Engine::saveGame(int slotNumber, const Common::String &desc) {
 	delete saveFile;
 }
 
-bool CGE2Engine::canLoadGameStateCurrently() {
+bool CGE2Engine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (_gamePhase == kPhaseInGame) && _mouse->_active;
 }
 
diff --git a/engines/chamber/chamber.h b/engines/chamber/chamber.h
index 1b68026754f..ea55d194afd 100644
--- a/engines/chamber/chamber.h
+++ b/engines/chamber/chamber.h
@@ -49,8 +49,8 @@ public:
 
 	Common::Error run() override;
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override { return true; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 	void syncGameStream(Common::Serializer &s);
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 6c0741512f6..4517ed0f1a9 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -82,10 +82,10 @@ public:
 	uint32 getFeatures() const;
 	Common::Language getLanguage() const;
 
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return _canLoad;
 	}
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return _canSave;
 	}
 	void setCanLoadSave(bool canLoadSave) {
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index b567e1f299f..c7760ecda90 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -126,8 +126,8 @@ public:
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::String getSaveStateName(int slot) const override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	const CINEGameDescription *_gameDescription;
 	Common::File _partFileHandle;
diff --git a/engines/cine/metaengine.cpp b/engines/cine/metaengine.cpp
index b6bf983af78..97de7741d40 100644
--- a/engines/cine/metaengine.cpp
+++ b/engines/cine/metaengine.cpp
@@ -340,11 +340,11 @@ Common::String CineEngine::getSaveStateName(int slot) const {
 	return getMetaEngine()->getSavegameFile(slot, _targetName.c_str());
 }
 
-bool CineEngine::canLoadGameStateCurrently() {
+bool CineEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (!disableSystemMenu && !inMenu);
 }
 
-bool CineEngine::canSaveGameStateCurrently() {
+bool CineEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (allowPlayerInput && !disableSystemMenu && !inMenu);
 }
 
diff --git a/engines/composer/composer.h b/engines/composer/composer.h
index 47cc1b2ea71..22e86a734fc 100644
--- a/engines/composer/composer.h
+++ b/engines/composer/composer.h
@@ -153,9 +153,9 @@ protected:
 	void syncListReverse(Common::Serializer &ser, Common::List<T> &data, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion);
 	template <typename T>
 	void sync(Common::Serializer &ser, T &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion);
-	bool canLoadGameStateCurrently() override { return true; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	Common::Error loadGameState(int slot) override;
-	bool canSaveGameStateCurrently() override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
 public:
diff --git a/engines/crab/crab.cpp b/engines/crab/crab.cpp
index 06c89dccfb1..8f07ec2535d 100644
--- a/engines/crab/crab.cpp
+++ b/engines/crab/crab.cpp
@@ -179,7 +179,7 @@ Common::Error CrabEngine::syncGame(Common::Serializer &s) {
 	return Common::kNoError;
 }
 
-bool CrabEngine::canSaveGameStateCurrently() {
+bool CrabEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _screenSettings->_inGame;
 }
 
diff --git a/engines/crab/crab.h b/engines/crab/crab.h
index da7d6560255..a6ecb79b4f3 100644
--- a/engines/crab/crab.h
+++ b/engines/crab/crab.h
@@ -152,11 +152,11 @@ public:
 			   (f == kSupportsReturnToLauncher);
 	};
 
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Uses a serializer to allow implementing savegame
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index 44ee391e421..e5c471cdbba 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -200,7 +200,7 @@ Common::Error CruiseEngine::loadGameState(int slot) {
 	return loadSavegameData(slot);
 }
 
-bool CruiseEngine::canLoadGameStateCurrently() {
+bool CruiseEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return playerMenuEnabled != 0;
 }
 
@@ -208,7 +208,7 @@ Common::Error CruiseEngine::saveGameState(int slot, const Common::String &desc,
 	return saveSavegameData(slot, desc);
 }
 
-bool CruiseEngine::canSaveGameStateCurrently() {
+bool CruiseEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (playerMenuEnabled != 0) && (userEnabled != 0);
 }
 
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index 329ab426b80..43b13edab74 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -92,9 +92,9 @@ public:
 
 	static const char *getSavegameFile(int saveGameIdx);
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override { return getSavegameFile(slot); }
 	void syncSoundSettings() override;
 
diff --git a/engines/cryomni3d/cryomni3d.h b/engines/cryomni3d/cryomni3d.h
index 56f118827a4..4f4d772603f 100644
--- a/engines/cryomni3d/cryomni3d.h
+++ b/engines/cryomni3d/cryomni3d.h
@@ -95,8 +95,8 @@ public:
 	Common::Language getLanguage() const;
 
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override { return _canLoadSave; }
-	bool canSaveGameStateCurrently() override { return _canLoadSave; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _canLoadSave; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _canLoadSave; }
 
 	void setCanLoadSave(bool canLoadSave) { _canLoadSave = canLoadSave; }
 	static const uint kSaveDescriptionLen = 20;
diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp
index 79038fe7b49..dde1e37889c 100644
--- a/engines/dm/dm.cpp
+++ b/engines/dm/dm.cpp
@@ -226,7 +226,7 @@ Common::Error DMEngine::loadGameState(int slot) {
 	return Common::kNoGameDataFoundError;
 }
 
-bool DMEngine::canLoadGameStateCurrently() {
+bool DMEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _canLoadFromGMM;
 }
 
diff --git a/engines/dm/dm.h b/engines/dm/dm.h
index f1e52caca3a..1d972239862 100644
--- a/engines/dm/dm.h
+++ b/engines/dm/dm.h
@@ -175,7 +175,7 @@ public:
 	bool hasFeature(EngineFeature f) const override;
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	bool isDemo() const;
 
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index 4da99b66b4c..96e1a71020b 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -452,7 +452,7 @@ Common::Error DraciEngine::loadGameState(int slot) {
 	return loadSavegameData(slot, this);
 }
 
-bool DraciEngine::canLoadGameStateCurrently() {
+bool DraciEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (_game->getLoopStatus() == kStatusOrdinary) &&
 		(_game->getLoopSubstatus() == kOuterLoop);
 }
@@ -461,7 +461,7 @@ Common::Error DraciEngine::saveGameState(int slot, const Common::String &desc, b
 	return saveSavegameData(slot, desc, *this);
 }
 
-bool DraciEngine::canSaveGameStateCurrently() {
+bool DraciEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (_game->getLoopStatus() == kStatusOrdinary) &&
 		(_game->getLoopSubstatus() == kOuterLoop);
 }
diff --git a/engines/draci/draci.h b/engines/draci/draci.h
index 71c3e3a9972..105a7b84ecc 100644
--- a/engines/draci/draci.h
+++ b/engines/draci/draci.h
@@ -69,9 +69,9 @@ public:
 	static Common::String getSavegameFile(int saveGameIdx);
 	Common::String getSaveStateName(int slot) const override { return getSavegameFile(slot); }
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	Screen *_screen;
 	Mouse *_mouse;
diff --git a/engines/dragons/dragons.cpp b/engines/dragons/dragons.cpp
index 3eabac51abe..af79d9e3d99 100644
--- a/engines/dragons/dragons.cpp
+++ b/engines/dragons/dragons.cpp
@@ -1230,12 +1230,12 @@ void DragonsEngine::reset_screen_maybe() {
 	//TODO
 }
 
-bool DragonsEngine::canLoadGameStateCurrently() {
+bool DragonsEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	//player has control and not currently talking to anyone.
 	return isInputEnabled() && isFlagSet(ENGINE_FLAG_8) && !isFlagSet(Dragons::ENGINE_FLAG_100);
 }
 
-bool DragonsEngine::canSaveGameStateCurrently() {
+bool DragonsEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return isInputEnabled() && !_inventory->isOpen() && isFlagSet(ENGINE_FLAG_8) && !isFlagSet(Dragons::ENGINE_FLAG_100);
 }
 
diff --git a/engines/dragons/dragons.h b/engines/dragons/dragons.h
index 44e47aea442..d61662b31cb 100644
--- a/engines/dragons/dragons.h
+++ b/engines/dragons/dragons.h
@@ -256,9 +256,9 @@ public:
 	static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail = true);
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	void syncSoundSettings() override;
 
 	void updateActorSequences();
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index 8aa41f56db9..fbddd5cfb95 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -325,9 +325,9 @@ public:
 	void syncSoundSettings() override;
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	Common::RandomSource *_rnd;
 	const DrasculaGameDescription *_gameDescription;
diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp
index 2c9d6ddaffc..9f4ee26536b 100644
--- a/engines/drascula/saveload.cpp
+++ b/engines/drascula/saveload.cpp
@@ -194,7 +194,7 @@ Common::Error DrasculaEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool DrasculaEngine::canLoadGameStateCurrently() {
+bool DrasculaEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _canSaveLoad;
 }
 
@@ -203,7 +203,7 @@ Common::Error DrasculaEngine::saveGameState(int slot, const Common::String &desc
 	return Common::kNoError;
 }
 
-bool DrasculaEngine::canSaveGameStateCurrently() {
+bool DrasculaEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _canSaveLoad;
 }
 
diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index fd53d14a9a5..5f3d7a654dc 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -119,8 +119,8 @@ public:
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	uint8 randomNumber() { return _rnd.getRandomNumber(255); }
 
diff --git a/engines/dreamweb/metaengine.cpp b/engines/dreamweb/metaengine.cpp
index 77eb5b1c4cc..a4950c59baa 100644
--- a/engines/dreamweb/metaengine.cpp
+++ b/engines/dreamweb/metaengine.cpp
@@ -251,11 +251,11 @@ Common::Error DreamWebEngine::saveGameState(int slot, const Common::String &desc
 	return Common::kNoError;
 }
 
-bool DreamWebEngine::canLoadGameStateCurrently() {
+bool DreamWebEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return false;
 }
 
-bool DreamWebEngine::canSaveGameStateCurrently() {
+bool DreamWebEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return false;
 }
 
diff --git a/engines/efh/efh.h b/engines/efh/efh.h
index 240835283e5..aa944792542 100644
--- a/engines/efh/efh.h
+++ b/engines/efh/efh.h
@@ -277,8 +277,8 @@ public:
 
 	// savegames.cpp
 	Common::String getSavegameFilename(int slot);
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
diff --git a/engines/efh/savegames.cpp b/engines/efh/savegames.cpp
index bd4160efe2b..0dee11838fe 100644
--- a/engines/efh/savegames.cpp
+++ b/engines/efh/savegames.cpp
@@ -33,11 +33,11 @@ Common::String EfhEngine::getSavegameFilename(int slot) {
 	return _targetName + Common::String::format("-%03d.SAV", slot);
 }
 
-bool EfhEngine::canLoadGameStateCurrently() {
+bool EfhEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
-bool EfhEngine::canSaveGameStateCurrently() {
+bool EfhEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _saveAuthorized;
 }
 
diff --git a/engines/engine.cpp b/engines/engine.cpp
index e7da04a8b3f..e94a92bc0bb 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -874,7 +874,7 @@ Common::Error Engine::loadGameStream(Common::SeekableReadStream *stream) {
 	return Common::kReadingFailed;
 }
 
-bool Engine::canLoadGameStateCurrently() {
+bool Engine::canLoadGameStateCurrently(Common::U32String *msg) {
 	// Do not allow loading by default
 	return false;
 }
@@ -901,7 +901,7 @@ Common::Error Engine::saveGameStream(Common::WriteStream *stream, bool isAutosav
 	return Common::kWritingFailed;
 }
 
-bool Engine::canSaveGameStateCurrently() {
+bool Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// Do not allow saving by default
 	return false;
 }
diff --git a/engines/engine.h b/engines/engine.h
index e2d1e6e1a86..ade46d5fd9b 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -444,8 +444,10 @@ public:
 
 	/**
 	 * Indicate whether a game state can be loaded.
+	 *
+	 * @param msg        Optional pointer to message explaining why it is disabled
 	 */
-	virtual bool canLoadGameStateCurrently();
+	virtual bool canLoadGameStateCurrently(Common::U32String *msg = nullptr);
 
 	/**
 	 * Save a game state.
@@ -470,8 +472,10 @@ public:
 
 	/**
 	 * Indicate whether a game state can be saved.
+	 *
+	 * @param msg        Optional pointer to message explaining why it is disabled
 	 */
-	virtual bool canSaveGameStateCurrently();
+	virtual bool canSaveGameStateCurrently(Common::U32String *msg = nullptr);
 
 	/**
 	 * Show the ScummVM save dialog, allowing users to save their game.
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index c59ef03dac4..e88cceeb846 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -411,9 +411,9 @@ public:
 	void takeDamageFromSensor();
 
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override { return true; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	bool canSaveAutosaveCurrently() override { return false; }
-	bool canSaveGameStateCurrently() override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 	virtual Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false);
diff --git a/engines/glk/comprehend/comprehend.h b/engines/glk/comprehend/comprehend.h
index 311fdc6450c..526dc5036c0 100644
--- a/engines/glk/comprehend/comprehend.h
+++ b/engines/glk/comprehend/comprehend.h
@@ -195,14 +195,14 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return !_disableSaves && GlkAPI::canLoadGameStateCurrently();
 	}
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return !_disableSaves && GlkAPI::canSaveGameStateCurrently();
 	}
 
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 572b8ed2971..1a2af57355a 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -151,13 +151,13 @@ Common::Error GlkEngine::run() {
 	return Common::kNoError;
 }
 
-bool GlkEngine::canLoadGameStateCurrently() {
+bool GlkEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	// Only allow savegames by default when sub-engines are waiting for a line
 	Window *win = _windows->getFocusWindow();
 	return win && (win->_lineRequest || win->_lineRequestUni);
 }
 
-bool GlkEngine::canSaveGameStateCurrently() {
+bool GlkEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// Only allow savegames by default when sub-engines are waiting for a line
 	Window *win = _windows->getFocusWindow();
 	return win && (win->_lineRequest || win->_lineRequestUni);
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index fa64e16a312..805686eb693 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -137,12 +137,12 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Returns the language
diff --git a/engines/glk/magnetic/magnetic.h b/engines/glk/magnetic/magnetic.h
index d7814ee92e1..b2966b89c80 100644
--- a/engines/glk/magnetic/magnetic.h
+++ b/engines/glk/magnetic/magnetic.h
@@ -1385,14 +1385,14 @@ public:
 	/**
 	 * The Magnetic engine currently doesn't support loading savegames from the GMM
 	 */
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return false;
 	}
 
 	/**
 	 * The Magnetic engine currently doesn't support saving games from the GMM
 	 */
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return false;
 	}
 
diff --git a/engines/glk/quest/quest.h b/engines/glk/quest/quest.h
index 780c29c9929..f1ce36d957f 100644
--- a/engines/glk/quest/quest.h
+++ b/engines/glk/quest/quest.h
@@ -76,14 +76,14 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return _runner != nullptr && GlkAPI::canLoadGameStateCurrently();
 	}
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return _runner != nullptr && GlkAPI::canLoadGameStateCurrently();
 	}
 
diff --git a/engines/griffon/griffon.h b/engines/griffon/griffon.h
index 195791c54f2..bc95ab95688 100644
--- a/engines/griffon/griffon.h
+++ b/engines/griffon/griffon.h
@@ -444,8 +444,8 @@ private:
 
 	// Common engine overrides
 	void pauseEngineIntern(bool pause) override;
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override { return _gameMode == kGameModePlay; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _gameMode == kGameModePlay; }
 	int getAutosaveSlot() const override { return 4; }
 	bool hasFeature(EngineFeature f) const override;
 
diff --git a/engines/grim/grim.h b/engines/grim/grim.h
index 4263c12cb00..c71b3c13a1f 100644
--- a/engines/grim/grim.h
+++ b/engines/grim/grim.h
@@ -85,7 +85,7 @@ public:
 	Common::Language getGameLanguage() { return _gameLanguage; }
 	Common::Platform getGamePlatform() { return _gamePlatform; }
 	virtual const char *getUpdateFilename();
-	bool canLoadGameStateCurrently() override { return true; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	Common::Error loadGameState(int slot) override;
 	bool isRemastered() const { return !!(_gameFlags & ADGF_REMASTERED); }
 
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 3a789c57711..f9688ce2b9b 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -397,7 +397,7 @@ void GroovieEngine::syncSoundSettings() {
 		mute ? 0 : ConfMan.getInt("speech_volume"));
 }
 
-bool GroovieEngine::canLoadGameStateCurrently() {
+bool GroovieEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	// TODO: verify the engine has been initialized
 	if (isDemo())
 		return false;
@@ -407,7 +407,7 @@ bool GroovieEngine::canLoadGameStateCurrently() {
 		return false;
 }
 
-bool GroovieEngine::canSaveGameStateCurrently() {
+bool GroovieEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// TODO: verify the engine has been initialized
 	if (isDemo())
 		return false;
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index b22864830e3..7e4aa980da6 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -132,8 +132,8 @@ protected:
 
 	bool hasFeature(EngineFeature f) const override;
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void syncSoundSettings() override;
diff --git a/engines/hadesch/hadesch.h b/engines/hadesch/hadesch.h
index d1f31adcece..ce842d2093f 100644
--- a/engines/hadesch/hadesch.h
+++ b/engines/hadesch/hadesch.h
@@ -113,8 +113,8 @@ public:
 
 	bool hasFeature(EngineFeature f) const override;
 
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override { return _persistent._currentRoomId != 0; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _persistent._currentRoomId != 0; }
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 
diff --git a/engines/hdb/hdb.h b/engines/hdb/hdb.h
index 487cffe0e8b..7c2eccc0661 100644
--- a/engines/hdb/hdb.h
+++ b/engines/hdb/hdb.h
@@ -209,8 +209,8 @@ public:
 
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	void saveGame(Common::OutSaveFile *out);
 	void loadGame(Common::InSaveFile *in);
 
diff --git a/engines/hdb/saveload.cpp b/engines/hdb/saveload.cpp
index 96976b74603..db121700067 100644
--- a/engines/hdb/saveload.cpp
+++ b/engines/hdb/saveload.cpp
@@ -31,7 +31,7 @@
 
 namespace HDB {
 
-bool HDBGame::canSaveGameStateCurrently() {
+bool HDBGame::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (_gameState == GAME_PLAY && !_ai->cinematicsActive());
 }
 
@@ -82,7 +82,7 @@ Common::Error HDBGame::saveGameState(int slot, const Common::String &desc, bool
 	return Common::kNoError;
 }
 
-bool HDBGame::canLoadGameStateCurrently() {
+bool HDBGame::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _gameState == GAME_PLAY;
 }
 
diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp
index e6127879c20..cc341e5f7a5 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -77,14 +77,14 @@ HopkinsEngine::~HopkinsEngine() {
 /**
  * Returns true if it is currently okay to restore a game
  */
-bool HopkinsEngine::canLoadGameStateCurrently() {
+bool HopkinsEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl && _globals->_curRoomNum != 0;
 }
 
 /**
  * Returns true if it is currently okay to save the game
  */
-bool HopkinsEngine::canSaveGameStateCurrently() {
+bool HopkinsEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl
 		&& _globals->_curRoomNum != 0 && !isUnderwaterSubScene();
 }
diff --git a/engines/hopkins/hopkins.h b/engines/hopkins/hopkins.h
index aa3b3a3d280..ac098a64450 100644
--- a/engines/hopkins/hopkins.h
+++ b/engines/hopkins/hopkins.h
@@ -160,8 +160,8 @@ public:
 	const Common::String &getTargetName() const;
 
 	int getRandomNumber(int maxNumber);
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
diff --git a/engines/hpl1/hpl1.h b/engines/hpl1/hpl1.h
index 8c9019c5562..afc9c901752 100644
--- a/engines/hpl1/hpl1.h
+++ b/engines/hpl1/hpl1.h
@@ -82,7 +82,7 @@ public:
 			   (f == kSupportsArbitraryResolutions);
 	};
 
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index b158d4927e6..e6d246d0082 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -713,11 +713,11 @@ void HugoEngine::endGame() {
 	_status._viewState = kViewExit;
 }
 
-bool HugoEngine::canLoadGameStateCurrently() {
+bool HugoEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
-bool HugoEngine::canSaveGameStateCurrently() {
+bool HugoEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (_status._viewState == kViewPlay);
 }
 
diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h
index ee5f6df3a25..d9863086c4d 100644
--- a/engines/hugo/hugo.h
+++ b/engines/hugo/hugo.h
@@ -238,8 +238,8 @@ public:
 		return *s_Engine;
 	}
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	bool loadHugoDat();
 
 	int8 getTPS() const;
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index a507a1e0317..cb55a31cad4 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -144,9 +144,9 @@ public:
 	bool cursorMask(Common::Point);
 
 	virtual void loadGame(const Common::String &nextLevel, int score, int puzzleDifficulty, int combatDifficulty);
-	bool canLoadGameStateCurrently() override { return (isDemo() ? false : true); }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return (isDemo() ? false : true); }
 	bool canSaveAutosaveCurrently() override { return false; }
-	bool canSaveGameStateCurrently() override { return (isDemo() ? false : true); }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return (isDemo() ? false : true); }
 	Common::String _checkpoint;
 
 	Common::String _prefixDir;
diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h
index eba3b592814..7b7771ace37 100644
--- a/engines/illusions/illusions.h
+++ b/engines/illusions/illusions.h
@@ -221,8 +221,8 @@ public:
 
 	bool _isSaveAllowed;
 
-	bool canLoadGameStateCurrently() override { return _isSaveAllowed; }
-	bool canSaveGameStateCurrently() override { return _isSaveAllowed; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error removeGameState(int slot);
diff --git a/engines/immortal/immortal.h b/engines/immortal/immortal.h
index 672f656a903..cce7511db0a 100644
--- a/engines/immortal/immortal.h
+++ b/engines/immortal/immortal.h
@@ -745,10 +745,10 @@ public:
 		    (f == kSupportsReturnToLauncher);
 	};
 
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 0270af6a70c..c6e7c0d9a5c 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -356,8 +356,8 @@ protected:
 
 	bool _isSaveAllowed;
 
-	bool canLoadGameStateCurrently() override { return _isSaveAllowed; }
-	bool canSaveGameStateCurrently() override { return _isSaveAllowed; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
 	int getAutosaveSlot() const override { return 999; }
 
 	const char *getSavegameFilename(int num);
diff --git a/engines/lab/lab.cpp b/engines/lab/lab.cpp
index 4de34f08ce7..0f2f2dd4766 100644
--- a/engines/lab/lab.cpp
+++ b/engines/lab/lab.cpp
@@ -213,11 +213,11 @@ Common::Error LabEngine::saveGameState(int slot, const Common::String &desc, boo
 	return (result) ? Common::kNoError : Common::kUserCanceled;
 }
 
-bool LabEngine::canLoadGameStateCurrently() {
+bool LabEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_introPlaying;
 }
 
-bool LabEngine::canSaveGameStateCurrently() {
+bool LabEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !_introPlaying;
 }
 
diff --git a/engines/lab/lab.h b/engines/lab/lab.h
index f3be0394bb0..3a065fd162b 100644
--- a/engines/lab/lab.h
+++ b/engines/lab/lab.h
@@ -222,8 +222,8 @@ public:
 
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	bool isMainDisplay() const { return _mainDisplay; }
 
diff --git a/engines/lure/lure.h b/engines/lure/lure.h
index 47176867bac..32c08214526 100644
--- a/engines/lure/lure.h
+++ b/engines/lure/lure.h
@@ -129,10 +129,10 @@ public:
 		Common::String s(desc);
 		return saveGame(slot, s) ? Common::kNoError : Common::kReadingFailed;
 	}
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return _saveLoadAllowed && !Fights.isFighting();
 	}
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return _saveLoadAllowed && !Fights.isFighting();
 	}
 };
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 663a25c6f62..2417cf8828f 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -193,8 +193,8 @@ public:
 	Common::Error run() override;
 
 	bool scummVMSaveLoadDialog(bool isSave);
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void newGame();
diff --git a/engines/macventure/saveload.cpp b/engines/macventure/saveload.cpp
index 93e70085a86..1b18756fe06 100644
--- a/engines/macventure/saveload.cpp
+++ b/engines/macventure/saveload.cpp
@@ -196,11 +196,11 @@ bool MacVentureEngine::scummVMSaveLoadDialog(bool isSave) {
 	return saveGameState(slot, desc).getCode() == Common::kNoError;
 }
 
-bool MacVentureEngine::canLoadGameStateCurrently() {
+bool MacVentureEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
-bool MacVentureEngine::canSaveGameStateCurrently() {
+bool MacVentureEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index a7403547815..be5ece8e27b 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -185,13 +185,13 @@ int MADSEngine::getRandomNumber(int minNumber, int maxNumber) {
 	return minNumber + _randomSource.getRandomNumber(range);
 }
 
-bool MADSEngine::canLoadGameStateCurrently() {
+bool MADSEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_game->_winStatus && !_game->globals()[5]
 		&& _dialogs->_pendingDialog == DIALOG_NONE
 		&& _events->_cursorId != CURSOR_WAIT;
 }
 
-bool MADSEngine::canSaveGameStateCurrently() {
+bool MADSEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !_game->_winStatus && !_game->globals()[5]
 		&& _dialogs->_pendingDialog == DIALOG_NONE
 		&& _events->_cursorId != CURSOR_WAIT
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
index bcca576750b..1971f2120b2 100644
--- a/engines/mads/mads.h
+++ b/engines/mads/mads.h
@@ -121,12 +121,12 @@ public:
 	/**
 	* Returns true if it is currently okay to restore a game
 	*/
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	* Returns true if it is currently okay to save the game
 	*/
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Handles loading a game via the GMM
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index f0149e3144c..36d31712732 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -138,7 +138,7 @@ bool MM1Engine::setupEnhanced() {
 	return true;
 }
 
-bool MM1Engine::canSaveGameStateCurrently() {
+bool MM1Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!g_events)
 		return false;
 
@@ -147,7 +147,7 @@ bool MM1Engine::canSaveGameStateCurrently() {
 		dynamic_cast<ViewsEnh::Game *>(view) != nullptr;
 }
 
-bool MM1Engine::canLoadGameStateCurrently() {
+bool MM1Engine::canLoadGameStateCurrently(Common::U32String *msg) {
 	if (!g_events)
 		return false;
 
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index c24f0ea9231..cf55ef0c901 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -85,12 +85,12 @@ public:
 	/**
 	 * Returns true if a game can be saved
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Saves or loads a savegame
diff --git a/engines/mm/xeen/xeen.cpp b/engines/mm/xeen/xeen.cpp
index 1799a4195e3..17aefa70438 100644
--- a/engines/mm/xeen/xeen.cpp
+++ b/engines/mm/xeen/xeen.cpp
@@ -188,11 +188,11 @@ Common::Error XeenEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool XeenEngine::canLoadGameStateCurrently() {
+bool XeenEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _mode != MODE_STARTUP;
 }
 
-bool XeenEngine::canSaveGameStateCurrently() {
+bool XeenEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _mode != MODE_COMBAT && _mode != MODE_STARTUP && _mode != MODE_SCRIPT_IN_PROGRESS
 		&& (_map->mazeData()._mazeFlags & RESTRICTION_SAVE) == 0;
 }
diff --git a/engines/mm/xeen/xeen.h b/engines/mm/xeen/xeen.h
index b86f047cf5d..aede957108c 100644
--- a/engines/mm/xeen/xeen.h
+++ b/engines/mm/xeen/xeen.h
@@ -244,12 +244,12 @@ public:
 	/**
 	 * Returns true if a savegame can currently be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	* Returns true if the game can currently be saved
 	*/
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	* Returns true if an autosave can be created
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index b613cc6ea1d..24b9424546b 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -1080,7 +1080,7 @@ bool MohawkEngine_Myst::isInteractive() const {
 	return !_stack->isScriptRunning() && !_waitingOnBlockingOperation;
 }
 
-bool MohawkEngine_Myst::canLoadGameStateCurrently() {
+bool MohawkEngine_Myst::canLoadGameStateCurrently(Common::U32String *msg) {
 	bool isInMenu = _stack->getStackId() == kMenuStack;
 
 	if (!isInMenu) {
@@ -1101,7 +1101,7 @@ bool MohawkEngine_Myst::canLoadGameStateCurrently() {
 	return true;
 }
 
-bool MohawkEngine_Myst::canSaveGameStateCurrently() {
+bool MohawkEngine_Myst::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!canLoadGameStateCurrently()) {
 		return false;
 	}
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index eccc134223b..be0a30870ba 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -188,8 +188,8 @@ public:
 	 */
 	bool isInteractive() const;
 	bool isGameStarted() const;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::String getSaveStateName(int slot) const override {
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 8118b22c927..9ffcd45d958 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -753,7 +753,7 @@ bool MohawkEngine_Riven::isZipVisitedCard(const Common::String &hotspotName) con
 	return foundMatch;
 }
 
-bool MohawkEngine_Riven::canLoadGameStateCurrently() {
+bool MohawkEngine_Riven::canLoadGameStateCurrently(Common::U32String *msg) {
 	if (isGameVariant(GF_DEMO)) {
 		return false;
 	}
@@ -765,7 +765,7 @@ bool MohawkEngine_Riven::canLoadGameStateCurrently() {
 	return true;
 }
 
-bool MohawkEngine_Riven::canSaveGameStateCurrently() {
+bool MohawkEngine_Riven::canSaveGameStateCurrently(Common::U32String *msg) {
 	return canLoadGameStateCurrently() && isGameStarted();
 }
 
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 864f71af899..b6dc753fb55 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -106,8 +106,8 @@ public:
 	// Display debug rectangles around the hotspots
 	bool _showHotspots;
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::String getSaveStateName(int slot) const override {
diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp
index e7f9c992e46..97270b413ee 100644
--- a/engines/mortevielle/mortevielle.cpp
+++ b/engines/mortevielle/mortevielle.cpp
@@ -176,7 +176,7 @@ bool MortevielleEngine::hasFeature(EngineFeature f) const {
 /**
  * Return true if a game can currently be loaded
  */
-bool MortevielleEngine::canLoadGameStateCurrently() {
+bool MortevielleEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	// Saving is only allowed in the main game event loop
 	return _inMainGameLoop;
 }
@@ -184,7 +184,7 @@ bool MortevielleEngine::canLoadGameStateCurrently() {
 /**
  * Return true if a game can currently be saved
  */
-bool MortevielleEngine::canSaveGameStateCurrently() {
+bool MortevielleEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// Loading is only allowed in the main game event loop
 	return _inMainGameLoop;
 }
diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h
index 385ab6f90b3..75957067416 100644
--- a/engines/mortevielle/mortevielle.h
+++ b/engines/mortevielle/mortevielle.h
@@ -432,8 +432,8 @@ public:
 	MortevielleEngine(OSystem *system, const MortevielleGameDescription *gameDesc);
 	~MortevielleEngine() override;
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error run() override;
diff --git a/engines/mtropolis/mtropolis.h b/engines/mtropolis/mtropolis.h
index ecdaa64fdb8..eb54054c368 100644
--- a/engines/mtropolis/mtropolis.h
+++ b/engines/mtropolis/mtropolis.h
@@ -73,7 +73,7 @@ public:
 
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave) override;
 	bool canSaveAutosaveCurrently() override;
-	bool canSaveGameStateCurrently() override;	
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;	
 
 public:
 	void handleEvents();
diff --git a/engines/mtropolis/saveload.cpp b/engines/mtropolis/saveload.cpp
index a48106fe96d..fdf56393680 100644
--- a/engines/mtropolis/saveload.cpp
+++ b/engines/mtropolis/saveload.cpp
@@ -252,7 +252,7 @@ bool MTropolisEngine::canSaveAutosaveCurrently() {
 	return canSaveGameStateCurrently();
 }
 
-bool MTropolisEngine::canSaveGameStateCurrently() {
+bool MTropolisEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!_runtime->isIdle())
 		return false;
 
diff --git a/engines/mutationofjb/mutationofjb.cpp b/engines/mutationofjb/mutationofjb.cpp
index 883c9123c20..ae4667e7719 100644
--- a/engines/mutationofjb/mutationofjb.cpp
+++ b/engines/mutationofjb/mutationofjb.cpp
@@ -119,7 +119,7 @@ bool MutationOfJBEngine::hasFeature(Engine::EngineFeature f) const {
 	return false;
 }
 
-bool MutationOfJBEngine::canLoadGameStateCurrently() {
+bool MutationOfJBEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _game->loadSaveAllowed();
 }
 
@@ -142,7 +142,7 @@ Common::Error MutationOfJBEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool MutationOfJBEngine::canSaveGameStateCurrently() {
+bool MutationOfJBEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _game->loadSaveAllowed();
 }
 
diff --git a/engines/mutationofjb/mutationofjb.h b/engines/mutationofjb/mutationofjb.h
index bf491531250..ed84feb1996 100644
--- a/engines/mutationofjb/mutationofjb.h
+++ b/engines/mutationofjb/mutationofjb.h
@@ -65,9 +65,9 @@ public:
 	void setCursorState(CursorState cursorState);
 
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
 	const ADGameDescription *getGameDescription() const;
diff --git a/engines/myst3/myst3.cpp b/engines/myst3/myst3.cpp
index c694a5c8d5f..895dcb3a7b6 100644
--- a/engines/myst3/myst3.cpp
+++ b/engines/myst3/myst3.cpp
@@ -1498,12 +1498,12 @@ void Myst3Engine::dragItem(uint16 statusVar, uint16 movie, uint16 frame, uint16
 	}
 }
 
-bool Myst3Engine::canSaveGameStateCurrently() {
+bool Myst3Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	bool inMenuWithNoGameLoaded = _state->getLocationRoom() == kRoomMenu && _state->getMenuSavedAge() == 0;
 	return canLoadGameStateCurrently() && !inMenuWithNoGameLoaded && _cursor->isVisible();
 }
 
-bool Myst3Engine::canLoadGameStateCurrently() {
+bool Myst3Engine::canLoadGameStateCurrently(Common::U32String *msg) {
 	// Loading from the GMM is only possible when the game is interactive
 	// This is to prevent loading from inner loops. Loading while
 	// in an inner loop can cause the exit condition to never happen,
diff --git a/engines/myst3/myst3.h b/engines/myst3/myst3.h
index df69e923be3..497f67daf63 100644
--- a/engines/myst3/myst3.h
+++ b/engines/myst3/myst3.h
@@ -118,8 +118,8 @@ public:
 	bool isTextLanguageEnglish() const;
 	bool isWideScreenModEnabled() const;
 
-	bool canSaveGameStateCurrently() override;
-	bool canLoadGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error loadGameState(Common::String fileName, TransitionType transition);
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 8558cee9541..2a162252fb6 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -119,11 +119,11 @@ Common::Error NancyEngine::saveGameStream(Common::WriteStream *stream, bool isAu
 	return synchronize(ser);
 }
 
-bool NancyEngine::canLoadGameStateCurrently() {
+bool NancyEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return canSaveGameStateCurrently();
 }
 
-bool NancyEngine::canSaveGameStateCurrently() {
+bool NancyEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// TODO also disable during secondary movie
 	return State::Scene::hasInstance() &&
 			NancySceneState._state == State::Scene::kRun &&
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index c20dcd506fe..c79aa932c1b 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -84,8 +84,8 @@ public:
 
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	void secondChance();
 
diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h
index 5f9a4f54b4e..10b161926aa 100644
--- a/engines/neverhood/neverhood.h
+++ b/engines/neverhood/neverhood.h
@@ -117,8 +117,8 @@ public:
 
 	bool _isSaveAllowed;
 
-	bool canLoadGameStateCurrently() override { return _isSaveAllowed; }
-	bool canSaveGameStateCurrently() override { return _isSaveAllowed; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
 
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &description, bool isAutosave = false) override;
diff --git a/engines/ngi/ngi.h b/engines/ngi/ngi.h
index fd54a099b07..544ced37d04 100644
--- a/engines/ngi/ngi.h
+++ b/engines/ngi/ngi.h
@@ -372,8 +372,8 @@ public:
 	Common::Error saveGameState(int slot, const Common::String &description, bool isAutosave = false) override;
 	Common::String getSaveStateName(int slot) const override;
 
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override { return _isSaveAllowed; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
 	bool hasFeature(EngineFeature f) const override;
 
 };
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index e33436590ad..b5b05338a81 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -211,11 +211,11 @@ Common::Error PegasusEngine::run() {
 	return Common::kNoError;
 }
 
-bool PegasusEngine::canLoadGameStateCurrently() {
+bool PegasusEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _loadAllowed && !isDemo();
 }
 
-bool PegasusEngine::canSaveGameStateCurrently() {
+bool PegasusEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _saveAllowed && !isDemo() && g_neighborhood;
 }
 
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
index 848c79358b8..f994fb0c34f 100644
--- a/engines/pegasus/pegasus.h
+++ b/engines/pegasus/pegasus.h
@@ -77,8 +77,8 @@ public:
 	// Engine stuff
 	const PegasusGameDescription *_gameDescription;
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
diff --git a/engines/petka/petka.h b/engines/petka/petka.h
index 592e5e6c303..85f98bc4af4 100644
--- a/engines/petka/petka.h
+++ b/engines/petka/petka.h
@@ -122,10 +122,10 @@ public:
 	void pushMouseMoveEvent();
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	int getAutosaveSlot() const override { return - 1;}
 
diff --git a/engines/petka/saveload.cpp b/engines/petka/saveload.cpp
index eb5f7f05432..080fbddc64e 100644
--- a/engines/petka/saveload.cpp
+++ b/engines/petka/saveload.cpp
@@ -94,7 +94,7 @@ Common::Error PetkaEngine::saveGameState(int slot, const Common::String &desci,
 	return Common::kNoError;
 }
 
-bool PetkaEngine::canSaveGameStateCurrently() {
+bool PetkaEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (isDemo() || !_qsystem)
 		return false;
 
@@ -107,7 +107,7 @@ bool PetkaEngine::canSaveGameStateCurrently() {
 	return prev == _qsystem->_mainInterface.get() && (curr == saveLoad || curr == panel);
 }
 
-bool PetkaEngine::canLoadGameStateCurrently() {
+bool PetkaEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !isDemo() && _qsystem;
 }
 
diff --git a/engines/pink/pink.cpp b/engines/pink/pink.cpp
index fe16f4224d3..3289c12c019 100644
--- a/engines/pink/pink.cpp
+++ b/engines/pink/pink.cpp
@@ -295,11 +295,11 @@ void PinkEngine::setCursor(uint cursorIndex) {
 	CursorMan.showMouse(true);
 }
 
-bool PinkEngine::canLoadGameStateCurrently() {
+bool PinkEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
-bool PinkEngine::canSaveGameStateCurrently() {
+bool PinkEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
diff --git a/engines/pink/pink.h b/engines/pink/pink.h
index 6a70924e7fe..a53ab02b625 100644
--- a/engines/pink/pink.h
+++ b/engines/pink/pink.h
@@ -102,10 +102,10 @@ public:
 	bool hasFeature(EngineFeature f) const override;
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override {
 		return Common::String::format("%s.s%02d", _targetName.c_str(), slot);
 	}
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
index b4058a544f7..c55e2f00bac 100644
--- a/engines/prince/prince.h
+++ b/engines/prince/prince.h
@@ -279,8 +279,8 @@ public:
 
 	bool hasFeature(EngineFeature f) const override;
 	void pauseEngineIntern(bool pause) override;
-	bool canSaveGameStateCurrently() override;
-	bool canLoadGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error loadGameState(int slot) override;
 
diff --git a/engines/prince/saveload.cpp b/engines/prince/saveload.cpp
index 04b651e3f20..6c5612e50c8 100644
--- a/engines/prince/saveload.cpp
+++ b/engines/prince/saveload.cpp
@@ -113,7 +113,7 @@ WARN_UNUSED_RESULT bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in,
 	return true;
 }
 
-bool PrinceEngine::canSaveGameStateCurrently() {
+bool PrinceEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (_mouseFlag && _mouseFlag != 3) {
 		if (_mainHero->_visible) {
 			// 29 - Basement
@@ -128,7 +128,7 @@ bool PrinceEngine::canSaveGameStateCurrently() {
 	return false;
 }
 
-bool PrinceEngine::canLoadGameStateCurrently() {
+bool PrinceEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	if (_mouseFlag && _mouseFlag != 3) {
 		if (_mainHero->_visible) {
 			// 29 - Basement
diff --git a/engines/private/private.h b/engines/private/private.h
index 7e997faae8b..3fa64ada715 100644
--- a/engines/private/private.h
+++ b/engines/private/private.h
@@ -180,13 +180,13 @@ public:
 	bool cursorMask(Common::Point);
 
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 	bool canSaveAutosaveCurrently() override  {
 		return false;
 	}
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return true;
 	}
 
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index a0512e75bda..1b5d2a8d246 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -169,11 +169,11 @@ bool QueenEngine::canLoadOrSave() const {
 	return !_input->cutawayRunning() && !(_resource->isDemo() || _resource->isInterview()) && _gameStarted;
 }
 
-bool QueenEngine::canLoadGameStateCurrently() {
+bool QueenEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return canLoadOrSave();
 }
 
-bool QueenEngine::canSaveGameStateCurrently() {
+bool QueenEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return canLoadOrSave();
 }
 
diff --git a/engines/queen/queen.h b/engines/queen/queen.h
index 10b9599b4cf..8658286016d 100644
--- a/engines/queen/queen.h
+++ b/engines/queen/queen.h
@@ -93,8 +93,8 @@ public:
 	void update(bool checkPlayerInput = false);
 
 	bool canLoadOrSave() const;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error loadGameState(int slot) override;
 	int getAutosaveSlot() const override { return 99; }
diff --git a/engines/saga/metaengine.cpp b/engines/saga/metaengine.cpp
index 93e8ffeb295..2fead3822a8 100644
--- a/engines/saga/metaengine.cpp
+++ b/engines/saga/metaengine.cpp
@@ -302,12 +302,12 @@ Common::Error SagaEngine::saveGameState(int slot, const Common::String &desc, bo
 	return Common::kNoError;	// TODO: return success/failure
 }
 
-bool SagaEngine::canLoadGameStateCurrently() {
+bool SagaEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_scene->isInIntro() &&
 		(_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
 }
 
-bool SagaEngine::canSaveGameStateCurrently() {
+bool SagaEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !_scene->isInIntro() &&
 		(_interface->getMode() == kPanelMain || _interface->getMode() == kPanelChapterSelection);
 }
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 63c57c57c4e..9aa19769f57 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -623,8 +623,8 @@ public:
 	const Common::Rect &getDisplayClip() const { return _displayClip;}
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	const GameDisplayInfo &getDisplayInfo();
 
 	int getLanguageIndex();
diff --git a/engines/saga2/saga2.h b/engines/saga2/saga2.h
index 1f67f30e2c4..fdaf4278ca2 100644
--- a/engines/saga2/saga2.h
+++ b/engines/saga2/saga2.h
@@ -113,8 +113,8 @@ public:
 	bool hasFeature(EngineFeature f) const override;
 	const ADGameFileDescription *getFilesDescriptions() const;
 	int getGameId() const;
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override { return true; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave) override;
diff --git a/engines/sci/metaengine.cpp b/engines/sci/metaengine.cpp
index 6ebc45011b5..05b576f0a48 100644
--- a/engines/sci/metaengine.cpp
+++ b/engines/sci/metaengine.cpp
@@ -449,7 +449,7 @@ Common::Error SciEngine::saveGameState(int slot, const Common::String &desc, boo
 	return res ? Common::kNoError : Common::kWritingFailed;
 }
 
-bool SciEngine::canLoadGameStateCurrently() {
+bool SciEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 #ifdef ENABLE_SCI32
 	const Common::String &guiOptions = ConfMan.get("guioptions");
 	if (getSciVersion() >= SCI_VERSION_2) {
@@ -464,7 +464,7 @@ bool SciEngine::canLoadGameStateCurrently() {
 	return !_gamestate->executionStackBase;
 }
 
-bool SciEngine::canSaveGameStateCurrently() {
+bool SciEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return
 		_features->canSaveFromGMM() &&
 		!_gamestate->executionStackBase &&
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 2dadd0aebe6..a709d1404f4 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -146,8 +146,8 @@ public:
 	Console *getSciDebugger();
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	void syncSoundSettings() override; ///< from ScummVM to the game
 	void updateSoundMixerVolumes();
 	uint32 getTickCount();
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 10634f415e2..6edae9386ef 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -78,7 +78,7 @@ Common::Error ScummEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool ScummEngine::canLoadGameStateCurrently() {
+bool ScummEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	if (!_setupIsComplete)
 		return false;
 
@@ -141,7 +141,7 @@ Common::Error ScummEngine::saveGameState(int slot, const Common::String &desc, b
 	return Common::kNoError;
 }
 
-bool ScummEngine::canSaveGameStateCurrently() {
+bool ScummEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	if (!_setupIsComplete)
 		return false;
 
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index bfb30fa4dcf..d3a712637d6 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -589,9 +589,9 @@ public:
 	void syncSoundSettings() override;
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	void pauseEngineIntern(bool pause) override;
 
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index d1fe1d44cf5..3ad585250e5 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -289,11 +289,11 @@ void SherlockEngine::synchronize(Serializer &s) {
 		s.syncAsByte(_flags[idx]);
 }
 
-bool SherlockEngine::canLoadGameStateCurrently() {
+bool SherlockEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _canLoadSave;
 }
 
-bool SherlockEngine::canSaveGameStateCurrently() {
+bool SherlockEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _canLoadSave;
 }
 
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 2ba9acbf360..870a5933f78 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -142,12 +142,12 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Called by the GMM to load a savegame
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 48f125eceb7..7867cb7cd98 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -202,12 +202,12 @@ void TattooEngine::saveConfig() {
 	ConfMan.flushToDisk();
 }
 
-bool TattooEngine::canLoadGameStateCurrently() {
+bool TattooEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	TattooUserInterface &ui = *(TattooUserInterface *)_ui;
 	return _canLoadSave && !ui._creditsWidget.active() && !_runningProlog;
 }
 
-bool TattooEngine::canSaveGameStateCurrently() {
+bool TattooEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	TattooUserInterface &ui = *(TattooUserInterface *)_ui;
 	return _canLoadSave && !ui._creditsWidget.active() && !_runningProlog;
 }
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index 035eb79dc5d..b45cea9e4df 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -104,12 +104,12 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 };
 
 } // End of namespace Tattoo
diff --git a/engines/sky/metaengine.cpp b/engines/sky/metaengine.cpp
index 774558e2840..496e68b755b 100644
--- a/engines/sky/metaengine.cpp
+++ b/engines/sky/metaengine.cpp
@@ -386,13 +386,13 @@ Common::Error SkyEngine::saveGameState(int slot, const Common::String &desc, boo
 	return Common::kNoError;
 }
 
-bool SkyEngine::canLoadGameStateCurrently() {
+bool SkyEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _systemVars->pastIntro
 	    && _skyControl->loadSaveAllowed()
 	    && !_skyControl->isControlPanelOpen();
 }
 
-bool SkyEngine::canSaveGameStateCurrently() {
+bool SkyEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _systemVars->pastIntro
 	    && _skyControl->loadSaveAllowed()
 	    && !_skyControl->isControlPanelOpen();
diff --git a/engines/sky/sky.h b/engines/sky/sky.h
index a0332d1d34c..a67cd023529 100644
--- a/engines/sky/sky.h
+++ b/engines/sky/sky.h
@@ -101,8 +101,8 @@ public:
 
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override {
 		return Common::String::format("SKY-VM.%03d", slot);
 	}
diff --git a/engines/stark/stark.cpp b/engines/stark/stark.cpp
index 7ec8476f37b..92487c2f404 100644
--- a/engines/stark/stark.cpp
+++ b/engines/stark/stark.cpp
@@ -357,7 +357,7 @@ bool StarkEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsReturnToLauncher);
 }
 
-bool StarkEngine::canLoadGameStateCurrently() {
+bool StarkEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !StarkUserInterface->isInSaveLoadMenuScreen();
 }
 
@@ -424,7 +424,7 @@ Common::Error StarkEngine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool StarkEngine::canSaveGameStateCurrently() {
+bool StarkEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// Disallow saving when there is no level loaded or when a script is running
 	// or when the save & load menu is currently displayed
 	return StarkGlobal->getLevel() && StarkGlobal->getCurrent() && StarkUserInterface->isInteractive() && !StarkUserInterface->isInSaveLoadMenuScreen();
diff --git a/engines/stark/stark.h b/engines/stark/stark.h
index 6e3685bdd9b..887aa4fd2a8 100644
--- a/engines/stark/stark.h
+++ b/engines/stark/stark.h
@@ -79,8 +79,8 @@ protected:
 	// Engine APIs
 	Common::Error run() override;
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void pauseEngineIntern(bool pause) override;
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index 0648843746d..a47abe7eb92 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -659,7 +659,7 @@ bool SupernovaEngine::quitGameDialog() {
 }
 
 
-bool SupernovaEngine::canLoadGameStateCurrently() {
+bool SupernovaEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _allowLoadGame;
 }
 
@@ -667,7 +667,7 @@ Common::Error SupernovaEngine::loadGameState(int slot) {
 	return (loadGame(slot) ? Common::kNoError : Common::kReadingFailed);
 }
 
-bool SupernovaEngine::canSaveGameStateCurrently() {
+bool SupernovaEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// Do not allow saving when either _allowSaveGame, _animationEnabled or _guiEnabled is false
 	return _allowSaveGame && _gm->canSaveGameStateCurrently();
 }
diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h
index 9145ea64cad..40014661e06 100644
--- a/engines/supernova/supernova.h
+++ b/engines/supernova/supernova.h
@@ -65,9 +65,9 @@ public:
 
 	Common::Error run() override;
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	bool hasFeature(EngineFeature f) const override;
 	void pauseEngineIntern(bool pause) override;
 
diff --git a/engines/sword1/metaengine.cpp b/engines/sword1/metaengine.cpp
index 54bd40e6ef7..164fffa5d0a 100644
--- a/engines/sword1/metaengine.cpp
+++ b/engines/sword1/metaengine.cpp
@@ -191,7 +191,7 @@ Common::Error SwordEngine::loadGameState(int slot) {
 	return Common::kNoError;    // TODO: return success/failure
 }
 
-bool SwordEngine::canLoadGameStateCurrently() {
+bool SwordEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (mouseIsActive() && !_control->isPanelShown()); // Disable GMM loading when game panel is shown
 }
 
@@ -201,7 +201,7 @@ Common::Error SwordEngine::saveGameState(int slot, const Common::String &desc, b
 	return Common::kNoError;    // TODO: return success/failure
 }
 
-bool SwordEngine::canSaveGameStateCurrently() {
+bool SwordEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (mouseIsActive() && !_control->isPanelShown() && Logic::_scriptVars[SCREEN] != 91);
 }
 
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index 105b9b46e32..afff3474f50 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -146,9 +146,9 @@ protected:
 	void syncSoundSettings() override;
 
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override {
 		return Common::String::format("sword1.%03d", slot);
 	}
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 13a9db96e45..7243e367b87 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -575,7 +575,7 @@ Common::Error Sword2Engine::saveGameState(int slot, const Common::String &desc,
 		return Common::kUnknownError;
 }
 
-bool Sword2Engine::canSaveGameStateCurrently() {
+bool Sword2Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	bool canSave = true;
 
 	// No save if dead
@@ -605,7 +605,7 @@ Common::Error Sword2Engine::loadGameState(int slot) {
 	return Common::kNoError;
 }
 
-bool Sword2Engine::canLoadGameStateCurrently() {
+bool Sword2Engine::canLoadGameStateCurrently(Common::U32String *msg) {
 	bool canLoad = true;
 
 	// No load if mouse is disabled
diff --git a/engines/sword2/sword2.h b/engines/sword2/sword2.h
index cd2cf6b72a2..a7320168d63 100644
--- a/engines/sword2/sword2.h
+++ b/engines/sword2/sword2.h
@@ -162,9 +162,9 @@ public:
 
 	// GMM Loading/Saving
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	uint32 _features;
 
diff --git a/engines/teenagent/teenagent.h b/engines/teenagent/teenagent.h
index f7372aa4c21..c7fcf787e42 100644
--- a/engines/teenagent/teenagent.h
+++ b/engines/teenagent/teenagent.h
@@ -89,8 +89,8 @@ public:
 	Common::String getSaveStateName(int slot) const override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override { return !_sceneBusy; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return !_sceneBusy; }
 	bool hasFeature(EngineFeature f) const override;
 
 	void init();
diff --git a/engines/tetraedge/tetraedge.cpp b/engines/tetraedge/tetraedge.cpp
index f2942a55d41..77bac9ebf13 100644
--- a/engines/tetraedge/tetraedge.cpp
+++ b/engines/tetraedge/tetraedge.cpp
@@ -151,11 +151,11 @@ bool TetraedgeEngine::isGameDemo() const {
 	return (_gameDescription->flags & ADGF_DEMO) != 0;
 }
 
-bool TetraedgeEngine::canLoadGameStateCurrently() {
+bool TetraedgeEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _game && _application && !_application->mainMenu().isEntered();
 }
 
-bool TetraedgeEngine::canSaveGameStateCurrently() {
+bool TetraedgeEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return canSaveAutosaveCurrently() && !_application->isLockCursor();
 }
 
diff --git a/engines/tetraedge/tetraedge.h b/engines/tetraedge/tetraedge.h
index 012982d9497..deab9e9e9c4 100644
--- a/engines/tetraedge/tetraedge.h
+++ b/engines/tetraedge/tetraedge.h
@@ -110,8 +110,8 @@ public:
 			(f == kSupportsQuitDialogOverride);
 	};
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	bool canSaveAutosaveCurrently() override;
 
 	/**
diff --git a/engines/tinsel/metaengine.cpp b/engines/tinsel/metaengine.cpp
index c70cfacbd51..d8f5b0f7f6b 100644
--- a/engines/tinsel/metaengine.cpp
+++ b/engines/tinsel/metaengine.cpp
@@ -260,10 +260,10 @@ Common::Error TinselEngine::saveGameState(int slot, const Common::String &desc,
 }
 #endif
 
-bool TinselEngine::canLoadGameStateCurrently() { return !_bmv->MoviePlaying(); }
+bool TinselEngine::canLoadGameStateCurrently(Common::U32String *msg) { return !_bmv->MoviePlaying(); }
 
 #if 0
-bool TinselEngine::canSaveGameStateCurrently() { return isCursorShown(); }
+bool TinselEngine::canSaveGameStateCurrently(Common::U32String *msg) { return isCursorShown(); }
 #endif
 
 } // End of namespace Tinsel
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index ec45737707a..a73966e4505 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -139,7 +139,7 @@ protected:
 #if 0
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false);
 #endif
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 #if 0
 	bool canSaveGameStateCurrently();
 #endif
diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp
index d8ac5f197d6..e502867daab 100644
--- a/engines/titanic/titanic.cpp
+++ b/engines/titanic/titanic.cpp
@@ -176,7 +176,7 @@ void TitanicEngine::setRoomNames() {
 	delete r;
 }
 
-bool TitanicEngine::canLoadGameStateCurrently() {
+bool TitanicEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	CGameManager *gameManager = _window->_gameManager;
 	CScreenManager *screenMan = CScreenManager::_screenManagerPtr;
 
@@ -205,7 +205,7 @@ bool TitanicEngine::canLoadGameStateCurrently() {
 	return true;
 }
 
-bool TitanicEngine::canSaveGameStateCurrently() {
+bool TitanicEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	CGameManager *gameManager = _window->_gameManager;
 	if (!gameManager)
 		return false;
diff --git a/engines/titanic/titanic.h b/engines/titanic/titanic.h
index e6986674687..7d4c9a0852e 100644
--- a/engines/titanic/titanic.h
+++ b/engines/titanic/titanic.h
@@ -133,12 +133,12 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Called by the GMM to load a savegame
diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h
index 88792443225..616aec80fe3 100644
--- a/engines/toltecs/toltecs.h
+++ b/engines/toltecs/toltecs.h
@@ -211,8 +211,8 @@ public:
 
 	bool _isSaveAllowed;
 
-	bool canLoadGameStateCurrently() override { return _isSaveAllowed; }
-	bool canSaveGameStateCurrently() override { return _isSaveAllowed; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &description, bool isAutosave = false) override;
 	void savegame(const char *filename, const char *description);
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index 652355148d5..482ddb92c10 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -736,11 +736,11 @@ uint32 TonyEngine::getTime() {
 	return g_system->getMillis();
 }
 
-bool TonyEngine::canLoadGameStateCurrently() {
+bool TonyEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return GLOBALS._gfxEngine != NULL && GLOBALS._gfxEngine->canLoadSave();
 }
 
-bool TonyEngine::canSaveGameStateCurrently() {
+bool TonyEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return GLOBALS._gfxEngine != NULL && GLOBALS._gfxEngine->canLoadSave();
 }
 
diff --git a/engines/tony/tony.h b/engines/tony/tony.h
index adefc2c06b1..80ff8b38c79 100644
--- a/engines/tony/tony.h
+++ b/engines/tony/tony.h
@@ -161,8 +161,8 @@ public:
 		return &_theEngine;
 	}
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 7eb49085a9b..ee5b8e70e0f 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -3771,11 +3771,11 @@ void ToonEngine::pauseEngineIntern(bool pause) {
 	}
 }
 
-bool ToonEngine::canSaveGameStateCurrently() {
+bool ToonEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return !_gameState->_inMenu && !_gameState->_inInventory && !_gameState->_inConversation && !_gameState->_inCutaway && !_gameState->_mouseHidden && !_moviePlayer->isPlaying();
 }
 
-bool ToonEngine::canLoadGameStateCurrently() {
+bool ToonEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_gameState->_inMenu && !_gameState->_inInventory && !_gameState->_inConversation && !_gameState->_inCutaway && !_gameState->_mouseHidden && !_moviePlayer->isPlaying();
 }
 
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index db7f8cc58a7..44ed9f40bbe 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -212,8 +212,8 @@ public:
 	void doMagnifierEffect();
 	void drawCustomText(int16 x, int16 y, const char *line, Graphics::Surface *frame, byte color);
 	bool showConversationText() const;
-	bool canSaveGameStateCurrently() override;
-	bool canLoadGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	void pauseEngineIntern(bool pause) override;
 	void syncSoundSettings() override;
 
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 24cc7a77283..9a88c33cec1 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -3406,11 +3406,11 @@ void ToucheEngine::updatePalette() {
 	_system->getPaletteManager()->setPalette(_paletteBuffer, 0, 256);
 }
 
-bool ToucheEngine::canLoadGameStateCurrently() {
+bool ToucheEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _gameState == kGameStateGameLoop && _flagsTable[618] == 0 && !_hideInventoryTexts;
 }
 
-bool ToucheEngine::canSaveGameStateCurrently() {
+bool ToucheEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _gameState == kGameStateGameLoop && _flagsTable[618] == 0 && !_hideInventoryTexts;
 }
 
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index 33ad737e4ae..eeafc07770a 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -619,8 +619,8 @@ protected:
 	void loadGameStateData(Common::ReadStream *stream);
 	Common::Error saveGameState(int num, const Common::String &description, bool isAutosave = false) override;
 	Common::Error loadGameState(int num) override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::String getSaveStateName(int slot) const override {
 		return Common::String::format("%s.%d", _targetName.c_str(), slot);
 	}
diff --git a/engines/trecision/trecision.h b/engines/trecision/trecision.h
index 139545cc086..0b5eaf78a9e 100644
--- a/engines/trecision/trecision.h
+++ b/engines/trecision/trecision.h
@@ -169,8 +169,8 @@ public:
 	bool isDemo() const { return _gameDescription->flags & ADGF_DEMO; }
 	bool isAmiga() const { return _gameDescription->platform == Common::kPlatformAmiga; }
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override { return canPlayerInteract() && _curRoom != kRoomIntro; }
-	bool canSaveGameStateCurrently() override { return canPlayerInteract() && _curRoom != kRoomIntro; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return canPlayerInteract() && _curRoom != kRoomIntro; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return canPlayerInteract() && _curRoom != kRoomIntro; }
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 	bool syncGameStream(Common::Serializer &ser);
diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp
index 8d03dbafdab..2d23ad1fe18 100644
--- a/engines/tsage/tsage.cpp
+++ b/engines/tsage/tsage.cpp
@@ -143,14 +143,14 @@ Common::Error TSageEngine::run() {
 /**
  * Returns true if it is currently okay to restore a game
  */
-bool TSageEngine::canLoadGameStateCurrently() {
+bool TSageEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return (g_globals != NULL) && (g_globals->_game != NULL) && g_globals->_game->canLoadGameStateCurrently();
 }
 
 /**
  * Returns true if it is currently okay to save the game
  */
-bool TSageEngine::canSaveGameStateCurrently() {
+bool TSageEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return (g_globals != NULL) && (g_globals->_game != NULL) && g_globals->_game->canSaveGameStateCurrently();
 }
 
diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h
index 7aeaaf4dadc..972329eb897 100644
--- a/engines/tsage/tsage.h
+++ b/engines/tsage/tsage.h
@@ -61,8 +61,8 @@ public:
 
 	virtual Common::Error init();
 	Common::Error run() override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void syncSoundSettings() override;
diff --git a/engines/tucker/saveload.cpp b/engines/tucker/saveload.cpp
index 460a50f7819..384f0060ccc 100644
--- a/engines/tucker/saveload.cpp
+++ b/engines/tucker/saveload.cpp
@@ -283,11 +283,11 @@ bool TuckerEngine::canLoadOrSave() const {
 	return !_player && _cursorState != kCursorStateDisabledHidden;
 }
 
-bool TuckerEngine::canLoadGameStateCurrently() {
+bool TuckerEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return canLoadOrSave();
 }
 
-bool TuckerEngine::canSaveGameStateCurrently() {
+bool TuckerEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return canLoadOrSave();
 }
 
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index 27124fb1cad..379d6cc2a94 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -745,8 +745,8 @@ protected:
 	}
 
 	bool canLoadOrSave() const;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	virtual bool existsSavegame();
 
 	void handleIntroSequence();
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index a8793da3f70..a565a87b01c 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -394,7 +394,7 @@ void TwinEEngine::wipeSaveSlot(int slot) {
 	saveFileMan->removeSavefile(saveFile);
 }
 
-bool TwinEEngine::canSaveGameStateCurrently() { return _scene->isGameRunning(); }
+bool TwinEEngine::canSaveGameStateCurrently(Common::U32String *msg) { return _scene->isGameRunning(); }
 
 Common::Error TwinEEngine::loadGameStream(Common::SeekableReadStream *stream) {
 	debug("load game stream");
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 8997924f3d6..2eb4778f374 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -238,8 +238,8 @@ public:
 	Common::Error run() override;
 	bool hasFeature(EngineFeature f) const override;
 
-	bool canLoadGameStateCurrently() override { return true; }
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
diff --git a/engines/ultima/shared/engine/ultima.h b/engines/ultima/shared/engine/ultima.h
index 57365e4c68b..d15bc4bac94 100644
--- a/engines/ultima/shared/engine/ultima.h
+++ b/engines/ultima/shared/engine/ultima.h
@@ -117,7 +117,7 @@ public:
 	/**
 	 * Indicates whether a game state can be loaded.
 	 */
-	bool canLoadGameStateCurrently() override {
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return canLoadGameStateCurrently(false);
 	}
 
@@ -130,7 +130,7 @@ public:
 	/**
 	 * Indicates whether a game state can be saved.
 	 */
-	bool canSaveGameStateCurrently() override {
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
 		return canSaveGameStateCurrently(false);
 	}
 };
diff --git a/engines/ultima/ultima8/ultima8.cpp b/engines/ultima/ultima8/ultima8.cpp
index 7c25d0391a4..5f90bee6e1c 100644
--- a/engines/ultima/ultima8/ultima8.cpp
+++ b/engines/ultima/ultima8/ultima8.cpp
@@ -911,7 +911,7 @@ void Ultima8Engine::writeSaveInfo(Common::WriteStream *ws) {
 	_game->writeSaveInfo(ws);
 }
 
-bool Ultima8Engine::canSaveGameStateCurrently() {
+bool Ultima8Engine::canSaveGameStateCurrently(Common::U32String *msg) {
 	// Can't save when avatar in stasis during cutscenes
 	if (_avatarInStasis || _cruStasis)
 		return false;
diff --git a/engines/ultima/ultima8/ultima8.h b/engines/ultima/ultima8/ultima8.h
index 58092fa86e7..71a99fcc8e9 100644
--- a/engines/ultima/ultima8/ultima8.h
+++ b/engines/ultima/ultima8/ultima8.h
@@ -315,12 +315,12 @@ public:
 	/**
 	 * Returns true if a savegame can be loaded
 	 */
-	bool canLoadGameStateCurrently() override { return true; }
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
 
 	/**
 	 * Returns true if the game can be saved
 	 */
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	/**
 	 * Load a game
diff --git a/engines/vcruise/vcruise.cpp b/engines/vcruise/vcruise.cpp
index b650b00a177..e3cc7490be1 100644
--- a/engines/vcruise/vcruise.cpp
+++ b/engines/vcruise/vcruise.cpp
@@ -334,11 +334,11 @@ bool VCruiseEngine::canSaveAutosaveCurrently() {
 	return _runtime->canSave(false);
 }
 
-bool VCruiseEngine::canSaveGameStateCurrently() {
+bool VCruiseEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _runtime->canSave(false);
 }
 
-bool VCruiseEngine::canLoadGameStateCurrently() {
+bool VCruiseEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _runtime->canLoad();
 }
 
diff --git a/engines/vcruise/vcruise.h b/engines/vcruise/vcruise.h
index 0be86ef5c29..920037171e2 100644
--- a/engines/vcruise/vcruise.h
+++ b/engines/vcruise/vcruise.h
@@ -57,8 +57,8 @@ public:
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 
 	bool canSaveAutosaveCurrently() override;
-	bool canSaveGameStateCurrently() override;
-	bool canLoadGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	void initializePath(const Common::FSNode &gamePath) override;
 
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index a0085576272..1d8ab81d3a4 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -755,14 +755,14 @@ void VoyeurEngine::showEndingNews() {
 /**
  * Returns true if it is currently okay to restore a game
  */
-bool VoyeurEngine::canLoadGameStateCurrently() {
+bool VoyeurEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return _voyeurArea == AREA_APARTMENT;
 }
 
 /**
  * Returns true if it is currently okay to save the game
  */
-bool VoyeurEngine::canSaveGameStateCurrently() {
+bool VoyeurEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return _voyeurArea == AREA_APARTMENT;
 }
 
diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h
index 024783961b6..8789923abfa 100644
--- a/engines/voyeur/voyeur.h
+++ b/engines/voyeur/voyeur.h
@@ -204,8 +204,8 @@ public:
 	bool getIsDemo() const;
 
 	int getRandomNumber(int maxNumber);
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void loadGame(int slot);
diff --git a/engines/wage/metaengine.cpp b/engines/wage/metaengine.cpp
index 81808b3b83e..2e7feb0f909 100644
--- a/engines/wage/metaengine.cpp
+++ b/engines/wage/metaengine.cpp
@@ -79,11 +79,11 @@ int WageMetaEngine::getMaximumSaveSlot() const { return 999; }
 
 namespace Wage {
 
-bool WageEngine::canLoadGameStateCurrently() {
+bool WageEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
-bool WageEngine::canSaveGameStateCurrently() {
+bool WageEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index eb4e12afcb1..7c582a4cbc6 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -133,8 +133,8 @@ public:
 
 	Common::Error run() override;
 
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 
 	const char *getGameFile() const;
 	void processTurn(Common::String *textInput, Designed *clickInput);
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 4bc58b62e4f..e430dfe8bec 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -341,11 +341,11 @@ Common::Error WintermuteEngine::saveGameState(int slot, const Common::String &de
 	return Common::kNoError;
 }
 
-bool WintermuteEngine::canSaveGameStateCurrently() {
+bool WintermuteEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
-bool WintermuteEngine::canLoadGameStateCurrently() {
+bool WintermuteEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	return true;
 }
 
diff --git a/engines/wintermute/wintermute.h b/engines/wintermute/wintermute.h
index a75cb99a878..0b752382df6 100644
--- a/engines/wintermute/wintermute.h
+++ b/engines/wintermute/wintermute.h
@@ -60,9 +60,9 @@ public:
 	bool hasFeature(EngineFeature f) const override;
 	Common::SaveFileManager *getSaveFileMan() { return _saveFileMan; }
 	Common::Error loadGameState(int slot) override;
-	bool canLoadGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
-	bool canSaveGameStateCurrently() override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	// For detection-purposes:
 	static bool getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption);
 private:
diff --git a/engines/zvision/metaengine.cpp b/engines/zvision/metaengine.cpp
index b4ea238694b..89905a96407 100644
--- a/engines/zvision/metaengine.cpp
+++ b/engines/zvision/metaengine.cpp
@@ -163,11 +163,11 @@ Common::Error ZVision::ZVision::saveGameState(int slot, const Common::String &de
 	return Common::kNoError;
 }
 
-bool ZVision::ZVision::canLoadGameStateCurrently() {
+bool ZVision::ZVision::canLoadGameStateCurrently(Common::U32String *msg) {
 	return !_videoIsPlaying;
 }
 
-bool ZVision::ZVision::canSaveGameStateCurrently() {
+bool ZVision::ZVision::canSaveGameStateCurrently(Common::U32String *msg) {
 	Location currentLocation = _scriptManager->getCurrentLocation();
 	return !_videoIsPlaying && currentLocation.world != 'g' && !(currentLocation.room == 'j' || currentLocation.room == 'a');
 }
diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h
index f2746e656d1..5a5081f36ab 100644
--- a/engines/zvision/zvision.h
+++ b/engines/zvision/zvision.h
@@ -255,8 +255,8 @@ public:
 
 	// Engine features
 	bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override;
-	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
+	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 


Commit: 735a6693d7a6f2a090f0f49aab0d3b6c6e506e6f
    https://github.com/scummvm/scummvm/commit/735a6693d7a6f2a090f0f49aab0d3b6c6e506e6f
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:24:52+01:00

Commit Message:
ENGINES: Show pop-up message for save/load in GMM and explain the reason

This is very confusing to the users, so now instead of hiding or disabling
the buttons, we show message explaining the reason why it is disabled now

  - The engine is not supporting loading from GMM at all
  - The engine does not allow save/load at this time

These messages could be overridden by the engines

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


diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 57d847b83e0..fed52f81774 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -66,13 +66,8 @@ MainMenuDialog::MainMenuDialog(Engine *engine)
 
 	new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), Common::U32String(), kPlayCmd, 'P');
 
-	_loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), Common::U32String(), kLoadCmd);
-	_loadButton->setVisible(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime));
-	_loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime));
-
-	_saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), Common::U32String(), kSaveCmd);
-	_saveButton->setVisible(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime));
-	_saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime));
+	new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), Common::U32String(), kLoadCmd);
+	new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), Common::U32String(), kSaveCmd);
 
 	new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), Common::U32String(), kOptionsCmd);
 
@@ -152,11 +147,6 @@ void MainMenuDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint3
 }
 
 void MainMenuDialog::reflowLayout() {
-	if (_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime))
-		_loadButton->setEnabled(_engine->canLoadGameStateCurrently());
-	if (_engine->hasFeature(Engine::kSupportsSavingDuringRuntime))
-		_saveButton->setEnabled(_engine->canSaveGameStateCurrently());
-
 	// Overlay size might have changed since the construction of the dialog.
 	// Update labels when it might be needed
 	// FIXME: it might be better to declare GUI::StaticTextWidget::setLabel() virtual
@@ -198,6 +188,24 @@ void MainMenuDialog::reflowLayout() {
 }
 
 void MainMenuDialog::save() {
+	if (!_engine->hasFeature(Engine::kSupportsSavingDuringRuntime)) {
+		GUI::MessageDialog dialog(_("This game does not support saving from the menu. Use in-game interface"));
+		dialog.runModal();
+
+		return;
+	}
+
+	Common::U32String msg;
+	if (!_engine->canSaveGameStateCurrently(&msg)) {
+		if (msg.empty())
+			msg = _("This game cannot be saved at this time. Please try again later");
+
+		GUI::MessageDialog dialog(msg);
+		dialog.runModal();
+
+		return;
+	}
+
 	int slot = _saveDialog->runModalWithCurrentTarget();
 
 	if (slot >= 0) {
@@ -221,6 +229,24 @@ void MainMenuDialog::save() {
 }
 
 void MainMenuDialog::load() {
+	if (!_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime)) {
+		GUI::MessageDialog dialog(_("This game does not support loading from the menu. Use in-game interface"));
+		dialog.runModal();
+
+		return;
+	}
+
+	Common::U32String msg;
+	if (!_engine->canLoadGameStateCurrently(&msg)) {
+		if (msg.empty())
+			msg = _("This game cannot be loaded at this time. Please try again later");
+
+		GUI::MessageDialog dialog(msg);
+		dialog.runModal();
+
+		return;
+	}
+
 	int slot = _loadDialog->runModalWithCurrentTarget();
 
 	_engine->setGameToLoadSlot(slot);
diff --git a/engines/dialogs.h b/engines/dialogs.h
index 43f213c9377..67d61736767 100644
--- a/engines/dialogs.h
+++ b/engines/dialogs.h
@@ -67,8 +67,6 @@ protected:
 	GUI::GraphicsWidget  *_logo;
 
 	GUI::ButtonWidget    *_returnToLauncherButton;
-	GUI::ButtonWidget    *_loadButton;
-	GUI::ButtonWidget    *_saveButton;
 	GUI::ButtonWidget    *_helpButton;
 
 	GUI::Dialog          *_aboutDialog;


Commit: 8a9fa5184609b64e22fe0bf208ea908ea18e32bc
    https://github.com/scummvm/scummvm/commit/8a9fa5184609b64e22fe0bf208ea908ea18e32bc
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:25:07+01:00

Commit Message:
SCUMM: Explain to HE games players that the save/loading is not supported from GMM

Changed paths:
    engines/scumm/POTFILES
    engines/scumm/saveload.cpp


diff --git a/engines/scumm/POTFILES b/engines/scumm/POTFILES
index 141544a8618..02837666525 100644
--- a/engines/scumm/POTFILES
+++ b/engines/scumm/POTFILES
@@ -6,6 +6,7 @@ engines/scumm/dialogs.cpp
 engines/scumm/help.cpp
 engines/scumm/input.cpp
 engines/scumm/metaengine.cpp
+engines/scumm/saveload.cpp
 engines/scumm/scumm.cpp
 engines/scumm/he/sound_he.cpp
 engines/scumm/imuse/drivers/amiga.cpp
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 6edae9386ef..af2b0afda52 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -24,6 +24,7 @@
 #include "common/savefile.h"
 #include "common/serializer.h"
 #include "common/system.h"
+#include "common/translation.h"
 
 #include "scumm/actor.h"
 #include "scumm/charset.h"
@@ -92,8 +93,12 @@ bool ScummEngine::canLoadGameStateCurrently(Common::U32String *msg) {
 	//
 	// Except the earliest HE Games (3DO and initial DOS version of
 	// puttputt), which didn't offer scripted load/save screens.
-	if (_game.heversion >= 62)
+	if (_game.heversion >= 62) {
+		if (msg)
+			*msg = _("This game does not support loading from the menu. Use in-game interface");
+
 		return false;
+	}
 
 	// COMI always disables saving/loading (to tell the truth:
 	// the main menu) via its scripts, thus we need to make an
@@ -160,8 +165,12 @@ bool ScummEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 	//
 	// Except the earliest HE Games (3DO and initial DOS version of
 	// puttputt), which didn't offer scripted load/save screens.
-	if (_game.heversion >= 62)
+	if (_game.heversion >= 62) {
+		if (msg)
+			*msg = _("This game does not support saving from the menu. Use in-game interface");
+
 		return false;
+	}
 
 #ifdef ENABLE_SCUMM_7_8
 	// COMI always disables saving/loading (to tell the truth:


Commit: b4b529df89da8c45fcca2c88910b0edfbef9ef29
    https://github.com/scummvm/scummvm/commit/b4b529df89da8c45fcca2c88910b0edfbef9ef29
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:25:19+01:00

Commit Message:
GLK: MAGNETIC: Explain that magnetic games save/load is not available from the GMM

Changed paths:
    engines/glk/POTFILES
    engines/glk/magnetic/magnetic.h


diff --git a/engines/glk/POTFILES b/engines/glk/POTFILES
index 7ae8591a127..add5301de64 100644
--- a/engines/glk/POTFILES
+++ b/engines/glk/POTFILES
@@ -8,6 +8,7 @@ engines/glk/advsys/vm.cpp
 engines/glk/alan2/alan2.cpp
 engines/glk/comprehend/game.cpp
 engines/glk/glulx/glulx.cpp
+engines/glk/magnetic/magnetic.h
 engines/glk/quest/quest.cpp
 engines/glk/scott/scott.cpp
 engines/glk/zcode/detection.cpp
diff --git a/engines/glk/magnetic/magnetic.h b/engines/glk/magnetic/magnetic.h
index b2966b89c80..01d82e6b30f 100644
--- a/engines/glk/magnetic/magnetic.h
+++ b/engines/glk/magnetic/magnetic.h
@@ -25,6 +25,7 @@
 #define GLK_MAGNETIC_MAGNETIC
 
 #include "common/scummsys.h"
+#include "common/translation.h"
 #include "glk/glk_api.h"
 #include "glk/magnetic/magnetic_types.h"
 #include "glk/magnetic/magnetic_defs.h"
@@ -1386,6 +1387,9 @@ public:
 	 * The Magnetic engine currently doesn't support loading savegames from the GMM
 	 */
 	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
+		if (msg)
+			*msg = _("This game does not support loading from the menu. Use in-game interface");
+
 		return false;
 	}
 
@@ -1393,6 +1397,9 @@ public:
 	 * The Magnetic engine currently doesn't support saving games from the GMM
 	 */
 	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
+		if (msg)
+			*msg = _("This game does not support saving from the menu. Use in-game interface");
+
 		return false;
 	}
 


Commit: 65dad3186bffcdb8177413efdc780e9507d8fada
    https://github.com/scummvm/scummvm/commit/65dad3186bffcdb8177413efdc780e9507d8fada
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:26:21+01:00

Commit Message:
AGI: Explain that preAGI games cannot be load or saved

Changed paths:
    engines/agi/metaengine.cpp


diff --git a/engines/agi/metaengine.cpp b/engines/agi/metaengine.cpp
index ff1a8e44f25..4459bd99fb7 100644
--- a/engines/agi/metaengine.cpp
+++ b/engines/agi/metaengine.cpp
@@ -414,6 +414,10 @@ bool AgiBase::canLoadGameStateCurrently(Common::U32String *msg) {
 			}
 		}
 	}
+
+	if (msg)
+		*msg = _("This game does not support loading");
+
 	return false;
 }
 
@@ -432,6 +436,10 @@ bool AgiBase::canSaveGameStateCurrently(Common::U32String *msg) {
 			}
 		}
 	}
+
+	if (msg)
+		*msg = _("This game does not support saving");
+
 	return false;
 }
 


Commit: f4f0ac39d09a0fba2d724f724e33d010f9a11c94
    https://github.com/scummvm/scummvm/commit/f4f0ac39d09a0fba2d724f724e33d010f9a11c94
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:26:21+01:00

Commit Message:
ASYLUM: Explain that demo does not support save/load

Changed paths:
    engines/asylum/asylum.cpp


diff --git a/engines/asylum/asylum.cpp b/engines/asylum/asylum.cpp
index 6d37c6b7e46..8f00d620214 100644
--- a/engines/asylum/asylum.cpp
+++ b/engines/asylum/asylum.cpp
@@ -669,15 +669,25 @@ void AsylumEngine::checkAchievements() {
 // Save/Load
 //////////////////////////////////////////////////////////////////////////
 bool AsylumEngine::canLoadGameStateCurrently(Common::U32String *msg) {
-	return (!checkGameVersion("Demo")
-		&& (_handler == _scene || _handler == _menu)
-		&& !speech()->getSoundResourceId());
+	if (checkGameVersion("Demo")) {
+		if (msg)
+			*msg = _("This game does not support loading");
+
+		return false;
+	}
+
+	return ((_handler == _scene || _handler == _menu) && !speech()->getSoundResourceId());
 }
 
 bool AsylumEngine::canSaveGameStateCurrently(Common::U32String *msg) {
-	return (!checkGameVersion("Demo")
-		&& (_handler == _scene)
-		&& !speech()->getSoundResourceId());
+	if (checkGameVersion("Demo")) {
+		if (msg)
+			*msg = _("This game does not support saving");
+
+		return false;
+	}
+
+	return ((_handler == _scene) && !speech()->getSoundResourceId());
 }
 
 bool AsylumEngine::canSaveAutosaveCurrently() {


Commit: e2fd89bc2aba88cf56661fddf2199d9f191ba6e8
    https://github.com/scummvm/scummvm/commit/e2fd89bc2aba88cf56661fddf2199d9f191ba6e8
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:26:21+01:00

Commit Message:
BURIED: Explain that demo does not support save/load

Changed paths:
    engines/buried/saveload.cpp


diff --git a/engines/buried/saveload.cpp b/engines/buried/saveload.cpp
index 71101f523d7..a36ab70dba2 100644
--- a/engines/buried/saveload.cpp
+++ b/engines/buried/saveload.cpp
@@ -48,11 +48,25 @@ namespace Buried {
 #define SAVEGAME_CURRENT_VERSION 1
 
 bool BuriedEngine::canLoadGameStateCurrently(Common::U32String *msg) {
-	return !isDemo() && _mainWindow && !_yielding;
+	if (isDemo()) {
+		if (msg)
+			*msg = _("This game does not support loading");
+
+		return false;
+	}
+
+	return _mainWindow && !_yielding;
 }
 
 bool BuriedEngine::canSaveGameStateCurrently(Common::U32String *msg) {
-	return !isDemo() && _mainWindow && !_yielding && ((FrameWindow *)_mainWindow)->isGameInProgress();
+	if (isDemo()) {
+		if (msg)
+			*msg = _("This game does not support saving");
+
+		return false;
+	}
+
+	return _mainWindow && !_yielding && ((FrameWindow *)_mainWindow)->isGameInProgress();
 }
 
 void BuriedEngine::checkForOriginalSavedGames() {
@@ -117,7 +131,7 @@ void BuriedEngine::convertSavedGame(Common::String oldFile, Common::String newFi
 		warning("Saved game %s is using an unsupported format, skipping", oldFile.c_str());
 		return;
 	}
-	
+
 	// Set necessary properties from the old save
 	Common::Serializer inS(inFile, nullptr);
 	Common::Error res = syncSaveData(inS, location, flags, inventoryItems);


Commit: 0b4d19ddfdd5955f5127a461bc764850cc8a75ad
    https://github.com/scummvm/scummvm/commit/0b4d19ddfdd5955f5127a461bc764850cc8a75ad
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:26:21+01:00

Commit Message:
DREAMWEB: Removing redundant methods: the game does not allow save/load from GMM

Changed paths:
    engines/dreamweb/dreamweb.h
    engines/dreamweb/metaengine.cpp


diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index 5f3d7a654dc..bc9dd90cdb4 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -119,9 +119,6 @@ public:
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 
-	bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
-	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
-
 	uint8 randomNumber() { return _rnd.getRandomNumber(255); }
 
 	void mouseCall(uint16 *x, uint16 *y, uint16 *state); //fill mouse pos and button state
diff --git a/engines/dreamweb/metaengine.cpp b/engines/dreamweb/metaengine.cpp
index a4950c59baa..02621d9700e 100644
--- a/engines/dreamweb/metaengine.cpp
+++ b/engines/dreamweb/metaengine.cpp
@@ -251,14 +251,6 @@ Common::Error DreamWebEngine::saveGameState(int slot, const Common::String &desc
 	return Common::kNoError;
 }
 
-bool DreamWebEngine::canLoadGameStateCurrently(Common::U32String *msg) {
-	return false;
-}
-
-bool DreamWebEngine::canSaveGameStateCurrently(Common::U32String *msg) {
-	return false;
-}
-
 Common::Language DreamWebEngine::getLanguage() const {
 	return _gameDescription->desc.language;
 }


Commit: e8692001c4b6d729abee50223738432ee4bde04a
    https://github.com/scummvm/scummvm/commit/e8692001c4b6d729abee50223738432ee4bde04a
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:26:21+01:00

Commit Message:
MOHAWK: Riven demo does not support save/load. Message this to the user

Changed paths:
    engines/mohawk/riven.cpp


diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 9ffcd45d958..e732ee169a1 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -279,11 +279,11 @@ void MohawkEngine_Riven::processInput() {
 				} else if (!isGameVariant(GF_25TH)) {
 					openMainMenuDialog();
 				}
-					
+
 				if (!isGameVariant(GF_DEMO) && hasGameEnded()) {
 					// Attempt to autosave before exiting
 					saveAutosaveIfEnabled();
-				}	
+				}
 				break;
 			case kRivenActionPlayIntroVideos:
 				// Play the intro videos in the demo
@@ -755,6 +755,9 @@ bool MohawkEngine_Riven::isZipVisitedCard(const Common::String &hotspotName) con
 
 bool MohawkEngine_Riven::canLoadGameStateCurrently(Common::U32String *msg) {
 	if (isGameVariant(GF_DEMO)) {
+		if (msg)
+			*msg = _("This game does not support loading");
+
 		return false;
 	}
 
@@ -766,7 +769,14 @@ bool MohawkEngine_Riven::canLoadGameStateCurrently(Common::U32String *msg) {
 }
 
 bool MohawkEngine_Riven::canSaveGameStateCurrently(Common::U32String *msg) {
-	return canLoadGameStateCurrently() && isGameStarted();
+	if (isGameVariant(GF_DEMO)) {
+		if (msg)
+			*msg = _("This game does not support saving");
+
+		return false;
+	}
+
+	return canLoadGameStateCurrently(msg) && isGameStarted();
 }
 
 bool MohawkEngine_Riven::hasGameEnded() const {


Commit: 9355c6693bfb11ce4003e6acb8667568155139b8
    https://github.com/scummvm/scummvm/commit/9355c6693bfb11ce4003e6acb8667568155139b8
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-12-08T12:26:21+01:00

Commit Message:
PETKA: Demo does not allow save/load. Message to the user

Changed paths:
  A engines/petka/POTFILES
    engines/petka/saveload.cpp


diff --git a/engines/petka/POTFILES b/engines/petka/POTFILES
new file mode 100644
index 00000000000..cc7c27cd54f
--- /dev/null
+++ b/engines/petka/POTFILES
@@ -0,0 +1 @@
+engines/petka/saveload.cpp
diff --git a/engines/petka/saveload.cpp b/engines/petka/saveload.cpp
index 080fbddc64e..fb5275c2ee9 100644
--- a/engines/petka/saveload.cpp
+++ b/engines/petka/saveload.cpp
@@ -21,6 +21,7 @@
 
 #include "common/system.h"
 #include "common/savefile.h"
+#include "common/translation.h"
 
 #include "engines/savestate.h"
 
@@ -95,7 +96,14 @@ Common::Error PetkaEngine::saveGameState(int slot, const Common::String &desci,
 }
 
 bool PetkaEngine::canSaveGameStateCurrently(Common::U32String *msg) {
-	if (isDemo() || !_qsystem)
+	if (isDemo()) {
+		if (msg)
+			*msg = _("This game does not support saving");
+
+		return false;
+	}
+
+	if (!_qsystem)
 		return false;
 
 	Interface *panel = _qsystem->_panelInterface.get();
@@ -108,7 +116,14 @@ bool PetkaEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 }
 
 bool PetkaEngine::canLoadGameStateCurrently(Common::U32String *msg) {
-	return !isDemo() && _qsystem;
+	if (isDemo()) {
+		if (msg)
+			*msg = _("This game does not support loading");
+
+		return false;
+	}
+
+	return _qsystem;
 }
 
 int PetkaEngine::getSaveSlot() {
@@ -149,4 +164,3 @@ Common::String generateSaveName(int slot, const char *gameId) {
 }
 
 }
-




More information about the Scummvm-git-logs mailing list