diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/main.cpp | 21 | ||||
-rw-r--r-- | base/plugins.cpp | 109 | ||||
-rw-r--r-- | base/plugins.h | 40 |
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); |