aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/advancedDetector.cpp120
-rw-r--r--common/advancedDetector.h5
-rw-r--r--engines/agi/detection.cpp2
-rw-r--r--engines/agos/game.cpp2
-rw-r--r--engines/cine/detection.cpp2
-rw-r--r--engines/gob/detection.cpp160
-rw-r--r--engines/kyra/plugin.cpp2
-rw-r--r--engines/parallaction/detection.cpp2
-rw-r--r--engines/saga/game.cpp2
9 files changed, 242 insertions, 55 deletions
diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp
index 1193b1c72e..faca7184d0 100644
--- a/common/advancedDetector.cpp
+++ b/common/advancedDetector.cpp
@@ -251,6 +251,7 @@ static ADList detectGame(const FSList *fslist, const Common::ADParams &params, L
typedef HashMap<String, int32, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> IntMap;
StringMap filesMD5;
IntMap filesSize;
+ IntMap allFiles;
String tstr, tstr2;
@@ -293,6 +294,8 @@ static ADList detectGame(const FSList *fslist, const Common::ADParams &params, L
tstr.toLowercase();
tstr2 = tstr + ".";
+ allFiles[tstr] = allFiles[tstr2] = 1;
+
debug(3, "+ %s", tstr.c_str());
if (!filesList.contains(tstr) && !filesList.contains(tstr2)) continue;
@@ -349,7 +352,12 @@ static ADList detectGame(const FSList *fslist, const Common::ADParams &params, L
(platform != kPlatformUnknown && g->platform != platform)) {
continue;
}
-
+
+ if (g->filesDescriptions[0].fileName == 0) {
+ debug(5, "Skipping dummy entry: %s", g->gameid);
+ continue;
+ }
+
// Try to open all files for this game
for (j = 0; g->filesDescriptions[j].fileName; j++) {
fileDesc = &g->filesDescriptions[j];
@@ -357,28 +365,26 @@ static ADList detectGame(const FSList *fslist, const Common::ADParams &params, L
tstr.toLowercase();
tstr2 = tstr + ".";
+ if (!filesMD5.contains(tstr) && !filesMD5.contains(tstr2)) {
+ fileMissing = true;
+ break;
+ }
if (fileDesc->md5 != NULL) {
- if (!filesMD5.contains(tstr) && !filesMD5.contains(tstr2)) {
- fileMissing = true;
- break;
- }
if (strcmp(fileDesc->md5, filesMD5[tstr].c_str()) && strcmp(fileDesc->md5, filesMD5[tstr2].c_str())) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesMD5[tstr].c_str());
fileMissing = true;
break;
}
}
+
if (fileDesc->fileSize != -1) {
- if (!filesMD5.contains(tstr) && !filesMD5.contains(tstr2)) {
- fileMissing = true;
- break;
- }
if (fileDesc->fileSize != filesSize[tstr] && fileDesc->fileSize != filesSize[tstr2]) {
debug(3, "Size Mismatch. Skipping");
fileMissing = true;
break;
}
}
+
debug(3, "Matched file: %s", tstr.c_str());
}
if (!fileMissing) {
@@ -416,6 +422,102 @@ static ADList detectGame(const FSList *fslist, const Common::ADParams &params, L
printf("%s: \"%s\", %d\n", file->_key.c_str(), file->_value.c_str(), filesSize[file->_key]);
}
+ if (params.flags & kADFlagFilebasedFallback) {
+ if (params.fileBased == NULL) {
+ error("Engine %s has FilebasedFallback flag set but list fileBased is empty",
+ params.singleid); // We may get 0 as singleid here, but let's ignore it
+ }
+
+ const char **ptr = params.fileBased;
+
+ // First we create list of files required for detection
+ if (allFiles.empty()) {
+ File testFile;
+
+ while (*ptr) {
+ ptr++;
+
+ while (*ptr) {
+ tstr = String(*ptr);
+ tstr.toLowercase();
+
+ if (!allFiles.contains(tstr)) {
+ if (testFile.open(tstr)) {
+ tstr2 = tstr + ".";
+ allFiles[tstr] = allFiles[tstr2] = 1;
+ testFile.close();
+ }
+ }
+
+ ptr++;
+ }
+
+ ptr++;
+ }
+ }
+
+ int maxFiles = 0;
+ int matchFiles;
+ const char **matchEntry = 0;
+ const char **entryStart;
+
+ ptr = params.fileBased;
+
+ while (*ptr) {
+ entryStart = ptr;
+ fileMissing = false;
+ matchFiles = 0;
+
+ ptr++;
+
+ while (*ptr) {
+ if (fileMissing) {
+ ptr++;
+ continue;
+ }
+
+ tstr = String(*ptr);
+
+ tstr.toLowercase();
+ tstr2 = tstr + ".";
+
+ debug(3, "++ %s", *ptr);
+ if (!allFiles.contains(tstr) && !allFiles.contains(tstr2)) {
+ fileMissing = true;
+ ptr++;
+ continue;
+ }
+
+ matchFiles++;
+ ptr++;
+ }
+
+ if (!fileMissing)
+ debug(4, "Matched: %s", *entryStart);
+
+ if (!fileMissing && matchFiles > maxFiles) {
+ matchEntry = entryStart;
+ maxFiles = matchFiles;
+
+ debug(4, "and overrided");
+ }
+
+ ptr++;
+ }
+
+ if (matchEntry) { // We got a match
+ for (i = 0; i < gameDescriptions.size(); i++) {
+ if (gameDescriptions[i]->filesDescriptions[0].fileName == 0) {
+ if (!scumm_stricmp(gameDescriptions[i]->gameid, *matchEntry)) {
+ warning("But it looks like unknown variant of %s", *matchEntry);
+
+ matched.push_back(i);
+ }
+ }
+ }
+ }
+ }
+
return matched;
}
diff --git a/common/advancedDetector.h b/common/advancedDetector.h
index 4f79cd87db..93650f7f72 100644
--- a/common/advancedDetector.h
+++ b/common/advancedDetector.h
@@ -52,7 +52,8 @@ struct ADObsoleteGameID {
};
enum ADFlags {
- kADFlagComplexID = (1 << 0) // Generate complex suggested IDs
+ kADFlagComplexID = (1 << 0), // Generate complex suggested IDs
+ kADFlagFilebasedFallback = (1 << 1) // Use file based fallback detection
};
struct ADParams {
@@ -68,6 +69,8 @@ struct ADParams {
const Common::ADObsoleteGameID *obsoleteList;
// Name of single gameid (optional)
const char *singleid;
+ // List of files for file-based fallback detection (optional)
+ const char **fileBased;
// Flags
uint32 flags;
};
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index dcb328c314..6b8e7348de 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -1013,6 +1013,8 @@ static const Common::ADParams detectionParams = {
0,
// Name of single gameid (optional)
"agi",
+ // List of files for file-based fallback detection (optional)
+ 0,
// Flags
Common::kADFlagComplexID
};
diff --git a/engines/agos/game.cpp b/engines/agos/game.cpp
index 89a22caa30..8652cb726b 100644
--- a/engines/agos/game.cpp
+++ b/engines/agos/game.cpp
@@ -95,6 +95,8 @@ static const Common::ADParams detectionParams = {
obsoleteGameIDsTable,
// Name of single gameid (optional)
0,
+ // List of files for file-based fallback detection (optional)
+ 0,
// Flags
0
};
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index c455322a85..14c829a0dc 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -450,6 +450,8 @@ static const Common::ADParams detectionParams = {
obsoleteGameIDsTable,
// Name of single gameid (optional)
"cine",
+ // List of files for file-based fallback detection (optional)
+ 0,
// Flags
Common::kADFlagComplexID
};
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 2379e8fa97..1997b117d6 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -45,10 +45,13 @@ using namespace Common;
static const PlainGameDescriptor gobGames[] = {
{"gob", "Gob engine game"},
{"gob1", "Gobliiins"},
+ {"gob1cd", "Gobliiins CD"},
{"gob1-demo", "Gobliiins Demo"},
{"gob2", "Gobliins 2"},
+ {"gob2cd", "Gobliins 2 CD"},
{"gob2-demo", "Gobliins 2 Demo"},
{"gob3", "Goblins Quest 3"},
+ {"gob3cd", "Goblins Quest 3 CD"},
{"gob3-demo", "Goblins Quest 3 Demo"},
{"bargon", "Bargon Attack"},
{"ween", "Ween: The Prohpecy"},
@@ -66,6 +69,17 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = {
namespace Gob {
static const GOBGameDescription gameDescriptions[] = {
+ { // Dummy entry for fallback detection
+ {
+ "gob1",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ },
+ GF_GOB1,
+ "intro"
+ },
{ // Supplied by Florian Zeitz on scummvm-devel
{
"gob1",
@@ -99,10 +113,21 @@ static const GOBGameDescription gameDescriptions[] = {
GF_GOB1,
"intro"
},
- { // CD 1.000 version. Multilingual
+ { // Dummy entry for fallback detection
{
- "gob1",
- "CD 1.000",
+ "gob1cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ },
+ GF_GOB1 | GF_CD,
+ "intro"
+ },
+ { // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
UNK_LANG,
kPlatformPC,
@@ -112,10 +137,43 @@ static const GOBGameDescription gameDescriptions[] = {
},
{ // CD 1.02 version. Multilingual
{
- "gob1",
- "CD 1.02",
+ "gob1cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- UNK_LANG,
+ EN_USA,
+ kPlatformPC,
+ },
+ GF_GOB1 | GF_CD,
+ "intro"
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ FR_FRA,
+ kPlatformPC,
+ },
+ GF_GOB1 | GF_CD,
+ "intro"
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ IT_ITA,
+ kPlatformPC,
+ },
+ GF_GOB1 | GF_CD,
+ "intro"
+ },
+ { // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ ES_ESP,
kPlatformPC,
},
GF_GOB1 | GF_CD,
@@ -154,6 +212,17 @@ static const GOBGameDescription gameDescriptions[] = {
GF_GOB1,
"intro"
},
+ { // Dummy entry for fallback detection
+ {
+ "gob2",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ },
+ GF_GOB2,
+ "intro"
+ },
{
{
"gob2",
@@ -231,10 +300,21 @@ static const GOBGameDescription gameDescriptions[] = {
GF_GOB2,
"intro"
},
+ { // Dummy entry for fallback detection
+ {
+ "gob2cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ },
+ GF_GOB2 | GF_CD,
+ "intro"
+ },
{
{
- "gob2",
- "CD 1.000",
+ "gob2cd",
+ "v1.000",
AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"),
EN_USA,
kPlatformPC,
@@ -244,8 +324,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob2",
- "CD 1.02",
+ "gob2cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
EN_ANY,
kPlatformPC,
@@ -255,8 +335,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob2",
- "CD 1.02",
+ "gob2cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
DE_DEU,
kPlatformPC,
@@ -266,8 +346,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob2",
- "CD 1.02",
+ "gob2cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
FR_FRA,
kPlatformPC,
@@ -277,8 +357,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob2",
- "CD 1.02",
+ "gob2cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
IT_ITA,
kPlatformPC,
@@ -288,8 +368,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob2",
- "CD 1.02",
+ "gob2cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
ES_ESP,
kPlatformPC,
@@ -453,8 +533,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob3",
- "CD 1.000",
+ "gob3cd",
+ "v1.000",
AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"),
UNK_LANG,
kPlatformPC,
@@ -464,8 +544,8 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
- "gob3",
- "CD 1.02",
+ "gob3cd",
+ "v1.02",
AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
UNK_LANG,
kPlatformPC,
@@ -542,6 +622,15 @@ static const GOBGameDescription gameDescriptions[] = {
{ { NULL, NULL, { { NULL, 0, NULL, 0 } }, UNK_LANG, kPlatformUnknown }, 0, NULL }
};
+static const char *fileBased[] = {
+ "gob1", "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0,
+ "gob1cd", "intro.stk", "gob.lic", 0,
+ "gob2", "intro.stk", 0,
+ "gob2", "intro.stk", "disk2.stk", "disk3.stk", 0,
+ "gob2cd", "intro.stk", "gobnew.lic", 0,
+ 0
+};
+
}
static const ADParams detectionParams = {
@@ -557,8 +646,10 @@ static const ADParams detectionParams = {
obsoleteGameIDsTable,
// Name of single gameid (optional)
"gob",
+ // List of files for file-based fallback detection (optional)
+ Gob::fileBased,
// Flags
- kADFlagComplexID
+ kADFlagComplexID | kADFlagFilebasedFallback
};
ADVANCED_DETECTOR_DEFINE_PLUGIN(GOB, Gob::GobEngine, Gob::GAME_detectGames, detectionParams);
@@ -593,28 +684,7 @@ bool GobEngine::detectGame() {
}
GameList GAME_detectGames(const FSList &fslist) {
- GameList gl(AdvancedDetector::detectAllGames(fslist, detectionParams));
-
- if (gl.empty()) {
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory()) continue;
-
- if (!scumm_stricmp(file->name().c_str(), "intro.stk")) {
- const PlainGameDescriptor *g = detectionParams.list;
- while (g->gameid) {
- if (0 == scumm_stricmp(detectionParams.singleid, g->gameid)) {
- gl.push_back(GameDescriptor(g->gameid, g->description));
-
- return gl;
- }
-
- g++;
- }
- }
- }
- }
-
- return gl;
+ return AdvancedDetector::detectAllGames(fslist, detectionParams);
}
} // End of namespace Parallaction
diff --git a/engines/kyra/plugin.cpp b/engines/kyra/plugin.cpp
index 6f497e3a61..31f87afaa8 100644
--- a/engines/kyra/plugin.cpp
+++ b/engines/kyra/plugin.cpp
@@ -94,6 +94,8 @@ const Common::ADParams detectionParams = {
0,
// Name of single gameid (optional)
0,
+ // List of files for file-based fallback detection (optional)
+ 0,
// Flags
0
};
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index 898df9d7da..709879a4c0 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -93,6 +93,8 @@ static const Common::ADParams detectionParams = {
0,
// Name of single gameid (optional)
"parallaction",
+ // List of files for file-based fallback detection (optional)
+ 0,
// Flags
Common::kADFlagComplexID
};
diff --git a/engines/saga/game.cpp b/engines/saga/game.cpp
index f2c3ff0628..24dfd41398 100644
--- a/engines/saga/game.cpp
+++ b/engines/saga/game.cpp
@@ -114,6 +114,8 @@ static const Common::ADParams detectionParams = {
obsoleteGameIDsTable,
// Name of single gameid (optional)
"saga",
+ // List of files for file-based fallback detection (optional)
+ 0,
// Flags
Common::kADFlagComplexID
};