[Scummvm-git-logs] scummvm master -> 9f07bbacd2c6dc183c13e5734138f9b9c4674820

mduggan noreply at scummvm.org
Sun Apr 13 06:56:02 UTC 2025


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

Summary:
9f07bbacd2 DGDS: Add support for loading original save format


Commit: 9f07bbacd2c6dc183c13e5734138f9b9c4674820
    https://github.com/scummvm/scummvm/commit/9f07bbacd2c6dc183c13e5734138f9b9c4674820
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-04-13T16:53:54+10:00

Commit Message:
DGDS: Add support for loading original save format

Changed paths:
    engines/dgds/dgds.cpp
    engines/dgds/dgds.h
    engines/dgds/metaengine.cpp
    engines/dgds/scene.cpp
    engines/dgds/scene.h


diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index 42abb74c309..639764850c9 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -889,6 +889,32 @@ void DgdsEngine::disableKeymapper() {
 	_eventMan->getKeymapper()->setEnabledKeymapType(Common::Keymap::kKeymapTypeGui);
 }
 
+Common::Error DgdsEngine::loadGameStream(Common::SeekableReadStream *stream) {
+	//
+	// First check if it's an original game save file
+	//
+	// This should be safe on ScummVM save files because they have
+	// a 32 bit version number first, so the string will be 0 length.
+	//
+	uint16 origSlotNum = stream->readUint16LE();
+	Common::String origName = stream->readString();
+	uint32 magic = stream->readUint32LE();
+
+	if (magic == _gdsScene->getMagic()) {
+		// Original type save.
+		debug("Loading original game save %03d '%s' magic %08x", origSlotNum, origName.c_str(), magic);
+		_menu->hideMenu();
+		_gdsScene->loadGameStateFromFile(stream, origName);
+		return Common::kNoError;
+	} else {
+		// Rewind stream to load ScummVM save
+		stream->seek(0, SEEK_SET);
+		Common::Serializer s(stream, nullptr);
+		return syncGame(s);
+	}
+}
+
+
 Common::Error DgdsEngine::syncGame(Common::Serializer &s) {
 	//
 	// Version history:
@@ -898,7 +924,6 @@ Common::Error DgdsEngine::syncGame(Common::Serializer &s) {
 	// 3: Stopped saving ADS/TTM state
 	// 4: Stopped saving palette state
 	//
-
 	assert(_scene && _gdsScene);
 
 	_menu->hideMenu();
diff --git a/engines/dgds/dgds.h b/engines/dgds/dgds.h
index f431e423670..1eedfb4d349 100644
--- a/engines/dgds/dgds.h
+++ b/engines/dgds/dgds.h
@@ -247,10 +247,7 @@ public:
 		return syncGame(s);
 	}
 
-	Common::Error loadGameStream(Common::SeekableReadStream *stream) override {
-		Common::Serializer s(stream, nullptr);
-		return syncGame(s);
-	}
+	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 
 	bool hasFeature(EngineFeature f) const override {
 		return
diff --git a/engines/dgds/metaengine.cpp b/engines/dgds/metaengine.cpp
index 3d9499c75c5..daa373cd8ca 100644
--- a/engines/dgds/metaengine.cpp
+++ b/engines/dgds/metaengine.cpp
@@ -24,6 +24,7 @@
 #include "engines/advancedDetector.h"
 #include "common/system.h"
 #include "common/translation.h"
+#include "common/savefile.h"
 
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymapper.h"
@@ -40,6 +41,7 @@ public:
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	Common::KeymapArray initKeymaps(const char *target) const override;
+	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
 };
 
 bool DgdsMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -96,6 +98,44 @@ Common::KeymapArray DgdsMetaEngine::initKeymaps(const char *target) const {
 	return Common::Keymap::arrayOf(map);
 }
 
+//
+// Used for detecting original game saves
+//
+// Ideally save file magic should be compared to the one in the GDS file,
+// but when loading from the launcher the game engine isn't created,
+// so use a static list.
+//
+static const uint32 GAME_MAGICS[] {
+	0x53E83426, // Rise of the Dragon
+	0xFF553726, // Heart of China
+	0x7ADA2628, // Adventures of Willy Beamish
+};
+
+SaveStateDescriptor DgdsMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+	SaveStateDescriptor desc = AdvancedMetaEngine::querySaveMetaInfos(target, slot);
+	if (!desc.isValid() && slot > 0) {
+		const Common::String filename = getSavegameFile(slot, target);
+		Common::ScopedPtr<Common::InSaveFile> f(g_system->getSavefileManager()->openForLoading(filename));
+
+		if (f) {
+			uint16 origSlotNum = f->readUint16LE();
+			const Common::String origName = f->readString();
+			uint32 magic = f->readUint32BE();
+
+			for (uint32 game_magic : GAME_MAGICS) {
+				if (magic == game_magic && origSlotNum < 4096 && !origName.empty()) {
+					desc.setDescription(origName);
+					desc.setSaveSlot(slot);
+					break;
+				}
+			}
+		}
+	}
+
+	return desc;
+}
+
+
 #if PLUGIN_ENABLED_DYNAMIC(DGDS)
 	REGISTER_PLUGIN_DYNAMIC(DGDS, PLUGIN_TYPE_ENGINE, DgdsMetaEngine);
 #else
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index 7ee29f4e971..0b1ca895739 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -1811,11 +1811,6 @@ bool GDSScene::load(const Common::String &filename, ResourceManager *resourceMan
 
 
 bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor) {
-	// TODO: RST file format is also the original save game format, so this
-	// function could be used to load saves from the original games.
-	// The only thing to change would be supporting loading of sound bank
-	// and game time (which would need converting to our game time)
-
 	Common::SeekableReadStream *file = resourceManager->getResource(filename);
 	if (!file)
 		error("Game state data %s not found", filename.c_str());
@@ -1824,6 +1819,14 @@ bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *reso
 	if (magic != _magic)
 		error("%s file magic doesn't match game (%04X vs %04X)", filename.c_str(), magic, _magic);
 
+	loadGameStateFromFile(file, filename);
+
+	delete file;
+
+	return true;
+}
+
+void GDSScene::loadGameStateFromFile(Common::SeekableReadStream *file, const Common::String &filename) {
 	uint16 num = file->readUint16LE();
 	// Find matching game item and load its values
 	while (num && !file->eos()) {
@@ -1979,10 +1982,9 @@ bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *reso
 			num = triggers[t++];
 		}
 	}
-
-	return true;
 }
 
+
 void GDSScene::initIconSizes() {
 	const Common::SharedPtr<Image> icons = DgdsEngine::getInstance()->getIcons();
 	uint16 nicons = icons ? icons->getFrames().size() : 0;
diff --git a/engines/dgds/scene.h b/engines/dgds/scene.h
index 07079094f4d..29ca00a6a2a 100644
--- a/engines/dgds/scene.h
+++ b/engines/dgds/scene.h
@@ -216,6 +216,7 @@ public:
 
 	bool load(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor);
 	bool loadRestart(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor);
+	void loadGameStateFromFile(Common::SeekableReadStream *file, const Common::String &filename);
 	bool parse(Common::SeekableReadStream *s) override;
 	bool parseInf(Common::SeekableReadStream *s);
 	const Common::String &getIconFile() const { return _iconFile; }




More information about the Scummvm-git-logs mailing list