本文整理汇总了C++中common::FSList::begin方法的典型用法代码示例。如果您正苦于以下问题:C++ FSList::begin方法的具体用法?C++ FSList::begin怎么用?C++ FSList::begin使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类common::FSList
的用法示例。
在下文中一共展示了FSList::begin方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: composeFileHashMap
void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName) const {
if (depth <= 0)
return;
if (fslist.empty())
return;
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
Common::String tstr = (_matchFullPaths && !parentName.empty() ? parentName + "/" : "") + file->getName();
if (file->isDirectory()) {
Common::FSList files;
if (!_directoryGlobs)
continue;
bool matched = false;
for (const char * const *glob = _directoryGlobs; *glob; glob++)
if (file->getName().matchString(*glob, true)) {
matched = true;
break;
}
if (!matched)
continue;
if (!file->getChildren(files, Common::FSNode::kListAll))
continue;
composeFileHashMap(allFiles, files, depth - 1, tstr);
}
// Strip any trailing dot
if (tstr.lastChar() == '.')
tstr.deleteLastChar();
allFiles[tstr] = *file; // Record the presence of this file
}
}
示例2: registerPackages
bool BaseFileManager::registerPackages() {
debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Scanning packages");
// Register without using SearchMan, as otherwise the FSNode-based lookup in openPackage will fail
// and that has to be like that to support the detection-scheme.
Common::FSList files;
for (Common::FSList::iterator it = _packagePaths.begin(); it != _packagePaths.end(); ++it) {
debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", (*it).getPath().c_str(), (*it).getName().c_str());
(*it).getChildren(files, Common::FSNode::kListFilesOnly);
for (Common::FSList::iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
if (!fileIt->getName().hasSuffix(".dcp")) {
continue;
}
// Avoid registering all the language files
// TODO: Select based on the gameDesc.
if (_language != Common::UNK_LANG && fileIt->getParent().getName() == "language") {
Common::String parentName = fileIt->getParent().getName();
Common::String dcpName = fileIt->getName();
if (_language == Common::EN_ANY && fileIt->getName() != "english.dcp") {
continue;
} else if (_language == Common::CZ_CZE && fileIt->getName() != "czech.dcp") {
continue;
} else if (_language == Common::IT_ITA && fileIt->getName() != "italian.dcp") {
continue;
} else if (_language == Common::PL_POL && fileIt->getName() != "polish.dcp") {
continue;
} else if (_language == Common::RU_RUS && fileIt->getName() != "russian.dcp") {
continue;
}
}
debugC(kWintermuteDebugFileAccess, "Registering %s %s", (*fileIt).getPath().c_str(), (*fileIt).getName().c_str());
registerPackage((*fileIt));
}
}
// debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, " Registered %d files in %d package(s)", _files.size(), _packages.size());
return STATUS_OK;
}
示例3: directory
Common::HashMap<Common::String, Score *> DirectorEngine::loadMMMNames(Common::String folder) {
Common::FSNode directory(folder);
Common::FSList movies;
Common::HashMap<Common::String, Score *> nameMap;
directory.getChildren(movies, Common::FSNode::kListFilesOnly);
if (!movies.empty()) {
for (Common::FSList::const_iterator i = movies.begin(); i != movies.end(); ++i) {
if (i->getName() == _sharedMMM) {
loadSharedCastsFrom(i->getPath());
continue;
}
RIFFArchive *arc = new RIFFArchive();
arc->openFile(i->getPath());
Score *sc = new Score(this);
nameMap[sc->getMacName()] = sc;
}
}
return nameMap;
}
示例4: directory
Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Common::String &folder) {
Common::FSNode directory(folder);
Common::FSList movies;
const char *sharedMMMname;
if (getPlatform() == Common::kPlatformWindows)
sharedMMMname = "SHARDCST.MMM";
else
sharedMMMname = "Shared Cast*";
Common::HashMap<Common::String, Score *> *nameMap = new Common::HashMap<Common::String, Score *>();
if (!directory.getChildren(movies, Common::FSNode::kListFilesOnly))
return nameMap;
if (!movies.empty()) {
for (Common::FSList::const_iterator i = movies.begin(); i != movies.end(); ++i) {
debugC(2, kDebugLoading, "File: %s", i->getName().c_str());
if (Common::matchString(i->getName().c_str(), sharedMMMname, true)) {
_sharedCastFile = i->getName();
continue;
}
Archive *arc = createArchive();
warning("name: %s", i->getName().c_str());
arc->openFile(i->getName());
Score *sc = new Score(this, arc);
nameMap->setVal(sc->getMacName(), sc);
debugC(2, kDebugLoading, "Movie name: \"%s\"", sc->getMacName().c_str());
}
}
return nameMap;
}
示例5: detectGames
bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
const char *const EXTENSIONS[] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8",
".dat", ".zip", nullptr };
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
// Check for a recognised filename
if (file->isDirectory())
continue;
Common::String filename = file->getName();
bool hasExt = Blorb::hasBlorbExt(filename), isBlorb = false;
for (const char *const *ext = &EXTENSIONS[0]; *ext && !hasExt; ++ext)
hasExt = filename.hasSuffixIgnoreCase(*ext);
if (!hasExt)
continue;
// Open up the file and calculate the md5, and get the serial
Common::File gameFile;
if (!gameFile.open(*file))
continue;
Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
size_t filesize = gameFile.size();
char serial[9] = "";
bool emptyBlorb = false;
gameFile.seek(0);
isBlorb = Blorb::isBlorb(gameFile, ID_ZCOD);
if (!isBlorb) {
if (Blorb::hasBlorbExt(filename)) {
gameFile.close();
continue;
}
gameFile.seek(18);
strcpy(&serial[0], "\"");
gameFile.read(&serial[1], 6);
strcpy(&serial[7], "\"");
} else {
Blorb b(*file, INTERPRETER_FROTZ);
Common::SeekableReadStream *f = b.createReadStreamForMember("game");
emptyBlorb = f == nullptr;
if (!emptyBlorb) {
f->seek(18);
strcpy(&serial[0], "\"");
f->read(&serial[1], 6);
strcpy(&serial[7], "\"");
delete f;
}
}
gameFile.close();
// Check for known games. Note that there has been some variation in exact filesizes
// for Infocom games due to padding at the end of files. So we match on md5s for the
// first 5Kb, and only worry about filesize for more recent Blorb based Zcode games
const FrotzGameDescription *p = FROTZ_GAMES;
while (p->_gameId && p->_md5 && (md5 != p->_md5 ||
(filesize != p->_filesize && isBlorb)))
++p;
DetectedGame gd;
if (!p->_gameId) {
// Generic .dat/.zip files don't get reported as matches unless they have a known md5
if (filename.hasSuffixIgnoreCase(".dat") || filename.hasSuffixIgnoreCase(".zip") || emptyBlorb)
continue;
if (gDebugLevel > 0) {
// Print an entry suitable for putting into the detection_tables.h, using the
// name of the parent folder the game is in as the presumed game Id
Common::String folderName = file->getParent().getName();
if (folderName.hasSuffix("\\"))
folderName.deleteLastChar();
Common::String fname = filename;
const char *dot = strchr(fname.c_str(), '.');
if (dot)
fname = Common::String(fname.c_str(), dot);
debug("ENTRY0(\"%s\", %s, \"%s\", %u),",
fname.c_str(), strlen(serial) ? serial : "nullptr", md5.c_str(), (uint)filesize);
}
const PlainGameDescriptor &desc = ZCODE_GAME_LIST[0];
gd = DetectedGame(desc.gameId, desc.description, Common::UNK_LANG, Common::kPlatformUnknown);
} else {
GameDescriptor gameDesc = findGame(p->_gameId);
gd = DetectedGame(p->_gameId, gameDesc._description, p->_language, Common::kPlatformUnknown, p->_extra);
gd.setGUIOptions(p->_guiOptions);
}
gd.addExtraEntry("filename", filename);
gameList.push_back(gd);
}
return !gameList.empty();
}
示例6: detectGame
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra) {
FileMap allFiles;
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.
// Includes nifty stuff like removing trailing dots and ignoring case.
composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth), params.directoryGlobs);
// 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) {
g = (const ADGameDescription *)descPtr;
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
Common::String fname = fileDesc->fileName;
SizeMD5 tmp;
if (filesSizeMD5.contains(fname))
continue;
// FIXME/TODO: We don't handle the case that a file is listed as a regular
// file and as one with resource fork.
if (g->flags & ADGF_MACRESFORK) {
Common::MacResManager *macResMan = new Common::MacResManager();
if (macResMan->open(parent, fname)) {
tmp.md5 = macResMan->computeResForkMD5AsString(params.md5Bytes);
tmp.size = macResMan->getResForkDataSize();
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str());
filesSizeMD5[fname] = tmp;
}
delete macResMan;
} else {
if (allFiles.contains(fname)) {
debug(3, "+ %s", fname.c_str());
Common::File testFile;
if (testFile.open(allFiles[fname])) {
tmp.size = (int32)testFile.size();
tmp.md5 = Common::computeStreamMD5AsString(testFile, params.md5Bytes);
} else {
tmp.size = -1;
}
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str());
filesSizeMD5[fname] = tmp;
}
}
}
}
ADGameDescList matched;
int maxFilesMatched = 0;
bool gotAnyMatchesWithAllFiles = false;
// MD5 based matching
uint i;
for (i = 0, descPtr = params.descs; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += params.descItemSize, ++i) {
g = (const ADGameDescription *)descPtr;
bool fileMissing = false;
// Do not even bother to look at entries which do not have matching
// language and platform (if specified).
if ((language != Common::UNK_LANG && g->language != Common::UNK_LANG && g->language != language
&& !(language == Common::EN_ANY && (g->flags & ADGF_ADDENGLISH))) ||
(platform != Common::kPlatformUnknown && g->platform != Common::kPlatformUnknown && g->platform != platform)) {
continue;
}
if ((params.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra)
continue;
bool allFilesPresent = true;
int curFilesMatched = 0;
// Try to match all files for this game
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
Common::String tstr = fileDesc->fileName;
if (!filesSizeMD5.contains(tstr)) {
fileMissing = true;
allFilesPresent = false;
break;
}
if (fileDesc->md5 != NULL && fileDesc->md5 != filesSizeMD5[tstr].md5) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesSizeMD5[tstr].md5.c_str());
fileMissing = true;
//.........这里部分代码省略.........
示例7: createInstance
Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(engine);
const ADGameDescription *agdDesc = 0;
Common::Language language = Common::UNK_LANG;
Common::Platform platform = Common::kPlatformUnknown;
Common::String extra;
if (ConfMan.hasKey("language"))
language = Common::parseLanguage(ConfMan.get("language"));
if (ConfMan.hasKey("platform"))
platform = Common::parsePlatform(ConfMan.get("platform"));
if (_flags & kADFlagUseExtraAsHint) {
if (ConfMan.hasKey("extra"))
extra = ConfMan.get("extra");
}
Common::String gameid = ConfMan.get("gameid");
Common::String path;
if (ConfMan.hasKey("path")) {
path = ConfMan.get("path");
} else {
path = ".";
// This situation may happen only when game was
// launched from a command line with wrong target and
// no path was provided.
//
// A dummy entry will get created and will keep game path
// We mark this entry, so it will not be added to the
// config file.
//
// Fixes bug #1544799
ConfMan.setBool("autoadded", true);
warning("No path was provided. Assuming the data files are in the current directory");
}
Common::FSNode dir(path);
Common::FSList files;
if (!dir.isDirectory() || !dir.getChildren(files, Common::FSNode::kListAll, true)) {
warning("Game data path does not exist or is not a directory (%s)", path.c_str());
return Common::kNoGameDataFoundError;
}
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 (_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];
break;
}
}
} else if (matches.size() > 0) {
agdDesc = matches[0];
}
if (agdDesc == 0) {
// Use fallback detector if there were no matches by other means
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 (_singleId == NULL && agdDesc->gameId != gameid)
agdDesc = 0;
}
}
if (agdDesc == 0)
return Common::kNoGameDataFoundError;
// If the GUI options were updated, we catch this here and update them in the users config
// file transparently.
Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc->language);
if (agdDesc->flags & ADGF_ADDENGLISH)
lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY);
Common::updateGameGUIOptions(agdDesc->guiOptions + _guiOptions, lang);
GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc, _gameIds);
bool showTestingWarning = false;
#ifdef RELEASE_BUILD
showTestingWarning = true;
#endif
//.........这里部分代码省略.........
示例8: detectGamesImpl
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;
}
示例9: selectDirectories
bool DownloadDialog::selectDirectories() {
if (Networking::Connection::isLimited()) {
MessageDialog alert(_("It looks like your connection is limited. "
"Do you really want to download files with it?"), _("Yes"), _("No"));
if (alert.runModal() != GUI::kMessageOK)
return false;
}
//first user should select remote directory to download
if (_remoteBrowser->runModal() <= 0)
return false;
Cloud::StorageFile remoteDirectory = _remoteBrowser->getResult();
//now user should select local directory to download into
if (_browser->runModal() <= 0)
return false;
Common::FSNode dir(_browser->getResult());
Common::FSList files;
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
MessageDialog alert(_("ScummVM couldn't open the specified directory!"));
alert.runModal();
return false;
}
//check that there is no file with the remote directory's name in the local one
for (Common::FSList::iterator i = files.begin(); i != files.end(); ++i) {
if (i->getName().equalsIgnoreCase(remoteDirectory.name())) {
//if there is, ask user whether it's OK
if (!i->isDirectory()) {
GUI::MessageDialog alert(_("Cannot create a directory to download - the specified directory has a file with the same name."), _("OK"));
alert.runModal();
return false;
}
GUI::MessageDialog alert(
Common::String::format(_("The \"%s\" already exists in the specified directory.\nDo you really want to download files into that directory?"), remoteDirectory.name().c_str()),
_("Yes"),
_("No")
);
if (alert.runModal() != GUI::kMessageOK)
return false;
break;
}
}
//make a local path
Common::String localPath = dir.getPath();
//simple heuristic to determine which path separator to use
if (localPath.size() && localPath.lastChar() != '/' && localPath.lastChar() != '\\') {
int backslashes = 0;
for (uint32 i = 0; i < localPath.size(); ++i)
if (localPath[i] == '/')
--backslashes;
else if (localPath[i] == '\\')
++backslashes;
if (backslashes > 0)
localPath += '\\' + remoteDirectory.name();
else
localPath += '/' + remoteDirectory.name();
} else {
localPath += remoteDirectory.name();
}
CloudMan.startDownload(remoteDirectory.path(), localPath);
CloudMan.setDownloadTarget(this);
_localDirectory = localPath;
return true;
}
示例10: registerPackages
bool BaseFileManager::registerPackages() {
debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Scanning packages");
// We need the target name as a Common::String to perform some game-specific hacks.
Common::String targetName = BaseEngine::instance().getGameTargetName();
// Register without using SearchMan, as otherwise the FSNode-based lookup in openPackage will fail
// and that has to be like that to support the detection-scheme.
Common::FSList files;
for (Common::FSList::const_iterator it = _packagePaths.begin(); it != _packagePaths.end(); ++it) {
debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", it->getPath().c_str(), it->getName().c_str());
if (!it->getChildren(files, Common::FSNode::kListFilesOnly)) {
warning("getChildren() failed for path: %s", it->getDisplayName().c_str());
}
for (Common::FSList::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
// To prevent any case sensitivity issues we make the filename
// all lowercase here. This makes the code slightly prettier
// than the equivalent of using equalsIgnoreCase.
Common::String fileName = fileIt->getName();
fileName.toLowercase();
if (!fileName.hasSuffix(".dcp")) {
continue;
}
// HACK: for Reversion1, avoid loading xlanguage_pt.dcp from the main folder:
if (_language != Common::PT_BRA && targetName.hasPrefix("reversion1")) {
if (fileName == "xlanguage_pt.dcp") {
continue;
}
}
// Again, make the parent's name all lowercase to avoid any case
// issues.
Common::String parentName = fileIt->getParent().getName();
parentName.toLowercase();
// Avoid registering all the language files
// TODO: Select based on the gameDesc.
if (_language != Common::UNK_LANG && (parentName == "language" || parentName == "languages")) {
// English
if (_language == Common::EN_ANY && (fileName != "english.dcp" && fileName != "xlanguage_en.dcp")) {
continue;
// Chinese
} else if (_language == Common::ZH_CNA && (fileName != "chinese.dcp" && fileName != "xlanguage_nz.dcp")) {
continue;
// Czech
} else if (_language == Common::CZ_CZE && (fileName != "czech.dcp" && fileName != "xlanguage_cz.dcp")) {
continue;
// French
} else if (_language == Common::FR_FRA && (fileName != "french.dcp" && fileName != "xlanguage_fr.dcp")) {
continue;
// German
} else if (_language == Common::DE_DEU && (fileName != "german.dcp" && fileName != "xlanguage_de.dcp")) {
continue;
// Italian
} else if (_language == Common::IT_ITA && (fileName != "italian.dcp" && fileName != "xlanguage_it.dcp")) {
continue;
// Latvian
} else if (_language == Common::LV_LAT && (fileName != "latvian.dcp" && fileName != "xlanguage_lv.dcp")) {
// TODO: 'latvian.dcp' is just guesswork. Is there any
// game using Latvian and using this filename?
continue;
// Polish
} else if (_language == Common::PL_POL && (fileName != "polish.dcp" && fileName != "xlanguage_pl.dcp")) {
continue;
// Portuguese
} else if (_language == Common::PT_BRA && (fileName != "portuguese.dcp" && fileName != "xlanguage_pt.dcp")) {
continue;
// Russian
} else if (_language == Common::RU_RUS && (fileName != "russian.dcp" && fileName != "xlanguage_ru.dcp")) {
continue;
}
}
debugC(kWintermuteDebugFileAccess, "Registering %s %s", fileIt->getPath().c_str(), fileIt->getName().c_str());
registerPackage((*fileIt));
}
}
// debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, " Registered %d files in %d package(s)", _files.size(), _packages.size());
return STATUS_OK;
}
示例11: fallbackDetect
ADDetectedGame DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
// TODO: Handle Mac fallback
// reset fallback description
Director::DirectorGameDescription *desc = &s_fallbackDesc;
desc->desc.gameId = "director";
desc->desc.extra = "";
desc->desc.language = Common::UNK_LANG;
desc->desc.flags = ADGF_NO_FLAGS;
desc->desc.platform = Common::kPlatformWindows;
desc->desc.guiOptions = GUIO0();
desc->desc.filesDescriptions[0].fileName = 0;
desc->version = 0;
desc->gameID = Director::GID_GENERIC;
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (file->isDirectory())
continue;
Common::String fileName = file->getName();
fileName.toLowercase();
if (!fileName.hasSuffix(".exe"))
continue;
Common::File f;
if (!f.open(*file))
continue;
f.seek(-4, SEEK_END);
uint32 offset = f.readUint32LE();
if (f.eos() || offset == 0 || offset >= (uint32)(f.size() - 4))
continue;
f.seek(offset);
uint32 tag = f.readUint32LE();
switch (tag) {
case MKTAG('3', '9', 'J', 'P'):
desc->version = 4;
break;
case MKTAG('P', 'J', '9', '5'):
desc->version = 5;
break;
case MKTAG('P', 'J', '0', '0'):
desc->version = 7;
break;
default:
// Prior to version 4, there was no tag here. So we'll use a bit of a
// heuristic to detect. The first field is the entry count, of which
// there should only be one.
if ((tag & 0xFFFF) != 1)
continue;
f.skip(3);
uint32 mmmSize = f.readUint32LE();
if (f.eos() || mmmSize == 0)
continue;
byte fileNameSize = f.readByte();
if (f.eos())
continue;
f.skip(fileNameSize);
byte directoryNameSize = f.readByte();
if (f.eos())
continue;
f.skip(directoryNameSize);
if (f.pos() != f.size() - 4)
continue;
// Assume v3 at this point (for now at least)
desc->version = 3;
}
strncpy(s_fallbackFileNameBuffer, fileName.c_str(), 50);
s_fallbackFileNameBuffer[50] = '\0';
desc->desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer;
warning("Director fallback detection D%d", desc->version);
return ADDetectedGame(&desc->desc);
}
return ADDetectedGame();
}