[Scummvm-git-logs] scummvm master -> 047184a1b5d8254e5ed844b9952c5595341c0c38

sev- noreply at scummvm.org
Mon Mar 13 22:26:03 UTC 2023


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

Summary:
2a2217cb46 DIRECTOR: Add ProjectorArchive
ea9d0d39f8 JANITORIAL: Fix code formatting issues in ProjectorArchive
e10f756d68 DIRECTOR: Use BufferedStream in ProjectorArchive
7ee8e6653c DIRECTOR: Return false on failure in ProjectorArchive
3f49fca324 DIRECTOR: Check for invalid seeks in ProjectorArchive
7172b7620a DIRECTOR: Prefix warnings with BUILDBOT in ProjectorArchive
58ff07f4a6 DIRECTOR: ProjectorArchive filemap offset needs to be 32 bit only
325594ab0b DIRECTOR: Offset to PJXX tags is always in fixed endian
a15208bded DIRECTOR: Fix incorrect dict parsing in ProjectorArchive
047184a1b5 DIRECTOR: Fix alignment issue during seeking in ProjectorArchive


Commit: 2a2217cb46132403bb50b529b8fe2219f795b0cb
    https://github.com/scummvm/scummvm/commit/2a2217cb46132403bb50b529b8fe2219f795b0cb
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Add ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 9b27f263261..8402efc1fed 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -23,6 +23,7 @@
 #include "common/error.h"
 #include "common/file.h"
 #include "common/macresman.h"
+#include "common/memstream.h"
 #include "common/substream.h"
 #include "common/formats/winexe.h"
 #include "graphics/wincursor.h"
@@ -522,5 +523,173 @@ void Window::loadStartMovieXLibs() {
 	}
 	g_lingo->openXLib("SerialPort", kXObj);
 }
+class ProjectorArchive : public Common::Archive {
+public:
+	ProjectorArchive(Common::String path);
+	~ProjectorArchive() override;
+
+	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;
+private:
+	int Load(Common::SeekableReadStream *stream);
+
+	struct Entry {
+		uint64 offset;
+		uint32 size;
+	};
+	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	FileMap _files;
+	Common::String _path;
+};
+
+ProjectorArchive::ProjectorArchive(Common::String path)
+	: _path(path), _files() {
+
+	// We'll first build our fileMap
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(path);
+	if (!stream)
+		error("ProjectorArchive::ProjectorArchive(): Cannot open %s", path.c_str());
+	Load(stream);
+	delete stream;
+}
+
+ProjectorArchive::~ProjectorArchive() {
+	_files.clear();
+}
+
+int ProjectorArchive::Load(Common::SeekableReadStream *stream) {
+	bool bigEndian = true, found = false;
+	uint32 off, tag, rifxOffset;
+
+	// Assume the endianness of the file and try to locate the PJXX tags
+	for(int i = 0; i < 2; i++) {
+		bigEndian = !bigEndian;
+		stream->seek(-4, SEEK_END);
+		off = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+		stream->seek(off);
+		tag = stream->readUint32BE();
+
+		if (((tag & 0xffff0000) == MKTAG('P','J', 0, 0)) || ((tag & 0x0000ffff) == MKTAG(0, 0,'J','P'))) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		warning("ProjectorArchive::Load(): Projector Tag not found");
+		return true;
+	}
 
+	rifxOffset = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+	stream->seek(rifxOffset);
+	tag = stream->readUint32BE();
+	debugC(1, kDebugLoading, "File: %s off: 0x%x, tag: %s rifx: 0x%x", _path.c_str(), off, tag2str(tag), rifxOffset);
+
+	//Try to locate the very next Dict tag
+	tag = stream->readUint32BE();
+	found = false;
+	while (!stream->eos()) {
+		if (tag == MKTAG('D', 'i', 'c', 't') || tag == MKTAG('t', 'c', 'i', 'D')) {
+			found = true;
+			break;
+		}
+		tag = stream->readUint32BE();
+	}
+
+	// Return if dict tag is not found
+	if (!found) {
+		warning("ProjectorArchive::Load(): Dict Tag not found.");
+		return true;
+	}
+
+	uint32 size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+	uint32 dictOff = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+
+	// Jump to the actual dict block and begin parsing
+	stream->seek(dictOff);
+	tag = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+	size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+	stream->seek(dictOff + 24);
+	uint32 cnt = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+	int8 offsetDict = 0;
+	bool oBigEndian = bigEndian;
+
+	if (cnt > 0xFFFF) {
+		cnt = SWAP_BYTES_32(cnt);
+		offsetDict = 2;
+		bigEndian = true;
+	}
+
+	debugC(1, kDebugLoading, "Dict off: 0x%x, Size: 0x%x cnt: %d", dictOff, size, cnt);
+	uint32 pt = (cnt * 8) + (64 - offsetDict);
+	Common::StringArray arr(cnt);
+
+	for (uint32 i = 0; i < cnt; i++) {
+		stream->seek(dictOff + pt, SEEK_SET);
+		uint32 namelen = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+		arr[i] = stream->readString(0, namelen);
+		if (i < cnt - 1) {
+			int sub = (namelen % 4) ? (namelen % 4) : 4;
+			pt += 4 + namelen + (4 - sub);
+		}
+	}
+
+	bigEndian = oBigEndian;
+
+	for (uint32 i = 0; i < cnt; i++) {
+		tag = stream->readUint32BE();
+		size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+		debugC(1, kDebugLoading, "Entry: %s offset %llX tag %s size %d", arr[i].c_str(), stream->pos() - 8, tag2str(tag), size);
+		Entry entry;
+		// subtract 8 since we want to include tag and size as well
+		entry.offset = stream->pos() - 8;
+		entry.size = size + 8;
+		_files[arr[i]] = entry;
+		stream->seek(size, SEEK_CUR);
+	}
+
+	return false;
+}
+
+bool ProjectorArchive::hasFile(const Common::Path &path) const {
+	Common::String name = path.toString();
+	return (_files.find(name) != _files.end());
+}
+
+int ProjectorArchive::listMembers(Common::ArchiveMemberList &list) const {
+	int count = 0;
+
+	for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) {
+		list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(i->_key, this)));
+		++count;
+	}
+
+	return count;
+}
+
+const Common::ArchiveMemberPtr ProjectorArchive::getMember(const Common::Path &path) const {
+	Common::String name = path.toString();
+	if (!hasFile(name))
+		return Common::ArchiveMemberPtr();
+
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *ProjectorArchive::createReadStreamForMember(const Common::Path &path) const {
+	Common::String name = path.toString();
+	FileMap::const_iterator fDesc = _files.find(name);
+	if (fDesc == _files.end())
+		return nullptr;
+
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(_path);
+
+	stream->seek(fDesc->_value.offset, SEEK_SET);
+	byte *data = (byte *)malloc(fDesc->_value.size);
+	stream->read(data, fDesc->_value.size);
+	delete stream;
+
+	return new Common::MemoryReadStream(data, fDesc->_value.size, DisposeAfterUse::YES);
+}
 } // End of namespace Director


Commit: ea9d0d39f81f3de01045b3362a8514d8966f70bb
    https://github.com/scummvm/scummvm/commit/ea9d0d39f81f3de01045b3362a8514d8966f70bb
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
JANITORIAL: Fix code formatting issues in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 8402efc1fed..36529bc9bf5 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -523,6 +523,13 @@ void Window::loadStartMovieXLibs() {
 	}
 	g_lingo->openXLib("SerialPort", kXObj);
 }
+
+/*******************************************
+ *
+ * Projector Archive
+ *
+ *******************************************/
+
 class ProjectorArchive : public Common::Archive {
 public:
 	ProjectorArchive(Common::String path);
@@ -532,8 +539,9 @@ 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;
+
 private:
-	int Load(Common::SeekableReadStream *stream);
+	bool loadArchive(Common::SeekableReadStream *stream);
 
 	struct Entry {
 		uint64 offset;
@@ -551,7 +559,8 @@ ProjectorArchive::ProjectorArchive(Common::String path)
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(path);
 	if (!stream)
 		error("ProjectorArchive::ProjectorArchive(): Cannot open %s", path.c_str());
-	Load(stream);
+
+	loadArchive(stream);
 	delete stream;
 }
 
@@ -559,35 +568,37 @@ ProjectorArchive::~ProjectorArchive() {
 	_files.clear();
 }
 
-int ProjectorArchive::Load(Common::SeekableReadStream *stream) {
+bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 	bool bigEndian = true, found = false;
 	uint32 off, tag, rifxOffset;
 
-	// Assume the endianness of the file and try to locate the PJXX tags
-	for(int i = 0; i < 2; i++) {
+	// Assume the endianness of the file and try to locate the PJXX tag
+	for (int i = 0; i < 2; i++) {
 		bigEndian = !bigEndian;
 		stream->seek(-4, SEEK_END);
 		off = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 		stream->seek(off);
 		tag = stream->readUint32BE();
 
-		if (((tag & 0xffff0000) == MKTAG('P','J', 0, 0)) || ((tag & 0x0000ffff) == MKTAG(0, 0,'J','P'))) {
+		// Check whether we got a 'PJ' tag while ignoring the version and accounting for endianness
+		if (((tag & 0xffff0000) == MKTAG('P','J', 0, 0)) || ((tag & 0x0000ffff) == MKTAG(0, 0, 'J','P'))) {
 			found = true;
 			break;
 		}
 	}
 
 	if (!found) {
-		warning("ProjectorArchive::Load(): Projector Tag not found");
+		warning("ProjectorArchive::loadArchive(): Projector Tag not found");
 		return true;
 	}
 
 	rifxOffset = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 	stream->seek(rifxOffset);
 	tag = stream->readUint32BE();
+
 	debugC(1, kDebugLoading, "File: %s off: 0x%x, tag: %s rifx: 0x%x", _path.c_str(), off, tag2str(tag), rifxOffset);
 
-	//Try to locate the very next Dict tag
+	// Try to locate the very next Dict tag
 	tag = stream->readUint32BE();
 	found = false;
 	while (!stream->eos()) {
@@ -600,7 +611,7 @@ int ProjectorArchive::Load(Common::SeekableReadStream *stream) {
 
 	// Return if dict tag is not found
 	if (!found) {
-		warning("ProjectorArchive::Load(): Dict Tag not found.");
+		warning("ProjectorArchive::loadArchive(): Dict Tag not found.");
 		return true;
 	}
 
@@ -623,6 +634,7 @@ int ProjectorArchive::Load(Common::SeekableReadStream *stream) {
 	}
 
 	debugC(1, kDebugLoading, "Dict off: 0x%x, Size: 0x%x cnt: %d", dictOff, size, cnt);
+
 	uint32 pt = (cnt * 8) + (64 - offsetDict);
 	Common::StringArray arr(cnt);
 
@@ -630,6 +642,7 @@ int ProjectorArchive::Load(Common::SeekableReadStream *stream) {
 		stream->seek(dictOff + pt, SEEK_SET);
 		uint32 namelen = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 		arr[i] = stream->readString(0, namelen);
+
 		if (i < cnt - 1) {
 			int sub = (namelen % 4) ? (namelen % 4) : 4;
 			pt += 4 + namelen + (4 - sub);
@@ -641,12 +654,16 @@ int ProjectorArchive::Load(Common::SeekableReadStream *stream) {
 	for (uint32 i = 0; i < cnt; i++) {
 		tag = stream->readUint32BE();
 		size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+
 		debugC(1, kDebugLoading, "Entry: %s offset %llX tag %s size %d", arr[i].c_str(), stream->pos() - 8, tag2str(tag), size);
+
 		Entry entry;
+
 		// subtract 8 since we want to include tag and size as well
 		entry.offset = stream->pos() - 8;
 		entry.size = size + 8;
 		_files[arr[i]] = entry;
+
 		stream->seek(size, SEEK_CUR);
 	}
 
@@ -671,6 +688,7 @@ int ProjectorArchive::listMembers(Common::ArchiveMemberList &list) const {
 
 const Common::ArchiveMemberPtr ProjectorArchive::getMember(const Common::Path &path) const {
 	Common::String name = path.toString();
+
 	if (!hasFile(name))
 		return Common::ArchiveMemberPtr();
 
@@ -680,6 +698,7 @@ const Common::ArchiveMemberPtr ProjectorArchive::getMember(const Common::Path &p
 Common::SeekableReadStream *ProjectorArchive::createReadStreamForMember(const Common::Path &path) const {
 	Common::String name = path.toString();
 	FileMap::const_iterator fDesc = _files.find(name);
+
 	if (fDesc == _files.end())
 		return nullptr;
 


Commit: e10f756d6813b38c04ed6045926c1bc37709535e
    https://github.com/scummvm/scummvm/commit/e10f756d6813b38c04ed6045926c1bc37709535e
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Use BufferedStream in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 36529bc9bf5..87c38afedec 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -24,6 +24,7 @@
 #include "common/file.h"
 #include "common/macresman.h"
 #include "common/memstream.h"
+#include "common/bufferedstream.h"
 #include "common/substream.h"
 #include "common/formats/winexe.h"
 #include "graphics/wincursor.h"
@@ -541,6 +542,7 @@ public:
 	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
 
 private:
+	Common::SeekableReadStream *createBufferedReadStream();
 	bool loadArchive(Common::SeekableReadStream *stream);
 
 	struct Entry {
@@ -555,15 +557,25 @@ private:
 ProjectorArchive::ProjectorArchive(Common::String path)
 	: _path(path), _files() {
 
-	// We'll first build our fileMap
-	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(path);
-	if (!stream)
-		error("ProjectorArchive::ProjectorArchive(): Cannot open %s", path.c_str());
+	// Buffer 100K into memory
+	Common::SeekableReadStream *stream = createBufferedReadStream();
 
+	// Build our filemap using the buffered stream
 	loadArchive(stream);
+
 	delete stream;
 }
 
+Common::SeekableReadStream *ProjectorArchive::createBufferedReadStream() {
+	const uint32 READ_BUFFER_SIZE = 1024 * 100;
+
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(_path);
+	if (!stream)
+		error("ProjectorArchive::createBufferedReadStream(): Cannot open %s", _path.c_str());
+
+	return Common::wrapBufferedSeekableReadStream(stream, READ_BUFFER_SIZE, DisposeAfterUse::NO);
+}
+
 ProjectorArchive::~ProjectorArchive() {
 	_files.clear();
 }
@@ -598,14 +610,19 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 
 	debugC(1, kDebugLoading, "File: %s off: 0x%x, tag: %s rifx: 0x%x", _path.c_str(), off, tag2str(tag), rifxOffset);
 
-	// Try to locate the very next Dict tag
+	// Try to locate the very next Dict tag(byte-by-byte)
 	tag = stream->readUint32BE();
 	found = false;
+
+	// This loop has neglible performance impact due to the stream being buffered.
+	// Furthermore, comparing 4 bytes at a time should be pretty fast on mordern systems.
 	while (!stream->eos()) {
 		if (tag == MKTAG('D', 'i', 'c', 't') || tag == MKTAG('t', 'c', 'i', 'D')) {
 			found = true;
 			break;
 		}
+
+		stream->seek(-3, SEEK_CUR);
 		tag = stream->readUint32BE();
 	}
 
@@ -627,6 +644,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 	int8 offsetDict = 0;
 	bool oBigEndian = bigEndian;
 
+	// For 16-bit win projector
 	if (cnt > 0xFFFF) {
 		cnt = SWAP_BYTES_32(cnt);
 		offsetDict = 2;


Commit: 7ee8e6653c904f3c5b05b6a38dcc196de0d86303
    https://github.com/scummvm/scummvm/commit/7ee8e6653c904f3c5b05b6a38dcc196de0d86303
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Return false on failure in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 87c38afedec..fa408c8ae7d 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -601,7 +601,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 
 	if (!found) {
 		warning("ProjectorArchive::loadArchive(): Projector Tag not found");
-		return true;
+		return false;
 	}
 
 	rifxOffset = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
@@ -629,7 +629,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 	// Return if dict tag is not found
 	if (!found) {
 		warning("ProjectorArchive::loadArchive(): Dict Tag not found.");
-		return true;
+		return false;
 	}
 
 	uint32 size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
@@ -685,7 +685,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 		stream->seek(size, SEEK_CUR);
 	}
 
-	return false;
+	return true;
 }
 
 bool ProjectorArchive::hasFile(const Common::Path &path) const {


Commit: 3f49fca324362f67e74a43a431632598969e90d8
    https://github.com/scummvm/scummvm/commit/3f49fca324362f67e74a43a431632598969e90d8
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Check for invalid seeks in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index fa408c8ae7d..25e70c2eb4b 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -635,8 +635,12 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 	uint32 size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 	uint32 dictOff = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 
-	// Jump to the actual dict block and begin parsing
-	stream->seek(dictOff);
+	// Jump to the actual dict block and parse it
+	if (!stream->seek(dictOff)) {
+		warning("ProjectorArchive::loadArchive(): Incorrect dict offset (0x%x)", dictOff);
+		return false;
+	}
+
 	tag = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 	size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 	stream->seek(dictOff + 24);
@@ -657,7 +661,12 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 	Common::StringArray arr(cnt);
 
 	for (uint32 i = 0; i < cnt; i++) {
-		stream->seek(dictOff + pt, SEEK_SET);
+		// if this fails it likely means that the dict was invalid.
+		if (!stream->seek(dictOff + pt, SEEK_SET)) {
+			warning("ProjectorArchive::loadArchive(): Incorrect entry name offset (0x%x)", dictOff + pt);
+			return false;
+		}
+
 		uint32 namelen = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 		arr[i] = stream->readString(0, namelen);
 
@@ -682,7 +691,12 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 		entry.size = size + 8;
 		_files[arr[i]] = entry;
 
-		stream->seek(size, SEEK_CUR);
+		// if this fails it suggests something is either wrong with the dict or the file itself.
+		if (!stream->seek(size, SEEK_CUR)) {
+			warning("ProjectorArchive::loadArchive(): Could not read next block (0x%x) Prev Block(0x%x : %d)",
+			        entry.offset + entry.size, entry.offset, entry.size);
+			return false;
+		}
 	}
 
 	return true;


Commit: 7172b7620ad7752cdec76f5fff2728274b3aae4a
    https://github.com/scummvm/scummvm/commit/7172b7620ad7752cdec76f5fff2728274b3aae4a
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Prefix warnings with BUILDBOT in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 25e70c2eb4b..bb3023aba9e 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -637,7 +637,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 
 	// Jump to the actual dict block and parse it
 	if (!stream->seek(dictOff)) {
-		warning("ProjectorArchive::loadArchive(): Incorrect dict offset (0x%x)", dictOff);
+		warning("BUILDBOT: ProjectorArchive::loadArchive(): Incorrect dict offset (0x%x)", dictOff);
 		return false;
 	}
 


Commit: 58ff07f4a67b4c1c23d6a15e92eac0a79e192ba6
    https://github.com/scummvm/scummvm/commit/58ff07f4a67b4c1c23d6a15e92eac0a79e192ba6
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: ProjectorArchive filemap offset needs to be 32 bit only

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index bb3023aba9e..fdd03cd2342 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -546,7 +546,7 @@ private:
 	bool loadArchive(Common::SeekableReadStream *stream);
 
 	struct Entry {
-		uint64 offset;
+		uint32 offset;
 		uint32 size;
 	};
 	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
@@ -687,7 +687,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 		Entry entry;
 
 		// subtract 8 since we want to include tag and size as well
-		entry.offset = stream->pos() - 8;
+		entry.offset = static_cast<uint32>(stream->pos() - 8);
 		entry.size = size + 8;
 		_files[arr[i]] = entry;
 


Commit: 325594ab0bedd3d8384e1f91b7140dbc9782a6bc
    https://github.com/scummvm/scummvm/commit/325594ab0bedd3d8384e1f91b7140dbc9782a6bc
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Offset to PJXX tags is always in fixed endian

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index fdd03cd2342..1f3d51d47b4 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -581,25 +581,16 @@ ProjectorArchive::~ProjectorArchive() {
 }
 
 bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
-	bool bigEndian = true, found = false;
+	bool bigEndian = false, found = false;
 	uint32 off, tag, rifxOffset;
 
-	// Assume the endianness of the file and try to locate the PJXX tag
-	for (int i = 0; i < 2; i++) {
-		bigEndian = !bigEndian;
-		stream->seek(-4, SEEK_END);
-		off = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
-		stream->seek(off);
-		tag = stream->readUint32BE();
-
-		// Check whether we got a 'PJ' tag while ignoring the version and accounting for endianness
-		if (((tag & 0xffff0000) == MKTAG('P','J', 0, 0)) || ((tag & 0x0000ffff) == MKTAG(0, 0, 'J','P'))) {
-			found = true;
-			break;
-		}
-	}
+	stream->seek(-4, SEEK_END);
+	off = stream->readUint32LE();
+	stream->seek(off);
+	tag = stream->readUint32BE();
 
-	if (!found) {
+	// Check whether we got a 'PJ' tag while ignoring the version and accounting for endianness
+	if (((tag & 0xffff0000) != MKTAG('P','J', 0, 0)) && ((tag & 0x0000ffff) != MKTAG(0, 0, 'J','P'))) {
 		warning("ProjectorArchive::loadArchive(): Projector Tag not found");
 		return false;
 	}


Commit: a15208bded47e800d3f007683664c736c43ba0d7
    https://github.com/scummvm/scummvm/commit/a15208bded47e800d3f007683664c736c43ba0d7
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Fix incorrect dict parsing in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 1f3d51d47b4..e44782b6271 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -595,7 +595,14 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 		return false;
 	}
 
-	rifxOffset = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
+	rifxOffset = stream->readUint32LE();
+
+	// if value is bigger than the stream size this is most likely a endianness issue.
+	if (rifxOffset > stream->size()) {
+		bigEndian = true;
+		rifxOffset = SWAP_BYTES_32(rifxOffset);
+	}
+
 	stream->seek(rifxOffset);
 	tag = stream->readUint32BE();
 
@@ -636,7 +643,9 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 	size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 	stream->seek(dictOff + 24);
 	uint32 cnt = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
-	int8 offsetDict = 0;
+
+	// Correction for when there is only a single element present according to the dict
+	uint8 offsetDict = bigEndian && cnt == 1 ? 2 : 0;
 	bool oBigEndian = bigEndian;
 
 	// For 16-bit win projector
@@ -669,6 +678,9 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 
 	bigEndian = oBigEndian;
 
+	// The first block would start right after the dict.
+	stream->seek(dictOff + size + 8, SEEK_SET);
+
 	for (uint32 i = 0; i < cnt; i++) {
 		tag = stream->readUint32BE();
 		size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();


Commit: 047184a1b5d8254e5ed844b9952c5595341c0c38
    https://github.com/scummvm/scummvm/commit/047184a1b5d8254e5ed844b9952c5595341c0c38
Author: hax0kartik (agarwala.kartik at gmail.com)
Date: 2023-03-13T23:25:55+01:00

Commit Message:
DIRECTOR: Fix alignment issue during seeking in ProjectorArchive

Changed paths:
    engines/director/resource.cpp


diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index e44782b6271..c2803f1ac9d 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -678,13 +678,20 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 
 	bigEndian = oBigEndian;
 
-	// The first block would start right after the dict.
+	// Jump to the first block which should start right after the dict while making sure size is aligned.
+	size += (size % 2);
 	stream->seek(dictOff + size + 8, SEEK_SET);
 
 	for (uint32 i = 0; i < cnt; i++) {
 		tag = stream->readUint32BE();
 		size = bigEndian ? stream->readUint32BE() : stream->readUint32LE();
 
+		// endianness issue, swap size and continue
+		if (size > stream->pos()) {
+			bigEndian = !bigEndian;
+			size = SWAP_BYTES_32(size);
+		}
+
 		debugC(1, kDebugLoading, "Entry: %s offset %llX tag %s size %d", arr[i].c_str(), stream->pos() - 8, tag2str(tag), size);
 
 		Entry entry;
@@ -694,6 +701,9 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 		entry.size = size + 8;
 		_files[arr[i]] = entry;
 
+		// Align size for the next seek.
+		size += (size % 2);
+
 		// if this fails it suggests something is either wrong with the dict or the file itself.
 		if (!stream->seek(size, SEEK_CUR)) {
 			warning("ProjectorArchive::loadArchive(): Could not read next block (0x%x) Prev Block(0x%x : %d)",




More information about the Scummvm-git-logs mailing list