[Scummvm-git-logs] scummvm master -> be0ee20b4aec6fefb6fcb26042488dd75131a2a2
sev-
noreply at scummvm.org
Tue Aug 29 22:31:04 UTC 2023
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
9892bedc61 COMMON: Add createReadStreamForAltStream to open Mac resource fork and metadata streams
be0ee20b4a MTROPOLIS: Fix SPQR Mac not booting
Commit: 9892bedc61d8fee94587f80a589960ef6876ce02
https://github.com/scummvm/scummvm/commit/9892bedc61d8fee94587f80a589960ef6876ce02
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-30T00:31:00+02:00
Commit Message:
COMMON: Add createReadStreamForAltStream to open Mac resource fork and metadata streams
Changed paths:
backends/fs/abstract-fs.cpp
backends/fs/abstract-fs.h
backends/fs/posix/posix-fs.cpp
backends/fs/posix/posix-fs.h
common/archive.cpp
common/archive.h
common/compression/gentee_installer.cpp
common/compression/stuffit.cpp
common/compression/vise.cpp
common/formats/prodos.cpp
common/formats/prodos.h
common/fs.cpp
common/fs.h
common/macresman.cpp
engines/grim/lab.h
engines/mm/shared/utils/engine_data.cpp
engines/stark/formats/xarc.cpp
engines/ultima/shared/engine/data_archive.cpp
engines/wintermute/base/file/base_file_entry.cpp
engines/wintermute/base/file/base_file_entry.h
diff --git a/backends/fs/abstract-fs.cpp b/backends/fs/abstract-fs.cpp
index 3feb04a1553..b5b8c44542a 100644
--- a/backends/fs/abstract-fs.cpp
+++ b/backends/fs/abstract-fs.cpp
@@ -35,3 +35,7 @@ const char *AbstractFSNode::lastPathComponent(const Common::String &str, const c
return cur + 1;
}
+
+Common::SeekableReadStream *AbstractFSNode::createReadStreamForAltStream(Common::AltStreamType altStreamType) {
+ return nullptr;
+}
diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h
index 3458a61fc69..54831079e89 100644
--- a/backends/fs/abstract-fs.h
+++ b/backends/fs/abstract-fs.h
@@ -182,6 +182,16 @@ public:
*/
virtual Common::SeekableReadStream *createReadStream() = 0;
+ /**
+ * Creates a SeekableReadStream instance corresponding to an alternate
+ * stream of the file referred by this node. This assumes that the node
+ * actually refers to a readable file and the alt stream exists.
+ * If either is not the case, 0 is returned.
+ *
+ * @return pointer to the stream object, 0 in case of a failure
+ */
+ virtual Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType);
+
/**
* Creates a WriteStream instance corresponding to the file
* referred by this node. This assumes that the node actually refers
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 4db92eb7e96..d63af64a5fd 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -269,6 +269,17 @@ Common::SeekableReadStream *POSIXFilesystemNode::createReadStream() {
return PosixIoStream::makeFromPath(getPath(), false);
}
+Common::SeekableReadStream *POSIXFilesystemNode::createReadStreamForAltStream(Common::AltStreamType altStreamType) {
+#ifdef MACOSX
+ if (altStreamType == Common::AltStreamType::MacResourceFork) {
+ // Check the actual fork on a Mac computer
+ return PosixIoStream::makeFromPath(getPath() + "/..namedfork/rsrc", false);
+ }
+#endif
+
+ return nullptr;
+}
+
Common::SeekableWriteStream *POSIXFilesystemNode::createWriteStream() {
return PosixIoStream::makeFromPath(getPath(), true);
}
diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h
index 3f70a233229..f1ed9607e84 100644
--- a/backends/fs/posix/posix-fs.h
+++ b/backends/fs/posix/posix-fs.h
@@ -66,6 +66,7 @@ public:
AbstractFSNode *getParent() const override;
Common::SeekableReadStream *createReadStream() override;
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) override;
Common::SeekableWriteStream *createWriteStream() override;
bool createDirectory() override;
diff --git a/common/archive.cpp b/common/archive.cpp
index ae50f6492ae..e882cd88d4a 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -54,6 +54,9 @@ SeekableReadStream *GenericArchiveMember::createReadStream() const {
return _parent.createReadStreamForMember(_path);
}
+SeekableReadStream *GenericArchiveMember::createReadStreamForAltStream(AltStreamType altStreamType) const {
+ return _parent.createReadStreamForMemberAltStream(_path, altStreamType);
+}
int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents) const {
// Get all "names" (TODO: "files" ?)
@@ -80,6 +83,10 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, b
return matches;
}
+SeekableReadStream *Archive::createReadStreamForMemberAltStream(const Path &path, AltStreamType altStreamType) const {
+ return nullptr;
+}
+
Common::Error Archive::dumpArchive(String destPath) {
Common::ArchiveMemberList files;
@@ -135,17 +142,34 @@ char Archive::getPathSeparator() const {
}
SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(const Path &path) const {
- String translated = translatePath(path);
+ return createReadStreamForMemberImpl(path, false, Common::AltStreamType::Invalid);
+}
+
+SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMemberAltStream(const Path &path, Common::AltStreamType altStreamType) const {
+ // There is no situation where an invalid alt stream should be returning anything unless the implementation
+ // of readContentsForPathAltStream is broken, and attempting that will break the cache keying since we used Invalid
+ // for keying the primary stream.
+ if (altStreamType == Common::AltStreamType::Invalid)
+ return nullptr;
+
+ return createReadStreamForMemberImpl(path, true, altStreamType);
+}
+
+SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMemberImpl(const Path &path, bool isAltStream, Common::AltStreamType altStreamType) const {
+ CacheKey cacheKey;
+ cacheKey.path = translatePath(path);
+ cacheKey.altStreamType = isAltStream ? altStreamType : AltStreamType::Invalid;
+
bool isNew = false;
- if (!_cache.contains(translated)) {
- SharedArchiveContents readResult = readContentsForPath(translated);
+ if (!_cache.contains(cacheKey)) {
+ SharedArchiveContents readResult = isAltStream ? readContentsForPathAltStream(cacheKey.path, altStreamType) : readContentsForPath(cacheKey.path);
if (readResult._bypass)
return readResult._bypass;
- _cache[translated] = readResult;
+ _cache[cacheKey] = readResult;
isNew = true;
}
- SharedArchiveContents* entry = &_cache[translated];
+ SharedArchiveContents* entry = &_cache[cacheKey];
// Errors and missing files. Just return nullptr,
// no need to create stream.
@@ -155,11 +179,11 @@ SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(
// Check whether the entry is still valid as WeakPtr might have expired.
if (!entry->makeStrong()) {
// If it's expired, recreate the entry.
- SharedArchiveContents readResult = readContentsForPath(translated);
+ SharedArchiveContents readResult = isAltStream ? readContentsForPathAltStream(cacheKey.path, altStreamType) : readContentsForPath(cacheKey.path);
if (readResult._bypass)
return readResult._bypass;
- _cache[translated] = readResult;
- entry = &_cache[translated];
+ _cache[cacheKey] = readResult;
+ entry = &_cache[cacheKey];
isNew = true;
}
@@ -180,6 +204,20 @@ SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(
return memStream;
}
+SharedArchiveContents MemcachingCaseInsensitiveArchive::readContentsForPathAltStream(const String &translatedPath, AltStreamType altStreamType) const {
+ return SharedArchiveContents();
+}
+
+MemcachingCaseInsensitiveArchive::CacheKey::CacheKey() : altStreamType(AltStreamType::Invalid) {
+}
+
+bool MemcachingCaseInsensitiveArchive::CacheKey_EqualTo::operator()(const CacheKey &x, const CacheKey &y) const {
+ return (x.altStreamType == y.altStreamType) && x.path.equalsIgnoreCase(y.path);
+}
+
+uint MemcachingCaseInsensitiveArchive::CacheKey_Hash::operator()(const CacheKey &x) const {
+ return static_cast<uint>(hashit_lower(x.path) * 1000003u) ^ static_cast<uint>(x.altStreamType);
+};
SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
ArchiveNodeList::iterator it = _list.begin();
@@ -415,6 +453,20 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const Path &path) const
return nullptr;
}
+SeekableReadStream *SearchSet::createReadStreamForMemberAltStream(const Path &path, AltStreamType altStreamType) const {
+ if (path.empty())
+ return nullptr;
+
+ ArchiveNodeList::const_iterator it = _list.begin();
+ for (; it != _list.end(); ++it) {
+ SeekableReadStream *stream = it->_arc->createReadStreamForMemberAltStream(path, altStreamType);
+ if (stream)
+ return stream;
+ }
+
+ return nullptr;
+}
+
SeekableReadStream *SearchSet::createReadStreamForMemberNext(const Path &path, const Archive *starting) const {
if (path.empty())
return nullptr;
diff --git a/common/archive.h b/common/archive.h
index 96f07d79ddd..6624c73ad71 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -46,6 +46,13 @@ namespace Common {
class FSNode;
class SeekableReadStream;
+enum class AltStreamType {
+ Invalid,
+
+ MacFinderInfo,
+ MacResourceFork,
+};
+
/**
* The ArchiveMember class is an abstract interface to represent elements inside
@@ -59,6 +66,7 @@ class ArchiveMember {
public:
virtual ~ArchiveMember() { }
virtual SeekableReadStream *createReadStream() const = 0; /*!< Create a read stream. */
+ virtual SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const = 0; /*!< Create a read stream of an alternate stream. */
/**
* @deprecated Get the name of the archive member. This may be a file name or a full path depending on archive type.
@@ -112,6 +120,7 @@ public:
Path getPathInArchive() const override; /*!< Get the full path of the archive member relative to the containing archive root. */
String getFileName() const override; /*!< Get the file name of the archive member relative to its containing directory within the archive. */
SeekableReadStream *createReadStream() const override; /*!< Create a read stream. */
+ SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const override; /*!< Create a read stream of an alternate stream. */
private:
const Archive &_parent;
@@ -167,6 +176,14 @@ public:
*/
virtual SeekableReadStream *createReadStreamForMember(const Path &path) const = 0;
+ /**
+ * Create a stream bound to an alternate stream of a member with the specified
+ * name in the archive. If no member with this name exists, 0 is returned.
+ *
+ * @return The newly created input stream.
+ */
+ virtual SeekableReadStream *createReadStreamForMemberAltStream(const Path &path, AltStreamType altStreamType) const;
+
/**
* For most archives: same as previous. For SearchSet see SearchSet
* documentation.
@@ -243,6 +260,7 @@ class MemcachingCaseInsensitiveArchive : public Archive {
public:
MemcachingCaseInsensitiveArchive(uint32 maxStronglyCachedSize = 512) : _maxStronglyCachedSize(maxStronglyCachedSize) {}
SeekableReadStream *createReadStreamForMember(const Path &path) const;
+ SeekableReadStream *createReadStreamForMemberAltStream(const Path &path, Common::AltStreamType altStreamType) const;
virtual String translatePath(const Path &path) const {
// Most of users of this class implement DOS-like archives.
@@ -250,10 +268,28 @@ public:
return normalizePath(path.toString('\\'), '\\');
}
- virtual SharedArchiveContents readContentsForPath(const String& translatedPath) const = 0;
+ virtual SharedArchiveContents readContentsForPath(const String &translatedPath) const = 0;
+ virtual SharedArchiveContents readContentsForPathAltStream(const String &translatedPath, AltStreamType altStreamType) const;
private:
- mutable HashMap<String, SharedArchiveContents, IgnoreCase_Hash, IgnoreCase_EqualTo> _cache;
+ struct CacheKey {
+ CacheKey();
+
+ String path;
+ AltStreamType altStreamType;
+ };
+
+ struct CacheKey_EqualTo {
+ bool operator()(const CacheKey &x, const CacheKey &y) const;
+ };
+
+ struct CacheKey_Hash {
+ uint operator()(const CacheKey &x) const;
+ };
+
+ SeekableReadStream *createReadStreamForMemberImpl(const Path &path, bool isAltStream, Common::AltStreamType altStreamType) const;
+
+ mutable HashMap<CacheKey, SharedArchiveContents, CacheKey_Hash, CacheKey_EqualTo> _cache;
uint32 _maxStronglyCachedSize;
};
@@ -388,6 +424,12 @@ public:
*/
SeekableReadStream *createReadStreamForMember(const Path &path) const override;
+ /**
+ * Implement createReadStreamForMemberAltStream from the Archive base class. The current policy is
+ * opening the first file encountered that matches the name.
+ */
+ SeekableReadStream *createReadStreamForMemberAltStream(const Path &path, AltStreamType altStreamType) const override;
+
/**
* Similar to above but exclude matches from archives before starting and starting itself.
*/
diff --git a/common/compression/gentee_installer.cpp b/common/compression/gentee_installer.cpp
index ab0d71f5e80..7abda6a1a09 100644
--- a/common/compression/gentee_installer.cpp
+++ b/common/compression/gentee_installer.cpp
@@ -585,6 +585,7 @@ public:
ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::String &path, const Common::String &name, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed);
Common::SeekableReadStream *createReadStream() const override;
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
Common::String getName() const override;
Common::Path getPathInArchive() const override { return getName(); }
Common::String getFileName() const override { return getName(); }
@@ -623,6 +624,10 @@ Common::SeekableReadStream *ArchiveItem::createReadStream() const {
return sliceSubstream;
}
+Common::SeekableReadStream *ArchiveItem::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
+ return nullptr;
+}
+
Common::String ArchiveItem::getName() const {
return _name;
}
diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index 529fa07c928..217f0397b1b 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -52,17 +52,25 @@ public:
bool hasFile(const Common::Path &path) const override;
int listMembers(Common::ArchiveMemberList &list) const override;
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
- Common::SharedArchiveContents readContentsForPath(const Common::String& name) const override;
+ Common::SharedArchiveContents readContentsForPath(const Common::String &name) const override;
+ Common::SharedArchiveContents readContentsForPathAltStream(const String &translatedPath, Common::AltStreamType altStreamType) const override;
Common::String translatePath(const Common::Path &path) const override;
char getPathSeparator() const override;
private:
- struct FileEntry {
- byte compression;
+ struct FileEntryFork {
+ FileEntryFork();
+
uint32 uncompressedSize;
uint32 compressedSize;
uint32 offset;
uint16 crc;
+ byte compression;
+ };
+
+ struct FileEntry {
+ FileEntryFork dataFork;
+ FileEntryFork resFork;
};
Common::SeekableReadStream *_stream;
@@ -82,6 +90,8 @@ private:
// Decompression Helpers
void update14(uint16 first, uint16 last, byte *code, uint16 *freq) const;
void readTree14(Common::BitStream8LSB *bits, SIT14Data *dat, uint16 codesize, uint16 *result) const;
+
+ Common::SharedArchiveContents readContentsForPathFork(const String &translatedPath, bool isResFork) const;
};
StuffItArchive::StuffItArchive() : Common::MemcachingCaseInsensitiveArchive(), _flattenTree(false) {
@@ -220,37 +230,32 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree)
if (!flattenTree)
name = dirPrefix + name;
- _metadataMap[name + ".finf"] = finfo.toData();
+ _metadataMap[name] = finfo.toData();
if (dataForkUncompressedSize != 0) {
// We have a data fork
- FileEntry entry;
- entry.compression = dataForkCompression;
- entry.uncompressedSize = dataForkUncompressedSize;
- entry.compressedSize = dataForkCompressedSize;
- entry.offset = _stream->pos() + resForkCompressedSize;
- entry.crc = dataForkCRC;
- _map[name] = entry;
+ FileEntryFork &entryFork = _map[name].dataFork;
+ entryFork.compression = dataForkCompression;
+ entryFork.uncompressedSize = dataForkUncompressedSize;
+ entryFork.compressedSize = dataForkCompressedSize;
+ entryFork.offset = _stream->pos() + resForkCompressedSize;
+ entryFork.crc = dataForkCRC;
- debug(0, "StuffIt file '%s', Compression = %d", name.c_str(), entry.compression);
+ debug(0, "StuffIt file '%s' data fork, Compression = %d", name.c_str(), entryFork.compression);
}
if (resForkUncompressedSize != 0) {
// We have a resource fork
- // Add a .rsrc extension so we know it's the resource fork
- name += ".rsrc";
-
- FileEntry entry;
- entry.compression = resForkCompression;
- entry.uncompressedSize = resForkUncompressedSize;
- entry.compressedSize = resForkCompressedSize;
- entry.offset = _stream->pos();
- entry.crc = resForkCRC;
- _map[name] = entry;
+ FileEntryFork &entryFork = _map[name].resFork;
+ entryFork.compression = resForkCompression;
+ entryFork.uncompressedSize = resForkUncompressedSize;
+ entryFork.compressedSize = resForkCompressedSize;
+ entryFork.offset = _stream->pos();
+ entryFork.crc = resForkCRC;
- debug(0, "StuffIt file '%s', Compression = %d", name.c_str(), entry.compression);
+ debug(0, "StuffIt file '%s' res fork, Compression = %d", name.c_str(), entryFork.compression);
}
// Go to the next entry
@@ -282,10 +287,14 @@ const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &pat
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
}
-Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String& name) const {
- if (!_stream || !_map.contains(name)) {
- if (_metadataMap.contains(name)) {
- const Common::MacFinderInfoData &metadata = _metadataMap[name];
+Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String &name) const {
+ return readContentsForPathFork(name, false);
+}
+
+Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const String &translatedPath, Common::AltStreamType altStreamType) const {
+ if (altStreamType == Common::AltStreamType::MacFinderInfo) {
+ if (_metadataMap.contains(translatedPath)) {
+ const Common::MacFinderInfoData &metadata = _metadataMap[translatedPath];
byte *copy = new byte[sizeof(Common::MacFinderInfoData)];
memcpy(copy, reinterpret_cast<const byte *>(&metadata), sizeof(Common::MacFinderInfoData));
return Common::SharedArchiveContents(copy, sizeof(Common::MacFinderInfoData));
@@ -293,39 +302,59 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::
return Common::SharedArchiveContents();
}
+ if (altStreamType == Common::AltStreamType::MacResourceFork)
+ return readContentsForPathFork(translatedPath, true);
+
+ return Common::SharedArchiveContents();
+}
+
+Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Common::String &name, bool isResFork) const {
+ FileMap::const_iterator entryIt = _map.find(name);
+
+ if (entryIt == _map.end())
+ return Common::SharedArchiveContents();
+
const FileEntry &entry = _map[name];
+ const FileEntryFork &entryFork = isResFork ? entry.resFork : entry.dataFork;
- if (entry.compression & 0xF0)
+ if (entryFork.uncompressedSize == 0) {
+ if (isResFork)
+ return Common::SharedArchiveContents();
+ else
+ return Common::SharedArchiveContents(nullptr, 0); // Treat no data fork as an empty stream
+ }
+
+ if (entryFork.compression & 0xF0)
error("Unhandled StuffIt encryption");
- Common::SeekableSubReadStream subStream(_stream, entry.offset, entry.offset + entry.compressedSize);
+ Common::SeekableSubReadStream subStream(_stream, entryFork.offset, entryFork.offset + entryFork.compressedSize);
- byte *uncompressedBlock = new byte[entry.uncompressedSize];
+ byte *uncompressedBlock = new byte[entryFork.uncompressedSize];
// We currently only support type 14 compression
- switch (entry.compression) {
+ switch (entryFork.compression) {
case 0: // Uncompressed
- subStream.read(uncompressedBlock, entry.uncompressedSize);
+ subStream.read(uncompressedBlock, entryFork.uncompressedSize);
break;
case 13: // TableHuff
- if (!decompress13(&subStream, uncompressedBlock, entry.uncompressedSize))
+ if (!decompress13(&subStream, uncompressedBlock, entryFork.uncompressedSize))
error("SIT-13 decompression failed");
break;
case 14: // Installer
- decompress14(&subStream, uncompressedBlock, entry.uncompressedSize);
+ decompress14(&subStream, uncompressedBlock, entryFork.uncompressedSize);
break;
default:
- error("Unhandled StuffIt compression %d", entry.compression);
+ error("Unhandled StuffIt compression %d", entryFork.compression);
return Common::SharedArchiveContents();
}
- uint16 actualCRC = Common::CRC16().crcFast(uncompressedBlock, entry.uncompressedSize);
+ uint16 actualCRC = Common::CRC16().crcFast(uncompressedBlock, entryFork.uncompressedSize);
- if (actualCRC != entry.crc) {
- error("StuffItArchive::readContentsForPath(): CRC mismatch: %04x vs %04x for file %s", actualCRC, entry.crc, name.c_str());
+ if (actualCRC != entryFork.crc) {
+ error("StuffItArchive::readContentsForPath(): CRC mismatch: %04x vs %04x for file %s %s fork", actualCRC, entryFork.crc, name.c_str(), (isResFork ? "res" : "data"));
}
- return Common::SharedArchiveContents(uncompressedBlock, entry.uncompressedSize);
+ return Common::SharedArchiveContents(uncompressedBlock, entryFork.uncompressedSize);
}
Common::String StuffItArchive::translatePath(const Common::Path &path) const {
@@ -1085,6 +1114,10 @@ void StuffItArchive::decompress14(Common::SeekableReadStream *src, byte *dst, ui
#undef OUTPUT_VAL
#undef ALIGN_BITS
+
+StuffItArchive::FileEntryFork::FileEntryFork() : uncompressedSize(0), compressedSize(0), offset(0), crc(0), compression(0) {
+}
+
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 649c1fd81c7..f21631c56f6 100644
--- a/common/compression/vise.cpp
+++ b/common/compression/vise.cpp
@@ -66,23 +66,19 @@ private:
class ArchiveMember : public Common::ArchiveMember {
public:
- enum SubstreamType {
- kSubstreamTypeData,
- kSubstreamTypeResource,
- kSubstreamTypeFinderInfo,
- };
-
- ArchiveMember(Common::SeekableReadStream *archiveStream, const FileDesc *fileDesc, SubstreamType substreamType);
+ ArchiveMember(Common::SeekableReadStream *archiveStream, const FileDesc *fileDesc);
Common::SeekableReadStream *createReadStream() const override;
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
Common::String getName() const override;
Common::Path getPathInArchive() const override;
Common::String getFileName() const override;
private:
+ Common::SeekableReadStream *createReadStreamForDataStream(bool isResFork) const;
+
Common::SeekableReadStream *_archiveStream;
const FileDesc *_fileDesc;
- SubstreamType _substreamType;
};
public:
@@ -96,23 +92,28 @@ public:
int listMembers(Common::ArchiveMemberList &list) const override;
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
+ Common::SeekableReadStream *createReadStreamForMemberAltStream(const Common::Path &path, Common::AltStreamType altStreamType) const override;
char getPathSeparator() const override;
private:
- bool getFileDescIndex(const Common::Path &path, uint &outIndex, ArchiveMember::SubstreamType &outSubstreamType) const;
+ bool getFileDescIndex(const Common::Path &path, uint &outIndex) const;
Common::SeekableReadStream *_archiveStream;
Common::Array<FileDesc> _fileDescs;
Common::Array<DirectoryDesc> _directoryDescs;
};
-MacVISEArchive::ArchiveMember::ArchiveMember(Common::SeekableReadStream *archiveStream, const FileDesc *fileDesc, SubstreamType substreamType)
- : _archiveStream(archiveStream), _fileDesc(fileDesc), _substreamType(substreamType) {
+MacVISEArchive::ArchiveMember::ArchiveMember(Common::SeekableReadStream *archiveStream, const FileDesc *fileDesc)
+ : _archiveStream(archiveStream), _fileDesc(fileDesc) {
}
Common::SeekableReadStream *MacVISEArchive::ArchiveMember::createReadStream() const {
- if (_substreamType == kSubstreamTypeFinderInfo) {
- Common::MacFinderInfoData *finfoData = static_cast<Common::MacFinderInfoData*>(malloc(sizeof(Common::MacFinderInfoData)));
+ return createReadStreamForDataStream(false);
+}
+
+Common::SeekableReadStream *MacVISEArchive::ArchiveMember::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
+ if (altStreamType == AltStreamType::MacFinderInfo) {
+ Common::MacFinderInfoData *finfoData = static_cast<Common::MacFinderInfoData *>(malloc(sizeof(Common::MacFinderInfoData)));
if (!finfoData)
return nullptr;
@@ -126,6 +127,13 @@ Common::SeekableReadStream *MacVISEArchive::ArchiveMember::createReadStream() co
return new Common::MemoryReadStream(reinterpret_cast<const byte *>(finfoData), sizeof(Common::MacFinderInfoData), DisposeAfterUse::YES);
}
+ if (altStreamType == AltStreamType::MacResourceFork)
+ return createReadStreamForDataStream(true);
+
+ return nullptr;
+}
+
+Common::SeekableReadStream *MacVISEArchive::ArchiveMember::createReadStreamForDataStream(bool isResFork) const {
static const uint8 vl3DeobfuscationTable[] = {
0x6a, 0xb7, 0x36, 0xec, 0x15, 0xd9, 0xc8, 0x73, 0xe8, 0x38, 0x9a, 0xdf, 0x21, 0x25, 0xd0, 0xcc,
0xfd, 0xdc, 0x16, 0xd7, 0xe3, 0x43, 0x05, 0xc5, 0x8f, 0x48, 0xda, 0xf2, 0x3f, 0x10, 0x23, 0x6c,
@@ -145,12 +153,15 @@ Common::SeekableReadStream *MacVISEArchive::ArchiveMember::createReadStream() co
0x86, 0xdd, 0x5f, 0x42, 0xd3, 0x02, 0x61, 0x95, 0x0c, 0x5c, 0xa5, 0xcd, 0xc0, 0x07, 0xe2, 0xf3,
};
- const bool isResFork = (_substreamType == kSubstreamTypeResource);
-
uint32 uncompressedSize = isResFork ? _fileDesc->uncompressedResSize : _fileDesc->uncompressedDataSize;
uint32 compressedSize = isResFork ? _fileDesc->compressedResSize : _fileDesc->compressedDataSize;
uint32 filePosition = _fileDesc->positionInArchive;
+ if (uncompressedSize == 0 && !isResFork) {
+ // Always return a stream for the data fork, even if it's empty
+ return new Common::MemoryReadStream(nullptr, 0, DisposeAfterUse::NO);
+ }
+
if (isResFork)
filePosition += _fileDesc->compressedDataSize;
@@ -201,21 +212,11 @@ Common::String MacVISEArchive::ArchiveMember::getName() const {
}
Common::Path MacVISEArchive::ArchiveMember::getPathInArchive() const {
- if (_substreamType == kSubstreamTypeFinderInfo)
- return _fileDesc->fullPath.append(".finf", ':');
- else if (_substreamType == kSubstreamTypeResource)
- return _fileDesc->fullPath.append(".rsrc", ':');
- else
- return _fileDesc->fullPath;
+ return _fileDesc->fullPath;
}
Common::String MacVISEArchive::ArchiveMember::getFileName() const {
- if (_substreamType == kSubstreamTypeFinderInfo)
- return _fileDesc->name + ".finf";
- else if (_substreamType == kSubstreamTypeResource)
- return _fileDesc->name + ".rsrc";
- else
- return _fileDesc->name;
+ return _fileDesc->name;
}
MacVISEArchive::FileDesc::FileDesc() : type{0, 0, 0, 0}, creator{0, 0, 0, 0}, compressedDataSize(0), uncompressedDataSize(0), compressedResSize(0), uncompressedResSize(0), positionInArchive(0) {
@@ -360,8 +361,7 @@ const MacVISEArchive::FileDesc *MacVISEArchive::getFileDesc(const Common::Path &
bool MacVISEArchive::hasFile(const Common::Path &path) const {
uint index = 0;
- ArchiveMember::SubstreamType substreamType = ArchiveMember::kSubstreamTypeData;
- return getFileDescIndex(path, index, substreamType);
+ return getFileDescIndex(path, index);
}
int MacVISEArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -369,16 +369,7 @@ int MacVISEArchive::listMembers(Common::ArchiveMemberList &list) const {
for (uint fileIndex = 0; fileIndex < _fileDescs.size(); fileIndex++) {
const FileDesc &desc = _fileDescs[fileIndex];
- if (desc.uncompressedDataSize) {
- list.push_back(Common::ArchiveMemberPtr(new ArchiveMember(_archiveStream, &desc, ArchiveMember::kSubstreamTypeData)));
- numMembers++;
- }
- if (desc.uncompressedResSize) {
- list.push_back(Common::ArchiveMemberPtr(new ArchiveMember(_archiveStream, &desc, ArchiveMember::kSubstreamTypeResource)));
- numMembers++;
- }
-
- list.push_back(Common::ArchiveMemberPtr(new ArchiveMember(nullptr, &desc, ArchiveMember::kSubstreamTypeFinderInfo)));
+ list.push_back(Common::ArchiveMemberPtr(new ArchiveMember(_archiveStream, &desc)));
numMembers++;
}
return numMembers;
@@ -386,11 +377,10 @@ int MacVISEArchive::listMembers(Common::ArchiveMemberList &list) const {
const Common::ArchiveMemberPtr MacVISEArchive::getMember(const Common::Path &path) const {
uint descIndex = 0;
- ArchiveMember::SubstreamType substreamType = ArchiveMember::kSubstreamTypeData;
- if (!getFileDescIndex(path, descIndex, substreamType))
+ if (!getFileDescIndex(path, descIndex))
return nullptr;
- return Common::ArchiveMemberPtr(new ArchiveMember(_archiveStream, &_fileDescs[descIndex], substreamType));
+ return Common::ArchiveMemberPtr(new ArchiveMember(_archiveStream, &_fileDescs[descIndex]));
}
Common::SeekableReadStream *MacVISEArchive::createReadStreamForMember(const Common::Path &path) const {
@@ -401,34 +391,23 @@ Common::SeekableReadStream *MacVISEArchive::createReadStreamForMember(const Comm
return archiveMember->createReadStream();
}
+Common::SeekableReadStream *MacVISEArchive::createReadStreamForMemberAltStream(const Common::Path &path, Common::AltStreamType altStreamType) const {
+ Common::ArchiveMemberPtr archiveMember = getMember(path);
+ if (!archiveMember)
+ return nullptr;
+
+ return archiveMember->createReadStreamForAltStream(altStreamType);
+}
+
char MacVISEArchive::getPathSeparator() const {
return ':';
}
-bool MacVISEArchive::getFileDescIndex(const Common::Path &path, uint &outIndex, ArchiveMember::SubstreamType &outSubstreamType) const {
- Common::String convertedPath = path.toString(getPathSeparator());
-
- ArchiveMember::SubstreamType substreamType = ArchiveMember::kSubstreamTypeData;
- if (convertedPath.hasSuffix(".rsrc")) {
- substreamType = ArchiveMember::kSubstreamTypeResource;
- convertedPath = convertedPath.substr(0, convertedPath.size() - 5);
- } else if (convertedPath.hasSuffix(".finf")) {
- substreamType = ArchiveMember::kSubstreamTypeFinderInfo;
- convertedPath = convertedPath.substr(0, convertedPath.size() - 5);
- }
-
- Common::Path filePath(convertedPath, getPathSeparator());
-
+bool MacVISEArchive::getFileDescIndex(const Common::Path &path, uint &outIndex) const {
for (uint descIndex = 0; descIndex < _fileDescs.size(); descIndex++) {
const FileDesc &desc = _fileDescs[descIndex];
- if (desc.fullPath == filePath) {
- if (substreamType == ArchiveMember::SubstreamType::kSubstreamTypeData && desc.uncompressedDataSize == 0)
- return false;
- if (substreamType == ArchiveMember::SubstreamType::kSubstreamTypeResource && desc.uncompressedResSize == 0)
- return false;
-
- outSubstreamType = substreamType;
+ if (desc.fullPath == path) {
outIndex = descIndex;
return true;
}
diff --git a/common/formats/prodos.cpp b/common/formats/prodos.cpp
index 1fa5e498eb0..78b7c0ad2c0 100644
--- a/common/formats/prodos.cpp
+++ b/common/formats/prodos.cpp
@@ -172,6 +172,10 @@ Common::SeekableReadStream *ProDOSFile::createReadStream() const {
return new Common::MemoryReadStream(finalData, _eof, DisposeAfterUse::YES);
}
+Common::SeekableReadStream *ProDOSFile::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
+ return nullptr;
+}
+
// --- ProDOSDisk methods ---
/* The time and date are compressed into 16bit words, so to make them useable
diff --git a/common/formats/prodos.h b/common/formats/prodos.h
index 085e0ec2c91..f71db7ebfea 100644
--- a/common/formats/prodos.h
+++ b/common/formats/prodos.h
@@ -90,6 +90,7 @@ public:
Common::Path getPathInArchive() const override; // Returns _name
Common::String getFileName() const override; // Returns _name
Common::SeekableReadStream *createReadStream() const override; // This is what the archive needs to create a file
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
void getDataBlock(byte *memOffset, int offset, int size) const; // Gets data up to the size of a single data block (512 bytes)
int parseIndexBlock(byte *memOffset, int blockNum, int cSize) const; // Uses getDataBlock() on every pointer in the index file, adding them to byte * memory block
diff --git a/common/fs.cpp b/common/fs.cpp
index e794adbe6bc..42ab5f7b1be 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -33,6 +33,7 @@ public:
FSDirectoryFile(const Common::Path &pathInDirectory, const FSNode &fsNode);
SeekableReadStream *createReadStream() const override;
+ SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const override;
String getName() const override;
Path getPathInArchive() const override;
String getFileName() const override;
@@ -50,6 +51,10 @@ SeekableReadStream *FSDirectoryFile::createReadStream() const {
return _fsNode.createReadStream();
}
+SeekableReadStream *FSDirectoryFile::createReadStreamForAltStream(AltStreamType altStreamType) const {
+ return _fsNode.createReadStreamForAltStream(altStreamType);
+}
+
String FSDirectoryFile::getName() const {
return _fsNode.getName();
}
@@ -194,6 +199,21 @@ SeekableReadStream *FSNode::createReadStream() const {
return _realNode->createReadStream();
}
+SeekableReadStream *FSNode::createReadStreamForAltStream(AltStreamType altStreamType) const {
+ if (_realNode == nullptr)
+ return nullptr;
+
+ if (!_realNode->exists()) {
+ warning("FSNode::createReadStream: '%s' does not exist", getName().c_str());
+ return nullptr;
+ } else if (_realNode->isDirectory()) {
+ warning("FSNode::createReadStream: '%s' is a directory", getName().c_str());
+ return nullptr;
+ }
+
+ return _realNode->createReadStreamForAltStream(altStreamType);
+}
+
SeekableWriteStream *FSNode::createWriteStream() const {
if (_realNode == nullptr)
return nullptr;
@@ -360,21 +380,8 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const Path& pr
warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'",
Common::toPrintable(name.toString('/')).c_str());
}
- } else {
+ } else
_fileCache[name] = *it;
-
-#ifdef MACOSX
- // On Mac, check for native resource fork
- String rsrcName = it->getPath() + "/..namedfork/rsrc";
- FSNode rsrc = FSNode(rsrcName);
-
- Path cacheName = prefix.join(it->getRealName() + "/..namedfork/rsrc");
-
- if (rsrc.exists()) {
- _fileCache[cacheName] = rsrc;
- }
-#endif
- }
}
}
diff --git a/common/fs.h b/common/fs.h
index eb3e4ba03ee..6fa54266f2a 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -256,10 +256,20 @@ public:
* referred by this node. This assumes that the node actually refers
* to a readable file. If this is not the case, 0 is returned.
*
- * @return Pointer to the stream object, 0 in case of a failure.
+ * @return Pointer to the stream object, nullptr in case of a failure.
*/
SeekableReadStream *createReadStream() const override;
+ /**
+ * Create a SeekableReadStream instance corresponding to an alternate stream
+ * of the file referred by this node. This assumes that the node actually
+ * refers to a readable file and the alternate stream exists. If either is
+ * not the case, nullptr is returned.
+ *
+ * @return Pointer to the stream object, nullptr in case of a failure.
+ */
+ SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const override;
+
/**
* Create a WriteStream instance corresponding to the file
* referred by this node. This assumes that the node actually refers
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 3601ce364c8..fa819dd5b16 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -252,15 +252,19 @@ bool MacResManager::open(const Path &fileName, Archive &archive) {
// Maybe file is in MacBinary but without .bin extension?
// Check it here
- SeekableReadStream *rawStream = archive.createReadStreamForMember(fileName);
- if (rawStream && isMacBinary(*rawStream)) {
- rawStream->seek(0);
- if (loadFromMacBinary(rawStream)) {
+ stream = archive.createReadStreamForMember(fileName);
+ if (stream && isMacBinary(*stream)) {
+ stream->seek(0);
+ if (loadFromMacBinary(stream)) {
_baseFileName = fileName;
return true;
}
}
+ bool fileExists = (stream != nullptr);
+
+ delete stream;
+
// Then try for AppleDouble using Apple's naming
// As they are created silently from plain files (e.g. from a macbinary) they are pretty low quality often.
stream = openAppleDoubleWithAppleOrOSXNaming(archive, fileName);
@@ -270,6 +274,15 @@ bool MacResManager::open(const Path &fileName, Archive &archive) {
}
delete stream;
+ // Try alternate stream
+ stream = archive.createReadStreamForMemberAltStream(fileName, AltStreamType::MacResourceFork);
+ if (stream && loadFromRawFork(stream)) {
+ _baseFileName = fileName;
+ return true;
+ }
+ delete stream;
+
+
#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(+).
@@ -296,9 +309,8 @@ bool MacResManager::open(const Path &fileName, Archive &archive) {
}
#endif
- if (rawStream) { // No non-empty resource fork found.
+ if (fileExists) { // No non-empty resource fork found, but the file still exists
_baseFileName = fileName;
- delete rawStream;
_stream = nullptr;
return true;
}
@@ -390,15 +402,15 @@ bool MacResManager::getFileFinderInfo(const Path &fileName, Archive &archive, Ma
bool MacResManager::getFileFinderInfo(const Path &fileName, Archive &archive, MacFinderInfo &outFinderInfo, MacFinderExtendedInfo &outFinderExtendedInfo) {
// Our preference is as following:
- // .finf -> AppleDouble in .rsrc -> MacBinary with .bin -> MacBinary without .bin -> AppleDouble in ._
+ // Alt stream -> AppleDouble in .rsrc -> MacBinary with .bin -> MacBinary without .bin -> AppleDouble in ._
// -> AppleDouble in __MACOSX -> No finder info
// If you compare with open there are following differences:
// * We add .finf. It has only finder info
// * We skip raw .rsrc as it lack finder info
// * Actual finder info on OSX isn't implemented yet
- // 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")));
+ // Prefer alt stream first (especially since this can avoid decompressing entire files from slow archive formats like StuffIt Installer)
+ Common::ScopedPtr<SeekableReadStream> stream(archive.createReadStreamForMemberAltStream(fileName, AltStreamType::MacFinderInfo));
if (stream) {
MacFinderInfoData finfoData;
MacFinderExtendedInfoData fxinfoData;
diff --git a/engines/grim/lab.h b/engines/grim/lab.h
index 6573ff43c03..621bba394d0 100644
--- a/engines/grim/lab.h
+++ b/engines/grim/lab.h
@@ -42,6 +42,7 @@ public:
Common::String getFileName() const override { return _name; }
Common::Path getPathInArchive() const override { return _name; }
Common::SeekableReadStream *createReadStream() const override;
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override { return nullptr; }
friend class Lab;
};
diff --git a/engines/mm/shared/utils/engine_data.cpp b/engines/mm/shared/utils/engine_data.cpp
index b37230e81ff..87a8e4155b1 100644
--- a/engines/mm/shared/utils/engine_data.cpp
+++ b/engines/mm/shared/utils/engine_data.cpp
@@ -45,6 +45,9 @@ public:
Common::SeekableReadStream *createReadStream() const override {
return _member->createReadStream();
}
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override {
+ return nullptr;
+ }
Common::String getName() const override {
Common::String name = _member->getName();
assert(name.hasPrefixIgnoreCase(_innerfolder));
diff --git a/engines/stark/formats/xarc.cpp b/engines/stark/formats/xarc.cpp
index be96aa84767..16cb78b30f0 100644
--- a/engines/stark/formats/xarc.cpp
+++ b/engines/stark/formats/xarc.cpp
@@ -39,6 +39,7 @@ public:
XARCMember(const XARCArchive *xarc, Common::ReadStream &stream, uint32 offset);
Common::SeekableReadStream *createReadStream() const override;
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
Common::String getName() const override { return _name; }
Common::Path getPathInArchive() const { return _name; }
Common::String getFileName() const { return _name; }
@@ -76,6 +77,10 @@ Common::SeekableReadStream *XARCMember::createReadStream() const {
return _xarc->createReadStreamForMember(this);
}
+Common::SeekableReadStream *XARCMember::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
+ return nullptr;
+}
+
Common::String XARCMember::readString(Common::ReadStream &stream) {
Common::String str;
diff --git a/engines/ultima/shared/engine/data_archive.cpp b/engines/ultima/shared/engine/data_archive.cpp
index 6cbcfb04634..b2c89163525 100644
--- a/engines/ultima/shared/engine/data_archive.cpp
+++ b/engines/ultima/shared/engine/data_archive.cpp
@@ -44,6 +44,9 @@ public:
Common::SeekableReadStream *createReadStream() const override {
return _member->createReadStream();
}
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override {
+ return _member->createReadStreamForAltStream(altStreamType);
+ }
Common::String getName() const override {
Common::String name = _member->getName();
assert(name.hasPrefixIgnoreCase(_innerfolder));
diff --git a/engines/wintermute/base/file/base_file_entry.cpp b/engines/wintermute/base/file/base_file_entry.cpp
index 162a7f8ee4c..f6f0c06ec59 100644
--- a/engines/wintermute/base/file/base_file_entry.cpp
+++ b/engines/wintermute/base/file/base_file_entry.cpp
@@ -52,6 +52,10 @@ Common::SeekableReadStream *BaseFileEntry::createReadStream() const {
return file;
}
+Common::SeekableReadStream *BaseFileEntry::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
+ return nullptr;
+}
+
//////////////////////////////////////////////////////////////////////////
BaseFileEntry::BaseFileEntry() {
_package = nullptr;
diff --git a/engines/wintermute/base/file/base_file_entry.h b/engines/wintermute/base/file/base_file_entry.h
index f7e3d66b7df..9f53377d8dd 100644
--- a/engines/wintermute/base/file/base_file_entry.h
+++ b/engines/wintermute/base/file/base_file_entry.h
@@ -39,6 +39,7 @@ class BasePackage;
class BaseFileEntry : public Common::ArchiveMember {
public:
Common::SeekableReadStream *createReadStream() const override;
+ Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
Common::String getName() const override { return _filename; }
Common::Path getPathInArchive() const override { return _filename; }
Common::String getFileName() const override { return _filename; }
Commit: be0ee20b4aec6fefb6fcb26042488dd75131a2a2
https://github.com/scummvm/scummvm/commit/be0ee20b4aec6fefb6fcb26042488dd75131a2a2
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-30T00:31:00+02:00
Commit Message:
MTROPOLIS: Fix SPQR Mac not booting
Changed paths:
engines/mtropolis/boot.cpp
diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index 2a7b99f1751..e9220f17a8a 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -506,8 +506,10 @@ void SPQRGameDataHandler::unpackAdditionalFiles(Common::Array<Common::SharedPtr<
debug(1, "Unpacking files...");
for (const MacVISE3InstallerUnpackRequest &request : unpackRequests) {
+ Common::Path requestPath(request.fileName, ':');
+
Common::MacFinderInfo finfo;
- if (!Common::MacResManager::getFileFinderInfo(request.fileName, *archive, finfo))
+ if (!Common::MacResManager::getFileFinderInfo(requestPath, *archive, finfo))
error("Couldn't get Finder info for file '%s'", request.fileName);
FileIdentification ident;
@@ -518,14 +520,14 @@ void SPQRGameDataHandler::unpackAdditionalFiles(Common::Array<Common::SharedPtr<
if (request.extractResources) {
Common::SharedPtr<Common::MacResManager> resMan(new Common::MacResManager());
- if (!resMan->open(request.fileName, *archive))
+ if (!resMan->open(requestPath, *archive))
error("Failed to open Mac res manager for file '%s'", request.fileName);
ident.resMan = resMan;
}
if (request.extractData)
- ident.stream.reset(archive->createReadStreamForMember(request.fileName));
+ ident.stream.reset(archive->createReadStreamForMember(requestPath));
files.push_back(ident);
}
More information about the Scummvm-git-logs
mailing list