[Scummvm-git-logs] scummvm master -> d7aa54bf30df79e84a27d0358c736601d2a9d04f

phcoder noreply at scummvm.org
Wed Dec 7 23:02:45 UTC 2022


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

Summary:
571a807257 COMMON: Switch stuffit to MemcachingCaseInsensitiveArchive
d9888b9ac6 COMMON: Support stuffit-13 algorithm
2c8fd71b47 KYRA: Switch to openFileOrDataFork
9f4d744b46 KYRA: Store cached installer mac archive as its simple name
1b90cea645 KYRA: Support loading stuffit archive from abstract stream
d7aa54bf30 KYRA: Support multi-floppy installer


Commit: 571a80725730eab0f81c8a2e0a16630196419ec1
    https://github.com/scummvm/scummvm/commit/571a80725730eab0f81c8a2e0a16630196419ec1
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-08T00:02:39+01:00

Commit Message:
COMMON: Switch stuffit to MemcachingCaseInsensitiveArchive

Changed paths:
    common/compression/stuffit.cpp


diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index e2d6e436444..f36e0964ff8 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -37,7 +37,7 @@ namespace Common {
 
 struct SIT14Data;
 
-class StuffItArchive : public Common::Archive {
+class StuffItArchive : public Common::MemcachingCaseInsensitiveArchive {
 public:
 	StuffItArchive();
 	~StuffItArchive() override;
@@ -51,7 +51,10 @@ 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::SeekableReadStream *createReadStreamForMember(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();
+	}
 
 private:
 	struct FileEntry {
@@ -70,14 +73,14 @@ private:
 	MetadataMap _metadataMap;
 
 	// Decompression Functions
-	Common::SeekableReadStream *decompress14(Common::SeekableReadStream *src, uint32 uncompressedSize) const;
+	void decompress14(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const;
 
 	// 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;
 };
 
-StuffItArchive::StuffItArchive() : Common::Archive() {
+StuffItArchive::StuffItArchive() : Common::MemcachingCaseInsensitiveArchive() {
 	_stream = nullptr;
 }
 
@@ -230,15 +233,15 @@ const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &pat
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
 }
 
-Common::SeekableReadStream *StuffItArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-
+Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String& name) const {
 	if (!_stream || !_map.contains(name)) {
 		if (_metadataMap.contains(name)) {
 			const Common::MacFinderInfoData &metadata = _metadataMap[name];
-			return new Common::MemoryReadStream(reinterpret_cast<const byte *>(&metadata), sizeof(Common::MacFinderInfoData), DisposeAfterUse::NO);
+			byte *copy = new byte[sizeof(Common::MacFinderInfoData)];
+			memcpy(copy, reinterpret_cast<const byte *>(&metadata), sizeof(Common::MacFinderInfoData));
+			return Common::SharedArchiveContents(copy, sizeof(Common::MacFinderInfoData));
 		}
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	const FileEntry &entry = _map[name];
@@ -248,17 +251,22 @@ Common::SeekableReadStream *StuffItArchive::createReadStreamForMember(const Comm
 
 	Common::SeekableSubReadStream subStream(_stream, entry.offset, entry.offset + entry.compressedSize);
 
+	byte *uncompressedBlock = new byte[entry.uncompressedSize];
+
 	// We currently only support type 14 compression
 	switch (entry.compression) {
 	case 0: // Uncompressed
-		return subStream.readStream(subStream.size());
+		subStream.read(uncompressedBlock, entry.uncompressedSize);
+		break;
 	case 14: // Installer
-		return decompress14(&subStream, entry.uncompressedSize);
+		decompress14(&subStream, uncompressedBlock, entry.uncompressedSize);
+		break;
 	default:
 		error("Unhandled StuffIt compression %d", entry.compression);
+		return Common::SharedArchiveContents();
 	}
 
-	return nullptr;
+	return Common::SharedArchiveContents(uncompressedBlock, entry.uncompressedSize);
 }
 
 void StuffItArchive::update14(uint16 first, uint16 last, byte *code, uint16 *freq) const {
@@ -448,8 +456,7 @@ void StuffItArchive::readTree14(Common::BitStream8LSB *bits, SIT14Data *dat, uin
 	dat->window[j++] = x; \
 	j &= 0x3FFFF
 
-Common::SeekableReadStream *StuffItArchive::decompress14(Common::SeekableReadStream *src, uint32 uncompressedSize) const {
-	byte *dst = (byte *)malloc(uncompressedSize);
+void StuffItArchive::decompress14(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const {
 	Common::MemoryWriteStream out(dst, uncompressedSize);
 
 	Common::BitStream8LSB *bits = new Common::BitStream8LSB(src);
@@ -539,8 +546,6 @@ Common::SeekableReadStream *StuffItArchive::decompress14(Common::SeekableReadStr
 
 	delete dat;
 	delete bits;
-
-	return new Common::MemoryReadStream(dst, uncompressedSize, DisposeAfterUse::YES);
 }
 
 #undef OUTPUT_VAL


Commit: d9888b9ac6cb41ef438c6e98f5e4a771810f030e
    https://github.com/scummvm/scummvm/commit/d9888b9ac6cb41ef438c6e98f5e4a771810f030e
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-08T00:02:39+01:00

Commit Message:
COMMON: Support stuffit-13 algorithm

Changed paths:
    common/compression/stuffit.cpp


diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index f36e0964ff8..bf7852c0b2f 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -20,7 +20,7 @@
  */
 
 // StuffIt parsing based on https://github.com/mietek/theunarchiver/wiki/StuffItFormat
-// Compression 14 based on libxad (http://sourceforge.net/projects/libxad/)
+// Compressions 13 and 14 based on libxad (http://sourceforge.net/projects/libxad/)
 
 #include "common/compression/stuffit.h"
 
@@ -73,6 +73,7 @@ private:
 	MetadataMap _metadataMap;
 
 	// Decompression Functions
+	bool decompress13(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const;
 	void decompress14(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const;
 
 	// Decompression Helpers
@@ -258,6 +259,10 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::
 	case 0: // Uncompressed
 		subStream.read(uncompressedBlock, entry.uncompressedSize);
 		break;
+	case 13: // TableHuff
+		if (!decompress13(&subStream, uncompressedBlock, entry.uncompressedSize))
+			error("SIT-13 decompression failed");
+		break;
 	case 14: // Installer
 		decompress14(&subStream, uncompressedBlock, entry.uncompressedSize);
 		break;
@@ -451,6 +456,473 @@ void StuffItArchive::readTree14(Common::BitStream8LSB *bits, SIT14Data *dat, uin
 	ALIGN_BITS(bits);
 }
 
+struct SIT13Buffer {
+	uint16 data;
+	int8  bits;
+
+	SIT13Buffer() : data(0), bits(0) {}
+};
+
+struct SIT13Store {
+	int16  freq;
+	uint16 d1;
+	uint16 d2;
+
+	SIT13Store() : freq(0), d1(0), d2(0) {}
+};
+
+struct SIT13Data {
+	uint16              MaxBits;
+	struct SIT13Store  Buffer4[0xE08];
+	struct SIT13Buffer Buffer1[0x1000];
+	struct SIT13Buffer Buffer2[0x1000];
+	struct SIT13Buffer Buffer3[0x1000];
+	struct SIT13Buffer Buffer3b[0x1000];
+	struct SIT13Buffer Buffer5[0x141];
+	uint8              TextBuf[658];
+	uint8              Window[0x10000];
+
+	SIT13Data() : MaxBits(0) {
+		memset(TextBuf, 0, sizeof(TextBuf));
+		memset(Window, 0, sizeof(Window));
+	}
+};
+
+static const uint8 SIT13Bits[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
+static const uint16 SIT13Info[37] = {
+	0x5D8, 0x058, 0x040, 0x0C0, 0x000, 0x078, 0x02B, 0x014,
+	0x00C, 0x01C, 0x01B, 0x00B, 0x010, 0x020, 0x038, 0x018,
+	0x0D8, 0xBD8, 0x180, 0x680, 0x380, 0xF80, 0x780, 0x480,
+	0x080, 0x280, 0x3D8, 0xFD8, 0x7D8, 0x9D8, 0x1D8, 0x004,
+	0x001, 0x002, 0x007, 0x003, 0x008
+};
+static const uint16 SIT13InfoBits[37] = {
+	11,  8,  8,  8,  8,  7,  6,  5,  5,  5,  5,  6,  5,  6,  7,  7,
+	9, 12, 10, 11, 11, 12, 12, 11, 11, 11, 12, 12, 12, 12, 12,  5,
+	2,  2,  3,  4,  5
+};
+static const uint16 SIT13StaticPos[5] = {0, 330, 661, 991, 1323};
+static const uint8 SIT13StaticBits[5] = {11, 13, 14, 11, 11};
+static const uint8 SIT13Static[1655] = {
+	0xB8,0x98,0x78,0x77,0x75,0x97,0x76,0x87,0x77,0x77,0x77,0x78,0x67,0x87,0x68,0x67,0x3B,0x77,0x78,0x67,
+	0x77,0x77,0x77,0x59,0x76,0x87,0x77,0x77,0x77,0x77,0x77,0x77,0x76,0x87,0x67,0x87,0x77,0x77,0x75,0x88,
+	0x59,0x75,0x79,0x77,0x78,0x68,0x77,0x67,0x73,0xB6,0x65,0xB6,0x76,0x97,0x67,0x47,0x9A,0x2A,0x4A,0x87,
+	0x77,0x78,0x67,0x86,0x78,0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
+	0x68,0x77,0x77,0x77,0x67,0x87,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x68,0x77,0x77,0x68,0x77,0x77,0x77,
+	0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x77,0x77,0x67,0x87,
+	0x68,0x77,0x77,0x77,0x68,0x77,0x68,0x63,0x86,0x7A,0x87,0x77,0x77,0x87,0x76,0x87,0x77,0x77,0x77,0x77,
+	0x77,0x77,0x77,0x77,0x77,0x76,0x86,0x77,0x86,0x86,0x86,0x86,0x87,0x76,0x86,0x87,0x67,0x74,0xA7,0x86,
+	0x36,0x88,0x78,0x76,0x87,0x76,0x96,0x87,0x77,0x84,0xA6,0x86,0x87,0x76,0x92,0xB5,0x94,0xA6,0x96,0x85,
+	0x78,0x75,0x96,0x86,0x86,0x75,0xA7,0x67,0x87,0x85,0x87,0x85,0x95,0x77,0x77,0x85,0xA3,0xA7,0x93,0x87,
+	0x86,0x94,0x85,0xA8,0x67,0x85,0xA5,0x95,0x86,0x68,0x67,0x77,0x96,0x78,0x75,0x86,0x77,0xA5,0x67,0x87,
+	0x85,0xA6,0x75,0x96,0x85,0x87,0x95,0x95,0x87,0x86,0x94,0xA5,0x86,0x85,0x87,0x86,0x86,0x86,0x86,0x77,
+	0x67,0x76,0x66,0x9A,0x75,0xA5,0x94,0x97,0x76,0x96,0x76,0x95,0x86,0x77,0x86,0x87,0x75,0xA5,0x96,0x85,
+	0x86,0x96,0x86,0x86,0x85,0x96,0x86,0x76,0x95,0x86,0x95,0x95,0x95,0x87,0x76,0x87,0x76,0x96,0x85,0x78,
+	0x75,0xA6,0x85,0x86,0x95,0x86,0x95,0x86,0x45,0x69,0x78,0x77,0x87,0x67,0x69,0x58,0x79,0x68,0x78,0x87,
+	0x78,0x66,0x88,0x68,0x68,0x77,0x76,0x87,0x68,0x68,0x69,0x58,0x5A,0x4B,0x76,0x88,0x69,0x67,0xA7,0x70,
+	0x9F,0x90,0xA4,0x84,0x77,0x77,0x77,0x89,0x17,0x77,0x7B,0xA7,0x86,0x87,0x77,0x68,0x68,0x69,0x67,0x78,
+	0x77,0x78,0x76,0x87,0x77,0x76,0x73,0xB6,0x87,0x96,0x66,0x87,0x76,0x85,0x87,0x78,0x77,0x77,0x86,0x77,
+	0x86,0x78,0x66,0x76,0x77,0x87,0x86,0x78,0x76,0x76,0x86,0xA5,0x67,0x97,0x77,0x87,0x87,0x76,0x66,0x59,
+	0x67,0x59,0x77,0x6A,0x65,0x86,0x78,0x94,0x77,0x88,0x77,0x78,0x86,0x86,0x76,0x88,0x76,0x87,0x67,0x87,
+	0x77,0x77,0x76,0x87,0x86,0x77,0x77,0x77,0x86,0x86,0x76,0x96,0x77,0x77,0x76,0x78,0x86,0x86,0x86,0x95,
+	0x86,0x96,0x85,0x95,0x86,0x87,0x75,0x88,0x77,0x87,0x57,0x78,0x76,0x86,0x76,0x96,0x86,0x87,0x76,0x87,
+	0x86,0x76,0x77,0x86,0x78,0x78,0x57,0x87,0x86,0x76,0x85,0xA5,0x87,0x76,0x86,0x86,0x85,0x86,0x53,0x98,
+	0x78,0x78,0x77,0x87,0x79,0x67,0x79,0x85,0x87,0x69,0x67,0x68,0x78,0x69,0x68,0x69,0x58,0x87,0x66,0x97,
+	0x68,0x68,0x76,0x85,0x78,0x87,0x67,0x97,0x67,0x74,0xA2,0x28,0x77,0x78,0x77,0x77,0x78,0x68,0x67,0x78,
+	0x77,0x78,0x68,0x68,0x77,0x59,0x67,0x5A,0x68,0x68,0x68,0x68,0x68,0x68,0x67,0x77,0x78,0x68,0x68,0x78,
+	0x59,0x58,0x76,0x77,0x68,0x78,0x68,0x59,0x69,0x58,0x68,0x68,0x67,0x78,0x77,0x78,0x69,0x58,0x68,0x57,
+	0x78,0x67,0x78,0x76,0x88,0x58,0x67,0x7A,0x46,0x88,0x77,0x78,0x68,0x68,0x66,0x78,0x78,0x68,0x68,0x59,
+	0x68,0x69,0x68,0x59,0x67,0x78,0x59,0x58,0x69,0x59,0x67,0x68,0x67,0x69,0x69,0x57,0x79,0x68,0x59,0x59,
+	0x59,0x68,0x68,0x68,0x58,0x78,0x67,0x59,0x68,0x78,0x59,0x58,0x78,0x58,0x76,0x78,0x68,0x68,0x68,0x69,
+	0x59,0x67,0x68,0x69,0x59,0x59,0x58,0x69,0x59,0x59,0x58,0x5A,0x58,0x68,0x68,0x59,0x58,0x68,0x66,0x47,
+	0x88,0x77,0x87,0x77,0x87,0x76,0x87,0x87,0x87,0x77,0x77,0x87,0x67,0x96,0x78,0x76,0x87,0x68,0x77,0x77,
+	0x76,0x86,0x96,0x86,0x88,0x77,0x85,0x86,0x8B,0x76,0x0A,0xF9,0x07,0x38,0x57,0x67,0x77,0x78,0x77,0x91,
+	0x77,0xD7,0x77,0x7A,0x67,0x3C,0x68,0x68,0x77,0x68,0x78,0x59,0x77,0x68,0x77,0x68,0x76,0x77,0x69,0x68,
+	0x68,0x68,0x68,0x67,0x68,0x68,0x77,0x87,0x77,0x67,0x78,0x68,0x67,0x58,0x78,0x68,0x77,0x68,0x78,0x67,
+	0x68,0x68,0x67,0x78,0x77,0x77,0x87,0x77,0x76,0x67,0x86,0x85,0x87,0x86,0x97,0x58,0x67,0x79,0x57,0x77,
+	0x87,0x77,0x87,0x77,0x76,0x59,0x78,0x77,0x77,0x68,0x77,0x77,0x76,0x78,0x77,0x77,0x77,0x76,0x87,0x77,
+	0x77,0x68,0x77,0x77,0x77,0x67,0x78,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x68,0x77,0x76,0x68,0x87,0x77,
+	0x77,0x77,0x77,0x68,0x77,0x68,0x77,0x77,0x77,0x77,0x77,0x77,0x76,0x78,0x77,0x77,0x76,0x87,0x77,0x77,
+	0x67,0x78,0x77,0x77,0x76,0x78,0x67,0x68,0x68,0x29,0x77,0x88,0x78,0x78,0x77,0x68,0x77,0x77,0x77,0x77,
+	0x77,0x77,0x77,0x77,0x4A,0x77,0x4A,0x74,0x77,0x77,0x68,0xA4,0x7A,0x47,0x76,0x86,0x78,0x76,0x7A,0x4A,
+	0x83,0xB2,0x87,0x77,0x87,0x76,0x96,0x86,0x96,0x76,0x78,0x87,0x77,0x85,0x87,0x85,0x96,0x65,0xB5,0x95,
+	0x96,0x77,0x77,0x86,0x76,0x86,0x86,0x87,0x86,0x86,0x76,0x96,0x96,0x57,0x77,0x85,0x97,0x85,0x86,0xA5,
+	0x86,0x85,0x87,0x77,0x68,0x78,0x77,0x95,0x86,0x75,0x87,0x76,0x86,0x79,0x68,0x84,0x96,0x76,0xB3,0x87,
+	0x77,0x68,0x86,0xA5,0x77,0x56,0xB6,0x68,0x85,0x93,0xB6,0x95,0x95,0x85,0x95,0xA5,0x95,0x95,0x69,0x85,
+	0x95,0x85,0x86,0x86,0x97,0x84,0x85,0xB6,0x84,0xA5,0x95,0xA4,0x95,0x95,0x95,0x68,0x95,0x66,0xA6,0x95,
+	0x95,0x95,0x86,0x93,0xB5,0x86,0x77,0x94,0x96,0x95,0x96,0x85,0x68,0x94,0x87,0x95,0x86,0x86,0x93,0xB4,
+	0xA3,0xB3,0xA6,0x86,0x85,0x85,0x96,0x76,0x86,0x64,0x69,0x78,0x68,0x78,0x78,0x77,0x67,0x79,0x68,0x79,
+	0x59,0x56,0x87,0x98,0x68,0x78,0x76,0x88,0x68,0x68,0x67,0x76,0x87,0x68,0x78,0x76,0x78,0x77,0x78,0xA6,
+	0x80,0xAF,0x81,0x38,0x47,0x67,0x77,0x78,0x77,0x89,0x07,0x79,0xB7,0x87,0x86,0x86,0x87,0x86,0x87,0x76,
+	0x78,0x77,0x87,0x66,0x96,0x86,0x86,0x74,0xA6,0x87,0x86,0x77,0x86,0x77,0x76,0x77,0x77,0x87,0x77,0x77,
+	0x77,0x77,0x87,0x65,0x78,0x77,0x78,0x75,0x88,0x85,0x76,0x87,0x95,0x77,0x86,0x87,0x86,0x96,0x85,0x76,
+	0x69,0x67,0x59,0x77,0x6A,0x65,0x86,0x78,0x94,0x77,0x88,0x77,0x78,0x85,0x96,0x65,0x98,0x77,0x87,0x67,
+	0x86,0x77,0x87,0x66,0x87,0x86,0x86,0x86,0x77,0x86,0x86,0x76,0x87,0x86,0x77,0x76,0x87,0x77,0x86,0x86,
+	0x86,0x87,0x76,0x95,0x86,0x86,0x87,0x65,0x97,0x86,0x87,0x76,0x86,0x86,0x87,0x75,0x88,0x76,0x87,0x76,
+	0x87,0x76,0x77,0x77,0x86,0x78,0x76,0x76,0x96,0x78,0x76,0x77,0x86,0x77,0x77,0x76,0x96,0x75,0x95,0x56,
+	0x87,0x87,0x87,0x78,0x88,0x67,0x87,0x87,0x58,0x87,0x77,0x87,0x77,0x76,0x87,0x96,0x59,0x88,0x37,0x89,
+	0x69,0x69,0x84,0x96,0x67,0x77,0x57,0x4B,0x58,0xB7,0x80,0x8E,0x0D,0x78,0x87,0x77,0x87,0x68,0x79,0x49,
+	0x76,0x78,0x77,0x5A,0x67,0x69,0x68,0x68,0x68,0x4A,0x68,0x69,0x67,0x69,0x59,0x58,0x68,0x67,0x69,0x77,
+	0x77,0x69,0x68,0x68,0x66,0x68,0x87,0x68,0x77,0x5A,0x68,0x67,0x68,0x68,0x67,0x78,0x78,0x67,0x6A,0x59,
+	0x67,0x57,0x95,0x78,0x77,0x86,0x88,0x57,0x77,0x68,0x67,0x79,0x76,0x76,0x98,0x68,0x75,0x68,0x88,0x58,
+	0x87,0x5A,0x57,0x79,0x67,0x59,0x78,0x49,0x58,0x77,0x79,0x49,0x68,0x59,0x77,0x68,0x78,0x48,0x79,0x67,
+	0x68,0x59,0x68,0x68,0x59,0x75,0x6A,0x68,0x76,0x4C,0x67,0x77,0x78,0x59,0x69,0x56,0x96,0x68,0x68,0x68,
+	0x77,0x69,0x67,0x68,0x67,0x78,0x69,0x68,0x58,0x59,0x68,0x68,0x69,0x49,0x77,0x59,0x67,0x69,0x67,0x68,
+	0x65,0x48,0x77,0x87,0x86,0x96,0x88,0x75,0x87,0x96,0x87,0x95,0x87,0x77,0x68,0x86,0x77,0x77,0x96,0x68,
+	0x86,0x77,0x85,0x5A,0x81,0xD5,0x95,0x68,0x99,0x74,0x98,0x77,0x09,0xF9,0x0A,0x5A,0x66,0x58,0x77,0x87,
+	0x91,0x77,0x77,0xE9,0x77,0x77,0x77,0x76,0x87,0x75,0x97,0x77,0x77,0x77,0x78,0x68,0x68,0x68,0x67,0x3B,
+	0x59,0x77,0x77,0x57,0x79,0x57,0x86,0x87,0x67,0x97,0x77,0x57,0x79,0x77,0x77,0x75,0x95,0x77,0x79,0x75,
+	0x97,0x57,0x77,0x79,0x58,0x69,0x77,0x77,0x77,0x77,0x77,0x75,0x86,0x77,0x87,0x58,0x95,0x78,0x65,0x8A,
+	0x39,0x58,0x87,0x96,0x87,0x77,0x77,0x77,0x86,0x87,0x76,0x78,0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x77,
+	0x77,0x68,0x77,0x68,0x77,0x67,0x86,0x77,0x78,0x77,0x77,0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x77,0x68,
+	0x77,0x68,0x77,0x67,0x78,0x77,0x77,0x68,0x68,0x76,0x87,0x68,0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x77,
+	0x77,0x77,0x77,0x68,0x77,0x77,0x77,0x68,0x68,0x68,0x76,0x38,0x97,0x67,0x79,0x77,0x77,0x77,0x77,0x77,
+	0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x78,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x68,
+	0x72,0xC5,0x86,0x86,0x98,0x77,0x86,0x78,0x1C,0x85,0x2E,0x77,0x77,0x77,0x87,0x86,0x76,0x86,0x86,0xA0,
+	0xBD,0x49,0x97,0x66,0x48,0x88,0x48,0x68,0x86,0x78,0x77,0x77,0x78,0x66,0xA6,0x87,0x83,0x85,0x88,0x78,
+	0x66,0xA7,0x56,0x87,0x6A,0x46,0x89,0x76,0xA7,0x76,0x87,0x74,0xA2,0x86,0x77,0x79,0x66,0xB6,0x48,0x67,
+	0x8A,0x36,0x88,0x77,0xA5,0xA5,0xB1,0xE9,0x39,0x78,0x78,0x75,0x87,0x77,0x77,0x77,0x68,0x58,0x79,0x69,
+	0x4A,0x59,0x29,0x6A,0x3C,0x3B,0x46,0x78,0x75,0x89,0x76,0x89,0x4A,0x56,0x88,0x3B,0x66,0x88,0x68,0x87,
+	0x57,0x97,0x38,0x87,0x56,0xB7,0x84,0x88,0x67,0x57,0x95,0xA8,0x59,0x77,0x68,0x4A,0x49,0x69,0x57,0x6A,
+	0x59,0x58,0x67,0x87,0x5A,0x75,0x78,0x69,0x56,0x97,0x77,0x73,0x08,0x78,0x78,0x77,0x87,0x78,0x77,0x78,
+	0x77,0x77,0x87,0x78,0x68,0x77,0x77,0x87,0x78,0x76,0x86,0x97,0x58,0x77,0x78,0x58,0x78,0x77,0x68,0x78,
+	0x75,0x95,0xB7,0x70,0x8F,0x80,0xA6,0x87,0x65,0x66,0x78,0x7A,0x17,0x77,0x70,
+};
+
+static void SIT13_Func1(struct SIT13Data *s, struct SIT13Buffer *buf, uint32 info, uint16 bits, uint16 num)
+{
+	uint32 i, j;
+
+	if(bits <= 12)
+	{
+		for(i = 0; i < (1<<12); i += (1<<bits))
+		{
+			buf[info+i].data = num;
+			buf[info+i].bits = bits;
+		}
+	}
+	else
+	{
+		j = bits-12;
+
+		if(buf[info & 0xFFF].bits != 0x1F)
+		{
+			buf[info & 0xFFF].bits = 0x1F;
+			buf[info & 0xFFF].data = s->MaxBits++;
+		}
+		bits = buf[info & 0xFFF].data;
+		info >>= 12;
+
+		while(j--)
+		{
+			uint16 *a;
+
+			a = info & 1 ? &s->Buffer4[bits].d2 : &s->Buffer4[bits].d1;
+			if(!*a)
+				*a = s->MaxBits++;
+			bits = *a;
+			info >>= 1;
+		}
+		s->Buffer4[bits].freq = num;
+	}
+}
+
+static void SIT13_SortTree(struct SIT13Data *s, struct SIT13Buffer *buf, struct SIT13Buffer *buf2)
+{
+	uint16 td;
+	int8 tb;
+
+	struct SIT13Buffer *a, *b;
+
+	while(buf2-1 > buf)
+	{
+		a = buf;
+		b = buf2;
+
+		for(;;)
+		{
+			while(++a < buf2)
+			{
+				tb = a->bits - buf->bits;
+				if(tb > 0 || (!tb && (a->data >= buf->data)))
+					break;
+			}
+			while(--b > buf)
+			{
+				tb = b->bits - buf->bits;
+				if(tb < 0 || (!tb && (b->data <= buf->data)))
+					break;
+			}
+			if(b < a)
+				break;
+			else
+			{
+				tb = a->bits;
+				td = a->data;
+				a->bits = b->bits;
+				a->data = b->data;
+				b->bits = tb;
+				b->data = td;
+			}
+		}
+		if(b == buf)
+			++buf;
+		else
+		{
+			tb = buf->bits;
+			td = buf->data;
+			buf->bits = b->bits;
+			buf->data = b->data;
+			b->bits = tb;
+			b->data = td;
+			if(buf2-b-1 > b-buf)
+			{
+				SIT13_SortTree(s, buf, b);
+				buf = b+1;
+			}
+			else
+			{
+				SIT13_SortTree(s, b+1, buf2);
+				buf2 = b;
+			}
+		}
+	}
+}
+
+static void SIT13_Func2(struct SIT13Data *s, struct SIT13Buffer *buf, uint16 bits, struct SIT13Buffer *buf2)
+{
+	int32 i, j, k, l, m, n;
+
+	SIT13_SortTree(s, buf2, buf2 + bits);
+
+	l = k = j = 0;
+	for(i = 0; i < bits; ++i)
+	{
+		l += k;
+		m = buf2[i].bits;
+		if(m != j)
+		{
+			if((j = m) == -1)
+				k = 0;
+			else
+				k = 1 << (32-j);
+		}
+		if(j > 0)
+		{
+			for(n = m = 0; n < 8*4; n += 4)
+				m += SIT13Bits[(l>>n)&0xF]<<(7*4-n);
+			SIT13_Func1(s, buf, m, j, buf2[i].data);
+		}
+	}
+}
+
+static void SIT13_CreateStaticTree(struct SIT13Data *s, struct SIT13Buffer *buf, uint16 bits, uint8 *bitsbuf)
+{
+	uint32 i;
+
+	for(i = 0; i < bits; ++i)
+	{
+		s->Buffer5[i].data = i;
+		s->Buffer5[i].bits = bitsbuf[i];
+	}
+	SIT13_Func2(s, buf, bits, s->Buffer5);
+}
+
+static void SIT13InitInfo(struct SIT13Data *s, uint8 id)
+{
+	int32 i;
+	uint8 k, l = 0, *a;
+	const uint8 *b;
+
+	a = s->TextBuf;
+	b = (const uint8 *) SIT13Static+SIT13StaticPos[id-1];
+	id &= 1;
+
+	for(i = 658; i; --i)
+	{
+		k = id ? *b >> 4 : *(b++) & 0xF; id ^=1;
+
+		if(!k)
+		{
+			l -= id ? *b >> 4 : *(b++) & 0xF; id ^= 1;
+		}
+		else
+		{
+			if(k == 15)
+			{
+				l += id ? *b >> 4 : *(b++) & 0xF; id ^= 1;
+			}
+			else
+				l += k-7;
+		}
+		*(a++) = l;
+	}
+}
+
+static bool SIT13_Extract(struct SIT13Data *s, Common::BitStream8LSB *bits, Common::MemoryWriteStream& out)
+{
+	uint32 wpos = 0, j, k, l, size;
+	struct SIT13Buffer *buf = s->Buffer3;
+
+	while(!bits->eos())
+	{
+		k = bits->peekBits<12>();
+		if((j = buf[k].bits) <= 12)
+		{
+			l = buf[k].data;
+			if (j == 0)
+				return false;
+			bits->getBits(j);
+		}
+		else
+		{
+			bits->getBits<12>();
+
+			j = buf[k].data;
+			while(s->Buffer4[j].freq == -1)
+				j = bits->getBit() ? s->Buffer4[j].d2 : s->Buffer4[j].d1;
+			l = s->Buffer4[j].freq;
+		}
+		if(l < 0x100)
+		{
+			s->Window[wpos++] = l;
+			out.writeByte(l);
+			wpos &= 0xFFFF;
+			buf = s->Buffer3;
+		}
+		else
+		{
+			buf = s->Buffer3b;
+			if(l < 0x13E)
+				size = l - 0x100 + 3;
+			else
+			{
+				if(l == 0x13E)
+					size = bits->getBits<10>();
+				else
+				{
+					if(l == 0x140)
+						return true;
+					size = bits->getBits<15>();
+				}
+				size += 65;
+			}
+			j = bits->peekBits<12>();
+			k = s->Buffer2[j].bits;
+			if(k <= 12)
+			{
+				l = s->Buffer2[j].data;
+				bits->getBits(k);
+			}
+			else
+			{
+				bits->getBits<12>();
+				j = s->Buffer2[j].data;
+				while(s->Buffer4[j].freq == -1)
+					j = bits->getBit() ? s->Buffer4[j].d2 : s->Buffer4[j].d1;
+				l = s->Buffer4[j].freq;
+			}
+			k = 0;
+			if(l--)
+				k = (1 << l) | bits->getBits(l);
+			l = wpos+0x10000-(k+1);
+			while(size--)
+			{
+				l &= 0xFFFF;
+				byte b = s->Window[l++];
+				out.writeByte(b);
+				s->Window[wpos++] = b;
+				wpos &= 0xFFFF;
+			}
+		} /* l >= 0x100 */
+	}
+
+	return false;
+}
+
+static void SIT13_CreateTree(struct SIT13Data *s, Common::BitStream8LSB *bits, struct SIT13Buffer *buf, uint16 num)
+{
+	struct SIT13Buffer *b;
+	uint32 i;
+	uint16 data;
+	int8 bi = 0;
+
+	for(i = 0; i < num; ++i)
+	{
+		b = &s->Buffer1[bits->peekBits<12>()];
+		data = b->data;
+		bits->getBits(b->bits);
+
+		switch(data-0x1F)
+		{
+		case 0: bi = -1; break;
+		case 1: ++bi; break;
+		case 2: --bi; break;
+		case 3:
+			if(bits->getBit())
+				s->Buffer5[i++].bits = bi;
+			break;
+		case 4:
+			data = bits->getBits<3>()+2;
+			while(data--)
+				s->Buffer5[i++].bits = bi;
+			break;
+		case 5:
+			data = bits->getBits<6>()+10;
+			while(data--)
+				s->Buffer5[i++].bits = bi;
+			break;
+		default: bi = data+1; break;
+		}
+		s->Buffer5[i].bits = bi;
+	}
+	for(i = 0; i < num; ++i)
+		s->Buffer5[i].data = i;
+	SIT13_Func2(s, buf, num, s->Buffer5);
+}
+
+bool StuffItArchive::decompress13(Common::SeekableReadStream *src, byte *dst, uint32 uncompressedSize) const {
+	Common::MemoryWriteStream out(dst, uncompressedSize);
+
+	Common::BitStream8LSB *bits = new Common::BitStream8LSB(src);
+
+	uint32 i, j;
+
+	SIT13Data *s = new SIT13Data();
+
+	s->MaxBits = 1;
+	for(i = 0; i < 37; ++i)
+		SIT13_Func1(s, s->Buffer1, SIT13Info[i], SIT13InfoBits[i], i);
+	for(i = 1; i < 0x704; ++i)
+	{
+		/* s->Buffer4[i].d1 = s->Buffer4[i].d2 = 0; */
+		s->Buffer4[i].freq = -1;
+	}
+
+	j = bits->getBits<8>();
+	i = j>>4;
+	if(i > 5)
+		return false;
+	if(i)
+	{
+		SIT13InitInfo(s, i--);
+		SIT13_CreateStaticTree(s, s->Buffer3, 0x141, s->TextBuf);
+		SIT13_CreateStaticTree(s, s->Buffer3b, 0x141, s->TextBuf+0x141);
+		SIT13_CreateStaticTree(s, s->Buffer2, SIT13StaticBits[i], s->TextBuf+0x282);
+	}
+	else
+	{
+		SIT13_CreateTree(s, bits, s->Buffer3, 0x141);
+		if(j&8)
+			memcpy(s->Buffer3b, s->Buffer3, 0x1000*sizeof(struct SIT13Buffer));
+		else
+			SIT13_CreateTree(s, bits, s->Buffer3b, 0x141);
+		j = (j&7)+10;
+		SIT13_CreateTree(s, bits, s->Buffer2, j);
+	}
+	return SIT13_Extract(s, bits, out);
+}
+
 #define OUTPUT_VAL(x) \
 	out.writeByte(x); \
 	dat->window[j++] = x; \


Commit: 2c8fd71b479de32ba60f89fbc2fdf468cdd223f6
    https://github.com/scummvm/scummvm/commit/2c8fd71b479de32ba60f89fbc2fdf468cdd223f6
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-08T00:02:39+01:00

Commit Message:
KYRA: Switch to openFileOrDataFork

Changed paths:
    engines/kyra/resource/resource.cpp
    engines/kyra/resource/resource.h
    engines/kyra/resource/resource_intern.cpp
    engines/kyra/resource/resource_intern.h


diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index 772b790e7c3..bde1adbf1f0 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -28,12 +28,9 @@
 
 namespace Kyra {
 
-Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(), _protectedFiles(), _macResMan(), _loaders(), _vm(vm), _bigEndianPlatForm(vm->gameFlags().platform == Common::kPlatformAmiga || vm->gameFlags().platform == Common::kPlatformSegaCD) {
+Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(), _protectedFiles(), _loaders(), _vm(vm), _bigEndianPlatForm(vm->gameFlags().platform == Common::kPlatformAmiga || vm->gameFlags().platform == Common::kPlatformSegaCD) {
 	initializeLoaders();
 
-	if (_vm->gameFlags().useInstallerPackage)
-		_macResMan = new Common::MacResManager();
-
 	// Initialize directories for playing from CD or with original
 	// directory structure
 	if (_vm->game() == GI_KYRA3)
@@ -55,7 +52,6 @@ Resource::~Resource() {
 	for (ArchiveMap::iterator i = _archiveCache.begin(); i != _archiveCache.end(); ++i)
 		delete i->_value;
 	_archiveCache.clear();
-	delete _macResMan;
 }
 
 bool Resource::reset() {
@@ -406,7 +402,7 @@ Common::Archive *Resource::loadStuffItArchive(const Common::String &file) {
 	if (cachedArchive != _archiveCache.end())
 		return cachedArchive->_value;
 
-	Common::Archive *archive = StuffItLoader::load(this, file, _macResMan);
+	Common::Archive *archive = StuffItLoader::load(this, file);
 	if (!archive)
 		return nullptr;
 
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index 11604872489..b2460a97055 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -95,8 +95,6 @@ protected:
 	Common::SearchSet _archiveFiles;
 	Common::SearchSet _protectedFiles;
 
-	Common::MacResManager *_macResMan;
-
 	Common::Archive *loadArchive(const Common::String &name, Common::ArchiveMemberPtr member);
 	Common::Archive *loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset);
 	Common::Archive *loadStuffItArchive(const Common::String &file);
diff --git a/engines/kyra/resource/resource_intern.cpp b/engines/kyra/resource/resource_intern.cpp
index 2c520527666..b3b0d595f17 100644
--- a/engines/kyra/resource/resource_intern.cpp
+++ b/engines/kyra/resource/resource_intern.cpp
@@ -1217,13 +1217,11 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi
 	return new CachedArchive(fileList);
 }
 
-Common::Archive *StuffItLoader::load(Resource *owner, const Common::String &filename, Common::MacResManager *macResMan) {
-	if (macResMan->open(filename)) {
-		Common::SeekableReadStream *stream = macResMan->getDataFork();
-		if (stream) {
-			Common::Archive *archive = Common::createStuffItArchive(stream);
-			return archive;
-		}
+Common::Archive *StuffItLoader::load(Resource *owner, const Common::String &filename) {
+	Common::SeekableReadStream *stream = Common::MacResManager::openFileOrDataFork(filename);
+	if (stream) {
+		Common::Archive *archive = Common::createStuffItArchive(stream);
+		return archive;
 	}
 
 	error("StuffItLoader::load: Could not load %s", filename.c_str());
diff --git a/engines/kyra/resource/resource_intern.h b/engines/kyra/resource/resource_intern.h
index cf8c1ff7ca1..216a76c7916 100644
--- a/engines/kyra/resource/resource_intern.h
+++ b/engines/kyra/resource/resource_intern.h
@@ -144,7 +144,7 @@ public:
 
 class StuffItLoader {
 public:
-	static Common::Archive *load(Resource *owner, const Common::String &filename, Common::MacResManager *macResMan);
+	static Common::Archive *load(Resource *owner, const Common::String &filename);
 };
 
 } // End of namespace Kyra


Commit: 9f4d744b46509174c37b74039dee1b7a2a02547a
    https://github.com/scummvm/scummvm/commit/9f4d744b46509174c37b74039dee1b7a2a02547a
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-08T00:02:39+01:00

Commit Message:
KYRA: Store cached installer mac archive as its simple name

This avoids the complexity of discovering its name again.

It makes supporting multi-floppy installer much less hairy as well

Changed paths:
    engines/kyra/resource/resource.cpp
    engines/kyra/resource/resource.h
    engines/kyra/sound/sound_mac_lok.cpp


diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index bde1adbf1f0..fabefedaee7 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -69,7 +69,7 @@ bool Resource::reset() {
 			error("Could not find Legend of Kyrandia installer file");
 		}
 
-		Common::Archive *archive = loadStuffItArchive(kyraInstaller);
+		Common::Archive *archive = loadStuffItArchive(kyraInstaller, "Install Legend of Kyrandia");
 		if (!archive)
 			error("Failed to load Legend of Kyrandia installer file");
 
@@ -397,8 +397,8 @@ Common::Archive *Resource::loadInstallerArchive(const Common::String &file, cons
 	return archive;
 }
 
-Common::Archive *Resource::loadStuffItArchive(const Common::String &file) {
-	ArchiveMap::iterator cachedArchive = _archiveCache.find(file);
+Common::Archive *Resource::loadStuffItArchive(const Common::String &file, const Common::String& canonicalName) {
+	ArchiveMap::iterator cachedArchive = _archiveCache.find(canonicalName);
 	if (cachedArchive != _archiveCache.end())
 		return cachedArchive->_value;
 
@@ -406,7 +406,7 @@ Common::Archive *Resource::loadStuffItArchive(const Common::String &file) {
 	if (!archive)
 		return nullptr;
 
-	_archiveCache[file] = archive;
+	_archiveCache[canonicalName] = archive;
 	return archive;
 }
 
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index b2460a97055..61d61ad81c7 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -97,7 +97,7 @@ protected:
 
 	Common::Archive *loadArchive(const Common::String &name, Common::ArchiveMemberPtr member);
 	Common::Archive *loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset);
-	Common::Archive *loadStuffItArchive(const Common::String &file);
+	Common::Archive *loadStuffItArchive(const Common::String &file, const Common::String& canonicalName);
 
 	bool loadProtectedFiles(const char *const * list);
 
diff --git a/engines/kyra/sound/sound_mac_lok.cpp b/engines/kyra/sound/sound_mac_lok.cpp
index abf5985a7c3..52819e54b4e 100644
--- a/engines/kyra/sound/sound_mac_lok.cpp
+++ b/engines/kyra/sound/sound_mac_lok.cpp
@@ -40,10 +40,7 @@ SoundMacRes::SoundMacRes(KyraEngine_v1 *vm) : _resMan(0), _stuffItArchive(nullpt
 	_resMan = new Common::MacResManager[2];
 
 	if (vm->gameFlags().useInstallerPackage) {
-		Common::String str = Util::findMacResourceFile("Install Legend of Kyrandia");
-		if (str.empty())
-			error("SoundMacRes::SoundMacRes(): Could not find Legend of Kyrandia installer file");
-		_stuffItArchive = vm->resource()->getCachedArchive(str);
+		_stuffItArchive = vm->resource()->getCachedArchive("Install Legend of Kyrandia");
 		if (!_stuffItArchive)
 			error("SoundMacRes::SoundMacRes(): Failed to load Legend of Kyrandia installer file");
 	}


Commit: 1b90cea645b86887c815b21b3873ccf6fec9a80f
    https://github.com/scummvm/scummvm/commit/1b90cea645b86887c815b21b3873ccf6fec9a80f
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-08T00:02:39+01:00

Commit Message:
KYRA: Support loading stuffit archive from abstract stream

Multi-floppy installer needs to use a fake stream composed from several
real files.

Changed paths:
    engines/kyra/resource/resource.cpp
    engines/kyra/resource/resource.h
    engines/kyra/resource/resource_intern.cpp
    engines/kyra/resource/resource_intern.h


diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index fabefedaee7..b8f85c18763 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -410,6 +410,21 @@ Common::Archive *Resource::loadStuffItArchive(const Common::String &file, const
 	return archive;
 }
 
+Common::Archive *Resource::loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String& canonicalName, const Common::String& debugName) {
+	ArchiveMap::iterator cachedArchive = _archiveCache.find(canonicalName);
+	if (cachedArchive != _archiveCache.end()) {
+		delete stream;
+		return cachedArchive->_value;
+	}
+
+	Common::Archive *archive = StuffItLoader::load(this, stream, debugName);
+	if (!archive)
+		return nullptr;
+
+	_archiveCache[canonicalName] = archive;
+	return archive;
+}
+
 #pragma mark -
 
 void Resource::initializeLoaders() {
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index 61d61ad81c7..e4bbdf63b30 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -98,6 +98,7 @@ protected:
 	Common::Archive *loadArchive(const Common::String &name, Common::ArchiveMemberPtr member);
 	Common::Archive *loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset);
 	Common::Archive *loadStuffItArchive(const Common::String &file, const Common::String& canonicalName);
+	Common::Archive *loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String& canonicalName, const Common::String& debugName);
 
 	bool loadProtectedFiles(const char *const * list);
 
diff --git a/engines/kyra/resource/resource_intern.cpp b/engines/kyra/resource/resource_intern.cpp
index b3b0d595f17..64a53ac553b 100644
--- a/engines/kyra/resource/resource_intern.cpp
+++ b/engines/kyra/resource/resource_intern.cpp
@@ -1218,13 +1218,16 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi
 }
 
 Common::Archive *StuffItLoader::load(Resource *owner, const Common::String &filename) {
-	Common::SeekableReadStream *stream = Common::MacResManager::openFileOrDataFork(filename);
+	return load(owner, Common::MacResManager::openFileOrDataFork(filename), filename);
+}
+
+Common::Archive *StuffItLoader::load(Resource *owner, Common::SeekableReadStream *stream, const Common::String& debugName) {
 	if (stream) {
 		Common::Archive *archive = Common::createStuffItArchive(stream);
 		return archive;
 	}
 
-	error("StuffItLoader::load: Could not load %s", filename.c_str());
+	error("StuffItLoader::load: Could not load %s", debugName.c_str());
 }
 
 CmpVocDecoder::CmpVocDecoder() {
diff --git a/engines/kyra/resource/resource_intern.h b/engines/kyra/resource/resource_intern.h
index 216a76c7916..be17623fac1 100644
--- a/engines/kyra/resource/resource_intern.h
+++ b/engines/kyra/resource/resource_intern.h
@@ -145,6 +145,7 @@ public:
 class StuffItLoader {
 public:
 	static Common::Archive *load(Resource *owner, const Common::String &filename);
+	static Common::Archive *load(Resource *owner, Common::SeekableReadStream *stream, const Common::String &debugName);
 };
 
 } // End of namespace Kyra


Commit: d7aa54bf30df79e84a27d0358c736601d2a9d04f
    https://github.com/scummvm/scummvm/commit/d7aa54bf30df79e84a27d0358c736601d2a9d04f
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-08T00:02:39+01:00

Commit Message:
KYRA: Support multi-floppy installer

Changed paths:
    engines/kyra/detection_tables.h
    engines/kyra/engine/util.cpp
    engines/kyra/engine/util.h
    engines/kyra/resource/resource.cpp
    engines/kyra/resource/resource.h


diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index 41972c8851f..88010519c15 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -312,6 +312,19 @@ const KYRAGameDescription adGameDescs[] = {
 		KYRA1_FLOPPY_FLAGS
 	},
 
+	{
+		{
+			"kyra1",
+			"StuffIt multi-floppy",
+			AD_ENTRY1s("xn--Legend of Kyrandia Installer-o11r", "83d0f8e8c44a0aaa92b06081c40cd3c2", 69726),
+			Common::EN_ANY,
+			Common::kPlatformMacintosh,
+			ADGF_MACRESFORK,
+			GUIO3(GUIO_NOSPEECH, GUIO_MIDIGM, GUIO_RENDERVGA)
+		},
+				KYRA1_FLOPPY_CMP_FLAGS
+	},
+
 	{
 		{
 			"kyra1",
diff --git a/engines/kyra/engine/util.cpp b/engines/kyra/engine/util.cpp
index 4e451484f25..01931848f33 100644
--- a/engines/kyra/engine/util.cpp
+++ b/engines/kyra/engine/util.cpp
@@ -289,7 +289,7 @@ Common::String Util::decodeString2(const Common::String &src) {
 	return reslt;
 }
 
-Common::String Util::findMacResourceFile(const char *baseName) {
+Common::String Util::findMacResourceFile(const char *baseName, const char *suffix) {
 	// The original executable has a TM char as its last character (character
 	// 0xAA from Mac code page). Depending on the emulator or platform used to
 	// copy the file it might have been reencoded to something else. So I look
@@ -308,7 +308,7 @@ Common::String Util::findMacResourceFile(const char *baseName) {
 
 	for (int i = 0; i < 2; ++i) {
 		for (int ii = 0; ii < ARRAYSIZE(tryCodePages); ++ii) {
-			Common::U32String fn(tryName, tryCodePages[ii]);
+			Common::U32String fn(tryName + suffix, tryCodePages[ii]);
 			fileName = fn.encode(Common::kUtf8);
 			if (resource.exists(fileName))
 				return fileName;
diff --git a/engines/kyra/engine/util.h b/engines/kyra/engine/util.h
index 80aa9741210..fb6fc2c6229 100644
--- a/engines/kyra/engine/util.h
+++ b/engines/kyra/engine/util.h
@@ -48,7 +48,7 @@ public:
 	// e. g. when typing a one-byte character, like a digit).
 	static void mergeUpdateJohabChars(uint16 &destJohabChar0, uint16 &destJohabChar1, char asciiInput, bool reset);
 
-	static Common::String findMacResourceFile(const char *baseName);
+	static Common::String findMacResourceFile(const char *baseName, const char *suffix = "");
 
 private:
 	struct DOS2JOHABEntry {
diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index b8f85c18763..70eeac7d77c 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -23,11 +23,44 @@
 #include "kyra/resource/resource.h"
 #include "kyra/resource/resource_intern.h"
 
+#include "common/macresman.h"
+#include "common/compression/stuffit.h"
+#include "common/concatstream.h"
 #include "common/config-manager.h"
 #include "common/fs.h"
+#include "common/substream.h"
 
 namespace Kyra {
 
+Common::Archive *Resource::loadKyra1MacInstaller() {
+	Common::String kyraInstaller = Util::findMacResourceFile("Install Legend of Kyrandia");
+
+	if (!kyraInstaller.empty()) {
+		Common::Archive *archive = loadStuffItArchive(kyraInstaller, "Install Legend of Kyrandia");
+		if (!archive)
+			error("Failed to load Legend of Kyrandia installer file");
+		return archive;
+	}
+
+	kyraInstaller = Util::findMacResourceFile("Legend of Kyrandia", " Installer");
+
+	if (!kyraInstaller.empty()) {
+		Common::Array<Common::SharedPtr<Common::SeekableReadStream>> parts;
+		for (int i = 1; i <= 5; i++) {
+			Common::String partName = i == 1 ? kyraInstaller : Common::String::format("%s.%d", kyraInstaller.c_str(), i);
+			Common::SeekableReadStream *stream = Common::MacResManager::openFileOrDataFork(partName);
+			if (!stream)
+				error("Failed to load Legend of Kyrandia installer file part %s", partName.c_str());
+			if (stream->size() <= 100)
+				error("Legend of Kyrandia installer file part %s is too short", partName.c_str());
+			parts.push_back(Common::SharedPtr<Common::SeekableReadStream>(new Common::SeekableSubReadStream(stream, 100, stream->size(), DisposeAfterUse::YES)));
+		}
+		return loadStuffItArchive(new Common::ConcatReadStream(parts), "Install Legend of Kyrandia", "Legend of Kyrandia(TM) Installer.*");
+	}
+
+	return nullptr;
+}
+
 Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(), _protectedFiles(), _loaders(), _vm(vm), _bigEndianPlatForm(vm->gameFlags().platform == Common::kPlatformAmiga || vm->gameFlags().platform == Common::kPlatformSegaCD) {
 	initializeLoaders();
 
@@ -63,15 +96,9 @@ bool Resource::reset() {
 		error("invalid game path '%s'", dir.getPath().c_str());
 
 	if (_vm->game() == GI_KYRA1 && _vm->gameFlags().platform == Common::kPlatformMacintosh && _vm->gameFlags().useInstallerPackage) {
-		Common::String kyraInstaller = Util::findMacResourceFile("Install Legend of Kyrandia");
-
-		if (kyraInstaller.empty()) {
-			error("Could not find Legend of Kyrandia installer file");
-		}
-
-		Common::Archive *archive = loadStuffItArchive(kyraInstaller, "Install Legend of Kyrandia");
+		Common::Archive *archive = loadKyra1MacInstaller();
 		if (!archive)
-			error("Failed to load Legend of Kyrandia installer file");
+			error("Could not find Legend of Kyrandia installer file");
 
 		_files.add("installer", archive, 0, false);
 
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index e4bbdf63b30..407b73c5253 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -99,6 +99,7 @@ protected:
 	Common::Archive *loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset);
 	Common::Archive *loadStuffItArchive(const Common::String &file, const Common::String& canonicalName);
 	Common::Archive *loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String& canonicalName, const Common::String& debugName);
+	Common::Archive *loadKyra1MacInstaller();
 
 	bool loadProtectedFiles(const char *const * list);
 




More information about the Scummvm-git-logs mailing list