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

sev- noreply at scummvm.org
Sun Nov 27 23:25:09 UTC 2022


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

Summary:
ba10a93d99 COMMON: Support multivolume arj archives
ee8d850062 SAGA: Support running directly from arj archives
b27f715505 SAGA: Add entry for packed floppy ITE


Commit: ba10a93d99f3f8ef30ec7facee375acd3b31524e
    https://github.com/scummvm/scummvm/commit/ba10a93d99f3f8ef30ec7facee375acd3b31524e
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-28T00:25:05+01:00

Commit Message:
COMMON: Support multivolume arj archives

Changed paths:
    common/unarj.cpp
    common/unarj.h


diff --git a/common/unarj.cpp b/common/unarj.cpp
index 3e6ae10cb1e..c4e25f8f6c6 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -690,14 +690,21 @@ void ArjDecoder::decode_f(int32 origsize) {
 
 #pragma mark ArjArchive implementation
 
-typedef HashMap<String, ArjHeader*, IgnoreCase_Hash, IgnoreCase_EqualTo> ArjHeadersMap;
+struct ArjFileChunk {
+	ArjHeader* _header;
+	uint _volume;
+
+	ArjFileChunk(ArjHeader* header, uint volume) : _header(header), _volume(volume) {}
+};
+
+typedef HashMap<String, Array<ArjFileChunk>, IgnoreCase_Hash, IgnoreCase_EqualTo> ArjHeadersMap;
 
 class ArjArchive : public Archive {
 	ArjHeadersMap _headers;
-	String _arjFilename;
+	Array<String> _arjFilenames;
 
 public:
-	ArjArchive(const String &name);
+	ArjArchive(const Array<String> &names);
 	virtual ~ArjArchive();
 
 	// Archive implementation
@@ -707,42 +714,45 @@ public:
 	SeekableReadStream *createReadStreamForMember(const Path &path) const override;
 };
 
-ArjArchive::ArjArchive(const String &filename) : _arjFilename(filename) {
-	File arjFile;
-
-	if (!arjFile.open(_arjFilename)) {
-		warning("ArjArchive::ArjArchive(): Could not find the archive file");
-		return;
-	}
+ArjArchive::~ArjArchive() {
+       debug(0, "ArjArchive Destructor Called");
+       ArjHeadersMap::iterator it = _headers.begin();
+       for ( ; it != _headers.end(); ++it) {
+	       for (uint i = 0; i < it->_value.size(); i++)
+		       delete it->_value[i]._header;
+       }
+}
 
-	int32 firstHeaderOffset = findHeader(arjFile);
+ArjArchive::ArjArchive(const Array<String> &filenames) : _arjFilenames(filenames) {
+	for (uint i = 0; i < _arjFilenames.size(); i++) {
+		File arjFile;
 
-	if (firstHeaderOffset < 0) {
-		warning("ArjArchive::ArjArchive(): Could not find a valid header");
-		return;
-	}
+		if (!arjFile.open(_arjFilenames[i])) {
+			warning("ArjArchive::ArjArchive(): Could not find the archive file");
+			return;
+		}
 
-	ArjHeader *header = nullptr;
+		int32 firstHeaderOffset = findHeader(arjFile);
 
-	arjFile.seek(firstHeaderOffset, SEEK_SET);
-	if ((header = readHeader(arjFile)) == nullptr)
-		return;
-	delete header;
+		if (firstHeaderOffset < 0) {
+			warning("ArjArchive::ArjArchive(): Could not find a valid header");
+			return;
+		}
 
-	while ((header = readHeader(arjFile)) != nullptr) {
-		_headers[header->filename] = header;
-		arjFile.seek(header->compSize, SEEK_CUR);
-	}
+		ArjHeader *header = nullptr;
 
-	debug(0, "ArjArchive::ArjArchive(%s): Located %d files", filename.c_str(), _headers.size());
-}
+		arjFile.seek(firstHeaderOffset, SEEK_SET);
+		if ((header = readHeader(arjFile)) == nullptr)
+			return;
+		delete header;
 
-ArjArchive::~ArjArchive() {
-	debug(0, "ArjArchive Destructor Called");
-	ArjHeadersMap::iterator it = _headers.begin();
-	for ( ; it != _headers.end(); ++it) {
-		delete it->_value;
+		while ((header = readHeader(arjFile)) != nullptr) {
+			_headers[header->filename].push_back(ArjFileChunk(header, i));
+			arjFile.seek(header->compSize, SEEK_CUR);
+		}
 	}
+	
+	debug(0, "ArjArchive::ArjArchive(%d volume(s) starting with %s): Located %d files", filenames.size(), filenames.empty() ? "" : filenames[0].c_str(), _headers.size());
 }
 
 bool ArjArchive::hasFile(const Path &path) const {
@@ -755,7 +765,7 @@ int ArjArchive::listMembers(ArchiveMemberList &list) const {
 
 	ArjHeadersMap::const_iterator it = _headers.begin();
 	for ( ; it != _headers.end(); ++it) {
-		list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(it->_value->filename, this)));
+		list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(it->_value[0]._header->filename, this)));
 		matches++;
 	}
 
@@ -776,43 +786,66 @@ SeekableReadStream *ArjArchive::createReadStreamForMember(const Path &path) cons
 		return nullptr;
 	}
 
-	ArjHeader *hdr = _headers[name];
+	const Array <ArjFileChunk>& hdrs = _headers[name];
 
-	File archiveFile;
-	archiveFile.open(_arjFilename);
-	archiveFile.seek(hdr->pos, SEEK_SET);
+	uint64 uncompressedSize = 0;
+	uint totalChunks;
+	for (totalChunks = 0; totalChunks < hdrs.size(); totalChunks++) {
+		uncompressedSize += hdrs[totalChunks]._header->origSize;
+		if (!(hdrs[totalChunks]._header->flags & 0x4)) {
+			totalChunks++;
+			break;
+		}
+	}
+
+	// Prevent overflows
+	if (uncompressedSize > 0x70000000)
+		return nullptr;
 
 	// TODO: It would be good if ArjFile could decompress files in a streaming
 	// mode, so it would not need to pre-allocate the entire output.
-	byte *uncompressedData = (byte *)malloc(hdr->origSize);
+	byte *uncompressedData = (byte *)malloc(uncompressedSize);
+	uint32 uncompressedPtr = 0;
 	assert(uncompressedData);
 
-	if (hdr->method == 0) { // store
-		int32 len = archiveFile.read(uncompressedData, hdr->origSize);
-		assert(len == hdr->origSize);
-	} else {
-		ArjDecoder *decoder = new ArjDecoder(hdr);
+	for (uint chunk = 0; chunk < totalChunks; chunk++) {
+		File archiveFile;
+		ArjHeader *hdr = hdrs[chunk]._header;
+		archiveFile.open(_arjFilenames[hdrs[chunk]._volume]);
+		archiveFile.seek(hdr->pos, SEEK_SET);
+
+		if (hdr->method == 0) { // store
+			int32 len = archiveFile.read(uncompressedData + uncompressedPtr, hdr->origSize);
+			assert(len == hdr->origSize);
+		} else {
+			ArjDecoder *decoder = new ArjDecoder(hdr);
 
-		// TODO: It might not be appropriate to use this wrapper inside ArjFile.
-		// If reading from archiveFile directly is too slow to be usable,
-		// maybe the filesystem code should instead wrap its files
-		// in a BufferedReadStream.
-		decoder->_compressed = wrapBufferedReadStream(&archiveFile, 4096, DisposeAfterUse::NO);
-		decoder->_outstream = new MemoryWriteStream(uncompressedData, hdr->origSize);
+			// TODO: It might not be appropriate to use this wrapper inside ArjFile.
+			// If reading from archiveFile directly is too slow to be usable,
+			// maybe the filesystem code should instead wrap its files
+			// in a BufferedReadStream.
+			decoder->_compressed = wrapBufferedReadStream(&archiveFile, 4096, DisposeAfterUse::NO);
+			decoder->_outstream = new MemoryWriteStream(uncompressedData + uncompressedPtr, hdr->origSize);
 
-		if (hdr->method == 1 || hdr->method == 2 || hdr->method == 3)
-			decoder->decode(hdr->origSize);
-		else if (hdr->method == 4)
-			decoder->decode_f(hdr->origSize);
+			if (hdr->method == 1 || hdr->method == 2 || hdr->method == 3)
+				decoder->decode(hdr->origSize);
+			else if (hdr->method == 4)
+				decoder->decode_f(hdr->origSize);
 
-		delete decoder;
+			delete decoder;
+		}
+		uncompressedPtr += hdr->origSize;
 	}
 
-	return new MemoryReadStream(uncompressedData, hdr->origSize, DisposeAfterUse::YES);
+	return new MemoryReadStream(uncompressedData, uncompressedSize, DisposeAfterUse::YES);
 }
 
 Archive *makeArjArchive(const String &name) {
-	return new ArjArchive(name);
+	return new ArjArchive({name});
+}
+
+Archive *makeArjArchive(const Array<String> &names) {
+	return new ArjArchive(names);
 }
 
 } // End of namespace Common
diff --git a/common/unarj.h b/common/unarj.h
index 8f894dccab9..6e08b5778aa 100644
--- a/common/unarj.h
+++ b/common/unarj.h
@@ -51,6 +51,11 @@ class Archive;
  */
 Archive *makeArjArchive(const String &name);
 
+/**
+ * Similar to previous but for multi-volume archives
+ */
+Archive *makeArjArchive(const Array<String> &names);
+
 /** @} */
 
 } // End of namespace Common


Commit: ee8d850062022b37b708b9c8b5d089424354467e
    https://github.com/scummvm/scummvm/commit/ee8d850062022b37b708b9c8b5d089424354467e
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-28T00:25:05+01:00

Commit Message:
SAGA: Support running directly from arj archives

Changed paths:
    engines/saga/detection.h
    engines/saga/detection_tables.h
    engines/saga/metaengine.cpp
    engines/saga/saga.cpp
    engines/saga/saga.h


diff --git a/engines/saga/detection.h b/engines/saga/detection.h
index 5ce7a6f7230..f96d4bf8f92 100644
--- a/engines/saga/detection.h
+++ b/engines/saga/detection.h
@@ -39,7 +39,8 @@ enum GameFeatures {
 	GF_IHNM_COLOR_FIX    = 1 << 4,
 	GF_SOME_MAC_RESOURCES= 1 << 5,
 	GF_AGA_GRAPHICS      = 1 << 6,
-	GF_ECS_GRAPHICS      = 1 << 7
+	GF_ECS_GRAPHICS      = 1 << 7,
+	GF_INSTALLER         = 1 << 8
 };
 
 enum GameFileTypes {
@@ -114,6 +115,8 @@ struct SAGAGameDescription {
 	GameFontList fontList;
 	GamePatchList patchList;
 	GameIntroList introList;
+	// Only used if GF_INSTALLER is set
+	ADGameFileDescription filesInArchive[5];
 };
 
 } // End of namespace Saga
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 76660c2066e..5d3774d764f 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -63,6 +63,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_DEMO,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DOS_DEMO,
+		{},
 	},
 
 	// Inherit the earth - MAC Demo version
@@ -87,6 +88,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_ITE_MAC,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 
@@ -113,6 +115,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_ITE_MAC,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 
@@ -139,6 +142,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 
@@ -165,6 +169,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 
@@ -198,6 +203,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - MAC CD First edition
@@ -225,6 +231,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - MAC CD Wyrmkeep version
@@ -249,6 +256,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE_WIN_DEMO,
 		PATCHLIST_ITE_MAC,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - MAC CD GOG version 1.1
@@ -273,6 +281,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 
@@ -305,6 +314,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - German Wyrmkeep combined Windows/Mac/Linux CD
@@ -332,6 +342,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Italian Wyrmkeep combined Windows/Mac/Linux CD (fan translation)
@@ -363,6 +374,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Wyrmkeep Windows CD version
@@ -389,6 +401,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Wyrmkeep Linux CD version
@@ -415,6 +428,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - DOS CD version - 17-06-1994
@@ -440,6 +454,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Wyrmkeep Italian Windows CD version (fan translation)
@@ -465,6 +480,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Wyrmkeep Italian Linux CD version (fan translation)
@@ -490,6 +506,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Italian DOS CD version (fan translation)
@@ -514,6 +531,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Wyrmkeep French Windows CD version (fan translation)
@@ -539,6 +557,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Wyrmkeep French Linux CD version (fan translation)
@@ -564,6 +583,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - French DOS CD version (fan translation)
@@ -588,6 +608,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - DOS CD version - 30-06-1994
@@ -612,6 +633,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Hebrew fan translation
@@ -636,6 +658,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - DOS CD German version
@@ -661,6 +684,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Windows Trial
@@ -688,6 +712,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - macOS Trial
@@ -714,6 +739,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Pocket PC Trial
@@ -740,6 +766,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the Earth - Japanese PC-98 CD version
@@ -764,6 +791,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
  	},
 
 	// Inherit the earth - Russian CD version (fan translation)
@@ -788,6 +816,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// ITE floppy versions ////////////////////////////////////////////////////////////////////////////////////
@@ -814,6 +843,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_NONE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Disk version
@@ -838,6 +868,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Italian Disk version (fan translation)
@@ -862,6 +893,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Chinese Disk version
@@ -886,6 +918,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// Inherit the earth - Russian Disk version (fan translation)
@@ -910,6 +943,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_DEFAULT,
+		{},
 	},
 
 	// ITE Amiga versions /////////////////////////////////////////////////////////////////////////////////////
@@ -935,6 +969,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_AMIGA_GERMAN_AGA,
+		{},
 	},
 	// This is on the same disk as previous but it's for ECS systems
 	{
@@ -957,6 +992,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_AMIGA_GERMAN_ECS,
+		{},
 	},
 	// Amiga Future coverdisk/Wyrmkeep English edition
 	{
@@ -979,6 +1015,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_AMIGA_ENGLISH_AGA_CD,
+		{},
 	},
 	// This is on the same disk as previous but it's for ECS systems
 	{
@@ -1001,6 +1038,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_ITE,
 		PATCHLIST_ITE,
 		INTROLIST_ITE_AMIGA_ENGLISH_ECS_CD,
+		{},
 	},
 
 	// TODO: Add Amiga floppy versions
@@ -1031,6 +1069,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_DEMO,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - English CD version
@@ -1063,6 +1102,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - De CD version
@@ -1093,6 +1133,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - German fan CD translation
@@ -1123,6 +1164,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Hungarian fan CD translation
@@ -1153,6 +1195,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Sp CD version
@@ -1181,6 +1224,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Korean CD version
@@ -1210,6 +1254,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Fr CD version
@@ -1239,6 +1284,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Chinese CD
@@ -1268,6 +1314,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_ZH,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Italian fan CD translation
@@ -1296,6 +1343,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Russian fan translaction v1.0 (by jack7277 et al)
@@ -1328,6 +1376,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
 	// I Have No Mouth And I Must Scream - Mac English CD
@@ -1354,9 +1403,10 @@ static const SAGAGameDescription gameDescriptions[] = {
 		FONTLIST_IHNM_CD,
 		PATCHLIST_NONE,
 		INTROLIST_NONE,
+		{},
 	},
 
-	{ AD_TABLE_END_MARKER, 0, 0, 0, RESOURCELIST_NONE, FONTLIST_MAX, PATCHLIST_MAX, INTROLIST_NONE }
+	{ AD_TABLE_END_MARKER, 0, 0, 0, RESOURCELIST_NONE, FONTLIST_MAX, PATCHLIST_MAX, INTROLIST_NONE, {} }
 };
 
 } // End of namespace Saga
diff --git a/engines/saga/metaengine.cpp b/engines/saga/metaengine.cpp
index d20589fd07f..0b791b4d4ea 100644
--- a/engines/saga/metaengine.cpp
+++ b/engines/saga/metaengine.cpp
@@ -61,7 +61,13 @@ Common::Platform SagaEngine::getPlatform() const { return _gameDescription->desc
 int SagaEngine::getGameNumber() const { return _gameNumber; }
 int SagaEngine::getStartSceneNumber() const { return _gameDescription->startSceneNumber; }
 
-const ADGameFileDescription *SagaEngine::getFilesDescriptions() const { return _gameDescription->desc.filesDescriptions; }
+const ADGameFileDescription *SagaEngine::getFilesDescriptions() const {
+    return getFeatures() & GF_INSTALLER ? _gameDescription->filesInArchive : _gameDescription->desc.filesDescriptions;
+}
+
+const ADGameFileDescription *SagaEngine::getArchivesDescriptions() const {
+  return getFeatures() & GF_INSTALLER ? _gameDescription->desc.filesDescriptions : nullptr;
+}
 
 } // End of namespace Saga
 
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 3ab19174f6e..40797ae16e7 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -25,6 +25,7 @@
 #include "common/system.h"
 #include "common/events.h"
 #include "common/translation.h"
+#include "common/unarj.h"
 
 #include "audio/mixer.h"
 
@@ -343,6 +344,17 @@ SagaEngine::~SagaEngine() {
 Common::Error SagaEngine::run() {
 	setTotalPlayTime(0);
 
+	if (getFeatures() & GF_INSTALLER) {
+		Common::Array<Common::String> filenames;
+		for (const ADGameFileDescription *gameArchiveDescription = getArchivesDescriptions();
+		     gameArchiveDescription->fileName; gameArchiveDescription++)
+			filenames.push_back(gameArchiveDescription->fileName);
+		Common::Archive *arj = Common::makeArjArchive(filenames);
+		if (!arj)
+			error("Error opening ARJ archive");
+		SearchMan.add("arj", arj, DisposeAfterUse::YES);
+	}
+
 	// Assign default values to the config manager, in case settings are missing
 	ConfMan.registerDefault("talkspeed", "255");
 	ConfMan.registerDefault("subtitles", "true");
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 35932f0712e..7abb0774d2d 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -584,6 +584,7 @@ public:
 	int getStartSceneNumber() const;
 
 	const ADGameFileDescription *getFilesDescriptions() const;
+	const ADGameFileDescription *getArchivesDescriptions() const;
 
 	const Common::Rect &getDisplayClip() const { return _displayClip;}
 	Common::Error loadGameState(int slot) override;


Commit: b27f71550512fcb6c34b5f7db7a5b82e68378757
    https://github.com/scummvm/scummvm/commit/b27f71550512fcb6c34b5f7db7a5b82e68378757
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-28T00:25:05+01:00

Commit Message:
SAGA: Add entry for packed floppy ITE

Changed paths:
    engines/saga/detection_tables.h


diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 5d3774d764f..2c412cb009f 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -871,6 +871,40 @@ static const SAGAGameDescription gameDescriptions[] = {
 		{},
 	},
 
+	// Same as above but installer
+	{
+		{
+			"ite",
+			"Floppy Packed",
+			{
+				{"inherit.arj", 0, "a7910371d6b43c00a318bc9c6f0062b4", 1413298},
+				{"inherit.a01", 0, "e5034686e3bc531ba1bbcb6c6efe90c1", 1456420},
+				{"inherit.a02", 0, "a8d3bf36dd7ece019fd2f819a0dfed70", 1456328},
+				{"inherit.a03", 0, "456a4ee942cdf653754fbec4e942db46", 1456284},
+				{"inherit.a04", 0, "748865cda20e1404b19f17b5aaab255d", 1456289},
+				{"inherit.105", 0, "c03f250b95dedf7f10bf188c49047140", 1117200},
+				AD_LISTEND
+			},
+			Common::EN_ANY,
+			Common::kPlatformDOS,
+			ADGF_NO_FLAGS,
+			GUIO1(GUIO_NOSPEECH)
+		},
+		GID_ITE,
+		GF_ITE_FLOPPY | GF_INSTALLER,
+		ITE_DEFAULT_SCENE,
+		RESOURCELIST_ITE,
+		FONTLIST_ITE,
+		PATCHLIST_ITE,
+		INTROLIST_ITE_DEFAULT,
+		{
+			{"ite.rsc",		GAME_RESOURCEFILE,					"8f4315a9bb10ec839253108a032c8b54", 8903828},
+			{"scripts.rsc",	GAME_SCRIPTFILE,					"516f7330f8410057b834424ea719d1ef", -1},
+			AD_LISTEND
+		},
+	},
+
+
 	// Inherit the earth - Italian Disk version (fan translation)
 	{
 		{




More information about the Scummvm-git-logs mailing list