[Scummvm-git-logs] scummvm master -> 58fc875836007dc3053ec52b6c12bcb941cc169f

sev- noreply at scummvm.org
Sun Aug 13 08:58:38 UTC 2023


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

Summary:
e3bf334921 AGS: Engine: made run_interaction_script() safer in case evt is too high
4d28890458 AGS: Engine: fixed loop check... again...
cd6a6ddc8c AGS; Engine: tidied SetGameOption()
a31aac3bf2 AGS: Engine: fixed GUI controls not updated on set OPT_RIGHTLEFTWRITE
6b214f0477 AGS: Engine: fixed Buttons with invitem pic not redrawn on ActiveInventory
16a620e558 AGS: Updated build version (3.6.0.50)
808b90b39f AGS: Common: fixes for CreateAllDirectories, Path::GetParent, GetFilename
8d3a2f07ce AGS: Engine: fixed crash upon resizing DynamicSprite while it's on screen
cf90c85cd4 AGS: Engine: fixed crash upon resizing DynamicSprite while it's on screen
2e784f5cd0 AGS: Engine: report "voice available" only if Speech dir contains any files
ff0298be68 AGS: Engine: ignore mod and special keys when skipping speech and wait
4966d2a896 AGS: Engine: apply character's anim volume to portrait animation
3c4b80e14c AGS: Engine: report missing speech.vox as an "info", since this is optional
a6edbb5701 AGS: Engine: fixed few game warnings, may fill up the log in some games
d9377bbb63 AGS: Engine: Fix typo in commit b81abc533f508e5831e7ca6d2512c66d506ef09d
793a5d6273 AGS: Engine: fixed System.Log() may cause exceptions with wrong format
7688ff025f AGS: Engine: sync audio in case of scheduled post-script actions
9e6dfbf258 AGS: Engine: ensure that restricted game options not loaded from save
e946f9f99d AGS: Engine: fixed GfxDriverSpriteEvtCallback return value for no room case
6ea6675b3c AGS: Engine: tidy some code related to the old save format constants
5039b5f3a6 AGS: Engine: small refactor, rem duplicate list of restricted game options
58fc875836 AGS: Updated build version (3.6.0.51)


Commit: e3bf334921014bc4e464fef24147a332ef1b3652
    https://github.com/scummvm/scummvm/commit/e3bf334921014bc4e464fef24147a332ef1b3652
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: made run_interaction_script() safer in case evt is too high

>From upstream 4d7565099652c019d0dcbac5c60f62d735dfae3e

Changed paths:
    engines/ags/engine/script/script.cpp


diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index db2f3d615f7..0af73d5442d 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -159,12 +159,12 @@ int run_interaction_event(Interaction *nint, int evnt, int chkAny, int isInv) {
 // (eg. a room change occurred)
 int run_interaction_script(InteractionScripts *nint, int evnt, int chkAny) {
 
-	if ((nint->ScriptFuncNames[evnt] == nullptr) || (nint->ScriptFuncNames[evnt][0u] == 0)) {
+	if ((nint->ScriptFuncNames.size() <= evnt) || nint->ScriptFuncNames[evnt].IsEmpty()) {
 		// no response defined for this event
 		// If there is a response for "Any Click", then abort now so as to
 		// run that instead
 		if (chkAny < 0);
-		else if ((nint->ScriptFuncNames[chkAny] != nullptr) && (nint->ScriptFuncNames[chkAny][0u] != 0))
+		else if (!nint->ScriptFuncNames[chkAny].IsEmpty())
 			return 0;
 
 		// Otherwise, run unhandled_event
@@ -223,7 +223,7 @@ int create_global_script() {
 		instances_for_resolving.push_back(_G(dialogScriptsInst));
 	}
 
-	// Resolve the script imports after all the scripts have been loaded 
+	// Resolve the script imports after all the scripts have been loaded
 	for (size_t instance_idx = 0; instance_idx < instances_for_resolving.size(); instance_idx++) {
 		auto inst = instances_for_resolving[instance_idx];
 		if (!inst->ResolveScriptImports(inst->instanceof.get()))


Commit: 4d288904583eff306d7459e22b12993289e43ec2
    https://github.com/scummvm/scummvm/commit/4d288904583eff306d7459e22b12993289e43ec2
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed loop check... again...

The latest change (c694126) was meant to fix a timeout test logic,
 but it broke the primary loop count check.

The incorrect behavior may be observed when a function with
many loops and `noloopcheck` modifier is called *repeatedly*
from another function. Normally in such case the iterations
passed withing a `noloopcheck` function should not be counted,
but they were.

Apparently the situation cannot be resolved without having 2 counters:
1. One is working all the time, and is used to detect timeouts, as these
may occur both in normal circumstances and in functions with
`noloopcheck` modifier.
2. Second is working only in functions without `noloopcheck` modifier
and is used to do the "stuck in a loop" test.

+ backported small optimization from 3.6.1 branch.
>From upstream 70afd47f4879b4eaed5dab664af9e4485055875f

Changed paths:
    engines/ags/engine/script/cc_instance.cpp


diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 029d5871510..10067a1b986 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -438,10 +438,8 @@ int ccInstance::Run(int32_t curpc) {
 	int32_t thisbase[MAXNEST], funcstart[MAXNEST];
 	int was_just_callas = -1;
 	int curnest = 0;
-	unsigned loopIterations = 0;
 	int num_args_to_func = -1;
 	int next_call_needs_object = 0;
-	int loopIterationCheckDisabled = 0;
 	thisbase[0] = 0;
 	funcstart[0] = pc;
 	ccInstance *codeInst = runningInst;
@@ -449,6 +447,9 @@ int ccInstance::Run(int32_t curpc) {
 		(gDebugLevel > 0 && DebugMan.isDebugChannelEnabled(::AGS::kDebugScript));
 	ScriptOperation codeOp;
 	FunctionCallStack func_callstack;
+	int loopIterationCheckDisabled = 0;
+	unsigned loopIterations = 0u;      // any loop iterations (needed for timeout test)
+	unsigned loopCheckIterations = 0u; // loop iterations accumulated only if check is enabled
 
 	const auto timeout = std::chrono::milliseconds(_G(timeoutCheckMs));
 	// NOTE: removed timeout_abort check for now: was working *logically* wrong;
@@ -791,14 +792,15 @@ int ccInstance::Run(int32_t curpc) {
 				if (flags & INSTF_RUNNING) {
 					// was notified still running, don't do anything
 					flags &= ~INSTF_RUNNING;
-					loopIterations = 0;
-				} else if ((loopIterationCheckDisabled == 0) && (_G(maxWhileLoops) > 0) && (loopIterations > _G(maxWhileLoops))) {
-					cc_error("!Script appears to be hung (a while loop ran %d times). The problem may be in a calling function; check the call stack.", (int)loopIterations);
+					loopIterations = 0u;
+					loopCheckIterations = 0u;
+				} else if ((loopIterationCheckDisabled == 0) && (_G(maxWhileLoops) > 0) && (++loopIterations > _G(maxWhileLoops))) {
+					cc_error("!Script appears to be hung (a while loop ran %d times). The problem may be in a calling function; check the call stack.", (int)loopCheckIterations);
 					return -1;
-				} else if ((loopIterations % 1000) == 0 && (std::chrono::duration_cast<std::chrono::milliseconds>(AGS_Clock::now() - _lastAliveTs) > timeout)) {
+				} else if ((loopIterations & 0x3FF) == 0 && // test each 1024 loops (arbitrary)
+						   (std::chrono::duration_cast<std::chrono::milliseconds>(AGS_Clock::now() - _lastAliveTs) > timeout)) {
 					// minimal timeout occurred
 					// NOTE: removed timeout_abort check for now: was working *logically* wrong;
-					// at least let user to manipulate the game window
 					sys_evt_process_pending();
 					_lastAliveTs = AGS_Clock::now();
 				}


Commit: cd6a6ddc8cdfb5668ae1849696849d415927fad7
    https://github.com/scummvm/scummvm/commit/cd6a6ddc8cdfb5668ae1849696849d415927fad7
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS; Engine: tidied SetGameOption()

* handle readonly options;
* don't do anything if new value equals old value;
* replace if/else sequence with a switch;
>From upstream 2476bc3e517c13ef1abde83fca2e55571bcfff4a

Changed paths:
    engines/ags/engine/ac/global_game.cpp
    engines/ags/shared/ac/game_struct_defines.h


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index ce85168a6c1..817385829d0 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -395,49 +395,89 @@ int GetGameSpeed() {
 	return ::lround(get_current_fps()) - _GP(play).game_speed_modifier;
 }
 
-int SetGameOption(int opt, int setting) {
-	if (((opt < 1) || (opt > OPT_HIGHESTOPTION)) && (opt != OPT_LIPSYNCTEXT))
-		quit("!SetGameOption: invalid option specified");
+int SetGameOption(int opt, int newval) {
+	if (((opt < OPT_DEBUGMODE) || (opt > OPT_HIGHESTOPTION)) && (opt != OPT_LIPSYNCTEXT)) {
+		debug_script_warn("SetGameOption: invalid option specified: %d", opt);
+		return 0;
+	}
+
+	// Handle forbidden options
+	switch (opt) {
+	case OPT_DEBUGMODE: // we don't support switching OPT_DEBUGMODE from script
+	case OPT_LETTERBOX:
+	case OPT_HIRES_FONTS:
+	case OPT_SPLITRESOURCES:
+	case OPT_STRICTSCRIPTING:
+	case OPT_LEFTTORIGHTEVAL:
+	case OPT_COMPRESSSPRITES:
+	case OPT_STRICTSTRINGS:
+	case OPT_NATIVECOORDINATES:
+	case OPT_SAFEFILEPATHS:
+	case OPT_DIALOGOPTIONSAPI:
+	case OPT_BASESCRIPTAPI:
+	case OPT_SCRIPTCOMPATLEV:
+	case OPT_RELATIVEASSETRES:
+	case OPT_GAMETEXTENCODING:
+	case OPT_KEYHANDLEAPI:
+	case OPT_CUSTOMENGINETAG:
+		debug_script_warn("SetGameOption: option %d cannot be modified at runtime", opt);
+		return _GP(game).options[opt];
+	default:
+		break;
+	}
+
+	if (_GP(game).options[opt] == newval)
+		return _GP(game).options[opt]; // no change necessary
 
-	if (opt == OPT_ANTIGLIDE) {
+	const int oldval = _GP(game).options[opt];
+	_GP(game).options[opt] = newval;
+
+	// Update the game in accordance to the new option value
+	switch (opt) {
+	case OPT_ANTIGLIDE:
 		for (int i = 0; i < _GP(game).numcharacters; i++) {
-			if (setting)
+			if (newval)
 				_GP(game).chars[i].flags |= CHF_ANTIGLIDE;
 			else
 				_GP(game).chars[i].flags &= ~CHF_ANTIGLIDE;
 		}
-	}
-
-	if ((opt == OPT_CROSSFADEMUSIC) && (_GP(game).audioClipTypes.size() > AUDIOTYPE_LEGACY_MUSIC)) {
-		// legacy compatibility -- changing crossfade speed here also
-		// updates the new audio clip type style
-		_GP(game).audioClipTypes[AUDIOTYPE_LEGACY_MUSIC].crossfadeSpeed = setting;
-	}
-
-	int oldval = _GP(game).options[opt];
-	_GP(game).options[opt] = setting;
-
-	if (opt == OPT_DUPLICATEINV)
-		update_invorder();
-	else if (opt == OPT_DISABLEOFF) {
+		break;
+	case OPT_DISABLEOFF:
 		GUI::Options.DisabledStyle = static_cast<GuiDisableStyle>(_GP(game).options[OPT_DISABLEOFF]);
 		// If GUI was disabled at this time then also update it, as visual style could've changed
 		if (_GP(play).disabled_user_interface > 0) {
 			GUI::MarkAllGUIForUpdate(true, false);
 		}
-	} else if (opt == OPT_PORTRAITSIDE) {
-		if (setting == 0)  // set back to Left
+		break;
+	case OPT_CROSSFADEMUSIC:
+		if (_GP(game).audioClipTypes.size() > AUDIOTYPE_LEGACY_MUSIC) {
+			// legacy compatibility -- changing crossfade speed here also
+			// updates the new audio clip type style
+			_GP(game).audioClipTypes[AUDIOTYPE_LEGACY_MUSIC].crossfadeSpeed = newval;
+		}
+		break;
+	case OPT_ANTIALIASFONTS:
+		adjust_fonts_for_render_mode(newval != 0);
+		break;
+	case OPT_DUPLICATEINV:
+		update_invorder();
+		break;
+	case OPT_PORTRAITSIDE:
+		if (newval == 0) // set back to Left
 			_GP(play).swap_portrait_side = 0;
-	} else if (opt == OPT_ANTIALIASFONTS) {
-		adjust_fonts_for_render_mode(setting != 0);
+		break;
+	default:
+		break; // do nothing else
 	}
 
 	return oldval;
 }
 
 int GetGameOption(int opt) {
-	if (((opt < 1) || (opt > OPT_HIGHESTOPTION)) && (opt != OPT_LIPSYNCTEXT))
-		quit("!GetGameOption: invalid option specified");
+	if (((opt < OPT_DEBUGMODE) || (opt > OPT_HIGHESTOPTION)) && (opt != OPT_LIPSYNCTEXT)) {
+		debug_script_warn("GetGameOption: invalid option specified: %d", opt);
+		return 0;
+	}
 
 	return _GP(game).options[opt];
 }
diff --git a/engines/ags/shared/ac/game_struct_defines.h b/engines/ags/shared/ac/game_struct_defines.h
index cba85f2c106..0385056c5e9 100644
--- a/engines/ags/shared/ac/game_struct_defines.h
+++ b/engines/ags/shared/ac/game_struct_defines.h
@@ -34,6 +34,8 @@ namespace AGS3 {
 #define GLOBALMESLENGTH     500
 #define MAXLANGUAGE         5
 #define LEGACY_MAX_FONTS    30
+
+// General game options
 #define OPT_DEBUGMODE       0
 #define OPT_SCORESOUND      1
 #define OPT_WALKONLOOK      2
@@ -68,8 +70,8 @@ namespace AGS3 {
 #define OPT_PORTRAITSIDE    31
 #define OPT_STRICTSCRIPTING 32  // don't allow MoveCharacter-style commands
 #define OPT_LEFTTORIGHTEVAL 33  // left-to-right operator evaluation
-#define OPT_COMPRESSSPRITES 34
-#define OPT_STRICTSTRINGS   35  // don't allow old-style strings
+#define OPT_COMPRESSSPRITES 34  // [DEPRECATED]
+#define OPT_STRICTSTRINGS   35  // don't allow old-style strings, for reference only
 #define OPT_NEWGUIALPHA     36
 #define OPT_RUNGAMEDLGOPTS  37
 #define OPT_NATIVECOORDINATES 38 // defines coordinate relation between game logic and game screen
@@ -88,7 +90,7 @@ namespace AGS3 {
 #define OPT_KEYHANDLEAPI    50 // key handling mode (old/new)
 #define OPT_CUSTOMENGINETAG 51 // custom engine tag (for overriding behavior)
 #define OPT_HIGHESTOPTION   OPT_CUSTOMENGINETAG
-#define OPT_NOMODMUSIC      98 // unused
+#define OPT_NOMODMUSIC      98 // [DEPRECATED]
 #define OPT_LIPSYNCTEXT     99
 
 #define CUSTOMENG_NONE      0


Commit: a31aac3bf2ca5748a1194373a38c1feaa803a5ae
    https://github.com/scummvm/scummvm/commit/a31aac3bf2ca5748a1194373a38c1feaa803a5ae
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed GUI controls not updated on set OPT_RIGHTLEFTWRITE

>From upstream 3360f4a2f279d135d1107dd4fcda2031eed95fae

Changed paths:
    engines/ags/engine/ac/global_game.cpp


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 817385829d0..23c669b26db 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -459,6 +459,9 @@ int SetGameOption(int opt, int newval) {
 	case OPT_ANTIALIASFONTS:
 		adjust_fonts_for_render_mode(newval != 0);
 		break;
+	case OPT_RIGHTLEFTWRITE:
+		GUI::MarkForTranslationUpdate();
+		break;
 	case OPT_DUPLICATEINV:
 		update_invorder();
 		break;


Commit: 6b214f04773b4c92b7c113c5a9ef32802617dc76
    https://github.com/scummvm/scummvm/commit/6b214f04773b4c92b7c113c5a9ef32802617dc76
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed Buttons with invitem pic not redrawn on ActiveInventory

>From upstream 37127b81ea4c006f8f79f11df746c24e4039f0ba

Changed paths:
    engines/ags/shared/gui/gui_button.cpp
    engines/ags/shared/gui/gui_button.h
    engines/ags/shared/gui/gui_main.cpp
    engines/ags/shared/gui/gui_main.h


diff --git a/engines/ags/shared/gui/gui_button.cpp b/engines/ags/shared/gui/gui_button.cpp
index f12cd37cf8f..8185a464e4b 100644
--- a/engines/ags/shared/gui/gui_button.cpp
+++ b/engines/ags/shared/gui/gui_button.cpp
@@ -99,6 +99,10 @@ bool GUIButton::IsClippingImage() const {
 	return (Flags & kGUICtrl_Clip) != 0;
 }
 
+GUIButtonPlaceholder GUIButton::GetPlaceholder() const {
+	return _placeholder;
+}
+
 Rect GUIButton::CalcGraphicRect(bool clipped) {
 	if (clipped)
 		return RectWH(0, 0, Width, Height);
diff --git a/engines/ags/shared/gui/gui_button.h b/engines/ags/shared/gui/gui_button.h
index 390c7e45ed1..7b8c11598e3 100644
--- a/engines/ags/shared/gui/gui_button.h
+++ b/engines/ags/shared/gui/gui_button.h
@@ -58,6 +58,15 @@ enum LegacyButtonAlignment {
 	kLegacyButtonAlign_BottomRight = 8,
 };
 
+// Defines button placeholder mode; the mode is set
+// depending on special tags found in button text
+enum GUIButtonPlaceholder {
+	kButtonPlace_None,
+	kButtonPlace_InvItemStretch,
+	kButtonPlace_InvItemCenter,
+	kButtonPlace_InvItemAuto
+};
+
 class GUIButton : public GUIObject {
 public:
 	GUIButton();
@@ -66,6 +75,7 @@ public:
 	const String &GetText() const;
 	bool IsImageButton() const;
 	bool IsClippingImage() const;
+	GUIButtonPlaceholder GetPlaceholder() const;
 
 	// Operations
 	Rect CalcGraphicRect(bool clipped) override;
@@ -108,15 +118,6 @@ private:
 	void DrawTextButton(Bitmap *ds, int x, int y, bool draw_disabled);
 	void PrepareTextToDraw();
 
-	// Defines button placeholder mode; the mode is set
-	// depending on special tags found in button text
-	enum GUIButtonPlaceholder {
-		kButtonPlace_None,
-		kButtonPlace_InvItemStretch,
-		kButtonPlace_InvItemCenter,
-		kButtonPlace_InvItemAuto
-	};
-
 	// Text property set by user
 	String _text;
 	// type of content placeholder, if any
diff --git a/engines/ags/shared/gui/gui_main.cpp b/engines/ags/shared/gui/gui_main.cpp
index 5946327eaed..2367a2b8974 100644
--- a/engines/ags/shared/gui/gui_main.cpp
+++ b/engines/ags/shared/gui/gui_main.cpp
@@ -746,6 +746,10 @@ void MarkSpecialLabelsForUpdate(GUILabelMacro macro) {
 }
 
 void MarkInventoryForUpdate(int char_id, bool is_player) {
+	for (auto &btn : _GP(guibuts)) {
+		if (btn.GetPlaceholder() != kButtonPlace_None)
+			btn.MarkChanged();
+	}
 	for (auto &inv : _GP(guiinv)) {
 		if ((char_id < 0) || (inv.CharId == char_id) || (is_player && inv.CharId < 0)) {
 			inv.MarkChanged();
diff --git a/engines/ags/shared/gui/gui_main.h b/engines/ags/shared/gui/gui_main.h
index f082b9017fe..a4978dbec99 100644
--- a/engines/ags/shared/gui/gui_main.h
+++ b/engines/ags/shared/gui/gui_main.h
@@ -238,7 +238,8 @@ void MarkForTranslationUpdate();
 void MarkForFontUpdate(int font);
 // Mark labels that acts as special text placeholders for redraw
 void MarkSpecialLabelsForUpdate(GUILabelMacro macro);
-// Mark inventory windows for redraw, optionally only ones linked to given character
+// Mark inventory windows for redraw, optionally only ones linked to given character;
+// also marks buttons with inventory icon mode
 void MarkInventoryForUpdate(int char_id, bool is_player);
 
 // Parses the string and returns combination of label macro flags


Commit: 16a620e558be4bb90ac6338fa79305b24a3f6c52
    https://github.com/scummvm/scummvm/commit/16a620e558be4bb90ac6338fa79305b24a3f6c52
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Updated build version (3.6.0.50)

Partially from upstream 7cfa7fc419fb9f96c03ad5047b5b4ffa313d4e27

Changed paths:
    engines/ags/shared/core/def_version.h


diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 80eb76cba17..0ef1f023eda 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
 #ifndef AGS_SHARED_CORE_DEFVERSION_H
 #define AGS_SHARED_CORE_DEFVERSION_H
 
-#define ACI_VERSION_STR      "3.6.0.49"
+#define ACI_VERSION_STR      "3.6.0.50"
 #if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF  3.6.0.49
+#define ACI_VERSION_MSRC_DEF  3.6.0.50
 #endif
 
 #define SPECIAL_VERSION ""


Commit: 808b90b39f4d1f460ad9c663a6028dc094639ecd
    https://github.com/scummvm/scummvm/commit/808b90b39f4d1f460ad9c663a6028dc094639ecd
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Common: fixes for CreateAllDirectories, Path::GetParent, GetFilename

Partially from upstream 3086f1b19d6d6a01c7f32871161cea6e5e3c13d8

Changed paths:
    engines/ags/shared/util/directory.cpp
    engines/ags/shared/util/path.cpp


diff --git a/engines/ags/shared/util/directory.cpp b/engines/ags/shared/util/directory.cpp
index 91d5559724a..802033c19ba 100644
--- a/engines/ags/shared/util/directory.cpp
+++ b/engines/ags/shared/util/directory.cpp
@@ -56,7 +56,7 @@ bool CreateAllDirectories(const String &parent, const String &sub_dirs) {
 		const char *cur = sect + 1;
 		for (; *cur && *cur != '/' && *cur != PATH_ALT_SEPARATOR; ++cur);
 		// Skip empty dirs (duplicated separators etc)
-		if ((cur - sect == 1) && (*cur == '.' || *cur == '/' || *cur == PATH_ALT_SEPARATOR)) {
+		if ((cur - sect == 1) && (*sect == '.' || *sect == '/' || *sect == PATH_ALT_SEPARATOR)) {
 			sect = cur;
 			continue;
 		}
diff --git a/engines/ags/shared/util/path.cpp b/engines/ags/shared/util/path.cpp
index e29aaf606f6..08dbae602c2 100644
--- a/engines/ags/shared/util/path.cpp
+++ b/engines/ags/shared/util/path.cpp
@@ -51,7 +51,7 @@ String get_extension(const String &path) {
 String GetParent(const String &path) {
 	const char *cstr = path.GetCStr();
 	const char *ptr_end = cstr + path.GetLength();
-	for (const char *ptr = ptr_end; ptr > cstr; --ptr) {
+	for (const char *ptr = ptr_end; ptr >= cstr; --ptr) {
 		if (*ptr == '/' || *ptr == PATH_ALT_SEPARATOR)
 			return String(cstr, ptr - cstr);
 	}


Commit: 8d3a2f07cef54b746afd9b615c28b6bfe2eea9fd
    https://github.com/scummvm/scummvm/commit/8d3a2f07cef54b746afd9b615c28b6bfe2eea9fd
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed crash upon resizing DynamicSprite while it's on screen

The bug is in UpdateSharedDDB(), the short-term texture cache did not
test whether the bitmap resolution is still matching the texture.
>From upstream 1537ed77c875bbe660face3c07a3c4843b8bd95a

Changed paths:
    engines/ags/engine/gfx/gfx_driver_base.cpp


diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 88d213b5542..be049fe51a8 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -188,7 +188,7 @@ Bitmap *VideoMemoryGraphicsDriver::GetStageBackBuffer(bool mark_dirty) {
 	return GetStageScreenRaw(_rendSpriteBatch);
 }
 
-void VideoMemoryGraphicsDriver::SetStageBackBuffer(Bitmap *backBuffer) { 
+void VideoMemoryGraphicsDriver::SetStageBackBuffer(Bitmap *backBuffer) {
 	// do nothing, video-memory drivers don't support this
 }
 
@@ -226,10 +226,20 @@ IDriverDependantBitmap *VideoMemoryGraphicsDriver::GetSharedDDB(uint32_t sprite_
 
 void VideoMemoryGraphicsDriver::UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitmap, bool hasAlpha, bool opaque) {
 	const auto found = _txRefs.find(sprite_id);
-	if (found != _txRefs.end()) {
-		auto txdata = found->_value.Data.lock();
-		if (txdata)
-			UpdateTextureData(txdata.get(), bitmap, opaque, hasAlpha);
+	if (found == _txRefs.end())
+		return;
+	auto txdata = found->second.Data.lock();
+	if (!txdata)
+		return;
+
+	// Update texture ONLY if the bitmap's resolution matches;
+	// otherwise - detach shared texture (don't delete the data yet, as it may be in use)
+	const auto &res = found->second.Res;
+	if (res.Width == bitmap->GetWidth() && res.Height == bitmap->GetHeight() && res.ColorDepth == bitmap->GetColorDepth()) {
+		UpdateTextureData(txdata.get(), bitmap, opaque, hasAlpha);
+	} else {
+		txdata->ID = UINT32_MAX;
+		_txRefs.erase(found);
 	}
 }
 


Commit: cf90c85cd4eaa3bec5d0376eeee5b9c987acb122
    https://github.com/scummvm/scummvm/commit/cf90c85cd4eaa3bec5d0376eeee5b9c987acb122
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed crash upon resizing DynamicSprite while it's on screen

The bug is in UpdateSharedDDB(), the short-term texture cache did not test
whether the bitmap resolution is still matching the texture.
>From upstream 1537ed77c875bbe660face3c07a3c4843b8bd95a

Changed paths:
    engines/ags/engine/gfx/gfx_driver_base.cpp


diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index be049fe51a8..052219d2e73 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -228,13 +228,13 @@ void VideoMemoryGraphicsDriver::UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitm
 	const auto found = _txRefs.find(sprite_id);
 	if (found == _txRefs.end())
 		return;
-	auto txdata = found->second.Data.lock();
+	auto txdata = found->_value.Data.lock();
 	if (!txdata)
 		return;
 
 	// Update texture ONLY if the bitmap's resolution matches;
 	// otherwise - detach shared texture (don't delete the data yet, as it may be in use)
-	const auto &res = found->second.Res;
+	const auto &res = found->_value.Res;
 	if (res.Width == bitmap->GetWidth() && res.Height == bitmap->GetHeight() && res.ColorDepth == bitmap->GetColorDepth()) {
 		UpdateTextureData(txdata.get(), bitmap, opaque, hasAlpha);
 	} else {


Commit: 2e784f5cd05a47c7fbb75324d4c126f897427a26
    https://github.com/scummvm/scummvm/commit/2e784f5cd05a47c7fbb75324d4c126f897427a26
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: report "voice available" only if Speech dir contains any files

This fixes IsSpeechVoxAvailable() returning positive when game is run from
 the Editor, because Speech folder is always created in the project.
>From upstream 0ca660e998e69283484f74818e17e837889e5896

Changed paths:
    engines/ags/engine/ac/speech.cpp


diff --git a/engines/ags/engine/ac/speech.cpp b/engines/ags/engine/ac/speech.cpp
index 983b43d23b3..6fbf362a7e4 100644
--- a/engines/ags/engine/ac/speech.cpp
+++ b/engines/ags/engine/ac/speech.cpp
@@ -37,6 +37,7 @@
 #include "ags/engine/ac/game_state.h"
 #include "ags/shared/core/asset_manager.h"
 #include "ags/engine/main/engine.h"
+#include "ags/shared/util/directory.h"
 #include "ags/shared/util/path.h"
 #include "ags/globals.h"
 
@@ -121,7 +122,7 @@ bool init_voicepak(const String &name) {
 			!_GP(ResPaths).VoiceDir2.IsEmpty() && Path::ComparePaths(_GP(ResPaths).DataDir, _GP(ResPaths).VoiceDir2) != 0) {
 		// If we have custom voice directory set, we will enable voice-over even if speech.vox does not exist
 		speech_subdir = name.IsEmpty() ? _GP(ResPaths).VoiceDir2 : Path::ConcatPaths(_GP(ResPaths).VoiceDir2, name);
-		if (File::IsDirectory(speech_subdir)) {
+		if (File::IsDirectory(speech_subdir) && !FindFile::OpenFiles(speech_subdir).AtEnd()) {
 			Debug::Printf(kDbgMsg_Info, "Optional voice directory is defined: %s", speech_subdir.GetCStr());
 			_GP(play).voice_avail = true;
 		}


Commit: ff0298be688ed747dec155c499898f0f0f5440fb
    https://github.com/scummvm/scummvm/commit/ff0298be688ed747dec155c499898f0f0f5440fb
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: ignore mod and special keys when skipping speech and wait

Partially from upstream 8079c87ca11fa6b60ed2dd2ce345cda6c384c00b

Changed paths:
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/shared/ac/keycode.h


diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index d4d452cd76e..62deb6dc712 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -324,7 +324,7 @@ ScreenOverlay *_display_main(int xx, int yy, int wii, const char *text, int disp
 				KeyInput ki;
 				if (run_service_key_controls(ki)) {
 					check_skip_cutscene_keypress(ki.Key);
-					if ((skip_setting & SKIP_KEYPRESS) && !_GP(play).IsIgnoringInput()) {
+					if ((skip_setting & SKIP_KEYPRESS) && !_GP(play).IsIgnoringInput() && !IsAGSServiceKey(ki.Key)) {
 						_GP(play).SetWaitKeySkip(ki);
 						do_break = true;
 					}
@@ -554,7 +554,7 @@ void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *
 	}
 }
 
-// Draw an outline if requested, then draw the text on top 
+// Draw an outline if requested, then draw the text on top
 void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int font, color_t text_color, const char *texx) {
 	size_t const text_font = static_cast<size_t>(font);
 	// Draw outline (a backdrop) if requested
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index d9b8b6950a3..c7440a3398b 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -1072,7 +1072,8 @@ void start_skipping_cutscene() {
 }
 
 bool check_skip_cutscene_keypress(int kgn) {
-
+	if (IsAGSServiceKey(static_cast<eAGSKeyCode>(kgn)))
+		return false;
 	CutsceneSkipStyle skip = get_cutscene_skipstyle();
 	if (skip == eSkipSceneAnyKey || skip == eSkipSceneKeyMouse ||
 	        (kgn == eAGSKeyCodeEscape && (skip == eSkipSceneEscOnly || skip == eSkipSceneEscOrRMB))) {
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 91badc056f9..d1d64425fc8 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -438,7 +438,7 @@ static void check_keyboard_controls() {
 	}
 
 	// skip speech if desired by Speech.SkipStyle
-	if ((_GP(play).text_overlay_on > 0) && (_GP(play).cant_skip_speech & SKIP_KEYPRESS)) {
+	if ((_GP(play).text_overlay_on > 0) && (_GP(play).cant_skip_speech & SKIP_KEYPRESS) && !IsAGSServiceKey(ki.Key)) {
 		// only allow a key to remove the overlay if the icon bar isn't up
 		if (IsGamePaused() == 0) {
 			// check if it requires a specific keypress
@@ -452,7 +452,7 @@ static void check_keyboard_controls() {
 		return;
 	}
 
-	if ((_GP(play).wait_counter != 0) && (_GP(play).key_skip_wait & SKIP_KEYPRESS) != 0) {
+	if ((_GP(play).wait_counter != 0) && (_GP(play).key_skip_wait & SKIP_KEYPRESS) && !IsAGSServiceKey(ki.Key)) {
 		_GP(play).SetWaitKeySkip(ki);
 		return;
 	}
diff --git a/engines/ags/shared/ac/keycode.h b/engines/ags/shared/ac/keycode.h
index bd9e67ea13e..d2a4cdfa31d 100644
--- a/engines/ags/shared/ac/keycode.h
+++ b/engines/ags/shared/ac/keycode.h
@@ -77,8 +77,8 @@ enum eAGSKeyCode {
 	eAGSKeyCodeCtrlZ = 26,
 
 	eAGSKeyCodeBackspace = 8, // matches Ctrl + H
-	eAGSKeyCodeTab = 9, // matches Ctrl + I
-	eAGSKeyCodeReturn = 13, // matches Ctrl + M
+	eAGSKeyCodeTab = 9,       // matches Ctrl + I
+	eAGSKeyCodeReturn = 13,   // matches Ctrl + M
 	eAGSKeyCodeEscape = 27,
 
 	/* printable chars - from eAGSKeyCodeSpace to eAGSKeyCode_z */
@@ -207,13 +207,19 @@ enum eAGSKeyCode {
 	eAGSKeyCodeInsert = AGS_EXT_KEY_SHIFT + 82,
 	eAGSKeyCodeDelete = AGS_EXT_KEY_SHIFT + 83,
 
-	// not certain if necessary anymore (and not certain what was the origin of this value)
-	eAGSKeyCodeAltTab = AGS_EXT_KEY_SHIFT + 99,
-
 	// [sonneveld] These are only used by debugging and abort keys.
 	// They're based on allegro4 codes ...
 	eAGSKeyCodeAltV = AGS_EXT_KEY_ALPHA(eAGSKeyCodeV),
 	eAGSKeyCodeAltX = AGS_EXT_KEY_ALPHA(eAGSKeyCodeX),
+	eAGSKeyCodeAltY = AGS_EXT_KEY_ALPHA(eAGSKeyCodeY),
+	eAGSKeyCodeAltZ = AGS_EXT_KEY_ALPHA(eAGSKeyCodeZ),
+
+	// The beginning of "service key list": mod keys and other special keys
+	// not normally intended to affect the default game logic
+	eAGSKeyCode_FirstServiceKey = 391,
+
+	// not certain if necessary anymore (and not certain what was the origin of this value)
+	eAGSKeyCodeAltTab = AGS_EXT_KEY_SHIFT + 99,
 
 	// These keys are not defined in the script eAGSKey enum but are in the manual
 	// https://adventuregamestudio.github.io/ags-manual/ASCIIcodes.html
@@ -296,6 +302,17 @@ enum eAGSMouseButton
 	kNumMouseButtons
 };
 
+// Tells if the AGS keycode refers to the modifier key (ctrl, alt, etc)
+inline bool IsAGSModKey(eAGSKeyCode keycode) {
+	return (keycode >= eAGSKeyCodeLShift && keycode <= eAGSKeyCodeLAlt) || keycode == eAGSKeyCodeRAlt;
+}
+
+// Tells if the AGS keycode refers to the service key (modifier, PrintScreen and similar);
+// this lets distinct keys that normally should not affect the game
+inline bool IsAGSServiceKey(eAGSKeyCode keycode) {
+	return keycode >= eAGSKeyCode_FirstServiceKey;
+}
+
 // Converts eAGSKeyCode to script API code, for "on_key_press" and similar callbacks
 eAGSKeyCode AGSKeyToScriptKey(eAGSKeyCode keycode);
 // Converts eAGSKeyCode to ASCII text representation with the range check; returns 0 on failure


Commit: 4966d2a8961ff8cbd7b6ad38bf8dd939b6847fa0
    https://github.com/scummvm/scummvm/commit/4966d2a8961ff8cbd7b6ad38bf8dd939b6847fa0
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: apply character's anim volume to portrait animation

+ process frame features for the first portrait frame too.
>From upstream 59d4f740001b61af370ec0bca676a24d597f66b2

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/character.h
    engines/ags/engine/main/update.cpp


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 4cd92697088..f08009a5358 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -2063,7 +2063,11 @@ void stop_character_anim(CharacterInfo *chap) { // TODO: may expand with resetti
 	_GP(charextra)[chap->index_id].cur_anim_volume = 100;
 }
 
-void CheckViewFrameForCharacter(CharacterInfo * chi) {
+void CheckViewFrameForCharacter(CharacterInfo *chi) {
+	CheckViewFrame(chi->view, chi->loop, chi->frame, GetCharacterFrameVolume(chi));
+}
+
+int GetCharacterFrameVolume(CharacterInfo * chi) {
 	// We view the audio property relation as the relation of the entities:
 	// system -> audio type -> audio emitter (character) -> animation's audio
 	// therefore the sound volume is a multiplication of factors.
@@ -2084,8 +2088,7 @@ void CheckViewFrameForCharacter(CharacterInfo * chi) {
 			zoom_level = std::min(zoom_level, 100);
 		frame_vol = frame_vol * zoom_level / 100;
 	}
-
-	CheckViewFrame(chi->view, chi->loop, chi->frame, frame_vol);
+	return frame_vol;
 }
 
 Bitmap *GetCharacterImage(int charid, int *isFlipped) {
@@ -2610,10 +2613,10 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 			if (_GP(game).options[OPT_SPEECHTYPE] == 3)
 				overlay_x = 0;
 			_G(face_talking) = add_screen_overlay(false, overlay_x, ovr_yp, ovr_type, closeupface, closeupface_has_alpha);
+			_G(facetalkview) = useview;
+			_G(facetalkloop) = 0;
 			_G(facetalkframe) = 0;
 			_G(facetalkwait) = viptr->loops[0].frames[0].speed + GetCharacterSpeechAnimationDelay(speakingChar);
-			_G(facetalkloop) = 0;
-			_G(facetalkview) = useview;
 			_G(facetalkrepeat) = (isThought) ? 0 : 1;
 			_G(facetalkBlinkLoop) = 0;
 			_G(facetalkAllowBlink) = 1;
@@ -2624,6 +2627,9 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 				_G(facetalkchar)->blinktimer = _G(facetalkchar)->blinkinterval;
 			textcol = -textcol;
 			overlayPositionFixed = true;
+			// Process the first portrait view frame
+			const int frame_vol = GetCharacterFrameVolume(_G(facetalkchar));
+			CheckViewFrame(_G(facetalkview), _G(facetalkloop), _G(facetalkframe), frame_vol);
 		} else if (useview >= 0) {
 			// Lucasarts-style speech
 			_G(our_eip) = 154;
diff --git a/engines/ags/engine/ac/character.h b/engines/ags/engine/ac/character.h
index 6b24bad1f77..61e52bb963c 100644
--- a/engines/ags/engine/ac/character.h
+++ b/engines/ags/engine/ac/character.h
@@ -203,6 +203,7 @@ int  is_valid_character(int newchar);
 int  wantMoveNow(CharacterInfo *chi, CharacterExtras *chex);
 void setup_player_character(int charid);
 void CheckViewFrameForCharacter(CharacterInfo *chi);
+int  GetCharacterFrameVolume(CharacterInfo *chi);
 Shared::Bitmap *GetCharacterImage(int charid, int *isFlipped);
 CharacterInfo *GetCharacterAtScreen(int xx, int yy);
 CharacterInfo *GetCharacterAtRoom(int x, int y);
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index 33e1014ab6f..2e7babf2449 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -378,10 +378,11 @@ void update_sierra_speech() {
 		// _G(is_text_overlay) might be 0 if it was only just destroyed this loop
 		if ((updatedFrame) && (_GP(play).text_overlay_on > 0)) {
 
+			const int frame_vol = GetCharacterFrameVolume(_G(facetalkchar));
 			if (updatedFrame & 1)
-				CheckViewFrame(_G(facetalkview), _G(facetalkloop), _G(facetalkframe));
+				CheckViewFrame(_G(facetalkview), _G(facetalkloop), _G(facetalkframe), frame_vol);
 			if (updatedFrame & 2)
-				CheckViewFrame(_G(facetalkchar)->blinkview, _G(facetalkBlinkLoop), _G(facetalkchar)->blinkframe);
+				CheckViewFrame(_G(facetalkchar)->blinkview, _G(facetalkBlinkLoop), _G(facetalkchar)->blinkframe, frame_vol);
 
 			int thisPic = _GP(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)].pic;
 			int view_frame_x = 0;


Commit: 3c4b80e14ceb445febfe92304fa3548cfeb5d260
    https://github.com/scummvm/scummvm/commit/3c4b80e14ceb445febfe92304fa3548cfeb5d260
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: report missing speech.vox as an "info", since this is optional

>From upstream c6b5654a9cc7af05529c76b2a1d8ec3ad75c2c73

Changed paths:
    engines/ags/engine/ac/speech.cpp


diff --git a/engines/ags/engine/ac/speech.cpp b/engines/ags/engine/ac/speech.cpp
index 6fbf362a7e4..503e3e629b6 100644
--- a/engines/ags/engine/ac/speech.cpp
+++ b/engines/ags/engine/ac/speech.cpp
@@ -113,7 +113,7 @@ bool init_voicepak(const String &name) {
 		Debug::Printf(kDbgMsg_Info, "Voice pack found: %s", speech_file.GetCStr());
 		_GP(play).voice_avail = true;
 	} else {
-		Debug::Printf(kDbgMsg_Error, "Unable to init voice pack '%s', file not found or of unknown format.",
+		Debug::Printf(kDbgMsg_Info, "Was not able to init voice pack '%s': file not found or of unknown format.",
 			speech_file.GetCStr());
 	}
 


Commit: a6edbb5701fb22116719c4c2762a57805a73968a
    https://github.com/scummvm/scummvm/commit/a6edbb5701fb22116719c4c2762a57805a73968a
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed few game warnings, may fill up the log in some games

Partially from upstream 8b2c97672d179f0ea33890c66bb2baa7131dd3a4

Changed paths:
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/ac/global_gui.cpp
    engines/ags/engine/ac/sys_events.h


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 23c669b26db..29c8ab02454 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -120,12 +120,13 @@ void DeleteSaveSlot(int slnum) {
 
 void PauseGame() {
 	_G(game_paused)++;
-	debug_script_log("Game paused");
+	debug_script_log("Game paused (%d)", _G(game_paused));
 }
 void UnPauseGame() {
-	if (_G(game_paused) > 0)
+	if (_G(game_paused) > 0) {
 		_G(game_paused)--;
-	debug_script_log("Game UnPaused, pause level now %d", _G(game_paused));
+		debug_script_log("Game un-paused (%d)", _G(game_paused));
+	}
 }
 
 
@@ -653,12 +654,7 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 }
 
 int IsKeyPressed(int keycode) {
-	auto status = ags_iskeydown(static_cast<eAGSKeyCode>(keycode));
-	if (status < 0) {
-		debug_script_log("IsKeyPressed: unsupported keycode %d", keycode);
-		return 0;
-	}
-	return status;
+	return ags_iskeydown(static_cast<eAGSKeyCode>(keycode));
 }
 
 int SaveScreenShot(const char *namm) {
diff --git a/engines/ags/engine/ac/global_gui.cpp b/engines/ags/engine/ac/global_gui.cpp
index c74f09e7c64..01806e0006a 100644
--- a/engines/ags/engine/ac/global_gui.cpp
+++ b/engines/ags/engine/ac/global_gui.cpp
@@ -68,7 +68,6 @@ void InterfaceOn(int ifn) {
 	EndSkippingUntilCharStops();
 
 	if (_GP(guis)[ifn].IsVisible()) {
-		debug_script_log("GUIOn(%d) ignored (already on)", ifn);
 		return;
 	}
 	_GP(guis)[ifn].SetVisible(true);
@@ -83,7 +82,6 @@ void InterfaceOn(int ifn) {
 void InterfaceOff(int ifn) {
 	if ((ifn < 0) | (ifn >= _GP(game).numgui)) quit("!GUIOff: invalid GUI specified");
 	if (!_GP(guis)[ifn].IsVisible()) {
-		debug_script_log("GUIOff(%d) ignored (already off)", ifn);
 		return;
 	}
 	debug_script_log("GUI %d turned off", ifn);
diff --git a/engines/ags/engine/ac/sys_events.h b/engines/ags/engine/ac/sys_events.h
index 6b08c30348a..dc4f4ebe249 100644
--- a/engines/ags/engine/ac/sys_events.h
+++ b/engines/ags/engine/ac/sys_events.h
@@ -59,8 +59,7 @@ extern KeyInput ags_keycode_from_scummvm(const Common::Event &event, bool old_ke
 extern bool ags_keyevent_ready();
 // Queries for the next key event in buffer; returns uninitialized data if none was queued
 extern Common::Event ags_get_next_keyevent();
-// Tells if the key is currently down, provided AGS key;
-// Returns positive value if it's down, 0 if it's not, negative value if the key code is not supported.
+// Tells if the key is currently down, provided AGS key.
 // NOTE: for particular script codes this function returns positive if either of two keys are down.
 extern int ags_iskeydown(eAGSKeyCode ags_key);
 // Simulates key press with the given AGS key


Commit: d9377bbb6377c3d56dae119f506200b08351c8a9
    https://github.com/scummvm/scummvm/commit/d9377bbb6377c3d56dae119f506200b08351c8a9
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: Fix typo in commit b81abc533f508e5831e7ca6d2512c66d506ef09d

loopIterations -> loopCheckIterations

Changed paths:
    engines/ags/engine/script/cc_instance.cpp


diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 10067a1b986..5f36b8e56ef 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -794,7 +794,7 @@ int ccInstance::Run(int32_t curpc) {
 					flags &= ~INSTF_RUNNING;
 					loopIterations = 0u;
 					loopCheckIterations = 0u;
-				} else if ((loopIterationCheckDisabled == 0) && (_G(maxWhileLoops) > 0) && (++loopIterations > _G(maxWhileLoops))) {
+				} else if ((loopIterationCheckDisabled == 0) && (_G(maxWhileLoops) > 0) && (++loopCheckIterations > _G(maxWhileLoops))) {
 					cc_error("!Script appears to be hung (a while loop ran %d times). The problem may be in a calling function; check the call stack.", (int)loopCheckIterations);
 					return -1;
 				} else if ((loopIterations & 0x3FF) == 0 && // test each 1024 loops (arbitrary)


Commit: 793a5d62734ba2bee2fa72ad27d8ffc76d300a67
    https://github.com/scummvm/scummvm/commit/793a5d62734ba2bee2fa72ad27d8ffc76d300a67
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed System.Log() may cause exceptions with wrong format

>From upstream ec9c494e391db23d587708cbe20cc6203b503396

Changed paths:
    engines/ags/engine/ac/system.cpp


diff --git a/engines/ags/engine/ac/system.cpp b/engines/ags/engine/ac/system.cpp
index ddee4daff7a..36c3e8a6e84 100644
--- a/engines/ags/engine/ac/system.cpp
+++ b/engines/ags/engine/ac/system.cpp
@@ -351,7 +351,7 @@ RuntimeScriptValue Sc_System_SaveConfigToFile(const RuntimeScriptValue *params,
 
 RuntimeScriptValue Sc_System_Log(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_SCRIPT_SPRINTF_PURE(Sc_System_Log, 2);
-	Debug::Printf(kDbgGroup_Script, (MessageType)params[0].IValue, scsf_buffer);
+	Debug::Printf(kDbgGroup_Script, (MessageType)params[0].IValue, "%s", scsf_buffer);
 	return RuntimeScriptValue((int32_t)0);
 }
 


Commit: 7688ff025f860fc8826b9c5fbb6308a7e1fa91e5
    https://github.com/scummvm/scummvm/commit/7688ff025f860fc8826b9c5fbb6308a7e1fa91e5
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: sync audio in case of scheduled post-script actions

This fixes a case when a clip was ordered to Play right before
a Room change, or similar game mode change, but is delayed
 until after the change occurs.
>From upstream d327b06bf5f3d8fff02b454d07560fcd5fc05b24

Changed paths:
    engines/ags/engine/script/script.cpp


diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 0af73d5442d..e1ee81cc29a 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -500,6 +500,11 @@ void post_script_cleanup() {
 
 	int old_room_number = _G(displayed_room);
 
+	// FIXME: sync audio in case any screen changing or time-consuming post-script actions were scheduled
+	if (copyof.numPostScriptActions > 0) {
+		sync_audio_playback();
+	}
+
 	// run the queued post-script actions
 	for (int ii = 0; ii < copyof.numPostScriptActions; ii++) {
 		int thisData = copyof.postScriptActionData[ii];
@@ -551,6 +556,9 @@ void post_script_cleanup() {
 		}
 	}
 
+	if (copyof.numPostScriptActions > 0) {
+		sync_audio_playback();
+	}
 
 	for (int jj = 0; jj < copyof.numanother; jj++) {
 		old_room_number = _G(displayed_room);


Commit: 9e6dfbf2584ddd63da859a9a565a64f98e988c4c
    https://github.com/scummvm/scummvm/commit/9e6dfbf2584ddd63da859a9a565a64f98e988c4c
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: ensure that restricted game options not loaded from save

This fixes occasional problem with save overriding game options that
must not be changed at runtime.
>From upstream cf093f3a6ea657a2082edfc08c35cc7650961ab6

Changed paths:
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame_internal.h


diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index ce52665877a..f21ee9915da 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -327,6 +327,7 @@ HSaveError OpenSavegame(const String &filename, SavegameDescription &desc, Saveg
 void DoBeforeRestore(PreservedParams &pp) {
 	pp.SpeechVOX = _GP(play).voice_avail;
 	pp.MusicVOX = _GP(play).separate_music_lib;
+	memcpy(pp.GameOptions, _GP(game).options, GameSetupStruct::MAX_OPTIONS * sizeof(int));
 
 	unload_old_room();
 	delete _G(raw_saved_screen);
@@ -423,6 +424,17 @@ void RestoreViewportsAndCameras(const RestoredData &r_data) {
 	_GP(play).InvalidateViewportZOrder();
 }
 
+// Resets a number of options that are not supposed to be changed at runtime
+static void CopyPreservedGameOptions(GameSetupStructBase &gs, const PreservedParams &pp) {
+	const Common::Array<int> preserved_opts = {{OPT_DEBUGMODE, OPT_LETTERBOX, OPT_HIRES_FONTS, OPT_SPLITRESOURCES,
+												OPT_STRICTSCRIPTING, OPT_LEFTTORIGHTEVAL, OPT_COMPRESSSPRITES, OPT_STRICTSTRINGS,
+												OPT_NATIVECOORDINATES, OPT_SAFEFILEPATHS, OPT_DIALOGOPTIONSAPI, OPT_BASESCRIPTAPI,
+												OPT_SCRIPTCOMPATLEV, OPT_RELATIVEASSETRES, OPT_GAMETEXTENCODING, OPT_KEYHANDLEAPI,
+												OPT_CUSTOMENGINETAG}};
+	for (auto opt : preserved_opts)
+		gs.options[opt] = pp.GameOptions[opt];
+}
+
 // Final processing after successfully restoring from save
 HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data) {
 	// Use a yellow dialog highlight for older game versions
@@ -434,6 +446,9 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	_GP(play).voice_avail = pp.SpeechVOX;
 	_GP(play).separate_music_lib = pp.MusicVOX;
 
+	// Restore particular game options that must not change at runtime
+	CopyPreservedGameOptions(_GP(game), pp);
+
 	// Restore debug flags
 	if (_G(debug_flags) & DBG_DEBUGMODE)
 		_GP(play).debug_mode = 1;
diff --git a/engines/ags/engine/game/savegame_internal.h b/engines/ags/engine/game/savegame_internal.h
index 92721a56fca..8ef51753a8f 100644
--- a/engines/ags/engine/game/savegame_internal.h
+++ b/engines/ags/engine/game/savegame_internal.h
@@ -43,10 +43,12 @@ typedef std::shared_ptr<Bitmap> PBitmap;
 // loading save data
 struct PreservedParams {
 	// Whether speech and audio packages available
-	bool SpeechVOX;
-	bool MusicVOX;
+	bool SpeechVOX = false;
+	bool MusicVOX = false;
+	// Game options, to preserve ones that must not change at runtime
+	int GameOptions[GameSetupStructBase::MAX_OPTIONS]{};
 	// Script global data sizes
-	size_t GlScDataSize;
+	size_t GlScDataSize = 0u;
 	std::vector<size_t> ScMdDataSize;
 
 	PreservedParams();


Commit: e946f9f99d44a92c7bbede4033a80649b6e15c36
    https://github.com/scummvm/scummvm/commit/e946f9f99d44a92c7bbede4033a80649b6e15c36
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: fixed GfxDriverSpriteEvtCallback return value for no room case

>From upstream e3bb8a85d2af9c425528eb7a2f16741e2de7b9ab

Changed paths:
    engines/ags/engine/ac/draw.cpp


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 2ef276f2473..66f6320e9be 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -2052,7 +2052,7 @@ void put_sprite_list_on_screen(bool in_room) {
 bool GfxDriverSpriteEvtCallback(int evt, int data) {
 	if (_G(displayed_room) < 0) {
 		// if no room loaded, various stuff won't be initialized yet
-		return 1;
+		return false;
 	}
 	return (pl_run_plugin_hooks(evt, data) != 0);
 }


Commit: 6ea6675b3cdc0430627df69a7023b69c2007d466
    https://github.com/scummvm/scummvm/commit/6ea6675b3cdc0430627df69a7023b69c2007d466
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: tidy some code related to the old save format constants

>From upstream fac1a5bed8e84d210a7ac6878133e13c39bde20b

Changed paths:
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/main/main.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index f21ee9915da..1f939880a5d 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -238,13 +238,13 @@ HSaveError ReadDescription_v321(Stream *in, SavegameVersion &svg_ver, SavegameDe
 	else
 		SkipSaveImage(in);
 
+	const Version low_compat_version(3, 2, 0, 1123);
 	String version_str = String::FromStream(in);
 	Version eng_version(version_str);
-	if (eng_version > _G(EngineVersion) ||
-	        eng_version < _G(SavedgameLowestBackwardCompatVersion)) {
+	if (eng_version > _G(EngineVersion) || eng_version < low_compat_version) {
 		// Engine version is either non-forward or non-backward compatible
 		return new SavegameError(kSvgErr_IncompatibleEngine,
-		                         String::FromFormat("Required: %s, supported: %s - %s.", eng_version.LongString.GetCStr(), _G(SavedgameLowestBackwardCompatVersion).LongString.GetCStr(), _G(EngineVersion).LongString.GetCStr()));
+		                         String::FromFormat("Required: %s, supported: %s - %s.", eng_version.LongString.GetCStr(), low_compat_version.LongString.GetCStr(), _G(EngineVersion).LongString.GetCStr()));
 	}
 	if (elems & kSvgDesc_EnvInfo) {
 		desc.MainDataFilename.Read(in);
diff --git a/engines/ags/engine/main/main.cpp b/engines/ags/engine/main/main.cpp
index 0257a266e52..f5f8dc1f762 100644
--- a/engines/ags/engine/main/main.cpp
+++ b/engines/ags/engine/main/main.cpp
@@ -47,18 +47,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-// this needs to be updated if the "play" struct changes
-#define SVG_VERSION_BWCOMPAT_MAJOR      3
-#define SVG_VERSION_BWCOMPAT_MINOR      2
-#define SVG_VERSION_BWCOMPAT_RELEASE    0
-#define SVG_VERSION_BWCOMPAT_REVISION   1103
-// CHECKME: we may lower this down, if we find that earlier versions may still
-// load new savedgames
-#define SVG_VERSION_FWCOMPAT_MAJOR      3
-#define SVG_VERSION_FWCOMPAT_MINOR      2
-#define SVG_VERSION_FWCOMPAT_RELEASE    1
-#define SVG_VERSION_FWCOMPAT_REVISION   1111
-
 void main_init(int argc, const char *argv[]) {
 	_G(our_eip) = -999;
 
@@ -70,8 +58,6 @@ void main_init(int argc, const char *argv[]) {
 #if defined (BUILD_STR)
 	_G(EngineVersion).BuildInfo = BUILD_STR;
 #endif
-	_G(SavedgameLowestBackwardCompatVersion) = Version(SVG_VERSION_BWCOMPAT_MAJOR, SVG_VERSION_BWCOMPAT_MINOR, SVG_VERSION_BWCOMPAT_RELEASE, SVG_VERSION_BWCOMPAT_REVISION);
-	_G(SavedgameLowestForwardCompatVersion) = Version(SVG_VERSION_FWCOMPAT_MAJOR, SVG_VERSION_FWCOMPAT_MINOR, SVG_VERSION_FWCOMPAT_RELEASE, SVG_VERSION_FWCOMPAT_REVISION);
 
 	_G(platform) = AGSPlatformDriver::GetDriver();
 	_G(platform)->SetCommandArgs(argv, argc);
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index bbfe52c49f9..c0b9979f03e 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1107,10 +1107,6 @@ public:
 
 	// Current engine version
 	Version _EngineVersion;
-	// Lowest savedgame version, accepted by this engine
-	Version _SavedgameLowestBackwardCompatVersion;
-	// Lowest engine version, which would accept current savedgames
-	Version _SavedgameLowestForwardCompatVersion;
 
 	/**@}*/
 


Commit: 5039b5f3a6bf2106c7ad6dd96780489708796c78
    https://github.com/scummvm/scummvm/commit/5039b5f3a6bf2106c7ad6dd96780489708796c78
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Engine: small refactor, rem duplicate list of restricted game options

>From upstream c4efd74fd28b31ee786e85a0ecc4a7c1fcb0685a

Changed paths:
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/shared/ac/game_setup_struct_base.h


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 29c8ab02454..d2ca3bca5cc 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -403,32 +403,17 @@ int SetGameOption(int opt, int newval) {
 	}
 
 	// Handle forbidden options
-	switch (opt) {
-	case OPT_DEBUGMODE: // we don't support switching OPT_DEBUGMODE from script
-	case OPT_LETTERBOX:
-	case OPT_HIRES_FONTS:
-	case OPT_SPLITRESOURCES:
-	case OPT_STRICTSCRIPTING:
-	case OPT_LEFTTORIGHTEVAL:
-	case OPT_COMPRESSSPRITES:
-	case OPT_STRICTSTRINGS:
-	case OPT_NATIVECOORDINATES:
-	case OPT_SAFEFILEPATHS:
-	case OPT_DIALOGOPTIONSAPI:
-	case OPT_BASESCRIPTAPI:
-	case OPT_SCRIPTCOMPATLEV:
-	case OPT_RELATIVEASSETRES:
-	case OPT_GAMETEXTENCODING:
-	case OPT_KEYHANDLEAPI:
-	case OPT_CUSTOMENGINETAG:
-		debug_script_warn("SetGameOption: option %d cannot be modified at runtime", opt);
-		return _GP(game).options[opt];
-	default:
-		break;
+	const auto restricted_opts = GameSetupStructBase::GetRestrictedOptions();
+	for (auto r_opt : restricted_opts) {
+		if (r_opt == opt) {
+			debug_script_warn("SetGameOption: option %d cannot be modified at runtime", opt);
+			return _GP(game).options[opt];
+		}
 	}
 
+	// Test if option already has this value
 	if (_GP(game).options[opt] == newval)
-		return _GP(game).options[opt]; // no change necessary
+		return _GP(game).options[opt];
 
 	const int oldval = _GP(game).options[opt];
 	_GP(game).options[opt] = newval;
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 1f939880a5d..7345993e1a4 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -426,12 +426,8 @@ void RestoreViewportsAndCameras(const RestoredData &r_data) {
 
 // Resets a number of options that are not supposed to be changed at runtime
 static void CopyPreservedGameOptions(GameSetupStructBase &gs, const PreservedParams &pp) {
-	const Common::Array<int> preserved_opts = {{OPT_DEBUGMODE, OPT_LETTERBOX, OPT_HIRES_FONTS, OPT_SPLITRESOURCES,
-												OPT_STRICTSCRIPTING, OPT_LEFTTORIGHTEVAL, OPT_COMPRESSSPRITES, OPT_STRICTSTRINGS,
-												OPT_NATIVECOORDINATES, OPT_SAFEFILEPATHS, OPT_DIALOGOPTIONSAPI, OPT_BASESCRIPTAPI,
-												OPT_SCRIPTCOMPATLEV, OPT_RELATIVEASSETRES, OPT_GAMETEXTENCODING, OPT_KEYHANDLEAPI,
-												OPT_CUSTOMENGINETAG}};
-	for (auto opt : preserved_opts)
+	const auto restricted_opts = GameSetupStructBase::GetRestrictedOptions();
+	for (auto opt : restricted_opts)
 		gs.options[opt] = pp.GameOptions[opt];
 }
 
diff --git a/engines/ags/shared/ac/game_setup_struct_base.h b/engines/ags/shared/ac/game_setup_struct_base.h
index 26a0160bbdb..0a23078aa9a 100644
--- a/engines/ags/shared/ac/game_setup_struct_base.h
+++ b/engines/ags/shared/ac/game_setup_struct_base.h
@@ -219,6 +219,17 @@ struct GameSetupStructBase {
 		return IsLegacyAudioSystem() ? "music.vox" : "audio.vox";
 	}
 
+	// Returns a list of game options that are forbidden to change at runtime
+	inline static Common::Array<int> GetRestrictedOptions() {
+		return Common::Array<int> {{
+			OPT_DEBUGMODE, OPT_LETTERBOX, OPT_HIRES_FONTS, OPT_SPLITRESOURCES,
+			OPT_STRICTSCRIPTING, OPT_LEFTTORIGHTEVAL, OPT_COMPRESSSPRITES, OPT_STRICTSTRINGS,
+			OPT_NATIVECOORDINATES, OPT_SAFEFILEPATHS, OPT_DIALOGOPTIONSAPI, OPT_BASESCRIPTAPI,
+			OPT_SCRIPTCOMPATLEV, OPT_RELATIVEASSETRES, OPT_GAMETEXTENCODING, OPT_KEYHANDLEAPI,
+			OPT_CUSTOMENGINETAG
+		}};
+	}
+
 private:
 	void SetDefaultResolution(GameResolutionType type, Size game_res);
 	void SetNativeResolution(GameResolutionType type, Size game_res);


Commit: 58fc875836007dc3053ec52b6c12bcb941cc169f
    https://github.com/scummvm/scummvm/commit/58fc875836007dc3053ec52b6c12bcb941cc169f
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-08-13T10:58:26+02:00

Commit Message:
AGS: Updated build version (3.6.0.51)

Partially from upstream 2a0177cc7cf114cf9585e39a7d7db68dbfc4bb8a

Changed paths:
    engines/ags/shared/core/def_version.h


diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 0ef1f023eda..73232b179ac 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
 #ifndef AGS_SHARED_CORE_DEFVERSION_H
 #define AGS_SHARED_CORE_DEFVERSION_H
 
-#define ACI_VERSION_STR      "3.6.0.50"
+#define ACI_VERSION_STR      "3.6.0.51"
 #if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF  3.6.0.50
+#define ACI_VERSION_MSRC_DEF  3.6.0.51
 #endif
 
 #define SPECIAL_VERSION ""




More information about the Scummvm-git-logs mailing list