diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 3694d02f512..6b2e5dc9773 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -1516,6 +1516,16 @@ void Actor::setDirection(int direction) { vald = _cost.frame[i]; if (vald == 0xFFFF) continue; + if (!(_vm->_game.features & GF_NEW_COSTUMES)) { + // Fix bug mentioned here: https://github.com/scummvm/scummvm/pull/3795/ + // For versions 1 to 6 we need to store the direction info in the frame array (like + // the original interpreters do). I haven't found any signs that v7/8 require it, though. + // I haven't checked HE, but since it uses the same AKOS costumes as v7/8 I leave that + // as it is... + if ((vald & 3) == newDirToOldDir(direction)) + continue; + vald >>= 2; + } _vm->_costumeLoader->costumeDecodeData(this, vald, (_vm->_game.version <= 2) ? 0xFFFF : aMask); } @@ -3800,6 +3810,14 @@ void Actor::saveLoadWithSerializer(Common::Serializer &s) { setDirection(_facing); } + + if (s.isLoading() && _vm->_game.version > 0 && !(_vm->_game.features & GF_NEW_COSTUMES) && s.getVersion() < VER(105)) { + // For older saves, we can't reconstruct the frame's direction if it is different from the actor + // direction, this is the best we can do. However, it seems to be relevant only for very rare + // edge cases, anyway... + for (int i = 0; i < 16; ++i) + _cost.frame[i] = (_cost.frame[i] << 2) | newDirToOldDir(_facing); + } } void Actor_v3::saveLoadWithSerializer(Common::Serializer &s) { diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp index 8f7d64f9beb..09530661feb 100644 --- a/engines/scumm/costume.cpp +++ b/engines/scumm/costume.cpp @@ -773,7 +773,7 @@ byte NESCostumeRenderer::drawLimb(const Actor *a, int limb) { palette = darkpalette; src = _loaded._dataOffsets; - anim = 4 * cost.frame[limb] + newDirToOldDir(a->getFacing()); + anim = cost.frame[limb]; frameNum = cost.curpos[limb]; frame = src[src[2 * anim] + frameNum]; @@ -967,10 +967,8 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) loadCostume(a->_costume); anim = newDirToOldDir(a->getFacing()) + frame * 4; - - if (anim > _numAnim) { + if (anim > _numAnim) return; - } if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) baseptr = _dataOffsets + anim * 2 + 2; @@ -1006,7 +1004,7 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) if (j == 0xFFFF) { a->_cost.curpos[i] = 0xFFFF; a->_cost.start[i] = 0; - a->_cost.frame[i] = frame; + a->_cost.frame[i] = anim; } else { extra = *r++; cmd = _animCmds[j]; @@ -1019,7 +1017,7 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) a->_cost.end[i] = j + (extra & 0x7F); if (extra & 0x80) a->_cost.curpos[i] |= 0x8000; - a->_cost.frame[i] = frame; + a->_cost.frame[i] = anim; } } } else { @@ -1162,7 +1160,7 @@ void NESCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) { a->_cost.curpos[0] = 0; a->_cost.start[0] = 0; a->_cost.end[0] = _dataOffsets[2 * anim + 1]; - a->_cost.frame[0] = frame; + a->_cost.frame[0] = anim; } byte NESCostumeLoader::increaseAnims(Actor *a) { diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 4fd074dfeef..b7058e6b234 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -67,7 +67,7 @@ struct SaveInfoSection { #define SaveInfoSectionSize (4+4+4 + 4+4 + 4+2) -#define CURRENT_VER 104 +#define CURRENT_VER 105 #define INFOSECTION_VERSION 2 #pragma mark -