From 9587dd5c21d388616dc8d42db909390fab384c2f Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 2 Dec 2017 16:43:48 +0100 Subject: ENGINES: Fix clang-tidy warnings --- engines/advancedDetector.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index d258f49621..dea9b8e6ec 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -167,7 +167,7 @@ GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist, bool useU if (matches.empty()) { // Use fallback detector if there were no matches by other means const ADGameDescription *fallbackDesc = fallbackDetect(allFiles, fslist); - if (fallbackDesc != 0) { + if (fallbackDesc != nullptr) { GameDescriptor desc(toGameDescriptor(*fallbackDesc, _gameIds)); updateGameDescriptor(desc, fallbackDesc); detectedGames.push_back(desc); @@ -336,7 +336,7 @@ void AdvancedMetaEngine::reportUnknown(const Common::FSNode &path, const ADFileP Common::String reportTranslated = Common::String::format(_(reportCommon), path.getPath().c_str(), getName(), "https://bugs.scummvm.org/"); Common::String bugtrackerAffectedEngine = getName(); - if (matchedGameIds.size()) { + if (!matchedGameIds.empty()) { report += "\n\n"; reportTranslated += "\n\n"; report += "Matched game IDs:"; @@ -460,7 +460,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons // Check which files are included in some ADGameDescription *and* are present. // Compute MD5s and file sizes for these files. - for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != 0; descPtr += _descItemSize) { + for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != nullptr; descPtr += _descItemSize) { g = (const ADGameDescription *)descPtr; for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { @@ -484,7 +484,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons // MD5 based matching uint i; - for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != 0; descPtr += _descItemSize, ++i) { + for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != nullptr; descPtr += _descItemSize, ++i) { g = (const ADGameDescription *)descPtr; bool fileMissing = false; @@ -516,7 +516,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons if (hashOrSizeMismatch) continue; - if (fileDesc->md5 != NULL && fileDesc->md5 != filesProps[tstr].md5) { + if (fileDesc->md5 != nullptr && fileDesc->md5 != filesProps[tstr].md5) { debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesProps[tstr].md5.c_str()); fileMissing = true; hashOrSizeMismatch = true; @@ -545,7 +545,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons // cases. if (allFilesPresent) { gotAnyMatchesWithAllFiles = true; - if (!matchedGameIds.size() || strcmp(matchedGameIds.back(), g->gameId) != 0) + if (matchedGameIds.empty() || strcmp(matchedGameIds.back(), g->gameId) != 0) matchedGameIds.push_back(g->gameId); } -- cgit v1.2.3 From cf1ebf29516bd74927fd7b632b72fd8973f72e98 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 2 Dec 2017 17:14:22 +0100 Subject: ENGINES: Add unknown game variants to the game detector results --- base/commandLine.cpp | 38 ++++-- base/plugins.cpp | 20 +++- engines/adl/detection.cpp | 69 +++++------ engines/advancedDetector.cpp | 231 ++++++++++++++---------------------- engines/advancedDetector.h | 52 ++++---- engines/agi/detection.cpp | 8 +- engines/cge/detection.cpp | 32 +++-- engines/cge2/detection.cpp | 34 +++--- engines/director/detection.cpp | 8 +- engines/game.cpp | 87 ++++++++++++++ engines/game.h | 104 ++++++++++++++++ engines/gob/detection/detection.cpp | 25 ++-- engines/made/detection.cpp | 6 +- engines/metaengine.h | 4 +- engines/mohawk/detection.cpp | 2 +- engines/queen/detection.cpp | 10 +- engines/sci/detection.cpp | 14 +-- engines/scumm/detection.cpp | 21 ++-- engines/sky/detection.cpp | 15 +-- engines/sludge/detection.cpp | 18 ++- engines/sword1/detection.cpp | 36 +++--- engines/sword2/sword2.cpp | 21 ++-- engines/tinsel/detection.cpp | 21 ++-- engines/toon/detection.cpp | 2 +- engines/touche/detection.cpp | 11 +- engines/tucker/detection.cpp | 7 +- engines/unknown-game-dialog.cpp | 70 ++++++----- engines/unknown-game-dialog.h | 18 +-- engines/wintermute/detection.cpp | 8 +- gui/launcher.cpp | 20 +++- gui/massadd.cpp | 13 +- 31 files changed, 597 insertions(+), 428 deletions(-) diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 83c7b56171..8e701408ef 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -864,12 +864,20 @@ static GameList getGameList(const Common::FSNode &dir) { } // detect Games - GameList candidates(EngineMan.detectGames(files)); - Common::String dataPath = dir.getPath(); - // add game data path - for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) { - (*v)["path"] = dataPath; + DetectionResults detectionResults = EngineMan.detectGames(files); + + if (detectionResults.foundUnknownGames()) { + Common::String report = detectionResults.generateUnknownGameReport(false, 80); + g_system->logMessage(LogMessageType::kInfo, report.c_str()); } + + DetectedGames detectedGames = detectionResults.listRecognizedGames(); + + GameList candidates; + for (uint i = 0; i < detectedGames.size(); i++) { + candidates.push_back(detectedGames[i].matchedGame); + } + return candidates; } @@ -1014,7 +1022,14 @@ static void runDetectorTest() { continue; } - GameList candidates(EngineMan.detectGames(files)); + DetectionResults detectionResults = EngineMan.detectGames(files); + DetectedGames detectedGames = detectionResults.listRecognizedGames(); + + GameList candidates; + for (uint i = 0; i < detectedGames.size(); i++) { + candidates.push_back(detectedGames[i].matchedGame); + } + bool gameidDiffers = false; GameList::iterator x; for (x = candidates.begin(); x != candidates.end(); ++x) { @@ -1092,7 +1107,14 @@ void upgradeTargets() { Common::Platform plat = Common::parsePlatform(dom.getVal("platform")); Common::String desc(dom.getVal("description")); - GameList candidates(EngineMan.detectGames(files)); + DetectionResults detectionResults = EngineMan.detectGames(files); + DetectedGames detectedGames = detectionResults.listRecognizedGames(); + + GameList candidates; + for (uint i = 0; i < detectedGames.size(); i++) { + candidates.push_back(detectedGames[i].matchedGame); + } + GameDescriptor *g = 0; // We proceed as follows: @@ -1100,7 +1122,7 @@ void upgradeTargets() { // * 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) { + if (candidates.empty()) { printf(" ... failed to detect game, skipping\n"); continue; } diff --git a/base/plugins.cpp b/base/plugins.cpp index 852786919b..02f6998ad9 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -22,6 +22,7 @@ #include "base/plugins.h" +#include "common/translation.h" #include "common/func.h" #include "common/debug.h" #include "common/config-manager.h" @@ -514,8 +515,9 @@ GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &game return result; } -GameList EngineManager::detectGames(const Common::FSList &fslist, bool useUnknownGameDialog) const { - GameList candidates; +DetectionResults EngineManager::detectGames(const Common::FSList &fslist) const { + DetectedGames candidates; + Common::String path = fslist.begin()->getParent().getPath(); PluginList plugins; PluginList::const_iterator iter; PluginManager::instance().loadFirstPlugin(); @@ -524,17 +526,25 @@ GameList EngineManager::detectGames(const Common::FSList &fslist, bool useUnknow // Iterate over all known games and for each check if it might be // the game in the presented directory. for (iter = plugins.begin(); iter != plugins.end(); ++iter) { - candidates.push_back((*iter)->get().detectGames(fslist, useUnknownGameDialog)); + const MetaEngine &metaEngine = (*iter)->get(); + DetectedGames engineCandidates = metaEngine.detectGames(fslist); + + for (uint i = 0; i < engineCandidates.size(); i++) { + engineCandidates[i].engineName = metaEngine.getName(); + engineCandidates[i].matchedGame["path"] = path; + candidates.push_back(engineCandidates[i]); + } + } } while (PluginManager::instance().loadNextPlugin()); - return candidates; + + return DetectionResults(candidates); } const PluginList &EngineManager::getPlugins() const { return PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE); } - // Music plugins #include "audio/musicplugin.h" diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp index 14646c78e3..2276576baa 100644 --- a/engines/adl/detection.cpp +++ b/engines/adl/detection.cpp @@ -332,9 +332,9 @@ public: int getMaximumSaveSlot() const { return 'O' - 'A'; } SaveStateList listSaves(const char *target) const; void removeSaveState(const char *target, int slot) const; - virtual ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, bool useUnknownGameDialog = false) const; + ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override; - bool addFileProps(const FileMap &allFiles, Common::String fname, ADFilePropertiesMap &filePropsMap) const; + bool addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const; bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const; }; @@ -492,14 +492,14 @@ Common::Platform getPlatform(const AdlGameDescription &adlDesc) { return adlDesc.desc.platform; } -bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname, ADFilePropertiesMap &filePropsMap) const { +bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const { if (filePropsMap.contains(fname)) return true; if (!allFiles.contains(fname)) return false; - ADFileProperties fileProps; + FileProperties fileProps; fileProps.size = computeMD5(allFiles[fname], fileProps.md5, 16384); if (fileProps.size != -1) { @@ -511,42 +511,39 @@ bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname, } // Based on AdvancedMetaEngine::detectGame -ADGameDescList AdlMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, bool useUnknownGameDialog) const { +ADDetectedGames AdlMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const { // We run the file-based detector first and then add to the returned list - ADGameDescList matched = AdvancedMetaEngine::detectGame(parent, allFiles, language, platform, extra, useUnknownGameDialog); + ADDetectedGames matched = AdvancedMetaEngine::detectGame(parent, allFiles, language, platform, extra); debug(3, "Starting disk image detection in dir '%s'", parent.getPath().c_str()); - ADFilePropertiesMap filesProps; - ADGameIdList matchedGameIds; + FilePropertiesMap filesProps; bool gotAnyMatchesWithAllFiles = false; for (uint g = 0; gameDiskDescriptions[g].desc.gameId != 0; ++g) { - const ADGameDescription &desc = gameDiskDescriptions[g].desc; + ADDetectedGame game(&gameDiskDescriptions[g].desc); // Skip games that don't meet the language/platform/extra criteria - if (language != Common::UNK_LANG && desc.language != Common::UNK_LANG) { - if (desc.language != language && !(language == Common::EN_ANY && (desc.flags & ADGF_ADDENGLISH))) - continue; + if (language != Common::UNK_LANG && game.desc->language != Common::UNK_LANG) { + if (game.desc->language != language && !(language == Common::EN_ANY && (game.desc->flags & ADGF_ADDENGLISH))) + continue; } - if (platform != Common::kPlatformUnknown && desc.platform != Common::kPlatformUnknown && desc.platform != platform) + if (platform != Common::kPlatformUnknown && game.desc->platform != Common::kPlatformUnknown && game.desc->platform != platform) continue; - if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && desc.extra != extra) + if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && game.desc->extra != extra) continue; - bool fileMissing = false; bool allFilesPresent = true; - bool hashOrSizeMismatch = false; - for (uint f = 0; desc.filesDescriptions[f].fileName; ++f) { - const ADGameFileDescription &fDesc = desc.filesDescriptions[f]; + for (uint f = 0; game.desc->filesDescriptions[f].fileName; ++f) { + const ADGameFileDescription &fDesc = game.desc->filesDescriptions[f]; Common::String fileName; bool foundDiskImage = false; for (uint e = 0; e < ARRAYSIZE(diskImageExts); ++e) { - if (diskImageExts[e].platform == desc.platform) { + if (diskImageExts[e].platform == game.desc->platform) { Common::String testFileName(fDesc.fileName); testFileName += diskImageExts[e].extension; @@ -563,49 +560,41 @@ ADGameDescList AdlMetaEngine::detectGame(const Common::FSNode &parent, const Fil } if (!foundDiskImage) { - fileMissing = true; allFilesPresent = false; break; } - if (hashOrSizeMismatch) + game.matchedFiles[fileName] = filesProps[fileName]; + + if (game.hasUnknownFiles) continue; if (fDesc.md5 && fDesc.md5 != filesProps[fileName].md5) { debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fDesc.md5, filesProps[fileName].md5.c_str()); - fileMissing = true; - hashOrSizeMismatch = true; + game.hasUnknownFiles = true; continue; } if (fDesc.fileSize != -1 && fDesc.fileSize != filesProps[fileName].size) { debug(3, "Size Mismatch. Skipping"); - fileMissing = true; - hashOrSizeMismatch = true; + game.hasUnknownFiles = true; continue; } debug(3, "Matched file: %s", fileName.c_str()); } - if (!fileMissing) { - debug(2, "Found game: %s (%s/%s) (%d)", desc.gameId, getPlatformDescription(desc.platform), getLanguageDescription(desc.language), g); - matched.push_back(&desc); + if (allFilesPresent && !game.hasUnknownFiles) { + debug(2, "Found game: %s (%s/%s) (%d)", game.desc->gameId, getPlatformDescription(game.desc->platform), getLanguageDescription(game.desc->language), g); + gotAnyMatchesWithAllFiles = true; + matched.push_back(game); } else { - if (allFilesPresent) { - gotAnyMatchesWithAllFiles = true; - if (!matchedGameIds.size() || strcmp(matchedGameIds.back(), desc.gameId) != 0) - matchedGameIds.push_back(desc.gameId); + if (allFilesPresent && !gotAnyMatchesWithAllFiles) { + if (matched.empty() || strcmp(matched.back().desc->gameId, game.desc->gameId) != 0) + matched.push_back(game); } - debug(5, "Skipping game: %s (%s/%s) (%d)", desc.gameId, getPlatformDescription(desc.platform), getLanguageDescription(desc.language), g); - } - } - - // TODO: This could be improved to handle matched and unknown games together in a single directory - if (matched.empty()) { - if (!filesProps.empty() && gotAnyMatchesWithAllFiles) { - reportUnknown(parent, filesProps, matchedGameIds, useUnknownGameDialog); + debug(5, "Skipping game: %s (%s/%s) (%d)", game.desc->gameId, getPlatformDescription(game.desc->platform), getLanguageDescription(game.desc->language), g); } } diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index dea9b8e6ec..9c1a700423 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -30,8 +30,6 @@ #include "common/textconsole.h" #include "common/translation.h" #include "gui/EventRecorder.h" -#include "gui/gui-manager.h" -#include "engines/unknown-game-dialog.h" #include "engines/advancedDetector.h" #include "engines/obsolete.h" @@ -63,6 +61,17 @@ static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGa return gd; } +DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const { + DetectedGame game; + game.engineName = getName(); + game.gameId = adGame.desc->gameId; + game.hasUnknownFiles = adGame.hasUnknownFiles; + game.matchedFiles = adGame.matchedFiles; + game.matchedGame = toGameDescriptor(*adGame.desc, _gameIds); + updateGameDescriptor(game.matchedGame, adGame.desc); + return game; +} + /** * Generate a preferred target value as * GAMEID-PLAFORM-LANG @@ -129,11 +138,11 @@ void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGame desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); } -bool cleanupPirated(ADGameDescList &matched) { +bool cleanupPirated(ADDetectedGames &matched) { // OKay, now let's sense presence of pirated games if (!matched.empty()) { for (uint j = 0; j < matched.size();) { - if (matched[j]->flags & ADGF_PIRATED) + if (matched[j].desc->flags & ADGF_PIRATED) matched.remove_at(j); else ++j; @@ -150,35 +159,46 @@ bool cleanupPirated(ADGameDescList &matched) { } -GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist, bool useUnknownGameDialog) const { - ADGameDescList matches; - GameList detectedGames; +DetectedGames AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { FileMap allFiles; if (fslist.empty()) - return detectedGames; + return DetectedGames(); // Compose a hashmap of all files in fslist. composeFileHashMap(allFiles, fslist, (_maxScanDepth == 0 ? 1 : _maxScanDepth)); // Run the detector on this - matches = detectGame(fslist.begin()->getParent(), allFiles, Common::UNK_LANG, Common::kPlatformUnknown, "", useUnknownGameDialog); + ADDetectedGames matches = detectGame(fslist.begin()->getParent(), allFiles, Common::UNK_LANG, Common::kPlatformUnknown, ""); - if (matches.empty()) { - // Use fallback detector if there were no matches by other means - const ADGameDescription *fallbackDesc = fallbackDetect(allFiles, fslist); - if (fallbackDesc != nullptr) { - GameDescriptor desc(toGameDescriptor(*fallbackDesc, _gameIds)); - updateGameDescriptor(desc, fallbackDesc); - detectedGames.push_back(desc); + cleanupPirated(matches); + + DetectedGames detectedGames; + for (uint i = 0; i < matches.size(); i++) { + DetectedGame game = toDetectedGame(matches[i]); + + if (game.hasUnknownFiles) { + // Non fallback games with unknown files cannot be added/launched + game.canBeAdded = false; } - } else { - // Otherwise use the found matches - cleanupPirated(matches); - for (uint i = 0; i < matches.size(); i++) { - GameDescriptor desc(toGameDescriptor(*matches[i], _gameIds)); - updateGameDescriptor(desc, matches[i]); - detectedGames.push_back(desc); + + detectedGames.push_back(game); + } + + bool foundKnownGames = false; + for (uint i = 0; i < detectedGames.size(); i++) { + foundKnownGames |= detectedGames[i].canBeAdded; + } + + if (!foundKnownGames) { + // Use fallback detector if there were no matches by other means + ADDetectedGame fallbackDetectionResult = fallbackDetect(allFiles, fslist); + + if (fallbackDetectionResult.desc) { + DetectedGame fallbackDetectedGame = toDetectedGame(fallbackDetectionResult); + fallbackDetectedGame.preferredTarget += "-fallback"; + + detectedGames.push_back(fallbackDetectedGame); } } @@ -216,7 +236,6 @@ const ExtraGuiOptions AdvancedMetaEngine::getExtraGuiOptions(const Common::Strin Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(engine); - const ADGameDescription *agdDesc = 0; Common::Language language = Common::UNK_LANG; Common::Platform platform = Common::kPlatformUnknown; Common::String extra; @@ -266,46 +285,43 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) composeFileHashMap(allFiles, files, (_maxScanDepth == 0 ? 1 : _maxScanDepth)); // Run the detector on this - ADGameDescList matches = detectGame(files.begin()->getParent(), allFiles, language, platform, extra); + ADDetectedGames matches = detectGame(files.begin()->getParent(), allFiles, language, platform, extra); if (cleanupPirated(matches)) return Common::kNoGameDataFoundError; - if (_singleId == NULL) { - // Find the first match with correct gameid. - for (uint i = 0; i < matches.size(); i++) { - if (matches[i]->gameId == gameid) { - agdDesc = matches[i]; - break; - } + ADDetectedGame agdDesc; + for (uint i = 0; i < matches.size(); i++) { + if ((_singleId || matches[i].desc->gameId == gameid) && !matches[i].hasUnknownFiles) { + agdDesc = matches[i]; + break; } - } else if (matches.size() > 0) { - agdDesc = matches[0]; } - if (agdDesc == 0) { + if (!agdDesc.desc) { // Use fallback detector if there were no matches by other means - agdDesc = fallbackDetect(allFiles, files); - if (agdDesc != 0) { + ADDetectedGame fallbackDetectedGame = fallbackDetect(allFiles, files); + agdDesc = fallbackDetectedGame; + if (agdDesc.desc) { // Seems we found a fallback match. But first perform a basic // sanity check: the gameid must match. - if (_singleId == NULL && agdDesc->gameId != gameid) - agdDesc = 0; + if (!_singleId && agdDesc.desc->gameId != gameid) + agdDesc = ADDetectedGame(); } } - if (agdDesc == 0) + if (!agdDesc.desc) return Common::kNoGameDataFoundError; // If the GUI options were updated, we catch this here and update them in the users config // file transparently. - Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc->language); - if (agdDesc->flags & ADGF_ADDENGLISH) + Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc.desc->language); + if (agdDesc.desc->flags & ADGF_ADDENGLISH) lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY); - Common::updateGameGUIOptions(agdDesc->guiOptions + _guiOptions, lang); + Common::updateGameGUIOptions(agdDesc.desc->guiOptions + _guiOptions, lang); - GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc, _gameIds); + GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc.desc, _gameIds); bool showTestingWarning = false; @@ -320,65 +336,13 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) return Common::kUserCanceled; debug(2, "Running %s", gameDescriptor.description().c_str()); - initSubSystems(agdDesc); - if (!createInstance(syst, engine, agdDesc)) + initSubSystems(agdDesc.desc); + if (!createInstance(syst, engine, agdDesc.desc)) return Common::kNoGameDataFoundError; else return Common::kNoError; } -void AdvancedMetaEngine::reportUnknown(const Common::FSNode &path, const ADFilePropertiesMap &filesProps, const ADGameIdList &matchedGameIds, bool useUnknownGameDialog) const { - const char *reportCommon = _s("The game in '%s' seems to be an unknown %s engine game " - "variant.\n\nPlease report the following data to the ScummVM " - "team at %s along with the name of the game you tried to add and " - "its version, language, etc.:"); - Common::String report = Common::String::format(reportCommon, path.getPath().c_str(), getName(), "https://bugs.scummvm.org/"); - Common::String reportTranslated = Common::String::format(_(reportCommon), path.getPath().c_str(), getName(), "https://bugs.scummvm.org/"); - Common::String bugtrackerAffectedEngine = getName(); - - if (!matchedGameIds.empty()) { - report += "\n\n"; - reportTranslated += "\n\n"; - report += "Matched game IDs:"; - reportTranslated += _("Matched game IDs:"); - report += " "; - reportTranslated += " "; - - for (ADGameIdList::const_iterator gameId = matchedGameIds.begin(); gameId != matchedGameIds.end(); ++gameId) { - if (gameId != matchedGameIds.begin()) { - report += ", "; - reportTranslated += ", "; - } - report += *gameId; - reportTranslated += *gameId; - } - } - - report += "\n\n"; - reportTranslated += "\n\n"; - - reportTranslated.wordWrap(65); - Common::String reportLog = report; - reportLog.wordWrap(80); - - Common::String unknownFiles; - for (ADFilePropertiesMap::const_iterator file = filesProps.begin(); file != filesProps.end(); ++file) - unknownFiles += Common::String::format(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size); - - report += unknownFiles; - reportTranslated += unknownFiles; - reportLog += unknownFiles + "\n"; - - // Write the original message about the unknown game to the log file - g_system->logMessage(LogMessageType::kInfo, reportLog.c_str()); - - // Check if the GUI is running, show the UnknownGameDialog and print the translated unknown game information - if (GUI::GuiManager::hasInstance() && g_gui.isActive() && useUnknownGameDialog == true) { - UnknownGameDialog dialog(report, reportTranslated, bugtrackerAffectedEngine); - dialog.runModal(); - } -} - void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName) const { if (depth <= 0) return; @@ -419,7 +383,7 @@ void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSL } } -bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, ADFileProperties &fileProps) const { +bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const { // FIXME/TODO: We don't handle the case that a file is listed as a regular // file and as one with resource fork. @@ -449,8 +413,9 @@ bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const F return true; } -ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, bool useUnknownGameDialog) const { - ADFilePropertiesMap filesProps; +ADDetectedGames AdvancedMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const { + FilePropertiesMap filesProps; + ADDetectedGames matched; const ADGameFileDescription *fileDesc; const ADGameDescription *g; @@ -465,7 +430,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { Common::String fname = fileDesc->fileName; - ADFileProperties tmp; + FileProperties tmp; if (filesProps.contains(fname)) continue; @@ -477,8 +442,6 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons } } - ADGameDescList matched; - ADGameIdList matchedGameIds; int maxFilesMatched = 0; bool gotAnyMatchesWithAllFiles = false; @@ -486,7 +449,6 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons uint i; for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != nullptr; descPtr += _descItemSize, ++i) { g = (const ADGameDescription *)descPtr; - bool fileMissing = false; // Do not even bother to look at entries which do not have matching // language and platform (if specified). @@ -499,34 +461,33 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra) continue; + ADDetectedGame game(g); bool allFilesPresent = true; int curFilesMatched = 0; - bool hashOrSizeMismatch = false; // Try to match all files for this game - for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { + for (fileDesc = game.desc->filesDescriptions; fileDesc->fileName; fileDesc++) { Common::String tstr = fileDesc->fileName; if (!filesProps.contains(tstr)) { - fileMissing = true; allFilesPresent = false; break; } - if (hashOrSizeMismatch) + game.matchedFiles[tstr] = filesProps[tstr]; + + if (game.hasUnknownFiles) continue; if (fileDesc->md5 != nullptr && fileDesc->md5 != filesProps[tstr].md5) { debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesProps[tstr].md5.c_str()); - fileMissing = true; - hashOrSizeMismatch = true; + game.hasUnknownFiles = true; continue; } if (fileDesc->fileSize != -1 && fileDesc->fileSize != filesProps[tstr].size) { debug(3, "Size Mismatch. Skipping"); - fileMissing = true; - hashOrSizeMismatch = true; + game.hasUnknownFiles = true; continue; } @@ -543,13 +504,12 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons // Potentially this could rule out variants where some particular file // is really missing, but the developers should better know about such // cases. - if (allFilesPresent) { - gotAnyMatchesWithAllFiles = true; - if (matchedGameIds.empty() || strcmp(matchedGameIds.back(), g->gameId) != 0) - matchedGameIds.push_back(g->gameId); + if (allFilesPresent && !gotAnyMatchesWithAllFiles) { + if (matched.empty() || strcmp(matched.back().desc->gameId, g->gameId) != 0) + matched.push_back(game); } - if (!fileMissing) { + if (allFilesPresent && !game.hasUnknownFiles) { debug(2, "Found game: %s (%s %s/%s) (%d)", g->gameId, g->extra, getPlatformDescription(g->platform), getLanguageDescription(g->language), i); @@ -558,37 +518,29 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons maxFilesMatched = curFilesMatched; matched.clear(); // Remove any prior, lower ranked matches. - matched.push_back(g); + matched.push_back(game); } else if (curFilesMatched == maxFilesMatched) { - matched.push_back(g); + matched.push_back(game); } else { debug(2, " ... skipped"); } + gotAnyMatchesWithAllFiles = true; } else { debug(5, "Skipping game: %s (%s %s/%s) (%d)", g->gameId, g->extra, getPlatformDescription(g->platform), getLanguageDescription(g->language), i); } } - // We didn't find a match - if (matched.empty()) { - if (!filesProps.empty() && gotAnyMatchesWithAllFiles) { - reportUnknown(parent, filesProps, matchedGameIds, useUnknownGameDialog); - } - - // Filename based fallback - } - return matched; } -const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback, ADFilePropertiesMap *filesProps) const { +ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const { const ADFileBasedFallback *ptr; const char* const* filenames; int maxNumMatchedFiles = 0; - const ADGameDescription *matchedDesc = 0; + ADDetectedGame result; for (ptr = fileBasedFallback; ptr->desc; ++ptr) { const ADGameDescription *agdesc = ptr->desc; @@ -609,25 +561,26 @@ const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap & debug(4, "Matched: %s", agdesc->gameId); if (numMatchedFiles > maxNumMatchedFiles) { - matchedDesc = agdesc; maxNumMatchedFiles = numMatchedFiles; debug(4, "and overridden"); - if (filesProps) { - for (filenames = ptr->filenames; *filenames; ++filenames) { - ADFileProperties tmp; + ADDetectedGame game(agdesc); + game.hasUnknownFiles = true; + + for (filenames = ptr->filenames; *filenames; ++filenames) { + FileProperties tmp; - if (getFileProperties(fslist.begin()->getParent(), allFiles, *agdesc, *filenames, tmp)) - (*filesProps)[*filenames] = tmp; - } + if (getFileProperties(fslist.begin()->getParent(), allFiles, *agdesc, *filenames, tmp)) + game.matchedFiles[*filenames] = tmp; } + result = game; } } } - return matchedDesc; + return result; } GameList AdvancedMetaEngine::getSupportedGames() const { diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index d7e85f86fe..f1f55d0b4b 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -47,20 +47,6 @@ struct ADGameFileDescription { int32 fileSize; ///< Size of the described file. Set to -1 to ignore. }; -/** - * A record describing the properties of a file. Used on the existing - * files while detecting a game. - */ -struct ADFileProperties { - int32 size; - Common::String md5; -}; - -/** - * A map of all relevant existing files in a game directory while detecting. - */ -typedef Common::HashMap ADFilePropertiesMap; - /** * A shortcut to produce an empty ADGameFileDescription record. Used to mark * the end of a list of these. @@ -112,14 +98,19 @@ struct ADGameDescription { }; /** - * A list of pointers to ADGameDescription structs (or subclasses thereof). + * A game installation matching an AD game description */ -typedef Common::Array ADGameDescList; +struct ADDetectedGame { + bool hasUnknownFiles; + FilePropertiesMap matchedFiles; + const ADGameDescription *desc; -/** - * A list of raw game ID strings. - */ -typedef Common::Array ADGameIdList; + ADDetectedGame() : desc(nullptr), hasUnknownFiles(false) {} + explicit ADDetectedGame(const ADGameDescription *d) : desc(d), hasUnknownFiles(false) {} +}; + +/** A list of games detected by the AD */ +typedef Common::Array ADDetectedGames; /** * End marker for a table of ADGameDescription structs. Use this to @@ -278,7 +269,7 @@ public: virtual GameDescriptor findGame(const char *gameId) const; - virtual GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const; + DetectedGames detectGames(const Common::FSList &fslist) const override; virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; @@ -294,8 +285,8 @@ protected: * An (optional) generic fallback detect function which is invoked * if the regular MD5 based detection failed to detect anything. */ - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - return 0; + virtual ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + return ADDetectedGame(); } private: @@ -313,7 +304,7 @@ protected: * @param extra restrict results to specified extra string (only if kADFlagUseExtraAsHint is set) * @return list of ADGameDescription pointers corresponding to matched games */ - virtual ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, bool useUnknownGameDialog = false) const; + virtual ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const; /** * Iterates over all ADFileBasedFallback records inside fileBasedFallback. @@ -327,13 +318,7 @@ protected: * @param fileBasedFallback a list of ADFileBasedFallback records, zero-terminated * @param filesProps if not 0, return a map of properties for all detected files here */ - const ADGameDescription *detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback, ADFilePropertiesMap *filesProps = 0) const; - - /** - * Log and print a report that we found an unknown game variant, together with the file - * names, sizes and MD5 sums. - */ - void reportUnknown(const Common::FSNode &path, const ADFilePropertiesMap &filesProps, const ADGameIdList &matchedGameIds = ADGameIdList(), bool useUnknownGameDialog = false) const; + ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const; // TODO void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const; @@ -345,7 +330,10 @@ protected: void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName = Common::String()) const; /** Get the properties (size and MD5) of this file. */ - bool getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, ADFileProperties &fileProps) const; + bool getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const; + + /** Convert an AD game description into the shared game description format */ + DetectedGame toDetectedGame(const ADDetectedGame &adGame) const; }; #endif diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 817be08f2c..39275c4f70 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -220,7 +220,7 @@ public: virtual void removeSaveState(const char *target, int slot) const; SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; }; bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -421,7 +421,7 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl } } -const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const { +ADDetectedGame AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const { typedef Common::HashMap IntMap; IntMap allFiles; bool matchedUsingFilenames = false; @@ -584,10 +584,10 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX g_system->logMessage(LogMessageType::kWarning, fallbackWarning.c_str()); - return (const ADGameDescription *)&g_fallbackDesc; + return ADDetectedGame(&g_fallbackDesc.desc); } - return 0; + return ADDetectedGame(); } #if PLUGIN_ENABLED_DYNAMIC(AGI) diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp index 4c23939d60..f6399d484c 100644 --- a/engines/cge/detection.cpp +++ b/engines/cge/detection.cpp @@ -126,7 +126,7 @@ public: return "Soltys (C) 1994-1996 L.K. Avalon"; } - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; virtual int getMaximumSaveSlot() const; @@ -135,13 +135,8 @@ public: virtual void removeSaveState(const char *target, int slot) const; }; -static const ADFileBasedFallback fileBasedFallback[] = { - { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } }, - { 0, { 0 } } -}; - static ADGameDescription s_fallbackDesc = { - "Soltys", + "soltys", "Unknown version", AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor Common::UNK_LANG, @@ -150,28 +145,29 @@ static ADGameDescription s_fallbackDesc = { GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }; -const ADGameDescription *CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADFilePropertiesMap filesProps; +static const ADFileBasedFallback fileBasedFallback[] = { + { &s_fallbackDesc, { "vol.cat", "vol.dat", 0 } }, + { 0, { 0 } } +}; - const ADGameDescription *game; - game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback, &filesProps); +ADDetectedGame CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + ADDetectedGame game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback); - if (!game) - return nullptr; + if (!game.desc) + return ADDetectedGame(); SearchMan.addDirectory("CGEMetaEngine::fallbackDetect", fslist.begin()->getParent()); ResourceManager *resman; resman = new ResourceManager(); - bool result = resman->exist("CGE.SAY"); + bool sayFileFound = resman->exist("CGE.SAY"); delete resman; SearchMan.remove("CGEMetaEngine::fallbackDetect"); - if (!result) - return nullptr; + if (!sayFileFound) + return ADDetectedGame(); - reportUnknown(fslist.begin()->getParent(), filesProps); - return &s_fallbackDesc; + return game; } bool CGEMetaEngine::hasFeature(MetaEngineFeature f) const { diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp index 648dcc01e2..ec6925ac74 100644 --- a/engines/cge2/detection.cpp +++ b/engines/cge2/detection.cpp @@ -132,7 +132,7 @@ public: return "Sfinx (C) 1994-1997 Janus B. Wisniewski and L.K. Avalon"; } - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; virtual bool hasFeature(MetaEngineFeature f) const; virtual int getMaximumSaveSlot() const; @@ -141,13 +141,8 @@ public: virtual void removeSaveState(const char *target, int slot) const; }; -static const ADFileBasedFallback fileBasedFallback[] = { - { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } }, - { 0, { 0 } } -}; - static ADGameDescription s_fallbackDesc = { - "Sfinx", + "sfinx", "Unknown version", AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor Common::UNK_LANG, @@ -156,30 +151,31 @@ static ADGameDescription s_fallbackDesc = { GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }; +static const ADFileBasedFallback fileBasedFallback[] = { + { &s_fallbackDesc, { "vol.cat", "vol.dat", 0 } }, + { 0, { 0 } } +}; + // This fallback detection looks identical to the one used for CGE. In fact, the difference resides // in the ResourceManager which handles a different archive format. The rest of the detection is identical. -const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADFilePropertiesMap filesProps; - - const ADGameDescription *game; - game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback, &filesProps); +ADDetectedGame CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + ADDetectedGame game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback); - if (!game) - return 0; + if (!game.desc) + return ADDetectedGame(); SearchMan.addDirectory("CGE2MetaEngine::fallbackDetect", fslist.begin()->getParent()); ResourceManager *resman; resman = new ResourceManager(); - bool result = resman->exist("CGE.SAY"); + bool sayFileFound = resman->exist("CGE.SAY"); delete resman; SearchMan.remove("CGE2MetaEngine::fallbackDetect"); - if (!result) - return 0; + if (!sayFileFound) + return ADDetectedGame(); - reportUnknown(fslist.begin()->getParent(), filesProps); - return &s_fallbackDesc; + return game; } bool CGE2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp index 16d838fcca..9d293846bc 100644 --- a/engines/director/detection.cpp +++ b/engines/director/detection.cpp @@ -112,7 +112,7 @@ public: return "Macromedia Director (C) Macromedia"; } - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; }; @@ -141,7 +141,7 @@ static Director::DirectorGameDescription s_fallbackDesc = { static char s_fallbackFileNameBuffer[51]; -const ADGameDescription *DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { +ADDetectedGame DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { // TODO: Handle Mac fallback // reset fallback description @@ -230,10 +230,10 @@ const ADGameDescription *DirectorMetaEngine::fallbackDetect(const FileMap &allFi warning("Director fallback detection D%d", desc->version); - return (ADGameDescription *)desc; + return ADDetectedGame(&desc->desc); } - return 0; + return ADDetectedGame(); } #if PLUGIN_ENABLED_DYNAMIC(DIRECTOR) diff --git a/engines/game.cpp b/engines/game.cpp index 7ff51a99cc..177880c39d 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -22,6 +22,7 @@ #include "engines/game.h" #include "common/gui_options.h" +#include "common/translation.h" const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) { @@ -124,3 +125,89 @@ void GameDescriptor::setSupportLevel(GameSupportLevel gsl) { erase("gsl"); } } + +DetectionResults::DetectionResults(const DetectedGames &detectedGames) : + _detectedGames(detectedGames) { +} + +bool DetectionResults::foundUnknownGames() const { + for (uint i = 0; i < _detectedGames.size(); i++) { + if (_detectedGames[i].hasUnknownFiles) { + return true; + } + } + return false; +} + +DetectedGames DetectionResults::listRecognizedGames() { + DetectedGames candidates; + for (uint i = 0; i < _detectedGames.size(); i++) { + if (_detectedGames[i].canBeAdded) { + candidates.push_back(_detectedGames[i]); + } + } + return candidates; +} + +Common::String DetectionResults::generateUnknownGameReport(bool translate, uint32 wordwrapAt) const { + assert(!_detectedGames.empty()); + + const char *reportStart = _s("The game in '%s' seems to be an unknown game variant.\n\n" + "Please report the following data to the ScummVM team at %s " + "along with the name of the game you tried to add and " + "its version, language, etc.:"); + const char *reportEngineHeader = _s("Matched game IDs for the %s engine:"); + + Common::String report = Common::String::format( + translate ? _(reportStart) : reportStart, _detectedGames[0].matchedGame["path"].c_str(), + "https://bugs.scummvm.org/" + ); + report += "\n"; + + FilePropertiesMap matchedFiles; + + const char *currentEngineName = nullptr; + for (uint i = 0; i < _detectedGames.size(); i++) { + const DetectedGame &game = _detectedGames[i]; + + if (!game.hasUnknownFiles) continue; + + if (!currentEngineName || strcmp(currentEngineName, game.engineName) != 0) { + currentEngineName = game.engineName; + + // If the engine is not the same as for the previous entry, print an engine line header + report += "\n"; + report += Common::String::format( + translate ? _(reportEngineHeader) : reportEngineHeader, + game.engineName + ); + report += " "; + + } else { + report += ", "; + } + + // Add the gameId to the list of matched games for the engine + // TODO: Use the gameId here instead of the preferred target. + // This is currently impossible due to the AD singleId feature losing the information. + report += game.matchedGame["preferredtarget"]; + + // Consolidate matched files across all engines and detection entries + for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) { + matchedFiles.setVal(it->_key, it->_value); + } + } + + if (wordwrapAt) { + report.wordWrap(wordwrapAt); + } + + report += "\n\n"; + + for (FilePropertiesMap::const_iterator file = matchedFiles.begin(); file != matchedFiles.end(); ++file) + report += Common::String::format(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size); + + report += "\n"; + + return report; +} diff --git a/engines/game.h b/engines/game.h index e01e5c6885..54c1af3949 100644 --- a/engines/game.h +++ b/engines/game.h @@ -115,4 +115,108 @@ public: } }; +/** + * A record describing the properties of a file. Used on the existing + * files while detecting a game. + */ +struct FileProperties { + int32 size; + Common::String md5; + + FileProperties() : size(-1) {} +}; + +/** + * A map of all relevant existing files while detecting. + */ +typedef Common::HashMap FilePropertiesMap; + +struct DetectedGame { + /** + * The name of the engine supporting the detected game + */ + const char *engineName; + + /** + * The identifier of the detected game + * + * For engines using the singleId feature, this is the true engine-specific gameId, not the singleId. + */ + const char *gameId; + + /** + * A game was detected, but some files were not recognized + * + * This can happen when the md5 or size of the detected files did not match the engine's detection tables. + * When this is true, the list of matched files below contains detail about the unknown files. + * + * @see matchedFiles + */ + bool hasUnknownFiles; + + /** + * An optional list of the files that were used to match the game with the engine's detection tables + */ + FilePropertiesMap matchedFiles; + + /** + * This detection entry contains enough data to add the game to the configuration manager and launch it + * + * @see matchedGame + */ + bool canBeAdded; + + /** + * Details about the detected game + */ + GameDescriptor matchedGame; + + DetectedGame() : engineName(nullptr), gameId(nullptr), hasUnknownFiles(false), canBeAdded(true) {} +}; + +typedef Common::Array DetectedGames; + +/** + * Contains a list of games found by the engines' detectors. + * + * Each detected game can either: + * - be fully recognized (e.g. an exact match was found in the detection tables of an engine) + * - be an unknown variant (e.g. a game using files with the same name was found in the detection tables) + * - be recognized with unknown files (e.g. the game was exactly not found in the detection tables, + * but the detector was able to gather enough data to allow launching the game) + * + * Practically, this means a detected game can be in both the recognized game list and in the unknown game + * report handled by this class. + */ +class DetectionResults { +public: + explicit DetectionResults(const DetectedGames &detectedGames); + + /** + * List all the games that were recognized by the engines + * + * Recognized games can be added to the configuration manager and then launched. + */ + DetectedGames listRecognizedGames(); + + /** + * Were unknown game variants found by the engines? + * + * When unknown game variants are found, an unknown game report can be generated. + */ + bool foundUnknownGames() const; + + /** + * Generate a report that we found an unknown game variant, together with the file + * names, sizes and MD5 sums. + * + * @param translate translate the report to the currently active GUI language + * @param wordwrapAt word wrap the text part of the report after a number of characters + */ + Common::String generateUnknownGameReport(bool translate, uint32 wordwrapAt = 0) const; + +private: + DetectedGames _detectedGames; +}; + #endif diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp index e204ced1e8..487b65f4a8 100644 --- a/engines/gob/detection/detection.cpp +++ b/engines/gob/detection/detection.cpp @@ -35,7 +35,7 @@ public: virtual GameDescriptor findGame(const char *gameId) const; - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; virtual const char *getName() const; virtual const char *getOriginalCopyright() const; @@ -63,25 +63,22 @@ GameDescriptor GobMetaEngine::findGame(const char *gameId) const { return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable); } -const ADGameDescription *GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADFilePropertiesMap filesProps; +ADDetectedGame GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + ADDetectedGame detectedGame = detectGameFilebased(allFiles, fslist, Gob::fileBased); + if (!detectedGame.desc) { + return ADDetectedGame(); + } - const Gob::GOBGameDescription *game; - game = (const Gob::GOBGameDescription *)detectGameFilebased(allFiles, fslist, Gob::fileBased, &filesProps); - if (!game) - return 0; + const Gob::GOBGameDescription *game = (const Gob::GOBGameDescription *)detectedGame.desc; if (game->gameType == Gob::kGameTypeOnceUponATime) { game = detectOnceUponATime(fslist); - if (!game) - return 0; + if (game) { + detectedGame.desc = &game->desc; + } } - ADGameIdList gameIds; - gameIds.push_back(game->desc.gameId); - - reportUnknown(fslist.begin()->getParent(), filesProps, gameIds); - return (const ADGameDescription *)game; + return detectedGame; } const Gob::GOBGameDescription *GobMetaEngine::detectOnceUponATime(const Common::FSList &fslist) { diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 636c2d147c..bf05385c88 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -535,7 +535,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; }; @@ -557,7 +557,7 @@ bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame return gd != 0; } -const ADGameDescription *MadeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { +ADDetectedGame MadeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { // Set the default values for the fallback descriptor's ADGameDescription part. Made::g_fallbackDesc.desc.language = Common::UNK_LANG; Made::g_fallbackDesc.desc.platform = Common::kPlatformDOS; @@ -569,7 +569,7 @@ const ADGameDescription *MadeMetaEngine::fallbackDetect(const FileMap &allFiles, Made::g_fallbackDesc.version = 3; //return (const ADGameDescription *)&Made::g_fallbackDesc; - return NULL; + return ADDetectedGame(); } #if PLUGIN_ENABLED_DYNAMIC(MADE) diff --git a/engines/metaengine.h b/engines/metaengine.h index 68f4b36848..9a0280d116 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -79,7 +79,7 @@ public: * (possibly empty) list of games supported by the engine which it was able * to detect amongst the given files. */ - virtual GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const = 0; + virtual DetectedGames detectGames(const Common::FSList &fslist) const = 0; /** * Tries to instantiate an engine instance based on the settings of @@ -269,7 +269,7 @@ class EngineManager : public Common::Singleton { public: GameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin = NULL) const; GameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const; - GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const; + DetectionResults detectGames(const Common::FSList &fslist) const; const PluginList &getPlugins() const; }; diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 82f901d9ad..94ca4f0513 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -184,7 +184,7 @@ public: _directoryGlobs = directoryGlobs; } - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { return detectGameFilebased(allFiles, fslist, Mohawk::fileBased); } diff --git a/engines/queen/detection.cpp b/engines/queen/detection.cpp index aed8b7dcb1..f7cde05fbd 100644 --- a/engines/queen/detection.cpp +++ b/engines/queen/detection.cpp @@ -447,7 +447,7 @@ public: virtual int getMaximumSaveSlot() const { return 99; } virtual void removeSaveState(const char *target, int slot) const; - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; }; bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -457,7 +457,7 @@ bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSupportsDeleteSave); } -const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { +ADDetectedGame QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { static ADGameDescription desc; // Iterate over all files in the given directory @@ -492,11 +492,13 @@ const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles desc.extra = "Talkie"; desc.guiOptions = GAMEOPTION_ALT_INTRO; } - return (const ADGameDescription *)&desc; + + return ADDetectedGame(&desc); } } } - return 0; + + return ADDetectedGame(); } SaveStateList QueenMetaEngine::listSaves(const char *target) const { diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index bc7241269d..9a70429e47 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -562,7 +562,7 @@ public: } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const; - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; virtual bool hasFeature(MetaEngineFeature f) const; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; @@ -590,7 +590,7 @@ Common::Language charToScummVMLanguage(const char c) { } } -const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { +ADDetectedGame SciMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { bool foundResMap = false; bool foundRes000 = false; @@ -647,7 +647,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, // If these files aren't found, it can't be SCI if (!foundResMap && !foundRes000) - return 0; + return ADDetectedGame(); ResourceManager resMan(true); resMan.addAppropriateSourcesForDetection(fslist); @@ -658,7 +658,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, // Is SCI32 compiled in? If not, and this is a SCI32 game, // stop here if (getSciVersionForDetection() >= SCI_VERSION_2) - return 0; + return ADDetectedGame(); #endif ViewType gameViews = resMan.getViewType(); @@ -667,7 +667,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, // Can't be SCI (or unsupported SCI views). Pinball Creep by Sierra also uses resource.map/resource.000 files // but doesn't share SCI format at all if (gameViews == kViewUnknown) - return 0; + return ADDetectedGame(); // Set the platform to Amiga if the game is using Amiga views if (gameViews == kViewAmiga) @@ -678,7 +678,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, // If we don't have a game id, the game is not SCI if (sierraGameId.empty()) - return 0; + return ADDetectedGame(); Common::String gameId = convertSierraGameId(sierraGameId, &s_fallbackDesc.flags, resMan); strncpy(s_fallbackGameIdBuf, gameId.c_str(), sizeof(s_fallbackGameIdBuf) - 1); @@ -753,7 +753,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, s_fallbackDesc.extra = "CD"; } - return &s_fallbackDesc; + return ADDetectedGame(&s_fallbackDesc); } bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 9573db55cd..078cc8de27 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -961,7 +961,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual GameList getSupportedGames() const; virtual GameDescriptor findGame(const char *gameid) const; - virtual GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const; + virtual DetectedGames detectGames(const Common::FSList &fslist) const override; virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; @@ -1026,29 +1026,30 @@ static Common::String generatePreferredTarget(const DetectorResult &x) { return res; } -GameList ScummMetaEngine::detectGames(const Common::FSList &fslist, bool /*useUnknownGameDialog*/) const { - GameList detectedGames; +DetectedGames ScummMetaEngine::detectGames(const Common::FSList &fslist) const { + DetectedGames detectedGames; Common::List results; - ::detectGames(fslist, results, 0); for (Common::List::iterator x = results.begin(); x != results.end(); ++x) { const PlainGameDescriptor *g = findPlainGameDescriptor(x->game.gameid, gameDescriptions); assert(g); - GameDescriptor dg(x->game.gameid, g->description, x->language, x->game.platform); + + DetectedGame game; + game.matchedGame = GameDescriptor(x->game.gameid, g->description, x->language, x->game.platform); // Append additional information, if set, to the description. - dg.updateDesc(x->extra); + game.matchedGame.updateDesc(x->extra); // Compute and set the preferred target name for this game. // Based on generateComplexID() in advancedDetector.cpp. - dg["preferredtarget"] = generatePreferredTarget(*x); + game.matchedGame["preferredtarget"] = generatePreferredTarget(*x); - dg.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi)); - dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); + game.matchedGame.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); - detectedGames.push_back(dg); + detectedGames.push_back(game); } return detectedGames; diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index a74b63fb8c..cc1f1adc82 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -79,7 +79,7 @@ public: virtual GameList getSupportedGames() const; virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; virtual GameDescriptor findGame(const char *gameid) const; - virtual GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const; + DetectedGames detectGames(const Common::FSList &fslist) const override; virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; @@ -141,8 +141,8 @@ GameDescriptor SkyMetaEngine::findGame(const char *gameid) const { return GameDescriptor(); } -GameList SkyMetaEngine::detectGames(const Common::FSList &fslist, bool /*useUnknownGameDialog*/) const { - GameList detectedGames; +DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const { + DetectedGames detectedGames; bool hasSkyDsk = false; bool hasSkyDnr = false; int dinnerTableEntries = -1; @@ -173,18 +173,19 @@ GameList SkyMetaEngine::detectGames(const Common::FSList &fslist, bool /*useUnkn // Match found, add to list of candidates, then abort inner loop. // The game detector uses US English by default. We want British // English to match the recorded voices better. - GameDescriptor dg(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown); + DetectedGame game; + game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown); const SkyVersion *sv = skyVersions; while (sv->dinnerTableEntries) { if (dinnerTableEntries == sv->dinnerTableEntries && (sv->dataDiskSize == dataDiskSize || sv->dataDiskSize == -1)) { - dg.updateDesc(Common::String::format("v0.0%d %s", sv->version, sv->extraDesc).c_str()); - dg.setGUIOptions(sv->guioptions); + game.matchedGame.updateDesc(Common::String::format("v0.0%d %s", sv->version, sv->extraDesc).c_str()); + game.matchedGame.setGUIOptions(sv->guioptions); break; } ++sv; } - detectedGames.push_back(dg); + detectedGames.push_back(game); } return detectedGames; diff --git a/engines/sludge/detection.cpp b/engines/sludge/detection.cpp index a530a5c796..85c0f22907 100644 --- a/engines/sludge/detection.cpp +++ b/engines/sludge/detection.cpp @@ -100,10 +100,10 @@ public: } // for fall back detection - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; }; -const ADGameDescription *SludgeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { +ADDetectedGame SludgeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { // reset fallback description s_fallbackDesc.desc.gameId = "sludge"; s_fallbackDesc.desc.extra = ""; @@ -147,9 +147,19 @@ const ADGameDescription *SludgeMetaEngine::fallbackDetect(const FileMap &allFile s_fallbackFileNameBuffer[50] = '\0'; s_fallbackDesc.desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer; - return (const ADGameDescription *)&s_fallbackDesc; + ADDetectedGame game; + game.desc = &s_fallbackDesc.desc; + + FileProperties tmp; + if (getFileProperties(file->getParent(), allFiles, s_fallbackDesc.desc, fileName, tmp)) { + game.hasUnknownFiles = true; + game.matchedFiles[fileName] = tmp; + } + + return game; } - return 0; + + return ADDetectedGame(); } #if PLUGIN_ENABLED_DYNAMIC(SLUDGE) diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index ddfc4b8c14..7fb86fec0b 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -89,7 +89,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual GameList getSupportedGames() const; virtual GameDescriptor findGame(const char *gameid) const; - virtual GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const; + DetectedGames detectGames(const Common::FSList &fslist) const override; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; virtual void removeSaveState(const char *target, int slot) const; @@ -175,9 +175,9 @@ void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound, bool r } } -GameList SwordMetaEngine::detectGames(const Common::FSList &fslist, bool /*useUnknownGameDialog*/) const { +DetectedGames SwordMetaEngine::detectGames(const Common::FSList &fslist) const { int i, j; - GameList detectedGames; + DetectedGames detectedGames; bool filesFound[NUM_FILES_TO_CHECK]; for (i = 0; i < NUM_FILES_TO_CHECK; i++) filesFound[i] = false; @@ -212,31 +212,31 @@ GameList SwordMetaEngine::detectGames(const Common::FSList &fslist, bool /*useUn if (!filesFound[i] || psxFilesFound) psxDemoFilesFound = false; - GameDescriptor gd; + DetectedGame game; if (mainFilesFound && pcFilesFound && demoFilesFound) - gd = GameDescriptor(sword1DemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1DemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); else if (mainFilesFound && pcFilesFound && psxFilesFound) - gd = GameDescriptor(sword1PSXSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1PSXSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); else if (mainFilesFound && pcFilesFound && psxDemoFilesFound) - gd = GameDescriptor(sword1PSXDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1PSXDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); else if (mainFilesFound && pcFilesFound && !psxFilesFound) - gd = GameDescriptor(sword1FullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1FullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); else if (mainFilesFound && macFilesFound) - gd = GameDescriptor(sword1MacFullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1MacFullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); else if (mainFilesFound && macDemoFilesFound) - gd = GameDescriptor(sword1MacDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1MacDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); else return detectedGames; - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU)); - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA)); - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA)); - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP)); - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA)); - gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE)); - detectedGames.push_back(gd); + detectedGames.push_back(game); return detectedGames; } diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 10ddda7d2e..27fcc74ad5 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -95,7 +95,7 @@ public: virtual GameList getSupportedGames() const; virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; virtual GameDescriptor findGame(const char *gameid) const; - virtual GameList detectGames(const Common::FSList &fslist, bool useUnknownGameDialog = false) const; + virtual DetectedGames detectGames(const Common::FSList &fslist) const; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; virtual void removeSaveState(const char *target, int slot) const; @@ -148,7 +148,7 @@ GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const { bool isFullGame(const Common::FSList &fslist) { Common::FSList::const_iterator file; - // We distinguish between the two versions by the presense of paris.clu + // We distinguish between the two versions by the presence of paris.clu for (file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { if (file->getName().equalsIgnoreCase("paris.clu")) @@ -159,8 +159,8 @@ bool isFullGame(const Common::FSList &fslist) { return false; } -GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { - GameList detectedGames; +DetectedGames detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { + DetectedGames detectedGames; const Sword2::GameSettings *g; Common::FSList::const_iterator file; bool isFullVersion = isFullGame(fslist); @@ -192,7 +192,10 @@ GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { continue; // Match found, add to list of candidates, then abort inner loop. - detectedGames.push_back(GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); + DetectedGame game; + game.matchedGame = GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + + detectedGames.push_back(game); break; } } @@ -208,7 +211,7 @@ GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { if (file->getName().equalsIgnoreCase("clusters")) { Common::FSList recList; if (file->getChildren(recList, Common::FSNode::kListAll)) { - GameList recGames(detectGamesImpl(recList, true)); + DetectedGames recGames = detectGamesImpl(recList, true); if (!recGames.empty()) { detectedGames.push_back(recGames); break; @@ -223,7 +226,7 @@ GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { return detectedGames; } -GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist, bool /*useUnknownGameDialog*/) const { +DetectedGames Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { return detectGamesImpl(fslist); } @@ -278,10 +281,10 @@ Common::Error Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) c // Invoke the detector Common::String gameid = ConfMan.get("gameid"); - GameList detectedGames = detectGames(fslist); + DetectedGames detectedGames = detectGames(fslist); for (uint i = 0; i < detectedGames.size(); i++) { - if (detectedGames[i].gameid() == gameid) { + if (detectedGames[i].matchedGame.gameid() == gameid) { *engine = new Sword2::Sword2Engine(syst); return Common::kNoError; } diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index d6bcfe5ea0..1c60c5eb8a 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -97,7 +97,7 @@ public: } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; virtual bool hasFeature(MetaEngineFeature f) const; virtual SaveStateList listSaves(const char *target) const; @@ -185,7 +185,7 @@ typedef Common::Array ADGameDescList; * Fallback detection scans the list of Discworld 2 targets to see if it can detect an installation * where the files haven't been renamed (i.e. don't have the '1' just before the extension) */ -const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const { +ADDetectedGame TinselMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const { Common::String extra; FileMap allFiles; SizeMD5Map filesSizeMD5; @@ -194,7 +194,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile const Tinsel::TinselGameDescription *g; if (fslist.empty()) - return NULL; + return ADDetectedGame(); // TODO: The following code is essentially a slightly modified copy of the // complete code of function detectGame() in engines/advancedDetector.cpp. @@ -262,7 +262,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile } } - ADGameDescList matched; + ADDetectedGame matched; int maxFilesMatched = 0; // MD5 based matching @@ -310,22 +310,15 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) curFilesMatched++; - if (curFilesMatched > maxFilesMatched) { + if (curFilesMatched >= maxFilesMatched) { maxFilesMatched = curFilesMatched; - matched.clear(); // Remove any prior, lower ranked matches. - matched.push_back((const ADGameDescription *)g); - } else if (curFilesMatched == maxFilesMatched) { - matched.push_back((const ADGameDescription *)g); + matched = ADDetectedGame(&g->desc); } } } - // We didn't find a match - if (matched.empty()) - return NULL; - - return *matched.begin(); + return matched; } int TinselMetaEngine::getMaximumSaveSlot() const { return 99; } diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp index 6eb38c4883..634d286c7c 100644 --- a/engines/toon/detection.cpp +++ b/engines/toon/detection.cpp @@ -132,7 +132,7 @@ public: _directoryGlobs = directoryGlobs; } - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { return detectGameFilebased(allFiles, fslist, Toon::fileBasedFallback); } diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index dcb58ffae6..51b17b26d9 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -133,15 +133,8 @@ public: _directoryGlobs = directoryGlobs; } - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADFilePropertiesMap filesProps; - - const ADGameDescription *matchedDesc = detectGameFilebased(allFiles, fslist, Touche::fileBasedFallback, &filesProps); - if (!matchedDesc) - return 0; - - reportUnknown(fslist.begin()->getParent(), filesProps); - return matchedDesc; + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { + return detectGameFilebased(allFiles, fslist, Touche::fileBasedFallback); } virtual const char *getName() const { diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index 119d60f23a..2318947b12 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -149,18 +149,19 @@ public: return desc != 0; } - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + virtual ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { for (Common::FSList::const_iterator d = fslist.begin(); d != fslist.end(); ++d) { Common::FSList audiofslist; if (d->isDirectory() && d->getName().equalsIgnoreCase("audio") && d->getChildren(audiofslist, Common::FSNode::kListFilesOnly)) { for (Common::FSList::const_iterator f = audiofslist.begin(); f != audiofslist.end(); ++f) { if (!f->isDirectory() && f->getName().equalsIgnoreCase("demorolc.raw")) { - return &tuckerDemoGameDescription; + return ADDetectedGame(&tuckerDemoGameDescription); } } } } - return 0; + + return ADDetectedGame(); } virtual SaveStateList listSaves(const char *target) const { diff --git a/engines/unknown-game-dialog.cpp b/engines/unknown-game-dialog.cpp index f737eb1c67..1b7dd73a92 100644 --- a/engines/unknown-game-dialog.cpp +++ b/engines/unknown-game-dialog.cpp @@ -20,14 +20,16 @@ * */ +#include "engines/unknown-game-dialog.h" + #include "common/translation.h" #include "common/str-array.h" #include "common/system.h" + #include "gui/gui-manager.h" #include "gui/message.h" #include "gui/ThemeEval.h" #include "gui/widgets/popup.h" -#include "engines/unknown-game-dialog.h" enum { kCopyToClipboard = 'cpcl', @@ -35,36 +37,33 @@ enum { kClose = 'clse' }; -UnknownGameDialog::UnknownGameDialog(const Common::String &reportData, const Common::String &reportTranslated, const Common::String &bugtrackerAffectedEngine) - : Dialog(30, 20, 260, 124) { - - _reportData = reportData; - _reportTranslated = reportTranslated; - _bugtrackerAffectedEngine = bugtrackerAffectedEngine; +UnknownGameDialog::UnknownGameDialog(const DetectionResults &detectionResults) : + Dialog(30, 20, 260, 124), + _detectionResults(detectionResults) { + Common::String reportTranslated = _detectionResults.generateUnknownGameReport(true); - //Check if we have clipboard functionality and expand the reportTranslated message if needed... + // Check if we have clipboard functionality and expand the reportTranslated message if needed... if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) { - _reportTranslated += "\n"; - _reportTranslated += _("Use the button below to copy the required game information into your clipboard."); + reportTranslated += "\n"; + reportTranslated += _("Use the button below to copy the required game information into your clipboard."); } #if 0 - //Check if we have support for opening URLs and expand the reportTranslated message if needed... + // Check if we have support for opening URLs and expand the reportTranslated message if needed... if (g_system->hasFeature(OSystem::kFeatureOpenUrl)) { - _reportTranslated += "\n"; - _reportTranslated += _("You can also directly report your game to the Bug Tracker!"); + reportTranslated += "\n"; + reportTranslated += _("You can also directly report your game to the Bug Tracker."); } #endif const int screenW = g_system->getOverlayWidth(); - const int screenH = g_system->getOverlayHeight(); int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0); int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0); - //Calculate the size the dialog needs + // Calculate the size the dialog needs Common::Array lines; - int maxlineWidth = g_gui.getFont().wordWrapText(_reportTranslated, screenW - 2 * 20, lines); + int maxlineWidth = g_gui.getFont().wordWrapText(reportTranslated, screenW - 2 * 20, lines); int lineCount = lines.size() + 1; _h = 3 * kLineHeight + lineCount * kLineHeight; @@ -84,7 +83,7 @@ UnknownGameDialog::UnknownGameDialog(const Common::String &reportData, const Com int buttonPos = _w - closeButtonWidth - 10; new GUI::ButtonWidget(this, buttonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, _("Close"), 0, kClose); - //Check if we have clipboard functionality + // Check if we have clipboard functionality if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) { buttonPos -= copyToClipboardButtonWidth + 5; new GUI::ButtonWidget(this, buttonPos, _h - buttonHeight - 8, copyToClipboardButtonWidth, buttonHeight, _("Copy to clipboard"), 0, kCopyToClipboard); @@ -98,15 +97,10 @@ UnknownGameDialog::UnknownGameDialog(const Common::String &reportData, const Com // https://www.scummvm.org/unknowngame?engine=Foo&description=Bar) that would // redirect to whatever our bugtracker system is. - //Check if we have support for opening URLs + // Check if we have support for opening URLs if (g_system->hasFeature(OSystem::kFeatureOpenUrl)) { buttonPos -= openBugtrackerURLButtonWidth + 5; new GUI::ButtonWidget(this, buttonPos, _h - buttonHeight - 8, openBugtrackerURLButtonWidth, buttonHeight, _("Report game"), 0, kOpenBugtrackerURL); - //Formatting the reportData for bugtracker submission [replace line breaks]... - _bugtrackerGameData = _reportData; - while (_bugtrackerGameData.contains("\n")) { - Common::replace(_bugtrackerGameData, "\n", "%0A"); - } } #endif @@ -126,27 +120,39 @@ void UnknownGameDialog::reflowLayout() { } Common::String UnknownGameDialog::generateBugtrackerURL() { - return Common::String::format(( + // TODO: Remove the filesystem path from the bugtracker report + Common::String report = _detectionResults.generateUnknownGameReport(false); + + // Formatting the report for bugtracker submission [replace line breaks]... + while (report.contains("\n")) { + Common::replace(report, "\n", "%0A"); + } + + return Common::String::format( "https://bugs.scummvm.org/newticket?" - "summary=[UNK] Unknown game for engine %s:" "&description=%s" - "&component=Engine%%3A%s" "&type=enhancement" - "&keywords=unknown-game,%s"), - _bugtrackerAffectedEngine.c_str(), _bugtrackerGameData.c_str(), _bugtrackerAffectedEngine.c_str(), _bugtrackerAffectedEngine.c_str()); + "&keywords=unknown-game", + report.c_str()); } void UnknownGameDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) { switch(cmd) { - case kCopyToClipboard: - g_system->setTextInClipboard(_reportData); - if (g_system->setTextInClipboard(_reportData)) { - g_system->displayMessageOnOSD(_("All necessary information about your game has been copied into the clipboard")); + case kCopyToClipboard: { + // TODO: Remove the filesystem path from the report + Common::String report = _detectionResults.generateUnknownGameReport(false); + + if (g_system->setTextInClipboard(report)) { + g_system->displayMessageOnOSD( + _("All necessary information about your game has been copied into the clipboard")); } else { g_system->displayMessageOnOSD(_("Copying the game information to the clipboard has failed!")); } break; + } case kClose: + // When the detection entry comes from the fallback detector, the game can be added / launched anyways. + // TODO: Add a button to cancel adding the game. And make it clear that launching the game may not work properly. close(); break; case kOpenBugtrackerURL: diff --git a/engines/unknown-game-dialog.h b/engines/unknown-game-dialog.h index 51adf27996..0878406244 100644 --- a/engines/unknown-game-dialog.h +++ b/engines/unknown-game-dialog.h @@ -22,16 +22,18 @@ #include "gui/dialog.h" +#include "engines/metaengine.h" + class UnknownGameDialog : public GUI::Dialog { public: - UnknownGameDialog(const Common::String &reportData, const Common::String &reportTranslated, const Common::String &bugtrackerAffectedEngine); - void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); - virtual Common::String generateBugtrackerURL(); - virtual void reflowLayout(); + UnknownGameDialog(const DetectionResults &detectionResults); private: - Common::String _reportData; - Common::String _reportTranslated; - Common::String _bugtrackerGameData; - Common::String _bugtrackerAffectedEngine; + // Dialog API + void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override; + void reflowLayout() override; + + Common::String generateBugtrackerURL(); + + const DetectionResults &_detectionResults; }; diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index df5cc41b10..6208d775a6 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -100,7 +100,7 @@ public: return "Copyright (C) 2011 Jan Nedoma"; } - virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { // Set some defaults s_fallbackDesc.extra = ""; s_fallbackDesc.language = Common::UNK_LANG; @@ -130,10 +130,12 @@ public: s_fallbackDesc.extra = offset; s_fallbackDesc.flags |= ADGF_USEEXTRAASTITLE; } - return &s_fallbackDesc; + + return ADDetectedGame(&s_fallbackDesc); } // Fall through to return 0; } - return 0; + + return ADDetectedGame(); } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 857d7d001a..b14be6c11e 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -45,6 +45,7 @@ #include "gui/EventRecorder.h" #endif #include "gui/saveload.h" +#include "engines/unknown-game-dialog.h" #include "gui/widgets/edittext.h" #include "gui/widgets/list.h" #include "gui/widgets/tab.h" @@ -573,7 +574,17 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { // ...so let's determine a list of candidates, games that // could be contained in the specified directory. - GameList candidates(EngineMan.detectGames(files, true)); + DetectionResults detectionResults = EngineMan.detectGames(files); + + if (detectionResults.foundUnknownGames()) { + Common::String report = detectionResults.generateUnknownGameReport(false, 80); + g_system->logMessage(LogMessageType::kInfo, report.c_str()); + + UnknownGameDialog dialog(detectionResults); + dialog.runModal(); + } + + Common::Array candidates = detectionResults.listRecognizedGames(); int idx; if (candidates.empty()) { @@ -589,17 +600,14 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { // Display the candidates to the user and let her/him pick one StringArray list; for (idx = 0; idx < (int)candidates.size(); idx++) - list.push_back(candidates[idx].description()); + list.push_back(candidates[idx].matchedGame.description()); ChooserDialog dialog(_("Pick the game:")); dialog.setList(list); idx = dialog.runModal(); } if (0 <= idx && idx < (int)candidates.size()) { - GameDescriptor result = candidates[idx]; - - // TODO: Change the detectors to set "path" ! - result["path"] = dir.getPath(); + const GameDescriptor &result = candidates[idx].matchedGame; Common::String domain = addGameToConf(result); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index db569fac82..2774d476db 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -187,7 +187,12 @@ void MassAddDialog::handleTickle() { } // Run the detector on the dir - GameList candidates(EngineMan.detectGames(files)); + DetectionResults detectionResults = EngineMan.detectGames(files); + + if (detectionResults.foundUnknownGames()) { + Common::String report = detectionResults.generateUnknownGameReport(false, 80); + g_system->logMessage(LogMessageType::kInfo, report.c_str()); + } // Just add all detected games / game variants. If we get more than one, // that either means the directory contains multiple games, or the detector @@ -195,8 +200,9 @@ void MassAddDialog::handleTickle() { // case, let the user choose which entries he wants to keep. // // However, we only add games which are not already in the config file. - for (GameList::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) { - GameDescriptor result = *cand; + DetectedGames candidates = detectionResults.listRecognizedGames(); + for (DetectedGames::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) { + const GameDescriptor &result = cand->matchedGame; Common::String path = dir.getPath(); // Remove trailing slashes @@ -224,7 +230,6 @@ void MassAddDialog::handleTickle() { break; // Skip duplicates } } - result["path"] = path; _games.push_back(result); _list->append(result.description()); -- cgit v1.2.3 From 8fb149e3c7603f023dfccf2b2056a9a2fda431c2 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 6 May 2018 12:57:08 +0200 Subject: ENGINES: Change MetaEngine::findGame to return a plain game descriptor --- base/commandLine.cpp | 14 +++++++------- base/main.cpp | 9 ++++++--- base/plugins.cpp | 16 ++++++++-------- engines/advancedDetector.cpp | 6 +++--- engines/advancedDetector.h | 2 +- engines/agos/detection.cpp | 2 +- engines/cine/detection.cpp | 2 +- engines/game.h | 5 ++++- engines/gob/detection/detection.cpp | 4 ++-- engines/metaengine.h | 8 ++++---- engines/obsolete.cpp | 10 +++++----- engines/obsolete.h | 2 +- engines/saga/detection.cpp | 2 +- engines/scumm/detection.cpp | 4 ++-- engines/sky/detection.cpp | 8 ++++---- engines/sword1/detection.cpp | 18 +++++++++--------- engines/sword2/sword2.cpp | 6 +++--- gui/EventRecorder.cpp | 4 ++-- gui/editgamedialog.cpp | 8 ++++---- gui/editgamedialog.h | 2 +- gui/launcher.cpp | 11 ++++++----- gui/recorderdialog.cpp | 4 ++-- 22 files changed, 77 insertions(+), 70 deletions(-) diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 8e701408ef..0755165094 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -714,10 +714,10 @@ static void listTargets() { // FIXME: At this point, we should check for a "gameid" override // to find the proper desc. In fact, the platform probably should // be taken into account, too. - Common::String gameid(name); - GameDescriptor g = EngineMan.findGame(gameid); - if (g.description().size() > 0) - description = g.description(); + const Common::String &gameid = name; + PlainGameDescriptor g = EngineMan.findGame(gameid); + if (g.description) + description = g.description; } targets.push_back(Common::String::format("%-20s %s", name.c_str(), description.c_str())); @@ -770,7 +770,7 @@ static Common::Error listSaves(const Common::String &target) { // Find the plugin that will handle the specified gameid const Plugin *plugin = nullptr; - GameDescriptor game = EngineMan.findGame(gameid, &plugin); + EngineMan.findGame(gameid, &plugin); if (!plugin) { // If the target was specified, treat this as an error, and otherwise skip it. @@ -1276,8 +1276,8 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo // domain (i.e. a target) matching this argument, or alternatively // whether there is a gameid matching that name. if (!command.empty()) { - GameDescriptor gd = EngineMan.findGame(command); - if (ConfMan.hasGameDomain(command) || !gd.gameid().empty()) { + PlainGameDescriptor gd = EngineMan.findGame(command); + if (ConfMan.hasGameDomain(command) || gd.gameId) { bool idCameFromCommandLine = false; // WORKAROUND: Fix for bug #1719463: "DETECTOR: Launching diff --git a/base/main.cpp b/base/main.cpp index 8e783c9776..385b8f35a9 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -128,13 +128,13 @@ static const Plugin *detectPlugin() { printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str()); printf(" Looking for a plugin supporting this gameid... "); - GameDescriptor game = EngineMan.findGame(gameid, &plugin); + PlainGameDescriptor game = EngineMan.findGame(gameid, &plugin); if (plugin == 0) { printf("failed\n"); warning("%s is an invalid gameid. Use the --list-games option to list supported gameid", gameid.c_str()); } else { - printf("%s\n Starting '%s'\n", plugin->getName(), game.description().c_str()); + printf("%s\n Starting '%s'\n", plugin->getName(), game.description); } return plugin; @@ -210,7 +210,10 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common Common::String caption(ConfMan.get("description")); if (caption.empty()) { - caption = EngineMan.findGame(ConfMan.get("gameid")).description(); + PlainGameDescriptor game = EngineMan.findGame(ConfMan.get("gameid")); + if (game.description) { + caption = game.description; + } } if (caption.empty()) caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name diff --git a/base/plugins.cpp b/base/plugins.cpp index 02f6998ad9..25dd3e1e0c 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -458,13 +458,13 @@ DECLARE_SINGLETON(EngineManager); * For the uncached version, we first try to find the plugin using the gameId * and only if we can't find it there, we loop through the plugins. **/ -GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plugin **plugin) const { - GameDescriptor result; +PlainGameDescriptor EngineManager::findGame(const Common::String &gameName, const Plugin **plugin) const { + PlainGameDescriptor result; // First look for the game using the plugins in memory. This is critical // for calls coming from inside games result = findGameInLoadedPlugins(gameName, plugin); - if (!result.gameid().empty()) { + if (result.gameId) { return result; } @@ -472,7 +472,7 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plu // by plugin if (PluginMan.loadPluginFromGameId(gameName)) { result = findGameInLoadedPlugins(gameName, plugin); - if (!result.gameid().empty()) { + if (result.gameId) { return result; } } @@ -481,7 +481,7 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plu PluginMan.loadFirstPlugin(); do { result = findGameInLoadedPlugins(gameName, plugin); - if (!result.gameid().empty()) { + if (result.gameId) { // Update with new plugin file name PluginMan.updateConfigWithFileName(gameName); break; @@ -494,10 +494,10 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plu /** * Find the game within the plugins loaded in memory **/ -GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin) const { +PlainGameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin) const { // Find the GameDescriptor for this target const PluginList &plugins = getPlugins(); - GameDescriptor result; + PlainGameDescriptor result; if (plugin) *plugin = 0; @@ -506,7 +506,7 @@ GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &game for (iter = plugins.begin(); iter != plugins.end(); ++iter) { result = (*iter)->get().findGame(gameName.c_str()); - if (!result.gameid().empty()) { + if (result.gameId) { if (plugin) *plugin = *iter; return result; diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 9c1a700423..43c2082c7d 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -602,14 +602,14 @@ GameList AdvancedMetaEngine::getSupportedGames() const { return GameList(_gameIds); } -GameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const { +PlainGameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const { // First search the list of supported gameids for a match. const PlainGameDescriptor *g = findPlainGameDescriptor(gameId, _gameIds); if (g) - return GameDescriptor(*g); + return *g; // No match found - return GameDescriptor(); + return PlainGameDescriptor(); } AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds, const ADExtraGuiOptionsMap *extraGuiOptions) diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index f1f55d0b4b..ec52134c78 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -267,7 +267,7 @@ public: */ virtual GameList getSupportedGames() const; - virtual GameDescriptor findGame(const char *gameId) const; + PlainGameDescriptor findGame(const char *gameId) const override; DetectedGames detectGames(const Common::FSList &fslist) const override; diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index dbc4ee9145..1847434200 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -99,7 +99,7 @@ public: _directoryGlobs = directoryGlobs; } - virtual GameDescriptor findGame(const char *gameId) const { + PlainGameDescriptor findGame(const char *gameId) const override { return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable); } diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index 6c8b4a676d..f1636c902b 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -84,7 +84,7 @@ public: _guiOptions = GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD); } - virtual GameDescriptor findGame(const char *gameId) const { + PlainGameDescriptor findGame(const char *gameId) const override { return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable); } diff --git a/engines/game.h b/engines/game.h index 54c1af3949..88033dcf09 100644 --- a/engines/game.h +++ b/engines/game.h @@ -38,6 +38,9 @@ struct PlainGameDescriptor { const char *gameId; const char *description; + + PlainGameDescriptor() : gameId(nullptr), description(nullptr) {} + PlainGameDescriptor(const char *id, const char *desc) : gameId(id), description(desc) {} }; /** @@ -66,7 +69,7 @@ enum GameSupportLevel { class GameDescriptor : public Common::StringMap { public: GameDescriptor(); - GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions = Common::String()); + explicit GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions = Common::String()); GameDescriptor(const Common::String &gameid, const Common::String &description, Common::Language language = Common::UNK_LANG, diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp index 487b65f4a8..864a701aa6 100644 --- a/engines/gob/detection/detection.cpp +++ b/engines/gob/detection/detection.cpp @@ -33,7 +33,7 @@ class GobMetaEngine : public AdvancedMetaEngine { public: GobMetaEngine(); - virtual GameDescriptor findGame(const char *gameId) const; + PlainGameDescriptor findGame(const char *gameId) const override; ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override; @@ -59,7 +59,7 @@ GobMetaEngine::GobMetaEngine() : _guiOptions = GUIO1(GUIO_NOLAUNCHLOAD); } -GameDescriptor GobMetaEngine::findGame(const char *gameId) const { +PlainGameDescriptor GobMetaEngine::findGame(const char *gameId) const { return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable); } diff --git a/engines/metaengine.h b/engines/metaengine.h index 9a0280d116..9ce8dc9f11 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -71,8 +71,8 @@ public: /** Returns a list of games supported by this engine. */ virtual GameList getSupportedGames() const = 0; - /** Query the engine for a GameDescriptor for the specified gameid, if any. */ - virtual GameDescriptor findGame(const char *gameid) const = 0; + /** Query the engine for a PlainGameDescriptor for the specified gameid, if any. */ + virtual PlainGameDescriptor findGame(const char *gameId) const = 0; /** * Runs the engine's game detector on the given list of files, and returns a @@ -267,8 +267,8 @@ public: */ class EngineManager : public Common::Singleton { public: - GameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin = NULL) const; - GameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const; + PlainGameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin = NULL) const; + PlainGameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const; DetectionResults detectGames(const Common::FSList &fslist) const; const PluginList &getPlugins() const; }; diff --git a/engines/obsolete.cpp b/engines/obsolete.cpp index d65fb13ec1..48809df712 100644 --- a/engines/obsolete.cpp +++ b/engines/obsolete.cpp @@ -55,7 +55,7 @@ void upgradeTargetIfNecessary(const ObsoleteGameID *obsoleteList) { } } -GameDescriptor findGameID( +PlainGameDescriptor findGameID( const char *gameid, const PlainGameDescriptor *gameids, const ObsoleteGameID *obsoleteList @@ -63,7 +63,7 @@ GameDescriptor findGameID( // First search the list of supported gameids for a match. const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, gameids); if (g) - return GameDescriptor(*g); + return *g; // If we didn't find the gameid in the main list, check if it // is an obsolete game id. @@ -73,16 +73,16 @@ GameDescriptor findGameID( if (0 == scumm_stricmp(gameid, o->from)) { g = findPlainGameDescriptor(o->to, gameids); if (g && g->description) - return GameDescriptor(gameid, "Obsolete game ID (" + Common::String(g->description) + ")"); + return PlainGameDescriptor(gameid, g->description); else - return GameDescriptor(gameid, "Obsolete game ID"); + return PlainGameDescriptor(gameid, "Obsolete game ID"); } o++; } } // No match found - return GameDescriptor(); + return PlainGameDescriptor(); } } // End of namespace Engines diff --git a/engines/obsolete.h b/engines/obsolete.h index be0963a7dc..7c7249e52b 100644 --- a/engines/obsolete.h +++ b/engines/obsolete.h @@ -66,7 +66,7 @@ void upgradeTargetIfNecessary(const ObsoleteGameID *obsoleteList); * Optionally can take a list of obsolete game ids into account in order * to support obsolete gameids. */ -GameDescriptor findGameID( +PlainGameDescriptor findGameID( const char *gameid, const PlainGameDescriptor *gameids, const ObsoleteGameID *obsoleteList = 0 diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index fcd78502d9..82c29d3389 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -105,7 +105,7 @@ public: _singleId = "saga"; } - virtual GameDescriptor findGame(const char *gameId) const { + PlainGameDescriptor findGame(const char *gameId) const override { return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable); } diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 078cc8de27..2ba5bd3f74 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -960,7 +960,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual GameList getSupportedGames() const; - virtual GameDescriptor findGame(const char *gameid) const; + PlainGameDescriptor findGame(const char *gameid) const override; virtual DetectedGames detectGames(const Common::FSList &fslist) const override; virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; @@ -996,7 +996,7 @@ GameList ScummMetaEngine::getSupportedGames() const { return GameList(gameDescriptions); } -GameDescriptor ScummMetaEngine::findGame(const char *gameid) const { +PlainGameDescriptor ScummMetaEngine::findGame(const char *gameid) const { return Engines::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable); } diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index cc1f1adc82..629996bae1 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -78,7 +78,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual GameList getSupportedGames() const; virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; - virtual GameDescriptor findGame(const char *gameid) const; + PlainGameDescriptor findGame(const char *gameid) const override; DetectedGames detectGames(const Common::FSList &fslist) const override; virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; @@ -112,7 +112,7 @@ bool Sky::SkyEngine::hasFeature(EngineFeature f) const { GameList SkyMetaEngine::getSupportedGames() const { GameList games; - games.push_back(skySetting); + games.push_back(GameDescriptor(skySetting)); return games; } @@ -135,10 +135,10 @@ const ExtraGuiOptions SkyMetaEngine::getExtraGuiOptions(const Common::String &ta return options; } -GameDescriptor SkyMetaEngine::findGame(const char *gameid) const { +PlainGameDescriptor SkyMetaEngine::findGame(const char *gameid) const { if (0 == scumm_stricmp(gameid, skySetting.gameId)) return skySetting; - return GameDescriptor(); + return PlainGameDescriptor(); } DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const { diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 7fb86fec0b..62e8f1c905 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -88,7 +88,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual GameList getSupportedGames() const; - virtual GameDescriptor findGame(const char *gameid) const; + PlainGameDescriptor findGame(const char *gameId) const override; DetectedGames detectGames(const Common::FSList &fslist) const override; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; @@ -127,20 +127,20 @@ GameList SwordMetaEngine::getSupportedGames() const { return games; } -GameDescriptor SwordMetaEngine::findGame(const char *gameid) const { - if (0 == scumm_stricmp(gameid, sword1FullSettings.gameId)) +PlainGameDescriptor SwordMetaEngine::findGame(const char *gameId) const { + if (0 == scumm_stricmp(gameId, sword1FullSettings.gameId)) return sword1FullSettings; - if (0 == scumm_stricmp(gameid, sword1DemoSettings.gameId)) + if (0 == scumm_stricmp(gameId, sword1DemoSettings.gameId)) return sword1DemoSettings; - if (0 == scumm_stricmp(gameid, sword1MacFullSettings.gameId)) + if (0 == scumm_stricmp(gameId, sword1MacFullSettings.gameId)) return sword1MacFullSettings; - if (0 == scumm_stricmp(gameid, sword1MacDemoSettings.gameId)) + if (0 == scumm_stricmp(gameId, sword1MacDemoSettings.gameId)) return sword1MacDemoSettings; - if (0 == scumm_stricmp(gameid, sword1PSXSettings.gameId)) + if (0 == scumm_stricmp(gameId, sword1PSXSettings.gameId)) return sword1PSXSettings; - if (0 == scumm_stricmp(gameid, sword1PSXDemoSettings.gameId)) + if (0 == scumm_stricmp(gameId, sword1PSXDemoSettings.gameId)) return sword1PSXDemoSettings; - return GameDescriptor(); + return PlainGameDescriptor(); } void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound, bool recursion = false) { diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 27fcc74ad5..bf2f329119 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -94,7 +94,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual GameList getSupportedGames() const; virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; - virtual GameDescriptor findGame(const char *gameid) const; + PlainGameDescriptor findGame(const char *gameid) const override; virtual DetectedGames detectGames(const Common::FSList &fslist) const; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; @@ -135,14 +135,14 @@ const ExtraGuiOptions Sword2MetaEngine::getExtraGuiOptions(const Common::String return options; } -GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const { +PlainGameDescriptor Sword2MetaEngine::findGame(const char *gameid) const { const Sword2::GameSettings *g = Sword2::sword2_settings; while (g->gameid) { if (0 == scumm_stricmp(gameid, g->gameid)) break; g++; } - return GameDescriptor(g->gameid, g->description); + return PlainGameDescriptor(g->gameid, g->description); } bool isFullGame(const Common::FSList &fslist) { diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp index 849405410a..560df0ec35 100644 --- a/gui/EventRecorder.cpp +++ b/gui/EventRecorder.cpp @@ -600,13 +600,13 @@ void EventRecorder::setFileHeader() { return; } TimeDate t; - GameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName()); + PlainGameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName()); g_system->getTimeAndDate(t); if (_author.empty()) { setAuthor("Unknown Author"); } if (_name.empty()) { - g_eventRec.setName(Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description()); + g_eventRec.setName(Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description); } _playbackFile->getHeader().author = _author; _playbackFile->getHeader().notes = _desc; diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp index 4192c4058a..c4cf6e7800 100644 --- a/gui/editgamedialog.cpp +++ b/gui/editgamedialog.cpp @@ -95,7 +95,7 @@ protected: } }; -EditGameDialog::EditGameDialog(const String &domain, const String &desc) +EditGameDialog::EditGameDialog(const String &domain) : OptionsDialog(domain, "GameOptions") { // Retrieve all game specific options. const Plugin *plugin = nullptr; @@ -106,7 +106,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) gameId = domain; // Retrieve the plugin, since we need to access the engine's MetaEngine // implementation. - EngineMan.findGame(gameId, &plugin); + PlainGameDescriptor pgd = EngineMan.findGame(gameId, &plugin); if (plugin) { _engineOptions = plugin->get().getExtraGuiOptions(domain); } else { @@ -120,8 +120,8 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // GAME: Determine the description string String description(ConfMan.get("description", domain)); - if (description.empty() && !desc.empty()) { - description = desc; + if (description.empty() && pgd.description) { + description = pgd.description; } // GUI: Add tab widget diff --git a/gui/editgamedialog.h b/gui/editgamedialog.h index a317e364c6..06a8514dd5 100644 --- a/gui/editgamedialog.h +++ b/gui/editgamedialog.h @@ -62,7 +62,7 @@ class EditGameDialog : public OptionsDialog { typedef Common::String String; typedef Common::Array StringArray; public: - EditGameDialog(const String &domain, const String &desc); + EditGameDialog(const String &domain); void open(); virtual void apply(); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index b14be6c11e..f257c53e11 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -267,9 +267,9 @@ void LauncherDialog::updateListing() { if (gameid.empty()) gameid = iter->_key; if (description.empty()) { - GameDescriptor g = EngineMan.findGame(gameid); - if (g.contains("description")) - description = g.description(); + PlainGameDescriptor g = EngineMan.findGame(gameid); + if (g.description) + description = g.description; } if (description.empty()) { @@ -443,7 +443,8 @@ void LauncherDialog::editGame(int item) { String gameId(ConfMan.get("gameid", _domains[item])); if (gameId.empty()) gameId = _domains[item]; - EditGameDialog editDialog(_domains[item], EngineMan.findGame(gameId).description()); + + EditGameDialog editDialog(_domains[item]); if (editDialog.runModal() > 0) { // User pressed OK, so make changes permanent @@ -612,7 +613,7 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { Common::String domain = addGameToConf(result); // Display edit dialog for the new entry - EditGameDialog editDialog(domain, result.description()); + EditGameDialog editDialog(domain); if (editDialog.runModal() > 0) { // User pressed OK, so make changes permanent diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp index cd89b58f00..7a2cd048f4 100644 --- a/gui/recorderdialog.cpp +++ b/gui/recorderdialog.cpp @@ -167,9 +167,9 @@ void RecorderDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat case kRecordCmd: { TimeDate t; Common::String gameId = ConfMan.get("gameid", _target); - GameDescriptor desc = EngineMan.findGame(gameId); + PlainGameDescriptor desc = EngineMan.findGame(gameId); g_system->getTimeAndDate(t); - EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), ""); + EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description, ""); if (editDlg.runModal() != kOKCmd) { return; } -- cgit v1.2.3 From 643c24db75797728087999abd8acf1ecc83757fa Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 6 May 2018 13:09:52 +0200 Subject: ENGINES: Change MetaEngine::listSupportedGames to return plain game descriptors --- base/commandLine.cpp | 6 +++--- engines/advancedDetector.cpp | 8 ++++---- engines/advancedDetector.h | 2 +- engines/game.h | 24 +++++++++++++----------- engines/metaengine.h | 2 +- engines/scumm/detection.cpp | 6 +++--- engines/sky/detection.cpp | 8 ++++---- engines/sword1/detection.cpp | 18 +++++++++--------- engines/sword2/sword2.cpp | 8 ++++---- 9 files changed, 42 insertions(+), 40 deletions(-) diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 0755165094..1c7916c48f 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -687,9 +687,9 @@ static void listGames() { const PluginList &plugins = EngineMan.getPlugins(); for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) { - GameList list = (*iter)->get().getSupportedGames(); - for (GameList::iterator v = list.begin(); v != list.end(); ++v) { - printf("%-20s %s\n", v->gameid().c_str(), v->description().c_str()); + PlainGameList list = (*iter)->get().getSupportedGames(); + for (PlainGameList::iterator v = list.begin(); v != list.end(); ++v) { + printf("%-20s %s\n", v->gameId, v->description); } } } diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 43c2082c7d..562ad5dfe2 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -583,14 +583,14 @@ ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, return result; } -GameList AdvancedMetaEngine::getSupportedGames() const { +PlainGameList AdvancedMetaEngine::getSupportedGames() const { if (_singleId != NULL) { - GameList gl; + PlainGameList gl; const PlainGameDescriptor *g = _gameIds; while (g->gameId) { if (0 == scumm_stricmp(_singleId, g->gameId)) { - gl.push_back(GameDescriptor(g->gameId, g->description)); + gl.push_back(*g); return gl; } @@ -599,7 +599,7 @@ GameList AdvancedMetaEngine::getSupportedGames() const { error("Engine %s doesn't have its singleid specified in ids list", _singleId); } - return GameList(_gameIds); + return PlainGameList(_gameIds); } PlainGameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const { diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index ec52134c78..5762009ea7 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -265,7 +265,7 @@ public: * Returns list of targets supported by the engine. * Distinguishes engines with single ID */ - virtual GameList getSupportedGames() const; + PlainGameList getSupportedGames() const override; PlainGameDescriptor findGame(const char *gameId) const override; diff --git a/engines/game.h b/engines/game.h index 88033dcf09..a5cc4de4ec 100644 --- a/engines/game.h +++ b/engines/game.h @@ -50,6 +50,18 @@ struct PlainGameDescriptor { */ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list); +class PlainGameList : public Common::Array { +public: + PlainGameList() {} + PlainGameList(const PlainGameList &list) : Common::Array(list) {} + PlainGameList(const PlainGameDescriptor *g) { + while (g->gameId) { + push_back(*g); + g++; + } + } +}; + /** * Ths is an enum to describe how done a game is. This also indicates what level of support is expected. */ @@ -106,17 +118,7 @@ public: }; /** List of games. */ -class GameList : public Common::Array { -public: - GameList() {} - GameList(const GameList &list) : Common::Array(list) {} - GameList(const PlainGameDescriptor *g) { - while (g->gameId) { - push_back(GameDescriptor(*g)); - g++; - } - } -}; +typedef Common::Array GameList; /** * A record describing the properties of a file. Used on the existing diff --git a/engines/metaengine.h b/engines/metaengine.h index 9ce8dc9f11..74eb367200 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -69,7 +69,7 @@ public: virtual const char *getOriginalCopyright() const = 0; /** Returns a list of games supported by this engine. */ - virtual GameList getSupportedGames() const = 0; + virtual PlainGameList getSupportedGames() const = 0; /** Query the engine for a PlainGameDescriptor for the specified gameid, if any. */ virtual PlainGameDescriptor findGame(const char *gameId) const = 0; diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 2ba5bd3f74..6276f1ae41 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -959,7 +959,7 @@ public: virtual const char *getOriginalCopyright() const; virtual bool hasFeature(MetaEngineFeature f) const; - virtual GameList getSupportedGames() const; + PlainGameList getSupportedGames() const override; PlainGameDescriptor findGame(const char *gameid) const override; virtual DetectedGames detectGames(const Common::FSList &fslist) const override; @@ -992,8 +992,8 @@ bool ScummEngine::hasFeature(EngineFeature f) const { (f == kSupportsSubtitleOptions); } -GameList ScummMetaEngine::getSupportedGames() const { - return GameList(gameDescriptions); +PlainGameList ScummMetaEngine::getSupportedGames() const { + return PlainGameList(gameDescriptions); } PlainGameDescriptor ScummMetaEngine::findGame(const char *gameid) const { diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index 629996bae1..ffed998ab1 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -76,7 +76,7 @@ public: virtual const char *getOriginalCopyright() const; virtual bool hasFeature(MetaEngineFeature f) const; - virtual GameList getSupportedGames() const; + PlainGameList getSupportedGames() const override; virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; PlainGameDescriptor findGame(const char *gameid) const override; DetectedGames detectGames(const Common::FSList &fslist) const override; @@ -110,9 +110,9 @@ bool Sky::SkyEngine::hasFeature(EngineFeature f) const { (f == kSupportsSavingDuringRuntime); } -GameList SkyMetaEngine::getSupportedGames() const { - GameList games; - games.push_back(GameDescriptor(skySetting)); +PlainGameList SkyMetaEngine::getSupportedGames() const { + PlainGameList games; + games.push_back(skySetting); return games; } diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 62e8f1c905..80176aee40 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -87,7 +87,7 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; - virtual GameList getSupportedGames() const; + PlainGameList getSupportedGames() const override; PlainGameDescriptor findGame(const char *gameId) const override; DetectedGames detectGames(const Common::FSList &fslist) const override; virtual SaveStateList listSaves(const char *target) const; @@ -116,14 +116,14 @@ bool Sword1::SwordEngine::hasFeature(EngineFeature f) const { (f == kSupportsLoadingDuringRuntime); } -GameList SwordMetaEngine::getSupportedGames() const { - GameList games; - games.push_back(GameDescriptor(sword1FullSettings, GUIO_NOMIDI)); - games.push_back(GameDescriptor(sword1DemoSettings, GUIO_NOMIDI)); - games.push_back(GameDescriptor(sword1MacFullSettings, GUIO_NOMIDI)); - games.push_back(GameDescriptor(sword1MacDemoSettings, GUIO_NOMIDI)); - games.push_back(GameDescriptor(sword1PSXSettings, GUIO_NOMIDI)); - games.push_back(GameDescriptor(sword1PSXDemoSettings, GUIO_NOMIDI)); +PlainGameList SwordMetaEngine::getSupportedGames() const { + PlainGameList games; + games.push_back(sword1FullSettings); + games.push_back(sword1DemoSettings); + games.push_back(sword1MacFullSettings); + games.push_back(sword1MacDemoSettings); + games.push_back(sword1PSXSettings); + games.push_back(sword1PSXDemoSettings); return games; } diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index bf2f329119..f9e308ca63 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -92,7 +92,7 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; - virtual GameList getSupportedGames() const; + PlainGameList getSupportedGames() const override; virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; PlainGameDescriptor findGame(const char *gameid) const override; virtual DetectedGames detectGames(const Common::FSList &fslist) const; @@ -119,11 +119,11 @@ bool Sword2::Sword2Engine::hasFeature(EngineFeature f) const { (f == kSupportsLoadingDuringRuntime); } -GameList Sword2MetaEngine::getSupportedGames() const { +PlainGameList Sword2MetaEngine::getSupportedGames() const { const Sword2::GameSettings *g = Sword2::sword2_settings; - GameList games; + PlainGameList games; while (g->gameid) { - games.push_back(GameDescriptor(g->gameid, g->description)); + games.push_back(PlainGameDescriptor(g->gameid, g->description)); g++; } return games; -- cgit v1.2.3 From 5aff87dc153f392cb14423efa78a96397789a6fd Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 3 Dec 2017 12:19:08 +0100 Subject: ENGINES: Turn GameDescriptor into a simple struct --- base/commandLine.cpp | 83 ++++++++++++++++++++--------------- base/plugins.cpp | 2 +- engines/advancedDetector.cpp | 20 ++++----- engines/game.cpp | 101 ++++++++++++++++++------------------------- engines/game.h | 38 ++++++++-------- engines/scumm/detection.cpp | 2 +- engines/sword2/sword2.cpp | 2 +- gui/launcher.cpp | 27 +++++++++--- gui/massadd.cpp | 27 +++++++----- gui/massadd.h | 2 +- 10 files changed, 157 insertions(+), 147 deletions(-) diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 1c7916c48f..e1539d7a3e 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -881,8 +881,17 @@ static GameList getGameList(const Common::FSNode &dir) { return candidates; } +namespace { + +static void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) { + if (!value.empty()) + ConfMan.set(key, value, domain); +} + +} // End of anonymous namespace + static bool addGameToConf(const GameDescriptor &gd) { - const Common::String &domain = gd.preferredtarget(); + const Common::String &domain = gd.preferredTarget; // If game has already been added, don't add if (ConfMan.hasGameDomain(domain)) @@ -891,18 +900,22 @@ static bool addGameToConf(const GameDescriptor &gd) { // Add the name domain ConfMan.addGameDomain(domain); - // Copy all non-empty key/value pairs into the new domain - for (GameDescriptor::const_iterator iter = gd.begin(); iter != gd.end(); ++iter) { - if (!iter->_value.empty() && iter->_key != "preferredtarget") - ConfMan.set(iter->_key, iter->_value, domain); - } + // Copy all non-empty relevant values into the new domain + // FIXME: Factor out + addStringToConf("gameid", gd.gameId, domain); + addStringToConf("description", gd.description, domain); + addStringToConf("language", Common::getLanguageCode(gd.language), domain); + addStringToConf("platform", Common::getPlatformCode(gd.platform), domain); + addStringToConf("path", gd.path, domain); + addStringToConf("extra", gd.extra, domain); + addStringToConf("guioptions", gd.getGUIOptions(), domain); // Display added game info printf("Game Added: \n GameID: %s\n Name: %s\n Language: %s\n Platform: %s\n", - gd.gameid().c_str(), - gd.description().c_str(), - Common::getLanguageDescription(gd.language()), - Common::getPlatformDescription(gd.platform())); + gd.gameId.c_str(), + gd.description.c_str(), + Common::getLanguageDescription(gd.language), + Common::getPlatformDescription(gd.platform)); return true; } @@ -916,7 +929,7 @@ static GameList recListGames(const Common::FSNode &dir, const Common::String &ga for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) { GameList rec = recListGames(*file, gameId, recursive); for (GameList::const_iterator game = rec.begin(); game != rec.end(); ++game) { - if (gameId.empty() || game->gameid().c_str() == gameId) + if (gameId.empty() || game->gameId == gameId) list.push_back(*game); } } @@ -946,23 +959,23 @@ static Common::String detectGames(const Common::String &path, const Common::Stri printf("ID Description Full Path\n"); printf("-------------- ---------------------------------------------------------- ---------------------------------------------------------\n"); for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) { - printf("%-14s %-58s %s\n", v->gameid().c_str(), v->description().c_str(), (*v)["path"].c_str()); + printf("%-14s %-58s %s\n", v->gameId.c_str(), v->description.c_str(), v->path.c_str()); } - return candidates[0].gameid(); + return candidates[0].gameId; } static int recAddGames(const Common::FSNode &dir, const Common::String &game, bool recursive) { int count = 0; GameList list = getGameList(dir); for (GameList::iterator v = list.begin(); v != list.end(); ++v) { - if (v->gameid().c_str() != game && !game.empty()) { - printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameid().c_str(), game.c_str()); + if (v->gameId != game && !game.empty()) { + printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameId.c_str(), game.c_str()); } else if (!addGameToConf(*v)) { // TODO Is it reall the case that !addGameToConf iff already added? - printf("Found %s, but has already been added, skipping\n", v->gameid().c_str()); + printf("Found %s, but has already been added, skipping\n", v->gameId.c_str()); } else { - printf("Found %s, adding...\n", v->gameid().c_str()); + printf("Found %s, adding...\n", v->gameId.c_str()); count++; } } @@ -1033,7 +1046,7 @@ static void runDetectorTest() { bool gameidDiffers = false; GameList::iterator x; for (x = candidates.begin(); x != candidates.end(); ++x) { - gameidDiffers |= (scumm_stricmp(gameid.c_str(), x->gameid().c_str()) != 0); + gameidDiffers |= (scumm_stricmp(gameid.c_str(), x->gameId.c_str()) != 0); } if (candidates.empty()) { @@ -1056,10 +1069,10 @@ static void runDetectorTest() { for (x = candidates.begin(); x != candidates.end(); ++x) { printf(" gameid '%s', desc '%s', language '%s', platform '%s'\n", - x->gameid().c_str(), - x->description().c_str(), - Common::getLanguageCode(x->language()), - Common::getPlatformCode(x->platform())); + x->gameId.c_str(), + x->description.c_str(), + Common::getLanguageDescription(x->language), + Common::getPlatformDescription(x->platform)); } } int total = domains.size(); @@ -1131,7 +1144,7 @@ void upgradeTargets() { GameList::iterator x; int matchesFound = 0; for (x = candidates.begin(); x != candidates.end(); ++x) { - if (x->gameid() == gameid && x->language() == lang && x->platform() == plat) { + if (x->gameId == gameid && x->language == lang && x->platform == plat) { matchesFound++; g = &(*x); } @@ -1149,27 +1162,27 @@ void upgradeTargets() { // the target referred to by dom. We update several things // Always set the gameid explicitly (in case of legacy targets) - dom["gameid"] = g->gameid(); + 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"]; + if (!g->getGUIOptions().empty()) { + printf(" -> update guioptions to '%s'\n", g->getGUIOptions().c_str()); + dom["guioptions"] = g->getGUIOptions(); } 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 language to '%s'\n", Common::getLanguageCode(g->language())); - dom["language"] = (*g)["language"]; + if (lang == Common::UNK_LANG && g->language != Common::UNK_LANG) { + printf(" -> set language to '%s'\n", Common::getLanguageCode(g->language)); + dom["language"] = Common::getLanguageCode(g->language); } // Update the platform setting but only if none has been set yet. - if (plat == Common::kPlatformUnknown && g->platform() != Common::kPlatformUnknown) { - printf(" -> set platform to '%s'\n", Common::getPlatformCode(g->platform())); - dom["platform"] = (*g)["platform"]; + if (plat == Common::kPlatformUnknown && g->platform != Common::kPlatformUnknown) { + printf(" -> set platform to '%s'\n", Common::getPlatformCode(g->platform)); + dom["platform"] = Common::getPlatformCode(g->platform); } // TODO: We could also update the description. But not everybody will want that. @@ -1178,8 +1191,8 @@ void upgradeTargets() { // 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"]; + printf(" -> update desc from '%s' to\n '%s' ?\n", desc.c_str(), g->description.c_str()); + dom["description"] = g->description; } #endif } diff --git a/base/plugins.cpp b/base/plugins.cpp index 25dd3e1e0c..61dae910f9 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -531,7 +531,7 @@ DetectionResults EngineManager::detectGames(const Common::FSList &fslist) const for (uint i = 0; i < engineCandidates.size(); i++) { engineCandidates[i].engineName = metaEngine.getName(); - engineCandidates[i].matchedGame["path"] = path; + engineCandidates[i].matchedGame.path = path; candidates.push_back(engineCandidates[i]); } diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 562ad5dfe2..ac606d3e4b 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -114,22 +114,22 @@ static Common::String sanitizeName(const char *name) { void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const { if (_singleId != NULL) { - desc["preferredtarget"] = desc["gameid"]; - desc["gameid"] = _singleId; + desc.preferredTarget = desc.gameId; + desc.gameId = _singleId; } - if (!desc.contains("preferredtarget")) - desc["preferredtarget"] = desc["gameid"]; + if (desc.preferredTarget.empty()) + desc.preferredTarget = desc.gameId; if (realDesc->flags & ADGF_AUTOGENTARGET) { if (*realDesc->extra) - desc["preferredtarget"] = sanitizeName(realDesc->extra); + desc.preferredTarget = sanitizeName(realDesc->extra); } - desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], realDesc); + desc.preferredTarget = generatePreferredTarget(desc.preferredTarget, realDesc); if (_flags & kADFlagUseExtraAsHint) - desc["extra"] = realDesc->extra; + desc.extra = realDesc->extra; desc.setGUIOptions(realDesc->guiOptions + _guiOptions); desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language)); @@ -329,13 +329,13 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) showTestingWarning = true; #endif - if (((gameDescriptor.getSupportLevel() == kUnstableGame - || (gameDescriptor.getSupportLevel() == kTestingGame + if (((gameDescriptor.gameSupportLevel == kUnstableGame + || (gameDescriptor.gameSupportLevel == kTestingGame && showTestingWarning))) && !Engine::warnUserAboutUnsupportedGame()) return Common::kUserCanceled; - debug(2, "Running %s", gameDescriptor.description().c_str()); + debug(2, "Running %s", gameDescriptor.description.c_str()); initSubSystems(agdDesc.desc); if (!createInstance(syst, engine, agdDesc.desc)) return Common::kNoGameDataFoundError; diff --git a/engines/game.cpp b/engines/game.cpp index 177880c39d..1e96020fde 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -35,94 +35,75 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla return 0; } -GameDescriptor::GameDescriptor() { - setVal("gameid", ""); - setVal("description", ""); +GameDescriptor::GameDescriptor() : + language(Common::UNK_LANG), + platform(Common::kPlatformUnknown), + gameSupportLevel(kStableGame) { } -GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions) { - setVal("gameid", pgd.gameId); - setVal("description", pgd.description); +GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, const Common::String &guioptions) : + language(Common::UNK_LANG), + platform(Common::kPlatformUnknown), + gameSupportLevel(kStableGame) { + + gameId = pgd.gameId; + preferredTarget = pgd.gameId; + description = pgd.description; if (!guioptions.empty()) - setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions)); + _guiOptions = Common::getGameGUIOptionsDescription(guioptions); } -GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p, Common::String guioptions, GameSupportLevel gsl) { - setVal("gameid", g); - setVal("description", d); - if (l != Common::UNK_LANG) - setVal("language", Common::getLanguageCode(l)); - if (p != Common::kPlatformUnknown) - setVal("platform", Common::getPlatformCode(p)); - if (!guioptions.empty()) - setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions)); +GameDescriptor::GameDescriptor(const Common::String &id, const Common::String &d, Common::Language l, Common::Platform p, const Common::String &guioptions, GameSupportLevel gsl) { + gameId = id; + preferredTarget = id; + description = d; + language = l; + platform = p; + gameSupportLevel = gsl; - setSupportLevel(gsl); + if (!guioptions.empty()) + _guiOptions = Common::getGameGUIOptionsDescription(guioptions); } -void GameDescriptor::setGUIOptions(Common::String guioptions) { - if (!guioptions.empty()) - setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions)); +void GameDescriptor::setGUIOptions(const Common::String &guioptions) { + if (guioptions.empty()) + _guiOptions.clear(); else - erase("guioptions"); + _guiOptions = Common::getGameGUIOptionsDescription(guioptions); } void GameDescriptor::appendGUIOptions(const Common::String &str) { - setVal("guioptions", getVal("guioptions", "") + " " + str); + if (!_guiOptions.empty()) + _guiOptions += " "; + + _guiOptions += str; } -void GameDescriptor::updateDesc(const char *extra) { - const bool hasCustomLanguage = (language() != Common::UNK_LANG); - const bool hasCustomPlatform = (platform() != Common::kPlatformUnknown); - const bool hasExtraDesc = (extra && extra[0]); +void GameDescriptor::updateDesc(const char *extraDesc) { + const bool hasCustomLanguage = (language != Common::UNK_LANG); + const bool hasCustomPlatform = (platform != Common::kPlatformUnknown); + const bool hasExtraDesc = (extraDesc && extraDesc[0]); // Adapt the description string if custom platform/language is set. if (hasCustomLanguage || hasCustomPlatform || hasExtraDesc) { - Common::String descr = description(); + Common::String descr = description; descr += " ("; if (hasExtraDesc) - descr += extra; + descr += extraDesc; if (hasCustomPlatform) { if (hasExtraDesc) descr += "/"; - descr += Common::getPlatformDescription(platform()); + descr += Common::getPlatformDescription(platform); } if (hasCustomLanguage) { if (hasExtraDesc || hasCustomPlatform) descr += "/"; - descr += Common::getLanguageDescription(language()); + descr += Common::getLanguageDescription(language); } descr += ")"; - setVal("description", descr); - } -} - -GameSupportLevel GameDescriptor::getSupportLevel() { - GameSupportLevel gsl = kStableGame; - if (contains("gsl")) { - Common::String gslString = getVal("gsl"); - if (gslString.equals("unstable")) - gsl = kUnstableGame; - else if (gslString.equals("testing")) - gsl = kTestingGame; - } - return gsl; -} - -void GameDescriptor::setSupportLevel(GameSupportLevel gsl) { - switch (gsl) { - case kUnstableGame: - setVal("gsl", "unstable"); - break; - case kTestingGame: - setVal("gsl", "testing"); - break; - case kStableGame: - // Fall Through intended - default: - erase("gsl"); + description = descr; } } @@ -159,7 +140,7 @@ Common::String DetectionResults::generateUnknownGameReport(bool translate, uint3 const char *reportEngineHeader = _s("Matched game IDs for the %s engine:"); Common::String report = Common::String::format( - translate ? _(reportStart) : reportStart, _detectedGames[0].matchedGame["path"].c_str(), + translate ? _(reportStart) : reportStart, _detectedGames[0].matchedGame.path.c_str(), "https://bugs.scummvm.org/" ); report += "\n"; @@ -190,7 +171,7 @@ Common::String DetectionResults::generateUnknownGameReport(bool translate, uint3 // Add the gameId to the list of matched games for the engine // TODO: Use the gameId here instead of the preferred target. // This is currently impossible due to the AD singleId feature losing the information. - report += game.matchedGame["preferredtarget"]; + report += game.matchedGame.preferredTarget; // Consolidate matched files across all engines and detection entries for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) { diff --git a/engines/game.h b/engines/game.h index a5cc4de4ec..053c0c85b1 100644 --- a/engines/game.h +++ b/engines/game.h @@ -78,15 +78,15 @@ enum GameSupportLevel { * can be contained in a GameDescriptor. * This is an essential part of the glue between the game engines and the launcher code. */ -class GameDescriptor : public Common::StringMap { +class GameDescriptor { public: GameDescriptor(); - explicit GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions = Common::String()); - GameDescriptor(const Common::String &gameid, + explicit GameDescriptor(const PlainGameDescriptor &pgd, const Common::String &guioptions = Common::String()); + GameDescriptor(const Common::String &id, const Common::String &description, Common::Language language = Common::UNK_LANG, Common::Platform platform = Common::kPlatformUnknown, - Common::String guioptions = Common::String(), + const Common::String &guioptions = Common::String(), GameSupportLevel gsl = kStableGame); /** @@ -94,27 +94,27 @@ public: * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be * added if no platform has been specified but a language and an extra string. */ - void updateDesc(const char *extra = 0); + void updateDesc(const char *extraDesc = 0); - void setGUIOptions(Common::String options); + void setGUIOptions(const Common::String &options); void appendGUIOptions(const Common::String &str); + Common::String getGUIOptions() const { return _guiOptions; } + + Common::String gameId; + Common::String preferredTarget; + Common::String description; + Common::Language language; + Common::Platform platform; + Common::String path; + Common::String extra; /** * What level of support is expected of this game */ - GameSupportLevel getSupportLevel(); - void setSupportLevel(GameSupportLevel gsl); - - Common::String &gameid() { return getVal("gameid"); } - Common::String &description() { return getVal("description"); } - const Common::String &gameid() const { return getVal("gameid"); } - const Common::String &description() const { return getVal("description"); } - Common::Language language() const { return contains("language") ? Common::parseLanguage(getVal("language")) : Common::UNK_LANG; } - Common::Platform platform() const { return contains("platform") ? Common::parsePlatform(getVal("platform")) : Common::kPlatformUnknown; } - - const Common::String &preferredtarget() const { - return contains("preferredtarget") ? getVal("preferredtarget") : getVal("gameid"); - } + GameSupportLevel gameSupportLevel; + +private: + Common::String _guiOptions; }; /** List of games. */ diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 6276f1ae41..dea0d3a026 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -1044,7 +1044,7 @@ DetectedGames ScummMetaEngine::detectGames(const Common::FSList &fslist) const { // Compute and set the preferred target name for this game. // Based on generateComplexID() in advancedDetector.cpp. - game.matchedGame["preferredtarget"] = generatePreferredTarget(*x); + game.matchedGame.preferredTarget = generatePreferredTarget(*x); game.matchedGame.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi)); game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index f9e308ca63..67f6904cbe 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -284,7 +284,7 @@ Common::Error Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) c DetectedGames detectedGames = detectGames(fslist); for (uint i = 0; i < detectedGames.size(); i++) { - if (detectedGames[i].matchedGame.gameid() == gameid) { + if (detectedGames[i].matchedGame.gameId == gameid) { *engine = new Sword2::Sword2Engine(syst); return Common::kNoError; } diff --git a/gui/launcher.cpp b/gui/launcher.cpp index f257c53e11..4edd3527f4 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -376,11 +376,20 @@ void LauncherDialog::addGame() { } while (looping); } +namespace { + +static void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) { + if (!value.empty()) + ConfMan.set(key, value, domain); +} + +} // End of anonymous namespace + Common::String addGameToConf(const GameDescriptor &result) { // The auto detector or the user made a choice. // Pick a domain name which does not yet exist (after all, we // are *adding* a game to the config, not replacing). - Common::String domain = result.preferredtarget(); + Common::String domain = result.preferredTarget; assert(!domain.empty()); if (ConfMan.hasGameDomain(domain)) { @@ -396,11 +405,15 @@ Common::String addGameToConf(const GameDescriptor &result) { // Add the name domain ConfMan.addGameDomain(domain); - // Copy all non-empty key/value pairs into the new domain - for (GameDescriptor::const_iterator iter = result.begin(); iter != result.end(); ++iter) { - if (!iter->_value.empty() && iter->_key != "preferredtarget") - ConfMan.set(iter->_key, iter->_value, domain); - } + // Copy all non-empty relevant values into the new domain + // FIXME: Factor out + addStringToConf("gameid", result.gameId, domain); + addStringToConf("description", result.description, domain); + addStringToConf("language", Common::getLanguageCode(result.language), domain); + addStringToConf("platform", Common::getPlatformCode(result.platform), domain); + addStringToConf("path", result.path, domain); + addStringToConf("extra", result.extra, domain); + addStringToConf("guioptions", result.getGUIOptions(), domain); // TODO: Setting the description field here has the drawback // that the user does never notice when we upgrade our descriptions. @@ -601,7 +614,7 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { // Display the candidates to the user and let her/him pick one StringArray list; for (idx = 0; idx < (int)candidates.size(); idx++) - list.push_back(candidates[idx].matchedGame.description()); + list.push_back(candidates[idx].matchedGame.description); ChooserDialog dialog(_("Pick the game:")); dialog.setList(list); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 2774d476db..7c54c503a3 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -121,13 +121,13 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) struct GameTargetLess { bool operator()(const GameDescriptor &x, const GameDescriptor &y) const { - return x.preferredtarget().compareToIgnoreCase(y.preferredtarget()) < 0; + return x.preferredTarget.compareToIgnoreCase(y.preferredTarget) < 0; } }; struct GameDescLess { bool operator()(const GameDescriptor &x, const GameDescriptor &y) const { - return x.description().compareToIgnoreCase(y.description()) < 0; + return x.description.compareToIgnoreCase(y.description) < 0; } }; @@ -143,13 +143,13 @@ void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data if (cmd == kOkCmd) { // Sort the detected games. This is not strictly necessary, but nice for // people who want to edit their config file by hand after a mass add. - sort(_games.begin(), _games.end(), GameTargetLess()); + Common::sort(_games.begin(), _games.end(), GameTargetLess()); // Add all the detected games to the config for (GameList::iterator iter = _games.begin(); iter != _games.end(); ++iter) { debug(1, " Added gameid '%s', desc '%s'\n", - (*iter)["gameid"].c_str(), - (*iter)["description"].c_str()); - (*iter)["gameid"] = addGameToConf(*iter); + iter->gameId.c_str(), + iter->description.c_str()); + iter->gameId = addGameToConf(*iter); } // Write everything to disk @@ -157,8 +157,8 @@ void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data // And scroll to first detected game if (!_games.empty()) { - sort(_games.begin(), _games.end(), GameDescLess()); - ConfMan.set("temp_selection", _games.front().gameid()); + Common::sort(_games.begin(), _games.end(), GameDescLess()); + ConfMan.set("temp_selection", _games.front().gameId); } close(); @@ -211,6 +211,9 @@ void MassAddDialog::handleTickle() { // Check for existing config entries for this path/gameid/lang/platform combination if (_pathToTargets.contains(path)) { + const char *resultPlatformCode = Common::getPlatformCode(result.platform); + const char *resultLanguageCode = Common::getLanguageCode(result.language); + bool duplicate = false; const StringArray &targets = _pathToTargets[path]; for (StringArray::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) { @@ -218,9 +221,9 @@ void MassAddDialog::handleTickle() { Common::ConfigManager::Domain *dom = ConfMan.getDomain(*iter); assert(dom); - if ((*dom)["gameid"] == result["gameid"] && - (*dom)["platform"] == result["platform"] && - (*dom)["language"] == result["language"]) { + if ((*dom)["gameid"] == result.gameId && + (*dom)["platform"] == resultPlatformCode && + (*dom)["language"] == resultLanguageCode) { duplicate = true; break; } @@ -232,7 +235,7 @@ void MassAddDialog::handleTickle() { } _games.push_back(result); - _list->append(result.description()); + _list->append(result.description); } diff --git a/gui/massadd.h b/gui/massadd.h index 116a420d79..58071cda0a 100644 --- a/gui/massadd.h +++ b/gui/massadd.h @@ -44,7 +44,7 @@ public: Common::String getFirstAddedTarget() const { if (!_games.empty()) - return _games.front().gameid(); + return _games.front().gameId; return Common::String(); } -- cgit v1.2.3 From 1de5aca585af3e04a64a4f287dd348c0e7b4b967 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 24 Dec 2017 11:01:38 +0100 Subject: ENGINES: Set the GameDescriptor decription in the constructor --- engines/advancedDetector.cpp | 4 ++-- engines/game.cpp | 52 ++++++++++++++++++++++---------------------- engines/game.h | 21 +++++++++--------- engines/scumm/detection.cpp | 5 +---- engines/sky/detection.cpp | 16 ++++++++++---- engines/sword1/detection.cpp | 14 +++++++----- engines/sword2/sword2.cpp | 3 ++- 7 files changed, 61 insertions(+), 54 deletions(-) diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index ac606d3e4b..b7bf4b40e0 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -56,8 +56,8 @@ static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGa else if (g.flags & ADGF_TESTING) gsl = kTestingGame; - GameDescriptor gd(g.gameId, title, g.language, g.platform, 0, gsl); - gd.updateDesc(extra); + GameDescriptor gd(g.gameId, title, g.language, g.platform, extra); + gd.gameSupportLevel = gsl; return gd; } diff --git a/engines/game.cpp b/engines/game.cpp index 1e96020fde..bdf8e322dd 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -41,7 +41,7 @@ GameDescriptor::GameDescriptor() : gameSupportLevel(kStableGame) { } -GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, const Common::String &guioptions) : +GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) : language(Common::UNK_LANG), platform(Common::kPlatformUnknown), gameSupportLevel(kStableGame) { @@ -49,21 +49,18 @@ GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, const Common::Str gameId = pgd.gameId; preferredTarget = pgd.gameId; description = pgd.description; - - if (!guioptions.empty()) - _guiOptions = Common::getGameGUIOptionsDescription(guioptions); } -GameDescriptor::GameDescriptor(const Common::String &id, const Common::String &d, Common::Language l, Common::Platform p, const Common::String &guioptions, GameSupportLevel gsl) { +GameDescriptor::GameDescriptor(const Common::String &id, const Common::String &d, Common::Language l, Common::Platform p, const Common::String &ex) { gameId = id; preferredTarget = id; description = d; language = l; platform = p; - gameSupportLevel = gsl; + extra = ex; - if (!guioptions.empty()) - _guiOptions = Common::getGameGUIOptionsDescription(guioptions); + // Append additional information, if set, to the description. + description += updateDesc(); } void GameDescriptor::setGUIOptions(const Common::String &guioptions) { @@ -80,31 +77,34 @@ void GameDescriptor::appendGUIOptions(const Common::String &str) { _guiOptions += str; } -void GameDescriptor::updateDesc(const char *extraDesc) { +Common::String GameDescriptor::updateDesc() const { const bool hasCustomLanguage = (language != Common::UNK_LANG); const bool hasCustomPlatform = (platform != Common::kPlatformUnknown); - const bool hasExtraDesc = (extraDesc && extraDesc[0]); + const bool hasExtraDesc = !extra.empty(); // Adapt the description string if custom platform/language is set. - if (hasCustomLanguage || hasCustomPlatform || hasExtraDesc) { - Common::String descr = description; + Common::String descr; + if (!hasCustomLanguage && !hasCustomPlatform && !hasExtraDesc) + return descr; - descr += " ("; + descr += " ("; + + if (hasExtraDesc) + descr += extra; + if (hasCustomPlatform) { if (hasExtraDesc) - descr += extraDesc; - if (hasCustomPlatform) { - if (hasExtraDesc) - descr += "/"; - descr += Common::getPlatformDescription(platform); - } - if (hasCustomLanguage) { - if (hasExtraDesc || hasCustomPlatform) - descr += "/"; - descr += Common::getLanguageDescription(language); - } - descr += ")"; - description = descr; + descr += "/"; + descr += Common::getPlatformDescription(platform); + } + if (hasCustomLanguage) { + if (hasExtraDesc || hasCustomPlatform) + descr += "/"; + descr += Common::getLanguageDescription(language); } + + descr += ")"; + + return descr; } DetectionResults::DetectionResults(const DetectedGames &detectedGames) : diff --git a/engines/game.h b/engines/game.h index 053c0c85b1..d675e7bdf4 100644 --- a/engines/game.h +++ b/engines/game.h @@ -81,20 +81,12 @@ enum GameSupportLevel { class GameDescriptor { public: GameDescriptor(); - explicit GameDescriptor(const PlainGameDescriptor &pgd, const Common::String &guioptions = Common::String()); + explicit GameDescriptor(const PlainGameDescriptor &pgd); GameDescriptor(const Common::String &id, const Common::String &description, Common::Language language = Common::UNK_LANG, - Common::Platform platform = Common::kPlatformUnknown, - const Common::String &guioptions = Common::String(), - GameSupportLevel gsl = kStableGame); - - /** - * Update the description string by appending (EXTRA/PLATFORM/LANG) to it. - * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be - * added if no platform has been specified but a language and an extra string. - */ - void updateDesc(const char *extraDesc = 0); + Common::Platform platform = Common::kPlatformUnknown, + const Common::String &extra = Common::String()); void setGUIOptions(const Common::String &options); void appendGUIOptions(const Common::String &str); @@ -114,6 +106,13 @@ public: GameSupportLevel gameSupportLevel; private: + /** + * Update the description string by appending (EXTRA/PLATFORM/LANG) to it. + * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be + * added if no platform has been specified but a language and an extra string. + */ + Common::String updateDesc() const; + Common::String _guiOptions; }; diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index dea0d3a026..1395fc4fd7 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -1037,10 +1037,7 @@ DetectedGames ScummMetaEngine::detectGames(const Common::FSList &fslist) const { assert(g); DetectedGame game; - game.matchedGame = GameDescriptor(x->game.gameid, g->description, x->language, x->game.platform); - - // Append additional information, if set, to the description. - game.matchedGame.updateDesc(x->extra); + game.matchedGame = GameDescriptor(x->game.gameid, g->description, x->language, x->game.platform, x->extra); // Compute and set the preferred target name for this game. // Based on generateComplexID() in advancedDetector.cpp. diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index ffed998ab1..b8abd6bcb5 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -173,18 +173,26 @@ DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const { // Match found, add to list of candidates, then abort inner loop. // The game detector uses US English by default. We want British // English to match the recorded voices better. - DetectedGame game; - game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown); const SkyVersion *sv = skyVersions; while (sv->dinnerTableEntries) { if (dinnerTableEntries == sv->dinnerTableEntries && (sv->dataDiskSize == dataDiskSize || sv->dataDiskSize == -1)) { - game.matchedGame.updateDesc(Common::String::format("v0.0%d %s", sv->version, sv->extraDesc).c_str()); - game.matchedGame.setGUIOptions(sv->guioptions); break; } ++sv; } + + DetectedGame game; + if (sv->dinnerTableEntries) { + Common::String extra = Common::String::format("v0.0%d %s", sv->version, sv->extraDesc); + + game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown, extra); + game.matchedGame.setGUIOptions(sv->guioptions); + + } else { + game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description); + } + detectedGames.push_back(game); } diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 80176aee40..205640a0a6 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -214,20 +214,22 @@ DetectedGames SwordMetaEngine::detectGames(const Common::FSList &fslist) const { DetectedGame game; if (mainFilesFound && pcFilesFound && demoFilesFound) - game.matchedGame = GameDescriptor(sword1DemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1DemoSettings); else if (mainFilesFound && pcFilesFound && psxFilesFound) - game.matchedGame = GameDescriptor(sword1PSXSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1PSXSettings); else if (mainFilesFound && pcFilesFound && psxDemoFilesFound) - game.matchedGame = GameDescriptor(sword1PSXDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1PSXDemoSettings); else if (mainFilesFound && pcFilesFound && !psxFilesFound) - game.matchedGame = GameDescriptor(sword1FullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1FullSettings); else if (mainFilesFound && macFilesFound) - game.matchedGame = GameDescriptor(sword1MacFullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1MacFullSettings); else if (mainFilesFound && macDemoFilesFound) - game.matchedGame = GameDescriptor(sword1MacDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(sword1MacDemoSettings); else return detectedGames; + game.matchedGame.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU)); game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA)); diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 67f6904cbe..231074641e 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -193,7 +193,8 @@ DetectedGames detectGamesImpl(const Common::FSList &fslist, bool recursion = fal // Match found, add to list of candidates, then abort inner loop. DetectedGame game; - game.matchedGame = GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.matchedGame = GameDescriptor(g->gameid, g->description); + game.matchedGame.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); detectedGames.push_back(game); break; -- cgit v1.2.3 From faa2534f46611a47913004b55aa0e5ed5b7e4b7a Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 4 Feb 2018 08:46:12 +0100 Subject: ENGINES: Factor adding games to ConfMan --- base/commandLine.cpp | 44 +++--------------------------------------- base/plugins.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ engines/metaengine.h | 7 +++++++ gui/launcher.cpp | 54 +--------------------------------------------------- gui/launcher.h | 2 -- gui/massadd.cpp | 5 +---- gui/massadd.h | 1 + 7 files changed, 64 insertions(+), 100 deletions(-) diff --git a/base/commandLine.cpp b/base/commandLine.cpp index e1539d7a3e..02c3d1c454 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -881,45 +881,6 @@ static GameList getGameList(const Common::FSNode &dir) { return candidates; } -namespace { - -static void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) { - if (!value.empty()) - ConfMan.set(key, value, domain); -} - -} // End of anonymous namespace - -static bool addGameToConf(const GameDescriptor &gd) { - const Common::String &domain = gd.preferredTarget; - - // If game has already been added, don't add - if (ConfMan.hasGameDomain(domain)) - return false; - - // Add the name domain - ConfMan.addGameDomain(domain); - - // Copy all non-empty relevant values into the new domain - // FIXME: Factor out - addStringToConf("gameid", gd.gameId, domain); - addStringToConf("description", gd.description, domain); - addStringToConf("language", Common::getLanguageCode(gd.language), domain); - addStringToConf("platform", Common::getPlatformCode(gd.platform), domain); - addStringToConf("path", gd.path, domain); - addStringToConf("extra", gd.extra, domain); - addStringToConf("guioptions", gd.getGUIOptions(), domain); - - // Display added game info - printf("Game Added: \n GameID: %s\n Name: %s\n Language: %s\n Platform: %s\n", - gd.gameId.c_str(), - gd.description.c_str(), - Common::getLanguageDescription(gd.language), - Common::getPlatformDescription(gd.platform)); - - return true; -} - static GameList recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) { GameList list = getGameList(dir); @@ -971,11 +932,12 @@ static int recAddGames(const Common::FSNode &dir, const Common::String &game, bo for (GameList::iterator v = list.begin(); v != list.end(); ++v) { if (v->gameId != game && !game.empty()) { printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameId.c_str(), game.c_str()); - } else if (!addGameToConf(*v)) { - // TODO Is it reall the case that !addGameToConf iff already added? + } else if (ConfMan.hasGameDomain(v->preferredTarget)) { + // TODO Better check for game already added? printf("Found %s, but has already been added, skipping\n", v->gameId.c_str()); } else { printf("Found %s, adding...\n", v->gameId.c_str()); + EngineMan.createTargetForGame(*v); count++; } } diff --git a/base/plugins.cpp b/base/plugins.cpp index 61dae910f9..1bfb929950 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -545,6 +545,57 @@ const PluginList &EngineManager::getPlugins() const { return PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE); } +namespace { + +void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) { + if (!value.empty()) + ConfMan.set(key, value, domain); +} + +} // End of anonymous namespace + +Common::String EngineManager::createTargetForGame(const GameDescriptor &game) { + // The auto detector or the user made a choice. + // Pick a domain name which does not yet exist (after all, we + // are *adding* a game to the config, not replacing). + Common::String domain = game.preferredTarget; + + assert(!domain.empty()); + if (ConfMan.hasGameDomain(domain)) { + int suffixN = 1; + Common::String gameid(domain); + + while (ConfMan.hasGameDomain(domain)) { + domain = gameid + Common::String::format("-%d", suffixN); + suffixN++; + } + } + + // Add the name domain + ConfMan.addGameDomain(domain); + + // Copy all non-empty relevant values into the new domain + addStringToConf("gameid", game.gameId, domain); + addStringToConf("description", game.description, domain); + addStringToConf("language", Common::getLanguageCode(game.language), domain); + addStringToConf("platform", Common::getPlatformCode(game.platform), domain); + addStringToConf("path", game.path, domain); + addStringToConf("extra", game.extra, domain); + addStringToConf("guioptions", game.getGUIOptions(), domain); + + // TODO: Setting the description field here has the drawback + // that the user does never notice when we upgrade our descriptions. + // It might be nice to leave this field empty, and only set it to + // a value when the user edits the description string. + // However, at this point, that's impractical. Once we have a method + // to query all backends for the proper & full description of a given + // game target, we can change this (currently, you can only query + // for the generic gameid description; it's not possible to obtain + // a description which contains extended information like language, etc.). + + return domain; +} + // Music plugins #include "audio/musicplugin.h" diff --git a/engines/metaengine.h b/engines/metaengine.h index 74eb367200..6e8ab16af8 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -271,6 +271,13 @@ public: PlainGameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const; DetectionResults detectGames(const Common::FSList &fslist) const; const PluginList &getPlugins() const; + + /** + * Create a target from the supplied game descriptor + * + * Returns the created target name. + */ + Common::String createTargetForGame(const GameDescriptor &game); }; /** Convenience shortcut for accessing the engine manager. */ diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 4edd3527f4..67a62ad61e 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -376,58 +376,6 @@ void LauncherDialog::addGame() { } while (looping); } -namespace { - -static void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) { - if (!value.empty()) - ConfMan.set(key, value, domain); -} - -} // End of anonymous namespace - -Common::String addGameToConf(const GameDescriptor &result) { - // The auto detector or the user made a choice. - // Pick a domain name which does not yet exist (after all, we - // are *adding* a game to the config, not replacing). - Common::String domain = result.preferredTarget; - - assert(!domain.empty()); - if (ConfMan.hasGameDomain(domain)) { - int suffixN = 1; - Common::String gameid(domain); - - while (ConfMan.hasGameDomain(domain)) { - domain = gameid + Common::String::format("-%d", suffixN); - suffixN++; - } - } - - // Add the name domain - ConfMan.addGameDomain(domain); - - // Copy all non-empty relevant values into the new domain - // FIXME: Factor out - addStringToConf("gameid", result.gameId, domain); - addStringToConf("description", result.description, domain); - addStringToConf("language", Common::getLanguageCode(result.language), domain); - addStringToConf("platform", Common::getPlatformCode(result.platform), domain); - addStringToConf("path", result.path, domain); - addStringToConf("extra", result.extra, domain); - addStringToConf("guioptions", result.getGUIOptions(), domain); - - // TODO: Setting the description field here has the drawback - // that the user does never notice when we upgrade our descriptions. - // It might be nice ot leave this field empty, and only set it to - // a value when the user edits the description string. - // However, at this point, that's impractical. Once we have a method - // to query all backends for the proper & full description of a given - // game target, we can change this (currently, you can only query - // for the generic gameid description; it's not possible to obtain - // a description which contains extended information like language, etc.). - - return domain; -} - void LauncherDialog::removeGame(int item) { MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No")); @@ -623,7 +571,7 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { if (0 <= idx && idx < (int)candidates.size()) { const GameDescriptor &result = candidates[idx].matchedGame; - Common::String domain = addGameToConf(result); + Common::String domain = EngineMan.createTargetForGame(result); // Display edit dialog for the new entry EditGameDialog editDialog(domain); diff --git a/gui/launcher.h b/gui/launcher.h index 08413fe3d2..9f0a1c8e95 100644 --- a/gui/launcher.h +++ b/gui/launcher.h @@ -38,8 +38,6 @@ class StaticTextWidget; class EditTextWidget; class SaveLoadChooser; -Common::String addGameToConf(const GameDescriptor &result); - class LauncherDialog : public Dialog { typedef Common::String String; typedef Common::Array StringArray; diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 7c54c503a3..56b15ecfd7 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -28,10 +28,7 @@ #include "common/taskbar.h" #include "common/translation.h" -#include "gui/launcher.h" // For addGameToConf() #include "gui/massadd.h" -#include "gui/widget.h" -#include "gui/widgets/list.h" #ifndef DISABLE_MASS_ADD namespace GUI { @@ -149,7 +146,7 @@ void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data debug(1, " Added gameid '%s', desc '%s'\n", iter->gameId.c_str(), iter->description.c_str()); - iter->gameId = addGameToConf(*iter); + iter->gameId = EngineMan.createTargetForGame(*iter); } // Write everything to disk diff --git a/gui/massadd.h b/gui/massadd.h index 58071cda0a..b954c87161 100644 --- a/gui/massadd.h +++ b/gui/massadd.h @@ -24,6 +24,7 @@ #define MASSADD_DIALOG_H #include "gui/dialog.h" +#include "gui/widgets/list.h" #include "common/fs.h" #include "common/hashmap.h" #include "common/stack.h" -- cgit v1.2.3 From 90b78c544657bf0fc41d6b86276a0873060345b5 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 6 May 2018 15:51:03 +0200 Subject: ENGINES: Merge GameDescriptor and DetectedGame --- backends/platform/dc/selector.cpp | 12 ++--- base/commandLine.cpp | 61 +++++++++++-------------- base/plugins.cpp | 4 +- engines/advancedDetector.cpp | 50 ++++++++------------ engines/advancedDetector.h | 2 +- engines/game.cpp | 27 +++++++---- engines/game.h | 96 ++++++++++++++++----------------------- engines/metaengine.h | 2 +- engines/scumm/detection.cpp | 9 ++-- engines/sky/detection.cpp | 10 ++-- engines/sword1/detection.cpp | 28 ++++++------ engines/sword2/sword2.cpp | 7 ++- gui/editgamedialog.h | 2 - gui/launcher.cpp | 4 +- gui/massadd.cpp | 9 ++-- gui/massadd.h | 2 +- 16 files changed, 147 insertions(+), 178 deletions(-) diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 033f06e32d..3192f3e8cf 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -271,21 +271,21 @@ static int findGames(Game *games, int max, bool use_ini) } if (!use_ini) { - GameList candidates = EngineMan.detectGames(files); + DetectedGames candidates = EngineMan.detectGames(files); - for (GameList::const_iterator ge = candidates.begin(); + for (DetectedGames::const_iterator ge = candidates.begin(); ge != candidates.end(); ++ge) if (curr_game < max) { - strcpy(games[curr_game].filename_base, ge->gameid().c_str()); + strcpy(games[curr_game].filename_base, ge->gameId.c_str()); strcpy(games[curr_game].dir, dirs[curr_dir-1].name); - games[curr_game].language = ge->language(); - games[curr_game].platform = ge->platform(); + games[curr_game].language = ge->language; + games[curr_game].platform = ge->platform; if (uniqueGame(games[curr_game].filename_base, games[curr_game].dir, games[curr_game].language, games[curr_game].platform, games, curr_game)) { - strcpy(games[curr_game].text, ge->description().c_str()); + strcpy(games[curr_game].text, ge->description.c_str()); #if 0 printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n", games[curr_game].text, diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 02c3d1c454..96548b9129 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -854,13 +854,13 @@ static void listAudioDevices() { } /** Display all games in the given directory, or current directory if empty */ -static GameList getGameList(const Common::FSNode &dir) { +static DetectedGames getGameList(const Common::FSNode &dir) { Common::FSList files; // Collect all files from directory if (!dir.getChildren(files, Common::FSNode::kListAll)) { printf("Path %s does not exist or is not a directory.\n", dir.getPath().c_str()); - return GameList(); + return DetectedGames(); } // detect Games @@ -871,25 +871,18 @@ static GameList getGameList(const Common::FSNode &dir) { g_system->logMessage(LogMessageType::kInfo, report.c_str()); } - DetectedGames detectedGames = detectionResults.listRecognizedGames(); - - GameList candidates; - for (uint i = 0; i < detectedGames.size(); i++) { - candidates.push_back(detectedGames[i].matchedGame); - } - - return candidates; + return detectionResults.listRecognizedGames(); } -static GameList recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) { - GameList list = getGameList(dir); +static DetectedGames recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) { + DetectedGames list = getGameList(dir); if (recursive) { Common::FSList files; dir.getChildren(files, Common::FSNode::kListDirectoriesOnly); for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) { - GameList rec = recListGames(*file, gameId, recursive); - for (GameList::const_iterator game = rec.begin(); game != rec.end(); ++game) { + DetectedGames rec = recListGames(*file, gameId, recursive); + for (DetectedGames::const_iterator game = rec.begin(); game != rec.end(); ++game) { if (gameId.empty() || game->gameId == gameId) list.push_back(*game); } @@ -904,7 +897,7 @@ static Common::String detectGames(const Common::String &path, const Common::Stri bool noPath = path.empty(); //Current directory Common::FSNode dir(path); - GameList candidates = recListGames(dir, gameId, recursive); + DetectedGames candidates = recListGames(dir, gameId, recursive); if (candidates.empty()) { printf("WARNING: ScummVM could not find any game in %s\n", dir.getPath().c_str()); @@ -919,7 +912,7 @@ static Common::String detectGames(const Common::String &path, const Common::Stri // TODO this is not especially pretty printf("ID Description Full Path\n"); printf("-------------- ---------------------------------------------------------- ---------------------------------------------------------\n"); - for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) { + for (DetectedGames::const_iterator v = candidates.begin(); v != candidates.end(); ++v) { printf("%-14s %-58s %s\n", v->gameId.c_str(), v->description.c_str(), v->path.c_str()); } @@ -928,17 +921,25 @@ static Common::String detectGames(const Common::String &path, const Common::Stri static int recAddGames(const Common::FSNode &dir, const Common::String &game, bool recursive) { int count = 0; - GameList list = getGameList(dir); - for (GameList::iterator v = list.begin(); v != list.end(); ++v) { + DetectedGames list = getGameList(dir); + for (DetectedGames::const_iterator v = list.begin(); v != list.end(); ++v) { if (v->gameId != game && !game.empty()) { printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameId.c_str(), game.c_str()); } else if (ConfMan.hasGameDomain(v->preferredTarget)) { // TODO Better check for game already added? printf("Found %s, but has already been added, skipping\n", v->gameId.c_str()); } else { - printf("Found %s, adding...\n", v->gameId.c_str()); - EngineMan.createTargetForGame(*v); + Common::String target = EngineMan.createTargetForGame(*v); count++; + + // Display added game info + printf("Game Added: \n Target: %s\n GameID: %s\n Name: %s\n Language: %s\n Platform: %s\n", + target.c_str(), + v->gameId.c_str(), + v->description.c_str(), + Common::getLanguageDescription(v->language), + Common::getPlatformDescription(v->platform) + ); } } @@ -998,15 +999,10 @@ static void runDetectorTest() { } DetectionResults detectionResults = EngineMan.detectGames(files); - DetectedGames detectedGames = detectionResults.listRecognizedGames(); - - GameList candidates; - for (uint i = 0; i < detectedGames.size(); i++) { - candidates.push_back(detectedGames[i].matchedGame); - } + DetectedGames candidates = detectionResults.listRecognizedGames(); bool gameidDiffers = false; - GameList::iterator x; + DetectedGames::const_iterator x; for (x = candidates.begin(); x != candidates.end(); ++x) { gameidDiffers |= (scumm_stricmp(gameid.c_str(), x->gameId.c_str()) != 0); } @@ -1083,14 +1079,9 @@ void upgradeTargets() { Common::String desc(dom.getVal("description")); DetectionResults detectionResults = EngineMan.detectGames(files); - DetectedGames detectedGames = detectionResults.listRecognizedGames(); - - GameList candidates; - for (uint i = 0; i < detectedGames.size(); i++) { - candidates.push_back(detectedGames[i].matchedGame); - } + DetectedGames candidates = detectionResults.listRecognizedGames(); - GameDescriptor *g = 0; + DetectedGame *g = 0; // We proceed as follows: // * If detection failed to produce candidates, skip. @@ -1103,7 +1094,7 @@ void upgradeTargets() { } if (candidates.size() > 1) { // Scan over all candidates, check if there is a unique match for gameid, language and platform - GameList::iterator x; + DetectedGames::iterator x; int matchesFound = 0; for (x = candidates.begin(); x != candidates.end(); ++x) { if (x->gameId == gameid && x->language == lang && x->platform == plat) { diff --git a/base/plugins.cpp b/base/plugins.cpp index 1bfb929950..40a4d77053 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -531,7 +531,7 @@ DetectionResults EngineManager::detectGames(const Common::FSList &fslist) const for (uint i = 0; i < engineCandidates.size(); i++) { engineCandidates[i].engineName = metaEngine.getName(); - engineCandidates[i].matchedGame.path = path; + engineCandidates[i].path = path; candidates.push_back(engineCandidates[i]); } @@ -554,7 +554,7 @@ void addStringToConf(const Common::String &key, const Common::String &value, con } // End of anonymous namespace -Common::String EngineManager::createTargetForGame(const GameDescriptor &game) { +Common::String EngineManager::createTargetForGame(const DetectedGame &game) { // The auto detector or the user made a choice. // Pick a domain name which does not yet exist (after all, we // are *adding* a game to the config, not replacing). diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index b7bf4b40e0..8e7ec4856f 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -33,42 +33,32 @@ #include "engines/advancedDetector.h" #include "engines/obsolete.h" -static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGameDescriptor *sg) { - const char *title = 0; +DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const { + const char *title; const char *extra; - if (g.flags & ADGF_USEEXTRAASTITLE) { - title = g.extra; + if (adGame.desc->flags & ADGF_USEEXTRAASTITLE) { + title = adGame.desc->extra; extra = ""; } else { - while (sg->gameId) { - if (!scumm_stricmp(g.gameId, sg->gameId)) - title = sg->description; - sg++; - } - - extra = g.extra; + const PlainGameDescriptor *pgd = findPlainGameDescriptor(adGame.desc->gameId, _gameIds); + title = pgd->description; + extra = adGame.desc->extra; } - GameSupportLevel gsl = kStableGame; - if (g.flags & ADGF_UNSTABLE) - gsl = kUnstableGame; - else if (g.flags & ADGF_TESTING) - gsl = kTestingGame; - - GameDescriptor gd(g.gameId, title, g.language, g.platform, extra); - gd.gameSupportLevel = gsl; - return gd; -} - -DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const { - DetectedGame game; + DetectedGame game(adGame.desc->gameId, title, adGame.desc->language, adGame.desc->platform, extra); game.engineName = getName(); - game.gameId = adGame.desc->gameId; game.hasUnknownFiles = adGame.hasUnknownFiles; game.matchedFiles = adGame.matchedFiles; - game.matchedGame = toGameDescriptor(*adGame.desc, _gameIds); - updateGameDescriptor(game.matchedGame, adGame.desc); + + game.gameSupportLevel = kStableGame; + if (adGame.desc->flags & ADGF_UNSTABLE) + game.gameSupportLevel = kUnstableGame; + else if (adGame.desc->flags & ADGF_TESTING) + game.gameSupportLevel = kTestingGame; + + updateGameDescriptor(game, adGame.desc); + return game; } @@ -112,8 +102,8 @@ static Common::String sanitizeName(const char *name) { return res; } -void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const { - if (_singleId != NULL) { +void AdvancedMetaEngine::updateGameDescriptor(DetectedGame &desc, const ADGameDescription *realDesc) const { + if (_singleId) { desc.preferredTarget = desc.gameId; desc.gameId = _singleId; } @@ -321,7 +311,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) Common::updateGameGUIOptions(agdDesc.desc->guiOptions + _guiOptions, lang); - GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc.desc, _gameIds); + DetectedGame gameDescriptor = toDetectedGame(agdDesc); bool showTestingWarning = false; diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index 5762009ea7..9f2016465d 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -321,7 +321,7 @@ protected: ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const; // TODO - void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const; + void updateGameDescriptor(DetectedGame &desc, const ADGameDescription *realDesc) const; /** * Compose a hashmap of all files in fslist. diff --git a/engines/game.cpp b/engines/game.cpp index bdf8e322dd..d23a006a4c 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -35,13 +35,19 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla return 0; } -GameDescriptor::GameDescriptor() : +DetectedGame::DetectedGame() : + engineName(nullptr), + hasUnknownFiles(false), + canBeAdded(true), language(Common::UNK_LANG), platform(Common::kPlatformUnknown), gameSupportLevel(kStableGame) { } -GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) : +DetectedGame::DetectedGame(const PlainGameDescriptor &pgd) : + engineName(nullptr), + hasUnknownFiles(false), + canBeAdded(true), language(Common::UNK_LANG), platform(Common::kPlatformUnknown), gameSupportLevel(kStableGame) { @@ -51,7 +57,12 @@ GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) : description = pgd.description; } -GameDescriptor::GameDescriptor(const Common::String &id, const Common::String &d, Common::Language l, Common::Platform p, const Common::String &ex) { +DetectedGame::DetectedGame(const Common::String &id, const Common::String &d, Common::Language l, Common::Platform p, const Common::String &ex) : + engineName(nullptr), + hasUnknownFiles(false), + canBeAdded(true), + gameSupportLevel(kStableGame) { + gameId = id; preferredTarget = id; description = d; @@ -63,21 +74,21 @@ GameDescriptor::GameDescriptor(const Common::String &id, const Common::String &d description += updateDesc(); } -void GameDescriptor::setGUIOptions(const Common::String &guioptions) { +void DetectedGame::setGUIOptions(const Common::String &guioptions) { if (guioptions.empty()) _guiOptions.clear(); else _guiOptions = Common::getGameGUIOptionsDescription(guioptions); } -void GameDescriptor::appendGUIOptions(const Common::String &str) { +void DetectedGame::appendGUIOptions(const Common::String &str) { if (!_guiOptions.empty()) _guiOptions += " "; _guiOptions += str; } -Common::String GameDescriptor::updateDesc() const { +Common::String DetectedGame::updateDesc() const { const bool hasCustomLanguage = (language != Common::UNK_LANG); const bool hasCustomPlatform = (platform != Common::kPlatformUnknown); const bool hasExtraDesc = !extra.empty(); @@ -140,7 +151,7 @@ Common::String DetectionResults::generateUnknownGameReport(bool translate, uint3 const char *reportEngineHeader = _s("Matched game IDs for the %s engine:"); Common::String report = Common::String::format( - translate ? _(reportStart) : reportStart, _detectedGames[0].matchedGame.path.c_str(), + translate ? _(reportStart) : reportStart, _detectedGames[0].path.c_str(), "https://bugs.scummvm.org/" ); report += "\n"; @@ -171,7 +182,7 @@ Common::String DetectionResults::generateUnknownGameReport(bool translate, uint3 // Add the gameId to the list of matched games for the engine // TODO: Use the gameId here instead of the preferred target. // This is currently impossible due to the AD singleId feature losing the information. - report += game.matchedGame.preferredTarget; + report += game.preferredTarget; // Consolidate matched files across all engines and detection entries for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) { diff --git a/engines/game.h b/engines/game.h index d675e7bdf4..660a94ad6c 100644 --- a/engines/game.h +++ b/engines/game.h @@ -71,53 +71,6 @@ enum GameSupportLevel { kUnstableGame // the game is not even ready for public testing yet }; -/** - * A hashmap describing details about a given game. In a sense this is a refined - * version of PlainGameDescriptor, as it also contains a gameid and a description string. - * But in addition, platform and language settings, as well as arbitrary other settings, - * can be contained in a GameDescriptor. - * This is an essential part of the glue between the game engines and the launcher code. - */ -class GameDescriptor { -public: - GameDescriptor(); - explicit GameDescriptor(const PlainGameDescriptor &pgd); - GameDescriptor(const Common::String &id, - const Common::String &description, - Common::Language language = Common::UNK_LANG, - Common::Platform platform = Common::kPlatformUnknown, - const Common::String &extra = Common::String()); - - void setGUIOptions(const Common::String &options); - void appendGUIOptions(const Common::String &str); - Common::String getGUIOptions() const { return _guiOptions; } - - Common::String gameId; - Common::String preferredTarget; - Common::String description; - Common::Language language; - Common::Platform platform; - Common::String path; - Common::String extra; - - /** - * What level of support is expected of this game - */ - GameSupportLevel gameSupportLevel; - -private: - /** - * Update the description string by appending (EXTRA/PLATFORM/LANG) to it. - * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be - * added if no platform has been specified but a language and an extra string. - */ - Common::String updateDesc() const; - - Common::String _guiOptions; -}; - -/** List of games. */ -typedef Common::Array GameList; /** * A record describing the properties of a file. Used on the existing @@ -135,19 +88,31 @@ struct FileProperties { */ typedef Common::HashMap FilePropertiesMap; +/** + * Details about a given game. + * + * While PlainGameDescriptor refers to a game supported by an engine, this refers to a game copy + * that has been detected by an engine's detector. + * It contains all the necessary data to add the game to the configuration manager and / or to launch it. + */ struct DetectedGame { + DetectedGame(); + explicit DetectedGame(const PlainGameDescriptor &pgd); + DetectedGame(const Common::String &id, + const Common::String &description, + Common::Language language = Common::UNK_LANG, + Common::Platform platform = Common::kPlatformUnknown, + const Common::String &extra = Common::String()); + + void setGUIOptions(const Common::String &options); + void appendGUIOptions(const Common::String &str); + Common::String getGUIOptions() const { return _guiOptions; } + /** * The name of the engine supporting the detected game */ const char *engineName; - /** - * The identifier of the detected game - * - * For engines using the singleId feature, this is the true engine-specific gameId, not the singleId. - */ - const char *gameId; - /** * A game was detected, but some files were not recognized * @@ -170,14 +135,31 @@ struct DetectedGame { */ bool canBeAdded; + Common::String gameId; + Common::String preferredTarget; + Common::String description; + Common::Language language; + Common::Platform platform; + Common::String path; + Common::String extra; + + /** + * What level of support is expected of this game + */ + GameSupportLevel gameSupportLevel; + +private: /** - * Details about the detected game + * Update the description string by appending (EXTRA/PLATFORM/LANG) to it. + * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be + * added if no platform has been specified but a language and an extra string. */ - GameDescriptor matchedGame; + Common::String updateDesc() const; - DetectedGame() : engineName(nullptr), gameId(nullptr), hasUnknownFiles(false), canBeAdded(true) {} + Common::String _guiOptions; }; +/** List of games. */ typedef Common::Array DetectedGames; /** diff --git a/engines/metaengine.h b/engines/metaengine.h index 6e8ab16af8..a95ff1593e 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -277,7 +277,7 @@ public: * * Returns the created target name. */ - Common::String createTargetForGame(const GameDescriptor &game); + Common::String createTargetForGame(const DetectedGame &game); }; /** Convenience shortcut for accessing the engine manager. */ diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 1395fc4fd7..fccb30b0fa 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -1036,15 +1036,14 @@ DetectedGames ScummMetaEngine::detectGames(const Common::FSList &fslist) const { const PlainGameDescriptor *g = findPlainGameDescriptor(x->game.gameid, gameDescriptions); assert(g); - DetectedGame game; - game.matchedGame = GameDescriptor(x->game.gameid, g->description, x->language, x->game.platform, x->extra); + DetectedGame game = DetectedGame(x->game.gameid, g->description, x->language, x->game.platform, x->extra); // Compute and set the preferred target name for this game. // Based on generateComplexID() in advancedDetector.cpp. - game.matchedGame.preferredTarget = generatePreferredTarget(*x); + game.preferredTarget = generatePreferredTarget(*x); - game.matchedGame.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); + game.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); detectedGames.push_back(game); } diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index b8abd6bcb5..6beaf02fdc 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -182,18 +182,16 @@ DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const { ++sv; } - DetectedGame game; if (sv->dinnerTableEntries) { Common::String extra = Common::String::format("v0.0%d %s", sv->version, sv->extraDesc); - game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown, extra); - game.matchedGame.setGUIOptions(sv->guioptions); + DetectedGame game = DetectedGame(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown, extra); + game.setGUIOptions(sv->guioptions); + detectedGames.push_back(game); } else { - game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description); + detectedGames.push_back(DetectedGame(skySetting.gameId, skySetting.description)); } - - detectedGames.push_back(game); } return detectedGames; diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 205640a0a6..6504806423 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -214,29 +214,29 @@ DetectedGames SwordMetaEngine::detectGames(const Common::FSList &fslist) const { DetectedGame game; if (mainFilesFound && pcFilesFound && demoFilesFound) - game.matchedGame = GameDescriptor(sword1DemoSettings); + game = DetectedGame(sword1DemoSettings); else if (mainFilesFound && pcFilesFound && psxFilesFound) - game.matchedGame = GameDescriptor(sword1PSXSettings); + game = DetectedGame(sword1PSXSettings); else if (mainFilesFound && pcFilesFound && psxDemoFilesFound) - game.matchedGame = GameDescriptor(sword1PSXDemoSettings); + game = DetectedGame(sword1PSXDemoSettings); else if (mainFilesFound && pcFilesFound && !psxFilesFound) - game.matchedGame = GameDescriptor(sword1FullSettings); + game = DetectedGame(sword1FullSettings); else if (mainFilesFound && macFilesFound) - game.matchedGame = GameDescriptor(sword1MacFullSettings); + game = DetectedGame(sword1MacFullSettings); else if (mainFilesFound && macDemoFilesFound) - game.matchedGame = GameDescriptor(sword1MacDemoSettings); + game = DetectedGame(sword1MacDemoSettings); else return detectedGames; - game.matchedGame.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + game.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA)); - game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA)); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE)); detectedGames.push_back(game); diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 231074641e..0ec0e3f726 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -192,9 +192,8 @@ DetectedGames detectGamesImpl(const Common::FSList &fslist, bool recursion = fal continue; // Match found, add to list of candidates, then abort inner loop. - DetectedGame game; - game.matchedGame = GameDescriptor(g->gameid, g->description); - game.matchedGame.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); + DetectedGame game = DetectedGame(g->gameid, g->description); + game.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)); detectedGames.push_back(game); break; @@ -285,7 +284,7 @@ Common::Error Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) c DetectedGames detectedGames = detectGames(fslist); for (uint i = 0; i < detectedGames.size(); i++) { - if (detectedGames[i].matchedGame.gameId == gameid) { + if (detectedGames[i].gameId == gameid) { *engine = new Sword2::Sword2Engine(syst); return Common::kNoError; } diff --git a/gui/editgamedialog.h b/gui/editgamedialog.h index 06a8514dd5..7c6a08eb3c 100644 --- a/gui/editgamedialog.h +++ b/gui/editgamedialog.h @@ -40,8 +40,6 @@ class StaticTextWidget; class EditTextWidget; class SaveLoadChooser; -Common::String addGameToConf(const GameDescriptor &result); - /* * A dialog that allows the user to edit a config game entry. * TODO: add widgets for some/all of the following diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 67a62ad61e..7a37a7d3be 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -562,14 +562,14 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { // Display the candidates to the user and let her/him pick one StringArray list; for (idx = 0; idx < (int)candidates.size(); idx++) - list.push_back(candidates[idx].matchedGame.description); + list.push_back(candidates[idx].description); ChooserDialog dialog(_("Pick the game:")); dialog.setList(list); idx = dialog.runModal(); } if (0 <= idx && idx < (int)candidates.size()) { - const GameDescriptor &result = candidates[idx].matchedGame; + const DetectedGame &result = candidates[idx]; Common::String domain = EngineMan.createTargetForGame(result); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 56b15ecfd7..8bc5a10720 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -117,13 +117,13 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) } struct GameTargetLess { - bool operator()(const GameDescriptor &x, const GameDescriptor &y) const { + bool operator()(const DetectedGame &x, const DetectedGame &y) const { return x.preferredTarget.compareToIgnoreCase(y.preferredTarget) < 0; } }; struct GameDescLess { - bool operator()(const GameDescriptor &x, const GameDescriptor &y) const { + bool operator()(const DetectedGame &x, const DetectedGame &y) const { return x.description.compareToIgnoreCase(y.description) < 0; } }; @@ -142,7 +142,7 @@ void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data // people who want to edit their config file by hand after a mass add. Common::sort(_games.begin(), _games.end(), GameTargetLess()); // Add all the detected games to the config - for (GameList::iterator iter = _games.begin(); iter != _games.end(); ++iter) { + for (DetectedGames::iterator iter = _games.begin(); iter != _games.end(); ++iter) { debug(1, " Added gameid '%s', desc '%s'\n", iter->gameId.c_str(), iter->description.c_str()); @@ -199,7 +199,8 @@ void MassAddDialog::handleTickle() { // However, we only add games which are not already in the config file. DetectedGames candidates = detectionResults.listRecognizedGames(); for (DetectedGames::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) { - const GameDescriptor &result = cand->matchedGame; + const DetectedGame &result = *cand; + Common::String path = dir.getPath(); // Remove trailing slashes diff --git a/gui/massadd.h b/gui/massadd.h index b954c87161..b81a6046e2 100644 --- a/gui/massadd.h +++ b/gui/massadd.h @@ -51,7 +51,7 @@ public: private: Common::Stack _scanStack; - GameList _games; + DetectedGames _games; /** * Map each path occuring in the config file to the target(s) using that path. -- cgit v1.2.3 From 2fe060e5c9491ddd7c8f639aab5d7c58c7c73092 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 6 May 2018 16:26:57 +0200 Subject: ENGINES: Cleanup DetectedGame initialization in the AD --- engines/advancedDetector.cpp | 96 ++++++++++++++++++++------------------------ engines/advancedDetector.h | 3 -- engines/game.cpp | 5 +-- 3 files changed, 44 insertions(+), 60 deletions(-) diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 8e7ec4856f..c7b5c18892 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -33,33 +33,16 @@ #include "engines/advancedDetector.h" #include "engines/obsolete.h" -DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const { - const char *title; - const char *extra; +static Common::String sanitizeName(const char *name) { + Common::String res; - if (adGame.desc->flags & ADGF_USEEXTRAASTITLE) { - title = adGame.desc->extra; - extra = ""; - } else { - const PlainGameDescriptor *pgd = findPlainGameDescriptor(adGame.desc->gameId, _gameIds); - title = pgd->description; - extra = adGame.desc->extra; + while (*name) { + if (Common::isAlnum(*name)) + res += tolower(*name); + name++; } - DetectedGame game(adGame.desc->gameId, title, adGame.desc->language, adGame.desc->platform, extra); - game.engineName = getName(); - game.hasUnknownFiles = adGame.hasUnknownFiles; - game.matchedFiles = adGame.matchedFiles; - - game.gameSupportLevel = kStableGame; - if (adGame.desc->flags & ADGF_UNSTABLE) - game.gameSupportLevel = kUnstableGame; - else if (adGame.desc->flags & ADGF_TESTING) - game.gameSupportLevel = kTestingGame; - - updateGameDescriptor(game, adGame.desc); - - return game; + return res; } /** @@ -68,8 +51,14 @@ DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) co * or (if ADGF_DEMO has been set) * GAMEID-demo-PLAFORM-LANG */ -static Common::String generatePreferredTarget(const Common::String &id, const ADGameDescription *desc) { - Common::String res(id); +static Common::String generatePreferredTarget(const ADGameDescription *desc) { + Common::String res; + + if (desc->flags & ADGF_AUTOGENTARGET && desc->extra && *desc->extra) { + res = sanitizeName(desc->extra); + } else { + res = desc->gameId; + } if (desc->flags & ADGF_DEMO) { res = res + "-demo"; @@ -90,42 +79,43 @@ static Common::String generatePreferredTarget(const Common::String &id, const AD return res; } -static Common::String sanitizeName(const char *name) { - Common::String res; - - while (*name) { - if (Common::isAlnum(*name)) - res += tolower(*name); - name++; - } +DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const { + const ADGameDescription *desc = adGame.desc; - return res; -} + const char *gameId = _singleId ? _singleId : desc->gameId; -void AdvancedMetaEngine::updateGameDescriptor(DetectedGame &desc, const ADGameDescription *realDesc) const { - if (_singleId) { - desc.preferredTarget = desc.gameId; - desc.gameId = _singleId; + const char *title; + const char *extra; + if (desc->flags & ADGF_USEEXTRAASTITLE) { + title = desc->extra; + extra = ""; + } else { + const PlainGameDescriptor *pgd = findPlainGameDescriptor(desc->gameId, _gameIds); + title = pgd->description; + extra = desc->extra; } - if (desc.preferredTarget.empty()) - desc.preferredTarget = desc.gameId; + DetectedGame game(gameId, title, desc->language, desc->platform, extra); + game.hasUnknownFiles = adGame.hasUnknownFiles; + game.matchedFiles = adGame.matchedFiles; + game.preferredTarget = generatePreferredTarget(desc); - if (realDesc->flags & ADGF_AUTOGENTARGET) { - if (*realDesc->extra) - desc.preferredTarget = sanitizeName(realDesc->extra); - } + game.gameSupportLevel = kStableGame; + if (desc->flags & ADGF_UNSTABLE) + game.gameSupportLevel = kUnstableGame; + else if (desc->flags & ADGF_TESTING) + game.gameSupportLevel = kTestingGame; - desc.preferredTarget = generatePreferredTarget(desc.preferredTarget, realDesc); + game.setGUIOptions(desc->guiOptions + _guiOptions); + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(desc->language)); - if (_flags & kADFlagUseExtraAsHint) - desc.extra = realDesc->extra; + if (desc->flags & ADGF_ADDENGLISH) + game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); - desc.setGUIOptions(realDesc->guiOptions + _guiOptions); - desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language)); + if (_flags & kADFlagUseExtraAsHint) + game.extra = desc->extra; - if (realDesc->flags & ADGF_ADDENGLISH) - desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY)); + return game; } bool cleanupPirated(ADDetectedGames &matched) { diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index 9f2016465d..326cb79c49 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -320,9 +320,6 @@ protected: */ ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const; - // TODO - void updateGameDescriptor(DetectedGame &desc, const ADGameDescription *realDesc) const; - /** * Compose a hashmap of all files in fslist. * Includes nifty stuff like removing trailing dots and ignoring case. diff --git a/engines/game.cpp b/engines/game.cpp index d23a006a4c..3823000bce 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -75,10 +75,7 @@ DetectedGame::DetectedGame(const Common::String &id, const Common::String &d, Co } void DetectedGame::setGUIOptions(const Common::String &guioptions) { - if (guioptions.empty()) - _guiOptions.clear(); - else - _guiOptions = Common::getGameGUIOptionsDescription(guioptions); + _guiOptions = Common::getGameGUIOptionsDescription(guioptions); } void DetectedGame::appendGUIOptions(const Common::String &str) { -- cgit v1.2.3 From 1dcb8076db64420ab28722a73583f89b38314e71 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Thu, 10 May 2018 09:26:26 +0200 Subject: ENGINES: Remove usage of C++11 extended initializer lists --- base/plugins.cpp | 14 ++++++-------- engines/advancedDetector.cpp | 2 +- engines/game.cpp | 14 ++++++++++++++ engines/game.h | 4 ++-- engines/obsolete.cpp | 6 +++--- engines/sky/detection.cpp | 2 +- engines/sword1/detection.cpp | 2 +- engines/sword2/sword2.cpp | 4 ++-- 8 files changed, 30 insertions(+), 18 deletions(-) diff --git a/base/plugins.cpp b/base/plugins.cpp index 40a4d77053..023f2f3bb3 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -459,11 +459,9 @@ DECLARE_SINGLETON(EngineManager); * and only if we can't find it there, we loop through the plugins. **/ PlainGameDescriptor EngineManager::findGame(const Common::String &gameName, const Plugin **plugin) const { - PlainGameDescriptor result; - // First look for the game using the plugins in memory. This is critical // for calls coming from inside games - result = findGameInLoadedPlugins(gameName, plugin); + PlainGameDescriptor result = findGameInLoadedPlugins(gameName, plugin); if (result.gameId) { return result; } @@ -497,7 +495,6 @@ PlainGameDescriptor EngineManager::findGame(const Common::String &gameName, cons PlainGameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin) const { // Find the GameDescriptor for this target const PluginList &plugins = getPlugins(); - PlainGameDescriptor result; if (plugin) *plugin = 0; @@ -505,14 +502,15 @@ PlainGameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String PluginList::const_iterator iter; for (iter = plugins.begin(); iter != plugins.end(); ++iter) { - result = (*iter)->get().findGame(gameName.c_str()); - if (result.gameId) { + PlainGameDescriptor pgd = (*iter)->get().findGame(gameName.c_str()); + if (pgd.gameId) { if (plugin) *plugin = *iter; - return result; + return pgd; } } - return result; + + return PlainGameDescriptor::empty(); } DetectionResults EngineManager::detectGames(const Common::FSList &fslist) const { diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index c7b5c18892..3167dd9581 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -589,7 +589,7 @@ PlainGameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const { return *g; // No match found - return PlainGameDescriptor(); + return PlainGameDescriptor::empty(); } AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds, const ADExtraGuiOptionsMap *extraGuiOptions) diff --git a/engines/game.cpp b/engines/game.cpp index 3823000bce..ee14acf7c8 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -35,6 +35,20 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla return 0; } +PlainGameDescriptor PlainGameDescriptor::empty() { + PlainGameDescriptor pgd; + pgd.gameId = nullptr; + pgd.description = nullptr; + return pgd; +} + +PlainGameDescriptor PlainGameDescriptor::of(const char *gameId, const char *description) { + PlainGameDescriptor pgd; + pgd.gameId = gameId; + pgd.description = description; + return pgd; +} + DetectedGame::DetectedGame() : engineName(nullptr), hasUnknownFiles(false), diff --git a/engines/game.h b/engines/game.h index 660a94ad6c..14f9962ce6 100644 --- a/engines/game.h +++ b/engines/game.h @@ -39,8 +39,8 @@ struct PlainGameDescriptor { const char *gameId; const char *description; - PlainGameDescriptor() : gameId(nullptr), description(nullptr) {} - PlainGameDescriptor(const char *id, const char *desc) : gameId(id), description(desc) {} + static PlainGameDescriptor empty(); + static PlainGameDescriptor of(const char *gameId, const char *description); }; /** diff --git a/engines/obsolete.cpp b/engines/obsolete.cpp index 48809df712..ea96cff42e 100644 --- a/engines/obsolete.cpp +++ b/engines/obsolete.cpp @@ -73,16 +73,16 @@ PlainGameDescriptor findGameID( if (0 == scumm_stricmp(gameid, o->from)) { g = findPlainGameDescriptor(o->to, gameids); if (g && g->description) - return PlainGameDescriptor(gameid, g->description); + return PlainGameDescriptor::of(gameid, g->description); else - return PlainGameDescriptor(gameid, "Obsolete game ID"); + return PlainGameDescriptor::of(gameid, "Obsolete game ID"); } o++; } } // No match found - return PlainGameDescriptor(); + return PlainGameDescriptor::empty(); } } // End of namespace Engines diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index 6beaf02fdc..642e4d31a7 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -138,7 +138,7 @@ const ExtraGuiOptions SkyMetaEngine::getExtraGuiOptions(const Common::String &ta PlainGameDescriptor SkyMetaEngine::findGame(const char *gameid) const { if (0 == scumm_stricmp(gameid, skySetting.gameId)) return skySetting; - return PlainGameDescriptor(); + return PlainGameDescriptor::empty(); } DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const { diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 6504806423..52394cec41 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -140,7 +140,7 @@ PlainGameDescriptor SwordMetaEngine::findGame(const char *gameId) const { return sword1PSXSettings; if (0 == scumm_stricmp(gameId, sword1PSXDemoSettings.gameId)) return sword1PSXDemoSettings; - return PlainGameDescriptor(); + return PlainGameDescriptor::empty(); } void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound, bool recursion = false) { diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 0ec0e3f726..4d8399e630 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -123,7 +123,7 @@ PlainGameList Sword2MetaEngine::getSupportedGames() const { const Sword2::GameSettings *g = Sword2::sword2_settings; PlainGameList games; while (g->gameid) { - games.push_back(PlainGameDescriptor(g->gameid, g->description)); + games.push_back(PlainGameDescriptor::of(g->gameid, g->description)); g++; } return games; @@ -142,7 +142,7 @@ PlainGameDescriptor Sword2MetaEngine::findGame(const char *gameid) const { break; g++; } - return PlainGameDescriptor(g->gameid, g->description); + return PlainGameDescriptor::of(g->gameid, g->description); } bool isFullGame(const Common::FSList &fslist) { -- cgit v1.2.3