[Scummvm-git-logs] scummvm branch-3-0 -> b2d4b7b05a16292607fe89ecd19af0415275b504

sluicebox noreply at scummvm.org
Fri Jan 2 02:08:19 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:
e3a5e09adf HUGO: Fix Hero direction when restoring
b2d4b7b05a HUGO: Fix stuck DOS notes when turning off sound


Commit: e3a5e09adfe8bfddf7ca96a391c048f6a8c8c815
    https://github.com/scummvm/scummvm/commit/e3a5e09adfe8bfddf7ca96a391c048f6a8c8c815
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-01-01T18:07:48-08:00

Commit Message:
HUGO: Fix Hero direction when restoring

Hero's direction was not restored in HUGO3 or Windows versions when
Hero's image was swapped. (HUGO1 mask, HUGO2 Penelope, HUGO3 small)

This was caused by a ScummVM bug that masked an original engine bug.

In ScummVM we were calling ObjectHanlder::restoreAllSeq() in the
wrong location when restoring. It's supposed to be called between
the two calls to ObjectHanlder::swapImages(), not afterwards.
Fixing this fixes HUGO3 and Windows versions, but it exposes an
original bug in the DOS versions of HUGO1 and HUGO2. They would
only set Hero's direction to face right when the image was swapped.

To fix the original bug, ObjectHanlder_v1d::swapImages() now preserves
Hero's direction when restoring. This was fixed in later versions of
the engine, and now We apply that fix to the early versions as well.

Changed paths:
    engines/hugo/file.cpp
    engines/hugo/object.h
    engines/hugo/object_v1d.cpp
    engines/hugo/object_v1w.cpp
    engines/hugo/object_v3d.cpp
    engines/hugo/schedule.cpp


diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index c1fe3590bc2..0e4a3908308 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -434,16 +434,19 @@ bool FileManager::restoreGame(const int16 slot) {
 
 	// If hero image is currently swapped, swap it back before restore
 	if (_vm->_heroImage != kHeroIndex)
-		_vm->_object->swapImages(kHeroIndex, _vm->_heroImage);
+		_vm->_object->swapImages(kHeroIndex, _vm->_heroImage, true);
 
 	_vm->_object->restoreObjects(in);
 
 	_vm->_heroImage = in->readByte();
 
+	// Restore ptrs to currently loaded objects
+	_vm->_object->restoreAllSeq();
+
 	// If hero swapped in saved game, swap it
 	byte heroImg = _vm->_heroImage;
 	if (heroImg != kHeroIndex)
-		_vm->_object->swapImages(kHeroIndex, _vm->_heroImage);
+		_vm->_object->swapImages(kHeroIndex, _vm->_heroImage, true);
 	_vm->_heroImage = heroImg;
 
 	Status &gameStatus = _vm->getGameStatus();
diff --git a/engines/hugo/object.h b/engines/hugo/object.h
index 9d36207db93..573379de6d6 100644
--- a/engines/hugo/object.h
+++ b/engines/hugo/object.h
@@ -72,7 +72,7 @@ public:
 	virtual void homeIn(const int objIndex1, const int objIndex2, const int8 objDx, const int8 objDy) = 0;
 	virtual void moveObjects() = 0;
 	virtual void updateImages() = 0;
-	virtual void swapImages(int objIndex1, int objIndex2) = 0;
+	virtual void swapImages(int objIndex1, int objIndex2, bool restoring) = 0;
 
 	bool isCarrying(uint16 wordIndex);
 	bool findObjectSpace(Object *obj, int16 *destx, int16 *desty);
@@ -128,7 +128,7 @@ public:
 	void homeIn(const int objIndex1, const int objIndex2, const int8 objDx, const int8 objDy) override;
 	void moveObjects() override;
 	void updateImages() override;
-	void swapImages(int objIndex1, int objIndex2) override;
+	void swapImages(int objIndex1, int objIndex2, bool restoring) override;
 };
 
 class ObjectHandler_v2d : public ObjectHandler_v1d {
@@ -148,7 +148,7 @@ public:
 	~ObjectHandler_v3d() override;
 
 	void moveObjects() override;
-	void swapImages(int objIndex1, int objIndex2) override;
+	void swapImages(int objIndex1, int objIndex2, bool restoring) override;
 };
 
 class ObjectHandler_v1w : public ObjectHandler_v3d {
@@ -158,7 +158,7 @@ public:
 
 	void moveObjects() override;
 	void updateImages() override;
-	void swapImages(int objIndex1, int objIndex2) override;
+	void swapImages(int objIndex1, int objIndex2, bool restoring) override;
 };
 
 } // End of namespace Hugo
diff --git a/engines/hugo/object_v1d.cpp b/engines/hugo/object_v1d.cpp
index 5416df9e192..9850937d29b 100644
--- a/engines/hugo/object_v1d.cpp
+++ b/engines/hugo/object_v1d.cpp
@@ -348,8 +348,16 @@ void ObjectHandler_v1d::moveObjects() {
  * the assumption for now that the first obj is always the HERO) to the object
  * number of the swapped image
  */
-void ObjectHandler_v1d::swapImages(int objIndex1, int objIndex2) {
-	debugC(1, kDebugObject, "swapImages(%d, %d)", objIndex1, objIndex2);
+void ObjectHandler_v1d::swapImages(int objIndex1, int objIndex2, bool restoring) {
+	debugC(1, kDebugObject, "swapImages(%d, %d, %d)", objIndex1, objIndex2, restoring);
+
+	// WORKAROUND: If Hero's image is swapped then restoring a game sets Hero's
+	// direction to right. This bug is quite noticeable in Hugo2 as Penelope.
+	// This was fixed in Hugo3 and Windows. We backport the fix to this version,
+	// but only when restoring so that original in-game behavior is preserved.
+	if (restoring) {
+		saveSeq(&_objects[objIndex1]);
+	}
 
 	SeqList tmpSeqList[kMaxSeqNumb];
 	int seqListSize = sizeof(SeqList) * kMaxSeqNumb;
@@ -357,7 +365,11 @@ void ObjectHandler_v1d::swapImages(int objIndex1, int objIndex2) {
 	memmove(tmpSeqList, _objects[objIndex1]._seqList, seqListSize);
 	memmove(_objects[objIndex1]._seqList, _objects[objIndex2]._seqList, seqListSize);
 	memmove(_objects[objIndex2]._seqList, tmpSeqList, seqListSize);
-	_objects[objIndex1]._currImagePtr = _objects[objIndex1]._seqList[0]._seqPtr;
+	if (restoring) {
+		restoreSeq(&_objects[objIndex1]);
+	} else {
+		_objects[objIndex1]._currImagePtr = _objects[objIndex1]._seqList[0]._seqPtr;
+	}
 	_objects[objIndex2]._currImagePtr = _objects[objIndex2]._seqList[0]._seqPtr;
 	_vm->_heroImage = (_vm->_heroImage == kHeroIndex) ? objIndex2 : kHeroIndex;
 }
diff --git a/engines/hugo/object_v1w.cpp b/engines/hugo/object_v1w.cpp
index 21c26f621a3..f9d47636a3c 100644
--- a/engines/hugo/object_v1w.cpp
+++ b/engines/hugo/object_v1w.cpp
@@ -360,8 +360,8 @@ void ObjectHandler_v1w::moveObjects() {
  * the assumption for now that the first obj is always the HERO) to the object
  * number of the swapped image
  */
-void ObjectHandler_v1w::swapImages(int objIndex1, int objIndex2) {
-	debugC(1, kDebugObject, "swapImages(%d, %d)", objIndex1, objIndex2);
+void ObjectHandler_v1w::swapImages(int objIndex1, int objIndex2, bool restoring) {
+	debugC(1, kDebugObject, "swapImages(%d, %d, %d)", objIndex1, objIndex2, restoring);
 
 	saveSeq(&_objects[objIndex1]);
 
diff --git a/engines/hugo/object_v3d.cpp b/engines/hugo/object_v3d.cpp
index 078b659d592..a50746683f4 100644
--- a/engines/hugo/object_v3d.cpp
+++ b/engines/hugo/object_v3d.cpp
@@ -245,8 +245,8 @@ void ObjectHandler_v3d::moveObjects() {
  * the assumption for now that the first obj is always the HERO) to the object
  * number of the swapped image
  */
-void ObjectHandler_v3d::swapImages(int objIndex1, int objIndex2) {
-	debugC(1, kDebugObject, "swapImages(%d, %d)", objIndex1, objIndex2);
+void ObjectHandler_v3d::swapImages(int objIndex1, int objIndex2, bool restoring) {
+	debugC(1, kDebugObject, "swapImages(%d, %d, %d)", objIndex1, objIndex2, restoring);
 
 	saveSeq(&_objects[objIndex1]);
 
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index e065ffd6c81..d5ab53aeb7c 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -1091,7 +1091,6 @@ void Scheduler::saveSchedulerData(Common::WriteStream *out) {
 
 void Scheduler::restoreSchedulerData(Common::ReadStream *in) {
 	restorePoints(in);
-	_vm->_object->restoreAllSeq();
 
 	// Now restore time of the save and the event queue
 	restoreEvents(in);
@@ -1262,7 +1261,7 @@ Event *Scheduler::doAction(Event *curEvent) {
 		Utils::notifyBox(_vm->_file->fetchString(action->_a12._stringIndex));   // Fetch string from file
 		break;
 	case SWAP_IMAGES:                                 // act13: Swap 2 object images
-		_vm->_object->swapImages(action->_a13._objIndex1, action->_a13._objIndex2);
+		_vm->_object->swapImages(action->_a13._objIndex1, action->_a13._objIndex2, false);
 		break;
 	case COND_SCR:                                    // act14: Conditional on current screen
 		if (_vm->_object->_objects[action->_a14._objIndex]._screenIndex == action->_a14._screenReq)


Commit: b2d4b7b05a16292607fe89ecd19af0415275b504
    https://github.com/scummvm/scummvm/commit/b2d4b7b05a16292607fe89ecd19af0415275b504
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-01-01T18:08:04-08:00

Commit Message:
HUGO: Fix stuck DOS notes when turning off sound

Changed paths:
    engines/hugo/sound.cpp


diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index 5e4b917bdb5..3c56ce49132 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -273,8 +273,19 @@ void SoundHandler::pcspkr_player() {
 	static const uint16 pcspkrFlats[8] =  {1435, 1279, 2342, 2150, 1916, 1755, 1611}; // The flats, Ab to Bb
 
 	// Does the user not want any sound?
-	if (!_vm->_config._soundFl || !_vm->_mixer->isReady())
+	if (!_vm->_config._soundFl) {
+		// If user turned off sound during a song then stop note and song
+		if (_DOSSongPtr != nullptr && *_DOSSongPtr != '\0') {
+			_speaker->stop();
+			// Advance to end of song
+			while (*_DOSSongPtr != '\0') {
+				_DOSSongPtr++;
+			}
+		}
 		return;
+	} else if (!_vm->_mixer->isReady()) {
+		return;
+	}
 
 	// Is there no song?
 	if (!_DOSSongPtr)




More information about the Scummvm-git-logs mailing list