[Scummvm-git-logs] scummvm master -> 63f720a33054b552e18d04c24529a5574eed2428

fracturehill noreply at scummvm.org
Thu Nov 2 09:43:40 UTC 2023


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

Summary:
ce1ac137e1 NANCY: Fix Coverity issues
172b87ebf7 NANCY: Synchronize nancy2 movies with sound
2f7861963e NANCY: Ensure consistent ciftree names for SearchMan
d67fcb5e8b AUDIO: Fix memory leak in AIFF
25c3efb0e2 AUDIO: Fix memory leak in WMA
d3976468b1 BACKENDS: LIBRETRO: Fix memory leak
2f42aade45 NANCY: Fix ciftree export
82cd37ce34 DEVTOOLS: Add nancy2 patches to create_nancy
63f720a330 NANCY: Implement reading patches from nancy.dat


Commit: ce1ac137e14fe23a7ecf3ca2b715a56e1698caba
    https://github.com/scummvm/scummvm/commit/ce1ac137e14fe23a7ecf3ca2b715a56e1698caba
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:21+02:00

Commit Message:
NANCY: Fix Coverity issues

Changed paths:
    engines/nancy/cif.cpp
    engines/nancy/cif.h


diff --git a/engines/nancy/cif.cpp b/engines/nancy/cif.cpp
index 7ef94694e67..93a6d0ed6bf 100644
--- a/engines/nancy/cif.cpp
+++ b/engines/nancy/cif.cpp
@@ -64,7 +64,7 @@ static void syncCifInfo(Common::Serializer &ser, CifInfo &info, bool tree) {
 // Reads the data for ciftree cif files
 static void syncCiftreeInfo(Common::Serializer &ser, CifInfo &info) {
 	uint nameSize = g_nancy->getGameType() <= kGameTypeNancy2 ? 9 : 33;
-	byte name[33];
+	byte name[34];
 	if (ser.isSaving()) {
 		memcpy(name, info.name.c_str(), nameSize);
 		name[nameSize] = 0;
@@ -127,8 +127,8 @@ Common::SeekableReadStream *CifFile::createReadStream() const {
 	if (!success) {
 		warning("Failed to read data for CifFile '%s'", _info.name.c_str());
 		delete[] buf;
-		return nullptr;
 		_stream->clearErr();
+		return nullptr;
 	}
 	
 	return new Common::MemoryReadStream(buf, _info.size, DisposeAfterUse::YES);
@@ -237,8 +237,8 @@ Common::SeekableReadStream *CifTree::createReadStreamForMember(const Common::Pat
 	if (!success) {
 		warning("Failed to read data for '%s' from CifTree '%s'", info.name.c_str(), _name.c_str());
 		delete[] buf;
-		return nullptr;
 		_stream->clearErr();
+		return nullptr;
 	}
 	
 	return new Common::MemoryReadStream(buf, info.size, DisposeAfterUse::YES);
diff --git a/engines/nancy/cif.h b/engines/nancy/cif.h
index 5140074304c..00f2260a55d 100644
--- a/engines/nancy/cif.h
+++ b/engines/nancy/cif.h
@@ -50,9 +50,9 @@ struct CifInfo {
 	Common::String name;
 	ResType type = kResTypeEmpty; // ResType
 	ResCompression comp = kResCompressionNone; // ResCompression
-	uint16 width, pitch, height = 0;
+	uint16 width = 0, pitch = 0, height = 0;
 	byte depth = 0; // Bit depth
-	uint32 compressedSize, size = 0;
+	uint32 compressedSize = 0, size = 0;
 	Common::Rect src, dest; // Used when drawing conversation cels
 
 	uint32 dataOffset;


Commit: 172b87ebf7dc7020bd3d08b1999a60cd158b0b9c
    https://github.com/scummvm/scummvm/commit/172b87ebf7dc7020bd3d08b1999a60cd158b0b9c
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:21+02:00

Commit Message:
NANCY: Synchronize nancy2 movies with sound

It seems earlier games were aware of the engine bug that
slows down all videos, and their movies were correctly synced
in the original engine. This commit duplicates that bug,
but only in the cases where a movie has an embedded sound
(e.g. the nancy2 cutscenes)

Changed paths:
    engines/nancy/action/actionmanager.cpp
    engines/nancy/action/secondarymovie.cpp


diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index e5bb8f2d253..7cfdb146180 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -653,7 +653,7 @@ void ActionManager::synchronizeMovieWithSound() {
 		}
 	}
 
-	if (movie && sound) {
+	if (movie && sound && movie->_sound.name != "NO SOUND") {
 		// A movie and a sound both got activated this frame, check if their scene changes match
 		if (	movie->_videoSceneChange == PlaySecondaryMovie::kMovieSceneChange &&
 				movie->_sceneChange.sceneID == sound->_sceneChange.sceneID &&
diff --git a/engines/nancy/action/secondarymovie.cpp b/engines/nancy/action/secondarymovie.cpp
index 67e97344110..b2223db989e 100644
--- a/engines/nancy/action/secondarymovie.cpp
+++ b/engines/nancy/action/secondarymovie.cpp
@@ -137,6 +137,13 @@ void PlaySecondaryMovie::execute() {
 		g_nancy->_sound->loadSound(_sound);
 		g_nancy->_sound->playSound(_sound);
 
+		if (_sound.name != "NO SOUND" && g_nancy->getGameType() <= kGameTypeNancy5) {
+			// Sync audio and video. This is mostly relevant for some nancy2 scenes, as the
+			// devs stopped using the built-in movie sound around nancy4. The 12 ms
+			// difference is roughly how long it takes for a single execution of the main game loop
+			((AVFDecoder *)_decoder)->addFrameTime(12);
+		}
+
 		if (_playerCursorAllowed == kNoPlayerCursorAllowed) {
 			g_nancy->setMouseEnabled(false);
 		}


Commit: 2f7861963e0aafbf566412304cd57d098b5fcc07
    https://github.com/scummvm/scummvm/commit/2f7861963e0aafbf566412304cd57d098b5fcc07
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:21+02:00

Commit Message:
NANCY: Ensure consistent ciftree names for SearchMan

It appears SearchMan Archive storage is case-sensitive,
which can cause errors when loading files. This commit
makes sure all ciftrees are stored and looked up as
_tree_TREENAME in SearchMan to avoid such errors.

Changed paths:
    engines/nancy/resource.cpp


diff --git a/engines/nancy/resource.cpp b/engines/nancy/resource.cpp
index 7c52aec4e2d..0dd702c1ad3 100644
--- a/engines/nancy/resource.cpp
+++ b/engines/nancy/resource.cpp
@@ -80,12 +80,16 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 		// First, get the correct tree
 		const CifTree *tree = nullptr;
 		if (treeName.size()) {
-			tree = (const CifTree *)SearchMan.getArchive(treePrefix + treeName);
+			Common::String upper = treeName;
+			upper.toUppercase();
+			tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 		} else {
 			for (uint i = 0; i < _cifTreeNames.size(); ++i) {
 				// No provided tree name, check inside every loaded tree
-				if (SearchMan.getArchive(treePrefix + _cifTreeNames[i])->hasFile(name)) {
-					tree = (const CifTree *)SearchMan.getArchive(treePrefix + _cifTreeNames[i]);
+				Common::String upper = _cifTreeNames[i];
+				upper.toUppercase();
+				if (SearchMan.getArchive(treePrefix + upper)->hasFile(name)) {
+					tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 					break;
 				}
 			}
@@ -168,8 +172,12 @@ bool ResourceManager::readCifTree(const Common::String &name, const Common::Stri
 		return false;
 	}
 
-	// Add a prefix to avoid clashes with the ciftree folder present in some games
-	SearchMan.add(treePrefix + name, tree, priority, true);
+	// Add a prefix to avoid clashes with the ciftree folder present in some games.
+	// Also, set the name itself to uppercase since SearchMan is case-sensitive.
+	// Final name to look up is _tree_TREENAME
+	Common::String upper = name;
+	upper.toUppercase();
+	SearchMan.add(treePrefix + upper, tree, priority, true);
 	_cifTreeNames.push_back(name);
 	return true;
 }
@@ -177,12 +185,16 @@ bool ResourceManager::readCifTree(const Common::String &name, const Common::Stri
 Common::String ResourceManager::getCifDescription(const Common::String &treeName, const Common::String &name) const {
 	const CifTree *tree = nullptr;
 	if (treeName.size()) {
-		tree = (const CifTree *)SearchMan.getArchive(treePrefix + treeName);
+		Common::String upper = treeName;
+		upper.toUppercase();
+		tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 	} else {
 		for (uint i = 0; i < _cifTreeNames.size(); ++i) {
 			// No provided tree name, check inside every loaded tree
-			if (SearchMan.getArchive(treePrefix + _cifTreeNames[i])->hasFile(name)) {
-				tree = (const CifTree *)SearchMan.getArchive(treePrefix + _cifTreeNames[i]);
+			Common::String upper = _cifTreeNames[i];
+			upper.toUppercase();
+			if (SearchMan.getArchive(treePrefix + upper)->hasFile(name)) {
+				tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 				break;
 			}
 		}
@@ -210,7 +222,9 @@ Common::String ResourceManager::getCifDescription(const Common::String &treeName
 
 void ResourceManager::list(const Common::String &treeName, Common::StringArray &outList, CifInfo::ResType type) const {
 	if (treeName.size()) {
-		const CifTree *tree = (const CifTree *)SearchMan.getArchive(treePrefix + treeName);
+		Common::String upper = treeName;
+		upper.toUppercase();
+		const CifTree *tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 		if (!tree) {
 			return;
 		}
@@ -222,7 +236,9 @@ void ResourceManager::list(const Common::String &treeName, Common::StringArray &
 	} else {
 		for (uint i = 0; i < _cifTreeNames.size(); ++i) {
 			// No provided tree name, check inside every loaded tree
-			const CifTree *tree = (const CifTree *)SearchMan.getArchive(treePrefix + _cifTreeNames[i]);
+			Common::String upper = _cifTreeNames[i];
+			upper.toUppercase();
+			const CifTree *tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 			for (auto &it : tree->_fileMap) {
 				if (type == CifInfo::kResTypeAny || it._value.type == type) {
 					outList.push_back(it._key);
@@ -259,8 +275,10 @@ bool ResourceManager::exportCif(const Common::String &treeName, const Common::St
 			// Look inside ciftrees
 			const CifTree *tree = nullptr;
 			for (uint j = 0; j < _cifTreeNames.size(); ++j) {
-				if (SearchMan.getArchive(treePrefix + _cifTreeNames[j])->hasFile(name)) {
-					tree = (const CifTree *)SearchMan.getArchive(treePrefix + _cifTreeNames[j]);
+				Common::String upper = _cifTreeNames[j];
+				upper.toUppercase();
+				if (SearchMan.getArchive(treePrefix + upper)->hasFile(name)) {
+					tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 					break;
 				}
 			}
@@ -344,8 +362,10 @@ bool ResourceManager::exportCifTree(const Common::String &treeName, const Common
 				// Look inside ciftrees
 				const CifTree *tree = nullptr;
 				for (uint j = 0; j < _cifTreeNames.size(); ++j) {
-					if (SearchMan.getArchive(treePrefix + _cifTreeNames[j])->hasFile(names[i])) {
-						tree = (const CifTree *)SearchMan.getArchive(treePrefix + _cifTreeNames[j]);
+					Common::String upper = _cifTreeNames[j];
+					upper.toUppercase();
+					if (SearchMan.getArchive(treePrefix + upper)->hasFile(names[i])) {
+						tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 						break;
 					}
 				}


Commit: d67fcb5e8b7a3a5f8b0474ef123081aae3864081
    https://github.com/scummvm/scummvm/commit/d67fcb5e8b7a3a5f8b0474ef123081aae3864081
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:21+02:00

Commit Message:
AUDIO: Fix memory leak in AIFF

Coverity CID 1490097

Changed paths:
    audio/decoders/aiff.cpp


diff --git a/audio/decoders/aiff.cpp b/audio/decoders/aiff.cpp
index fb278339eea..fe92d6acf99 100644
--- a/audio/decoders/aiff.cpp
+++ b/audio/decoders/aiff.cpp
@@ -149,6 +149,7 @@ AIFFHeader *AIFFHeader::readAIFFHeader(Common::SeekableReadStream *stream, Dispo
 				delete stream;
 
 			delete aiffHeader->_dataStream;
+			delete aiffHeader;
 			return nullptr;
 		default:
 			debug(1, "Skipping AIFF '%s' chunk", tag2str(tag));


Commit: 25c3efb0e2c3844641aa6f0e2b2512b72ba0bb3f
    https://github.com/scummvm/scummvm/commit/25c3efb0e2c3844641aa6f0e2b2512b72ba0bb3f
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:22+02:00

Commit Message:
AUDIO: Fix memory leak in WMA

Coverity CID 1338118

Changed paths:
    audio/decoders/wma.cpp


diff --git a/audio/decoders/wma.cpp b/audio/decoders/wma.cpp
index bc76fdfd57c..59c166c5453 100644
--- a/audio/decoders/wma.cpp
+++ b/audio/decoders/wma.cpp
@@ -635,8 +635,10 @@ Common::SeekableReadStream *WMACodec::decodeSuperFrame(Common::SeekableReadStrea
 
 		// Decode the frames
 		for (int i = 0; i < newFrameCount; i++, _curFrame++)
-			if (!decodeFrame(bits, outputData))
+			if (!decodeFrame(bits, outputData)) {
+				delete[] outputData;
 				return nullptr;
+			}
 
 		// Check if we've got new overhang data
 		int remainingBits = bits.size() - bits.pos();


Commit: d3976468b100133d487148716a8b08014d485d72
    https://github.com/scummvm/scummvm/commit/d3976468b100133d487148716a8b08014d485d72
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:22+02:00

Commit Message:
BACKENDS: LIBRETRO: Fix memory leak

Coverity CID 1502443

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index e8b43906542..65a8f9a3854 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -552,6 +552,7 @@ bool LibRetroPipeline::loadPasses(Common::SearchSet &archSet) {
 				 ARRAYSIZE(vertexSources), vertexSources,
 				 ARRAYSIZE(fragmentSources), fragmentSources,
 				 g_libretroShaderAttributes)) {
+			delete shader;
 			return false;
 		}
 


Commit: 2f42aade454cefa3cbc06d381a3200012c4832bc
    https://github.com/scummvm/scummvm/commit/2f42aade454cefa3cbc06d381a3200012c4832bc
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:22+02:00

Commit Message:
NANCY: Fix ciftree export

Fixed the data offsets, which were previously really wrong

Changed paths:
    engines/nancy/resource.cpp


diff --git a/engines/nancy/resource.cpp b/engines/nancy/resource.cpp
index 0dd702c1ad3..8e6f0f9b212 100644
--- a/engines/nancy/resource.cpp
+++ b/engines/nancy/resource.cpp
@@ -389,16 +389,19 @@ bool ResourceManager::exportCifTree(const Common::String &treeName, const Common
 				}
 			}
 		}
-		
-		info.dataOffset = headerSize + file._fileMap.size() * infoSize; // Initial offset after header/infos
-		for (uint j = 0; j < resStreams.size(); ++j) {
-			info.dataOffset += resStreams[j]->size(); // Final offset, following raw data of previous files
-		}
 
 		resStreams.push_back(stream);
 		file._writeFileMap.push_back(info);
 	}
 
+	uint16 dataOffset = headerSize + file._writeFileMap.size() * infoSize; // Initial offset after header/infos
+	for (uint i = 0; i < file._writeFileMap.size(); ++i) {
+		file._writeFileMap[i].dataOffset = dataOffset;
+		for (uint j = 0; j < i; ++j) {
+			file._writeFileMap[i].dataOffset += resStreams[j]->size(); // Final offset, following raw data of previous files
+		}
+	}
+
 	Common::DumpFile dump;
 	dump.open(treeName + ".dat");
 


Commit: 82cd37ce341effa8f3276077c0978e5e9edac628
    https://github.com/scummvm/scummvm/commit/82cd37ce341effa8f3276077c0978e5e9edac628
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:22+02:00

Commit Message:
DEVTOOLS: Add nancy2 patches to create_nancy

Added facilities for embedding game patches into nancy.dat
Added two game patches for nancy2:
- one of the original patches, as distributed by the original
devs. Specifically, only the patch to extend the end-game
timer; there exists another patch that fixes an error when
double-clicking a specific cupboard, but that's caused by
an engine bug that does not exist in ScummVM.
- a new, custom patch that fixes a nasty softlock caused
by incorrect dependencies in a certain scene.

Changed paths:
  A devtools/create_nancy/files/nancy2_patchtree.dat
    devtools/create_nancy/create_nancy.cpp
    devtools/create_nancy/file.cpp
    devtools/create_nancy/file.h
    devtools/create_nancy/nancy2_data.h
    devtools/create_nancy/types.h


diff --git a/devtools/create_nancy/create_nancy.cpp b/devtools/create_nancy/create_nancy.cpp
index 9735ac6d6e0..3f046e3d6a1 100644
--- a/devtools/create_nancy/create_nancy.cpp
+++ b/devtools/create_nancy/create_nancy.cpp
@@ -155,6 +155,27 @@ void writeEventFlagNames(File &output, const Common::Array<const char *> &eventF
 	writeToFile(output, eventFlagNames);
 }
 
+void writePatchFile(File &output, const char *filename) {
+	File file;
+	if (!file.open(filename, AccessMode::kFileReadMode)) {
+		return;
+	}
+	
+	byte *buf = new byte[file.size()];
+	file.read(buf, file.size());
+
+	output.writeUint32(MKTAG('P', 'A', 'T', 'C'));
+	output.write(buf, file.size());
+
+	file.close();
+	delete[] buf;
+}
+
+void writePatchAssociations(File &output, const Common::Array<PatchAssociation> &patchAssociations) {
+	output.writeUint32(MKTAG('P', 'A', 'S', 'S'));
+	writeToFile(output, patchAssociations);
+}
+
 int main(int argc, char *argv[]) {
 	File output;
 	if (!output.open("nancy.dat", kFileWriteMode)) {
@@ -209,6 +230,8 @@ int main(int argc, char *argv[]) {
 	WRAPWITHOFFSET(writeRingingTexts(output, _nancy2TelephoneRinging))
 	WRAPWITHOFFSET(writeEmptySaveTexts(output, _nancy2EmptySaveStrings))
 	WRAPWITHOFFSET(writeEventFlagNames(output, _nancy2EventFlagNames))
+	WRAPWITHOFFSET(writePatchFile(output, "files/nancy2_patchtree.dat"))
+	WRAPWITHOFFSET(writePatchAssociations(output, nancy2PatchAssociations))
 	
 	// Nancy Drew: Message in a Haunted Mansion data
 	gameOffsets.push_back(output.pos());
diff --git a/devtools/create_nancy/file.cpp b/devtools/create_nancy/file.cpp
index bb22a74f59d..3842a31e2ed 100644
--- a/devtools/create_nancy/file.cpp
+++ b/devtools/create_nancy/file.cpp
@@ -217,6 +217,12 @@ void writeToFile(File &file, const Hint &obj) {
 	writeToFile(file, obj.conditions);
 }
 
+template<>
+void writeToFile(File &file, const PatchAssociation &obj) {
+	file.writeString(obj.confManID);
+	writeToFile(file, obj.fileIDs);
+}
+
 void writeMultilangArray(File &file, const Common::Array<Common::Array<const char *>> &array) {
 	Common::Array<uint32> offsets;
 	uint32 offsetsOffset = file.pos();
diff --git a/devtools/create_nancy/file.h b/devtools/create_nancy/file.h
index 6b16f7b702c..87394514509 100644
--- a/devtools/create_nancy/file.h
+++ b/devtools/create_nancy/file.h
@@ -94,6 +94,8 @@ template<>
 void writeToFile(File &file, const Goodbye &obj);
 template<>
 void writeToFile(File &file, const Hint &obj);
+template<>
+void writeToFile(File &file, const PatchAssociation &obj);
 
 void writeMultilangArray(File &file, const Common::Array<Common::Array<const char *>> &array);
 
diff --git a/devtools/create_nancy/files/nancy2_patchtree.dat b/devtools/create_nancy/files/nancy2_patchtree.dat
new file mode 100644
index 00000000000..5a1ffa064a4
Binary files /dev/null and b/devtools/create_nancy/files/nancy2_patchtree.dat differ
diff --git a/devtools/create_nancy/nancy2_data.h b/devtools/create_nancy/nancy2_data.h
index ac360011e7c..721e7e5f03b 100644
--- a/devtools/create_nancy/nancy2_data.h
+++ b/devtools/create_nancy/nancy2_data.h
@@ -617,4 +617,14 @@ const Common::Array<const char *> _nancy2EventFlagNames = {
 	"empty"
 };
 
+// Patch notes:
+// - The patch that extends the final timer was originally distributed by HeR.
+// - The softlock fix is custom, and works by adding a second inventory dependency
+// to the last two ARs in scene S1160. This allows the player to re-enter the
+// prop room when they've collected the door knob, but not the wire clippers.
+const Common::Array<PatchAssociation> nancy2PatchAssociations {
+	{ "softlocks_fix", { "S1160" } },
+	{ "final_timer", { "S1563", "S1564", "S1565" } }
+};
+
 #endif // NANCY2DATA
diff --git a/devtools/create_nancy/types.h b/devtools/create_nancy/types.h
index 7f87451531c..2b1ff7319c1 100644
--- a/devtools/create_nancy/types.h
+++ b/devtools/create_nancy/types.h
@@ -90,4 +90,9 @@ struct SoundChannelInfo {
 	Common::Array<byte> sfxChannels; // 2
 };
 
+struct PatchAssociation {
+	const char *confManID;
+	Common::Array<const char *> fileIDs;
+};
+
 #endif // CREATE_NANCY_TYPES_H


Commit: 63f720a33054b552e18d04c24529a5574eed2428
    https://github.com/scummvm/scummvm/commit/63f720a33054b552e18d04c24529a5574eed2428
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-11-02T11:41:22+02:00

Commit Message:
NANCY: Implement reading patches from nancy.dat

Added facilities for reading patch files embedded within
nancy.dat. The patches are distributed as a single ciftree,
which is loaded (almost) normally into SearchMan. However,
patches can also be enabled/disabled at will via specific
ConfMan entries, whose names are also embedded within
nancy.dat, and read at runtime.

Changed paths:
    engines/nancy/cif.cpp
    engines/nancy/cif.h
    engines/nancy/commontypes.cpp
    engines/nancy/nancy.cpp
    engines/nancy/resource.cpp
    engines/nancy/resource.h


diff --git a/engines/nancy/cif.cpp b/engines/nancy/cif.cpp
index 93a6d0ed6bf..712aeee8cc9 100644
--- a/engines/nancy/cif.cpp
+++ b/engines/nancy/cif.cpp
@@ -27,6 +27,7 @@
 #include "common/memstream.h"
 #include "common/substream.h"
 #include "common/serializer.h"
+#include "common/config-manager.h"
 
 namespace Nancy {
 
@@ -327,4 +328,21 @@ bool CifTree::sync(Common::Serializer &ser) {
 	return true;
 }
 
+bool PatchTree::hasFile(const Common::Path &path) const {
+	if (CifTree::hasFile(path)) {
+		for (auto &assoc : _associations) {
+			for (const Common::String &s : assoc._value) {
+				if (s == path.toString()) {
+					return ConfMan.getBool(assoc._key, ConfMan.getActiveDomainName());
+				}
+			}
+		}
+
+		// Files without an associated ConfMan ID are always marked as present
+		return true;
+	}
+
+	return false;
+}
+
 } // End of namespace Nancy
diff --git a/engines/nancy/cif.h b/engines/nancy/cif.h
index 00f2260a55d..b634bd4aad8 100644
--- a/engines/nancy/cif.h
+++ b/engines/nancy/cif.h
@@ -79,10 +79,11 @@ private:
 
 // Container type comprising of multiple CIF files. Contrary to its name it contains no tree structure.
 class CifTree : public Common::Archive {
+protected:
 friend class ResourceManager;
 	CifTree() : _stream(nullptr) {}
 	CifTree(Common::SeekableReadStream *stream, const Common::String &name);
-	~CifTree();
+	virtual ~CifTree();
 
 public:
 	// Used for extracting additional image data for conversation cels (nancy2 and up)
@@ -109,6 +110,16 @@ private:
 	Common::Array<CifInfo> _writeFileMap;
 };
 
+// Ciftree that only provides a file if a certain ConfMan flag is true. Used for handling game patches
+class PatchTree : public CifTree {
+public:
+	PatchTree(Common::SeekableReadStream *stream, const Common::String &name) : CifTree(stream, name) {}
+	virtual ~PatchTree() {}
+
+	bool hasFile(const Common::Path &path) const override;
+
+	Common::HashMap<Common::String, Common::Array<Common::String>> _associations;
+};
 
 } // End of namespace Nancy
 
diff --git a/engines/nancy/commontypes.cpp b/engines/nancy/commontypes.cpp
index ed1703c5bf3..f10a8518a19 100644
--- a/engines/nancy/commontypes.cpp
+++ b/engines/nancy/commontypes.cpp
@@ -22,9 +22,12 @@
 #include "engines/nancy/commontypes.h"
 #include "engines/nancy/util.h"
 #include "engines/nancy/nancy.h"
-
+#include "engines/nancy/cif.h"
+#include "engines/nancy/resource.h"
 #include "engines/nancy/state/scene.h"
 
+#include "common/memstream.h"
+
 namespace Nancy {
 
 void SceneChangeDescription::readData(Common::SeekableReadStream &stream, bool longFormat) {
@@ -350,6 +353,12 @@ void StaticData::readData(Common::SeekableReadStream &stream, Common::Language l
 	uint16 num = 0;
 	int languageID = -1;
 
+	// Used for patch file reading
+	byte *patchBuf = nullptr;
+	uint32 patchBufSize = 0;
+	Common::Array<Common::String> confManIDs;
+	Common::Array<Common::Array<Common::String>> fileIDs;
+
 	while (stream.pos() < endPos) {
 		uint32 nextSectionOffset = stream.readUint32LE();
 
@@ -531,33 +540,45 @@ void StaticData::readData(Common::SeekableReadStream &stream, Common::Language l
 				eventFlagNames[i] = stream.readString();
 			}
 
+			break;
+		case MKTAG('P', 'A', 'T', 'C') :
+			// Patch file
+			patchBufSize = nextSectionOffset - stream.pos();
+			patchBuf = new byte[patchBufSize];
+			stream.read(patchBuf, patchBufSize);
+			break;
+		case MKTAG('P', 'A', 'S', 'S') :
+			// Patch file <-> ConfMan entries associations
+			num = stream.readUint16LE();
+			confManIDs.resize(num);
+			fileIDs.resize(num);
+			for (uint i = 0; i < num; ++i) {
+				confManIDs[i] = stream.readString();
+
+				uint16 num2 = stream.readUint16LE();
+				fileIDs[i].resize(num2);
+				for (uint j = 0; j < num2; ++j) {
+					fileIDs[i][j] = stream.readString();
+				}
+			}
+
 			break;
 		default:
 			stream.seek(nextSectionOffset);
 		}
 	}
-	
-
-	
 
-	// Read the strings logic
-	
+	if (patchBuf) {
+		// Load the patch tree into the ResourceManager
+		Common::MemoryReadStream *patchStream = new Common::MemoryReadStream(patchBuf, patchBufSize, DisposeAfterUse::YES);
+		PatchTree *tree = g_nancy->_resource->readPatchTree(patchStream, "patchtree", 2);
+		assert(tree);
 
-	
-
-	
-
-	// Read the in-game strings, making sure to pick the correct language
-
-
-	
-
-	
-
-	
-
-	// Read debug strings
-	
+		// Write the ConfMan associations
+		for (uint i = 0; i < confManIDs.size(); ++i) {
+			tree->_associations.setVal(confManIDs[i], fileIDs[i]);
+		}
+	}
 }
 
 } // End of namespace Nancy
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 38ed7698ddd..e10a394cff8 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -392,8 +392,8 @@ void NancyEngine::bootGameEngine() {
 	}
 
 	_resource = new ResourceManager();
-	_resource->readCifTree("ciftree", "dat", 2);
-	_resource->readCifTree("promotree", "dat", 2);
+	_resource->readCifTree("ciftree", "dat", 1);
+	_resource->readCifTree("promotree", "dat", 1);
 
 	// Read nancy.dat
 	readDatFile();
diff --git a/engines/nancy/resource.cpp b/engines/nancy/resource.cpp
index 8e6f0f9b212..90b026706af 100644
--- a/engines/nancy/resource.cpp
+++ b/engines/nancy/resource.cpp
@@ -182,6 +182,26 @@ bool ResourceManager::readCifTree(const Common::String &name, const Common::Stri
 	return true;
 }
 
+PatchTree *ResourceManager::readPatchTree(Common::SeekableReadStream *stream, const Common::String &name, int priority) {
+	if (!stream) {
+		return nullptr;
+	}
+
+	PatchTree *tree = new PatchTree(stream, name);
+	Common::Serializer ser(stream, nullptr);
+
+	if (!tree->sync(ser)) {
+		delete tree;
+		return nullptr;
+	}
+
+	Common::String upper = name;
+	upper.toUppercase();
+	SearchMan.add(treePrefix + upper, tree, priority, true);
+	_cifTreeNames.push_back(name);
+	return tree;
+}
+
 Common::String ResourceManager::getCifDescription(const Common::String &treeName, const Common::String &name) const {
 	const CifTree *tree = nullptr;
 	if (treeName.size()) {
diff --git a/engines/nancy/resource.h b/engines/nancy/resource.h
index 671d9882c21..459dd981677 100644
--- a/engines/nancy/resource.h
+++ b/engines/nancy/resource.h
@@ -50,6 +50,7 @@ public:
 
 	// Load a new ciftree
 	bool readCifTree(const Common::String &name, const Common::String &ext, int priority);
+	PatchTree *readPatchTree(Common::SeekableReadStream *stream, const Common::String &name, int priority);
 
 private:
 	// Debug functions




More information about the Scummvm-git-logs mailing list