[Scummvm-git-logs] scummvm master -> c489eb2e50408c35fd6d604165c3a81d8de47b5a

elasota noreply at scummvm.org
Tue Jul 19 23:18:33 UTC 2022


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:
c489eb2e50 MTROPOLIS: Use pre-menu screenshot for savegame thumbnail in Obsidian


Commit: c489eb2e50408c35fd6d604165c3a81d8de47b5a
    https://github.com/scummvm/scummvm/commit/c489eb2e50408c35fd6d604165c3a81d8de47b5a
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-19T19:17:53-04:00

Commit Message:
MTROPOLIS: Use pre-menu screenshot for savegame thumbnail in Obsidian

Changed paths:
    engines/mtropolis/hacks.cpp
    engines/mtropolis/hacks.h
    engines/mtropolis/metaengine.cpp
    engines/mtropolis/modifiers.cpp
    engines/mtropolis/mtropolis.cpp
    engines/mtropolis/mtropolis.h
    engines/mtropolis/runtime.cpp
    engines/mtropolis/runtime.h
    engines/mtropolis/saveload.cpp
    engines/mtropolis/saveload.h


diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp
index d263bac2b61..2ab5807dcbf 100644
--- a/engines/mtropolis/hacks.cpp
+++ b/engines/mtropolis/hacks.cpp
@@ -22,6 +22,7 @@
 #include "common/system.h"
 #include "common/hashmap.h"
 
+#include "graphics/managed_surface.h"
 #include "graphics/surface.h"
 
 #include "mtropolis/assets.h"
@@ -364,6 +365,35 @@ void ObsidianRSGLogoWidescreenHooks::onCreate(Structural *structural) {
 	movie->setResizeFilter(Common::SharedPtr<MovieResizeFilter>(new ObsidianRSGLogoAnamorphicFilter()));
 }
 
+class ObsidianSaveScreenshotHooks : public SceneTransitionHooks {
+public:
+	void onSceneTransitionSetup(Runtime *runtime, const Common::WeakPtr<Structural> &oldScene, const Common::WeakPtr<Structural> &newScene) override;
+};
+
+void ObsidianSaveScreenshotHooks::onSceneTransitionSetup(Runtime *runtime, const Common::WeakPtr<Structural> &oldScene, const Common::WeakPtr<Structural> &newScene) {
+	Structural *newScenePtr = newScene.lock().get();
+
+	if (!newScenePtr)
+		return;
+
+	if (newScenePtr->getName() == "Game_Screen") {
+		Window *mainWindow = runtime->getMainWindow().lock().get();
+		if (mainWindow) {
+			Common::SharedPtr<Graphics::ManagedSurface> mainWindowSurface = mainWindow->getSurface();
+			Common::SharedPtr<Graphics::Surface> screenshot(new Graphics::Surface());
+			screenshot->copyFrom(*mainWindowSurface);
+
+			runtime->setSaveScreenshotOverride(screenshot);
+		}
+	} else {
+		runtime->setSaveScreenshotOverride(Common::SharedPtr<Graphics::Surface>());
+	}
+}
+
+void addObsidianQuirks(const MTropolisGameDescription &desc, Hacks &hacks) {
+	hacks.addSceneTransitionHooks(Common::SharedPtr<SceneTransitionHooks>(new ObsidianSaveScreenshotHooks()));
+}
+
 void addObsidianBugFixes(const MTropolisGameDescription &desc, Hacks &hacks) {
 	// Workaround for bug in Obsidian:
 	// When opening the journal in the intro, a script checks if cGSt.cfst.binjournal is false and if so,
diff --git a/engines/mtropolis/hacks.h b/engines/mtropolis/hacks.h
index 804e204ce60..8df373e9a99 100644
--- a/engines/mtropolis/hacks.h
+++ b/engines/mtropolis/hacks.h
@@ -63,6 +63,7 @@ struct Hacks {
 
 namespace HackSuites {
 
+void addObsidianQuirks(const MTropolisGameDescription &desc, Hacks &hacks);
 void addObsidianBugFixes(const MTropolisGameDescription &desc, Hacks &hacks);
 void addObsidianAutoSaves(const MTropolisGameDescription &desc, Hacks &hacks, IAutoSaveProvider *autoSaveProvider);
 void addObsidianImprovedWidescreen(const MTropolisGameDescription &desc, Hacks &hacks);
diff --git a/engines/mtropolis/metaengine.cpp b/engines/mtropolis/metaengine.cpp
index 11d99973d3f..107b787d609 100644
--- a/engines/mtropolis/metaengine.cpp
+++ b/engines/mtropolis/metaengine.cpp
@@ -19,19 +19,29 @@
  *
  */
 
+#include "common/translation.h"
+
 #include "engines/advancedDetector.h"
 
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymap.h"
 
-#include "common/translation.h"
+#include "graphics/scaler.h"
+#include "graphics/surface.h"
 
 #include "mtropolis/actions.h"
 #include "mtropolis/debug.h"
 #include "mtropolis/detection.h"
+#include "mtropolis/mtropolis.h"
 
 #include "mtropolis/mtropolis.h"
 
+namespace Graphics {
+
+struct Surface;
+
+} // End of namespace Graphics
+
 namespace MTropolis {
 
 uint32 MTropolisEngine::getGameID() const {
@@ -58,6 +68,8 @@ public:
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	Common::Array<Common::Keymap *> initKeymaps(const char *target) const override;
+
+	void getSavegameThumbnail(Graphics::Surface &thumb) override;
 };
 
 bool MTropolisMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -86,7 +98,7 @@ bool MTropolis::MTropolisEngine::hasFeature(EngineFeature f) const {
 }
 
 Common::Error MTropolisMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new MTropolis::MTropolisEngine(syst, (const MTropolis::MTropolisGameDescription *)desc);
+	*engine = new MTropolis::MTropolisEngine(syst, reinterpret_cast<const MTropolis::MTropolisGameDescription *>(desc));
 	return Common::kNoError;
 }
 
@@ -103,6 +115,96 @@ Common::Array<Common::Keymap *> MTropolisMetaEngine::initKeymaps(const char *tar
 	return Common::Keymap::arrayOf(keymap);
 }
 
+void MTropolisMetaEngine::getSavegameThumbnail(Graphics::Surface &thumb) {
+	const Graphics::Surface *savegameScreenshot = static_cast<MTropolis::MTropolisEngine *>(g_engine)->getSavegameScreenshot();
+
+	if (savegameScreenshot) {
+		int thumbnailWidth = kThumbnailWidth;
+		int thumbnailHeight = thumbnailWidth * savegameScreenshot->h / savegameScreenshot->w;
+		if (thumbnailHeight > kThumbnailHeight2) {
+			thumbnailHeight = kThumbnailHeight2;
+			thumbnailWidth = thumbnailHeight * savegameScreenshot->w / savegameScreenshot->h;
+		}
+
+		Common::SharedPtr<Graphics::Surface> outSurface(new Graphics::Surface());
+		outSurface->create(savegameScreenshot->w, savegameScreenshot->h, Graphics::createPixelFormat<888>());
+
+		for (int y = 0; y < savegameScreenshot->h; y++) {
+			for (int x = 0; x < savegameScreenshot->w; x++) {
+				uint8 r, g, b;
+				savegameScreenshot->format.colorToRGB(savegameScreenshot->getPixel(x, y), r, g, b);
+				outSurface->setPixel(x, y, outSurface->format.RGBToColor(r, g, b));
+			}
+		}
+
+		while (outSurface->w >= thumbnailWidth * 2) {
+			Common::SharedPtr<Graphics::Surface> temp(new Graphics::Surface());
+			temp->create(outSurface->w / 2, outSurface->h, Graphics::createPixelFormat<888>());
+
+			for (int y = 0; y < temp->h; y++) {
+				for (int x = 0; x < temp->w; x++) {
+					uint32 px1 = outSurface->getPixel(x * 2, y);
+					uint32 px2 = outSurface->getPixel(x * 2 + 1, y);
+
+					uint8 r1, g1, b1;
+					outSurface->format.colorToRGB(px1, r1, g1, b1);
+
+					uint8 r2, g2, b2;
+					outSurface->format.colorToRGB(px2, r2, g2, b2);
+
+					temp->setPixel(x, y, temp->format.RGBToColor((r1 + r2) >> 1, (g1 + g2) >> 1, (b1 + b2) >> 1));
+				}
+			}
+
+			outSurface = temp;
+		}
+
+		while (outSurface->h >= thumbnailHeight * 2) {
+			Common::SharedPtr<Graphics::Surface> temp(new Graphics::Surface());
+			temp->create(outSurface->w, outSurface->h / 2, Graphics::createPixelFormat<888>());
+
+			for (int y = 0; y < temp->h; y++) {
+				for (int x = 0; x < temp->w; x++) {
+					uint32 px1 = outSurface->getPixel(x, y * 2);
+					uint32 px2 = outSurface->getPixel(x, y * 2 + 1);
+
+					uint8 r1, g1, b1;
+					outSurface->format.colorToRGB(px1, r1, g1, b1);
+
+					uint8 r2, g2, b2;
+					outSurface->format.colorToRGB(px2, r2, g2, b2);
+
+					temp->setPixel(x, y, temp->format.RGBToColor((r1 + r2) >> 1, (g1 + g2) >> 1, (b1 + b2) >> 1));
+				}
+			}
+
+			outSurface = temp;
+		}
+
+		// TODO: Fix this for weird sizes
+		Common::SharedPtr<Graphics::Surface> changeTo16Temp = outSurface;
+		outSurface.reset(new Graphics::Surface());
+		outSurface->create(changeTo16Temp->w, changeTo16Temp->h, Graphics::createPixelFormat<565>());
+
+		for (int y = 0; y < outSurface->h; y++) {
+			for (int x = 0; x < outSurface->w; x++) {
+				uint32 px = changeTo16Temp->getPixel(x, y);
+
+				uint8 r, g, b;
+				changeTo16Temp->format.colorToRGB(px, r, g, b);
+
+				outSurface->setPixel(x, y, outSurface->format.RGBToColor(r, g, b));
+			}
+		}
+
+		changeTo16Temp.reset();
+
+		thumb.copyFrom(*outSurface);
+	} else {
+		AdvancedMetaEngine::getSavegameThumbnail(thumb);
+	}
+}
+
 #if PLUGIN_ENABLED_DYNAMIC(MTROPOLIS)
 REGISTER_PLUGIN_DYNAMIC(MTROPOLIS, PLUGIN_TYPE_ENGINE, MTropolisMetaEngine);
 #else
diff --git a/engines/mtropolis/modifiers.cpp b/engines/mtropolis/modifiers.cpp
index 845ffe04ef6..10291c26020 100644
--- a/engines/mtropolis/modifiers.cpp
+++ b/engines/mtropolis/modifiers.cpp
@@ -277,7 +277,7 @@ VThreadState SaveAndRestoreModifier::consumeMessage(Runtime *runtime, const Comm
 
 	if (_saveWhen.respondsTo(msg->getEvent())) {
 		CompoundVarSaver saver(obj);
-		if (runtime->getSaveProvider()->promptSave(&saver)) {
+		if (runtime->getSaveProvider()->promptSave(&saver, runtime->getSaveScreenshotOverride().get())) {
 			for (const Common::SharedPtr<SaveLoadHooks> &hooks : runtime->getHacks().saveLoadHooks)
 				hooks->onSave(runtime, this, static_cast<Modifier *>(obj));
 		}
diff --git a/engines/mtropolis/mtropolis.cpp b/engines/mtropolis/mtropolis.cpp
index 70d318f6b86..0b9e8e0f5de 100644
--- a/engines/mtropolis/mtropolis.cpp
+++ b/engines/mtropolis/mtropolis.cpp
@@ -119,6 +119,7 @@ Common::Error MTropolisEngine::run() {
 		preferredColorDepthMode = kColorDepthMode16Bit;
 		enhancedColorDepthMode = kColorDepthMode32Bit;
 
+		HackSuites::addObsidianQuirks(*_gameDescription, _runtime->getHacks());
 		HackSuites::addObsidianBugFixes(*_gameDescription, _runtime->getHacks());
 
 		if (ConfMan.getBool("mtropolis_mod_auto_save"))
diff --git a/engines/mtropolis/mtropolis.h b/engines/mtropolis/mtropolis.h
index 73dfac59ba3..c014eb939de 100644
--- a/engines/mtropolis/mtropolis.h
+++ b/engines/mtropolis/mtropolis.h
@@ -59,10 +59,12 @@ public:
 	uint16 getVersion() const;
 	Common::Platform getPlatform() const;
 
-	bool promptSave(ISaveWriter *writer) override;
+	bool promptSave(ISaveWriter *writer, const Graphics::Surface *screenshotOverride) override;
 	bool autoSave(ISaveWriter *writer) override;
 	bool promptLoad(ISaveReader *reader) override;
 
+	const Graphics::Surface *getSavegameScreenshot() const;
+
 public:
 	void handleEvents();
 
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index d994cba6973..c3503483e32 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -3728,6 +3728,10 @@ Runtime::SceneStackEntry::SceneStackEntry() {
 SceneTransitionHooks::~SceneTransitionHooks() {
 }
 
+
+void SceneTransitionHooks::onSceneTransitionSetup(Runtime *runtime, const Common::WeakPtr<Structural> &oldScene, const Common::WeakPtr<Structural> &newScene) {
+}
+
 void SceneTransitionHooks::onSceneTransitionEnded(Runtime *runtime, const Common::WeakPtr<Structural> &newScene) {
 }
 
@@ -4258,6 +4262,9 @@ void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structura
 
 	Common::SharedPtr<Structural> targetSharedScene = findDefaultSharedSceneForScene(targetScene.get());
 
+	for (const Common::SharedPtr<SceneTransitionHooks> &hooks : _hacks.sceneTransitionHooks)
+		hooks->onSceneTransitionSetup(this, _activeMainScene, targetScene);
+
 	if (targetScene == targetSharedScene)
 		error("Transitioned into a default shared scene, this is not supported");
 
@@ -5673,6 +5680,18 @@ const Common::String *Runtime::resolveAttributeIDName(uint32 attribID) const {
 		return &it->_value;
 }
 
+const Common::WeakPtr<Window> &Runtime::getMainWindow() const {
+	return _mainWindow;
+}
+
+const Common::SharedPtr<Graphics::Surface> &Runtime::getSaveScreenshotOverride() const {
+	return _saveScreenshotOverride;
+}
+
+void Runtime::setSaveScreenshotOverride(const Common::SharedPtr<Graphics::Surface> &screenshot) {
+	_saveScreenshotOverride = screenshot;
+}
+
 void Runtime::ensureMainWindowExists() {
 	// Maybe there's a better spot for this
 	if (_mainWindow.expired() && _project) {
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 684fcc599b8..1cfcb235d73 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -1472,6 +1472,7 @@ class SceneTransitionHooks {
 public:
 	virtual ~SceneTransitionHooks();
 
+	virtual void onSceneTransitionSetup(Runtime *runtime, const Common::WeakPtr<Structural> &oldScene, const Common::WeakPtr<Structural> &newScene);
 	virtual void onSceneTransitionEnded(Runtime *runtime, const Common::WeakPtr<Structural> &newScene);
 };
 
@@ -1595,6 +1596,11 @@ public:
 
 	const Common::String *resolveAttributeIDName(uint32 attribID) const;
 
+	const Common::WeakPtr<Window> &getMainWindow() const;
+
+	const Common::SharedPtr<Graphics::Surface> &getSaveScreenshotOverride() const;
+	void setSaveScreenshotOverride(const Common::SharedPtr<Graphics::Surface> &screenshot);
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	void debugSetEnabled(bool enabled);
 	void debugBreak();
@@ -1758,8 +1764,10 @@ private:
 	Scheduler _scheduler;
 	OSystem *_system;
 	Audio::Mixer *_mixer;
+
 	ISaveUIProvider *_saveProvider;
 	ILoadUIProvider *_loadProvider;
+	Common::SharedPtr<Graphics::Surface> _saveScreenshotOverride;
 
 	Common::SharedPtr<CursorGraphic> _lastFrameCursor;
 	Common::SharedPtr<CursorGraphic> _defaultCursor;
diff --git a/engines/mtropolis/saveload.cpp b/engines/mtropolis/saveload.cpp
index 0ae46092663..52ba0d41897 100644
--- a/engines/mtropolis/saveload.cpp
+++ b/engines/mtropolis/saveload.cpp
@@ -27,6 +27,7 @@
 #include "gui/saveload.h"
 
 #include "mtropolis/mtropolis.h"
+#include "mtropolis/render.h"
 #include "mtropolis/runtime.h"
 
 namespace MTropolis {
@@ -57,7 +58,7 @@ void SaveLoadHooks::onLoad(Runtime *runtime, Modifier *saveLoadModifier, Modifie
 void SaveLoadHooks::onSave(Runtime *runtime, Modifier *saveLoadModifier, Modifier *varModifier) {
 }
 
-bool MTropolisEngine::promptSave(ISaveWriter *writer) {
+bool MTropolisEngine::promptSave(ISaveWriter *writer, const Graphics::Surface *screenshotOverride) {
 	Common::String desc;
 	int slot;
 
@@ -159,4 +160,16 @@ bool MTropolisEngine::autoSave(ISaveWriter *writer) {
 	return true;
 }
 
+const Graphics::Surface *MTropolisEngine::getSavegameScreenshot() const {
+	const Graphics::Surface *screenshotOverride = _runtime->getSaveScreenshotOverride().get();
+	if (screenshotOverride)
+		return screenshotOverride;
+	else {
+		Window *mainWindow = _runtime->getMainWindow().lock().get();
+		if (!mainWindow)
+			return nullptr;
+		return mainWindow->getSurface().get()->surfacePtr();
+	}
+}
+
 } // End of namespace MTropolis
diff --git a/engines/mtropolis/saveload.h b/engines/mtropolis/saveload.h
index 6ef2e173799..ea9bed54f48 100644
--- a/engines/mtropolis/saveload.h
+++ b/engines/mtropolis/saveload.h
@@ -31,6 +31,12 @@ class WriteStream;
 
 } // End of namespace Common
 
+namespace Graphics {
+
+struct Surface;
+
+} // End of namespace Graphics
+
 namespace MTropolis {
 
 class Modifier;
@@ -46,7 +52,7 @@ struct ISaveReader : public IInterfaceBase {
 };
 
 struct ISaveUIProvider : public IInterfaceBase {
-	virtual bool promptSave(ISaveWriter *writer) = 0;
+	virtual bool promptSave(ISaveWriter *writer, const Graphics::Surface *screenshotOverride) = 0;
 };
 
 struct ILoadUIProvider : public IInterfaceBase {




More information about the Scummvm-git-logs mailing list