diff options
author | Max Horn | 2003-09-17 22:41:01 +0000 |
---|---|---|
committer | Max Horn | 2003-09-17 22:41:01 +0000 |
commit | c1a678afeb5100a99030bb51782e5de98d771997 (patch) | |
tree | bae1b38145179bae284a14c983c9541db7644f8c /base | |
parent | 0b16afb067a7b3f09a97507675eaa4872a59df38 (diff) | |
download | scummvm-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/.cvsignore | 1 | ||||
-rw-r--r-- | base/gameDetector.cpp | 822 | ||||
-rw-r--r-- | base/gameDetector.h | 207 | ||||
-rw-r--r-- | base/main.cpp | 313 | ||||
-rw-r--r-- | base/module.mk | 16 | ||||
-rw-r--r-- | base/plugins.cpp | 118 | ||||
-rw-r--r-- | base/plugins.h | 83 |
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 |