[Scummvm-git-logs] scummvm master -> 09729ac9de48e6f8da9541af10e4b9bb84786c3f

sev- noreply at scummvm.org
Sun Jun 30 16:39:23 UTC 2024


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

Summary:
98d6f155d2 ENGINES: Split Engine::createInstance in two
90b886097f ENGINES: Create a type aware advanced detector
b61bd3ff85 ENGINES: Create a type aware advanced meta engine
a7d0db4947 ENGINES: Let MetaEngine delete the engine
7e0048b4a3 ENGINES: Add ADDynamicGameDescription class
37de547ec1 ENGINES: Make AdvancedMetaEngine use ADDynamicGameDescription
ab4d6db36b GLK: Split detection from running
2645b1431c PLUGINS: Rename findPlugin to findDetectionPlugin
5ded4aedec PLUGINS: Don't call plugin->getType repeatedly
c93f53b491 PLUGINS: Rename getEngineFromMetaEngine to getEngineFromDetectionPlugin
ebdcf6ccd6 ENGINES: Mark getName() functions as overrides
c9d701884b PLUGINS: Reset pointer after deletion
93b10df84a PLUGINS: Rework (un)loading of detection plugin
2575cdacff PLUGINS: Cleanup when destroying PluginManagerUncached
55ac8ba07f PLUGINS: Remove default value for EngineMan::getPlugins argument
05a62249a9 PLUGINS: hide unloadAllPlugins from outside of PluginManager
a1193a02eb PLUGINS: Make findEnginePlugin publicly available
885208e8f2 BASE: Split listSaves in two parts
d01827b509 GUI: Make auto saves update check work with PluginManagerUncached
1c1667bf68 GUI: Fix listing of available engines when using uncached plugins
16e72ad181 GUI: Make listing saves not depend on detection
a835803695 GUI: Make engine options not depend on detection plugin
bef5e4e0a5 GUI: Make EventRecorder not use detection to find engine plugin
21bd468b9a SCI: Simplify engine plugin search
310063af6c WINTERMUTE: Simplify engine plugin search
a92dab8a8c BASE: Unload detection plugin before running game
07daa6c225 ENGINES: Simplify EngineManager::findTarget
5169a395a5 PLUGINS: Remove now useless functions
b07a9388a4 ENGINES: Remove now useless Engine::getMetaEngineDetection
a4fb9d6145 PLUGINS: Unload engine plugins while loading detection
ca2c49476f GUI: Avoid engine plugin unload while creating AboutDialog
34108724ed ENGINES: Factorize sizing and writing functions for dynamic descriptions
d0e0ff60c5 GUI: Don't list available engines if this is too slow
09729ac9de PLUGINS: Use override keyword


Commit: 98d6f155d2495a845205531a58e8cfd0781d0908
    https://github.com/scummvm/scummvm/commit/98d6f155d2495a845205531a58e8cfd0781d0908
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Split Engine::createInstance in two

This brings a cleaner separation between AdvancedMetaEngineDetection and
AdvancedMetaEngine.

Changed paths:
    base/main.cpp
    engines/advancedDetector.cpp
    engines/advancedDetector.h
    engines/agos/detection.cpp
    engines/agos/metaengine.cpp
    engines/glk/detection.cpp
    engines/glk/detection.h
    engines/glk/metaengine.cpp
    engines/gob/detection/detection.cpp
    engines/gob/metaengine.cpp
    engines/grim/detection.cpp
    engines/grim/metaengine.cpp
    engines/metaengine.h
    engines/scumm/detection.cpp
    engines/scumm/metaengine.cpp
    engines/scumm/metaengine.h
    engines/sky/detection.cpp
    engines/sky/metaengine.cpp
    engines/sword1/detection.cpp
    engines/sword1/metaengine.cpp
    engines/sword2/detection.cpp
    engines/sword2/metaengine.cpp


diff --git a/base/main.cpp b/base/main.cpp
index f70085737e5..54ec0925956 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -120,7 +120,9 @@ static bool launcherDialog() {
 	return status;
 }
 
-static const Plugin *detectPlugin() {
+static Common::Error identifyGame(const Common::String &debugLevels, const Plugin **detectionPlugin, DetectedGame &game, const void **descriptor) {
+	assert(detectionPlugin);
+
 	// Figure out the engine ID and game ID
 	Common::String engineId = ConfMan.get("engineid");
 	Common::String gameId = ConfMan.get("gameid");
@@ -131,31 +133,39 @@ static const Plugin *detectPlugin() {
 	// At this point the engine ID and game ID must be known
 	if (engineId.empty()) {
 		warning("The engine ID is not set for target '%s'", ConfMan.getActiveDomainName().c_str());
-		return nullptr;
+		return Common::kUnknownError;
 	}
 
 	if (gameId.empty()) {
 		warning("The game ID is not set for target '%s'", ConfMan.getActiveDomainName().c_str());
-		return nullptr;
+		return Common::kUnknownError;
 	}
 
-	const Plugin *plugin = EngineMan.findPlugin(engineId);
-	if (!plugin) {
+	*detectionPlugin = EngineMan.findPlugin(engineId);
+	if (!*detectionPlugin) {
 		warning("'%s' is an invalid engine ID. Use the --list-engines command to list supported engine IDs", engineId.c_str());
-		return nullptr;
+		return Common::kMetaEnginePluginNotFound;
 	}
-
 	// Query the plugin for the game descriptor
-	const MetaEngineDetection &metaEngine = plugin->get<MetaEngineDetection>();
-	printf("   Looking for a plugin supporting this target... %s\n", metaEngine.getEngineName());
+	MetaEngineDetection &metaEngine = (*detectionPlugin)->get<MetaEngineDetection>();
+
+	// before doing anything, we register the debug channels of the (Meta)Engine(Detection)
 	DebugMan.addAllDebugChannels(metaEngine.getDebugChannels());
-	PlainGameDescriptor game = metaEngine.findGame(gameId.c_str());
-	if (!game.gameId) {
-		warning("'%s' is an invalid game ID for the engine '%s'. Use the --list-games option to list supported game IDs", gameId.c_str(), engineId.c_str());
-		return nullptr;
+	// Setup now the debug channels
+	Common::StringTokenizer tokenizer(debugLevels, " ,");
+	while (!tokenizer.empty()) {
+		Common::String token = tokenizer.nextToken();
+		if (token.equalsIgnoreCase("all"))
+			DebugMan.enableAllDebugChannels();
+		else if (!DebugMan.enableDebugChannel(token))
+			warning("Engine does not support debug level '%s'", token.c_str());
 	}
 
-	return plugin;
+	Common::Error result = metaEngine.identifyGame(game, descriptor);
+	if (result.getCode() != Common::kNoError) {
+		warning("Couldn't identify game '%s' for the engine '%s'.", gameId.c_str(), engineId.c_str());
+	}
+	return result;
 }
 
 void saveLastLaunchedTarget(const Common::String &target) {
@@ -168,8 +178,7 @@ void saveLastLaunchedTarget(const Common::String &target) {
 }
 
 // TODO: specify the possible return values here
-static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, OSystem &system, const Common::String &debugLevels) {
-	assert(plugin);
+static Common::Error runGame(const Plugin *enginePlugin, OSystem &system, const DetectedGame &game, const void *meDescriptor) {
 	assert(enginePlugin);
 
 	// Determine the game data path, for validation and error messages
@@ -198,23 +207,6 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 		err = Common::kPathNotDirectory;
 	}
 
-	// Create the game's MetaEngineDetection.
-	const MetaEngineDetection &metaEngineDetection = plugin->get<MetaEngineDetection>();
-
-	// before we instantiate the engine, we register debug channels for it
-	DebugMan.addAllDebugChannels(metaEngineDetection.getDebugChannels());
-
-	// On creation the engine should have set up all debug levels so we can use
-	// the command line arguments here
-	Common::StringTokenizer tokenizer(debugLevels, " ,");
-	while (!tokenizer.empty()) {
-		Common::String token = tokenizer.nextToken();
-		if (token.equalsIgnoreCase("all"))
-			DebugMan.enableAllDebugChannels();
-		else if (!DebugMan.enableDebugChannel(token))
-			warning("Engine does not support debug level '%s'", token.c_str());
-	}
-
 	// Create the game's MetaEngine.
 	MetaEngine &metaEngine = enginePlugin->get<MetaEngine>();
 	if (err.getCode() == Common::kNoError) {
@@ -222,17 +214,16 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 		// Apparently some engines query them in their constructor, thus we
 		// need to set this up before instance creation.
 		metaEngine.registerDefaultSettings(target);
+		err = metaEngine.createInstance(&system, &engine, game, meDescriptor);
 	}
 
-	err = metaEngine.createInstance(&system, &engine);
-
 	// Check for errors
 	if (!engine || err.getCode() != Common::kNoError) {
 
 		// Print a warning; note that scummvm_main will also
 		// display an error dialog, so we don't have to do this here.
 		warning("%s failed to instantiate engine: %s (target '%s', path '%s')",
-			metaEngineDetection.getEngineName(),
+			game.engineId.c_str(),
 			err.getDesc().c_str(),
 			target.c_str(),
 			dir.getPath().toString(Common::Path::kNativeSeparator).c_str()
@@ -245,7 +236,6 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 			ConfMan.removeGameDomain(target.c_str());
 		}
 
-		DebugMan.removeAllDebugChannels();
 		return err;
 	}
 
@@ -255,13 +245,8 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 	// Set the window caption to the game name
 	Common::String caption(ConfMan.get("description"));
 
-	if (caption.empty()) {
-		// here, we don't need to set the debug channels because it has been set earlier
-		PlainGameDescriptor game = metaEngineDetection.findGame(ConfMan.get("gameid").c_str());
-		if (game.description) {
-			caption = game.description;
-		}
-	}
+	if (caption.empty())
+		caption = game.description;
 	if (caption.empty())
 		caption = target;
 	if (!caption.empty())	{
@@ -338,8 +323,6 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 	// Free up memory
 	delete engine;
 
-	DebugMan.removeAllDebugChannels();
-
 	// Reset the file/directory mappings
 	SearchMan.clear();
 
@@ -760,14 +743,21 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 		EngineMan.upgradeTargetIfNecessary(ConfMan.getActiveDomainName());
 
 		// Try to find a MetaEnginePlugin which feels responsible for the specified game.
-		const Plugin *plugin = detectPlugin();
-
-		// Then, get the relevant Engine plugin from MetaEngine.
 		const Plugin *enginePlugin = nullptr;
-		if (plugin)
+		const Plugin *plugin = nullptr;
+		DetectedGame game;
+		const void *meDescriptor = nullptr;
+		Common::Error result = identifyGame(specialDebug, &plugin, game, &meDescriptor);
+
+		if (result.getCode() == Common::kNoError) {
+			// Then, get the relevant Engine plugin from MetaEngine.
 			enginePlugin = PluginMan.getEngineFromMetaEngine(plugin);
+			if (enginePlugin == nullptr) {
+				result = Common::kEnginePluginNotFound;
+			}
+		}
 
-		if (enginePlugin) {
+		if (result.getCode() == Common::kNoError) {
 			// Unload all plugins not needed for this game, to save memory
 			// Right now, we have a MetaEngine plugin, and we want to unload all except Engine.
 
@@ -795,6 +785,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 				Common::PlaybackFile record;
 				record.openRead(recordFileName);
 				debug("info:author=%s name=%s description=%s", record.getHeader().author.c_str(), record.getHeader().name.c_str(), record.getHeader().description.c_str());
+
+				DebugMan.removeAllDebugChannels();
 				break;
 			}
 #endif
@@ -803,11 +795,13 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 				ttsMan->pushState();
 			}
 			// Try to run the game
-			Common::Error result = runGame(plugin, enginePlugin, system, specialDebug);
+			result = runGame(enginePlugin, system, game, meDescriptor);
 			if (ttsMan != nullptr) {
 				ttsMan->popState();
 			}
 
+			DebugMan.removeAllDebugChannels();
+
 #ifdef ENABLE_EVENTRECORDER
 			// Flush Event recorder file. The recorder does not get reinitialized for next game
 			// which is intentional. Only single game per session is allowed.
@@ -874,6 +868,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 			PluginManager::instance().loadAllPluginsOfType(PLUGIN_TYPE_ENGINE); // only for cached manager
 			PluginManager::instance().loadDetectionPlugin(); // only for uncached manager
 		} else {
+			DebugMan.removeAllDebugChannels();
+
 			GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game"));
 
 			// Clear the active domain
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index ad91a40ffe7..6bdd35d3c70 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -334,9 +334,7 @@ const ExtraGuiOptions AdvancedMetaEngine::getExtraGuiOptions(const Common::Strin
 	return options;
 }
 
-Common::Error AdvancedMetaEngineDetection::createInstance(OSystem *syst, Engine **engine) {
-	assert(engine);
-
+Common::Error AdvancedMetaEngineDetection::identifyGame(DetectedGame &game, const void **descriptor) {
 	Common::Language language = Common::UNK_LANG;
 	Common::Platform platform = Common::kPlatformUnknown;
 	Common::String extra;
@@ -406,73 +404,25 @@ Common::Error AdvancedMetaEngineDetection::createInstance(OSystem *syst, Engine
 		}
 	}
 
-	if (!agdDesc.desc)
-		return Common::kNoGameDataFoundError;
-
-	DetectedGame gameDescriptor = toDetectedGame(agdDesc);
-
 	// Detection is done, no need to keep archives in memory anymore
 	ADCacheMan.clearArchives();
 
-	// If the GUI options were updated, we catch this here and update them in the users config
-	// file transparently.
-	ConfMan.setAndFlush("guioptions", gameDescriptor.getGUIOptions());
-
-	bool showTestingWarning = false;
-
-#ifdef RELEASE_BUILD
-	showTestingWarning = true;
-#endif
-
-	if (((gameDescriptor.gameSupportLevel == kUnstableGame
-			|| (gameDescriptor.gameSupportLevel == kTestingGame
-					&& showTestingWarning)))
-			&& !Engine::warnUserAboutUnsupportedGame())
-		return Common::kUserCanceled;
-
-	if (gameDescriptor.gameSupportLevel == kWarningGame
-			&& !Engine::warnUserAboutUnsupportedGame(gameDescriptor.extra))
-		return Common::kUserCanceled;
-
-	if (gameDescriptor.gameSupportLevel == kUnsupportedGame) {
-		Engine::errorUnsupportedGame(gameDescriptor.extra);
-		return Common::kUserCanceled;
-	}
-
-	debug("Running %s", gameDescriptor.description.c_str());
-	Common::Array<Common::Path> filenames;
-	for (FilePropertiesMap::const_iterator i = gameDescriptor.matchedFiles.begin(); i != gameDescriptor.matchedFiles.end(); ++i) {
-		filenames.push_back(i->_key);
-	}
-	Common::sort(filenames.begin(), filenames.end());
-	for (uint i = 0; i < filenames.size(); ++i) {
-		const FileProperties &file = gameDescriptor.matchedFiles[filenames[i]];
-		debug("%s: %s, %llu bytes.", filenames[i].toString().c_str(), file.md5.c_str(), (unsigned long long)file.size);
-	}
-	initSubSystems(agdDesc.desc);
+	if (!agdDesc.desc)
+		return Common::kNoGameDataFoundError;
 
-	PluginList pl = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
-	Plugin *plugin = nullptr;
+	// We can't add search directories from AdvancedMetaEngine
+	if (_flags & kADFlagMatchFullPaths) {
+		Common::StringArray dirs = getPathsFromEntry(agdDesc.desc);
+		Common::FSNode gameDataDir = Common::FSNode(ConfMan.getPath("path"));
 
-	// By this point of time, we should have only one plugin in memory.
-	if (pl.size() == 1) {
-		plugin = pl[0];
+		for (auto d = dirs.begin(); d != dirs.end(); ++d)
+			SearchMan.addSubDirectoryMatching(gameDataDir, *d, 0, _fullPathGlobsDepth);
 	}
 
-	if (plugin) {
-		if (_flags & kADFlagMatchFullPaths) {
-			Common::StringArray dirs = getPathsFromEntry(agdDesc.desc);
-			Common::FSNode gameDataDir = Common::FSNode(ConfMan.getPath("path"));
-
-			for (auto d = dirs.begin(); d != dirs.end(); ++d)
-				SearchMan.addSubDirectoryMatching(gameDataDir, *d, 0, _fullPathGlobsDepth);
-		}
+	game = toDetectedGame(agdDesc);
+	*descriptor = agdDesc.desc;
 
-		// Call child class's createInstanceMethod.
-		return plugin->get<AdvancedMetaEngine>().createInstance(syst, engine, agdDesc.desc);
-	}
-
-	return Common::Error(Common::kEnginePluginNotFound);
+	return Common::kNoError;
 }
 
 void AdvancedMetaEngineDetection::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::Path &parentName) const {
@@ -1027,14 +977,6 @@ AdvancedMetaEngineDetection::AdvancedMetaEngineDetection(const void *descs, uint
 		_grayListMap.setVal(*f, true);
 }
 
-void AdvancedMetaEngineDetection::initSubSystems(const ADGameDescription *gameDesc) const {
-#ifdef ENABLE_EVENTRECORDER
-	if (gameDesc) {
-		g_eventRec.processGameDescription(gameDesc);
-	}
-#endif
-}
-
 void AdvancedMetaEngineDetection::preprocessDescriptions() {
 	if (_hashMapsInited)
 		return;
@@ -1133,18 +1075,6 @@ bool AdvancedMetaEngineDetection::isEntryGrayListed(const ADGameDescription *g)
 	return (grayIsPresent && !nonGrayIsPresent);
 }
 
-Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) {
-	PluginList pl = PluginMan.getPlugins(PLUGIN_TYPE_ENGINE);
-	if (pl.size() == 1) {
-		const Plugin *metaEnginePlugin = PluginMan.getMetaEngineFromEngine(pl[0]);
-		if (metaEnginePlugin) {
-			return metaEnginePlugin->get<AdvancedMetaEngineDetection>().createInstance(syst, engine);
-		}
-	}
-
-	return Common::Error();
-}
-
 void AdvancedMetaEngineDetection::detectClashes() const {
 	// First, check that we do not have duplicated entries in _gameIds
 	Common::HashMap<Common::String, int, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> idsMap;
@@ -1197,6 +1127,59 @@ void AdvancedMetaEngineDetection::detectClashes() const {
 	}
 }
 
+Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine, const DetectedGame &gameDescriptor, const void *meDescriptor) {
+	assert(engine);
+
+	const ADGameDescription *adgDesc = (const ADGameDescription *)meDescriptor;
+
+	// If the GUI options were updated, we catch this here and update them in the users config
+	// file transparently.
+	ConfMan.setAndFlush("guioptions", gameDescriptor.getGUIOptions());
+
+	bool showTestingWarning = false;
+
+#ifdef RELEASE_BUILD
+	showTestingWarning = true;
+#endif
+
+	if (((gameDescriptor.gameSupportLevel == kUnstableGame
+			|| (gameDescriptor.gameSupportLevel == kTestingGame
+					&& showTestingWarning)))
+			&& !Engine::warnUserAboutUnsupportedGame())
+		return Common::kUserCanceled;
+
+	if (gameDescriptor.gameSupportLevel == kWarningGame
+			&& !Engine::warnUserAboutUnsupportedGame(gameDescriptor.extra))
+		return Common::kUserCanceled;
+
+	if (gameDescriptor.gameSupportLevel == kUnsupportedGame) {
+		Engine::errorUnsupportedGame(gameDescriptor.extra);
+		return Common::kUserCanceled;
+	}
+
+	debug("Running %s", gameDescriptor.description.c_str());
+	Common::Array<Common::Path> filenames;
+	for (FilePropertiesMap::const_iterator i = gameDescriptor.matchedFiles.begin(); i != gameDescriptor.matchedFiles.end(); ++i) {
+		filenames.push_back(i->_key);
+	}
+	Common::sort(filenames.begin(), filenames.end());
+	for (uint i = 0; i < filenames.size(); ++i) {
+		const FileProperties &file = gameDescriptor.matchedFiles[filenames[i]];
+		debug("%s: %s, %llu bytes.", filenames[i].toString().c_str(), file.md5.c_str(), (unsigned long long)file.size);
+	}
+	initSubSystems(adgDesc);
+
+	return createInstance(syst, engine, adgDesc);
+}
+
+void AdvancedMetaEngine::initSubSystems(const ADGameDescription *gameDesc) const {
+#ifdef ENABLE_EVENTRECORDER
+	if (gameDesc) {
+		g_eventRec.processGameDescription(gameDesc);
+	}
+#endif
+}
+
 bool AdvancedMetaEngine::checkExtendedSaves(MetaEngineFeature f) const {
 	return (f == kSavesUseExtendedFormat) ||
 		(f == kSimpleSavesNames) ||
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index eb22b435fe0..88904cdaaf2 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -377,6 +377,9 @@ public:
 	/** Query the engine for a @ref PlainGameDescriptor for the specified gameid, if any. */
 	PlainGameDescriptor findGame(const char *gameId) const override;
 
+	/** Identify the active game and check its data files. */
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override;
+
 	/**
 	 * Run the engine's game detector on the given list of files, and return a
 	 * (possibly empty) list of games supported by the engine that were
@@ -384,16 +387,6 @@ public:
 	 */
 	DetectedGames detectGames(const Common::FSList &fslist, uint32 skipADFlags, bool skipIncomplete) override;
 
-	/**
-	 * A generic createInstance.
-	 *
-	 * For instantiating engine objects, this method is called first,
-	 * and then the subclass implemented createInstance is called from within.
-	 */
-	Common::Error createInstance(OSystem *syst, Engine **engine);
-
-	static Common::StringArray getPathsFromEntry(const ADGameDescription *g);
-
 	uint getMD5Bytes() const override final { return _md5Bytes; }
 
 	int getGameVariantCount() const override final {
@@ -420,8 +413,8 @@ protected:
 	}
 
 private:
-	void initSubSystems(const ADGameDescription *gameDesc) const;
 	void preprocessDescriptions();
+	static Common::StringArray getPathsFromEntry(const ADGameDescription *g);
 	bool isEntryGrayListed(const ADGameDescription *g) const;
 	void detectClashes() const;
 
@@ -494,7 +487,7 @@ public:
 	 * By the time this is called, it is assumed that there is only one
 	 * plugin engine loaded in memory.
 	 */
-	Common::Error createInstance(OSystem *syst, Engine **engine) override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) override;
 
 	/**
 	 * A createInstance implementation for subclasses. To be called after the base
@@ -568,6 +561,9 @@ protected:
 	 * extended save format to work
 	 */
 	bool checkExtendedSaves(MetaEngineFeature f) const;
+
+private:
+	void initSubSystems(const ADGameDescription *gameDesc) const;
 };
 
 /**
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 376137e7567..de10e1c9b84 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -85,6 +85,11 @@ public:
 		return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
 	}
 
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override {
+		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+		return AdvancedMetaEngineDetection::identifyGame(game, descriptor);
+	}
+
 	const char *getName() const override {
 		return "agos";
 	}
diff --git a/engines/agos/metaengine.cpp b/engines/agos/metaengine.cpp
index 49a5d31bce1..50ec2079d6c 100644
--- a/engines/agos/metaengine.cpp
+++ b/engines/agos/metaengine.cpp
@@ -30,12 +30,10 @@
 #include "backends/keymapper/standard-actions.h"
 
 #include "engines/advancedDetector.h"
-#include "engines/obsolete.h"
 
 #include "agos/intern.h"
 #include "agos/agos.h"
 #include "agos/detection.h"
-#include "agos/obsolete.h"
 
 namespace AGOS {
 
@@ -123,10 +121,6 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override {
-		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
-		return AdvancedMetaEngine::createInstance(syst, engine);
-	}
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index fe87cca019b..73ee57f0e0e 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -178,6 +178,12 @@ PlainGameDescriptor GlkMetaEngineDetection::findGame(const char *gameId) const {
 
 #undef FIND_GAME
 
+Common::Error GlkMetaEngineDetection::identifyGame(DetectedGame &game, const void **descriptor) {
+	*descriptor = nullptr;
+	game = DetectedGame(getName(), findGame(ConfMan.get("gameid").c_str()));
+	return game.gameId.empty() ? Common::kUnknownError : Common::kNoError;
+}
+
 DetectedGames GlkMetaEngineDetection::detectGames(const Common::FSList &fslist, uint32 /*skipADFlags*/, bool /*skipIncomplete*/) {
 #ifndef RELEASE_BUILD
 	// This is as good a place as any to detect multiple sub-engines using the same Ids
diff --git a/engines/glk/detection.h b/engines/glk/detection.h
index ca637ca0213..172bae62913 100644
--- a/engines/glk/detection.h
+++ b/engines/glk/detection.h
@@ -63,6 +63,8 @@ public:
 	 */
 	PlainGameDescriptor findGame(const char *gameId) const override;
 
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override;
+
 	/**
 	 * Calls each sub-engine in turn to ensure no game Id accidentally shares the same Id
 	 */
diff --git a/engines/glk/metaengine.cpp b/engines/glk/metaengine.cpp
index 3831e8fe367..7ec639a884e 100644
--- a/engines/glk/metaengine.cpp
+++ b/engines/glk/metaengine.cpp
@@ -81,7 +81,8 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine) override;
+	Common::Error createInstance(OSystem *syst, Engine **engine,
+	                             const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) override;
 
 	const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const override;
 
@@ -164,7 +165,8 @@ Common::String GlkMetaEngine::findFileByGameId(const Common::String &gameId) con
 	return Common::String();
 }
 
-Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) {
+Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine,
+		const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) {
 #ifndef RELEASE_BUILD
 	Glk::GameDescriptor td = Glk::GameDescriptor::empty();
 #endif
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
index 29264be19fd..3e3d00f3240 100644
--- a/engines/gob/detection/detection.cpp
+++ b/engines/gob/detection/detection.cpp
@@ -59,6 +59,11 @@ public:
 		return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
 	}
 
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override {
+		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+		return AdvancedMetaEngineDetection::identifyGame(game, descriptor);
+	}
+
 	const char *getName() const override {
 		return "gob";
 	}
diff --git a/engines/gob/metaengine.cpp b/engines/gob/metaengine.cpp
index cb26adf59b7..6f23fc1b8d3 100644
--- a/engines/gob/metaengine.cpp
+++ b/engines/gob/metaengine.cpp
@@ -26,13 +26,11 @@
  */
 
 #include "engines/advancedDetector.h"
-#include "engines/obsolete.h"
 
 #include "common/translation.h"
 
 #include "gob/gameidtotype.h"
 #include "gob/gob.h"
-#include "gob/obsolete.h"
 
 // For struct GOBGameDescription.
 #include "gob/detection/detection.h"
@@ -60,11 +58,6 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override {
-		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
-		return AdvancedMetaEngine::createInstance(syst, engine);
-	}
-
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
diff --git a/engines/grim/detection.cpp b/engines/grim/detection.cpp
index 0901893be6c..b40ba328536 100644
--- a/engines/grim/detection.cpp
+++ b/engines/grim/detection.cpp
@@ -704,6 +704,11 @@ public:
 		return Engines::findGameID(gameid, _gameIds, obsoleteGameIDsTable);
 	}
 
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override {
+		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+		return AdvancedMetaEngineDetection::identifyGame(game, descriptor);
+	}
+
 	const char *getEngineName() const override {
 		return "Grim";
 	}
diff --git a/engines/grim/metaengine.cpp b/engines/grim/metaengine.cpp
index fd9082a4ec1..6cacfe35493 100644
--- a/engines/grim/metaengine.cpp
+++ b/engines/grim/metaengine.cpp
@@ -67,11 +67,6 @@ public:
 		return gameGuiOptions;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override {
-		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
-		return AdvancedMetaEngine::createInstance(syst, engine);
-	}
-
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	bool hasFeature(MetaEngineFeature f) const override;
diff --git a/engines/metaengine.h b/engines/metaengine.h
index cc07e9fe1d1..b57ca738681 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -142,6 +142,9 @@ public:
 	/** Query the engine for a PlainGameDescriptor for the specified gameid, if any. */
 	virtual PlainGameDescriptor findGame(const char *gameId) const = 0;
 
+	/** Identify the active game and check its data files. */
+	virtual Common::Error identifyGame(DetectedGame &game, const void **descriptor) = 0;
+
 	/**
 	 * Run the engine's game detector on the given list of files, and return a
 	 * (possibly empty) list of games supported by the engine that were
@@ -241,13 +244,16 @@ public:
 	 * The MetaEngine queries the ConfMan singleton for data like the target,
 	 * gameid, path etc.
 	 *
-	 * @param syst    Pointer to the global OSystem object.
-	 * @param engine  Pointer to a pointer that the MetaEngine sets to
-	 *                the newly created Engine, or 0 in case of an error.
+	 * @param syst            Pointer to the global OSystem object.
+	 * @param engine          Pointer to a pointer that the MetaEngine sets to
+	 *                        the newly created Engine, or 0 in case of an error.
+	 * @param gameDescriptor  Detected game as returned by MetaEngineDetection::identifyGame
+	 * @param meDescriptor    Pointer to a meta engine specific descriptor as returned by
+	 *                        MetaEngineDetection::identifyGame
 	 *
 	 * @return A Common::Error describing the error that occurred, or kNoError.
 	 */
-	virtual Common::Error createInstance(OSystem *syst, Engine **engine) = 0;
+	virtual Common::Error createInstance(OSystem *syst, Engine **engine, const DetectedGame &gameDescriptor, const void *meDescriptor) = 0;
 
 	/**
 	 * Return a list of all save states associated with the given target.
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index fab985f5651..08da116a268 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -83,6 +83,7 @@ public:
 
 	PlainGameList getSupportedGames() const override;
 	PlainGameDescriptor findGame(const char *gameid) const override;
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override;
 	DetectedGames detectGames(const Common::FSList &fslist, uint32 /*skipADFlags*/, bool /*skipIncomplete*/) override;
 
 	uint getMD5Bytes() const override {
@@ -106,6 +107,12 @@ PlainGameDescriptor ScummMetaEngineDetection::findGame(const char *gameid) const
 	return Engines::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable);
 }
 
+Common::Error ScummMetaEngineDetection::identifyGame(DetectedGame &game, const void **descriptor) {
+	*descriptor = nullptr;
+	game = DetectedGame(getName(), findGame(ConfMan.get("gameid").c_str()));
+	return game.gameId.empty() ? Common::kUnknownError : Common::kNoError;
+}
+
 static Common::String generatePreferredTarget(const DetectorResult &x) {
 	Common::String res(x.game.gameid);
 
diff --git a/engines/scumm/metaengine.cpp b/engines/scumm/metaengine.cpp
index 1f734d725fd..377a899774c 100644
--- a/engines/scumm/metaengine.cpp
+++ b/engines/scumm/metaengine.cpp
@@ -259,7 +259,8 @@ bool Scumm::ScummEngine::enhancementEnabled(int32 cls) {
  *
  * This is heavily based on our MD5 detection scheme.
  */
-Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) {
+Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine,
+	const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) {
 	assert(syst);
 	assert(engine);
 	const char *gameid = ConfMan.get("gameid").c_str();
diff --git a/engines/scumm/metaengine.h b/engines/scumm/metaengine.h
index 2bfe69e6ebc..304b8fcce2c 100644
--- a/engines/scumm/metaengine.h
+++ b/engines/scumm/metaengine.h
@@ -29,7 +29,8 @@ class ScummMetaEngine : public MetaEngine {
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override;
+	Common::Error createInstance(OSystem *syst, Engine **engine,
+	                             const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp
index 148c51ef99f..bb0dc62bfb7 100644
--- a/engines/sky/detection.cpp
+++ b/engines/sky/detection.cpp
@@ -67,6 +67,7 @@ public:
 
 	PlainGameList getSupportedGames() const override;
 	PlainGameDescriptor findGame(const char *gameid) const override;
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override;
 	DetectedGames detectGames(const Common::FSList &fslist, uint32 /*skipADFlags*/, bool /*skipIncomplete*/) override;
 
 	uint getMD5Bytes() const override {
@@ -103,6 +104,12 @@ PlainGameDescriptor SkyMetaEngineDetection::findGame(const char *gameid) const {
 	return PlainGameDescriptor::empty();
 }
 
+Common::Error SkyMetaEngineDetection::identifyGame(DetectedGame &game, const void **descriptor) {
+	*descriptor = nullptr;
+	game = DetectedGame(getName(), findGame(ConfMan.get("gameid").c_str()));
+	return game.gameId.empty() ? Common::kUnknownError : Common::kNoError;
+}
+
 DetectedGames SkyMetaEngineDetection::detectGames(const Common::FSList &fslist, uint32 /*skipADFlags*/, bool /*skipIncomplete*/) {
 	DetectedGames detectedGames;
 	bool hasSkyDsk = false;
diff --git a/engines/sky/metaengine.cpp b/engines/sky/metaengine.cpp
index 496e68b755b..991f3bd9172 100644
--- a/engines/sky/metaengine.cpp
+++ b/engines/sky/metaengine.cpp
@@ -44,7 +44,8 @@ class SkyMetaEngine : public MetaEngine {
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override;
+	Common::Error createInstance(OSystem *syst, Engine **engine,
+	                             const DetectedGame &gameDescriptor, const void *metaEngineDescriptor);
 
 	const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const override;
 
@@ -144,7 +145,8 @@ Common::KeymapArray SkyMetaEngine::initKeymaps(const char *target) const {
 	return keymaps;
 }
 
-Common::Error SkyMetaEngine::createInstance(OSystem *syst, Engine **engine) {
+Common::Error SkyMetaEngine::createInstance(OSystem *syst, Engine **engine,
+	const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) {
 	assert(engine);
 	*engine = new Sky::SkyEngine(syst);
 	return Common::kNoError;
diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp
index 24a2905ff15..d671ff307bc 100644
--- a/engines/sword1/detection.cpp
+++ b/engines/sword1/detection.cpp
@@ -54,6 +54,11 @@ public:
 		return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
 	}
 
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override {
+		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+		return AdvancedMetaEngineDetection::identifyGame(game, descriptor);
+	}
+
 	const char *getName() const override {
 		return "sword1";
 	}
diff --git a/engines/sword1/metaengine.cpp b/engines/sword1/metaengine.cpp
index e4572e2b83c..21fc0d4f39c 100644
--- a/engines/sword1/metaengine.cpp
+++ b/engines/sword1/metaengine.cpp
@@ -20,12 +20,10 @@
  */
 
 #include "engines/advancedDetector.h"
-#include "engines/obsolete.h"
 
 #include "sword1/sword1.h"
 #include "sword1/control.h"
 #include "sword1/logic.h"
-#include "sword1/obsolete.h"
 
 #include "common/savefile.h"
 #include "common/system.h"
@@ -72,10 +70,6 @@ public:
 		return Sword1::optionsList;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override {
-		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
-		return AdvancedMetaEngine::createInstance(syst, engine);
-	}
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	Common::String getSavegameFile(int saveGameIdx, const char *target) const override {
diff --git a/engines/sword2/detection.cpp b/engines/sword2/detection.cpp
index 7d36a2c6c05..f24faed9042 100644
--- a/engines/sword2/detection.cpp
+++ b/engines/sword2/detection.cpp
@@ -55,6 +55,11 @@ public:
 		return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
 	}
 
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override {
+		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+		return AdvancedMetaEngineDetection::identifyGame(game, descriptor);
+	}
+
 	const char *getName() const override {
 		return "sword2";
 	}
diff --git a/engines/sword2/metaengine.cpp b/engines/sword2/metaengine.cpp
index 6f6b771936d..582ac29e74d 100644
--- a/engines/sword2/metaengine.cpp
+++ b/engines/sword2/metaengine.cpp
@@ -22,7 +22,6 @@
  */
 
 #include "engines/advancedDetector.h"
-#include "engines/obsolete.h"
 
 #include "common/config-manager.h"
 #include "common/events.h"
@@ -34,7 +33,6 @@
 
 #include "sword2/sword2.h"
 #include "sword2/saveload.h"
-#include "sword2/obsolete.h"
 
 namespace Sword2 {
 
@@ -71,10 +69,6 @@ public:
 	int getMaximumSaveSlot() const override;
 	void removeSaveState(const char *target, int slot) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine) override {
-		Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
-		return AdvancedMetaEngine::createInstance(syst, engine);
-	}
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 };
 


Commit: 90b886097f5192057ab515b6a591f36ad839255f
    https://github.com/scummvm/scummvm/commit/90b886097f5192057ab515b6a591f36ad839255f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Create a type aware advanced detector

Changed paths:
    devtools/create_engine/files/detection.cpp
    devtools/create_engine/files/detection.h
    engines/access/detection.cpp
    engines/adl/detection.cpp
    engines/advancedDetector.cpp
    engines/advancedDetector.h
    engines/agi/detection.cpp
    engines/agos/detection.cpp
    engines/ags/detection.cpp
    engines/ags/detection.h
    engines/asylum/detection.cpp
    engines/avalanche/detection.cpp
    engines/bagel/detection.cpp
    engines/bagel/detection.h
    engines/bbvs/detection.cpp
    engines/bladerunner/detection.cpp
    engines/buried/detection.cpp
    engines/cge/detection.cpp
    engines/cge2/detection.cpp
    engines/chamber/detection.cpp
    engines/chewy/detection.cpp
    engines/cine/detection.cpp
    engines/composer/detection.cpp
    engines/crab/detection.cpp
    engines/crab/detection.h
    engines/cruise/detection.cpp
    engines/cryo/detection.cpp
    engines/cryomni3d/detection.cpp
    engines/director/detection.cpp
    engines/dm/detection.cpp
    engines/draci/detection.cpp
    engines/dragons/detection.cpp
    engines/drascula/detection.cpp
    engines/dreamweb/detection.cpp
    engines/efh/detection.cpp
    engines/freescape/detection.cpp
    engines/gnap/detection.cpp
    engines/gob/detection/detection.cpp
    engines/griffon/detection.cpp
    engines/grim/detection.cpp
    engines/groovie/detection.cpp
    engines/hadesch/detection.cpp
    engines/hdb/detection.cpp
    engines/hopkins/detection.cpp
    engines/hpl1/detection.cpp
    engines/hpl1/detection.h
    engines/hugo/detection.cpp
    engines/hypno/detection.cpp
    engines/icb/detection.cpp
    engines/illusions/detection.cpp
    engines/immortal/detection.cpp
    engines/immortal/detection.h
    engines/kingdom/detection.cpp
    engines/kyra/detection.cpp
    engines/lab/detection.cpp
    engines/lastexpress/detection.cpp
    engines/lilliput/detection.cpp
    engines/lure/detection.cpp
    engines/m4/detection.cpp
    engines/m4/detection.h
    engines/macventure/detection.cpp
    engines/made/detection.cpp
    engines/mads/detection.cpp
    engines/mm/detection.cpp
    engines/mohawk/detection.cpp
    engines/mortevielle/detection.cpp
    engines/mtropolis/detection.cpp
    engines/mutationofjb/detection.cpp
    engines/myst3/detection.cpp
    engines/nancy/detection.cpp
    engines/neverhood/detection.cpp
    engines/ngi/detection.cpp
    engines/parallaction/detection.cpp
    engines/pegasus/detection.cpp
    engines/petka/detection.cpp
    engines/pink/detection.cpp
    engines/playground3d/detection.cpp
    engines/plumbers/detection.cpp
    engines/prince/detection.cpp
    engines/private/detection.cpp
    engines/queen/detection.cpp
    engines/saga/detection.cpp
    engines/saga2/detection.cpp
    engines/sci/detection.cpp
    engines/sherlock/detection.cpp
    engines/sludge/detection.cpp
    engines/stark/detection.cpp
    engines/startrek/detection.cpp
    engines/supernova/detection.cpp
    engines/sword1/detection.cpp
    engines/sword2/detection.cpp
    engines/sword25/detection.cpp
    engines/teenagent/detection.cpp
    engines/testbed/detection.cpp
    engines/tetraedge/detection.cpp
    engines/tetraedge/detection.h
    engines/tinsel/detection.cpp
    engines/titanic/detection.cpp
    engines/toltecs/detection.cpp
    engines/tony/detection.cpp
    engines/toon/detection.cpp
    engines/touche/detection.cpp
    engines/trecision/detection.cpp
    engines/tsage/detection.cpp
    engines/tucker/detection.cpp
    engines/twine/detection.cpp
    engines/twp/detection.cpp
    engines/twp/detection.h
    engines/ultima/detection.cpp
    engines/ultima/detection.h
    engines/vcruise/detection.cpp
    engines/voyeur/detection.cpp
    engines/wage/detection.cpp
    engines/watchmaker/detection.cpp
    engines/wintermute/detection.cpp
    engines/zvision/detection.cpp


diff --git a/devtools/create_engine/files/detection.cpp b/devtools/create_engine/files/detection.cpp
index fcd39c1dfad..b74ae8380a3 100644
--- a/devtools/create_engine/files/detection.cpp
+++ b/devtools/create_engine/files/detection.cpp
@@ -38,8 +38,8 @@ const DebugChannelDef XyzzyMetaEngineDetection::debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-XyzzyMetaEngineDetection::XyzzyMetaEngineDetection() : AdvancedMetaEngineDetection(Xyzzy::gameDescriptions,
-	sizeof(ADGameDescription), Xyzzy::xyzzyGames) {
+XyzzyMetaEngineDetection::XyzzyMetaEngineDetection() : AdvancedMetaEngineDetection(
+	Xyzzy::gameDescriptions, Xyzzy::xyzzyGames) {
 }
 
 REGISTER_PLUGIN_STATIC(XYZZY_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, XyzzyMetaEngineDetection);
diff --git a/devtools/create_engine/files/detection.h b/devtools/create_engine/files/detection.h
index d43ef0df3d5..f373dbeef4b 100644
--- a/devtools/create_engine/files/detection.h
+++ b/devtools/create_engine/files/detection.h
@@ -42,7 +42,7 @@ extern const ADGameDescription gameDescriptions[];
 
 } // End of namespace Xyzzy
 
-class XyzzyMetaEngineDetection : public AdvancedMetaEngineDetection {
+class XyzzyMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/access/detection.cpp b/engines/access/detection.cpp
index 02b1f62133a..a2aa876ec2d 100644
--- a/engines/access/detection.cpp
+++ b/engines/access/detection.cpp
@@ -40,9 +40,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "access/detection_tables.h"
 
-class AccessMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AccessMetaEngineDetection : public AdvancedMetaEngineDetection<Access::AccessGameDescription> {
 public:
-	AccessMetaEngineDetection() : AdvancedMetaEngineDetection(Access::gameDescriptions, sizeof(Access::AccessGameDescription), AccessGames) {
+	AccessMetaEngineDetection() : AdvancedMetaEngineDetection(Access::gameDescriptions, AccessGames) {
 		_maxScanDepth = 3;
 	}
 
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index dd409bfd4cc..3df2bcd7f76 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -443,9 +443,9 @@ static const AdlGameDescription gameDiskDescriptions[] = {
 	{ AD_TABLE_END_MARKER, GAME_TYPE_NONE, GAME_VER_NONE }
 };
 
-class AdlMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AdlMetaEngineDetection : public AdvancedMetaEngineDetection<AdlGameDescription> {
 public:
-	AdlMetaEngineDetection() : AdvancedMetaEngineDetection(gameFileDescriptions, sizeof(AdlGameDescription), adlGames) { }
+	AdlMetaEngineDetection() : AdvancedMetaEngineDetection(gameFileDescriptions, adlGames) { }
 
 	const char *getEngineName() const override {
 		return "ADL";
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index 6bdd35d3c70..66e20b118ce 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -45,7 +45,7 @@
  */
 class FileMapArchive : public Common::Archive {
 public:
-	FileMapArchive(const AdvancedMetaEngineDetection::FileMap &fileMap) : _fileMap(fileMap) {}
+	FileMapArchive(const AdvancedMetaEngineDetectionBase::FileMap &fileMap) : _fileMap(fileMap) {}
 
 	bool hasFile(const Common::Path &path) const override {
 		return _fileMap.contains(path);
@@ -53,7 +53,7 @@ public:
 
 	int listMembers(Common::ArchiveMemberList &list) const override {
 		int files = 0;
-		for (AdvancedMetaEngineDetection::FileMap::const_iterator it = _fileMap.begin(); it != _fileMap.end(); ++it) {
+		for (AdvancedMetaEngineDetectionBase::FileMap::const_iterator it = _fileMap.begin(); it != _fileMap.end(); ++it) {
 			list.push_back(Common::ArchiveMemberPtr(new Common::FSNode(it->_value)));
 			++files;
 		}
@@ -62,7 +62,7 @@ public:
 	}
 
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override {
-		AdvancedMetaEngineDetection::FileMap::const_iterator it = _fileMap.find(path);
+		AdvancedMetaEngineDetectionBase::FileMap::const_iterator it = _fileMap.find(path);
 		if (it == _fileMap.end()) {
 			return Common::ArchiveMemberPtr();
 		}
@@ -76,7 +76,7 @@ public:
 	}
 
 private:
-	const AdvancedMetaEngineDetection::FileMap &_fileMap;
+	const AdvancedMetaEngineDetectionBase::FileMap &_fileMap;
 };
 
 static Common::String sanitizeName(const char *name, int maxLen) {
@@ -164,7 +164,7 @@ static Common::String generatePreferredTarget(const ADGameDescription *desc, int
 	return res;
 }
 
-DetectedGame AdvancedMetaEngineDetection::toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const {
+DetectedGame AdvancedMetaEngineDetectionBase::toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const {
 	const ADGameDescription *desc = adGame.desc;
 
 	const char *title;
@@ -219,7 +219,7 @@ DetectedGame AdvancedMetaEngineDetection::toDetectedGame(const ADDetectedGame &a
 	return game;
 }
 
-bool AdvancedMetaEngineDetection::cleanupPirated(ADDetectedGames &matched) const {
+bool AdvancedMetaEngineDetectionBase::cleanupPirated(ADDetectedGames &matched) const {
 	// OKay, now let's sense presence of pirated games
 	if (!matched.empty()) {
 		for (uint j = 0; j < matched.size();) {
@@ -243,7 +243,7 @@ bool AdvancedMetaEngineDetection::cleanupPirated(ADDetectedGames &matched) const
 	return false;
 }
 
-DetectedGames AdvancedMetaEngineDetection::detectGames(const Common::FSList &fslist, uint32 skipADFlags, bool skipIncomplete) {
+DetectedGames AdvancedMetaEngineDetectionBase::detectGames(const Common::FSList &fslist, uint32 skipADFlags, bool skipIncomplete) {
 	FileMap allFiles;
 
 	if (fslist.empty())
@@ -334,7 +334,7 @@ const ExtraGuiOptions AdvancedMetaEngine::getExtraGuiOptions(const Common::Strin
 	return options;
 }
 
-Common::Error AdvancedMetaEngineDetection::identifyGame(DetectedGame &game, const void **descriptor) {
+Common::Error AdvancedMetaEngineDetectionBase::identifyGame(DetectedGame &game, const void **descriptor) {
 	Common::Language language = Common::UNK_LANG;
 	Common::Platform platform = Common::kPlatformUnknown;
 	Common::String extra;
@@ -425,7 +425,7 @@ Common::Error AdvancedMetaEngineDetection::identifyGame(DetectedGame &game, cons
 	return Common::kNoError;
 }
 
-void AdvancedMetaEngineDetection::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::Path &parentName) const {
+void AdvancedMetaEngineDetectionBase::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::Path &parentName) const {
 	if (depth <= 0)
 		return;
 
@@ -531,7 +531,7 @@ Common::String md5PropToGameFile(MD5Properties flags) {
 
 static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps);
 
-bool AdvancedMetaEngineDetection::getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
+bool AdvancedMetaEngineDetectionBase::getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
 	Common::String hashname = md5PropToCachePrefix(md5prop);
 		hashname += ':';
 		hashname += fname.toString('/');
@@ -678,7 +678,7 @@ Common::String escapeString(const char *string) {
 	return res;
 }
 
-void AdvancedMetaEngineDetection::dumpDetectionEntries() const {
+void AdvancedMetaEngineDetectionBase::dumpDetectionEntries() const {
 	const byte *descPtr;
 
 	for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != nullptr; descPtr += _descItemSize) {
@@ -713,7 +713,7 @@ void AdvancedMetaEngineDetection::dumpDetectionEntries() const {
 	}
 }
 
-ADDetectedGames AdvancedMetaEngineDetection::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, uint32 skipADFlags, bool skipIncomplete) {
+ADDetectedGames AdvancedMetaEngineDetectionBase::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, uint32 skipADFlags, bool skipIncomplete) {
 	CachedPropertiesMap filesProps;
 	ADDetectedGames matched;
 
@@ -866,7 +866,7 @@ ADDetectedGames AdvancedMetaEngineDetection::detectGame(const Common::FSNode &pa
 	return matched;
 }
 
-ADDetectedGame AdvancedMetaEngineDetection::detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const {
+ADDetectedGame AdvancedMetaEngineDetectionBase::detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const {
 	const ADFileBasedFallback *ptr;
 	const char* const* filenames;
 
@@ -915,11 +915,11 @@ ADDetectedGame AdvancedMetaEngineDetection::detectGameFilebased(const FileMap &a
 	return result;
 }
 
-PlainGameList AdvancedMetaEngineDetection::getSupportedGames() const {
+PlainGameList AdvancedMetaEngineDetectionBase::getSupportedGames() const {
 	return PlainGameList(_gameIds);
 }
 
-PlainGameDescriptor AdvancedMetaEngineDetection::findGame(const char *gameId) const {
+PlainGameDescriptor AdvancedMetaEngineDetectionBase::findGame(const char *gameId) const {
 	// First search the list of supported gameids for a match.
 	const PlainGameDescriptor *g = findPlainGameDescriptor(gameId, _gameIds);
 	if (g)
@@ -960,7 +960,7 @@ static const char *const grayList[] = {
 	0
 };
 
-AdvancedMetaEngineDetection::AdvancedMetaEngineDetection(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds)
+AdvancedMetaEngineDetectionBase::AdvancedMetaEngineDetectionBase(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds)
 	: _gameDescriptors((const byte *)descs), _descItemSize(descItemSize), _gameIds(gameIds) {
 
 	_md5Bytes = 5000;
@@ -977,7 +977,7 @@ AdvancedMetaEngineDetection::AdvancedMetaEngineDetection(const void *descs, uint
 		_grayListMap.setVal(*f, true);
 }
 
-void AdvancedMetaEngineDetection::preprocessDescriptions() {
+void AdvancedMetaEngineDetectionBase::preprocessDescriptions() {
 	if (_hashMapsInited)
 		return;
 
@@ -1036,7 +1036,7 @@ void AdvancedMetaEngineDetection::preprocessDescriptions() {
 #endif
 }
 
-Common::StringArray AdvancedMetaEngineDetection::getPathsFromEntry(const ADGameDescription *g) {
+Common::StringArray AdvancedMetaEngineDetectionBase::getPathsFromEntry(const ADGameDescription *g) {
 	Common::StringArray result;
 	Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> unique;
 
@@ -1061,7 +1061,7 @@ Common::StringArray AdvancedMetaEngineDetection::getPathsFromEntry(const ADGameD
 	return result;
 }
 
-bool AdvancedMetaEngineDetection::isEntryGrayListed(const ADGameDescription *g) const {
+bool AdvancedMetaEngineDetectionBase::isEntryGrayListed(const ADGameDescription *g) const {
 	bool grayIsPresent = false, nonGrayIsPresent = false;
 
 	for (const ADGameFileDescription *fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
@@ -1075,7 +1075,7 @@ bool AdvancedMetaEngineDetection::isEntryGrayListed(const ADGameDescription *g)
 	return (grayIsPresent && !nonGrayIsPresent);
 }
 
-void AdvancedMetaEngineDetection::detectClashes() const {
+void AdvancedMetaEngineDetectionBase::detectClashes() const {
 	// First, check that we do not have duplicated entries in _gameIds
 	Common::HashMap<Common::String, int, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> idsMap;
 
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 88904cdaaf2..ee5c866b7e3 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -279,7 +279,7 @@ struct ADExtraGuiOptionsMap {
 /**
  * A @ref MetaEngineDetection implementation based on the Advanced Detector code.
  */
-class AdvancedMetaEngineDetection : public MetaEngineDetection {
+class AdvancedMetaEngineDetectionBase : public MetaEngineDetection {
 protected:
 	/**
 	 * Pointer to an array of objects which are either ADGameDescription
@@ -361,12 +361,12 @@ protected:
 	 */
 	 int _fullPathGlobsDepth;
 
-public:
 	/**
 	 * Initialize game detection using AdvancedMetaEngineDetection.
 	 */
-	AdvancedMetaEngineDetection(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds);
+	AdvancedMetaEngineDetectionBase(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds);
 
+public:
 	/**
 	 * Return a list of targets supported by the engine.
 	 *
@@ -474,6 +474,12 @@ protected:
 	friend class FileMapArchive;
 };
 
+template<class Descriptor>
+class AdvancedMetaEngineDetection : public AdvancedMetaEngineDetectionBase {
+protected:
+	AdvancedMetaEngineDetection(const Descriptor *descs, const PlainGameDescriptor *gameIds) : AdvancedMetaEngineDetectionBase(descs, sizeof(Descriptor), gameIds) {}
+};
+
 /**
  * A MetaEngine implementation of AdvancedMetaEngine.
  */
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index aa803ff4f0e..f3067b89894 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -82,12 +82,12 @@ static const PlainGameDescriptor agiGames[] = {
 
 using namespace Agi;
 
-class AgiMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AgiMetaEngineDetection : public AdvancedMetaEngineDetection<AGIGameDescription> {
 	mutable Common::String _gameid;
 	mutable Common::String _extra;
 
 public:
-	AgiMetaEngineDetection() : AdvancedMetaEngineDetection(Agi::gameDescriptions, sizeof(Agi::AGIGameDescription), agiGames) {
+	AgiMetaEngineDetection() : AdvancedMetaEngineDetection(Agi::gameDescriptions, agiGames) {
 		_guiOptions = GUIO_NOSPEECH GUIO_RENDEREGA GUIO_RENDERCGA GUIO_RENDERHERCAMBER GUIO_RENDERHERCGREEN
 			GUIO_RENDERAMIGA GUIO_RENDERAPPLE2GS GUIO_RENDERATARIST GUIO_RENDERMACINTOSH;
 
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index de10e1c9b84..5509a29e33d 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -73,9 +73,9 @@ static const char *const directoryGlobs[] = {
 
 using namespace AGOS;
 
-class AgosMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AgosMetaEngineDetection : public AdvancedMetaEngineDetection<AGOS::AGOSGameDescription> {
 public:
-	AgosMetaEngineDetection() : AdvancedMetaEngineDetection(AGOS::gameDescriptions, sizeof(AGOS::AGOSGameDescription), agosGames) {
+	AgosMetaEngineDetection() : AdvancedMetaEngineDetection(AGOS::gameDescriptions, agosGames) {
 		_guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/ags/detection.cpp b/engines/ags/detection.cpp
index f6139c73b38..07069343d17 100644
--- a/engines/ags/detection.cpp
+++ b/engines/ags/detection.cpp
@@ -71,8 +71,7 @@ const DebugChannelDef AGSMetaEngineDetection::debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-AGSMetaEngineDetection::AGSMetaEngineDetection() : AdvancedMetaEngineDetection(AGS::GAME_DESCRIPTIONS,
-	        sizeof(AGS::AGSGameDescription), AGS::GAME_NAMES) {
+AGSMetaEngineDetection::AGSMetaEngineDetection() : AdvancedMetaEngineDetection(AGS::GAME_DESCRIPTIONS, AGS::GAME_NAMES) {
 	_flags = kADFlagCanPlayUnknownVariants;
 }
 
diff --git a/engines/ags/detection.h b/engines/ags/detection.h
index 6a11772c2dd..d58f75717cf 100644
--- a/engines/ags/detection.h
+++ b/engines/ags/detection.h
@@ -64,7 +64,7 @@ enum AGSSpriteFontVersion { kAGSSpriteFont = 0, kClifftopGames = 1 };
 } // namespace AGS
 
 
-class AGSMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AGSMetaEngineDetection : public AdvancedMetaEngineDetection<AGS::AGSGameDescription> {
 	mutable Common::String _gameid;
 	mutable Common::String _extra;
 	mutable Common::Path _filename;
diff --git a/engines/asylum/detection.cpp b/engines/asylum/detection.cpp
index 5fb70461fc3..a48fb83e41e 100644
--- a/engines/asylum/detection.cpp
+++ b/engines/asylum/detection.cpp
@@ -43,9 +43,9 @@ static const DebugChannelDef debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-class AsylumMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AsylumMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	AsylumMetaEngineDetection() : AdvancedMetaEngineDetection(Asylum::gameDescriptions, sizeof(ADGameDescription), asylumGames) {
+	AsylumMetaEngineDetection() : AdvancedMetaEngineDetection(Asylum::gameDescriptions, asylumGames) {
 		_md5Bytes = 0;
 		_maxScanDepth = 4;
 		_directoryGlobs = Asylum::directoryGlobs;
diff --git a/engines/avalanche/detection.cpp b/engines/avalanche/detection.cpp
index c58d1bb871c..654bb278686 100644
--- a/engines/avalanche/detection.cpp
+++ b/engines/avalanche/detection.cpp
@@ -38,7 +38,7 @@ static const PlainGameDescriptor avalancheGames[] = {
 	{nullptr, nullptr}
 };
 
-static const ADGameDescription gameDescriptions[] = {
+static const AvalancheGameDescription gameDescriptions[] = {
 	{
 		"avalanche", nullptr,
 		AD_ENTRY2s("avalot.sez",	"de10eb353228013da3d3297784f81ff9", 48763,
@@ -52,9 +52,9 @@ static const ADGameDescription gameDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-class AvalancheMetaEngineDetection : public AdvancedMetaEngineDetection {
+class AvalancheMetaEngineDetection : public AdvancedMetaEngineDetection<AvalancheGameDescription> {
 public:
-	AvalancheMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(AvalancheGameDescription), avalancheGames) {
+	AvalancheMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, avalancheGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/bagel/detection.cpp b/engines/bagel/detection.cpp
index 2174ac378db..06216564581 100644
--- a/engines/bagel/detection.cpp
+++ b/engines/bagel/detection.cpp
@@ -26,7 +26,7 @@ const DebugChannelDef BagelMetaEngineDetection::debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-BagelMetaEngineDetection::BagelMetaEngineDetection() : AdvancedMetaEngineDetection(Bagel::gameDescriptions, sizeof(ADGameDescription), Bagel::bagelGames) {
+BagelMetaEngineDetection::BagelMetaEngineDetection() : AdvancedMetaEngineDetection(Bagel::gameDescriptions, Bagel::bagelGames) {
 	_guiOptions = GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD);
 	_flags = kADFlagMatchFullPaths;
 }
diff --git a/engines/bagel/detection.h b/engines/bagel/detection.h
index d08416a621a..3ac661a92a0 100644
--- a/engines/bagel/detection.h
+++ b/engines/bagel/detection.h
@@ -38,7 +38,7 @@ extern const ADGameDescription gameDescriptions[];
 
 } // End of namespace Bagel
 
-class BagelMetaEngineDetection : public AdvancedMetaEngineDetection {
+class BagelMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/bbvs/detection.cpp b/engines/bbvs/detection.cpp
index bcbdc271e41..70913a5649e 100644
--- a/engines/bbvs/detection.cpp
+++ b/engines/bbvs/detection.cpp
@@ -92,9 +92,9 @@ static const char * const directoryGlobs[] = {
 	nullptr
 };
 
-class BbvsMetaEngineDetection : public AdvancedMetaEngineDetection {
+class BbvsMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	BbvsMetaEngineDetection() : AdvancedMetaEngineDetection(Bbvs::gameDescriptions, sizeof(ADGameDescription), bbvsGames) {
+	BbvsMetaEngineDetection() : AdvancedMetaEngineDetection(Bbvs::gameDescriptions, bbvsGames) {
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/bladerunner/detection.cpp b/engines/bladerunner/detection.cpp
index fd6238ca025..b80c0107ac4 100644
--- a/engines/bladerunner/detection.cpp
+++ b/engines/bladerunner/detection.cpp
@@ -53,7 +53,7 @@ static const char *const directoryGlobs[] = {
 };
 } // End of namespace BladeRunner
 
-class BladeRunnerMetaEngineDetection : public AdvancedMetaEngineDetection {
+class BladeRunnerMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
 	BladeRunnerMetaEngineDetection();
 
@@ -66,7 +66,6 @@ public:
 BladeRunnerMetaEngineDetection::BladeRunnerMetaEngineDetection()
 	: AdvancedMetaEngineDetection(
 		BladeRunner::gameDescriptions,
-		sizeof(BladeRunner::gameDescriptions[0]),
 		BladeRunner::bladeRunnerGames) {
 		// Setting this, allows the demo files to be copied in the BladeRunner
 		// game data folder and be detected and subsequently launched without
diff --git a/engines/buried/detection.cpp b/engines/buried/detection.cpp
index e43c0d33964..b65169b10ff 100644
--- a/engines/buried/detection.cpp
+++ b/engines/buried/detection.cpp
@@ -48,11 +48,10 @@ static const char *const directoryGlobs[] = {
 } // End of namespace Buried
 
 
-class BuriedMetaEngineDetection : public AdvancedMetaEngineDetection {
+class BuriedMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
 	BuriedMetaEngineDetection() : AdvancedMetaEngineDetection(
 		Buried::gameDescriptions,
-		sizeof(ADGameDescription),
 		buriedGames) {
 		_guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_ALLOW_SKIP);
 		_flags = kADFlagUseExtraAsHint;
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 7c10825cc4a..a7e37b02641 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -104,9 +104,9 @@ static const ADGameDescription gameDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-class CGEMetaEngineDetection : public AdvancedMetaEngineDetection {
+class CGEMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	CGEMetaEngineDetection() : AdvancedMetaEngineDetection(CGE::gameDescriptions, sizeof(ADGameDescription), CGEGames) {
+	CGEMetaEngineDetection() : AdvancedMetaEngineDetection(CGE::gameDescriptions, CGEGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp
index dfe69d3f3b8..f6759ea9349 100644
--- a/engines/cge2/detection.cpp
+++ b/engines/cge2/detection.cpp
@@ -94,9 +94,9 @@ static const ADGameDescription gameDescriptions[] = {
 		AD_TABLE_END_MARKER
 };
 
-class CGE2MetaEngineDetection : public AdvancedMetaEngineDetection {
+class CGE2MetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	CGE2MetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(ADGameDescription), CGE2Games) {
+	CGE2MetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, CGE2Games) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/chamber/detection.cpp b/engines/chamber/detection.cpp
index 596a6e40473..54bd3c1de5b 100644
--- a/engines/chamber/detection.cpp
+++ b/engines/chamber/detection.cpp
@@ -54,9 +54,9 @@ static const ADGameDescription gameDescriptions[] = {
 };
 } // End of namespace Chamber
 
-class ChamberMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ChamberMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	ChamberMetaEngineDetection() : AdvancedMetaEngineDetection(Chamber::gameDescriptions, sizeof(ADGameDescription), Chamber::ChamberGames) {
+	ChamberMetaEngineDetection() : AdvancedMetaEngineDetection(Chamber::gameDescriptions, Chamber::ChamberGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/chewy/detection.cpp b/engines/chewy/detection.cpp
index f1de4f703f6..94ad947df9a 100644
--- a/engines/chewy/detection.cpp
+++ b/engines/chewy/detection.cpp
@@ -104,9 +104,9 @@ static const ChewyGameDescription gameDescriptions[] = {
 
 } // namespace Chewy
 
-class ChewyMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ChewyMetaEngineDetection : public AdvancedMetaEngineDetection<Chewy::ChewyGameDescription> {
 public:
-	ChewyMetaEngineDetection() : AdvancedMetaEngineDetection(Chewy::gameDescriptions, sizeof(Chewy::ChewyGameDescription), chewyGames) {
+	ChewyMetaEngineDetection() : AdvancedMetaEngineDetection(Chewy::gameDescriptions, chewyGames) {
 		_maxScanDepth = 2;
 		_flags = kADFlagMatchFullPaths;
 	}
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index 603ac91da91..0e2776ebdf6 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -42,9 +42,9 @@ static const DebugChannelDef debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-class CineMetaEngineDetection : public AdvancedMetaEngineDetection {
+class CineMetaEngineDetection : public AdvancedMetaEngineDetection<Cine::CINEGameDescription> {
 public:
-	CineMetaEngineDetection() : AdvancedMetaEngineDetection(Cine::gameDescriptions, sizeof(Cine::CINEGameDescription), cineGames) {
+	CineMetaEngineDetection() : AdvancedMetaEngineDetection(Cine::gameDescriptions, cineGames) {
 		_guiOptions = GUIO3(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_TRANSPARENT_DIALOG_BOXES);
 	}
 
diff --git a/engines/composer/detection.cpp b/engines/composer/detection.cpp
index 0c129977d54..d52ed11ef70 100644
--- a/engines/composer/detection.cpp
+++ b/engines/composer/detection.cpp
@@ -51,9 +51,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class ComposerMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ComposerMetaEngineDetection : public AdvancedMetaEngineDetection<Composer::ComposerGameDescription> {
 public:
-	ComposerMetaEngineDetection() : AdvancedMetaEngineDetection(Composer::gameDescriptions, sizeof(Composer::ComposerGameDescription), composerGames) {
+	ComposerMetaEngineDetection() : AdvancedMetaEngineDetection(Composer::gameDescriptions, composerGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/crab/detection.cpp b/engines/crab/detection.cpp
index c43c4229e1a..455c91388aa 100644
--- a/engines/crab/detection.cpp
+++ b/engines/crab/detection.cpp
@@ -64,7 +64,7 @@ static const ADGameDescription gameDescriptions[] = {
 }
 
 CrabMetaEngineDetection::CrabMetaEngineDetection() : AdvancedMetaEngineDetection(Crab::gameDescriptions,
-																				 sizeof(ADGameDescription), crabGames) {
+																				 crabGames) {
 	_flags = kADFlagMatchFullPaths;
 }
 
diff --git a/engines/crab/detection.h b/engines/crab/detection.h
index ebaa6c9f17f..d9c09899e27 100644
--- a/engines/crab/detection.h
+++ b/engines/crab/detection.h
@@ -38,7 +38,7 @@ enum CrabDebugChannels {
 
 } // End of namespace Crab
 
-class CrabMetaEngineDetection : public AdvancedMetaEngineDetection {
+class CrabMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index 9b2309dad1e..dd99155a927 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -220,9 +220,9 @@ static const CRUISEGameDescription gameDescriptions[] = {
 
 }
 
-class CruiseMetaEngineDetection : public AdvancedMetaEngineDetection {
+class CruiseMetaEngineDetection : public AdvancedMetaEngineDetection<Cruise::CRUISEGameDescription> {
 public:
-	CruiseMetaEngineDetection() : AdvancedMetaEngineDetection(Cruise::gameDescriptions, sizeof(Cruise::CRUISEGameDescription), cruiseGames) {
+	CruiseMetaEngineDetection() : AdvancedMetaEngineDetection(Cruise::gameDescriptions, cruiseGames) {
 		_guiOptions = GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI);
 	}
 
diff --git a/engines/cryo/detection.cpp b/engines/cryo/detection.cpp
index 54a6bf8d430..63b9bf2b05b 100644
--- a/engines/cryo/detection.cpp
+++ b/engines/cryo/detection.cpp
@@ -118,9 +118,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace Cryo
 
-class CryoMetaEngineDetection : public AdvancedMetaEngineDetection {
+class CryoMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	CryoMetaEngineDetection() : AdvancedMetaEngineDetection(Cryo::gameDescriptions, sizeof(ADGameDescription), cryoGames) {
+	CryoMetaEngineDetection() : AdvancedMetaEngineDetection(Cryo::gameDescriptions, cryoGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/cryomni3d/detection.cpp b/engines/cryomni3d/detection.cpp
index 03d7a7f71a1..3b5413530f8 100644
--- a/engines/cryomni3d/detection.cpp
+++ b/engines/cryomni3d/detection.cpp
@@ -50,10 +50,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 namespace CryOmni3D {
 
-class CryOmni3DMetaEngineDetection : public AdvancedMetaEngineDetection {
+class CryOmni3DMetaEngineDetection : public AdvancedMetaEngineDetection<CryOmni3DGameDescription> {
 public:
-	CryOmni3DMetaEngineDetection() : AdvancedMetaEngineDetection(CryOmni3D::gameDescriptions,
-				sizeof(CryOmni3DGameDescription), cryomni3DGames) {
+	CryOmni3DMetaEngineDetection() : AdvancedMetaEngineDetection(CryOmni3D::gameDescriptions, cryomni3DGames) {
 		_directoryGlobs = directoryGlobs;
 		_maxScanDepth = 5;
 	}
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index d223177b52a..9bf8079fa8e 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -82,12 +82,12 @@ static const DebugChannelDef debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-class DirectorMetaEngineDetection : public AdvancedMetaEngineDetection {
+class DirectorMetaEngineDetection : public AdvancedMetaEngineDetection<Director::DirectorGameDescription> {
 private:
 	Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _customTarget;
 
 public:
-	DirectorMetaEngineDetection() : AdvancedMetaEngineDetection(Director::gameDescriptions, sizeof(Director::DirectorGameDescription), directorGames) {
+	DirectorMetaEngineDetection() : AdvancedMetaEngineDetection(Director::gameDescriptions, directorGames) {
 		_maxScanDepth = 5;
 		_directoryGlobs = Director::directoryGlobs;
 		_flags = kADFlagMatchFullPaths | kADFlagCanPlayUnknownVariants;
diff --git a/engines/dm/detection.cpp b/engines/dm/detection.cpp
index 2dd41f0023e..82bb6793d11 100644
--- a/engines/dm/detection.cpp
+++ b/engines/dm/detection.cpp
@@ -89,9 +89,9 @@ static const DMADGameDescription gameDescriptions[] = {
 	}
 };
 
-class DMMetaEngineDetection : public AdvancedMetaEngineDetection {
+class DMMetaEngineDetection : public AdvancedMetaEngineDetection<DMADGameDescription> {
 public:
-	DMMetaEngineDetection() : AdvancedMetaEngineDetection(DM::gameDescriptions, sizeof(DMADGameDescription), DMGames) {
+	DMMetaEngineDetection() : AdvancedMetaEngineDetection(DM::gameDescriptions, DMGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp
index 3f01b991429..e6a09c6b29b 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -90,9 +90,9 @@ const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace Draci
 
-class DraciMetaEngineDetection : public AdvancedMetaEngineDetection {
+class DraciMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	DraciMetaEngineDetection() : AdvancedMetaEngineDetection(Draci::gameDescriptions, sizeof(ADGameDescription), draciGames) {
+	DraciMetaEngineDetection() : AdvancedMetaEngineDetection(Draci::gameDescriptions, draciGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/dragons/detection.cpp b/engines/dragons/detection.cpp
index 5fa41e91d87..411e8aa087e 100644
--- a/engines/dragons/detection.cpp
+++ b/engines/dragons/detection.cpp
@@ -119,9 +119,9 @@ static const char * const directoryGlobs[] = {
 	nullptr
 };
 
-class DragonsMetaEngineDetection : public AdvancedMetaEngineDetection {
+class DragonsMetaEngineDetection : public AdvancedMetaEngineDetection<Dragons::DragonsGameDescription> {
 public:
-	DragonsMetaEngineDetection() : AdvancedMetaEngineDetection(Dragons::gameDescriptions, sizeof(Dragons::DragonsGameDescription), dragonsGames) {
+	DragonsMetaEngineDetection() : AdvancedMetaEngineDetection(Dragons::gameDescriptions, dragonsGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index ea130643f7f..2bbac38a2cb 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -293,9 +293,9 @@ static const DrasculaGameDescription gameDescriptions[] = {
 	{ AD_TABLE_END_MARKER }
 };
 
-class DrasculaMetaEngineDetection : public AdvancedMetaEngineDetection {
+class DrasculaMetaEngineDetection : public AdvancedMetaEngineDetection<Drascula::DrasculaGameDescription> {
 public:
-	DrasculaMetaEngineDetection() : AdvancedMetaEngineDetection(Drascula::gameDescriptions, sizeof(Drascula::DrasculaGameDescription), drasculaGames) {
+	DrasculaMetaEngineDetection() : AdvancedMetaEngineDetection(Drascula::gameDescriptions, drasculaGames) {
 		_guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD);
 	}
 
diff --git a/engines/dreamweb/detection.cpp b/engines/dreamweb/detection.cpp
index c237887c6b8..da34d4903fc 100644
--- a/engines/dreamweb/detection.cpp
+++ b/engines/dreamweb/detection.cpp
@@ -43,11 +43,11 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "dreamweb/detection_tables.h"
 
-class DreamWebMetaEngineDetection : public AdvancedMetaEngineDetection {
+class DreamWebMetaEngineDetection : public AdvancedMetaEngineDetection<DreamWeb::DreamWebGameDescription> {
 public:
 	DreamWebMetaEngineDetection():
 	AdvancedMetaEngineDetection(DreamWeb::gameDescriptions,
-	sizeof(DreamWeb::DreamWebGameDescription), dreamWebGames) {
+	dreamWebGames) {
 		_guiOptions = GUIO5(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE, GAMEOPTION_TTS_THINGS, GAMEOPTION_TTS_SPEECH);
 	}
 
diff --git a/engines/efh/detection.cpp b/engines/efh/detection.cpp
index cb6fd0eef88..12b092989f3 100644
--- a/engines/efh/detection.cpp
+++ b/engines/efh/detection.cpp
@@ -59,9 +59,9 @@ static const DebugChannelDef debugFlagList[] = {
 	{Efh::kDebugGraphics, "graphics", "Graphics debug level"},
 	DEBUG_CHANNEL_END};
 
-class EfhMetaEngineDetection : public AdvancedMetaEngineDetection {
+class EfhMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	EfhMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(ADGameDescription), efhGames) {
+	EfhMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, efhGames) {
 	}
 
 	const char *getEngineName() const override {
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 2db255eb964..1a50bb164e3 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -928,9 +928,9 @@ static const DebugChannelDef debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-class FreescapeMetaEngineDetection : public AdvancedMetaEngineDetection {
+class FreescapeMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	FreescapeMetaEngineDetection() : AdvancedMetaEngineDetection(Freescape::gameDescriptions, sizeof(ADGameDescription), Freescape::freescapeGames) {
+	FreescapeMetaEngineDetection() : AdvancedMetaEngineDetection(Freescape::gameDescriptions, Freescape::freescapeGames) {
 		_guiOptions = GUIO7(GUIO_NOMIDI, GAMEOPTION_EXTENDED_TIMER, GAMEOPTION_DISABLE_DEMO_MODE, GAMEOPTION_DISABLE_SENSORS, GAMEOPTION_DISABLE_FALLING, GAMEOPTION_INVERT_Y, GAMEOPTION_AUTHENTIC_GRAPHICS);
 	}
 
diff --git a/engines/gnap/detection.cpp b/engines/gnap/detection.cpp
index 47d7ec8fc5e..ddb197e4555 100644
--- a/engines/gnap/detection.cpp
+++ b/engines/gnap/detection.cpp
@@ -77,9 +77,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace Gnap
 
-class GnapMetaEngineDetection : public AdvancedMetaEngineDetection {
+class GnapMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	GnapMetaEngineDetection() : AdvancedMetaEngineDetection(Gnap::gameDescriptions, sizeof(ADGameDescription), gnapGames) {
+	GnapMetaEngineDetection() : AdvancedMetaEngineDetection(Gnap::gameDescriptions, gnapGames) {
 		_maxScanDepth = 3;
 	}
 
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
index 3e3d00f3240..c220d69b858 100644
--- a/engines/gob/detection/detection.cpp
+++ b/engines/gob/detection/detection.cpp
@@ -51,7 +51,7 @@ static const DebugChannelDef debugFlagList[] = {
 	DEBUG_CHANNEL_END
 };
 
-class GobMetaEngineDetection : public AdvancedMetaEngineDetection {
+class GobMetaEngineDetection : public AdvancedMetaEngineDetection<Gob::GOBGameDescription> {
 public:
 	GobMetaEngineDetection();
 
@@ -85,7 +85,7 @@ private:
 };
 
 GobMetaEngineDetection::GobMetaEngineDetection() :
-	AdvancedMetaEngineDetection(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) {
+	AdvancedMetaEngineDetection(Gob::gameDescriptions, gobGames) {
 
 	_guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
 }
diff --git a/engines/griffon/detection.cpp b/engines/griffon/detection.cpp
index d80f8151406..29c84abd19a 100644
--- a/engines/griffon/detection.cpp
+++ b/engines/griffon/detection.cpp
@@ -53,9 +53,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 }
 
-class GriffonMetaEngineDetection: public AdvancedMetaEngineDetection {
+class GriffonMetaEngineDetection: public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	GriffonMetaEngineDetection() : AdvancedMetaEngineDetection(Griffon::gameDescriptions, sizeof(ADGameDescription), griffonGames) {
+	GriffonMetaEngineDetection() : AdvancedMetaEngineDetection(Griffon::gameDescriptions, griffonGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/grim/detection.cpp b/engines/grim/detection.cpp
index b40ba328536..9df3823bc5c 100644
--- a/engines/grim/detection.cpp
+++ b/engines/grim/detection.cpp
@@ -694,9 +694,9 @@ static const GrimGameDescription gameDescriptions[] = {
 	{ AD_TABLE_END_MARKER, GType_GRIM }
 };
 
-class GrimMetaEngineDetection : public AdvancedMetaEngineDetection {
+class GrimMetaEngineDetection : public AdvancedMetaEngineDetection<Grim::GrimGameDescription> {
 public:
-	GrimMetaEngineDetection() : AdvancedMetaEngineDetection(Grim::gameDescriptions, sizeof(Grim::GrimGameDescription), grimGames) {
+	GrimMetaEngineDetection() : AdvancedMetaEngineDetection(Grim::gameDescriptions, grimGames) {
 		_guiOptions = GUIO_NOMIDI;
 	}
 
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 2d6f7f8c3f9..60e50283294 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -275,9 +275,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class GroovieMetaEngineDetection : public AdvancedMetaEngineDetection {
+class GroovieMetaEngineDetection : public AdvancedMetaEngineDetection<GroovieGameDescription> {
 public:
-	GroovieMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(GroovieGameDescription), groovieGames) {
+	GroovieMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, groovieGames) {
 		// Use kADFlagUseExtraAsHint in order to distinguish the 11th hour from
 		// its "Making of" as well as the Clandestiny Trailer; they all share
 		// the same MD5.
diff --git a/engines/hadesch/detection.cpp b/engines/hadesch/detection.cpp
index 56abdf6ef22..8e23d91c088 100644
--- a/engines/hadesch/detection.cpp
+++ b/engines/hadesch/detection.cpp
@@ -69,9 +69,9 @@ static const char *const directoryGlobs[] = {
 };
 }
 
-class HadeschMetaEngineDetection : public AdvancedMetaEngineDetection {
+class HadeschMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	HadeschMetaEngineDetection() : AdvancedMetaEngineDetection(Hadesch::gameDescriptions, sizeof(ADGameDescription), Hadesch::hadeschGames) {
+	HadeschMetaEngineDetection() : AdvancedMetaEngineDetection(Hadesch::gameDescriptions, Hadesch::hadeschGames) {
 		// mac puts wd.pod in Hades - Copy To Hard Drive/Hades Challenge/World. So we need 4 levels
 		_maxScanDepth = 4;
 		_directoryGlobs = Hadesch::directoryGlobs;
diff --git a/engines/hdb/detection.cpp b/engines/hdb/detection.cpp
index bf386beaa7a..c9e1132ba27 100644
--- a/engines/hdb/detection.cpp
+++ b/engines/hdb/detection.cpp
@@ -113,9 +113,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace HDB
 
-class HDBMetaEngineDetection : public AdvancedMetaEngineDetection {
+class HDBMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	HDBMetaEngineDetection() : AdvancedMetaEngineDetection(HDB::gameDescriptions, sizeof(ADGameDescription), hdbGames) {
+	HDBMetaEngineDetection() : AdvancedMetaEngineDetection(HDB::gameDescriptions, hdbGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp
index 79efa7247e6..9f3900d497d 100644
--- a/engines/hopkins/detection.cpp
+++ b/engines/hopkins/detection.cpp
@@ -44,9 +44,9 @@ const static char *const directoryGlobs[] = {
 	nullptr
 };
 
-class HopkinsMetaEngineDetection : public AdvancedMetaEngineDetection {
+class HopkinsMetaEngineDetection : public AdvancedMetaEngineDetection<Hopkins::HopkinsGameDescription> {
 public:
-	HopkinsMetaEngineDetection() : AdvancedMetaEngineDetection(Hopkins::gameDescriptions, sizeof(Hopkins::HopkinsGameDescription), hopkinsGames) {
+	HopkinsMetaEngineDetection() : AdvancedMetaEngineDetection(Hopkins::gameDescriptions, hopkinsGames) {
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/hpl1/detection.cpp b/engines/hpl1/detection.cpp
index cf272feaf14..720c481bec2 100644
--- a/engines/hpl1/detection.cpp
+++ b/engines/hpl1/detection.cpp
@@ -43,7 +43,7 @@ const DebugChannelDef Hpl1MetaEngineDetection::debugFlagList[] = {
 	DEBUG_CHANNEL_END};
 
 Hpl1MetaEngineDetection::Hpl1MetaEngineDetection() : AdvancedMetaEngineDetection(Hpl1::GAME_DESCRIPTIONS,
-																				 sizeof(ADGameDescription), Hpl1::GAME_NAMES) {
+																				 Hpl1::GAME_NAMES) {
 }
 
 REGISTER_PLUGIN_STATIC(HPL1_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, Hpl1MetaEngineDetection);
diff --git a/engines/hpl1/detection.h b/engines/hpl1/detection.h
index cebef96485f..e3f9ba0bfd9 100644
--- a/engines/hpl1/detection.h
+++ b/engines/hpl1/detection.h
@@ -32,7 +32,7 @@ extern const ADGameDescription GAME_DESCRIPTIONS[];
 
 } // namespace Hpl1
 
-class Hpl1MetaEngineDetection : public AdvancedMetaEngineDetection {
+class Hpl1MetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index e642489f8cc..e6e79f852d7 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -127,9 +127,9 @@ static const HugoGameDescription gameDescriptions[] = {
 	{AD_TABLE_END_MARKER, kGameTypeNone}
 };
 
-class HugoMetaEngineDetection : public AdvancedMetaEngineDetection {
+class HugoMetaEngineDetection : public AdvancedMetaEngineDetection<HugoGameDescription> {
 public:
-	HugoMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(HugoGameDescription), hugoGames) {
+	HugoMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, hugoGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 51dbacbb8e2..9b0aeb5340a 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -281,9 +281,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
+class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	HypnoMetaEngineDetection() : AdvancedMetaEngineDetection(Hypno::gameDescriptions, sizeof(ADGameDescription), Hypno::hypnoGames) {
+	HypnoMetaEngineDetection() : AdvancedMetaEngineDetection(Hypno::gameDescriptions, Hypno::hypnoGames) {
 		_guiOptions = GUIO6(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_CHEATS, GAMEOPTION_INFINITE_HEALTH, GAMEOPTION_INFINITE_AMMO, GAMEOPTION_UNLOCK_ALL_LEVELS, GAMEOPTION_RESTORED_CONTENT);
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/icb/detection.cpp b/engines/icb/detection.cpp
index 542d901e86a..2c8b2753d77 100644
--- a/engines/icb/detection.cpp
+++ b/engines/icb/detection.cpp
@@ -305,9 +305,9 @@ static const IcbGameDescription gameDescriptions[] = {
 	{ AD_TABLE_END_MARKER, GType_ICB }
 };
 
-class IcbMetaEngineDetection : public AdvancedMetaEngineDetection {
+class IcbMetaEngineDetection : public AdvancedMetaEngineDetection<IcbGameDescription> {
 public:
-	IcbMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(IcbGameDescription), icbGames) {
+	IcbMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, icbGames) {
 		_guiOptions = GUIO_NOMIDI;
 		_flags = kADFlagMatchFullPaths;
 	}
diff --git a/engines/illusions/detection.cpp b/engines/illusions/detection.cpp
index c4d0e9b860e..4559142d411 100644
--- a/engines/illusions/detection.cpp
+++ b/engines/illusions/detection.cpp
@@ -109,9 +109,9 @@ static const char * const directoryGlobs[] = {
 	nullptr
 };
 
-class IllusionsMetaEngineDetection : public AdvancedMetaEngineDetection {
+class IllusionsMetaEngineDetection : public AdvancedMetaEngineDetection<Illusions::IllusionsGameDescription> {
 public:
-	IllusionsMetaEngineDetection() : AdvancedMetaEngineDetection(Illusions::gameDescriptions, sizeof(Illusions::IllusionsGameDescription), illusionsGames) {
+	IllusionsMetaEngineDetection() : AdvancedMetaEngineDetection(Illusions::gameDescriptions, illusionsGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/immortal/detection.cpp b/engines/immortal/detection.cpp
index a071b6448fa..183d1d92fdf 100644
--- a/engines/immortal/detection.cpp
+++ b/engines/immortal/detection.cpp
@@ -26,7 +26,7 @@
 #include "immortal/detection_tables.h"
 
 ImmortalMetaEngineDetection::ImmortalMetaEngineDetection() : AdvancedMetaEngineDetection(Immortal::gameDescriptions,
-	sizeof(ADGameDescription), Immortal::immortalGames) {
+	Immortal::immortalGames) {
 }
 
 REGISTER_PLUGIN_STATIC(IMMORTAL_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, ImmortalMetaEngineDetection);
diff --git a/engines/immortal/detection.h b/engines/immortal/detection.h
index 69699995ce4..7a7d6f4c91a 100644
--- a/engines/immortal/detection.h
+++ b/engines/immortal/detection.h
@@ -35,7 +35,7 @@ extern const ADGameDescription gameDescriptions[];
 
 } // namespace Immortal
 
-class ImmortalMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ImmortalMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/kingdom/detection.cpp b/engines/kingdom/detection.cpp
index 136a472eaa8..5b6c02542e6 100644
--- a/engines/kingdom/detection.cpp
+++ b/engines/kingdom/detection.cpp
@@ -88,9 +88,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace Kingdom
 
-class KingdomMetaEngineDetection : public AdvancedMetaEngineDetection {
+class KingdomMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	KingdomMetaEngineDetection() : AdvancedMetaEngineDetection(Kingdom::gameDescriptions, sizeof(ADGameDescription), kingdomGames) {
+	KingdomMetaEngineDetection() : AdvancedMetaEngineDetection(Kingdom::gameDescriptions, kingdomGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 6ef2036d58c..b026abda453 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -52,9 +52,9 @@ const char *const directoryGlobs[] = {
 
 } // End of anonymous namespace
 
-class KyraMetaEngineDetection : public AdvancedMetaEngineDetection {
+class KyraMetaEngineDetection : public AdvancedMetaEngineDetection<KYRAGameDescription> {
 public:
-	KyraMetaEngineDetection() : AdvancedMetaEngineDetection(adGameDescs, sizeof(KYRAGameDescription), gameList) {
+	KyraMetaEngineDetection() : AdvancedMetaEngineDetection(adGameDescs, gameList) {
 		_md5Bytes = 1024 * 1024;
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/lab/detection.cpp b/engines/lab/detection.cpp
index bb3195b8084..3356878f13e 100644
--- a/engines/lab/detection.cpp
+++ b/engines/lab/detection.cpp
@@ -94,9 +94,9 @@ static const char *const directoryGlobs[] = {
 
 
 
-class LabMetaEngineDetection : public AdvancedMetaEngineDetection {
+class LabMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	LabMetaEngineDetection() : AdvancedMetaEngineDetection(labDescriptions, sizeof(ADGameDescription), lab_setting) {
+	LabMetaEngineDetection() : AdvancedMetaEngineDetection(labDescriptions, lab_setting) {
 		_maxScanDepth = 4;
 		_directoryGlobs = directoryGlobs;
 		_flags = kADFlagUseExtraAsHint;
diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp
index b1ed5be5608..0183d8dd219 100644
--- a/engines/lastexpress/detection.cpp
+++ b/engines/lastexpress/detection.cpp
@@ -221,9 +221,9 @@ static const char *const directoryGlobs[] = {
 		nullptr
 };
 
-class LastExpressMetaEngineDetection : public AdvancedMetaEngineDetection {
+class LastExpressMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	LastExpressMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(ADGameDescription), lastExpressGames) {
+	LastExpressMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, lastExpressGames) {
 		_guiOptions = GUIO2(GUIO_NOSUBTITLES, GUIO_NOSFX);
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/lilliput/detection.cpp b/engines/lilliput/detection.cpp
index fb50c197061..9ec5707565e 100644
--- a/engines/lilliput/detection.cpp
+++ b/engines/lilliput/detection.cpp
@@ -114,9 +114,9 @@ static const LilliputGameDescription gameDescriptions[] = {
 	{AD_TABLE_END_MARKER, kGameTypeNone}
 };
 
-class LilliputMetaEngineDetection : public AdvancedMetaEngineDetection {
+class LilliputMetaEngineDetection : public AdvancedMetaEngineDetection<LilliputGameDescription> {
 public:
-	LilliputMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(LilliputGameDescription), lilliputGames) {
+	LilliputMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, lilliputGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index b9400bde8c7..a50fdec3fe7 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -242,9 +242,9 @@ static const LureGameDescription gameDescriptions[] = {
 
 } // End of namespace Lure
 
-class LureMetaEngineDetection : public AdvancedMetaEngineDetection {
+class LureMetaEngineDetection : public AdvancedMetaEngineDetection<Lure::LureGameDescription> {
 public:
-	LureMetaEngineDetection() : AdvancedMetaEngineDetection(Lure::gameDescriptions, sizeof(Lure::LureGameDescription), lureGames) {
+	LureMetaEngineDetection() : AdvancedMetaEngineDetection(Lure::gameDescriptions, lureGames) {
 		_md5Bytes = 1024;
 
 		// Use kADFlagUseExtraAsHint to distinguish between EGA and VGA versions
diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp
index 3e8aabd8d61..2c26f5b62c7 100644
--- a/engines/m4/detection.cpp
+++ b/engines/m4/detection.cpp
@@ -44,7 +44,7 @@ static const char *const DIRECTORY_GLOBS[] = {
 };
 
 M4MetaEngineDetection::M4MetaEngineDetection() : AdvancedMetaEngineDetection(M4::gameDescriptions,
-		sizeof(M4::M4GameDescription), M4::m4Games) {
+		M4::m4Games) {
 	_guiOptions = GUIO1(GAMEOPTION_ORIGINAL_SAVELOAD);
 	_maxScanDepth = 2;
 	_directoryGlobs = DIRECTORY_GLOBS;
diff --git a/engines/m4/detection.h b/engines/m4/detection.h
index b4f80d29f6c..1f38661910c 100644
--- a/engines/m4/detection.h
+++ b/engines/m4/detection.h
@@ -65,7 +65,7 @@ struct M4GameDescription {
 
 } // End of namespace M4
 
-class M4MetaEngineDetection : public AdvancedMetaEngineDetection {
+class M4MetaEngineDetection : public AdvancedMetaEngineDetection<M4::M4GameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/macventure/detection.cpp b/engines/macventure/detection.cpp
index 261e12dcacb..cdd496ec0de 100644
--- a/engines/macventure/detection.cpp
+++ b/engines/macventure/detection.cpp
@@ -82,9 +82,9 @@ namespace MacVenture {
 
 SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot, bool skipThumbnail = true);
 
-class MacVentureMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MacVentureMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	MacVentureMetaEngineDetection() : AdvancedMetaEngineDetection(MacVenture::gameDescriptions, sizeof(ADGameDescription), macventureGames) {
+	MacVentureMetaEngineDetection() : AdvancedMetaEngineDetection(MacVenture::gameDescriptions, macventureGames) {
 		_guiOptions = GUIO1(GUIO_NOMIDI);
 	}
 
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index ad504d21b89..feff2a7a29c 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -36,9 +36,9 @@ static const PlainGameDescriptor madeGames[] = {
 
 #include "made/detection_tables.h"
 
-class MadeMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MadeMetaEngineDetection : public AdvancedMetaEngineDetection<Made::MadeGameDescription> {
 public:
-	MadeMetaEngineDetection() : AdvancedMetaEngineDetection(Made::gameDescriptions, sizeof(Made::MadeGameDescription), madeGames) {
+	MadeMetaEngineDetection() : AdvancedMetaEngineDetection(Made::gameDescriptions, madeGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp
index 5658d1c2bcf..485826f68f3 100644
--- a/engines/mads/detection.cpp
+++ b/engines/mads/detection.cpp
@@ -45,9 +45,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "mads/detection_tables.h"
 
-class MADSMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MADSMetaEngineDetection : public AdvancedMetaEngineDetection<MADS::MADSGameDescription> {
 public:
-	MADSMetaEngineDetection() : AdvancedMetaEngineDetection(MADS::gameDescriptions, sizeof(MADS::MADSGameDescription), MADSGames) {
+	MADSMetaEngineDetection() : AdvancedMetaEngineDetection(MADS::gameDescriptions, MADSGames) {
 		_maxScanDepth = 3;
 	}
 
diff --git a/engines/mm/detection.cpp b/engines/mm/detection.cpp
index 5fe7b5dcc71..10532b543c9 100644
--- a/engines/mm/detection.cpp
+++ b/engines/mm/detection.cpp
@@ -49,10 +49,10 @@ static const DebugChannelDef DEBUG_FLAT_LIST[] = {
 
 #include "mm/detection_tables.h"
 
-class MMMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MMMetaEngineDetection : public AdvancedMetaEngineDetection<MM::MightAndMagicGameDescription> {
 public:
 	MMMetaEngineDetection() : AdvancedMetaEngineDetection(MM::GAME_DESCRIPTIONS,
-		sizeof(MM::MightAndMagicGameDescription), MIGHT_AND_MAGIC_GAMES) {
+		MIGHT_AND_MAGIC_GAMES) {
 		_maxScanDepth = 3;
 	}
 
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 7df3e337900..40f77868d12 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -93,9 +93,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class MohawkMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MohawkMetaEngineDetection : public AdvancedMetaEngineDetection<Mohawk::MohawkGameDescription> {
 public:
-	MohawkMetaEngineDetection() : AdvancedMetaEngineDetection(Mohawk::gameDescriptions, sizeof(Mohawk::MohawkGameDescription), mohawkGames) {
+	MohawkMetaEngineDetection() : AdvancedMetaEngineDetection(Mohawk::gameDescriptions, mohawkGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/mortevielle/detection.cpp b/engines/mortevielle/detection.cpp
index a646dce6402..44e1451c9d2 100644
--- a/engines/mortevielle/detection.cpp
+++ b/engines/mortevielle/detection.cpp
@@ -38,10 +38,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "mortevielle/detection_tables.h"
 
-class MortevielleMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MortevielleMetaEngineDetection : public AdvancedMetaEngineDetection<Mortevielle::MortevielleGameDescription> {
 public:
-	MortevielleMetaEngineDetection() : AdvancedMetaEngineDetection(Mortevielle::MortevielleGameDescriptions, sizeof(Mortevielle::MortevielleGameDescription),
-		MortevielleGame) {
+	MortevielleMetaEngineDetection() : AdvancedMetaEngineDetection(Mortevielle::MortevielleGameDescriptions, MortevielleGame) {
 		_md5Bytes = 512;
 		// Use kADFlagUseExtraAsHint to distinguish between original and improved versions
 		// (i.e. use or not of the game data file).
diff --git a/engines/mtropolis/detection.cpp b/engines/mtropolis/detection.cpp
index b56adf7a274..5fb5e565584 100644
--- a/engines/mtropolis/detection.cpp
+++ b/engines/mtropolis/detection.cpp
@@ -53,9 +53,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class MTropolisMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MTropolisMetaEngineDetection : public AdvancedMetaEngineDetection<MTropolis::MTropolisGameDescription> {
 public:
-	MTropolisMetaEngineDetection() : AdvancedMetaEngineDetection(MTropolis::gameDescriptions, sizeof(MTropolis::MTropolisGameDescription), mTropolisGames) {
+	MTropolisMetaEngineDetection() : AdvancedMetaEngineDetection(MTropolis::gameDescriptions, mTropolisGames) {
 		_guiOptions = GUIO3(GAMEOPTION_DYNAMIC_MIDI, GAMEOPTION_LAUNCH_DEBUG, GAMEOPTION_ENABLE_SHORT_TRANSITIONS);
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/mutationofjb/detection.cpp b/engines/mutationofjb/detection.cpp
index 71bda2faccb..f4e7395ff7c 100644
--- a/engines/mutationofjb/detection.cpp
+++ b/engines/mutationofjb/detection.cpp
@@ -96,9 +96,9 @@ static const char *const mutationofjbDirectoryGlobs[] = {
 	nullptr
 };
 
-class MutationOfJBMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MutationOfJBMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	MutationOfJBMetaEngineDetection() : AdvancedMetaEngineDetection(mutationofjbDescriptions, sizeof(ADGameDescription), mutationofjbGames) {
+	MutationOfJBMetaEngineDetection() : AdvancedMetaEngineDetection(mutationofjbDescriptions, mutationofjbGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = mutationofjbDirectoryGlobs;
 	}
diff --git a/engines/myst3/detection.cpp b/engines/myst3/detection.cpp
index 29648c31b4a..8ace6566833 100644
--- a/engines/myst3/detection.cpp
+++ b/engines/myst3/detection.cpp
@@ -205,9 +205,9 @@ static const Myst3GameDescription gameDescriptions[] = {
 	{ AD_TABLE_END_MARKER, 0 }
 };
 
-class Myst3MetaEngineDetection : public AdvancedMetaEngineDetection {
+class Myst3MetaEngineDetection : public AdvancedMetaEngineDetection<Myst3GameDescription> {
 public:
-	Myst3MetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(Myst3GameDescription), myst3Games) {
+	Myst3MetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, myst3Games) {
 		_guiOptions = GUIO5(GUIO_NOMIDI, GUIO_NOSFX, GUIO_NOSPEECH, GUIO_NOSUBTITLES, GAMEOPTION_WIDESCREEN_MOD);
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/nancy/detection.cpp b/engines/nancy/detection.cpp
index 04f52f52ea3..9c72e4dcbde 100644
--- a/engines/nancy/detection.cpp
+++ b/engines/nancy/detection.cpp
@@ -756,9 +756,9 @@ static const Nancy::NancyGameDescription gameDescriptions[] = {
 	{ AD_TABLE_END_MARKER, Nancy::kGameTypeNone }
 };
 
-class NancyMetaEngineDetection : public AdvancedMetaEngineDetection {
+class NancyMetaEngineDetection : public AdvancedMetaEngineDetection<Nancy::NancyGameDescription> {
 public:
-	NancyMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(Nancy::NancyGameDescription), nancyGames) {
+	NancyMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, nancyGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 		_guiOptions = GUIO2(GUIO_NOMIDI, GUIO_NOASPECT);
diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp
index b7dd801064e..ae9a971d57e 100644
--- a/engines/neverhood/detection.cpp
+++ b/engines/neverhood/detection.cpp
@@ -130,9 +130,9 @@ static const ADGameDescription gameDescriptions[] = {
 } // End of namespace Neverhood
 
 
-class NeverhoodMetaEngineDetection : public AdvancedMetaEngineDetection {
+class NeverhoodMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	NeverhoodMetaEngineDetection() : AdvancedMetaEngineDetection(Neverhood::gameDescriptions, sizeof(ADGameDescription), neverhoodGames) {
+	NeverhoodMetaEngineDetection() : AdvancedMetaEngineDetection(Neverhood::gameDescriptions, neverhoodGames) {
 		_guiOptions = GUIO5(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_SKIP_HALL_OF_RECORDS,
 				    GAMEOPTION_SCALE_MAKING_OF_VIDEOS, GAMEOPTION_REPEAT_WILLIE_HINT);
 	}
diff --git a/engines/ngi/detection.cpp b/engines/ngi/detection.cpp
index 7de546e1a9b..902b0abda67 100644
--- a/engines/ngi/detection.cpp
+++ b/engines/ngi/detection.cpp
@@ -185,9 +185,9 @@ static const NGIGameDescription gameDescriptions[] = {
 
 } // End of namespace NGI
 
-class NGIMetaEngineDetection : public AdvancedMetaEngineDetection {
+class NGIMetaEngineDetection : public AdvancedMetaEngineDetection<NGI::NGIGameDescription> {
 public:
-	NGIMetaEngineDetection() : AdvancedMetaEngineDetection(NGI::gameDescriptions, sizeof(NGI::NGIGameDescription), ngiGames) {
+	NGIMetaEngineDetection() : AdvancedMetaEngineDetection(NGI::gameDescriptions, ngiGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index 34885f9ec4c..414db021127 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -226,9 +226,9 @@ static const PARALLACTIONGameDescription gameDescriptions[] = {
 
 }
 
-class ParallactionMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ParallactionMetaEngineDetection : public AdvancedMetaEngineDetection<Parallaction::PARALLACTIONGameDescription> {
 public:
-	ParallactionMetaEngineDetection() : AdvancedMetaEngineDetection(Parallaction::gameDescriptions, sizeof(Parallaction::PARALLACTIONGameDescription), parallactionGames) {
+	ParallactionMetaEngineDetection() : AdvancedMetaEngineDetection(Parallaction::gameDescriptions, parallactionGames) {
 		_guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
 	}
 
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
index a505262f68b..6a6f7c78df2 100644
--- a/engines/pegasus/detection.cpp
+++ b/engines/pegasus/detection.cpp
@@ -144,9 +144,9 @@ static const PegasusGameDescription gameDescriptions[] = {
 } // End of namespace Pegasus
 
 
-class PegasusMetaEngineDetection : public AdvancedMetaEngineDetection {
+class PegasusMetaEngineDetection : public AdvancedMetaEngineDetection<Pegasus::PegasusGameDescription> {
 public:
-	PegasusMetaEngineDetection() : AdvancedMetaEngineDetection(Pegasus::gameDescriptions, sizeof(Pegasus::PegasusGameDescription), pegasusGames) {
+	PegasusMetaEngineDetection() : AdvancedMetaEngineDetection(Pegasus::gameDescriptions, pegasusGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/petka/detection.cpp b/engines/petka/detection.cpp
index 67ef5bfa045..31318363ae6 100644
--- a/engines/petka/detection.cpp
+++ b/engines/petka/detection.cpp
@@ -41,9 +41,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "petka/detection_tables.h"
 
-class PetkaMetaEngineDetection : public AdvancedMetaEngineDetection {
+class PetkaMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	PetkaMetaEngineDetection() : AdvancedMetaEngineDetection(Petka::gameDescriptions, sizeof(ADGameDescription), petkaGames) {
+	PetkaMetaEngineDetection() : AdvancedMetaEngineDetection(Petka::gameDescriptions, petkaGames) {
 		_gameIds = petkaGames;
 		_maxScanDepth = 2;
 	}
diff --git a/engines/pink/detection.cpp b/engines/pink/detection.cpp
index bc213076f47..31749a5bdab 100644
--- a/engines/pink/detection.cpp
+++ b/engines/pink/detection.cpp
@@ -48,9 +48,9 @@ static const DebugChannelDef debugFlagList[] = {
 };
 
 
-class PinkMetaEngineDetection : public AdvancedMetaEngineDetection {
+class PinkMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	PinkMetaEngineDetection() : AdvancedMetaEngineDetection(Pink::gameDescriptions, sizeof(ADGameDescription), pinkGames) {
+	PinkMetaEngineDetection() : AdvancedMetaEngineDetection(Pink::gameDescriptions, pinkGames) {
 		_gameIds = pinkGames;
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/playground3d/detection.cpp b/engines/playground3d/detection.cpp
index b13de0dfeb4..2a5f1709d84 100644
--- a/engines/playground3d/detection.cpp
+++ b/engines/playground3d/detection.cpp
@@ -42,9 +42,9 @@ static const ADGameDescription playground3dDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-class Playground3dMetaEngineDetection : public AdvancedMetaEngineDetection {
+class Playground3dMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	Playground3dMetaEngineDetection() : AdvancedMetaEngineDetection(playground3dDescriptions, sizeof(ADGameDescription), playground3d_setting) {
+	Playground3dMetaEngineDetection() : AdvancedMetaEngineDetection(playground3dDescriptions, playground3d_setting) {
 		_md5Bytes = 512;
 	}
 
diff --git a/engines/plumbers/detection.cpp b/engines/plumbers/detection.cpp
index 844494eebec..035d2c2e6b3 100644
--- a/engines/plumbers/detection.cpp
+++ b/engines/plumbers/detection.cpp
@@ -66,9 +66,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace Plumbers
 
-class PlumbersMetaEngineDetection : public AdvancedMetaEngineDetection {
+class PlumbersMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	PlumbersMetaEngineDetection() : AdvancedMetaEngineDetection(Plumbers::gameDescriptions, sizeof(ADGameDescription), plumbersGames) {
+	PlumbersMetaEngineDetection() : AdvancedMetaEngineDetection(Plumbers::gameDescriptions, plumbersGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/prince/detection.cpp b/engines/prince/detection.cpp
index 2e537d90735..2c877e62086 100644
--- a/engines/prince/detection.cpp
+++ b/engines/prince/detection.cpp
@@ -161,9 +161,9 @@ const static char *const directoryGlobs[] = {
 	nullptr
 };
 
-class PrinceMetaEngineDetection : public AdvancedMetaEngineDetection {
+class PrinceMetaEngineDetection : public AdvancedMetaEngineDetection<Prince::PrinceGameDescription> {
 public:
-	PrinceMetaEngineDetection() : AdvancedMetaEngineDetection(Prince::gameDescriptions, sizeof(Prince::PrinceGameDescription), princeGames) {
+	PrinceMetaEngineDetection() : AdvancedMetaEngineDetection(Prince::gameDescriptions, princeGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/private/detection.cpp b/engines/private/detection.cpp
index f0e13973dbd..850277ee017 100644
--- a/engines/private/detection.cpp
+++ b/engines/private/detection.cpp
@@ -245,9 +245,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class PrivateMetaEngineDetection : public AdvancedMetaEngineDetection {
+class PrivateMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	PrivateMetaEngineDetection() : AdvancedMetaEngineDetection(Private::gameDescriptions, sizeof(ADGameDescription), Private::privateGames) {
+	PrivateMetaEngineDetection() : AdvancedMetaEngineDetection(Private::gameDescriptions, Private::privateGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/queen/detection.cpp b/engines/queen/detection.cpp
index 5f329ff7e7f..13987172148 100644
--- a/engines/queen/detection.cpp
+++ b/engines/queen/detection.cpp
@@ -474,9 +474,9 @@ static const QueenGameDescription gameDescriptions[] = {
 
 } // End of namespace Queen
 
-class QueenMetaEngineDetection : public AdvancedMetaEngineDetection {
+class QueenMetaEngineDetection : public AdvancedMetaEngineDetection<Queen::QueenGameDescription> {
 public:
-	QueenMetaEngineDetection() : AdvancedMetaEngineDetection(Queen::gameDescriptions, sizeof(Queen::QueenGameDescription), queenGames) {
+	QueenMetaEngineDetection() : AdvancedMetaEngineDetection(Queen::gameDescriptions, queenGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 6fb28c12247..43d5f870fb2 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -34,9 +34,9 @@ static const PlainGameDescriptor sagaGames[] = {
 
 #include "saga/detection_tables.h"
 
-class SagaMetaEngineDetection : public AdvancedMetaEngineDetection {
+class SagaMetaEngineDetection : public AdvancedMetaEngineDetection<Saga::SAGAGameDescription> {
 public:
-	SagaMetaEngineDetection() : AdvancedMetaEngineDetection(Saga::gameDescriptions, sizeof(Saga::SAGAGameDescription), sagaGames) {
+	SagaMetaEngineDetection() : AdvancedMetaEngineDetection(Saga::gameDescriptions, sagaGames) {
 		static const char *const DIRECTORY_GLOBS[3] = { "music", "ITE Data Files", nullptr };
 		_maxScanDepth = 2;
 		_directoryGlobs = DIRECTORY_GLOBS;
diff --git a/engines/saga2/detection.cpp b/engines/saga2/detection.cpp
index 4572b16d027..7ef7aed70d3 100644
--- a/engines/saga2/detection.cpp
+++ b/engines/saga2/detection.cpp
@@ -127,9 +127,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class Saga2MetaEngineDetection : public AdvancedMetaEngineDetection {
+class Saga2MetaEngineDetection : public AdvancedMetaEngineDetection<Saga2::SAGA2GameDescription> {
 public:
-	Saga2MetaEngineDetection() : AdvancedMetaEngineDetection(Saga2::gameDescriptions, sizeof(Saga2::SAGA2GameDescription), Saga2::saga2Games) {
+	Saga2MetaEngineDetection() : AdvancedMetaEngineDetection(Saga2::gameDescriptions, Saga2::saga2Games) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 47abac3944f..0c6d6ccf927 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -179,9 +179,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class SciMetaEngineDetection : public AdvancedMetaEngineDetection {
+class SciMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	SciMetaEngineDetection() : AdvancedMetaEngineDetection(Sci::SciGameDescriptions, sizeof(ADGameDescription), s_sciGameTitles) {
+	SciMetaEngineDetection() : AdvancedMetaEngineDetection(Sci::SciGameDescriptions, s_sciGameTitles) {
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
 		// Use SCI fallback detection results instead of the partial matches found by
diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp
index eaac406781d..b09b3ff2cb2 100644
--- a/engines/sherlock/detection.cpp
+++ b/engines/sherlock/detection.cpp
@@ -40,10 +40,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "sherlock/detection_tables.h"
 
-class SherlockMetaEngineDetection : public AdvancedMetaEngineDetection {
+class SherlockMetaEngineDetection : public AdvancedMetaEngineDetection<Sherlock::SherlockGameDescription> {
 public:
-	SherlockMetaEngineDetection() : AdvancedMetaEngineDetection(Sherlock::gameDescriptions, sizeof(Sherlock::SherlockGameDescription),
-		sherlockGames) {}
+	SherlockMetaEngineDetection() : AdvancedMetaEngineDetection(Sherlock::gameDescriptions, sherlockGames) {}
 
 	const char *getName() const override {
 		return "sherlock";
diff --git a/engines/sludge/detection.cpp b/engines/sludge/detection.cpp
index 096bd58ef04..e48fb5b15af 100644
--- a/engines/sludge/detection.cpp
+++ b/engines/sludge/detection.cpp
@@ -75,9 +75,9 @@ static Sludge::SludgeGameDescription s_fallbackDesc =
 
 static char s_fallbackFileNameBuffer[51];
 
-class SludgeMetaEngineDetection : public AdvancedMetaEngineDetection {
+class SludgeMetaEngineDetection : public AdvancedMetaEngineDetection<Sludge::SludgeGameDescription> {
 public:
-	SludgeMetaEngineDetection() : AdvancedMetaEngineDetection(Sludge::gameDescriptions, sizeof(Sludge::SludgeGameDescription), sludgeGames) {
+	SludgeMetaEngineDetection() : AdvancedMetaEngineDetection(Sludge::gameDescriptions, sludgeGames) {
 		_maxScanDepth = 1;
 	}
 
diff --git a/engines/stark/detection.cpp b/engines/stark/detection.cpp
index 0b672b8537a..43944e47fb0 100644
--- a/engines/stark/detection.cpp
+++ b/engines/stark/detection.cpp
@@ -401,9 +401,9 @@ static const ADGameDescription gameDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-class StarkMetaEngineDetection : public AdvancedMetaEngineDetection {
+class StarkMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	StarkMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, sizeof(ADGameDescription), starkGames) {
+	StarkMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, starkGames) {
 		_guiOptions = GUIO4(GUIO_NOMIDI, GAMEOPTION_ASSETS_MOD, GAMEOPTION_LINEAR_FILTERING, GAMEOPTION_FONT_ANTIALIASING);
 	}
 
diff --git a/engines/startrek/detection.cpp b/engines/startrek/detection.cpp
index 106fab9ee25..52cb6408f8a 100644
--- a/engines/startrek/detection.cpp
+++ b/engines/startrek/detection.cpp
@@ -352,9 +352,9 @@ static const StarTrekGameDescription gameDescriptions[] = {
 
 } // End of namespace StarTrek
 
-class StarTrekMetaEngineDetection : public AdvancedMetaEngineDetection {
+class StarTrekMetaEngineDetection : public AdvancedMetaEngineDetection<StarTrek::StarTrekGameDescription> {
 public:
-	StarTrekMetaEngineDetection() : AdvancedMetaEngineDetection(StarTrek::gameDescriptions, sizeof(StarTrek::StarTrekGameDescription), starTrekGames) {
+	StarTrekMetaEngineDetection() : AdvancedMetaEngineDetection(StarTrek::gameDescriptions, starTrekGames) {
 	}
 
 	const DebugChannelDef *getDebugChannels() const override {
diff --git a/engines/supernova/detection.cpp b/engines/supernova/detection.cpp
index 16aa40669d6..e1c63b663a4 100644
--- a/engines/supernova/detection.cpp
+++ b/engines/supernova/detection.cpp
@@ -89,9 +89,9 @@ static const ADGameDescription gameDescriptions[] = {
 };
 }
 
-class SupernovaMetaEngineDetection: public AdvancedMetaEngineDetection {
+class SupernovaMetaEngineDetection: public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	SupernovaMetaEngineDetection() : AdvancedMetaEngineDetection(Supernova::gameDescriptions, sizeof(ADGameDescription), supernovaGames) {
+	SupernovaMetaEngineDetection() : AdvancedMetaEngineDetection(Supernova::gameDescriptions, supernovaGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp
index d671ff307bc..b6d919e2d2b 100644
--- a/engines/sword1/detection.cpp
+++ b/engines/sword1/detection.cpp
@@ -42,9 +42,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class SwordMetaEngineDetection : public AdvancedMetaEngineDetection {
+class SwordMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	SwordMetaEngineDetection() : AdvancedMetaEngineDetection(Sword1::gameDescriptions, sizeof(ADGameDescription), swordGames) {
+	SwordMetaEngineDetection() : AdvancedMetaEngineDetection(Sword1::gameDescriptions, swordGames) {
 		_guiOptions = GUIO2(GUIO_NOMIDI, GUIO_NOASPECT);
 		_flags = kADFlagMatchFullPaths;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/sword2/detection.cpp b/engines/sword2/detection.cpp
index f24faed9042..944126f0619 100644
--- a/engines/sword2/detection.cpp
+++ b/engines/sword2/detection.cpp
@@ -43,9 +43,9 @@ static const char *const directoryGlobs[] = {
 	nullptr
 };
 
-class Sword2MetaEngineDetection : public AdvancedMetaEngineDetection {
+class Sword2MetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	Sword2MetaEngineDetection() : AdvancedMetaEngineDetection(Sword2::gameDescriptions, sizeof(ADGameDescription), sword2Games) {
+	Sword2MetaEngineDetection() : AdvancedMetaEngineDetection(Sword2::gameDescriptions, sword2Games) {
 		_guiOptions = GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GAMEOPTION_OBJECT_LABELS);
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp
index 1845418c9c6..614c2662edb 100644
--- a/engines/sword25/detection.cpp
+++ b/engines/sword25/detection.cpp
@@ -42,9 +42,9 @@ static const char *const directoryGlobs[] = {
 	0
 };
 
-class Sword25MetaEngineDetection : public AdvancedMetaEngineDetection {
+class Sword25MetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	Sword25MetaEngineDetection() : AdvancedMetaEngineDetection(Sword25::gameDescriptions, sizeof(ADGameDescription), sword25Game) {
+	Sword25MetaEngineDetection() : AdvancedMetaEngineDetection(Sword25::gameDescriptions, sword25Game) {
 		_guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_ENGLISH_SPEECH);
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index 97d9509c646..ec3c3a11ba1 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -202,9 +202,9 @@ static const ADGameDescription teenAgentGameDescriptions[] = {
 
 
 
-class TeenAgentMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TeenAgentMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	TeenAgentMetaEngineDetection() : AdvancedMetaEngineDetection(teenAgentGameDescriptions, sizeof(ADGameDescription), teenAgentGames) {
+	TeenAgentMetaEngineDetection() : AdvancedMetaEngineDetection(teenAgentGameDescriptions, teenAgentGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp
index 6d66f7f18a2..bb360ae212f 100644
--- a/engines/testbed/detection.cpp
+++ b/engines/testbed/detection.cpp
@@ -48,9 +48,9 @@ static const ADGameDescription testbedDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-class TestbedMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TestbedMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	TestbedMetaEngineDetection() : AdvancedMetaEngineDetection(testbedDescriptions, sizeof(ADGameDescription), testbed_setting) {
+	TestbedMetaEngineDetection() : AdvancedMetaEngineDetection(testbedDescriptions, testbed_setting) {
 		_md5Bytes = 512;
 	}
 
diff --git a/engines/tetraedge/detection.cpp b/engines/tetraedge/detection.cpp
index bad5b25783f..d47b9182d0b 100644
--- a/engines/tetraedge/detection.cpp
+++ b/engines/tetraedge/detection.cpp
@@ -33,7 +33,7 @@ const DebugChannelDef TetraedgeMetaEngineDetection::debugFlagList[] = {
 };
 
 TetraedgeMetaEngineDetection::TetraedgeMetaEngineDetection() : AdvancedMetaEngineDetection(Tetraedge::GAME_DESCRIPTIONS,
-	sizeof(ADGameDescription), Tetraedge::GAME_NAMES) {
+	Tetraedge::GAME_NAMES) {
 	_flags = kADFlagMatchFullPaths;
 }
 
diff --git a/engines/tetraedge/detection.h b/engines/tetraedge/detection.h
index f1fae7a47b5..cf5bbf1c796 100644
--- a/engines/tetraedge/detection.h
+++ b/engines/tetraedge/detection.h
@@ -40,7 +40,7 @@ extern const ADGameDescription GAME_DESCRIPTIONS[];
 
 } // namespace Tetraedge
 
-class TetraedgeMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TetraedgeMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 751fea53892..7692d908dbb 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -45,9 +45,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "tinsel/detection_tables.h"
 
-class TinselMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TinselMetaEngineDetection : public AdvancedMetaEngineDetection<Tinsel::TinselGameDescription> {
 public:
-	TinselMetaEngineDetection() : AdvancedMetaEngineDetection(Tinsel::gameDescriptions, sizeof(Tinsel::TinselGameDescription), tinselGames) {
+	TinselMetaEngineDetection() : AdvancedMetaEngineDetection(Tinsel::gameDescriptions, tinselGames) {
 	}
 
 	const char *getName() const  override{
diff --git a/engines/titanic/detection.cpp b/engines/titanic/detection.cpp
index e099a4cfd34..2db8aa56220 100644
--- a/engines/titanic/detection.cpp
+++ b/engines/titanic/detection.cpp
@@ -42,9 +42,9 @@ static const PlainGameDescriptor TitanicGames[] = {
 
 #include "titanic/detection_tables.h"
 
-class TitanicMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TitanicMetaEngineDetection : public AdvancedMetaEngineDetection<Titanic::TitanicGameDescription> {
 public:
-	TitanicMetaEngineDetection() : AdvancedMetaEngineDetection(Titanic::gameDescriptions, sizeof(Titanic::TitanicGameDescription), TitanicGames) {
+	TitanicMetaEngineDetection() : AdvancedMetaEngineDetection(Titanic::gameDescriptions, TitanicGames) {
 		_maxScanDepth = 3;
 	}
 
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index 307292093cc..ed601fb1337 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -221,9 +221,9 @@ static const ToltecsGameDescription gameDescriptions[] = {
 
 } // End of namespace Toltecs
 
-class ToltecsMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ToltecsMetaEngineDetection : public AdvancedMetaEngineDetection<Toltecs::ToltecsGameDescription> {
 public:
-	ToltecsMetaEngineDetection() : AdvancedMetaEngineDetection(Toltecs::gameDescriptions, sizeof(Toltecs::ToltecsGameDescription), toltecsGames) {
+	ToltecsMetaEngineDetection() : AdvancedMetaEngineDetection(Toltecs::gameDescriptions, toltecsGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/tony/detection.cpp b/engines/tony/detection.cpp
index fa3e8e429f7..2e5359b0463 100644
--- a/engines/tony/detection.cpp
+++ b/engines/tony/detection.cpp
@@ -47,9 +47,9 @@ static const char *const directoryGlobs[] = {
 	0
 };
 
-class TonyMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TonyMetaEngineDetection : public AdvancedMetaEngineDetection<Tony::TonyGameDescription> {
 public:
-	TonyMetaEngineDetection() : AdvancedMetaEngineDetection(Tony::gameDescriptions, sizeof(Tony::TonyGameDescription), tonyGames) {
+	TonyMetaEngineDetection() : AdvancedMetaEngineDetection(Tony::gameDescriptions, tonyGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index 2acf43b628b..ca920d274e6 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -165,9 +165,9 @@ static const char * const directoryGlobs[] = {
 	0
 };
 
-class ToonMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ToonMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	ToonMetaEngineDetection() : AdvancedMetaEngineDetection(Toon::gameDescriptions, sizeof(ADGameDescription), toonGames) {
+	ToonMetaEngineDetection() : AdvancedMetaEngineDetection(Toon::gameDescriptions, toonGames) {
 		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
 	}
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 301243d6380..308a13b7aa4 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -138,9 +138,9 @@ static const char *const directoryGlobs[] = {
 	0
 };
 
-class ToucheMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ToucheMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	ToucheMetaEngineDetection() : AdvancedMetaEngineDetection(Touche::gameDescriptions, sizeof(ADGameDescription), toucheGames) {
+	ToucheMetaEngineDetection() : AdvancedMetaEngineDetection(Touche::gameDescriptions, toucheGames) {
 		_md5Bytes = 4096;
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
diff --git a/engines/trecision/detection.cpp b/engines/trecision/detection.cpp
index d0bcbd3d8e7..4f3f06b85ef 100644
--- a/engines/trecision/detection.cpp
+++ b/engines/trecision/detection.cpp
@@ -219,9 +219,9 @@ static const char *const directoryGlobs[] = {
 	0
 };
 
-class TrecisionMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TrecisionMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	TrecisionMetaEngineDetection() : AdvancedMetaEngineDetection(Trecision::gameDescriptions, sizeof(ADGameDescription), trecisionGames) {
+	TrecisionMetaEngineDetection() : AdvancedMetaEngineDetection(Trecision::gameDescriptions, trecisionGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 		_guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD);
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index a21c375847c..9ae6e5657ff 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -42,9 +42,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "tsage/detection_tables.h"
 
-class TSageMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TSageMetaEngineDetection : public AdvancedMetaEngineDetection<TsAGE::tSageGameDescription> {
 public:
-	TSageMetaEngineDetection() : AdvancedMetaEngineDetection(TsAGE::gameDescriptions, sizeof(TsAGE::tSageGameDescription), tSageGameTitles) {
+	TSageMetaEngineDetection() : AdvancedMetaEngineDetection(TsAGE::gameDescriptions, tSageGameTitles) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index d114bb6ac4b..257cdf6eb0f 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -115,9 +115,9 @@ static const ADGameDescription tuckerDemoGameDescription = {
 	GUIO1(GUIO_NOMIDI)
 };
 
-class TuckerMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TuckerMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	TuckerMetaEngineDetection() : AdvancedMetaEngineDetection(tuckerGameDescriptions, sizeof(ADGameDescription), tuckerGames) {
+	TuckerMetaEngineDetection() : AdvancedMetaEngineDetection(tuckerGameDescriptions, tuckerGames) {
 		_md5Bytes = 512;
 	}
 
diff --git a/engines/twine/detection.cpp b/engines/twine/detection.cpp
index fc5a4d075b7..10c252ab3ef 100644
--- a/engines/twine/detection.cpp
+++ b/engines/twine/detection.cpp
@@ -413,9 +413,9 @@ static const ADGameDescription twineGameDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-class TwinEMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TwinEMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	TwinEMetaEngineDetection() : AdvancedMetaEngineDetection(twineGameDescriptions, sizeof(ADGameDescription), twineGames) {
+	TwinEMetaEngineDetection() : AdvancedMetaEngineDetection(twineGameDescriptions, twineGames) {
 		_guiOptions = GUIO12(GAMEOPTION_WALL_COLLISION, GAMEOPTION_DISABLE_SAVE_MENU,  GAMEOPTION_DEBUG, GAMEOPTION_AUDIO_CD, GAMEOPTION_SOUND, GAMEOPTION_VOICES, GAMEOPTION_TEXT, GAMEOPTION_MOVIES, GAMEOPTION_MOUSE, GAMEOPTION_USA_VERSION, GAMEOPTION_HIGH_RESOLUTION, GAMEOPTION_TEXT_TO_SPEECH);
 	}
 
diff --git a/engines/twp/detection.cpp b/engines/twp/detection.cpp
index 04922edb6e0..b29b43d8c66 100644
--- a/engines/twp/detection.cpp
+++ b/engines/twp/detection.cpp
@@ -42,7 +42,7 @@ const DebugChannelDef TwpMetaEngineDetection::debugFlagList[] = {
 
 TwpMetaEngineDetection::TwpMetaEngineDetection()
 	: AdvancedMetaEngineDetection(Twp::gameDescriptions,
-								  sizeof(Twp::TwpGameDescription), Twp::twpGames) {
+								  Twp::twpGames) {
 }
 
 DetectedGame TwpMetaEngineDetection::toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const {
diff --git a/engines/twp/detection.h b/engines/twp/detection.h
index a15f129d34e..f0bfe5c4750 100644
--- a/engines/twp/detection.h
+++ b/engines/twp/detection.h
@@ -65,7 +65,7 @@ extern const TwpGameDescription gameDescriptions[];
 
 } // End of namespace Twp
 
-class TwpMetaEngineDetection : public AdvancedMetaEngineDetection {
+class TwpMetaEngineDetection : public AdvancedMetaEngineDetection<Twp::TwpGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/ultima/detection.cpp b/engines/ultima/detection.cpp
index 4188fc46002..1f4588f8e04 100644
--- a/engines/ultima/detection.cpp
+++ b/engines/ultima/detection.cpp
@@ -61,7 +61,7 @@ const DebugChannelDef UltimaMetaEngineDetection::debugFlagList[] = {
 };
 
 UltimaMetaEngineDetection::UltimaMetaEngineDetection() : AdvancedMetaEngineDetection(Ultima::GAME_DESCRIPTIONS,
-	        sizeof(Ultima::UltimaGameDescription), Ultima::ULTIMA_GAMES) {
+	        Ultima::ULTIMA_GAMES) {
 	static const char *const DIRECTORY_GLOBS[2] = { "usecode", 0 };
 	_maxScanDepth = 2;
 	_directoryGlobs = DIRECTORY_GLOBS;
diff --git a/engines/ultima/detection.h b/engines/ultima/detection.h
index 2f92fc05ffc..a78be325dcb 100644
--- a/engines/ultima/detection.h
+++ b/engines/ultima/detection.h
@@ -82,7 +82,7 @@ struct UltimaGameDescription {
 
 } // End of namespace Ultima
 
-class UltimaMetaEngineDetection : public AdvancedMetaEngineDetection {
+class UltimaMetaEngineDetection : public AdvancedMetaEngineDetection<Ultima::UltimaGameDescription> {
 	static const DebugChannelDef debugFlagList[];
 
 public:
diff --git a/engines/vcruise/detection.cpp b/engines/vcruise/detection.cpp
index db1eee153b4..e93adf80cac 100644
--- a/engines/vcruise/detection.cpp
+++ b/engines/vcruise/detection.cpp
@@ -46,9 +46,9 @@ static const char *const g_vcruiseDirectoryGlobs[] = {
 
 #include "vcruise/detection_tables.h"
 
-class VCruiseMetaEngineDetection : public AdvancedMetaEngineDetection {
+class VCruiseMetaEngineDetection : public AdvancedMetaEngineDetection<VCruise::VCruiseGameDescription> {
 public:
-	VCruiseMetaEngineDetection() : AdvancedMetaEngineDetection(VCruise::gameDescriptions, sizeof(VCruise::VCruiseGameDescription), g_vcruiseGames) {
+	VCruiseMetaEngineDetection() : AdvancedMetaEngineDetection(VCruise::gameDescriptions, g_vcruiseGames) {
 		_guiOptions = GUIO4(GAMEOPTION_FAST_ANIMATIONS, GAMEOPTION_INCREASE_DRAG_DISTANCE, GAMEOPTION_LAUNCH_DEBUG, GAMEOPTION_SKIP_MENU);
 		_maxScanDepth = 3;
 		_directoryGlobs = g_vcruiseDirectoryGlobs;
diff --git a/engines/voyeur/detection.cpp b/engines/voyeur/detection.cpp
index 8579563c2f0..dfa3f0a0f38 100644
--- a/engines/voyeur/detection.cpp
+++ b/engines/voyeur/detection.cpp
@@ -39,9 +39,9 @@ static const DebugChannelDef debugFlagList[] = {
 
 #include "voyeur/detection_tables.h"
 
-class VoyeurMetaEngineDetection : public AdvancedMetaEngineDetection {
+class VoyeurMetaEngineDetection : public AdvancedMetaEngineDetection<Voyeur::VoyeurGameDescription> {
 public:
-	VoyeurMetaEngineDetection() : AdvancedMetaEngineDetection(Voyeur::gameDescriptions, sizeof(Voyeur::VoyeurGameDescription), voyeurGames) {
+	VoyeurMetaEngineDetection() : AdvancedMetaEngineDetection(Voyeur::gameDescriptions, voyeurGames) {
 		_maxScanDepth = 3;
 	}
 
diff --git a/engines/wage/detection.cpp b/engines/wage/detection.cpp
index b44491b3dde..a0c99c9d357 100644
--- a/engines/wage/detection.cpp
+++ b/engines/wage/detection.cpp
@@ -39,9 +39,9 @@ static const PlainGameDescriptor wageGames[] = {
 
 #include "wage/detection_tables.h"
 
-class WageMetaEngineDetection : public AdvancedMetaEngineDetection {
+class WageMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	WageMetaEngineDetection() : AdvancedMetaEngineDetection(Wage::gameDescriptions, sizeof(ADGameDescription), wageGames) {
+	WageMetaEngineDetection() : AdvancedMetaEngineDetection(Wage::gameDescriptions, wageGames) {
 		_md5Bytes = 2 * 1024 * 1024;
 		_guiOptions = GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI);
 	}
diff --git a/engines/watchmaker/detection.cpp b/engines/watchmaker/detection.cpp
index e050ae2d1a1..84d94fbb603 100644
--- a/engines/watchmaker/detection.cpp
+++ b/engines/watchmaker/detection.cpp
@@ -66,9 +66,9 @@ static const ADGameDescription gameDescriptions[] = {
 
 } // End of namespace Watchmaker
 
-class WatchmakerMetaEngineDetection : public AdvancedMetaEngineDetection {
+class WatchmakerMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
-	WatchmakerMetaEngineDetection() : AdvancedMetaEngineDetection(Watchmaker::gameDescriptions, sizeof(ADGameDescription), watchmakerGames) {
+	WatchmakerMetaEngineDetection() : AdvancedMetaEngineDetection(Watchmaker::gameDescriptions, watchmakerGames) {
 	}
 
 	const char *getName() const override {
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index 77048f002f6..b48fc2a1c11 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -51,9 +51,9 @@ static const char *const directoryGlobs[] = {
 	0
 };
 
-class WintermuteMetaEngineDetection : public AdvancedMetaEngineDetection {
+class WintermuteMetaEngineDetection : public AdvancedMetaEngineDetection<WMEGameDescription> {
 public:
-	WintermuteMetaEngineDetection() : AdvancedMetaEngineDetection(Wintermute::gameDescriptions, sizeof(WMEGameDescription), Wintermute::wintermuteGames) {
+	WintermuteMetaEngineDetection() : AdvancedMetaEngineDetection(Wintermute::gameDescriptions, Wintermute::wintermuteGames) {
 		// Use kADFlagUseExtraAsHint to distinguish between SD and HD versions
 		// of J.U.L.I.A. when their datafiles sit in the same directory (e.g. in Steam distribution).
 		_flags = kADFlagUseExtraAsHint;
diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp
index 96f1449bfe5..7ad6ecd7a9c 100644
--- a/engines/zvision/detection.cpp
+++ b/engines/zvision/detection.cpp
@@ -30,9 +30,9 @@
 #include "zvision/detection.h"
 #include "zvision/detection_tables.h"
 
-class ZVisionMetaEngineDetection : public AdvancedMetaEngineDetection {
+class ZVisionMetaEngineDetection : public AdvancedMetaEngineDetection<ZVision::ZVisionGameDescription> {
 public:
-	ZVisionMetaEngineDetection() : AdvancedMetaEngineDetection(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), ZVision::zVisionGames) {
+	ZVisionMetaEngineDetection() : AdvancedMetaEngineDetection(ZVision::gameDescriptions, ZVision::zVisionGames) {
 		_maxScanDepth = 2;
 		_directoryGlobs = ZVision::directoryGlobs;
 	}


Commit: b61bd3ff85ed06d10f152c74423cbecda00f5537
    https://github.com/scummvm/scummvm/commit/b61bd3ff85ed06d10f152c74423cbecda00f5537
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Create a type aware advanced meta engine

Changed paths:
    devtools/create_engine/files/metaengine.h
    engines/access/metaengine.cpp
    engines/adl/metaengine.cpp
    engines/advancedDetector.cpp
    engines/advancedDetector.h
    engines/agi/metaengine.cpp
    engines/agos/metaengine.cpp
    engines/ags/metaengine.cpp
    engines/ags/metaengine.h
    engines/asylum/metaengine.cpp
    engines/avalanche/metaengine.cpp
    engines/bagel/metaengine.h
    engines/bbvs/metaengine.cpp
    engines/bladerunner/metaengine.cpp
    engines/buried/metaengine.cpp
    engines/cge/metaengine.cpp
    engines/cge2/metaengine.cpp
    engines/chamber/metaengine.cpp
    engines/chewy/metaengine.cpp
    engines/cine/metaengine.cpp
    engines/composer/metaengine.cpp
    engines/crab/metaengine.h
    engines/cruise/metaengine.cpp
    engines/cryo/metaengine.cpp
    engines/cryomni3d/metaengine.cpp
    engines/director/metaengine.cpp
    engines/dm/metaengine.cpp
    engines/draci/metaengine.cpp
    engines/dragons/dragons.cpp
    engines/dragons/dragons.h
    engines/dragons/metaengine.cpp
    engines/drascula/metaengine.cpp
    engines/dreamweb/metaengine.cpp
    engines/efh/metaengine.cpp
    engines/freescape/metaengine.cpp
    engines/gnap/metaengine.cpp
    engines/gob/metaengine.cpp
    engines/griffon/metaengine.cpp
    engines/grim/metaengine.cpp
    engines/groovie/metaengine.cpp
    engines/hadesch/metaengine.cpp
    engines/hdb/metaengine.cpp
    engines/hopkins/metaengine.cpp
    engines/hpl1/metaengine.h
    engines/hugo/metaengine.cpp
    engines/hypno/metaengine.cpp
    engines/icb/metaengine.cpp
    engines/illusions/metaengine.cpp
    engines/immortal/metaengine.h
    engines/kingdom/metaengine.cpp
    engines/kyra/metaengine.cpp
    engines/lab/metaengine.cpp
    engines/lastexpress/metaengine.cpp
    engines/lilliput/metaengine.cpp
    engines/lure/metaengine.cpp
    engines/m4/metaengine.cpp
    engines/m4/metaengine.h
    engines/macventure/metaengine.cpp
    engines/made/metaengine.cpp
    engines/mads/metaengine.cpp
    engines/mm/metaengine.cpp
    engines/mohawk/metaengine.cpp
    engines/mortevielle/metaengine.cpp
    engines/mtropolis/metaengine.cpp
    engines/mutationofjb/metaengine.cpp
    engines/myst3/metaengine.cpp
    engines/nancy/metaengine.cpp
    engines/neverhood/metaengine.cpp
    engines/ngi/metaengine.cpp
    engines/parallaction/metaengine.cpp
    engines/pegasus/metaengine.cpp
    engines/petka/metaengine.cpp
    engines/pink/metaengine.cpp
    engines/playground3d/metaengine.cpp
    engines/plumbers/metaengine.cpp
    engines/prince/metaengine.cpp
    engines/private/metaengine.cpp
    engines/queen/metaengine.cpp
    engines/saga/metaengine.cpp
    engines/saga2/metaengine.cpp
    engines/sci/detection.cpp
    engines/sci/metaengine.cpp
    engines/sherlock/metaengine.cpp
    engines/sludge/metaengine.cpp
    engines/stark/metaengine.cpp
    engines/startrek/metaengine.cpp
    engines/supernova/metaengine.cpp
    engines/sword1/metaengine.cpp
    engines/sword2/metaengine.cpp
    engines/sword25/metaengine.cpp
    engines/teenagent/metaengine.cpp
    engines/testbed/metaengine.cpp
    engines/tetraedge/metaengine.h
    engines/tinsel/metaengine.cpp
    engines/titanic/metaengine.cpp
    engines/toltecs/metaengine.cpp
    engines/tony/metaengine.cpp
    engines/toon/metaengine.cpp
    engines/touche/metaengine.cpp
    engines/trecision/metaengine.cpp
    engines/tsage/metaengine.cpp
    engines/tucker/metaengine.cpp
    engines/twine/metaengine.cpp
    engines/twp/metaengine.cpp
    engines/twp/metaengine.h
    engines/ultima/metaengine.cpp
    engines/ultima/metaengine.h
    engines/vcruise/metaengine.cpp
    engines/voyeur/metaengine.cpp
    engines/wage/metaengine.cpp
    engines/watchmaker/metaengine.cpp
    engines/wintermute/detection.cpp
    engines/wintermute/metaengine.cpp
    engines/zvision/metaengine.cpp


diff --git a/devtools/create_engine/files/metaengine.h b/devtools/create_engine/files/metaengine.h
index 9bd9ea23150..ab793369ab4 100644
--- a/devtools/create_engine/files/metaengine.h
+++ b/devtools/create_engine/files/metaengine.h
@@ -24,7 +24,7 @@
 
 #include "engines/advancedDetector.h"
 
-class XyzzyMetaEngine : public AdvancedMetaEngine {
+class XyzzyMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/access/metaengine.cpp b/engines/access/metaengine.cpp
index 72767a2fbfc..7f3350d2301 100644
--- a/engines/access/metaengine.cpp
+++ b/engines/access/metaengine.cpp
@@ -67,7 +67,7 @@ Common::Platform AccessEngine::getPlatform() const {
 
 } // End of namespace Access
 
-class AccessMetaEngine : public AdvancedMetaEngine {
+class AccessMetaEngine : public AdvancedMetaEngine<Access::AccessGameDescription> {
 public:
 	const char *getName() const override {
 		return "access";
@@ -75,7 +75,7 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Access::AccessGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -100,8 +100,7 @@ bool Access::AccessEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error AccessMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Access::AccessGameDescription *gd = (const Access::AccessGameDescription *)desc;
+Common::Error AccessMetaEngine::createInstance(OSystem *syst, Engine **engine, const Access::AccessGameDescription *gd) const {
 	switch (gd->gameID) {
 	case Access::GType_Amazon:
 		*engine = new Access::Amazon::AmazonEngine(syst, gd);
diff --git a/engines/adl/metaengine.cpp b/engines/adl/metaengine.cpp
index 509149577dd..269793b287a 100644
--- a/engines/adl/metaengine.cpp
+++ b/engines/adl/metaengine.cpp
@@ -139,7 +139,7 @@ Common::Platform getPlatform(const AdlGameDescription &adlDesc) {
 	return adlDesc.desc.platform;
 }
 
-class AdlMetaEngine : public AdvancedMetaEngine {
+class AdlMetaEngine : public AdvancedMetaEngine<AdlGameDescription> {
 public:
 	const char *getName() const override {
 		return "adl";
@@ -156,7 +156,7 @@ public:
 	SaveStateList listSaves(const char *target) const override;
 	void removeSaveState(const char *target, int slot) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const AdlGameDescription *adlGd) const override;
 	Common::KeymapArray initKeymaps(const char *target) const override;
 };
 
@@ -286,9 +286,7 @@ Engine *HiRes4Engine_create(OSystem *syst, const AdlGameDescription *gd);
 Engine *HiRes5Engine_create(OSystem *syst, const AdlGameDescription *gd);
 Engine *HiRes6Engine_create(OSystem *syst, const AdlGameDescription *gd);
 
-Common::Error AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
-	const AdlGameDescription *adlGd = (const AdlGameDescription *)gd;
-
+Common::Error AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const AdlGameDescription *adlGd) const {
 	switch (adlGd->gameType) {
 	case GAME_TYPE_HIRES1:
 		*engine = HiRes1Engine_create(syst, adlGd);
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index 66e20b118ce..969bd169490 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -305,7 +305,7 @@ DetectedGames AdvancedMetaEngineDetectionBase::detectGames(const Common::FSList
 	return detectedGames;
 }
 
-const ExtraGuiOptions AdvancedMetaEngine::getExtraGuiOptions(const Common::String &target) const {
+const ExtraGuiOptions AdvancedMetaEngineBase::getExtraGuiOptions(const Common::String &target) const {
 	const ADExtraGuiOptionsMap *extraGuiOptions = getAdvancedExtraGuiOptions();
 	if (!extraGuiOptions)
 		return ExtraGuiOptions();
@@ -529,7 +529,7 @@ Common::String md5PropToGameFile(MD5Properties flags) {
 	return res;
 }
 
-static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps);
+static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngineBase::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps);
 
 bool AdvancedMetaEngineDetectionBase::getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
 	Common::String hashname = md5PropToCachePrefix(md5prop);
@@ -554,11 +554,11 @@ bool AdvancedMetaEngineDetectionBase::getFileProperties(const FileMap &allFiles,
 	return res;
 }
 
-bool AdvancedMetaEngine::getFilePropertiesExtern(uint md5Bytes, const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
+bool AdvancedMetaEngineBase::getFilePropertiesExtern(uint md5Bytes, const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
 	return getFilePropertiesIntern(md5Bytes, allFiles, md5prop, fname, fileProps);
 }
 
-static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) {
+static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngineBase::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) {
 	if (md5prop & (kMD5MacResFork | kMD5MacDataFork)) {
 		FileMapArchive fileMapArchive(allFiles);
 		bool is_legacy = ((md5prop & kMD5MacMask) == kMD5MacResOrDataFork);
@@ -1127,7 +1127,7 @@ void AdvancedMetaEngineDetectionBase::detectClashes() const {
 	}
 }
 
-Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine, const DetectedGame &gameDescriptor, const void *meDescriptor) {
+Common::Error AdvancedMetaEngineBase::createInstance(OSystem *syst, Engine **engine, const DetectedGame &gameDescriptor, const void *meDescriptor) {
 	assert(engine);
 
 	const ADGameDescription *adgDesc = (const ADGameDescription *)meDescriptor;
@@ -1169,10 +1169,10 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine,
 	}
 	initSubSystems(adgDesc);
 
-	return createInstance(syst, engine, adgDesc);
+	return createInstance(syst, engine, meDescriptor);
 }
 
-void AdvancedMetaEngine::initSubSystems(const ADGameDescription *gameDesc) const {
+void AdvancedMetaEngineBase::initSubSystems(const ADGameDescription *gameDesc) const {
 #ifdef ENABLE_EVENTRECORDER
 	if (gameDesc) {
 		g_eventRec.processGameDescription(gameDesc);
@@ -1180,7 +1180,7 @@ void AdvancedMetaEngine::initSubSystems(const ADGameDescription *gameDesc) const
 #endif
 }
 
-bool AdvancedMetaEngine::checkExtendedSaves(MetaEngineFeature f) const {
+bool AdvancedMetaEngineBase::checkExtendedSaves(MetaEngineFeature f) const {
 	return (f == kSavesUseExtendedFormat) ||
 		(f == kSimpleSavesNames) ||
 		(f == kSupportsListSaves) ||
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index ee5c866b7e3..a623fa6b399 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -483,7 +483,7 @@ protected:
 /**
  * A MetaEngine implementation of AdvancedMetaEngine.
  */
-class AdvancedMetaEngine : public MetaEngine {
+class AdvancedMetaEngineBase : public MetaEngine {
 public:
 	/**
 	 * Base createInstance for AdvancedMetaEngine.
@@ -499,7 +499,7 @@ public:
 	 * A createInstance implementation for subclasses. To be called after the base
 	 * createInstance function above is called.
 	 */
-	virtual Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const = 0;
+	virtual Common::Error createInstance(OSystem *syst, Engine **engine, const void *desc) const = 0;
 
 	/**
 	 * Return the name of the engine plugin based on the engineID.
@@ -572,6 +572,19 @@ private:
 	void initSubSystems(const ADGameDescription *gameDesc) const;
 };
 
+template<class Descriptor>
+class AdvancedMetaEngine : public AdvancedMetaEngineBase {
+protected:
+	virtual Common::Error createInstance(OSystem *syst, Engine **engine, const Descriptor *desc) const = 0;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const void *desc) const override final {
+		return createInstance(syst, engine, static_cast<const Descriptor *>(desc));
+	}
+
+private:
+	// Silence overloaded-virtual warning from clang
+	using AdvancedMetaEngineBase::createInstance;
+};
+
 /**
  * Singleton Cache Storage for Computed MD5s and Open Archives
  */
diff --git a/engines/agi/metaengine.cpp b/engines/agi/metaengine.cpp
index 5f393b66eed..e0af7988f21 100644
--- a/engines/agi/metaengine.cpp
+++ b/engines/agi/metaengine.cpp
@@ -182,7 +182,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 using namespace Agi;
 
-class AgiMetaEngine : public AdvancedMetaEngine {
+class AgiMetaEngine : public AdvancedMetaEngine<Agi::AGIGameDescription> {
 public:
 	const char *getName() const override {
 		return "agi";
@@ -192,7 +192,7 @@ public:
 		return optionsList;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Agi::AGIGameDescription *gd) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -214,9 +214,7 @@ bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const {
 		(f == kSimpleSavesNames);
 }
 
-Common::Error AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Agi::AGIGameDescription *gd = (const Agi::AGIGameDescription *)desc;
-
+Common::Error AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const Agi::AGIGameDescription *gd) const {
 	switch (gd->gameType) {
 	case Agi::GType_PreAGI:
 		switch (gd->gameID) {
diff --git a/engines/agos/metaengine.cpp b/engines/agos/metaengine.cpp
index 50ec2079d6c..3444f558dd8 100644
--- a/engines/agos/metaengine.cpp
+++ b/engines/agos/metaengine.cpp
@@ -109,7 +109,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 } // End of namespace AGOS
 
-class AgosMetaEngine : public AdvancedMetaEngine {
+class AgosMetaEngine : public AdvancedMetaEngine<AGOS::AGOSGameDescription> {
 public:
 	const char *getName() const override {
 		return "agos";
@@ -121,7 +121,7 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const AGOS::AGOSGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -140,9 +140,7 @@ bool AGOS::AGOSEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsReturnToLauncher);
 }
 
-Common::Error AgosMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const AGOS::AGOSGameDescription *gd = (const AGOS::AGOSGameDescription *)desc;
-
+Common::Error AgosMetaEngine::createInstance(OSystem *syst, Engine **engine, const AGOS::AGOSGameDescription *gd) const {
 	switch (gd->gameType) {
 	case AGOS::GType_PN:
 		*engine = new AGOS::AGOSEngine_PN(syst, gd);
diff --git a/engines/ags/metaengine.cpp b/engines/ags/metaengine.cpp
index 0f534f9ee4d..3dc8085eaf7 100644
--- a/engines/ags/metaengine.cpp
+++ b/engines/ags/metaengine.cpp
@@ -38,9 +38,7 @@ const char *AGSMetaEngine::getName() const {
 	return "ags";
 }
 
-Common::Error AGSMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const AGS::AGSGameDescription *gd = (const AGS::AGSGameDescription *)desc;
-
+Common::Error AGSMetaEngine::createInstance(OSystem *syst, Engine **engine, const AGS::AGSGameDescription *gd) const {
 	*engine = new AGS::AGSEngine(syst, gd);
 	return Common::kNoError;
 }
diff --git a/engines/ags/metaengine.h b/engines/ags/metaengine.h
index 000704aaf86..805cfeadb1d 100644
--- a/engines/ags/metaengine.h
+++ b/engines/ags/metaengine.h
@@ -25,11 +25,13 @@
 #include "engines/achievements.h"
 #include "engines/advancedDetector.h"
 
-class AGSMetaEngine : public AdvancedMetaEngine {
+#include "engines/ags/detection.h"
+
+class AGSMetaEngine : public AdvancedMetaEngine<AGS::AGSGameDescription> {
 public:
 	const char *getName() const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const AGS::AGSGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 
diff --git a/engines/asylum/metaengine.cpp b/engines/asylum/metaengine.cpp
index 833a72d7ab3..6b777037d81 100644
--- a/engines/asylum/metaengine.cpp
+++ b/engines/asylum/metaengine.cpp
@@ -40,7 +40,7 @@
 #include "asylum/asylum.h"
 #include "asylum/shared.h"
 
-class AsylumMetaEngine : public AdvancedMetaEngine {
+class AsylumMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "asylum";
diff --git a/engines/avalanche/metaengine.cpp b/engines/avalanche/metaengine.cpp
index 855f2145e50..570b1beea27 100644
--- a/engines/avalanche/metaengine.cpp
+++ b/engines/avalanche/metaengine.cpp
@@ -53,13 +53,13 @@ Common::Platform AvalancheEngine::getPlatform() const {
 
 namespace Avalanche {
 
-class AvalancheMetaEngine : public AdvancedMetaEngine {
+class AvalancheMetaEngine : public AdvancedMetaEngine<AvalancheGameDescription> {
 public:
 	const char *getName() const override {
 		return "avalanche";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const AvalancheGameDescription *gd) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	int getMaximumSaveSlot() const override { return 99; }
@@ -68,8 +68,8 @@ public:
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
 };
 
-Common::Error AvalancheMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
-	*engine = new AvalancheEngine(syst, (const AvalancheGameDescription *)gd);
+Common::Error AvalancheMetaEngine::createInstance(OSystem *syst, Engine **engine, const AvalancheGameDescription *gd) const {
+	*engine = new AvalancheEngine(syst,gd);
 	return Common::kNoError;
 }
 
diff --git a/engines/bagel/metaengine.h b/engines/bagel/metaengine.h
index 5a030b6a9d0..0c7bc8cb4ca 100644
--- a/engines/bagel/metaengine.h
+++ b/engines/bagel/metaengine.h
@@ -31,7 +31,7 @@ namespace Bagel {
 	};
 }
 
-class BagelMetaEngine : public AdvancedMetaEngine {
+class BagelMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/bbvs/metaengine.cpp b/engines/bbvs/metaengine.cpp
index fc1fcb399b5..ee6d46f2fd2 100644
--- a/engines/bbvs/metaengine.cpp
+++ b/engines/bbvs/metaengine.cpp
@@ -44,7 +44,7 @@ bool BbvsEngine::isLoogieAltDemo() const {
 
 } // End of namespace Bbvs
 
-class BbvsMetaEngine : public AdvancedMetaEngine {
+class BbvsMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "bbvs";
diff --git a/engines/bladerunner/metaengine.cpp b/engines/bladerunner/metaengine.cpp
index a6e47e86c88..177a0361596 100644
--- a/engines/bladerunner/metaengine.cpp
+++ b/engines/bladerunner/metaengine.cpp
@@ -121,7 +121,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 } // End of namespace BladeRunner
 
-class BladeRunnerMetaEngine : public AdvancedMetaEngine {
+class BladeRunnerMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/buried/metaengine.cpp b/engines/buried/metaengine.cpp
index 043295251c1..c6de121e7d5 100644
--- a/engines/buried/metaengine.cpp
+++ b/engines/buried/metaengine.cpp
@@ -90,7 +90,7 @@ Common::Language BuriedEngine::getLanguage() const {
 
 } // End of namespace Buried
 
-class BuriedMetaEngine : public AdvancedMetaEngine {
+class BuriedMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "buried";
diff --git a/engines/cge/metaengine.cpp b/engines/cge/metaengine.cpp
index 0a8e6dc31bf..4f8f4c3fca7 100644
--- a/engines/cge/metaengine.cpp
+++ b/engines/cge/metaengine.cpp
@@ -66,7 +66,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class CGEMetaEngine : public AdvancedMetaEngine {
+class CGEMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "cge";
diff --git a/engines/cge2/metaengine.cpp b/engines/cge2/metaengine.cpp
index 7c7dc565490..9623cdbd364 100644
--- a/engines/cge2/metaengine.cpp
+++ b/engines/cge2/metaengine.cpp
@@ -81,7 +81,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 		AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class CGE2MetaEngine : public AdvancedMetaEngine {
+class CGE2MetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "cge2";
diff --git a/engines/chamber/metaengine.cpp b/engines/chamber/metaengine.cpp
index d39465ab1f9..13eeb7b14b6 100644
--- a/engines/chamber/metaengine.cpp
+++ b/engines/chamber/metaengine.cpp
@@ -30,7 +30,7 @@ Common::Language ChamberEngine::getLanguage() const {
 
 } // end of namespace Chamber
 
-class ChamberMetaEngine : public AdvancedMetaEngine {
+class ChamberMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "chamber";
diff --git a/engines/chewy/metaengine.cpp b/engines/chewy/metaengine.cpp
index 53cf3964036..4d286a7406e 100644
--- a/engines/chewy/metaengine.cpp
+++ b/engines/chewy/metaengine.cpp
@@ -54,7 +54,7 @@ Common::Language ChewyEngine::getLanguage() const {
 
 } // End of namespace Chewy
 
-class ChewyMetaEngine : public AdvancedMetaEngine {
+class ChewyMetaEngine : public AdvancedMetaEngine<Chewy::ChewyGameDescription> {
 public:
 	const char *getName() const override {
 		return "chewy";
@@ -65,7 +65,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Chewy::ChewyGameDescription *desc) const override;
 
 	int getMaximumSaveSlot() const override;
 };
@@ -83,8 +83,8 @@ bool Chewy::ChewyEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error ChewyMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Chewy::ChewyEngine(syst, (const Chewy::ChewyGameDescription *)desc);
+Common::Error ChewyMetaEngine::createInstance(OSystem *syst, Engine **engine, const Chewy::ChewyGameDescription *desc) const {
+	*engine = new Chewy::ChewyEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/cine/metaengine.cpp b/engines/cine/metaengine.cpp
index 97de7741d40..ad7158af1f0 100644
--- a/engines/cine/metaengine.cpp
+++ b/engines/cine/metaengine.cpp
@@ -74,7 +74,7 @@ Common::Platform CineEngine::getPlatform() const { return _gameDescription->desc
 
 } // End of namespace Cine
 
-class CineMetaEngine : public AdvancedMetaEngine {
+class CineMetaEngine : public AdvancedMetaEngine<Cine::CINEGameDescription> {
 public:
 	const char *getName() const override {
 		return "cine";
@@ -84,7 +84,7 @@ public:
 		return Cine::optionsList;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Cine::CINEGameDescription *desc) const override;
 
 	bool hasFeature(MetaEngineFeature f) const override;
 	SaveStateList listSaves(const char *target) const override;
@@ -107,8 +107,8 @@ bool Cine::CineEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error CineMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Cine::CineEngine(syst, (const Cine::CINEGameDescription *)desc);
+Common::Error CineMetaEngine::createInstance(OSystem *syst, Engine **engine, const Cine::CINEGameDescription *desc) const {
+	*engine = new Cine::CineEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/composer/metaengine.cpp b/engines/composer/metaengine.cpp
index dcc0ee36429..41de2c7d1fd 100644
--- a/engines/composer/metaengine.cpp
+++ b/engines/composer/metaengine.cpp
@@ -70,13 +70,13 @@ bool ComposerEngine::loadDetectedConfigFile(Common::INIFile &configFile) const {
 
 } // End of namespace Composer
 
-class ComposerMetaEngine : public AdvancedMetaEngine {
+class ComposerMetaEngine : public AdvancedMetaEngine<Composer::ComposerGameDescription> {
 public:
 	const char *getName() const override {
 		return "composer";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Composer::ComposerGameDescription *desc) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	Common::KeymapArray initKeymaps(const char *target) const override;
@@ -93,8 +93,8 @@ public:
 	}
 };
 
-Common::Error ComposerMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Composer::ComposerEngine(syst, (const Composer::ComposerGameDescription *)desc);
+Common::Error ComposerMetaEngine::createInstance(OSystem *syst, Engine **engine, const Composer::ComposerGameDescription *desc) const {
+	*engine = new Composer::ComposerEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/crab/metaengine.h b/engines/crab/metaengine.h
index 12d33d913a9..afe7c1cf13a 100644
--- a/engines/crab/metaengine.h
+++ b/engines/crab/metaengine.h
@@ -25,7 +25,7 @@
 #include "backends/keymapper/keymapper.h"
 #include "engines/advancedDetector.h"
 
-class CrabMetaEngine : public AdvancedMetaEngine {
+class CrabMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/cruise/metaengine.cpp b/engines/cruise/metaengine.cpp
index 85c6d1aa35d..905eb1e4370 100644
--- a/engines/cruise/metaengine.cpp
+++ b/engines/cruise/metaengine.cpp
@@ -43,7 +43,7 @@ Common::Platform CruiseEngine::getPlatform() const {
 
 } // End of namespace Cruise
 
-class CruiseMetaEngine : public AdvancedMetaEngine {
+class CruiseMetaEngine : public AdvancedMetaEngine<Cruise::CRUISEGameDescription> {
 public:
 	const char *getName() const override {
 		return "cruise";
@@ -55,7 +55,7 @@ public:
 	SaveStateList listSaves(const char *target) const override;
 	void removeSaveState(const char *target, int slot) const override;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Cruise::CRUISEGameDescription *desc) const override;
 };
 
 bool CruiseMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -122,8 +122,8 @@ SaveStateDescriptor CruiseMetaEngine::querySaveMetaInfos(const char *target, int
 	return SaveStateDescriptor();
 }
 
-Common::Error CruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Cruise::CruiseEngine(syst, (const Cruise::CRUISEGameDescription *)desc);
+Common::Error CruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const Cruise::CRUISEGameDescription *desc) const {
+	*engine = new Cruise::CruiseEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/cryo/metaengine.cpp b/engines/cryo/metaengine.cpp
index d1d6dc6500b..44b1df18f41 100644
--- a/engines/cryo/metaengine.cpp
+++ b/engines/cryo/metaengine.cpp
@@ -34,7 +34,7 @@ Common::Platform CryoEngine::getPlatform() const { return _gameDescription->plat
 
 } // End of namespace Cryo
 
-class CryoMetaEngine : public AdvancedMetaEngine {
+class CryoMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "cryo";
diff --git a/engines/cryomni3d/metaengine.cpp b/engines/cryomni3d/metaengine.cpp
index 8b426bee033..5c9cef1e3bb 100644
--- a/engines/cryomni3d/metaengine.cpp
+++ b/engines/cryomni3d/metaengine.cpp
@@ -66,14 +66,14 @@ bool CryOmni3DEngine::hasFeature(EngineFeature f) const {
 }
 
 
-class CryOmni3DMetaEngine : public AdvancedMetaEngine {
+class CryOmni3DMetaEngine : public AdvancedMetaEngine<CryOmni3DGameDescription> {
 public:
 	const char *getName() const override {
 		return "cryomni3d";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const CryOmni3DGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override { return 999; }
@@ -133,9 +133,7 @@ void CryOmni3DMetaEngine::removeSaveState(const char *target, int slot) const {
 }
 
 Common::Error CryOmni3DMetaEngine::createInstance(OSystem *syst, Engine **engine,
-		const ADGameDescription *desc) const {
-	const CryOmni3DGameDescription *gd = (const CryOmni3DGameDescription *)desc;
-
+		const CryOmni3DGameDescription *gd) const {
 	switch (gd->gameType) {
 	case GType_VERSAILLES:
 #ifdef ENABLE_VERSAILLES
diff --git a/engines/director/metaengine.cpp b/engines/director/metaengine.cpp
index 5189ce4e411..5b3c114c4a1 100644
--- a/engines/director/metaengine.cpp
+++ b/engines/director/metaengine.cpp
@@ -64,17 +64,17 @@ bool DirectorEngine::hasFeature(EngineFeature f) const {
 
 } // End of Namespace Director
 
-class DirectorMetaEngine : public AdvancedMetaEngine {
+class DirectorMetaEngine : public AdvancedMetaEngine<Director::DirectorGameDescription> {
 public:
 	const char *getName() const override {
 		return "director";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Director::DirectorGameDescription *desc) const override;
 };
 
-Common::Error DirectorMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Director::DirectorEngine(syst, (const Director::DirectorGameDescription *)desc);
+Common::Error DirectorMetaEngine::createInstance(OSystem *syst, Engine **engine, const Director::DirectorGameDescription *desc) const {
+	*engine = new Director::DirectorEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/dm/metaengine.cpp b/engines/dm/metaengine.cpp
index 6dbc397c823..4e331c9b453 100644
--- a/engines/dm/metaengine.cpp
+++ b/engines/dm/metaengine.cpp
@@ -35,13 +35,13 @@
 
 namespace DM {
 
-class DMMetaEngine : public AdvancedMetaEngine {
+class DMMetaEngine : public AdvancedMetaEngine<DMADGameDescription> {
 public:
 	const char *getName() const override {
 		return "dm";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
+	Common::Error createInstance(OSystem *syst, Engine **engine, const DMADGameDescription *desc) const override {
 		*engine = new DM::DMEngine(syst, (const DMADGameDescription*)desc);
 		return Common::kNoError;
 	}
diff --git a/engines/draci/metaengine.cpp b/engines/draci/metaengine.cpp
index 9519dc4c314..07f42da11c7 100644
--- a/engines/draci/metaengine.cpp
+++ b/engines/draci/metaengine.cpp
@@ -27,7 +27,7 @@
 #include "engines/advancedDetector.h"
 #include "engines/metaengine.h"
 
-class DraciMetaEngine : public AdvancedMetaEngine {
+class DraciMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "draci";
diff --git a/engines/dragons/dragons.cpp b/engines/dragons/dragons.cpp
index af79d9e3d99..52fb3d74a91 100644
--- a/engines/dragons/dragons.cpp
+++ b/engines/dragons/dragons.cpp
@@ -60,8 +60,8 @@ DragonsEngine *getEngine() {
 	return _engine;
 }
 
-DragonsEngine::DragonsEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst) {
-	_language = desc->language;
+DragonsEngine::DragonsEngine(OSystem *syst, const DragonsGameDescription *gd) : Engine(syst) {
+	_language = gd->desc.language;
 	_bigfileArchive = nullptr;
 	_dragonRMS = nullptr;
 	_backgroundResourceLoader = nullptr;
diff --git a/engines/dragons/dragons.h b/engines/dragons/dragons.h
index d61662b31cb..61a6362860c 100644
--- a/engines/dragons/dragons.h
+++ b/engines/dragons/dragons.h
@@ -245,7 +245,7 @@ private:
 protected:
 	bool hasFeature(EngineFeature f) const override;
 public:
-	DragonsEngine(OSystem *syst, const ADGameDescription *desc);
+	DragonsEngine(OSystem *syst, const DragonsGameDescription *desc);
 	~DragonsEngine();
 
 	void updateEvents();
diff --git a/engines/dragons/metaengine.cpp b/engines/dragons/metaengine.cpp
index e9fbf888ec9..e1adbffc087 100644
--- a/engines/dragons/metaengine.cpp
+++ b/engines/dragons/metaengine.cpp
@@ -30,14 +30,14 @@
 #include "base/plugins.h"
 #include "graphics/thumbnail.h"
 
-class DragonsMetaEngine : public AdvancedMetaEngine {
+class DragonsMetaEngine : public AdvancedMetaEngine<Dragons::DragonsGameDescription> {
 public:
 	const char *getName() const override {
 		return "dragons";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Dragons::DragonsGameDescription *desc) const override;
 	int getMaximumSaveSlot() const override;
 	SaveStateList listSaves(const char *target) const override;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
@@ -110,13 +110,12 @@ SaveStateDescriptor DragonsMetaEngine::querySaveMetaInfos(const char *target, in
 	return SaveStateDescriptor();
 }
 
-Common::Error DragonsMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Dragons::DragonsGameDescription *gd = (const Dragons::DragonsGameDescription *)desc;
+Common::Error DragonsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Dragons::DragonsGameDescription *gd) const {
 	const char* urlForRequiredDataFiles = "https://wiki.scummvm.org/index.php?title=Blazing_Dragons#Required_data_files";
 
 	switch (gd->gameId) {
 	case Dragons::kGameIdDragons:
-		*engine = new Dragons::DragonsEngine(syst, desc);
+		*engine = new Dragons::DragonsEngine(syst, gd);
 		break;
 	case Dragons::kGameIdDragonsBadExtraction:
 		GUIErrorMessageWithURL(Common::U32String::format(_("Error: It appears that the game data files were extracted incorrectly.\n\nYou should only extract STR and XA files using the special method. The rest should be copied normally from your game CD.\n\n See %s"), urlForRequiredDataFiles), urlForRequiredDataFiles);
diff --git a/engines/drascula/metaengine.cpp b/engines/drascula/metaengine.cpp
index a22b918aafd..d2e9c598b42 100644
--- a/engines/drascula/metaengine.cpp
+++ b/engines/drascula/metaengine.cpp
@@ -74,7 +74,7 @@ namespace Drascula {
 
 SaveStateDescriptor loadMetaData(Common::ReadStream *s, int slot, bool setPlayTime);
 
-class DrasculaMetaEngine : public AdvancedMetaEngine {
+class DrasculaMetaEngine : public AdvancedMetaEngine<Drascula::DrasculaGameDescription> {
 public:
 	const char *getName() const override {
 		return "drascula";
@@ -84,7 +84,7 @@ public:
 		return Drascula::optionsList;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Drascula::DrasculaGameDescription *gd) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	SaveStateList listSaves(const char *target) const override;
@@ -172,8 +172,8 @@ void DrasculaMetaEngine::removeSaveState(const char *target, int slot) const {
 	g_system->getSavefileManager()->removeSavefile(fileName);
 }
 
-Common::Error DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Drascula::DrasculaEngine(syst, (const Drascula::DrasculaGameDescription *)desc);
+Common::Error DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Drascula::DrasculaGameDescription *desc) const {
+	*engine = new Drascula::DrasculaEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/dreamweb/metaengine.cpp b/engines/dreamweb/metaengine.cpp
index 9de33bb63cf..265bd73be37 100644
--- a/engines/dreamweb/metaengine.cpp
+++ b/engines/dreamweb/metaengine.cpp
@@ -95,7 +95,7 @@ static const ADExtraGuiOptionsMap gameGuiOptions[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class DreamWebMetaEngine : public AdvancedMetaEngine {
+class DreamWebMetaEngine : public AdvancedMetaEngine<DreamWeb::DreamWebGameDescription> {
 public:
 	const char *getName() const override {
 		return "dreamweb";
@@ -105,7 +105,7 @@ public:
 		return gameGuiOptions;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const DreamWeb::DreamWebGameDescription *desc) const override;
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
@@ -147,8 +147,8 @@ bool DreamWeb::DreamWebEngine::hasFeature(EngineFeature f) const {
 	}
 }
 
-Common::Error DreamWebMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new DreamWeb::DreamWebEngine(syst, (const DreamWeb::DreamWebGameDescription *)desc);
+Common::Error DreamWebMetaEngine::createInstance(OSystem *syst, Engine **engine, const DreamWeb::DreamWebGameDescription *desc) const {
+	*engine = new DreamWeb::DreamWebEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/efh/metaengine.cpp b/engines/efh/metaengine.cpp
index 122e2c4d649..6e1b80ebd2a 100644
--- a/engines/efh/metaengine.cpp
+++ b/engines/efh/metaengine.cpp
@@ -57,7 +57,7 @@ Common::Platform EfhEngine::getPlatform() const {
 
 namespace Efh {
 
-class EfhMetaEngine : public AdvancedMetaEngine {
+class EfhMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "efh";
diff --git a/engines/freescape/metaengine.cpp b/engines/freescape/metaengine.cpp
index 4ae108f70be..32f8c64a0a9 100644
--- a/engines/freescape/metaengine.cpp
+++ b/engines/freescape/metaengine.cpp
@@ -125,7 +125,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class FreescapeMetaEngine : public AdvancedMetaEngine {
+class FreescapeMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "freescape";
diff --git a/engines/gnap/metaengine.cpp b/engines/gnap/metaengine.cpp
index 8146d3c18e0..3871e43df39 100644
--- a/engines/gnap/metaengine.cpp
+++ b/engines/gnap/metaengine.cpp
@@ -28,7 +28,7 @@
 #include "base/plugins.h"
 #include "graphics/thumbnail.h"
 
-class GnapMetaEngine : public AdvancedMetaEngine {
+class GnapMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "gnap";
diff --git a/engines/gob/metaengine.cpp b/engines/gob/metaengine.cpp
index 6f23fc1b8d3..e0e7e77b607 100644
--- a/engines/gob/metaengine.cpp
+++ b/engines/gob/metaengine.cpp
@@ -50,7 +50,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class GobMetaEngine : public AdvancedMetaEngine {
+class GobMetaEngine : public AdvancedMetaEngine<Gob::GOBGameDescription> {
 public:
 	const char *getName() const override {
 		return "gob";
@@ -58,7 +58,7 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Gob::GOBGameDescription *desc) const override;
 
 	const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
 		return optionsList;
@@ -74,8 +74,7 @@ bool Gob::GobEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsReturnToLauncher);
 }
 
-Common::Error GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Gob::GOBGameDescription *gd = (const Gob::GOBGameDescription *)desc;
+Common::Error GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const Gob::GOBGameDescription *gd) const {
 	*engine = new Gob::GobEngine(syst);
 	((Gob::GobEngine *)*engine)->initGame(gd);
 	return Common::kNoError;
diff --git a/engines/griffon/metaengine.cpp b/engines/griffon/metaengine.cpp
index 838e89db58b..f5817dc5a21 100644
--- a/engines/griffon/metaengine.cpp
+++ b/engines/griffon/metaengine.cpp
@@ -50,7 +50,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 #endif
 
-class GriffonMetaEngine: public AdvancedMetaEngine {
+class GriffonMetaEngine: public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "griffon";
diff --git a/engines/grim/metaengine.cpp b/engines/grim/metaengine.cpp
index 6cacfe35493..92fcd5d4157 100644
--- a/engines/grim/metaengine.cpp
+++ b/engines/grim/metaengine.cpp
@@ -57,7 +57,7 @@ static const ADExtraGuiOptionsMap gameGuiOptions[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class GrimMetaEngine : public AdvancedMetaEngine {
+class GrimMetaEngine : public AdvancedMetaEngine<Grim::GrimGameDescription> {
 public:
 	const char *getName() const override {
 		return "grim";
@@ -67,7 +67,7 @@ public:
 		return gameGuiOptions;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Grim::GrimGameDescription *desc) const override;
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
@@ -77,7 +77,7 @@ public:
 
 };
 
-Common::Error GrimMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+Common::Error GrimMetaEngine::createInstance(OSystem *syst, Engine **engine, const Grim::GrimGameDescription *desc) const {
 	const GrimGameDescription *gd = (const GrimGameDescription *)desc;
 
 	if (gd->gameType == GType_MONKEY4) {
diff --git a/engines/groovie/metaengine.cpp b/engines/groovie/metaengine.cpp
index d034c20c3f6..94e1545755d 100644
--- a/engines/groovie/metaengine.cpp
+++ b/engines/groovie/metaengine.cpp
@@ -118,7 +118,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class GroovieMetaEngine : public AdvancedMetaEngine {
+class GroovieMetaEngine : public AdvancedMetaEngine<GroovieGameDescription> {
 public:
 	const char *getName() const override {
 		return "groovie";
@@ -128,7 +128,7 @@ public:
 		return optionsList;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const GroovieGameDescription *gd) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	SaveStateList listSaves(const char *target) const override;
@@ -138,13 +138,13 @@ public:
 	int getAutosaveSlot() const override;
 };
 
-Common::Error GroovieMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
+Common::Error GroovieMetaEngine::createInstance(OSystem *syst, Engine **engine, const GroovieGameDescription *gd) const {
 #ifndef ENABLE_GROOVIE2
-	if (((const GroovieGameDescription *)gd)->version != kGroovieT7G)
+	if (gd->version != kGroovieT7G)
 		return Common::Error(Common::kUnsupportedGameidError, _s("GroovieV2 support is not compiled in"));
 #endif
 
-	*engine = new GroovieEngine(syst, (const GroovieGameDescription *)gd);
+	*engine = new GroovieEngine(syst,gd);
 	return Common::kNoError;
 }
 
diff --git a/engines/hadesch/metaengine.cpp b/engines/hadesch/metaengine.cpp
index baf23dc0d74..28b6e02e94b 100644
--- a/engines/hadesch/metaengine.cpp
+++ b/engines/hadesch/metaengine.cpp
@@ -26,7 +26,7 @@
 #include "hadesch/hadesch.h"
 #include "engines/advancedDetector.h"
 
-class HadeschMetaEngine : public AdvancedMetaEngine {
+class HadeschMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	bool hasFeature(MetaEngineFeature f) const override {
 		return
diff --git a/engines/hdb/metaengine.cpp b/engines/hdb/metaengine.cpp
index f90dee6b7ab..9e51c1d0403 100644
--- a/engines/hdb/metaengine.cpp
+++ b/engines/hdb/metaengine.cpp
@@ -78,7 +78,7 @@ bool HDBGame::isHandango() const {
 
 } // End of namespace HDB
 
-class HDBMetaEngine : public AdvancedMetaEngine {
+class HDBMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "hdb";
diff --git a/engines/hopkins/metaengine.cpp b/engines/hopkins/metaengine.cpp
index b35ac3b84ae..49d32b2730d 100644
--- a/engines/hopkins/metaengine.cpp
+++ b/engines/hopkins/metaengine.cpp
@@ -86,7 +86,7 @@ const Common::String &HopkinsEngine::getTargetName() const {
 
 } // End of namespace Hopkins
 
-class HopkinsMetaEngine : public AdvancedMetaEngine {
+class HopkinsMetaEngine : public AdvancedMetaEngine<Hopkins::HopkinsGameDescription> {
 public:
 	const char *getName() const override {
 		return "hopkins";
@@ -97,7 +97,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Hopkins::HopkinsGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -122,8 +122,8 @@ bool Hopkins::HopkinsEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error HopkinsMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Hopkins::HopkinsEngine(syst, (const Hopkins::HopkinsGameDescription *)desc);
+Common::Error HopkinsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Hopkins::HopkinsGameDescription *desc) const {
+	*engine = new Hopkins::HopkinsEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/hpl1/metaengine.h b/engines/hpl1/metaengine.h
index bb90ddbfa00..f185340f024 100644
--- a/engines/hpl1/metaengine.h
+++ b/engines/hpl1/metaengine.h
@@ -24,7 +24,7 @@
 
 #include "engines/advancedDetector.h"
 
-class Hpl1MetaEngine : public AdvancedMetaEngine {
+class Hpl1MetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/hugo/metaengine.cpp b/engines/hugo/metaengine.cpp
index d7169aa8dfd..0b1eccdc92d 100644
--- a/engines/hugo/metaengine.cpp
+++ b/engines/hugo/metaengine.cpp
@@ -39,13 +39,13 @@ const char *HugoEngine::getGameId() const {
 	return _gameDescription->desc.gameId;
 }
 
-class HugoMetaEngine : public AdvancedMetaEngine {
+class HugoMetaEngine : public AdvancedMetaEngine<HugoGameDescription> {
 public:
 	const char *getName() const override {
 		return "hugo";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const HugoGameDescription *gd) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	int getMaximumSaveSlot() const override;
@@ -62,9 +62,9 @@ public:
 	}
 };
 
-Common::Error HugoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
-	*engine = new HugoEngine(syst, (const HugoGameDescription *)gd);
-	((HugoEngine *)*engine)->initGame((const HugoGameDescription *)gd);
+Common::Error HugoMetaEngine::createInstance(OSystem *syst, Engine **engine, const HugoGameDescription *gd) const {
+	*engine = new HugoEngine(syst,gd);
+	((HugoEngine *)*engine)->initGame(gd);
 	return Common::kNoError;
 }
 
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index 20d51dfd620..ebb0a36df4e 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -85,7 +85,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class HypnoMetaEngine : public AdvancedMetaEngine {
+class HypnoMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "hypno";
diff --git a/engines/icb/metaengine.cpp b/engines/icb/metaengine.cpp
index 2920f20edf3..0e0edd0f37d 100644
--- a/engines/icb/metaengine.cpp
+++ b/engines/icb/metaengine.cpp
@@ -27,20 +27,19 @@
 
 namespace ICB {
 
-class IcbMetaEngine : public AdvancedMetaEngine {
+class IcbMetaEngine : public AdvancedMetaEngine<IcbGameDescription> {
 public:
 	const char *getName() const override {
 		return "icb";
 	}
 	bool hasFeature(MetaEngineFeature f) const override { return false; }
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const IcbGameDescription *desc) const override;
 
 	Common::KeymapArray initKeymaps(const char *target) const override;
 };
 
-Common::Error IcbMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const IcbGameDescription *gd = (const IcbGameDescription *)desc;
+Common::Error IcbMetaEngine::createInstance(OSystem *syst, Engine **engine, const IcbGameDescription *gd) const {
 	*engine = new IcbEngine(syst, gd);
 	return Common::kNoError;
 }
diff --git a/engines/illusions/metaengine.cpp b/engines/illusions/metaengine.cpp
index 476c38fd5dc..5f7f2889331 100644
--- a/engines/illusions/metaengine.cpp
+++ b/engines/illusions/metaengine.cpp
@@ -44,14 +44,14 @@ Common::Language IllusionsEngine::getGameLanguage() const {
 
 } // End of namespace Illusions
 
-class IllusionsMetaEngine : public AdvancedMetaEngine {
+class IllusionsMetaEngine : public AdvancedMetaEngine<Illusions::IllusionsGameDescription> {
 public:
 	const char *getName() const override {
 		return "illusions";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Illusions::IllusionsGameDescription *desc) const override;
 
 	int getMaximumSaveSlot() const override;
 	SaveStateList listSaves(const char *target) const override;
@@ -124,8 +124,7 @@ SaveStateDescriptor IllusionsMetaEngine::querySaveMetaInfos(const char *target,
 	return SaveStateDescriptor();
 }
 
-Common::Error IllusionsMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Illusions::IllusionsGameDescription *gd = (const Illusions::IllusionsGameDescription *)desc;
+Common::Error IllusionsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Illusions::IllusionsGameDescription *gd) const {
 	switch (gd->gameId) {
 	case Illusions::kGameIdBBDOU:
 		*engine = new Illusions::IllusionsEngine_BBDOU(syst, gd);
diff --git a/engines/immortal/metaengine.h b/engines/immortal/metaengine.h
index cb80691c010..b98ac8dc656 100644
--- a/engines/immortal/metaengine.h
+++ b/engines/immortal/metaengine.h
@@ -26,7 +26,7 @@
 #include "engines/achievements.h"
 #include "engines/advancedDetector.h"
 
-class ImmortalMetaEngine : public AdvancedMetaEngine {
+class ImmortalMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/kingdom/metaengine.cpp b/engines/kingdom/metaengine.cpp
index 03f23569370..6ac6c593ad4 100644
--- a/engines/kingdom/metaengine.cpp
+++ b/engines/kingdom/metaengine.cpp
@@ -37,7 +37,7 @@ Common::Platform KingdomGame::getPlatform() const { return _gameDescription->pla
 } // End of namespace Kingdom
 
 
-class KingdomMetaEngine : public AdvancedMetaEngine {
+class KingdomMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "kingdom";
diff --git a/engines/kyra/metaengine.cpp b/engines/kyra/metaengine.cpp
index a1ed1ad7063..f1c80db71e2 100644
--- a/engines/kyra/metaengine.cpp
+++ b/engines/kyra/metaengine.cpp
@@ -156,7 +156,7 @@ const ADExtraGuiOptionsMap gameGuiOptions[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class KyraMetaEngine : public AdvancedMetaEngine {
+class KyraMetaEngine : public AdvancedMetaEngine<KYRAGameDescription> {
 public:
 	const char *getName() const override {
 		return "kyra";
@@ -167,7 +167,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const KYRAGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -198,9 +198,7 @@ bool Kyra::KyraEngine_v1::hasFeature(EngineFeature f) const {
 	    (f == kSupportsSubtitleOptions);
 }
 
-Common::Error KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const KYRAGameDescription *gd = (const KYRAGameDescription *)desc;
-
+Common::Error KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const KYRAGameDescription *gd) const {
 	Kyra::GameFlags flags = gd->flags;
 
 	flags.lang = gd->desc.language;
diff --git a/engines/lab/metaengine.cpp b/engines/lab/metaengine.cpp
index d886fb40f1a..1925b64fb93 100644
--- a/engines/lab/metaengine.cpp
+++ b/engines/lab/metaengine.cpp
@@ -42,7 +42,7 @@ uint32 LabEngine::getFeatures() const {
 
 } // End of namespace Lab
 
-class LabMetaEngine : public AdvancedMetaEngine {
+class LabMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "lab";
diff --git a/engines/lastexpress/metaengine.cpp b/engines/lastexpress/metaengine.cpp
index 63f546eb4aa..648a8722b2f 100644
--- a/engines/lastexpress/metaengine.cpp
+++ b/engines/lastexpress/metaengine.cpp
@@ -25,7 +25,7 @@
 
 namespace LastExpress {
 
-class LastExpressMetaEngine : public AdvancedMetaEngine {
+class LastExpressMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "lastexpress";
@@ -42,7 +42,7 @@ protected:
 };
 
 Common::Error LastExpressMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
-	*engine = new LastExpressEngine(syst, (const ADGameDescription *)gd);
+	*engine = new LastExpressEngine(syst, gd);
 	return Common::kNoError;
 }
 
diff --git a/engines/lilliput/metaengine.cpp b/engines/lilliput/metaengine.cpp
index 9bb6ead78f3..a1707f05a5d 100644
--- a/engines/lilliput/metaengine.cpp
+++ b/engines/lilliput/metaengine.cpp
@@ -43,13 +43,13 @@ const char *LilliputEngine::getGameId() const {
 
 namespace Lilliput {
 
-class LilliputMetaEngine : public AdvancedMetaEngine {
+class LilliputMetaEngine : public AdvancedMetaEngine<LilliputGameDescription> {
 public:
 	const char *getName() const override {
 		return "lilliput";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const LilliputGameDescription *gd) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	int getMaximumSaveSlot() const override;
@@ -66,9 +66,9 @@ public:
 	}
 };
 
-Common::Error LilliputMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
-	*engine = new LilliputEngine(syst, (const LilliputGameDescription *)gd);
-	((LilliputEngine *)*engine)->initGame((const LilliputGameDescription *)gd);
+Common::Error LilliputMetaEngine::createInstance(OSystem *syst, Engine **engine, const LilliputGameDescription *gd) const {
+	*engine = new LilliputEngine(syst,gd);
+	((LilliputEngine *)*engine)->initGame(gd);
 	return Common::kNoError;
 }
 
diff --git a/engines/lure/metaengine.cpp b/engines/lure/metaengine.cpp
index b2fda3ca96c..878c6c84b9d 100644
--- a/engines/lure/metaengine.cpp
+++ b/engines/lure/metaengine.cpp
@@ -80,7 +80,7 @@ LureLanguage LureEngine::getLureLanguage() const {
 
 } // End of namespace Lure
 
-class LureMetaEngine : public AdvancedMetaEngine {
+class LureMetaEngine : public AdvancedMetaEngine<Lure::LureGameDescription> {
 public:
 	const char *getName() const override {
 		return "lure";
@@ -91,7 +91,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Lure::LureGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -113,8 +113,8 @@ bool Lure::LureEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error LureMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Lure::LureEngine(syst, (const Lure::LureGameDescription *)desc);
+Common::Error LureMetaEngine::createInstance(OSystem *syst, Engine **engine, const Lure::LureGameDescription *desc) const {
+	*engine = new Lure::LureEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/m4/metaengine.cpp b/engines/m4/metaengine.cpp
index 5bfde064deb..df4c75d3f88 100644
--- a/engines/m4/metaengine.cpp
+++ b/engines/m4/metaengine.cpp
@@ -55,9 +55,7 @@ const ADExtraGuiOptionsMap *M4MetaEngine::getAdvancedExtraGuiOptions() const {
 	return M4::optionsList;
 }
 
-Common::Error M4MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const M4::M4GameDescription *gd = (const M4::M4GameDescription *)desc;
-
+Common::Error M4MetaEngine::createInstance(OSystem *syst, Engine **engine, const M4::M4GameDescription *gd) const {
 	switch (gd->gameType) {
 	case M4::GType_Burger:
 		*engine = new M4::Burger::BurgerEngine(syst, gd);
diff --git a/engines/m4/metaengine.h b/engines/m4/metaengine.h
index 4ee90f1a1c9..10008819bba 100644
--- a/engines/m4/metaengine.h
+++ b/engines/m4/metaengine.h
@@ -25,7 +25,9 @@
 #include "graphics/surface.h"
 #include "engines/advancedDetector.h"
 
-class M4MetaEngine : public AdvancedMetaEngine {
+#include "engines/m4/detection.h"
+
+class M4MetaEngine : public AdvancedMetaEngine<M4::M4GameDescription> {
 private:
 	Common::InSaveFile *getOriginalSave(const Common::String &saveName) const;
 
@@ -37,7 +39,7 @@ public:
 
 	const char *getName() const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const M4::M4GameDescription *desc) const override;
 
 	/**
 	 * Determine whether the engine supports the specified MetaEngine feature.
diff --git a/engines/macventure/metaengine.cpp b/engines/macventure/metaengine.cpp
index 787e9c54da2..02fab9e582c 100644
--- a/engines/macventure/metaengine.cpp
+++ b/engines/macventure/metaengine.cpp
@@ -39,7 +39,7 @@ namespace MacVenture {
 
 SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot, bool skipThumbnail = true);
 
-class MacVentureMetaEngine : public AdvancedMetaEngine {
+class MacVentureMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "macventure";
diff --git a/engines/made/metaengine.cpp b/engines/made/metaengine.cpp
index 3400154e4dc..1c3eb9d4d2a 100644
--- a/engines/made/metaengine.cpp
+++ b/engines/made/metaengine.cpp
@@ -64,7 +64,7 @@ uint16 MadeEngine::getVersion() const {
 
 } // End of namespace Made
 
-class MadeMetaEngine : public AdvancedMetaEngine {
+class MadeMetaEngine : public AdvancedMetaEngine<Made::MadeGameDescription> {
 public:
 	const char *getName() const override {
 		return "made";
@@ -75,7 +75,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Made::MadeGameDescription *desc) const override;
 
 	Common::KeymapArray initKeymaps(const char *target) const override;
 };
@@ -90,8 +90,8 @@ bool Made::MadeEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsReturnToLauncher);
 }
 
-Common::Error MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Made::MadeEngine(syst, (const Made::MadeGameDescription *)desc);
+Common::Error MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const Made::MadeGameDescription *desc) const {
+	*engine = new Made::MadeEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/mads/metaengine.cpp b/engines/mads/metaengine.cpp
index 7c1596a48a9..7dffa95153d 100644
--- a/engines/mads/metaengine.cpp
+++ b/engines/mads/metaengine.cpp
@@ -156,7 +156,7 @@ Common::Platform MADSEngine::getPlatform() const {
 
 } // End of namespace MADS
 
-class MADSMetaEngine : public AdvancedMetaEngine {
+class MADSMetaEngine : public AdvancedMetaEngine<MADS::MADSGameDescription> {
 public:
 	const char *getName() const override {
 		return "mads";
@@ -167,7 +167,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const MADS::MADSGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -192,8 +192,8 @@ bool MADS::MADSEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error MADSMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new MADS::MADSEngine(syst, (const MADS::MADSGameDescription *)desc);
+Common::Error MADSMetaEngine::createInstance(OSystem *syst, Engine **engine, const MADS::MADSGameDescription *desc) const {
+	*engine = new MADS::MADSEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/mm/metaengine.cpp b/engines/mm/metaengine.cpp
index 5ebe55c9488..1a4c1690fd8 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -87,7 +87,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class MMMetaEngine : public AdvancedMetaEngine {
+class MMMetaEngine : public AdvancedMetaEngine<MM::MightAndMagicGameDescription> {
 private:
 	/**
 	 * Gets the game Id given a target string
@@ -104,7 +104,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const MM::MightAndMagicGameDescription *desc) const override;
 	SaveStateList listSaves(const char *target) const override;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
 	Common::KeymapArray initKeymaps(const char *target) const override;
@@ -119,9 +119,7 @@ bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
 		(f == kSupportsLoadingDuringStartup);
 }
 
-Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const MM::MightAndMagicGameDescription *gd = (const MM::MightAndMagicGameDescription *)desc;
-
+Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const MM::MightAndMagicGameDescription *gd) const {
 	switch (gd->gameID) {
 #ifdef ENABLE_MM1
 	case MM::GType_MightAndMagic1:
diff --git a/engines/mohawk/metaengine.cpp b/engines/mohawk/metaengine.cpp
index 426151f69be..05c7921bc24 100644
--- a/engines/mohawk/metaengine.cpp
+++ b/engines/mohawk/metaengine.cpp
@@ -121,14 +121,14 @@ bool MohawkEngine_Riven::hasFeature(EngineFeature f) const {
 
 } // End of Namespace Mohawk
 
-class MohawkMetaEngine : public AdvancedMetaEngine {
+class MohawkMetaEngine : public AdvancedMetaEngine<Mohawk::MohawkGameDescription> {
 public:
 	const char *getName() const override {
 		return "mohawk";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Mohawk::MohawkGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	SaveStateList listSavesForPrefix(const char *prefix, const char *extension) const;
@@ -280,9 +280,7 @@ Common::KeymapArray MohawkMetaEngine::initKeymaps(const char *target) const {
 	return AdvancedMetaEngine::initKeymaps(target);
 }
 
-Common::Error MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Mohawk::MohawkGameDescription *gd = (const Mohawk::MohawkGameDescription *)desc;
-
+Common::Error MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const Mohawk::MohawkGameDescription *gd) const {
 	switch (gd->gameType) {
 	case Mohawk::GType_MYST:
 	case Mohawk::GType_MAKINGOF:
diff --git a/engines/mortevielle/metaengine.cpp b/engines/mortevielle/metaengine.cpp
index 505a77b0095..127d4d11bd8 100644
--- a/engines/mortevielle/metaengine.cpp
+++ b/engines/mortevielle/metaengine.cpp
@@ -38,13 +38,13 @@ bool MortevielleEngine::useOriginalData() const { return _gameDescription->dataF
 
 } // End of namespace Mortevielle
 
-class MortevielleMetaEngine : public AdvancedMetaEngine {
+class MortevielleMetaEngine : public AdvancedMetaEngine<Mortevielle::MortevielleGameDescription> {
 public:
 	const char *getName() const override {
 		return "mortevielle";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Mortevielle::MortevielleGameDescription *desc) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	int getMaximumSaveSlot() const override;
@@ -60,8 +60,8 @@ public:
 	}
 };
 
-Common::Error MortevielleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Mortevielle::MortevielleEngine(syst, (const Mortevielle::MortevielleGameDescription *)desc);
+Common::Error MortevielleMetaEngine::createInstance(OSystem *syst, Engine **engine, const Mortevielle::MortevielleGameDescription *desc) const {
+	*engine = new Mortevielle::MortevielleEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/mtropolis/metaengine.cpp b/engines/mtropolis/metaengine.cpp
index 9153581a066..fd51e34d439 100644
--- a/engines/mtropolis/metaengine.cpp
+++ b/engines/mtropolis/metaengine.cpp
@@ -125,7 +125,7 @@ Common::Platform MTropolisEngine::getPlatform() const {
 
 } // End of namespace MTropolis
 
-class MTropolisMetaEngine : public AdvancedMetaEngine {
+class MTropolisMetaEngine : public AdvancedMetaEngine<MTropolis::MTropolisGameDescription> {
 public:
 	const char *getName() const override {
 		return "mtropolis";
@@ -136,7 +136,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const MTropolis::MTropolisGameDescription *desc) const override;
 
 	Common::Array<Common::Keymap *> initKeymaps(const char *target) const override;
 
@@ -147,7 +147,7 @@ bool MTropolisMetaEngine::hasFeature(MetaEngineFeature f) const {
 	return checkExtendedSaves(f);
 }
 
-Common::Error MTropolisMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+Common::Error MTropolisMetaEngine::createInstance(OSystem *syst, Engine **engine, const MTropolis::MTropolisGameDescription *desc) const {
 	*engine = new MTropolis::MTropolisEngine(syst, reinterpret_cast<const MTropolis::MTropolisGameDescription *>(desc));
 	return Common::kNoError;
 }
diff --git a/engines/mutationofjb/metaengine.cpp b/engines/mutationofjb/metaengine.cpp
index ae4e5faaf05..7cb8692b478 100644
--- a/engines/mutationofjb/metaengine.cpp
+++ b/engines/mutationofjb/metaengine.cpp
@@ -28,7 +28,7 @@
 
 #include "engines/advancedDetector.h"
 
-class MutationOfJBMetaEngine : public AdvancedMetaEngine {
+class MutationOfJBMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "mutationofjb";
diff --git a/engines/myst3/metaengine.cpp b/engines/myst3/metaengine.cpp
index c915484744a..69e4b65747e 100644
--- a/engines/myst3/metaengine.cpp
+++ b/engines/myst3/metaengine.cpp
@@ -49,7 +49,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class Myst3MetaEngine : public AdvancedMetaEngine {
+class Myst3MetaEngine : public AdvancedMetaEngine<Myst3GameDescription> {
 public:
 	const char *getName() const override {
 		return "myst3";
@@ -150,13 +150,13 @@ public:
 		return 999;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Myst3GameDescription *desc) const override;
 
 	// TODO: Add getSavegameFile()
 };
 
-Common::Error Myst3MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Myst3Engine(syst, (const Myst3GameDescription *)desc);
+Common::Error Myst3MetaEngine::createInstance(OSystem *syst, Engine **engine, const Myst3GameDescription *desc) const {
+	*engine = new Myst3Engine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/nancy/metaengine.cpp b/engines/nancy/metaengine.cpp
index 2330bc7e758..8c0da47db73 100644
--- a/engines/nancy/metaengine.cpp
+++ b/engines/nancy/metaengine.cpp
@@ -101,14 +101,14 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class NancyMetaEngine : public AdvancedMetaEngine {
+class NancyMetaEngine : public AdvancedMetaEngine<Nancy::NancyGameDescription> {
 public:
 	const char *getName() const override {
 		return "nancy";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Nancy::NancyGameDescription *gd) const override;
 
 	int getMaximumSaveSlot() const override;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
@@ -134,9 +134,9 @@ bool NancyMetaEngine::hasFeature(MetaEngineFeature f) const {
 		checkExtendedSaves(f);
 }
 
-Common::Error NancyMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
+Common::Error NancyMetaEngine::createInstance(OSystem *syst, Engine **engine, const Nancy::NancyGameDescription *gd) const {
 	if (gd) {
-		*engine = Nancy::NancyEngine::create(((const Nancy::NancyGameDescription *)gd)->gameType, syst, (const Nancy::NancyGameDescription *)gd);
+		*engine = Nancy::NancyEngine::create(gd->gameType, syst, gd);
 	}
 
 	if (gd) {
diff --git a/engines/neverhood/metaengine.cpp b/engines/neverhood/metaengine.cpp
index a36bbc6bc8c..aa59d490763 100644
--- a/engines/neverhood/metaengine.cpp
+++ b/engines/neverhood/metaengine.cpp
@@ -56,7 +56,7 @@ bool NeverhoodEngine::applyResourceFixes() const {
 
 } // End of namespace Neverhood
 
-class NeverhoodMetaEngine : public AdvancedMetaEngine {
+class NeverhoodMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "neverhood";
diff --git a/engines/ngi/metaengine.cpp b/engines/ngi/metaengine.cpp
index 79e9b8805f4..ac05ce7cda6 100644
--- a/engines/ngi/metaengine.cpp
+++ b/engines/ngi/metaengine.cpp
@@ -54,7 +54,7 @@ int NGIEngine::getGameGID() const {
 
 } // End of namspace Fullpipe
 
-class NGIMetaEngine : public AdvancedMetaEngine {
+class NGIMetaEngine : public AdvancedMetaEngine<NGI::NGIGameDescription> {
 public:
 	const char *getName() const override {
 		return "ngi";
@@ -64,7 +64,7 @@ public:
 
 	int getMaximumSaveSlot() const override { return 99; }
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const NGI::NGIGameDescription *desc) const override;
 };
 
 bool NGIMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -79,8 +79,8 @@ bool NGI::NGIEngine::hasFeature(EngineFeature f) const {
 }
 
 
-Common::Error NGIMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new NGI::NGIEngine(syst, (const NGI::NGIGameDescription *)desc);
+Common::Error NGIMetaEngine::createInstance(OSystem *syst, Engine **engine, const NGI::NGIGameDescription *desc) const {
+	*engine = new NGI::NGIEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/parallaction/metaengine.cpp b/engines/parallaction/metaengine.cpp
index 97e7115d718..da043a237ff 100644
--- a/engines/parallaction/metaengine.cpp
+++ b/engines/parallaction/metaengine.cpp
@@ -43,14 +43,14 @@ Common::Platform Parallaction::getPlatform() const { return _gameDescription->de
 
 } // End of namespace Parallaction
 
-class ParallactionMetaEngine : public AdvancedMetaEngine {
+class ParallactionMetaEngine : public AdvancedMetaEngine<Parallaction::PARALLACTIONGameDescription> {
 public:
 	const char *getName() const override {
 		return "parallaction";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Parallaction::PARALLACTIONGameDescription *desc) const override;
 	Common::KeymapArray initKeymaps(const char *target) const override;
 
 	SaveStateList listSaves(const char *target) const override;
@@ -79,9 +79,7 @@ bool Parallaction::Parallaction::hasFeature(EngineFeature f) const {
 		(f == kSupportsReturnToLauncher);
 }
 
-Common::Error ParallactionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Parallaction::PARALLACTIONGameDescription *gd = (const Parallaction::PARALLACTIONGameDescription *)desc;
-
+Common::Error ParallactionMetaEngine::createInstance(OSystem *syst, Engine **engine, const Parallaction::PARALLACTIONGameDescription *gd) const {
 	switch (gd->gameType) {
 	case Parallaction::GType_Nippon:
 		*engine = new Parallaction::Parallaction_ns(syst, gd);
diff --git a/engines/pegasus/metaengine.cpp b/engines/pegasus/metaengine.cpp
index f564f148082..e042bf1768f 100644
--- a/engines/pegasus/metaengine.cpp
+++ b/engines/pegasus/metaengine.cpp
@@ -64,14 +64,14 @@ bool PegasusEngine::isLinux() const {
 
 } // End of namespace Pegasus
 
-class PegasusMetaEngine : public AdvancedMetaEngine {
+class PegasusMetaEngine : public AdvancedMetaEngine<Pegasus::PegasusGameDescription> {
 public:
 	const char *getName() const override {
 		return "pegasus";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Pegasus::PegasusGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override { return 999; }
@@ -127,8 +127,8 @@ Common::KeymapArray PegasusMetaEngine::initKeymaps(const char *target) const {
 	return Pegasus::PegasusEngine::initKeymaps();
 }
 
-Common::Error PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Pegasus::PegasusEngine(syst, (const Pegasus::PegasusGameDescription *)desc);
+Common::Error PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const Pegasus::PegasusGameDescription *desc) const {
+	*engine = new Pegasus::PegasusEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/petka/metaengine.cpp b/engines/petka/metaengine.cpp
index feafdf81b27..ce807883c2e 100644
--- a/engines/petka/metaengine.cpp
+++ b/engines/petka/metaengine.cpp
@@ -26,7 +26,7 @@
 
 #include "petka/petka.h"
 
-class PetkaMetaEngine : public AdvancedMetaEngine {
+class PetkaMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "petka";
diff --git a/engines/pink/metaengine.cpp b/engines/pink/metaengine.cpp
index 4d92edf895e..c691a3e643d 100644
--- a/engines/pink/metaengine.cpp
+++ b/engines/pink/metaengine.cpp
@@ -33,7 +33,7 @@ Common::Language PinkEngine::getLanguage() const {
 
 } // End of Namespace Pink
 
-class PinkMetaEngine : public AdvancedMetaEngine {
+class PinkMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "pink";
diff --git a/engines/playground3d/metaengine.cpp b/engines/playground3d/metaengine.cpp
index e8a953f4fe1..c197db4a37c 100644
--- a/engines/playground3d/metaengine.cpp
+++ b/engines/playground3d/metaengine.cpp
@@ -27,7 +27,7 @@
 
 #include "playground3d/playground3d.h"
 
-class Playground3dMetaEngine : public AdvancedMetaEngine {
+class Playground3dMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "playground3d";
diff --git a/engines/plumbers/metaengine.cpp b/engines/plumbers/metaengine.cpp
index ead531071e1..414d777f2a4 100644
--- a/engines/plumbers/metaengine.cpp
+++ b/engines/plumbers/metaengine.cpp
@@ -33,7 +33,7 @@ const char *PlumbersGame::getGameId() const { return _gameDescription->gameId; }
 Common::Platform PlumbersGame::getPlatform() const { return _gameDescription->platform; }
 } // End of namespace Plumbers
 
-class PlumbersMetaEngine : public AdvancedMetaEngine {
+class PlumbersMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 	const char *getName() const override {
 		return "plumbers";
 	}
diff --git a/engines/prince/metaengine.cpp b/engines/prince/metaengine.cpp
index 74321b51029..80afc6b11d7 100644
--- a/engines/prince/metaengine.cpp
+++ b/engines/prince/metaengine.cpp
@@ -43,13 +43,13 @@ Common::Language PrinceEngine::getLanguage() const {
 
 } // End of namespace Prince
 
-class PrinceMetaEngine : public AdvancedMetaEngine {
+class PrinceMetaEngine : public AdvancedMetaEngine<Prince::PrinceGameDescription> {
 public:
 	const char *getName() const override {
 		return "prince";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Prince::PrinceGameDescription *desc) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 
 	int getMaximumSaveSlot() const override { return 99; }
@@ -158,8 +158,8 @@ void PrinceMetaEngine::removeSaveState(const char *target, int slot) const {
 	g_system->getSavefileManager()->removeSavefile(fileName);
 }
 
-Common::Error PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Prince::PrinceEngine(syst, (const Prince::PrinceGameDescription *)desc);
+Common::Error PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const Prince::PrinceGameDescription *desc) const {
+	*engine = new Prince::PrinceEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/private/metaengine.cpp b/engines/private/metaengine.cpp
index a2cd82c2b70..f7b93438c0f 100644
--- a/engines/private/metaengine.cpp
+++ b/engines/private/metaengine.cpp
@@ -24,7 +24,7 @@
 
 #include "private/private.h"
 
-class PrivateMetaEngine : public AdvancedMetaEngine {
+class PrivateMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "private";
diff --git a/engines/queen/metaengine.cpp b/engines/queen/metaengine.cpp
index 41482dc3d99..3bcac713259 100644
--- a/engines/queen/metaengine.cpp
+++ b/engines/queen/metaengine.cpp
@@ -56,7 +56,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class QueenMetaEngine : public AdvancedMetaEngine {
+class QueenMetaEngine : public AdvancedMetaEngine<Queen::QueenGameDescription> {
 public:
 	const char *getName() const override {
 		return "queen";
@@ -67,7 +67,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Queen::QueenGameDescription *desc) const override;
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override { return 99; }
 	void removeSaveState(const char *target, int slot) const override;
@@ -117,8 +117,8 @@ void QueenMetaEngine::removeSaveState(const char *target, int slot) const {
 	g_system->getSavefileManager()->removeSavefile(filename);
 }
 
-Common::Error QueenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Queen::QueenEngine(syst); //FIXME , (const Queen::QueenGameDescription *)desc);
+Common::Error QueenMetaEngine::createInstance(OSystem *syst, Engine **engine, const Queen::QueenGameDescription *desc) const {
+	*engine = new Queen::QueenEngine(syst); //FIXME ,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/saga/metaengine.cpp b/engines/saga/metaengine.cpp
index 4d353c63ff9..d57e7a689fc 100644
--- a/engines/saga/metaengine.cpp
+++ b/engines/saga/metaengine.cpp
@@ -85,7 +85,7 @@ const ADGameFileDescription *SagaEngine::getArchivesDescriptions() const {
 
 } // End of namespace Saga
 
-class SagaMetaEngine : public AdvancedMetaEngine {
+class SagaMetaEngine : public AdvancedMetaEngine<Saga::SAGAGameDescription> {
 public:
 	const char *getName() const override {
 		return "saga";
@@ -97,7 +97,7 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Saga::SAGAGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -123,9 +123,7 @@ bool Saga::SagaEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error SagaMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Saga::SAGAGameDescription *gd = (const Saga::SAGAGameDescription *)desc;
-
+Common::Error SagaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Saga::SAGAGameDescription *gd) const {
 	switch (gd->gameId) {
 	case Saga::GID_IHNM:
 #ifndef ENABLE_IHNM
diff --git a/engines/saga2/metaengine.cpp b/engines/saga2/metaengine.cpp
index 889fae16fbc..649f4ce2bb2 100644
--- a/engines/saga2/metaengine.cpp
+++ b/engines/saga2/metaengine.cpp
@@ -22,13 +22,13 @@
 #include "saga2/saga2.h"
 #include "engines/advancedDetector.h"
 
-class Saga2MetaEngine : public AdvancedMetaEngine {
+class Saga2MetaEngine : public AdvancedMetaEngine<Saga2::SAGA2GameDescription> {
 public:
 	const char *getName() const override {
 		return "saga2";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Saga2::SAGA2GameDescription *desc) const override;
 	bool hasFeature(MetaEngineFeature f) const override;
 };
 
@@ -38,8 +38,7 @@ bool Saga2MetaEngine::hasFeature(MetaEngineFeature f) const {
 		checkExtendedSaves(f);
 }
 
-Common::Error Saga2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Saga2::SAGA2GameDescription *gd = (const Saga2::SAGA2GameDescription *)desc;
+Common::Error Saga2MetaEngine::createInstance(OSystem *syst, Engine **engine, const Saga2::SAGA2GameDescription *gd) const {
 	*engine = new Saga2::Saga2Engine(syst, gd);
 	return Common::kNoError;
 }
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 0c6d6ccf927..3d6cc46a34a 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -266,7 +266,7 @@ ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		return ADDetectedGame();
 	}
 
-	ADDetectedGame game = enginePlugin->get<AdvancedMetaEngine>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
+	ADDetectedGame game = enginePlugin->get<AdvancedMetaEngineBase>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
 	if (!game.desc) {
 		return game;
 	}
diff --git a/engines/sci/metaengine.cpp b/engines/sci/metaengine.cpp
index dc4d0b0cc26..d8ba6b1915c 100644
--- a/engines/sci/metaengine.cpp
+++ b/engines/sci/metaengine.cpp
@@ -179,7 +179,7 @@ static Common::String convertSierraGameId(Common::String sierraId, SciVersion sc
 
 namespace Sci {
 
-class SciMetaEngine : public AdvancedMetaEngine {
+class SciMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "sci";
@@ -441,7 +441,7 @@ static ADGameDescription s_fallbackDesc = {
 	GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_MIDI_MODE)
 };
 
-Common::Platform getSciFallbackDetectionPlatform(const AdvancedMetaEngine::FileMap &allFiles) {
+Common::Platform getSciFallbackDetectionPlatform(const AdvancedMetaEngineBase::FileMap &allFiles) {
 	// Data1 contains both map and volume for SCI1.1+ Mac games
 	if (allFiles.contains("Data1"))
 		return Common::kPlatformMacintosh;
@@ -461,7 +461,7 @@ Common::Platform getSciFallbackDetectionPlatform(const AdvancedMetaEngine::FileM
 	return Common::kPlatformDOS;
 }
 
-bool necessarySciResourceFilesFound(const AdvancedMetaEngine::FileMap &allFiles) {
+bool necessarySciResourceFilesFound(const AdvancedMetaEngineBase::FileMap &allFiles) {
 	bool foundResMap = false;
 	bool foundRes000 = false;
 
@@ -487,7 +487,7 @@ bool necessarySciResourceFilesFound(const AdvancedMetaEngine::FileMap &allFiles)
 	return foundResMap && foundRes000;
 }
 
-bool isSciCDVersion(const AdvancedMetaEngine::FileMap &allFiles) {
+bool isSciCDVersion(const AdvancedMetaEngineBase::FileMap &allFiles) {
 	// Determine if we got a CD version and set the CD flag accordingly, by checking for
 	// resource.aud for SCI1.1 CD games, or audio001.002 for SCI1 CD games. We assume that
 	// the file should be over 10MB, as it contains all the game speech and is usually
diff --git a/engines/sherlock/metaengine.cpp b/engines/sherlock/metaengine.cpp
index 1d4d3ec9693..96ee3fb52af 100644
--- a/engines/sherlock/metaengine.cpp
+++ b/engines/sherlock/metaengine.cpp
@@ -136,7 +136,7 @@ Common::Language SherlockEngine::getLanguage() const {
 } // End of namespace Sherlock
 
 
-class SherlockMetaEngine : public AdvancedMetaEngine {
+class SherlockMetaEngine : public AdvancedMetaEngine<Sherlock::SherlockGameDescription> {
 public:
 	const char *getName() const override {
 		return "sherlock";
@@ -149,7 +149,7 @@ public:
 	/**
 	 * Creates an instance of the game engine
 	 */
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Sherlock::SherlockGameDescription *desc) const override;
 
 	/**
 	 * Returns a list of features the game's MetaEngine support
@@ -177,8 +177,7 @@ public:
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
 };
 
-Common::Error SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Sherlock::SherlockGameDescription *gd = (const Sherlock::SherlockGameDescription *)desc;
+Common::Error SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const Sherlock::SherlockGameDescription *gd) const {
 	switch (gd->gameID) {
 	case Sherlock::GType_SerratedScalpel:
 		*engine = new Sherlock::Scalpel::ScalpelEngine(syst, gd);
diff --git a/engines/sludge/metaengine.cpp b/engines/sludge/metaengine.cpp
index 275de41babf..cc1c32295d1 100644
--- a/engines/sludge/metaengine.cpp
+++ b/engines/sludge/metaengine.cpp
@@ -36,14 +36,14 @@ const char *SludgeEngine::getGameFile() const {
 
 } // End of namespace Sludge
 
-class SludgeMetaEngine : public AdvancedMetaEngine {
+class SludgeMetaEngine : public AdvancedMetaEngine<Sludge::SludgeGameDescription> {
 public:
 	const char *getName() const override {
 		return "sludge";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
-		*engine = new Sludge::SludgeEngine(syst, (const Sludge::SludgeGameDescription *)desc);
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Sludge::SludgeGameDescription *desc) const override {
+		*engine = new Sludge::SludgeEngine(syst, desc);
 		return Common::kNoError;
 	}
 };
diff --git a/engines/stark/metaengine.cpp b/engines/stark/metaengine.cpp
index 8482e51058d..9504e811b7a 100644
--- a/engines/stark/metaengine.cpp
+++ b/engines/stark/metaengine.cpp
@@ -68,7 +68,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class StarkMetaEngine : public AdvancedMetaEngine {
+class StarkMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "stark";
diff --git a/engines/startrek/metaengine.cpp b/engines/startrek/metaengine.cpp
index 72903fcabf3..c0f2b36b658 100644
--- a/engines/startrek/metaengine.cpp
+++ b/engines/startrek/metaengine.cpp
@@ -53,14 +53,14 @@ Common::Language StarTrekEngine::getLanguage() const {
 
 } // End of Namespace StarTrek
 
-class StarTrekMetaEngine : public AdvancedMetaEngine {
+class StarTrekMetaEngine : public AdvancedMetaEngine<StarTrek::StarTrekGameDescription> {
 public:
 	const char *getName() const override {
 		return "startrek";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const StarTrek::StarTrekGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -80,8 +80,8 @@ bool StarTrekMetaEngine::hasFeature(MetaEngineFeature f) const {
 	    (f == kSimpleSavesNames);
 }
 
-Common::Error StarTrekMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new StarTrek::StarTrekEngine(syst, (const StarTrek::StarTrekGameDescription *)desc);
+Common::Error StarTrekMetaEngine::createInstance(OSystem *syst, Engine **engine, const StarTrek::StarTrekGameDescription *desc) const {
+	*engine = new StarTrek::StarTrekEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/supernova/metaengine.cpp b/engines/supernova/metaengine.cpp
index 0905eab7c48..905b5201379 100644
--- a/engines/supernova/metaengine.cpp
+++ b/engines/supernova/metaengine.cpp
@@ -58,7 +58,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class SupernovaMetaEngine : public AdvancedMetaEngine {
+class SupernovaMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "supernova";
diff --git a/engines/sword1/metaengine.cpp b/engines/sword1/metaengine.cpp
index 21fc0d4f39c..ea57e672274 100644
--- a/engines/sword1/metaengine.cpp
+++ b/engines/sword1/metaengine.cpp
@@ -54,7 +54,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 } // End of namespace Sword1
 
-class SwordMetaEngine : public AdvancedMetaEngine {
+class SwordMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "sword1";
diff --git a/engines/sword2/metaengine.cpp b/engines/sword2/metaengine.cpp
index 582ac29e74d..91210b5d5df 100644
--- a/engines/sword2/metaengine.cpp
+++ b/engines/sword2/metaengine.cpp
@@ -53,7 +53,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 } // End of namespace Sword2
 
-class Sword2MetaEngine : public AdvancedMetaEngine {
+class Sword2MetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "sword2";
diff --git a/engines/sword25/metaengine.cpp b/engines/sword25/metaengine.cpp
index c5d1858d5e7..cf85ef02e71 100644
--- a/engines/sword25/metaengine.cpp
+++ b/engines/sword25/metaengine.cpp
@@ -47,7 +47,7 @@ uint32 Sword25Engine::getGameFlags() const { return _gameDescription->flags; }
 
 } // End of namespace Sword25
 
-class Sword25MetaEngine : public AdvancedMetaEngine {
+class Sword25MetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "sword25";
diff --git a/engines/teenagent/metaengine.cpp b/engines/teenagent/metaengine.cpp
index 3d8f5de3f8d..cc92acbf9c6 100644
--- a/engines/teenagent/metaengine.cpp
+++ b/engines/teenagent/metaengine.cpp
@@ -34,7 +34,7 @@ enum {
 	MAX_SAVES = 20
 };
 
-class TeenAgentMetaEngine : public AdvancedMetaEngine {
+class TeenAgentMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "teenagent";
diff --git a/engines/testbed/metaengine.cpp b/engines/testbed/metaengine.cpp
index af172a8eb09..a1f81a4cb97 100644
--- a/engines/testbed/metaengine.cpp
+++ b/engines/testbed/metaengine.cpp
@@ -27,7 +27,7 @@
 
 #include "testbed/testbed.h"
 
-class TestbedMetaEngine : public AdvancedMetaEngine {
+class TestbedMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "testbed";
diff --git a/engines/tetraedge/metaengine.h b/engines/tetraedge/metaengine.h
index cd6d3d7e1eb..4bb0d92b5ec 100644
--- a/engines/tetraedge/metaengine.h
+++ b/engines/tetraedge/metaengine.h
@@ -28,7 +28,7 @@
 #define GAMEOPTION_CORRECT_MOVIE_ASPECT GUIO_GAMEOPTIONS1
 #define GAMEOPTION_RESTORE_SCENES GUIO_GAMEOPTIONS2
 
-class TetraedgeMetaEngine : public AdvancedMetaEngine {
+class TetraedgeMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override;
 
diff --git a/engines/tinsel/metaengine.cpp b/engines/tinsel/metaengine.cpp
index 8efab61a3e6..12890f38cd2 100644
--- a/engines/tinsel/metaengine.cpp
+++ b/engines/tinsel/metaengine.cpp
@@ -79,13 +79,13 @@ bool TinselEngine::isV1CD() const {
 
 } // End of namespace Tinsel
 
-class TinselMetaEngine : public AdvancedMetaEngine {
+class TinselMetaEngine : public AdvancedMetaEngine<Tinsel::TinselGameDescription> {
 public:
 	const char *getName() const  override{
 		return "tinsel";
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Tinsel::TinselGameDescription *desc) const override;
 
 	bool hasFeature(MetaEngineFeature f) const override;
 	SaveStateList listSaves(const char *target) const override;
@@ -190,8 +190,8 @@ SaveStateList TinselMetaEngine::listSaves(const char *target) const {
 	return saveList;
 }
 
-Common::Error TinselMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Tinsel::TinselEngine(syst, (const Tinsel::TinselGameDescription *)desc);
+Common::Error TinselMetaEngine::createInstance(OSystem *syst, Engine **engine, const Tinsel::TinselGameDescription *desc) const {
+	*engine = new Tinsel::TinselEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/titanic/metaengine.cpp b/engines/titanic/metaengine.cpp
index 079d2e765c6..1d6b2a8cc1e 100644
--- a/engines/titanic/metaengine.cpp
+++ b/engines/titanic/metaengine.cpp
@@ -44,14 +44,14 @@ Common::Language TitanicEngine::getLanguage() const {
 
 } // End of namespace Titanic
 
-class TitanicMetaEngine : public AdvancedMetaEngine {
+class TitanicMetaEngine : public AdvancedMetaEngine<Titanic::TitanicGameDescription> {
 public:
 	const char *getName() const override {
 		return "titanic";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Titanic::TitanicGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -78,8 +78,8 @@ bool Titanic::TitanicEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error TitanicMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Titanic::TitanicEngine(syst, (const Titanic::TitanicGameDescription *)desc);
+Common::Error TitanicMetaEngine::createInstance(OSystem *syst, Engine **engine, const Titanic::TitanicGameDescription *desc) const {
+	*engine = new Titanic::TitanicEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/toltecs/metaengine.cpp b/engines/toltecs/metaengine.cpp
index 2a5879eeea3..dc00882e894 100644
--- a/engines/toltecs/metaengine.cpp
+++ b/engines/toltecs/metaengine.cpp
@@ -58,7 +58,7 @@ Common::Language ToltecsEngine::getLanguage() const {
 
 } // End of namespace Toltecs
 
-class ToltecsMetaEngine : public AdvancedMetaEngine {
+class ToltecsMetaEngine : public AdvancedMetaEngine<Toltecs::ToltecsGameDescription> {
 public:
 	const char *getName() const override {
 		return "toltecs";
@@ -69,7 +69,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Toltecs::ToltecsGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -96,8 +96,8 @@ bool Toltecs::ToltecsEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Toltecs::ToltecsEngine(syst, (const Toltecs::ToltecsGameDescription *)desc);
+Common::Error ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Toltecs::ToltecsGameDescription *desc) const {
+	*engine = new Toltecs::ToltecsEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/tony/metaengine.cpp b/engines/tony/metaengine.cpp
index e89ad85ba18..d5818e059f1 100644
--- a/engines/tony/metaengine.cpp
+++ b/engines/tony/metaengine.cpp
@@ -50,14 +50,14 @@ bool TonyEngine::isCompressed() const {
 
 } // End of namespace Tony
 
-class TonyMetaEngine : public AdvancedMetaEngine {
+class TonyMetaEngine : public AdvancedMetaEngine<Tony::TonyGameDescription> {
 public:
 	const char *getName() const override {
 		return "tony";
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Tony::TonyGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -82,8 +82,8 @@ bool Tony::TonyEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error TonyMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Tony::TonyEngine(syst, (const Tony::TonyGameDescription *)desc);
+Common::Error TonyMetaEngine::createInstance(OSystem *syst, Engine **engine, const Tony::TonyGameDescription *desc) const {
+	*engine = new Tony::TonyEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/toon/metaengine.cpp b/engines/toon/metaengine.cpp
index e1d25d3ccdd..3e07ef6bae4 100644
--- a/engines/toon/metaengine.cpp
+++ b/engines/toon/metaengine.cpp
@@ -34,7 +34,7 @@
 #include "graphics/thumbnail.h"
 #include "toon/toon.h"
 
-class ToonMetaEngine : public AdvancedMetaEngine {
+class ToonMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "toon";
diff --git a/engines/touche/metaengine.cpp b/engines/touche/metaengine.cpp
index 90368364576..7158ada6329 100644
--- a/engines/touche/metaengine.cpp
+++ b/engines/touche/metaengine.cpp
@@ -28,7 +28,7 @@
 
 #include "touche/touche.h"
 
-class ToucheMetaEngine : public AdvancedMetaEngine {
+class ToucheMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "touche";
diff --git a/engines/trecision/metaengine.cpp b/engines/trecision/metaengine.cpp
index 87d51b5fa19..f874dd68237 100644
--- a/engines/trecision/metaengine.cpp
+++ b/engines/trecision/metaengine.cpp
@@ -45,7 +45,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class TrecisionMetaEngine : public AdvancedMetaEngine {
+class TrecisionMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 	const char *getName() const override {
 		return "trecision";
 	}
diff --git a/engines/tsage/metaengine.cpp b/engines/tsage/metaengine.cpp
index c8db8f41d45..cc3238935be 100644
--- a/engines/tsage/metaengine.cpp
+++ b/engines/tsage/metaengine.cpp
@@ -58,7 +58,7 @@ enum {
 	MAX_SAVES = 100
 };
 
-class TSageMetaEngine : public AdvancedMetaEngine {
+class TSageMetaEngine : public AdvancedMetaEngine<TsAGE::tSageGameDescription> {
 public:
 	const char *getName() const override {
 		return "tsage";
@@ -80,8 +80,8 @@ public:
 		}
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
-		*engine = new TsAGE::TSageEngine(syst, (const TsAGE::tSageGameDescription *)desc);
+	Common::Error createInstance(OSystem *syst, Engine **engine, const TsAGE::tSageGameDescription *desc) const override {
+		*engine = new TsAGE::TSageEngine(syst, desc);
 		return Common::kNoError;
 	}
 
diff --git a/engines/tucker/metaengine.cpp b/engines/tucker/metaengine.cpp
index 4b92364c8fe..e0cbfe5ccea 100644
--- a/engines/tucker/metaengine.cpp
+++ b/engines/tucker/metaengine.cpp
@@ -28,7 +28,7 @@
 
 #include "tucker/tucker.h"
 
-class TuckerMetaEngine : public AdvancedMetaEngine {
+class TuckerMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "tucker";
diff --git a/engines/twine/metaengine.cpp b/engines/twine/metaengine.cpp
index bfcdc77590a..e8b0bcaeb20 100644
--- a/engines/twine/metaengine.cpp
+++ b/engines/twine/metaengine.cpp
@@ -165,7 +165,7 @@ static const ADExtraGuiOptionsMap twineOptionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-class TwinEMetaEngine : public AdvancedMetaEngine {
+class TwinEMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "twine";
diff --git a/engines/twp/metaengine.cpp b/engines/twp/metaengine.cpp
index d0359ac707d..143e2d6eabd 100644
--- a/engines/twp/metaengine.cpp
+++ b/engines/twp/metaengine.cpp
@@ -49,8 +49,8 @@ const char *TwpMetaEngine::getName() const {
 	return "twp";
 }
 
-Common::Error TwpMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Twp::TwpEngine(syst, (const Twp::TwpGameDescription *)(desc));
+Common::Error TwpMetaEngine::createInstance(OSystem *syst, Engine **engine, const Twp::TwpGameDescription *desc) const {
+	*engine = new Twp::TwpEngine(syst,(desc));
 	return Common::kNoError;
 }
 
diff --git a/engines/twp/metaengine.h b/engines/twp/metaengine.h
index 19dfc464bf8..e6f733baa69 100644
--- a/engines/twp/metaengine.h
+++ b/engines/twp/metaengine.h
@@ -24,11 +24,11 @@
 
 #include "engines/advancedDetector.h"
 
-class TwpMetaEngine : public AdvancedMetaEngine {
+class TwpMetaEngine : public AdvancedMetaEngine<Twp::TwpGameDescription> {
 public:
 	const char *getName() const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Twp::TwpGameDescription *desc) const override;
 
 	/**
 	 * Determine whether the engine supports the specified MetaEngine feature.
diff --git a/engines/ultima/metaengine.cpp b/engines/ultima/metaengine.cpp
index 7215dc5eed1..bb6d7599e61 100644
--- a/engines/ultima/metaengine.cpp
+++ b/engines/ultima/metaengine.cpp
@@ -179,8 +179,7 @@ const ADExtraGuiOptionsMap *UltimaMetaEngine::getAdvancedExtraGuiOptions() const
 	return optionsList;
 }
 
-Common::Error UltimaMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	const Ultima::UltimaGameDescription *gd = (const Ultima::UltimaGameDescription *)desc;
+Common::Error UltimaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Ultima::UltimaGameDescription *gd) const {
 	switch (gd->gameId) {
 #ifdef ENABLE_ULTIMA1
 	case Ultima::GAME_ULTIMA1:
diff --git a/engines/ultima/metaengine.h b/engines/ultima/metaengine.h
index 4318def2955..99ee90bfa56 100644
--- a/engines/ultima/metaengine.h
+++ b/engines/ultima/metaengine.h
@@ -27,7 +27,7 @@
 
 #define MAX_SAVES 99
 
-class UltimaMetaEngine : public AdvancedMetaEngine {
+class UltimaMetaEngine : public AdvancedMetaEngine<Ultima::UltimaGameDescription> {
 private:
 	/**
 	 * Gets the game Id given a target string
@@ -37,7 +37,7 @@ public:
 	const char *getName() const override;
 	const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override;
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Ultima::UltimaGameDescription *desc) const override;
 	int getMaximumSaveSlot() const override;
 
 	/**
diff --git a/engines/vcruise/metaengine.cpp b/engines/vcruise/metaengine.cpp
index 575f0f1b405..f0d6af80eb7 100644
--- a/engines/vcruise/metaengine.cpp
+++ b/engines/vcruise/metaengine.cpp
@@ -96,7 +96,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 
 } // End of namespace VCruise
 
-class VCruiseMetaEngine : public AdvancedMetaEngine {
+class VCruiseMetaEngine : public AdvancedMetaEngine<VCruise::VCruiseGameDescription> {
 public:
 	const char *getName() const override {
 		return "vcruise";
@@ -107,7 +107,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const VCruise::VCruiseGameDescription *desc) const override;
 
 	Common::Array<Common::Keymap *> initKeymaps(const char *target) const override;
 };
@@ -123,7 +123,7 @@ bool VCruiseMetaEngine::hasFeature(MetaEngineFeature f) const {
 	return checkExtendedSaves(f);
 }
 
-Common::Error VCruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+Common::Error VCruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const VCruise::VCruiseGameDescription *desc) const {
 	*engine = new VCruise::VCruiseEngine(syst, reinterpret_cast<const VCruise::VCruiseGameDescription *>(desc));
 	return Common::kNoError;
 }
diff --git a/engines/voyeur/metaengine.cpp b/engines/voyeur/metaengine.cpp
index f5d3b920660..7ae045c38ad 100644
--- a/engines/voyeur/metaengine.cpp
+++ b/engines/voyeur/metaengine.cpp
@@ -69,7 +69,7 @@ bool VoyeurEngine::getIsDemo() const {
 
 } // End of namespace Voyeur
 
-class VoyeurMetaEngine : public AdvancedMetaEngine {
+class VoyeurMetaEngine : public AdvancedMetaEngine<Voyeur::VoyeurGameDescription> {
 public:
 	const char *getName() const override {
 		return "voyeur";
@@ -80,7 +80,7 @@ public:
 	}
 
 	bool hasFeature(MetaEngineFeature f) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const Voyeur::VoyeurGameDescription *desc) const override;
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
 	void removeSaveState(const char *target, int slot) const override;
@@ -104,8 +104,8 @@ bool Voyeur::VoyeurEngine::hasFeature(EngineFeature f) const {
 		(f == kSupportsSavingDuringRuntime);
 }
 
-Common::Error VoyeurMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new Voyeur::VoyeurEngine(syst, (const Voyeur::VoyeurGameDescription *)desc);
+Common::Error VoyeurMetaEngine::createInstance(OSystem *syst, Engine **engine, const Voyeur::VoyeurGameDescription *desc) const {
+	*engine = new Voyeur::VoyeurEngine(syst,desc);
 	return Common::kNoError;
 }
 
diff --git a/engines/wage/metaengine.cpp b/engines/wage/metaengine.cpp
index 2e7feb0f909..5ced1e261ac 100644
--- a/engines/wage/metaengine.cpp
+++ b/engines/wage/metaengine.cpp
@@ -40,7 +40,7 @@ const char *WageEngine::getGameFile() const {
 
 } // End of namespace Wage
 
-class WageMetaEngine : public AdvancedMetaEngine {
+class WageMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "wage";
diff --git a/engines/watchmaker/metaengine.cpp b/engines/watchmaker/metaengine.cpp
index 4cfc7ca94b3..628eb3d09a2 100644
--- a/engines/watchmaker/metaengine.cpp
+++ b/engines/watchmaker/metaengine.cpp
@@ -35,7 +35,7 @@ Common::Platform WatchmakerGame::getPlatform() const {
 }
 } // End of namespace Watchmaker
 
-class WatchmakerMetaEngine : public AdvancedMetaEngine {
+class WatchmakerMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 	const char *getName() const override {
 		return "watchmaker";
 	}
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index b48fc2a1c11..ae6886092df 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -100,7 +100,7 @@ public:
 		if (metaEnginePlugin) {
 			const Plugin *enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
 			if (enginePlugin) {
-				return enginePlugin->get<AdvancedMetaEngine>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
+				return enginePlugin->get<AdvancedMetaEngineBase>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
 			} else {
 				static bool warn = true;
 				if (warn) {
diff --git a/engines/wintermute/metaengine.cpp b/engines/wintermute/metaengine.cpp
index 469e07c04cf..7492d69252e 100644
--- a/engines/wintermute/metaengine.cpp
+++ b/engines/wintermute/metaengine.cpp
@@ -94,7 +94,7 @@ static ADGameDescription s_fallbackDesc = {
 
 static char s_fallbackExtraBuf[256];
 
-class WintermuteMetaEngine : public AdvancedMetaEngine {
+class WintermuteMetaEngine : public AdvancedMetaEngine<WMEGameDescription> {
 public:
 	const char *getName() const override {
 		return "wintermute";
@@ -104,9 +104,7 @@ public:
 		return gameGuiOptions;
 	}
 
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
-		const WMEGameDescription *gd = (const WMEGameDescription *)desc;
-
+	Common::Error createInstance(OSystem *syst, Engine **engine, const WMEGameDescription *gd) const override {
 #ifndef ENABLE_FOXTAIL
 		if (gd->targetExecutable >= FOXTAIL_OLDEST_VERSION && gd->targetExecutable <= FOXTAIL_LATEST_VERSION) {
 			return Common::Error(Common::kUnsupportedGameidError, _s("FoxTail support is not compiled in"));
diff --git a/engines/zvision/metaengine.cpp b/engines/zvision/metaengine.cpp
index 89905a96407..be7385a5ada 100644
--- a/engines/zvision/metaengine.cpp
+++ b/engines/zvision/metaengine.cpp
@@ -115,7 +115,7 @@ uint32 ZVision::getFeatures() const {
 
 } // End of namespace ZVision
 
-class ZVisionMetaEngine : public AdvancedMetaEngine {
+class ZVisionMetaEngine : public AdvancedMetaEngine<ZVision::ZVisionGameDescription> {
 public:
 	const char *getName() const override {
 		return "zvision";
@@ -127,7 +127,7 @@ public:
 
 	bool hasFeature(MetaEngineFeature f) const override;
 	Common::KeymapArray initKeymaps(const char *target) const override;
-	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	Common::Error createInstance(OSystem *syst, Engine **engine, const ZVision::ZVisionGameDescription *desc) const override;
 
 	SaveStateList listSaves(const char *target) const override;
 	int getMaximumSaveSlot() const override;
@@ -300,8 +300,8 @@ Common::KeymapArray ZVisionMetaEngine::initKeymaps(const char *target) const {
 	return keymaps;
 }
 
-Common::Error ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	*engine = new ZVision::ZVision(syst, (const ZVision::ZVisionGameDescription *)desc);
+Common::Error ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ZVision::ZVisionGameDescription *desc) const {
+	*engine = new ZVision::ZVision(syst,desc);
 	return Common::kNoError;
 }
 


Commit: a7d0db4947aea2e077747cba41932df9c1737123
    https://github.com/scummvm/scummvm/commit/a7d0db4947aea2e077747cba41932df9c1737123
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Let MetaEngine delete the engine

This will allow to cleanup other data managed by the MetaEngine (game
descriptors).

Changed paths:
    base/main.cpp
    engines/metaengine.cpp
    engines/metaengine.h


diff --git a/base/main.cpp b/base/main.cpp
index 54ec0925956..766dde1c456 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -321,7 +321,7 @@ static Common::Error runGame(const Plugin *enginePlugin, OSystem &system, const
 	keymapper->cleanupGameKeymaps();
 
 	// Free up memory
-	delete engine;
+	metaEngine.deleteInstance(engine, game, meDescriptor);
 
 	// Reset the file/directory mappings
 	SearchMan.clear();
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 96cb6c4923c..503edfcec37 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "engines/metaengine.h"
+#include "engines/engine.h"
 
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymap.h"
@@ -341,6 +342,10 @@ WARN_UNUSED_RESULT bool MetaEngine::readSavegameHeader(Common::InSaveFile *in, E
 // MetaEngine default implementations
 //////////////////////////////////////////////
 
+void MetaEngine::deleteInstance(Engine *engine, const DetectedGame &gameDescriptor, const void *meDescriptor) {
+	delete engine;
+}
+
 int MetaEngine::findEmptySaveSlot(const char *target) {
 	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
 	const int maxSaveSlot = getMaximumSaveSlot();
diff --git a/engines/metaengine.h b/engines/metaengine.h
index b57ca738681..e5ed7093601 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -255,6 +255,20 @@ public:
 	 */
 	virtual Common::Error createInstance(OSystem *syst, Engine **engine, const DetectedGame &gameDescriptor, const void *meDescriptor) = 0;
 
+	/**
+	 * Deinstantiate an engine instance.
+	 * The default implementation merely deletes the engine.
+	 *
+	 * The MetaEngine queries the ConfMan singleton for data like the target,
+	 * gameid, path etc.
+	 *
+	 * @param engine          Pointer to the Engine that MetaEngine created.
+	 * @param gameDescriptor  Detected game as returned by MetaEngineDetection::identifyGame
+	 * @param meDescriptor    Pointer to a meta engine specific descriptor as returned by
+	 *                        MetaEngineDetection::identifyGame
+	 */
+	virtual void deleteInstance(Engine *engine, const DetectedGame &gameDescriptor, const void *meDescriptor);
+
 	/**
 	 * Return a list of all save states associated with the given target.
 	 *


Commit: 7e0048b4a38747017fb0c99fad1b20208dc177d0
    https://github.com/scummvm/scummvm/commit/7e0048b4a38747017fb0c99fad1b20208dc177d0
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Add ADDynamicGameDescription class

This class manages a buffer where all data usually stored in detection
plugin will get copied before unloading the plugin and starting the
game.

This class expects that two functions are present in every
GameDescription: sizeBuffer which calculates how many bytes we will need
to store the entry in RAM and toBuffer which copies the data in the
buffer and fix the pointers in the class.
At the end, it is expected that an ADDynamicGameDescription doesn't
depend anymore on data stored in the detection plugin.

The AD_GAME_DESCRIPTION_HELPERS macro allow to implement these functions
in all GameDescription which don't have any pointer except those in
ADGameDescription.

Changed paths:
    engines/access/detection.h
    engines/adl/detection.h
    engines/advancedDetector.h
    engines/agi/detection.h
    engines/agos/detection.h
    engines/ags/detection.h
    engines/avalanche/detection.h
    engines/chewy/detection.h
    engines/cine/detection.h
    engines/composer/detection.h
    engines/cruise/detection.h
    engines/cryomni3d/detection.h
    engines/director/detection.h
    engines/dm/detection.h
    engines/dragons/detection.h
    engines/drascula/detection.h
    engines/dreamweb/detection.h
    engines/gob/detection/detection.h
    engines/grim/detection.h
    engines/groovie/detection.h
    engines/hopkins/detection.h
    engines/hugo/detection.h
    engines/icb/detection.h
    engines/illusions/detection.h
    engines/kyra/detection.h
    engines/lilliput/detection.h
    engines/lure/detection.h
    engines/m4/detection.h
    engines/made/detection.h
    engines/mads/detection.h
    engines/mm/detection.h
    engines/mohawk/detection.h
    engines/mortevielle/detection.h
    engines/mtropolis/detection.h
    engines/myst3/detection.h
    engines/nancy/detection.h
    engines/ngi/detection.h
    engines/parallaction/detection.h
    engines/pegasus/detection.h
    engines/prince/detection.h
    engines/queen/detection.h
    engines/saga/detection.h
    engines/saga2/detection.h
    engines/sherlock/detection.h
    engines/sludge/detection.h
    engines/startrek/detection.h
    engines/tinsel/detection.h
    engines/titanic/detection.h
    engines/toltecs/detection.h
    engines/tony/detection.h
    engines/tsage/detection.h
    engines/twp/detection.h
    engines/ultima/detection.h
    engines/vcruise/detection.h
    engines/voyeur/detection.h
    engines/wintermute/detection.h
    engines/zvision/detection.h


diff --git a/engines/access/detection.h b/engines/access/detection.h
index 353e255345b..d019e5daf79 100644
--- a/engines/access/detection.h
+++ b/engines/access/detection.h
@@ -33,6 +33,8 @@ enum {
 };
 
 struct AccessGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/adl/detection.h b/engines/adl/detection.h
index 058bf2a294d..f06f437e244 100644
--- a/engines/adl/detection.h
+++ b/engines/adl/detection.h
@@ -69,6 +69,8 @@ enum GameVersion {
 };
 
 struct AdlGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GameType gameType;
 	GameVersion version;
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index a623fa6b399..1204f03f205 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -52,6 +52,33 @@ struct ADGameFileDescription {
 	uint16 fileType;      ///< Optional. Not used during detection, only by engines.
 	const char *md5;      ///< MD5 of (the beginning of) the described file. Optional. Set to NULL to ignore.
 	int64 fileSize;       ///< Size of the described file. Set to -1 to ignore.
+
+	uint32 sizeBuffer() const {
+		uint32 ret = 0;
+		if (fileName) {
+			ret += strlen(fileName) + 1;
+		}
+		if (md5) {
+			ret += strlen(md5) + 1;
+		}
+		return ret;
+	}
+
+	void *toBuffer(void *buffer) {
+		if (fileName) {
+			int len = strlen(fileName) + 1;
+			memcpy((char *)buffer, fileName, len);
+			fileName = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		if (md5) {
+			int len = strlen(md5) + 1;
+			memcpy((char *)buffer, md5, len);
+			md5 = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		return buffer;
+	}
 };
 
 /**
@@ -170,6 +197,105 @@ struct ADGameDescription {
 	 * or have MIDI controls in a game that only supports digital music.
 	 */
 	const char *guiOptions;
+
+	/**
+	 * Calculates the size needed to store all pointed data
+	 */
+	uint32 sizeBuffer() const {
+		uint32 ret = 0;
+		if (gameId) {
+			ret += strlen(gameId) + 1;
+		}
+		if (extra) {
+			ret += strlen(extra) + 1;
+		}
+		for(int i = 0; i < ARRAYSIZE(filesDescriptions); i++) {
+			ret += filesDescriptions[i].sizeBuffer();
+		}
+		if (guiOptions) {
+			ret += strlen(guiOptions) + 1;
+		}
+		return ret;
+	}
+
+	/**
+	 * Fixup all pointers to lie inside buffer and stores the needed data in it
+	 *
+	 * @param buffer Where the original data is copied in and pointed at
+	 *
+	 * @return The new pointer on buffer after the stored data.
+	 */
+	void *toBuffer(void *buffer) {
+		if (gameId) {
+			int len = strlen(gameId) + 1;
+			memcpy((char *)buffer, gameId, len);
+			gameId = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		if (extra) {
+			int len = strlen(extra) + 1;
+			memcpy((char *)buffer, extra, len);
+			extra = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		for(int i = 0; i < ARRAYSIZE(filesDescriptions); i++) {
+			buffer = filesDescriptions[i].toBuffer(buffer);
+		}
+		if (guiOptions) {
+			int len = strlen(guiOptions) + 1;
+			memcpy((char *)buffer, guiOptions, len);
+			guiOptions = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		return buffer;
+	}
+};
+
+/**
+ * This macro can be used in simple ADGameDescription containers
+ * to let them be used by ADDynamicGameDescription
+ *
+ * Simple containers are the one not making use of pointers.
+ */
+#define AD_GAME_DESCRIPTION_HELPERS(field) \
+	uint32 sizeBuffer() const { \
+		return field.sizeBuffer(); \
+	} \
+	void *toBuffer(void *buffer) { \
+		return field.toBuffer(buffer); \
+	}
+
+/**
+ * This class is a small helper to manage copies in heap
+ * of static ADGameDescription.
+ * To work, all ADGameDescription and derived classes that manipulate
+ * pointers must define the sizeBuffer and toBuffer functions like ADGameDescription.
+ */
+template<class T>
+class ADDynamicGameDescription : public T {
+public:
+	ADDynamicGameDescription(const T *other) : _buffer(nullptr) {
+		// First copy all fields
+		memcpy(static_cast<T*>(this), other, sizeof(T));
+
+		// Then calculate the size of the dynamic buffer
+		// we will need to store evrything pointed at by
+		// the structures
+		uint32 sz = other->sizeBuffer();
+		_buffer = new byte[sz];
+
+		// Finally copy every pointer in the buffer
+		// and make the structure point into it
+		void *end = this->toBuffer(_buffer);
+		assert(end <= _buffer + sz);
+	}
+
+	~ADDynamicGameDescription() {
+		delete[] _buffer;
+	}
+
+private:
+	byte *_buffer;
 };
 
 /**
diff --git a/engines/agi/detection.h b/engines/agi/detection.h
index 9c126b2cce0..22d082074a1 100644
--- a/engines/agi/detection.h
+++ b/engines/agi/detection.h
@@ -27,6 +27,8 @@
 namespace Agi {
 
 struct AGIGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/agos/detection.h b/engines/agos/detection.h
index 18ff334c8fd..87a63a90852 100644
--- a/engines/agos/detection.h
+++ b/engines/agos/detection.h
@@ -38,6 +38,8 @@ enum SIMONGameType {
 };
 
 struct AGOSGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameType;
diff --git a/engines/ags/detection.h b/engines/ags/detection.h
index d58f75717cf..57be0fde425 100644
--- a/engines/ags/detection.h
+++ b/engines/ags/detection.h
@@ -42,12 +42,77 @@ enum GameFlag {
 struct PluginVersion {
 	const char *_plugin;
 	int _version;
+
+	uint32 sizeBuffer() const {
+		uint32 ret = 0;
+		if (_plugin) {
+			ret += strlen(_plugin) + 1;
+		}
+		return ret;
+	}
+	void *toBuffer(void *buffer) {
+		if (_plugin) {
+			int len = strlen(_plugin) + 1;
+			memcpy((char *)buffer, _plugin, len);
+			_plugin = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		return buffer;
+	}
 };
 
 struct AGSGameDescription {
 	ADGameDescription desc;
 	const PluginVersion *_plugins;
 	const char *_mainNameInsideInstaller;
+
+	uint32 sizeBuffer() const {
+		uint32 ret = desc.sizeBuffer();
+		if (_plugins) {
+			const PluginVersion *p;
+			for (p = _plugins; p->_plugin != nullptr; p++) {
+				ret += p->sizeBuffer();
+			}
+			// Make sure we have enough room for worst case alignment
+			// by adding the size of a pointer minus one
+			ret += sizeof(*p) * (p - _plugins + 1) + sizeof(void *) - 1;
+		}
+		if (_mainNameInsideInstaller) {
+			ret += strlen(_mainNameInsideInstaller) + 1;
+		}
+		return ret;
+	}
+
+	void *toBuffer(void *buffer) {
+		buffer = desc.toBuffer(buffer);
+		if (_plugins) {
+			const PluginVersion *p;
+			for (p = _plugins; p->_plugin != nullptr; p++)
+				;
+			uint count = (p - _plugins + 1);
+
+			buffer = (void *)(((uintptr)buffer + sizeof(void *) - 1) & -sizeof(void *));
+			memcpy(buffer, _plugins, sizeof(*p) * count);
+
+			_plugins = (PluginVersion *)buffer;
+
+			PluginVersion *dp = (PluginVersion *)buffer;
+			buffer = (PluginVersion *)buffer + count;
+
+			for (; dp->_plugin != nullptr; dp++) {
+				buffer = dp->toBuffer(buffer);
+			}
+		}
+
+		if (_mainNameInsideInstaller) {
+			int len = strlen(_mainNameInsideInstaller) + 1;
+			memcpy((char *)buffer, _mainNameInsideInstaller, len);
+			_mainNameInsideInstaller = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+
+		return buffer;
+	}
 };
 
 extern const PlainGameDescriptor GAME_NAMES[];
diff --git a/engines/avalanche/detection.h b/engines/avalanche/detection.h
index d8b49ef18a8..84927851faf 100644
--- a/engines/avalanche/detection.h
+++ b/engines/avalanche/detection.h
@@ -30,6 +30,8 @@
 namespace Avalanche {
 
 struct AvalancheGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/chewy/detection.h b/engines/chewy/detection.h
index a8f5fc281d4..5c7b25ba326 100644
--- a/engines/chewy/detection.h
+++ b/engines/chewy/detection.h
@@ -25,6 +25,8 @@
 namespace Chewy {
 
 struct ChewyGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/cine/detection.h b/engines/cine/detection.h
index 26c26462adc..02e869ed460 100644
--- a/engines/cine/detection.h
+++ b/engines/cine/detection.h
@@ -39,6 +39,8 @@ enum CineGameFeatures {
 };
 
 struct CINEGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameType;
diff --git a/engines/composer/detection.h b/engines/composer/detection.h
index a5394386845..d7c43e5c3d2 100644
--- a/engines/composer/detection.h
+++ b/engines/composer/detection.h
@@ -38,6 +38,8 @@ enum GameFileTypes {
 };
 
 struct ComposerGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameType;
diff --git a/engines/cruise/detection.h b/engines/cruise/detection.h
index 5b331c49fa6..3e82dc2eeb1 100644
--- a/engines/cruise/detection.h
+++ b/engines/cruise/detection.h
@@ -25,6 +25,8 @@
 namespace Cruise {
 
 struct CRUISEGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/cryomni3d/detection.h b/engines/cryomni3d/detection.h
index 162f4053daf..d0e39ced76d 100644
--- a/engines/cryomni3d/detection.h
+++ b/engines/cryomni3d/detection.h
@@ -46,6 +46,8 @@ enum CryOmni3DGameFeatures {
 };
 
 struct CryOmni3DGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	uint8 gameType;
diff --git a/engines/director/detection.h b/engines/director/detection.h
index 8743bd85405..c45aa2a0c0d 100644
--- a/engines/director/detection.h
+++ b/engines/director/detection.h
@@ -33,6 +33,8 @@ enum DirectorGameGID {
 };
 
 struct DirectorGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	DirectorGameGID gameGID;
diff --git a/engines/dm/detection.h b/engines/dm/detection.h
index 1edf7d69893..eba58ba2c51 100644
--- a/engines/dm/detection.h
+++ b/engines/dm/detection.h
@@ -68,6 +68,8 @@ enum SaveTarget {
 };
 
 struct DMADGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(_desc);
+
 	ADGameDescription _desc;
 
 	SaveTarget _saveTargetToWrite;
diff --git a/engines/dragons/detection.h b/engines/dragons/detection.h
index 7b86b64e71d..7d32e7f5c90 100644
--- a/engines/dragons/detection.h
+++ b/engines/dragons/detection.h
@@ -32,6 +32,8 @@ enum {
 };
 
 struct DragonsGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	int gameId;
 };
diff --git a/engines/drascula/detection.h b/engines/drascula/detection.h
index 63126513257..7a71682a8f5 100644
--- a/engines/drascula/detection.h
+++ b/engines/drascula/detection.h
@@ -31,6 +31,8 @@ enum DrasculaGameFeatures {
 };
 
 struct DrasculaGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/dreamweb/detection.h b/engines/dreamweb/detection.h
index 62373179e90..fe551f6cb7b 100644
--- a/engines/dreamweb/detection.h
+++ b/engines/dreamweb/detection.h
@@ -25,6 +25,8 @@
 namespace DreamWeb {
 
 struct DreamWebGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/gob/detection/detection.h b/engines/gob/detection/detection.h
index 7ee0c30f72c..12d647a6695 100644
--- a/engines/gob/detection/detection.h
+++ b/engines/gob/detection/detection.h
@@ -89,6 +89,34 @@ struct GOBGameDescription {
 	const char *startStkBase;
 	const char *startTotBase;
 	uint32 demoIndex;
+
+	uint32 sizeBuffer() const {
+		uint32 ret = desc.sizeBuffer();
+		if (startStkBase) {
+			ret += strlen(startStkBase) + 1;
+		}
+		if (startTotBase) {
+			ret += strlen(startTotBase) + 1;
+		}
+		return ret;
+	}
+
+	void *toBuffer(void *buffer) {
+		buffer = desc.toBuffer(buffer);
+		if (startStkBase) {
+			int len = strlen(startStkBase) + 1;
+			memcpy((char *)buffer, startStkBase, len);
+			startStkBase = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		if (startTotBase) {
+			int len = strlen(startTotBase) + 1;
+			memcpy((char *)buffer, startTotBase, len);
+			startTotBase = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		return buffer;
+	}
 };
 
 #define GAMEOPTION_COPY_PROTECTION	GUIO_GAMEOPTIONS1
diff --git a/engines/grim/detection.h b/engines/grim/detection.h
index 7007d045472..e46e49e80fa 100644
--- a/engines/grim/detection.h
+++ b/engines/grim/detection.h
@@ -38,6 +38,8 @@ enum GrimGameType {
 };
 
 struct GrimGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GrimGameType gameType;
 };
diff --git a/engines/groovie/detection.h b/engines/groovie/detection.h
index a6337829922..5202864e2dd 100644
--- a/engines/groovie/detection.h
+++ b/engines/groovie/detection.h
@@ -35,6 +35,8 @@ enum EngineVersion {
 };
 
 struct GroovieGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	EngineVersion version; // Version of the engine
diff --git a/engines/hopkins/detection.h b/engines/hopkins/detection.h
index e5c66ccd139..22ec70adea2 100644
--- a/engines/hopkins/detection.h
+++ b/engines/hopkins/detection.h
@@ -25,6 +25,8 @@
 namespace Hopkins {
 
 struct HopkinsGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/hugo/detection.h b/engines/hugo/detection.h
index 7176058360b..2714f40bd6e 100644
--- a/engines/hugo/detection.h
+++ b/engines/hugo/detection.h
@@ -48,6 +48,8 @@ enum GameVariant {
 };
 
 struct HugoGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GameType gameType;
 };
diff --git a/engines/icb/detection.h b/engines/icb/detection.h
index 84d26259883..e748f169526 100644
--- a/engines/icb/detection.h
+++ b/engines/icb/detection.h
@@ -32,6 +32,8 @@ enum IcbGameType {
 };
 
 struct IcbGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	IcbGameType gameType;
 };
diff --git a/engines/illusions/detection.h b/engines/illusions/detection.h
index eb234f116b7..20471254cdd 100644
--- a/engines/illusions/detection.h
+++ b/engines/illusions/detection.h
@@ -32,6 +32,8 @@ enum {
 };
 
 struct IllusionsGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	int gameId;
 };
diff --git a/engines/kyra/detection.h b/engines/kyra/detection.h
index add17e93ae6..793ca500409 100644
--- a/engines/kyra/detection.h
+++ b/engines/kyra/detection.h
@@ -65,6 +65,8 @@ struct GameFlags {
 namespace {
 
 struct KYRAGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	Kyra::GameFlags flags;
diff --git a/engines/lilliput/detection.h b/engines/lilliput/detection.h
index c504a242f9b..8f7b6ef94cb 100644
--- a/engines/lilliput/detection.h
+++ b/engines/lilliput/detection.h
@@ -33,6 +33,8 @@ enum GameType {
 };
 
 struct LilliputGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GameType gameType;
 };
diff --git a/engines/lure/detection.h b/engines/lure/detection.h
index f4ecd578cf6..14d5df0eb8d 100644
--- a/engines/lure/detection.h
+++ b/engines/lure/detection.h
@@ -34,6 +34,8 @@ enum {
 };
 
 struct LureGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	uint32 features;
diff --git a/engines/m4/detection.h b/engines/m4/detection.h
index 1f38661910c..0f2f2e76bcd 100644
--- a/engines/m4/detection.h
+++ b/engines/m4/detection.h
@@ -55,6 +55,8 @@ enum Features {
 };
 
 struct M4GameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameType;
diff --git a/engines/made/detection.h b/engines/made/detection.h
index 642d5467c43..9ccedfff1d0 100644
--- a/engines/made/detection.h
+++ b/engines/made/detection.h
@@ -41,6 +41,8 @@ enum MadeGameFeatures {
 };
 
 struct MadeGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/mads/detection.h b/engines/mads/detection.h
index 56075087f58..04f0a28bd72 100644
--- a/engines/mads/detection.h
+++ b/engines/mads/detection.h
@@ -39,6 +39,8 @@ enum {
 };
 
 struct MADSGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/mm/detection.h b/engines/mm/detection.h
index 6ec57406fe6..6b8d9605a8c 100644
--- a/engines/mm/detection.h
+++ b/engines/mm/detection.h
@@ -41,6 +41,8 @@ enum GameFeature {
 };
 
 struct MightAndMagicGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/mohawk/detection.h b/engines/mohawk/detection.h
index 8dbe8dd8647..c95ac9ec436 100644
--- a/engines/mohawk/detection.h
+++ b/engines/mohawk/detection.h
@@ -68,6 +68,25 @@ struct MohawkGameDescription {
 	uint8 gameType;
 	uint32 features;
 	const char *appName;
+
+	uint32 sizeBuffer() const {
+		uint32 ret = desc.sizeBuffer();
+		if (appName) {
+			ret += strlen(appName) + 1;
+		}
+		return ret;
+	}
+
+	void *toBuffer(void *buffer) {
+		buffer = desc.toBuffer(buffer);
+		if (appName) {
+			int len = strlen(appName) + 1;
+			memcpy((char *)buffer, appName, len);
+			appName = (const char *)buffer;
+			buffer = (char *)buffer + len;
+		}
+		return buffer;
+	}
 };
 
 } // End of namespace Mohawk
diff --git a/engines/mortevielle/detection.h b/engines/mortevielle/detection.h
index 15115e00c22..acad8e9e6a4 100644
--- a/engines/mortevielle/detection.h
+++ b/engines/mortevielle/detection.h
@@ -32,6 +32,8 @@ enum {
 };
 
 struct MortevielleGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	Common::Language originalLanguage;
 	uint8 dataFeature;
diff --git a/engines/mtropolis/detection.h b/engines/mtropolis/detection.h
index 946287861e6..0ba4ae0c3fa 100644
--- a/engines/mtropolis/detection.h
+++ b/engines/mtropolis/detection.h
@@ -99,6 +99,8 @@ enum MTGameFlag {
 };
 
 struct MTropolisGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/myst3/detection.h b/engines/myst3/detection.h
index 634fd29969c..c83a27f7210 100644
--- a/engines/myst3/detection.h
+++ b/engines/myst3/detection.h
@@ -33,6 +33,8 @@ enum GameLocalizationType {
 };
 
 struct Myst3GameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	uint32 localizationType;
 };
diff --git a/engines/nancy/detection.h b/engines/nancy/detection.h
index e88de519828..8e7815d97ab 100644
--- a/engines/nancy/detection.h
+++ b/engines/nancy/detection.h
@@ -47,6 +47,8 @@ enum NancyGameFlags {
 };
 
 struct NancyGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GameType gameType;
 };
diff --git a/engines/ngi/detection.h b/engines/ngi/detection.h
index 13e4dd4a3db..04a1fc1eab1 100644
--- a/engines/ngi/detection.h
+++ b/engines/ngi/detection.h
@@ -32,6 +32,8 @@ enum NGIGameId {
 };
 
 struct NGIGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameId;
diff --git a/engines/parallaction/detection.h b/engines/parallaction/detection.h
index 94f6131d87a..5b0d88b8eae 100644
--- a/engines/parallaction/detection.h
+++ b/engines/parallaction/detection.h
@@ -41,6 +41,8 @@ enum ParallactionGameType {
 };
 
 struct PARALLACTIONGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameType;
diff --git a/engines/pegasus/detection.h b/engines/pegasus/detection.h
index 83e591703b4..19a995bbc1a 100644
--- a/engines/pegasus/detection.h
+++ b/engines/pegasus/detection.h
@@ -31,6 +31,8 @@ enum {
 };
 
 struct PegasusGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/prince/detection.h b/engines/prince/detection.h
index 38fb09395aa..49f365355e4 100644
--- a/engines/prince/detection.h
+++ b/engines/prince/detection.h
@@ -40,6 +40,8 @@ enum {
 };
 
 struct PrinceGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	PrinceGameType gameType;
 };
diff --git a/engines/queen/detection.h b/engines/queen/detection.h
index 4e65dd4c3ba..c3900ff19c4 100644
--- a/engines/queen/detection.h
+++ b/engines/queen/detection.h
@@ -25,6 +25,8 @@
 namespace Queen {
 
 struct QueenGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/saga/detection.h b/engines/saga/detection.h
index b1c99f99275..ea790a84c2b 100644
--- a/engines/saga/detection.h
+++ b/engines/saga/detection.h
@@ -118,6 +118,22 @@ struct SAGAGameDescription {
 	GameIntroList introList;
 	// Only used if GF_INSTALLER is set
 	ADGameFileDescription filesInArchive[5];
+
+	uint32 sizeBuffer() const {
+		uint32 ret = desc.sizeBuffer();
+		for(int i = 0; i < ARRAYSIZE(filesInArchive); i++) {
+			ret += filesInArchive[i].sizeBuffer();
+		}
+		return ret;
+	}
+
+	void *toBuffer(void *buffer) {
+		buffer = desc.toBuffer(buffer);
+		for(int i = 0; i < ARRAYSIZE(filesInArchive); i++) {
+			buffer = filesInArchive[i].toBuffer(buffer);
+		}
+		return buffer;
+	}
 };
 
 #define GAMEOPTION_COPY_PROTECTION	GUIO_GAMEOPTIONS1
diff --git a/engines/saga2/detection.h b/engines/saga2/detection.h
index 983798574bf..d12060bdad9 100644
--- a/engines/saga2/detection.h
+++ b/engines/saga2/detection.h
@@ -40,6 +40,8 @@ enum GameFileTypes {
 };
 
 struct SAGA2GameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameId;
diff --git a/engines/sherlock/detection.h b/engines/sherlock/detection.h
index 3ac34c2a170..47b1308ca95 100644
--- a/engines/sherlock/detection.h
+++ b/engines/sherlock/detection.h
@@ -32,6 +32,8 @@ enum GameType {
 };
 
 struct SherlockGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	GameType gameID;
diff --git a/engines/sludge/detection.h b/engines/sludge/detection.h
index 67e043d27ae..e5ae66b9195 100644
--- a/engines/sludge/detection.h
+++ b/engines/sludge/detection.h
@@ -25,6 +25,8 @@
 namespace Sludge {
 
 struct SludgeGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	uint languageID;
 };
diff --git a/engines/startrek/detection.h b/engines/startrek/detection.h
index 3d44fe2c5f2..2c9ae1c9b4d 100644
--- a/engines/startrek/detection.h
+++ b/engines/startrek/detection.h
@@ -37,6 +37,8 @@ enum StarTrekGameFeatures {
 };
 
 struct StarTrekGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	uint8 gameType;
diff --git a/engines/tinsel/detection.h b/engines/tinsel/detection.h
index 10756a9ed9e..1ba39472f7a 100644
--- a/engines/tinsel/detection.h
+++ b/engines/tinsel/detection.h
@@ -67,6 +67,8 @@ enum TinselEngineVersion {
 };
 
 struct TinselGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/titanic/detection.h b/engines/titanic/detection.h
index 8194020b53f..5a78dcc2aa3 100644
--- a/engines/titanic/detection.h
+++ b/engines/titanic/detection.h
@@ -25,6 +25,8 @@
 namespace Titanic {
 
 struct TitanicGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/toltecs/detection.h b/engines/toltecs/detection.h
index 8f3fc5f2d9e..3b44af2ebd5 100644
--- a/engines/toltecs/detection.h
+++ b/engines/toltecs/detection.h
@@ -25,6 +25,8 @@
 namespace Toltecs {
 
 struct ToltecsGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/tony/detection.h b/engines/tony/detection.h
index e3b1bf64339..f0274daf2fd 100644
--- a/engines/tony/detection.h
+++ b/engines/tony/detection.h
@@ -29,6 +29,8 @@ enum {
 };
 
 struct TonyGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/tsage/detection.h b/engines/tsage/detection.h
index 21bc4270b1d..c4514fee6c5 100644
--- a/engines/tsage/detection.h
+++ b/engines/tsage/detection.h
@@ -42,6 +42,8 @@ enum {
 };
 
 struct tSageGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	int gameID;
diff --git a/engines/twp/detection.h b/engines/twp/detection.h
index f0bfe5c4750..9924e12f81a 100644
--- a/engines/twp/detection.h
+++ b/engines/twp/detection.h
@@ -56,6 +56,8 @@ enum LanguageSupported {
 
 extern const PlainGameDescriptor twpGames[];
 struct TwpGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GameXorKey xorKey;
 	LanguageSupported languageSupported;
diff --git a/engines/ultima/detection.h b/engines/ultima/detection.h
index a78be325dcb..89acbad61cd 100644
--- a/engines/ultima/detection.h
+++ b/engines/ultima/detection.h
@@ -63,6 +63,8 @@ enum UltimaGameFlags {
 };
 
 struct UltimaGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	GameId gameId;
 	uint32 features;
diff --git a/engines/vcruise/detection.h b/engines/vcruise/detection.h
index cdb143a05e6..20293390521 100644
--- a/engines/vcruise/detection.h
+++ b/engines/vcruise/detection.h
@@ -47,6 +47,8 @@ enum VCruiseGameFlag {
 };
 
 struct VCruiseGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 
 	VCruiseGameID gameID;
diff --git a/engines/voyeur/detection.h b/engines/voyeur/detection.h
index 0ab06176942..f8ad6e8855c 100644
--- a/engines/voyeur/detection.h
+++ b/engines/voyeur/detection.h
@@ -25,6 +25,8 @@
 namespace Voyeur {
 
 struct VoyeurGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 };
 
diff --git a/engines/wintermute/detection.h b/engines/wintermute/detection.h
index eb81e5829b4..e02dc3a86df 100644
--- a/engines/wintermute/detection.h
+++ b/engines/wintermute/detection.h
@@ -129,6 +129,8 @@ enum WintermuteGameFeatures {
 };
 
 struct WMEGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(adDesc);
+
 	ADGameDescription adDesc;
 	WMETargetExecutable targetExecutable;
 };
diff --git a/engines/zvision/detection.h b/engines/zvision/detection.h
index 56358206ad5..064e0832958 100644
--- a/engines/zvision/detection.h
+++ b/engines/zvision/detection.h
@@ -37,6 +37,8 @@ enum ZVisionFeatures {
 };
 
 struct ZVisionGameDescription {
+	AD_GAME_DESCRIPTION_HELPERS(desc);
+
 	ADGameDescription desc;
 	ZVisionGameId gameId;
 };


Commit: 37de547ec17023daa99f6eaf23963d14a9f5e8d3
    https://github.com/scummvm/scummvm/commit/37de547ec17023daa99f6eaf23963d14a9f5e8d3
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Make AdvancedMetaEngine use ADDynamicGameDescription

This will allow to unload AdvancedMetaEngineDetection plugin as
soon as identifyGame is done and before loading the AdvancedMetaEngine.

Changed paths:
    engines/advancedDetector.h
    engines/saga2/metaengine.cpp


diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 1204f03f205..ee863797003 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -604,6 +604,18 @@ template<class Descriptor>
 class AdvancedMetaEngineDetection : public AdvancedMetaEngineDetectionBase {
 protected:
 	AdvancedMetaEngineDetection(const Descriptor *descs, const PlainGameDescriptor *gameIds) : AdvancedMetaEngineDetectionBase(descs, sizeof(Descriptor), gameIds) {}
+
+	Common::Error identifyGame(DetectedGame &game, const void **descriptor) override {
+		assert(descriptor);
+		Common::Error err = AdvancedMetaEngineDetectionBase::identifyGame(game, descriptor);
+		if (err.getCode() != Common::kNoError) {
+			return err;
+		}
+		if (*descriptor) {
+			*descriptor = new ADDynamicGameDescription<Descriptor>(static_cast<const Descriptor *>(*descriptor));
+		}
+		return err;
+	}
 };
 
 /**
@@ -706,6 +718,12 @@ protected:
 		return createInstance(syst, engine, static_cast<const Descriptor *>(desc));
 	}
 
+	void deleteInstance(Engine *engine, const DetectedGame &gameDescriptor, const void *meDescriptor) override {
+		delete engine;
+		delete static_cast<ADDynamicGameDescription<Descriptor> *>(
+                                const_cast<void *>(meDescriptor));
+	}
+
 private:
 	// Silence overloaded-virtual warning from clang
 	using AdvancedMetaEngineBase::createInstance;
diff --git a/engines/saga2/metaengine.cpp b/engines/saga2/metaengine.cpp
index 649f4ce2bb2..6fe3d9417f7 100644
--- a/engines/saga2/metaengine.cpp
+++ b/engines/saga2/metaengine.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "saga2/saga2.h"
+#include "saga2/detection.h"
 #include "engines/advancedDetector.h"
 
 class Saga2MetaEngine : public AdvancedMetaEngine<Saga2::SAGA2GameDescription> {


Commit: ab4d6db36b73cbe72b38c62ee5fce6ce4e6cfff4
    https://github.com/scummvm/scummvm/commit/ab4d6db36b73cbe72b38c62ee5fce6ce4e6cfff4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GLK: Split detection from running

This allows to not use the detection plugin while running the engine.

Changed paths:
    engines/glk/detection.cpp
    engines/glk/detection.h
    engines/glk/metaengine.cpp


diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index 73ee57f0e0e..c559b7d5b58 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -178,8 +178,70 @@ PlainGameDescriptor GlkMetaEngineDetection::findGame(const char *gameId) const {
 
 #undef FIND_GAME
 
+Common::String GlkMetaEngineDetection::findFileByGameId(const Common::String &gameId) {
+	// Get the list of files in the folder and return detection against them
+	Common::FSNode folder = Common::FSNode(ConfMan.getPath("path"));
+	Common::FSList fslist;
+	folder.getChildren(fslist, Common::FSNode::kListFilesOnly);
+
+	// Iterate over the files
+	for (Common::FSList::iterator i = fslist.begin(); i != fslist.end(); ++i) {
+		// Run a detection on each file in the folder individually
+		Common::FSList singleList;
+		singleList.push_back(*i);
+		DetectedGames games = detectGames(singleList);
+
+		// If a detection was found with the correct game Id, we have a winner
+		if (!games.empty() && games.front().gameId == gameId)
+			return (*i).getName();
+	}
+
+	// No match found
+	return Common::String();
+}
+
 Common::Error GlkMetaEngineDetection::identifyGame(DetectedGame &game, const void **descriptor) {
 	*descriptor = nullptr;
+
+	// Populate the game description
+	Glk::GlkGameDescription *gameDesc = new Glk::GlkGameDescription;
+
+	gameDesc->_gameId = ConfMan.get("gameid");
+	gameDesc->_filename = ConfMan.get("filename");
+
+	gameDesc->_language = Common::UNK_LANG;
+	gameDesc->_platform = Common::kPlatformUnknown;
+	if (ConfMan.hasKey("language"))
+		gameDesc->_language = Common::parseLanguage(ConfMan.get("language"));
+	if (ConfMan.hasKey("platform"))
+		gameDesc->_platform = Common::parsePlatform(ConfMan.get("platform"));
+
+	// If the game description has no filename, the engine has been launched directly from
+	// the command line. Do a scan for supported games for that Id in the game folder
+	if (gameDesc->_filename.empty()) {
+		gameDesc->_filename = findFileByGameId(gameDesc->_gameId);
+		if (gameDesc->_filename.empty()) {
+			delete gameDesc;
+			return Common::kNoGameDataFoundError;
+		}
+	}
+
+	// Get the MD5
+	Common::File f;
+	if (!f.open(Common::FSNode(ConfMan.getPath("path")).getChild(gameDesc->_filename))) {
+		delete gameDesc;
+		return Common::kNoGameDataFoundError;
+	}
+
+	Common::String fileName = f.getName();
+	if (fileName.hasSuffixIgnoreCase(".D64"))
+		gameDesc->_md5 = Common::computeStreamMD5AsString(f);
+	else
+		gameDesc->_md5 = Common::computeStreamMD5AsString(f, 5000);
+	f.close();
+
+	*descriptor = gameDesc;
+
 	game = DetectedGame(getName(), findGame(ConfMan.get("gameid").c_str()));
 	return game.gameId.empty() ? Common::kUnknownError : Common::kNoError;
 }
diff --git a/engines/glk/detection.h b/engines/glk/detection.h
index 172bae62913..a2bdc8e9e47 100644
--- a/engines/glk/detection.h
+++ b/engines/glk/detection.h
@@ -29,6 +29,8 @@
  * ScummVM Meta Engine interface
  */
 class GlkMetaEngineDetection : public MetaEngineDetection {
+private:
+	Common::String findFileByGameId(const Common::String &gameId);
 public:
 	GlkMetaEngineDetection() : MetaEngineDetection() {}
 
@@ -56,7 +58,7 @@ public:
 	 * (possibly empty) list of games supported by the engine which it was able
 	 * to detect amongst the given files.
 	 */
-	DetectedGames detectGames(const Common::FSList &fslist, uint32 /*skipUnsupported*/, bool /*skipIncomplete*/) override;
+	DetectedGames detectGames(const Common::FSList &fslist, uint32 skipADFlags = 0, bool skipIncomplete = false) override;
 
 	/**
 	 * Query the engine for a PlainGameDescriptor for the specified gameid, if any.
diff --git a/engines/glk/metaengine.cpp b/engines/glk/metaengine.cpp
index 7ec639a884e..57c8b239b5d 100644
--- a/engines/glk/metaengine.cpp
+++ b/engines/glk/metaengine.cpp
@@ -73,8 +73,6 @@
 #define MAX_SAVES 99
 
 class GlkMetaEngine : public MetaEngine {
-private:
-	Common::String findFileByGameId(const Common::String &gameId) const;
 public:
 	const char* getName() const override {
 		return "glk";
@@ -140,31 +138,6 @@ template<class META, class ENG>bool create(OSystem *syst,
 	}
 }
 
-Common::String GlkMetaEngine::findFileByGameId(const Common::String &gameId) const {
-	// Get the list of files in the folder and return detection against them
-	Common::FSNode folder = Common::FSNode(ConfMan.getPath("path"));
-	Common::FSList fslist;
-	folder.getChildren(fslist, Common::FSNode::kListFilesOnly);
-
-	// Get the matching MetaEngine for this Engine.
-	MetaEngineDetection &metaEngine = g_engine->getMetaEngineDetection();
-
-	// Iterate over the files
-	for (Common::FSList::iterator i = fslist.begin(); i != fslist.end(); ++i) {
-		// Run a detection on each file in the folder individually
-		Common::FSList singleList;
-		singleList.push_back(*i);
-		DetectedGames games = metaEngine.detectGames(singleList);
-
-		// If a detection was found with the correct game Id, we have a winner
-		if (!games.empty() && games.front().gameId == gameId)
-			return (*i).getName();
-	}
-
-	// No match found
-	return Common::String();
-}
-
 Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine,
 		const DetectedGame &gameDescriptor, const void *metaEngineDescriptor) {
 #ifndef RELEASE_BUILD
@@ -172,69 +145,44 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine,
 #endif
 	assert(engine);
 
-	// Populate the game description
-	Glk::GlkGameDescription gameDesc;
-	gameDesc._gameId = ConfMan.get("gameid");
-	gameDesc._filename = ConfMan.get("filename");
-
-	gameDesc._language = Common::UNK_LANG;
-	gameDesc._platform = Common::kPlatformUnknown;
-	if (ConfMan.hasKey("language"))
-		gameDesc._language = Common::parseLanguage(ConfMan.get("language"));
-	if (ConfMan.hasKey("platform"))
-		gameDesc._platform = Common::parsePlatform(ConfMan.get("platform"));
-
-	// If the game description has no filename, the engine has been launched directly from
-	// the command line. Do a scan for supported games for that Id in the game folder
-	if (gameDesc._filename.empty()) {
-		gameDesc._filename = findFileByGameId(gameDesc._gameId);
-		if (gameDesc._filename.empty())
-			return Common::kNoGameDataFoundError;
-	}
-
-	// Get the MD5
-	Common::File f;
-	if (!f.open(Common::FSNode(ConfMan.getPath("path")).getChild(gameDesc._filename)))
-		return Common::kNoGameDataFoundError;
-
-	Common::String fileName = f.getName();
-	if (fileName.hasSuffixIgnoreCase(".D64"))
-		gameDesc._md5 = Common::computeStreamMD5AsString(f);
-	else
-		gameDesc._md5 = Common::computeStreamMD5AsString(f, 5000);
-	f.close();
+	Glk::GlkGameDescription *gameDesc = static_cast<Glk::GlkGameDescription *>(
+			const_cast<void *>(metaEngineDescriptor));
+	assert(gameDesc);
 
 	// Create the correct engine
 	*engine = nullptr;
-	if ((create<Glk::Adrift::AdriftMetaEngine, Glk::Adrift::Adrift>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::AdvSys::AdvSysMetaEngine, Glk::AdvSys::AdvSys>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::AGT::AGTMetaEngine, Glk::AGT::AGT>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Alan2::Alan2MetaEngine, Glk::Alan2::Alan2>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Alan3::Alan3MetaEngine, Glk::Alan3::Alan3>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Archetype::ArchetypeMetaEngine, Glk::Archetype::Archetype>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Comprehend::ComprehendMetaEngine, Glk::Comprehend::Comprehend>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Glulx::GlulxMetaEngine, Glk::Glulx::Glulx>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Hugo::HugoMetaEngine, Glk::Hugo::Hugo>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::JACL::JACLMetaEngine, Glk::JACL::JACL>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Level9::Level9MetaEngine, Glk::Level9::Level9>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Magnetic::MagneticMetaEngine, Glk::Magnetic::Magnetic>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Quest::QuestMetaEngine, Glk::Quest::Quest>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::Scott::ScottMetaEngine, Glk::Scott::Scott>(syst, gameDesc, *engine))) {}
-	else if ((create<Glk::ZCode::ZCodeMetaEngine, Glk::ZCode::ZCode>(syst, gameDesc, *engine))) {}
+	if ((create<Glk::Adrift::AdriftMetaEngine, Glk::Adrift::Adrift>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::AdvSys::AdvSysMetaEngine, Glk::AdvSys::AdvSys>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::AGT::AGTMetaEngine, Glk::AGT::AGT>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Alan2::Alan2MetaEngine, Glk::Alan2::Alan2>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Alan3::Alan3MetaEngine, Glk::Alan3::Alan3>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Archetype::ArchetypeMetaEngine, Glk::Archetype::Archetype>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Comprehend::ComprehendMetaEngine, Glk::Comprehend::Comprehend>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Glulx::GlulxMetaEngine, Glk::Glulx::Glulx>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Hugo::HugoMetaEngine, Glk::Hugo::Hugo>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::JACL::JACLMetaEngine, Glk::JACL::JACL>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Level9::Level9MetaEngine, Glk::Level9::Level9>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Magnetic::MagneticMetaEngine, Glk::Magnetic::Magnetic>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Quest::QuestMetaEngine, Glk::Quest::Quest>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::Scott::ScottMetaEngine, Glk::Scott::Scott>(syst, *gameDesc, *engine))) {}
+	else if ((create<Glk::ZCode::ZCodeMetaEngine, Glk::ZCode::ZCode>(syst, *gameDesc, *engine))) {}
 #ifndef RELEASE_BUILD
-	else if ((td = Glk::TADS::TADSMetaEngine::findGame(gameDesc._gameId.c_str()))._description) {
+	else if ((td = Glk::TADS::TADSMetaEngine::findGame(gameDesc->_gameId.c_str()))._description) {
 		if (!isGameAllowed(td._supportLevel))
 			return Common::kUserCanceled;
 		else if (td._options & Glk::TADS::OPTION_TADS3)
-			new Glk::TADS::TADS3::TADS3(syst, gameDesc);
+			new Glk::TADS::TADS3::TADS3(syst, *gameDesc);
 		else
-			new Glk::TADS::TADS2::TADS2(syst, gameDesc);
+			new Glk::TADS::TADS2::TADS2(syst, *gameDesc);
 	}
 #endif
 	else {
+		delete gameDesc;
 		return Common::kNoGameDataFoundError;
 	}
 
+	// gameDesc is copied in Glk
+	delete gameDesc;
 	return *engine ? Common::kNoError : Common::kUserCanceled;
 }
 


Commit: 2645b1431cea95638d0c083ea331058f15ba0732
    https://github.com/scummvm/scummvm/commit/2645b1431cea95638d0c083ea331058f15ba0732
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Rename findPlugin to findDetectionPlugin

This function does return a MetaEngineDetection plugin

Changed paths:
    base/commandLine.cpp
    base/main.cpp
    base/plugins.cpp
    engines/engine.cpp
    engines/metaengine.h
    engines/sci/detection.cpp
    engines/wintermute/detection.cpp
    gui/EventRecorder.cpp
    gui/about.cpp
    gui/launcher.cpp
    gui/options.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 4c2b527925b..0ebaf8b1d54 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1026,8 +1026,8 @@ static void listGames(const Common::String &engineID) {
 
 	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
-		const Plugin *p = EngineMan.findPlugin((*iter)->getName());
-		/* If for some reason, we can't find the MetaEngine for this Engine, just ignore it */
+		const Plugin *p = EngineMan.findDetectionPlugin((*iter)->getName());
+		/* If for some reason, we can't find the MetaEngineDetection for this Engine, just ignore it */
 		if (!p) {
 			continue;
 		}
@@ -1073,8 +1073,8 @@ static void listEngines() {
 
 	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
-		const Plugin *p = EngineMan.findPlugin((*iter)->getName());
-		/* If for some reason, we can't find the MetaEngine for this Engine, just ignore it */
+		const Plugin *p = EngineMan.findDetectionPlugin((*iter)->getName());
+		/* If for some reason, we can't find the MetaEngineDetection for this Engine, just ignore it */
 		if (!p) {
 			continue;
 		}
@@ -1347,7 +1347,7 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 			game = EngineMan.findTarget(*i, &metaEnginePlugin);
 		} else if (game = findGameMatchingName(*i), !game.gameId.empty()) {
 			// The name is a known game id
-			metaEnginePlugin = EngineMan.findPlugin(game.engineId);
+			metaEnginePlugin = EngineMan.findDetectionPlugin(game.engineId);
 			currentTarget = createTemporaryTarget(game.engineId, game.gameId);
 		} else {
 			return Common::Error(Common::kEnginePluginNotFound, Common::String::format("target '%s'", singleTarget.c_str()));
@@ -2019,7 +2019,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		if (command == "md5" && settings.contains("md5-engine")) {
 			Common::String engineID = settings["md5-engine"];
 
-			const Plugin *plugin = EngineMan.findPlugin(engineID);
+			const Plugin *plugin = EngineMan.findDetectionPlugin(engineID);
 			if (!plugin) {
 				warning("'%s' is an invalid engine ID. Use the --list-engines command to list supported engine IDs", engineID.c_str());
 				return true;
diff --git a/base/main.cpp b/base/main.cpp
index 766dde1c456..2bbaa02a4bf 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -141,7 +141,7 @@ static Common::Error identifyGame(const Common::String &debugLevels, const Plugi
 		return Common::kUnknownError;
 	}
 
-	*detectionPlugin = EngineMan.findPlugin(engineId);
+	*detectionPlugin = EngineMan.findDetectionPlugin(engineId);
 	if (!*detectionPlugin) {
 		warning("'%s' is an invalid engine ID. Use the --list-engines command to list supported engine IDs", engineId.c_str());
 		return Common::kMetaEnginePluginNotFound;
diff --git a/base/plugins.cpp b/base/plugins.cpp
index ebdfd65fd5e..8b6fc936f96 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -671,7 +671,7 @@ QualifiedGameList EngineManager::findGamesMatching(const Common::String &engineI
 
 	if (!engineId.empty()) {
 		// If we got an engine name, look for THE game only in that engine
-		const Plugin *p = EngineMan.findPlugin(engineId);
+		const Plugin *p = EngineMan.findDetectionPlugin(engineId);
 		if (p) {
 			const MetaEngineDetection &engine = p->get<MetaEngineDetection>();
 			DebugMan.addAllDebugChannels(engine.getDebugChannels());
@@ -811,7 +811,7 @@ Common::String EngineManager::createTargetForGame(const DetectedGame &game) {
 	return domain;
 }
 
-const Plugin *EngineManager::findPlugin(const Common::String &engineId) const {
+const Plugin *EngineManager::findDetectionPlugin(const Common::String &engineId) const {
 	const PluginList &plugins = getPlugins();
 
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); iter++)
@@ -871,7 +871,7 @@ QualifiedGameDescriptor EngineManager::findTarget(const Common::String &target,
 		return QualifiedGameDescriptor();
 
 	// Look for the engine ID
-	const Plugin *foundPlugin = findPlugin(domain->getVal("engineid"));
+	const Plugin *foundPlugin = findDetectionPlugin(domain->getVal("engineid"));
 	if (!foundPlugin) {
 		return QualifiedGameDescriptor();
 	}
@@ -939,7 +939,7 @@ void EngineManager::upgradeTargetForEngineId(const Common::String &target) const
 
 	// First, try to update entries for engines that previously used the "single id" system
 	// Search for an engine whose ID is the game ID
-	const Plugin *plugin = findPlugin(oldGameId);
+	const Plugin *plugin = findDetectionPlugin(oldGameId);
 	if (plugin) {
 		// Run detection on the game path
 		Common::FSNode dir(path);
diff --git a/engines/engine.cpp b/engines/engine.cpp
index a29c632922c..4138b1f1797 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -1009,13 +1009,13 @@ GUI::Debugger *Engine::getOrCreateDebugger() {
 
 /*
 EnginePlugin *Engine::getMetaEnginePlugin() const {
-	return EngineMan.findPlugin(ConfMan.get("engineid"));
+	return EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
 }
 
 */
 
 MetaEngineDetection &Engine::getMetaEngineDetection() {
-	const Plugin *plugin = EngineMan.findPlugin(ConfMan.get("engineid"));
+	const Plugin *plugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
 	assert(plugin);
 	return plugin->get<MetaEngineDetection>();
 }
diff --git a/engines/metaengine.h b/engines/metaengine.h
index e5ed7093601..a686e1de810 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -596,7 +596,7 @@ public:
 	DetectionResults detectGames(const Common::FSList &fslist, uint32 skipADFlags = 0, bool skipIncomplete = false);
 
 	/** Find a plugin by its engine ID. */
-	const Plugin *findPlugin(const Common::String &engineId) const;
+	const Plugin *findDetectionPlugin(const Common::String &engineId) const;
 
 	/**
 	 * Get the list of all plugins for the type specified.
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 3d6cc46a34a..4ec7c229925 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -251,7 +251,7 @@ ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		}
 	}
 
-	const Plugin *metaEnginePlugin = EngineMan.findPlugin(getName());
+	const Plugin *metaEnginePlugin = EngineMan.findDetectionPlugin(getName());
 	if (!metaEnginePlugin) {
 		return ADDetectedGame();
 	}
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index ae6886092df..cbdf4e98a48 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -95,7 +95,7 @@ public:
 			}
 		}
 
-		const Plugin *metaEnginePlugin = EngineMan.findPlugin(getName());
+		const Plugin *metaEnginePlugin = EngineMan.findDetectionPlugin(getName());
 
 		if (metaEnginePlugin) {
 			const Plugin *enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index 15bb539d7e5..7c4c84a3dc4 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -762,7 +762,7 @@ SDL_Surface *EventRecorder::getSurface(int width, int height) {
 }
 
 bool EventRecorder::switchMode() {
-	const Plugin *detectionPlugin = EngineMan.findPlugin(ConfMan.get("engineid"));
+	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
 	const Plugin *plugin = PluginMan.getEngineFromMetaEngine(detectionPlugin);
 	bool metaInfoSupport = plugin->get<MetaEngine>().hasFeature(MetaEngine::kSavesSupportMetaInfo);
 	bool featuresSupport = metaInfoSupport &&
@@ -811,7 +811,7 @@ bool EventRecorder::checkForContinueGame() {
 
 void EventRecorder::deleteTemporarySave() {
 	if (_temporarySlot == -1) return;
-	const Plugin *detectionPlugin = EngineMan.findPlugin(ConfMan.get("engineid"));
+	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
 	const Plugin *plugin = PluginMan.getEngineFromMetaEngine(detectionPlugin);
 	const Common::String target = ConfMan.getActiveDomainName();
 	 plugin->get<MetaEngine>().removeSaveState(target.c_str(), _temporarySlot);
diff --git a/gui/about.cpp b/gui/about.cpp
index 88de3cb5e28..f3d505fe5b3 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -160,7 +160,7 @@ AboutDialog::AboutDialog()
 	for (; iter != plugins.end(); ++iter) {
 		Common::String str;
 
-		const Plugin *p = EngineMan.findPlugin((*iter)->getName());
+		const Plugin *p = EngineMan.findDetectionPlugin((*iter)->getName());
 
 		if (!p) {
 			warning("Cannot find plugin for %s", (*iter)->getName());
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index ce0cd472e89..a64f7734cd8 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -589,7 +589,7 @@ Common::Array<LauncherEntry> LauncherDialog::generateEntries(const Common::Confi
 
 		Common::StringMap &engineMap = _engines[engineid];
 		if (!engineMap.contains(gameid)) {
-			const Plugin *plugin = EngineMan.findPlugin(engineid);
+			const Plugin *plugin = EngineMan.findDetectionPlugin(engineid);
 			if (plugin) {
 				PlainGameDescriptor gd = plugin->get<MetaEngineDetection>().findGame(gameid.c_str());
 				if (gd.description)
diff --git a/gui/options.cpp b/gui/options.cpp
index d706bcf3780..6d7b6ad3bf2 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2870,7 +2870,7 @@ bool GlobalOptionsDialog::updateAutosavePeriod(int newValue) {
 		// note that engineid isn't present on games that predate it
 		// and haven't been run since it was introduced.
 		const Common::String engine = domain.getValOrDefault("engineid");
-		if (const Plugin *detectionPlugin = EngineMan.findPlugin(engine)) {
+		if (const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(engine)) {
 			if (const Plugin *plugin = PluginMan.getEngineFromMetaEngine(detectionPlugin)) {
 				MetaEngine &metaEngine = plugin->get<MetaEngine>();
 				const int autoSaveSlot = metaEngine.getAutosaveSlot();


Commit: 5ded4aedec3d0143a60818c57e63320c1b64d3e7
    https://github.com/scummvm/scummvm/commit/5ded4aedec3d0143a60818c57e63320c1b64d3e7
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Don't call plugin->getType repeatedly

Changed paths:
    base/plugins.cpp


diff --git a/base/plugins.cpp b/base/plugins.cpp
index 8b6fc936f96..692743ec22b 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -632,8 +632,9 @@ void PluginManager::addToPluginsInMemList(Plugin *plugin) {
 	// The plugin is valid, see if it provides the same module as an
 	// already loaded one and should replace it.
 
-	PluginList::iterator pl = _pluginsInMem[plugin->getType()].begin();
-	while (!found && pl != _pluginsInMem[plugin->getType()].end()) {
+	PluginList &list = _pluginsInMem[plugin->getType()];
+	PluginList::iterator pl = list.begin();
+	while (!found && pl != list.end()) {
 		if (!strcmp(plugin->getName(), (*pl)->getName())) {
 			// Found a duplicated module. Replace the old one.
 			found = true;
@@ -647,7 +648,7 @@ void PluginManager::addToPluginsInMemList(Plugin *plugin) {
 
 	if (!found) {
 		// If it provides a new module, just add it to the list of known plugins in memory.
-		_pluginsInMem[plugin->getType()].push_back(plugin);
+		list.push_back(plugin);
 	}
 }
 


Commit: c93f53b491c3c8222809e0fea51da7f006213d13
    https://github.com/scummvm/scummvm/commit/c93f53b491c3c8222809e0fea51da7f006213d13
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Rename getEngineFromMetaEngine to getEngineFromDetectionPlugin

Update comments and variable names accordingly.
This now matches what this function really do.

Changed paths:
    base/commandLine.cpp
    base/main.cpp
    base/plugins.cpp
    base/plugins.h
    engines/sci/detection.cpp
    engines/wintermute/detection.cpp
    gui/EventRecorder.cpp
    gui/editgamedialog.cpp
    gui/launcher.cpp
    gui/options.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 0ebaf8b1d54..6682742cd68 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1337,17 +1337,17 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 		Common::String currentTarget;
 		QualifiedGameDescriptor game;
 
-		const Plugin *metaEnginePlugin = nullptr;
+		const Plugin *detectionPlugin = nullptr;
 		const Plugin *enginePlugin = nullptr;
 
 		if (ConfMan.hasGameDomain(*i)) {
 			// The name is a known target
 			currentTarget = *i;
 			EngineMan.upgradeTargetIfNecessary(*i);
-			game = EngineMan.findTarget(*i, &metaEnginePlugin);
+			game = EngineMan.findTarget(*i, &detectionPlugin);
 		} else if (game = findGameMatchingName(*i), !game.gameId.empty()) {
 			// The name is a known game id
-			metaEnginePlugin = EngineMan.findDetectionPlugin(game.engineId);
+			detectionPlugin = EngineMan.findDetectionPlugin(game.engineId);
 			currentTarget = createTemporaryTarget(game.engineId, game.gameId);
 		} else {
 			return Common::Error(Common::kEnginePluginNotFound, Common::String::format("target '%s'", singleTarget.c_str()));
@@ -1356,7 +1356,7 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 		// If we actually found a domain, we're going to change the domain
 		ConfMan.setActiveDomain(currentTarget);
 
-		if (!metaEnginePlugin) {
+		if (!detectionPlugin) {
 			// If the target was specified, treat this as an error, and otherwise skip it.
 			if (!singleTarget.empty())
 				return Common::Error(Common::kMetaEnginePluginNotFound,
@@ -1364,7 +1364,7 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 			printf("MetaEnginePlugin could not be loaded for target '%s'\n", i->c_str());
 			continue;
 		} else {
-			enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
+			enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 
 			if (!enginePlugin) {
 				// If the target was specified, treat this as an error, and otherwise skip it.
diff --git a/base/main.cpp b/base/main.cpp
index 2bbaa02a4bf..5a498bafe06 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -751,7 +751,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 
 		if (result.getCode() == Common::kNoError) {
 			// Then, get the relevant Engine plugin from MetaEngine.
-			enginePlugin = PluginMan.getEngineFromMetaEngine(plugin);
+			enginePlugin = PluginMan.getEngineFromDetectionPlugin(plugin);
 			if (enginePlugin == nullptr) {
 				result = Common::kEnginePluginNotFound;
 			}
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 692743ec22b..8535858f9b5 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -286,7 +286,7 @@ void PluginManager::addPluginProvider(PluginProvider *pp) {
 	_providers.push_back(pp);
 }
 
-const Plugin *PluginManager::getEngineFromMetaEngine(const Plugin *plugin) {
+const Plugin *PluginManager::getEngineFromDetectionPlugin(const Plugin *plugin) {
 	assert(plugin->getType() == PLUGIN_TYPE_ENGINE_DETECTION);
 
 	const Plugin *enginePlugin = nullptr;
diff --git a/base/plugins.h b/base/plugins.h
index 823ab10828f..416457b4584 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -319,16 +319,16 @@ public:
 	const Plugin *getMetaEngineFromEngine(const Plugin *plugin);
 
 	/**
-	 * A method which takes in a plugin of type METAENGINE,
-	 * and returns the appropriate & matching ENGINE.
-	 * It uses the MetaEngine's getEngineID to reconstruct the name
+	 * A method which takes in a plugin of type ENGINE_DETECTION,
+	 * and returns the appropriate & matching ENGINE plugin.
+	 * It uses the MetaEngineDetection's getEngineID to reconstruct the name
 	 * of engine plugin, and then tries to matches it with each plugin in memory.
 	 *
-	 * @param A plugin of type METAENGINE.
+	 * @param A plugin of type ENGINE_DETECTION.
 	 *
 	 * @return A plugin of type ENGINE.
 	 */
-	const Plugin *getEngineFromMetaEngine(const Plugin *plugin);
+	const Plugin *getEngineFromDetectionPlugin(const Plugin *plugin);
 
 	// Functions used by the uncached PluginManager
 	virtual void init()	{}
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 4ec7c229925..f4c9963227b 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -251,12 +251,12 @@ ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		}
 	}
 
-	const Plugin *metaEnginePlugin = EngineMan.findDetectionPlugin(getName());
-	if (!metaEnginePlugin) {
+	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(getName());
+	if (!detectionPlugin) {
 		return ADDetectedGame();
 	}
 
-	const Plugin *enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
+	const Plugin *enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 	if (!enginePlugin) {
 		static bool warn = true;
 		if (warn) {
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index cbdf4e98a48..18b2a41858d 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -95,10 +95,10 @@ public:
 			}
 		}
 
-		const Plugin *metaEnginePlugin = EngineMan.findDetectionPlugin(getName());
+		const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(getName());
 
-		if (metaEnginePlugin) {
-			const Plugin *enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
+		if (detectionPlugin) {
+			const Plugin *enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 			if (enginePlugin) {
 				return enginePlugin->get<AdvancedMetaEngineBase>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
 			} else {
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index 7c4c84a3dc4..79b84e535d8 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -763,7 +763,7 @@ SDL_Surface *EventRecorder::getSurface(int width, int height) {
 
 bool EventRecorder::switchMode() {
 	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
-	const Plugin *plugin = PluginMan.getEngineFromMetaEngine(detectionPlugin);
+	const Plugin *plugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 	bool metaInfoSupport = plugin->get<MetaEngine>().hasFeature(MetaEngine::kSavesSupportMetaInfo);
 	bool featuresSupport = metaInfoSupport &&
 						  g_engine->canSaveGameStateCurrently() &&
@@ -812,7 +812,7 @@ bool EventRecorder::checkForContinueGame() {
 void EventRecorder::deleteTemporarySave() {
 	if (_temporarySlot == -1) return;
 	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
-	const Plugin *plugin = PluginMan.getEngineFromMetaEngine(detectionPlugin);
+	const Plugin *plugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 	const Common::String target = ConfMan.getActiveDomainName();
 	 plugin->get<MetaEngine>().removeSaveState(target.c_str(), _temporarySlot);
 	_temporarySlot = -1;
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index 5be989b6c5a..c0aef1a112c 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -101,13 +101,13 @@ EditGameDialog::EditGameDialog(const Common::String &domain)
 
 	// Retrieve the plugin, since we need to access the engine's MetaEngine
 	// implementation.
-	const Plugin *metaEnginePlugin = nullptr;
+	const Plugin *detectionPlugin = nullptr;
 	const Plugin *enginePlugin = nullptr;
-	QualifiedGameDescriptor qgd = EngineMan.findTarget(domain, &metaEnginePlugin);
-	if (!metaEnginePlugin) {
+	QualifiedGameDescriptor qgd = EngineMan.findTarget(domain, &detectionPlugin);
+	if (!detectionPlugin) {
 		warning("MetaEnginePlugin for target \"%s\" not found!", domain.c_str());
 	} else {
-		enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
+		enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 		if (!enginePlugin) {
 			warning("Engine Plugin for target \"%s\" not found! Game specific settings might be missing.", domain.c_str());
 		}
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index a64f7734cd8..f91d0b7a166 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -533,13 +533,13 @@ void LauncherDialog::loadGame(int item) {
 	EngineMan.upgradeTargetIfNecessary(target);
 
 	// Look for the plugin
-	const Plugin *metaEnginePlugin = nullptr;
+	const Plugin *detectionPlugin = nullptr;
 	const Plugin *enginePlugin = nullptr;
-	EngineMan.findTarget(target, &metaEnginePlugin);
+	EngineMan.findTarget(target, &detectionPlugin);
 
 	// If we found a relevant plugin, find the matching engine plugin.
-	if (metaEnginePlugin) {
-		enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
+	if (detectionPlugin) {
+		enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
 	}
 
 	if (enginePlugin) {
diff --git a/gui/options.cpp b/gui/options.cpp
index 6d7b6ad3bf2..0edd584780f 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2871,7 +2871,7 @@ bool GlobalOptionsDialog::updateAutosavePeriod(int newValue) {
 		// and haven't been run since it was introduced.
 		const Common::String engine = domain.getValOrDefault("engineid");
 		if (const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(engine)) {
-			if (const Plugin *plugin = PluginMan.getEngineFromMetaEngine(detectionPlugin)) {
+			if (const Plugin *plugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin)) {
 				MetaEngine &metaEngine = plugin->get<MetaEngine>();
 				const int autoSaveSlot = metaEngine.getAutosaveSlot();
 				if (autoSaveSlot < 0)


Commit: ebdcf6ccd66ec8349932a0e4eb34b72c1b9bc85c
    https://github.com/scummvm/scummvm/commit/ebdcf6ccd66ec8349932a0e4eb34b72c1b9bc85c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Mark getName() functions as overrides

They do override PluginObject::getName().
This is more readable that calling this method is the same as calling it
on PluginObject.

Changed paths:
    engines/metaengine.h


diff --git a/engines/metaengine.h b/engines/metaengine.h
index a686e1de810..f498e87f540 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -128,7 +128,7 @@ public:
 	virtual ~MetaEngineDetection() {}
 
 	/** Get the engine ID. */
-	virtual const char *getName() const = 0;
+	virtual const char *getName() const override = 0;
 
 	/** Get the engine name. */
 	virtual const char *getEngineName() const = 0;
@@ -235,7 +235,7 @@ public:
 	 * engineID of "scumm". ScummMetaEngine inherits MetaEngine and provides the name
 	 * "Scumm". This way, an Engine can be easily matched with a MetaEngine.
 	 */
-	virtual const char *getName() const = 0;
+	virtual const char *getName() const override = 0;
 
 	/**
 	 * Instantiate an engine instance based on the settings of


Commit: c9d701884ba6b3649bd5fa3bed9d529eeaddbc92
    https://github.com/scummvm/scummvm/commit/c9d701884ba6b3649bd5fa3bed9d529eeaddbc92
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Reset pointer after deletion

This avoids error on double unload.

Changed paths:
    backends/plugins/dynamic-plugin.h


diff --git a/backends/plugins/dynamic-plugin.h b/backends/plugins/dynamic-plugin.h
index 66e70ec8bc3..c40e4460c85 100644
--- a/backends/plugins/dynamic-plugin.h
+++ b/backends/plugins/dynamic-plugin.h
@@ -98,6 +98,7 @@ public:
 
 	virtual void unloadPlugin() {
 		delete _pluginObject;
+		_pluginObject = nullptr;
 	}
 
 	virtual Common::Path getFileName() const override {


Commit: 93b10df84a86f745ca6c2d490815913c777e02a5
    https://github.com/scummvm/scummvm/commit/93b10df84a86f745ca6c2d490815913c777e02a5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Rework (un)loading of detection plugin

Make the function more readable and avoid leaking memory when plugin is
loaded twice.

Changed paths:
    base/plugins.cpp


diff --git a/base/plugins.cpp b/base/plugins.cpp
index 8535858f9b5..2b575f51f18 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -338,8 +338,6 @@ const Plugin *PluginManager::getMetaEngineFromEngine(const Plugin *plugin) {
  * This should only be called once by main()
  **/
 void PluginManagerUncached::init() {
-	unloadAllPlugins();
-	_allEnginePlugins.clear();
 	ConfMan.setBool("always_run_fallback_detection_extern", false);
 
 	unloadPluginsExcept(PLUGIN_TYPE_ENGINE, nullptr, false); // empty the engine plugins
@@ -463,45 +461,40 @@ void PluginManagerUncached::updateConfigWithFileName(const Common::String &engin
 
 #ifndef DETECTION_STATIC
 void PluginManagerUncached::loadDetectionPlugin() {
-	bool linkMetaEngines = false;
-
 	if (_isDetectionLoaded) {
 		debug(9, "Detection plugin is already loaded. Adding each available engines to the memory.");
-		linkMetaEngines = true;
-	} else {
-		if (_detectionPlugin) {
-			if (_detectionPlugin->loadPlugin()) {
-				assert((_detectionPlugin)->getType() == PLUGIN_TYPE_DETECTION);
+		return;
+	}
 
-				linkMetaEngines = true;
-				_isDetectionLoaded = true;
-			} else {
-				debug(9, "Detection plugin was not loaded correctly.");
-				return;
-			}
-		} else {
-			debug(9, "Detection plugin not found.");
-			return;
-		}
+	if (!_detectionPlugin) {
+		debug(9, "Detection plugin not found.");
+		return;
 	}
 
-	if (linkMetaEngines) {
-		_pluginsInMem[PLUGIN_TYPE_ENGINE_DETECTION].clear();
-		const Detection &detectionConnect = _detectionPlugin->get<Detection>();
-		const PluginList &pl = detectionConnect.getPlugins();
-		Common::for_each(pl.begin(), pl.end(), Common::bind1st(Common::mem_fun(&PluginManagerUncached::tryLoadPlugin), this));
+	if (!_detectionPlugin->loadPlugin()) {
+		debug(9, "Detection plugin was not loaded correctly.");
+		return;
 	}
 
+	assert((_detectionPlugin)->getType() == PLUGIN_TYPE_DETECTION);
+
+	_pluginsInMem[PLUGIN_TYPE_ENGINE_DETECTION].clear();
+	const Detection &detectionConnect = _detectionPlugin->get<Detection>();
+	const PluginList &pl = detectionConnect.getPlugins();
+	Common::for_each(pl.begin(), pl.end(), Common::bind1st(Common::mem_fun(&PluginManagerUncached::tryLoadPlugin), this));
+
+	_isDetectionLoaded = true;
 }
 
 void PluginManagerUncached::unloadDetectionPlugin() {
-	if (_isDetectionLoaded) {
-		_pluginsInMem[PLUGIN_TYPE_ENGINE_DETECTION].clear();
-		_detectionPlugin->unloadPlugin();
-		_isDetectionLoaded = false;
-	} else {
+	if (!_isDetectionLoaded) {
 		debug(9, "Detection plugin is already unloaded.");
+		return;
 	}
+
+	unloadPluginsExcept(PLUGIN_TYPE_ENGINE_DETECTION, nullptr, true);
+	_detectionPlugin->unloadPlugin();
+	_isDetectionLoaded = false;
 }
 #endif
 


Commit: 2575cdacffa63b041d7070cfb3b1c764db1cfe54
    https://github.com/scummvm/scummvm/commit/2575cdacffa63b041d7070cfb3b1c764db1cfe54
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Cleanup when destroying PluginManagerUncached

This removes memory leaks when destroying the manager.

Changed paths:
    base/plugins.cpp
    base/plugins.h


diff --git a/base/plugins.cpp b/base/plugins.cpp
index 2b575f51f18..0127ea8e544 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -334,6 +334,19 @@ const Plugin *PluginManager::getMetaEngineFromEngine(const Plugin *plugin) {
 	return nullptr;
 }
 
+PluginManagerUncached::~PluginManagerUncached() {
+	// Unload from memory all engine plugins without deleting them
+	// They are also referenced from _allEnginePlugins which we clean up here
+	unloadPluginsExcept(PLUGIN_TYPE_ENGINE, nullptr, false);
+
+	for (PluginList::iterator p = _allEnginePlugins.begin(); p != _allEnginePlugins.end(); ++p) {
+		delete *p;
+	}
+	_allEnginePlugins.clear();
+
+	delete _detectionPlugin;
+}
+
 /**
  * This should only be called once by main()
  **/
diff --git a/base/plugins.h b/base/plugins.h
index 416457b4584..bb230351e0d 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -366,6 +366,7 @@ protected:
 	bool loadPluginByFileName(const Common::Path &filename);
 
 public:
+	virtual ~PluginManagerUncached();
 	void init() override;
 	void loadFirstPlugin() override;
 	bool loadNextPlugin() override;


Commit: 55ac8ba07f9a955938b85b9548c852862e4c7317
    https://github.com/scummvm/scummvm/commit/55ac8ba07f9a955938b85b9548c852862e4c7317
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Remove default value for EngineMan::getPlugins argument

This is now obvious of which type is the list of plugins returned.

Changed paths:
    base/commandLine.cpp
    base/plugins.cpp
    engines/metaengine.h


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 6682742cd68..17f9a3dfc36 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1053,7 +1053,7 @@ static void listAllGames(const Common::String &engineID) {
 	printf("Game ID                        Full Title                                                 \n"
 	       "------------------------------ -----------------------------------------------------------\n");
 
-	const PluginList &plugins = EngineMan.getPlugins();
+	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 		const MetaEngineDetection &metaEngine = (*iter)->get<MetaEngineDetection>();
 
@@ -1088,7 +1088,7 @@ static void listAllEngines() {
 	printf("Engine ID       Engine Name                                           \n"
 	       "--------------- ------------------------------------------------------\n");
 
-	const PluginList &plugins = EngineMan.getPlugins();
+	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 		const MetaEngineDetection &metaEngine = (*iter)->get<MetaEngineDetection>();
 		printf("%-15s %s\n", metaEngine.getName(), metaEngine.getEngineName());
@@ -1178,7 +1178,7 @@ static void printStatistics(const Common::String &engineID) {
 
 	bool approximation = false;
 	int engineCount = 0, gameCount = 0, variantCount = 0;
-	const PluginList &plugins = EngineMan.getPlugins();
+	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 		const MetaEngineDetection &metaEngine = (*iter)->get<MetaEngineDetection>();
 		if (summary || all || Common::find(engines.begin(), engines.end(), metaEngine.getName()) != engines.end()) {
@@ -1226,7 +1226,7 @@ static void listDebugFlags(const Common::String &engineID) {
 	if (engineID == "global")
 		printDebugFlags(gDebugChannels);
 	else {
-		const PluginList &plugins = EngineMan.getPlugins();
+		const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 		for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 			const MetaEngineDetection &metaEngine = (*iter)->get<MetaEngineDetection>();
 			if (metaEngine.getName() == engineID) {
@@ -1245,7 +1245,7 @@ static void listDebugFlags(const Common::String &engineID) {
 static void listAllEngineDebugFlags() {
 	printf("Flag name       Flag description                                           \n");
 
-	const PluginList &plugins = EngineMan.getPlugins();
+	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 		const MetaEngineDetection &metaEngine = (*iter)->get<MetaEngineDetection>();
 		printf("--------------- ------------------------------------------------------\n");
@@ -1451,7 +1451,7 @@ static void listAudioDevices() {
 
 /** Dump MD5s from detection entries into STDOUT */
 static void dumpAllDetectionEntries() {
-	const PluginList &plugins = EngineMan.getPlugins();
+	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 
 	printf("scummvm (\n");
 	printf("\tauthor \"scummvm\"\n");
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 0127ea8e544..7c90a2afaa5 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -704,7 +704,7 @@ QualifiedGameList EngineManager::findGamesMatching(const Common::String &engineI
  **/
 QualifiedGameList EngineManager::findGameInLoadedPlugins(const Common::String &gameId) const {
 	// Find the GameDescriptor for this target
-	const PluginList &plugins = getPlugins();
+	const PluginList &plugins = getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 
 	QualifiedGameList results;
 	PluginList::const_iterator iter;
@@ -819,7 +819,7 @@ Common::String EngineManager::createTargetForGame(const DetectedGame &game) {
 }
 
 const Plugin *EngineManager::findDetectionPlugin(const Common::String &engineId) const {
-	const PluginList &plugins = getPlugins();
+	const PluginList &plugins = getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
 
 	for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); iter++)
 		if (engineId == (*iter)->get<MetaEngineDetection>().getName())
diff --git a/engines/metaengine.h b/engines/metaengine.h
index f498e87f540..a9266a93ebb 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -600,12 +600,8 @@ public:
 
 	/**
 	 * Get the list of all plugins for the type specified.
-	 *
-	 * By default, it will get METAENGINES, for now.
-	 * If usage of actual engines never occurs, the default arguments can be skipped,
-	 * and always have it return PLUGIN_TYPE_ENGINE_DETECTION.
 	 */
-	const PluginList &getPlugins(const PluginType fetchPluginType = PLUGIN_TYPE_ENGINE_DETECTION) const;
+	const PluginList &getPlugins(const PluginType fetchPluginType) const;
 
 	/** Find a target. */
 	QualifiedGameDescriptor findTarget(const Common::String &target, const Plugin **plugin = NULL) const;


Commit: 05a62249a96ce6830d2f5dffffc6ad6d2e610c55
    https://github.com/scummvm/scummvm/commit/05a62249a96ce6830d2f5dffffc6ad6d2e610c55
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: hide unloadAllPlugins from outside of PluginManager

This function will delete all plugins even those also stored in
_allEnginePlugins list which triggers a double free when cleaning up.

Changed paths:
    backends/platform/libretro/src/libretro-os-utils.cpp
    base/main.cpp
    base/plugins.h


diff --git a/backends/platform/libretro/src/libretro-os-utils.cpp b/backends/platform/libretro/src/libretro-os-utils.cpp
index 4302dff0105..ebfa40996b9 100644
--- a/backends/platform/libretro/src/libretro-os-utils.cpp
+++ b/backends/platform/libretro/src/libretro-os-utils.cpp
@@ -150,8 +150,6 @@ int OSystem_libretro::testGame(const char *filedata, bool autodetect) {
 		}
 	}
 
-	PluginManager::instance().unloadDetectionPlugin();
-	PluginManager::instance().unloadAllPlugins();
 	PluginManager::destroy();
 	return res;
 }
diff --git a/base/main.cpp b/base/main.cpp
index 5a498bafe06..36158a60054 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -519,8 +519,6 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 		if (res.getCode() != Common::kNoError)
 			warning("%s", res.getDesc().c_str());
 
-		PluginManager::instance().unloadDetectionPlugin();
-		PluginManager::instance().unloadAllPlugins();
 		PluginManager::destroy();
 
 		return res.getCode();
@@ -892,8 +890,6 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 	Cloud::CloudManager::destroy();
 #endif
 #endif
-	PluginManager::instance().unloadDetectionPlugin();
-	PluginManager::instance().unloadAllPlugins();
 	PluginManager::destroy();
 	GUI::GuiManager::destroy();
 	Common::ConfigManager::destroy();
diff --git a/base/plugins.h b/base/plugins.h
index bb230351e0d..8d6d90bec49 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -298,6 +298,7 @@ protected:
 	static PluginManager *_instance;
 	PluginManager();
 
+	void unloadAllPlugins();
 public:
 	virtual ~PluginManager();
 
@@ -342,7 +343,6 @@ public:
 	// Functions used only by the cached PluginManager
 	virtual void loadAllPlugins();
 	virtual void loadAllPluginsOfType(PluginType type);
-	void unloadAllPlugins();
 
 	void unloadPluginsExcept(PluginType type, const Plugin *plugin, bool deletePlugin = true);
 


Commit: a1193a02eb7f64bea5d3ce223a3b765d93f5ea3b
    https://github.com/scummvm/scummvm/commit/a1193a02eb7f64bea5d3ce223a3b765d93f5ea3b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Make findEnginePlugin publicly available

This will allow to remove getEngineFromDetectionPlugin which needs both
plugins loaded at the same time.

Changed paths:
    base/plugins.h


diff --git a/base/plugins.h b/base/plugins.h
index 8d6d90bec49..48ab1114d4a 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -292,7 +292,6 @@ protected:
 
 	bool tryLoadPlugin(Plugin *plugin);
 	void addToPluginsInMemList(Plugin *plugin);
-	const Plugin *findEnginePlugin(const Common::String &engineId);
 	const Plugin *findLoadedPlugin(const Common::String &engineId);
 
 	static PluginManager *_instance;
@@ -307,6 +306,15 @@ public:
 
 	void addPluginProvider(PluginProvider *pp);
 
+	/**
+	 * A method which finds the METAENGINE plugin for the provided engineId
+	 *
+	 * @param engineId The engine ID
+	 *
+	 * @return A plugin of type METAENGINE.
+	 */
+	const Plugin *findEnginePlugin(const Common::String &engineId);
+
 	/**
 	 * A method which takes in a plugin of type ENGINE,
 	 * and returns the appropriate & matching METAENGINE.


Commit: 885208e8f251d3f8625093196deb05a8c32174be
    https://github.com/scummvm/scummvm/commit/885208e8f251d3f8625093196deb05a8c32174be
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
BASE: Split listSaves in two parts

First get all the games using the detection plugins.
Then, list all the saves by loading all engines.

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 17f9a3dfc36..081ec3159f3 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1330,6 +1330,12 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 
 	Common::String oldDomain = ConfMan.getActiveDomainName();
 
+	struct GameTarget {
+		Common::String target;
+		QualifiedGameDescriptor game;
+	};
+	Common::Array<GameTarget> gameTargets;
+
 	bool atLeastOneFound = false;
 	for (Common::Array<Common::String>::const_iterator i = targets.begin(), end = targets.end(); i != end; ++i) {
 		// Check whether there is either a game domain (i.e. a target) matching
@@ -1337,65 +1343,66 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 		Common::String currentTarget;
 		QualifiedGameDescriptor game;
 
-		const Plugin *detectionPlugin = nullptr;
-		const Plugin *enginePlugin = nullptr;
-
 		if (ConfMan.hasGameDomain(*i)) {
 			// The name is a known target
 			currentTarget = *i;
 			EngineMan.upgradeTargetIfNecessary(*i);
-			game = EngineMan.findTarget(*i, &detectionPlugin);
+			game = EngineMan.findTarget(*i);
 		} else if (game = findGameMatchingName(*i), !game.gameId.empty()) {
 			// The name is a known game id
-			detectionPlugin = EngineMan.findDetectionPlugin(game.engineId);
 			currentTarget = createTemporaryTarget(game.engineId, game.gameId);
 		} else {
 			return Common::Error(Common::kEnginePluginNotFound, Common::String::format("target '%s'", singleTarget.c_str()));
 		}
+		gameTargets.push_back({currentTarget, game});
+	}
+
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
+	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
+	PluginMan.unloadDetectionPlugin();
+#endif
+
+	for (Common::Array<GameTarget>::const_iterator i = gameTargets.begin(), end = gameTargets.end(); i != end; ++i) {
+		const Plugin *enginePlugin = nullptr;
 
 		// If we actually found a domain, we're going to change the domain
-		ConfMan.setActiveDomain(currentTarget);
+		ConfMan.setActiveDomain(i->target);
+
+		enginePlugin = PluginMan.findEnginePlugin(i->game.engineId);
 
-		if (!detectionPlugin) {
+		if (!enginePlugin) {
 			// If the target was specified, treat this as an error, and otherwise skip it.
-			if (!singleTarget.empty())
-				return Common::Error(Common::kMetaEnginePluginNotFound,
-				                     Common::String::format("target '%s'", i->c_str()));
-			printf("MetaEnginePlugin could not be loaded for target '%s'\n", i->c_str());
-			continue;
-		} else {
-			enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
-
-			if (!enginePlugin) {
-				// If the target was specified, treat this as an error, and otherwise skip it.
-				if (!singleTarget.empty())
-					return Common::Error(Common::kEnginePluginNotFound,
-				                     	 Common::String::format("target '%s'", i->c_str()));
-				printf("EnginePlugin could not be loaded for target '%s'\n", i->c_str());
-				continue;
+			if (!singleTarget.empty()) {
+				result = Common::Error(Common::kEnginePluginNotFound,
+						 Common::String::format("target '%s'", i->target.c_str()));
+				break;
 			}
+			printf("EnginePlugin could not be loaded for target '%s'\n", i->target.c_str());
+			continue;
 		}
 
 		const MetaEngine &metaEngine = enginePlugin->get<MetaEngine>();
-		Common::String qualifiedGameId = buildQualifiedGameName(game.engineId, game.gameId);
+		Common::String qualifiedGameId = buildQualifiedGameName(i->game.engineId, i->game.gameId);
 
 		if (!metaEngine.hasFeature(MetaEngine::kSupportsListSaves)) {
 			// If the target was specified, treat this as an error, and otherwise skip it.
-			if (!singleTarget.empty())
+			if (!singleTarget.empty()) {
 				// TODO: Include more info about the target (desc, engine name, ...) ???
-				return Common::Error(Common::kEnginePluginNotSupportSaves,
-				                     Common::String::format("target '%s', gameid '%s'", i->c_str(), qualifiedGameId.c_str()));
+				result = Common::Error(Common::kEnginePluginNotSupportSaves,
+				                     Common::String::format("target '%s', gameid '%s'", i->target.c_str(), qualifiedGameId.c_str()));
+				break;
+			}
 			continue;
 		}
 
 		// Query the plugin for a list of saved games
-		SaveStateList saveList = metaEngine.listSaves(i->c_str());
+		SaveStateList saveList = metaEngine.listSaves(i->target.c_str());
 
 		if (!saveList.empty()) {
 			// TODO: Include more info about the target (desc, engine name, ...) ???
 			if (atLeastOneFound)
 				printf("\n");
-			printf("Save states for target '%s' (gameid '%s'):\n", i->c_str(), qualifiedGameId.c_str());
+			printf("Save states for target '%s' (gameid '%s'):\n", i->target.c_str(), qualifiedGameId.c_str());
 			printf("  Slot Description                                           \n"
 					   "  ---- ------------------------------------------------------\n");
 
@@ -1407,16 +1414,18 @@ static Common::Error listSaves(const Common::String &singleTarget) {
 		} else {
 			// If the target was specified, indicate no save games were found for it. Otherwise just skip it.
 			if (!singleTarget.empty())
-				printf("There are no save states for target '%s' (gameid '%s'):\n", i->c_str(), qualifiedGameId.c_str());
+				printf("There are no save states for target '%s' (gameid '%s'):\n", i->target.c_str(), qualifiedGameId.c_str());
 		}
 	}
 
 	// Revert to the old active domain
 	ConfMan.setActiveDomain(oldDomain);
 
-	if (!atLeastOneFound && singleTarget.empty())
+	if (!atLeastOneFound && singleTarget.empty() && result.getCode() == Common::kNoError)
 		printf("No save states could be found.\n");
 
+	PluginMan.loadDetectionPlugin(); // only for uncached manager
+
 	return result;
 }
 


Commit: d01827b5095024b1aaf9fe690ade9e75bbca625c
    https://github.com/scummvm/scummvm/commit/d01827b5095024b1aaf9fe690ade9e75bbca625c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Make auto saves update check work with PluginManagerUncached

This also unloads detection before loading the engines.

Changed paths:
    gui/options.cpp


diff --git a/gui/options.cpp b/gui/options.cpp
index 0edd584780f..1ae2bd3edcd 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2843,12 +2843,12 @@ void GlobalOptionsDialog::addAccessibilityControls(GuiObject *boss, const Common
 #endif // USE_TTS
 
 struct ExistingSave {
-	MetaEngine *metaEngine;
+	Common::String engine;
 	Common::String target;
 	SaveStateDescriptor desc;
 
-	ExistingSave(MetaEngine *_metaEngine, const Common::String &_target, const SaveStateDescriptor &_desc) :
-		metaEngine(_metaEngine),
+	ExistingSave(const Common::String &_engine, const Common::String &_target, const SaveStateDescriptor &_desc) :
+		engine(_engine),
 		target(_target),
 		desc(_desc)
 	{}
@@ -2864,26 +2864,33 @@ bool GlobalOptionsDialog::updateAutosavePeriod(int newValue) {
 	const int maxListSize = 10;
 	bool hasMore = false;
 	const ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
+
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
+	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
+	PluginMan.unloadDetectionPlugin();
+#endif
+
 	for (ConfigManager::DomainMap::const_iterator it = domains.begin(), end = domains.end(); it != end; ++it) {
 		const Common::String target = it->_key;
 		const ConfigManager::Domain domain = it->_value;
 		// note that engineid isn't present on games that predate it
 		// and haven't been run since it was introduced.
 		const Common::String engine = domain.getValOrDefault("engineid");
-		if (const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(engine)) {
-			if (const Plugin *plugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin)) {
-				MetaEngine &metaEngine = plugin->get<MetaEngine>();
-				const int autoSaveSlot = metaEngine.getAutosaveSlot();
-				if (autoSaveSlot < 0)
-					continue;
-				SaveStateDescriptor desc = metaEngine.querySaveMetaInfos(target.c_str(), autoSaveSlot);
-				if (desc.getSaveSlot() != -1 && !desc.getDescription().empty() && !desc.isAutosave()) {
-					if (saveList.size() >= maxListSize) {
-						hasMore = true;
-						break;
-					}
-					saveList.push_back(ExistingSave(&metaEngine, target, desc));
+		if (engine.empty()) {
+			continue;
+		}
+		if (const Plugin *plugin = PluginMan.findEnginePlugin(engine)) {
+			MetaEngine &metaEngine = plugin->get<MetaEngine>();
+			const int autoSaveSlot = metaEngine.getAutosaveSlot();
+			if (autoSaveSlot < 0)
+				continue;
+			SaveStateDescriptor desc = metaEngine.querySaveMetaInfos(target.c_str(), autoSaveSlot);
+			if (desc.getSaveSlot() != -1 && !desc.getDescription().empty() && !desc.isAutosave()) {
+				if (saveList.size() >= maxListSize) {
+					hasMore = true;
+					break;
 				}
+				saveList.push_back(ExistingSave(engine, target, desc));
 			}
 		}
 	}
@@ -2906,9 +2913,15 @@ bool GlobalOptionsDialog::updateAutosavePeriod(int newValue) {
 		case GUI::kMessageOK: {
 			ExistingSaveList failedSaves;
 			for (ExistingSaveList::const_iterator it = saveList.begin(), end = saveList.end(); it != end; ++it) {
-				if (it->metaEngine->copySaveFileToFreeSlot(it->target.c_str(), it->desc.getSaveSlot())) {
+				const Plugin *plugin = PluginMan.findEnginePlugin(it->engine);
+				if (!plugin) {
+					failedSaves.push_back(*it);
+					continue;
+				}
+				MetaEngine &metaEngine = plugin->get<MetaEngine>();
+				if (metaEngine.copySaveFileToFreeSlot(it->target.c_str(), it->desc.getSaveSlot())) {
 					g_system->getSavefileManager()->removeSavefile(
-							it->metaEngine->getSavegameFile(it->desc.getSaveSlot(), it->target.c_str()));
+							metaEngine.getSavegameFile(it->desc.getSaveSlot(), it->target.c_str()));
 				} else {
 					failedSaves.push_back(*it);
 				}
@@ -2925,9 +2938,11 @@ bool GlobalOptionsDialog::updateAutosavePeriod(int newValue) {
 		case GUI::kMessageAlt:
 			break;
 		case GUI::kMessageAlt + 1:
+			PluginMan.loadDetectionPlugin(); // only for uncached manager
 			return false;
 		}
 	}
+	PluginMan.loadDetectionPlugin(); // only for uncached manager
 	return true;
 }
 


Commit: 1c1667bf688da453fd3b6ed858a55420a47d1080
    https://github.com/scummvm/scummvm/commit/1c1667bf688da453fd3b6ed858a55420a47d1080
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Fix listing of available engines when using uncached plugins

Also avoids loading detection while iterating over engines

Changed paths:
    gui/about.cpp


diff --git a/gui/about.cpp b/gui/about.cpp
index f3d505fe5b3..bab9980cc2e 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -155,15 +155,28 @@ AboutDialog::AboutDialog()
 	engines += _("Available engines:");
 	addLine(engines);
 
-	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
-	PluginList::const_iterator iter = plugins.begin();
-	for (; iter != plugins.end(); ++iter) {
+	Common::StringArray enginesDetected;
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
+	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
+	PluginMan.unloadDetectionPlugin();
+#endif
+	PluginMan.loadFirstPlugin();
+	do {
+		const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
+		for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
+			enginesDetected.push_back((*iter)->getName());
+		}
+	} while (PluginMan.loadNextPlugin());
+
+	PluginMan.loadDetectionPlugin();
+
+	for (Common::StringArray::iterator iter = enginesDetected.begin(); iter != enginesDetected.end(); iter++) {
 		Common::String str;
 
-		const Plugin *p = EngineMan.findDetectionPlugin((*iter)->getName());
+		const Plugin *p = EngineMan.findDetectionPlugin(*iter);
 
 		if (!p) {
-			warning("Cannot find plugin for %s", (*iter)->getName());
+			warning("Cannot find plugin for %s", iter->c_str());
 			continue;
 		}
 


Commit: 16e72ad1812d01509fe35e70a6d4b39d3819f2cb
    https://github.com/scummvm/scummvm/commit/16e72ad1812d01509fe35e70a6d4b39d3819f2cb
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Make listing saves not depend on detection

And unload detection before loading engine.

Changed paths:
    gui/launcher.cpp


diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index f91d0b7a166..04458ba9309 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -533,15 +533,15 @@ void LauncherDialog::loadGame(int item) {
 	EngineMan.upgradeTargetIfNecessary(target);
 
 	// Look for the plugin
-	const Plugin *detectionPlugin = nullptr;
 	const Plugin *enginePlugin = nullptr;
-	EngineMan.findTarget(target, &detectionPlugin);
+	QualifiedGameDescriptor game = EngineMan.findTarget(target);
 
-	// If we found a relevant plugin, find the matching engine plugin.
-	if (detectionPlugin) {
-		enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
-	}
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
+	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
+	PluginMan.unloadDetectionPlugin();
+#endif
 
+	enginePlugin = PluginMan.findEnginePlugin(game.engineId);
 	if (enginePlugin) {
 		assert(enginePlugin->getType() == PLUGIN_TYPE_ENGINE);
 		const MetaEngine &metaEngine = enginePlugin->get<MetaEngine>();
@@ -562,6 +562,8 @@ void LauncherDialog::loadGame(int item) {
 		MessageDialog dialog(_("ScummVM could not find any engine capable of running the selected game!"), _("OK"));
 		dialog.runModal();
 	}
+
+	PluginMan.loadDetectionPlugin(); // only for uncached manager
 }
 
 Common::Array<LauncherEntry> LauncherDialog::generateEntries(const Common::ConfigManager::DomainMap &domains) {


Commit: a8358036956f6f6bde646ba886bd82641fb28559
    https://github.com/scummvm/scummvm/commit/a8358036956f6f6bde646ba886bd82641fb28559
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Make engine options not depend on detection plugin

Load back detection plugin when closing and make sure nothing needs
engine plugin anymore before.

Changed paths:
    gui/editgamedialog.cpp
    gui/editgamedialog.h


diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index c0aef1a112c..0b723383474 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -101,16 +101,17 @@ EditGameDialog::EditGameDialog(const Common::String &domain)
 
 	// Retrieve the plugin, since we need to access the engine's MetaEngine
 	// implementation.
-	const Plugin *detectionPlugin = nullptr;
 	const Plugin *enginePlugin = nullptr;
-	QualifiedGameDescriptor qgd = EngineMan.findTarget(domain, &detectionPlugin);
-	if (!detectionPlugin) {
-		warning("MetaEnginePlugin for target \"%s\" not found!", domain.c_str());
-	} else {
-		enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
-		if (!enginePlugin) {
-			warning("Engine Plugin for target \"%s\" not found! Game specific settings might be missing.", domain.c_str());
-		}
+	QualifiedGameDescriptor qgd = EngineMan.findTarget(domain);
+
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
+	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
+	PluginMan.unloadDetectionPlugin();
+#endif
+
+	enginePlugin = PluginMan.findEnginePlugin(qgd.engineId);
+	if (!enginePlugin) {
+		warning("Engine Plugin for target \"%s\" not found! Game specific settings might be missing.", domain.c_str());
 	}
 
 	// GAME: Path to game data (r/o), extra data (r/o), and save data (r/w)
@@ -470,6 +471,20 @@ void EditGameDialog::open() {
 	_platformPopUp->setSelected(sel);
 }
 
+void EditGameDialog::close() {
+	OptionsDialog::close();
+
+	// Cleanup engine widgets before unloading its plugin
+	if (_engineOptions) {
+		// Switch back to Game tab before deleting the widget
+		_tabWidget->setActiveTab(0);
+		_tabWidget->removeWidget(_engineOptions);
+		delete _engineOptions;
+	}
+
+	PluginMan.loadDetectionPlugin(); // only for uncached manager
+}
+
 void EditGameDialog::apply() {
 	ConfMan.set("description", _descriptionWidget->getEditString(), _domain);
 
diff --git a/gui/editgamedialog.h b/gui/editgamedialog.h
index b02142bfef6..0dc95c8a838 100644
--- a/gui/editgamedialog.h
+++ b/gui/editgamedialog.h
@@ -62,6 +62,7 @@ public:
 
 	void open() override;
 	void apply() override;
+	void close() override;
 	void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
 
 protected:


Commit: bef5e4e0a55644dc8ee6445893a9ce7c141ec3d0
    https://github.com/scummvm/scummvm/commit/bef5e4e0a55644dc8ee6445893a9ce7c141ec3d0
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Make EventRecorder not use detection to find engine plugin

This has not been tested though as the event manager seems broken on
these parts.

Changed paths:
    gui/EventRecorder.cpp


diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index 79b84e535d8..62940b45209 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -762,8 +762,7 @@ SDL_Surface *EventRecorder::getSurface(int width, int height) {
 }
 
 bool EventRecorder::switchMode() {
-	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
-	const Plugin *plugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
+	const Plugin *plugin = PluginMan.findEnginePlugin(ConfMan.get("engineid"));
 	bool metaInfoSupport = plugin->get<MetaEngine>().hasFeature(MetaEngine::kSavesSupportMetaInfo);
 	bool featuresSupport = metaInfoSupport &&
 						  g_engine->canSaveGameStateCurrently() &&
@@ -811,8 +810,7 @@ bool EventRecorder::checkForContinueGame() {
 
 void EventRecorder::deleteTemporarySave() {
 	if (_temporarySlot == -1) return;
-	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
-	const Plugin *plugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
+	const Plugin *plugin = PluginMan.findEnginePlugin(ConfMan.get("engineid"));
 	const Common::String target = ConfMan.getActiveDomainName();
 	 plugin->get<MetaEngine>().removeSaveState(target.c_str(), _temporarySlot);
 	_temporarySlot = -1;


Commit: 21bd468b9a380cde2409f88e75c33eb58cd56f30
    https://github.com/scummvm/scummvm/commit/21bd468b9a380cde2409f88e75c33eb58cd56f30
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
SCI: Simplify engine plugin search

Changed paths:
    engines/sci/detection.cpp


diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index f4c9963227b..8ff876fd1f2 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -251,12 +251,7 @@ ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		}
 	}
 
-	const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(getName());
-	if (!detectionPlugin) {
-		return ADDetectedGame();
-	}
-
-	const Plugin *enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
+	const Plugin *enginePlugin = PluginMan.findEnginePlugin(getName());
 	if (!enginePlugin) {
 		static bool warn = true;
 		if (warn) {


Commit: 310063af6c0b2ee08ffcf6bee9370a91c4c152e3
    https://github.com/scummvm/scummvm/commit/310063af6c0b2ee08ffcf6bee9370a91c4c152e3
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
WINTERMUTE: Simplify engine plugin search

Changed paths:
    engines/wintermute/detection.cpp


diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index 18b2a41858d..1c4342f2660 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -95,21 +95,16 @@ public:
 			}
 		}
 
-		const Plugin *detectionPlugin = EngineMan.findDetectionPlugin(getName());
-
-		if (detectionPlugin) {
-			const Plugin *enginePlugin = PluginMan.getEngineFromDetectionPlugin(detectionPlugin);
-			if (enginePlugin) {
-				return enginePlugin->get<AdvancedMetaEngineBase>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
-			} else {
-				static bool warn = true;
-				if (warn) {
-					warning("Engine plugin for Wintermute not present. Fallback detection is disabled.");
-					warn = false;
-				}
+		const Plugin *enginePlugin = PluginMan.findEnginePlugin(getName());
+		if (!enginePlugin) {
+			static bool warn = true;
+			if (warn) {
+				warning("Engine plugin for Wintermute not present. Fallback detection is disabled.");
+				warn = false;
 			}
+			return ADDetectedGame();
 		}
-		return ADDetectedGame();
+		return enginePlugin->get<AdvancedMetaEngineBase>().fallbackDetectExtern(_md5Bytes, allFiles, fslist);
 	}
 
 };


Commit: a92dab8a8c8d86f8c10417e9f59b9061b3c98db4
    https://github.com/scummvm/scummvm/commit/a92dab8a8c8d86f8c10417e9f59b9061b3c98db4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
BASE: Unload detection plugin before running game

Changed paths:
    base/main.cpp


diff --git a/base/main.cpp b/base/main.cpp
index 36158a60054..65e9cf34a2b 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -748,8 +748,14 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 		Common::Error result = identifyGame(specialDebug, &plugin, game, &meDescriptor);
 
 		if (result.getCode() == Common::kNoError) {
+			Common::String engineId = plugin->getName();
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
+			// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
+			PluginManager::instance().unloadDetectionPlugin();
+#endif
+
 			// Then, get the relevant Engine plugin from MetaEngine.
-			enginePlugin = PluginMan.getEngineFromDetectionPlugin(plugin);
+			enginePlugin = PluginMan.findEnginePlugin(engineId);
 			if (enginePlugin == nullptr) {
 				result = Common::kEnginePluginNotFound;
 			}
@@ -762,12 +768,6 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 			// Pass in the pointer to enginePlugin, with the matching type, so our function behaves as-is.
 			PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, enginePlugin);
 
-#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
-			// Unload all MetaEngines not needed for the current engine, if we're using uncached plugins
-			// to save extra memory.
-			PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE_DETECTION, plugin);
-#endif
-
 #ifdef ENABLE_EVENTRECORDER
 			Common::String recordMode = ConfMan.get("record_mode");
 			Common::String recordFileName = ConfMan.get("record_file_name");


Commit: 07daa6c225584c1c992b7a6907c194c76ff8cd08
    https://github.com/scummvm/scummvm/commit/07daa6c225584c1c992b7a6907c194c76ff8cd08
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Simplify EngineManager::findTarget

Do not make it return the detection plugin. It's never used anymore and
tends to imply that detection plugin can be used alongside the engine
plugin.

Changed paths:
    base/commandLine.cpp
    base/plugins.cpp
    engines/metaengine.h


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 081ec3159f3..f3fb5281181 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1290,8 +1290,7 @@ static Common::Error listRecords(const Common::String &singleTarget) {
 			// The name is a known target
 			currentTarget = *i;
 			EngineMan.upgradeTargetIfNecessary(*i);
-			const Plugin *metaEnginePlugin = nullptr;
-			game = EngineMan.findTarget(*i, &metaEnginePlugin);
+			game = EngineMan.findTarget(*i);
 		} else if (game = findGameMatchingName(*i), !game.gameId.empty()) {
 			currentTarget = createTemporaryTarget(game.engineId, game.gameId);
 		} else {
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 7c90a2afaa5..fc41cdd08ed 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -867,7 +867,7 @@ const Plugin *PluginManager::findEnginePlugin(const Common::String &engineId) {
 	return nullptr;
 }
 
-QualifiedGameDescriptor EngineManager::findTarget(const Common::String &target, const Plugin **plugin) const {
+QualifiedGameDescriptor EngineManager::findTarget(const Common::String &target) const {
 	// Ignore empty targets
 	if (target.empty())
 		return QualifiedGameDescriptor();
@@ -891,9 +891,6 @@ QualifiedGameDescriptor EngineManager::findTarget(const Common::String &target,
 		return QualifiedGameDescriptor();
 	}
 
-	if (plugin)
-		*plugin = foundPlugin;
-
 	return QualifiedGameDescriptor(engine.getName(), desc);
 }
 
diff --git a/engines/metaengine.h b/engines/metaengine.h
index a9266a93ebb..ec2e4462a72 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -604,7 +604,7 @@ public:
 	const PluginList &getPlugins(const PluginType fetchPluginType) const;
 
 	/** Find a target. */
-	QualifiedGameDescriptor findTarget(const Common::String &target, const Plugin **plugin = NULL) const;
+	QualifiedGameDescriptor findTarget(const Common::String &target) const;
 
 	/**
 	 * List games matching the specified criteria.


Commit: 5169a395a530b17d95ed0037430cf9c592d4b21a
    https://github.com/scummvm/scummvm/commit/5169a395a530b17d95ed0037430cf9c592d4b21a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Remove now useless functions

These functions heavily rely on the fact that detection plugin and
engine plugin can be loaded at the same time.

Changed paths:
    base/plugins.cpp
    base/plugins.h


diff --git a/base/plugins.cpp b/base/plugins.cpp
index fc41cdd08ed..a47b6d611c8 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -286,54 +286,6 @@ void PluginManager::addPluginProvider(PluginProvider *pp) {
 	_providers.push_back(pp);
 }
 
-const Plugin *PluginManager::getEngineFromDetectionPlugin(const Plugin *plugin) {
-	assert(plugin->getType() == PLUGIN_TYPE_ENGINE_DETECTION);
-
-	const Plugin *enginePlugin = nullptr;
-
-	// Use the engineID from MetaEngine for comparison.
-	Common::String metaEnginePluginName = plugin->getName();
-
-	enginePlugin = PluginMan.findEnginePlugin(metaEnginePluginName);
-
-	if (enginePlugin) {
-		debug(9, "MetaEngine: %s \t matched to \t Engine: %s", plugin->get<MetaEngineDetection>().getEngineName(), enginePlugin->getFileName().toString().c_str());
-		return enginePlugin;
-	}
-
-	debug(9, "MetaEngine: %s couldn't find a match for an engine plugin.", plugin->get<MetaEngineDetection>().getEngineName());
-	return nullptr;
-}
-
-const Plugin *PluginManager::getMetaEngineFromEngine(const Plugin *plugin) {
-	assert(plugin->getType() == PLUGIN_TYPE_ENGINE);
-
-	const Plugin *metaEngine = nullptr;
-
-	PluginList pl = PluginMan.getPlugins(PLUGIN_TYPE_ENGINE_DETECTION);
-
-	// This will return a name of the Engine plugin, which will be identical to
-	// a getEngineID from a relevant MetaEngine.
-	Common::String enginePluginName(plugin->getName());
-
-	for (PluginList::const_iterator itr = pl.begin(); itr != pl.end(); itr++) {
-		Common::String metaEngineName = (*itr)->getName();
-
-		if (metaEngineName.equalsIgnoreCase(enginePluginName)) {
-			metaEngine = (*itr);
-			break;
-		}
-	}
-
-	if (metaEngine) {
-		debug(9, "Engine: %s matched to MetaEngine: %s", plugin->getFileName().toString().c_str(), metaEngine->get<MetaEngineDetection>().getEngineName());
-		return metaEngine;
-	}
-
-	debug(9, "Engine: %s couldn't find a match for a MetaEngine plugin.", plugin->getFileName().toString().c_str());
-	return nullptr;
-}
-
 PluginManagerUncached::~PluginManagerUncached() {
 	// Unload from memory all engine plugins without deleting them
 	// They are also referenced from _allEnginePlugins which we clean up here
diff --git a/base/plugins.h b/base/plugins.h
index 48ab1114d4a..8a432ecd74f 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -315,30 +315,6 @@ public:
 	 */
 	const Plugin *findEnginePlugin(const Common::String &engineId);
 
-	/**
-	 * A method which takes in a plugin of type ENGINE,
-	 * and returns the appropriate & matching METAENGINE.
-	 * It uses the Engine plugin's getName method, which is an identifier,
-	 * and then tries to matches it with each plugin present in memory.
-	 *
-	 * @param plugin A plugin of type ENGINE.
-	 *
-	 * @return A plugin of type METAENGINE.
-	 */
-	const Plugin *getMetaEngineFromEngine(const Plugin *plugin);
-
-	/**
-	 * A method which takes in a plugin of type ENGINE_DETECTION,
-	 * and returns the appropriate & matching ENGINE plugin.
-	 * It uses the MetaEngineDetection's getEngineID to reconstruct the name
-	 * of engine plugin, and then tries to matches it with each plugin in memory.
-	 *
-	 * @param A plugin of type ENGINE_DETECTION.
-	 *
-	 * @return A plugin of type ENGINE.
-	 */
-	const Plugin *getEngineFromDetectionPlugin(const Plugin *plugin);
-
 	// Functions used by the uncached PluginManager
 	virtual void init()	{}
 	virtual void loadFirstPlugin() {}


Commit: b07a9388a418b72a3342b062d0099db314e3272c
    https://github.com/scummvm/scummvm/commit/b07a9388a418b72a3342b062d0099db314e3272c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Remove now useless Engine::getMetaEngineDetection

This function assumes that the detection plugin is loaded alongside the
engine plugin.

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


diff --git a/engines/engine.cpp b/engines/engine.cpp
index 4138b1f1797..5b697564c96 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -1007,19 +1007,6 @@ GUI::Debugger *Engine::getOrCreateDebugger() {
 	return _debugger;
 }
 
-/*
-EnginePlugin *Engine::getMetaEnginePlugin() const {
-	return EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
-}
-
-*/
-
-MetaEngineDetection &Engine::getMetaEngineDetection() {
-	const Plugin *plugin = EngineMan.findDetectionPlugin(ConfMan.get("engineid"));
-	assert(plugin);
-	return plugin->get<MetaEngineDetection>();
-}
-
 PauseToken::PauseToken() : _engine(nullptr) {}
 
 PauseToken::PauseToken(Engine *engine) : _engine(engine) {}
diff --git a/engines/engine.h b/engines/engine.h
index 0b176bee852..036245c69f1 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -518,11 +518,6 @@ public:
 	 */
 	static bool shouldQuit();
 
-	/**
-	 * Return the MetaEngineDetection instance used by this engine.
-	 */
-	static MetaEngineDetection &getMetaEngineDetection();
-
 	/**
 	 * Return the MetaEngine instance used by this engine.
 	 */


Commit: a4fb9d614569c3ef59fb0a96faa688e241502c90
    https://github.com/scummvm/scummvm/commit/a4fb9d614569c3ef59fb0a96faa688e241502c90
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Unload engine plugins while loading detection

This makes sure that the engine is never loaded while having the
detection.
The opposite is not (yet?) enforced to avoid crashing some unhandled
case.

Changed paths:
    base/plugins.cpp


diff --git a/base/plugins.cpp b/base/plugins.cpp
index a47b6d611c8..17f8b3e7089 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -436,6 +436,9 @@ void PluginManagerUncached::loadDetectionPlugin() {
 		return;
 	}
 
+	// Unload all leftover engines before reloading the detection plugin
+	unloadPluginsExcept(PLUGIN_TYPE_ENGINE, nullptr, false);
+
 	if (!_detectionPlugin->loadPlugin()) {
 		debug(9, "Detection plugin was not loaded correctly.");
 		return;


Commit: ca2c49476fd850f3c0c15b8daca9c991f023e6db
    https://github.com/scummvm/scummvm/commit/ca2c49476fd850f3c0c15b8daca9c991f023e6db
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Avoid engine plugin unload while creating AboutDialog

When in game, don't list engines if the PluginManagerUncached is used.
If the detection is built as a separate plugin, nothing is listed but
that's better than crashing.

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


diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 85a27090bef..e56931b36b9 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -90,7 +90,7 @@ MainMenuDialog::MainMenuDialog(Engine *engine)
 	if (!g_system->hasFeature(OSystem::kFeatureNoQuit) && (!(ConfMan.getBool("gui_return_to_launcher_at_exit")) || !_engine->hasFeature(Engine::kSupportsReturnToLauncher)))
 		new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), Common::U32String(), kQuitCmd);
 
-	_aboutDialog = new GUI::AboutDialog();
+	_aboutDialog = new GUI::AboutDialog(true);
 	_loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
 	_saveDialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
 }
diff --git a/gui/about.cpp b/gui/about.cpp
index bab9980cc2e..b1dfe76aa67 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -84,7 +84,7 @@ static const char *const gpl_text[] = {
 
 #include "gui/credits.h"
 
-AboutDialog::AboutDialog()
+AboutDialog::AboutDialog(bool inGame)
 	: Dialog(10, 20, 300, 174),
 	  _scrollPos(0), _scrollTime(0), _willClose(false), _autoScroll(true) {
 
@@ -158,17 +158,17 @@ AboutDialog::AboutDialog()
 	Common::StringArray enginesDetected;
 #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
 	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
-	PluginMan.unloadDetectionPlugin();
+	if (!inGame) PluginMan.unloadDetectionPlugin();
 #endif
-	PluginMan.loadFirstPlugin();
+	if (!inGame) PluginMan.loadFirstPlugin();
 	do {
 		const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
 		for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 			enginesDetected.push_back((*iter)->getName());
 		}
-	} while (PluginMan.loadNextPlugin());
+	} while (!inGame && PluginMan.loadNextPlugin());
 
-	PluginMan.loadDetectionPlugin();
+	if (!inGame) PluginMan.loadDetectionPlugin();
 
 	for (Common::StringArray::iterator iter = enginesDetected.begin(); iter != enginesDetected.end(); iter++) {
 		Common::String str;
@@ -176,7 +176,7 @@ AboutDialog::AboutDialog()
 		const Plugin *p = EngineMan.findDetectionPlugin(*iter);
 
 		if (!p) {
-			warning("Cannot find plugin for %s", iter->c_str());
+			if (!inGame) warning("Cannot find plugin for %s", iter->c_str());
 			continue;
 		}
 
diff --git a/gui/about.h b/gui/about.h
index b51266f0865..00215cb88a8 100644
--- a/gui/about.h
+++ b/gui/about.h
@@ -48,7 +48,7 @@ protected:
 	EEHandler	*_eeHandler;
 
 public:
-	AboutDialog();
+	AboutDialog(bool inGame = false);
 
 	void open() override;
 	void close() override;


Commit: 34108724ed8aa75d87cfed34d24286ea5dc6c582
    https://github.com/scummvm/scummvm/commit/34108724ed8aa75d87cfed34d24286ea5dc6c582
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
ENGINES: Factorize sizing and writing functions for dynamic descriptions

Changed paths:
    engines/advancedDetector.h
    engines/ags/detection.h
    engines/gob/detection/detection.h
    engines/mohawk/detection.h


diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index ee863797003..24091468f54 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -42,6 +42,34 @@ class FSList;
  * @{
  */
 
+/* Some helpers functions to avoid code duplication */
+namespace ADDynamicDescription {
+
+static inline uint32 strSizeBuffer(const char * const &field) {
+	return field ? strlen(field) + 1 : 0;
+}
+static inline void *strToBuffer(void *buffer, const char *&field) {
+	if (field) {
+		int len = strlen(field) + 1;
+		memcpy((char *)buffer, field, len);
+		field = (const char *)buffer;
+		buffer = (char *)buffer + len;
+	}
+	return buffer;
+}
+
+static inline uint32 alignSizeBuffer() {
+	// We consider alignments up to pointer size
+	return sizeof(void *) - 1;
+}
+static inline void *alignToBuffer(void *buffer) {
+	// Round up
+	uintptr tmp = (uintptr)buffer + sizeof(void *) - 1;
+	return (void *)(tmp & -sizeof(void *));
+}
+
+} // End of namespace ADDynamicDescription
+
 /**
  * A record describing a file to be matched for detecting a specific game
  * variant. A list of such records is used inside every ADGameDescription to
@@ -55,28 +83,14 @@ struct ADGameFileDescription {
 
 	uint32 sizeBuffer() const {
 		uint32 ret = 0;
-		if (fileName) {
-			ret += strlen(fileName) + 1;
-		}
-		if (md5) {
-			ret += strlen(md5) + 1;
-		}
+		ret += ADDynamicDescription::strSizeBuffer(fileName);
+		ret += ADDynamicDescription::strSizeBuffer(md5);
 		return ret;
 	}
 
 	void *toBuffer(void *buffer) {
-		if (fileName) {
-			int len = strlen(fileName) + 1;
-			memcpy((char *)buffer, fileName, len);
-			fileName = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
-		if (md5) {
-			int len = strlen(md5) + 1;
-			memcpy((char *)buffer, md5, len);
-			md5 = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
+		buffer = ADDynamicDescription::strToBuffer(buffer, fileName);
+		buffer = ADDynamicDescription::strToBuffer(buffer, md5);
 		return buffer;
 	}
 };
@@ -203,18 +217,12 @@ struct ADGameDescription {
 	 */
 	uint32 sizeBuffer() const {
 		uint32 ret = 0;
-		if (gameId) {
-			ret += strlen(gameId) + 1;
-		}
-		if (extra) {
-			ret += strlen(extra) + 1;
-		}
+		ret += ADDynamicDescription::strSizeBuffer(gameId);
+		ret += ADDynamicDescription::strSizeBuffer(extra);
 		for(int i = 0; i < ARRAYSIZE(filesDescriptions); i++) {
 			ret += filesDescriptions[i].sizeBuffer();
 		}
-		if (guiOptions) {
-			ret += strlen(guiOptions) + 1;
-		}
+		ret += ADDynamicDescription::strSizeBuffer(guiOptions);
 		return ret;
 	}
 
@@ -226,27 +234,12 @@ struct ADGameDescription {
 	 * @return The new pointer on buffer after the stored data.
 	 */
 	void *toBuffer(void *buffer) {
-		if (gameId) {
-			int len = strlen(gameId) + 1;
-			memcpy((char *)buffer, gameId, len);
-			gameId = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
-		if (extra) {
-			int len = strlen(extra) + 1;
-			memcpy((char *)buffer, extra, len);
-			extra = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
+		buffer = ADDynamicDescription::strToBuffer(buffer, gameId);
+		buffer = ADDynamicDescription::strToBuffer(buffer, extra);
 		for(int i = 0; i < ARRAYSIZE(filesDescriptions); i++) {
 			buffer = filesDescriptions[i].toBuffer(buffer);
 		}
-		if (guiOptions) {
-			int len = strlen(guiOptions) + 1;
-			memcpy((char *)buffer, guiOptions, len);
-			guiOptions = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
+		buffer = ADDynamicDescription::strToBuffer(buffer, guiOptions);
 		return buffer;
 	}
 };
diff --git a/engines/ags/detection.h b/engines/ags/detection.h
index 57be0fde425..8c2740f8804 100644
--- a/engines/ags/detection.h
+++ b/engines/ags/detection.h
@@ -45,18 +45,11 @@ struct PluginVersion {
 
 	uint32 sizeBuffer() const {
 		uint32 ret = 0;
-		if (_plugin) {
-			ret += strlen(_plugin) + 1;
-		}
+		ret += ADDynamicDescription::strSizeBuffer(_plugin);
 		return ret;
 	}
 	void *toBuffer(void *buffer) {
-		if (_plugin) {
-			int len = strlen(_plugin) + 1;
-			memcpy((char *)buffer, _plugin, len);
-			_plugin = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
+		buffer = ADDynamicDescription::strToBuffer(buffer, _plugin);
 		return buffer;
 	}
 };
@@ -73,13 +66,12 @@ struct AGSGameDescription {
 			for (p = _plugins; p->_plugin != nullptr; p++) {
 				ret += p->sizeBuffer();
 			}
-			// Make sure we have enough room for worst case alignment
-			// by adding the size of a pointer minus one
-			ret += sizeof(*p) * (p - _plugins + 1) + sizeof(void *) - 1;
-		}
-		if (_mainNameInsideInstaller) {
-			ret += strlen(_mainNameInsideInstaller) + 1;
+			// Make space for alignment
+			ret += ADDynamicDescription::alignSizeBuffer();
+			// Add all plugins plus the final element
+			ret += sizeof(*p) * (p - _plugins + 1);
 		}
+		ret += ADDynamicDescription::strSizeBuffer(_mainNameInsideInstaller);
 		return ret;
 	}
 
@@ -91,7 +83,9 @@ struct AGSGameDescription {
 				;
 			uint count = (p - _plugins + 1);
 
-			buffer = (void *)(((uintptr)buffer + sizeof(void *) - 1) & -sizeof(void *));
+			// Align for pointers
+			buffer = ADDynamicDescription::alignToBuffer(buffer);
+
 			memcpy(buffer, _plugins, sizeof(*p) * count);
 
 			_plugins = (PluginVersion *)buffer;
@@ -103,14 +97,7 @@ struct AGSGameDescription {
 				buffer = dp->toBuffer(buffer);
 			}
 		}
-
-		if (_mainNameInsideInstaller) {
-			int len = strlen(_mainNameInsideInstaller) + 1;
-			memcpy((char *)buffer, _mainNameInsideInstaller, len);
-			_mainNameInsideInstaller = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
-
+		buffer = ADDynamicDescription::strToBuffer(buffer, _mainNameInsideInstaller);
 		return buffer;
 	}
 };
diff --git a/engines/gob/detection/detection.h b/engines/gob/detection/detection.h
index 12d647a6695..1864a7c4279 100644
--- a/engines/gob/detection/detection.h
+++ b/engines/gob/detection/detection.h
@@ -92,29 +92,15 @@ struct GOBGameDescription {
 
 	uint32 sizeBuffer() const {
 		uint32 ret = desc.sizeBuffer();
-		if (startStkBase) {
-			ret += strlen(startStkBase) + 1;
-		}
-		if (startTotBase) {
-			ret += strlen(startTotBase) + 1;
-		}
+		ret += ADDynamicDescription::strSizeBuffer(startStkBase);
+		ret += ADDynamicDescription::strSizeBuffer(startTotBase);
 		return ret;
 	}
 
 	void *toBuffer(void *buffer) {
 		buffer = desc.toBuffer(buffer);
-		if (startStkBase) {
-			int len = strlen(startStkBase) + 1;
-			memcpy((char *)buffer, startStkBase, len);
-			startStkBase = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
-		if (startTotBase) {
-			int len = strlen(startTotBase) + 1;
-			memcpy((char *)buffer, startTotBase, len);
-			startTotBase = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
+		buffer = ADDynamicDescription::strToBuffer(buffer, startStkBase);
+		buffer = ADDynamicDescription::strToBuffer(buffer, startTotBase);
 		return buffer;
 	}
 };
diff --git a/engines/mohawk/detection.h b/engines/mohawk/detection.h
index c95ac9ec436..024accdcd72 100644
--- a/engines/mohawk/detection.h
+++ b/engines/mohawk/detection.h
@@ -71,20 +71,13 @@ struct MohawkGameDescription {
 
 	uint32 sizeBuffer() const {
 		uint32 ret = desc.sizeBuffer();
-		if (appName) {
-			ret += strlen(appName) + 1;
-		}
+		ret += ADDynamicDescription::strSizeBuffer(appName);
 		return ret;
 	}
 
 	void *toBuffer(void *buffer) {
 		buffer = desc.toBuffer(buffer);
-		if (appName) {
-			int len = strlen(appName) + 1;
-			memcpy((char *)buffer, appName, len);
-			appName = (const char *)buffer;
-			buffer = (char *)buffer + len;
-		}
+		buffer = ADDynamicDescription::strToBuffer(buffer, appName);
 		return buffer;
 	}
 };


Commit: d0e0ff60c5b3344c1175202653ca364b5960e1e6
    https://github.com/scummvm/scummvm/commit/d0e0ff60c5b3344c1175202653ca364b5960e1e6
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
GUI: Don't list available engines if this is too slow

Changed paths:
    gui/about.cpp


diff --git a/gui/about.cpp b/gui/about.cpp
index b1dfe76aa67..918e9574879 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -156,12 +156,20 @@ AboutDialog::AboutDialog(bool inGame)
 	addLine(engines);
 
 	Common::StringArray enginesDetected;
+
+	uint32 beginTime = g_system->getMillis(true);
 #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) && !defined(DETECTION_STATIC)
 	// Unload all MetaEnginesDetection if we're using uncached plugins to save extra memory.
 	if (!inGame) PluginMan.unloadDetectionPlugin();
 #endif
 	if (!inGame) PluginMan.loadFirstPlugin();
 	do {
+		uint32 currentTime = g_system->getMillis(true);
+		if (currentTime - beginTime > 1500) {
+			// Too slow
+			enginesDetected.clear();
+			break;
+		}
 		const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
 		for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
 			enginesDetected.push_back((*iter)->getName());


Commit: 09729ac9de48e6f8da9541af10e4b9bb84786c3f
    https://github.com/scummvm/scummvm/commit/09729ac9de48e6f8da9541af10e4b9bb84786c3f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-06-30T18:39:06+02:00

Commit Message:
PLUGINS: Use override keyword

This silences a clang warning

Changed paths:
    backends/plugins/dynamic-plugin.h


diff --git a/backends/plugins/dynamic-plugin.h b/backends/plugins/dynamic-plugin.h
index c40e4460c85..669f2bf729d 100644
--- a/backends/plugins/dynamic-plugin.h
+++ b/backends/plugins/dynamic-plugin.h
@@ -40,7 +40,7 @@ public:
 	DynamicPlugin(const Common::Path &filename) :
 		_filename(filename) {}
 
-	virtual bool loadPlugin() {
+	bool loadPlugin() override {
 		// Validate the plugin API version
 		IntFunc verFunc = (IntFunc)findSymbol("PLUGIN_getVersion");
 		if (!verFunc) {
@@ -96,12 +96,12 @@ public:
 		return true;
 	}
 
-	virtual void unloadPlugin() {
+	void unloadPlugin() override {
 		delete _pluginObject;
 		_pluginObject = nullptr;
 	}
 
-	virtual Common::Path getFileName() const override {
+	Common::Path getFileName() const override {
 		return _filename;
 	}
 };




More information about the Scummvm-git-logs mailing list