[Scummvm-git-logs] scummvm master -> 2e58159d50f2a9d1d3ad2e17a656233dfc3e0aac
AndywinXp
noreply at scummvm.org
Wed Jan 25 23:40:37 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
2e58159d50 SCUMM: Fix bug #2377
Commit: 2e58159d50f2a9d1d3ad2e17a656233dfc3e0aac
https://github.com/scummvm/scummvm/commit/2e58159d50f2a9d1d3ad2e17a656233dfc3e0aac
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-01-26T00:40:15+01:00
Commit Message:
SCUMM: Fix bug #2377
This was a tricky one, as in order to obtain the correct behavior there was
the need to simulate what seems to be an oversight in the original code.
Changed paths:
engines/scumm/actor.cpp
engines/scumm/actor.h
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 29d2b0b02fb..708850b7d19 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -184,6 +184,8 @@ void Actor::initActor(int mode) {
_charset = 0;
memset(_sound, 0, sizeof(_sound));
_targetFacing = _facing;
+ _lastValidX = 0;
+ _lastValidY = 0;
_shadowMode = 0;
_layer = 0;
@@ -1906,12 +1908,37 @@ AdjustBoxResult Actor::adjustXYToBeInBox(int dstX, int dstY) {
int box;
const int firstValidBox = (_vm->_game.features & GF_SMALL_HEADER) ? 0 : 1;
- abr.x = dstX;
- abr.y = dstY;
+ // The original v3-4 interpreters register and use the last valid (X,Y) values
+ // for the current actor. During the execution of the current function, if
+ // the routine can't find a bestDist which is smaller than the init value
+ // (0xFFFF), the rest of the code flow just happens to reuse the last valid
+ // coordinates obtained from a previous call of the function.
+ // This sounds like pseudo-undefined behavior caused by an oversight, but we
+ // can get along with it as it appears we actually need this to happen...
+ //
+ // By simulating what v3 and v4 disasms did, we correctly fix bug #2377.
+ // The originals relied on global variables containing the latest valid
+ // coordinates modified in here and in startWalkActor, but registering
+ // the modifications only in here seems to be enough to cover this edge case.
+ //
+ // HE and v5-6 games appear to actually have undefined behavior, since they
+ // create something akin to our AdjustBoxResult structure right inside the
+ // current function, so this means that the coordinates inside it potentially
+ // might never be initialized if bestDist is never modified.
+ // The same thing applies to v7-8, but it's really unlikely that any distance
+ // would end up being higher than 0x7FFFFFFF...
+
+ bool isOldSystem = _vm->_game.version <= 4;
+
+ abr.x = isOldSystem ? _lastValidX : dstX;
+ abr.y = isOldSystem ? _lastValidY : dstY;
abr.box = kInvalidBox;
- if (_ignoreBoxes)
+ if (_ignoreBoxes) {
+ abr.x = dstX;
+ abr.y = dstY;
return abr;
+ }
for (int tIdx = 0; tIdx < ARRAYSIZE(thresholdTable); tIdx++) {
threshold = thresholdTable[tIdx];
@@ -1941,6 +1968,8 @@ AdjustBoxResult Actor::adjustXYToBeInBox(int dstX, int dstY) {
// Check if the point is contained in the box. If it is,
// we don't have to search anymore.
if (_vm->checkXYInBoxBounds(box, dstX, dstY)) {
+ _lastValidX = dstX;
+ _lastValidY = dstY;
abr.x = dstX;
abr.y = dstY;
abr.box = box;
@@ -1952,6 +1981,8 @@ AdjustBoxResult Actor::adjustXYToBeInBox(int dstX, int dstY) {
// Check if the box is closer than the previous boxes.
if (tmpDist < bestDist) {
+ _lastValidX = tmpX;
+ _lastValidY = tmpY;
abr.x = tmpX;
abr.y = tmpY;
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index e4415ecd6e0..24a051a4482 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -108,6 +108,7 @@ public:
byte _moving;
bool _ignoreBoxes;
byte _forceClip;
+ uint16 _lastValidX, _lastValidY;
byte _initFrame;
byte _walkFrame;
More information about the Scummvm-git-logs
mailing list