diff options
-rw-r--r-- | engines/wintermute/detection.cpp | 62 | ||||
-rw-r--r-- | engines/wintermute/wintermute.cpp | 62 | ||||
-rw-r--r-- | engines/wintermute/wintermute.h | 3 |
3 files changed, 125 insertions, 2 deletions
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index 285c3ffaeb..5e259f717d 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -32,6 +32,24 @@ #include "engines/wintermute/detection_tables.h" +namespace WinterMute { + +/** + * The fallback game descriptor used by the WinterMute engine's fallbackDetector. + * Contents of this struct are overwritten by the fallbackDetector. (logic copied partially + * from the SCI-engine). + */ +static ADGameDescription s_fallbackDesc = { + "", + "", + AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() +}; +static char s_fallbackGameIdBuf[256]; + class WinterMuteMetaEngine : public AdvancedMetaEngine { public: WinterMuteMetaEngine() : AdvancedMetaEngine(WinterMute::gameDescriptions, sizeof(ADGameDescription), WinterMute::wintermuteGames) { @@ -83,6 +101,44 @@ public: } return detectedGames; }*/ + + + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + // Set some defaults + s_fallbackDesc.extra = ""; + s_fallbackDesc.language = Common::UNK_LANG; + s_fallbackDesc.flags = ADGF_UNSTABLE; + s_fallbackDesc.platform = Common::kPlatformWindows; // default to Windows + s_fallbackDesc.gameid = "wintermute"; + s_fallbackDesc.guioptions = GUIO0(); + + if (allFiles.contains("data.dcp")) { + Common::String name, caption; + if (WinterMuteEngine::getGameInfo(fslist, name, caption)) { + for (int32 i = 0; i < name.size(); i++) { + // Replace spaces with underscores + if (name[i] == ' ') { + name.setChar('_', (uint32)i); + } + } + // Prefix to avoid collisions with actually known games + name = "wmefan-" + name; + strncpy(s_fallbackGameIdBuf, name.c_str(), sizeof(s_fallbackGameIdBuf) - 1); + s_fallbackDesc.gameid = s_fallbackGameIdBuf; + if (caption != name) { + caption += " (fangame) "; + char *offset = s_fallbackGameIdBuf + name.size() + 1; + uint32 remainingLength = (sizeof(s_fallbackGameIdBuf) - 1) - (name.size() + 1); + strncpy(offset, caption.c_str(), remainingLength); + s_fallbackDesc.extra = offset; + s_fallbackDesc.flags |= ADGF_USEEXTRAASTITLE; + } + return &s_fallbackDesc; + } // Fall through to return 0; + } + return 0; + } + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { assert(syst); assert(engine); @@ -141,8 +197,10 @@ public: } }; +} // end of namespace WinterMute + #if PLUGIN_ENABLED_DYNAMIC(WINTERMUTE) -REGISTER_PLUGIN_DYNAMIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMuteMetaEngine); +REGISTER_PLUGIN_DYNAMIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMute::WinterMuteMetaEngine); #else -REGISTER_PLUGIN_STATIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMuteMetaEngine); +REGISTER_PLUGIN_STATIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, WinterMute::WinterMuteMetaEngine); #endif diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp index 69c5df5bc5..9040de66e6 100644 --- a/engines/wintermute/wintermute.cpp +++ b/engines/wintermute/wintermute.cpp @@ -29,6 +29,7 @@ #include "common/EventRecorder.h" #include "common/file.h" #include "common/fs.h" +#include "common/tokenizer.h" #include "engines/util.h" #include "engines/wintermute/ad/ad_game.h" @@ -37,12 +38,24 @@ #include "engines/wintermute/base/base_registry.h" #include "engines/wintermute/base/sound/base_sound_manager.h" +#include "engines/wintermute/base/base_file_manager.h" #include "engines/wintermute/base/scriptables/script_engine.h" namespace WinterMute { WinterMuteEngine *g_wintermute; +// Simple constructor for detection - we need to setup the persistence to avoid special-casing in-engine +// This might not be the prettiest solution +WinterMuteEngine::WinterMuteEngine() : Engine(g_system) { + g_wintermute = this; + _classReg = new SystemClassRegistry(); + _classReg->registerClasses(); + + _game = new AdGame(); + _rnd = NULL; +} + WinterMuteEngine::WinterMuteEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc) { // Put your engine in a sane state, but do nothing big yet; @@ -74,7 +87,10 @@ WinterMuteEngine::~WinterMuteEngine() { debug("WinterMuteEngine::~WinterMuteEngine"); // Dispose your resources here + delete _classReg; delete _rnd; + delete _game; + g_wintermute = NULL; // Remove all of our debug levels here DebugMan.clearAllDebugChannels(); @@ -320,6 +336,52 @@ int WinterMuteEngine::messageLoop() { void WinterMuteEngine::deinit() { delete _classReg; + _classReg = NULL; +} + +bool WinterMuteEngine::getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption) { + bool retVal = false; + caption = name = "(invalid)"; + + // Quick-fix, instead of possibly breaking the persistence-system, let's just roll with it + WinterMuteEngine *engine = new WinterMuteEngine(); + + engine->_game->initialize1(); + engine->_game->_fileManager->registerPackages(fslist); + if (engine->_game->loadSettings("startup.settings")) { + // We do some manual parsing here, as the engine needs gfx to be initalized to do that. + Common::SeekableReadStream *stream = engine->_game->_fileManager->openFile((engine->_game->_settingsGameFile ? engine->_game->_settingsGameFile : "default.game"), false, false); + while (!stream->eos() && !stream->err()) { + Common::String line = stream->readLine(); + line.trim(); // Get rid of indentation + // Expect "GAME {" or comment, or empty line + if (line.size() == 0 || line[0] == ';' || (line.contains("{"))) + continue; + else { + Common::StringTokenizer token(line, "="); + Common::String key = token.nextToken(); + Common::String value = token.nextToken(); + if (value.size() == 0) + continue; + if (value[0] == '\"') + value.deleteChar(0); + else + continue; // not a string + if (value.lastChar() == '\"') + value.deleteLastChar(); + if (key == "NAME") { + retVal = true; + name = value; + } else if (key == "CAPTION") { + retVal = true; + caption = value; + } + } + } + delete stream; + } + delete engine; + return retVal; } uint32 WinterMuteEngine::randInt(int from, int to) { diff --git a/engines/wintermute/wintermute.h b/engines/wintermute/wintermute.h index b37f495b5e..e850a72196 100644 --- a/engines/wintermute/wintermute.h +++ b/engines/wintermute/wintermute.h @@ -44,6 +44,7 @@ enum { class WinterMuteEngine : public Engine { public: WinterMuteEngine(OSystem *syst, const ADGameDescription *desc); + WinterMuteEngine(); ~WinterMuteEngine(); virtual Common::Error run(); @@ -51,6 +52,8 @@ public: Common::SaveFileManager *getSaveFileMan() { return _saveFileMan; } SystemClassRegistry *getClassRegistry(){ return _classReg; } uint32 randInt(int from, int to); + // For detection-purposes: + static bool getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption); private: int init(); void deinit(); |