aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2003-09-08 17:13:40 +0000
committerMax Horn2003-09-08 17:13:40 +0000
commit6455c819896d58782f9ec195e0b716a1df32c296 (patch)
treeba0d5a4c7fe2381177fe7d119f90e748204798da /common
parent90ec1dc34ea403c0e23ff820d5ca20a7b9ca0140 (diff)
downloadscummvm-rg350-6455c819896d58782f9ec195e0b716a1df32c296.tar.gz
scummvm-rg350-6455c819896d58782f9ec195e0b716a1df32c296.tar.bz2
scummvm-rg350-6455c819896d58782f9ec195e0b716a1df32c296.zip
more plugin related work
svn-id: r10098
Diffstat (limited to 'common')
-rw-r--r--common/engine.cpp47
-rw-r--r--common/engine.h28
-rw-r--r--common/gameDetector.cpp148
-rw-r--r--common/gameDetector.h39
-rw-r--r--common/main.cpp13
-rw-r--r--common/plugins.cpp74
-rw-r--r--common/plugins.h14
-rw-r--r--common/timer.cpp2
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);
}
}
}