[Scummvm-git-logs] scummvm master -> 1ffbd7395903925a004b36319a94f75c38269ae3

scemino noreply at scummvm.org
Sat Mar 23 20:39:56 UTC 2024


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

Summary:
1ffbd73959 TWP: Improve savegames


Commit: 1ffbd7395903925a004b36319a94f75c38269ae3
    https://github.com/scummvm/scummvm/commit/1ffbd7395903925a004b36319a94f75c38269ae3
Author: scemino (scemino74 at gmail.com)
Date: 2024-03-23T21:38:43+01:00

Commit Message:
TWP: Improve savegames

Use ScummVM extended saves.
Add debug flag to support original savegames.

Changed paths:
    engines/twp/detection.cpp
    engines/twp/detection.h
    engines/twp/metaengine.cpp
    engines/twp/metaengine.h
    engines/twp/savegame.cpp
    engines/twp/savegame.h
    engines/twp/twp.cpp
    engines/twp/twp.h


diff --git a/engines/twp/detection.cpp b/engines/twp/detection.cpp
index 54b24c09aed..32bd08fe919 100644
--- a/engines/twp/detection.cpp
+++ b/engines/twp/detection.cpp
@@ -38,6 +38,7 @@ const DebugChannelDef TwpMetaEngineDetection::debugFlagList[] = {
 	{Twp::kDebugSndScript, "Sound", "Enable debug sound script dump"},
 	{Twp::kDebugGame, "Game", "Game debug level"},
 	{Twp::kDebugConsole, "imgui", "Show ImGui debug window (if available)"},
+	{Twp::kDebugSave, "Save", "Export savegame supported by the original game"},
 	DEBUG_CHANNEL_END};
 
 TwpMetaEngineDetection::TwpMetaEngineDetection()
diff --git a/engines/twp/detection.h b/engines/twp/detection.h
index d7db69c40dc..a15f129d34e 100644
--- a/engines/twp/detection.h
+++ b/engines/twp/detection.h
@@ -38,7 +38,8 @@ enum TwpDebugChannels {
 	kDebugActScript,
 	kDebugSndScript,
 	kDebugGame,
-	kDebugConsole
+	kDebugConsole,
+	kDebugSave
 };
 
 enum GameXorKey {
diff --git a/engines/twp/metaengine.cpp b/engines/twp/metaengine.cpp
index 704236407ca..819e8d3761e 100644
--- a/engines/twp/metaengine.cpp
+++ b/engines/twp/metaengine.cpp
@@ -39,6 +39,7 @@
 #include "twp/actions.h"
 #include "twp/debugtools.h"
 #include "twp/dialogs.h"
+#include "twp/twp.h"
 
 #define MAX_SAVES 99
 
@@ -47,7 +48,7 @@ const char *TwpMetaEngine::getName() const {
 }
 
 Common::Error TwpMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Twp::TwpEngine(syst, (const Twp::TwpGameDescription*)(desc));
+	*engine = new Twp::TwpEngine(syst, (const Twp::TwpGameDescription *)(desc));
 	return Common::kNoError;
 }
 
@@ -79,15 +80,17 @@ static Common::String getDesc(const Twp::SaveGame &savegame) {
 }
 
 SaveStateDescriptor TwpMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
-	Common::String filename = Common::String::format("%s.%03d", target, slot);
-	Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
+	SaveStateDescriptor desc = MetaEngine::querySaveMetaInfos(target, slot);
+	if (desc.isValid())
+		return desc;
 
+	Common::String name(getSavegameFile(slot, target));
+	Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(name);
 	if (f) {
-
-		Common::InSaveFile *thumbnailFile = g_system->getSavefileManager()->openForLoading(filename + ".png");
+		Common::InSaveFile *thumbnailFile = g_system->getSavefileManager()->openForLoading(name + ".png");
 
 		// Create the return descriptor
-		SaveStateDescriptor desc(this, slot, "?");
+		desc = SaveStateDescriptor(this, slot, "?");
 
 		if (thumbnailFile) {
 			Image::PNGDecoder png;
@@ -119,6 +122,10 @@ GUI::OptionsContainerWidget *TwpMetaEngine::buildEngineOptionsWidget(GUI::GuiObj
 	return widget;
 }
 
+void TwpMetaEngine::getSavegameThumbnail(Graphics::Surface &thumb) {
+	Twp::g_twp->capture(thumb, 160, 120);
+}
+
 Common::Array<Common::Keymap *> TwpMetaEngine::initKeymaps(const char *target) const {
 	Common::Keymap *engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, target, "Thimbleweed Park keymap");
 
diff --git a/engines/twp/metaengine.h b/engines/twp/metaengine.h
index 28fd0d5d1c0..0fdb84a8d6b 100644
--- a/engines/twp/metaengine.h
+++ b/engines/twp/metaengine.h
@@ -45,6 +45,8 @@ public:
 	GUI::OptionsContainerWidget *buildEngineOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
 
 	virtual Common::Array<Common::Keymap *> initKeymaps(const char *target) const override;
+
+	virtual void getSavegameThumbnail(Graphics::Surface &thumb) override;
 };
 
 #endif // TWP_METAENGINE_H
diff --git a/engines/twp/savegame.cpp b/engines/twp/savegame.cpp
index 610a3ec4567..b4d8514f4f9 100644
--- a/engines/twp/savegame.cpp
+++ b/engines/twp/savegame.cpp
@@ -386,18 +386,32 @@ static int32 computeHash(byte *data, size_t n) {
 	return result;
 }
 
-bool SaveGameManager::loadGame(const SaveGame &savegame) {
+bool SaveGameManager::loadGame(Common::SeekableReadStream &stream) {
+	Common::Array<byte> data(500016);
+	stream.read(data.data(), data.size());
+	Common::BTEACrypto::decrypt((uint32 *)data.data(), data.size() / 4, savegameKey);
+
+	MemStream ms;
+	if (!ms.open(data.data(), data.size() - 16))
+		return false;
+
+	GGHashMapDecoder decoder;
+	Common::JSONValue *jSavegame = decoder.open(&ms);
+	if (!jSavegame)
+		return false;
+
 	// dump savegame as json
 	if (DebugMan.isDebugChannelEnabled(kDebugGame)) {
-		debugC(kDebugGame, "load game: %s", savegame.jSavegame->stringify().c_str());
+		debugC(kDebugGame, "load game: %s", jSavegame->stringify().c_str());
 	}
 
-	const Common::JSONObject &json = savegame.jSavegame->asObject();
+	const Common::JSONObject &json = jSavegame->asObject();
 	long long int version = json["version"]->asIntegerNumber();
 	if (version != 2) {
 		error("Cannot load savegame version %lld", version);
 		return false;
 	}
+	uint32 gameTime = (uint32)json["gameTime"]->asNumber();
 
 	sqcall("preLoad");
 	loadGameScene(json["gameScene"]->asObject());
@@ -407,8 +421,8 @@ bool SaveGameManager::loadGame(const SaveGame &savegame) {
 	loadActors(json["actors"]->asObject());
 	loadInventory(json["inventory"]);
 	loadRooms(json["rooms"]->asObject());
-	g_twp->_time = json["gameTime"]->asNumber();
-	g_twp->setTotalPlayTime(savegame.gameTime * 1000);
+	g_twp->_time = (float)gameTime;
+	g_twp->setTotalPlayTime(gameTime * 1000);
 	g_twp->_inputState.setState((InputStateFlag)json["inputState"]->asIntegerNumber());
 	loadObjects(json["objects"]->asObject());
 	g_twp->setRoom(room(json["currentRoom"]->asString()), true);
diff --git a/engines/twp/savegame.h b/engines/twp/savegame.h
index 9285f5ffa39..4d0255cb23e 100644
--- a/engines/twp/savegame.h
+++ b/engines/twp/savegame.h
@@ -38,7 +38,7 @@ struct SaveGame {
 class SaveGameManager {
 public:
 	static bool getSaveGame(Common::SeekableReadStream *stream, SaveGame &savegame);
-	bool loadGame(const SaveGame &savegame);
+	bool loadGame(Common::SeekableReadStream &stream);
 	void saveGame(Common::WriteStream *stream);
 
 private:
diff --git a/engines/twp/twp.cpp b/engines/twp/twp.cpp
index d208e10fcca..76554dbee18 100644
--- a/engines/twp/twp.cpp
+++ b/engines/twp/twp.cpp
@@ -25,6 +25,7 @@
 #include "common/events.h"
 #include "common/savefile.h"
 #include "common/translation.h"
+#include "common/debug-channels.h"
 #include "engines/util.h"
 #include "graphics/cursorman.h"
 #include "graphics/screen.h"
@@ -1041,6 +1042,10 @@ Common::Error TwpEngine::run() {
 }
 
 Common::Error TwpEngine::loadGameState(int slot) {
+	Common::Error result = Engine::loadGameState(slot);
+	if (result.getCode() == Common::kNoError)
+		return Common::kNoError;
+
 	Common::InSaveFile *file = getSaveFileManager()->openRawFile(getSaveStateName(slot));
 	if (file) {
 		return loadGameStream(file);
@@ -1049,9 +1054,8 @@ Common::Error TwpEngine::loadGameState(int slot) {
 }
 
 Common::Error TwpEngine::loadGameStream(Common::SeekableReadStream *stream) {
-	SaveGame savegame;
-	if (_saveGameManager->getSaveGame(stream, savegame)) {
-		_saveGameManager->loadGame(savegame);
+	if (!_saveGameManager->loadGame(*stream)) {
+		return Common::kUnknownError;
 	}
 	return Common::kNoError;
 }
@@ -1061,22 +1065,28 @@ bool TwpEngine::canSaveGameStateCurrently(Common::U32String *msg) {
 }
 
 Common::Error TwpEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
-	Common::String name = getSaveStateName(slot);
-	Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(name, false);
-	if (!saveFile)
-		return Common::kWritingFailed;
-
-	Common::Error result = saveGameStream(saveFile, isAutosave);
-	if (result.getCode() == Common::kNoError) {
-		name = name + ".png";
-		Common::OutSaveFile *thumbnail = _saveFileMan->openForSaving(name, false);
-		g_twp->capture(*thumbnail, Math::Vector2d(320, 180));
-		thumbnail->finalize();
+	Common::Error result = Engine::saveGameState(slot, desc, isAutosave);
+	if (result.getCode() != Common::kNoError)
+		return result;
+
+	if (DebugMan.isDebugChannelEnabled(kDebugSave)) {
+		Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(Common::String::format("Savegame%d.save", slot), false);
+		if (!saveFile)
+			return Common::kWritingFailed;
+
+		result = saveGameStream(saveFile, isAutosave);
+		if (result.getCode() == Common::kNoError) {
+			Common::OutSaveFile *thumbnail = _saveFileMan->openForSaving(Common::String::format("Savegame%d.png", slot), false);
+			Graphics::Surface surface;
+			g_twp->capture(surface, 320, 180);
+			Image::writePNG(*thumbnail, surface);
+			thumbnail->finalize();
+			delete thumbnail;
+		}
 
 		saveFile->finalize();
+		delete saveFile;
 	}
-
-	delete saveFile;
 	return result;
 }
 
@@ -1774,7 +1784,7 @@ Scaling *TwpEngine::getScaling(const Common::String &name) {
 	return nullptr;
 }
 
-void TwpEngine::capture(Common::WriteStream &stream, Math::Vector2d size) {
+void TwpEngine::capture(Graphics::Surface &surface, int width, int height) {
 	// render scene into texture
 	Common::Array<byte> data;
 	RenderTexture rt(Math::Vector2d(SCREEN_WIDTH, SCREEN_HEIGHT));
@@ -1788,11 +1798,10 @@ void TwpEngine::capture(Common::WriteStream &stream, Math::Vector2d size) {
 	Graphics::Surface s;
 	s.init(SCREEN_WIDTH, SCREEN_HEIGHT, 4 * SCREEN_WIDTH, data.data(), fmt);
 	s.flipVertical(Common::Rect(s.w, s.h));
-	Graphics::Surface *scaledSurface = s.scale(size.getX(), size.getY());
 
+	Graphics::Surface *scaledSurface = s.scale(width, height);
 	// and save to stream
-	Image::writePNG(stream, s);
-
+	surface.copyFrom(*scaledSurface);
 	delete scaledSurface;
 }
 
diff --git a/engines/twp/twp.h b/engines/twp/twp.h
index 58426b5174b..b9e61b74428 100644
--- a/engines/twp/twp.h
+++ b/engines/twp/twp.h
@@ -129,7 +129,7 @@ public:
 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	bool canSaveAutosaveCurrently() override { return false; }
-	void capture(Common::WriteStream &stream, Math::Vector2d size);
+	void capture(Graphics::Surface &surface, int width, int height);
 
 	Math::Vector2d winToScreen(Math::Vector2d pos);
 	Math::Vector2d roomToScreen(Math::Vector2d pos);




More information about the Scummvm-git-logs mailing list