GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { ADGameDescList matches = detectGame(fslist, params, Common::UNK_LANG, Common::kPlatformUnknown, ""); GameList detectedGames; if (cleanupPirated(matches)) return detectedGames; if (matches.empty()) { // Use fallback detector if there were no matches by other means const ADGameDescription *fallbackDesc = fallbackDetect(fslist); if (fallbackDesc != 0) { GameDescriptor desc(toGameDescriptor(*fallbackDesc, params.list)); updateGameDescriptor(desc, fallbackDesc, params); detectedGames.push_back(desc); } } else { // Otherwise use the found matches for (uint i = 0; i < matches.size(); i++) { GameDescriptor desc(toGameDescriptor(*matches[i], params.list)); updateGameDescriptor(desc, matches[i], params); detectedGames.push_back(desc); } } return detectedGames; }
GameList QueenMetaEngine::detectGames(const Common::FSList &fslist) const { GameList detectedGames; // Iterate over all files in the given directory for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { continue; } if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) { Common::File dataFile; if (!dataFile.open(*file)) { continue; } Queen::DetectedGameVersion version; if (Queen::Resource::detectVersion(&version, &dataFile)) { GameDescriptor dg(queenGameDescriptor.gameid, queenGameDescriptor.description, version.language, version.platform); if (version.features & Queen::GF_DEMO) { dg.updateDesc("Demo"); dg.setGUIOptions(Common::GUIO_NOSPEECH); } else if (version.features & Queen::GF_INTERVIEW) { dg.updateDesc("Interview"); dg.setGUIOptions(Common::GUIO_NOSPEECH); } else if (version.features & Queen::GF_FLOPPY) { dg.updateDesc("Floppy"); dg.setGUIOptions(Common::GUIO_NOSPEECH); } else if (version.features & Queen::GF_TALKIE) { dg.updateDesc("Talkie"); } detectedGames.push_back(dg); break; } } } return detectedGames; }
GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { ADGameDescList matches; GameList detectedGames; FileMap allFiles; 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(allFiles, fslist); if (fallbackDesc != 0) { 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], _gameIds)); updateGameDescriptor(desc, matches[i]); detectedGames.push_back(desc); } } return detectedGames; }
static int findGames(Game *games, int max) { Dir *dirs = new Dir[MAX_DIR]; int curr_game = 0, curr_dir = 0, num_dirs = 1; dirs[0].node = Common::FSNode(""); while (curr_game < max && curr_dir < num_dirs) { strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().c_str(), 252); dirs[curr_dir].name[251] = '\0'; dirs[curr_dir].deficon[0] = '\0'; Common::FSList files, fslist; dirs[curr_dir++].node.getChildren(fslist, Common::FSNode::kListAll); for (Common::FSList::const_iterator entry = fslist.begin(); entry != fslist.end(); ++entry) { if (entry->isDirectory()) { if (num_dirs < MAX_DIR && strcasecmp(entry->getDisplayName().c_str(), "install")) { dirs[num_dirs].node = *entry; num_dirs++; } } else if (isIcon(*entry)) strcpy(dirs[curr_dir-1].deficon, entry->getDisplayName().c_str()); else files.push_back(*entry); } GameList candidates = EngineMan.detectGames(files); for (GameList::const_iterator ge = candidates.begin(); ge != candidates.end(); ++ge) if (curr_game < max) { strcpy(games[curr_game].filename_base, ge->gameid().c_str()); strcpy(games[curr_game].dir, dirs[curr_dir-1].name); games[curr_game].language = ge->language(); games[curr_game].platform = ge->platform(); if (uniqueGame(games[curr_game].filename_base, games[curr_game].dir, games[curr_game].language, games[curr_game].platform, games, curr_game)) { strcpy(games[curr_game].text, ge->description().c_str()); #if 0 printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n", games[curr_game].text, (int)games[curr_game].language, (int)games[curr_game].platform, games[curr_game].dir, games[curr_game].filename_base, dirs[curr_dir-1].name); #endif curr_game++; } } } for (int i=0; i<curr_game; i++) if (!loadIcon(games[i], dirs, num_dirs)) makeDefIcon(games[i].icon); delete[] dirs; return curr_game; }
GameList Sword2MetaEngine::getSupportedGames() const { const Sword2::GameSettings *g = Sword2::sword2_settings; GameList games; while (g->gameid) { games.push_back(GameDescriptor(g->gameid, g->description)); g++; } return games; }
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); return games; }
GameList SwordMetaEngine::getSupportedGames() const { GameList games; games.push_back(GameDescriptor(getEngineID(), sword1FullSettings, GUIO_NOMIDI)); games.push_back(GameDescriptor(getEngineID(), sword1DemoSettings, GUIO_NOMIDI)); games.push_back(GameDescriptor(getEngineID(), sword1MacFullSettings, GUIO_NOMIDI)); games.push_back(GameDescriptor(getEngineID(), sword1MacDemoSettings, GUIO_NOMIDI)); games.push_back(GameDescriptor(getEngineID(), sword1PSXSettings, GUIO_NOMIDI)); games.push_back(GameDescriptor(getEngineID(), sword1PSXDemoSettings, GUIO_NOMIDI)); return games; }
GameList Engine_GOB_gameIDList() { GameList games; const PlainGameDescriptor *g = gob_list; while (g->gameid) { games.push_back(*g); g++; } return games; }
GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const { GameList detectedGames; Common::List<DetectorResult> results; ::detectGames(fslist, results, 0); // TODO: We still don't handle the FM-TOWNS demos (like zakloom) very well. // In particular, they are detected as ZakTowns, which is bad. for (Common::List<DetectorResult>::iterator x = results.begin(); x != results.end(); ++x) { const PlainGameDescriptor *g = findPlainGameDescriptor(x->game.gameid, gameDescriptions); assert(g); GameDescriptor dg(x->game.gameid, g->description, x->language, x->game.platform); // Append additional information, if set, to the description. dg.updateDesc(x->extra); // Compute and set the preferred target name for this game. // Based on generateComplexID() in advancedDetector.cpp. dg["preferredtarget"] = generatePreferredTarget(*x); // HACK: Detect and distinguish the FM-TOWNS demos if (x->game.platform == Common::kPlatformFMTowns && (x->game.features & GF_DEMO)) { if (x->md5 == "2d388339d6050d8ccaa757b64633954e") { // Indy + Loom demo dg.description() = "Indiana Jones and the Last Crusade & Loom"; dg.updateDesc(x->extra); dg["preferredtarget"] = "indyloom"; } else if (x->md5 == "77f5c9cc0986eb729c1a6b4c8823bbae") { // Zak + Loom demo dg.description() = "Zak McKracken & Loom"; dg.updateDesc(x->extra); dg["preferredtarget"] = "zakloom"; } else if (x->md5 == "3938ee1aa4433fca9d9308c9891172b1") { // Indy + Zak demo dg.description() = "Indiana Jones and the Last Crusade & Zak McKracken"; dg.updateDesc(x->extra); dg["preferredtarget"] = "indyzak"; } } dg.setGUIOptions(x->game.guioptions | MidiDriver::musicType2GUIO(x->game.midi)); dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); detectedGames.push_back(dg); } return detectedGames; }
GameList SkyMetaEngine::detectGames(const Common::FSList &fslist) const { GameList detectedGames; bool hasSkyDsk = false; bool hasSkyDnr = false; int dinnerTableEntries = -1; int dataDiskSize = -1; // Iterate over all files in the given directory for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { const char *fileName = file->getName().c_str(); if (0 == scumm_stricmp("sky.dsk", fileName)) { Common::File dataDisk; if (dataDisk.open(*file)) { hasSkyDsk = true; dataDiskSize = dataDisk.size(); } } if (0 == scumm_stricmp("sky.dnr", fileName)) { Common::File dinner; if (dinner.open(*file)) { hasSkyDnr = true; dinnerTableEntries = dinner.readUint32LE(); } } } } if (hasSkyDsk && hasSkyDnr) { // Match found, add to list of candidates, then abort inner loop. // The game detector uses US English by default. We want British // English to match the recorded voices better. GameDescriptor dg("sky", skySetting.gameid, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown); const SkyVersion *sv = skyVersions; while (sv->dinnerTableEntries) { if (dinnerTableEntries == sv->dinnerTableEntries && (sv->dataDiskSize == dataDiskSize || sv->dataDiskSize == -1)) { dg.updateDesc(Common::String::format("v0.0%d %s", sv->version, sv->extraDesc).c_str()); dg.setGUIOptions(sv->guioptions); break; } ++sv; } detectedGames.push_back(dg); } return detectedGames; }
GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { GameList detectedGames; const Sword2::GameSettings *g; Common::FSList::const_iterator file; // TODO: It would be nice if we had code here which distinguishes // between the 'sword2' and 'sword2demo' targets. The current code // can't do that since they use the same detectname. for (g = Sword2::sword2_settings; g->gameid; ++g) { // Iterate over all files in the given directory for (file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { const char *fileName = file->getName().c_str(); if (0 == scumm_stricmp(g->detectname, fileName)) { // Match found, add to list of candidates, then abort inner loop. detectedGames.push_back(GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, Common::GUIO_NOMIDI)); break; } } } } if (detectedGames.empty()) { // Nothing found -- try to recurse into the 'clusters' subdirectory, // present e.g. if the user copied the data straight from CD. for (file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { const char *fileName = file->getName().c_str(); if (0 == scumm_stricmp("clusters", fileName)) { Common::FSList recList; if (file->getChildren(recList, Common::FSNode::kListAll)) { GameList recGames(detectGames(recList)); if (!recGames.empty()) { detectedGames.push_back(recGames); break; } } } } } } return detectedGames; }
/** * Returns list of targets supported by the engine. * Distinguishes engines with single ID */ static GameList gameIDList(const ADParams ¶ms) { if (params.singleid != NULL) { GameList gl; const PlainGameDescriptor *g = params.list; while (g->gameid) { if (0 == scumm_stricmp(params.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); } return GameList(params.list); }
GameList AdvancedMetaEngine::getSupportedGames() const { if (_singleId != NULL) { GameList gl; const PlainGameDescriptor *g = _gameIds; while (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", _singleId); } return GameList(_gameIds); }
Common::Error Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(syst); assert(engine); Common::FSList fslist; Common::FSNode dir(ConfMan.get("path")); if (!dir.getChildren(fslist, Common::FSNode::kListAll)) { return Common::kNoGameDataFoundError; } // Invoke the detector Common::String gameid = ConfMan.get("gameid"); GameList detectedGames = detectGames(fslist); for (uint i = 0; i < detectedGames.size(); i++) { if (detectedGames[i].gameid() == gameid) { *engine = new Sword2::Sword2Engine(syst); return Common::kNoError; } } return Common::kNoGameDataFoundError; }
GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const { int i, j; GameList detectedGames; bool filesFound[NUM_FILES_TO_CHECK]; for (i = 0; i < NUM_FILES_TO_CHECK; i++) filesFound[i] = false; Sword1CheckDirectory(fslist, filesFound); bool mainFilesFound = true; bool pcFilesFound = true; bool macFilesFound = true; bool demoFilesFound = true; bool macDemoFilesFound = true; bool psxFilesFound = true; bool psxDemoFilesFound = true; for (i = 0; i < NUM_COMMON_FILES_TO_CHECK; i++) if (!filesFound[i]) mainFilesFound = false; for (j = 0; j < NUM_PC_FILES_TO_CHECK; i++, j++) if (!filesFound[i]) pcFilesFound = false; for (j = 0; j < NUM_MAC_FILES_TO_CHECK; i++, j++) if (!filesFound[i]) macFilesFound = false; for (j = 0; j < NUM_DEMO_FILES_TO_CHECK; i++, j++) if (!filesFound[i]) demoFilesFound = false; for (j = 0; j < NUM_DEMO_FILES_TO_CHECK; i++, j++) if (!filesFound[i]) macDemoFilesFound = false; for (j = 0; j < NUM_PSX_FILES_TO_CHECK; i++, j++) if (!filesFound[i]) psxFilesFound = false; for (j = 0; j < NUM_PSX_DEMO_FILES_TO_CHECK; i++, j++) if (!filesFound[i] || psxFilesFound) psxDemoFilesFound = false; if (mainFilesFound && pcFilesFound && demoFilesFound) detectedGames.push_back(GameDescriptor(getEngineID(), sword1DemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); else if (mainFilesFound && pcFilesFound && psxFilesFound) detectedGames.push_back(GameDescriptor(getEngineID(), sword1PSXSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); else if (mainFilesFound && pcFilesFound && psxDemoFilesFound) detectedGames.push_back(GameDescriptor(getEngineID(), sword1PSXDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); else if (mainFilesFound && pcFilesFound && !psxFilesFound) detectedGames.push_back(GameDescriptor(getEngineID(), sword1FullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); else if (mainFilesFound && macFilesFound) detectedGames.push_back(GameDescriptor(getEngineID(), sword1MacFullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); else if (mainFilesFound && macDemoFilesFound) detectedGames.push_back(GameDescriptor(getEngineID(), sword1MacDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); return detectedGames; }
GameList SkyMetaEngine::getSupportedGames() const { GameList games; games.push_back(GameDescriptor("sky", skySetting)); return games; }
GameList QueenMetaEngine::getSupportedGames() const { GameList games; games.push_back(queenGameDescriptor); return games; }
GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { GameList detectedGames; const Sword2::GameSettings *g; Common::FSList::const_iterator file; bool isFullVersion = isFullGame(fslist); for (g = Sword2::sword2_settings; g->gameid; ++g) { // Iterate over all files in the given directory for (file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { // The required game data files can be located in the game directory, or in // a subdirectory called "clusters". In the latter case, we don't want to // detect the game in that subdirectory, as this will detect the game twice // when mass add is searching inside a directory. In this case, the first // result (the game directory) will be correct, but the second result (the // clusters subdirectory) will be wrong, as the optional speech, music and // video data files will be ignored. Note that this fix will skip the game // data files if the user has placed them inside a "clusters" subdirectory, // or if he/she points ScummVM directly to the "clusters" directory of the // game CD. Fixes bug #3049336. Common::String directory = file->getParent().getName(); directory.toLowercase(); if (directory.hasPrefix("clusters") && directory.size() <= 9 && !recursion) continue; if (file->getName().equalsIgnoreCase(g->detectname)) { // Make sure that the sword2 demo is not mixed up with the // full version, since they use the same filename for detection if ((g->features == Sword2::GF_DEMO && isFullVersion) || (g->features == 0 && !isFullVersion)) continue; // Match found, add to list of candidates, then abort inner loop. detectedGames.push_back(GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); break; } } } } if (detectedGames.empty()) { // Nothing found -- try to recurse into the 'clusters' subdirectory, // present e.g. if the user copied the data straight from CD. for (file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { if (file->getName().equalsIgnoreCase("clusters")) { Common::FSList recList; if (file->getChildren(recList, Common::FSNode::kListAll)) { GameList recGames(detectGamesImpl(recList, true)); if (!recGames.empty()) { detectedGames.push_back(recGames); break; } } } } } } return detectedGames; }
GameList Engine_SWORD1_gameIDList() { GameList games; games.push_back(sword1FullSettings); games.push_back(sword1DemoSettings); return games; }
GameList SkyMetaEngine::getSupportedGames() const { GameList games; games.push_back(skySetting); return games; }