New MetaEngine class (work in progress to replace the current Engine plugin API with a more object oriented approach)

svn-id: r30726
This commit is contained in:
Max Horn 2008-02-02 00:54:52 +00:00
parent 249877fa82
commit dc979b03cf
8 changed files with 238 additions and 21 deletions

View file

@ -26,10 +26,11 @@
#define COMMON_ADVANCED_DETECTOR_H #define COMMON_ADVANCED_DETECTOR_H
#include "common/fs.h" #include "common/fs.h"
#include "common/error.h"
#include "base/game.h" // For PlainGameDescriptor and GameList #include "base/game.h" // For PlainGameDescriptor and GameList
#include "base/plugins.h" // For PluginError
#include "engines/metaengine.h"
namespace Common { namespace Common {
@ -273,4 +274,41 @@ void reportUnknown(StringList &files, int md5Bytes);
} // End of namespace Common } // End of namespace Common
/**
* A MetaEngine implementation based around the advanced detector code.
*/
class AdvancedMetaEngine : public MetaEngine {
const Common::ADParams &params;
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 #endif

View file

@ -2250,7 +2250,21 @@ static const Common::ADParams detectionParams = {
Common::kADFlagAugmentPreferredTarget 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); const Agi::AGIGameDescription *gd = (const Agi::AGIGameDescription *)(encapsulatedDesc.realDesc);
bool res = true; bool res = true;
@ -2270,7 +2284,7 @@ bool engineCreateAgi(OSystem *syst, Engine **engine, Common::EncapsulatedADGameD
return res; 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"); REGISTER_PLUGIN(AGI, "AGI preAGI + v2 + v3 Engine", "Sierra AGI Engine (C) Sierra On-Line Software");

81
engines/metaengine.h Normal file
View file

@ -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

View file

@ -27,6 +27,8 @@
#include "saga/saga.h" #include "saga/saga.h"
#include "base/plugins.h"
#include "common/config-manager.h" #include "common/config-manager.h"
#include "common/advancedDetector.h" #include "common/advancedDetector.h"

View file

@ -36,6 +36,9 @@
#include "scumm/intern.h" #include "scumm/intern.h"
#include "scumm/he/intern_he.h" #include "scumm/he/intern_he.h"
#include "engines/metaengine.h"
namespace Scumm { namespace Scumm {
enum { enum {
@ -662,20 +665,33 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com
using namespace Scumm; 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); return GameList(gameDescriptions);
} }
GameDescriptor Engine_SCUMM_findGameID(const char *gameid) { GameDescriptor ScummMetaEngine::findGame(const char *gameid) const {
return Common::AdvancedDetector::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable); return Common::AdvancedDetector::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable);
} }
GameList Engine_SCUMM_detectGames(const FSList &fslist) { GameList ScummMetaEngine::detectGames(const FSList &fslist) const {
GameList detectedGames; GameList detectedGames;
Common::List<DetectorResult> results; 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. // TODO: We still don't handle the FM-TOWNS demos (like zakloom) very well.
// In particular, they are detected as ZakTowns, which is bad. // 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. * 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(syst);
assert(engine); assert(engine);
const char *gameid = ConfMan.get("gameid").c_str(); 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. // Invoke the detector, but fixed to the specified gameid.
Common::List<DetectorResult> results; Common::List<DetectorResult> results;
detectGames(fslist, results, gameid); ::detectGames(fslist, results, gameid);
// Unable to locate game data // Unable to locate game data
if (results.empty()) { if (results.empty()) {
@ -904,6 +920,17 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) {
return kNoError; 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", REGISTER_PLUGIN(SCUMM, "Scumm Engine",
"LucasArts SCUMM Games (C) LucasArts\n" "LucasArts SCUMM Games (C) LucasArts\n"
"Humongous SCUMM Games (C) Humongous" ); "Humongous SCUMM Games (C) Humongous" );

View file

@ -34,6 +34,8 @@
#include "common/events.h" #include "common/events.h"
#include "common/system.h" #include "common/system.h"
#include "engines/metaengine.h"
#include "sword1/resman.h" #include "sword1/resman.h"
#include "sword1/objectman.h" #include "sword1/objectman.h"
#include "sword1/mouse.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 // 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; GameList games;
games.push_back(sword1FullSettings); games.push_back(sword1FullSettings);
games.push_back(sword1DemoSettings); games.push_back(sword1DemoSettings);
@ -92,7 +110,7 @@ GameList Engine_SWORD1_gameIDList() {
return games; return games;
} }
GameDescriptor Engine_SWORD1_findGameID(const char *gameid) { GameDescriptor SwordMetaEngine::findGame(const char *gameid) const {
if (0 == scumm_stricmp(gameid, sword1FullSettings.gameid)) if (0 == scumm_stricmp(gameid, sword1FullSettings.gameid))
return sword1FullSettings; return sword1FullSettings;
if (0 == scumm_stricmp(gameid, sword1DemoSettings.gameid)) 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; int i, j;
GameList detectedGames; GameList detectedGames;
bool filesFound[NUM_FILES_TO_CHECK]; bool filesFound[NUM_FILES_TO_CHECK];
@ -163,12 +181,14 @@ GameList Engine_SWORD1_detectGames(const FSList &fslist) {
return detectedGames; return detectedGames;
} }
PluginError Engine_SWORD1_create(OSystem *syst, Engine **engine) { PluginError SwordMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(engine); assert(engine);
*engine = new SwordEngine(syst); *engine = new SwordEngine(syst);
return kNoError; return kNoError;
} }
META_COMPATIBLITY_WRAPPER(SWORD1, SwordMetaEngine);
REGISTER_PLUGIN(SWORD1, "Broken Sword", "Broken Sword Games (C) Revolution"); REGISTER_PLUGIN(SWORD1, "Broken Sword", "Broken Sword Games (C) Revolution");
namespace Sword1 { namespace Sword1 {

View file

@ -35,6 +35,8 @@
#include "common/events.h" #include "common/events.h"
#include "common/system.h" #include "common/system.h"
#include "engines/metaengine.h"
#include "sword2/sword2.h" #include "sword2/sword2.h"
#include "sword2/defs.h" #include "sword2/defs.h"
#include "sword2/header.h" #include "sword2/header.h"
@ -68,7 +70,23 @@ static const GameSettings sword2_settings[] = {
} // End of namespace Sword2 } // 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; const Sword2::GameSettings *g = Sword2::sword2_settings;
GameList games; GameList games;
while (g->gameid) { while (g->gameid) {
@ -78,7 +96,7 @@ GameList Engine_SWORD2_gameIDList() {
return games; return games;
} }
GameDescriptor Engine_SWORD2_findGameID(const char *gameid) { GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const {
const Sword2::GameSettings *g = Sword2::sword2_settings; const Sword2::GameSettings *g = Sword2::sword2_settings;
while (g->gameid) { while (g->gameid) {
if (0 == scumm_stricmp(gameid, 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); return GameDescriptor(g->gameid, g->description);
} }
GameList Engine_SWORD2_detectGames(const FSList &fslist) { GameList Sword2MetaEngine::detectGames(const FSList &fslist) const {
GameList detectedGames; GameList detectedGames;
const Sword2::GameSettings *g; const Sword2::GameSettings *g;
FSList::const_iterator file; FSList::const_iterator file;
@ -123,7 +141,7 @@ GameList Engine_SWORD2_detectGames(const FSList &fslist) {
if (0 == scumm_stricmp("clusters", fileName)) { if (0 == scumm_stricmp("clusters", fileName)) {
FSList recList; FSList recList;
if (file->getChildren(recList, FilesystemNode::kListAll)) { if (file->getChildren(recList, FilesystemNode::kListAll)) {
GameList recGames(Engine_SWORD2_detectGames(recList)); GameList recGames(detectGames(recList));
if (!recGames.empty()) { if (!recGames.empty()) {
detectedGames.push_back(recGames); detectedGames.push_back(recGames);
break; break;
@ -138,7 +156,7 @@ GameList Engine_SWORD2_detectGames(const FSList &fslist) {
return detectedGames; return detectedGames;
} }
PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) { PluginError Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(syst); assert(syst);
assert(engine); assert(engine);
@ -150,7 +168,7 @@ PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) {
// Invoke the detector // Invoke the detector
Common::String gameid = ConfMan.get("gameid"); Common::String gameid = ConfMan.get("gameid");
GameList detectedGames = Engine_SWORD2_detectGames(fslist); GameList detectedGames = detectGames(fslist);
for (uint i = 0; i < detectedGames.size(); i++) { for (uint i = 0; i < detectedGames.size(); i++) {
if (detectedGames[i].gameid() == gameid) { if (detectedGames[i].gameid() == gameid) {
@ -162,6 +180,8 @@ PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) {
return kNoGameDataFoundError; return kNoGameDataFoundError;
} }
META_COMPATIBLITY_WRAPPER(SWORD2, Sword2MetaEngine);
REGISTER_PLUGIN(SWORD2, "Broken Sword 2", "Broken Sword Games (C) Revolution"); REGISTER_PLUGIN(SWORD2, "Broken Sword 2", "Broken Sword Games (C) Revolution");
namespace Sword2 { namespace Sword2 {

View file

@ -124,7 +124,22 @@ static const Common::ADParams detectionParams = {
Common::kADFlagAugmentPreferredTarget | Common::kADFlagPrintWarningOnFileBasedFallback 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; const Common::ADGameDescription *gd = encapsulatedDesc.realDesc;
if (gd) { if (gd) {
*engine = new Touche::ToucheEngine(syst, gd->language); *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; 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"); REGISTER_PLUGIN(TOUCHE, "Touche Engine", "Touche: The Adventures of the 5th Musketeer (C) Clipper Software");