[Scummvm-git-logs] scummvm master -> 7e8632b25c68ab34b8feda0327959d309962aa0b
bluegr
noreply at scummvm.org
Thu Aug 27 01:43:53 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:
332330d2be NANCY: Use the correct alpha value for MouseLightPuzzle
7e8632b25c NANCY: Fix init of RippedLetterPuzzle and handle multiple instances
Commit: 332330d2be2768c379f660c5afc881f9bf0a3f2b
https://github.com/scummvm/scummvm/commit/332330d2be2768c379f660c5afc881f9bf0a3f2b
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-27T03:30:47+03:00
Commit Message:
NANCY: Use the correct alpha value for MouseLightPuzzle
Fixes the mouse cursor glow in scenes with a light object, such as a
flashlight.
A regression from commit 852375a, which shifted the alpha value. This
is the only place in the engine that had a hardcoded alpha value
position.
Changed paths:
engines/nancy/action/puzzle/mouselightpuzzle.cpp
diff --git a/engines/nancy/action/puzzle/mouselightpuzzle.cpp b/engines/nancy/action/puzzle/mouselightpuzzle.cpp
index d92850dff55..21457f0a6a7 100644
--- a/engines/nancy/action/puzzle/mouselightpuzzle.cpp
+++ b/engines/nancy/action/puzzle/mouselightpuzzle.cpp
@@ -105,11 +105,13 @@ void MouseLightPuzzle::handleInput(NancyInput &input) {
Common::Rect::getBlitRect(blitDestPoint, srcRect, _drawSurface.getBounds());
// Copy over the transparency to the draw surface
+ const uint32 alphaMask = (uint32)0xFF << _drawSurface.format.aShift;
+
for (int y = srcRect.top; y < srcRect.bottom; ++y) {
uint32 *drawSurfPtr = (uint32 *)_drawSurface.getBasePtr(blitDestPoint.x, y + blitDestPoint.y - srcRect.top);
uint16 *circlePtr = (uint16 *)_maskCircle.getBasePtr(srcRect.left, y);
for (int x = srcRect.left; x < srcRect.right; ++x) {
- *drawSurfPtr = (*drawSurfPtr & 0xFFFFFF00) | (byte)*circlePtr;
+ *drawSurfPtr = (*drawSurfPtr & ~alphaMask) | ((uint32)*circlePtr << _drawSurface.format.aShift);
++drawSurfPtr;
++circlePtr;
}
Commit: 7e8632b25c68ab34b8feda0327959d309962aa0b
https://github.com/scummvm/scummvm/commit/7e8632b25c68ab34b8feda0327959d309962aa0b
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-27T04:41:26+03:00
Commit Message:
NANCY: Fix init of RippedLetterPuzzle and handle multiple instances
- Bump save game version
- Drop the puzzle state detection heuristic code
- Save the playerHasTriedPuzzle flag in new saved games
- Save the puzzle data scene, and only use saved puzzle data if it's
meant for the current puzzle. This allow us to handle multiple
puzzle instances (e.g. puzzle scenes 3415 and 3679 in Nancy7)
Fix #17085
Changed paths:
engines/nancy/action/puzzle/rippedletterpuzzle.cpp
engines/nancy/nancy.h
engines/nancy/puzzledata.cpp
engines/nancy/puzzledata.h
diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
index 114396f99f7..ea1717a2935 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
@@ -194,6 +194,8 @@ void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
}
void RippedLetterPuzzle::execute() {
+ const uint16 sceneId = NancySceneState.getSceneInfo().sceneID;
+
switch (_state) {
case kBegin: {
_puzzleState = (RippedLetterPuzzleData *)NancySceneState.getPuzzleData(RippedLetterPuzzleData::getTag());
@@ -204,58 +206,30 @@ void RippedLetterPuzzle::execute() {
NancySceneState.setNoHeldItem();
- bool hasLoadedProgress = false;
- // Detect progress from the loaded tile order because
- // playerHasTriedPuzzle is not serialized
- if (!_puzzleState->playerHasTriedPuzzle) {
- 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;
- }
- }
-
- // Traverse the order and rotations arrays to check if
- // they have been initialized. If they haven't, they'll
- // be full of zeroes, so there's no progress to continue,
- // thus the arrays will need to be initialized normally.
- if (hasLoadedProgress) {
- bool arraysAreInitialized = false;
- for (uint i = 0; i < loadedStateSize; ++i) {
- if (_puzzleState->order[i] != 0 || _puzzleState->rotations[i] != 0) {
- arraysAreInitialized = true;
- break;
- }
- }
-
- if (!arraysAreInitialized)
- hasLoadedProgress = false;
- }
- }
-
// 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) {
+ // Only load the saved puzzle data if it's saved for this scene.
+ // There are games such as Nancy7 that feature multiple puzzle of this type
+ // in different scenes, and we don't want to load the wrong puzzle state.
+ if (!_puzzleState->playerHasTriedPuzzle || _puzzleState->sceneId != sceneId) {
+ _puzzleState->order = _initOrder;
+ _puzzleState->rotations = _initRotations;
+ _puzzleState->playerHasTriedPuzzle = true;
+ _puzzleState->pickedUpPieceID = -1;
+ _puzzleState->pickedUpPieceLastPos = -1;
+ _puzzleState->pickedUpPieceRot = 0;
+ _puzzleState->sceneId = sceneId;
+ } 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
- _puzzleState->order[_puzzleState->_pickedUpPieceLastPos] = _puzzleState->_pickedUpPieceID;
- _puzzleState->rotations[_puzzleState->_pickedUpPieceLastPos] = _puzzleState->_pickedUpPieceRot;
- _puzzleState->_pickedUpPieceID = -1;
- _puzzleState->_pickedUpPieceLastPos = -1;
- _puzzleState->_pickedUpPieceRot = 0;
+ _puzzleState->order[_puzzleState->pickedUpPieceLastPos] = _puzzleState->pickedUpPieceID;
+ _puzzleState->rotations[_puzzleState->pickedUpPieceLastPos] = _puzzleState->pickedUpPieceRot;
+ _puzzleState->pickedUpPieceID = -1;
+ _puzzleState->pickedUpPieceLastPos = -1;
+ _puzzleState->pickedUpPieceRot = 0;
}
for (uint i = 0; i < _puzzleState->order.size(); ++i) {
@@ -336,7 +310,7 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
Common::Rect screenHotspot = NancySceneState.getViewport().convertViewportToScreen(_destRects[i]);
if (screenHotspot.contains(input.mousePos)) {
Common::Rect insideRect;
- if (_puzzleState->_pickedUpPieceID == -1) {
+ if (_puzzleState->pickedUpPieceID == -1) {
// No piece picked up
// Check if the mouse is inside the rotation hotspot
@@ -381,10 +355,10 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
_pickedUpPiece.pickUp();
// ...then change the data...
- _puzzleState->_pickedUpPieceID = _puzzleState->order[i];
- _puzzleState->_pickedUpPieceRot = _puzzleState->rotations[i];
+ _puzzleState->pickedUpPieceID = _puzzleState->order[i];
+ _puzzleState->pickedUpPieceRot = _puzzleState->rotations[i];
_puzzleState->order[i] = -1;
- _puzzleState->_pickedUpPieceLastPos = i;
+ _puzzleState->pickedUpPieceLastPos = i;
// ...then clear the piece from the drawSurface
drawPiece(i, 0);
@@ -411,7 +385,7 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
if (_puzzleState->order[i] == -1) {
// No, hide the picked up piece graphic
_pickedUpPiece.setVisible(false);
- _puzzleState->_pickedUpPieceLastPos = -1;
+ _puzzleState->pickedUpPieceLastPos = -1;
} else {
// Yes, change the picked piece graphic
if (!_useCustomPickUpTile) {
@@ -423,11 +397,11 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
_pickedUpPiece.setTransparent(true);
// After a swap, the held piece must return
// to this slot on save or re-entry
- _puzzleState->_pickedUpPieceLastPos = i;
+ _puzzleState->pickedUpPieceLastPos = i;
}
- SWAP<int8>(_puzzleState->order[i], _puzzleState->_pickedUpPieceID);
- SWAP<byte>(_puzzleState->rotations[i], _puzzleState->_pickedUpPieceRot);
+ SWAP<int8>(_puzzleState->order[i], _puzzleState->pickedUpPieceID);
+ SWAP<byte>(_puzzleState->rotations[i], _puzzleState->pickedUpPieceRot);
// Draw the newly placed piece
drawPiece(i, _puzzleState->rotations[i], _puzzleState->order[i]);
@@ -443,7 +417,7 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
_pickedUpPiece.handleInput(input);
- if (_puzzleState->_pickedUpPieceID == -1) {
+ if (_puzzleState->pickedUpPieceID == -1) {
// No piece picked up, check the exit hotspot
if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
if (_customCursorID != -1)
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index 14c9c5a0bcd..2ef81dde717 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -54,7 +54,7 @@ class Serializer;
*/
namespace Nancy {
-static const int kSavegameVersion = 8;
+static const int kSavegameVersion = 9;
struct NancyGameDescription;
diff --git a/engines/nancy/puzzledata.cpp b/engines/nancy/puzzledata.cpp
index 290f1505180..747dbf39f5d 100644
--- a/engines/nancy/puzzledata.cpp
+++ b/engines/nancy/puzzledata.cpp
@@ -22,6 +22,7 @@
#include "engines/nancy/puzzledata.h"
#include "engines/nancy/enginedata.h"
#include "engines/nancy/nancy.h"
+#include "state/scene.h"
namespace Nancy {
@@ -55,7 +56,8 @@ void SliderPuzzleData::synchronize(Common::Serializer &ser) {
RippedLetterPuzzleData::RippedLetterPuzzleData() :
order(24, 0),
rotations(24, 0),
- playerHasTriedPuzzle(false) {}
+ playerHasTriedPuzzle(false),
+ sceneId(0) {}
void RippedLetterPuzzleData::synchronize(Common::Serializer &ser) {
// Serialize through fixed size buffers so save or load never
@@ -73,9 +75,9 @@ void RippedLetterPuzzleData::synchronize(Common::Serializer &ser) {
// 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 (ser.isSaving() && _pickedUpPieceID != -1) {
- serializedOrder[_pickedUpPieceLastPos] = _pickedUpPieceID;
- serializedRotations[_pickedUpPieceLastPos] = _pickedUpPieceRot;
+ if (ser.isSaving() && pickedUpPieceID != -1) {
+ serializedOrder[pickedUpPieceLastPos] = pickedUpPieceID;
+ serializedRotations[pickedUpPieceLastPos] = pickedUpPieceRot;
}
ser.syncArray(serializedOrder.data(), serializedOrder.size(), Common::Serializer::Byte);
@@ -85,6 +87,11 @@ void RippedLetterPuzzleData::synchronize(Common::Serializer &ser) {
Common::move(serializedOrder.begin(), serializedOrder.end(), order.begin());
Common::move(serializedRotations.begin(), serializedRotations.end(), rotations.begin());
}
+
+ if (ser.getVersion() >= 9) {
+ ser.syncAsByte(playerHasTriedPuzzle);
+ ser.syncAsUint16LE(sceneId);
+ }
}
TowerPuzzleData::TowerPuzzleData() {
diff --git a/engines/nancy/puzzledata.h b/engines/nancy/puzzledata.h
index 90badcc3894..22de11e9043 100644
--- a/engines/nancy/puzzledata.h
+++ b/engines/nancy/puzzledata.h
@@ -62,11 +62,14 @@ struct RippedLetterPuzzleData : public PuzzleData {
Common::Array<int8> order;
Common::Array<byte> rotations;
bool playerHasTriedPuzzle;
+ // Some games (e.g. Nancy7) have multiple instances of the same puzzle in
+ // different scenes, so we need to key the puzzle data by scene ID.
+ uint16 sceneId;
// Temporary values, do not save to file
- int8 _pickedUpPieceID = -1;
- byte _pickedUpPieceRot = 0;
- int _pickedUpPieceLastPos = -1;
+ int8 pickedUpPieceID = -1;
+ byte pickedUpPieceRot = 0;
+ int pickedUpPieceLastPos = -1;
};
struct TowerPuzzleData : public PuzzleData {
More information about the Scummvm-git-logs
mailing list