Advanced detector: split out part of detectGame into a new function detectGameFilebased; some cleanup

svn-id: r33453
This commit is contained in:
Max Horn 2008-07-30 15:16:57 +00:00
parent aa2ffe047b
commit 04c05d3ca0
2 changed files with 95 additions and 106 deletions

View file

@ -34,7 +34,11 @@
namespace Common { namespace Common {
using namespace AdvancedDetector; /**
* A list of pointers to ADGameDescription structs (or subclasses thereof).
*/
typedef Array<const ADGameDescription*> ADGameDescList;
/** /**
* Detect games in specified directory. * Detect games in specified directory.
@ -282,10 +286,10 @@ PluginError AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) c
return kNoError; return kNoError;
} }
typedef HashMap<String, bool> StringSet; typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> StringSet;
typedef HashMap<String, int32> IntMap; typedef HashMap<String, int32, IgnoreCase_Hash, IgnoreCase_EqualTo> IntMap;
static void reportUnknown(StringMap &filesMD5, IntMap &filesSize) { static void reportUnknown(const StringMap &filesMD5, const IntMap &filesSize) {
// TODO: This message should be cleaned up / made more specific. // TODO: This message should be cleaned up / made more specific.
// For example, we should specify at least which engine triggered this. // For example, we should specify at least which engine triggered this.
// //
@ -301,21 +305,14 @@ static void reportUnknown(StringMap &filesMD5, IntMap &filesSize) {
printf("\n"); printf("\n");
} }
static ADGameDescList detectGameFilebased(const FSList &fslist, const Common::ADParams &params, IntMap &allFiles);
static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &params, Language language, Platform platform, const Common::String extra) { static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &params, Language language, Platform platform, const Common::String extra) {
StringSet filesList; StringSet filesList;
StringMap filesMD5; StringMap filesMD5;
IntMap filesSize; IntMap filesSize;
IntMap allFiles; IntMap allFiles;
File testFile;
String tstr;
uint i;
char md5str[32+1];
bool fileMissing;
const ADGameFileDescription *fileDesc; const ADGameFileDescription *fileDesc;
const ADGameDescription *g; const ADGameDescription *g;
const byte *descPtr; const byte *descPtr;
@ -327,34 +324,36 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
g = (const ADGameDescription *)descPtr; g = (const ADGameDescription *)descPtr;
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
tstr = String(fileDesc->fileName); filesList[String(fileDesc->fileName)] = true;
tstr.toLowercase();
filesList[tstr] = true;
} }
} }
// Get the information of the existing files // Get the information of the existing files
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (file->isDirectory()) continue; if (file->isDirectory())
tstr = file->getName(); continue;
tstr.toLowercase();
String tstr = file->getName();
// Strip any trailing dot // Strip any trailing dot
if (tstr.lastChar() == '.') if (tstr.lastChar() == '.')
tstr.deleteLastChar(); tstr.deleteLastChar();
allFiles[tstr] = true; allFiles[tstr] = true; // Record the presence of this file
debug(3, "+ %s", tstr.c_str()); debug(3, "+ %s", tstr.c_str());
if (!filesList.contains(tstr)) continue; if (!filesList.contains(tstr))
continue;
char md5str[32+1];
if (!md5_file_string(*file, md5str, params.md5Bytes)) if (!md5_file_string(*file, md5str, params.md5Bytes))
continue; continue;
filesMD5[tstr] = md5str; filesMD5[tstr] = md5str;
debug(3, "> %s: %s", tstr.c_str(), md5str); debug(3, "> %s: %s", tstr.c_str(), md5str);
File testFile;
if (testFile.open(file->getPath())) { if (testFile.open(file->getPath())) {
filesSize[tstr] = (int32)testFile.size(); filesSize[tstr] = (int32)testFile.size();
testFile.close(); testFile.close();
@ -366,9 +365,10 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
int maxFilesMatched = 0; int maxFilesMatched = 0;
// MD5 based matching // MD5 based matching
uint i;
for (i = 0, descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize, ++i) { for (i = 0, descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize, ++i) {
g = (const ADGameDescription *)descPtr; g = (const ADGameDescription *)descPtr;
fileMissing = false; bool fileMissing = false;
// Do not even bother to look at entries which do not have matching // Do not even bother to look at entries which do not have matching
// language and platform (if specified). // language and platform (if specified).
@ -377,33 +377,29 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
continue; continue;
} }
if ((params.flags & kADFlagUseExtraAsHint) && extra != "" && g->extra != extra) if ((params.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra)
continue; continue;
// Try to match all files for this game // Try to match all files for this game
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
tstr = fileDesc->fileName; String tstr = fileDesc->fileName;
tstr.toLowercase();
if (!filesMD5.contains(tstr)) { if (!filesMD5.contains(tstr)) {
fileMissing = true; fileMissing = true;
break; break;
} }
if (fileDesc->md5 != NULL) {
if (fileDesc->md5 != filesMD5[tstr]) { if (fileDesc->md5 != NULL && fileDesc->md5 != filesMD5[tstr]) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesMD5[tstr].c_str()); debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesMD5[tstr].c_str());
fileMissing = true; fileMissing = true;
break; break;
} }
}
if (fileDesc->fileSize != -1) { if (fileDesc->fileSize != -1 && fileDesc->fileSize != filesSize[tstr]) {
if (fileDesc->fileSize != filesSize[tstr]) {
debug(3, "Size Mismatch. Skipping"); debug(3, "Size Mismatch. Skipping");
fileMissing = true; fileMissing = true;
break; break;
} }
}
debug(3, "Matched file: %s", tstr.c_str()); debug(3, "Matched file: %s", tstr.c_str());
} }
@ -440,27 +436,31 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
} }
} }
// We've found a match // We didn't find a match
if (!matched.empty()) if (matched.empty()) {
return matched;
if (!filesMD5.empty()) if (!filesMD5.empty())
reportUnknown(filesMD5, filesSize); reportUnknown(filesMD5, filesSize);
// Filename based fallback // Filename based fallback
if (params.fileBasedFallback != 0) { if (params.fileBasedFallback != 0)
const ADFileBasedFallback *ptr = params.fileBasedFallback; matched = detectGameFilebased(fslist, params, allFiles);
const char* const* filenames = 0; }
return matched;
}
static ADGameDescList detectGameFilebased(const FSList &fslist, const Common::ADParams &params, IntMap &allFiles) {
const ADFileBasedFallback *ptr;
const char* const* filenames;
// First we create list of files required for detection. // First we create list of files required for detection.
// The filenames can be different than the MD5 based match ones. // The filenames can be different than the MD5 based match ones.
for (; ptr->desc; ptr++) { for (ptr = params.fileBasedFallback; ptr->desc; ++ptr) {
filenames = ptr->filenames; for (filenames = ptr->filenames; *filenames; ++filenames) {
for (; *filenames; filenames++) { String tstr = String(*filenames);
tstr = String(*filenames);
tstr.toLowercase();
if (!allFiles.contains(tstr)) { if (!allFiles.contains(tstr)) {
File testFile;
if (testFile.open(tstr) || testFile.open(tstr + ".")) { if (testFile.open(tstr) || testFile.open(tstr + ".")) {
allFiles[tstr] = true; allFiles[tstr] = true;
testFile.close(); testFile.close();
@ -475,24 +475,17 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
int maxNumMatchedFiles = 0; int maxNumMatchedFiles = 0;
const ADGameDescription *matchedDesc = 0; const ADGameDescription *matchedDesc = 0;
ptr = params.fileBasedFallback; for (ptr = params.fileBasedFallback; ptr->desc; ++ptr) {
for (; ptr->desc; ptr++) {
const ADGameDescription *agdesc = (const ADGameDescription *)ptr->desc; const ADGameDescription *agdesc = (const ADGameDescription *)ptr->desc;
int numMatchedFiles = 0; int numMatchedFiles = 0;
fileMissing = false; bool fileMissing = false;
filenames = ptr->filenames; for (filenames = ptr->filenames; *filenames; ++filenames) {
for (; *filenames; filenames++) { if (fileMissing)
if (fileMissing) {
continue; continue;
}
tstr = String(*filenames);
tstr.toLowercase();
debug(3, "++ %s", *filenames); debug(3, "++ %s", *filenames);
if (!allFiles.contains(tstr)) { if (!allFiles.contains(*filenames)) {
fileMissing = true; fileMissing = true;
continue; continue;
} }
@ -511,6 +504,8 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
} }
} }
ADGameDescList matched;
if (matchedDesc) { // We got a match if (matchedDesc) { // We got a match
matched.push_back(matchedDesc); matched.push_back(matchedDesc);
if (params.flags & kADFlagPrintWarningOnFileBasedFallback) { if (params.flags & kADFlagPrintWarningOnFileBasedFallback) {
@ -520,7 +515,6 @@ static ADGameDescList detectGame(const FSList &fslist, const Common::ADParams &p
printf("information previously printed by ScummVM to the team.\n"); printf("information previously printed by ScummVM to the team.\n");
} }
} }
}
return matched; return matched;
} }

View file

@ -68,11 +68,6 @@ struct ADGameDescription {
uint32 flags; uint32 flags;
}; };
/**
* A list of pointers to ADGameDescription structs (or subclasses thereof).
*/
typedef Array<const ADGameDescription*> ADGameDescList;
/** /**
* End marker for a table of ADGameDescription structs. Use this to * End marker for a table of ADGameDescription structs. Use this to
* terminate a list to be passed to the AdvancedDetector API. * terminate a list to be passed to the AdvancedDetector API.