diff options
-rw-r--r-- | common/macresman.cpp | 110 | ||||
-rw-r--r-- | common/macresman.h | 14 | ||||
-rw-r--r-- | engines/advancedDetector.cpp | 41 | ||||
-rw-r--r-- | engines/advancedDetector.h | 4 |
4 files changed, 140 insertions, 29 deletions
diff --git a/common/macresman.cpp b/common/macresman.cpp index 24099475a7..f36f8b2fe3 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -26,9 +26,10 @@ #include "common/scummsys.h" #include "common/debug.h" #include "common/util.h" - #include "common/file.h" +#include "common/fs.h" #include "common/macresman.h" +#include "common/md5.h" #ifdef MACOSX #include "common/config-manager.h" @@ -37,6 +38,15 @@ namespace Common { +#define MBI_INFOHDR 128 +#define MBI_ZERO1 0 +#define MBI_NAMELEN 1 +#define MBI_ZERO2 74 +#define MBI_ZERO3 82 +#define MBI_DFLEN 83 +#define MBI_RFLEN 87 +#define MAXNAMELEN 63 + MacResManager::MacResManager() { memset(this, 0, sizeof(MacResManager)); close(); @@ -72,14 +82,32 @@ bool MacResManager::hasResFork() { return !_baseFileName.empty() && _mode != kResForkNone; } +uint32 MacResManager::getResForkSize() { + if (!hasResFork()) + return 0; + + return _resForkSize; +} + +bool MacResManager::getResForkMD5(char *md5str, uint32 length) { + if (!hasResFork()) + return false; + + ReadStream *stream = new SeekableSubReadStream(_stream, _resForkOffset, _resForkOffset + _resForkSize); + bool retVal = md5_file_string(*stream, md5str, MIN<uint32>(length, _resForkSize)); + delete stream; + return retVal; +} + bool MacResManager::open(Common::String filename) { close(); #ifdef MACOSX // Check the actual fork on a Mac computer Common::String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc"; + Common::SeekableReadStream *macResForkRawStream = StdioStream::makeFromPath(fullPath, false); - if (loadFromRawFork(*StdioStream::makeFromPath(fullPath, false))) { + if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = filename; return true; } @@ -118,6 +146,53 @@ bool MacResManager::open(Common::String filename) { return false; } +bool MacResManager::open(Common::FSNode path, Common::String filename) { + close(); + +#ifdef MACOSX + // Check the actual fork on a Mac computer + Common::String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc"; + Common::SeekableReadStream *macResForkRawStream = StdioStream::makeFromPath(fullPath, false); + + if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { + _baseFileName = filename; + return true; + } +#endif + + // First, let's try to see if the Mac converted name exists + Common::FSNode fsNode = path.getChild("._" + filename); + if (fsNode.exists() && !fsNode.isDirectory() && loadFromAppleDouble(*fsNode.createReadStream())) { + _baseFileName = filename; + return true; + } + + // Check .bin too + fsNode = path.getChild(filename + ".bin"); + if (fsNode.exists() && !fsNode.isDirectory() && loadFromMacBinary(*fsNode.createReadStream())) { + _baseFileName = filename; + return true; + } + + // Maybe we have a dumped fork? + fsNode = path.getChild(filename + ".rsrc"); + if (fsNode.exists() && !fsNode.isDirectory() && loadFromRawFork(*fsNode.createReadStream())) { + _baseFileName = filename; + return true; + } + + // Fine, what about just the data fork? + fsNode = path.getChild(filename); + if (fsNode.exists() && !fsNode.isDirectory()) { + _baseFileName = filename; + _stream = fsNode.createReadStream(); + return true; + } + + // The file doesn't exist + return false; +} + bool MacResManager::loadFromAppleDouble(Common::SeekableReadStream &stream) { if (stream.readUint32BE() != 0x00051607) // tag return false; @@ -129,12 +204,13 @@ bool MacResManager::loadFromAppleDouble(Common::SeekableReadStream &stream) { for (uint16 i = 0; i < entryCount; i++) { uint32 id = stream.readUint32BE(); uint32 offset = stream.readUint32BE(); - stream.readUint32BE(); // length + uint32 length = stream.readUint32BE(); // length if (id == 1) { // Found the data fork! _resForkOffset = offset; _mode = kResForkAppleDouble; + _resForkSize = length; return load(stream); } } @@ -142,15 +218,6 @@ bool MacResManager::loadFromAppleDouble(Common::SeekableReadStream &stream) { return false; } -#define MBI_INFOHDR 128 -#define MBI_ZERO1 0 -#define MBI_NAMELEN 1 -#define MBI_ZERO2 74 -#define MBI_ZERO3 82 -#define MBI_DFLEN 83 -#define MBI_RFLEN 87 -#define MAXNAMELEN 63 - bool MacResManager::loadFromMacBinary(Common::SeekableReadStream &stream) { byte infoHeader[MBI_INFOHDR]; stream.read(infoHeader, MBI_INFOHDR); @@ -167,8 +234,10 @@ bool MacResManager::loadFromMacBinary(Common::SeekableReadStream &stream) { uint32 rsrcSizePad = (((rsrcSize + 127) >> 7) << 7); // Length check - if (MBI_INFOHDR + dataSizePad + rsrcSizePad == (uint32)stream.size()) + if (MBI_INFOHDR + dataSizePad + rsrcSizePad == (uint32)stream.size()) { _resForkOffset = MBI_INFOHDR + dataSizePad; + _resForkSize = rsrcSize; + } } if (_resForkOffset < 0) @@ -181,6 +250,7 @@ bool MacResManager::loadFromMacBinary(Common::SeekableReadStream &stream) { bool MacResManager::loadFromRawFork(Common::SeekableReadStream &stream) { _mode = kResForkRaw; _resForkOffset = 0; + _resForkSize = stream.size(); return load(stream); } @@ -251,6 +321,20 @@ MacResIDArray MacResManager::getResIDArray(uint32 typeID) { return res; } +MacResTagArray MacResManager::getResTagArray() { + MacResTagArray tagArray; + + if (!hasResFork()) + return tagArray; + + tagArray.resize(_resMap.numTypes); + + for (uint32 i = 0; i < _resMap.numTypes; i++) + tagArray[i] = _resTypes[i].id; + + return tagArray; +} + Common::String MacResManager::getResName(uint32 typeID, uint16 resID) { int typeNum = -1; diff --git a/common/macresman.h b/common/macresman.h index 2f47a67fa2..4afd2eebab 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -31,7 +31,10 @@ namespace Common { +class FSNode; + typedef Common::Array<uint16> MacResIDArray; +typedef Common::Array<uint32> MacResTagArray; /** * Class for reading Mac Binary files. @@ -43,7 +46,8 @@ public: MacResManager(); ~MacResManager(); - bool open(Common::String fileName); + bool open(Common::String filename); + bool open(Common::FSNode path, Common::String filename); void close(); bool hasDataFork(); @@ -59,6 +63,8 @@ public: Common::SeekableReadStream *getDataFork(); Common::String getResName(uint32 typeID, uint16 resID); + uint32 getResForkSize(); + bool getResForkMD5(char *md5str, uint32 length); /** * Convert cursor from crsr format to format suitable for feeding to CursorMan @@ -85,6 +91,11 @@ public: */ MacResIDArray getResIDArray(uint32 typeID); + /** + * Return list of resource tags + */ + MacResTagArray getResTagArray(); + private: Common::SeekableReadStream *_stream; Common::String _baseFileName; @@ -128,6 +139,7 @@ private: typedef Resource *ResPtr; int32 _resForkOffset; + uint32 _resForkSize; uint32 _dataOffset; uint32 _dataLength; diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index a957c5a3ed..b149b43ad7 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -29,6 +29,7 @@ #include "common/util.h" #include "common/hash-str.h" #include "common/file.h" +#include "common/macresman.h" #include "common/md5.h" #include "common/config-manager.h" @@ -374,24 +375,38 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { Common::String fname = fileDesc->fileName; - if (allFiles.contains(fname) && !filesSizeMD5.contains(fname)) { - debug(3, "+ %s", fname.c_str()); + SizeMD5 tmp; - SizeMD5 tmp; - Common::File testFile; - - if (testFile.open(allFiles[fname])) { - tmp.size = (int32)testFile.size(); - if (!md5_file_string(testFile, tmp.md5, params.md5Bytes)) + if (g->flags & ADGF_MACRESFORK) { + Common::MacResManager *macResMan = new Common::MacResManager(); + + if (macResMan->open(parent, fname)) { + if (!macResMan->getResForkMD5(tmp.md5, params.md5Bytes)) tmp.md5[0] = 0; - } else { - tmp.size = -1; - tmp.md5[0] = 0; + tmp.size = macResMan->getResForkSize(); + debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5); + filesSizeMD5[fname] = tmp; } - debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5); + delete macResMan; + } else { + if (allFiles.contains(fname) && !filesSizeMD5.contains(fname)) { + debug(3, "+ %s", fname.c_str()); + + Common::File testFile; - filesSizeMD5[fname] = tmp; + if (testFile.open(allFiles[fname])) { + tmp.size = (int32)testFile.size(); + if (!md5_file_string(testFile, tmp.md5, params.md5Bytes)) + tmp.md5[0] = 0; + } else { + tmp.size = -1; + tmp.md5[0] = 0; + } + + debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5); + filesSizeMD5[fname] = tmp; + } } } } diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index f5d0b4c2ee..370d958ce6 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -43,9 +43,9 @@ struct ADGameFileDescription { enum ADGameFlags { ADGF_NO_FLAGS = 0, + 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_KEEPMATCH = (1 << 27), // this entry is kept even when there are matched - // entries with more files + ADGF_KEEPMATCH = (1 << 27), // this entry is kept even when there are matched entries with more files 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 |