[Scummvm-git-logs] scummvm branch-2-7 -> 7b42cb65cbbc043acbdd88c1fd63d4909be8fe98

antoniou79 noreply at scummvm.org
Sat Jul 1 09:47:18 UTC 2023


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

Summary:
f59afadade HOPKINS: Fix cursor not scaling in OpenGL
6fc95c0ae8 PINK: PDA open from menu does not change pause level
47f213c64b PINK: Fix localized text encoding
171be660e4 PINK: Clear global game variables on New Game
c1af313371 LASTEXPRESS: Differentiate saved games per target
47d07630ec LASTEXPRESS: Fix compiler warnings and a bad index for entities array
c44c6342c7 LASTEXPRESS: Early support for demo
fc6a6e7833 TOON: Fix another overreading of picture data
a39e1f1a3d TOON: Free memory when movie and subtitles are destroyed
6e211a7949 TOON: Plug mem leak from loading subs resource
a14415209e TOON: Save facing for characters
7b42cb65cb TOON: Fix Picture::drawWithRectList() overreading


Commit: f59afadadeae94f1320e726aa18d4089a1b2f760
    https://github.com/scummvm/scummvm/commit/f59afadadeae94f1320e726aa18d4089a1b2f760
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:45:33+03:00

Commit Message:
HOPKINS: Fix cursor not scaling in OpenGL

Changed paths:
    engines/hopkins/events.cpp


diff --git a/engines/hopkins/events.cpp b/engines/hopkins/events.cpp
index 363d1ddb894..1f606400810 100644
--- a/engines/hopkins/events.cpp
+++ b/engines/hopkins/events.cpp
@@ -522,7 +522,7 @@ void EventsManager::updateCursor() {
 	// Set the ScummVM cursor from the surface
 	CursorMan.replaceCursorPalette(cursorPalette, 0, PALETTE_SIZE - 1);
 	CursorMan.replaceCursor(cursorSurface, _vm->_objectsMan->getObjectWidth(), _vm->_objectsMan->getObjectHeight(),
-		xOffset, 0, 0, true);
+		xOffset, 0, 0, false);
 
 	// Delete the cursor surface and palette
 	delete[] cursorPalette;


Commit: 6fc95c0ae838c00a7d3cc8c149ec5dc393bec152
    https://github.com/scummvm/scummvm/commit/6fc95c0ae838c00a7d3cc8c149ec5dc393bec152
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:45:40+03:00

Commit Message:
PINK: PDA open from menu does not change pause level

Addresses bug #13860 "PINK: Animations will freeze after exiting PDA"

Changed paths:
    engines/pink/objects/actors/lead_actor.cpp
    engines/pink/screen.cpp
    engines/pink/screen.h


diff --git a/engines/pink/objects/actors/lead_actor.cpp b/engines/pink/objects/actors/lead_actor.cpp
index 3206ba10623..466512fd83a 100644
--- a/engines/pink/objects/actors/lead_actor.cpp
+++ b/engines/pink/objects/actors/lead_actor.cpp
@@ -156,7 +156,7 @@ void LeadActor::loadPDA(const Common::String &pageName) {
 	if (_state != kPDA) {
 		if (_state == kMoving)
 			cancelInteraction();
-		if (_state != kInventory)
+		if (_state != kInventory && !_page->getGame()->getScreen()->isMenuActive())
 			_page->pause(true);
 
 		_stateBeforePDA = _state;
@@ -317,8 +317,9 @@ void LeadActor::onPDAClose() {
 	_page->getGame()->getScreen()->loadStage();
 
 	_state = _stateBeforePDA;
+	_stateBeforePDA = kUndefined;
 	if (_state != kInventory)
-		_page->pause(0);
+		_page->pause(false);
 }
 
 bool LeadActor::isInteractingWith(const Actor *actor) const {
diff --git a/engines/pink/screen.cpp b/engines/pink/screen.cpp
index 3505a3d148e..583afccc1a3 100644
--- a/engines/pink/screen.cpp
+++ b/engines/pink/screen.cpp
@@ -233,6 +233,10 @@ void Screen::pause(bool pause_) {
 	}
 }
 
+bool Screen::isMenuActive() {
+	return _wm != nullptr && _wm->isMenuActive();
+}
+
 void Screen::saveStage() {
 	_savedSprites = _sprites;
 	clear();
diff --git a/engines/pink/screen.h b/engines/pink/screen.h
index 52918990673..1055901c588 100644
--- a/engines/pink/screen.h
+++ b/engines/pink/screen.h
@@ -69,6 +69,7 @@ public:
 	void clear();
 
 	void pause(bool pause);
+	bool isMenuActive();
 
 	void saveStage();
 	void loadStage();


Commit: 47f213c64b2ddcea6022c112ad3d38f681598f6b
    https://github.com/scummvm/scummvm/commit/47f213c64b2ddcea6022c112ad3d38f681598f6b
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:45:47+03:00

Commit Message:
PINK: Fix localized text encoding

Should address bugs #13865 and #13866 PINK: German Umlauts not displayed

Also added text encoding support for the other language codes that are in the detection_tables.h for the PINK engine. Namely, IT_ITA, NL_NLD, and EN_GRB. The NL_NLD one I am uncertain about, but according to wikipedia, kWindows1252 should do for Dutch as well. I cannot test for it though.

Changed paths:
    engines/pink/objects/actions/action_text.cpp


diff --git a/engines/pink/objects/actions/action_text.cpp b/engines/pink/objects/actions/action_text.cpp
index 3a42ffacd26..0d5551d57e5 100644
--- a/engines/pink/objects/actions/action_text.cpp
+++ b/engines/pink/objects/actions/action_text.cpp
@@ -100,13 +100,23 @@ void ActionText::start() {
 	screen->getWndManager()._language = language;
 	switch(language) {
 	case Common::DA_DNK:
+		// fall through
 	case Common::ES_ESP:
+		// fall through
 	case Common::FR_FRA:
+		// fall through
 	case Common::PT_BRA:
+		// fall through
+	case Common::DE_DEU:
+		// fall through
+	case Common::IT_ITA:
+		// fall through
+	case Common::NL_NLD:
 		_text = Common::String(str).decode(Common::kWindows1252);
 		break;
 
 	case Common::FI_FIN:
+		// fall through
 	case Common::SE_SWE:
 		_text = Common::String(str).decode(Common::kWindows1257);
 		break;
@@ -126,7 +136,10 @@ void ActionText::start() {
 		_text = Common::String(str).decode(Common::kWindows1251);
 		break;
 
+	case Common::EN_GRB:
+		// fall through
 	case Common::EN_ANY:
+		// fall through
 	default:
 		_text = Common::String(str);
 		break;


Commit: 171be660e489e1268669154d6395bcf10ef557a0
    https://github.com/scummvm/scummvm/commit/171be660e489e1268669154d6395bcf10ef557a0
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:45:54+03:00

Commit Message:
PINK: Clear global game variables on New Game

This addresses the cause for #13869 PINK: Can't pickup the poker in sir Manley's house

However, this will not retroactively fix the broken saved games that carry stale global game variables from other playthroughs
It will also will not set the "appropriate" global game variables if the player uses the debug console to jump to different modules and pages back and forth.

Changed paths:
    engines/pink/constants.h
    engines/pink/cursor_mgr.cpp
    engines/pink/gui.cpp
    engines/pink/objects/module.cpp
    engines/pink/objects/pages/game_page.cpp
    engines/pink/pink.cpp


diff --git a/engines/pink/constants.h b/engines/pink/constants.h
index 91a81ef05a5..f5629671291 100644
--- a/engines/pink/constants.h
+++ b/engines/pink/constants.h
@@ -131,11 +131,6 @@ enum {
 	kPerilPDAClickableSecondFrameCursorID = 143
 };
 
-enum {
-	kLoadingSave = 1,
-	kLoadingNewGame = 0
-};
-
 enum {
 	kOrbMajorVersion = 2,
 	kOrbMinorVersion = 0,
diff --git a/engines/pink/cursor_mgr.cpp b/engines/pink/cursor_mgr.cpp
index c06452d5d74..77fa9544c5d 100644
--- a/engines/pink/cursor_mgr.cpp
+++ b/engines/pink/cursor_mgr.cpp
@@ -34,6 +34,7 @@ CursorMgr::CursorMgr(PinkEngine *game, Page *page)
 void CursorMgr::setCursor(byte index, Common::Point point, const Common::String &itemName) {
 	switch (index) {
 	case kClickableFirstFrameCursor:
+		// fall through
 	case kPDAClickableFirstFrameCursor:
 		startAnimation(index);
 		hideItem();
diff --git a/engines/pink/gui.cpp b/engines/pink/gui.cpp
index d898f567393..3a35d23e4bf 100644
--- a/engines/pink/gui.cpp
+++ b/engines/pink/gui.cpp
@@ -210,8 +210,7 @@ void PinkEngine::executeMenuCommand(uint id) {
 
 	switch (id) {
 	case kNewGameAction: {
-		const Common::String moduleName = _modules[0]->getName();
-		initModule(moduleName, "", nullptr);
+		initModule(_modules[0]->getName(), "", nullptr);
 		break;
 	}
 	case kLoadSave:
diff --git a/engines/pink/objects/module.cpp b/engines/pink/objects/module.cpp
index 45f89bf7c54..a8485fbe4db 100644
--- a/engines/pink/objects/module.cpp
+++ b/engines/pink/objects/module.cpp
@@ -65,7 +65,7 @@ void Module::init(bool isLoadingSave, const Common::String &pageName) {
 void Module::changePage(const Common::String &pageName) {
 	_page->unload();
 	_page = findPage(pageName);
-	_page->init(kLoadingNewGame);
+	_page->init(false);
 }
 
 GamePage *Module::findPage(const Common::String &pageName) const {
diff --git a/engines/pink/objects/pages/game_page.cpp b/engines/pink/objects/pages/game_page.cpp
index 2fedaa0f121..da8f2bc0051 100644
--- a/engines/pink/objects/pages/game_page.cpp
+++ b/engines/pink/objects/pages/game_page.cpp
@@ -185,7 +185,7 @@ void GamePage::unload() {
 
 void GamePage::clear() {
 	Page::clear();
-	_variables.clear(1);
+	_variables.clear(true);
 
 	for (uint i = 0; i < _handlers.size(); ++i) {
 		delete _handlers[i];
diff --git a/engines/pink/pink.cpp b/engines/pink/pink.cpp
index fd55e15c6fd..6d75b4eb61c 100644
--- a/engines/pink/pink.cpp
+++ b/engines/pink/pink.cpp
@@ -187,13 +187,19 @@ void PinkEngine::initModule(const Common::String &moduleName, const Common::Stri
 	if (_module)
 		removeModule();
 
+	if (moduleName == _modules[0]->getName()) {
+		// new game
+		_variables.clear();
+		debugC(6, kPinkDebugGeneral, "Global Game Variables cleared");
+	}
+
 	addModule(moduleName);
 	if (saveFile)
 		_module->loadState(*saveFile);
 
 	debugC(6, kPinkDebugGeneral, "Module added");
 
-	_module->init(saveFile ? kLoadingSave : kLoadingNewGame, pageName);
+	_module->init(saveFile != nullptr, pageName);
 }
 
 void PinkEngine::changeScene() {


Commit: c1af3133711a1de2c9cbc5b17ee9af52f2eed1a0
    https://github.com/scummvm/scummvm/commit/c1af3133711a1de2c9cbc5b17ee9af52f2eed1a0
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:01+03:00

Commit Message:
LASTEXPRESS: Differentiate saved games per target

Saved games still maintain the suffix blue.egg, red.egg, etc but the prefix depends on the current game target

Also support listing of saves, loading from launcher and removal

Changed paths:
    engines/lastexpress/game/savegame.cpp
    engines/lastexpress/game/savegame.h
    engines/lastexpress/lastexpress.cpp
    engines/lastexpress/lastexpress.h
    engines/lastexpress/menu/menu.cpp
    engines/lastexpress/metaengine.cpp
    engines/lastexpress/shared.h


diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 6e4a3a3e2e7..41e843bba6f 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -36,19 +36,20 @@
 #include "lastexpress/lastexpress.h"
 
 #include "common/file.h"
+#include "common/savefile.h"
 
 namespace LastExpress {
 
-// Names of savegames
+// Labels of savegames
 static const struct {
-	const char *saveFile;
-} gameInfo[6] = {
-	{"lastexpress-blue.egg"},
-	{"lastexpress-red.egg"},
-	{"lastexpress-green.egg"},
-	{"lastexpress-purple.egg"},
-	{"lastexpress-teal.egg"},
-	{"lastexpress-gold.egg"}
+	const char *label;
+} gameLabel[SaveLoad::kMaximumSaveSlots] = {
+	{"blue"},
+	{"red"},
+	{"green"},
+	{"purple"},
+	{"teal"},
+	{"gold"}
 };
 
 //////////////////////////////////////////////////////////////////////////
@@ -361,10 +362,10 @@ void SaveLoad::initStream() {
 	_savegame = new SavegameStream();
 }
 
-void SaveLoad::flushStream(GameId id) {
-	Common::OutSaveFile *save = openForSaving(id);
+void SaveLoad::flushStream(const Common::String &target, GameId id) {
+	Common::OutSaveFile *save = openForSaving(target, id);
 	if (!save)
-		error("[SaveLoad::flushStream] Cannot open savegame (%s)", getFilename(id).c_str());
+		error("[SaveLoad::flushStream] Cannot open savegame (%s)", getFilename(target, id).c_str());
 
 	if (!_savegame)
 		error("[SaveLoad::flushStream] Savegame stream is invalid");
@@ -378,21 +379,20 @@ void SaveLoad::flushStream(GameId id) {
 //////////////////////////////////////////////////////////////////////////
 // Init
 //////////////////////////////////////////////////////////////////////////
-void SaveLoad::create(GameId id) {
+void SaveLoad::create(const Common::String &target, GameId id) {
 	initStream();
 
 	Common::Serializer ser(nullptr, _savegame);
 	SavegameMainHeader header;
 	header.saveLoadWithSerializer(ser);
-
-	flushStream(id);
+	flushStream(target, id);
 }
 
-uint32 SaveLoad::init(GameId id, bool resetHeaders) {
+uint32 SaveLoad::init(const Common::String &target, GameId id, bool resetHeaders) {
 	initStream();
 
 	// Load game data
-	loadStream(id);
+	loadStream(target, id);
 
 	// Get the main header
 	Common::Serializer ser(_savegame, nullptr);
@@ -435,8 +435,8 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) {
 	return mainHeader.count;
 }
 
-void SaveLoad::loadStream(GameId id) {
-	Common::InSaveFile *save = openForLoading(id);
+void SaveLoad::loadStream(const Common::String &target, GameId id) {
+	Common::InSaveFile *save = openForLoading(target, id);
 	if (save->size() < 32)
 		error("[SaveLoad::loadStream] Savegame seems to be corrupted (not enough data: %i bytes)", (int)save->size());
 
@@ -490,7 +490,7 @@ void SaveLoad::loadLastGame() {
 	// Validate main header
 	SavegameMainHeader header;
 	if (!loadMainHeader(_savegame, &header)) {
-		debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
+		debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(_engine->getTargetName(), getMenu()->getGameId()).c_str());
 		return;
 	}
 
@@ -510,7 +510,6 @@ void SaveLoad::loadLastGame() {
 
 		readEntry(&type, &entity, &val, false);
 	}
-
 	getEntities()->reset();
 	getEntities()->setup(false, entity);
 }
@@ -550,7 +549,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
 	// Validate main header
 	SavegameMainHeader header;
 	if (!loadMainHeader(_savegame, &header)) {
-		debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
+		debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(_engine->getTargetName(), getMenu()->getGameId()).c_str());
 		return;
 	}
 
@@ -612,7 +611,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
 	Common::Serializer ser(nullptr, _savegame);
 	header.saveLoadWithSerializer(ser);
 
-	flushStream(getMenu()->getGameId());
+	flushStream(_engine->getTargetName(), getMenu()->getGameId());
 }
 
 void SaveLoad::saveVolumeBrightness() {
@@ -799,7 +798,12 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
 	// Skip padding
 	uint32 offset = (uint32)_savegame->pos() - originalPosition;
 	if (offset & 0xF) {
-		_savegame->seek((~offset & 0xF) + 1, SEEK_CUR);
+		// (offset & 0xF) is a value in [0, 15]; the remainder of division of offset with 16.
+		// Entering here, that remainder is not zero so, with the following code, we skip the padding
+		// by seeking ahead (forward) from SEEK_CUR for the amount of the bytes required to complete
+		// a full 16 bytes final segment for the entity entry that we are reading.
+		// That is: 16 - (offset & 0xF)  or equivalently: (~offset & 0xF) + 1) bytes skipped ahead.
+		_savegame->seek(16 - (offset & 0xF), SEEK_CUR);
 	}
 }
 
@@ -810,28 +814,53 @@ SaveLoad::SavegameEntryHeader *SaveLoad::getEntry(uint32 index) {
 	return _gameHeaders[index];
 }
 
+SaveStateList SaveLoad::list(const MetaEngine *metaEngine, const Common::String &target) {
+	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+	Common::StringArray files = saveFileMan->listSavefiles(target + "*.egg");
+
+	SaveStateList saveList;
+	for (Common::StringArray::const_iterator fileName = files.begin(); fileName != files.end(); ++fileName) {
+		for (int i = 0; i < kMaximumSaveSlots; ++i) {
+			// Do another more accurate filtering (than the more generic pattern used with listSavefiles() above)
+			// of save file names here
+			if (*fileName == getFilename(target, (GameId)i)) {
+				Common::InSaveFile *saveFile = saveFileMan->openForLoading(*fileName);
+				if (saveFile != nullptr && !saveFile->err()) {
+					saveList.push_back(SaveStateDescriptor(metaEngine, i, gameLabel[i].label));
+				}
+				delete saveFile;
+				break;
+			}
+		}
+	}
+
+	Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+
+	return saveList;
+}
+
 //////////////////////////////////////////////////////////////////////////
 // Checks
 //////////////////////////////////////////////////////////////////////////
 
 // Check if a specific savegame exists
-bool SaveLoad::isSavegamePresent(GameId id) {
-	if (g_system->getSavefileManager()->listSavefiles(getFilename(id)).size() == 0)
+bool SaveLoad::isSavegamePresent(const Common::String &target, GameId id) {
+	if (g_system->getSavefileManager()->listSavefiles(getFilename(target, id)).size() == 0)
 		return false;
 
 	return true;
 }
 
 // Check if the game has been started in the specific savegame
-bool SaveLoad::isSavegameValid(GameId id) {
-	if (!isSavegamePresent(id)) {
-		debugC(2, kLastExpressDebugSavegame, "Savegame does not exist: %s", getFilename(id).c_str());
+bool SaveLoad::isSavegameValid(const Common::String &target, GameId id) {
+	if (!isSavegamePresent(target, id)) {
+		debugC(2, kLastExpressDebugSavegame, "Savegame does not exist: %s", getFilename(target, id).c_str());
 		return false;
 	}
 
 	SavegameMainHeader header;
 
-	Common::InSaveFile *save = openForLoading(id);
+	Common::InSaveFile *save = openForLoading(target, id);
 	bool isHeaderValid = loadMainHeader(save, &header);
 	delete save;
 
@@ -886,29 +915,34 @@ bool SaveLoad::isGameFinished(uint32 menuIndex, uint32 savegameIndex) {
 //////////////////////////////////////////////////////////////////////////
 
 // Get the file name from the savegame ID
-Common::String SaveLoad::getFilename(GameId id) {
-	if (id >= 6)
-		error("[SaveLoad::getFilename] Attempting to use an invalid game id. Valid values: 0 - 5, was %d", id);
+Common::String SaveLoad::getFilename(const Common::String &target, GameId id) {
+	if (id < 0 || id >= kMaximumSaveSlots)
+		error("[SaveLoad::getFilename] Attempting to use an invalid game id. Valid values: 0 - %d, was %d", kMaximumSaveSlots - 1, id);
 
-	return gameInfo[id].saveFile;
+	return target + "-" + gameLabel[id].label + ".egg";
 }
 
-Common::InSaveFile *SaveLoad::openForLoading(GameId id) {
-	Common::InSaveFile *load = g_system->getSavefileManager()->openForLoading(getFilename(id));
+Common::InSaveFile *SaveLoad::openForLoading(const Common::String &target, GameId id) {
+	Common::InSaveFile *load = g_system->getSavefileManager()->openForLoading(getFilename(target, id));
 
 	if (!load)
-		debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for loading: %s", getFilename(id).c_str());
+		debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for loading: %s", getFilename(target, id).c_str());
 
 	return load;
 }
 
-Common::OutSaveFile *SaveLoad::openForSaving(GameId id) {
-	Common::OutSaveFile *save = g_system->getSavefileManager()->openForSaving(getFilename(id), false); // TODO Enable compression again
+Common::OutSaveFile *SaveLoad::openForSaving(const Common::String &target, GameId id) {
+	Common::OutSaveFile *save = g_system->getSavefileManager()->openForSaving(getFilename(target, id), false); // TODO Enable compression again
 
 	if (!save)
-		debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for writing: %s", getFilename(id).c_str());
+		debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for writing: %s", getFilename(target, id).c_str());
 
 	return save;
 }
 
+void SaveLoad::remove(const Common::String &target, GameId id) {
+	Common::String filename = getFilename(target, id);
+	g_system->getSavefileManager()->removeSavefile(filename);
+}
+
 } // End of namespace LastExpress
diff --git a/engines/lastexpress/game/savegame.h b/engines/lastexpress/game/savegame.h
index 3afe284d4e4..2f7152ccc34 100644
--- a/engines/lastexpress/game/savegame.h
+++ b/engines/lastexpress/game/savegame.h
@@ -76,6 +76,8 @@
 #include "common/serializer.h"
 #include "common/memstream.h"
 
+#include "engines/savestate.h"
+
 namespace LastExpress {
 
 // our own hack until compression code will be confirmed stable
@@ -146,13 +148,15 @@ private:
 
 class SaveLoad {
 public:
+	static const int kMaximumSaveSlots = 6; // blue, red, green, purple, teal, gold
+
 	SaveLoad(LastExpressEngine *engine);
 	~SaveLoad();
 
 	// Init
-	void create(GameId id);
+	void create(const Common::String &target, GameId id);
 	void clear(bool clearStream = false);
-	uint32 init(GameId id, bool resetHeaders);
+	uint32 init(const Common::String &target, GameId id, bool resetHeaders);
 
 	// Save & Load
 	void loadLastGame();
@@ -162,9 +166,17 @@ public:
 	void loadVolumeBrightness();
 	void saveVolumeBrightness();
 
+	static SaveStateList list(const MetaEngine *metaEngine, const Common::String &target);
+	static void remove(const Common::String &target, GameId slot);
+
+	// Opening save files
+	static Common::String getFilename(const Common::String &target, GameId slot);
+	static Common::InSaveFile *openForLoading(const Common::String &target, GameId slot);
+	static Common::OutSaveFile *openForSaving(const Common::String &target, GameId slot);
+
 	// Getting information
-	static bool isSavegamePresent(GameId id);
-	static bool isSavegameValid(GameId id);
+	static bool isSavegamePresent(const Common::String &target, GameId id);
+	static bool isSavegameValid(const Common::String &target, GameId id);
 
 	bool isGameFinished(uint32 menuIndex, uint32 savegameIndex);
 
@@ -195,7 +207,7 @@ private:
 			keepIndex = 0;
 			brightness = 3;
 			volume = 7;
-			field_1C = 9;
+			field_1C = 9; // Note: In demo's original save "BLUE.EGG" this value is 0x19
 		}
 
 		void saveLoadWithSerializer(Common::Serializer &s) override {
@@ -281,7 +293,7 @@ private:
 			if (time < kTimeStartGame || time > kTimeCityConstantinople)
 				return false;
 
-			if (offset <= 0 || offset & 15)
+			if (offset <= 0 || offset & 0xF)
 				return false;
 
 			/* No check for < 0, as it cannot happen normaly */
@@ -308,15 +320,10 @@ private:
 
 	SavegameEntryHeader *getEntry(uint32 index);
 
-	// Opening save files
-	static Common::String getFilename(GameId id);
-	static Common::InSaveFile  *openForLoading(GameId id);
-	static Common::OutSaveFile *openForSaving(GameId id);
-
 	// Savegame stream
 	void initStream();
-	void loadStream(GameId id);
-	void flushStream(GameId id);
+	void loadStream(const Common::String &target, GameId id);
+	void flushStream(const Common::String &target, GameId id);
 
 	// Misc
 	EntityIndex _entity;
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 14137dbee5e..b86d7f75398 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -91,6 +91,10 @@ LastExpressEngine::~LastExpressEngine() {
 	_gameDescription = nullptr;
 }
 
+Common::String LastExpressEngine::getTargetName() const {
+	return _targetName;
+}
+
 // TODO: which error should we return when some game files are missing/corrupted?
 Common::Error LastExpressEngine::run() {
 	// Initialize the graphics
diff --git a/engines/lastexpress/lastexpress.h b/engines/lastexpress/lastexpress.h
index 4938066ba23..86e7ef15635 100644
--- a/engines/lastexpress/lastexpress.h
+++ b/engines/lastexpress/lastexpress.h
@@ -101,6 +101,8 @@ public:
 
 	bool isDemo() const;
 
+	Common::String getTargetName() const;
+
 	// Frame Counter
 	// TODO: all callers could use _system->getMillis() directly without extra conversions
 	uint32 getFrameCounter() const;
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index 6fb2f515d26..249c1a7b95e 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -48,7 +48,7 @@
 
 #include "common/rational.h"
 
-#define getNextGameId() (GameId)((_gameId + 1) % 6)
+#define getNextGameId() (GameId)((_gameId + 1) % SaveLoad::kMaximumSaveSlots)
 
 namespace LastExpress {
 
@@ -303,7 +303,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
 
 	// If no blue savegame exists, this might be the first time we start the game, so we show the full intro
 	if (!getFlags()->mouseRightClick) {
-		if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
+		if (!SaveLoad::isSavegameValid(_engine->getTargetName(), kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
 
 			if (!_hasShownIntro) {
 				// Show Broderbrund logo
@@ -448,7 +448,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
 			cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2;
 
 		// Show tooltips & buttons to start a game, continue a game or load the proper cd
-		if (ResourceManager::isArchivePresent(cd)) {
+		if (_engine->getResourceManager()->isArchivePresent(cd)) {
 			if (_isGameStarted) {
 				showFrame(kOverlayEggButtons, kButtonContinue, true);
 
@@ -562,7 +562,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
 			break;
 		}
 
-		if (!SaveLoad::isSavegameValid(getNextGameId())) {
+		if (!SaveLoad::isSavegameValid(_engine->getTargetName(), getNextGameId())) {
 			showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
 			break;
 		}
@@ -829,7 +829,6 @@ void Menu::setLogicEventHandlers() {
 // Game-related
 //////////////////////////////////////////////////////////////////////////
 void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
-
 	bool useSameIndex = true;
 
 	if (getGlobalTimer()) {
@@ -853,7 +852,7 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
 			break;
 		}
 
-		if (ResourceManager::isArchivePresent(index)) {
+		if (_engine->getResourceManager()->isArchivePresent(index)) {
 			setGlobalTimer(0);
 			useSameIndex = false;
 
@@ -867,8 +866,8 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
 	}
 
 	// Create a new savegame if needed
-	if (!SaveLoad::isSavegamePresent(_gameId))
-		getSaveLoad()->create(_gameId);
+	if (!SaveLoad::isSavegamePresent(_engine->getTargetName(), _gameId))
+		getSaveLoad()->create(_engine->getTargetName(), _gameId);
 
 	if (doSavegame)
 		getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone);
@@ -878,7 +877,7 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
 	}
 
 	// Init savegame & menu values
-	_lastIndex = getSaveLoad()->init(_gameId, true);
+	_lastIndex = getSaveLoad()->init(_engine->getTargetName(), _gameId, true);
 	_lowerTime = getSaveLoad()->getTime(_lastIndex);
 
 	if (useSameIndex)
@@ -928,12 +927,12 @@ void Menu::startGame() {
 // Switch to the next savegame
 void Menu::switchGame() {
 
-	// Switch back to blue game is the current game is not started
-	_gameId = SaveLoad::isSavegameValid(_gameId) ? getNextGameId() : kGameBlue;
+	// Switch back to blue game if the current game is not started
+	_gameId = SaveLoad::isSavegameValid(_engine->getTargetName(), _gameId) ? getNextGameId() : kGameBlue;
 
 	// Initialize savegame if needed
-	if (!SaveLoad::isSavegamePresent(_gameId))
-		getSaveLoad()->create(_gameId);
+	if (!SaveLoad::isSavegamePresent(_engine->getTargetName(), _gameId))
+		getSaveLoad()->create(_engine->getTargetName(), _gameId);
 
 	getState()->time = kTimeNone;
 
diff --git a/engines/lastexpress/metaengine.cpp b/engines/lastexpress/metaengine.cpp
index 95a36b74093..63f546eb4aa 100644
--- a/engines/lastexpress/metaengine.cpp
+++ b/engines/lastexpress/metaengine.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "lastexpress/lastexpress.h"
+#include "lastexpress/game/savegame.h"
 #include "engines/advancedDetector.h"
 
 namespace LastExpress {
@@ -30,6 +31,12 @@ public:
 		return "lastexpress";
 	}
 
+	bool hasFeature(MetaEngineFeature f) const override;
+
+	SaveStateList listSaves(const char *target) const override;
+	int getMaximumSaveSlot() const override;
+	void removeSaveState(const char *target, int slot) const override;
+
 protected:
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
 };
@@ -43,6 +50,24 @@ bool LastExpressEngine::isDemo() const {
 	return (bool)(_gameDescription->flags & ADGF_DEMO);
 }
 
+bool LastExpressMetaEngine::hasFeature(MetaEngineFeature f) const {
+	return f == kSupportsListSaves
+	    || f == kSupportsLoadingDuringStartup
+	    || f == kSupportsDeleteSave;
+}
+
+SaveStateList LastExpressMetaEngine::listSaves(const char *target) const {
+	return LastExpress::SaveLoad::list(this, target);
+}
+
+int LastExpressMetaEngine::getMaximumSaveSlot() const {
+	return LastExpress::SaveLoad::kMaximumSaveSlots - 1;
+}
+
+void LastExpressMetaEngine::removeSaveState(const char *target, int slot) const {
+	LastExpress::SaveLoad::remove(target, (LastExpress::GameId)slot);
+}
+
 } // End of namespace LastExpress
 
 #if PLUGIN_ENABLED_DYNAMIC(LASTEXPRESS)
diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h
index 9c852e2498b..850f660b936 100644
--- a/engines/lastexpress/shared.h
+++ b/engines/lastexpress/shared.h
@@ -573,7 +573,7 @@ enum CityIndex {
 // Savegame ID
 //////////////////////////////////////////////////////////////////////////
 enum GameId {
-	kGameBlue,
+	kGameBlue = 0,
 	kGameRed,
 	kGameGreen,
 	kGamePurple,


Commit: 47d07630ec64849e6ce8adf37ccf1d59aed9f641
    https://github.com/scummvm/scummvm/commit/47d07630ec64849e6ce8adf37ccf1d59aed9f641
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:07+03:00

Commit Message:
LASTEXPRESS: Fix compiler warnings and a bad index for entities array

Compiler warnings were about uninitialized variables

Changed paths:
    engines/lastexpress/entities/entity.cpp
    engines/lastexpress/game/scenes.cpp
    engines/lastexpress/game/state.h
    engines/lastexpress/sound/entry.cpp


diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp
index 3b56d00d124..7ecfd123fd2 100644
--- a/engines/lastexpress/entities/entity.cpp
+++ b/engines/lastexpress/entities/entity.cpp
@@ -159,7 +159,7 @@ void EntityData::saveLoadWithSerializer(Common::Serializer &s, const Common::Arr
 		// (the original game has same-size-PODs and just memcpy-s them.
 		// *sigh* Why does this implementation even need the extra byte in strings?
 		// Well, big-endian vs little-endian is also a thing...)
-		byte buf[ARRAYSIZE(_parameters) * 32 * 4];
+		byte buf[ARRAYSIZE(_parameters) * 32 * 4] = {0};
 		s.syncBytes(buf, sizeof(buf));
 
 		_data.saveLoadWithSerializer(s);
diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp
index 1cd57a85b21..7be3cc46955 100644
--- a/engines/lastexpress/game/scenes.cpp
+++ b/engines/lastexpress/game/scenes.cpp
@@ -1115,14 +1115,14 @@ void SceneManager::postProcessScene() {
 		// If several entities are there, choose one to sound "Excuse me"
 		EntityPosition entityPosition = getEntityData(kEntityPlayer)->entityPosition;
 		if (getEntityData(kEntityPlayer)->car == kCar9 && (entityPosition == kPosition_4 || entityPosition == kPosition_3)) {
-			EntityIndex entities[39];
+			EntityIndex entities[40] = {(EntityIndex)0};
 
 			// Init entities
 			entities[0] = kEntityPlayer;
 
 			uint progress = 0;
 
-			for (uint i = 1; i < 40 /* number of entities */; i++) {
+			for (uint i = 1; i < 40 /* number of entities */; ++i) {
 				CarIndex car = getEntityData((EntityIndex)i)->car;
 				EntityPosition position = getEntityData((EntityIndex)i)->entityPosition;
 
diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h
index 61fba00ed98..83eccab9c25 100644
--- a/engines/lastexpress/game/state.h
+++ b/engines/lastexpress/game/state.h
@@ -474,7 +474,7 @@ public:
 		void saveLoadWithSerializer(Common::Serializer &s) override {
 			if (s.isLoading()) {
 				for (uint i = 0; i < 128; i++) {
-					uint32 val;
+					uint32 val = 0;
 					s.syncAsUint32LE(val);
 					getOrSetValueName(i, NULL, &val);
 				}
diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp
index 78dfec52517..59033040f3e 100644
--- a/engines/lastexpress/sound/entry.cpp
+++ b/engines/lastexpress/sound/entry.cpp
@@ -346,18 +346,18 @@ void SoundEntry::setSubtitles(Common::String filename) {
 void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) {
 	if (s.isLoading()) {
 		// load the fields
-		uint32 blocksLeft;
+		uint32 blocksLeft = 0;
 
 		s.syncAsUint32LE(_status);
 		s.syncAsUint32LE(_tag);
 		s.syncAsUint32LE(blocksLeft);
 		s.syncAsUint32LE(_startTime);
-		uint32 unused;
+		uint32 unused = 0;
 		s.syncAsUint32LE(unused);
 		s.syncAsUint32LE(unused);
 		s.syncAsUint32LE(_entity);
 
-		uint32 activateDelay;
+		uint32 activateDelay = 0;
 		s.syncAsUint32LE(activateDelay);
 		s.syncAsUint32LE(_priority);
 


Commit: c44c6342c710bb51d6744d3cac62b677033363c7
    https://github.com/scummvm/scummvm/commit/c44c6342c710bb51d6744d3cac62b677033363c7
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:14+03:00

Commit Message:
LASTEXPRESS: Early support for demo

Demo launches but the init state needs more work

Changed paths:
    engines/lastexpress/entities/chapters.cpp
    engines/lastexpress/game/entities.cpp
    engines/lastexpress/game/savegame.cpp
    engines/lastexpress/menu/clock.cpp
    engines/lastexpress/menu/menu.cpp
    engines/lastexpress/resource.cpp
    engines/lastexpress/resource.h


diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp
index a5424063ba7..01ac87db266 100644
--- a/engines/lastexpress/entities/chapters.cpp
+++ b/engines/lastexpress/entities/chapters.cpp
@@ -867,7 +867,12 @@ IMPLEMENT_FUNCTION(13, Chapters, chapter3)
 		}
 
 		// Set game time & delta
-		getState()->time = kTimeChapter3;
+		// TODO This check and code (for demo case) may be removed in the future
+		if (_engine->isDemo()){
+			getState()->time = kTime2241000;
+		} else {
+			getState()->time = kTimeChapter3;
+		}
 		getState()->timeDelta = 5;
 
 		setup_chapter3Init();
diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp
index ca35efec2d4..3f82e012d24 100644
--- a/engines/lastexpress/game/entities.cpp
+++ b/engines/lastexpress/game/entities.cpp
@@ -262,7 +262,14 @@ void Entities::saveCompartments(Common::Serializer &s) {
 // Setup
 //////////////////////////////////////////////////////////////////////////
 void Entities::setup(bool isFirstChapter, EntityIndex entityIndex) {
-	setupChapter(isFirstChapter ? kChapter1 : kChapterAll);
+	// TODO This check and code (for demo case) may be removed in the future
+	if (_engine->isDemo()) {
+		setupChapter(kChapter3);
+		// TODO Should this be set for the demo?
+		//isFirstChapter = false;
+	} else {
+		setupChapter(isFirstChapter ? kChapter1 : kChapterAll);
+	}
 
 	bool flag_4 = false;
 
@@ -300,8 +307,7 @@ void Entities::setupChapter(ChapterIndex chapter) {
 
 	// we skip the header when doing entity setup
 	for (uint i = 1; i < _entities.size(); i++) {
-		// Special case of chapters (prevents infinite loop as we will be called from Chapters functions when changing chapters)
-		if (i == kEntityChapters && chapter >= 2)
+		if (i == kEntityChapters && chapter >= 2 && !_engine->isDemo())
 			continue;
 
 		_entities[i]->setup(chapter);
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 41e843bba6f..3ed1edfac1b 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -406,9 +406,14 @@ uint32 SaveLoad::init(const Common::String &target, GameId id, bool resetHeaders
 		clear();
 
 		SavegameEntryHeader *entryHeader = new SavegameEntryHeader();
-		entryHeader->time = kTimeCityParis;
-		entryHeader->chapter = kChapter1;
-
+		// TODO This check and code (for demo case) may be removed in the future 
+		if (_engine->isDemo()) {
+			entryHeader->time = kTime2241000;
+			entryHeader->chapter = kChapter3;
+		} else {
+			entryHeader->time = kTimeCityParis;
+			entryHeader->chapter = kChapter1;
+		}
 		_gameHeaders.push_back(entryHeader);
 	}
 
diff --git a/engines/lastexpress/menu/clock.cpp b/engines/lastexpress/menu/clock.cpp
index 7aee60be6e2..0651bead4bc 100644
--- a/engines/lastexpress/menu/clock.cpp
+++ b/engines/lastexpress/menu/clock.cpp
@@ -35,15 +35,19 @@ namespace LastExpress {
 Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(nullptr), _frameHour(nullptr), _frameSun(nullptr), _frameDate(nullptr) {
 	_frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true);
 	_frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true);
-	_frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
-	_frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
+	if (!_engine->isDemo()) {
+		_frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
+		_frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
+	}
 }
 
 Clock::~Clock() {
 	SAFE_DELETE(_frameMinutes);
 	SAFE_DELETE(_frameHour);
-	SAFE_DELETE(_frameSun);
-	SAFE_DELETE(_frameDate);
+	if (!_engine->isDemo()) {
+		SAFE_DELETE(_frameSun);
+		SAFE_DELETE(_frameDate);
+	}
 
 	// Zero passed pointers
 	_engine = nullptr;
@@ -52,15 +56,17 @@ Clock::~Clock() {
 void Clock::clear() {
 	getScenes()->removeFromQueue(_frameMinutes);
 	getScenes()->removeFromQueue(_frameHour);
-	getScenes()->removeFromQueue(_frameSun);
-	getScenes()->removeFromQueue(_frameDate);
+	if (!_engine->isDemo()) {
+		getScenes()->removeFromQueue(_frameSun);
+		getScenes()->removeFromQueue(_frameDate);
+	}
 }
 
 void Clock::draw(uint32 time) {
 	assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
 
 	// Check that sequences have been loaded
-	if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate)
+	if (!_frameMinutes || !_frameHour || (!_engine->isDemo() && !_frameSun) || (!_engine->isDemo() && !_frameDate))
 		error("[Clock::draw] Clock sequences have not been loaded correctly");
 
 	// Clear existing frames
@@ -87,19 +93,25 @@ void Clock::draw(uint32 time) {
 	// Set sequences frames
 	_frameMinutes->setFrame(minute);
 	_frameHour->setFrame((5 * hour + minute / 12) % 60);
-	_frameSun->setFrame((5 * hour + minute / 12) % 120);
-	_frameDate->setFrame((uint16)index_date);
+	if (!_engine->isDemo()) {
+		_frameSun->setFrame((5 * hour + minute / 12) % 120);
+		_frameDate->setFrame((uint16)index_date);
+	}
 
 	// Adjust z-order and queue
 	_frameMinutes->getInfo()->location = 1;
 	_frameHour->getInfo()->location = 1;
-	_frameSun->getInfo()->location = 1;
-	_frameDate->getInfo()->location = 1;
+	if (!_engine->isDemo()) {
+		_frameSun->getInfo()->location = 1;
+		_frameDate->getInfo()->location = 1;
+	}
 
 	getScenes()->addToQueue(_frameMinutes);
 	getScenes()->addToQueue(_frameHour);
-	getScenes()->addToQueue(_frameSun);
-	getScenes()->addToQueue(_frameDate);
+	if (!_engine->isDemo()) {
+		getScenes()->addToQueue(_frameSun);
+		getScenes()->addToQueue(_frameDate);
+	}
 }
 
 } // End of namespace LastExpress
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index 249c1a7b95e..04e2bd85d85 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -148,12 +148,16 @@ Menu::Menu(LastExpressEngine *engine) : _engine(engine),
 	_currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) {
 
 	_clock = new Clock(_engine);
-	_trainLine = new TrainLine(_engine);
+	if (!_engine->isDemo()) {
+		_trainLine = new TrainLine(_engine);
+	}
 }
 
 Menu::~Menu() {
 	SAFE_DELETE(_clock);
-	SAFE_DELETE(_trainLine);
+	if (!_engine->isDemo()) {
+		SAFE_DELETE(_trainLine);
+	}
 
 	SAFE_DELETE(_seqTooltips);
 	SAFE_DELETE(_seqEggButtons);
@@ -303,7 +307,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
 
 	// If no blue savegame exists, this might be the first time we start the game, so we show the full intro
 	if (!getFlags()->mouseRightClick) {
-		if (!SaveLoad::isSavegameValid(_engine->getTargetName(), kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
+		if (!SaveLoad::isSavegameValid(_engine->getTargetName(), kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1) && !_engine->isDemo()) {
 
 			if (!_hasShownIntro) {
 				// Show Broderbrund logo
@@ -534,17 +538,18 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
 		}
 
 		if (clicked) {
-			showFrame(kOverlayAcorn, 1, true);
-			showFrame(kOverlayTooltip, -1, true);
-			getSound()->playSound(kEntityPlayer, "LIB047");
+			if (!_engine->isDemo()) {
+				showFrame(kOverlayAcorn, 1, true);
+				showFrame(kOverlayTooltip, -1, true);
+				getSound()->playSound(kEntityPlayer, "LIB047");
 
-			// Setup new menu screen
-			switchGame();
-			setup();
-
-			// Set fight state to 0
-			getFight()->resetState();
+				// Setup new menu screen
+				switchGame();
+				setup();
 
+				// Set fight state to 0
+				getFight()->resetState();
+			}
 			return true;
 		}
 
@@ -552,7 +557,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
 
 		showFrame(kOverlayAcorn, 0, true);
 
-		if (_isGameStarted) {
+		if (_isGameStarted && !_engine->isDemo()) {
 			showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
 			break;
 		}
@@ -562,7 +567,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
 			break;
 		}
 
-		if (!SaveLoad::isSavegameValid(_engine->getTargetName(), getNextGameId())) {
+		if (_engine->isDemo() || !SaveLoad::isSavegameValid(_engine->getTargetName(), getNextGameId())) {
 			showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
 			break;
 		}
@@ -886,8 +891,13 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
 	//if (!getGlobalTimer())
 	//	_index3 = 0;
 
-	if (!getProgress().chapter)
-		getProgress().chapter = kChapter1;
+	if (!getProgress().chapter) {
+		if (_engine->isDemo()) {
+			getProgress().chapter = kChapter3;
+		} else {
+			getProgress().chapter = kChapter1;
+		}
+	}
 
 	getState()->time = (TimeValue)getSaveLoad()->getTime(_index);
 	getProgress().chapter = getSaveLoad()->getChapter(_index);
@@ -896,7 +906,9 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
 		_currentTime = (uint32)getState()->time;
 		_time = (uint32)getState()->time;
 		_clock->draw(_time);
-		_trainLine->draw(_time);
+		if (!_engine->isDemo()) {
+			_trainLine->draw(_time);
+		}
 
 		initTime(type, value);
 	}
@@ -909,7 +921,9 @@ void Menu::startGame() {
 
 	// Hide menu elements
 	_clock->clear();
-	_trainLine->clear();
+	if (!_engine->isDemo()) {
+		_trainLine->clear();
+	}
 
 	if (_lastIndex == _index) {
 		setGlobalTimer(0);
@@ -917,6 +931,11 @@ void Menu::startGame() {
 			getSaveLoad()->loadLastGame();
 		} else {
 			getLogic()->resetState();
+			// TODO This check and code (for demo case) may be removed in the future
+			if (_engine->isDemo()) {
+				getState()->time = kTime2241000;
+				getProgress().chapter = kChapter3;
+			}
 			getEntities()->setup(true, kEntityPlayer);
 		}
 	} else {
@@ -938,7 +957,9 @@ void Menu::switchGame() {
 
 	// Clear menu elements
 	_clock->clear();
-	_trainLine->clear();
+	if (!_engine->isDemo()) {
+		_trainLine->clear();
+	}
 
 	// Clear loaded savegame data
 	getSaveLoad()->clear(true);
@@ -1006,6 +1027,10 @@ void Menu::clear() {
 
 // Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame
 Common::String Menu::getAcornSequenceName(GameId id) const {
+	if (_engine->isDemo()) {
+		return "aconred.seq";
+	}
+
 	Common::String name = "";
 	switch (id) {
 	default:
@@ -1252,7 +1277,9 @@ void Menu::adjustTime() {
 		getSoundQueue()->stop(kEntityChapters);
 
 	_clock->draw(_time);
-	_trainLine->draw(_time);
+	if (!_engine->isDemo()) {
+		_trainLine->draw(_time);
+	}
 	getScenes()->drawFrames(true);
 
 	adjustIndex(_time, originalTime, true);
diff --git a/engines/lastexpress/resource.cpp b/engines/lastexpress/resource.cpp
index 6db05257e4d..a835daffa47 100644
--- a/engines/lastexpress/resource.cpp
+++ b/engines/lastexpress/resource.cpp
@@ -47,6 +47,10 @@ ResourceManager::~ResourceManager() {
 }
 
 bool ResourceManager::isArchivePresent(ArchiveIndex type) {
+	// Demo version
+	if (_isDemo)
+		return Common::File::exists(archiveDemoPath);
+
 	switch (type) {
 	default:
 	case kArchiveAll:
diff --git a/engines/lastexpress/resource.h b/engines/lastexpress/resource.h
index 676492179b7..1df32e9afdf 100644
--- a/engines/lastexpress/resource.h
+++ b/engines/lastexpress/resource.h
@@ -40,7 +40,7 @@ public:
 
 	// Loading
 	bool loadArchive(ArchiveIndex type);
-	static bool isArchivePresent(ArchiveIndex type);
+	bool isArchivePresent(ArchiveIndex type);
 	Common::SeekableReadStream *getFileStream(const Common::String &name) const;
 
 	// Archive functions


Commit: fc6a6e7833236dbd6116ae6e5ddd18c72c10e107
    https://github.com/scummvm/scummvm/commit/fc6a6e7833236dbd6116ae6e5ddd18c72c10e107
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:24+03:00

Commit Message:
TOON: Fix another overreading of picture data

This was in Picture::floodFillNotWalkableOnMask() and only needed reordering of the logic AND clauses

Changed paths:
    engines/toon/picture.cpp


diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 26c964150f4..f3ad4f42af5 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -118,7 +118,6 @@ bool Picture::loadPicture(const Common::String &file) {
 		uint32 decSize = READ_BE_UINT32(fileData + 4);
 
 		_data = new uint8[decSize];
-
 		decSize = rnc.unpackM2(fileData, _data);
 
 		if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
@@ -282,21 +281,23 @@ void Picture::floodFillNotWalkableOnMask(int16 x, int16 y) {
 		pt.y++;
 		bool spanLeft = false;
 		bool spanRight = false;
-		while (_data[pt.x + pt.y * _width] & 0x1F && pt.y < _height) {
-			_data[pt.x + pt.y * _width] &= 0xE0;
-			if (!spanLeft && pt.x > 0 && _data[pt.x - 1 + pt.y * _width] & 0x1F) {
+		uint32 nextDataPos = pt.x + pt.y * _width;
+		while (pt.y < _height && _data[nextDataPos] & 0x1F) {
+			_data[nextDataPos] &= 0xE0;
+			if (!spanLeft && pt.x > 0 && _data[nextDataPos - 1] & 0x1F) {
 				stack.push(Common::Point(pt.x - 1, pt.y));
 				spanLeft = 1;
-			} else if (spanLeft && pt.x > 0 && !(_data[pt.x - 1 + pt.y * _width] & 0x1F)) {
+			} else if (spanLeft && pt.x > 0 && !(_data[nextDataPos - 1] & 0x1F)) {
 				spanLeft = 0;
 			}
-			if (!spanRight && pt.x < _width - 1 && _data[pt.x + 1 + pt.y * _width] & 0x1F) {
+			if (!spanRight && pt.x < _width - 1 && _data[nextDataPos + 1] & 0x1F) {
 				stack.push(Common::Point(pt.x + 1, pt.y));
 				spanRight = 1;
-			} else if (spanRight && pt.x < _width - 1 && !(_data[pt.x + 1 + pt.y * _width] & 0x1F)) {
+			} else if (spanRight && pt.x < _width - 1 && !(_data[nextDataPos + 1] & 0x1F)) {
 				spanRight = 0;
 			}
 			pt.y++;
+			nextDataPos = pt.x + pt.y * _width;
 		}
 	}
 }


Commit: a39e1f1a3d64a75ff42c3b3a782d6a30aed88c06
    https://github.com/scummvm/scummvm/commit/a39e1f1a3d64a75ff42c3b3a782d6a30aed88c06
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:31+03:00

Commit Message:
TOON: Free memory when movie and subtitles are destroyed

Leaks reported when running with aSan

Changed paths:
    engines/toon/movie.cpp
    engines/toon/subtitles.cpp


diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index 97be1be1902..ad5c180587e 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -72,6 +72,7 @@ Movie::Movie(ToonEngine *vm , ToonstruckSmackerDecoder *decoder) {
 
 Movie::~Movie() {
 	delete _decoder;
+	delete _subtitle;
 }
 
 void Movie::init() const {
diff --git a/engines/toon/subtitles.cpp b/engines/toon/subtitles.cpp
index 332c70654c1..e43a19386be 100644
--- a/engines/toon/subtitles.cpp
+++ b/engines/toon/subtitles.cpp
@@ -33,6 +33,10 @@ SubtitleRenderer::SubtitleRenderer(ToonEngine *vm) : _vm(vm) {
 }
 
 SubtitleRenderer::~SubtitleRenderer() {
+	if (_subSurface) {
+		_subSurface->free();
+		delete _subSurface;
+	}
 }
 
 


Commit: 6e211a79494cefbc20edda65208ec13e96eea11c
    https://github.com/scummvm/scummvm/commit/6e211a79494cefbc20edda65208ec13e96eea11c
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:40+03:00

Commit Message:
TOON: Plug mem leak from loading subs resource

This was also reported when running with aSan

Changed paths:
    engines/toon/resource.cpp
    engines/toon/subtitles.cpp


diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 6d1316ebbfe..6394ac41905 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -78,7 +78,7 @@ void Resources::addToCache(const Common::String &packName, const Common::String
 	_cacheSize += fileSize;
 
 	while (_cacheSize > MAX_CACHE_SIZE) {
-		CacheEntry *bestEntry = 0;
+		CacheEntry *bestEntry = nullptr;
 		for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
 			if ((*entry)->_data) {
 				if (!bestEntry || ((*entry)->_age >= bestEntry->_age && (*entry)->_size >= bestEntry->_size)) {
@@ -90,7 +90,7 @@ void Resources::addToCache(const Common::String &packName, const Common::String
 			break;
 
 		free(bestEntry->_data);
-		bestEntry->_data = 0;
+		bestEntry->_data = nullptr;
 		_cacheSize -= bestEntry->_size;
 		debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size);
 	}
@@ -153,7 +153,7 @@ uint8 *Resources::getFileData(const Common::String &fileName, uint32 *fileSize)
 		Common::File file;
 		bool opened = file.open(fileName);
 		if (!opened)
-			return 0;
+			return nullptr;
 
 		*fileSize = file.size();
 		uint8 *memory = (uint8 *)new uint8[*fileSize];
@@ -164,7 +164,7 @@ uint8 *Resources::getFileData(const Common::String &fileName, uint32 *fileSize)
 	} else {
 
 		uint32 locFileSize = 0;
-		uint8 *locFileData = 0;
+		uint8 *locFileData = nullptr;
 
 		if (getFromCache(fileName, &locFileSize, &locFileData)) {
 			*fileSize = locFileSize;
@@ -180,7 +180,7 @@ uint8 *Resources::getFileData(const Common::String &fileName, uint32 *fileSize)
 				return locFileData;
 			}
 		}
-		return 0;
+		return nullptr;
 	}
 }
 
@@ -190,22 +190,23 @@ Common::SeekableReadStream *Resources::openFile(const Common::String &fileName)
 	// first try to find files outside of .pak
 	// some patched files have not been included in package.
 	if (Common::File::exists(fileName)) {
-		Common::File *file = new Common::File();
-		bool opened = file->open(fileName);
-		if (!opened) {
-			delete file;
-			return 0;
+		Common::File file;
+		if (file.open(fileName)) {
+			Common::SeekableReadStream *stream = file.readStream(file.size());
+			file.close();
+			return stream;
+		} else {
+			return nullptr;
 		}
-		return file;
 	} else {
 		for (uint32 i = 0; i < _pakFiles.size(); i++) {
-			Common::SeekableReadStream *stream = 0;
+			Common::SeekableReadStream *stream = nullptr;
 			stream = _pakFiles[i]->createReadStream(fileName);
 			if (stream)
 				return stream;
 		}
 
-		return 0;
+		return nullptr;
 	}
 }
 
@@ -224,7 +225,7 @@ Common::SeekableReadStream *PakFile::createReadStream(const Common::String &file
 	if (buffer)
 		return new Common::MemoryReadStream(buffer, fileSize, DisposeAfterUse::YES);
 	else
-		return 0;
+		return nullptr;
 }
 
 uint8 *PakFile::getFileData(const Common::String &fileName, uint32 *fileSize) {
diff --git a/engines/toon/subtitles.cpp b/engines/toon/subtitles.cpp
index e43a19386be..194434d9140 100644
--- a/engines/toon/subtitles.cpp
+++ b/engines/toon/subtitles.cpp
@@ -75,8 +75,8 @@ bool SubtitleRenderer::load(const Common::String &video) {
 	Common::String ext("tss");
 	subfile.replace(subfile.size() - ext.size(), ext.size(), ext);
 
-	Common::SeekableReadStream *file = _vm->resources()->openFile(subfile);
-	if (!file) {
+	Common::ScopedPtr<Common::SeekableReadStream> subsStream(_vm->resources()->openFile(subfile));
+	if (subsStream == nullptr) {
 		return false;
 	}
 
@@ -84,8 +84,8 @@ bool SubtitleRenderer::load(const Common::String &video) {
 	int lineNo = 0;
 
 	_tw.clear();
-	while (!file->eos() && !file->err()) {
-		line = file->readLine();
+	while (!subsStream->eos() && !subsStream->err()) {
+		line = subsStream->readLine();
 
 		lineNo++;
 		if (line.empty() || line[0] == '#') {


Commit: a14415209ea41f4e9da33a7426c936dd2d8e10e5
    https://github.com/scummvm/scummvm/commit/a14415209ea41f4e9da33a7426c936dd2d8e10e5
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:48+03:00

Commit Message:
TOON: Save facing for characters

Saved game version increased to 6

Also added some comments and minor code formatting changes

Changed paths:
    engines/toon/anim.cpp
    engines/toon/character.cpp
    engines/toon/character.h
    engines/toon/drew.cpp
    engines/toon/script.cpp
    engines/toon/toon.cpp
    engines/toon/toon.h


diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index 92df787829f..d9652cf6d78 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -273,7 +273,7 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
 			int16 xs = (x - xx1) * 1024 / scale;
 			int16 ys = (y - yy1) * 1024 / scale;
 			// TODO Maybe check if we overread c here
-//			assert(ys * w + xs >= 0 && ys * w + xs <  _frames[dataFrame]._dataSize)
+//			assert(ys * w + xs >= 0 && ys * w + xs <  _frames[dataFrame]._dataSize);
 			uint8 cc = c[ys * w + xs];
 
 			if (cc && nextMaskPos < maskDataSize && (*(curRowMask + nextMaskPos)) >= zz) {
@@ -456,7 +456,7 @@ void AnimationInstance::update(int32 timeIncrement) {
 AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type) : _vm(vm) {
 	_id = 0;
 	_type = type;
-	_animation = 0;
+	_animation = nullptr;
 	_currentFrame = 0;
 	_currentTime = 0;
 	_fps = 15;
@@ -476,7 +476,7 @@ AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type)
 
 void AnimationInstance::render() {
 	debugC(5, kDebugAnim, "AnimationInstance::render()");
-	if (_visible && _animation) {
+	if (_visible && _animation != nullptr) {
 		int32 frame = _currentFrame;
 		if (frame < 0)
 			frame = 0;
@@ -509,7 +509,7 @@ void AnimationInstance::render() {
 
 void AnimationInstance::renderOnPicture() {
 	debugC(5, kDebugAnim, "renderOnPicture()");
-	if (_visible && _animation)
+	if (_visible && _animation != nullptr)
 		_animation->drawFrameOnPicture(_currentFrame, _x, _y);
 }
 
@@ -541,7 +541,7 @@ void AnimationInstance::setAnimationRange(int32 rangeStart, int32 rangeEnd) {
 
 void AnimationInstance::setPosition(int16 x, int16 y, int32 z, bool relative) {
 	debugC(5, kDebugAnim, "setPosition(%d, %d, %d, %d)", x, y, z, (relative) ? 1 : 0);
-	if (relative || !_animation) {
+	if (relative || _animation == nullptr) {
 		_x = x;
 		_y = y;
 		_z = z;
@@ -614,7 +614,7 @@ void AnimationInstance::getRect(int16 *x1, int16 *y1, int16 *x2, int16 *y2) cons
 
 void AnimationInstance::setX(int16 x, bool relative) {
 	debugC(1, kDebugAnim, "setX(%d, %d)", x, (relative) ? 1 : 0);
-	if (relative || !_animation)
+	if (relative || _animation == nullptr)
 		_x = x;
 	else
 		_x = x - _animation->_x1;
@@ -622,7 +622,7 @@ void AnimationInstance::setX(int16 x, bool relative) {
 
 void AnimationInstance::setY(int16 y, bool relative) {
 	debugC(1, kDebugAnim, "setY(%d, %d)", y, (relative) ? 1 : 0);
-	if (relative || !_animation)
+	if (relative || _animation == nullptr)
 		_y = y;
 	else
 		_y = y - _animation->_y1;
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index ae33fba4f1e..e776006ed7d 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -100,7 +100,7 @@ void Character::setFacing(int32 facing) {
 	if (_blockingWalk) {
 		_flags |= 2;
 
-		_currentFacingStamp++;
+		++_currentFacingStamp;
 		int32 localFacingStamp = _currentFacingStamp;
 
 		int32 dir = 0;
@@ -165,11 +165,13 @@ void Character::setPosition(int16 x, int16 y) {
 bool Character::walkTo(int16 newPosX, int16 newPosY) {
 	debugC(1, kDebugCharacter, "walkTo(%d, %d)", newPosX, newPosY);
 
-	if (!_visible)
+	if (!_visible) {
 		return true;
+	}
 
-	if (_x == newPosX && _y == newPosY)
+	if (_x == newPosX && _y == newPosY) {
 		return true;
+	}
 
 	_vm->getPathFinding()->resetBlockingRects();
 
@@ -181,8 +183,9 @@ bool Character::walkTo(int16 newPosX, int16 newPosY) {
 	}
 
 	_vm->getPathFinding()->findClosestWalkingPoint(newPosX, newPosY, &_finalX, &_finalY, _x, _y);
-	if (_x == _finalX && _y == _finalY)
+	if (_x == _finalX && _y == _finalY) {
 		return true;
+	}
 
 	if (_vm->getPathFinding()->findPath(_x, _y, _finalX, _finalY)) {
 
@@ -192,7 +195,7 @@ bool Character::walkTo(int16 newPosX, int16 newPosY) {
 		int32 smoothDy = 0;
 
 		_currentPath.clear();
-		for (uint32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); a++)
+		for (uint32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); ++a)
 			_currentPath.push_back(Common::Point(_vm->getPathFinding()->getPathNodeX(a), _vm->getPathFinding()->getPathNodeY(a)));
 		_currentPathNode = 0;
 		stopSpecialAnim();
@@ -203,7 +206,7 @@ bool Character::walkTo(int16 newPosX, int16 newPosY) {
 
 		_flags |= 0x1;
 
-		_currentWalkStamp++;
+		++_currentWalkStamp;
 
 		int32 localWalkStamp = _currentWalkStamp;
 
@@ -240,7 +243,7 @@ bool Character::walkTo(int16 newPosX, int16 newPosY) {
 				while (_numPixelToWalk >= 1000 && _currentPathNode < _currentPath.size()) {
 					_x = _currentPath[_currentPathNode].x;
 					_y = _currentPath[_currentPathNode].y;
-					_currentPathNode += 1;
+					++_currentPathNode;
 					_numPixelToWalk -= 1000;
 				}
 				setPosition(_x, _y);
@@ -376,7 +379,7 @@ void Character::update(int32 timeIncrement) {
 			while (_numPixelToWalk > 1000 && _currentPathNode < _currentPath.size()) {
 				_x = _currentPath[_currentPathNode].x;
 				_y = _currentPath[_currentPathNode].y;
-				_currentPathNode += 1;
+				++_currentPathNode;
 				_numPixelToWalk -= 1000;
 			}
 			setPosition(_x, _y);
@@ -569,12 +572,12 @@ int32 Character::getFacingFromDirection(int16 dx, int16 dy) {
 		ydiff = xdiff;
 		xdiff = temp;
 	} else
-		facingEntry++;
+		++facingEntry;
 
 	facingEntry *= 2;
 
 	if (xdiff < ((ydiff + 1) / 2))
-		facingEntry++;
+		++facingEntry;
 
 	return facingTable[facingEntry];
 }
@@ -612,6 +615,7 @@ void Character::save(Common::WriteStream *stream) {
 	stream->writeSint32LE(_z);
 	stream->writeSint32LE(_finalX);
 	stream->writeSint32LE(_finalY);
+	stream->writeSint32LE(_facing); // Introduced in save game version 6 and greater
 	stream->writeSint32LE(_scale);
 	stream->writeSint32LE(_id);
 
@@ -621,7 +625,7 @@ void Character::save(Common::WriteStream *stream) {
 	stream->writeSint32LE(_sceneAnimationId);
 }
 
-void Character::load(Common::ReadStream *stream) {
+void Character::load(Common::ReadStream *stream, int32 saveGameVersion) {
 	debugC(1, kDebugCharacter, "read(stream)");
 
 	_flags = stream->readSint32LE();
@@ -632,6 +636,9 @@ void Character::load(Common::ReadStream *stream) {
 	_z = stream->readSint32LE();
 	_finalX = stream->readSint32LE();
 	_finalY = stream->readSint32LE();
+	if (saveGameVersion >= 6) {
+		_facing = stream->readSint32LE();
+	}
 	_scale = stream->readSint32LE();
 	_id = stream->readSint32LE();
 
@@ -1304,7 +1311,7 @@ bool Character::loadShadowAnimation(const Common::String &animName) {
 }
 
 void Character::plotPath(Graphics::Surface& surface) {
-	for (uint32 i = 0; i < _currentPath.size(); i++) {
+	for (uint32 i = 0; i < _currentPath.size(); ++i) {
 		 *(byte *)surface.getBasePtr(_currentPath[i].x, _currentPath[i].y) = (i < _currentPathNode);
 	}
 }
diff --git a/engines/toon/character.h b/engines/toon/character.h
index 7a28106f3b6..d5999a8af74 100644
--- a/engines/toon/character.h
+++ b/engines/toon/character.h
@@ -90,7 +90,7 @@ public:
 	virtual AnimationInstance *getAnimationInstance();
 	virtual void setAnimationInstance(AnimationInstance *instance);
 	virtual void save(Common::WriteStream *stream);
-	virtual void load(Common::ReadStream *stream);
+	virtual void load(Common::ReadStream *stream, int32 saveGameVersion);
 	virtual void stopWalk();
 	virtual void stopSpecialAnim();
 	virtual void updateIdle();
diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp
index 23f0e1b0846..ec6af6df09a 100644
--- a/engines/toon/drew.cpp
+++ b/engines/toon/drew.cpp
@@ -40,7 +40,7 @@ CharacterDrew::~CharacterDrew() {
 bool CharacterDrew::setupPalette() {
 	debugC(1, kDebugCharacter, "setupPalette()");
 
-	if (_walkAnim) {
+	if (_walkAnim != nullptr) {
 		_walkAnim->applyPalette(129, 129 * 3, 63);
 		return true;
 	}
diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp
index 01cb1848a77..4707951ee5d 100644
--- a/engines/toon/script.cpp
+++ b/engines/toon/script.cpp
@@ -178,27 +178,31 @@ bool EMCInterpreter::start(EMCState *script, int function) {
 }
 
 bool EMCInterpreter::isValid(EMCState *script) {
-	if (!script->ip || !script->dataPtr || _vm->shouldQuitGame())
+	if (script->ip == nullptr || script->dataPtr == nullptr || _vm->shouldQuitGame())
 		return false;
 	return true;
 }
 
 bool EMCInterpreter::run(EMCState *script) {
-	if (script->running)
+	if (script->running) {
+		// Prevents nested call of same (already running script)
 		return false;
+	}
 
 	_parameter = 0;
 
-	if (!script->ip)
+	if (script->ip == nullptr) {
 		return false;
+	}
 
 	script->running = true;
 
 	// Should be no Problem at all to cast to uint32 here, since that's the biggest ptrdiff the original
 	// would allow, of course that's not realistic to happen to be somewhere near the limit of uint32 anyway.
+	// instOffset is the offset of currect instruction from the start of the script data
 	const uint32 instOffset = (uint32)((const byte *)script->ip - (const byte *)script->dataPtr->data);
-	int16 code = *script->ip++;
-	int16 opcode = (code >> 8) & 0x1F;
+	int16 code = *script->ip++; // get the next instruction (and increase instruction pointer)
+	int16 opcode = (code >> 8) & 0x1F; // get the opCode from the instruction
 
 	if (code & 0x8000) {
 		opcode = 0;
@@ -215,15 +219,15 @@ bool EMCInterpreter::run(EMCState *script) {
 		error("Unknown script opcode: %d in file '%s' at offset 0x%.08X", opcode, script->dataPtr->filename, instOffset);
 	} else {
 		static bool EMCDebug = false;
-		if (EMCDebug)
+		if (EMCDebug) {
 			debugC(5, 0, "[0x%.08X] EMCInterpreter::%s([%d/%u])", instOffset * 2, _opcodes[opcode].desc, _parameter, (uint)_parameter);
-		//printf( "[0x%.08X] EMCInterpreter::%s([%d/%u])\n", instOffset, _opcodes[opcode].desc, _parameter, (uint)_parameter);
+			//printf( "[0x%.08X] EMCInterpreter::%s([%d/%u])\n", instOffset, _opcodes[opcode].desc, _parameter, (uint)_parameter);
+		}
 
 		(this->*(_opcodes[opcode].proc))(script);
 	}
-
 	script->running = false;
-	return (script->ip != 0);
+	return (script->ip != nullptr);
 }
 
 #pragma mark -
@@ -241,17 +245,21 @@ void EMCInterpreter::op_setRetValue(EMCState *script) {
 void EMCInterpreter::op_pushRetOrPos(EMCState *script) {
 	switch (_parameter) {
 	case 0:
+		// store retValue in next free stack slot (from 99 moving "downwards" to 0)
 		script->stack[--script->sp] = script->retValue;
 		break;
 
 	case 1:
+		// store offset of next instruction (from script->dataPtr->data) in stack slot
+		// store script->bp in stack slot
+		// set script->bp to current free stack slot + 2 (essentially it's the stack slot before we pushed here)
 		script->stack[--script->sp] = script->ip - script->dataPtr->data + 1;
 		script->stack[--script->sp] = script->bp;
 		script->bp = script->sp + 2;
 		break;
 
 	default:
-		script->ip = 0;
+		script->ip = nullptr;
 	}
 }
 
@@ -279,15 +287,20 @@ void EMCInterpreter::op_popRetOrPos(EMCState *script) {
 
 	case 1:
 		if (script->sp >= EMCState::kStackLastEntry) {
-			script->ip = 0;
+			// Nothing to pop
+			script->ip = nullptr;
 		} else {
+			// set the base "pointer" to the value of script->stack[] of the script->sp slot (entry)
+			// and increase the script->sp slot index (it now points to a slot with the value of the offset used below).
+			// script->ip is set to point at an offset of stack[script->sp] after dataPtr->data.
+			// and increase (again) the script->sp slot index.
 			script->bp = script->stack[script->sp++];
 			script->ip = script->dataPtr->data + script->stack[script->sp++];
 		}
 		break;
 
 	default:
-		script->ip = 0;
+		script->ip = nullptr;
 	}
 }
 
@@ -352,7 +365,7 @@ void EMCInterpreter::op_negate(EMCState *script) {
 
 	default:
 		warning("Unknown negation func: %d", _parameter);
-		script->ip = 0;
+		script->ip = nullptr;
 	}
 }
 
@@ -442,14 +455,14 @@ void EMCInterpreter::op_eval(EMCState *script) {
 	}
 
 	if (error)
-		script->ip = 0;
+		script->ip = nullptr;
 	else
 		script->stack[--script->sp] = ret;
 }
 
 void EMCInterpreter::op_setRetAndJmp(EMCState *script) {
 	if (script->sp >= EMCState::kStackLastEntry) {
-		script->ip = 0;
+		script->ip = nullptr;
 	} else {
 		script->retValue = script->stack[script->sp++];
 		uint16 temp = script->stack[script->sp++];
@@ -461,7 +474,7 @@ void EMCInterpreter::op_setRetAndJmp(EMCState *script) {
 void EMCInterpreter::saveState(EMCState *script, Common::WriteStream *stream) {
 	stream->writeSint16LE(script->bp);
 	stream->writeSint16LE(script->sp);
-	if (!script->ip) {
+	if (script->ip == nullptr) {
 		stream->writeSint16LE(-1);
 	} else {
 		stream->writeSint16LE(script->ip - script->dataPtr->data);
@@ -484,7 +497,7 @@ void EMCInterpreter::loadState(EMCState *script, Common::ReadStream *stream) {
 
 	int16 scriptIp = stream->readSint16LE();
 	if (scriptIp == -1) {
-		script->ip = 0;
+		script->ip = nullptr;
 	} else {
 		script->ip = scriptIp + script->dataPtr->data;
 	}
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 43d01070998..c96c85fd548 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -112,7 +112,7 @@ void ToonEngine::init() {
 	// load subtitles if available (if fails to load it only return false, so there's no need to check)
 	resources()->openPackage("SUBTITLES.PAK");
 
-	for (int32 i = 0; i < 32; i++)
+	for (int32 i = 0; i < 32; ++i)
 		_characters[i] = nullptr;
 
 	_characters[0] = new CharacterDrew(this);
@@ -293,11 +293,10 @@ void ToonEngine::disableTimer(int32 timerId) {
 	_gameState->_timerEnabled[timerId] = false;
 }
 void ToonEngine::updateTimers() {
-	for (int32 i = 0; i < 2; i++) {
+	for (int32 i = 0; i < 2; ++i) {
 		if (_gameState->_timerEnabled[i]) {
 			if (_gameState->_timerDelay[i] > -1 && getOldMilli() > _gameState->_timerTimeout[i]) {
 				if (i == 0) {
-
 					EMCState *status = &_scriptState[_currentScriptRegion];
 					_script->init(status, &_scriptData);
 
@@ -306,13 +305,13 @@ void ToonEngine::updateTimers() {
 					status->regs[1] = _mouseY;
 					status->regs[2] = 0;
 
-					_currentScriptRegion++;
+					++_currentScriptRegion;
 
 					_script->start(status, 7);
 					while (_script->run(status))
 						waitForScriptStep();
 
-					_currentScriptRegion--;
+					--_currentScriptRegion;
 
 					_gameState->_timerTimeout[i] = getOldMilli() + _gameState->_timerDelay[i] * getTickLength();
 
@@ -483,18 +482,18 @@ void ToonEngine::doMagnifierEffect() {
 	};
 
 	byte tempBuffer[25 * 25];
-	for (int32 y = -12; y <= 12; y++) {
+	for (int32 y = -12; y <= 12; ++y) {
 		int32 cy = CLIP<int32>(posY + y, 0, TOON_BACKBUFFER_HEIGHT-1);
-		for (int32 x = -12; x <= 12; x++) {
+		for (int32 x = -12; x <= 12; ++x) {
 			int32 cx = CLIP<int32>(posX + x, 0, TOON_BACKBUFFER_WIDTH-1);
 			uint8 *curRow = (uint8 *)surface.getBasePtr(cx, cy);
 			tempBuffer[(y + 12) * 25 + x + 12] = *curRow;
 		}
 	}
 
-	for (int32 y = -12; y <= 12; y++) {
+	for (int32 y = -12; y <= 12; ++y) {
 		int32 cy = CLIP<int32>(posY + y, 0, TOON_BACKBUFFER_HEIGHT-1);
-		for (int32 x = -12; x <= 12; x++) {
+		for (int32 x = -12; x <= 12; ++x) {
 			int32 dist = y * y + x * x;
 			if (dist > 144)
 				continue;
@@ -524,7 +523,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
 	} else {
 
 		int32 offX = 0;
-		for (uint i = 0; i < _oldDirtyRects.size(); i++) {
+		for (uint i = 0; i < _oldDirtyRects.size(); ++i) {
 			Common::Rect rect = _oldDirtyRects[i];
 			rect.translate(-state()->_currentScrollValue, 0);
 			offX = 0;
@@ -540,7 +539,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
 			}
 		}
 
-		for (uint i = 0; i < _dirtyRects.size(); i++) {
+		for (uint i = 0; i < _dirtyRects.size(); ++i) {
 			Common::Rect rect = _dirtyRects[i];
 			rect.translate(-state()->_currentScrollValue, 0);
 			offX = 0;
@@ -1606,11 +1605,11 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
 	_locationDirVisited = nullptr;
 	_specialInfoLine = nullptr;
 
-	for (int i = 0; i < 64; i++) {
+	for (int i = 0; i < 64; ++i) {
 		_sceneAnimations[i]._active = false;
 	}
 
-	for (int i = 0; i < 32; i++) {
+	for (int i = 0; i < 32; ++i) {
 		_characters[i] = nullptr;
 	}
 
@@ -1640,7 +1639,7 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
 		break;
 	}
 
-	for (int i = 0; i < 64; i++) {
+	for (int i = 0; i < 64; ++i) {
 		_sceneAnimationScripts[i]._lastTimer = 0;
 		_sceneAnimationScripts[i]._frozen = false;
 		_sceneAnimationScripts[i]._frozenForConversation = false;
@@ -1672,7 +1671,7 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
 
 	_numVariant = 0;
 	_currentCutaway = nullptr;
-	for (int i = 0; i < 4; i++) {
+	for (int i = 0; i < 4; ++i) {
 		_scriptState[i].ip = nullptr;
 		_scriptState[i].dataPtr = nullptr;
 		_scriptState[i].retValue = 0;
@@ -1726,11 +1725,11 @@ ToonEngine::~ToonEngine() {
 
 	delete _pathFinding;
 
-	for (int32 i = 0; i < 64; i++) {
+	for (int32 i = 0; i < 64; ++i) {
 		if (_sceneAnimations[i]._active) {
 			// see if one character shares this instance
-			for (int32 c = 0; c < 32; c++) {
-				if (_characters[c] && _characters[c]->getAnimationInstance() == _sceneAnimations[i]._animInstance) {
+			for (int32 c = 0; c < 32; ++c) {
+				if (_characters[c] != nullptr && _characters[c]->getAnimationInstance() == _sceneAnimations[i]._animInstance) {
 					_characters[c]->setAnimationInstance(0);
 				}
 			}
@@ -1739,7 +1738,7 @@ ToonEngine::~ToonEngine() {
 		}
 	}
 
-	for (int32 i = 0; i < 32; i++)
+	for (int32 i = 0; i < 32; ++i)
 		delete _characters[i];
 
 	delete _cursorAnimation;
@@ -1788,7 +1787,7 @@ void ToonEngine::simpleUpdate(bool waitCharacterToTalk) {
 
 void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
 	// some color values are coded on 6bits ( for old 6bits DAC )
-	for (int32 i = 0; i < num * 3; i++) {
+	for (int32 i = 0; i < num * 3; ++i) {
 		int32 a = palette[i];
 		a = a * 4;
 		if (a > 255)
@@ -1800,7 +1799,7 @@ void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
 // adapted from KyraEngine
 void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
 	static int32 numReentrant = 0;
-	numReentrant++;
+	++numReentrant;
 	const int startScript = _lastProcessedSceneScript;
 
 	_updatingSceneScriptRunFlag = true;
@@ -1811,13 +1810,15 @@ void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
 			_animationSceneScriptRunFlag = true;
 
 			while (_animationSceneScriptRunFlag && _sceneAnimationScripts[_lastProcessedSceneScript]._lastTimer <= _system->getMillis() && !_shouldQuit) {
-				if (!_script->run(&_sceneAnimationScripts[_lastProcessedSceneScript]._state))
+				if (!_script->run(&_sceneAnimationScripts[_lastProcessedSceneScript]._state)) {
 					_animationSceneScriptRunFlag = false;
+				}
 
 				//waitForScriptStep();
 
-				if (_sceneAnimationScripts[_lastProcessedSceneScript]._frozen || _sceneAnimationScripts[_lastProcessedSceneScript]._frozenForConversation)
+				if (_sceneAnimationScripts[_lastProcessedSceneScript]._frozen || _sceneAnimationScripts[_lastProcessedSceneScript]._frozenForConversation) {
 					break;
+				}
 			}
 
 		}
@@ -1828,13 +1829,15 @@ void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
 		}
 
 		++_lastProcessedSceneScript;
-		if (_lastProcessedSceneScript >= state()->_locations[state()->_currentScene]._numSceneAnimations)
+		if (_lastProcessedSceneScript >= state()->_locations[state()->_currentScene]._numSceneAnimations) {
+			// cycle around
 			_lastProcessedSceneScript = 0;
+		}
 
 	} while (_lastProcessedSceneScript != startScript && !_shouldQuit);
 
 	_updatingSceneScriptRunFlag = false;
-	numReentrant--;
+	--numReentrant;
 }
 
 void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
@@ -1863,8 +1866,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
 		} while ((flag & 1) == 0);
 	}
 
-	for (int32 i = 0; i < 8; i++) {
-		if (_characters[i]) _characters[i]->setFlag(0);
+	for (int32 i = 0; i < 8; ++i) {
+		if (_characters[i] != nullptr)
+			_characters[i]->setFlag(0);
 	}
 	_drew->playStandingAnim();
 	_drew->setVisible(true);
@@ -1982,7 +1986,7 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
 	//_script->RoomScript->Decompile("decomp.txt");
 	//RoomScript->Decompile2("decomp2.txt");
 
-	for (int i = 0; i < state()->_locations[SceneId]._numSceneAnimations; i++) {
+	for (int i = 0; i < state()->_locations[SceneId]._numSceneAnimations; ++i) {
 		_sceneAnimationScripts[i]._data = &_scriptData;
 		_script->init(&_sceneAnimationScripts[i]._state, _sceneAnimationScripts[i]._data);
 		if (!forGameLoad) {
@@ -2174,13 +2178,13 @@ int32 ToonEngine::runEventScript(int32 x, int32 y, int32 mode, int32 id, int32 s
 	status->regs[7] = mode;
 	status->regs[8] = id;
 
-	_currentScriptRegion++;
+	++_currentScriptRegion;
 
 	_script->start(status, 1);
-	while (_script->run(status) && !_shouldQuit)
+	while (_script->run(status) && !_shouldQuit) {
 		waitForScriptStep();
-
-	_currentScriptRegion--;
+	}
+	--_currentScriptRegion;
 
 	return status->regs[2];
 }
@@ -2462,15 +2466,15 @@ void ToonEngine::exitScene() {
 	fadeOut(5);
 
 	// disable all scene animation
-	for (int32 i = 0; i < 64; i++) {
+	for (int32 i = 0; i < 64; ++i) {
 		if (_sceneAnimations[i]._active) {
 			delete _sceneAnimations[i]._animation;
 			_sceneAnimations[i]._active = false;
 			_animationManager->removeInstance(_sceneAnimations[i]._animInstance);
 
 			// see if one character shares this instance
-			for (int32 c = 0; c < 32; c++) {
-				if (_characters[c] && _characters[c]->getAnimationInstance() == _sceneAnimations[i]._animInstance) {
+			for (int32 c = 0; c < 32; ++c) {
+				if (_characters[c] != nullptr && _characters[c]->getAnimationInstance() == _sceneAnimations[i]._animInstance) {
 					_characters[c]->setAnimationInstance(nullptr);
 				}
 			}
@@ -2481,28 +2485,28 @@ void ToonEngine::exitScene() {
 			_sceneAnimations[i]._originalAnimInstance = nullptr;
 		}
 	}
-	for (int32 i = 0; i < 64; i++) {
+	for (int32 i = 0; i < 64; ++i) {
 		_sceneAnimationScripts[i]._frozen = true;
 		_sceneAnimationScripts[i]._active = false;
 	}
 
 	// remove all characters except drew and flux
-	for (int32 i = 0; i < 8; i++) {
+	for (int32 i = 0; i < 8; ++i) {
 		if (_characters[i] != _drew && _characters[i] != _flux) {
-			if (_characters[i]) {
+			if (_characters[i] != nullptr) {
 				delete _characters[i];
-				_characters[i] = 0;
+				_characters[i] = nullptr;
 			}
 		} else {
 			_characters[i]->stopSpecialAnim();
 		}
 	}
 
-	for (int32 i = 0; i < 2; i++) {
+	for (int32 i = 0; i < 2; ++i) {
 		_gameState->_timerEnabled[i] = false;
 	}
 
-	// put back our item if inventory if needed
+	// put back our item in inventory if needed
 	if (_gameState->_mouseState >= 0) {
 		addItemToInventory(_gameState->_mouseState);
 		_gameState->_mouseState = -1;
@@ -2542,10 +2546,10 @@ void ToonEngine::flipScreens() {
 }
 
 void ToonEngine::fadeIn(int32 numFrames) {
-	for (int32 f = 0; f < numFrames; f++) {
+	for (int32 f = 0; f < numFrames; ++f) {
 
 		uint8 vmpalette[3 * 256];
-		for (int32 i = 0; i < 256; i++) {
+		for (int32 i = 0; i < 256; ++i) {
 			vmpalette[i * 3 + 0] = f * _finalPalette[i * 3 + 0] / (numFrames - 1);
 			vmpalette[i * 3 + 1] = f * _finalPalette[i * 3 + 1] / (numFrames - 1);
 			vmpalette[i * 3 + 2] = f * _finalPalette[i * 3 + 2] / (numFrames - 1);
@@ -2561,9 +2565,9 @@ void ToonEngine::fadeOut(int32 numFrames) {
 	uint8 oldpalette[3 * 256];
 	_system->getPaletteManager()->grabPalette(oldpalette, 0, 256);
 
-	for (int32 f = 0; f < numFrames; f++) {
+	for (int32 f = 0; f < numFrames; ++f) {
 		uint8 vmpalette[3 * 256];
-		for (int32 i = 0; i < 256; i++) {
+		for (int32 i = 0; i < 256; ++i) {
 			vmpalette[i * 3 + 0] = (numFrames - f - 1) * oldpalette[i * 3 + 0] / (numFrames - 1);
 			vmpalette[i * 3 + 1] = (numFrames - f - 1) * oldpalette[i * 3 + 1] / (numFrames - 1);
 			vmpalette[i * 3 + 2] = (numFrames - f - 1) * oldpalette[i * 3 + 2] / (numFrames - 1);
@@ -2668,7 +2672,7 @@ void ToonEngine::storeRifFlags(int32 location) {
 		_gameState->_locations[location]._numRifBoxes = _hotspots->getCount();
 	}
 
-	for (int32 i = 0; i < _hotspots->getCount(); i++) {
+	for (int32 i = 0; i < _hotspots->getCount(); ++i) {
 		_gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->get(i)->getData(4);
 		_gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->get(i)->getData(7);
 	}
@@ -2677,7 +2681,7 @@ void ToonEngine::storeRifFlags(int32 location) {
 void ToonEngine::restoreRifFlags(int32 location) {
 	if (_hotspots) {
 		if (!_gameState->_locations[location]._visited) {
-			for (int32 i = 0; i < _hotspots->getCount(); i++) {
+			for (int32 i = 0; i < _hotspots->getCount(); ++i) {
 				_gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->get(i)->getData(4);
 				_gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->get(i)->getData(7);
 			}
@@ -2686,7 +2690,7 @@ void ToonEngine::restoreRifFlags(int32 location) {
 			if (_gameState->_locations[location]._numRifBoxes != _hotspots->getCount())
 				return;
 
-			for (int32 i = 0; i < _hotspots->getCount(); i++) {
+			for (int32 i = 0; i < _hotspots->getCount(); ++i) {
 				_hotspots->get(i)->setData(4, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0]);
 				_hotspots->get(i)->setData(7, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1]);
 			}
@@ -2712,7 +2716,7 @@ void ToonEngine::sayLines(int numLines, int dialogId) {
 
 	int32 currentLine = dialogId;
 
-	for (int32 i = 0; i < numLines; i++) {
+	for (int32 i = 0; i < numLines; ++i) {
 		if (!characterTalk(currentLine))
 			break;
 
@@ -2815,7 +2819,7 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
 
 		char *cc = c;
 		Character *waitChar;
-		for (int32 i = 0; i < numParticipants - 1; i++) {
+		for (int32 i = 0; i < numParticipants - 1; ++i) {
 			// listener
 			int32 listenerId = READ_LE_UINT16(cc - 2);
 			cc -= 4;
@@ -2836,7 +2840,7 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
 	} else if (_audioManager->voiceStillPlaying())
 		_audioManager->stopCurrentVoice();
 
-	for (int32 i = 0; i < numParticipants - 1; i++) {
+	for (int32 i = 0; i < numParticipants - 1; ++i) {
 		// listener
 		int32 listenerId = READ_LE_UINT16(c - 2);
 		int32 listenerAnimId = READ_LE_UINT16(c - 4);
@@ -2908,7 +2912,7 @@ void ToonEngine::haveAConversation(int32 convId) {
 
 	if (conv->_enable) {
 		// fix dialog script based on new flags
-		for (int32 i = 0; i < 10; i++) {
+		for (int32 i = 0; i < 10; ++i) {
 			if (conv->state[i]._data2 == 1 || conv->state[i]._data2 == 3) {
 				if (getConversationFlag(_gameState->_currentScene, conv->state[i]._data3))
 					conv->state[i]._data2 = 1;
@@ -2941,13 +2945,13 @@ void ToonEngine::haveAConversation(int32 convId) {
 		}
 		int selected = -1;
 		int a = 0;
-		for (int i = 0; i < 10; i++) {
+		for (int i = 0; i < 10; ++i) {
 			if (conv->state[i]._data2 == 1) {
 				if (_mouseX > 50 + a * 60 && _mouseX < 100 + a * 60 && _mouseY >= 336 && _mouseY <= 386) {
 					selected = i;
 					break;
 				}
-				a++;
+				++a;
 			}
 		}
 
@@ -2955,7 +2959,7 @@ void ToonEngine::haveAConversation(int32 convId) {
 			return;
 
 		_gameState->_showConversationIcons = false;
-		_gameState->_mouseHidden = 1;
+		_gameState->_mouseHidden = true;
 
 		if (selected < 0 || selected == 1 || selected == 3) {
 			if (_gameState->_firstConverstationLine)
@@ -2968,7 +2972,7 @@ void ToonEngine::haveAConversation(int32 convId) {
 		}
 	}
 
-	for (int i = 0; i < 10; i++) {
+	for (int i = 0; i < 10; ++i) {
 		if (conv->state[i]._data2 == 2) {
 			if (i != 3)
 				conv->state[i]._data2 = 1;
@@ -2989,7 +2993,7 @@ void ToonEngine::drawConversationIcons() {
 	if (!_gameState->_inConversation || !_gameState->_showConversationIcons)
 		return;
 	int32 aa = 50 + _gameState->_currentScrollValue;
-	for (int32 i = 0; i < 10; i++) {
+	for (int32 i = 0; i < 10; ++i) {
 		if (_gameState->_conversationState[_gameState->_currentConversationId].state[i]._data2 == 1) {
 			_dialogIcons->drawFrame(*_mainSurface, (i + _gameState->_currentScene) & 7, aa, 336);
 			_dialogIcons->drawFrame(*_mainSurface, 7 + _gameState->_conversationState[_gameState->_currentConversationId].state[i]._data3, aa, 339);
@@ -3000,7 +3004,7 @@ void ToonEngine::drawConversationIcons() {
 
 void ToonEngine::prepareConversations() {
 	Conversation *allConvs = _gameState->_conversationState;
-	for (int32 i = 0; i < 60; i++) {
+	for (int32 i = 0; i < 60; ++i) {
 
 		allConvs[i].state[0]._data2 = 1;
 		if (!allConvs[i].state[0]._data3) {
@@ -3013,7 +3017,7 @@ void ToonEngine::prepareConversations() {
 	}
 	int numConversations = READ_LE_UINT16(_conversationData + 1);
 	int16 *curConversation = _conversationData + 3;
-	for (int i = 0; i < numConversations; i++) {
+	for (int i = 0; i < numConversations; ++i) {
 		Conversation *conv = &allConvs[ READ_LE_UINT16(curConversation)];
 		if (!conv->_enable) {
 
@@ -3076,11 +3080,11 @@ void ToonEngine::processConversationClick(Conversation *conv, int32 status) {
 		_gameState->_mouseHidden = false;
 	} else {
 		while (v8 != -1) {
-			v7 += 1;
+			++v7;
 			int16 *v14 = (int16 *)((char *)_conversationData + v8);
 
 			// find free dialogue slot
-			for (int j = 0; j < 10; j++) {
+			for (int j = 0; j < 10; ++j) {
 				if (!conv->state[j]._data2) {
 					conv->state[j]._data3 = READ_LE_INT16(v14);
 					conv->state[j]._data4 = v14;
@@ -3318,7 +3322,7 @@ void ToonEngine::renderInventory() {
 	clearDirtyRects();
 
 	// draw items on screen
-	for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+	for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 		int32 x = 57 * (i % 7) + 114;
 		int32 y = ((9 * (i % 7)) & 0xf) + 56 * (i / 7) + 80;
 		_inventoryIconSlots->drawFrame(*_mainSurface, i % 12, x + _gameState->_currentScrollValue, y);
@@ -3379,7 +3383,7 @@ int32 ToonEngine::showInventory() {
 		if (justPressedButton & 0x3) {
 			// find out what object we're on
 			int32 foundObj = -1;
-			for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+			for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 				int32 x = 57 * (i % 7) + 114;
 				int32 y = ((9 * (i % 7)) & 0xf) + 56 * (i / 7) + 80;
 				if (_mouseX >= (_gameState->_currentScrollValue + x - 6) &&
@@ -3472,8 +3476,7 @@ void ToonEngine::getMouseEvent() {
 	Common::EventManager *_event = _system->getEventManager();
 
 	Common::Event event;
-	while (_event->pollEvent(event) && !_shouldQuit)
-		;
+	while (_event->pollEvent(event) && !_shouldQuit) { }
 
 	_mouseX = _event->getMousePos().x;
 	_mouseY = _event->getMousePos().y;
@@ -3496,7 +3499,7 @@ void ToonEngine::addItemToInventory(int32 item) {
 
 	if (item == 41) {
 		// confiscated inventory
-		for (int32 i = 0; i < _gameState->_numConfiscatedInventoryItems; i++)
+		for (int32 i = 0; i < _gameState->_numConfiscatedInventoryItems; ++i)
 			addItemToInventory(_gameState->_confiscatedInventory[i]);
 
 		_gameState->_numConfiscatedInventoryItems = 0;
@@ -3504,7 +3507,7 @@ void ToonEngine::addItemToInventory(int32 item) {
 		return;
 	}
 
-	for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+	for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 		if (_gameState->_inventory[i] == 0) {
 			_gameState->_inventory[i] = item;
 			_gameState->_mouseState = -1;
@@ -3555,15 +3558,15 @@ void ToonEngine::hideCutaway() {
 }
 
 void ToonEngine::updateCharacters(int32 timeElapsed) {
-	for (int32 i = 0; i < 8; i++) {
-		if (_characters[i]) {
+	for (int32 i = 0; i < 8; ++i) {
+		if (_characters[i] != nullptr) {
 			_characters[i]->update(timeElapsed);
 		}
 	}
 }
 
 void ToonEngine::drawPalette() {
-	for (int32 i = 0; i < 256; i++) {
+	for (int32 i = 0; i < 256; ++i) {
 		int32 x = i % 32;
 		int32 y = i / 32;
 		_mainSurface->fillRect(Common::Rect(x * 16, y * 16, x * 16 + 16, y * 16 + 16), i);
@@ -3571,10 +3574,10 @@ void ToonEngine::drawPalette() {
 }
 
 void ToonEngine::rearrangeInventory() {
-	for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+	for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 		if (_gameState->_inventory[i] == 0) {
 			// move all the following items from one
-			for (int32 j = i + 1; j < _gameState->_numInventoryItems; j++) {
+			for (int32 j = i + 1; j < _gameState->_numInventoryItems; ++j) {
 				_gameState->_inventory[j - 1] = _gameState->_inventory[j];
 			}
 			_gameState->_numInventoryItems--;
@@ -3675,8 +3678,8 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
 }
 
 Character *ToonEngine::getCharacterById(int32 charId) {
-	for (int32 i = 0; i < 8; i++) {
-		if (_characters[i] && _characters[i]->getId() == charId)
+	for (int32 i = 0; i < 8; ++i) {
+		if (_characters[i] != nullptr && _characters[i]->getId() == charId)
 			return _characters[i];
 	}
 	return 0;
@@ -3721,11 +3724,11 @@ void ToonEngine::pauseEngineIntern(bool pause) {
 
 		// we have to add the difference between the start and the current time
 		// to all "timer based" values.
-		for (int32 i = 0; i < _gameState->_locations[_gameState->_currentScene]._numSceneAnimations; i++) {
+		for (int32 i = 0; i < _gameState->_locations[_gameState->_currentScene]._numSceneAnimations; ++i) {
 			_sceneAnimationScripts[i]._lastTimer += diff;
 		}
-		for (int32 i = 0; i < 8; i++) {
-			if (_characters[i]) {
+		for (int32 i = 0; i < 8; ++i) {
+			if (_characters[i] != nullptr) {
 				_characters[i]->updateTimers(diff);
 			}
 		}
@@ -3815,12 +3818,12 @@ bool ToonEngine::saveGame(int32 slot, const Common::String &saveGameDesc) {
 	saveFile->writeSint32BE(getOldMilli());
 
 	// save script states
-	for (int32 i = 0; i < 4; i++) {
+	for (int32 i = 0; i < 4; ++i) {
 		_script->saveState(&_scriptState[i], saveFile);
 	}
 
 	// save animation script states
-	for (int32 i = 0; i < state()->_locations[_gameState->_currentScene]._numSceneAnimations; i++) {
+	for (int32 i = 0; i < state()->_locations[_gameState->_currentScene]._numSceneAnimations; ++i) {
 		saveFile->writeByte(_sceneAnimationScripts[i]._active);
 		saveFile->writeByte(_sceneAnimationScripts[i]._frozen);
 		saveFile->writeSint32BE(_sceneAnimationScripts[i]._lastTimer);
@@ -3828,12 +3831,12 @@ bool ToonEngine::saveGame(int32 slot, const Common::String &saveGameDesc) {
 	}
 
 	// save scene animations
-	for (int32 i = 0; i < 64; i++) {
+	for (int32 i = 0; i < 64; ++i) {
 		_sceneAnimations[i].save(this, saveFile);
 	}
 
-	for (int32 i = 0; i < 8; i++) {
-		if (_characters[i]) {
+	for (int32 i = 0; i < 8; ++i) {
+		if (_characters[i] != nullptr) {
 			saveFile->writeSByte(i);
 			_characters[i]->save(saveFile);
 		}
@@ -3903,12 +3906,12 @@ bool ToonEngine::loadGame(int32 slot) {
 	int32 timerDiff = _system->getMillis() - savedTime;
 
 	// load script states
-	for (int32 i = 0; i < 4; i++) {
+	for (int32 i = 0; i < 4; ++i) {
 		_script->loadState(&_scriptState[i], loadFile);
 	}
 
 	// load animation script states
-	for (int32 i = 0; i < state()->_locations[_gameState->_currentScene]._numSceneAnimations; i++) {
+	for (int32 i = 0; i < state()->_locations[_gameState->_currentScene]._numSceneAnimations; ++i) {
 		_sceneAnimationScripts[i]._active = loadFile->readByte();
 		_sceneAnimationScripts[i]._frozen = loadFile->readByte();
 		_sceneAnimationScripts[i]._frozenForConversation = false;
@@ -3918,12 +3921,12 @@ bool ToonEngine::loadGame(int32 slot) {
 	}
 
 	// load scene animations
-	for (int32 i = 0; i < 64; i++) {
+	for (int32 i = 0; i < 64; ++i) {
 		_sceneAnimations[i].load(this, loadFile);
 	}
 
 	// scene animations have to be added in reverse order in animation manager to preserve the z order
-	for (int32 i = 63; i >= 0; i--) {
+	for (int32 i = 63; i >= 0; --i) {
 		if (_sceneAnimations[i]._active && _sceneAnimations[i]._animInstance) {
 			_animationManager->addInstance(_sceneAnimations[i]._animInstance);
 		}
@@ -3941,10 +3944,19 @@ bool ToonEngine::loadGame(int32 slot) {
 		if (c < 0)
 			break;
 
-		if (!_characters[c]) {
+		// NOTE The exitScene() call above removes characters in scene (if any current exists) (and only for the 8 (scene?) characters)
+		if (_characters[c] == nullptr) {
 			_characters[c] = new Character(this);
 		}
-		_characters[c]->load(loadFile);
+
+		_characters[c]->load(loadFile, saveGameVersion);
+		// NOTE These playStandingAnim() calls are executed in the loadScene() call above,
+		// but that's before we're loading stuff like the _facing of actors
+		if (_characters[c] == _drew) {
+			_drew->playStandingAnim();
+		} else if (_characters[c] == _flux && _gameState->_currentChapter == 1) {
+			_flux->playStandingAnim();
+		}
 		//_characters[c]->setVisible(true);
 		_characters[c]->update(0);
 	}
@@ -4029,7 +4041,7 @@ bool ToonEngine::loadGame(int32 slot) {
 int32 ToonEngine::getSpecialInventoryItem(int32 item) {
 	// butter
 	if (item == 12) {
-		for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+		for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 			if (_gameState->_inventory[i] == 12)
 				_gameState->_inventory[i] = 11;
 		}
@@ -4055,13 +4067,15 @@ int32 ToonEngine::getSpecialInventoryItem(int32 item) {
 void ToonEngine::initCharacter(int32 characterId, int32 animScriptId, int32 sceneAnimationId, int32 animToPlayId) {
 	// find a new index
 	int32 characterIndex = -1;
-	for (int32 i = 0; i < 8; i++) {
-		if (_characters[i] && _characters[i]->getId() == characterId) {
+	for (int32 i = 0; i < 8; ++i) {
+		if (_characters[i] != nullptr && _characters[i]->getId() == characterId) {
+			// TODO Shouldn't _characters[i] be deleted here,
+			// since we assign a new Character object to it below?
 			characterIndex = i;
 			break;
 		}
 
-		if (!_characters[i]) {
+		if (_characters[i] == nullptr) {
 			characterIndex = i;
 			break;
 		}
@@ -5260,7 +5274,7 @@ int32 ToonEngine::handleInventoryOnDrew(int32 itemId) {
 }
 
 void ToonEngine::deleteItemFromInventory(int32 item) {
-	for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+	for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 		if (_gameState->_inventory[i] == item) {
 			_gameState->_inventory[i] = 0;
 			rearrangeInventory();
@@ -5270,7 +5284,7 @@ void ToonEngine::deleteItemFromInventory(int32 item) {
 }
 
 void ToonEngine::replaceItemFromInventory(int32 item, int32 newitem) {
-	for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
+	for (int32 i = 0; i < _gameState->_numInventoryItems; ++i) {
 		if (_gameState->_inventory[i] == item) {
 			_gameState->_inventory[i] = newitem;
 			return;
@@ -5307,7 +5321,7 @@ void ToonEngine::createShadowLUT() {
 	uint32 scaleNum = 77;
 	uint32 scaleDenom = 100;
 
-	for (int32 i = 0; i < 255; i++) {
+	for (int32 i = 0; i < 255; ++i) {
 
 		// goal color
 		uint32 destR = _finalPalette[i * 3 + 0] * scaleNum / scaleDenom;
@@ -5318,7 +5332,7 @@ void ToonEngine::createShadowLUT() {
 		int32 colorDist = 0xffffff;
 		int32 foundColor = 0;
 
-		for (int32 c = 1; c < 129; c++) {
+		for (int32 c = 1; c < 129; ++c) {
 
 			int32 diffR = _finalPalette[c * 3 + 0] - destR;
 			int32 diffG = _finalPalette[c * 3 + 1] - destG;
@@ -5330,7 +5344,7 @@ void ToonEngine::createShadowLUT() {
 			}
 		}
 
-		for (int32 c = 200; c < 256; c++) {
+		for (int32 c = 200; c < 256; ++c) {
 
 			int32 diffR = _finalPalette[c * 3 + 0] - destR;
 			int32 diffG = _finalPalette[c * 3 + 1] - destG;
@@ -5405,10 +5419,10 @@ void ToonEngine::unloadToonDat() {
 
 char **ToonEngine::loadTextsVariants(Common::File &in) {
 	int  len;
-	char **res = 0;
-	char *pos = 0;
+	char **res = nullptr;
+	char *pos = nullptr;
 
-	for (int varnt = 0; varnt < _numVariant; varnt++) {
+	for (int varnt = 0; varnt < _numVariant; ++varnt) {
 		int numTexts = in.readUint16BE();
 		int entryLen = in.readUint16BE();
 		pos = (char *)malloc(entryLen);
@@ -5425,7 +5439,7 @@ char **ToonEngine::loadTextsVariants(Common::File &in) {
 
 		pos += DATAALIGNMENT;
 
-		for (int i = 1; i < numTexts; i++) {
+		for (int i = 1; i < numTexts; ++i) {
 			pos -= 2;
 
 			len = READ_BE_UINT16(pos);
@@ -5484,17 +5498,17 @@ void ToonEngine::addDirtyRect( int32 left, int32 top, int32 right, int32 bottom
 
 	Common::Rect rect(left, top, right, bottom);
 
-	for (uint32 i = 0; i < _dirtyRects.size(); i++) {
+	for (uint32 i = 0; i < _dirtyRects.size(); ++i) {
 		if (_dirtyRects[i].contains(rect))
 			return;
 		if (rect.contains(_dirtyRects[i])) {
 			_dirtyRects.remove_at(i);
-			i--;
+			--i;
 		}
 	}
 
 	// check also in the old rect (of the old frame)
-	for (int32 i = _oldDirtyRects.size() - 1 ; i >= 0; i--) {
+	for (int32 i = _oldDirtyRects.size() - 1 ; i >= 0; --i) {
 		if (rect.contains(_oldDirtyRects[i])) {
 			_oldDirtyRects.remove_at(i);
 		}
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index c4696bc4a45..b364dc11aa0 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -46,7 +46,7 @@ struct ADGameDescription;
 
 #define TOON_DAT_VER_MAJ 0  // 1 byte
 #define TOON_DAT_VER_MIN 3  // 1 byte
-#define TOON_SAVEGAME_VERSION 5
+#define TOON_SAVEGAME_VERSION 6
 #define DATAALIGNMENT 4
 #define MAX_SAVE_SLOT 99
 


Commit: 7b42cb65cbbc043acbdd88c1fd63d4909be8fe98
    https://github.com/scummvm/scummvm/commit/7b42cb65cbbc043acbdd88c1fd63d4909be8fe98
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-07-01T12:46:55+03:00

Commit Message:
TOON: Fix Picture::drawWithRectList() overreading

Also added safe guards for drawMask() and draw() and plugged a mem leak for _currentCutaway Picture

Changed paths:
    engines/toon/picture.cpp
    engines/toon/toon.cpp


diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index f3ad4f42af5..8b0e0392949 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -163,7 +163,7 @@ void Picture::setupPalette() {
 void Picture::drawMask(Graphics::Surface &surface, int16 x, int16 y, int16 dx, int16 dy) {
 	debugC(1, kDebugPicture, "drawMask(surface, %d, %d, %d, %d)", x, y, dx, dy);
 
-	for (int32 i = 0; i < 128; i++) {
+	for (int32 i = 0; i < 128; ++i) {
 		byte color[3];
 		color[0] = i * 2;
 		color[1] = i * 2;
@@ -182,18 +182,20 @@ void Picture::drawMask(Graphics::Surface &surface, int16 x, int16 y, int16 dx, i
 	uint8 *c = _data + _width * dy + dx;
 	uint8 *curRow = (uint8 *)surface.getBasePtr(x, y);
 
-	for (int16 yy = 0; yy < ry; yy++) {
-		uint8 *curSrc = c;
-		uint8 *cur = curRow;
-		for (int16 xx = 0; xx < rx; xx++) {
-			//*cur = (*curSrc >> 5) * 8; // & 0x1f;
-			*cur = (*curSrc & 0x1f) ? 127 : 0;
+	if (_width > dx) {
+		for (int16 yy = 0; yy < ry; ++yy) {
+			uint8 *curSrc = c;
+			uint8 *cur = curRow;
+			for (int16 xx = 0; xx < rx; ++xx) {
+				//*cur = (*curSrc >> 5) * 8; // & 0x1f;
+				*cur = (*curSrc & 0x1f) ? 127 : 0;
 
-			curSrc++;
-			cur++;
+				++curSrc;
+				++cur;
+			}
+			curRow += destPitch;
+			c += srcPitch;
 		}
-		curRow += destPitch;
-		c += srcPitch;
 	}
 }
 
@@ -207,26 +209,30 @@ void Picture::drawWithRectList(Graphics::Surface& surface, int16 x, int16 y, int
 	int32 destPitch = surface.pitch;
 	int32 srcPitch = _width;
 
-	for (uint32 i = 0; i < rectArray.size(); i++) {
-
+	for (uint32 i = 0; i < rectArray.size(); ++i) {
 		Common::Rect rect = rectArray[i];
 
 		int16 fillRx = MIN<int32>(rx, rect.right - rect.left);
 		int16 fillRy = MIN<int32>(ry, rect.bottom - rect.top);
 
-		uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
-		uint8 *curRow = (uint8 *)surface.getBasePtr(x + rect.left, y + rect.top);
-
-		for (int16 yy = 0; yy < fillRy; yy++) {
-			uint8 *curSrc = c;
-			uint8 *cur = curRow;
-			for (int16 xx = 0; xx < fillRx; xx++) {
-				*cur = *curSrc;
-				curSrc++;
-				cur++;
+		if (_width > dx + rect.left) {
+			// Sometimes rect dimensions refer to the larger width ie. 1280, while the picture width is 640
+			// The if clause above is a simple check to avoid those cases.
+			// TODO maybe something smarter could be done to prevent adding such problematic rectangles to the list
+			uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
+			uint8 *curRow = (uint8 *)surface.getBasePtr(x + rect.left, y + rect.top);
+
+			for (int16 yy = 0; yy < fillRy; ++yy) {
+				uint8 *curSrc = c;
+				uint8 *cur = curRow;
+				for (int16 xx = 0; xx < fillRx; ++xx) {
+					*cur = *curSrc;  // Here is where the drawing happens (starting from rect Top Left)
+					++curSrc;    // This goes to the next entry of _data (to be read)
+					++cur;       // This goes to the next address BasePtr of surface (to write there, on surface)
+				}
+				c += srcPitch;       // data "row" is increased by srcPitch (_width)
+				curRow += destPitch; // surface row is increased by destPitch
 			}
-			curRow += destPitch;
-			c += srcPitch;
 		}
 	}
 }
@@ -245,16 +251,18 @@ void Picture::draw(Graphics::Surface &surface, int16 x, int16 y, int16 dx, int16
 	uint8 *c = _data + _width * dy + dx;
 	uint8 *curRow = (uint8 *)surface.getBasePtr(x, y);
 
-	for (int16 yy = 0; yy < ry; yy++) {
-		uint8 *curSrc = c;
-		uint8 *cur = curRow;
-		for (int16 xx = 0; xx < rx; xx++) {
-			*cur = *curSrc;
-			curSrc++;
-			cur++;
+	if (_width > dx) {
+		for (int16 yy = 0; yy < ry; ++yy) {
+			uint8 *curSrc = c;
+			uint8 *cur = curRow;
+			for (int16 xx = 0; xx < rx; ++xx) {
+				*cur = *curSrc;
+				++curSrc;
+				++cur;
+			}
+			curRow += destPitch;
+			c += srcPitch;
 		}
-		curRow += destPitch;
-		c += srcPitch;
 	}
 }
 
@@ -277,8 +285,8 @@ void Picture::floodFillNotWalkableOnMask(int16 x, int16 y) {
 	while (!stack.empty()) {
 		Common::Point pt = stack.pop();
 		while (_data[pt.x + pt.y * _width] & 0x1F && pt.y >= 0)
-			pt.y--;
-		pt.y++;
+			--pt.y;
+		++pt.y;
 		bool spanLeft = false;
 		bool spanRight = false;
 		uint32 nextDataPos = pt.x + pt.y * _width;
@@ -296,7 +304,7 @@ void Picture::floodFillNotWalkableOnMask(int16 x, int16 y) {
 			} else if (spanRight && pt.x < _width - 1 && !(_data[nextDataPos + 1] & 0x1F)) {
 				spanRight = 0;
 			}
-			pt.y++;
+			++pt.y;
 			nextDataPos = pt.x + pt.y * _width;
 		}
 	}
@@ -327,12 +335,12 @@ void Picture::drawLineOnMask(int16 x, int16 y, int16 x2, int16 y2, bool walkable
 	int32 cdx = (dx << 16) / t;
 	int32 cdy = (dy << 16) / t;
 
-	for (int16 i = t; i > 0; i--) {
+	for (int16 i = t; i > 0; --i) {
 		int32 rx = bx >> 16;
 		int32 ry = by >> 16;
 
-		if ( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) {	// sanity check: some lines in the game
-																	// were drawing outside the screen causing corruption
+		if ( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
+		                                                            // were drawing outside the screen causing corruption
 			if (!walkable) {
 				_data[_width * ry + rx] &= 0xe0;
 				_data[_width * ry + rx + 1] &= 0xe0;
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index c96c85fd548..f72e54087f7 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -1685,6 +1685,7 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
 
 ToonEngine::~ToonEngine() {
 	delete _currentPicture;
+	delete _currentCutaway;
 	delete _currentMask;
 	delete _inventoryPicture;
 
@@ -3532,6 +3533,8 @@ void ToonEngine::deleteMouseItem() {
 
 void ToonEngine::showCutaway(const Common::String &cutawayPicture) {
 	_gameState->_inCutaway = true;
+	delete _currentCutaway;
+	_currentCutaway = nullptr;
 	_currentCutaway = new Picture(this);
 	if (cutawayPicture.empty()) {
 		Common::String name = _gameState->_locations[_gameState->_currentScene]._cutaway;
@@ -3551,7 +3554,7 @@ void ToonEngine::hideCutaway() {
 	_gameState->_sackVisible = true;
 	delete _currentCutaway;
 	_gameState->_currentScrollValue = _oldScrollValue;
-	_currentCutaway = 0;
+	_currentCutaway = nullptr;
 	_currentPicture->setupPalette();
 	dirtyAllScreen();
 	flushPalette();




More information about the Scummvm-git-logs mailing list