diff options
-rw-r--r-- | common/engine.cpp | 47 | ||||
-rw-r--r-- | common/engine.h | 28 | ||||
-rw-r--r-- | common/gameDetector.cpp | 148 | ||||
-rw-r--r-- | common/gameDetector.h | 39 | ||||
-rw-r--r-- | common/main.cpp | 13 | ||||
-rw-r--r-- | common/plugins.cpp | 74 | ||||
-rw-r--r-- | common/plugins.h | 14 | ||||
-rw-r--r-- | common/timer.cpp | 2 |
8 files changed, 222 insertions, 143 deletions
diff --git a/common/engine.cpp b/common/engine.cpp index dbf7c09086..b6b2d1092d 100644 --- a/common/engine.cpp +++ b/common/engine.cpp @@ -121,40 +121,6 @@ const char *Engine::getSavePath() const { return dir; } -Engine *Engine::createFromDetector(GameDetector *detector, OSystem *syst) { - Engine *engine = NULL; - -#ifndef DISABLE_SCUMM - if (detector->_game.id >= GID_SCUMM_FIRST && detector->_game.id <= GID_SCUMM_LAST) { - // Some kind of Scumm game - engine = Engine_SCUMM_create(detector, syst); - } -#endif - -#ifndef DISABLE_SIMON - if (detector->_game.id >= GID_SIMON_FIRST && detector->_game.id <= GID_SIMON_LAST) { - // Simon the Sorcerer - engine = Engine_SIMON_create(detector, syst); - } -#endif - -#ifndef DISABLE_SKY - if (detector->_game.id >= GID_SKY_FIRST && detector->_game.id <= GID_SKY_LAST) { - // Beneath a Steel Sky - engine = Engine_SKY_create(detector, syst); - } -#endif - -#ifndef DISABLE_SWORD2 - if (detector->_game.id >= GID_SWORD2_FIRST && detector->_game.id <= GID_SWORD2_LAST) { - // Broken Sword 2 - engine = Engine_SWORD2_create(detector, syst); - } -#endif - - return engine; -} - void NORETURN CDECL error(const char *s, ...) { #ifdef __PALM_OS__ char buf_input[256]; // 1024 is too big overflow the stack @@ -274,3 +240,16 @@ void checkHeap() { } #endif } + +// +// HACK: The following is done to pull in symbols from all the engine modules here. +// If we don't do this, all sorts of linker problems may occur. +// +EngineFactory _factories[] = + { + Engine_SKY_create, + Engine_SCUMM_create, + Engine_SIMON_create, + Engine_SWORD2_create + }; + diff --git a/common/engine.h b/common/engine.h index 2ad6c3f638..58559dd4b5 100644 --- a/common/engine.h +++ b/common/engine.h @@ -74,10 +74,6 @@ public: const char *getSavePath() const; virtual const char *getGameDataPath() const { return _gameDataPath; } - - // Create a new engine object based on the detector - either - // a Scumm or a SimonEngine object currently. - static Engine *createFromDetector(GameDetector *detector, OSystem *syst); // Specific for each engine preparare of erroe string virtual void errorString(const char *buf_input, char *buf_output) = 0; @@ -96,29 +92,5 @@ void CDECL warning(const char *s, ...); void CDECL debug(int level, const char *s, ...); void checkHeap(); -// Factory functions => no need to include the specific classes -// in this header. This serves two purposes: -// 1) Clean seperation from the game modules (scumm, simon) and the generic code -// 2) Faster (compiler doesn't have to parse lengthy header files) -#ifndef DISABLE_SCUMM -extern const TargetSettings *Engine_SCUMM_targetList(); -extern Engine *Engine_SCUMM_create(GameDetector *detector, OSystem *syst); -#endif - -#ifndef DISABLE_SIMON -extern Engine *Engine_SIMON_create(GameDetector *detector, OSystem *syst); -extern const TargetSettings *Engine_SIMON_targetList(); -#endif - -#ifndef DISABLE_SKY -extern const TargetSettings *Engine_SKY_targetList(); -extern Engine *Engine_SKY_create(GameDetector *detector, OSystem *syst); -#endif - -#ifndef DISABLE_SWORD2 -extern const TargetSettings *Engine_SWORD2_targetList(); -extern Engine *Engine_SWORD2_create(GameDetector *detector, OSystem *syst); -#endif - #endif diff --git a/common/gameDetector.cpp b/common/gameDetector.cpp index 6192600788..ee8b98bf7d 100644 --- a/common/gameDetector.cpp +++ b/common/gameDetector.cpp @@ -25,6 +25,7 @@ #include "common/config-file.h" #include "common/engine.h" #include "common/gameDetector.h" +#include "common/plugins.h" #include "common/scaler.h" // Only for gfx_modes #include "sound/mididrv.h" @@ -99,8 +100,6 @@ static const char USAGE_STRING[] = "e.g. \"--no-aspect-ratio\".\n" ; #endif -// This contains a pointer to a list of all supported games. -const TargetSettings *version_settings = NULL; static const struct GraphicsMode gfx_modes[] = { {"normal", "Normal (no scaling)", GFX_NORMAL}, @@ -159,12 +158,13 @@ static const struct MusicDriver music_drivers[] = { {0, 0, 0} }; -static int countVersions(const TargetSettings *v) { - int count; - for (count = 0; v->targetName; v++, count++) - ; - return count; -} + +// This contains a pointer to a list of all supported games. +// FIXME: Get rid of version_settings. The only reaons we still have it is +// that launcher.cpp uses it. So let's convert launcher.cpp to use the new +// Plugin API instead! +const TargetSettings *version_settings = NULL; + GameDetector::GameDetector() { _fullScreen = false; @@ -213,70 +213,37 @@ GameDetector::GameDetector() { _gfx_mode = GFX_NORMAL; #endif _default_gfx_mode = true; - + if (version_settings == NULL) { - int totalCount = 0; + assert(g_pluginManager); + const PluginList &_plugins = g_pluginManager->getPlugins(); + int i; + int count = 0; // Gather & combine the target lists from the modules + for (i = 0; i < _plugins.size(); i++) { + count += _plugins[i]->countTargets(); + } -#ifndef DISABLE_SCUMM - const TargetSettings *scummVersions = Engine_SCUMM_targetList(); - int scummCount = countVersions(scummVersions); - totalCount += scummCount; -#endif - -#ifndef DISABLE_SIMON - const TargetSettings *simonVersions = Engine_SIMON_targetList(); - int simonCount = countVersions(simonVersions); - totalCount += simonCount; -#endif - -#ifndef DISABLE_SKY - const TargetSettings *skyVersions = Engine_SKY_targetList(); - int skyCount = countVersions(skyVersions); - totalCount += skyCount; -#endif - -#ifndef DISABLE_SWORD2 - const TargetSettings *sword2Versions = Engine_SWORD2_targetList(); - int sword2Count = countVersions(sword2Versions); - totalCount += sword2Count; -#endif - - TargetSettings *v = (TargetSettings *)calloc(totalCount + 1, sizeof(TargetSettings)); + TargetSettings *v = (TargetSettings *)calloc(count + 1, sizeof(TargetSettings)); version_settings = v; -#ifndef DISABLE_SCUMM - memcpy(v, scummVersions, scummCount * sizeof(TargetSettings)); - v += scummCount; -#endif - -#ifndef DISABLE_SIMON - memcpy(v, simonVersions, simonCount * sizeof(TargetSettings)); - v += simonCount; -#endif - -#ifndef DISABLE_SKY - memcpy(v, skyVersions, skyCount * sizeof(TargetSettings)); - v += skyCount; -#endif - -#ifndef DISABLE_SWORD2 - memcpy(v, sword2Versions, sword2Count * sizeof(TargetSettings)); - v += sword2Count; -#endif - + for (i = 0; i < _plugins.size(); i++) { + count = _plugins[i]->countTargets(); + memcpy(v, _plugins[i]->getTargets(), count * sizeof(TargetSettings)); + v += count; + } } } -#ifdef __PALM_OS__ GameDetector::~GameDetector() { +#ifdef __PALM_OS__ // This is a previously allocated chunck (line 224) // so we need to free it to prevent memory leak TargetSettings *v = (TargetSettings *)version_settings; free(v); -} #endif +} void GameDetector::updateconfig() { const char *val; @@ -349,29 +316,33 @@ void GameDetector::updateconfig() { } void GameDetector::list_games() { - const TargetSettings *v = version_settings; + const PluginList &_plugins = g_pluginManager->getPlugins(); + const TargetSettings *v; const char *config; printf("Game Full Title Config\n" "---------------- ------------------------------------------------------ -------\n"); - while (v->targetName && v->description) { - config = (g_config->has_domain(v->targetName)) ? "Yes" : ""; - printf("%-17s%-56s%s\n", v->targetName, v->description, config); - v++; + for (int i = 0; i < _plugins.size(); i++) { + v = _plugins[i]->getTargets(); + while (v->targetName && v->description) { + config = (g_config->has_domain(v->targetName)) ? "Yes" : ""; + printf("%-17s%-56s%s\n", v->targetName, v->description, config); + v++; + } } - } const TargetSettings *GameDetector::findTarget(const char *targetName) const { // Find the TargetSettings for this target - const TargetSettings *target = version_settings; assert(targetName); - while (target->targetName) { - if (!scumm_stricmp(target->targetName, targetName)) { + const TargetSettings *target; + const PluginList &_plugins = g_pluginManager->getPlugins(); + + for (int i = 0; i < _plugins.size(); i++) { + target = _plugins[i]->findTarget(targetName); + if (target) return target; - } - target++; } return 0; } @@ -802,6 +773,47 @@ OSystem *GameDetector::createSystem() { #endif } +Engine *GameDetector::createEngine(OSystem *system) { + Engine *engine = NULL; + + // FIXME: These checks are evil, as they require us to hard code GIDs. + // Much better would be to e.g. put a pointer to the instance creation + // method into the TargetSettings or so. That way, in addition to + // simplifying this code, GIDs wouldn't have to be unique globally + // anymore - only locally for each plugin. And it would be trivial + // to add new plugins, without touching the code here. + +#ifndef DISABLE_SCUMM + if (_game.id >= GID_SCUMM_FIRST && _game.id <= GID_SCUMM_LAST) { + // Some kind of Scumm game + engine = Engine_SCUMM_create(this, system); + } +#endif + +#ifndef DISABLE_SIMON + if (_game.id >= GID_SIMON_FIRST && _game.id <= GID_SIMON_LAST) { + // Simon the Sorcerer + engine = Engine_SIMON_create(this, system); + } +#endif + +#ifndef DISABLE_SKY + if (_game.id >= GID_SKY_FIRST && _game.id <= GID_SKY_LAST) { + // Beneath a Steel Sky + engine = Engine_SKY_create(this, system); + } +#endif + +#ifndef DISABLE_SWORD2 + if (_game.id >= GID_SWORD2_FIRST && _game.id <= GID_SWORD2_LAST) { + // Broken Sword 2 + engine = Engine_SWORD2_create(this, system); + } +#endif + + return engine; +} + int GameDetector::getMidiDriverType() { if (_midi_driver != MD_AUTO) return _midi_driver; diff --git a/common/gameDetector.h b/common/gameDetector.h index dd8d770d43..ae06966c74 100644 --- a/common/gameDetector.h +++ b/common/gameDetector.h @@ -25,6 +25,8 @@ #include "common/str.h" +class Engine; +class GameDetector; class OSystem; class MidiDriver; @@ -96,6 +98,33 @@ struct Language { int id; }; +typedef Engine *(*EngineFactory)(GameDetector *detector, OSystem *syst); + +// Factory functions => no need to include the specific classes +// in this header. This serves two purposes: +// 1) Clean seperation from the game modules (scumm, simon) and the generic code +// 2) Faster (compiler doesn't have to parse lengthy header files) +#ifndef DISABLE_SCUMM +extern const TargetSettings *Engine_SCUMM_targetList(); +extern Engine *Engine_SCUMM_create(GameDetector *detector, OSystem *syst); +#endif + +#ifndef DISABLE_SIMON +extern Engine *Engine_SIMON_create(GameDetector *detector, OSystem *syst); +extern const TargetSettings *Engine_SIMON_targetList(); +#endif + +#ifndef DISABLE_SKY +extern const TargetSettings *Engine_SKY_targetList(); +extern Engine *Engine_SKY_create(GameDetector *detector, OSystem *syst); +#endif + +#ifndef DISABLE_SWORD2 +extern const TargetSettings *Engine_SWORD2_targetList(); +extern Engine *Engine_SWORD2_create(GameDetector *detector, OSystem *syst); +#endif + + class GameDetector { typedef ScummVM::String String; @@ -105,14 +134,15 @@ public: public: GameDetector(); -#ifdef __PALM_OS__ ~GameDetector(); -#endif void parseCommandLine(int argc, char **argv); int detectMain(); void setGame(const String &name); const String& getGameName(void); + + String _gameFileName; + TargetSettings _game; bool _fullScreen; bool _aspectRatio; @@ -138,9 +168,6 @@ public: int _gameTempo; int _midi_driver; - String _gameFileName; - TargetSettings _game; - int _gfx_mode; bool _default_gfx_mode; @@ -155,6 +182,8 @@ public: public: OSystem *createSystem(); + Engine *createEngine(OSystem *system); + MidiDriver *createMidi(); int getMidiDriverType(); diff --git a/common/main.cpp b/common/main.cpp index 8f67fc3300..2ef2d76a4f 100644 --- a/common/main.cpp +++ b/common/main.cpp @@ -32,13 +32,14 @@ #include "common/config-file.h" #include "common/engine.h" #include "common/gameDetector.h" +#include "common/plugins.h" #include "common/scaler.h" // For GFX_NORMAL #include "gui/newgui.h" #include "gui/launcher.h" #include "gui/message.h" -Config *g_config = 0; -NewGui *g_gui = 0; +Config *g_config = 0; +NewGui *g_gui = 0; #if defined(QTOPIA) // FIXME - why exactly is this needed? @@ -151,7 +152,6 @@ static void launcherDialog(GameDetector &detector, OSystem *system) { } int main(int argc, char *argv[]) { - GameDetector detector; OSystem::Property prop; #if defined(UNIX) @@ -179,8 +179,13 @@ int main(int argc, char *argv[]) { // Read the config file g_config = new Config(scummhome, "scummvm"); g_config->set("versioninfo", gScummVMVersion); + + // Load the plugins + g_pluginManager = new PluginManager(); + g_pluginManager->loadPlugins(); // Parse the command line information + GameDetector detector; detector._saveconfig = false; detector.updateconfig(); detector.parseCommandLine(argc, argv); @@ -215,7 +220,7 @@ int main(int argc, char *argv[]) { } // Create the game engine - Engine *engine = Engine::createFromDetector(&detector, system); + Engine *engine = detector.createEngine(system); // print a message if gameid is invalid if (engine == NULL) diff --git a/common/plugins.cpp b/common/plugins.cpp index cdfae734be..006f342e5f 100644 --- a/common/plugins.cpp +++ b/common/plugins.cpp @@ -22,6 +22,64 @@ #include "common/plugins.h" #include "common/engine.h" +#include "common/gameDetector.h" + + +PluginManager *g_pluginManager = 0; + + +#pragma mark - + + +int Plugin::countTargets() const { + const TargetSettings *target = getTargets(); + int count; + for (count = 0; target->targetName; target++, count++) + ; + return count; +} + +const TargetSettings *Plugin::findTarget(const char *targetName) const { + // Find the TargetSettings for this target + const TargetSettings *target = getTargets(); + assert(targetName); + while (target->targetName) { + if (!scumm_stricmp(target->targetName, targetName)) { + return target; + } + target++; + } + return 0; +} + + +#pragma mark - + + +class StaticPlugin : public Plugin { + const char *_name; + const TargetSettings *_targets; + int _targetCount; + EngineFactory _ef; +public: + StaticPlugin(const char *name, const TargetSettings *targets, EngineFactory ef) + : _name(name), _targets(targets), _ef(ef) { + _targetCount = Plugin::countTargets(); + } + + const char *getName() const { return _name; } + int getVersion() const { return 0; } + + int countTargets() const { return _targetCount; } + const TargetSettings *getTargets() const { return _targets; } + + Engine *createInstance(GameDetector *detector, OSystem *syst) const { + return (*_ef)(detector, syst); + } +}; + + +#pragma mark - PluginManager::PluginManager() { @@ -33,7 +91,21 @@ PluginManager::~PluginManager() { } void PluginManager::loadPlugins() { - // TODO +#ifndef DISABLE_SCUMM + _plugins.push_back(new StaticPlugin("scumm", Engine_SCUMM_targetList(), Engine_SCUMM_create)); +#endif + +#ifndef DISABLE_SIMON + _plugins.push_back(new StaticPlugin("simon", Engine_SIMON_targetList(), Engine_SIMON_create)); +#endif + +#ifndef DISABLE_SKY + _plugins.push_back(new StaticPlugin("sky", Engine_SKY_targetList(), Engine_SKY_create)); +#endif + +#ifndef DISABLE_SWORD2 + _plugins.push_back(new StaticPlugin("sword2", Engine_SWORD2_targetList(), Engine_SWORD2_create)); +#endif } void PluginManager::unloadPlugins() { diff --git a/common/plugins.h b/common/plugins.h index 141f433202..8257bf1a53 100644 --- a/common/plugins.h +++ b/common/plugins.h @@ -43,10 +43,18 @@ public: virtual const char *getName() const = 0; virtual int getVersion() const = 0; + virtual int countTargets() const; virtual const TargetSettings *getTargets() const = 0; + virtual const TargetSettings *findTarget(const char *targetName) const; + virtual Engine *createInstance(GameDetector *detector, OSystem *syst) const = 0; }; + +/** List of plugins. */ +typedef ScummVM::List<Plugin *> PluginList; + + /** * Instances of this class manage all plugins, including loading them, * making wrapper objects of class Plugin available, and unloading them. @@ -55,8 +63,6 @@ public: */ class PluginManager { protected: - typedef ScummVM::List<Plugin *> PluginList; - PluginList _plugins; public: @@ -69,5 +75,9 @@ public: const PluginList &getPlugins() { return _plugins; } }; +/** + * Global, shared plugin manager. + */ +extern PluginManager *g_pluginManager; #endif diff --git a/common/timer.cpp b/common/timer.cpp index 2de3170b19..8ce5b809b2 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -91,7 +91,7 @@ int Timer::handler(int t) { _timerSlots[l].counter -= interval; if (_timerSlots[l].counter <= 0) { _timerSlots[l].counter += _timerSlots[l].interval; - _timerSlots[l].procedure (_engine); + _timerSlots[l].procedure(_engine); } } } |