aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/macresman.cpp110
-rw-r--r--common/macresman.h14
-rw-r--r--engines/advancedDetector.cpp41
-rw-r--r--engines/advancedDetector.h4
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