[Scummvm-git-logs] scummvm master -> 32bf970916f7cb2093e2cfa51ac1f93618747304

sdelamarre noreply at scummvm.org
Sat Mar 7 09:57:22 UTC 2026


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

Summary:
c9526a4d55 GOB: Fix some Adi4 high-color map not using special black/white values
e8d7414f5c GOB: Fix some edge case high color map computation for Adibou2/Adi4
c86824cce8 GOB: Fix a text background color bug in printTotText (Adi4)
32bf970916 GOB: New "gobStack" debug console command, to print the scripts' callstack


Commit: c9526a4d55cbfad4c309700dd9d35574d70eee6d
    https://github.com/scummvm/scummvm/commit/c9526a4d55cbfad4c309700dd9d35574d70eee6d
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-03-07T10:56:38+01:00

Commit Message:
GOB: Fix some Adi4 high-color map not using special black/white values

Changed paths:
    engines/gob/videoplayer.cpp


diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index 47f422f1a0f..5dc85593a5b 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -263,10 +263,12 @@ int VideoPlayer::openVideo(bool primary, const Common::String &file, Properties
 
 					if (!video->highColorMap)
 						video->highColorMap = new uint32[256];
+
+					bool useSpecialBlackWhiteValues = _vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4;
 					Surface::computeHighColorMap(video->highColorMap,
 												 video->decoder->getPalette(),
 												 _vm->getPixelFormat(),
-												 _vm->getGameType() == kGameTypeAdibou2);
+												 useSpecialBlackWhiteValues);
 					video->decoder->setSurfaceMemory(video->tmpSurfBppConversion->getPixels(),
 													 video->tmpSurfBppConversion->w,
 													 video->tmpSurfBppConversion->h,


Commit: e8d7414f5c7e93ad40a051d738f18b1efd1ad2d0
    https://github.com/scummvm/scummvm/commit/e8d7414f5c7e93ad40a051d738f18b1efd1ad2d0
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-03-07T10:56:38+01:00

Commit Message:
GOB: Fix some edge case high color map computation for Adibou2/Adi4

When start_color != 0 and useSpecialBlackWhiteValues = true, the special
transparent value 0 will be copied at wrong indexes.

Changed paths:
    engines/gob/surface.cpp


diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index 53bfaa31bf1..e433b7af63f 100644
--- a/engines/gob/surface.cpp
+++ b/engines/gob/surface.cpp
@@ -1186,9 +1186,9 @@ void Surface::computeHighColorMap(uint32 *highColorMap, const byte *palette,
 
 		if (!useSpecialBlackWhiteValues)
 			highColorMap[indexDest] = format.RGBToColor(red, green, blue);
-		else if (i == 0) // Trick from the original engine to handle transparency with high color surfaces
+		else if (indexDest == 0) // Trick from the original engine to handle transparency with high color surfaces
 			highColorMap[indexDest] = 0; // Palette index 0 is always mapped to high color value 0, possibly interpreted as the special transparent color.
-		else if (i == 255)
+		else if (indexDest == 255)
 			highColorMap[indexDest] = format.RGBToColor(0xFF, 0xFF, 0xFF); // Palette index 255 is always mapped to white.
 		else if (red == 0 && green == 0 && blue == 0)
 			highColorMap[indexDest] = format.RGBToColor((1 << format.rLoss),


Commit: c86824cce89349e16e7484d49c6520798c26c514
    https://github.com/scummvm/scummvm/commit/c86824cce89349e16e7484d49c6520798c26c514
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-03-07T10:56:38+01:00

Commit Message:
GOB: Fix a text background color bug in printTotText (Adi4)

Fixes the background color of some texts not being transparent in the
character creation step in Adi4

Changed paths:
    engines/gob/draw_playtoons.cpp


diff --git a/engines/gob/draw_playtoons.cpp b/engines/gob/draw_playtoons.cpp
index 97fd66ba7fc..5f9a8faf4b8 100644
--- a/engines/gob/draw_playtoons.cpp
+++ b/engines/gob/draw_playtoons.cpp
@@ -128,7 +128,7 @@ void Draw_Playtoons::printTotText(int16 id) {
 	if (*ptrEnd == 16)
 		_backColor = -1;
 	else
-		_backColor = *ptr + _colorOffset;
+		_backColor = *ptrEnd + _colorOffset;
 
 	_transparency = 1;
 


Commit: 32bf970916f7cb2093e2cfa51ac1f93618747304
    https://github.com/scummvm/scummvm/commit/32bf970916f7cb2093e2cfa51ac1f93618747304
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-03-07T10:56:38+01:00

Commit Message:
GOB: New "gobStack" debug console command, to print the scripts' callstack

Changed paths:
    engines/gob/console.cpp
    engines/gob/console.h
    engines/gob/game.cpp
    engines/gob/game.h
    engines/gob/hotspots.cpp
    engines/gob/inter.cpp
    engines/gob/inter_v1.cpp
    engines/gob/script.h


diff --git a/engines/gob/console.cpp b/engines/gob/console.cpp
index 8bcb70a94d5..705fb585cd2 100644
--- a/engines/gob/console.cpp
+++ b/engines/gob/console.cpp
@@ -27,6 +27,7 @@
 
 #include "gob/console.h"
 #include "gob/gob.h"
+#include "gob/game.h"
 #include "gob/inter.h"
 #include "gob/dataio.h"
 #include "gob/cheater.h"
@@ -44,6 +45,7 @@ GobConsole::GobConsole(GobEngine *vm) : GUI::Debugger(), _vm(vm), _cheater(nullp
 	registerCmd("varString",    WRAP_METHOD(GobConsole, cmd_varString));
 	registerCmd("cheat",        WRAP_METHOD(GobConsole, cmd_cheat));
 	registerCmd("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives));
+	registerCmd("gobStack",     WRAP_METHOD(GobConsole, cmd_gobStack));
 }
 
 GobConsole::~GobConsole() {
@@ -80,6 +82,10 @@ bool GobConsole::cmd_Help(int, const char **) {
 	debugPrintf(" var32 - manipulates 32-bit variables; usage: var32 <var offset> (<value>)\n");
 	debugPrintf(" varString - manipulates string references; usage: varString <var offset> (<value>)\n");
 	debugPrintf("\n");
+	debugPrintf("Scripts\n");
+	debugPrintf("------\n");
+	debugPrintf(" gobStack - prints the TOT scripts call stack (requires Gameflow debug flag)\n");
+	debugPrintf("\n");
 	return true;
 }
 
@@ -221,4 +227,9 @@ bool GobConsole::cmd_listArchives(int argc, const char **argv) {
 	return true;
 }
 
+bool GobConsole::cmd_gobStack(int argc, const char **argv) {
+	debugPrintf("%s", _vm->_game->getGobStack().c_str());
+	return true;
+}
+
 } // End of namespace Gob
diff --git a/engines/gob/console.h b/engines/gob/console.h
index a0e8caf73bf..0faf4b19efd 100644
--- a/engines/gob/console.h
+++ b/engines/gob/console.h
@@ -60,6 +60,8 @@ private:
 	bool cmd_cheat(int argc, const char **argv);
 
 	bool cmd_listArchives(int argc, const char **argv);
+
+	bool cmd_gobStack(int argc, const char **argv);
 };
 
 } // End of namespace Gob
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 36fee251a0b..b070db000a4 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -444,8 +444,14 @@ bool TotFunctions::call(const Tot &tot, uint16 offset) const {
 	_vm->_game->_resources  = tot.resources;
 	_vm->_game->_curTotFile = tot.file;
 
+	_vm->_game->pushOnGlobalCallStack(kNamedFunctionSub,
+									  curtotFile, script->_currentOpcodePos,
+									  tot.file, offset);
+
 	_vm->_game->playTot(offset);
 
+	_vm->_game->popGlobalCallStack();
+
 	_vm->_game->_script     = script;
 	_vm->_game->_resources  = resources;
 	_vm->_game->_curTotFile = curtotFile;
@@ -616,6 +622,8 @@ void Game::playTot(int32 function) {
 				_vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF);
 
 			_script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart));
+			if (!_globalFuncCallStack.empty())
+				_globalFuncCallStack.top().calleeOffset = _script->pos();
 
 			_vm->_inter->renewTimeInVars();
 
@@ -679,6 +687,8 @@ void Game::playTot(int32 function) {
 		else
 			_script->seek(_script->getFunctionOffset(function + 1));
 
+		if (!_globalFuncCallStack.empty())
+			_globalFuncCallStack.top().calleeOffset = _script->pos();
 		_vm->_inter->callSub(2);
 
 		if (_vm->_inter->_terminate != 0)
@@ -887,8 +897,13 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
 
 void Game::start() {
 	prepareStart();
+
+	pushOnGlobalCallStack(kStartGame, "(entry)", -1, _curTotFile, -1);
+
 	playTot(-2);
 
+	popGlobalCallStack();
+
 	_vm->_draw->closeScreen();
 
 	for (int i = 0; i < Draw::kSpriteCount; i++)
@@ -896,6 +911,30 @@ void Game::start() {
 	_vm->_draw->_scummvmCursor.reset();
 }
 
+void Game::pushOnGlobalCallStack(FuncCallType type,
+								 const Common::String &callingTot, int32 callSiteOffset,
+								 const Common::String &calledTot, int32 calleeOffset) {
+	if (!debugChannelSet(1, kDebugGameFlow))
+		return;
+
+	FuncCall fc;
+	fc.type = type;
+	fc.callingTot = callingTot;
+	fc.callSiteOffset = callSiteOffset;
+	fc.calledTot = calledTot;
+	fc.calleeOffset = calleeOffset;
+	_globalFuncCallStack.push(fc);
+}
+
+void Game::popGlobalCallStack() {
+	if (_globalFuncCallStack.empty())
+		return;
+
+	FuncCall call = _globalFuncCallStack.pop();
+	while (!_globalFuncCallStack.empty() && call.tailCall)
+		call = _globalFuncCallStack.pop();
+}
+
 // flagbits: 0 = freeInterVariables, 1 = function -1
 void Game::totSub(int8 flags, const Common::String &totFile) {
 	int8 curBackupPos;
@@ -911,6 +950,9 @@ void Game::totSub(int8 flags, const Common::String &totFile) {
 	debugC(4, kDebugGameFlow,
 		   "Pushing current env (index %d, script %s) to stack, opening env (index %d, script %s.TOT)",
 		   _numEnvironments, _curTotFile.c_str(), _numEnvironments + 1, totFile.c_str());
+
+	int32 callerOff = _script->_currentOpcodePos;
+
 	_environments.set(_numEnvironments);
 
 	if (flags == 18) {
@@ -926,11 +968,14 @@ void Game::totSub(int8 flags, const Common::String &totFile) {
 	_script = new Script(_vm);
 	_resources = new Resources(_vm);
 
+	Common::String calledTot = totFile + ".TOT";
+
+	pushOnGlobalCallStack(kTotSub, _curTotFile, callerOff, calledTot, -1);
+
 	if (flags & 5)
 		_vm->_inter->_variables = nullptr;
 
-	_curTotFile = totFile + ".TOT";
-
+	_curTotFile = calledTot;
 
 	bool copyPreviousMatchingEnv = flags & 0x80;
 	if (copyPreviousMatchingEnv) {
@@ -948,6 +993,7 @@ void Game::totSub(int8 flags, const Common::String &totFile) {
 
 		if (matchingEnvFoundP) {
 			if (_vm->_inter->_terminate != 0) {
+				popGlobalCallStack();
 				clearUnusedEnvironment();
 				return;
 			}
@@ -967,6 +1013,7 @@ void Game::totSub(int8 flags, const Common::String &totFile) {
 		}
 	} else {
 		if (_vm->_inter->_terminate != 0) {
+			popGlobalCallStack();
 			clearUnusedEnvironment();
 			return;
 		}
@@ -991,6 +1038,8 @@ void Game::totSub(int8 flags, const Common::String &totFile) {
 			_vm->_inter->delocateVars();
 	}
 
+	popGlobalCallStack();
+
 	clearUnusedEnvironment();
 
 
@@ -1026,6 +1075,9 @@ void Game::switchTotSub(int16 index, int16 function) {
 	     _environments.getTotFile(newPos).equalsIgnoreCase("gob06.tot"))
 		return;
 
+	Common::String callingTot = _curTotFile;
+	int32 callSiteOff = _script->_currentOpcodePos;
+
 	curBackupPos = _curEnvironment;
 	backupedCount = _numEnvironments;
 	if (_curEnvironment == _numEnvironments)
@@ -1044,6 +1096,8 @@ void Game::switchTotSub(int16 index, int16 function) {
 		return;
 	}
 
+	pushOnGlobalCallStack(kSwitchTotSub, callingTot, callSiteOff, _curTotFile, function);
+
 	_hotspots->push(0, true);
 	playTot(function);
 
@@ -1052,6 +1106,8 @@ void Game::switchTotSub(int16 index, int16 function) {
 
 	_hotspots->pop();
 
+	popGlobalCallStack();
+
 	clearUnusedEnvironment();
 
 	_curEnvironment = curBackupPos;
@@ -1119,4 +1175,80 @@ Common::String Game::getFunctionName(const Common::String &tot, uint16 offset) {
 	return _totFunctions.getFunctionName(tot, offset);
 }
 
+Common::String Game::formatSubNameInCallStack(const Common::String &totFile, int32 offset) {
+	if (offset < 0)
+		return "???";
+
+	Common::String name = _totFunctions.getFunctionName(totFile, (uint16)offset);
+	if (!name.empty()) {
+		const char *space = strchr(name.c_str(), ' ');
+		if (space)
+			name = Common::String(space + 1);
+	}
+	if (!name.empty())
+		return Common::String::format("sub_%d_%s", offset, name.c_str());
+	return Common::String::format("sub_%d", offset);
+}
+
+Common::String Game::getGobStack() {
+	uint stackSize = _globalFuncCallStack.size();
+
+	Common::Array<Common::String> positions;
+	Common::Array<Common::String> functions;
+	Common::Array<Common::String> tags;
+
+	for (uint i = 1; i < stackSize; i++) {
+		const FuncCall &fc = _globalFuncCallStack[i];
+		const FuncCall &previousFc = _globalFuncCallStack[i - 1];
+
+		functions.push_back(formatSubNameInCallStack(previousFc.calledTot, previousFc.calleeOffset));
+		const Common::String &callingTot = fc.callingTot;
+		positions.push_back(Common::String::format("%s:%05d", callingTot.c_str(), fc.callSiteOffset));
+
+		switch (fc.type) {
+		case kStartGame:        tags.push_back("[start]"); break; // Never met
+		case kCallSub:          tags.push_back("[callSub]"); break;
+		case kEvaluateHotspots: tags.push_back("[hotspots:evaluate]"); break;
+		case kTotSub:           tags.push_back("[totSub]"); break;
+		case kSwitchTotSub:     tags.push_back("[switchTotSub]"); break;
+		case kNamedFunctionSub: tags.push_back("[namedFunc]"); break;
+		case kHotspotEnter:     tags.push_back("[hotspot:enter]"); break;
+		case kHotspotLeave:     tags.push_back("[hotspot:leave]"); break;
+		}
+	}
+
+	if (_script && _script->isLoaded() && !_globalFuncCallStack.empty()) {
+		const FuncCall &fc = _globalFuncCallStack.top();
+		functions.push_back(formatSubNameInCallStack(fc.calledTot, fc.calleeOffset));
+		positions.push_back(Common::String::format("%s:%05d", _curTotFile.c_str(), _script->pos()));
+		tags.push_back("[current]");
+	}
+
+	// Compute column widths
+	uint lineCount = positions.size();
+	uint maxFrameW = 1, maxFuncW = 1, maxPosW = 1;
+	for (uint i = 0; i < lineCount; i++) {
+		Common::String frameStr = Common::String::format("#%d", i);
+		if (frameStr.size() > maxFrameW) maxFrameW = (uint)frameStr.size();
+		if (functions[i].size() > maxFuncW) maxFuncW = (uint)functions[i].size();
+		if (positions[i].size() > maxPosW) maxPosW = (uint)positions[i].size();
+	}
+
+	Common::String result = "--- TOT Scripts Stack ---\n";
+	for (int i = (int)lineCount - 1; i >= 0; i--) {
+		Common::String frameStr = Common::String::format("#%d", (int)lineCount - 1 - i);
+		result += Common::String::format("  %-*s | %-*s | %*s %s\n",
+										 maxFrameW, frameStr.c_str(),
+										 maxFuncW, functions[i].c_str(),
+										 maxPosW, positions[i].c_str(),
+										 tags[i].c_str());
+	}
+	result += "------------------------\n";
+	return result;
+}
+
+void Game::printGobStack() {
+	debug("%s", getGobStack().c_str());
+}
+
 } // End of namespace Gob
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 0f86ea6dc55..543a4720e2f 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -28,6 +28,7 @@
 #ifndef GOB_GAME_H
 #define GOB_GAME_H
 
+#include "common/stack.h"
 #include "common/str.h"
 
 #include "gob/util.h"
@@ -41,6 +42,26 @@ class Resources;
 class Variables;
 class Hotspots;
 
+enum FuncCallType {
+	kStartGame,
+	kCallSub,
+	kEvaluateHotspots,
+	kTotSub,
+	kSwitchTotSub,
+	kNamedFunctionSub,
+	kHotspotEnter,
+	kHotspotLeave
+};
+
+struct FuncCall {
+	FuncCallType type = kCallSub;
+	Common::String callingTot;
+	int32 callSiteOffset = -1;
+	Common::String calledTot;
+	int32 calleeOffset = -1;
+	bool tailCall = false;
+};
+
 class Environments {
 public:
 	static const uint8 kEnvironmentCount = 20;
@@ -187,6 +208,16 @@ public:
 	bool callFunction(const Common::String &tot, const Common::String &function, int16 param);
 	Common::String getFunctionName(const Common::String &tot, uint16 offset);
 
+	Common::String getGobStack();
+	void printGobStack();
+
+	void pushOnGlobalCallStack(FuncCallType type,
+							   const Common::String &callingTot, int32 callSiteOffset,
+							   const Common::String &calledTot, int32 calleeOffset);
+	void popGlobalCallStack();
+
+	Common::Stack<FuncCall> _globalFuncCallStack; // for debugging only
+
 protected:
 	GobEngine *_vm;
 
@@ -204,6 +235,8 @@ protected:
 	TotFunctions _totFunctions;
 
 	void clearUnusedEnvironment();
+
+	Common::String formatSubNameInCallStack(const Common::String &totFile, int32 offset);
 };
 
 } // End of namespace Gob
diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp
index 955c402d88c..b944ac74d6b 100644
--- a/engines/gob/hotspots.cpp
+++ b/engines/gob/hotspots.cpp
@@ -555,8 +555,15 @@ void Hotspots::enter(uint16 index) {
 	_currentX = _vm->_global->_inter_mouseX;
 	_currentY = _vm->_global->_inter_mouseY;
 
-	if (spot.funcEnter != 0)
+	if (spot.funcEnter != 0) {
+		_vm->_game->pushOnGlobalCallStack(kHotspotEnter,
+										  _vm->_game->_curTotFile, _vm->_game->_script->_currentOpcodePos,
+										  _vm->_game->_curTotFile, spot.funcEnter);
+
 		call(spot.funcEnter);
+
+		_vm->_game->popGlobalCallStack();
+	}
 }
 
 void Hotspots::leave(uint16 index) {
@@ -583,7 +590,14 @@ void Hotspots::leave(uint16 index) {
 		if (_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4) {
 			_vm->_game->_script = spot.scriptFuncLeave;
 		}
+
+		_vm->_game->pushOnGlobalCallStack(kHotspotLeave,
+										  _vm->_game->_curTotFile, curScript->_currentOpcodePos,
+										  _vm->_game->_curTotFile, spot.funcLeave);
+
 		call(spot.funcLeave);
+
+		_vm->_game->popGlobalCallStack();
 		_vm->_game->_script = curScript;
 	}
 }
@@ -1608,9 +1622,16 @@ bool Hotspots::evaluateFind(uint16 key, int16 timeVal, const uint16 *ids,
 			}
 
 			// Leave the current hotspot
-			if ((_currentKey != 0) && (_hotspots[_currentIndex].funcLeave != 0))
+			if ((_currentKey != 0) && (_hotspots[_currentIndex].funcLeave != 0)) {
+				_vm->_game->pushOnGlobalCallStack(kHotspotLeave,
+												  _vm->_game->_curTotFile, _vm->_game->_script->_currentOpcodePos,
+												  _vm->_game->_curTotFile, _hotspots[_currentIndex].funcLeave);
+
 				call(_hotspots[_currentIndex].funcLeave);
 
+				_vm->_game->popGlobalCallStack();
+			}
+
 			_currentKey = 0;
 		}
 
@@ -1738,9 +1759,16 @@ void Hotspots::evaluate() {
 		setCurrentHotspot(ids, id);
 
 		// Enter it
-		if (_hotspots[index].funcEnter != 0)
+		if (_hotspots[index].funcEnter != 0) {
+			_vm->_game->pushOnGlobalCallStack(kHotspotEnter,
+											  _vm->_game->_curTotFile, _vm->_game->_script->_currentOpcodePos,
+											  _vm->_game->_curTotFile, _hotspots[index].funcEnter);
+
 			call(_hotspots[index].funcEnter);
 
+			_vm->_game->popGlobalCallStack();
+		}
+
 		setCurrentHotspot(nullptr, 0);
 		id = 0;
 	}
@@ -2215,7 +2243,14 @@ bool Hotspots::leaveNthPlain(uint16 n, uint16 startIndex, int16 timeVal, const u
 
 		// Call the leave and time it
 		startTime = _vm->_util->getTimeKey();
+		_vm->_game->pushOnGlobalCallStack(kHotspotLeave,
+										  _vm->_game->_curTotFile, _vm->_game->_script->_currentOpcodePos,
+										  _vm->_game->_curTotFile, spot.funcLeave);
+
 		call(spot.funcLeave);
+
+		_vm->_game->popGlobalCallStack();
+
 		_vm->_inter->animPalette();
 		callTime = _vm->_util->getTimeKey() - startTime;
 
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index e6aec51d4f6..b7498135a48 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -85,6 +85,8 @@ void Inter::executeOpcodeDraw(byte i) {
 void Inter::executeOpcodeFunc(byte i, byte j, OpFuncParams &params) {
 	debugC(1, kDebugFuncOp, "%s:%08d: opcodeFunc %d.%d [0x%X.0x%X] (%s)",
 		   _vm->_game->_curTotFile.c_str(), _vm->_game->_script->pos(), i, j, i, j, getDescOpcodeFunc(i, j));
+	if (debugChannelSet(1, kDebugGameFlow))
+		_vm->_game->_script->_currentOpcodePos = _vm->_game->_script->pos();
 
 	int n = i * 16 + j;
 	if ((i <= 4) && (j <= 15) && _opcodesFunc[n].proc && _opcodesFunc[n].proc->isValid())
@@ -352,8 +354,11 @@ void Inter::callSub(int16 retFlag) {
 		block = _vm->_game->_script->peekByte();
 		if (block == 1)
 			funcBlock(retFlag);
-		else if (block == 2)
+		else if (block == 2) {
+			if (!_vm->_game->_globalFuncCallStack.empty())
+				_vm->_game->_globalFuncCallStack.top().type = kEvaluateHotspots;
 			_vm->_game->_hotspots->evaluate();
+		}
 		else
 			error("Unknown block type %d in Inter::callSub()", block);
 	}
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index b3d21aa2dac..e5911e5dc79 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -736,10 +736,16 @@ void Inter_v1::o1_callSub(OpFuncParams &params) {
 		return;
 	}
 
+	_vm->_game->pushOnGlobalCallStack(kCallSub,
+									  _vm->_game->_curTotFile, _vm->_game->_script->_currentOpcodePos,
+									  _vm->_game->_curTotFile, offset);
+
 	_vm->_game->_script->call(offset);
 
 	if ((params.counter == params.cmdCount) && (params.retFlag == 2)) {
 		_vm->_game->_script->pop(false);
+		if (!_vm->_game->_globalFuncCallStack.empty())
+			_vm->_game->_globalFuncCallStack.top().tailCall = true;
 		params.doReturn = true;
 		return;
 	}
@@ -747,6 +753,7 @@ void Inter_v1::o1_callSub(OpFuncParams &params) {
 	callSub(2);
 
 	_vm->_game->_script->pop();
+	_vm->_game->popGlobalCallStack();
 }
 
 void Inter_v1::o1_printTotText(OpFuncParams &params) {
diff --git a/engines/gob/script.h b/engines/gob/script.h
index 87f37f0b0da..7165dad888a 100644
--- a/engines/gob/script.h
+++ b/engines/gob/script.h
@@ -142,6 +142,8 @@ public:
 
 	static uint32 getVariablesCount(const char *fileName, GobEngine *vm);
 
+	int32 _currentOpcodePos = 0; // for debugging purposes only
+
 private:
 	struct CallEntry {
 		byte *totPtr;




More information about the Scummvm-git-logs mailing list