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

bluegr noreply at scummvm.org
Fri Mar 13 07:35:16 UTC 2026


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

Summary:
31a11df487 NANCY: Fix RippedLetterPuzzle crash after save
1f0d0c83e1 NANCY: Fix swapped held slot tracking in RippedLetterPuzzle
aac3941785 NANCY: Restore loaded RippedLetterPuzzle progress


Commit: 31a11df487618e61302e16836a47081bc91d30fa
    https://github.com/scummvm/scummvm/commit/31a11df487618e61302e16836a47081bc91d30fa
Author: flipkick (167208+flipkick at users.noreply.github.com)
Date: 2026-03-13T09:35:12+02:00

Commit Message:
NANCY: Fix RippedLetterPuzzle crash after save

Avoid mutating the live RippedLetterPuzzle state during save and load
by serializing through fixed size temporary buffers.

Changed paths:
    engines/nancy/puzzledata.cpp


diff --git a/engines/nancy/puzzledata.cpp b/engines/nancy/puzzledata.cpp
index f7c28404960..9a2dc6b0894 100644
--- a/engines/nancy/puzzledata.cpp
+++ b/engines/nancy/puzzledata.cpp
@@ -58,21 +58,33 @@ RippedLetterPuzzleData::RippedLetterPuzzleData() :
 	playerHasTriedPuzzle(false) {}
 
 void RippedLetterPuzzleData::synchronize(Common::Serializer &ser) {
-	order.resize(24);
-	rotations.resize(24);
+	// Serialize through fixed size buffers so save or load never
+	// mutates the live puzzle state
+	Common::Array<int8> serializedOrder(24, -1);
+	Common::Array<byte> serializedRotations(24, 0);
+
+	for (uint i = 0; i < order.size() && i < serializedOrder.size(); ++i) {
+		serializedOrder[i] = order[i];
+	}
+
+	for (uint i = 0; i < rotations.size() && i < serializedRotations.size(); ++i) {
+		serializedRotations[i] = rotations[i];
+	}
 
 	// A piece may still be held while saving; make sure the saved data
 	// has it back in the last place it was picked up from
-	if (_pickedUpPieceID != -1) {
-		order[_pickedUpPieceLastPos] = _pickedUpPieceID;
-		rotations[_pickedUpPieceLastPos] = _pickedUpPieceRot;
-		_pickedUpPieceID = -1;
-		_pickedUpPieceLastPos = -1;
-		_pickedUpPieceRot = 0;
+	if (ser.isSaving() && _pickedUpPieceID != -1) {
+		serializedOrder[_pickedUpPieceLastPos] = _pickedUpPieceID;
+		serializedRotations[_pickedUpPieceLastPos] = _pickedUpPieceRot;
 	}
 
-	ser.syncArray(order.data(), order.size(), Common::Serializer::Byte);
-	ser.syncArray(rotations.data(), 24, Common::Serializer::Byte);
+	ser.syncArray(serializedOrder.data(), serializedOrder.size(), Common::Serializer::Byte);
+	ser.syncArray(serializedRotations.data(), serializedRotations.size(), Common::Serializer::Byte);
+
+	if (ser.isLoading()) {
+		order = serializedOrder;
+		rotations = serializedRotations;
+	}
 }
 
 TowerPuzzleData::TowerPuzzleData() {


Commit: 1f0d0c83e148f53fd48b3c71ca6518030dab90a8
    https://github.com/scummvm/scummvm/commit/1f0d0c83e148f53fd48b3c71ca6518030dab90a8
Author: flipkick (167208+flipkick at users.noreply.github.com)
Date: 2026-03-13T09:35:12+02:00

Commit Message:
NANCY: Fix swapped held slot tracking in RippedLetterPuzzle

After a swap, the currently held tile came from the destination slot.
So save or re-entry recovery must return it to that slot, not the
original pickup slot.

Changed paths:
    engines/nancy/action/puzzle/rippedletterpuzzle.cpp


diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
index 14c898f5b57..bae4b3c7603 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
@@ -373,6 +373,9 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
 
 							_pickedUpPiece.setVisible(true);
 							_pickedUpPiece.setTransparent(true);
+							// After a swap, the held piece must return
+							// to this slot on save or re-entry
+							_puzzleState->_pickedUpPieceLastPos = i;
 						}
 
 						SWAP<int8>(_puzzleState->order[i], _puzzleState->_pickedUpPieceID);


Commit: aac3941785472b0e21a82598ee4086ee40b1e8f2
    https://github.com/scummvm/scummvm/commit/aac3941785472b0e21a82598ee4086ee40b1e8f2
Author: flipkick (167208+flipkick at users.noreply.github.com)
Date: 2026-03-13T09:35:12+02:00

Commit Message:
NANCY: Restore loaded RippedLetterPuzzle progress

Detect saved progress from the loaded tile order when
playerHasTriedPuzzle is false since that flag is not serialized.

Changed paths:
    engines/nancy/action/puzzle/rippedletterpuzzle.cpp


diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
index bae4b3c7603..da882c11ea5 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
@@ -195,7 +195,7 @@ void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
 
 void RippedLetterPuzzle::execute() {
 	switch (_state) {
-	case kBegin:
+	case kBegin: {
 		_puzzleState = (RippedLetterPuzzleData *)NancySceneState.getPuzzleData(RippedLetterPuzzleData::getTag());
 		assert(_puzzleState);
 
@@ -204,10 +204,33 @@ void RippedLetterPuzzle::execute() {
 
 		NancySceneState.setNoHeldItem();
 
+		bool hasLoadedProgress = false;
+		// Detect progress from the loaded tile order because
+		// playerHasTriedPuzzle is not serialized
 		if (!_puzzleState->playerHasTriedPuzzle) {
-			_puzzleState->order = _initOrder;
-			_puzzleState->rotations = _initRotations;
-			_puzzleState->playerHasTriedPuzzle = true;
+			const uint loadedStateSize = MIN<uint>(_puzzleState->order.size(), _puzzleState->rotations.size());
+			const uint loadedTileCount = MIN<uint>(loadedStateSize, _initOrder.size());
+			for (uint i = 0; i < loadedTileCount; ++i) {
+				if (_puzzleState->order[i] != _initOrder[i] || _puzzleState->rotations[i] != _initRotations[i]) {
+					hasLoadedProgress = true;
+					break;
+				}
+			}
+		}
+
+		// The serialized puzzle state uses 24 slots. Resize it to
+		// the current puzzle dimensions before use
+		_puzzleState->order.resize(_initOrder.size());
+		_puzzleState->rotations.resize(_initRotations.size());
+
+		if (!_puzzleState->playerHasTriedPuzzle) {
+			if (hasLoadedProgress) {
+				_puzzleState->playerHasTriedPuzzle = true;
+			} else {
+				_puzzleState->order = _initOrder;
+				_puzzleState->rotations = _initRotations;
+				_puzzleState->playerHasTriedPuzzle = true;
+			}
 		} else if (_puzzleState->_pickedUpPieceID != -1) {
 			// Puzzle was left while still holding a piece (e.g. by clicking a scene item).
 			// Make sure we put the held piece back in its place
@@ -227,7 +250,8 @@ void RippedLetterPuzzle::execute() {
 		g_nancy->_sound->loadSound(_rotateSound);
 
 		_state = kRun;
-		// fall through
+	}
+	// fall through
 	case kRun:
 		switch (_solveState) {
 		case kNotSolved :




More information about the Scummvm-git-logs mailing list