aboutsummaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
Diffstat (limited to 'base')
-rw-r--r--base/main.cpp21
-rw-r--r--base/plugins.cpp109
-rw-r--r--base/plugins.h40
3 files changed, 146 insertions, 24 deletions
diff --git a/base/main.cpp b/base/main.cpp
index d2da09fa2f..8928396642 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -105,7 +105,12 @@ static const EnginePlugin *detectPlugin() {
// Query the plugins and find one that will handle the specified gameid
printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str());
printf("%s", " Looking for a plugin supporting this gameid... ");
- GameDescriptor game = EngineMan.findGame(gameid, &plugin);
+
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ GameDescriptor game = EngineMan.findGameOnePlugAtATime(gameid, &plugin);
+#else
+ GameDescriptor game = EngineMan.findGame(gameid, &plugin);
+#endif
if (plugin == 0) {
printf("failed\n");
@@ -336,8 +341,13 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
settings.erase("debugflags");
}
- // Load the plugins.
- PluginManager::instance().loadPlugins();
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ // Only load non-engine plugins and first engine plugin initially in this case.
+ PluginManager::instance().loadFirstPlugin();
+#else
+ // Load the plugins.
+ PluginManager::instance().loadPlugins();
+#endif
// If we received an invalid music parameter via command line we check this here.
// We can't check this before loading the music plugins.
@@ -420,7 +430,12 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
ConfMan.setActiveDomain("");
// PluginManager::instance().unloadPlugins();
+
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ PluginManager::instance().loadFirstPlugin();
+#else
PluginManager::instance().loadPlugins();
+#endif
} else {
GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game"));
}
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 7102462173..d2fad34579 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -305,6 +305,7 @@ DECLARE_SINGLETON(PluginManager)
PluginManager::PluginManager() {
// Always add the static plugin provider.
addPluginProvider(new StaticPluginProvider());
+ _skipStaticPlugs = false;
}
PluginManager::~PluginManager() {
@@ -323,6 +324,60 @@ void PluginManager::addPluginProvider(PluginProvider *pp) {
_providers.push_back(pp);
}
+void PluginManager::loadFirstPlugin() { //TODO: rename? It's not quite clear that this loads all non-engine plugins and first engine plugin.
+ unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL);
+ _allPlugs.clear();
+ for (ProviderList::iterator pp = _providers.begin();
+ pp != _providers.end();
+ ++pp) {
+ if ((_skipStaticPlugs && (*pp)->isFilePluginProvider()) || !_skipStaticPlugs) {
+ PluginList pl((*pp)->getPlugins());
+ for (PluginList::iterator p = pl.begin(); p != pl.end(); ++p) {
+ _allPlugs.push_back(*p);
+ }
+ }
+ }
+
+ _nonEnginePlugs = 0;
+ _skipStaticPlugs = true; //Only need to load static plugins once.
+
+ _currentPlugin = _allPlugs.begin();
+
+ if (_allPlugs.empty()) {
+ return; //return here if somehow there are no plugins to load.
+ }
+
+ //this loop is for loading all non-engine plugins and the first engine plugin.
+ for (; _currentPlugin != _allPlugs.end(); ++_currentPlugin) {
+ if (!tryLoadPlugin(*_currentPlugin))
+ continue;
+
+ // TODO: This assumes all non-engine plugins will precede the first engine plugin!
+ if ((*_currentPlugin)->getType() == PLUGIN_TYPE_ENGINE)
+ break;
+
+ _nonEnginePlugs++;
+ }
+
+ return;
+}
+
+bool PluginManager::loadNextPlugin() {
+ if (_nonEnginePlugs == _allPlugs.size())
+ return false; //There are no Engine Plugins in this case.
+
+ // To ensure only one engine plugin is loaded at a time, we unload all engine plugins before trying to load a new one.
+ unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL);
+
+ ++_currentPlugin;
+ for (; _currentPlugin != _allPlugs.end(); ++_currentPlugin)
+ if (tryLoadPlugin(*_currentPlugin))
+ return true;
+
+ loadFirstPlugin();
+ return false;
+}
+
void PluginManager::loadPlugins() {
for (ProviderList::iterator pp = _providers.begin();
pp != _providers.end();
@@ -330,7 +385,6 @@ void PluginManager::loadPlugins() {
PluginList pl((*pp)->getPlugins());
Common::for_each(pl.begin(), pl.end(), Common::bind1st(Common::mem_fun(&PluginManager::tryLoadPlugin), this));
}
-
}
void PluginManager::unloadPlugins() {
@@ -361,7 +415,6 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {
// The plugin is valid, see if it provides the same module as an
// already loaded one and should replace it.
bool found = false;
-
PluginList::iterator pl = _plugins[plugin->getType()].begin();
while (!found && pl != _plugins[plugin->getType()].end()) {
if (!strcmp(plugin->getName(), (*pl)->getName())) {
@@ -387,13 +440,24 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {
}
}
-
// Engine plugins
#include "engines/metaengine.h"
DECLARE_SINGLETON(EngineManager)
+GameDescriptor EngineManager::findGameOnePlugAtATime(const Common::String &gameName, const EnginePlugin **plugin) const {
+ GameDescriptor result;
+ //PluginManager::instance().loadFirstPlugin();
+ do {
+ result = findGame(gameName, plugin);
+ if (!result.gameid().empty()) {
+ break;
+ }
+ } while (PluginManager::instance().loadNextPlugin());
+ return result;
+}
+
GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const {
// Find the GameDescriptor for this target
const EnginePlugin::List &plugins = getPlugins();
@@ -402,30 +466,35 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Eng
if (plugin)
*plugin = 0;
- EnginePlugin::List::const_iterator iter = plugins.begin();
- for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
- result = (**iter)->findGame(gameName.c_str());
- if (!result.gameid().empty()) {
- if (plugin)
- *plugin = *iter;
- break;
+ EnginePlugin::List::const_iterator iter;
+
+ for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
+ result = (**iter)->findGame(gameName.c_str());
+ if (!result.gameid().empty()) {
+ if (plugin)
+ *plugin = *iter;
+ return result;
+ }
}
- }
return result;
}
GameList EngineManager::detectGames(const Common::FSList &fslist) const {
GameList candidates;
-
- const EnginePlugin::List &plugins = getPlugins();
-
- // Iterate over all known games and for each check if it might be
- // the game in the presented directory.
+ EnginePlugin::List plugins;
EnginePlugin::List::const_iterator iter;
- for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
- candidates.push_back((**iter)->detectGames(fslist));
- }
-
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ do {
+#endif
+ plugins = getPlugins();
+ // Iterate over all known games and for each check if it might be
+ // the game in the presented directory.
+ for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
+ candidates.push_back((**iter)->detectGames(fslist));
+ }
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ } while (PluginManager::instance().loadNextPlugin());
+#endif
return candidates;
}
diff --git a/base/plugins.h b/base/plugins.h
index a4c7f114f9..5472ab2fce 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -30,6 +30,7 @@
#include "common/error.h"
#include "common/singleton.h"
#include "common/util.h"
+#include "backends/plugins/elf/version.h"
namespace Common {
class FSList;
@@ -90,6 +91,21 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
#define PLUGIN_ENABLED_DYNAMIC(ID) \
(ENABLE_##ID && (ENABLE_##ID == DYNAMIC_PLUGIN) && DYNAMIC_MODULES)
+// see comments in backends/plugins/elf/elf-provider.cpp
+#if defined(USE_ELF_LOADER) && defined(ELF_LOADER_CXA_ATEXIT)
+#define PLUGIN_DYNAMIC_DSO_HANDLE \
+ uint32 __dso_handle __attribute__((visibility("hidden"))) = 0;
+#else
+#define PLUGIN_DYNAMIC_DSO_HANDLE
+#endif
+
+#ifdef USE_ELF_LOADER
+#define PLUGIN_DYNAMIC_BUILD_DATE \
+ PLUGIN_EXPORT const char *PLUGIN_getBuildDate() { return gScummVMPluginBuildDate; }
+#else
+#define PLUGIN_DYNAMIC_BUILD_DATE
+#endif
+
/**
* REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare
* the plugin interface for static plugins. Code (such as game engines)
@@ -119,6 +135,8 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
*/
#define REGISTER_PLUGIN_DYNAMIC(ID,TYPE,PLUGINCLASS) \
extern "C" { \
+ PLUGIN_DYNAMIC_DSO_HANDLE \
+ PLUGIN_DYNAMIC_BUILD_DATE \
PLUGIN_EXPORT int32 PLUGIN_getVersion() { return PLUGIN_VERSION; } \
PLUGIN_EXPORT int32 PLUGIN_getType() { return TYPE; } \
PLUGIN_EXPORT int32 PLUGIN_getTypeVersion() { return TYPE##_VERSION; } \
@@ -212,6 +230,11 @@ public:
* @return a list of Plugin instances
*/
virtual PluginList getPlugins() = 0;
+
+ /**
+ * @return whether or not object is a FilePluginProvider.
+ */
+ virtual bool isFilePluginProvider() { return false; }
};
#ifdef DYNAMIC_MODULES
@@ -234,6 +257,11 @@ public:
*/
virtual PluginList getPlugins();
+ /**
+ * @return whether or not object is a FilePluginProvider.
+ */
+ bool isFilePluginProvider() { return true; }
+
protected:
/**
* Create a Plugin instance from a loadable code module with the specified name.
@@ -276,8 +304,15 @@ private:
PluginList _plugins[PLUGIN_TYPE_MAX];
ProviderList _providers;
- bool tryLoadPlugin(Plugin *plugin);
+ PluginList _allPlugs;
+ PluginList::iterator _currentPlugin;
+ bool _skipStaticPlugs;
+
+ uint _nonEnginePlugs;
+
+ bool tryLoadPlugin(Plugin *plugin);
+
friend class Common::Singleton<SingletonBaseType>;
PluginManager();
@@ -286,6 +321,9 @@ public:
void addPluginProvider(PluginProvider *pp);
+ void loadFirstPlugin();
+ bool loadNextPlugin();
+
void loadPlugins();
void unloadPlugins();
void unloadPluginsExcept(PluginType type, const Plugin *plugin);