diff --git a/common/macresman.cpp b/common/macresman.cpp index 917bb278543..49c4545b7d0 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -116,15 +116,20 @@ String MacResManager::computeResForkMD5AsString(uint32 length) const { } bool MacResManager::open(const String &fileName) { + return open(fileName, SearchMan); +} + +bool MacResManager::open(const String &fileName, Archive &archive) { close(); #ifdef MACOSX // Check the actual fork on a Mac computer - String fullPath = ConfMan.get("path") + "/" + fileName + "/..namedfork/rsrc"; - FSNode resFsNode = FSNode(fullPath); - if (resFsNode.exists()) { + const ArchiveMemberPtr archiveMember = archive.getMember(fileName); + const Common::FSNode *plainFsNode = dynamic_cast(archiveMember.get()); + if (plainFsNode) { + String fullPath = plainFsNode->getPath() + "/..namedfork/rsrc"; + FSNode resFsNode = FSNode(fullPath); SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); - if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = fileName; return true; @@ -134,111 +139,37 @@ bool MacResManager::open(const String &fileName) { } #endif - File *file = new File(); - // Prefer standalone files first, starting with raw forks - if (file->open(fileName + ".rsrc") && loadFromRawFork(*file)) { + SeekableReadStream *stream = archive.createReadStreamForMember(fileName + ".rsrc"); + if (stream && loadFromRawFork(*stream)) { _baseFileName = fileName; return true; } - file->close(); + delete stream; // Then try for AppleDouble using Apple's naming - if (file->open(constructAppleDoubleName(fileName)) && loadFromAppleDouble(*file)) { + stream = archive.createReadStreamForMember(constructAppleDoubleName(fileName)); + if (stream && loadFromAppleDouble(*stream)) { _baseFileName = fileName; return true; } - file->close(); + delete stream; // Check .bin for MacBinary next - if (file->open(fileName + ".bin") && loadFromMacBinary(*file)) { + stream = archive.createReadStreamForMember(fileName + ".bin"); + if (stream && loadFromMacBinary(*stream)) { _baseFileName = fileName; return true; } - file->close(); + delete stream; // As a last resort, see if just the data fork exists - if (file->open(fileName)) { + stream = archive.createReadStreamForMember(fileName); + if (stream) { _baseFileName = fileName; // Maybe file is in MacBinary but without .bin extension? // Check it here - if (isMacBinary(*file)) { - file->seek(0); - if (loadFromMacBinary(*file)) - return true; - } - - file->seek(0); - _stream = file; - return true; - } - - delete file; - - // The file doesn't exist - return false; -} - -bool MacResManager::open(const FSNode &path, const String &fileName) { - close(); - -#ifdef MACOSX - // Check the actual fork on a Mac computer - String fullPath = path.getPath() + "/" + fileName + "/..namedfork/rsrc"; - FSNode resFsNode = FSNode(fullPath); - if (resFsNode.exists()) { - SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); - - if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { - _baseFileName = fileName; - return true; - } - - delete macResForkRawStream; - } -#endif - - // Prefer standalone files first, starting with raw forks - FSNode fsNode = path.getChild(fileName + ".rsrc"); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromRawFork(*stream)) { - _baseFileName = fileName; - return true; - } - delete stream; - } - - // Then try for AppleDouble using Apple's naming - fsNode = path.getChild(constructAppleDoubleName(fileName)); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromAppleDouble(*stream)) { - _baseFileName = fileName; - return true; - } - delete stream; - } - - // Check .bin for MacBinary next - fsNode = path.getChild(fileName + ".bin"); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromMacBinary(*stream)) { - _baseFileName = fileName; - return true; - } - delete stream; - } - - // As a last resort, see if just the data fork exists - fsNode = path.getChild(fileName); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - _baseFileName = fileName; - - // FIXME: Is this really needed? if (isMacBinary(*stream)) { stream->seek(0); if (loadFromMacBinary(*stream)) diff --git a/common/macresman.h b/common/macresman.h index 6ae3fd36dcd..6ac831fe2e7 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -68,14 +68,14 @@ public: bool open(const String &fileName); /** - * Open a Mac data/resource fork pair. + * Open a Mac data/resource fork pair from within the given archive. * * @param path The path that holds the forks * @param fileName The base file name of the file * @note This will check for the raw resource fork, MacBinary, and AppleDouble formats. * @return True on success */ - bool open(const FSNode &path, const String &fileName); + bool open(const String &fileName, Archive &archive); /** * See if a Mac data/resource fork pair exists. diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index d220abf55ac..58b162805a0 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -35,6 +35,45 @@ #include "engines/advancedDetector.h" #include "engines/obsolete.h" +/** + * Adapter to be able to use Common::Archive based code from the AD. + */ +class FileMapArchive : public Common::Archive { +public: + FileMapArchive(const AdvancedMetaEngine::FileMap &fileMap) : _fileMap(fileMap) {} + + bool hasFile(const Common::String &name) const override { + return _fileMap.contains(name); + } + + int listMembers(Common::ArchiveMemberList &list) const override { + int files = 0; + for (AdvancedMetaEngine::FileMap::const_iterator it = _fileMap.begin(); it != _fileMap.end(); ++it) { + list.push_back(Common::ArchiveMemberPtr(new Common::FSNode(it->_value))); + ++files; + } + + return files; + } + + const Common::ArchiveMemberPtr getMember(const Common::String &name) const override { + AdvancedMetaEngine::FileMap::const_iterator it = _fileMap.find(name); + if (it == _fileMap.end()) { + return Common::ArchiveMemberPtr(); + } + + return Common::ArchiveMemberPtr(new Common::FSNode(it->_value)); + } + + Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override { + Common::FSNode fsNode = _fileMap[name]; + return fsNode.createReadStream(); + } + +private: + const AdvancedMetaEngine::FileMap &_fileMap; +}; + static Common::String sanitizeName(const char *name) { Common::String res; @@ -355,14 +394,16 @@ void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSL } } -bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const { +bool AdvancedMetaEngine::getFileProperties(const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const { // FIXME/TODO: We don't handle the case that a file is listed as a regular // file and as one with resource fork. if (game.flags & ADGF_MACRESFORK) { + FileMapArchive fileMapArchive(allFiles); + Common::MacResManager macResMan; - if (!macResMan.open(parent, fname)) + if (!macResMan.open(fname, fileMapArchive)) return false; fileProps.md5 = macResMan.computeResForkMD5AsString(_md5Bytes); @@ -407,7 +448,7 @@ ADDetectedGames AdvancedMetaEngine::detectGame(const Common::FSNode &parent, con continue; FileProperties tmp; - if (getFileProperties(parent, allFiles, *g, fname, tmp)) { + if (getFileProperties(allFiles, *g, fname, tmp)) { debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str()); } @@ -510,7 +551,7 @@ ADDetectedGames AdvancedMetaEngine::detectGame(const Common::FSNode &parent, con return matched; } -ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const { +ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const { const ADFileBasedFallback *ptr; const char* const* filenames; @@ -546,7 +587,7 @@ ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, for (filenames = ptr->filenames; *filenames; ++filenames) { FileProperties tmp; - if (getFileProperties(fslist.begin()->getParent(), allFiles, *agdesc, *filenames, tmp)) + if (getFileProperties(allFiles, *agdesc, *filenames, tmp)) game.matchedFiles[*filenames] = tmp; } diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index ee8b7cbfd78..941f59d4976 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -305,7 +305,7 @@ protected: * @param fileBasedFallback a list of ADFileBasedFallback records, zero-terminated * @param filesProps if not 0, return a map of properties for all detected files here */ - ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const; + ADDetectedGame detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const; /** * Compose a hashmap of all files in fslist. @@ -314,10 +314,12 @@ protected: void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName = Common::String()) const; /** Get the properties (size and MD5) of this file. */ - bool getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const; + bool getFileProperties(const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const; /** Convert an AD game description into the shared game description format */ virtual DetectedGame toDetectedGame(const ADDetectedGame &adGame) const; + + friend class FileMapArchive; // for FileMap }; #endif diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp index 08de205ab95..5769c81c952 100644 --- a/engines/cge/detection.cpp +++ b/engines/cge/detection.cpp @@ -164,7 +164,7 @@ static const ADFileBasedFallback fileBasedFallback[] = { }; ADDetectedGame CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADDetectedGame game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback); + ADDetectedGame game = detectGameFilebased(allFiles, CGE::fileBasedFallback); if (!game.desc) return ADDetectedGame(); diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp index d45d1b78e34..58081622acf 100644 --- a/engines/cge2/detection.cpp +++ b/engines/cge2/detection.cpp @@ -162,7 +162,7 @@ static const ADFileBasedFallback fileBasedFallback[] = { // This fallback detection looks identical to the one used for CGE. In fact, the difference resides // in the ResourceManager which handles a different archive format. The rest of the detection is identical. ADDetectedGame CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADDetectedGame game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback); + ADDetectedGame game = detectGameFilebased(allFiles, CGE2::fileBasedFallback); if (!game.desc) return ADDetectedGame(); diff --git a/engines/cryomni3d/detection.cpp b/engines/cryomni3d/detection.cpp index e0e746bb7ca..da307b9c490 100644 --- a/engines/cryomni3d/detection.cpp +++ b/engines/cryomni3d/detection.cpp @@ -91,7 +91,7 @@ public: ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { - return detectGameFilebased(allFiles, fslist, fileBased); + return detectGameFilebased(allFiles, fileBased); } const char *getEngineId() const override { diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp index 6d9310291e0..a95fcd6200d 100644 --- a/engines/director/detection.cpp +++ b/engines/director/detection.cpp @@ -384,7 +384,7 @@ ADDetectedGame DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const ADDetectedGame game(&desc->desc); FileProperties tmp; - if (getFileProperties(file->getParent(), allFiles, desc->desc, file->getName(), tmp)) { + if (getFileProperties(allFiles, desc->desc, file->getName(), tmp)) { game.hasUnknownFiles = true; game.matchedFiles[file->getName()] = tmp; } diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp index 3ab3dbff995..cdc74848f65 100644 --- a/engines/gob/detection/detection.cpp +++ b/engines/gob/detection/detection.cpp @@ -60,7 +60,7 @@ GobMetaEngine::GobMetaEngine() : } ADDetectedGame GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { - ADDetectedGame detectedGame = detectGameFilebased(allFiles, fslist, Gob::fileBased); + ADDetectedGame detectedGame = detectGameFilebased(allFiles, Gob::fileBased); if (!detectedGame.desc) { return ADDetectedGame(); } diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 4672f3c60fb..baf03057b43 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -179,7 +179,7 @@ public: } ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { - return detectGameFilebased(allFiles, fslist, Mohawk::fileBased); + return detectGameFilebased(allFiles, Mohawk::fileBased); } const char *getEngineId() const override { diff --git a/engines/sludge/detection.cpp b/engines/sludge/detection.cpp index 0e2fd20ed09..0061f50d97f 100644 --- a/engines/sludge/detection.cpp +++ b/engines/sludge/detection.cpp @@ -159,7 +159,7 @@ ADDetectedGame SludgeMetaEngine::fallbackDetect(const FileMap &allFiles, const C game.desc = &s_fallbackDesc.desc; FileProperties tmp; - if (getFileProperties(file->getParent(), allFiles, s_fallbackDesc.desc, fileName, tmp)) { + if (getFileProperties(allFiles, s_fallbackDesc.desc, fileName, tmp)) { game.hasUnknownFiles = true; game.matchedFiles[fileName] = tmp; } diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp index 21dabd7f60a..9ad65b735c2 100644 --- a/engines/toon/detection.cpp +++ b/engines/toon/detection.cpp @@ -142,7 +142,7 @@ public: } ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { - return detectGameFilebased(allFiles, fslist, Toon::fileBasedFallback); + return detectGameFilebased(allFiles, Toon::fileBasedFallback); } const char *getEngineId() const override { diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index c300b3099ec..584be68744b 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -133,7 +133,7 @@ public: } ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override { - return detectGameFilebased(allFiles, fslist, Touche::fileBasedFallback); + return detectGameFilebased(allFiles, Touche::fileBasedFallback); } const char *getEngineId() const override { diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index ebd54879739..1ad248c192b 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -148,7 +148,7 @@ public: if (!file->getName().hasSuffixIgnoreCase(".dcp")) continue; FileProperties tmp; - if (getFileProperties(file->getParent(), allFiles, s_fallbackDesc, file->getName(), tmp)) { + if (getFileProperties(allFiles, s_fallbackDesc, file->getName(), tmp)) { game.hasUnknownFiles = true; game.matchedFiles[file->getName()] = tmp; }