diff options
-rw-r--r-- | common/advancedDetector.h | 40 | ||||
-rw-r--r-- | engines/agi/detection.cpp | 18 | ||||
-rw-r--r-- | engines/metaengine.h | 81 | ||||
-rw-r--r-- | engines/saga/detection.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/detection.cpp | 39 | ||||
-rw-r--r-- | engines/sword1/sword1.cpp | 28 | ||||
-rw-r--r-- | engines/sword2/sword2.cpp | 32 | ||||
-rw-r--r-- | engines/touche/detection.cpp | 19 |
8 files changed, 238 insertions, 21 deletions
diff --git a/common/advancedDetector.h b/common/advancedDetector.h index f0d6c88e4e..171673771c 100644 --- a/common/advancedDetector.h +++ b/common/advancedDetector.h @@ -26,10 +26,11 @@ #define COMMON_ADVANCED_DETECTOR_H #include "common/fs.h" +#include "common/error.h" #include "base/game.h" // For PlainGameDescriptor and GameList -#include "base/plugins.h" // For PluginError +#include "engines/metaengine.h" namespace Common { @@ -273,4 +274,41 @@ void reportUnknown(StringList &files, int md5Bytes); } // End of namespace Common +/** + * A MetaEngine implementation based around the advanced detector code. + */ +class AdvancedMetaEngine : public MetaEngine { + const Common::ADParams ¶ms; +public: + AdvancedMetaEngine(const Common::ADParams &dp) : params(dp) {} + + // To be provided by subclasses + virtual bool createInstance(OSystem *syst, Engine **engine, const Common::EncapsulatedADGameDesc &encapsulatedDesc) const = 0; + + +protected: + virtual GameList getSupportedGames() const { + return Common::AdvancedDetector::gameIDList(params); + } + virtual GameDescriptor findGame(const char *gameid) const { + return Common::AdvancedDetector::findGameID(gameid, params.list, params.obsoleteList); + } + virtual GameList detectGames(const FSList &fslist) const { + return Common::AdvancedDetector::detectAllGames(fslist, params); + } + + virtual PluginError createInstance(OSystem *syst, Engine **engine) const { + assert(engine); + Common::AdvancedDetector::upgradeTargetIfNecessary(params); + Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(params); + if (encapsulatedDesc.realDesc == 0) { + return kNoGameDataFoundError; + } + if (!createInstance(syst,engine,encapsulatedDesc)) { + return kNoGameDataFoundError; + } + return kNoError; + } +}; + #endif diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 9c0a5c3585..8c88906a99 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -2250,7 +2250,21 @@ static const Common::ADParams detectionParams = { Common::kADFlagAugmentPreferredTarget }; -bool engineCreateAgi(OSystem *syst, Engine **engine, Common::EncapsulatedADGameDesc encapsulatedDesc) { +class AgiMetaEngine : public AdvancedMetaEngine { +public: + AgiMetaEngine() : AdvancedMetaEngine(detectionParams) {} + + virtual const char *getName() const { + return "AGI preAGI + v2 + v3 Engine"; + } + virtual const char *getCopyright() const { + return "Sierra AGI Engine (C) Sierra On-Line Software"; + } + + virtual bool createInstance(OSystem *syst, Engine **engine, const Common::EncapsulatedADGameDesc &encapsulatedDesc) const; +}; + +bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::EncapsulatedADGameDesc &encapsulatedDesc) const { const Agi::AGIGameDescription *gd = (const Agi::AGIGameDescription *)(encapsulatedDesc.realDesc); bool res = true; @@ -2270,7 +2284,7 @@ bool engineCreateAgi(OSystem *syst, Engine **engine, Common::EncapsulatedADGameD return res; } -ADVANCED_DETECTOR_DEFINE_PLUGIN(AGI, engineCreateAgi, detectionParams); +META_COMPATIBLITY_WRAPPER(AGI, AgiMetaEngine); REGISTER_PLUGIN(AGI, "AGI preAGI + v2 + v3 Engine", "Sierra AGI Engine (C) Sierra On-Line Software"); diff --git a/engines/metaengine.h b/engines/metaengine.h new file mode 100644 index 0000000000..a290044d2b --- /dev/null +++ b/engines/metaengine.h @@ -0,0 +1,81 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef ENGINES_METAENGINE_H +#define ENGINES_METAENGINE_H + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/error.h" + +#include "base/game.h" + +class Engine; +class OSystem; + +/** + * A meta engine is essentially a factory for Engine instances with the + * added ability of listing and detecting supported games. + * Every engine "plugin" provides a hook to get an instance of a MetaEngine + * subclass for that "engine plugin". E.g. SCUMM povides ScummMetaEngine. + * This is then in turn used by the frontend code to detect games, + * and instantiate actual Engine objects. + */ +class MetaEngine { +public: + virtual ~MetaEngine() {} + + virtual const char *getName() const = 0; + virtual const char *getCopyright() const = 0; +// virtual int getVersion() const = 0; // TODO! + + virtual GameList getSupportedGames() const = 0; + virtual GameDescriptor findGame(const char *gameid) const = 0; + virtual GameList detectGames(const FSList &fslist) const = 0; + + virtual PluginError createInstance(OSystem *syst, Engine **engine) const = 0; +}; + + +/** + * The META_COMPATIBLITY_WRAPPER macro is there to ease the transition from the + * old plugin API to the new MetaEngine class. Ultimately, this macro will go + * and REGISTER_PLUGIN will be changedd to simply take an ID and a METACLASS. + * Until then, use META_COMPATIBLITY_WRAPPER + REGISTER_PLUGIN. + */ +#define META_COMPATIBLITY_WRAPPER(ID,METACLASS) \ + static MetaEngine &getMetaEngine() { \ + static MetaEngine *meta = 0; \ + if (!meta) meta = new METACLASS(); \ + return *meta; \ + } \ + GameList Engine_##ID##_gameIDList() { return getMetaEngine().getSupportedGames(); } \ + GameDescriptor Engine_##ID##_findGameID(const char *gameid) { return getMetaEngine().findGame(gameid); } \ + PluginError Engine_##ID##_create(OSystem *syst, Engine **engine) { return getMetaEngine().createInstance(syst, engine); } \ + GameList Engine_##ID##_detectGames(const FSList &fslist) { return getMetaEngine().detectGames(fslist); } \ + void dummyFuncToAllowTrailingSemicolon() + + + +#endif diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index aeac536af3..74acdf0743 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -27,6 +27,8 @@ #include "saga/saga.h" +#include "base/plugins.h" + #include "common/config-manager.h" #include "common/advancedDetector.h" diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 8eb59ea66a..c85500fcc9 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -36,6 +36,9 @@ #include "scumm/intern.h" #include "scumm/he/intern_he.h" +#include "engines/metaengine.h" + + namespace Scumm { enum { @@ -662,20 +665,33 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com using namespace Scumm; -GameList Engine_SCUMM_gameIDList() { +class ScummMetaEngine : public MetaEngine { +public: + virtual const char *getName() const; + virtual const char *getCopyright() const; +// virtual int getVersion() const { return 0; } // TODO! + + virtual GameList getSupportedGames() const; + virtual GameDescriptor findGame(const char *gameid) const; + virtual GameList detectGames(const FSList &fslist) const; + + virtual PluginError createInstance(OSystem *syst, Engine **engine) const; +}; + +GameList ScummMetaEngine::getSupportedGames() const { return GameList(gameDescriptions); } -GameDescriptor Engine_SCUMM_findGameID(const char *gameid) { +GameDescriptor ScummMetaEngine::findGame(const char *gameid) const { return Common::AdvancedDetector::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable); } -GameList Engine_SCUMM_detectGames(const FSList &fslist) { +GameList ScummMetaEngine::detectGames(const FSList &fslist) const { GameList detectedGames; Common::List<DetectorResult> results; - detectGames(fslist, results, 0); + ::detectGames(fslist, results, 0); // TODO: We still don't handle the FM-TOWNS demos (like zakloom) very well. // In particular, they are detected as ZakTowns, which is bad. @@ -724,7 +740,7 @@ GameList Engine_SCUMM_detectGames(const FSList &fslist) { * * This is heavily based on our MD5 detection scheme. */ -PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) { +PluginError ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(syst); assert(engine); const char *gameid = ConfMan.get("gameid").c_str(); @@ -756,7 +772,7 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) { // Invoke the detector, but fixed to the specified gameid. Common::List<DetectorResult> results; - detectGames(fslist, results, gameid); + ::detectGames(fslist, results, gameid); // Unable to locate game data if (results.empty()) { @@ -904,6 +920,17 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) { return kNoError; } +const char *ScummMetaEngine::getName() const { + return "Scumm Engine"; +} + +const char *ScummMetaEngine::getCopyright() const { + return "LucasArts SCUMM Games (C) LucasArts\n" + "Humongous SCUMM Games (C) Humongous"; +} + +META_COMPATIBLITY_WRAPPER(SCUMM, ScummMetaEngine); + REGISTER_PLUGIN(SCUMM, "Scumm Engine", "LucasArts SCUMM Games (C) LucasArts\n" "Humongous SCUMM Games (C) Humongous" ); diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp index dd64833584..faee215904 100644 --- a/engines/sword1/sword1.cpp +++ b/engines/sword1/sword1.cpp @@ -34,6 +34,8 @@ #include "common/events.h" #include "common/system.h" +#include "engines/metaengine.h" + #include "sword1/resman.h" #include "sword1/objectman.h" #include "sword1/mouse.h" @@ -83,7 +85,23 @@ static const char *g_filesToCheck[NUM_FILES_TO_CHECK] = { // these files have to // the engine needs several more files to work, but checking these should be sufficient }; -GameList Engine_SWORD1_gameIDList() { +class SwordMetaEngine : public MetaEngine { +public: + virtual const char *getName() const { + return "Broken Sword"; + } + virtual const char *getCopyright() const { + return "Broken Sword Games (C) Revolution"; + } + + virtual GameList getSupportedGames() const; + virtual GameDescriptor findGame(const char *gameid) const; + virtual GameList detectGames(const FSList &fslist) const; + + virtual PluginError createInstance(OSystem *syst, Engine **engine) const; +}; + +GameList SwordMetaEngine::getSupportedGames() const { GameList games; games.push_back(sword1FullSettings); games.push_back(sword1DemoSettings); @@ -92,7 +110,7 @@ GameList Engine_SWORD1_gameIDList() { return games; } -GameDescriptor Engine_SWORD1_findGameID(const char *gameid) { +GameDescriptor SwordMetaEngine::findGame(const char *gameid) const { if (0 == scumm_stricmp(gameid, sword1FullSettings.gameid)) return sword1FullSettings; if (0 == scumm_stricmp(gameid, sword1DemoSettings.gameid)) @@ -122,7 +140,7 @@ void Sword1CheckDirectory(const FSList &fslist, bool *filesFound) { } } -GameList Engine_SWORD1_detectGames(const FSList &fslist) { +GameList SwordMetaEngine::detectGames(const FSList &fslist) const { int i, j; GameList detectedGames; bool filesFound[NUM_FILES_TO_CHECK]; @@ -163,12 +181,14 @@ GameList Engine_SWORD1_detectGames(const FSList &fslist) { return detectedGames; } -PluginError Engine_SWORD1_create(OSystem *syst, Engine **engine) { +PluginError SwordMetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(engine); *engine = new SwordEngine(syst); return kNoError; } +META_COMPATIBLITY_WRAPPER(SWORD1, SwordMetaEngine); + REGISTER_PLUGIN(SWORD1, "Broken Sword", "Broken Sword Games (C) Revolution"); namespace Sword1 { diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index e8c3166948..af4474cd87 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -35,6 +35,8 @@ #include "common/events.h" #include "common/system.h" +#include "engines/metaengine.h" + #include "sword2/sword2.h" #include "sword2/defs.h" #include "sword2/header.h" @@ -68,7 +70,23 @@ static const GameSettings sword2_settings[] = { } // End of namespace Sword2 -GameList Engine_SWORD2_gameIDList() { +class Sword2MetaEngine : public MetaEngine { +public: + virtual const char *getName() const { + return "Broken Sword 2"; + } + virtual const char *getCopyright() const { + return "Broken Sword Games (C) Revolution"; + } + + virtual GameList getSupportedGames() const; + virtual GameDescriptor findGame(const char *gameid) const; + virtual GameList detectGames(const FSList &fslist) const; + + virtual PluginError createInstance(OSystem *syst, Engine **engine) const; +}; + +GameList Sword2MetaEngine::getSupportedGames() const { const Sword2::GameSettings *g = Sword2::sword2_settings; GameList games; while (g->gameid) { @@ -78,7 +96,7 @@ GameList Engine_SWORD2_gameIDList() { return games; } -GameDescriptor Engine_SWORD2_findGameID(const char *gameid) { +GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const { const Sword2::GameSettings *g = Sword2::sword2_settings; while (g->gameid) { if (0 == scumm_stricmp(gameid, g->gameid)) @@ -88,7 +106,7 @@ GameDescriptor Engine_SWORD2_findGameID(const char *gameid) { return GameDescriptor(g->gameid, g->description); } -GameList Engine_SWORD2_detectGames(const FSList &fslist) { +GameList Sword2MetaEngine::detectGames(const FSList &fslist) const { GameList detectedGames; const Sword2::GameSettings *g; FSList::const_iterator file; @@ -123,7 +141,7 @@ GameList Engine_SWORD2_detectGames(const FSList &fslist) { if (0 == scumm_stricmp("clusters", fileName)) { FSList recList; if (file->getChildren(recList, FilesystemNode::kListAll)) { - GameList recGames(Engine_SWORD2_detectGames(recList)); + GameList recGames(detectGames(recList)); if (!recGames.empty()) { detectedGames.push_back(recGames); break; @@ -138,7 +156,7 @@ GameList Engine_SWORD2_detectGames(const FSList &fslist) { return detectedGames; } -PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) { +PluginError Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(syst); assert(engine); @@ -150,7 +168,7 @@ PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) { // Invoke the detector Common::String gameid = ConfMan.get("gameid"); - GameList detectedGames = Engine_SWORD2_detectGames(fslist); + GameList detectedGames = detectGames(fslist); for (uint i = 0; i < detectedGames.size(); i++) { if (detectedGames[i].gameid() == gameid) { @@ -162,6 +180,8 @@ PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) { return kNoGameDataFoundError; } +META_COMPATIBLITY_WRAPPER(SWORD2, Sword2MetaEngine); + REGISTER_PLUGIN(SWORD2, "Broken Sword 2", "Broken Sword Games (C) Revolution"); namespace Sword2 { diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index 41b2062ffc..d6ba2d0667 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -124,7 +124,22 @@ static const Common::ADParams detectionParams = { Common::kADFlagAugmentPreferredTarget | Common::kADFlagPrintWarningOnFileBasedFallback }; -static bool Engine_TOUCHE_createInstance(OSystem *syst, Engine **engine, const Common::EncapsulatedADGameDesc &encapsulatedDesc) { +class ToucheMetaEngine : public AdvancedMetaEngine { +public: + ToucheMetaEngine() : AdvancedMetaEngine(detectionParams) {} + + virtual const char *getName() const { + return "Touche Engine"; + } + virtual const char *getCopyright() const { + return "Touche: The Adventures of the 5th Musketeer (C) Clipper Software"; + } + + virtual bool createInstance(OSystem *syst, Engine **engine, const Common::EncapsulatedADGameDesc &encapsulatedDesc) const; +}; + + +bool ToucheMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::EncapsulatedADGameDesc &encapsulatedDesc) const { const Common::ADGameDescription *gd = encapsulatedDesc.realDesc; if (gd) { *engine = new Touche::ToucheEngine(syst, gd->language); @@ -132,6 +147,6 @@ static bool Engine_TOUCHE_createInstance(OSystem *syst, Engine **engine, const C return gd != 0; } -ADVANCED_DETECTOR_DEFINE_PLUGIN(TOUCHE, Engine_TOUCHE_createInstance, detectionParams); +META_COMPATIBLITY_WRAPPER(TOUCHE, ToucheMetaEngine); REGISTER_PLUGIN(TOUCHE, "Touche Engine", "Touche: The Adventures of the 5th Musketeer (C) Clipper Software"); |