ENGINES: Merge GameDescriptor and DetectedGame
This commit is contained in:
parent
faa2534f46
commit
90b78c5446
16 changed files with 165 additions and 196 deletions
|
@ -271,21 +271,21 @@ static int findGames(Game *games, int max, bool use_ini)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!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)
|
ge != candidates.end(); ++ge)
|
||||||
if (curr_game < max) {
|
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);
|
strcpy(games[curr_game].dir, dirs[curr_dir-1].name);
|
||||||
games[curr_game].language = ge->language();
|
games[curr_game].language = ge->language;
|
||||||
games[curr_game].platform = ge->platform();
|
games[curr_game].platform = ge->platform;
|
||||||
if (uniqueGame(games[curr_game].filename_base,
|
if (uniqueGame(games[curr_game].filename_base,
|
||||||
games[curr_game].dir,
|
games[curr_game].dir,
|
||||||
games[curr_game].language,
|
games[curr_game].language,
|
||||||
games[curr_game].platform, games, curr_game)) {
|
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
|
#if 0
|
||||||
printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n",
|
printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n",
|
||||||
games[curr_game].text,
|
games[curr_game].text,
|
||||||
|
|
|
@ -854,13 +854,13 @@ static void listAudioDevices() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Display all games in the given directory, or current directory if empty */
|
/** 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;
|
Common::FSList files;
|
||||||
|
|
||||||
// Collect all files from directory
|
// Collect all files from directory
|
||||||
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
|
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
|
||||||
printf("Path %s does not exist or is not a directory.\n", dir.getPath().c_str());
|
printf("Path %s does not exist or is not a directory.\n", dir.getPath().c_str());
|
||||||
return GameList();
|
return DetectedGames();
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect Games
|
// detect Games
|
||||||
|
@ -871,25 +871,18 @@ static GameList getGameList(const Common::FSNode &dir) {
|
||||||
g_system->logMessage(LogMessageType::kInfo, report.c_str());
|
g_system->logMessage(LogMessageType::kInfo, report.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectedGames detectedGames = detectionResults.listRecognizedGames();
|
return detectionResults.listRecognizedGames();
|
||||||
|
|
||||||
GameList candidates;
|
|
||||||
for (uint i = 0; i < detectedGames.size(); i++) {
|
|
||||||
candidates.push_back(detectedGames[i].matchedGame);
|
|
||||||
}
|
|
||||||
|
|
||||||
return candidates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GameList recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) {
|
static DetectedGames recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) {
|
||||||
GameList list = getGameList(dir);
|
DetectedGames list = getGameList(dir);
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
Common::FSList files;
|
Common::FSList files;
|
||||||
dir.getChildren(files, Common::FSNode::kListDirectoriesOnly);
|
dir.getChildren(files, Common::FSNode::kListDirectoriesOnly);
|
||||||
for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
|
for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
|
||||||
GameList rec = recListGames(*file, gameId, recursive);
|
DetectedGames rec = recListGames(*file, gameId, recursive);
|
||||||
for (GameList::const_iterator game = rec.begin(); game != rec.end(); ++game) {
|
for (DetectedGames::const_iterator game = rec.begin(); game != rec.end(); ++game) {
|
||||||
if (gameId.empty() || game->gameId == gameId)
|
if (gameId.empty() || game->gameId == gameId)
|
||||||
list.push_back(*game);
|
list.push_back(*game);
|
||||||
}
|
}
|
||||||
|
@ -904,7 +897,7 @@ static Common::String detectGames(const Common::String &path, const Common::Stri
|
||||||
bool noPath = path.empty();
|
bool noPath = path.empty();
|
||||||
//Current directory
|
//Current directory
|
||||||
Common::FSNode dir(path);
|
Common::FSNode dir(path);
|
||||||
GameList candidates = recListGames(dir, gameId, recursive);
|
DetectedGames candidates = recListGames(dir, gameId, recursive);
|
||||||
|
|
||||||
if (candidates.empty()) {
|
if (candidates.empty()) {
|
||||||
printf("WARNING: ScummVM could not find any game in %s\n", dir.getPath().c_str());
|
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
|
// TODO this is not especially pretty
|
||||||
printf("ID Description Full Path\n");
|
printf("ID Description Full Path\n");
|
||||||
printf("-------------- ---------------------------------------------------------- ---------------------------------------------------------\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());
|
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) {
|
static int recAddGames(const Common::FSNode &dir, const Common::String &game, bool recursive) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
GameList list = getGameList(dir);
|
DetectedGames list = getGameList(dir);
|
||||||
for (GameList::iterator v = list.begin(); v != list.end(); ++v) {
|
for (DetectedGames::const_iterator v = list.begin(); v != list.end(); ++v) {
|
||||||
if (v->gameId != game && !game.empty()) {
|
if (v->gameId != game && !game.empty()) {
|
||||||
printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameId.c_str(), game.c_str());
|
printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameId.c_str(), game.c_str());
|
||||||
} else if (ConfMan.hasGameDomain(v->preferredTarget)) {
|
} else if (ConfMan.hasGameDomain(v->preferredTarget)) {
|
||||||
// TODO Better check for game already added?
|
// TODO Better check for game 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 {
|
} else {
|
||||||
printf("Found %s, adding...\n", v->gameId.c_str());
|
Common::String target = EngineMan.createTargetForGame(*v);
|
||||||
EngineMan.createTargetForGame(*v);
|
|
||||||
count++;
|
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);
|
DetectionResults detectionResults = EngineMan.detectGames(files);
|
||||||
DetectedGames detectedGames = detectionResults.listRecognizedGames();
|
DetectedGames candidates = detectionResults.listRecognizedGames();
|
||||||
|
|
||||||
GameList candidates;
|
|
||||||
for (uint i = 0; i < detectedGames.size(); i++) {
|
|
||||||
candidates.push_back(detectedGames[i].matchedGame);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool gameidDiffers = false;
|
bool gameidDiffers = false;
|
||||||
GameList::iterator x;
|
DetectedGames::const_iterator x;
|
||||||
for (x = candidates.begin(); x != candidates.end(); ++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);
|
||||||
}
|
}
|
||||||
|
@ -1083,14 +1079,9 @@ void upgradeTargets() {
|
||||||
Common::String desc(dom.getVal("description"));
|
Common::String desc(dom.getVal("description"));
|
||||||
|
|
||||||
DetectionResults detectionResults = EngineMan.detectGames(files);
|
DetectionResults detectionResults = EngineMan.detectGames(files);
|
||||||
DetectedGames detectedGames = detectionResults.listRecognizedGames();
|
DetectedGames candidates = detectionResults.listRecognizedGames();
|
||||||
|
|
||||||
GameList candidates;
|
DetectedGame *g = 0;
|
||||||
for (uint i = 0; i < detectedGames.size(); i++) {
|
|
||||||
candidates.push_back(detectedGames[i].matchedGame);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameDescriptor *g = 0;
|
|
||||||
|
|
||||||
// We proceed as follows:
|
// We proceed as follows:
|
||||||
// * If detection failed to produce candidates, skip.
|
// * If detection failed to produce candidates, skip.
|
||||||
|
@ -1103,7 +1094,7 @@ void upgradeTargets() {
|
||||||
}
|
}
|
||||||
if (candidates.size() > 1) {
|
if (candidates.size() > 1) {
|
||||||
// Scan over all candidates, check if there is a unique match for gameid, language and platform
|
// 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;
|
int matchesFound = 0;
|
||||||
for (x = candidates.begin(); x != candidates.end(); ++x) {
|
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) {
|
||||||
|
|
|
@ -531,7 +531,7 @@ DetectionResults EngineManager::detectGames(const Common::FSList &fslist) const
|
||||||
|
|
||||||
for (uint i = 0; i < engineCandidates.size(); i++) {
|
for (uint i = 0; i < engineCandidates.size(); i++) {
|
||||||
engineCandidates[i].engineName = metaEngine.getName();
|
engineCandidates[i].engineName = metaEngine.getName();
|
||||||
engineCandidates[i].matchedGame.path = path;
|
engineCandidates[i].path = path;
|
||||||
candidates.push_back(engineCandidates[i]);
|
candidates.push_back(engineCandidates[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,7 +554,7 @@ void addStringToConf(const Common::String &key, const Common::String &value, con
|
||||||
|
|
||||||
} // End of anonymous namespace
|
} // 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.
|
// The auto detector or the user made a choice.
|
||||||
// Pick a domain name which does not yet exist (after all, we
|
// Pick a domain name which does not yet exist (after all, we
|
||||||
// are *adding* a game to the config, not replacing).
|
// are *adding* a game to the config, not replacing).
|
||||||
|
|
|
@ -33,42 +33,32 @@
|
||||||
#include "engines/advancedDetector.h"
|
#include "engines/advancedDetector.h"
|
||||||
#include "engines/obsolete.h"
|
#include "engines/obsolete.h"
|
||||||
|
|
||||||
static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGameDescriptor *sg) {
|
DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const {
|
||||||
const char *title = 0;
|
const char *title;
|
||||||
const char *extra;
|
const char *extra;
|
||||||
|
|
||||||
if (g.flags & ADGF_USEEXTRAASTITLE) {
|
if (adGame.desc->flags & ADGF_USEEXTRAASTITLE) {
|
||||||
title = g.extra;
|
title = adGame.desc->extra;
|
||||||
extra = "";
|
extra = "";
|
||||||
} else {
|
} else {
|
||||||
while (sg->gameId) {
|
const PlainGameDescriptor *pgd = findPlainGameDescriptor(adGame.desc->gameId, _gameIds);
|
||||||
if (!scumm_stricmp(g.gameId, sg->gameId))
|
title = pgd->description;
|
||||||
title = sg->description;
|
extra = adGame.desc->extra;
|
||||||
sg++;
|
|
||||||
}
|
|
||||||
|
|
||||||
extra = g.extra;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameSupportLevel gsl = kStableGame;
|
DetectedGame game(adGame.desc->gameId, title, adGame.desc->language, adGame.desc->platform, extra);
|
||||||
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;
|
|
||||||
game.engineName = getName();
|
game.engineName = getName();
|
||||||
game.gameId = adGame.desc->gameId;
|
|
||||||
game.hasUnknownFiles = adGame.hasUnknownFiles;
|
game.hasUnknownFiles = adGame.hasUnknownFiles;
|
||||||
game.matchedFiles = adGame.matchedFiles;
|
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;
|
return game;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,8 +102,8 @@ static Common::String sanitizeName(const char *name) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const {
|
void AdvancedMetaEngine::updateGameDescriptor(DetectedGame &desc, const ADGameDescription *realDesc) const {
|
||||||
if (_singleId != NULL) {
|
if (_singleId) {
|
||||||
desc.preferredTarget = desc.gameId;
|
desc.preferredTarget = desc.gameId;
|
||||||
desc.gameId = _singleId;
|
desc.gameId = _singleId;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +311,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
|
||||||
|
|
||||||
Common::updateGameGUIOptions(agdDesc.desc->guiOptions + _guiOptions, lang);
|
Common::updateGameGUIOptions(agdDesc.desc->guiOptions + _guiOptions, lang);
|
||||||
|
|
||||||
GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc.desc, _gameIds);
|
DetectedGame gameDescriptor = toDetectedGame(agdDesc);
|
||||||
|
|
||||||
bool showTestingWarning = false;
|
bool showTestingWarning = false;
|
||||||
|
|
||||||
|
|
|
@ -321,7 +321,7 @@ protected:
|
||||||
ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const;
|
ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const;
|
||||||
|
|
||||||
// TODO
|
// 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.
|
* Compose a hashmap of all files in fslist.
|
||||||
|
|
|
@ -35,13 +35,19 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameDescriptor::GameDescriptor() :
|
DetectedGame::DetectedGame() :
|
||||||
|
engineName(nullptr),
|
||||||
|
hasUnknownFiles(false),
|
||||||
|
canBeAdded(true),
|
||||||
language(Common::UNK_LANG),
|
language(Common::UNK_LANG),
|
||||||
platform(Common::kPlatformUnknown),
|
platform(Common::kPlatformUnknown),
|
||||||
gameSupportLevel(kStableGame) {
|
gameSupportLevel(kStableGame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) :
|
DetectedGame::DetectedGame(const PlainGameDescriptor &pgd) :
|
||||||
|
engineName(nullptr),
|
||||||
|
hasUnknownFiles(false),
|
||||||
|
canBeAdded(true),
|
||||||
language(Common::UNK_LANG),
|
language(Common::UNK_LANG),
|
||||||
platform(Common::kPlatformUnknown),
|
platform(Common::kPlatformUnknown),
|
||||||
gameSupportLevel(kStableGame) {
|
gameSupportLevel(kStableGame) {
|
||||||
|
@ -51,7 +57,12 @@ GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) :
|
||||||
description = pgd.description;
|
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;
|
gameId = id;
|
||||||
preferredTarget = id;
|
preferredTarget = id;
|
||||||
description = d;
|
description = d;
|
||||||
|
@ -63,21 +74,21 @@ GameDescriptor::GameDescriptor(const Common::String &id, const Common::String &d
|
||||||
description += updateDesc();
|
description += updateDesc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameDescriptor::setGUIOptions(const Common::String &guioptions) {
|
void DetectedGame::setGUIOptions(const Common::String &guioptions) {
|
||||||
if (guioptions.empty())
|
if (guioptions.empty())
|
||||||
_guiOptions.clear();
|
_guiOptions.clear();
|
||||||
else
|
else
|
||||||
_guiOptions = Common::getGameGUIOptionsDescription(guioptions);
|
_guiOptions = Common::getGameGUIOptionsDescription(guioptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameDescriptor::appendGUIOptions(const Common::String &str) {
|
void DetectedGame::appendGUIOptions(const Common::String &str) {
|
||||||
if (!_guiOptions.empty())
|
if (!_guiOptions.empty())
|
||||||
_guiOptions += " ";
|
_guiOptions += " ";
|
||||||
|
|
||||||
_guiOptions += str;
|
_guiOptions += str;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::String GameDescriptor::updateDesc() const {
|
Common::String DetectedGame::updateDesc() const {
|
||||||
const bool hasCustomLanguage = (language != Common::UNK_LANG);
|
const bool hasCustomLanguage = (language != Common::UNK_LANG);
|
||||||
const bool hasCustomPlatform = (platform != Common::kPlatformUnknown);
|
const bool hasCustomPlatform = (platform != Common::kPlatformUnknown);
|
||||||
const bool hasExtraDesc = !extra.empty();
|
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:");
|
const char *reportEngineHeader = _s("Matched game IDs for the %s engine:");
|
||||||
|
|
||||||
Common::String report = Common::String::format(
|
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/"
|
"https://bugs.scummvm.org/"
|
||||||
);
|
);
|
||||||
report += "\n";
|
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
|
// Add the gameId to the list of matched games for the engine
|
||||||
// TODO: Use the gameId here instead of the preferred target.
|
// TODO: Use the gameId here instead of the preferred target.
|
||||||
// This is currently impossible due to the AD singleId feature losing the information.
|
// 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
|
// Consolidate matched files across all engines and detection entries
|
||||||
for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) {
|
for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) {
|
||||||
|
|
132
engines/game.h
132
engines/game.h
|
@ -71,27 +71,70 @@ enum GameSupportLevel {
|
||||||
kUnstableGame // the game is not even ready for public testing yet
|
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
|
* A record describing the properties of a file. Used on the existing
|
||||||
* version of PlainGameDescriptor, as it also contains a gameid and a description string.
|
* files while detecting a game.
|
||||||
* 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 {
|
struct FileProperties {
|
||||||
public:
|
int32 size;
|
||||||
GameDescriptor();
|
Common::String md5;
|
||||||
explicit GameDescriptor(const PlainGameDescriptor &pgd);
|
|
||||||
GameDescriptor(const Common::String &id,
|
FileProperties() : size(-1) {}
|
||||||
const Common::String &description,
|
};
|
||||||
Common::Language language = Common::UNK_LANG,
|
|
||||||
Common::Platform platform = Common::kPlatformUnknown,
|
/**
|
||||||
const Common::String &extra = Common::String());
|
* A map of all relevant existing files while detecting.
|
||||||
|
*/
|
||||||
|
typedef Common::HashMap<Common::String, FileProperties, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> 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 setGUIOptions(const Common::String &options);
|
||||||
void appendGUIOptions(const Common::String &str);
|
void appendGUIOptions(const Common::String &str);
|
||||||
Common::String getGUIOptions() const { return _guiOptions; }
|
Common::String getGUIOptions() const { return _guiOptions; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the engine supporting the detected game
|
||||||
|
*/
|
||||||
|
const char *engineName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
Common::String gameId;
|
Common::String gameId;
|
||||||
Common::String preferredTarget;
|
Common::String preferredTarget;
|
||||||
Common::String description;
|
Common::String description;
|
||||||
|
@ -117,67 +160,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/** List of games. */
|
/** List of games. */
|
||||||
typedef Common::Array<GameDescriptor> GameList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<Common::String, FileProperties, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> 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<DetectedGame> DetectedGames;
|
typedef Common::Array<DetectedGame> DetectedGames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -277,7 +277,7 @@ public:
|
||||||
*
|
*
|
||||||
* Returns the created target name.
|
* Returns the created target name.
|
||||||
*/
|
*/
|
||||||
Common::String createTargetForGame(const GameDescriptor &game);
|
Common::String createTargetForGame(const DetectedGame &game);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Convenience shortcut for accessing the engine manager. */
|
/** Convenience shortcut for accessing the engine manager. */
|
||||||
|
|
|
@ -1036,15 +1036,14 @@ DetectedGames ScummMetaEngine::detectGames(const Common::FSList &fslist) const {
|
||||||
const PlainGameDescriptor *g = findPlainGameDescriptor(x->game.gameid, gameDescriptions);
|
const PlainGameDescriptor *g = findPlainGameDescriptor(x->game.gameid, gameDescriptions);
|
||||||
assert(g);
|
assert(g);
|
||||||
|
|
||||||
DetectedGame game;
|
DetectedGame game = DetectedGame(x->game.gameid, g->description, x->language, x->game.platform, 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.
|
// Compute and set the preferred target name for this game.
|
||||||
// Based on generateComplexID() in advancedDetector.cpp.
|
// 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.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language));
|
||||||
|
|
||||||
detectedGames.push_back(game);
|
detectedGames.push_back(game);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,18 +182,16 @@ DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const {
|
||||||
++sv;
|
++sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectedGame game;
|
|
||||||
if (sv->dinnerTableEntries) {
|
if (sv->dinnerTableEntries) {
|
||||||
Common::String extra = Common::String::format("v0.0%d %s", sv->version, sv->extraDesc);
|
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);
|
DetectedGame game = DetectedGame(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown, extra);
|
||||||
game.matchedGame.setGUIOptions(sv->guioptions);
|
game.setGUIOptions(sv->guioptions);
|
||||||
|
|
||||||
|
detectedGames.push_back(game);
|
||||||
} else {
|
} else {
|
||||||
game.matchedGame = GameDescriptor(skySetting.gameId, skySetting.description);
|
detectedGames.push_back(DetectedGame(skySetting.gameId, skySetting.description));
|
||||||
}
|
}
|
||||||
|
|
||||||
detectedGames.push_back(game);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return detectedGames;
|
return detectedGames;
|
||||||
|
|
|
@ -214,29 +214,29 @@ DetectedGames SwordMetaEngine::detectGames(const Common::FSList &fslist) const {
|
||||||
|
|
||||||
DetectedGame game;
|
DetectedGame game;
|
||||||
if (mainFilesFound && pcFilesFound && demoFilesFound)
|
if (mainFilesFound && pcFilesFound && demoFilesFound)
|
||||||
game.matchedGame = GameDescriptor(sword1DemoSettings);
|
game = DetectedGame(sword1DemoSettings);
|
||||||
else if (mainFilesFound && pcFilesFound && psxFilesFound)
|
else if (mainFilesFound && pcFilesFound && psxFilesFound)
|
||||||
game.matchedGame = GameDescriptor(sword1PSXSettings);
|
game = DetectedGame(sword1PSXSettings);
|
||||||
else if (mainFilesFound && pcFilesFound && psxDemoFilesFound)
|
else if (mainFilesFound && pcFilesFound && psxDemoFilesFound)
|
||||||
game.matchedGame = GameDescriptor(sword1PSXDemoSettings);
|
game = DetectedGame(sword1PSXDemoSettings);
|
||||||
else if (mainFilesFound && pcFilesFound && !psxFilesFound)
|
else if (mainFilesFound && pcFilesFound && !psxFilesFound)
|
||||||
game.matchedGame = GameDescriptor(sword1FullSettings);
|
game = DetectedGame(sword1FullSettings);
|
||||||
else if (mainFilesFound && macFilesFound)
|
else if (mainFilesFound && macFilesFound)
|
||||||
game.matchedGame = GameDescriptor(sword1MacFullSettings);
|
game = DetectedGame(sword1MacFullSettings);
|
||||||
else if (mainFilesFound && macDemoFilesFound)
|
else if (mainFilesFound && macDemoFilesFound)
|
||||||
game.matchedGame = GameDescriptor(sword1MacDemoSettings);
|
game = DetectedGame(sword1MacDemoSettings);
|
||||||
else
|
else
|
||||||
return detectedGames;
|
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.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA));
|
||||||
game.matchedGame.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE));
|
game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE));
|
||||||
|
|
||||||
detectedGames.push_back(game);
|
detectedGames.push_back(game);
|
||||||
|
|
||||||
|
|
|
@ -192,9 +192,8 @@ DetectedGames detectGamesImpl(const Common::FSList &fslist, bool recursion = fal
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Match found, add to list of candidates, then abort inner loop.
|
// Match found, add to list of candidates, then abort inner loop.
|
||||||
DetectedGame game;
|
DetectedGame game = DetectedGame(g->gameid, g->description);
|
||||||
game.matchedGame = GameDescriptor(g->gameid, g->description);
|
game.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
|
||||||
game.matchedGame.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
|
|
||||||
|
|
||||||
detectedGames.push_back(game);
|
detectedGames.push_back(game);
|
||||||
break;
|
break;
|
||||||
|
@ -285,7 +284,7 @@ Common::Error Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) c
|
||||||
DetectedGames detectedGames = detectGames(fslist);
|
DetectedGames detectedGames = detectGames(fslist);
|
||||||
|
|
||||||
for (uint i = 0; i < detectedGames.size(); i++) {
|
for (uint i = 0; i < detectedGames.size(); i++) {
|
||||||
if (detectedGames[i].matchedGame.gameId == gameid) {
|
if (detectedGames[i].gameId == gameid) {
|
||||||
*engine = new Sword2::Sword2Engine(syst);
|
*engine = new Sword2::Sword2Engine(syst);
|
||||||
return Common::kNoError;
|
return Common::kNoError;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,6 @@ class StaticTextWidget;
|
||||||
class EditTextWidget;
|
class EditTextWidget;
|
||||||
class SaveLoadChooser;
|
class SaveLoadChooser;
|
||||||
|
|
||||||
Common::String addGameToConf(const GameDescriptor &result);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A dialog that allows the user to edit a config game entry.
|
* A dialog that allows the user to edit a config game entry.
|
||||||
* TODO: add widgets for some/all of the following
|
* TODO: add widgets for some/all of the following
|
||||||
|
|
|
@ -562,14 +562,14 @@ bool LauncherDialog::doGameDetection(const Common::String &path) {
|
||||||
// Display the candidates to the user and let her/him pick one
|
// Display the candidates to the user and let her/him pick one
|
||||||
StringArray list;
|
StringArray list;
|
||||||
for (idx = 0; idx < (int)candidates.size(); idx++)
|
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:"));
|
ChooserDialog dialog(_("Pick the game:"));
|
||||||
dialog.setList(list);
|
dialog.setList(list);
|
||||||
idx = dialog.runModal();
|
idx = dialog.runModal();
|
||||||
}
|
}
|
||||||
if (0 <= idx && idx < (int)candidates.size()) {
|
if (0 <= idx && idx < (int)candidates.size()) {
|
||||||
const GameDescriptor &result = candidates[idx].matchedGame;
|
const DetectedGame &result = candidates[idx];
|
||||||
|
|
||||||
Common::String domain = EngineMan.createTargetForGame(result);
|
Common::String domain = EngineMan.createTargetForGame(result);
|
||||||
|
|
||||||
|
|
|
@ -117,13 +117,13 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GameTargetLess {
|
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;
|
return x.preferredTarget.compareToIgnoreCase(y.preferredTarget) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GameDescLess {
|
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;
|
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.
|
// people who want to edit their config file by hand after a mass add.
|
||||||
Common::sort(_games.begin(), _games.end(), GameTargetLess());
|
Common::sort(_games.begin(), _games.end(), GameTargetLess());
|
||||||
// Add all the detected games to the config
|
// 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",
|
debug(1, " Added gameid '%s', desc '%s'\n",
|
||||||
iter->gameId.c_str(),
|
iter->gameId.c_str(),
|
||||||
iter->description.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.
|
// However, we only add games which are not already in the config file.
|
||||||
DetectedGames candidates = detectionResults.listRecognizedGames();
|
DetectedGames candidates = detectionResults.listRecognizedGames();
|
||||||
for (DetectedGames::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) {
|
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();
|
Common::String path = dir.getPath();
|
||||||
|
|
||||||
// Remove trailing slashes
|
// Remove trailing slashes
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Common::Stack<Common::FSNode> _scanStack;
|
Common::Stack<Common::FSNode> _scanStack;
|
||||||
GameList _games;
|
DetectedGames _games;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map each path occuring in the config file to the target(s) using that path.
|
* Map each path occuring in the config file to the target(s) using that path.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue