[Scummvm-cvs-logs] CVS: scummvm/base .cvsignore,NONE,1.1 gameDetector.cpp,NONE,1.1 gameDetector.h,NONE,1.1 main.cpp,NONE,1.1 module.mk,NONE,1.1 plugins.cpp,NONE,1.1 plugins.h,NONE,1.1

Max Horn fingolfin at users.sourceforge.net
Wed Sep 17 15:42:01 CEST 2003


Update of /cvsroot/scummvm/scummvm/base
In directory sc8-pr-cvs1:/tmp/cvs-serv4274/base

Added Files:
	.cvsignore gameDetector.cpp gameDetector.h main.cpp module.mk 
	plugins.cpp plugins.h 
Log Message:
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)

--- NEW FILE: .cvsignore ---
.deps

--- NEW FILE: gameDetector.cpp ---
/* 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: /cvsroot/scummvm/scummvm/base/gameDetector.cpp,v 1.1 2003/09/17 22:40:55 fingolfin Exp $
 *
 */

#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;
}

--- NEW FILE: gameDetector.h ---
/* 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: /cvsroot/scummvm/scummvm/base/gameDetector.h,v 1.1 2003/09/17 22:40:55 fingolfin Exp $
 *
 */

#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

--- NEW FILE: main.cpp ---
/* 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: /cvsroot/scummvm/scummvm/base/main.cpp,v 1.1 2003/09/17 22:40:55 fingolfin Exp $
 *
 */

/*! \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

--- NEW FILE: module.mk ---
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

--- NEW FILE: plugins.cpp ---
/* 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: /cvsroot/scummvm/scummvm/base/plugins.cpp,v 1.1 2003/09/17 22:40:55 fingolfin Exp $
 *
 */

#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();
}

--- NEW FILE: plugins.h ---
/* 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: /cvsroot/scummvm/scummvm/base/plugins.h,v 1.1 2003/09/17 22:40:55 fingolfin Exp $
 *
 */

#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





More information about the Scummvm-git-logs mailing list