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

bluegr noreply at scummvm.org
Thu Aug 27 12:08:55 UTC 2026


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

Summary:
fbe6a8f465 NANCY: Hide the cursor glow when the MouseLightPuzzle AR is hidden
ffdea87367 NANCY: Close CIF streams after reading data


Commit: fbe6a8f4650e3253551fb0997a202e77b60e6707
    https://github.com/scummvm/scummvm/commit/fbe6a8f4650e3253551fb0997a202e77b60e6707
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-27T15:08:35+03:00

Commit Message:
NANCY: Hide the cursor glow when the MouseLightPuzzle AR is hidden

Also, fix the Z-order of the mouse cursor glow

Fix #16936

Changed paths:
    engines/nancy/action/puzzle/mouselightpuzzle.cpp
    engines/nancy/action/puzzle/mouselightpuzzle.h


diff --git a/engines/nancy/action/puzzle/mouselightpuzzle.cpp b/engines/nancy/action/puzzle/mouselightpuzzle.cpp
index 21457f0a6a7..8b15e41853d 100644
--- a/engines/nancy/action/puzzle/mouselightpuzzle.cpp
+++ b/engines/nancy/action/puzzle/mouselightpuzzle.cpp
@@ -65,6 +65,15 @@ void MouseLightPuzzle::init() {
 	}
 }
 
+void MouseLightPuzzle::updateGraphics() {
+	// The light only exists while the player holds the light source. The record stops
+	// receiving input as soon as its cursor dependency stops being satisfied, so hide
+	// it instead of leaving the last drawn circle on screen.
+	if (_state == kRun && isVisible() != _isActive) {
+		setVisible(_isActive);
+	}
+}
+
 void MouseLightPuzzle::execute() {
 	if (_state == kBegin) {
 		init();
diff --git a/engines/nancy/action/puzzle/mouselightpuzzle.h b/engines/nancy/action/puzzle/mouselightpuzzle.h
index d8960f52941..b91d0370cae 100644
--- a/engines/nancy/action/puzzle/mouselightpuzzle.h
+++ b/engines/nancy/action/puzzle/mouselightpuzzle.h
@@ -35,10 +35,11 @@ namespace Action {
 // TODO: Add noise to the circle mask; there are artifacts at low brightness
 class MouseLightPuzzle : public RenderActionRecord {
 public:
-	MouseLightPuzzle() : RenderActionRecord(7) {}
+	MouseLightPuzzle() : RenderActionRecord(10) {}
 	virtual ~MouseLightPuzzle() {}
 
 	void init() override;
+	void updateGraphics() override;
 
 	void readData(Common::SeekableReadStream &stream) override;
 	void execute() override;


Commit: ffdea87367105ecfcbd7722a3804cfa2cded523d
    https://github.com/scummvm/scummvm/commit/ffdea87367105ecfcbd7722a3804cfa2cded523d
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-27T15:08:36+03:00

Commit Message:
NANCY: Close CIF streams after reading data

Avoids keeping a lot of file handles open, which is a problem in
platforms that support only a limited number of concurrent open file
handles, such as the PSP, which supports up to 8.

Fix #16947

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


diff --git a/engines/nancy/cif.cpp b/engines/nancy/cif.cpp
index 76c0aa48e66..1fe36d1eb64 100644
--- a/engines/nancy/cif.cpp
+++ b/engines/nancy/cif.cpp
@@ -24,6 +24,7 @@
 #include "engines/nancy/util.h"
 #include "engines/nancy/nancy.h"
 
+#include "common/fs.h"
 #include "common/memstream.h"
 #include "common/substream.h"
 #include "common/serializer.h"
@@ -204,13 +205,28 @@ bool CifFile::sync(Common::Serializer &ser) {
 }
 
 CifTree::CifTree(Common::SeekableReadStream *stream, const Common::Path &name) :
-		_stream(stream),
-		_name(name) {}
+		_name(name),
+		_stream(stream) {}
+
+CifTree::CifTree(const Common::ArchiveMemberPtr &member, const Common::Path &name) :
+		_name(name),
+		_stream(nullptr),
+		_member(member) {}
 
 CifTree::~CifTree() {
 	delete _stream;
 }
 
+Common::SeekableReadStream *CifTree::openStream() const {
+	return _member ? _member->createReadStream() : _stream;
+}
+
+void CifTree::closeStream(Common::SeekableReadStream *stream) const {
+	if (_member) {
+		delete stream;
+	}
+}
+
 const CifInfo &CifTree::getCifInfo(const Common::Path &name) const {
 	return _fileMap[name];
 }
@@ -241,22 +257,28 @@ Common::SeekableReadStream *CifTree::createReadStreamForMember(const Common::Pat
 	}
 
 	const CifInfo &info = _fileMap[path];
+	Common::SeekableReadStream *stream = openStream();
+	if (!stream) {
+		warning("Failed to open CifTree '%s'", _name.toString().c_str());
+		return nullptr;
+	}
+
 	byte *buf = (byte *)malloc(info.size);
 
 	bool success = true;
 
 	if (info.comp == CifInfo::kResCompression) {
 		// Decompress the data into the buffer
-		if (_stream->seek(info.dataOffset)) {
+		if (stream->seek(info.dataOffset)) {
 			Common::MemoryWriteStream write(buf, info.size);
-			Common::SeekableSubReadStream read(_stream, info.dataOffset, info.dataOffset + info.compressedSize);
+			Common::SeekableSubReadStream read(stream, info.dataOffset, info.dataOffset + info.compressedSize);
 			Decompressor dec;
 			success = dec.decompress(read, write);
 		} else {
 			success = false;
 		}
 	} else {
-		if (!_stream->seek(info.dataOffset) || _stream->read(buf, info.size) < info.size) {
+		if (!stream->seek(info.dataOffset) || stream->read(buf, info.size) < info.size) {
 			success = false;
 		}
 	}
@@ -265,10 +287,12 @@ Common::SeekableReadStream *CifTree::createReadStreamForMember(const Common::Pat
 		warning("Failed to read data for '%s' from CifTree '%s'", info.name.toString().c_str(), _name.toString().c_str());
 		free(buf);
 		buf = nullptr;
-		_stream->clearErr();
+		stream->clearErr();
+		closeStream(stream);
 		return nullptr;
 	}
 
+	closeStream(stream);
 	return new Common::MemoryReadStream(buf, info.size, DisposeAfterUse::YES);
 }
 
@@ -278,13 +302,20 @@ Common::SeekableReadStream *CifTree::createReadStreamRaw(const Common::Path &pat
 	}
 
 	const CifInfo &info = _fileMap[path];
+	Common::SeekableReadStream *stream = openStream();
+	if (!stream) {
+		warning("Failed to open CifTree '%s'", _name.toString().c_str());
+		return nullptr;
+	}
+
 	uint32 size = (info.comp == CifInfo::kResCompression ? info.compressedSize : info.size);
 	byte *buf = new byte[size];
 
-	if (!_stream->seek(info.dataOffset) || _stream->read(buf, size) < size) {
+	if (!stream->seek(info.dataOffset) || stream->read(buf, size) < size) {
 		warning("Failed to read data for '%s' from CifTree '%s'", info.name.toString().c_str(), _name.toString().c_str());
 	}
 
+	closeStream(stream);
 	return new Common::MemoryReadStream(buf, size, DisposeAfterUse::YES);
 }
 
@@ -292,16 +323,36 @@ CifTree *CifTree::makeCifTreeArchive(const Common::String &name, const Common::S
 	Common::Path path(name);
 	path.appendInPlace('.' + ext);
 
-	auto *stream = SearchMan.createReadStreamForMember(path);
+	Common::Archive *container = nullptr;
+	Common::ArchiveMemberPtr member = SearchMan.getMember(path, &container);
 
-	if (!stream) {
+	if (!member) {
 		return nullptr;
 	}
 
-	CifTree *ret = new CifTree(stream, path);
-	Common::Serializer ser(stream, nullptr);
+	CifTree *ret = nullptr;
+	if (dynamic_cast<Common::FSDirectory *>(container)) {
+		ret = new CifTree(member, path);
+	} else {
+		Common::SeekableReadStream *stream = member->createReadStream();
+		if (!stream) {
+			return nullptr;
+		}
+
+		ret = new CifTree(stream, path);
+	}
+
+	Common::SeekableReadStream *headerStream = ret->openStream();
+	if (!headerStream) {
+		delete ret;
+		return nullptr;
+	}
+
+	Common::Serializer ser(headerStream, nullptr);
+	bool synced = ret->sync(ser);
+	ret->closeStream(headerStream);
 
-	if (!ret->sync(ser)) {
+	if (!synced) {
 		delete ret;
 		return nullptr;
 	}
diff --git a/engines/nancy/cif.h b/engines/nancy/cif.h
index 8a30df2036f..bbbc8c7e03f 100644
--- a/engines/nancy/cif.h
+++ b/engines/nancy/cif.h
@@ -81,6 +81,7 @@ class CifTree : public Common::Archive {
 public:
 	CifTree() : _stream(nullptr) {}
 	CifTree(Common::SeekableReadStream *stream, const Common::Path &name);
+	CifTree(const Common::ArchiveMemberPtr &member, const Common::Path &name);
 	virtual ~CifTree();
 
 	// Used for extracting additional image data for conversation cels (nancy2 and up)
@@ -107,8 +108,16 @@ public:
 	Common::Array<Common::Path> getPathsForType(CifInfo::ResType type = CifInfo::kResTypeAny) const;
 
 private:
+	// Trees backed by a plain file are opened only for as long as a read takes, since
+	// some platforms allow very few files to be open at the same time, and a game can
+	// load a lot of trees. Trees living inside another archive keep their stream, as
+	// reopening those means extracting them all over again.
+	Common::SeekableReadStream *openStream() const;
+	void closeStream(Common::SeekableReadStream *stream) const;
+
 	Common::Path _name;
 	Common::SeekableReadStream *_stream;
+	Common::ArchiveMemberPtr _member;
 	Common::HashMap<Common::Path, CifInfo, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _fileMap;
 	Common::Array<CifInfo> _writeFileMap;
 };




More information about the Scummvm-git-logs mailing list