aboutsummaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorMax Horn2003-09-17 22:41:01 +0000
committerMax Horn2003-09-17 22:41:01 +0000
commitc1a678afeb5100a99030bb51782e5de98d771997 (patch)
treebae1b38145179bae284a14c983c9541db7644f8c /base
parent0b16afb067a7b3f09a97507675eaa4872a59df38 (diff)
downloadscummvm-rg350-c1a678afeb5100a99030bb51782e5de98d771997.tar.gz
scummvm-rg350-c1a678afeb5100a99030bb51782e5de98d771997.tar.bz2
scummvm-rg350-c1a678afeb5100a99030bb51782e5de98d771997.zip
new module 'base'; moved gameDetector.*, main.cpp and base/plugins.* there (this removes the need for an ugly hack in the build system, and is also conceptionally cleaner)
svn-id: r10282
Diffstat (limited to 'base')
-rw-r--r--base/.cvsignore1
-rw-r--r--base/gameDetector.cpp822
-rw-r--r--base/gameDetector.h207
-rw-r--r--base/main.cpp313
-rw-r--r--base/module.mk16
-rw-r--r--base/plugins.cpp118
-rw-r--r--base/plugins.h83
7 files changed, 1560 insertions, 0 deletions
diff --git a/base/.cvsignore b/base/.cvsignore
new file mode 100644
index 0000000000..39a06683b7
--- /dev/null
+++ b/base/.cvsignore
@@ -0,0 +1 @@
+.deps
diff --git a/base/gameDetector.cpp b/base/gameDetector.cpp
new file mode 100644
index 0000000000..a7f468f4fa
--- /dev/null
+++ b/base/gameDetector.cpp
@@ -0,0 +1,822 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2003 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+#include "backends/intern.h"
+#include "base/gameDetector.h"
+#include "base/plugins.h"
+#include "common/config-file.h"
+#include "common/engine.h"
+#include "common/scaler.h" // Only for gfx_modes
+#include "sound/mididrv.h"
+#include "sound/mixer.h"
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#define CHECK_OPTION() if ((current_option != NULL) || (*s != '\0')) goto ShowHelpAndExit
+#define HANDLE_OPTION() if ((*s == '\0') && (current_option == NULL)) goto ShowHelpAndExit; \
+ if ((*s != '\0') && (current_option != NULL)) goto ShowHelpAndExit; \
+ option = (*s == '\0' ? current_option : s); \
+ current_option = NULL
+#define HANDLE_OPT_OPTION() if ((*s != '\0') && (current_option != NULL)) goto ShowHelpAndExit; \
+ if ((*s == '\0') && (current_option == NULL)) option = NULL; \
+ else option = (*s == '\0' ? current_option : s); \
+ current_option = NULL
+
+// DONT FIXME: DO NOT ORDER ALPHABETICALY, THIS IS ORDERED BY IMPORTANCE/CATEGORY! :)
+#ifdef __PALM_OS__
+static const char USAGE_STRING[] = "NoUsageString"; // save more data segment space
+#else
+static const char USAGE_STRING[] =
+ "ScummVM - Graphical Adventure Game Interpreter\n"
+ "Syntax:\n"
+ "\tscummvm [OPTIONS] [game]\n"
+ "Options:\n"
+ "\t-p<path> - Look for game in <path>\n"
+ "\t-x[<num>] - Load this savegame (default: 0 - autosave)\n"
+ "\t-f - Full-screen mode (-F forces window mode.)\n"
+ "\t-g<mode> - Graphics mode (normal,2x,3x,2xsai,super2xsai,\n"
+ "\t supereagle,advmame2x, advmame3x,tv2x,dotmatrix)\n"
+ "\t-e<mode> - Set music engine (see README for details)\n"
+ "\t-q<lang> - Specify language (en,de,fr,it,pt,es,jp,zh,kr,se,\n"
+ "\t gb,hb)\n"
+ "\n"
+ "\t-c<num> - Use cdrom <num> for cd audio\n"
+ "\t-m<num> - Set music volume to <num> (0-255)\n"
+ "\t-o<num> - Set master volume to <num> (0-255)\n"
+ "\t-s<num> - Set sfx volume to <num> (0-255)\n"
+ "\t-t<num> - Set music tempo (50-200, default 100%%)\n"
+ "\n"
+ "\t-n - No subtitles for speech\n"
+ "\t-y - Set text speed (default: 60)\n"
+ "\n"
+ "\t-l<file> - Load config file instead of default\n"
+#if defined(UNIX)
+ "\t-w[<file>] - Write to config file [~/.scummvmrc]\n"
+#else
+ "\t-w[<file>] - Write to config file [scummvm.ini]\n"
+#endif
+ "\t-v - Show version info and exit\n"
+ "\t-h - Display this text and exit\n"
+ "\t-z - Display list of games\n"
+ "\n"
+ "\t-b<num> - Pass number to the boot script (boot param)\n"
+ "\t-d[<num>] - Enable debug output (debug level [1])\n"
+ "\t-u - Dump scripts\n"
+ "\n"
+ "\t--platform= - Specify version of game (amiga,atari-st,macintosh)\n"
+ "\t--multi-midi - Enable combination Adlib and native MIDI\n"
+ "\t--native-mt32 - True Roland MT-32 (disable GM emulation)\n"
+ "\t--fullscreen - Full-screen mode (same as -f)\n"
+ "\t--aspect-ratio - Enable aspect ratio correction\n"
+#ifndef DISABLE_SCUMM
+ "\t--demo-mode - Start demo mode of Maniac Mansion (Classic version)\n"
+#endif
+#ifndef DISABLE_SKY
+ "\t--floppy-intro - Use floppy version intro for Beneath a Steel Sky CD\n"
+#endif
+ "\n"
+ "The meaning of long options can be inverted by prefixing them with \"no-\",\n"
+ "e.g. \"--no-aspect-ratio\".\n"
+;
+#endif
+
+static const struct GraphicsMode gfx_modes[] = {
+ {"normal", "Normal (no scaling)", GFX_NORMAL},
+ {"1x", "Normal (no scaling)", GFX_NORMAL},
+#ifndef __PALM_OS__ // reduce contant data size
+ {"2x", "2x", GFX_DOUBLESIZE},
+ {"3x", "3x", GFX_TRIPLESIZE},
+ {"2xsai", "2xSAI", GFX_2XSAI},
+ {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI},
+ {"supereagle", "SuperEagle", GFX_SUPEREAGLE},
+ {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X},
+ {"advmame3x", "AdvMAME3x", GFX_ADVMAME3X},
+ {"tv2x", "TV2x", GFX_TV2X},
+ {"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
+ {"opengl", "OpenGL", GFX_BILINEAR},
+#else
+ {"flipping", "Page Flipping", GFX_FLIPPING},
+ {"dbuffer", "Double Buffer", GFX_DOUBLEBUFFER},
+ {"wide", "Wide (HiRes+ only)", GFX_WIDE},
+#endif
+ {0, 0, 0}
+};
+
+static const struct Language languages[] = {
+ {"en", "English", EN_USA},
+ {"de", "German", DE_DEU},
+ {"fr", "French", FR_FRA},
+ {"it", "Italian", IT_ITA},
+ {"pt", "Portuguese", PT_BRA},
+ {"es", "Spanish", ES_ESP},
+ {"jp", "Japanese", JA_JPN},
+ {"zh", "Chinese (Taiwan)", ZH_TWN},
+ {"kr", "Korean", KO_KOR},
+ {"gb", "English", EN_GRB},
+ {"se", "Swedish", SE_SWE},
+ {"hb", "Hebrew", HB_HEB},
+ {0, 0, 0}
+};
+
+static const struct MusicDriver music_drivers[] = {
+ {"auto", "Default", MD_AUTO},
+ {"null", "No music", MD_NULL},
+#ifndef __PALM_OS__ // reduce contant data size
+ {"windows", "Windows MIDI", MD_WINDOWS},
+ {"seq", "SEQ", MD_SEQ},
+ {"qt", "QuickTime", MD_QTMUSIC},
+ {"core", "CoreAudio", MD_COREAUDIO},
+ {"etude", "Etude", MD_ETUDE},
+ {"alsa", "ALSA", MD_ALSA},
+ {"adlib", "Adlib", MD_ADLIB},
+ {"pcspk", "PC Speaker", MD_PCSPK},
+ {"pcjr", "IBM PCjr", MD_PCJR},
+#else
+ {"ypa1", "Yamaha Pa1", MD_YPA1},
+#endif
+ {0, 0, 0}
+};
+
+
+GameDetector::GameDetector() {
+ _fullScreen = false;
+ _aspectRatio = false;
+
+ _master_volume = kDefaultMasterVolume;
+ _music_volume = kDefaultMusicVolume;
+ _sfx_volume = kDefaultSFXVolume;
+ _amiga = false;
+ _platform = 0;
+ _language = 0;
+
+#ifndef DISABLE_SCUMM
+ _demo_mode = false;
+#endif
+
+#ifndef DISABLE_SKY
+ _floppyIntro = false;
+#endif
+
+ _talkSpeed = 60;
+ _debugMode = 0;
+ _debugLevel = 0;
+ _dumpScripts = 0;
+ _noSubtitles = false;
+ _bootParam = 0;
+
+ _gameDataPath = 0;
+ _gameTempo = 0;
+ _midi_driver = MD_AUTO;
+ _game.id = 0;
+ _game.features = 0;
+ _plugin = 0;
+
+ _multi_midi = false;
+ _native_mt32 = false;
+
+ _cdrom = 0;
+ _save_slot = 0;
+
+ _saveconfig = false;
+ _confirmExit = false;
+
+#ifndef _WIN32_WCE
+ _gfx_mode = GFX_DOUBLESIZE;
+#else
+ _gfx_mode = GFX_NORMAL;
+#endif
+ _default_gfx_mode = true;
+}
+
+void GameDetector::updateconfig() {
+ const char *val;
+
+ _amiga = g_config->getBool("amiga", _amiga);
+
+ _platform = g_config->getInt("platform", _platform);
+
+ _save_slot = g_config->getInt("save_slot", _save_slot);
+
+ _cdrom = g_config->getInt("cdrom", _cdrom);
+
+ if ((val = g_config->get("music_driver")))
+ if (!parseMusicDriver(val)) {
+ printf("Error in the config file: invalid music_driver.\n");
+ printf(USAGE_STRING);
+ exit(-1);
+ }
+
+ _fullScreen = g_config->getBool("fullscreen", _fullScreen);
+ _aspectRatio = g_config->getBool("aspect_ratio", _aspectRatio);
+
+ if ((val = g_config->get("gfx_mode")))
+ if ((_gfx_mode = parseGraphicsMode(val)) == -1) {
+ printf("Error in the config file: invalid gfx_mode.\n");
+ printf(USAGE_STRING);
+ exit(-1);
+ }
+
+#ifndef DISABLE_SKY
+ _floppyIntro = g_config->getBool("floppy_intro", _floppyIntro);
+#endif
+
+#ifndef DISABLE_SCUMM
+ _demo_mode = g_config->getBool("demo_mode", _demo_mode);
+#endif
+
+ if ((val = g_config->get("language")))
+ if ((_language = parseLanguage(val)) == -1) {
+ printf("Error in the config file: invalid language.\n");
+ printf(USAGE_STRING);
+ exit(-1);
+ }
+
+ _master_volume = g_config->getInt("master_volume", _master_volume);
+
+ _music_volume = g_config->getInt("music_volume", _music_volume);
+
+ _noSubtitles = g_config->getBool("nosubtitles", _noSubtitles ? true : false);
+
+ if ((val = g_config->get("path")))
+ _gameDataPath = strdup(val);
+
+ _sfx_volume = g_config->getInt("sfx_volume", _sfx_volume);
+
+ _debugLevel = g_config->getInt("debuglevel", _debugLevel);
+ if (_debugLevel)
+ _debugMode = true;
+
+ // We use strtol for the tempo to allow it to be specified in hex.
+ if ((val = g_config->get("tempo")))
+ _gameTempo = strtol(val, NULL, 0);
+
+ _talkSpeed = g_config->getInt("talkspeed", _talkSpeed);
+
+ _confirmExit = g_config->getBool("confirm_exit", _confirmExit ? true : false);
+
+ _multi_midi = g_config->getBool ("multi_midi", _multi_midi);
+ _native_mt32 = g_config->getBool ("native_mt32", _native_mt32);
+}
+
+void GameDetector::list_games() {
+ const PluginList &plugins = g_pluginManager->getPlugins();
+ const TargetSettings *v;
+ const char *config;
+
+ printf("Game Full Title Config\n"
+ "---------------- ------------------------------------------------------ -------\n");
+
+ 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 Plugin **plugin) const {
+ // Find the TargetSettings for this target
+ assert(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) {
+ if (plugin)
+ *plugin = plugins[i];
+ return target;
+ }
+ }
+ return 0;
+}
+
+void GameDetector::parseCommandLine(int argc, char **argv) {
+ int i;
+ char *s;
+ char *current_option = NULL;
+ char *option = NULL;
+ char c;
+ bool long_option_value;
+ _save_slot = -1;
+
+ // Parse the arguments
+ // into a transient "_COMMAND_LINE" config comain.
+ g_config->set_domain ("_COMMAND_LINE");
+ for (i = argc - 1; i >= 1; i--) {
+ s = argv[i];
+
+ if (s[0] == '-') {
+ s++;
+ c = *s++;
+ switch (tolower(c)) {
+ case 'b':
+ HANDLE_OPTION();
+ _bootParam = atoi(option);
+ break;
+ case 'c':
+ HANDLE_OPTION();
+ _cdrom = atoi(option);
+ g_config->setInt("cdrom", _cdrom);
+ break;
+ case 'd':
+ HANDLE_OPT_OPTION();
+ if (option != NULL)
+ _debugLevel = atoi(option);
+ if (_debugLevel) {
+ _debugMode = true;
+ printf("Debuglevel (from command line): %d\n", _debugLevel);
+ }
+ break;
+ case 'e':
+ HANDLE_OPTION();
+ if (!parseMusicDriver(option))
+ goto ShowHelpAndExit;
+ g_config->set("music_driver", option);
+ break;
+ case 'f':
+ CHECK_OPTION();
+ _fullScreen = (c == 'f');
+ g_config->setBool("fullscreen", _fullScreen);
+ g_config->setBool("fullscreen", _fullScreen, "scummvm");
+ break;
+ case 'g':
+ HANDLE_OPTION();
+ _gfx_mode = parseGraphicsMode(option);
+ if (_gfx_mode == -1)
+ goto ShowHelpAndExit;
+ g_config->set("gfx_mode", option);
+ g_config->set("gfx_mode", option, "scummvm");
+ break;
+ // case 'h': reserved for help
+ // case 'j': reserved for joystick select
+ case 'l':
+ HANDLE_OPTION();
+ {
+ Config *newconfig = new Config(option, "scummvm");
+ g_config->merge_config(*newconfig);
+ delete newconfig;
+ updateconfig();
+ break;
+ }
+ break;
+ case 'm':
+ HANDLE_OPTION();
+ _music_volume = atoi(option);
+ g_config->setInt("music_volume", _music_volume);
+ break;
+ case 'n':
+ CHECK_OPTION();
+ _noSubtitles = (c == 'n');
+ g_config->setBool("nosubtitles", _noSubtitles ? true : false);
+ break;
+ case 'o':
+ HANDLE_OPTION();
+ _master_volume = atoi(option);
+ g_config->setInt("master_volume", _master_volume);
+ break;
+ case 'p':
+ HANDLE_OPTION();
+ _gameDataPath = option;
+ g_config->set("path", _gameDataPath);
+ break;
+ case 'q':
+ HANDLE_OPTION();
+ _language = parseLanguage(option);
+ if (_language == -1)
+ goto ShowHelpAndExit;
+ g_config->set("language", option);
+ break;
+ case 'r':
+ HANDLE_OPTION();
+ // Ignore -r for now, to ensure backward compatibility.
+ break;
+ case 's':
+ HANDLE_OPTION();
+ _sfx_volume = atoi(option);
+ g_config->setInt("sfx_volume", _sfx_volume);
+ break;
+ case 't':
+ HANDLE_OPTION();
+ _gameTempo = strtol(option, 0, 0);
+ g_config->set("tempo", option);
+ break;
+ case 'u':
+ CHECK_OPTION();
+ _dumpScripts = true;
+ break;
+ case 'v':
+ CHECK_OPTION();
+ printf("%s\n", gScummVMFullVersion);
+ exit(1);
+ case 'w':
+ _saveconfig = true;
+ g_config->set_writing(true);
+ HANDLE_OPT_OPTION();
+ if (option != NULL)
+ g_config->set_filename(option);
+ break;
+ case 'x':
+ _save_slot = 0;
+ HANDLE_OPT_OPTION();
+ if (option != NULL) {
+ _save_slot = atoi(option);
+ g_config->setInt("save_slot", _save_slot);
+ }
+ break;
+ case 'y':
+ HANDLE_OPTION();
+ _talkSpeed = atoi(option);
+ g_config->setInt("talkspeed", _talkSpeed);
+ break;
+ case 'z':
+ CHECK_OPTION();
+ list_games();
+ exit(1);
+ case '-':
+ // Long options. Let the fun begin!
+ if (!strncmp(s, "platform=", 9)) {
+ s += 9;
+ if (!strcmp (s, "amiga"))
+ _platform = 1;
+ else if (!strcmp (s, "atari-st"))
+ _platform = 2;
+ else if (!strcmp (s, "macintosh"))
+ _platform = 3;
+ else
+ goto ShowHelpAndExit;
+
+ g_config->setInt ("platform", _platform);
+ break;
+ }
+
+ if (!strncmp(s, "no-", 3)) {
+ long_option_value = false;
+ s += 3;
+ } else
+ long_option_value = true;
+
+ if (!strcmp (s, "multi-midi")) {
+ _multi_midi = long_option_value;
+ g_config->setBool ("multi_midi", _multi_midi);
+ } else if (!strcmp (s, "native-mt32")) {
+ _native_mt32 = long_option_value;
+ g_config->setBool ("native_mt32", _native_mt32);
+ } else if (!strcmp (s, "aspect-ratio")) {
+ _aspectRatio = long_option_value;
+ g_config->setBool ("aspect_ratio", _aspectRatio);
+ } else if (!strcmp (s, "fullscreen")) {
+ _fullScreen = long_option_value;
+ g_config->setBool("fullscreen", _fullScreen);
+ g_config->setBool("fullscreen", _fullScreen, "scummvm");
+#ifndef DISABLE_SCUMM
+ } else if (!strcmp (s, "demo-mode")) {
+ _demo_mode = long_option_value;
+ g_config->setBool ("demo_mode", _demo_mode);
+#endif
+
+#ifndef DISABLE_SKY
+ } else if (!strcmp (s, "floppy-intro")) {
+ _floppyIntro = long_option_value;
+ g_config->setBool ("floppy_intro", _floppyIntro);
+#endif
+ } else {
+ goto ShowHelpAndExit;
+ }
+ break;
+ default:
+ goto ShowHelpAndExit;
+ }
+ } else {
+ if (i == (argc - 1)) {
+ setGame(s);
+ } else {
+ if (current_option == NULL)
+ current_option = s;
+ else
+ goto ShowHelpAndExit;
+ }
+ }
+ }
+
+ if (!_gameFileName.isEmpty())
+ g_config->flush();
+
+ return;
+
+ShowHelpAndExit:
+ printf(USAGE_STRING);
+ exit(1);
+}
+
+void GameDetector::setGame(const String &name) {
+ _gameFileName = name;
+ g_config->set_domain(name);
+ g_config->rename_domain(name, "game-specific");
+ g_config->rename_domain("game-specific", name);
+ updateconfig();
+
+ // The command line and launcher options
+ // override config file global and game-specific options.
+ g_config->set_domain("_COMMAND_LINE");
+ updateconfig();
+ g_config->set_domain("_USER_OVERRIDES");
+ updateconfig();
+ g_config->delete_domain("_COMMAND_LINE");
+ g_config->delete_domain("_USER_OVERRIDES");
+ g_config->set_domain(name);
+ if (_debugMode)
+ printf("Debuglevel (from config): %d\n", _debugLevel);
+}
+
+int GameDetector::parseGraphicsMode(const char *s) {
+ const GraphicsMode *gm = gfx_modes;
+ while(gm->name) {
+ if (!scumm_stricmp(gm->name, s)) {
+ _default_gfx_mode = false;
+ return gm->id;
+ }
+ gm++;
+ }
+
+ return -1;
+}
+
+int GameDetector::parseLanguage(const char *s) {
+ const Language *l = languages;
+ while(l->name) {
+ if (!scumm_stricmp(l->name, s))
+ return l->id;
+ l++;
+ }
+
+ return -1;
+}
+
+bool GameDetector::isMusicDriverAvailable(int drv) {
+ switch(drv) {
+ case MD_AUTO:
+ case MD_NULL: return true;
+#ifndef __PALM_OS__ // don't show it on palmos
+ case MD_ADLIB:
+ case MD_PCSPK:
+ case MD_PCJR: return true;
+#else
+ case MD_YPA1: return true;
+#endif
+#if defined(WIN32) && !defined(_WIN32_WCE)
+ case MD_WINDOWS: return true;
+#endif
+#if defined(__MORPHOS__)
+ case MD_ETUDE: return true;
+#endif
+#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX)
+ case MD_SEQ: return true;
+#endif
+#if defined(MACOSX) || defined(macintosh)
+ case MD_QTMUSIC: return true;
+#endif
+#if defined(MACOSX)
+ case MD_COREAUDIO: return true;
+#endif
+#if defined(UNIX) && defined(USE_ALSA)
+ case MD_ALSA: return true;
+#endif
+ }
+ return false;
+}
+
+const MusicDriver *GameDetector::getMusicDrivers() {
+ return music_drivers;
+}
+
+
+bool GameDetector::parseMusicDriver(const char *s) {
+ const MusicDriver *md = music_drivers;
+
+ while (md->name) {
+ if (!scumm_stricmp(md->name, s)) {
+ _midi_driver = md->id;
+ return true;
+ }
+ md++;
+ }
+
+ return false;
+}
+
+bool GameDetector::detectGame() {
+ const TargetSettings *target;
+ const char *realGame, *basename;
+ _game.id = 0;
+ _gameText.clear();
+
+ realGame = g_config->get("gameid");
+ if (!realGame)
+ realGame = _gameFileName.c_str();
+ printf("Looking for %s\n", realGame);
+
+ target = findTarget(realGame, &_plugin);
+
+ if (target) {
+ _game = *target;
+ if ((basename = g_config->get("basename"))) {
+ // FIXME: What is this good for?
+ _game.targetName = basename;
+ }
+ _gameText = _game.description;
+ printf("Trying to start game '%s'\n", _game.description);
+ return true;
+ } else {
+ printf("Failed game detection\n");
+ return false;
+ }
+}
+
+const ScummVM::String& GameDetector::getGameName() {
+ if (_gameText.isEmpty()) {
+ _gameText = "Unknown game: \"";
+ _gameText += _gameFileName;
+ _gameText += "\"";
+ }
+ return _gameText;
+}
+
+int GameDetector::detectMain() {
+ if (_gameFileName.isEmpty()) {
+ warning("No game was specified...");
+ return (-1);
+ }
+
+ if (!detectGame()) {
+ warning("Game detection failed. Using default settings");
+ _gameText = "Please choose a game";
+ }
+
+ /* Use the adlib sound driver if auto mode is selected,
+ * and the game is one of those that want adlib as
+ * default, OR if the game is an older game that doesn't
+ * support anything else anyway. */
+ if (_midi_driver == MD_AUTO) {
+ if (_game.midi & MDT_PREFER_NATIVE)
+ _midi_driver = getMidiDriverType();
+ else
+ _midi_driver = MD_ADLIB;
+ }
+ bool nativeMidiDriver =
+ (_midi_driver != MD_NULL && _midi_driver != MD_ADLIB &&
+ _midi_driver != MD_PCSPK && _midi_driver != MD_PCJR);
+ if (nativeMidiDriver && !(_game.midi & MDT_NATIVE))
+ _midi_driver = MD_ADLIB;
+ if (_midi_driver == MD_ADLIB && !(_game.midi & MDT_ADLIB))
+ _midi_driver = MD_PCJR;
+ if ((_midi_driver == MD_PCSPK || _midi_driver == MD_PCJR) && !(_game.midi & MDT_PCSPK))
+ _midi_driver = MD_NULL;
+
+ if (!_gameDataPath) {
+ warning("No path was provided. Assuming the data files are in the current directory");
+ _gameDataPath = strdup("");
+#ifndef __PALM_OS__ // add last slash also in File::fopenNoCase, so this is not needed
+ } else if (_gameDataPath[strlen(_gameDataPath)-1] != '/'
+#ifdef __MORPHOS__
+ && _gameDataPath[strlen(_gameDataPath)-1] != ':'
+#endif
+ && _gameDataPath[strlen(_gameDataPath)-1] != '\\') {
+ char slashless[1024]; /* Append slash to path */
+ strcpy(slashless, _gameDataPath);
+
+ // need to allocate 2 extra bytes, one for the "/" and one for the NULL terminator
+ _gameDataPath = (char *)malloc((strlen(slashless) + 2) * sizeof(char));
+ sprintf(_gameDataPath, "%s/", slashless);
+#endif
+ }
+
+ return (0);
+}
+
+OSystem *GameDetector::createSystem() {
+#if defined(USE_NULL_DRIVER)
+ return OSystem_NULL_create();
+#elif defined(__DC__)
+ return OSystem_Dreamcast_create();
+#elif defined(X11_BACKEND)
+ return OSystem_X11_create();
+#elif defined(__MORPHOS__)
+ return OSystem_MorphOS_create(_game.id, _gfx_mode, _fullScreen);
+#elif defined(_WIN32_WCE)
+ return OSystem_WINCE3_create();
+#elif defined(MACOS_CARBON)
+ return OSystem_MAC_create(_gfx_mode, _fullScreen);
+#elif defined(__GP32__) // ph0x
+ return OSystem_GP32_create(GFX_NORMAL, true);
+#elif defined(__PALM_OS__) //chrilith
+ return OSystem_PALMOS_create(_gfx_mode, _fullScreen);
+#else
+ /* SDL is the default driver for now */
+ return OSystem_SDL_create(_gfx_mode, _fullScreen, _aspectRatio);
+#endif
+}
+
+Engine *GameDetector::createEngine(OSystem *system) {
+ Engine *engine = NULL;
+
+ assert(_plugin);
+ engine = _plugin->createInstance(this, system);
+
+ return engine;
+}
+
+int GameDetector::getMidiDriverType() {
+
+ if (_midi_driver != MD_AUTO) return _midi_driver;
+
+#if defined (WIN32) && !defined(_WIN32_WCE)
+ return MD_WINDOWS; // MD_WINDOWS is default MidiDriver on windows targets
+#elif defined(MACOSX)
+ return MD_COREAUDIO;
+#elif defined(__PALM_OS__) // must be before mac
+ return MD_YPA1;
+#elif defined(macintosh)
+ return MD_QTMUSIC;
+#elif defined(__MORPHOS__)
+ return MD_ETUDE;
+#elif defined (_WIN32_WCE) || defined(UNIX) || defined(X11_BACKEND)
+ // Always use MIDI emulation via adlib driver on CE and UNIX device
+
+ // TODO: We should, for the Unix targets, attempt to detect
+ // whether a sequencer is available, and use it instead.
+ return MD_ADLIB;
+#endif
+ return MD_NULL;
+}
+
+SoundMixer *GameDetector::createMixer() {
+ return new SoundMixer();
+}
+
+MidiDriver *GameDetector::createMidi() {
+ int drv = getMidiDriverType();
+
+ switch(drv) {
+ case MD_NULL: return MidiDriver_NULL_create();
+ // In the case of Adlib, we won't specify anything.
+ // IMuse is designed to set up its own Adlib driver
+ // if need be, and we only have to specify a native
+ // driver.
+ case MD_ADLIB: return NULL;
+
+ // Right now PC Speaker and PCjr are handled
+ // outside the MidiDriver architecture, so
+ // don't create anything for now.
+ case MD_PCSPK:
+ case MD_PCJR: return NULL;
+#if defined(__PALM_OS__)
+ case MD_YPA1: return MidiDriver_YamahaPa1_create();
+#endif
+#if defined(WIN32) && !defined(_WIN32_WCE)
+ case MD_WINDOWS: return MidiDriver_WIN_create();
+#endif
+#if defined(__MORPHOS__)
+ case MD_ETUDE: return MidiDriver_ETUDE_create();
+#endif
+#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX)
+ case MD_SEQ: return MidiDriver_SEQ_create();
+#endif
+#if (defined(MACOSX) || defined(macintosh)) && !defined(__PALM_OS__)
+ case MD_QTMUSIC: return MidiDriver_QT_create();
+#endif
+#if defined(MACOSX)
+ case MD_COREAUDIO: return MidiDriver_CORE_create();
+#endif
+#if defined(UNIX) && defined(USE_ALSA)
+ case MD_ALSA: return MidiDriver_ALSA_create();
+#endif
+ }
+
+ error("Invalid midi driver selected");
+ return NULL;
+}
diff --git a/base/gameDetector.h b/base/gameDetector.h
new file mode 100644
index 0000000000..32eaf96630
--- /dev/null
+++ b/base/gameDetector.h
@@ -0,0 +1,207 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2003 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef GAMEDETECTOR_H
+#define GAMEDETECTOR_H
+
+#include "common/str.h"
+
+class Engine;
+class GameDetector;
+class MidiDriver;
+class OSystem;
+class SoundMixer;
+class Plugin;
+
+/** Default sound/music volumes.
+ * @todo move this to a better place.
+ */
+enum {
+ kDefaultMasterVolume = 192,
+ kDefaultSFXVolume = 192,
+ kDefaultMusicVolume = 192
+};
+
+/** Global (shared) game feature flags. */
+enum {
+ GF_DEFAULT_TO_1X_SCALER = 1 << 31
+};
+
+/* Languages
+ * note: values 0->8 are are _needed_ for scripts in comi please don't
+ * remove/change fixed numbers from this enum
+ */
+enum {
+ EN_USA = 0,
+ DE_DEU = 1,
+ FR_FRA = 2,
+ IT_ITA = 3,
+ PT_BRA = 4,
+ ES_ESP = 5,
+ JA_JPN = 6,
+ ZH_TWN = 7,
+ KO_KOR = 8,
+ SE_SWE = 9,
+ EN_GRB = 10,
+ HB_HEB = 20
+};
+
+enum MidiDriverType {
+ MDT_NONE = 0,
+ MDT_PCSPK = 1, // MD_PCSPK and MD_PCJR
+ MDT_ADLIB = 2, // MD_ADLIB
+ MDT_NATIVE = 4, // Everything else
+ MDT_PREFER_NATIVE = 8
+};
+
+struct TargetSettings {
+ const char *targetName;
+ const char *description;
+ byte id, version;
+ int midi; // MidiDriverType values
+ uint32 features;
+ const char *detectname;
+};
+
+struct MusicDriver {
+ const char *name;
+ const char *description;
+ int id;
+};
+
+struct GraphicsMode {
+ const char *name;
+ const char *description;
+ int id;
+};
+
+struct Language {
+ const char *name;
+ const char *description;
+ 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;
+
+public:
+ static const MusicDriver *getMusicDrivers();
+ static bool isMusicDriverAvailable(int drv);
+
+public:
+ GameDetector();
+
+ void parseCommandLine(int argc, char **argv);
+ int detectMain();
+ void setGame(const String &name);
+ const String& getGameName(void);
+
+ String _gameFileName;
+ TargetSettings _game;
+ const Plugin *_plugin;
+
+ bool _fullScreen;
+ bool _aspectRatio;
+
+ int _master_volume;
+ int _music_volume;
+ int _sfx_volume;
+ bool _amiga;
+ int _platform;
+ int _language;
+
+ bool _demo_mode;
+ bool _floppyIntro;
+
+ uint16 _talkSpeed;
+ uint16 _debugMode;
+ uint16 _debugLevel;
+ bool _dumpScripts;
+ bool _noSubtitles;
+ uint16 _bootParam;
+
+ char *_gameDataPath;
+ int _gameTempo;
+ int _midi_driver;
+
+ int _gfx_mode;
+ bool _default_gfx_mode;
+
+ bool _multi_midi;
+ bool _native_mt32;
+
+ int _cdrom;
+ int _save_slot;
+
+ bool _saveconfig;
+ bool _confirmExit;
+
+public:
+ OSystem *createSystem();
+ Engine *createEngine(OSystem *system);
+
+ SoundMixer *createMixer();
+ MidiDriver *createMidi();
+ int getMidiDriverType();
+
+ int parseGraphicsMode(const char *s);
+ void updateconfig();
+
+ const TargetSettings *findTarget(const char *targetName, const Plugin **plugin = NULL) const;
+
+protected:
+ String _gameText;
+
+ bool detectGame(void);
+ bool parseMusicDriver(const char *s);
+ int parseLanguage(const char *s);
+ void list_games();
+};
+
+#endif
diff --git a/base/main.cpp b/base/main.cpp
new file mode 100644
index 0000000000..f549c2b831
--- /dev/null
+++ b/base/main.cpp
@@ -0,0 +1,313 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2003 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+/*! \mainpage %ScummVM Source Reference
+ *
+ * These pages contains a cross referenced documentation for the %ScummVM source code,
+ * generated with Doxygen (http://www.doxygen.org) directly from the source.
+ * Currently not much is actually properly documented, but at least you can get an overview
+ * of almost all the classes, methods and variables, and how they interact.
+ */
+
+#include "stdafx.h"
+#include "base/gameDetector.h"
+#include "base/plugins.h"
+#include "common/config-file.h"
+#include "common/engine.h"
+#include "common/scaler.h" // For GFX_NORMAL
+#include "gui/newgui.h"
+#include "gui/launcher.h"
+#include "gui/message.h"
+
+/*
+ * Version string and build date string. These can be used by anything that
+ * wants to display this information to the user (e.g. about dialog).
+ *
+ * Note: it would be very nice if we could instead of (or in addition to) the
+ * build date present a date which corresponds to the date our source files
+ * were last changed. To understand the difference, imagine that a user
+ * makes a checkout of CVS on January 1, then after a week compiles it
+ * (e.g. after doing a 'make clean'). The build date then will say January 8
+ * even though the files were last changed on January 1.
+ *
+ * Another problem is that __DATE__/__TIME__ depend on the local time zone.
+ *
+ * It's clear that such a "last changed" date would be much more useful to us
+ * for feedback purposes. After all, when somebody files a bug report, we
+ * don't care about the build date, we want to know which date their checkout
+ * was made. This is even more important now since anon CVS lags a few
+ * days behind developer CVS.
+ *
+ * So, how could we implement this? At least on unix systems, a special script
+ * could do it. Basically, that script would run over all .cpp/.h files and
+ * parse the CVS 'Header' keyword we have in our file headers.
+ * That line contains a date/time in GMT. Now, the script just has to collect
+ * all these times and find the latest. This time then would be inserted into
+ * a header file or so (common/date.h ?) which engine.cpp then could
+ * include and put into a global variable analog to gScummVMBuildDate.
+ *
+ * Drawback: scanning all source/header files will be rather slow. Also, this
+ * only works on systems which can run powerful enough scripts (so I guess
+ * Visual C++ would be out of the game here? don't know VC enough to be sure).
+ *
+ * Another approach would be to somehow get CVS to update a global file
+ * (e.g. LAST_CHANGED) whenever any checkins are made. That would be
+ * faster and work w/o much "logic" on the client side, in particular no
+ * scripts have to be run. The problem with this is that I am not even
+ * sure it's actually possible! Modifying files during commit time is trivial
+ * to setup, but I have no idea if/how one can also change files which are not
+ * currently being commit'ed.
+ */
+const char *gScummVMVersion = "0.5.3cvs";
+const char *gScummVMBuildDate = __DATE__ " " __TIME__;
+const char *gScummVMFullVersion = "ScummVM 0.5.3cvs (" __DATE__ " " __TIME__ ")";
+
+
+Config *g_config = 0;
+NewGui *g_gui = 0;
+
+#if defined(QTOPIA)
+// FIXME - why exactly is this needed?
+extern "C" int main(int argc, char *argv[]);
+#endif
+
+#if defined(MACOSX) || defined(QTOPIA)
+#include <SDL.h>
+#elif !defined(__MORPHOS__) && !defined(__DC__)
+#undef main
+#endif
+
+#if defined(UNIX)
+#include <sys/param.h>
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 256
+#endif
+#ifdef MACOSX
+#define DEFAULT_CONFIG_FILE "Library/Preferences/ScummVM Preferences"
+#else
+#define DEFAULT_CONFIG_FILE ".scummvmrc"
+#endif
+#else
+#define DEFAULT_CONFIG_FILE "scummvm.ini"
+#endif
+
+#if defined(UNIX)
+#include <signal.h>
+
+#ifndef SCUMM_NEED_ALIGNMENT
+static void handle_errors(int sig_num) {
+ error("Your system does not support unaligned memory accesses. Please rebuild with SCUMM_NEED_ALIGNMENT (signal %d)", sig_num);
+}
+#endif
+
+/* This function is here to test if the endianness / alignement compiled it is matching
+ with the one at run-time. */
+static void do_memory_test(void) {
+ unsigned char test[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
+ unsigned int value;
+ /* First test endianness */
+#ifdef SCUMM_LITTLE_ENDIAN
+ if (*((int *) test) != 0x44332211) {
+ error("Compiled as LITTLE_ENDIAN on a big endian system. Please rebuild ");
+ }
+ value = 0x55443322;
+#else
+ if (*((int *) test) != 0x11223344) {
+ error("Compiled as BIG_ENDIAN on a little endian system. Please rebuild ");
+ }
+ value = 0x22334455;
+#endif
+ /* Then check if one really supports unaligned memory accesses */
+#ifndef SCUMM_NEED_ALIGNMENT
+ signal(SIGBUS, handle_errors);
+ signal(SIGABRT, handle_errors);
+ signal(SIGSEGV, handle_errors);
+ if (*((unsigned int *) ((char *) test + 1)) != value) {
+ error("Your system does not support unaligned memory accesses. Please rebuild with SCUMM_NEED_ALIGNMENT ");
+ }
+ signal(SIGBUS, SIG_DFL);
+ signal(SIGABRT, SIG_DFL);
+ signal(SIGSEGV, SIG_DFL);
+#endif
+}
+
+#endif
+
+static void launcherDialog(GameDetector &detector, OSystem *system) {
+ // FIXME - we need to call init_size() here so that we can display for example
+ // the launcher dialog. But the Engine object will also call it again (possibly
+ // with a different widht/height!9 However, this method is not for all OSystem
+ // implementations reentrant (it is so now for the SDL backend). Thus we need
+ // to fix all backends to support it, if they don't already.
+ system->init_size(320, 200);
+
+ // FIXME - mouse cursors are currently always set via 8 bit data.
+ // Thus for now we need to setup a dummy palette. On the long run, we might
+ // want to add a set_mouse_cursor_overlay() method to OSystem, which would serve
+ // two purposes:
+ // 1) allow for 16 bit mouse cursors in overlay mode
+ // 2) no need to backup & restore the mouse cursor before/after the overlay is shown
+ const byte dummy_palette[] = {
+ 0, 0, 0, 0,
+ 0, 0, 171, 0,
+ 0, 171, 0, 0,
+ 0, 171, 171, 0,
+ 171, 0, 0, 0,
+ 171, 0, 171, 0,
+ 171, 87, 0, 0,
+ 171, 171, 171, 0,
+ 87, 87, 87, 0,
+ 87, 87, 255, 0,
+ 87, 255, 87, 0,
+ 87, 255, 255, 0,
+ 255, 87, 87, 0,
+ 255, 87, 255, 0,
+ 255, 255, 87, 0,
+ 255, 255, 255, 0,
+ };
+
+ system->set_palette(dummy_palette, 0, 16);
+
+ // FIXME - hack we use because LauncherDialog accesses g_system
+ extern OSystem *g_system;
+ g_system = system;
+
+ LauncherDialog dlg(g_gui, detector);
+ dlg.runModal();
+}
+
+int main(int argc, char *argv[]) {
+ OSystem::Property prop;
+
+#if defined(UNIX)
+ /* On Unix, do a quick endian / alignement check before starting */
+ do_memory_test();
+
+ char scummhome[MAXPATHLEN];
+ if(getenv("HOME") != NULL)
+ sprintf(scummhome,"%s/%s", getenv("HOME"), DEFAULT_CONFIG_FILE);
+ else strcpy(scummhome,DEFAULT_CONFIG_FILE);
+#else
+ char scummhome[256];
+ #if defined (WIN32) && !defined(_WIN32_WCE)
+ GetWindowsDirectory(scummhome, 256);
+ strcat(scummhome, "\\");
+ strcat(scummhome, DEFAULT_CONFIG_FILE);
+ #elif defined(__PALM_OS__)
+ strcpy(scummhome,"/PALM/Programs/ScummVM/");
+ strcat(scummhome, DEFAULT_CONFIG_FILE);
+ #else
+ strcpy(scummhome, DEFAULT_CONFIG_FILE);
+ #endif
+#endif
+
+ // 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);
+
+ // Create the system object
+ OSystem *system = detector.createSystem();
+
+ // Set initial window caption
+ prop.caption = "ScummVM";
+ system->property(OSystem::PROP_SET_WINDOW_CAPTION, &prop);
+
+ // Create the GUI manager
+ g_gui = new NewGui(system);
+
+ // Unless a game was specified, show the launcher dialog
+ if (detector._gameFileName.isEmpty())
+ launcherDialog(detector, system);
+
+ // Verify the given game name
+ if (!detector.detectMain()) {
+ // Set the window caption to the game name
+ prop.caption = g_config->get("description", detector._gameFileName);
+ if (prop.caption == NULL)
+ prop.caption = detector.getGameName().c_str();
+ system->property(OSystem::PROP_SET_WINDOW_CAPTION, &prop);
+
+ // See if the game should default to 1x scaler
+ if ((detector._default_gfx_mode) &&
+ (detector._game.features & GF_DEFAULT_TO_1X_SCALER)) {
+ prop.gfx_mode = GFX_NORMAL;
+ system->property(OSystem::PROP_SET_GFX_MODE, &prop);
+ }
+
+ // Create the game engine
+ Engine *engine = detector.createEngine(system);
+
+ // print a message if gameid is invalid
+ if (engine == NULL)
+ error("%s is an invalid target. Use the -z parameter to list targets",
+ detector._gameFileName.c_str());
+
+ // Run the game engine
+ engine->go();
+
+ // Stop all sound processing now (this prevents some race conditions later on)
+ system->clear_sound_proc();
+
+ // Free up memory
+ delete engine;
+ }
+
+ delete g_gui;
+ delete g_config;
+
+ // ...and quit (the return 0 should never be reached)
+ system->quit();
+ delete system;
+ return 0;
+}
+
+#ifndef __PALM_OS__
+void *operator new(size_t size) {
+ return memset(malloc(size), 0xE7, size);
+}
+
+void operator delete(void *ptr) {
+ free(ptr);
+}
+
+#undef free
+void free_check(void *ptr) {
+ if ((uint)ptr == 0xE7E7E7E7UL) {
+ printf("ERROR: freeing 0xE7E7E7E7\n");
+ exit(1);
+ }
+ if ((int)ptr & 1) {
+ warning("Freeing odd address 0x%x", ptr);
+ }
+ free(ptr);
+}
+#endif
diff --git a/base/module.mk b/base/module.mk
new file mode 100644
index 0000000000..e3af9b367c
--- /dev/null
+++ b/base/module.mk
@@ -0,0 +1,16 @@
+MODULE := base
+
+MODULE_OBJS := \
+ base/gameDetector.o \
+ base/main.o \
+ base/plugins.o
+
+MODULE_DIRS += \
+ base
+
+# Some of the base files depend on the values of the DISABLE_* flags defined
+# in config.mak. Hence we add an explicit make dependency on that file.
+base/gameDetector.o base/plugins.o: config.mak
+
+# Include common rules
+include common.rules
diff --git a/base/plugins.cpp b/base/plugins.cpp
new file mode 100644
index 0000000000..174a097b4d
--- /dev/null
+++ b/base/plugins.cpp
@@ -0,0 +1,118 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2003 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "base/gameDetector.h"
+#include "base/plugins.h"
+#include "common/engine.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() {
+}
+
+PluginManager::~PluginManager() {
+ // Explicitly unload all loaded plugins
+ unloadPlugins();
+}
+
+void PluginManager::loadPlugins() {
+#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() {
+ int i;
+ for (i = 0; i < _plugins.size(); i++) {
+ _plugins[i]->unloadPlugin();
+ delete _plugins[i];
+ }
+ _plugins.clear();
+}
diff --git a/base/plugins.h b/base/plugins.h
new file mode 100644
index 0000000000..8257bf1a53
--- /dev/null
+++ b/base/plugins.h
@@ -0,0 +1,83 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2003 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef COMMON_PLUGINS_H
+#define COMMON_PLUGINS_H
+
+#include "common/list.h"
+
+class Engine;
+class GameDetector;
+class OSystem;
+struct TargetSettings;
+
+/**
+ * Abstract base class for the plugin system.
+ * Subclasses for this can be used to wrap both static and dynamic
+ * plugins.
+ */
+class Plugin {
+public:
+ virtual void loadPlugin() {}
+ virtual void unloadPlugin() {}
+
+ 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.
+ *
+ * @todo Add support for dynamic plugins (this may need additional API, e.g. for a plugin path)
+ */
+class PluginManager {
+protected:
+ PluginList _plugins;
+
+public:
+ PluginManager();
+ ~PluginManager();
+
+ void loadPlugins();
+ void unloadPlugins();
+
+ const PluginList &getPlugins() { return _plugins; }
+};
+
+/**
+ * Global, shared plugin manager.
+ */
+extern PluginManager *g_pluginManager;
+
+#endif