diff options
-rw-r--r-- | base/commandLine.cpp | 132 | ||||
-rw-r--r-- | common/config-manager.h | 1 |
2 files changed, 132 insertions, 1 deletions
diff --git a/base/commandLine.cpp b/base/commandLine.cpp index b58c3d320d..e3d3437c73 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -37,6 +37,7 @@ #include "gui/ThemeEngine.h" #define DETECTOR_TESTING_HACK +#define UPGRADE_ALL_TARGETS_HACK namespace Base { @@ -322,9 +323,17 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha DO_COMMAND('z', "list-games") END_OPTION +#ifdef DETECTOR_TESTING_HACK // HACK FIXME TODO: This command is intentionally *not* documented! DO_LONG_COMMAND("test-detector") END_OPTION +#endif + +#ifdef UPGRADE_ALL_TARGETS_HACK + // HACK FIXME TODO: This command is intentionally *not* documented! + DO_LONG_COMMAND("upgrade-targets") + END_OPTION +#endif DO_LONG_OPTION("list-saves") // FIXME: Need to document this. @@ -685,7 +694,7 @@ static void runDetectorTest() { if (gameidDiffers) { printf(" WARNING: Multiple games detected, some/all with wrong gameid\n"); } else { - printf(" WARNING: Multiple games detected, but all have the same gameid\n"); + printf(" WARNING: Multiple games detected, but all have matching gameid\n"); } failure++; } else if (gameidDiffers) { @@ -710,6 +719,121 @@ static void runDetectorTest() { } #endif +#ifdef UPGRADE_ALL_TARGETS_HACK +void upgradeTargets() { + // HACK: The following upgrades all your targets to the latest and + // greatest. Right now that means updating the guioptions and (optionally) + // also the game descriptions. + // Basically, it loops over all targets, and calls the detector for the + // given path. It then compares the result with the settings of the target. + // If the basics seem to match, it updates the guioptions. + + printf("Upgrading all your existing targets\n"); + + Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains(); + Common::ConfigManager::DomainMap::iterator iter = domains.begin(); + for (iter = domains.begin(); iter != domains.end(); ++iter) { + Common::ConfigManager::Domain &dom = iter->_value; + Common::String name(iter->_key); + Common::String gameid(dom.get("gameid")); + Common::String path(dom.get("path")); + printf("Looking at target '%s', gameid '%s' ...\n", + name.c_str(), gameid.c_str()); + if (path.empty()) { + printf(" ... no path specified, skipping\n"); + continue; + } + if (gameid.empty()) { + gameid = name; + } + gameid.toLowercase(); // TODO: Is this paranoia? Maybe we should just assume all lowercase, always? + + Common::FSNode dir(path); + Common::FSList files; + if (!dir.getChildren(files, Common::FSNode::kListAll)) { + printf(" ... invalid path, skipping\n"); + continue; + } + + Common::Language lang = Common::parseLanguage(dom.get("language")); + Common::Platform plat = Common::parsePlatform(dom.get("platform")); + Common::String desc(dom.get("description")); + + GameList candidates(EngineMan.detectGames(files)); + GameDescriptor *g = 0; + + // We proceed as follows: + // * If detection failed to produce candidates, skip. + // * If there is a unique detector match, trust it. + // * If there are multiple match, run over them comparing gameid, language and platform. + // If we end up with a unique match, use it. Otherwise, skip. + if (candidates.size() == 0) { + printf(" ... failed to detect game, skipping\n"); + continue; + } + if (candidates.size() > 1) { + // Scan over all candidates, check if there is a unique match for gameid, language and platform + GameList::iterator x; + int matchesFound = 0; + for (x = candidates.begin(); x != candidates.end(); ++x) { + if (x->gameid() == gameid && x->language() == lang && x->platform() == plat) { + matchesFound++; + g = &(*x); + } + } + if (matchesFound != 1) { + printf(" ... detected multiple games, could not establish unique match, skipping\n"); + continue; + } + } else { + // Unique match -> use it + g = &candidates[0]; + } + + // At this point, g points to a GameDescriptor which we can use to update + // the target referred to by dom. We update several things + + // Always set the gameid explicitly (in case of legacy targets) + dom["gameid"] = g->gameid(); + + // Always set the GUI options. The user should not modify them, and engines might + // gain more features over time, so we want to keep this list up-to-date. + if (g->contains("guioptions")) { + printf(" -> update guioptions to '%s'\n", (*g)["guioptions"].c_str()); + dom["guioptions"] = (*g)["guioptions"]; + } else if (dom.contains("guioptions")) { + dom.erase("guioptions"); + } + + // Update the language setting but only if none has been set yet. + if (lang == Common::UNK_LANG && g->language() != Common::UNK_LANG) { + printf(" -> set lang to '%s'\n", Common::getLanguageCode(g->language())); + dom["language"] = (*g)["language"]; + } + + // Update the platform setting but only if none has been set yet. + if (plat == Common::kPlatformUnknown && g->platform() != Common::kPlatformUnknown) { + printf(" -> set plat to '%s'\n", Common::getPlatformCode(g->platform())); + dom["platform"] = (*g)["platform"]; + } + + // TODO: We could also update the description. But not everybody will want that. + // Esp. because for some games (e.g. the combined Zak/Loom FM-TOWNS demo etc.) + // ScummVM still generates an incorrect description string. So, the description + // should only be updated if the user explicitly requests this. +#if 0 + if (desc != g->description()) { + printf(" -> update desc from '%s' to\n '%s' ?\n", desc.c_str(), g->description().c_str()); + dom["description"] = (*g)["description"]; + } +#endif + } + + // Finally, save our changes to disk + ConfMan.flushToDisk(); +} +#endif + #else // DISABLE_COMMAND_LINE @@ -754,6 +878,12 @@ bool processSettings(Common::String &command, Common::StringMap &settings) { return false; } #endif +#ifdef UPGRADE_ALL_TARGETS_HACK + else if (command == "upgrade-targets") { + upgradeTargets(); + return false; + } +#endif #endif // DISABLE_COMMAND_LINE diff --git a/common/config-manager.h b/common/config-manager.h index d86431be2f..bc734dbdc3 100644 --- a/common/config-manager.h +++ b/common/config-manager.h @@ -155,6 +155,7 @@ public: void renameGameDomain(const String &oldName, const String &newName); bool hasGameDomain(const String &domName) const; const DomainMap & getGameDomains() const { return _gameDomains; } + DomainMap & getGameDomains() { return _gameDomains; } private: friend class Singleton<SingletonBaseType>; |