[Scummvm-git-logs] scummvm master -> 6ed3c946ffc8f371bce691a5b30b6bf9c2b2de53
sev-
noreply at scummvm.org
Sat Dec 16 18:30:26 UTC 2023
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:
6ed3c946ff COMMON: Add a way to check if an archive member is in a Mac archive so we can avoid decompressing the data fork to check
Commit: 6ed3c946ffc8f371bce691a5b30b6bf9c2b2de53
https://github.com/scummvm/scummvm/commit/6ed3c946ffc8f371bce691a5b30b6bf9c2b2de53
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2023-12-16T19:30:23+01:00
Commit Message:
COMMON: Add a way to check if an archive member is in a Mac archive so we can avoid decompressing the data fork to check for MacBinary when the resource data is always in the alt stream.
Changed paths:
common/archive.cpp
common/archive.h
common/compression/stuffit.cpp
common/compression/vise.cpp
common/macresman.cpp
engines/mtropolis/vfs.cpp
engines/mtropolis/vfs.h
diff --git a/common/archive.cpp b/common/archive.cpp
index db189daf2a6..56f243b17e0 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -37,6 +37,10 @@ U32String ArchiveMember::getDisplayName() const {
return getName();
}
+bool ArchiveMember::isInMacArchive() const {
+ return false;
+}
+
bool ArchiveMember::isDirectory() const {
return false;
}
diff --git a/common/archive.h b/common/archive.h
index aeae4e98265..7cc0f4901f0 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -82,6 +82,7 @@ public:
virtual bool isDirectory() const; /*!< Checks if the ArchiveMember is a directory. */
virtual void listChildren(ArchiveMemberList &childList, const char *pattern = nullptr) const; /*!< Adds the immediate children of this archive member to childList, optionally matching a pattern. */
virtual U32String getDisplayName() const; /*!< Get the display name of the archive member. */
+ virtual bool isInMacArchive() const; /*!< Checks if the ArchiveMember is in a Mac archive, in which case resource forks and Finder info can only be loaded via alt streams. */
};
struct ArchiveMemberDetails {
diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index 4d3449f38f6..704b1882d5c 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -73,6 +73,13 @@ private:
FileEntryFork resFork;
};
+ class StuffItArchiveMember : public Common::GenericArchiveMember {
+ public:
+ StuffItArchiveMember(const Common::Path &path, const Common::Archive &archive);
+
+ bool isInMacArchive() const override;
+ };
+
Common::SeekableReadStream *_stream;
typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
@@ -284,7 +291,7 @@ int StuffItArchive::listMembers(Common::ArchiveMemberList &list) const {
}
const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &path) const {
- return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
+ return Common::ArchiveMemberPtr(new StuffItArchiveMember(path, *this));
}
Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String &name) const {
@@ -1118,6 +1125,14 @@ void StuffItArchive::decompress14(Common::SeekableReadStream *src, byte *dst, ui
StuffItArchive::FileEntryFork::FileEntryFork() : uncompressedSize(0), compressedSize(0), offset(0), crc(0), compression(0) {
}
+StuffItArchive::StuffItArchiveMember::StuffItArchiveMember(const Common::Path &path, const Common::Archive &archive)
+ : Common::GenericArchiveMember(path, archive) {
+}
+
+bool StuffItArchive::StuffItArchiveMember::isInMacArchive() const {
+ return true;
+}
+
Common::Archive *createStuffItArchive(const Common::String &fileName, bool flattenTree) {
StuffItArchive *archive = new StuffItArchive();
diff --git a/common/compression/vise.cpp b/common/compression/vise.cpp
index f21631c56f6..e03f33d1dd4 100644
--- a/common/compression/vise.cpp
+++ b/common/compression/vise.cpp
@@ -73,6 +73,7 @@ private:
Common::String getName() const override;
Common::Path getPathInArchive() const override;
Common::String getFileName() const override;
+ bool isInMacArchive() const override;
private:
Common::SeekableReadStream *createReadStreamForDataStream(bool isResFork) const;
@@ -219,6 +220,10 @@ Common::String MacVISEArchive::ArchiveMember::getFileName() const {
return _fileDesc->name;
}
+bool MacVISEArchive::ArchiveMember::isInMacArchive() const {
+ return true;
+}
+
MacVISEArchive::FileDesc::FileDesc() : type{0, 0, 0, 0}, creator{0, 0, 0, 0}, compressedDataSize(0), uncompressedDataSize(0), compressedResSize(0), uncompressedResSize(0), positionInArchive(0) {
}
diff --git a/common/macresman.cpp b/common/macresman.cpp
index f8d741ab85d..23d4603dc9d 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -217,12 +217,28 @@ SeekableReadStream *MacResManager::openAppleDoubleWithAppleOrOSXNaming(Archive&
bool MacResManager::open(const Path &fileName, Archive &archive) {
close();
+ SeekableReadStream *stream = nullptr;
+
// Our preference is as following:
// AppleDouble in .rsrc -> Raw .rsrc -> MacBinary with .bin -> MacBinary without .bin -> AppleDouble in ._
// -> AppleDouble in __MACOSX -> Actual resource fork -> No resource fork
+ Common::ArchiveMemberPtr archiveMember = archive.getMember(fileName);
+
+ // If this is in a Mac archive, then the resource fork will always be in the alt stream
+ if (archiveMember && archiveMember->isInMacArchive()) {
+ _baseFileName = fileName;
+
+ stream = archive.createReadStreamForMemberAltStream(fileName, AltStreamType::MacResourceFork);
+ if (stream && !loadFromRawFork(stream))
+ _stream = nullptr;
+
+ // If the archive member exists, then the file exists, but has no res fork, so we should return true
+ return true;
+ }
+
// Prefer standalone files first, starting with raw forks
- SeekableReadStream *stream = archive.createReadStreamForMember(fileName.append(".rsrc"));
+ stream = archive.createReadStreamForMember(fileName.append(".rsrc"));
if (stream) {
// Some programs actually store AppleDouble there. Check it
@@ -251,14 +267,17 @@ bool MacResManager::open(const Path &fileName, Archive &archive) {
// Maybe file is in MacBinary but without .bin extension?
// Check it here
- stream = archive.createReadStreamForMember(fileName);
- if (stream && isMacBinary(*stream)) {
- stream->seek(0);
- if (loadFromMacBinary(stream)) {
- _baseFileName = fileName;
- return true;
+ if (archiveMember) {
+ stream = archiveMember->createReadStream();
+ if (stream && isMacBinary(*stream)) {
+ stream->seek(0);
+ if (loadFromMacBinary(stream)) {
+ _baseFileName = fileName;
+ return true;
+ }
}
- }
+ } else
+ stream = nullptr;
bool fileExists = (stream != nullptr);
@@ -285,7 +304,6 @@ bool MacResManager::open(const Path &fileName, Archive &archive) {
#ifdef MACOSX
// Check the actual fork on a Mac computer. It's even worse than __MACOSX as
// it's present on any HFS(+) and appears even after copying macbin on HFS(+).
- const ArchiveMemberPtr archiveMember = archive.getMember(fileName);
if (archiveMember.get()) {
// This could be a MacBinary file that still has a
// resource fork; if it is, it needs to get opened as MacBinary
@@ -332,7 +350,12 @@ SeekableReadStream * MacResManager::openDataForkFromMacBinary(SeekableReadStream
}
SeekableReadStream * MacResManager::openFileOrDataFork(const Path &fileName, Archive &archive) {
- SeekableReadStream *stream = archive.createReadStreamForMember(fileName);
+ SeekableReadStream *stream = nullptr;
+
+ Common::ArchiveMemberPtr archiveMember = archive.getMember(fileName);
+
+ bool mayBeMacBinary = true;
+
// Our preference is as following:
// File itself as macbinary -> File itself as raw -> .bin as macbinary
// Compared to open:
@@ -346,27 +369,37 @@ SeekableReadStream * MacResManager::openFileOrDataFork(const Path &fileName, Arc
// right levels of onion. Fortunately no game so far does it. But someday...
// Hopefully not.
- // Check the basename for Macbinary
- if (stream && isMacBinary(*stream)) {
- stream->seek(MBI_DFLEN);
- uint32 dataSize = stream->readUint32BE();
- return new SeekableSubReadStream(stream, MBI_INFOHDR, MBI_INFOHDR + dataSize, DisposeAfterUse::YES);
- }
- // All formats other than Macbinary and AppleSingle (not supported) use
- // basename-named file as data fork holder.
- if (stream) {
- stream->seek(0);
- return stream;
+ if (archiveMember && archiveMember->isInMacArchive())
+ mayBeMacBinary = false;
+
+ if (archiveMember) {
+ stream = archiveMember->createReadStream();
+
+ // Check the basename for Macbinary
+ if (mayBeMacBinary && stream && isMacBinary(*stream)) {
+ stream->seek(MBI_DFLEN);
+ uint32 dataSize = stream->readUint32BE();
+ return new SeekableSubReadStream(stream, MBI_INFOHDR, MBI_INFOHDR + dataSize, DisposeAfterUse::YES);
+ }
+
+ // All formats other than Macbinary and AppleSingle (not supported) use
+ // basename-named file as data fork holder.
+ if (stream) {
+ stream->seek(0);
+ return stream;
+ }
}
- // Check .bin for MacBinary next
- stream = archive.createReadStreamForMember(fileName.append(".bin"));
- if (stream && isMacBinary(*stream)) {
- stream->seek(MBI_DFLEN);
- uint32 dataSize = stream->readUint32BE();
- return new SeekableSubReadStream(stream, MBI_INFOHDR, MBI_INFOHDR + dataSize, DisposeAfterUse::YES);
+ if (mayBeMacBinary) {
+ // Check .bin for MacBinary next
+ stream = archive.createReadStreamForMember(fileName.append(".bin"));
+ if (stream && isMacBinary(*stream)) {
+ stream->seek(MBI_DFLEN);
+ uint32 dataSize = stream->readUint32BE();
+ return new SeekableSubReadStream(stream, MBI_INFOHDR, MBI_INFOHDR + dataSize, DisposeAfterUse::YES);
+ }
+ delete stream;
}
- delete stream;
// The file doesn't exist
return nullptr;
diff --git a/engines/mtropolis/vfs.cpp b/engines/mtropolis/vfs.cpp
index c2659183e02..f33e1005bc2 100644
--- a/engines/mtropolis/vfs.cpp
+++ b/engines/mtropolis/vfs.cpp
@@ -235,4 +235,8 @@ Common::U32String VirtualFileSystem::VFSArchiveMember::getDisplayName() const {
return _virtualFile->_archiveMember->getDisplayName();
}
+bool VirtualFileSystem::VFSArchiveMember::isInMacArchive() const {
+ return _virtualFile->_archiveMember->isInMacArchive();
+}
+
} // End of namespace MTropolis
diff --git a/engines/mtropolis/vfs.h b/engines/mtropolis/vfs.h
index c64ab56ce3b..43d4f27e756 100644
--- a/engines/mtropolis/vfs.h
+++ b/engines/mtropolis/vfs.h
@@ -92,6 +92,7 @@ private:
bool isDirectory() const override;
void listChildren(Common::ArchiveMemberList &childList, const char *pattern) const override;
Common::U32String getDisplayName() const override;
+ bool isInMacArchive() const override;
private:
const VirtualFile *_virtualFile;
More information about the Scummvm-git-logs
mailing list