diff options
| -rw-r--r-- | backends/plugins/dc/dc-provider.cpp | 3 | ||||
| -rw-r--r-- | backends/plugins/dynamic-plugin.h | 9 | ||||
| -rw-r--r-- | backends/plugins/elf/elf-provider.h | 3 | ||||
| -rw-r--r-- | backends/plugins/posix/posix-provider.cpp | 3 | ||||
| -rw-r--r-- | backends/plugins/sdl/sdl-provider.cpp | 3 | ||||
| -rw-r--r-- | backends/plugins/win32/win32-provider.cpp | 3 | ||||
| -rw-r--r-- | base/plugins.cpp | 103 | ||||
| -rw-r--r-- | base/plugins.h | 35 | 
8 files changed, 135 insertions, 27 deletions
diff --git a/backends/plugins/dc/dc-provider.cpp b/backends/plugins/dc/dc-provider.cpp index 67877dc9f4..86ef68828c 100644 --- a/backends/plugins/dc/dc-provider.cpp +++ b/backends/plugins/dc/dc-provider.cpp @@ -37,7 +37,6 @@  class DCPlugin : public DynamicPlugin {  protected:  	void *_dlHandle; -	Common::String _filename;  	virtual VoidFunc findSymbol(const char *symbol) {  		void *func = dlsym(_dlHandle, symbol); @@ -56,7 +55,7 @@ protected:  public:  	DCPlugin(const Common::String &filename) -		: _dlHandle(0), _filename(filename) {} +		: DynamicPlugin(filename), _dlHandle(0) {}  	bool loadPlugin() {  		assert(!_dlHandle); diff --git a/backends/plugins/dynamic-plugin.h b/backends/plugins/dynamic-plugin.h index ec051c4ed7..32d411656c 100644 --- a/backends/plugins/dynamic-plugin.h +++ b/backends/plugins/dynamic-plugin.h @@ -37,7 +37,12 @@ protected:  	virtual VoidFunc findSymbol(const char *symbol) = 0; +	const Common::String _filename; +  public: +	DynamicPlugin(const Common::String &filename) : +		_filename(filename) {} +  	virtual bool loadPlugin() {  		// Validate the plugin API version  		IntFunc verFunc = (IntFunc)findSymbol("PLUGIN_getVersion"); @@ -97,6 +102,10 @@ public:  	virtual void unloadPlugin() {  		delete _pluginObject;  	} + +	virtual const char *getFileName() const { +		return _filename.c_str(); +	}  };  #endif diff --git a/backends/plugins/elf/elf-provider.h b/backends/plugins/elf/elf-provider.h index fe8346f95e..8cc9e0a996 100644 --- a/backends/plugins/elf/elf-provider.h +++ b/backends/plugins/elf/elf-provider.h @@ -48,15 +48,14 @@ protected:  	typedef const char *(*CharFunc)();  	DLObject *_dlHandle; -	Common::String _filename;  	void *_dso_handle;  	virtual VoidFunc findSymbol(const char *symbol);  public:  	ELFPlugin(const Common::String &filename) : +		DynamicPlugin(filename),  		_dlHandle(0), -		_filename(filename),  		_dso_handle(0) {  	} diff --git a/backends/plugins/posix/posix-provider.cpp b/backends/plugins/posix/posix-provider.cpp index 01e48739bd..dd3591a992 100644 --- a/backends/plugins/posix/posix-provider.cpp +++ b/backends/plugins/posix/posix-provider.cpp @@ -37,7 +37,6 @@  class POSIXPlugin : public DynamicPlugin {  protected:  	void *_dlHandle; -	Common::String _filename;  	virtual VoidFunc findSymbol(const char *symbol) {  		void *func = dlsym(_dlHandle, symbol); @@ -56,7 +55,7 @@ protected:  public:  	POSIXPlugin(const Common::String &filename) -		: _dlHandle(0), _filename(filename) {} +		: DynamicPlugin(filename), _dlHandle(0) {}  	bool loadPlugin() {  		assert(!_dlHandle); diff --git a/backends/plugins/sdl/sdl-provider.cpp b/backends/plugins/sdl/sdl-provider.cpp index 51c19fcef3..5172abc4b0 100644 --- a/backends/plugins/sdl/sdl-provider.cpp +++ b/backends/plugins/sdl/sdl-provider.cpp @@ -36,7 +36,6 @@  class SDLPlugin : public DynamicPlugin {  protected:  	void *_dlHandle; -	Common::String _filename;  	virtual VoidFunc findSymbol(const char *symbol) {  		void *func = SDL_LoadFunction(_dlHandle, symbol); @@ -55,7 +54,7 @@ protected:  public:  	SDLPlugin(const Common::String &filename) -		: _dlHandle(0), _filename(filename) {} +		: DynamicPlugin(filename), _dlHandle(0) {}  	bool loadPlugin() {  		assert(!_dlHandle); diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp index 16532d4059..793b1bfc0c 100644 --- a/backends/plugins/win32/win32-provider.cpp +++ b/backends/plugins/win32/win32-provider.cpp @@ -51,7 +51,6 @@ private:  protected:  	void *_dlHandle; -	Common::String _filename;  	virtual VoidFunc findSymbol(const char *symbol) {  		#ifndef _WIN32_WCE @@ -67,7 +66,7 @@ protected:  public:  	Win32Plugin(const Common::String &filename) -		: _dlHandle(0), _filename(filename) {} +		: DynamicPlugin(filename), _dlHandle(0) {}  	bool loadPlugin() {  		assert(!_dlHandle); diff --git a/base/plugins.cpp b/base/plugins.cpp index 62ff15bf81..83377600af 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -335,16 +335,15 @@ void PluginManager::addPluginProvider(PluginProvider *pp) {  	_providers.push_back(pp);  } -// -// This should only be run once +/** + * This should only be called once by main() + **/  void PluginManagerUncached::init() {  	unloadAllPlugins();  	_allEnginePlugins.clear(); -	// We need to resize our pluginsInMem list to prevent fragmentation -	// Otherwise, as soon as we add our 1 engine plugin (which is all we'll have in memory at a time) -	// We'll get an allocation in memory that will never go away -	_pluginsInMem[PLUGIN_TYPE_ENGINE].resize(2);	// more than we need +	// Resize our pluginsInMem list to prevent fragmentation +	_pluginsInMem[PLUGIN_TYPE_ENGINE].resize(2);  	for (ProviderList::iterator pp = _providers.begin();  	                            pp != _providers.end(); @@ -371,6 +370,63 @@ void PluginManagerUncached::init() {   	}  } +/** + * Try to load the plugin by searching in the ConfigManager for a matching + * gameId under the domain 'plugin_files'. + **/ +bool PluginManagerUncached::loadPluginFromGameId(const Common::String &gameId) { +	Common::ConfigManager::Domain *domain = ConfMan.getDomain("plugin_files"); + +	if (domain) { +		if (domain->contains(gameId)) { +			Common::String filename = (*domain)[gameId]; + +		    if (loadPluginByFileName(filename)) { +				return true; +			} +		} +	} +	return false; +} + +/** + * Load a plugin with a filename taken from ConfigManager. + **/ +bool PluginManagerUncached::loadPluginByFileName(const Common::String &filename) { +	if (filename.empty()) +		return false; +	 +	unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); + +	PluginList::iterator i; +	for (i = _allEnginePlugins.begin(); i != _allEnginePlugins.end(); ++i) { +		if (Common::String((*i)->getFileName()) == filename && (*i)->loadPlugin()) { +			addToPluginsInMemList(*i); +			_currentPlugin = i; +			return true; +		} +	} +	return false; +} + +/**  + * Update the config manager with a plugin file name that we found can handle + * the game. + **/ +void PluginManagerUncached::updateConfigWithFileName(const Common::String &gameId) { +	// Check if we have a filename for the current plugin +	if ((*_currentPlugin)->getFileName()) { +		if (!ConfMan.hasMiscDomain("plugin_files")) +			ConfMan.addMiscDomain("plugin_files"); + +		Common::ConfigManager::Domain *domain = ConfMan.getDomain("plugin_files"); +		assert(domain); +		(*domain)[gameId] = (*_currentPlugin)->getFileName(); + +		ConfMan.flushToDisk(); +	} +} +  void PluginManagerUncached::loadFirstPlugin() {   	unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); @@ -395,6 +451,10 @@ bool PluginManagerUncached::loadNextPlugin() {  	return false;	// no more in list  } +/** + * Used by only the cached plugin manager. The uncached manager can only have + * one plugin in memory at a time. + **/  void PluginManager::loadAllPlugins() {  	for (ProviderList::iterator pp = _providers.begin();  	                            pp != _providers.end(); @@ -426,6 +486,9 @@ void PluginManager::unloadPluginsExcept(PluginType type, const Plugin *plugin, b  	}  } +/* + * Used only by the cached plugin manager since it deletes the plugin. + */  bool PluginManager::tryLoadPlugin(Plugin *plugin) {  	assert(plugin);  	// Try to load the plugin @@ -439,6 +502,9 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {  	}  } +/** + * Add to the list of plugins loaded in memory. + */  void PluginManager::addToPluginsInMemList(Plugin *plugin) {  	bool found = false;  	// The plugin is valid, see if it provides the same module as an @@ -468,16 +534,35 @@ void PluginManager::addToPluginsInMemList(Plugin *plugin) {  DECLARE_SINGLETON(EngineManager); +/**  + * This function works for both cached and uncached PluginManagers. + * For the cached version, most of the logic here will short circuit. + * + * For the uncached version, we first try to find the plugin using the gameId + * and only if we can't find it there, we loop through the plugins. + **/  GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const {  	GameDescriptor result; - -	PluginManager::instance().loadFirstPlugin(); +	 +	// first look for the game using the gameId +	if (PluginMan.loadPluginFromGameId(gameName))  { +		result = findGameInLoadedPlugins(gameName, plugin);  +		if (!result.gameid().empty()) { +			return result; +		} +	} +	 +	// We failed to find it using the gameid. Scan the list of plugins +	PluginMan.loadFirstPlugin();  	do {  		result = findGameInLoadedPlugins(gameName, plugin);   		if (!result.gameid().empty()) { +			// Update with new plugin file name +			PluginMan.updateConfigWithFileName(gameName);  			break;  		} -	} while (PluginManager::instance().loadNextPlugin()); +	} while (PluginMan.loadNextPlugin()); +  	return result;  } diff --git a/base/plugins.h b/base/plugins.h index 928be85c32..4f6d37ac86 100644 --- a/base/plugins.h +++ b/base/plugins.h @@ -152,11 +152,11 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];  // Abstract plugins  /** - * Abstract base class for the plugin objects which handle plugins - * instantiation. Subclasses for this may be used for engine plugins - * and other types of plugins. - * - * FIXME: This class needs better documentation, esp. how it differs from class Plugin + * Abstract base class for the plugin objects which handle plugins  + * instantiation. Subclasses for this may be used for engine plugins and other + * types of plugins. An existing PluginObject refers to an executable file + * loaded in memory and ready to run. The plugin, on the other hand, is just + * a handle to the file/object, whether it's loaded in memory or not.   */  class PluginObject {  public: @@ -169,9 +169,8 @@ public:  /**   * Abstract base class for the plugin system.   * Subclasses for this can be used to wrap both static and dynamic - * plugins. - * - * FIXME: This class needs better documentation, esp. how it differs from class PluginObject + * plugins. This class refers to a plugin which may or may not be loaded in + * memory.   */  class Plugin {  protected: @@ -189,8 +188,19 @@ public:  	virtual bool loadPlugin() = 0;	// TODO: Rename to load() ?  	virtual void unloadPlugin() = 0;	// TODO: Rename to unload() ? +	/** +	 * The following functions query information from the plugin object once +	 * it's loaded into memory. +	 **/  	PluginType getType() const;  	const char *getName() const; + +	/** +	 * The getFileName() function gets the name of the plugin file for those +	 * plugins that have files (ie. not static). It doesn't require the plugin +	 * object to be loaded into memory, unlike getName() +	 **/ +	virtual const char *getFileName() const { return 0; }  };  /** List of Plugin instances. */ @@ -294,6 +304,8 @@ protected:  #endif // DYNAMIC_MODULES +#define PluginMan PluginManager::instance() +  /**   * Singleton class which manages all plugins, including loading them,   * managing all Plugin class instances, and unloading them. @@ -319,10 +331,14 @@ public:  	void addPluginProvider(PluginProvider *pp); +	// Functions used by the uncached PluginManager  	virtual void init()	{}  	virtual void loadFirstPlugin() {}  	virtual bool loadNextPlugin() { return false; } +	virtual bool loadPluginFromGameId(const Common::String &gameId) { return false; }  +	virtual void updateConfigWithFileName(const Common::String &gameId) {}  +	// Functions used only by the cached PluginManager  	virtual void loadAllPlugins();  	void unloadAllPlugins(); @@ -342,11 +358,14 @@ protected:  	PluginList::iterator _currentPlugin;  	PluginManagerUncached() {} +	bool loadPluginByFileName(const Common::String &filename);   public:  	virtual void init();  	virtual void loadFirstPlugin();  	virtual bool loadNextPlugin(); +	virtual bool loadPluginFromGameId(const Common::String &gameId);  +	virtual void updateConfigWithFileName(const Common::String &gameId);   	virtual void loadAllPlugins() {} 	// we don't allow this  };  | 
