[Scummvm-git-logs] scummvm master -> 78d26927a850144e4ccfcb669f5c4cfcd578be4a
sev-
noreply at scummvm.org
Mon Nov 28 23:25:53 UTC 2022
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
78d26927a8 COMMON: Add functions to get Mac Finder metadata such as type/creator codes.
Commit: 78d26927a850144e4ccfcb669f5c4cfcd578be4a
https://github.com/scummvm/scummvm/commit/78d26927a850144e4ccfcb669f5c4cfcd578be4a
Author: elasota (ejlasota at gmail.com)
Date: 2022-11-29T00:25:50+01:00
Commit Message:
COMMON: Add functions to get Mac Finder metadata such as type/creator codes.
Changed paths:
common/macresman.cpp
common/macresman.h
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 5f48120b2f6..1eb222464c4 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -82,10 +82,17 @@ MacFinderExtendedInfoData MacFinderExtendedInfo::toData() const {
#define MBI_ZERO1 0
#define MBI_NAMELEN 1
+#define MBI_TYPE 65
+#define MBI_CREATOR 69
+#define MBI_FLAGSHIGH 73
#define MBI_ZERO2 74
+#define MBI_POSY 75
+#define MBI_POSX 77
+#define MBI_FOLDERID 79
#define MBI_ZERO3 82
#define MBI_DFLEN 83
#define MBI_RFLEN 87
+#define MBI_FLAGSLOW 101
#define MAXNAMELEN 63
MacResManager::MacResManager() {
@@ -305,6 +312,81 @@ bool MacResManager::exists(const Path &fileName) {
return false;
}
+bool MacResManager::getFileFinderInfo(const Path &fileName, Archive &archive, MacFinderInfo &outFinderInfo) {
+ MacFinderExtendedInfo fxinfo;
+ return getFileFinderInfo(fileName, archive, outFinderInfo, fxinfo);
+}
+
+bool MacResManager::getFileFinderInfo(const Path &fileName, Archive &archive, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo) {
+ // Prefer standalone .finf files first (especially since this can avoid decompressing entire files from slow archive formats like StuffIt Installer)
+ Common::ScopedPtr<SeekableReadStream> stream(archive.createReadStreamForMember(fileName.append(".finf")));
+ if (stream) {
+ MacFinderInfoData finfoData;
+ MacFinderExtendedInfoData fxinfoData;
+
+ uint32 finfoSize = stream->read(&finfoData, sizeof(finfoData));
+ uint32 fxinfoSize = stream->read(&fxinfoData, sizeof(fxinfoData));
+
+ if (finfoSize == sizeof(MacFinderInfoData)) {
+ outFinderInfo = MacFinderInfo(finfoData);
+
+ if (fxinfoSize == sizeof(MacFinderExtendedInfoData)) {
+ outFinderExtendedInfo = MacFinderExtendedInfo(fxinfoData);
+ } else {
+ outFinderExtendedInfo = MacFinderExtendedInfo();
+ if (fxinfoSize != 0)
+ warning("Finder extended info metadata file was too small");
+ }
+
+ return true;
+ } else if (finfoSize != 0) {
+ warning("Finder info metadata file was too small");
+ }
+ }
+
+ // Might have AppleDouble in the resource file
+ stream.reset();
+ stream.reset(archive.createReadStreamForMember(fileName.append(".rsrc")));
+
+ if (stream) {
+ bool appleDouble = (stream->readUint32BE() == 0x00051607);
+ stream->seek(0);
+
+ if (appleDouble && getFinderInfoFromAppleDouble(stream.get(), outFinderInfo, outFinderExtendedInfo))
+ return true;
+ }
+
+ // Try for AppleDouble using Apple's naming
+ stream.reset();
+ stream.reset(archive.createReadStreamForMember(constructAppleDoubleName(fileName)));
+ if (stream && getFinderInfoFromAppleDouble(stream.get(), outFinderInfo, outFinderExtendedInfo))
+ return true;
+
+ // Check .bin for MacBinary next
+ stream.reset();
+ stream.reset(archive.createReadStreamForMember(fileName.append(".bin")));
+ if (stream && getFinderInfoFromMacBinary(stream.get(), outFinderInfo, outFinderExtendedInfo))
+ return true;
+
+ // Check if the file is in MacBinary format
+ stream.reset();
+ stream.reset(archive.createReadStreamForMember(fileName));
+ if (stream && getFinderInfoFromMacBinary(stream.get(), outFinderInfo, outFinderExtendedInfo))
+ return true;
+
+ // No metadata
+ return false;
+}
+
+bool MacResManager::getFileFinderInfo(const Path &fileName, MacFinderInfo &outFinderInfo) {
+ MacFinderExtendedInfo fxinfo;
+ return getFileFinderInfo(fileName, outFinderInfo, fxinfo);
+}
+
+bool MacResManager::getFileFinderInfo(const Path &fileName, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo) {
+ return getFileFinderInfo(fileName, SearchMan, outFinderInfo, outFinderExtendedInfo);
+}
+
void MacResManager::listFiles(StringArray &files, const String &pattern) {
// Base names discovered so far.
typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> BaseNameSet;
@@ -403,8 +485,71 @@ bool MacResManager::loadFromAppleDouble(SeekableReadStream *stream) {
return false;
}
-bool MacResManager::isMacBinary(SeekableReadStream &stream) {
+bool MacResManager::getFinderInfoFromMacBinary(SeekableReadStream *stream, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo) {
byte infoHeader[MBI_INFOHDR];
+ if (!readAndValidateMacBinaryHeader(*stream, infoHeader))
+ return false;
+
+ MacFinderInfo finfo;
+
+ // Parse fields
+ memcpy(finfo.type, infoHeader + MBI_TYPE, 4);
+ memcpy(finfo.creator, infoHeader + MBI_CREATOR, 4);
+ finfo.flags = (infoHeader[MBI_FLAGSHIGH] << 8) + infoHeader[MBI_FLAGSLOW];
+ finfo.position.x = READ_BE_INT16(infoHeader + MBI_POSX);
+ finfo.position.y = READ_BE_INT16(infoHeader + MBI_POSY);
+ finfo.windowID = READ_BE_INT16(infoHeader + MBI_FOLDERID);
+
+ outFinderInfo = finfo;
+ outFinderExtendedInfo = MacFinderExtendedInfo();
+
+ return true;
+}
+
+bool MacResManager::getFinderInfoFromAppleDouble(SeekableReadStream *stream, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo) {
+ if (!stream)
+ return false;
+
+ if (stream->readUint32BE() != 0x00051607) // tag
+ return false;
+
+ stream->skip(20); // version + home file system
+
+ uint16 entryCount = stream->readUint16BE();
+
+ uint32 finderInfoPos = 0;
+ uint32 finderInfoLength = 0;
+
+ for (uint16 i = 0; i < entryCount; i++) {
+ uint32 id = stream->readUint32BE();
+ uint32 offset = stream->readUint32BE();
+ uint32 length = stream->readUint32BE(); // length
+
+ if (id == 9) {
+ finderInfoPos = offset;
+ finderInfoLength = length;
+ break;
+ }
+ }
+
+ if (finderInfoLength < sizeof(MacFinderInfoData) + sizeof(MacFinderExtendedInfoData))
+ return false;
+
+ if (!stream->seek(finderInfoPos))
+ return false;
+
+ MacFinderInfoData finfo;
+ MacFinderExtendedInfoData fxinfo;
+ if (stream->read(&finfo, sizeof(finfo)) != sizeof(finfo) || stream->read(&fxinfo, sizeof(fxinfo)) != sizeof(fxinfo))
+ return false;
+
+ outFinderInfo = MacFinderInfo(finfo);
+ outFinderExtendedInfo = MacFinderExtendedInfo(fxinfo);
+
+ return true;
+}
+
+bool MacResManager::readAndValidateMacBinaryHeader(SeekableReadStream &stream, byte (&infoHeader)[MBI_INFOHDR]) {
int resForkOffset = -1;
if (stream.read(infoHeader, MBI_INFOHDR) != MBI_INFOHDR)
@@ -427,7 +572,7 @@ bool MacResManager::isMacBinary(SeekableReadStream &stream) {
uint32 dataSizePad = (((dataSize + 127) >> 7) << 7);
// Files produced by ISOBuster are not padded, thus, compare with the actual size
- //uint32 rsrcSizePad = (((rsrcSize + 127) >> 7) << 7);
+ // uint32 rsrcSizePad = (((rsrcSize + 127) >> 7) << 7);
// Length check
if (MBI_INFOHDR + dataSizePad + rsrcSize <= (uint32)stream.size()) {
@@ -441,6 +586,11 @@ bool MacResManager::isMacBinary(SeekableReadStream &stream) {
return true;
}
+bool MacResManager::isMacBinary(SeekableReadStream &stream) {
+ byte infoHeader[MBI_INFOHDR];
+ return readAndValidateMacBinaryHeader(stream, infoHeader);
+}
+
bool MacResManager::isRawFork(SeekableReadStream &stream) {
// TODO: Is there a better way to detect whether this is a raw fork?
const uint32 dataOffset = stream.readUint32BE();
diff --git a/common/macresman.h b/common/macresman.h
index 34f785a9bd4..58aa93b3cc1 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -166,6 +166,19 @@ public:
*/
static bool exists(const Path &fileName);
+ /**
+ * Attempt to read the Mac Finder info metadata for a file path.
+ * @param fileName The base file name of the file
+ * @param archive The archive to search in
+ * @param outFinderInfo The loaded and parsed Finder info
+ * @param outFinderExtendedInfo The loaded and parsed Finder extended info
+ * @return True if finder info was available for a path, false if not
+ */
+ static bool getFileFinderInfo(const Path &fileName, Archive &archive, MacFinderInfo &outFinderInfo);
+ static bool getFileFinderInfo(const Path &fileName, Archive &archive, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo);
+ static bool getFileFinderInfo(const Path &fileName, MacFinderInfo &outFinderInfo);
+ static bool getFileFinderInfo(const Path &fileName, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo);
+
/**
* List all filenames matching pattern for opening with open().
*
@@ -302,6 +315,18 @@ private:
bool loadFromRawFork(SeekableReadStream *stream);
bool loadFromAppleDouble(SeekableReadStream *stream);
+ /**
+ * Get Finder info from a file in MacBinary format
+ */
+ static bool getFinderInfoFromMacBinary(SeekableReadStream *stream, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo);
+
+ /**
+ * Get Finder info from a file in AppleDouble format
+ */
+ static bool getFinderInfoFromAppleDouble(SeekableReadStream *stream, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo);
+
+ static bool readAndValidateMacBinaryHeader(SeekableReadStream &stream, byte (&outMacBinaryHeader)[MBI_INFOHDR]);
+
static Path constructAppleDoubleName(Path name);
static Path disassembleAppleDoubleName(Path name, bool *isAppleDouble);
More information about the Scummvm-git-logs
mailing list