[Scummvm-git-logs] scummvm master -> 654f7fd8d0dcdef4ff392372f2d6a56f0a3086bc

bluegr noreply at scummvm.org
Mon Jun 19 05:45:37 UTC 2023


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
7be3c8f602 COMMON: Add "flattenTree" param to createStuffItArchive and preserve directory structure by default
e53d2ec594 COMMON: Add "getPathSeparator" to Archive and return ":" for Mac archive formats
907252ecbd COMMON: Return correct path separator for InstallShieldV3
654f7fd8d0 COMMON: Add comments on usage


Commit: 7be3c8f6028de55ddd5cca6d43aee1b943414a97
    https://github.com/scummvm/scummvm/commit/7be3c8f6028de55ddd5cca6d43aee1b943414a97
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-19T08:45:32+03:00

Commit Message:
COMMON: Add "flattenTree" param to createStuffItArchive and preserve directory structure by default

Changed paths:
    common/compression/stuffit.cpp
    common/compression/stuffit.h
    engines/grim/grim.cpp
    engines/groovie/groovie.cpp
    engines/kyra/resource/resource_intern.cpp
    engines/mtropolis/boot.cpp
    engines/private/private.cpp


diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index d869685a07b..d6011b168e2 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -43,8 +43,8 @@ public:
 	StuffItArchive();
 	~StuffItArchive() override;
 
-	bool open(const Common::String &filename);
-	bool open(Common::SeekableReadStream *stream);
+	bool open(const Common::String &filename, bool flattenTree);
+	bool open(Common::SeekableReadStream *stream, bool flattenTree);
 	void close();
 	bool isOpen() const { return _stream != nullptr; }
 
@@ -54,7 +54,7 @@ public:
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
 	Common::SharedArchiveContents readContentsForPath(const Common::String& name) const override;
 	Common::String translatePath(const Common::Path &path) const override {
-		return path.toString();
+		return path.toString(':');
 	}
 
 private:
@@ -99,12 +99,12 @@ static const uint32 s_magicNumbers[] = {
 	MKTAG('S', 'T', 'i', '3'), MKTAG('S', 'T', 'i', '4'), MKTAG('S', 'T', '4', '6')
 };
 
-bool StuffItArchive::open(const Common::String &filename) {
+bool StuffItArchive::open(const Common::String &filename, bool flattenTree) {
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(filename);
-	return open(stream);
+	return open(stream, flattenTree);
 }
 
-bool StuffItArchive::open(Common::SeekableReadStream *stream) {
+bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree) {
 	close();
 
 	_stream = stream;
@@ -144,7 +144,11 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream) {
 
 	Common::CRC16 crc;
 
+	Common::String dirPrefix;
+
 	while (_stream->pos() < _stream->size() && !_stream->eos() && _stream->pos() < archiveSize) {
+		const uint kMaxFileLength = 31;
+
 		byte header[112];
 		_stream->read(header, sizeof(header));
 		Common::MemoryReadStream headStream(header, sizeof(header));
@@ -154,9 +158,10 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream) {
 		byte fileNameLength = headStream.readByte();
 		Common::String name;
 
-		if (fileNameLength > 63)
+		if (fileNameLength > kMaxFileLength)
 			error("File name length too long in stuffit archive: %d at 0x%x", fileNameLength, (int) (_stream->pos() - 3));
 
+
 		for (byte i = 0; i < fileNameLength; i++)
 			name += (char)headStream.readByte();
 
@@ -184,9 +189,32 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream) {
 		if (actualHeaderCRC != headerCRC)
 			error ("StuffItArchive::open(): Header CRC mismatch: %04x vs %04x", actualHeaderCRC, headerCRC);
 
-		// Ignore directories for now
-		if (dataForkCompression == 32 || dataForkCompression == 33)
+		byte dirCheckMethod = (dataForkCompression & 0x6f);	// Strip 0x80 (encrypted) and 0x10 (folder contents encrypted) flags
+		if (dirCheckMethod == 32) {
+			// Start of folder
+			if (!flattenTree)
+				dirPrefix = dirPrefix + name + ":";
+			continue;
+		}
+
+		if (dirCheckMethod == 33) {
+			// End of folder
+			if (!flattenTree && dirPrefix.size() > 0) {
+				size_t secondLastDelimiter = dirPrefix.rfind(':', dirPrefix.size() - 1);
+
+				if (secondLastDelimiter == Common::String::npos) {
+					// Only one level deep
+					dirPrefix.clear();
+				} else {
+					// Multiple levels deep
+					dirPrefix = dirPrefix.substr(0, secondLastDelimiter + 1);
+				}
+			}
 			continue;
+		}
+
+		if (!flattenTree)
+			name = dirPrefix + name;
 
 		_metadataMap[name + ".finf"] = finfo.toData();
 
@@ -235,7 +263,7 @@ void StuffItArchive::close() {
 }
 
 bool StuffItArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
+	Common::String name = path.toString(':');
 	return _map.contains(name);
 }
 
@@ -247,7 +275,7 @@ int StuffItArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
+	Common::String name = path.toString(':');
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
 }
 
@@ -1046,10 +1074,10 @@ void StuffItArchive::decompress14(Common::SeekableReadStream *src, byte *dst, ui
 #undef OUTPUT_VAL
 #undef ALIGN_BITS
 
-Common::Archive *createStuffItArchive(const Common::String &fileName) {
+Common::Archive *createStuffItArchive(const Common::String &fileName, bool flattenTree) {
 	StuffItArchive *archive = new StuffItArchive();
 
-	if (!archive->open(fileName)) {
+	if (!archive->open(fileName, flattenTree)) {
 		delete archive;
 		return nullptr;
 	}
@@ -1057,10 +1085,10 @@ Common::Archive *createStuffItArchive(const Common::String &fileName) {
 	return archive;
 }
 
-Common::Archive *createStuffItArchive(Common::SeekableReadStream *stream) {
+Common::Archive *createStuffItArchive(Common::SeekableReadStream *stream, bool flattenTree) {
 	StuffItArchive *archive = new StuffItArchive();
 
-	if (!archive->open(stream)) {
+	if (!archive->open(stream, flattenTree)) {
 		delete archive;
 		return nullptr;
 	}
diff --git a/common/compression/stuffit.h b/common/compression/stuffit.h
index 4350f4c69ba..3e56be491eb 100644
--- a/common/compression/stuffit.h
+++ b/common/compression/stuffit.h
@@ -52,8 +52,8 @@ class SeekableReadStream;
  *
  * May return 0 in case of a failure.
  */
-Archive *createStuffItArchive(const String &fileName);
-Archive *createStuffItArchive(SeekableReadStream *stream);
+Archive *createStuffItArchive(const String &fileName, bool flattenTree = false);
+Archive *createStuffItArchive(SeekableReadStream *stream, bool flattenTree = false);
 
 /** @} */
 
diff --git a/engines/grim/grim.cpp b/engines/grim/grim.cpp
index 420f5e612ff..5a079197bc7 100644
--- a/engines/grim/grim.cpp
+++ b/engines/grim/grim.cpp
@@ -334,13 +334,13 @@ Common::Error GrimEngine::run() {
 	// Currently, this requires the data fork to be standalone
 	if (getGameType() == GType_MONKEY4) {
 		if (SearchMan.hasFile("Monkey Island 4 Installer")) {
-			Common::Archive *archive = Common::createStuffItArchive("Monkey Island 4 Installer");
+			Common::Archive *archive = Common::createStuffItArchive("Monkey Island 4 Installer", true);
 
 			if (archive)
 				SearchMan.add("Monkey Island 4 Installer", archive, 0, true);
 		}
 		if (SearchMan.hasFile("EFMI Installer")) {
-			Common::Archive *archive = Common::createStuffItArchive("EFMI Installer");
+			Common::Archive *archive = Common::createStuffItArchive("EFMI Installer", true);
 
 			if (archive)
 				SearchMan.add("EFMI Installer", archive, 0, true);
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index c818e412a3f..3a789c57711 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -82,7 +82,7 @@ Common::Error GroovieEngine::run() {
 	if (_gameDescription->version == kGroovieT11H && getPlatform() == Common::kPlatformMacintosh) {
 		// Load the Mac installer with the lowest priority (in case the user has installed
 		// the game and has the MIDI folder present; faster to just load them)
-		Common::Archive *archive = Common::createStuffItArchive("The 11th Hour Installer");
+		Common::Archive *archive = Common::createStuffItArchive("The 11th Hour Installer", true);
 
 		if (archive)
 			SearchMan.add("The 11th Hour Installer", archive);
diff --git a/engines/kyra/resource/resource_intern.cpp b/engines/kyra/resource/resource_intern.cpp
index 64a53ac553b..68102f4f2d8 100644
--- a/engines/kyra/resource/resource_intern.cpp
+++ b/engines/kyra/resource/resource_intern.cpp
@@ -1223,7 +1223,7 @@ Common::Archive *StuffItLoader::load(Resource *owner, const Common::String &file
 
 Common::Archive *StuffItLoader::load(Resource *owner, Common::SeekableReadStream *stream, const Common::String& debugName) {
 	if (stream) {
-		Common::Archive *archive = Common::createStuffItArchive(stream);
+		Common::Archive *archive = Common::createStuffItArchive(stream, true);
 		return archive;
 	}
 
diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index 1e2c0c2d721..d20fcb42bd2 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -243,7 +243,7 @@ void ObsidianGameDataHandler::unpackMacRetailInstaller(Common::Array<Common::Sha
 		error("Obsidian Installer has no data fork");
 
 	// Not counted/persisted because the StuffIt archive owns the stream.  It will also delete it if createStuffItArchive fails.
-	_installerArchive.reset(Common::createStuffItArchive(installerDataForkStream));
+	_installerArchive.reset(Common::createStuffItArchive(installerDataForkStream, true));
 	installerDataForkStream = nullptr;
 
 	persistentResources.push_back(PersistentResource<Common::Archive>::wrap(_installerArchive));
diff --git a/engines/private/private.cpp b/engines/private/private.cpp
index 15a27a8dd30..296832eb60b 100644
--- a/engines/private/private.cpp
+++ b/engines/private/private.cpp
@@ -152,7 +152,7 @@ Common::SeekableReadStream *PrivateEngine::loadAssets() {
 	else
 		file = Common::MacResManager::openFileOrDataFork(isDemo() ? "Private Eye Demo Installer" : "Private Eye Installer");
 	if (file) {
-		Common::Archive *s = createStuffItArchive(file);
+		Common::Archive *s = createStuffItArchive(file, true);
 		Common::SeekableReadStream *file2 = nullptr;
 		if (s)
 			file2 = s->createReadStreamForMember(isDemo() ? "demogame.mac" : "game.mac");


Commit: e53d2ec59481c8ec95dc0157180bb08af594b6db
    https://github.com/scummvm/scummvm/commit/e53d2ec59481c8ec95dc0157180bb08af594b6db
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-19T08:45:32+03:00

Commit Message:
COMMON: Add "getPathSeparator" to Archive and return ":" for Mac archive formats

Changed paths:
    common/archive.cpp
    common/archive.h
    common/compression/stuffit.cpp
    common/compression/vise.cpp


diff --git a/common/archive.cpp b/common/archive.cpp
index 62b7e277b9e..c09a2aecccf 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -103,6 +103,10 @@ void Archive::dumpArchive(String destPath) {
 	free(data);
 }
 
+char Archive::getPathSeparator() const {
+	return '/';
+}
+
 SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(const Path &path) const {
 	String translated = translatePath(path);
 	bool isNew = false;
diff --git a/common/archive.h b/common/archive.h
index 462ac4ec279..8a31928958e 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -155,6 +155,11 @@ public:
 	 * Dump all files from the archive to the given directory
 	 */
 	void dumpArchive(String destPath);
+
+	/**
+	 * Returns the separator used by internal paths in the archive
+	 */
+	virtual char getPathSeparator() const;
 };
 
 class MemcachingCaseInsensitiveArchive;
diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index d6011b168e2..1e7797e2159 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -53,9 +53,8 @@ public:
 	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::String translatePath(const Common::Path &path) const override {
-		return path.toString(':');
-	}
+	Common::String translatePath(const Common::Path &path) const override;
+	char getPathSeparator() const override;
 
 private:
 	struct FileEntry {
@@ -74,6 +73,8 @@ private:
 	typedef Common::HashMap<Common::String, Common::MacFinderInfoData, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MetadataMap;
 	MetadataMap _metadataMap;
 
+	bool _flattenTree;
+
 	// Decompression Functions
 	bool decompress13(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const;
 	void decompress14(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const;
@@ -83,7 +84,7 @@ private:
 	void readTree14(Common::BitStream8LSB *bits, SIT14Data *dat, uint16 codesize, uint16 *result) const;
 };
 
-StuffItArchive::StuffItArchive() : Common::MemcachingCaseInsensitiveArchive() {
+StuffItArchive::StuffItArchive() : Common::MemcachingCaseInsensitiveArchive(), _flattenTree(false) {
 	_stream = nullptr;
 }
 
@@ -108,6 +109,7 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree)
 	close();
 
 	_stream = stream;
+	_flattenTree = flattenTree;
 
 	if (!_stream)
 		return false;
@@ -325,6 +327,14 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::
 	return Common::SharedArchiveContents(uncompressedBlock, entry.uncompressedSize);
 }
 
+Common::String StuffItArchive::translatePath(const Common::Path &path) const {
+	return _flattenTree ? path.getLastComponent().toString() : path.toString(':');
+}
+
+char StuffItArchive::getPathSeparator() const {
+	return ':';
+}
+
 void StuffItArchive::update14(uint16 first, uint16 last, byte *code, uint16 *freq) const {
 	uint16 i, j;
 
diff --git a/common/compression/vise.cpp b/common/compression/vise.cpp
index c1ada443a78..660049b8e08 100644
--- a/common/compression/vise.cpp
+++ b/common/compression/vise.cpp
@@ -94,6 +94,7 @@ 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;
+	char getPathSeparator() const override;
 
 private:
 	bool getFileDescIndex(const Common::Path &path, uint &outIndex, ArchiveMember::SubstreamType &outSubstreamType) const;
@@ -390,6 +391,10 @@ Common::SeekableReadStream *MacVISEArchive::createReadStreamForMember(const Comm
 	return archiveMember->createReadStream();
 }
 
+char MacVISEArchive::getPathSeparator() const {
+	return ':';
+}
+
 bool MacVISEArchive::getFileDescIndex(const Common::Path &path, uint &outIndex, ArchiveMember::SubstreamType &outSubstreamType) const {
 	Common::String convertedPath = path.toString(':');
 	ArchiveMember::SubstreamType substreamType = ArchiveMember::kSubstreamTypeData;


Commit: 907252ecbdc6e0db6d8ac39ad649fca548c0ac1a
    https://github.com/scummvm/scummvm/commit/907252ecbdc6e0db6d8ac39ad649fca548c0ac1a
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-19T08:45:32+03:00

Commit Message:
COMMON: Return correct path separator for InstallShieldV3

Changed paths:
    common/compression/installshieldv3_archive.cpp
    common/compression/installshieldv3_archive.h


diff --git a/common/compression/installshieldv3_archive.cpp b/common/compression/installshieldv3_archive.cpp
index 92cf3c7c416..e52228b4aa6 100644
--- a/common/compression/installshieldv3_archive.cpp
+++ b/common/compression/installshieldv3_archive.cpp
@@ -153,4 +153,8 @@ Common::SeekableReadStream *InstallShieldV3::createReadStreamForMember(const Com
 	return Common::decompressDCL(_stream, entry.compressedSize, entry.uncompressedSize);
 }
 
+char InstallShieldV3::getPathSeparator() const {
+	return '\\';
+}
+
 } // End of namespace Common
diff --git a/common/compression/installshieldv3_archive.h b/common/compression/installshieldv3_archive.h
index 1823df09b39..ee5ccc0e65a 100644
--- a/common/compression/installshieldv3_archive.h
+++ b/common/compression/installshieldv3_archive.h
@@ -46,6 +46,7 @@ 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;
+	char getPathSeparator() const override;
 
 private:
 	struct FileEntry {


Commit: 654f7fd8d0dcdef4ff392372f2d6a56f0a3086bc
    https://github.com/scummvm/scummvm/commit/654f7fd8d0dcdef4ff392372f2d6a56f0a3086bc
Author: elasota (ejlasota at gmail.com)
Date: 2023-06-19T08:45:32+03:00

Commit Message:
COMMON: Add comments on usage

Changed paths:
    common/compression/stuffit.h


diff --git a/common/compression/stuffit.h b/common/compression/stuffit.h
index 3e56be491eb..fa234106e71 100644
--- a/common/compression/stuffit.h
+++ b/common/compression/stuffit.h
@@ -50,7 +50,10 @@ class SeekableReadStream;
  * This factory method creates an Archive instance corresponding to the content
  * of the StuffIt compressed file with the given name.
  *
- * May return 0 in case of a failure.
+ * @param fileName        The file name to load
+ * @param flattenTree     If true, removes the directory prefixes from all file paths
+ *
+ * @return                The StuffIt archive
  */
 Archive *createStuffItArchive(const String &fileName, bool flattenTree = false);
 Archive *createStuffItArchive(SeekableReadStream *stream, bool flattenTree = false);




More information about the Scummvm-git-logs mailing list