Ticket #8690: fallback-alternate2.v2.patch
File fallback-alternate2.v2.patch, 19.0 KB (added by , 16 years ago) |
---|
-
common/advancedDetector.h
64 64 }; 65 65 66 66 /** 67 * Encapsulates ADGameDescription and makes gameid and extra strings dynamic. 68 * Used in fallback detection when dynamically creating string content. 69 */ 70 struct EncapsulatedADGameDesc { 71 Common::String gameid; 72 Common::String extra; 73 const ADGameDescription *realDesc; 74 75 // Constructor for the EncapsulatedADGameDesc 76 EncapsulatedADGameDesc() : realDesc(0) {} 77 EncapsulatedADGameDesc(const ADGameDescription *paramRealDesc, 78 Common::String paramGameID = Common::String(""), 79 Common::String paramExtra = Common::String("")) 80 : realDesc(paramRealDesc), gameid(paramGameID), extra(paramExtra) { 81 assert(paramRealDesc != NULL); 82 } 83 84 // Functions for getting the correct gameid and extra values from the struct 85 const char *getGameID() const { return (gameid.empty() && realDesc != 0) ? realDesc->gameid : gameid.c_str(); } 86 const char *getExtra() const { return (extra.empty() && realDesc != 0) ? realDesc->extra : extra.c_str(); } 87 }; 88 89 /** 67 90 * A list of pointers to ADGameDescription structs (or subclasses thereof). 68 91 */ 69 92 typedef Array<const ADGameDescription*> ADGameDescList; … … 177 200 * 178 201 * @todo 179 202 */ 180 ADGameDescList(*fallbackDetectFunc)(const FSList *fslist);203 EncapsulatedADGameDesc (*fallbackDetectFunc)(const FSList *fslist); 181 204 182 205 /** 183 206 * A bitmask of flags which can be used to configure the behavior … … 207 230 GameList detectAllGames(const FSList &fslist, const Common::ADParams ¶ms); 208 231 209 232 // FIXME/TODO: Rename this function to something more sensible. 210 const ADGameDescription *detectBestMatchingGame(const Common::ADParams ¶ms);233 EncapsulatedADGameDesc detectBestMatchingGame(const Common::ADParams ¶ms); 211 234 212 235 // FIXME/TODO: Rename this function to something more sensible. 213 236 // Only used by ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_FUNC -
common/advancedDetector.cpp
110 110 return gd; 111 111 } 112 112 113 // Almost identical to the toGameDescriptor function that takes a ADGameDescription and PlainGameDescriptor. 114 // Just a little fine tuning about accessing variables. 115 // Used because of fallback detection and the dynamic string content it needs. 116 static GameDescriptor toGameDescriptor(const EncapsulatedADGameDesc &g, const PlainGameDescriptor *sg) { 117 const char *title = 0; 118 119 while (sg->gameid) { 120 if (!scumm_stricmp(g.getGameID(), sg->gameid)) 121 title = sg->description; 122 sg++; 123 } 124 125 assert(g.realDesc); 126 GameDescriptor gd(g.getGameID(), title, g.realDesc->language, g.realDesc->platform); 127 gd.updateDesc(g.getExtra()); 128 return gd; 129 } 130 113 131 /** 114 132 * Generate a preferred target value as 115 133 * GAMEID-PLAFORM-LANG … … 134 152 return res; 135 153 } 136 154 155 static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc, const Common::ADParams ¶ms) { 156 if (params.singleid != NULL) { 157 desc["preferredtarget"] = desc["gameid"]; 158 desc["gameid"] = params.singleid; 159 } 160 161 if (params.flags & kADFlagAugmentPreferredTarget) { 162 if (!desc.contains("preferredtarget")) 163 desc["preferredtarget"] = desc["gameid"]; 164 165 desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], realDesc); 166 } 167 } 168 137 169 GameList detectAllGames( 138 170 const FSList &fslist, 139 171 const Common::ADParams ¶ms 140 172 ) { 141 173 ADGameDescList matches = detectGame(&fslist, params, Common::UNK_LANG, Common::kPlatformUnknown); 142 143 174 GameList detectedGames; 144 for (uint i = 0; i < matches.size(); i++) {145 GameDescriptor desc(toGameDescriptor(*matches[i], params.list));146 175 147 if (params.singleid != NULL) { 148 desc["preferredtarget"] = desc["gameid"]; 149 desc["gameid"] = params.singleid; 176 // Use fallback detector if there were no matches by other means 177 if (matches.empty() && params.fallbackDetectFunc != NULL) { 178 EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(&fslist); 179 if (fallbackDesc.realDesc != 0) { 180 GameDescriptor desc(toGameDescriptor(fallbackDesc, params.list)); 181 updateGameDescriptor(desc, fallbackDesc.realDesc, params); 182 detectedGames.push_back(desc); 150 183 } 151 152 if (params.flags & kADFlagAugmentPreferredTarget) { 153 if (!desc.contains("preferredtarget")) 154 desc["preferredtarget"] = desc["gameid"]; 155 156 desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], matches[i]); 157 } 158 184 } else for (uint i = 0; i < matches.size(); i++) { // Otherwise use the found matches 185 GameDescriptor desc(toGameDescriptor(*matches[i], params.list)); 186 updateGameDescriptor(desc, matches[i], params); 159 187 detectedGames.push_back(desc); 160 188 } 161 189 162 190 return detectedGames; 163 191 } 164 192 165 const ADGameDescription *detectBestMatchingGame(193 EncapsulatedADGameDesc detectBestMatchingGame( 166 194 const Common::ADParams ¶ms 167 195 ) { 168 196 const ADGameDescription *agdDesc = 0; 197 EncapsulatedADGameDesc result; 169 198 Common::Language language = Common::UNK_LANG; 170 199 Common::Platform platform = Common::kPlatformUnknown; 171 200 … … 189 218 agdDesc = matches[0]; 190 219 } 191 220 192 if (agdDesc != 0) { 193 debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str()); 221 if (agdDesc != 0) { // Check if we found a match without fallback detection 222 result = EncapsulatedADGameDesc(agdDesc); 223 } else if (params.fallbackDetectFunc != NULL) { // Use fallback detector if there were no matches by other means 224 EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(NULL); 225 if (fallbackDesc.realDesc != 0 && (params.singleid != NULL || fallbackDesc.getGameID() == gameid)) { 226 result = fallbackDesc; // Found a fallback match 227 } 194 228 } 195 229 196 return agdDesc; 230 if (result.realDesc != 0) { 231 debug(2, "Running %s", toGameDescriptor(result, params.list).description().c_str()); 232 } 233 234 return result; 197 235 } 198 236 199 237 PluginError detectGameForEngineCreation( … … 241 279 } 242 280 } 243 281 282 // Use fallback detector if there were no matches by other means 283 if (params.fallbackDetectFunc != NULL) { 284 EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(&fslist); 285 if (fallbackDesc.realDesc != 0 && (params.singleid != NULL || fallbackDesc.getGameID() == gameid)) { 286 return kNoError; 287 } 288 } 289 244 290 return kNoGameDataFoundError; 245 291 } 246 292 … … 491 537 } 492 538 } 493 539 494 // If we still haven't got a match, try to use the fallback callback :-)495 if (matched.empty() && params.fallbackDetectFunc != 0) {496 matched = (*params.fallbackDetectFunc)(fslist);497 }498 499 540 return matched; 500 541 } 501 542 -
engines/touche/detection.cpp
124 124 namespace Touche { 125 125 126 126 bool ToucheEngine::detectGame() { 127 const Common::ADGameDescription *gd = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 127 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 128 const Common::ADGameDescription *gd = encapsulatedDesc.realDesc; 129 128 130 if (gd == 0) 129 131 return false; 130 132 -
engines/agos/detection.cpp
117 117 assert(engine); 118 118 const char *gameid = ConfMan.get("gameid").c_str(); 119 119 120 //const AGOSGameDescription gd = (const AGOSGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 120 //Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 121 //const AGOSGameDescription *gd = (const AGOSGameDescription *)(encapsulatedDesc.realDesc); 121 122 //if (gd == 0) { 122 123 // return kNoGameDataFoundError; 123 124 //} … … 154 155 namespace AGOS { 155 156 156 157 bool AGOSEngine::initGame() { 157 _gameDescription = (const AGOSGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 158 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 159 _gameDescription = (const AGOSGameDescription *)(encapsulatedDesc.realDesc); 160 158 161 return (_gameDescription != 0); 159 162 } 160 163 -
engines/cruise/detection.cpp
118 118 namespace Cruise { 119 119 120 120 bool CruiseEngine::initGame() { 121 _gameDescription = (const CRUISEGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 121 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 122 _gameDescription = (const CRUISEGameDescription *)(encapsulatedDesc.realDesc); 122 123 123 124 return (_gameDescription != 0); 124 125 } -
engines/agi/detection.cpp
1825 1825 { AD_TABLE_END_MARKER, 0, 0, 0, 0 } 1826 1826 }; 1827 1827 1828 static const AGIGameDescription fallbackDescs[] = { 1828 /** 1829 * The fallback game descriptor used by the AGI engine's fallbackDetector. 1830 * Contents of this struct are to be overwritten by the fallbackDetector. 1831 */ 1832 static AGIGameDescription g_fallbackDesc = { 1829 1833 { 1830 { 1831 "agi-fanmade", 1832 "Unknown v2 Game", 1833 AD_ENTRY1(0, 0), 1834 Common::UNK_LANG, 1835 Common::kPlatformPC, 1836 Common::ADGF_NO_FLAGS 1837 }, 1838 GID_FANMADE, 1839 GType_V2, 1840 GF_FANMADE, 1841 0x2917, 1834 "", // Not used by the fallback descriptor, it uses the EncapsulatedADGameDesc's gameid 1835 "", // Not used by the fallback descriptor, it uses the EncapsulatedADGameDesc's extra 1836 AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor 1837 Common::UNK_LANG, 1838 Common::kPlatformPC, 1839 Common::ADGF_NO_FLAGS 1842 1840 }, 1843 { 1844 { 1845 "agi-fanmade", 1846 "Unknown v2 AGIPAL Game", 1847 AD_ENTRY1(0, 0), 1848 Common::UNK_LANG, 1849 Common::kPlatformPC, 1850 Common::ADGF_NO_FLAGS 1851 }, 1852 GID_FANMADE, 1853 GType_V2, 1854 GF_FANMADE | GF_AGIPAL, 1855 0x2917, 1856 }, 1857 { 1858 { 1859 "agi-fanmade", 1860 "Unknown v3 Game", 1861 AD_ENTRY1(0, 0), 1862 Common::UNK_LANG, 1863 Common::kPlatformPC, 1864 Common::ADGF_NO_FLAGS 1865 }, 1866 GID_FANMADE, 1867 GType_V3, 1868 GF_FANMADE, 1869 0x3149, 1870 }, 1841 GID_FANMADE, 1842 GType_V2, 1843 GF_FANMADE, 1844 0x2917, 1871 1845 }; 1872 1846 1873 Common::ADGameDescList fallbackDetector(const FSList *fslist) { 1874 Common::String tstr; 1847 Common::EncapsulatedADGameDesc fallbackDetector(const FSList *fslist) { 1875 1848 typedef Common::HashMap<Common::String, int32, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> IntMap; 1876 1849 IntMap allFiles; 1877 Common::ADGameDescList matched; 1878 int matchedNum = -1; 1850 bool matchedUsingFilenames = false; 1851 Common::String gameid("agi-fanmade"), description, extra; // Set the defaults for gameid, description and extra 1852 FSList fslistCurrentDir; // Only used if fslist == NULL 1879 1853 1880 // TODO: 1881 // WinAGI produces *.wag file with interpreter version, game name 1882 // and other parameters. Add support for this once specs are known 1854 // Use the current directory for searching if fslist == NULL 1855 if (fslist == NULL) { 1856 FilesystemNode fsCurrentDir("."); 1857 fslistCurrentDir.push_back(fsCurrentDir); 1858 fslist = &fslistCurrentDir; 1859 } 1883 1860 1861 // Set the default values for the fallback descriptor's ADGameDescription part. 1862 g_fallbackDesc.desc.language = Common::UNK_LANG; 1863 g_fallbackDesc.desc.platform = Common::kPlatformPC; 1864 g_fallbackDesc.desc.flags = Common::ADGF_NO_FLAGS; 1865 // g_fallbackDesc.desc.gameid can't be modified so let it be 1866 // g_fallbackDesc.desc.extra can't be modified so let it be 1867 // g_fallbackDesc.desc.filesDescriptions shouldn't be modified here, it should always be AD_ENTRY1(0, 0) 1884 1868 1869 // Set default values for the fallback descriptor's AGIGameDescription part. 1870 g_fallbackDesc.gameID = GID_FANMADE; 1871 g_fallbackDesc.features = GF_FANMADE; 1872 g_fallbackDesc.version = 0x2917; 1873 // g_fallbackDesc.gameType is set later according to the AGI interpreter version number 1874 1885 1875 // First grab all filenames 1886 1876 for (FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) { 1887 1877 if (file->isDirectory()) continue; 1888 tstr = file->name(); 1889 tstr.toLowercase(); 1890 1891 allFiles[tstr] = true; 1878 Common::String filename = file->name(); 1879 filename.toLowercase(); 1880 allFiles[filename] = true; // Save the filename in a hash table 1892 1881 } 1893 1882 1894 // Now check for v21895 1883 if (allFiles.contains("logdir") && allFiles.contains("object") && 1896 1884 allFiles.contains("picdir") && allFiles.contains("snddir") && 1897 1885 allFiles.contains("viewdir") && allFiles.contains("vol.0") && 1898 allFiles.contains("words.tok")) { 1899 matchedNum = 0; 1886 allFiles.contains("words.tok")) { // Check for v2 1887 // The default AGI interpreter version 0x2917 is okay for v2 games 1888 // so we don't have to change it here. 1889 matchedUsingFilenames = true; 1900 1890 1901 // Check if it is AGIPAL 1902 if (allFiles.contains("pal.101")) 1903 matchedNum = 1; 1891 if (allFiles.contains("pal.101")) { // Check if it is AGIPAL 1892 description = "Unknown v2 AGIPAL Game"; 1893 g_fallbackDesc.features |= GF_AGIPAL; // Add AGIPAL feature flag 1894 } else { // Not AGIPAL so just plain v2 1895 description = "Unknown v2 Game"; 1896 } 1904 1897 } else { // Try v3 1905 1898 char name[8]; 1906 1899 … … 1911 1904 1912 1905 if (allFiles.contains("object") && allFiles.contains("words.tok") && 1913 1906 allFiles.contains(Common::String(name) + "dir")) { 1914 matchedNum = 2; 1907 matchedUsingFilenames = true; 1908 description = "Unknown v3 Game"; 1909 g_fallbackDesc.version = 0x3149; // Set the default AGI version for an AGI v3 game 1915 1910 break; 1916 1911 } 1917 1912 } 1918 1913 } 1919 1914 } 1920 1915 1921 if (matchedNum != -1) { 1922 matched.push_back(&fallbackDescs[matchedNum].desc); 1916 // Check that the AGI interpreter version is a supported one 1917 if (!(g_fallbackDesc.version >= 0x2000 && g_fallbackDesc.version < 0x4000)) { 1918 warning("Unsupported AGI interpreter version 0x%x in AGI's fallback detection. Using default 0x2917", g_fallbackDesc.version); 1919 g_fallbackDesc.version = 0x2917; 1920 } 1923 1921 1922 // Set game type (v2 or v3) according to the AGI interpreter version number 1923 if (g_fallbackDesc.version >= 0x2000 && g_fallbackDesc.version < 0x3000) 1924 g_fallbackDesc.gameType = GType_V2; 1925 else if (g_fallbackDesc.version >= 0x3000 && g_fallbackDesc.version < 0x4000) 1926 g_fallbackDesc.gameType = GType_V3; 1927 1928 // Check if we found a match with any of the fallback methods 1929 Common::EncapsulatedADGameDesc result; 1930 if (matchedUsingFilenames) { 1931 extra = description + " " + extra; // Let's combine the description and extra 1932 result = Common::EncapsulatedADGameDesc((const Common::ADGameDescription *)&g_fallbackDesc, gameid, extra); 1933 1924 1934 printf("Your game version has been detected using fallback matching as a\n"); 1925 printf("variant of %s (%s).\n", fallbackDescs[matchedNum].desc.gameid, fallbackDescs[matchedNum].desc.extra);1935 printf("variant of %s (%s).\n", result.getGameID(), result.getExtra()); 1926 1936 printf("If this is an original and unmodified version or new made Fanmade game,\n"); 1927 1937 printf("please report any, information previously printed by ScummVM to the team.\n"); 1938 1928 1939 } 1929 1940 1930 return matched;1941 return result; 1931 1942 } 1932 1943 1933 } 1944 } // End of namespace Agi 1934 1945 1935 1946 static const Common::ADParams detectionParams = { 1936 1947 // Pointer to ADGameDescription or its superset structure … … 1960 1971 namespace Agi { 1961 1972 1962 1973 bool AgiEngine::initGame() { 1963 _gameDescription = (const AGIGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 1974 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 1975 _gameDescription = (const AGIGameDescription *)(encapsulatedDesc.realDesc); 1976 1964 1977 return (_gameDescription != 0); 1965 1978 } 1966 1979 -
engines/kyra/detection.cpp
133 133 assert(engine); 134 134 const char *gameid = ConfMan.get("gameid").c_str(); 135 135 136 const KYRAGameDescription *gd = (const KYRAGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 136 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 137 const KYRAGameDescription *gd = (const KYRAGameDescription *)(encapsulatedDesc.realDesc); 138 137 139 if (gd == 0) { 138 140 // maybe add non md5 based detection again? 139 141 return kNoGameDataFoundError; -
engines/gob/detection.cpp
1150 1150 namespace Gob { 1151 1151 1152 1152 bool GobEngine::detectGame() { 1153 const GOBGameDescription *gd = (const GOBGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 1153 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 1154 const GOBGameDescription *gd = (const GOBGameDescription *)(encapsulatedDesc.realDesc); 1155 1154 1156 if (gd == 0) 1155 1157 return false; 1156 1158 -
engines/parallaction/detection.cpp
131 131 namespace Parallaction { 132 132 133 133 bool Parallaction::detectGame() { 134 _gameDescription = (const PARALLACTIONGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 134 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 135 _gameDescription = (const PARALLACTIONGameDescription *)(encapsulatedDesc.realDesc); 136 135 137 return (_gameDescription != 0); 136 138 } 137 139 -
engines/saga/detection.cpp
124 124 namespace Saga { 125 125 126 126 bool SagaEngine::initGame() { 127 _gameDescription = (const SAGAGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 127 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 128 _gameDescription = (const SAGAGameDescription *)(encapsulatedDesc.realDesc); 129 128 130 if (_gameDescription == 0) 129 131 return false; 130 132 -
engines/cine/detection.cpp
494 494 namespace Cine { 495 495 496 496 bool CineEngine::initGame() { 497 _gameDescription = (const CINEGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 497 Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); 498 _gameDescription = (const CINEGameDescription *)(encapsulatedDesc.realDesc); 499 498 500 return (_gameDescription != 0); 499 501 } 500 502