Ticket #8690: fallback-alternate.patch

File fallback-alternate.patch, 8.0 KB (added by fingolfin, 13 years ago)

Alternate (incomplete) patch, for common/ only, rest of original patch needs to be adapted

  • common/advancedDetector.h

     
    6464};
    6565
    6666/**
     67 * Encapsulates ADGameDescription and makes gameid and extra strings dynamic.
     68 * Used in fallback detection when dynamically creating string content.
     69 */
     70struct EncapsulatedADGameDesc : ADGameDescription {
     71        Common::String gameid;
     72        Common::String extra;
     73
     74        EncapsulatedADGameDesc() {
     75        }
     76        EncapsulatedADGameDesc(const ADGameDescription &realDesc,
     77                Common::String paramGameID = Common::String(""),
     78                Common::String paramExtra = Common::String(""))
     79                : ADGameDescription(realDesc), gameid(paramGameID), extra(paramExtra) {
     80        }
     81
     82        // Functions for getting the correct gameid and extra values from the struct
     83        const char *getGameID() const { return gameid.empty() ? ((ADGameDescription *)this)->gameid : gameid.c_str(); }
     84        const char *getExtra() const { return extra.empty() ? ((ADGameDescription *)this)->extra : extra.c_str(); }
     85};
     86
     87/**
    6788 * A list of pointers to ADGameDescription structs (or subclasses thereof).
    6889 */
    6990typedef Array<const ADGameDescription*> ADGameDescList;
     
    175196         * @note The fslist parameter may be 0 -- in that case, it is assumed
    176197         *       that the callback searchs the current directory.
    177198         *
     199         * @note You need to handle deleting the returned pointer if it's not NULL.
     200         *       You don't need to delete the memory pointed to by the realDesc
     201         *       pointer inside the struct though because it should be statically
     202         *       allocated.
     203         *
     204         * @return A pointer to a single EncapsulatedADGameDesc if there was a
     205         *         match, otherwise NULL.
     206         *
    178207         * @todo
    179208         */
    180         ADGameDescList (*fallbackDetectFunc)(const FSList *fslist);
     209        EncapsulatedADGameDesc (*fallbackDetectFunc)(const FSList *fslist);
    181210
    182211        /**
    183212         * A bitmask of flags which can be used to configure the behavior
     
    206235// FIXME/TODO: Rename this function to something more sensible.
    207236GameList detectAllGames(const FSList &fslist, const Common::ADParams &params);
    208237
    209 // FIXME/TODO: Rename this function to something more sensible.
    210 const ADGameDescription *detectBestMatchingGame(const Common::ADParams &params);
     238/**
     239 * Detect the best matching game.
     240 *
     241 * FIXME/TODO: Rename this function to something more sensible.
     242 *
     243 * @note You need to handle deleting the returned pointer if it's not NULL.
     244 *       You don't need to delete the memory pointed to by the realDesc
     245 *       pointer inside the struct though because it should be statically
     246 *       allocated.
     247 */
     248EncapsulatedADGameDesc detectBestMatchingGame(const Common::ADParams &params);
    211249
    212250// FIXME/TODO: Rename this function to something more sensible.
    213251// Only used by ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_FUNC
  • common/advancedDetector.cpp

     
    110110        return gd;
    111111}
    112112
     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.
     116static 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        GameDescriptor gd(g.getGameID(), title, g.language, g.platform);
     126        gd.updateDesc(g.getExtra());
     127        return gd;
     128}
     129
    113130/**
    114131 * Generate a preferred target value as
    115132 *   GAMEID-PLAFORM-LANG
     
    139156        const Common::ADParams &params
    140157        ) {
    141158        ADGameDescList matches = detectGame(&fslist, params, Common::UNK_LANG, Common::kPlatformUnknown);
    142 
    143159        GameList detectedGames;
    144         for (uint i = 0; i < matches.size(); i++) {
    145                 GameDescriptor desc(toGameDescriptor(*matches[i], params.list));
     160        EncapsulatedADGameDesc fallbackDesc;
    146161
     162        // Use fallback detector if there were no matches by other means
     163        if (matches.empty() && params.fallbackDetectFunc != NULL) {
     164                fallbackDesc = (*params.fallbackDetectFunc)(&fslist);
     165                if (!fallbackDesc.gameid.empty()) detectedGames.push_back(toGameDescriptor(fallbackDesc, params.list));
     166        } else for (uint i = 0; i < matches.size(); i++) // Otherwise use the found matches
     167                detectedGames.push_back(toGameDescriptor(*matches[i], params.list));
     168
     169        for (uint i = 0; i < detectedGames.size(); i++) {
    147170                if (params.singleid != NULL) {
    148                         desc["preferredtarget"] = desc["gameid"];
    149                         desc["gameid"] = params.singleid;
     171                        detectedGames[i]["preferredtarget"] = detectedGames[i]["gameid"];
     172                        detectedGames[i]["gameid"] = params.singleid;
    150173                }
    151174
    152175                if (params.flags & kADFlagAugmentPreferredTarget) {
    153                         if (!desc.contains("preferredtarget"))
    154                                 desc["preferredtarget"] = desc["gameid"];
     176                        if (!detectedGames[i].contains("preferredtarget"))
     177                                detectedGames[i]["preferredtarget"] = detectedGames[i]["gameid"];
    155178
    156                         desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], matches[i]);
     179                        if (!matches.empty()) { // If found a match or matches without fallback detection
     180                                detectedGames[i]["preferredtarget"] = generatePreferredTarget(detectedGames[i]["preferredtarget"], matches[i]);
     181                        } else if (!fallbackDesc.gameid.empty()) { // If found match with the fallback detection
     182                                // This assumes that generatePreferredTarget doesn't need gameid or extra fields from the fallbackDesc,
     183                                // so we can just give it the ADGameDescription from inside the *fallbackDesc.
     184                                detectedGames[i]["preferredtarget"] = generatePreferredTarget(detectedGames[i]["preferredtarget"], &fallbackDesc);
     185                        }
    157186                }
    158 
    159                 detectedGames.push_back(desc);
    160187        }
    161188
    162189        return detectedGames;
    163190}
    164191
    165 const ADGameDescription *detectBestMatchingGame(
     192EncapsulatedADGameDesc detectBestMatchingGame(
    166193        const Common::ADParams &params
    167194        ) {
    168         const ADGameDescription *agdDesc = 0;
     195        const ADGameDescription *agdDesc = NULL;
     196        EncapsulatedADGameDesc result;
    169197        Common::Language language = Common::UNK_LANG;
    170198        Common::Platform platform = Common::kPlatformUnknown;
    171199
     
    176204
    177205        Common::String gameid = ConfMan.get("gameid");
    178206
    179         ADGameDescList matches = detectGame(0, params, language, platform);
     207        ADGameDescList matches = detectGame(NULL, params, language, platform);
    180208
    181209        if (params.singleid == NULL) {
    182210                for (uint i = 0; i < matches.size(); i++) {
     
    189217                agdDesc = matches[0];
    190218        }
    191219
    192         if (agdDesc != 0) {
    193                 debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str());
     220        // Use fallback detector if there were no matches by other means
     221        if (matches.empty() && params.fallbackDetectFunc != NULL) {
     222                EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(NULL);
     223                if (!fallbackDesc.gameid.empty() && (params.singleid != NULL || fallbackDesc.getGameID() == gameid)) {
     224                        result = fallbackDesc; // Found a fallback match
     225                }
    194226        }
    195227
    196         return agdDesc;
     228        // If we found a match without fallback detection
     229        // then let's convert it to this function's return format
     230        if (agdDesc != NULL) {
     231                result = EncapsulatedADGameDesc(*agdDesc);
     232        }
     233
     234        if (!result.gameid.empty()) {
     235                debug(2, "Running %s", toGameDescriptor(result, params.list).description().c_str());
     236        }
     237
     238        return result;
    197239}
    198240
    199241PluginError detectGameForEngineCreation(
     
    236278                }
    237279        }
    238280
     281        // Use fallback detector if there were no matches by other means
     282        if (matches.empty() && params.fallbackDetectFunc != NULL) {
     283                EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(&fslist);
     284                if (!fallbackDesc.gameid.empty()) {
     285                        bool foundFallbackMatch = (params.singleid != NULL || fallbackDesc.getGameID() == gameid);
     286                        if (foundFallbackMatch) return kNoError;
     287                }
     288        }
     289
    239290        return kNoGameDataFoundError;
    240291}
    241292
     
    486537                }
    487538        }
    488539
    489         // If we still haven't got a match, try to use the fallback callback :-)
    490         if (matched.empty() && params.fallbackDetectFunc != 0) {
    491                 matched = (*params.fallbackDetectFunc)(fslist);
    492         }
    493 
    494540        return matched;
    495541}
    496542