diff options
author | Matthew Hoops | 2011-06-14 16:18:33 -0400 |
---|---|---|
committer | Matthew Hoops | 2011-06-14 16:21:39 -0400 |
commit | 4926c41e01a46735747930b09cc924ecd826a215 (patch) | |
tree | 8832a663ade5b4baed0e3b426d5f72e482a12c30 /engines | |
parent | 5e7acc83b7ad363014e2a6681bcba22c9bbd9c07 (diff) | |
parent | e826aaab39f02360c5fa8f249ec6b788a903b948 (diff) | |
download | scummvm-rg350-4926c41e01a46735747930b09cc924ecd826a215.tar.gz scummvm-rg350-4926c41e01a46735747930b09cc924ecd826a215.tar.bz2 scummvm-rg350-4926c41e01a46735747930b09cc924ecd826a215.zip |
Merge remote branch 'upstream/master' into pegasus
Diffstat (limited to 'engines')
66 files changed, 697 insertions, 562 deletions
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index b0a304aad9..7ae4d7718a 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -32,68 +32,7 @@ #include "common/translation.h" #include "engines/advancedDetector.h" - -void AdvancedMetaEngine::upgradeTargetIfNecessary() const { - if (params.obsoleteList == 0) - return; - - Common::String gameid = ConfMan.get("gameid"); - - for (const ADObsoleteGameID *o = params.obsoleteList; o->from; ++o) { - if (gameid.equalsIgnoreCase(o->from)) { - gameid = o->to; - ConfMan.set("gameid", gameid); - - if (o->platform != Common::kPlatformUnknown) - ConfMan.set("platform", Common::getPlatformCode(o->platform)); - - warning("Target upgraded from %s to %s", o->from, o->to); - - // WORKAROUND: Fix for bug #1719463: "DETECTOR: Launching - // undefined target adds launcher entry" - if (ConfMan.hasKey("id_came_from_command_line")) { - warning("Target came from command line. Skipping save"); - } else { - ConfMan.flushToDisk(); - } - break; - } - } -} - -namespace AdvancedDetector { - -GameDescriptor findGameID( - const char *gameid, - const PlainGameDescriptor *gameDescriptors, - const ADObsoleteGameID *obsoleteList - ) { - // First search the list of supported gameids for a match. - const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, gameDescriptors); - if (g) - return GameDescriptor(*g); - - // If we didn't find the gameid in the main list, check if it - // is an obsolete game id. - if (obsoleteList != 0) { - const ADObsoleteGameID *o = obsoleteList; - while (o->from) { - if (0 == scumm_stricmp(gameid, o->from)) { - g = findPlainGameDescriptor(o->to, gameDescriptors); - if (g && g->description) - return GameDescriptor(gameid, "Obsolete game ID (" + Common::String(g->description) + ")"); - else - return GameDescriptor(gameid, "Obsolete game ID"); - } - o++; - } - } - - // No match found - return GameDescriptor(); -} - -} // End of namespace AdvancedDetector +#include "engines/obsolete.h" static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGameDescriptor *sg) { const char *title = 0; @@ -146,9 +85,9 @@ static Common::String generatePreferredTarget(const Common::String &id, const AD } void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const { - if (params.singleid != NULL) { + if (_singleid != NULL) { desc["preferredtarget"] = desc["gameid"]; - desc["gameid"] = params.singleid; + desc["gameid"] = _singleid; } if (!desc.contains("preferredtarget")) @@ -156,10 +95,10 @@ void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGame desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], realDesc); - if (params.flags & kADFlagUseExtraAsHint) + if (_flags & kADFlagUseExtraAsHint) desc["extra"] = realDesc->extra; - desc.setGUIOptions(realDesc->guioptions | params.guioptions); + desc.setGUIOptions(realDesc->guioptions | _guioptions); desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language)); if (realDesc->flags & ADGF_ADDENGLISH) @@ -167,7 +106,7 @@ void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGame } bool cleanupPirated(ADGameDescList &matched) { - // OKay, now let's sense presense of pirated games + // OKay, now let's sense presence of pirated games if (!matched.empty()) { for (uint j = 0; j < matched.size();) { if (matched[j]->flags & ADGF_PIRATED) @@ -178,9 +117,7 @@ bool cleanupPirated(ADGameDescList &matched) { // We ruled out all variants and now have nothing if (matched.empty()) { - warning("Illegitimate game copy detected. We give no support in such cases %d", matched.size()); - return true; } } @@ -190,24 +127,32 @@ bool cleanupPirated(ADGameDescList &matched) { GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { - ADGameDescList matches = detectGame(fslist, Common::UNK_LANG, Common::kPlatformUnknown, ""); + ADGameDescList matches; GameList detectedGames; + FileMap allFiles; - if (cleanupPirated(matches)) + if (fslist.empty()) return detectedGames; + // Compose a hashmap of all files in fslist. + composeFileHashMap(allFiles, fslist, (_maxScanDepth == 0 ? 1 : _maxScanDepth)); + + // Run the detector on this + matches = detectGame(fslist.begin()->getParent(), allFiles, Common::UNK_LANG, Common::kPlatformUnknown, ""); + if (matches.empty()) { // Use fallback detector if there were no matches by other means - const ADGameDescription *fallbackDesc = fallbackDetect(fslist); + const ADGameDescription *fallbackDesc = fallbackDetect(allFiles, fslist); if (fallbackDesc != 0) { - GameDescriptor desc(toGameDescriptor(*fallbackDesc, params.gameDescriptors)); + GameDescriptor desc(toGameDescriptor(*fallbackDesc, _gameids)); updateGameDescriptor(desc, fallbackDesc); detectedGames.push_back(desc); } } else { // Otherwise use the found matches + cleanupPirated(matches); for (uint i = 0; i < matches.size(); i++) { - GameDescriptor desc(toGameDescriptor(*matches[i], params.gameDescriptors)); + GameDescriptor desc(toGameDescriptor(*matches[i], _gameids)); updateGameDescriptor(desc, matches[i]); detectedGames.push_back(desc); } @@ -218,7 +163,6 @@ GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(engine); - upgradeTargetIfNecessary(); const ADGameDescription *agdDesc = 0; Common::Language language = Common::UNK_LANG; @@ -229,9 +173,10 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) language = Common::parseLanguage(ConfMan.get("language")); if (ConfMan.hasKey("platform")) platform = Common::parsePlatform(ConfMan.get("platform")); - if (params.flags & kADFlagUseExtraAsHint) + if (_flags & kADFlagUseExtraAsHint) { if (ConfMan.hasKey("extra")) extra = ConfMan.get("extra"); + } Common::String gameid = ConfMan.get("gameid"); @@ -261,12 +206,21 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) return Common::kNoGameDataFoundError; } - ADGameDescList matches = detectGame(files, language, platform, extra); + if (files.empty()) + return Common::kNoGameDataFoundError; + + // Compose a hashmap of all files in fslist. + FileMap allFiles; + composeFileHashMap(allFiles, files, (_maxScanDepth == 0 ? 1 : _maxScanDepth)); + + // Run the detector on this + ADGameDescList matches = detectGame(files.begin()->getParent(), allFiles, language, platform, extra); if (cleanupPirated(matches)) return Common::kNoGameDataFoundError; - if (params.singleid == NULL) { + if (_singleid == NULL) { + // Find the first match with correct gameid. for (uint i = 0; i < matches.size(); i++) { if (matches[i]->gameid == gameid) { agdDesc = matches[i]; @@ -279,11 +233,11 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) if (agdDesc == 0) { // Use fallback detector if there were no matches by other means - agdDesc = fallbackDetect(files); + agdDesc = fallbackDetect(allFiles, files); if (agdDesc != 0) { // Seems we found a fallback match. But first perform a basic // sanity check: the gameid must match. - if (params.singleid == NULL && agdDesc->gameid != gameid) + if (_singleid == NULL && agdDesc->gameid != gameid) agdDesc = 0; } } @@ -297,10 +251,10 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) if (agdDesc->flags & ADGF_ADDENGLISH) lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY); - Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions, lang); + Common::updateGameGUIOptions(agdDesc->guioptions | _guioptions, lang); - debug(2, "Running %s", toGameDescriptor(*agdDesc, params.gameDescriptors).description().c_str()); + debug(2, "Running %s", toGameDescriptor(*agdDesc, _gameids).description().c_str()); if (!createInstance(syst, engine, agdDesc)) return Common::kNoGameDataFoundError; else @@ -334,7 +288,7 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz g_system->logMessage(LogMessageType::kInfo, report.c_str()); } -void AdvancedMetaEngine::composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) const { +void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth) const { if (depth <= 0) return; @@ -345,11 +299,11 @@ void AdvancedMetaEngine::composeFileHashMap(const Common::FSList &fslist, FileMa if (file->isDirectory()) { Common::FSList files; - if (!params.directoryGlobs) + if (!_directoryGlobs) continue; bool matched = false; - for (const char * const *glob = params.directoryGlobs; *glob; glob++) + for (const char * const *glob = _directoryGlobs; *glob; glob++) if (file->getName().matchString(*glob, true)) { matched = true; break; @@ -361,7 +315,7 @@ void AdvancedMetaEngine::composeFileHashMap(const Common::FSList &fslist, FileMa if (!file->getChildren(files, Common::FSNode::kListAll)) continue; - composeFileHashMap(files, allFiles, depth - 1); + composeFileHashMap(allFiles, files, depth - 1); } Common::String tstr = file->getName(); @@ -374,25 +328,18 @@ void AdvancedMetaEngine::composeFileHashMap(const Common::FSList &fslist, FileMa } } -ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Common::Language language, Common::Platform platform, const Common::String &extra) const { - FileMap allFiles; +ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const { SizeMD5Map filesSizeMD5; const ADGameFileDescription *fileDesc; const ADGameDescription *g; const byte *descPtr; - if (fslist.empty()) - return ADGameDescList(); - Common::FSNode parent = fslist.begin()->getParent(); debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); - // First we compose a hashmap of all files in fslist. - composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth)); - - // Check which files are included in some ADGameDescription *and* present - // in fslist. Compute MD5s and file sizes for these files. - for (descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize) { + // Check which files are included in some ADGameDescription *and* are present. + // Compute MD5s and file sizes for these files. + for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += _descItemSize) { g = (const ADGameDescription *)descPtr; for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { @@ -409,7 +356,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Comm Common::MacResManager macResMan; if (macResMan.open(parent, fname)) { - tmp.md5 = macResMan.computeResForkMD5AsString(params.md5Bytes); + tmp.md5 = macResMan.computeResForkMD5AsString(_md5Bytes); tmp.size = macResMan.getResForkDataSize(); debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str()); filesSizeMD5[fname] = tmp; @@ -422,7 +369,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Comm if (testFile.open(allFiles[fname])) { tmp.size = (int32)testFile.size(); - tmp.md5 = Common::computeStreamMD5AsString(testFile, params.md5Bytes); + tmp.md5 = Common::computeStreamMD5AsString(testFile, _md5Bytes); } else { tmp.size = -1; } @@ -440,7 +387,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Comm // MD5 based matching uint i; - for (i = 0, descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize, ++i) { + for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += _descItemSize, ++i) { g = (const ADGameDescription *)descPtr; bool fileMissing = false; @@ -452,7 +399,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Comm continue; } - if ((params.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra) + if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra) continue; bool allFilesPresent = true; @@ -525,22 +472,20 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Comm } // Filename based fallback - if (params.fileBasedFallback != 0) - matched = detectGameFilebased(allFiles); } return matched; } -ADGameDescList AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles) const { +const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const { const ADFileBasedFallback *ptr; const char* const* filenames; int maxNumMatchedFiles = 0; const ADGameDescription *matchedDesc = 0; - for (ptr = params.fileBasedFallback; ptr->desc; ++ptr) { - const ADGameDescription *agdesc = (const ADGameDescription *)ptr->desc; + for (ptr = fileBasedFallback; ptr->desc; ++ptr) { + const ADGameDescription *agdesc = ptr->desc; int numMatchedFiles = 0; bool fileMissing = false; @@ -566,58 +511,45 @@ ADGameDescList AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles) } } - ADGameDescList matched; - - if (matchedDesc) { // We got a match - matched.push_back(matchedDesc); - if (params.flags & kADFlagPrintWarningOnFileBasedFallback) { - Common::String report = Common::String::format(_("Your game version has been detected using " - "filename matching as a variant of %s."), matchedDesc->gameid); - report += "\n"; - report += _("If this is an original and unmodified version, please report any"); - report += "\n"; - report += _("information previously printed by ScummVM to the team."); - report += "\n"; - g_system->logMessage(LogMessageType::kInfo, report.c_str()); - } - } - - return matched; + return matchedDesc; } GameList AdvancedMetaEngine::getSupportedGames() const { - if (params.singleid != NULL) { + if (_singleid != NULL) { GameList gl; - const PlainGameDescriptor *g = params.gameDescriptors; + const PlainGameDescriptor *g = _gameids; while (g->gameid) { - if (0 == scumm_stricmp(params.singleid, g->gameid)) { + if (0 == scumm_stricmp(_singleid, g->gameid)) { gl.push_back(GameDescriptor(g->gameid, g->description)); return gl; } g++; } - error("Engine %s doesn't have its singleid specified in ids list", params.singleid); + error("Engine %s doesn't have its singleid specified in ids list", _singleid); } - return GameList(params.gameDescriptors); + return GameList(_gameids); } GameDescriptor AdvancedMetaEngine::findGame(const char *gameid) const { - return AdvancedDetector::findGameID(gameid, params.gameDescriptors, params.obsoleteList); + // First search the list of supported gameids for a match. + const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, _gameids); + if (g) + return GameDescriptor(*g); + + // No match found + return GameDescriptor(); } -AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameDescriptors) { - params.descs = (const byte *)descs; - params.descItemSize = descItemSize; - params.md5Bytes = 5000; - params.gameDescriptors = gameDescriptors; - params.obsoleteList = NULL; - params.singleid = NULL; - params.fileBasedFallback = NULL; - params.flags = 0; - params.guioptions = Common::GUIO_NONE; - params.depth = 1; - params.directoryGlobs = NULL; +AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameids) + : _gameDescriptors((const byte *)descs), _descItemSize(descItemSize), _gameids(gameids) { + + _md5Bytes = 5000; + _singleid = NULL; + _flags = 0; + _guioptions = Common::GUIO_NONE; + _maxScanDepth = 1; + _directoryGlobs = NULL; } diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index e5922bea4a..5360d23ac1 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ + #ifndef ENGINES_ADVANCED_DETECTOR_H #define ENGINES_ADVANCED_DETECTOR_H @@ -29,28 +30,45 @@ class Error; class FSList; } - +/** + * A record describing a file to be matched for detecting a specific game + * variant. A list of such records is used inside every ADGameDescription to + * enable detection. + */ struct ADGameFileDescription { - const char *fileName; - uint16 fileType; // Optional. Not used during detection, only by engines. - const char *md5; // Optional. May be NULL. - int32 fileSize; // Optional. Set to -1 to ignore. + const char *fileName; ///< Name of described file. + uint16 fileType; ///< Optional. Not used during detection, only by engines. + const char *md5; ///< MD5 of (the beginning of) the described file. Optional. Set to NULL to ignore. + int32 fileSize; ///< Size of the described file. Set to -1 to ignore. }; +/** + * A shortcut to produce an empty ADGameFileDescription record. Used to mark + * the end of a list of these. + */ #define AD_LISTEND {NULL, 0, NULL, 0} +/** + * A shortcut to produce a list of ADGameFileDescription records with only one + * record that contains just a filename with an MD5, and no file size. + */ #define AD_ENTRY1(f, x) {{ f, 0, x, -1}, AD_LISTEND} + +/** + * A shortcut to produce a list of ADGameFileDescription records with only one + * record that contains just a filename with an MD5, plus a file size. + */ #define AD_ENTRY1s(f, x, s) {{ f, 0, x, s}, AD_LISTEND} enum ADGameFlags { ADGF_NO_FLAGS = 0, - ADGF_PIRATED = (1 << 23), // flag to designate well known pirated versions with cracks - ADGF_ADDENGLISH = (1 << 24), // always add English as language option - ADGF_MACRESFORK = (1 << 25), // the md5 for this entry will be calculated from the resource fork - ADGF_USEEXTRAASTITLE = (1 << 26), // Extra field value will be used as main game title, not gameid - ADGF_DROPLANGUAGE = (1 << 28), // don't add language to gameid - ADGF_CD = (1 << 29), // add "-cd" to gameid - ADGF_DEMO = (1 << 30) // add "-demo" to gameid + ADGF_PIRATED = (1 << 23), ///< flag to designate well known pirated versions with cracks + ADGF_ADDENGLISH = (1 << 24), ///< always add English as language option + ADGF_MACRESFORK = (1 << 25), ///< the md5 for this entry will be calculated from the resource fork + ADGF_USEEXTRAASTITLE = (1 << 26), ///< Extra field value will be used as main game title, not gameid + ADGF_DROPLANGUAGE = (1 << 28), ///< don't add language to gameid + ADGF_CD = (1 << 29), ///< add "-cd" to gameid + ADGF_DEMO = (1 << 30) ///< add "-demo" to gameid }; struct ADGameDescription { @@ -73,7 +91,7 @@ struct ADGameDescription { /** * A list of pointers to ADGameDescription structs (or subclasses thereof). */ -typedef Common::Array<const ADGameDescription*> ADGameDescList; +typedef Common::Array<const ADGameDescription *> ADGameDescList; /** * End marker for a table of ADGameDescription structs. Use this to @@ -82,19 +100,12 @@ typedef Common::Array<const ADGameDescription*> ADGameDescList; #define AD_TABLE_END_MARKER \ { NULL, NULL, { { NULL, 0, NULL, 0 } }, Common::UNK_LANG, Common::kPlatformUnknown, ADGF_NO_FLAGS, Common::GUIO_NONE } - -struct ADObsoleteGameID { - const char *from; - const char *to; - Common::Platform platform; -}; - struct ADFileBasedFallback { /** * Pointer to an ADGameDescription or subclass thereof which will get * returned if there's a detection match. */ - const void *desc; + const ADGameDescription *desc; /** * A zero-terminated list of filenames used for matching. All files in @@ -106,134 +117,90 @@ struct ADFileBasedFallback { enum ADFlags { /** - * Warn user about new variant if his version was detected with fallback - */ - kADFlagPrintWarningOnFileBasedFallback = (1 << 1), - /** * Store value of extra field in config file, and use it as a hint * on subsequent runs. Could be used when there is no way to autodetect * game (when more than one game sits in same directory), and user picks * up a variant manually. + * In addition, this is useful if two variants of a game sharing the same + * gameid are contained in a single directory. */ - kADFlagUseExtraAsHint = (1 << 2) + kADFlagUseExtraAsHint = (1 << 0) }; + /** - * A structure containing all parameters for the AdvancedDetector. - * Typically, an engine will have a single instance of this which is - * used by its AdvancedMetaEngine subclass as a parameter to the - * primary AdvancedMetaEngine constructor. + * A MetaEngine implementation based around the advanced detector code. */ -struct ADParams { +class AdvancedMetaEngine : public MetaEngine { +protected: /** * Pointer to an array of objects which are either ADGameDescription * or superset structures (i.e. start with an ADGameDescription member. * The list is terminated by an entry with a gameid equal to 0 * (see AD_TABLE_END_MARKER). */ - const byte *descs; + const byte *_gameDescriptors; /** * The size of a single entry of the above descs array. Always * must be >= sizeof(ADGameDescription). */ - uint descItemSize; - - /** - * The number of bytes to compute MD5 sum for. The AdvancedDetector - * is primarily based on computing and matching MD5 checksums of files. - * Since doing that for large files can be slow, it can be restricted - * to a subset of all files. - * Typically this will be set to something between 5 and 50 kilobyte, - * but arbitrary non-zero values are possible. - */ - uint md5Bytes; + const uint _descItemSize; /** * A list of all gameids (and their corresponding descriptions) supported * by this engine. */ - const PlainGameDescriptor *gameDescriptors; + const PlainGameDescriptor *_gameids; /** - * Structure for autoupgrading obsolete targets (optional). - * - * @todo Properly explain this. + * The number of bytes to compute MD5 sum for. The AdvancedDetector + * is primarily based on computing and matching MD5 checksums of files. + * Since doing that for large files can be slow, it can be restricted + * to a subset of all files. + * Typically this will be set to something between 5 and 50 kilobyte, + * but arbitrary non-zero values are possible. The default is 5000. */ - const ADObsoleteGameID *obsoleteList; + uint _md5Bytes; /** * Name of single gameid (optional). * * @todo Properly explain this -- what does it do? */ - const char *singleid; - - /** - * List of files for file-based fallback detection (optional). - * This is used if the regular MD5 based detection failed to - * detect anything. - * As usual this list is terminated by an all-zero entry. - * - * @todo Properly explain this - */ - const ADFileBasedFallback *fileBasedFallback; + const char *_singleid; /** * A bitmask of flags which can be used to configure the behavior * of the AdvancedDetector. Refer to ADFlags for a list of flags * that can be ORed together and passed here. */ - uint32 flags; + uint32 _flags; /** * A bitmask of game GUI options which will be added to each * entry in addition to per-game options. Refer to GameGUIOption * enum for the list. */ - uint32 guioptions; + uint32 _guioptions; /** - * Maximum depth of directories to look up + * Maximum depth of directories to look up. * If set to 0, the depth is 1 level */ - uint32 depth; + uint32 _maxScanDepth; /** * Case-insensitive list of directory globs which could be used for - * going deeper int directory structure. + * going deeper into the directory structure. * @see String::matchString() method for format description. * * @note Last item must be 0 */ - const char * const *directoryGlobs; -}; + const char * const *_directoryGlobs; - -namespace AdvancedDetector { - -/** - * Scan through the game descriptors specified in params and search for - * 'gameid' in there. If a match is found, returns a GameDescriptor - * with gameid and description set. - */ -GameDescriptor findGameID( - const char *gameid, - const PlainGameDescriptor *gameDescriptors, - const ADObsoleteGameID *obsoleteList = 0 - ); - -} // End of namespace AdvancedDetector - -/** - * A MetaEngine implementation based around the advanced detector code. - */ -class AdvancedMetaEngine : public MetaEngine { -protected: - ADParams params; public: - AdvancedMetaEngine(const ADParams &dp) : params(dp) {} - AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameDescriptors); + AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameids); /** * Returns list of targets supported by the engine. @@ -251,48 +218,50 @@ protected: // To be implemented by subclasses virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const = 0; + typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap; + /** * An (optional) generic fallback detect function which is invoked - * if both the regular MD5 based detection as well as the file - * based fallback failed to detect anything. + * if the regular MD5 based detection failed to detect anything. */ - virtual const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const { + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { return 0; } protected: - typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap; - /** * Detect games in specified directory. * Parameters language and platform are used to pass on values - * specified by the user. I.e. this is used to restrict search scope. + * specified by the user. This is used to restrict search scope. * - * @param fslist FSList to scan or NULL for scanning all specified - * default directories. - * @param language restrict results to specified language only - * @param platform restrict results to specified platform only - * @return list of ADGameDescription (or subclass) pointers corresponding to matched games + * @param allFiles list of all present files, as computed by composeFileHashMap + * @param language restrict results to specified language + * @param platform restrict results to specified platform + * @param extra restrict results to specified extra string (only if kADFlagUseExtraAsHint is set) + * @return list of ADGameDescription pointers corresponding to matched games */ - ADGameDescList detectGame(const Common::FSList &fslist, Common::Language language, Common::Platform platform, const Common::String &extra) const; + ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const; /** - * Check for each ADFileBasedFallback record whether all files listed - * in it are present. If multiple pass this test, we pick the one with - * the maximal number of matching files. In case of a tie, the entry - * coming first in the list is chosen. + * Iterates over all ADFileBasedFallback records inside fileBasedFallback. + * This then returns the record (or rather, the ADGameDescription + * contained in it) for which all files described by it are present, and + * among those the one with the maximal number of matching files. + * In case of a tie, the entry coming first in the list is chosen. + * + * @param allFiles a map describing all present files + * @param fileBasedFallback a list of ADFileBasedFallback records, zero-terminated */ - ADGameDescList detectGameFilebased(const FileMap &allFiles) const; - - void upgradeTargetIfNecessary() const; + const ADGameDescription *detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const; + // TODO void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const; /** * Compose a hashmap of all files in fslist. * Includes nifty stuff like removing trailing dots and ignoring case. */ - void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) const; + void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth) const; }; #endif diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index b0e055edcc..21ff5deb2c 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -137,8 +137,8 @@ class AgiMetaEngine : public AdvancedMetaEngine { public: AgiMetaEngine() : AdvancedMetaEngine(Agi::gameDescriptions, sizeof(Agi::AGIGameDescription), agiGames) { - params.singleid = "agi"; - params.guioptions = Common::GUIO_NOSPEECH; + _singleid = "agi"; + _guioptions = Common::GUIO_NOSPEECH; } virtual const char *getName() const { @@ -155,7 +155,7 @@ public: virtual void removeSaveState(const char *target, int slot) const; SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; - const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const; + const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; }; bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -293,7 +293,7 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl return SaveStateDescriptor(); } -const ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSList &fslist) const { +const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const { typedef Common::HashMap<Common::String, int32> IntMap; IntMap allFiles; bool matchedUsingFilenames = false; diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index eb78ca3d9b..d9a585bd05 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -29,6 +29,7 @@ #include "common/file.h" #include "common/system.h" #include "common/textconsole.h" +#include "common/translation.h" #include "graphics/cursorman.h" #include "graphics/palette.h" @@ -540,10 +541,8 @@ MoviePlayer *makeMoviePlayer(AGOSEngine_Feeble *vm, const char *name) { return new MoviePlayerSMK(vm, baseName); } - char buf[60]; - - sprintf(buf, "Cutscene file '%s' not found!", baseName); - GUI::MessageDialog dialog(buf, "OK"); + Common::String buf = Common::String::format(_("Cutscene file '%s' not found!"), baseName); + GUI::MessageDialog dialog(buf, _("OK")); dialog.runModal(); return NULL; diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index dbd1743304..2be888b92a 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -23,6 +23,7 @@ #include "base/plugins.h" #include "engines/advancedDetector.h" +#include "engines/obsolete.h" #include "common/config-manager.h" #include "common/savefile.h" #include "common/system.h" @@ -48,7 +49,7 @@ struct AGOSGameDescription { * corresponding new target and platform combination. * */ -static const ADObsoleteGameID obsoleteGameIDsTable[] = { +static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = { {"simon1acorn", "simon1", Common::kPlatformAcorn}, {"simon1amiga", "simon1", Common::kPlatformAmiga}, {"simon1cd32", "simon1", Common::kPlatformAmiga}, @@ -92,10 +93,13 @@ using namespace AGOS; class AgosMetaEngine : public AdvancedMetaEngine { public: AgosMetaEngine() : AdvancedMetaEngine(AGOS::gameDescriptions, sizeof(AGOS::AGOSGameDescription), agosGames) { - params.obsoleteList = obsoleteGameIDsTable; - params.guioptions = Common::GUIO_NOLAUNCHLOAD; - params.depth = 2; - params.directoryGlobs = directoryGlobs; + _guioptions = Common::GUIO_NOLAUNCHLOAD; + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; + } + + virtual GameDescriptor findGame(const char *gameid) const { + return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable); } virtual const char *getName() const { @@ -107,7 +111,13 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; + + virtual Common::Error createInstance(OSystem *syst, Engine **engine) const { + Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable); + return AdvancedMetaEngine::createInstance(syst, engine); + } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; }; diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index 89c81c2599..cffeb29418 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -23,6 +23,7 @@ #include "base/plugins.h" #include "engines/advancedDetector.h" +#include "engines/obsolete.h" #include "common/system.h" #include "common/textconsole.h" @@ -52,7 +53,7 @@ static const PlainGameDescriptor cineGames[] = { {0, 0} }; -static const ADObsoleteGameID obsoleteGameIDsTable[] = { +static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = { {"fw", "cine", Common::kPlatformUnknown}, {"os", "cine", Common::kPlatformUnknown}, {0, 0, Common::kPlatformUnknown} @@ -63,9 +64,12 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { class CineMetaEngine : public AdvancedMetaEngine { public: CineMetaEngine() : AdvancedMetaEngine(Cine::gameDescriptions, sizeof(Cine::CINEGameDescription), cineGames) { - params.obsoleteList = obsoleteGameIDsTable; - params.singleid = "cine"; - params.guioptions = Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI; + _singleid = "cine"; + _guioptions = Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI; + } + + virtual GameDescriptor findGame(const char *gameid) const { + return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable); } virtual const char *getName() const { @@ -76,7 +80,12 @@ public: return "Future Wars & Operation Stealth (C) Delphine Software"; } + virtual Common::Error createInstance(OSystem *syst, Engine **engine) const { + Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable); + return AdvancedMetaEngine::createInstance(syst, engine); + } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual bool hasFeature(MetaEngineFeature f) const; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index f6f8db4f3a..5be2fdeeea 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -220,8 +220,8 @@ static const CRUISEGameDescription gameDescriptions[] = { class CruiseMetaEngine : public AdvancedMetaEngine { public: CruiseMetaEngine() : AdvancedMetaEngine(Cruise::gameDescriptions, sizeof(Cruise::CRUISEGameDescription), cruiseGames) { - params.singleid = "cruise"; - params.guioptions = Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI; + _singleid = "cruise"; + _guioptions = Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI; } virtual const char *getName() const { diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 3fd8671e55..531cf32dbc 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -143,9 +143,9 @@ void MainMenuDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint3 break; case kHelpCmd: { GUI::MessageDialog dialog( - "Sorry, this engine does not currently provide in-game help. " + _("Sorry, this engine does not currently provide in-game help. " "Please consult the README for basic information, and for " - "instructions on how to obtain further assistance."); + "instructions on how to obtain further assistance.")); dialog.runModal(); } break; diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp index cf0413ffa9..b7e83e1edb 100644 --- a/engines/draci/detection.cpp +++ b/engines/draci/detection.cpp @@ -86,7 +86,7 @@ const ADGameDescription gameDescriptions[] = { class DraciMetaEngine : public AdvancedMetaEngine { public: DraciMetaEngine() : AdvancedMetaEngine(Draci::gameDescriptions, sizeof(ADGameDescription), draciGames) { - params.singleid = "draci"; + _singleid = "draci"; } virtual const char *getName() const { diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 9494bfa66b..2249a49e4d 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -269,8 +269,8 @@ static const DrasculaGameDescription gameDescriptions[] = { class DrasculaMetaEngine : public AdvancedMetaEngine { public: DrasculaMetaEngine() : AdvancedMetaEngine(Drascula::gameDescriptions, sizeof(Drascula::DrasculaGameDescription), drasculaGames) { - params.singleid = "drascula"; - params.guioptions = Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD; + _singleid = "drascula"; + _guioptions = Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD; } virtual const char *getName() const { diff --git a/engines/engine.cpp b/engines/engine.cpp index 210b0b46a3..dc30b4bd0d 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -42,6 +42,7 @@ #include "common/list_intern.h" #include "common/scummsys.h" #include "common/textconsole.h" +#include "common/translation.h" #include "gui/debugger.h" #include "gui/dialog.h" @@ -216,7 +217,7 @@ void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics: // Just show warnings then these occur: #ifdef USE_RGB_COLOR if (gfxError & OSystem::kTransactionFormatNotSupported) { - Common::String message = "Could not initialize color format."; + Common::String message = _("Could not initialize color format."); GUI::MessageDialog dialog(message); dialog.runModal(); @@ -224,7 +225,7 @@ void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics: #endif if (gfxError & OSystem::kTransactionModeSwitchFailed) { - Common::String message = "Could not switch to video mode: '"; + Common::String message = _("Could not switch to video mode: '"); message += ConfMan.get("gfx_mode"); message += "'."; @@ -233,12 +234,12 @@ void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics: } if (gfxError & OSystem::kTransactionAspectRatioFailed) { - GUI::MessageDialog dialog("Could not apply aspect ratio setting."); + GUI::MessageDialog dialog(_("Could not apply aspect ratio setting.")); dialog.runModal(); } if (gfxError & OSystem::kTransactionFullscreenFailed) { - GUI::MessageDialog dialog("Could not apply fullscreen setting."); + GUI::MessageDialog dialog(_("Could not apply fullscreen setting.")); dialog.runModal(); } } @@ -338,22 +339,22 @@ void Engine::checkCD() { if (GetDriveType(buffer) == DRIVE_CDROM) { GUI::MessageDialog dialog( - "You appear to be playing this game directly\n" + _("You appear to be playing this game directly\n" "from the CD. This is known to cause problems,\n" "and it is therefore recommended that you copy\n" "the data files to your hard disk instead.\n" - "See the README file for details.", "OK"); + "See the README file for details."), _("OK")); dialog.runModal(); } else { // If we reached here, the game has audio tracks, // it's not ran from the CD and the tracks have not // been ripped. GUI::MessageDialog dialog( - "This game has audio tracks in its disk. These\n" + _("This game has audio tracks in its disk. These\n" "tracks need to be ripped from the disk using\n" "an appropriate CD audio extracting tool in\n" "order to listen to the game's music.\n" - "See the README file for details.", "OK"); + "See the README file for details."), _("OK")); dialog.runModal(); } #endif diff --git a/engines/game.cpp b/engines/game.cpp index a14edb8af4..c6d9905b52 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -38,17 +38,12 @@ GameDescriptor::GameDescriptor() { setVal("description", ""); } -GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) { - setVal("gameid", pgd.gameid); - setVal("description", pgd.description); -} - -GameDescriptor::GameDescriptor(const PlainGameDescriptorGUIOpts &pgd) { +GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, uint32 guioptions) { setVal("gameid", pgd.gameid); setVal("description", pgd.description); - if (pgd.guioptions != 0) - setVal("guioptions", Common::getGameGUIOptionsDescription(pgd.guioptions)); + if (guioptions != 0) + setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions)); } GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p, uint32 guioptions) { diff --git a/engines/game.h b/engines/game.h index f9988c2965..3216cfb628 100644 --- a/engines/game.h +++ b/engines/game.h @@ -40,20 +40,9 @@ struct PlainGameDescriptor { }; /** - * Same as PlainGameDsscriptor except it adds Game GUI options parameter - * This is a plain struct to make it possible to declare NULL-terminated C arrays - * consisting of PlainGameDescriptors. - */ -struct PlainGameDescriptorGUIOpts { - const char *gameid; - const char *description; - uint32 guioptions; -}; - -/** * Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor * matching the given gameid. If not match is found return 0. - * The end of the list must marked by a PlainGameDescriptor with gameid equal to 0. + * The end of the list must be marked by an entry with gameid 0. */ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list); @@ -67,8 +56,7 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla class GameDescriptor : public Common::StringMap { public: GameDescriptor(); - GameDescriptor(const PlainGameDescriptor &pgd); - GameDescriptor(const PlainGameDescriptorGUIOpts &pgd); + GameDescriptor(const PlainGameDescriptor &pgd, uint32 guioptions = 0); GameDescriptor(const Common::String &gameid, const Common::String &description, Common::Language language = Common::UNK_LANG, @@ -102,7 +90,7 @@ public: GameList(const GameList &list) : Common::Array<GameDescriptor>(list) {} GameList(const PlainGameDescriptor *g) { while (g->gameid) { - push_back(GameDescriptor(g->gameid, g->description)); + push_back(GameDescriptor(*g)); g++; } } diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 2ecd6b741e..9a554b5429 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -22,6 +22,7 @@ #include "base/plugins.h" #include "engines/advancedDetector.h" +#include "engines/obsolete.h" #include "gob/gob.h" @@ -78,7 +79,7 @@ static const PlainGameDescriptor gobGames[] = { {0, 0} }; -static const ADObsoleteGameID obsoleteGameIDsTable[] = { +static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = { {"gob1", "gob", kPlatformUnknown}, {"gob2", "gob", kPlatformUnknown}, {0, 0, kPlatformUnknown} @@ -89,10 +90,16 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { class GobMetaEngine : public AdvancedMetaEngine { public: GobMetaEngine() : AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) { - params.obsoleteList = obsoleteGameIDsTable; - params.singleid = "gob"; - params.fileBasedFallback = Gob::fileBased; - params.guioptions = Common::GUIO_NOLAUNCHLOAD; + _singleid = "gob"; + _guioptions = Common::GUIO_NOLAUNCHLOAD; + } + + virtual GameDescriptor findGame(const char *gameid) const { + return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable); + } + + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + return detectGameFilebased(allFiles, Gob::fileBased); } virtual const char *getName() const { @@ -104,6 +111,11 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; + + virtual Common::Error createInstance(OSystem *syst, Engine **engine) const { + Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable); + return AdvancedMetaEngine::createInstance(syst, engine); + } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; }; diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h index 11cca2b65e..1c9811fe9e 100644 --- a/engines/gob/detection_tables.h +++ b/engines/gob/detection_tables.h @@ -5202,32 +5202,32 @@ static const GOBGameDescription fallbackDescs[] = { }; static const ADFileBasedFallback fileBased[] = { - { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } }, - { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } }, - { &fallbackDescs[ 2], { "intro.stk", 0 } }, - { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } }, - { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } }, - { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } }, - { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } }, - { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } }, - { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } }, - { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } }, - { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } }, - { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } }, - { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } }, - { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } }, - { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } }, - { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } }, - { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } }, - { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } }, - { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } }, - { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } }, - { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[22], { "adi2.stk", 0 } }, - { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } }, - { &fallbackDescs[24], { "coktelplayer.scn", 0 } }, + { &fallbackDescs[ 0].desc, { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } }, + { &fallbackDescs[ 1].desc, { "intro.stk", "gob.lic", 0 } }, + { &fallbackDescs[ 2].desc, { "intro.stk", 0 } }, + { &fallbackDescs[ 2].desc, { "intro.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[ 3].desc, { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } }, + { &fallbackDescs[ 4].desc, { "intro.stk", "gobnew.lic", 0 } }, + { &fallbackDescs[ 5].desc, { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } }, + { &fallbackDescs[ 6].desc, { "intro.stk", "imd.itk", 0 } }, + { &fallbackDescs[ 7].desc, { "intro.stk", "mus_gob3.lic", 0 } }, + { &fallbackDescs[ 8].desc, { "intro.stk", "woodruff.itk", 0 } }, + { &fallbackDescs[ 9].desc, { "intro.stk", "commun1.itk", 0 } }, + { &fallbackDescs[10].desc, { "intro.stk", "commun1.itk", "musmac1.mid", 0 } }, + { &fallbackDescs[11].desc, { "intro.stk", "commun1.itk", "lost.lic", 0 } }, + { &fallbackDescs[12].desc, { "intro.stk", "cd1.itk", "objet1.itk", 0 } }, + { &fallbackDescs[13].desc, { "playtoon.stk", "archi.stk", 0 } }, + { &fallbackDescs[14].desc, { "playtoon.stk", "spirou.stk", 0 } }, + { &fallbackDescs[15].desc, { "playtoon.stk", "chato.stk", 0 } }, + { &fallbackDescs[16].desc, { "playtoon.stk", "manda.stk", 0 } }, + { &fallbackDescs[17].desc, { "playtoon.stk", "wakan.stk", 0 } }, + { &fallbackDescs[18].desc, { "playtoon.stk", "dan.itk" } }, + { &fallbackDescs[19].desc, { "intro.stk", "bambou.itk", 0 } }, + { &fallbackDescs[20].desc, { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[21].desc, { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[22].desc, { "adi2.stk", 0 } }, + { &fallbackDescs[23].desc, { "adif41.stk", "adim41.stk", 0 } }, + { &fallbackDescs[24].desc, { "coktelplayer.scn", 0 } }, { 0, { 0 } } }; diff --git a/engines/gob/inter_playtoons.cpp b/engines/gob/inter_playtoons.cpp index d57d2f354b..e05cae354c 100644 --- a/engines/gob/inter_playtoons.cpp +++ b/engines/gob/inter_playtoons.cpp @@ -22,6 +22,7 @@ #include "common/endian.h" #include "common/str.h" +#include "common/translation.h" #include "gui/message.h" @@ -252,7 +253,7 @@ void Inter_Playtoons::oPlaytoons_readData(OpFuncParams ¶ms) { WRITE_VAR(1, 1); if (!_vm->_saveLoad->load(file.c_str(), dataVar, size, offset)) { - GUI::MessageDialog dialog("Failed to load game state from file."); + GUI::MessageDialog dialog(_("Failed to load game state from file.")); dialog.runModal(); } else WRITE_VAR(1, 0); diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 84cae3b380..2fea18343d 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -22,6 +22,7 @@ #include "common/endian.h" #include "common/str.h" +#include "common/translation.h" #include "gui/message.h" @@ -1279,7 +1280,7 @@ void Inter_v2::o2_readData(OpFuncParams ¶ms) { if (!_vm->_saveLoad->load(file, dataVar, size, offset)) { - GUI::MessageDialog dialog("Failed to load game state from file."); + GUI::MessageDialog dialog(_("Failed to load game state from file.")); dialog.runModal(); } else @@ -1349,7 +1350,7 @@ void Inter_v2::o2_writeData(OpFuncParams ¶ms) { if (!_vm->_saveLoad->save(file, dataVar, size, offset)) { - GUI::MessageDialog dialog("Failed to save game state to file."); + GUI::MessageDialog dialog(_("Failed to save game state to file.")); dialog.runModal(); } else diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp index ed371737bd..c0e8978afd 100644 --- a/engines/gob/inter_v5.cpp +++ b/engines/gob/inter_v5.cpp @@ -20,6 +20,8 @@ * */ +#include "common/translation.h" + #include "gui/message.h" #include "gob/gob.h" @@ -102,7 +104,7 @@ void Inter_v5::o5_deleteFile() { if (mode == SaveLoad::kSaveModeSave) { if (!_vm->_saveLoad->deleteFile(file)) { - GUI::MessageDialog dialog("Failed to delete file."); + GUI::MessageDialog dialog(_("Failed to delete file.")); dialog.runModal(); } diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index 62ee65d74a..2065307ca9 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -205,9 +205,18 @@ static const GroovieGameDescription gameDescriptions[] = { class GroovieMetaEngine : public AdvancedMetaEngine { public: GroovieMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(GroovieGameDescription), groovieGames) { - params.singleid = "groovie"; - params.flags = kADFlagUseExtraAsHint; - params.guioptions = Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX; + _singleid = "groovie"; + + // Use kADFlagUseExtraAsHint in order to distinguish the 11th hour from + // its "Making of" as well as the Clandestiny Trailer; they all share + // the same MD5. + // TODO: Is this the only reason, or are there others (like the three + // potentially sharing a single directory) ? In the former case, then + // perhaps a better solution would be to add additional files + // to the detection entries. In the latter case, this TODO should be + // replaced with an according explanation. + _flags = kADFlagUseExtraAsHint; + _guioptions = Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX; } const char *getName() const { diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index b52a8723fc..f87e6bb91b 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -36,6 +36,7 @@ #include "common/events.h" #include "common/file.h" #include "common/macresman.h" +#include "common/translation.h" #include "gui/message.h" @@ -413,7 +414,7 @@ void Script::savegame(uint slot) { if (!file) { debugC(9, kGroovieDebugScript, "Save file pointer is null"); - GUI::MessageDialog dialog("Failed to save game", "OK"); + GUI::MessageDialog dialog(_("Failed to save game"), _("OK")); dialog.runModal(); return; } diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 6589c2b45b..a6af584fb8 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -52,9 +52,9 @@ const char * const directoryGlobs[] = { class KyraMetaEngine : public AdvancedMetaEngine { public: KyraMetaEngine() : AdvancedMetaEngine(adGameDescs, sizeof(KYRAGameDescription), gameList) { - params.md5Bytes = 1024 * 1024; - params.depth = 2; - params.directoryGlobs = directoryGlobs; + _md5Bytes = 1024 * 1024; + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; } const char *getName() const { return "Kyra"; diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp index 6c003d0a11..dc0f8c11ec 100644 --- a/engines/kyra/sound_midi.cpp +++ b/engines/kyra/sound_midi.cpp @@ -25,6 +25,7 @@ #include "common/system.h" #include "common/config-manager.h" +#include "common/translation.h" #include "gui/message.h" @@ -471,11 +472,11 @@ SoundMidiPC::SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *dri // (This will only happen in The Legend of Kyrandia 1 though, all other // supported games include special General MIDI tracks). if (_type == kMidiMT32 && !_nativeMT32) { - ::GUI::MessageDialog dialog("You appear to be using a General MIDI device,\n" + ::GUI::MessageDialog dialog(_("You appear to be using a General MIDI device,\n" "but your game only supports Roland MT32 MIDI.\n" "We try to map the Roland MT32 instruments to\n" "General MIDI ones. After all it might happen\n" - "that a few tracks will not be correctly played."); + "that a few tracks will not be correctly played.")); dialog.runModal(); } } diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp index bf575b63f8..369d815543 100644 --- a/engines/lastexpress/detection.cpp +++ b/engines/lastexpress/detection.cpp @@ -181,8 +181,8 @@ static const ADGameDescription gameDescriptions[] = { class LastExpressMetaEngine : public AdvancedMetaEngine { public: LastExpressMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), lastExpressGames) { - params.singleid = "lastexpress"; - params.guioptions = Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX; + _singleid = "lastexpress"; + _guioptions = Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX; } const char *getName() const { diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp index 83ede92569..081625863d 100644 --- a/engines/lure/detection.cpp +++ b/engines/lure/detection.cpp @@ -178,10 +178,13 @@ static const LureGameDescription gameDescriptions[] = { class LureMetaEngine : public AdvancedMetaEngine { public: LureMetaEngine() : AdvancedMetaEngine(Lure::gameDescriptions, sizeof(Lure::LureGameDescription), lureGames) { - params.md5Bytes = 1024; - params.singleid = "lure"; - params.flags = kADFlagUseExtraAsHint; - params.guioptions = Common::GUIO_NOSPEECH; + _md5Bytes = 1024; + _singleid = "lure"; + + // Use kADFlagUseExtraAsHint to distinguish between EGA and VGA versions + // of italian Lure when their datafiles sit in the same directory. + _flags = kADFlagUseExtraAsHint; + _guioptions = Common::GUIO_NOSPEECH; } virtual const char *getName() const { diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp index bab17d9e1d..02ed967777 100644 --- a/engines/m4/detection.cpp +++ b/engines/m4/detection.cpp @@ -387,10 +387,10 @@ static const char *directoryGlobs[] = { class M4MetaEngine : public AdvancedMetaEngine { public: M4MetaEngine() : AdvancedMetaEngine(M4::gameDescriptions, sizeof(M4::M4GameDescription), m4Games) { - params.singleid = "m4"; - params.guioptions = Common::GUIO_NOMIDI; - params.depth = 2; - params.directoryGlobs = directoryGlobs; + _singleid = "m4"; + _guioptions = Common::GUIO_NOMIDI; + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; } virtual const char *getName() const { diff --git a/engines/m4/m4_menus.cpp b/engines/m4/m4_menus.cpp index 787d8666f6..3384a82c8b 100644 --- a/engines/m4/m4_menus.cpp +++ b/engines/m4/m4_menus.cpp @@ -22,6 +22,7 @@ #include "common/algorithm.h" // for find() #include "common/textconsole.h" +#include "common/translation.h" #include "gui/dialog.h" #include "gui/message.h" @@ -134,7 +135,7 @@ void OrionCallbacks::saveLoadSaveFn(DialogView *view, MenuObject *item) { bool succeeded = view->vm()->_saveLoad->save(view->_selectedSlot + 1, textItem->getText()); if (!succeeded) { - GUI::MessageDialog dialog("Save game failed!"); + GUI::MessageDialog dialog(_("Save game failed!")); dialog.runModal(); } diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index a0576a458e..e8c948af4e 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -528,7 +528,7 @@ static MadeGameDescription g_fallbackDesc = { class MadeMetaEngine : public AdvancedMetaEngine { public: MadeMetaEngine() : AdvancedMetaEngine(Made::gameDescriptions, sizeof(Made::MadeGameDescription), madeGames) { - params.singleid = "made"; + _singleid = "made"; } virtual const char *getName() const { @@ -542,7 +542,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const; + const ADGameDescription *fallbackDetect(const Common::FSList &fslist, const FileMap &allFiles) const; }; @@ -564,7 +564,7 @@ bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame return gd != 0; } -const ADGameDescription *MadeMetaEngine::fallbackDetect(const Common::FSList &fslist) const { +const ADGameDescription *MadeMetaEngine::fallbackDetect(const Common::FSList &fslist, const FileMap &allFiles) const { // Set the default values for the fallback descriptor's ADGameDescription part. Made::g_fallbackDesc.desc.language = Common::UNK_LANG; Made::g_fallbackDesc.desc.platform = Common::kPlatformPC; diff --git a/engines/module.mk b/engines/module.mk index 643310002f..7849c2ff25 100644 --- a/engines/module.mk +++ b/engines/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS := \ dialogs.o \ engine.o \ game.o \ + obsolete.o \ savestate.o # Include common rules diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index a7442729d2..f0c657897d 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -161,11 +161,15 @@ static const char *directoryGlobs[] = { class MohawkMetaEngine : public AdvancedMetaEngine { public: MohawkMetaEngine() : AdvancedMetaEngine(Mohawk::gameDescriptions, sizeof(Mohawk::MohawkGameDescription), mohawkGames) { - params.singleid = "mohawk"; - params.fileBasedFallback = Mohawk::fileBased; - params.depth = 2; - params.directoryGlobs = directoryGlobs; + _singleid = "mohawk"; + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; } + + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + return detectGameFilebased(allFiles, Mohawk::fileBased); + } + virtual const char *getName() const { return "Mohawk"; } diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index df66c3dc1c..2cf80377f6 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -2220,11 +2220,11 @@ static const MohawkGameDescription fallbackDescs[] = { }; static const ADFileBasedFallback fileBased[] = { - { &fallbackDescs[0], { "MYST.DAT", 0 } }, - { &fallbackDescs[1], { "MAKING.DAT", 0 } }, - { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original - { &fallbackDescs[3], { "a_Data.MHK", 0 } }, - { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } }, + { &fallbackDescs[0].desc, { "MYST.DAT", 0 } }, + { &fallbackDescs[1].desc, { "MAKING.DAT", 0 } }, + { &fallbackDescs[2].desc, { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original + { &fallbackDescs[3].desc, { "a_Data.MHK", 0 } }, + { &fallbackDescs[4].desc, { "a_Data.MHK", "t_Data1.MHK" , 0 } }, { 0, { 0 } } }; diff --git a/engines/mohawk/mohawk.h b/engines/mohawk/mohawk.h index b189f82040..f0618f7374 100644 --- a/engines/mohawk/mohawk.h +++ b/engines/mohawk/mohawk.h @@ -28,6 +28,8 @@ #include "engines/engine.h" +#include "mohawk/video.h" + class OSystem; namespace Common { @@ -76,7 +78,6 @@ struct MohawkGameDescription; class Sound; class PauseDialog; class MohawkArchive; -class VideoManager; class CursorManager; class MohawkEngine : public ::Engine { @@ -112,6 +113,10 @@ public: void pauseGame(); + // Check if events should be done based on a video's current time + // (currently only used for Riven's storeMovieOpcode function) + virtual void doVideoTimer(VideoHandle handle, bool force) {} + private: PauseDialog *_pauseDialog; void pauseEngineIntern(bool); diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 57a0ac717d..3514afdb61 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -833,6 +833,19 @@ void MohawkEngine_Riven::installCardTimer() { } } +void MohawkEngine_Riven::doVideoTimer(VideoHandle handle, bool force) { + assert(handle != NULL_VID_HANDLE); + + uint16 id = _scriptMan->getStoredMovieOpcodeID(); + + if (handle != _video->findVideoHandleRiven(id)) // Check if we've got a video match + return; + + // Run the opcode if we can at this point + if (force || _video->getElapsedTime(handle) >= _scriptMan->getStoredMovieOpcodeTime()) + _scriptMan->runStoredMovieOpcode(); +} + bool ZipMode::operator== (const ZipMode &z) const { return z.name == name && z.id == id; } diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index c80f497e37..c7d36e585d 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -131,6 +131,8 @@ public: typedef void (*TimerProc)(MohawkEngine_Riven *vm); + void doVideoTimer(VideoHandle handle, bool force); + private: MohawkArchive *_extrasFile; // We need a separate handle for the extra data RivenConsole *_console; diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index b3d5369a84..161acb665f 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -407,14 +407,14 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) { return; // The argument is a bitflag for the setting. - // bit 0 is normal sound stopping (unused) + // bit 0 is normal sound stopping // bit 1 is ambient sound stopping // Having no flags set means clear all if (argv[0] & 2 || argv[0] == 0) _vm->_sound->stopAllSLST(); - if (argv[0] & 1) - warning("Unhandled stopSound() flag"); + if (argv[0] & 1 || argv[0] == 0) + _vm->_sound->stopSound(); } // Command 13: set mouse cursor (cursor_id) @@ -536,6 +536,10 @@ void RivenScript::fadeAmbientSounds(uint16 op, uint16 argc, uint16 *argv) { // Command 38: Store an opcode for use when playing a movie (movie id, time high, time low, opcode, arguments...) void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) { + // This opcode is used to delay an opcode's usage based on the elapsed + // time of a specified movie. However, every use in the game is for + // delaying an activateSLST opcode. + uint32 scriptSize = 6 + (argc - 4) * 2; // Create our dummy script @@ -557,13 +561,11 @@ void RivenScript::storeMovieOpcode(uint16 op, uint16 argc, uint16 *argv) { // Store the script RivenScriptManager::StoredMovieOpcode storedOp; storedOp.script = script; - storedOp.time = delayTime + _vm->getTotalPlayTime(); + storedOp.time = delayTime; storedOp.id = argv[0]; - // TODO: Actually store the movie and call it in our movie loop - // For now, just delete the script and move on - //_vm->_scriptMan->setStoredMovieOpcode(storedOp); - delete script; + // Store the opcode for later + _vm->_scriptMan->setStoredMovieOpcode(storedOp); } else { // Run immediately if we have no delay script->runScript(); @@ -716,18 +718,10 @@ void RivenScriptManager::setStoredMovieOpcode(const StoredMovieOpcode &op) { _storedMovieOpcode.time = op.time; } -void RivenScriptManager::runStoredMovieOpcode(uint16 id) { +void RivenScriptManager::runStoredMovieOpcode() { if (_storedMovieOpcode.script) { - if (_storedMovieOpcode.id == id) { - // If we've passed the time, run our script - if (_vm->getTotalPlayTime() >= _storedMovieOpcode.time) { - _storedMovieOpcode.script->runScript(); - clearStoredMovieOpcode(); - } - } else { - // We're on a completely different video, kill off any remaining opcode - clearStoredMovieOpcode(); - } + _storedMovieOpcode.script->runScript(); + clearStoredMovieOpcode(); } } diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h index 75d4592e55..2932ba5939 100644 --- a/engines/mohawk/riven_scripts.h +++ b/engines/mohawk/riven_scripts.h @@ -141,8 +141,10 @@ public: uint16 id; }; + uint16 getStoredMovieOpcodeID() { return _storedMovieOpcode.id; } + uint32 getStoredMovieOpcodeTime() { return _storedMovieOpcode.time; } void setStoredMovieOpcode(const StoredMovieOpcode &op); - void runStoredMovieOpcode(uint16 id); + void runStoredMovieOpcode(); void clearStoredMovieOpcode(); private: diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index 0a74d058c9..eec6256276 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -133,6 +133,7 @@ void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) { break; case Common::KEYCODE_ESCAPE: continuePlaying = false; + _vm->doVideoTimer(videoHandle, true); break; default: break; @@ -208,14 +209,20 @@ bool VideoManager::updateMovies() { if (_videoStreams[i].loop) { _videoStreams[i]->seekToTime(_videoStreams[i].start); } else { + // Check the video time one last time before deleting it + _vm->doVideoTimer(i, true); delete _videoStreams[i].video; _videoStreams[i].clear(); continue; } } + // Nothing more to do if we're paused + if (_videoStreams[i]->isPaused()) + continue; + // Check if we need to draw a frame - if (!_videoStreams[i]->isPaused() && _videoStreams[i]->needsUpdate()) { + if (_videoStreams[i]->needsUpdate()) { const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame(); Graphics::Surface *convertedFrame = 0; @@ -266,6 +273,9 @@ bool VideoManager::updateMovies() { } } } + + // Check the video time + _vm->doVideoTimer(i, false); } // Return true if we need to update the screen diff --git a/engines/obsolete.cpp b/engines/obsolete.cpp new file mode 100644 index 0000000000..6733a384be --- /dev/null +++ b/engines/obsolete.cpp @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "engines/obsolete.h" + +#include "common/config-manager.h" + + +namespace Engines { + +void upgradeTargetIfNecessary(const ObsoleteGameID *obsoleteList) { + if (obsoleteList == 0) + return; + + Common::String gameid = ConfMan.get("gameid"); + + for (const ObsoleteGameID *o = obsoleteList; o->from; ++o) { + if (gameid.equalsIgnoreCase(o->from)) { + gameid = o->to; + ConfMan.set("gameid", gameid); + + if (o->platform != Common::kPlatformUnknown) + ConfMan.set("platform", Common::getPlatformCode(o->platform)); + + warning("Target upgraded from %s to %s", o->from, o->to); + + // WORKAROUND: Fix for bug #1719463: "DETECTOR: Launching + // undefined target adds launcher entry" + if (ConfMan.hasKey("id_came_from_command_line")) { + warning("Target came from command line. Skipping save"); + } else { + ConfMan.flushToDisk(); + } + break; + } + } +} + +GameDescriptor findGameID( + const char *gameid, + const PlainGameDescriptor *gameids, + const ObsoleteGameID *obsoleteList + ) { + // First search the list of supported gameids for a match. + const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, gameids); + if (g) + return GameDescriptor(*g); + + // If we didn't find the gameid in the main list, check if it + // is an obsolete game id. + if (obsoleteList != 0) { + const ObsoleteGameID *o = obsoleteList; + while (o->from) { + if (0 == scumm_stricmp(gameid, o->from)) { + g = findPlainGameDescriptor(o->to, gameids); + if (g && g->description) + return GameDescriptor(gameid, "Obsolete game ID (" + Common::String(g->description) + ")"); + else + return GameDescriptor(gameid, "Obsolete game ID"); + } + o++; + } + } + + // No match found + return GameDescriptor(); +} + +} // End of namespace Engines diff --git a/engines/obsolete.h b/engines/obsolete.h new file mode 100644 index 0000000000..97bc7524a6 --- /dev/null +++ b/engines/obsolete.h @@ -0,0 +1,78 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ENGINES_OBSOLETE_H +#define ENGINES_OBSOLETE_H + +#include "engines/game.h" + +namespace Engines { + +/** + * Structure for autoupgrading targets using an obsolete gameid + * to the correct new gameid. + */ +struct ObsoleteGameID { + + /** Name of the obsolete gameid. */ + const char *from; + + /** Name of the corresponding new gameid. */ + const char *to; + + /** + * If platform is set to a value different from Common::kPlatformUnknown, + * then upgradeTargetIfNecessary() will use this value to set the platform + * attribute of any target it updates using this ObsoleteGameID record. + * This is useful when the old gameid encoded the target platform (e.g. + * "zakTowns" for FM-TOWNS) while the new gameid does not (e.g. "zak"). + */ + Common::Platform platform; +}; + +/** + * Check if the currently active game target has an obsolete gameid; + * if so, replace it by the correct new gameid. + * This function is typically invoked by a MetaEngine::createInstance + * implementation. + */ +void upgradeTargetIfNecessary(const ObsoleteGameID *obsoleteList); + + +/** + * Scan through the given list of plain game descriptors specified and search + * for 'gameid' in there. If a match is found, returns a GameDescriptor + * with gameid and description set. + * + * Optionally can take a list of obsolete game ids into account in order + * to support obsolete gameids. + */ +GameDescriptor findGameID( + const char *gameid, + const PlainGameDescriptor *gameids, + const ObsoleteGameID *obsoleteList = 0 + ); + + +} // End of namespace Engines + +#endif diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index 09f6fa5e2e..d0610f7a29 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -223,7 +223,7 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { class ParallactionMetaEngine : public AdvancedMetaEngine { public: ParallactionMetaEngine() : AdvancedMetaEngine(Parallaction::gameDescriptions, sizeof(Parallaction::PARALLACTIONGameDescription), parallactionGames) { - params.guioptions = Common::GUIO_NOLAUNCHLOAD; + _guioptions = Common::GUIO_NOLAUNCHLOAD; } virtual const char *getName() const { diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp index 673c613485..5a1daa256b 100644 --- a/engines/parallaction/saveload.cpp +++ b/engines/parallaction/saveload.cpp @@ -23,6 +23,7 @@ #include "common/savefile.h" #include "common/config-manager.h" #include "common/textconsole.h" +#include "common/translation.h" #include "gui/dialog.h" #include "gui/saveload.h" @@ -129,8 +130,7 @@ void SaveLoad_ns::doLoadGame(uint16 slot) { void SaveLoad_ns::doSaveGame(uint16 slot, const char* name) { Common::OutSaveFile *f = getOutSaveFile(slot); if (f == 0) { - char buf[32]; - sprintf(buf, "Can't save game in slot %i\n\n", slot); + Common::String buf = Common::String::format(_("Can't save game in slot %i\n\n"), slot); GUI::MessageDialog dialog(buf); dialog.runModal(); return; @@ -208,7 +208,7 @@ bool SaveLoad::loadGame() { doLoadGame(_di); - GUI::TimedMessageDialog dialog("Loading game...", 1500); + GUI::TimedMessageDialog dialog(_("Loading game..."), 1500); dialog.runModal(); return true; @@ -223,7 +223,7 @@ bool SaveLoad::saveGame() { doSaveGame(slot, saveName.c_str()); - GUI::TimedMessageDialog dialog("Saving game...", 1500); + GUI::TimedMessageDialog dialog(_("Saving game..."), 1500); dialog.runModal(); return true; @@ -276,9 +276,9 @@ void SaveLoad_ns::getGamePartProgress(bool *complete, int size) { static bool askRenameOldSavefiles() { GUI::MessageDialog dialog0( - "ScummVM found that you have old savefiles for Nippon Safes that should be renamed.\n" + _("ScummVM found that you have old savefiles for Nippon Safes that should be renamed.\n" "The old names are no longer supported, so you will not be able to load your games if you don't convert them.\n\n" - "Press OK to convert them now, otherwise you will be asked next time.\n", "OK", "Cancel"); + "Press OK to convert them now, otherwise you will be asked next time.\n"), _("OK"), _("Cancel")); return (dialog0.runModal() != 0); } @@ -321,12 +321,11 @@ void SaveLoad_ns::renameOldSavefiles() { return; } - char msg[200]; + Common::String msg; if (success == numOldSaves) { - sprintf(msg, "ScummVM successfully converted all your savefiles."); + msg = _("ScummVM successfully converted all your savefiles."); } else { - sprintf(msg, - "ScummVM printed some warnings in your console window and can't guarantee all your files have been converted.\n\n" + msg = _("ScummVM printed some warnings in your console window and can't guarantee all your files have been converted.\n\n" "Please report to the team."); } diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp index d0e3fc17fd..9c486f7548 100644 --- a/engines/pegasus/detection.cpp +++ b/engines/pegasus/detection.cpp @@ -87,7 +87,7 @@ static const PegasusGameDescription gameDescriptions[] = { class PegasusMetaEngine : public AdvancedMetaEngine { public: PegasusMetaEngine() : AdvancedMetaEngine(Pegasus::gameDescriptions, sizeof(Pegasus::PegasusGameDescription), pegasusGames) { - params.singleid = "pegasus"; + _singleid = "pegasus"; } virtual const char *getName() const { diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index ece90855b7..7a98fe4164 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -28,6 +28,7 @@ #include "common/config-manager.h" #include "engines/advancedDetector.h" +#include "engines/obsolete.h" #include "common/system.h" #include "graphics/thumbnail.h" @@ -91,7 +92,7 @@ static const PlainGameDescriptor sagaGames[] = { {0, 0} }; -static const ADObsoleteGameID obsoleteGameIDsTable[] = { +static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = { {"ite", "saga", Common::kPlatformUnknown}, {"ihnm", "saga", Common::kPlatformUnknown}, {"dino", "saga", Common::kPlatformUnknown}, @@ -104,8 +105,11 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { class SagaMetaEngine : public AdvancedMetaEngine { public: SagaMetaEngine() : AdvancedMetaEngine(Saga::gameDescriptions, sizeof(Saga::SAGAGameDescription), sagaGames) { - params.obsoleteList = obsoleteGameIDsTable; - params.singleid = "saga"; + _singleid = "saga"; + } + + virtual GameDescriptor findGame(const char *gameid) const { + return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable); } virtual const char *getName() const { @@ -135,7 +139,13 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; + + virtual Common::Error createInstance(OSystem *syst, Engine **engine) const { + Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable); + return AdvancedMetaEngine::createInstance(syst, engine); + } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; virtual void removeSaveState(const char *target, int slot) const; diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 302ba13247..7bc9699e9b 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -374,7 +374,7 @@ static char s_fallbackGameIdBuf[256]; class SciMetaEngine : public AdvancedMetaEngine { public: SciMetaEngine() : AdvancedMetaEngine(Sci::SciGameDescriptions, sizeof(ADGameDescription), s_sciGameTitles) { - params.singleid = "sci"; + _singleid = "sci"; } virtual const char *getName() const { @@ -390,7 +390,7 @@ public: } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const; - const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const; + const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; virtual bool hasFeature(MetaEngineFeature f) const; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; @@ -418,7 +418,7 @@ Common::Language charToScummVMLanguage(const char c) { } } -const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fslist) const { +const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { bool foundResMap = false; bool foundRes000 = false; @@ -430,6 +430,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl s_fallbackDesc.gameid = "sci"; // First grab all filenames + // TODO: Consider using allFiles instead of fslist for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) continue; diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index aecd13db5a..e5c5906404 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -431,7 +431,7 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF } } -static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map, int depth, const char **globs) { +static void composeFileHashMap(DescMap &fileMD5Map, const Common::FSList &fslist, int depth, const char **globs) { if (depth <= 0) return; @@ -459,9 +459,8 @@ static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map continue; Common::FSList files; - if (file->getChildren(files, Common::FSNode::kListAll)) { - composeFileHashMap(files, fileMD5Map, depth - 1, globs); + composeFileHashMap(fileMD5Map, files, depth - 1, globs); } } } @@ -472,7 +471,7 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul DetectorResult dr; // Dive one level down since mac indy3/loom has its files split into directories. See Bug #1438631 - composeFileHashMap(fslist, fileMD5Map, 2, directoryGlobs); + composeFileHashMap(fileMD5Map, fslist, 2, directoryGlobs); // Iterate over all filename patterns. for (const GameFilenamePattern *gfp = gameFilenamesTable; gfp->gameid; ++gfp) { @@ -882,7 +881,7 @@ GameList ScummMetaEngine::getSupportedGames() const { } GameDescriptor ScummMetaEngine::findGame(const char *gameid) const { - return AdvancedDetector::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable); + return Engines::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable); } static Common::String generatePreferredTarget(const DetectorResult &x) { @@ -975,20 +974,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co // We start by checking whether the specified game ID is obsolete. // If that is the case, we automatically upgrade the target to use // the correct new game ID (and platform, if specified). - for (const ADObsoleteGameID *o = obsoleteGameIDsTable; o->from; ++o) { - if (!scumm_stricmp(gameid, o->from)) { - // Match found, perform upgrade - gameid = o->to; - ConfMan.set("gameid", o->to); - - if (o->platform != Common::kPlatformUnknown) - ConfMan.set("platform", Common::getPlatformCode(o->platform)); - - warning("Target upgraded from game ID %s to %s", o->from, o->to); - ConfMan.flushToDisk(); - break; - } - } + Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable); // Fetch the list of files in the current directory Common::FSList fslist; diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 7eb1e80132..e510c46cf2 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -23,7 +23,7 @@ #ifndef SCUMM_DETECTION_TABLES_H #define SCUMM_DETECTION_TABLES_H -#include "engines/advancedDetector.h" +#include "engines/obsolete.h" #include "common/rect.h" #include "common/util.h" @@ -145,7 +145,7 @@ static const PlainGameDescriptor gameDescriptions[] = { * Conversion table mapping old obsolete game IDs to the * corresponding new game ID and platform combination. */ -static const ADObsoleteGameID obsoleteGameIDsTable[] = { +static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = { {"bluesabctimedemo", "bluesabctime", UNK}, {"BluesBirthdayDemo", "BluesBirthday", UNK}, {"comidemo", "comi", UNK}, diff --git a/engines/scumm/gfx_towns.cpp b/engines/scumm/gfx_towns.cpp index 10d6ee0082..cdccd3e193 100644 --- a/engines/scumm/gfx_towns.cpp +++ b/engines/scumm/gfx_towns.cpp @@ -458,7 +458,7 @@ void TownsScreen::updateOutputBuffer() { } for (int y = r->top; y <= r->bottom; ++y) { - if (l->bpp == _bpp && l->scaleW == 1 && l->onBottom) { + if (l->bpp == _bpp && l->scaleW == 1 && l->onBottom && l->numCol & 0xff00) { memcpy(dst, &l->bltInternY[y][l->bltInternX[r->left]], (r->right + 1 - r->left) * _bpp); dst += _pitch; diff --git a/engines/scumm/resource.h b/engines/scumm/resource.h index e8b0c1eaae..2e8960717f 100644 --- a/engines/scumm/resource.h +++ b/engines/scumm/resource.h @@ -63,9 +63,9 @@ class ScummEngine; * marked in this way. */ enum ResTypeMode { - kDynamicResTypeMode = 0, ///!< Resource is generated during runtime and may change - kStaticResTypeMode = 1, ///!< Resource comes from data files, does not change - kSoundResTypeMode = 2 ///!< Resource comes from data files, but may change + kDynamicResTypeMode = 0, ///< Resource is generated during runtime and may change + kStaticResTypeMode = 1, ///< Resource comes from data files, does not change + kSoundResTypeMode = 2 ///< Resource comes from data files, but may change }; /** diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index dd26e23b4d..0a5338374e 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1766,8 +1766,10 @@ void ScummEngine::setupMusic(int midi) { if (missingFile) { GUI::MessageDialog dialog( - "Native MIDI support requires the Roland Upgrade from LucasArts,\n" - "but " + fileName + " is missing. Using AdLib instead.", "Ok"); + Common::String::format( + _("Native MIDI support requires the Roland Upgrade from LucasArts,\n" + "but %s is missing. Using AdLib instead."), fileName.c_str()), + _("OK")); dialog.runModal(); _musicType = MDT_ADLIB; } diff --git a/engines/sky/compact.cpp b/engines/sky/compact.cpp index 66ce92f8fc..84609d5500 100644 --- a/engines/sky/compact.cpp +++ b/engines/sky/compact.cpp @@ -25,6 +25,7 @@ #include "common/endian.h" #include "common/file.h" #include "common/textconsole.h" +#include "common/translation.h" #include "sky/compact.h" #include "gui/message.h" #include <stddef.h> // for ptrdiff_t @@ -126,8 +127,8 @@ static const uint32 turnTableOffsets[] = { SkyCompact::SkyCompact() { _cptFile = new Common::File(); if (!_cptFile->open("sky.cpt")) { - GUI::MessageDialog dialog("Unable to find \"sky.cpt\" file!\n" - "Please download it from www.scummvm.org", "OK", NULL); + GUI::MessageDialog dialog(_("Unable to find \"sky.cpt\" file!\n" + "Please download it from www.scummvm.org"), _("OK"), NULL); dialog.runModal(); error("Unable to find \"sky.cpt\" file\nPlease download it from www.scummvm.org"); } @@ -137,7 +138,7 @@ SkyCompact::SkyCompact() { error("unknown \"sky.cpt\" version"); if (SKY_CPT_SIZE != _cptFile->size()) { - GUI::MessageDialog dialog("The \"sky.cpt\" file has an incorrect size.\nPlease (re)download it from www.scummvm.org", "OK", NULL); + GUI::MessageDialog dialog(_("The \"sky.cpt\" file has an incorrect size.\nPlease (re)download it from www.scummvm.org"), _("OK"), NULL); dialog.runModal(); error("Incorrect sky.cpt size (%d, expected: %d)", _cptFile->size(), SKY_CPT_SIZE); } diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index 7e9d1142be..cb86264eeb 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -24,6 +24,7 @@ #include "common/events.h" #include "common/keyboard.h" #include "common/textconsole.h" +#include "common/translation.h" #include "sword1/sword1.h" #include "sword1/animation.h" #include "sword1/text.h" @@ -324,7 +325,6 @@ uint32 DXADecoderWithSound::getElapsedTime() const { MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system) { Common::String filename; - char buf[60]; Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle; filename = Common::String::format("%s.smk", sequenceList[id]); @@ -341,7 +341,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::M DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle); return new MoviePlayer(vm, textMan, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA); #else - GUI::MessageDialog dialog("DXA cutscenes found but ScummVM has been built without zlib support", "OK"); + GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK")); dialog.runModal(); return NULL; #endif @@ -351,13 +351,13 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::M filename = Common::String::format("%s.mp2", sequenceList[id]); if (Common::File::exists(filename)) { - GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK"); + GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK")); dialog.runModal(); return NULL; } - sprintf(buf, "Cutscene '%s' not found", sequenceList[id]); - GUI::MessageDialog dialog(buf, "OK"); + Common::String buf = Common::String::format(_("Cutscene '%s' not found"), sequenceList[id]); + GUI::MessageDialog dialog(buf, _("OK")); dialog.runModal(); return NULL; diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp index 86947db8ae..36d5a24e99 100644 --- a/engines/sword1/control.cpp +++ b/engines/sword1/control.cpp @@ -27,6 +27,7 @@ #include "common/system.h" #include "common/config-manager.h" #include "common/textconsole.h" +#include "common/translation.h" #include "graphics/palette.h" #include "graphics/thumbnail.h" @@ -859,9 +860,9 @@ void Control::checkForOldSaveGames() { } GUI::MessageDialog dialog0( - "ScummVM found that you have old savefiles for Broken Sword 1 that should be converted.\n" + _("ScummVM found that you have old savefiles for Broken Sword 1 that should be converted.\n" "The old save game format is no longer supported, so you will not be able to load your games if you don't convert them.\n\n" - "Press OK to convert them now, otherwise you will be asked again the next time you start the game.\n", "OK", "Cancel"); + "Press OK to convert them now, otherwise you will be asked again the next time you start the game.\n"), _("OK"), _("Cancel")); int choice = dialog0.runModal(); if (choice == GUI::kMessageCancel) { @@ -1228,11 +1229,10 @@ bool Control::convertSaveGame(uint8 slot, char* desc) { if (testSave) { delete testSave; - char msg[200]; - sprintf(msg, "Target new save game already exists!\n" - "Would you like to keep the old save game (%s) or the new one (%s)?\n", + Common::String msg = Common::String::format(_("Target new save game already exists!\n" + "Would you like to keep the old save game (%s) or the new one (%s)?\n"), oldFileName, newFileName); - GUI::MessageDialog dialog0(msg, "Keep the old one", "Keep the new one"); + GUI::MessageDialog dialog0(msg, _("Keep the old one"), _("Keep the new one")); int choice = dialog0.runModal(); if (choice == GUI::kMessageCancel) { diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 48c3a0d14d..0c1e74082f 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -33,18 +33,18 @@ #include "engines/metaengine.h" /* Broken Sword */ -static const PlainGameDescriptorGUIOpts sword1FullSettings = - {"sword1", "Broken Sword: The Shadow of the Templars", Common::GUIO_NOMIDI}; -static const PlainGameDescriptorGUIOpts sword1DemoSettings = - {"sword1demo", "Broken Sword: The Shadow of the Templars (Demo)", Common::GUIO_NOMIDI}; -static const PlainGameDescriptorGUIOpts sword1MacFullSettings = - {"sword1mac", "Broken Sword: The Shadow of the Templars (Mac)", Common::GUIO_NOMIDI}; -static const PlainGameDescriptorGUIOpts sword1MacDemoSettings = - {"sword1macdemo", "Broken Sword: The Shadow of the Templars (Mac demo)", Common::GUIO_NOMIDI}; -static const PlainGameDescriptorGUIOpts sword1PSXSettings = - {"sword1psx", "Broken Sword: The Shadow of the Templars (PlayStation)", Common::GUIO_NOMIDI}; -static const PlainGameDescriptorGUIOpts sword1PSXDemoSettings = - {"sword1psxdemo", "Broken Sword: The Shadow of the Templars (PlayStation demo)", Common::GUIO_NOMIDI}; +static const PlainGameDescriptor sword1FullSettings = + {"sword1", "Broken Sword: The Shadow of the Templars"}; +static const PlainGameDescriptor sword1DemoSettings = + {"sword1demo", "Broken Sword: The Shadow of the Templars (Demo)"}; +static const PlainGameDescriptor sword1MacFullSettings = + {"sword1mac", "Broken Sword: The Shadow of the Templars (Mac)"}; +static const PlainGameDescriptor sword1MacDemoSettings = + {"sword1macdemo", "Broken Sword: The Shadow of the Templars (Mac demo)"}; +static const PlainGameDescriptor sword1PSXSettings = + {"sword1psx", "Broken Sword: The Shadow of the Templars (PlayStation)"}; +static const PlainGameDescriptor sword1PSXDemoSettings = + {"sword1psxdemo", "Broken Sword: The Shadow of the Templars (PlayStation demo)"}; // check these subdirectories (if present) @@ -117,12 +117,12 @@ bool Sword1::SwordEngine::hasFeature(EngineFeature f) const { GameList SwordMetaEngine::getSupportedGames() const { GameList games; - games.push_back(sword1FullSettings); - games.push_back(sword1DemoSettings); - games.push_back(sword1MacFullSettings); - games.push_back(sword1MacDemoSettings); - games.push_back(sword1PSXSettings); - games.push_back(sword1PSXDemoSettings); + games.push_back(GameDescriptor(sword1FullSettings, Common::GUIO_NOMIDI)); + games.push_back(GameDescriptor(sword1DemoSettings, Common::GUIO_NOMIDI)); + games.push_back(GameDescriptor(sword1MacFullSettings, Common::GUIO_NOMIDI)); + games.push_back(GameDescriptor(sword1MacDemoSettings, Common::GUIO_NOMIDI)); + games.push_back(GameDescriptor(sword1PSXSettings, Common::GUIO_NOMIDI)); + games.push_back(GameDescriptor(sword1PSXDemoSettings, Common::GUIO_NOMIDI)); return games; } @@ -198,17 +198,17 @@ GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const { psxDemoFilesFound = false; if (mainFilesFound && pcFilesFound && demoFilesFound) - detectedGames.push_back(sword1DemoSettings); + detectedGames.push_back(GameDescriptor(sword1DemoSettings, Common::GUIO_NOMIDI)); else if (mainFilesFound && pcFilesFound && psxFilesFound) - detectedGames.push_back(sword1PSXSettings); + detectedGames.push_back(GameDescriptor(sword1PSXSettings, Common::GUIO_NOMIDI)); else if (mainFilesFound && pcFilesFound && psxDemoFilesFound) - detectedGames.push_back(sword1PSXDemoSettings); + detectedGames.push_back(GameDescriptor(sword1PSXDemoSettings, Common::GUIO_NOMIDI)); else if (mainFilesFound && pcFilesFound && !psxFilesFound) - detectedGames.push_back(sword1FullSettings); + detectedGames.push_back(GameDescriptor(sword1FullSettings, Common::GUIO_NOMIDI)); else if (mainFilesFound && macFilesFound) - detectedGames.push_back(sword1MacFullSettings); + detectedGames.push_back(GameDescriptor(sword1MacFullSettings, Common::GUIO_NOMIDI)); else if (mainFilesFound && macDemoFilesFound) - detectedGames.push_back(sword1MacDemoSettings); + detectedGames.push_back(GameDescriptor(sword1MacDemoSettings, Common::GUIO_NOMIDI)); return detectedGames; } diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp index 00f7112c05..5b42c9340e 100644 --- a/engines/sword1/logic.cpp +++ b/engines/sword1/logic.cpp @@ -23,6 +23,7 @@ #include "common/endian.h" #include "common/util.h" #include "common/textconsole.h" +#include "common/translation.h" #include "sword1/logic.h" #include "sword1/text.h" @@ -1629,7 +1630,7 @@ int Logic::fnRestartGame(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 int Logic::fnQuitGame(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d, int32 z, int32 x) { if (SwordEngine::_systemVars.isDemo) { - GUI::MessageDialog dialog("This is the end of the Broken Sword 1 Demo", "OK", NULL); + GUI::MessageDialog dialog(_("This is the end of the Broken Sword 1 Demo"), _("OK"), NULL); dialog.runModal(); Engine::quitGame(); } else diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp index a291d80f85..b4656ff89f 100644 --- a/engines/sword1/music.cpp +++ b/engines/sword1/music.cpp @@ -47,68 +47,65 @@ namespace Sword1 { // These functions are only called from Music, so I'm just going to // assume that if locking is needed it has already been taken care of. -bool MusicHandle::play(const char *fileBase, bool loop) { - char fileName[30]; +bool MusicHandle::play(const Common::String &filename, bool loop) { stop(); // FIXME: How about using AudioStream::openStreamFile instead of the code below? // I.e.: //_audioSource = Audio::AudioStream::openStreamFile(fileBase, 0, 0, loop ? 0 : 1); + Audio::RewindableAudioStream *stream = 0; + #ifdef USE_FLAC - if (!_audioSource) { - sprintf(fileName, "%s.flac", fileBase); - if (_file.open(fileName)) { - _audioSource = Audio::makeLoopingAudioStream(Audio::makeFLACStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); - if (!_audioSource) + if (!stream) { + if (_file.open(filename + ".flac")) { + stream = Audio::makeFLACStream(&_file, DisposeAfterUse::NO); + if (!stream) _file.close(); } } - if (!_audioSource) { - sprintf(fileName, "%s.fla", fileBase); - if (_file.open(fileName)) { - _audioSource = Audio::makeLoopingAudioStream(Audio::makeFLACStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); - if (!_audioSource) + if (!stream) { + if (_file.open(filename + ".fla")) { + stream = Audio::makeFLACStream(&_file, DisposeAfterUse::NO); + if (!stream) _file.close(); } } #endif #ifdef USE_VORBIS - if (!_audioSource) { - sprintf(fileName, "%s.ogg", fileBase); - if (_file.open(fileName)) { - _audioSource = Audio::makeLoopingAudioStream(Audio::makeVorbisStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); - if (!_audioSource) + if (!stream) { + if (_file.open(filename + ".ogg")) { + stream = Audio::makeVorbisStream(&_file, DisposeAfterUse::NO); + if (!stream) _file.close(); } } #endif #ifdef USE_MAD - if (!_audioSource) { - sprintf(fileName, "%s.mp3", fileBase); - if (_file.open(fileName)) { - _audioSource = Audio::makeLoopingAudioStream(Audio::makeMP3Stream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); - if (!_audioSource) + if (!stream) { + if (_file.open(filename + ".mp3")) { + stream = Audio::makeMP3Stream(&_file, DisposeAfterUse::NO); + if (!stream) _file.close(); } } #endif - if (!_audioSource) { - sprintf(fileName, "%s.wav", fileBase); - if (_file.open(fileName)) - _audioSource = Audio::makeLoopingAudioStream(Audio::makeWAVStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); + if (!stream) { + if (_file.open(filename + ".wav")) + stream = Audio::makeWAVStream(&_file, DisposeAfterUse::NO); } - if (!_audioSource) { - sprintf(fileName, "%s.aif", fileBase); - if (_file.open(fileName)) - _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); + if (!stream) { + if (_file.open(filename + ".aif")) + stream = Audio::makeAIFFStream(&_file, DisposeAfterUse::NO); } - if (!_audioSource) + if (!stream) return false; + _audioSource = Audio::makeLoopingAudioStream(stream, loop ? 0 : 1); + fadeUp(); return true; } @@ -219,12 +216,9 @@ int MusicHandle::readBuffer(int16 *buffer, const int numSamples) { } void MusicHandle::stop() { - if (_audioSource) { - delete _audioSource; - _audioSource = NULL; - } - if (_file.isOpen()) - _file.close(); + delete _audioSource; + _audioSource = NULL; + _file.close(); _fading = 0; } diff --git a/engines/sword1/music.h b/engines/sword1/music.h index 104bc1c536..4207019c13 100644 --- a/engines/sword1/music.h +++ b/engines/sword1/music.h @@ -43,7 +43,7 @@ private: public: MusicHandle() : _fading(0), _audioSource(NULL) {} virtual int readBuffer(int16 *buffer, const int numSamples); - bool play(const char *filename, bool loop); + bool play(const Common::String &filename, bool loop); bool playPSX(uint16 id, bool loop); void stop(); void fadeUp(); diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp index 11ee4a98fd..133abf165e 100644 --- a/engines/sword2/animation.cpp +++ b/engines/sword2/animation.cpp @@ -26,6 +26,7 @@ #include "common/mutex.h" #include "common/system.h" #include "common/textconsole.h" +#include "common/translation.h" #include "sword2/sword2.h" #include "sword2/defs.h" @@ -359,7 +360,6 @@ uint32 DXADecoderWithSound::getElapsedTime() const { MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system) { Common::String filename; - char buf[60]; Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle; filename = Common::String::format("%s.smk", name); @@ -376,7 +376,7 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *s DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle); return new MoviePlayer(vm, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA); #else - GUI::MessageDialog dialog("DXA cutscenes found but ScummVM has been built without zlib support", "OK"); + GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK")); dialog.runModal(); return NULL; #endif @@ -386,7 +386,7 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *s filename = Common::String::format("%s.mp2", name); if (Common::File::exists(filename)) { - GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK"); + GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK")); dialog.runModal(); return NULL; } @@ -394,8 +394,8 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *s // The demo tries to play some cutscenes that aren't there, so make those warnings more discreet. // In addition, some of the later re-releases of the game don't have the "eye" Virgin logo movie. if (!vm->_logic->readVar(DEMO) && strcmp(name, "eye") != 0) { - sprintf(buf, "Cutscene '%s' not found", name); - GUI::MessageDialog dialog(buf, "OK"); + Common::String buf = Common::String::format(_("Cutscene '%s' not found"), name); + GUI::MessageDialog dialog(buf, _("OK")); dialog.runModal(); } else warning("Cutscene '%s' not found", name); diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp index c704b3e833..b2f5795663 100644 --- a/engines/sword25/detection.cpp +++ b/engines/sword25/detection.cpp @@ -44,9 +44,9 @@ static const char *directoryGlobs[] = { class Sword25MetaEngine : public AdvancedMetaEngine { public: Sword25MetaEngine() : AdvancedMetaEngine(Sword25::gameDescriptions, sizeof(ADGameDescription), sword25Game) { - params.guioptions = Common::GUIO_NOMIDI; - params.depth = 2; - params.directoryGlobs = directoryGlobs; + _guioptions = Common::GUIO_NOMIDI; + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; } virtual const char *getName() const { return "Sword25"; diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp index b684560bc7..72a338664b 100644 --- a/engines/teenagent/detection.cpp +++ b/engines/teenagent/detection.cpp @@ -86,7 +86,7 @@ enum { class TeenAgentMetaEngine : public AdvancedMetaEngine { public: TeenAgentMetaEngine() : AdvancedMetaEngine(teenAgentGameDescriptions, sizeof(ADGameDescription), teenAgentGames) { - params.singleid = "teenagent"; + _singleid = "teenagent"; } virtual const char *getName() const { @@ -117,10 +117,6 @@ public: return desc != 0; } -// virtual const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const { -// return 0; -// } - static Common::String generateGameStateFileName(const char *target, int slot) { return Common::String::format("%s.%02d", target, slot); } diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp index 2c3d5b43c5..b869bb8ebb 100644 --- a/engines/testbed/detection.cpp +++ b/engines/testbed/detection.cpp @@ -48,8 +48,8 @@ static const ADGameDescription testbedDescriptions[] = { class TestbedMetaEngine : public AdvancedMetaEngine { public: TestbedMetaEngine() : AdvancedMetaEngine(testbedDescriptions, sizeof(ADGameDescription), testbed_setting) { - params.md5Bytes = 512; - params.singleid = "testbed"; + _md5Bytes = 512; + _singleid = "testbed"; } virtual const char *getName() const { diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 59a567bc63..9c52305a1c 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -77,7 +77,7 @@ static const PlainGameDescriptor tinselGames[] = { class TinselMetaEngine : public AdvancedMetaEngine { public: TinselMetaEngine() : AdvancedMetaEngine(Tinsel::gameDescriptions, sizeof(Tinsel::TinselGameDescription), tinselGames) { - params.singleid = "tinsel"; + _singleid = "tinsel"; } virtual const char *getName() const { @@ -89,7 +89,7 @@ public: } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const; + const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; virtual bool hasFeature(MetaEngineFeature f) const; virtual SaveStateList listSaves(const char *target) const; @@ -175,7 +175,7 @@ typedef Common::Array<const ADGameDescription*> ADGameDescList; * Fallback detection scans the list of Discworld 2 targets to see if it can detect an installation * where the files haven't been renamed (i.e. don't have the '1' just before the extension) */ -const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &fslist) const { +const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const { Common::String extra; FileMap allFiles; SizeMD5Map filesSizeMD5; @@ -242,7 +242,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList & if (testFile.open(allFiles[fname])) { tmp.size = (int32)testFile.size(); - tmp.md5 = computeStreamMD5AsString(testFile, params.md5Bytes); + tmp.md5 = computeStreamMD5AsString(testFile, _md5Bytes); } else { tmp.size = -1; } @@ -262,11 +262,6 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList & bool fileMissing = false; - if ((params.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->desc.extra != extra) - continue; - - bool allFilesPresent = true; - // Try to match all files for this game for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character @@ -284,7 +279,6 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList & if (!filesSizeMD5.contains(tstr)) { fileMissing = true; - allFilesPresent = false; break; } diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp index caaf9a13f8..1244168a21 100644 --- a/engines/tinsel/saveload.cpp +++ b/engines/tinsel/saveload.cpp @@ -34,6 +34,7 @@ #include "common/serializer.h" #include "common/savefile.h" #include "common/textconsole.h" +#include "common/translation.h" #include "gui/message.h" @@ -464,7 +465,7 @@ static bool DoRestore() { delete f; if (failed) { - GUI::MessageDialog dialog("Failed to load game state from file."); + GUI::MessageDialog dialog(_("Failed to load game state from file.")); dialog.runModal(); } @@ -542,7 +543,7 @@ save_failure: _vm->getSaveFileMan()->removeSavefile(SaveSceneName); SaveSceneName = NULL; // Invalidate save name } - GUI::MessageDialog dialog("Failed to save game state to file."); + GUI::MessageDialog dialog(_("Failed to save game state to file.")); dialog.runModal(); } diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp index 8ddfcd4fed..810a37720a 100644 --- a/engines/toon/detection.cpp +++ b/engines/toon/detection.cpp @@ -120,11 +120,15 @@ static const char * const directoryGlobs[] = { class ToonMetaEngine : public AdvancedMetaEngine { public: ToonMetaEngine() : AdvancedMetaEngine(Toon::gameDescriptions, sizeof(ADGameDescription), toonGames) { - params.singleid = "toon"; - params.fileBasedFallback = Toon::fileBasedFallback; - params.depth = 3; - params.directoryGlobs = directoryGlobs; + _singleid = "toon"; + _maxScanDepth = 3; + _directoryGlobs = directoryGlobs; } + + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + return detectGameFilebased(allFiles, Toon::fileBasedFallback); + } + virtual const char *getName() const { return "Toon"; } diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index 3e324b5685..0684144473 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -24,6 +24,7 @@ #include "engines/advancedDetector.h" #include "common/savefile.h" #include "common/system.h" +#include "common/translation.h" #include "base/plugins.h" @@ -129,13 +130,29 @@ static const char *directoryGlobs[] = { class ToucheMetaEngine : public AdvancedMetaEngine { public: ToucheMetaEngine() : AdvancedMetaEngine(Touche::gameDescriptions, sizeof(ADGameDescription), toucheGames) { - params.md5Bytes = 4096; - params.singleid = "touche"; - params.fileBasedFallback = Touche::fileBasedFallback; - params.flags = kADFlagPrintWarningOnFileBasedFallback; - params.depth = 2; - params.directoryGlobs = directoryGlobs; + _md5Bytes = 4096; + _singleid = "touche"; + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; } + + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + const ADGameDescription *matchedDesc = detectGameFilebased(allFiles, Touche::fileBasedFallback); + + if (matchedDesc) { // We got a match + Common::String report = Common::String::format(_("Your game version has been detected using " + "filename matching as a variant of %s."), matchedDesc->gameid); + report += "\n"; + report += _("If this is an original and unmodified version, please report any"); + report += "\n"; + report += _("information previously printed by ScummVM to the team."); + report += "\n"; + g_system->logMessage(LogMessageType::kInfo, report.c_str()); + } + + return matchedDesc; + } + virtual const char *getName() const { return "Touche"; } diff --git a/engines/touche/touche.h b/engines/touche/touche.h index 7e1aa3ac44..cbb3fec7aa 100644 --- a/engines/touche/touche.h +++ b/engines/touche/touche.h @@ -385,8 +385,6 @@ public: protected: - bool detectGame(); - void restart(); void readConfigurationSettings(); void writeConfigurationSettings(); diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp index e9e80312b9..aaa9030a04 100644 --- a/engines/tsage/detection.cpp +++ b/engines/tsage/detection.cpp @@ -73,9 +73,9 @@ enum { class TSageMetaEngine : public AdvancedMetaEngine { public: TSageMetaEngine() : AdvancedMetaEngine(tSage::gameDescriptions, sizeof(tSage::tSageGameDescription), tSageGameTitles) { - params.md5Bytes = 5000; - params.singleid = "tsage"; - params.guioptions = Common::GUIO_NOSPEECH; + _md5Bytes = 5000; + _singleid = "tsage"; + _guioptions = Common::GUIO_NOSPEECH; } virtual const char *getName() const { diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index 3eb3973371..4a3313e3f7 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -115,8 +115,8 @@ static const ADGameDescription tuckerDemoGameDescription = { class TuckerMetaEngine : public AdvancedMetaEngine { public: TuckerMetaEngine() : AdvancedMetaEngine(tuckerGameDescriptions, sizeof(ADGameDescription), tuckerGames) { - params.md5Bytes = 512; - params.singleid = "tucker"; + _md5Bytes = 512; + _singleid = "tucker"; } virtual const char *getName() const { @@ -145,7 +145,7 @@ public: return desc != 0; } - virtual const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const { + virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { for (Common::FSList::const_iterator d = fslist.begin(); d != fslist.end(); ++d) { Common::FSList audiofslist; if (d->isDirectory() && d->getName().equalsIgnoreCase("audio") && d->getChildren(audiofslist, Common::FSNode::kListFilesOnly)) { |