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
#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 &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

View file

@ -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");

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 "base/plugins.h"
#include "common/config-manager.h"
#include "common/advancedDetector.h"

View file

@ -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" );

View file

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

View file

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

View file

@ -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");