mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-01 15:55:45 +00:00
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.
This commit is contained in:
parent
237e6231dd
commit
6ed3c946ff
@ -37,6 +37,10 @@ U32String ArchiveMember::getDisplayName() const {
|
||||
return getName();
|
||||
}
|
||||
|
||||
bool ArchiveMember::isInMacArchive() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArchiveMember::isDirectory() const {
|
||||
return false;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user