[Scummvm-git-logs] scummvm master -> 3c062750ede859c240d169d5644fb217b51647aa

dreammaster noreply at scummvm.org
Sun Mar 20 04:25:41 UTC 2022


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

Summary:
a4bf82bd35 AGS: Removed "volume" param out of load clip factory functions
699a72af3b AGS: Removed redundant sound destroy calls
256cc2658a AGS: Note skipping merge of SOUNDCLIP and CLIP_OPENAL
16b89bd8ea AGS: tidy SOUNDCLIP's fields (volume, panning) and methods
d013cdfe3d AGS: Skipped "transactional" SOUNDCLIP commit
0988fbbe78 AGS: Dispose SOUNDCLIP when stopped playing
9e68fb7852 AGS: Fixed snprintf in PlayMP3File()
28d91ca846 AGS: Try report script section and line on fixup error
429dab7475 AGS: Updated build version (3.5.1.11)
19e7035ded AGS: Replaced few function params from PScript to ccScript*
02a6600080 AGS: Fix potentially invalid frame during Character turning
6aa5960eed AGS: Ensure quit() is called if engine startup was interrupted
394347a75d AGS: Reimplemented room area debug display as a persistent overlay
b0233b607e AGS: Update debug layer for walkable mask in realtime
cf62e3979b AGS: Reimplemented walk path display as a persistent overlay
3c062750ed AGS: Remove random limit of 50 walk speed and clamp to int16 limits


Commit: a4bf82bd3576584a744c47bed44db55d33b5f748
    https://github.com/scummvm/scummvm/commit/a4bf82bd3576584a744c47bed44db55d33b5f748
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:08-07:00

Commit Message:
AGS: Removed "volume" param out of load clip factory functions

>From upstream 903c4d7d69bf0400447b099cbd0b2818f3c1f7c7

Changed paths:
    engines/ags/engine/ac/global_audio.cpp
    engines/ags/engine/media/audio/audio.cpp
    engines/ags/engine/media/audio/sound.cpp
    engines/ags/engine/media/audio/sound.h
    engines/ags/engine/media/audio/sound_clip.cpp
    engines/ags/engine/media/audio/sound_clip.h
    engines/ags/plugins/ags_plugin.cpp


diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index 06e1d5128be..09e4420147e 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -375,40 +375,31 @@ void PlayMP3File(const char *filename) {
 	bool doLoop = (_GP(play).music_repeat > 0);
 
 	SOUNDCLIP *clip = nullptr;
+	int sound_type = 0;
 
 	if (!clip) {
-		clip = my_load_static_ogg(asset_name, 150, doLoop);
-		if (clip) {
-			if (clip->play()) {
-				AudioChans::SetChannel(useChan, clip);
-				_G(current_music_type) = MUS_OGG;
-				_GP(play).cur_music_number = 1000;
-				// save the filename (if it's not what we were supplied with)
-				if (filename != &_GP(play).playmp3file_name[0])
-					strcpy(_GP(play).playmp3file_name, filename);
-			} else {
-				clip->destroy();
-				delete clip;
-				clip = nullptr;
-			}
-		}
+		clip = my_load_ogg(asset_name, doLoop);
+		sound_type = MUS_OGG;
 	}
 
 	if (!clip) {
-		clip = my_load_static_mp3(asset_name, 150, doLoop);
-		if (clip) {
-			if (clip->play()) {
-				AudioChans::SetChannel(useChan, clip);
-				_G(current_music_type) = MUS_MP3;
-				_GP(play).cur_music_number = 1000;
-				// save the filename (if it's not what we were supplied with)
-				if (filename != &_GP(play).playmp3file_name[0])
-					strcpy(_GP(play).playmp3file_name, filename);
-			} else {
-				clip->destroy();
-				delete clip;
-				clip = nullptr;
-			}
+		clip = my_load_mp3(asset_name, doLoop);
+		sound_type = MUS_MP3;
+	}
+
+	if (clip) {
+		clip->set_volume(150);
+		if (clip->play()) {
+			AudioChans::SetChannel(useChan, clip);
+			_G(current_music_type) = sound_type;
+			_GP(play).cur_music_number = 1000;
+			// save the filename (if it's not what we were supplied with)
+			if (filename != &_GP(play).playmp3file_name[0])
+				snprintf(_GP(play).playmp3file_name, sizeof(_GP(play).playmp3file_name), filename);
+		} else {
+			clip->destroy();
+			delete clip;
+			clip = nullptr;
 		}
 	}
 
@@ -517,16 +508,26 @@ static bool play_voice_clip_on_channel(const String &voice_name) {
 
 	String asset_name = voice_name;
 	asset_name.Append(".wav");
-	SOUNDCLIP *speechmp3 = my_load_wave(get_voice_over_assetpath(asset_name), _GP(play).speech_volume, 0);
+	SOUNDCLIP *speechmp3 = my_load_wave(get_voice_over_assetpath(asset_name), false);
 
 	if (speechmp3 == nullptr) {
 		asset_name.ReplaceMid(asset_name.GetLength() - 3, 3, "ogg");
-		speechmp3 = my_load_ogg(get_voice_over_assetpath(asset_name), _GP(play).speech_volume);
+		speechmp3 = my_load_ogg(get_voice_over_assetpath(asset_name), false);
 	}
 
 	if (speechmp3 == nullptr) {
 		asset_name.ReplaceMid(asset_name.GetLength() - 3, 3, "mp3");
-		speechmp3 = my_load_mp3(get_voice_over_assetpath(asset_name), _GP(play).speech_volume);
+		speechmp3 = my_load_mp3(get_voice_over_assetpath(asset_name), false);
+	}
+
+	if (speechmp3 != nullptr) {
+		speechmp3->set_volume(_GP(play).speech_volume);
+		if (!speechmp3->play()) {
+			// not assigned to a channel, so clean up manually.
+			speechmp3->destroy();
+			delete speechmp3;
+			speechmp3 = nullptr;
+		}
 	}
 
 	if (speechmp3 == nullptr) {
@@ -534,13 +535,6 @@ static bool play_voice_clip_on_channel(const String &voice_name) {
 		return false;
 	}
 
-	if (!speechmp3->play()) {
-		// Could not play, so clean up manually.
-		speechmp3->destroy();
-		delete speechmp3;
-		speechmp3 = nullptr;
-	}
-
 	AudioChans::SetChannel(SCHAN_SPEECH, speechmp3);
 	return true;
 }
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index 0f231120d5a..366293594f0 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -202,14 +202,14 @@ SOUNDCLIP *load_sound_clip(ScriptAudioClip *audioClip, bool repeat) {
 	AssetPath asset_name = get_audio_clip_assetpath(audioClip->bundlingType, audioClip->fileName);
 	switch (audioClip->fileType) {
 	case eAudioFileOGG:
-		soundClip = my_load_static_ogg(asset_name, audioClip->defaultVolume, repeat);
+		soundClip = my_load_static_ogg(asset_name, repeat);
 		break;
 	case eAudioFileMP3:
-		soundClip = my_load_static_mp3(asset_name, audioClip->defaultVolume, repeat);
+		soundClip = my_load_static_mp3(asset_name, repeat);
 		break;
 	case eAudioFileWAV:
 	case eAudioFileVOC:
-		soundClip = my_load_wave(asset_name, audioClip->defaultVolume, repeat);
+		soundClip = my_load_wave(asset_name, repeat);
 		break;
 	case eAudioFileMIDI:
 		soundClip = my_load_midi(asset_name, repeat);
diff --git a/engines/ags/engine/media/audio/sound.cpp b/engines/ags/engine/media/audio/sound.cpp
index fe2df77eb3c..1a1c680d5c9 100644
--- a/engines/ags/engine/media/audio/sound.cpp
+++ b/engines/ags/engine/media/audio/sound.cpp
@@ -39,22 +39,22 @@
 
 namespace AGS3 {
 
-SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, bool loop) {
+SOUNDCLIP *my_load_wave(const AssetPath &asset_name, bool loop) {
 	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeWAVStream(data, DisposeAfterUse::YES);
-		return new SoundClipWave<MUS_WAVE>(audioStream, voll, loop);
+		return new SoundClipWave<MUS_WAVE>(audioStream, loop);
 	} else {
 		return nullptr;
 	}
 }
 
-SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop) {
+SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, bool loop) {
 #ifdef USE_MAD
 	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeMP3Stream(data, DisposeAfterUse::YES);
-		return new SoundClipWave<MUS_MP3>(audioStream, voll, false);
+		return new SoundClipWave<MUS_MP3>(audioStream, false);
 	} else {
 		return nullptr;
 	}
@@ -63,16 +63,16 @@ SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop)
 #endif
 }
 
-SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, int voll) {
-	return my_load_static_mp3(asset_name, voll, false);
+SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, bool loop) {
+	return my_load_static_mp3(asset_name, loop);
 }
 
-SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, int voll, bool loop) {
+SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, bool loop) {
 #ifdef USE_VORBIS
 	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeVorbisStream(data, DisposeAfterUse::YES);
-		return new SoundClipWave<MUS_OGG>(audioStream, voll, loop);
+		return new SoundClipWave<MUS_OGG>(audioStream, loop);
 	} else {
 		return nullptr;
 	}
@@ -81,8 +81,8 @@ SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, int voll, bool loop)
 #endif
 }
 
-SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll) {
-	return my_load_static_ogg(asset_name, voll, false);
+SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, bool loop) {
+	return my_load_static_ogg(asset_name, loop);
 }
 
 SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool loop) {
@@ -125,7 +125,7 @@ SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool loop) {
 			return nullptr;
 		}
 
-		return new SoundClipWave<MUS_MOD>(audioStream, 255, loop);
+		return new SoundClipWave<MUS_MOD>(audioStream, loop);
 	} else {
 		return nullptr;
 	}
diff --git a/engines/ags/engine/media/audio/sound.h b/engines/ags/engine/media/audio/sound.h
index e1a4864b6d0..f875f482a9d 100644
--- a/engines/ags/engine/media/audio/sound.h
+++ b/engines/ags/engine/media/audio/sound.h
@@ -33,11 +33,11 @@
 
 namespace AGS3 {
 
-SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, bool loop);
-SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, int voll);
-SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop);
-SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, int voll, bool loop);
-SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll);
+SOUNDCLIP *my_load_wave(const AssetPath &asset_name, bool loop);
+SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, bool loop);
+SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, bool loop);
+SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, bool loop);
+SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, bool doLoop);
 SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool loop);
 SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool loop);
 
diff --git a/engines/ags/engine/media/audio/sound_clip.cpp b/engines/ags/engine/media/audio/sound_clip.cpp
index e91351bdf98..6b06d270c8f 100644
--- a/engines/ags/engine/media/audio/sound_clip.cpp
+++ b/engines/ags/engine/media/audio/sound_clip.cpp
@@ -32,11 +32,11 @@ SOUNDCLIP::SOUNDCLIP() : _panning(12. / 8), _panningAsPercentage(0),
 
 /*------------------------------------------------------------------*/
 
-SoundClipWaveBase::SoundClipWaveBase(Audio::AudioStream *stream, int volume, bool repeat) :
+SoundClipWaveBase::SoundClipWaveBase(Audio::AudioStream *stream, bool repeat) :
 	SOUNDCLIP(), _state(SoundClipInitial), _stream(stream) {
 	_mixer = ::AGS::g_vm->_mixer;
 	_repeat = repeat;
-	_vol = volume;
+	_vol = 255;
 
 	if (repeat) {
 		Audio::SeekableAudioStream *str = dynamic_cast<Audio::SeekableAudioStream *>(stream);
diff --git a/engines/ags/engine/media/audio/sound_clip.h b/engines/ags/engine/media/audio/sound_clip.h
index 5438790f9dc..7fb9ba88ad0 100644
--- a/engines/ags/engine/media/audio/sound_clip.h
+++ b/engines/ags/engine/media/audio/sound_clip.h
@@ -172,7 +172,7 @@ public:
 	SoundClipState _state;
 	bool _waitingToPlay = false;
 
-	SoundClipWaveBase(Audio::AudioStream *stream, int volume, bool repeat = false);
+	SoundClipWaveBase(Audio::AudioStream *stream, bool repeat = false);
 	~SoundClipWaveBase() override {
 		destroy();
 	}
@@ -199,8 +199,8 @@ public:
 
 template<int SOUND_TYPE>
 struct SoundClipWave : public SoundClipWaveBase {
-	SoundClipWave(Audio::AudioStream *stream, int volume, bool repeat = false) :
-		SoundClipWaveBase(stream, volume, repeat) {}
+	SoundClipWave(Audio::AudioStream *stream, bool repeat = false) :
+		SoundClipWaveBase(stream, repeat) {}
 	int get_sound_type() const {
 		return SOUND_TYPE;
 	}
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 31faaa66ec7..7ccc42a8023 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -508,27 +508,29 @@ void IAGSEngine::PlaySoundChannel(int32 channel, int32 soundType, int32 volume,
 	// TODO: find out how engine was supposed to decide on where to load the sound from
 	AssetPath asset_name(filename, "audio");
 
-	if (soundType == PSND_WAVE)
-		newcha = my_load_wave(asset_name, volume, (loop != 0));
-	else if (soundType == PSND_MP3STREAM)
-		newcha = my_load_mp3(asset_name, volume);
-	else if (soundType == PSND_OGGSTREAM)
-		newcha = my_load_ogg(asset_name, volume);
-	else if (soundType == PSND_MP3STATIC)
-		newcha = my_load_static_mp3(asset_name, volume, (loop != 0));
-	else if (soundType == PSND_OGGSTATIC)
-		newcha = my_load_static_ogg(asset_name, volume, (loop != 0));
-	else if (soundType == PSND_MIDI) {
-		if (_GP(play).silent_midi != 0 || _G(current_music_type) == MUS_MIDI)
-			quit("!IAGSEngine::PlaySoundChannel: MIDI already in use");
-		newcha = my_load_midi(asset_name, (loop != 0));
-		newcha->set_volume(volume);
-	} else if (soundType == PSND_MOD) {
-		newcha = my_load_mod(asset_name, (loop != 0));
-		newcha->set_volume(volume);
-	} else
-		quit("!IAGSEngine::PlaySoundChannel: unknown sound type");
+	switch (soundType) {
+	case PSND_WAVE:
+		newcha = my_load_wave(asset_name, (loop != 0)); break;
+	case PSND_MP3STREAM:
+	case PSND_MP3STATIC:
+		newcha = my_load_mp3(asset_name, (loop != 0)); break;
+	case PSND_OGGSTREAM:
+	case PSND_OGGSTATIC:
+		newcha = my_load_ogg(asset_name, (loop != 0)); break;
+	case PSND_MIDI:
+		if (_GP(play).silent_midi != 0 || _G(current_music_type) == MUS_MIDI) {
+			debug_script_warn("IAGSEngine::PlaySoundChannel: MIDI already in use");
+			return;
+		}
+		newcha = my_load_midi(asset_name, (loop != 0)); break;
+	case PSND_MOD:
+		newcha = my_load_mod(asset_name, (loop != 0)); break;
+	default:
+		debug_script_warn("IAGSEngine::PlaySoundChannel: unknown sound type %d", soundType);
+		return;
+	}
 
+	newcha->set_volume(volume);
 	AudioChans::SetChannel(channel, newcha);
 }
 // Engine interface 12 and above are below


Commit: 699a72af3bf8cdd378d3c5865368d462b424c5ea
    https://github.com/scummvm/scummvm/commit/699a72af3bf8cdd378d3c5865368d462b424c5ea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:08-07:00

Commit Message:
AGS: Removed redundant sound destroy calls

>From upstream c8bedc8838635381fc186c9f54e8789a8c276063

Changed paths:
    engines/ags/engine/ac/global_audio.cpp
    engines/ags/engine/media/audio/audio.cpp


diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index 09e4420147e..abb121c0689 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -397,7 +397,6 @@ void PlayMP3File(const char *filename) {
 			if (filename != &_GP(play).playmp3file_name[0])
 				snprintf(_GP(play).playmp3file_name, sizeof(_GP(play).playmp3file_name), filename);
 		} else {
-			clip->destroy();
 			delete clip;
 			clip = nullptr;
 		}
@@ -432,7 +431,6 @@ void PlaySilentMIDI(int mnum) {
 	AudioChans::SetChannel(_GP(play).silent_midi_channel, clip);
 
 	if (!clip->play()) {
-		clip->destroy();
 		delete clip;
 		clip = nullptr;
 		quitprintf("!PlaySilentMIDI: failed to play aMusic%d", mnum);
@@ -524,7 +522,6 @@ static bool play_voice_clip_on_channel(const String &voice_name) {
 		speechmp3->set_volume(_GP(play).speech_volume);
 		if (!speechmp3->play()) {
 			// not assigned to a channel, so clean up manually.
-			speechmp3->destroy();
 			delete speechmp3;
 			speechmp3 = nullptr;
 		}
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index 366293594f0..14ba1e9a490 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -352,7 +352,6 @@ ScriptAudioChannel *play_audio_clip_on_channel(int channel, ScriptAudioClip *cli
 
 	if (soundfx->play_from(fromOffset) == 0) {
 		// not assigned to a channel, so clean up manually.
-		soundfx->destroy();
 		delete soundfx;
 		soundfx = nullptr;
 		debug_script_log("AudioClip.Play: failed to play sound file");
@@ -431,7 +430,6 @@ void stop_and_destroy_channel_ex(int chid, bool resetLegacyMusicSettings) {
 	SOUNDCLIP *ch = AudioChans::GetChannel(chid);
 
 	if (ch != nullptr) {
-		ch->destroy();
 		delete ch;
 		AudioChans::SetChannel(chid, nullptr);
 		ch = nullptr;
@@ -571,7 +569,6 @@ SOUNDCLIP *load_sound_and_play(ScriptAudioClip *aclip, bool repeat) {
 
 	if (soundfx->play() == 0) {
 		// not assigned to a channel, so clean up manually.
-		soundfx->destroy();
 		delete soundfx;
 		return nullptr;
 	}
@@ -684,7 +681,6 @@ void process_scheduled_music_update() {
 void clear_music_cache() {
 
 	if (_G(cachedQueuedMusic) != nullptr) {
-		_G(cachedQueuedMusic)->destroy();
 		delete _G(cachedQueuedMusic);
 		_G(cachedQueuedMusic) = nullptr;
 	}
@@ -995,7 +991,6 @@ static void play_new_music(int mnum, SOUNDCLIP *music) {
 	if (ch != nullptr) {
 		if (!ch->play()) {
 			// previous behavior was to set channel[] to null on error, so continue to do that here.
-			ch->destroy();
 			delete ch;
 			ch = nullptr;
 			AudioChans::SetChannel(useChannel, nullptr);


Commit: 256cc2658a80f4757751502270fd964068f42fa5
    https://github.com/scummvm/scummvm/commit/256cc2658a80f4757751502270fd964068f42fa5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:08-07:00

Commit Message:
AGS: Note skipping merge of SOUNDCLIP and CLIP_OPENAL

>From upstream 22b0f2b93e314b167f80e89a9dd138202a7e28a7

Changed paths:
    engines/ags/ags.h


diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index 3da1bf08546..18da134526e 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -49,13 +49,18 @@ namespace AGS {
  * @brief Engine to run Adventure Game Studio games.
  */
 
-/* Synced up to upstream: 3.5.1.10
- * f2736d21677d2db4b0559c1ded31e284b8a8f64f
+/* Synced up to upstream: ---
+ * ----
  *
  * Commits still pending to be ported:
  * cae84d689019313cad49b6dca7e916866b90e49e
  * - We have slightly different blending code, commit needs
  * to be modified to take that into account
+ *
+ * Skipped commits:
+ * 22b0f2b93e314b167f80e89a9dd138202a7e28a7
+ * * Engine: merged SOUNDCLIP and CLIP_OPENAL
+ * ScummVM has it's own sound clip classes, so doesn't have CLIP_OPENAL
  */
 #define SCREEN_WIDTH 320
 #define SCREEN_HEIGHT 200


Commit: 16b89bd8eaf37344b381984025ce4a3c4861b815
    https://github.com/scummvm/scummvm/commit/16b89bd8eaf37344b381984025ce4a3c4861b815
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:08-07:00

Commit Message:
AGS: tidy SOUNDCLIP's fields (volume, panning) and methods

>From upstream 66514167d3463f8191b10ec13898df136e8e33ee

Changed paths:
    engines/ags/ags.h
    engines/ags/engine/ac/audio_channel.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_audio.cpp
    engines/ags/engine/ac/view_frame.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/game/savegame_internal.h
    engines/ags/engine/game/savegame_v321.cpp
    engines/ags/engine/media/audio/audio.cpp
    engines/ags/engine/media/audio/clip_my_midi.cpp
    engines/ags/engine/media/audio/clip_my_midi.h
    engines/ags/engine/media/audio/sound_clip.cpp
    engines/ags/engine/media/audio/sound_clip.h
    engines/ags/plugins/ags_plugin.cpp


diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index 18da134526e..038d34ef0ba 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -57,7 +57,7 @@ namespace AGS {
  * - We have slightly different blending code, commit needs
  * to be modified to take that into account
  *
- * Skipped commits:
+ * Skipped upstream commits:
  * 22b0f2b93e314b167f80e89a9dd138202a7e28a7
  * * Engine: merged SOUNDCLIP and CLIP_OPENAL
  * ScummVM has it's own sound clip classes, so doesn't have CLIP_OPENAL
diff --git a/engines/ags/engine/ac/audio_channel.cpp b/engines/ags/engine/ac/audio_channel.cpp
index ea838204eee..2adafc4454b 100644
--- a/engines/ags/engine/ac/audio_channel.cpp
+++ b/engines/ags/engine/ac/audio_channel.cpp
@@ -60,7 +60,7 @@ int AudioChannel_GetPanning(ScriptAudioChannel *channel) {
 	auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
 
 	if (ch) {
-		return ch->_panningAsPercentage;
+		return ch->get_panning();
 	}
 	return 0;
 }
@@ -72,8 +72,7 @@ void AudioChannel_SetPanning(ScriptAudioChannel *channel, int newPanning) {
 	auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
 
 	if (ch) {
-		ch->set_panning(((newPanning + 100) * 255) / 200);
-		ch->_panningAsPercentage = newPanning;
+		ch->set_panning(newPanning);
 	}
 }
 
@@ -123,7 +122,7 @@ int AudioChannel_GetVolume(ScriptAudioChannel *channel) {
 	auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
 
 	if (ch) {
-		return ch->get_volume();
+		return ch->get_volume100();
 	}
 	return 0;
 }
@@ -135,7 +134,7 @@ int AudioChannel_SetVolume(ScriptAudioChannel *channel, int newVolume) {
 	auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
 
 	if (ch) {
-		ch->set_volume_percent(newVolume);
+		ch->set_volume100(newVolume);
 	}
 	return 0;
 }
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 3adcc50b5d8..8f7c9516842 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -150,7 +150,7 @@ void Game_SetAudioTypeVolume(int audioType, int volume, int changeType) {
 			if ((clip != nullptr) && (clip->type == audioType)) {
 				auto *ch = AudioChans::GetChannel(aa);
 				if (ch)
-					ch->set_volume_percent(volume);
+					ch->set_volume100(volume);
 			}
 		}
 	}
diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index abb121c0689..f981fb4ba7b 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -154,7 +154,7 @@ int PlaySoundEx(int val1, int channel) {
 	}
 
 	soundfx->_priority = 10;
-	soundfx->set_volume(_GP(play).sound_volume);
+	soundfx->set_volume255(_GP(play).sound_volume);
 	AudioChans::SetChannel(channel, soundfx);
 	return channel;
 }
@@ -341,7 +341,7 @@ void SetChannelVolume(int chan, int newvol) {
 			_GP(ambient)[chan].vol = newvol;
 			update_ambient_sound_vol();
 		} else
-			ch->set_volume(newvol);
+			ch->set_volume255(newvol);
 	}
 }
 
@@ -388,7 +388,7 @@ void PlayMP3File(const char *filename) {
 	}
 
 	if (clip) {
-		clip->set_volume(150);
+		clip->set_volume255(150);
 		if (clip->play()) {
 			AudioChans::SetChannel(useChan, clip);
 			_G(current_music_type) = sound_type;
@@ -435,7 +435,7 @@ void PlaySilentMIDI(int mnum) {
 		clip = nullptr;
 		quitprintf("!PlaySilentMIDI: failed to play aMusic%d", mnum);
 	}
-	clip->set_volume_percent(0);
+	clip->set_volume100(0);
 }
 
 void SetSpeechVolume(int newvol) {
@@ -444,7 +444,7 @@ void SetSpeechVolume(int newvol) {
 
 	auto *ch = AudioChans::GetChannel(SCHAN_SPEECH);
 	if (ch)
-		ch->set_volume(newvol);
+		ch->set_volume255(newvol);
 	_GP(play).speech_volume = newvol;
 }
 
@@ -519,7 +519,7 @@ static bool play_voice_clip_on_channel(const String &voice_name) {
 	}
 
 	if (speechmp3 != nullptr) {
-		speechmp3->set_volume(_GP(play).speech_volume);
+		speechmp3->set_volume255(_GP(play).speech_volume);
 		if (!speechmp3->play()) {
 			// not assigned to a channel, so clean up manually.
 			delete speechmp3;
diff --git a/engines/ags/engine/ac/view_frame.cpp b/engines/ags/engine/ac/view_frame.cpp
index 5be2f43f377..18b1abc316e 100644
--- a/engines/ags/engine/ac/view_frame.cpp
+++ b/engines/ags/engine/ac/view_frame.cpp
@@ -39,12 +39,6 @@ namespace AGS3 {
 using AGS::Shared::Bitmap;
 using AGS::Shared::Graphics;
 
-
-
-
-
-
-
 int ViewFrame_GetFlipped(ScriptViewFrame *svf) {
 	if (_GP(views)[svf->view].loops[svf->loop].frames[svf->frame].flags & VFLG_FLIPSPRITE)
 		return 1;
@@ -150,7 +144,7 @@ void CheckViewFrame(int view, int loop, int frame, int sound_volume) {
 		auto *ch = AudioChans::GetChannel(channel->id);
 
 		if (ch)
-			ch->set_volume_percent(ch->get_volume() * sound_volume / 100);
+			ch->set_volume100(ch->get_volume100() * sound_volume / 100);
 	}
 }
 
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 310575c45d2..9bacfe6cd8b 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -569,7 +569,6 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 			ch->set_volume_direct(chan_info.VolAsPercent, chan_info.Vol);
 			ch->set_speed(chan_info.Speed);
 			ch->set_panning(chan_info.Pan);
-			ch->_panningAsPercentage = chan_info.PanAsPercent;
 			ch->_xSource = chan_info.XSource;
 			ch->_ySource = chan_info.YSource;
 			ch->_maximumPossibleDistanceAway = chan_info.MaxDist;
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 05dcd890d7d..4058ebd998d 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -352,10 +352,10 @@ HSaveError WriteAudio(Stream *out) {
 			out->WriteInt32(ch->get_pos());
 			out->WriteInt32(ch->_priority);
 			out->WriteInt32(ch->_repeat ? 1 : 0);
-			out->WriteInt32(ch->_vol);
-			out->WriteInt32(ch->_panning);
-			out->WriteInt32(ch->_volAsPercentage);
-			out->WriteInt32(ch->_panningAsPercentage);
+			out->WriteInt32(ch->get_volume255());
+			out->WriteInt32(0); // unused
+			out->WriteInt32(ch->get_volume100());
+			out->WriteInt32(ch->get_panning());
 			out->WriteInt32(ch->get_speed());
 			// since version 1
 			out->WriteInt32(ch->_xSource);
@@ -415,9 +415,9 @@ HSaveError ReadAudio(Stream *in, int32_t cmp_ver, const PreservedParams &pp, Res
 			chan_info.Priority = in->ReadInt32();
 			chan_info.Repeat = in->ReadInt32();
 			chan_info.Vol = in->ReadInt32();
-			chan_info.Pan = in->ReadInt32();
+			in->ReadInt32(); // unused
 			chan_info.VolAsPercent = in->ReadInt32();
-			chan_info.PanAsPercent = in->ReadInt32();
+			chan_info.Pan = in->ReadInt32();
 			chan_info.Speed = 1000;
 			chan_info.Speed = in->ReadInt32();
 			if (cmp_ver >= 1) {
diff --git a/engines/ags/engine/game/savegame_internal.h b/engines/ags/engine/game/savegame_internal.h
index 0a7fee951bf..080a1317354 100644
--- a/engines/ags/engine/game/savegame_internal.h
+++ b/engines/ags/engine/game/savegame_internal.h
@@ -98,7 +98,6 @@ struct RestoredData {
 		int Vol = 0;
 		int VolAsPercent = 0;
 		int Pan = 0;
-		int PanAsPercent = 0;
 		int Speed = 0;
 		// since version 1
 		int XSource = -1;
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 004cec8a678..47ee3e2061b 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -374,9 +374,9 @@ static HSaveError restore_game_audioclips_and_crossfade(Stream *in, RestoredData
 			chan_info.Priority = in->ReadInt32();
 			chan_info.Repeat = in->ReadInt32();
 			chan_info.Vol = in->ReadInt32();
-			chan_info.Pan = in->ReadInt32();
+			in->ReadInt32(); // unused
 			chan_info.VolAsPercent = in->ReadInt32();
-			chan_info.PanAsPercent = in->ReadInt32();
+			chan_info.Pan = in->ReadInt32();
 			chan_info.Speed = 1000;
 			if (_G(loaded_game_file_version) >= kGameVersion_340_2)
 				chan_info.Speed = in->ReadInt32();
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index 14ba1e9a490..a6b4f7bae28 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -124,7 +124,7 @@ static void move_track_to_crossfade_channel(int currentChannel, int crossfadeSpe
 
 	_GP(play).crossfading_out_channel = SPECIAL_CROSSFADE_CHANNEL;
 	_GP(play).crossfade_step = 0;
-	_GP(play).crossfade_initial_volume_out = cfade_clip->get_volume();
+	_GP(play).crossfade_initial_volume_out = cfade_clip->get_volume100();
 	_GP(play).crossfade_out_volume_per_step = crossfadeSpeed;
 
 	_GP(play).crossfading_in_channel = fadeInChannel;
@@ -221,7 +221,7 @@ SOUNDCLIP *load_sound_clip(ScriptAudioClip *audioClip, bool repeat) {
 		quitprintf("AudioClip.Play: invalid audio file type encountered: %d", audioClip->fileType);
 	}
 	if (soundClip != nullptr) {
-		soundClip->set_volume_percent(audioClip->defaultVolume);
+		soundClip->set_volume100(audioClip->defaultVolume);
 		soundClip->_sourceClipID = audioClip->id;
 		soundClip->_sourceClipType = audioClip->type;
 	}
@@ -238,9 +238,9 @@ static void audio_update_polled_stuff() {
 
 	if (_GP(play).crossfading_out_channel > 0) {
 		SOUNDCLIP *ch = AudioChans::GetChannel(_GP(play).crossfading_out_channel);
-		int newVolume = ch ? ch->get_volume() - _GP(play).crossfade_out_volume_per_step : 0;
+		int newVolume = ch ? ch->get_volume100() - _GP(play).crossfade_out_volume_per_step : 0;
 		if (newVolume > 0) {
-			ch->set_volume_percent(newVolume);
+			ch->set_volume100(newVolume);
 		} else {
 			stop_and_destroy_channel(_GP(play).crossfading_out_channel);
 			_GP(play).crossfading_out_channel = 0;
@@ -252,12 +252,12 @@ static void audio_update_polled_stuff() {
 
 	if (_GP(play).crossfading_in_channel > 0) {
 		SOUNDCLIP *ch = AudioChans::GetChannel(_GP(play).crossfading_in_channel);
-		int newVolume = ch ? ch->get_volume() + _GP(play).crossfade_in_volume_per_step : 0;
+		int newVolume = ch ? ch->get_volume100() + _GP(play).crossfade_in_volume_per_step : 0;
 		if (newVolume > _GP(play).crossfade_final_volume_in) {
 			newVolume = _GP(play).crossfade_final_volume_in;
 		}
 
-		ch->set_volume_percent(newVolume);
+		ch->set_volume100(newVolume);
 
 		if (newVolume >= _GP(play).crossfade_final_volume_in) {
 			_GP(play).crossfading_in_channel = 0;
@@ -332,7 +332,7 @@ ScriptAudioChannel *play_audio_clip_on_channel(int channel, ScriptAudioClip *cli
 	soundfx->_priority = priority;
 
 	if (_GP(play).crossfading_in_channel == channel) {
-		soundfx->set_volume_percent(0);
+		soundfx->set_volume100(0);
 	}
 
 	// Mute the audio clip if fast-forwarding the cutscene
@@ -347,7 +347,7 @@ ScriptAudioChannel *play_audio_clip_on_channel(int channel, ScriptAudioClip *cli
 		// channel for this audio type? It does not even check if
 		// anything of this type is currently playing.
 		if (_GP(game).audioClipTypes[clip->type].reservedChannels != 1)
-			soundfx->set_volume_percent(0);
+			soundfx->set_volume100(0);
 	}
 
 	if (soundfx->play_from(fromOffset) == 0) {
@@ -389,7 +389,7 @@ void update_queued_clips_volume(int audioType, int new_vol) {
 		if (sndclip) {
 			ScriptAudioClip *clip = &_GP(game).audioClips[_GP(play).new_music_queue[i].audioClipIndex];
 			if (clip->type == audioType)
-				sndclip->set_volume_percent(new_vol);
+				sndclip->set_volume100(new_vol);
 		}
 	}
 }
@@ -513,11 +513,11 @@ void update_directional_sound_vol() {
 		auto *ch = AudioChans::GetChannelIfPlaying(chnum);
 		if ((ch != nullptr) && (ch->_xSource >= 0)) {
 			ch->apply_directional_modifier(
-			    get_volume_adjusted_for_distance(ch->_vol,
-			                                     ch->_xSource,
-			                                     ch->_ySource,
-			                                     ch->_maximumPossibleDistanceAway) -
-			    ch->_vol);
+				get_volume_adjusted_for_distance(ch->get_volume255(),
+					ch->_xSource,
+					ch->_ySource,
+					ch->_maximumPossibleDistanceAway) -
+				ch->get_volume255());
 		}
 	}
 }
@@ -557,7 +557,7 @@ void update_ambient_sound_vol() {
 
 		auto *ch = AudioChans::GetChannelIfPlaying(thisSound->channel);
 		if (ch)
-			ch->set_volume(wantvol);
+			ch->set_volume255(wantvol);
 	}
 }
 
@@ -859,7 +859,7 @@ void update_music_volume() {
 				if (_G(crossFading) > 0) {
 					auto *ch = AudioChans::GetChannel(_G(crossFading));
 					if (ch)
-						ch->set_volume((curvol > targetVol) ? targetVol : curvol);
+						ch->set_volume255((curvol > targetVol) ? targetVol : curvol);
 				}
 
 				newvol -= curvol;
@@ -869,7 +869,7 @@ void update_music_volume() {
 		}
 		auto *ch = AudioChans::GetChannel(SCHAN_MUSIC);
 		if (ch)
-			ch->set_volume(newvol);
+			ch->set_volume255(newvol);
 	}
 }
 
@@ -882,7 +882,6 @@ void post_new_music_check(int newchannel) {
 		if (AudioChans::GetChannel(SCHAN_MUSIC) != nullptr)
 			_G(crossFading) = -1;
 	}
-
 }
 
 int prepare_for_new_music() {
diff --git a/engines/ags/engine/media/audio/clip_my_midi.cpp b/engines/ags/engine/media/audio/clip_my_midi.cpp
index 36ba2357c56..b5240de4666 100644
--- a/engines/ags/engine/media/audio/clip_my_midi.cpp
+++ b/engines/ags/engine/media/audio/clip_my_midi.cpp
@@ -32,7 +32,7 @@ MYMIDI::MYMIDI(Common::SeekableReadStream *data, bool repeat) :
 	_repeat = repeat;
 }
 
-void MYMIDI::destroy() {
+MYMIDI::~MYMIDI() {
 	::AGS::g_music->stop();
 	delete _data;
 	_data = nullptr;
@@ -102,11 +102,6 @@ bool MYMIDI::is_paused() {
 	return false;
 }
 
-void MYMIDI::set_volume(int volume) {
-	_vol = volume;
-	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
-}
-
 void MYMIDI::set_panning(int newPanning) {
 	// No implementation for MIDI
 }
@@ -117,7 +112,7 @@ void MYMIDI::set_speed(int new_speed) {
 }
 
 void MYMIDI::adjust_volume() {
-	// TODO: See if this method is needed
+	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _vol255);
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/media/audio/clip_my_midi.h b/engines/ags/engine/media/audio/clip_my_midi.h
index 80a3a5ae556..0d646e60c3f 100644
--- a/engines/ags/engine/media/audio/clip_my_midi.h
+++ b/engines/ags/engine/media/audio/clip_my_midi.h
@@ -35,11 +35,7 @@ struct MYMIDI : public SOUNDCLIP {
 	SoundClipState _state;
 
 	MYMIDI(Common::SeekableReadStream *data, bool repeat);
-	~MYMIDI() override {
-		destroy();
-	}
-
-	void destroy() override;
+	~MYMIDI() override;
 
 	void poll() override;
 
@@ -63,7 +59,6 @@ struct MYMIDI : public SOUNDCLIP {
 	int play_from(int position) override;
 	bool is_playing() override;
 	bool is_paused() override;
-	void set_volume(int volume) override;
 	void set_panning(int newPanning) override;
 	void set_speed(int new_speed) override;
 	void adjust_volume() override;
diff --git a/engines/ags/engine/media/audio/sound_clip.cpp b/engines/ags/engine/media/audio/sound_clip.cpp
index 6b06d270c8f..80e4460665d 100644
--- a/engines/ags/engine/media/audio/sound_clip.cpp
+++ b/engines/ags/engine/media/audio/sound_clip.cpp
@@ -27,7 +27,41 @@ namespace AGS3 {
 SOUNDCLIP::SOUNDCLIP() : _panning(12. / 8), _panningAsPercentage(0),
 	_sourceClipID(-1), _sourceClipType(0), _speed(1000), _priority(50),
 	_xSource(-1), _ySource(-1), _maximumPossibleDistanceAway(0), _muted(false),
-	_volAsPercentage(0), _vol(0), _volModifier(0), _repeat(false), _directionalVolModifier(0) {
+	_vol100(0), _vol255(0), _volModifier(0), _repeat(false), _directionalVolModifier(0) {
+}
+
+void SOUNDCLIP::set_volume100(int volume) {
+	_vol100 = volume;
+	_vol255 = (volume * 255) / 100;
+	adjust_volume();
+}
+
+// Sets the current volume property in units of 255
+void SOUNDCLIP::set_volume255(int volume) {
+	_vol255 = volume;
+	_vol100 = (_vol255 * 100) / 255;
+	adjust_volume();
+}
+
+void SOUNDCLIP::set_volume_direct(int vol_percent, int vol_absolute) {
+	//vol255 = vol255;
+	_vol100 = vol_percent;
+	adjust_volume();
+}
+
+void SOUNDCLIP::set_mute(bool mute) {
+	_muted = mute;
+	adjust_volume();
+}
+
+void SOUNDCLIP::apply_volume_modifier(int mod) {
+	_volModifier = mod;
+	adjust_volume();
+}
+
+void SOUNDCLIP::apply_directional_modifier(int mod) {
+	_directionalVolModifier = mod;
+	adjust_volume();
 }
 
 /*------------------------------------------------------------------*/
@@ -36,7 +70,7 @@ SoundClipWaveBase::SoundClipWaveBase(Audio::AudioStream *stream, bool repeat) :
 	SOUNDCLIP(), _state(SoundClipInitial), _stream(stream) {
 	_mixer = ::AGS::g_vm->_mixer;
 	_repeat = repeat;
-	_vol = 255;
+	_vol255 = 255;
 
 	if (repeat) {
 		Audio::SeekableAudioStream *str = dynamic_cast<Audio::SeekableAudioStream *>(stream);
@@ -45,7 +79,7 @@ SoundClipWaveBase::SoundClipWaveBase(Audio::AudioStream *stream, bool repeat) :
 	}
 }
 
-void SoundClipWaveBase::destroy() {
+SoundClipWaveBase::~SoundClipWaveBase() {
 	_mixer->stopHandle(_soundHandle);
 	delete _stream;
 	_stream = nullptr;
@@ -62,7 +96,7 @@ void SoundClipWaveBase::poll() {
 int SoundClipWaveBase::play() {
 	if (_soundType != Audio::Mixer::kPlainSoundType) {
 		_mixer->playStream(_soundType, &_soundHandle, _stream,
-			-1, _vol, 0, DisposeAfterUse::NO);
+			-1, _vol255, 0, DisposeAfterUse::NO);
 	} else {
 		_waitingToPlay = true;
 	}
@@ -139,11 +173,6 @@ int SoundClipWaveBase::get_length_ms() {
 	}
 }
 
-void SoundClipWaveBase::set_volume(int volume) {
-	_vol = volume;
-	_mixer->setChannelVolume(_soundHandle, volume);
-}
-
 void SoundClipWaveBase::set_panning(int newPanning) {
 	_mixer->setChannelBalance(_soundHandle, newPanning);
 }
@@ -154,7 +183,7 @@ void SoundClipWaveBase::set_speed(int new_speed) {
 }
 
 void SoundClipWaveBase::adjust_volume() {
-	// TODO: See if this method is needed
+	_mixer->setChannelVolume(_soundHandle, _vol255);
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/media/audio/sound_clip.h b/engines/ags/engine/media/audio/sound_clip.h
index 7fb9ba88ad0..65a70e2a409 100644
--- a/engines/ags/engine/media/audio/sound_clip.h
+++ b/engines/ags/engine/media/audio/sound_clip.h
@@ -46,108 +46,123 @@ enum SoundClipState {
 };
 
 struct SOUNDCLIP {
-	int _priority;
+	SOUNDCLIP();
+	virtual ~SOUNDCLIP() {}
+
+	// TODO: move these to private
+	int _sourceClipID;
 	int _sourceClipType;
-	int _vol;
-	int _volAsPercentage;
+	bool _repeat;
+	int _priority;
+	int _xSource, _ySource;     // Used for positioning sounds in game rooms
+	int _maximumPossibleDistanceAway;
+
+	int _vol255;
+	int _vol100;
 	int _volModifier;
 	int _panning;
 	int _panningAsPercentage;
-	int _xSource, _ySource;     // Used for positioning sounds in game rooms
-	int _maximumPossibleDistanceAway;
 	int _directionalVolModifier;
-	bool _repeat;
-	int _sourceClipID;
 
-	virtual void poll() = 0;
-	virtual void destroy() = 0;
-	// apply volume directly to playback; volume is given in units of 255
-	// NOTE: this completely ignores volAsPercentage and muted property
-	virtual void set_volume(int volume) = 0;
-	virtual void seek(int offset) = 0;
-	virtual int get_pos() = 0; // return 0 to indicate seek not supported
-	virtual int get_pos_ms() = 0; // this must always return valid value if poss
-	virtual int get_length_ms() = 0; // return total track length in ms (or 0)
-	virtual int get_sound_type() const = 0;
 	virtual int play() = 0;
+	virtual void pause() = 0;
+	virtual void resume() = 0;
+	virtual void seek(int offset) = 0;
 	virtual int play_from(int position) = 0;
+	virtual bool is_playing() = 0; // true if playing or paused. false if never played or stopped.
+	virtual bool is_paused() = 0; // true if paused
+
+	/**
+	 * Get legacy sound format type
+	 */
+	virtual int get_sound_type() const = 0;
+
+	/**
+	 * Return current position in frames
+	 */
+	virtual int get_pos() = 0;
+
+	/**
+	 * Return the position in milliseconds
+	 */
+	virtual int get_pos_ms() = 0;
+
+	/**
+	 * Return total track length in ms (or 0)
+	 */
+	virtual int get_length_ms() = 0;
 
 	virtual void set_panning(int newPanning) = 0;
 	virtual void set_speed(int new_speed) = 0;
+	virtual void poll() = 0;
 
-	virtual void pause() = 0;
-	virtual void resume() = 0;
+	/**
+	 * Gets clip's volume property, as percentage (0 - 100);
+	 * note this may not be the real volume of playback (which could e.g. be muted)
+	 */
+	inline int get_volume100() const { return _vol100; }
 
-	virtual bool is_playing() = 0; // true if playing or paused. false if never played or stopped.
-	virtual bool is_paused() = 0; // true if paused
+	/**
+	 * Gets clip's volume measured in 255 units
+	 */
+    inline int get_volume255() const { return _vol255; }
 
-	inline int get_speed() const {
-		return _speed;
-	}
+	/**
+	 * Gets clip's panning (-100 - +100)
+	 */
+    inline int get_panning() const { return _panning; }
 
-	// Gets clip's volume property, as percentage (0 - 100);
-	// note this may not be the real volume of playback (which could e.g. be muted)
-	inline int get_volume() const {
-		return _volAsPercentage;
-	}
+	/**
+	 * Gets clip's playback speed in clip ms per real second
+	 */
+    inline int get_speed() const { return _speed; }
 
-	inline bool is_muted() const {
-		return _muted;
-	}
+	/**
+	 * Gets if clip is muted (without changing the volume setting)
+	 */
+    inline bool is_muted() const { return _muted; }
 
-	// Sets the current volume property, as percentage (0 - 100).
-	inline void set_volume_percent(int volume) {
-		_volAsPercentage = volume;
-		if (!_muted)
-			set_volume((volume * 255) / 100);
-	}
+	/**
+	 * Sets the current volume property, as percentage (0 - 100)
+	 */
+	void set_volume100(int volume);
+
+	/**
+	 * Sets the current volume property, as a level (0 - 255)
+	 */
+	void set_volume255(int volume);
 
 	/**
 	 * Explicitly defines both percentage and absolute volume value,
 	 * without calculating it from given percentage.
 	 * NOTE: this overrides the mute
 	 */
-	inline void set_volume_direct(int vol_percent, int vol_absolute) {
-		_muted = false;
-		_volAsPercentage = vol_percent;
-		set_volume(vol_absolute);
-	}
+	void set_volume_direct(int vol_percent, int vol_absolute);
 
-	// Mutes sound clip, while preserving current volume property
-	// for the future reference; when unmuted, that property is
-	// used to restart previous volume.
-	inline void set_mute(bool enable) {
-		_muted = enable;
-		if (enable)
-			set_volume(0);
-		else
-			set_volume((_volAsPercentage * 255) / 100);
-	}
+	/**
+	 * Mutes sound clip, while preserving current volume property
+	 * for the future reference; when unmuted, that property is
+	 * used to restart previous volume.
+	 */
+	void set_mute(bool mute);
 
-	// Apply arbitrary permanent volume modifier, in absolute units (0 - 255);
-	// this is distinct value that is used in conjunction with current volume
-	// (can be both positive and negative).
-	inline void apply_volume_modifier(int mod) {
-		_volModifier = mod;
-		adjust_volume();
-	}
+	/**
+	 * Apply arbitrary permanent volume modifier, in absolute units (0 - 255);
+	 * this is distinct value that is used in conjunction with current volume
+	 * (can be both positive and negative).
+	 */
+	void apply_volume_modifier(int mod);
 
 	/**
 	 * Apply permanent directional volume modifier, in absolute units (0 - 255)
 	 * this is distinct value that is used in conjunction with current volume
 	 * (can be both positive and negative).
 	 */
-	inline void apply_directional_modifier(int mod) {
-		_directionalVolModifier = mod;
-		adjust_volume();
-	}
+	void apply_directional_modifier(int mod);
 
+protected:
 	virtual void adjust_volume() = 0;
 
-	SOUNDCLIP();
-	virtual ~SOUNDCLIP() {}
-
-protected:
 	// mute mode overrides the volume; if set, any volume assigned is stored
 	// in properties, but not applied to playback itself
 	bool _muted;
@@ -157,7 +172,7 @@ protected:
 
 	// helper function for calculating volume with applied modifiers
 	inline int get_final_volume() const {
-		int final_vol = _vol + _volModifier + _directionalVolModifier;
+		int final_vol = _vol255 + _volModifier + _directionalVolModifier;
 		return final_vol >= 0 ? final_vol : 0;
 	}
 };
@@ -173,13 +188,10 @@ public:
 	bool _waitingToPlay = false;
 
 	SoundClipWaveBase(Audio::AudioStream *stream, bool repeat = false);
-	~SoundClipWaveBase() override {
-		destroy();
-	}
+	~SoundClipWaveBase() override;
 
 	void setType(Audio::Mixer::SoundType type);
 
-	void destroy() override;
 	void poll() override;
 	int play() override;
 	int play_from(int position) override;
@@ -191,7 +203,6 @@ public:
 	int get_pos() override;
 	int get_pos_ms() override;
 	int get_length_ms() override;
-	void set_volume(int volume) override;
 	void set_panning(int newPanning) override;
 	void set_speed(int new_speed) override;
 	void adjust_volume() override;
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 7ccc42a8023..0d3f4c69f58 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -530,7 +530,7 @@ void IAGSEngine::PlaySoundChannel(int32 channel, int32 soundType, int32 volume,
 		return;
 	}
 
-	newcha->set_volume(volume);
+	newcha->set_volume255(volume);
 	AudioChans::SetChannel(channel, newcha);
 }
 // Engine interface 12 and above are below


Commit: d013cdfe3d0e7bbc9db6d0cc0285e98014017ac8
    https://github.com/scummvm/scummvm/commit/d013cdfe3d0e7bbc9db6d0cc0285e98014017ac8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:09-07:00

Commit Message:
AGS: Skipped "transactional" SOUNDCLIP commit

>From upstream ff05f69f2361c34212b6ba1db0f22b2c1ba38d7b

Changed paths:
    engines/ags/ags.h


diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index 038d34ef0ba..89d26c28f3c 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -61,6 +61,9 @@ namespace AGS {
  * 22b0f2b93e314b167f80e89a9dd138202a7e28a7
  * * Engine: merged SOUNDCLIP and CLIP_OPENAL
  * ScummVM has it's own sound clip classes, so doesn't have CLIP_OPENAL
+ * ff05f69f2361c34212b6ba1db0f22b2c1ba38d7b
+ * Engine: "transactional" SOUNDCLIP
+ * ScummVM doesn't have the OPENAL decoder
  */
 #define SCREEN_WIDTH 320
 #define SCREEN_HEIGHT 200


Commit: 0988fbbe78ab7afb56e215ce1f59c1551fbc009e
    https://github.com/scummvm/scummvm/commit/0988fbbe78ab7afb56e215ce1f59c1551fbc009e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:09-07:00

Commit Message:
AGS: Dispose SOUNDCLIP when stopped playing

>From upstream 60d40072b429a641f6fcbf3cdb8c60809fc3f770

Changed paths:
    engines/ags/ags.h
    engines/ags/engine/media/audio/audio.cpp
    engines/ags/engine/media/audio/sound_clip.cpp
    engines/ags/engine/media/audio/sound_clip.h


diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index 89d26c28f3c..075fec226d2 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -51,19 +51,6 @@ namespace AGS {
 
 /* Synced up to upstream: ---
  * ----
- *
- * Commits still pending to be ported:
- * cae84d689019313cad49b6dca7e916866b90e49e
- * - We have slightly different blending code, commit needs
- * to be modified to take that into account
- *
- * Skipped upstream commits:
- * 22b0f2b93e314b167f80e89a9dd138202a7e28a7
- * * Engine: merged SOUNDCLIP and CLIP_OPENAL
- * ScummVM has it's own sound clip classes, so doesn't have CLIP_OPENAL
- * ff05f69f2361c34212b6ba1db0f22b2c1ba38d7b
- * Engine: "transactional" SOUNDCLIP
- * ScummVM doesn't have the OPENAL decoder
  */
 #define SCREEN_WIDTH 320
 #define SCREEN_HEIGHT 200
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index a6b4f7bae28..4ba7f22bed0 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -795,6 +795,21 @@ void update_audio_system_on_game_loop() {
 
 	_G(audio_doing_crossfade) = false;
 
+	if (_G(loopcounter) % 5 == 0) {
+		update_ambient_sound_vol();
+		update_directional_sound_vol();
+	}
+
+	// Update and sync logical game channels with the audio backend
+	for (int i = 0; i < _GP(game).numGameChannels; ++i) {
+		auto *ch = AudioChans::GetChannel(i);
+		if (ch) { // update the playing channel, and if it's finished then dispose it
+			if (ch->is_ready() && !ch->update()) {
+				delete ch;
+				AudioChans::SetChannel(i, nullptr);
+			}
+		}
+	}
 }
 
 void stopmusic() {
diff --git a/engines/ags/engine/media/audio/sound_clip.cpp b/engines/ags/engine/media/audio/sound_clip.cpp
index 80e4460665d..8c91ce2d9c0 100644
--- a/engines/ags/engine/media/audio/sound_clip.cpp
+++ b/engines/ags/engine/media/audio/sound_clip.cpp
@@ -64,6 +64,55 @@ void SOUNDCLIP::apply_directional_modifier(int mod) {
 	adjust_volume();
 }
 
+bool SOUNDCLIP::update() {
+	if (!is_ready())
+		return false;
+
+	if (_paramsChanged) {
+		auto vol_f = static_cast<float>(get_final_volume()) / 255.0f;
+		if (vol_f < 0.0f) {
+			vol_f = 0.0f;
+		}
+		if (vol_f > 1.0f) {
+			vol_f = 1.0f;
+		}
+
+		auto speed_f = static_cast<float>(_speed) / 1000.0f;
+		if (speed_f <= 0.0) {
+			speed_f = 1.0f;
+		}
+
+		// Sets the pan position, ranging from -100 (left) to +100 (right)
+		auto panning_f = (static_cast<float>(_panning) / 100.0f);
+		if (panning_f < -1.0f) {
+			panning_f = -1.0f;
+		}
+		if (panning_f > 1.0f) {
+			panning_f = 1.0f;
+		}
+
+		//audio_core_slot_configure(slot_, vol_f, speed_f, panning_f);
+		_paramsChanged = false;
+	}
+/*
+	float pos_f, posms_f;
+	PlaybackState core_state = audio_core_slot_get_play_state(slot_, pos_f, posms_f);
+	pos = static_cast<int>(pos_f);
+	posMs = static_cast<int>(posms_f);
+	if (state == core_state || core_state == PlayStateError || core_state == PlayStateFinished) {
+		state = core_state;
+		return is_ready();
+	}
+
+	switch (state) {
+	case PlaybackState::PlayStatePlaying:
+		state = audio_core_slot_play(slot_);
+		break;
+	}
+*/
+	return is_ready();
+}
+
 /*------------------------------------------------------------------*/
 
 SoundClipWaveBase::SoundClipWaveBase(Audio::AudioStream *stream, bool repeat) :
diff --git a/engines/ags/engine/media/audio/sound_clip.h b/engines/ags/engine/media/audio/sound_clip.h
index 65a70e2a409..24b169f7235 100644
--- a/engines/ags/engine/media/audio/sound_clip.h
+++ b/engines/ags/engine/media/audio/sound_clip.h
@@ -160,15 +160,24 @@ struct SOUNDCLIP {
 	 */
 	void apply_directional_modifier(int mod);
 
+	inline bool is_ready() { return is_playing(); }
+
+	/**
+	 * Returns if the clip is still playing, otherwise it's finished
+	 */
+	bool update();
+
 protected:
 	virtual void adjust_volume() = 0;
 
 	// mute mode overrides the volume; if set, any volume assigned is stored
 	// in properties, but not applied to playback itself
-	bool _muted;
+	bool _muted = false;
 
 	// speed of playback, in clip ms per real second
-	int _speed;
+	int _speed = 0;
+
+	bool _paramsChanged = false;
 
 	// helper function for calculating volume with applied modifiers
 	inline int get_final_volume() const {


Commit: 9e68fb7852cbe892eb73284425521a8f693c43ae
    https://github.com/scummvm/scummvm/commit/9e68fb7852cbe892eb73284425521a8f693c43ae
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:09-07:00

Commit Message:
AGS: Fixed snprintf in PlayMP3File()

>From upstream c31549be0efabafe7c63e5d51f2b19bd7ccff9d0

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


diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index f981fb4ba7b..25505046c1f 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -395,7 +395,7 @@ void PlayMP3File(const char *filename) {
 			_GP(play).cur_music_number = 1000;
 			// save the filename (if it's not what we were supplied with)
 			if (filename != &_GP(play).playmp3file_name[0])
-				snprintf(_GP(play).playmp3file_name, sizeof(_GP(play).playmp3file_name), filename);
+				snprintf(_GP(play).playmp3file_name, sizeof(_GP(play).playmp3file_name), "%s", filename);
 		} else {
 			delete clip;
 			clip = nullptr;


Commit: 28d91ca846ff85b06c12b4eee3351910083ba1b3
    https://github.com/scummvm/scummvm/commit/28d91ca846ff85b06c12b4eee3351910083ba1b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:09-07:00

Commit Message:
AGS: Try report script section and line on fixup error

>From upstream 27e578e8140d0bc7d455fbff0e365c2608554c61

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 2f6d2bebfc9..e5e092488a3 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -1605,6 +1605,33 @@ ScriptVariable *ccInstance::FindGlobalVar(int32_t var_addr) {
 	return it != globalvars->end() ? &it->_value : nullptr;
 }
 
+static int DetermineScriptLine(int32_t *code, size_t codesz, size_t at_pc) {
+	int line = -1;
+	for (size_t pc = 0; (pc <= at_pc) && (pc < codesz); ++pc) {
+		int op = code[pc] & INSTANCE_ID_REMOVEMASK;
+		if (op < 0 || op >= CC_NUM_SCCMDS) return -1;
+		if (pc + sccmd_info[op].ArgCount >= codesz) return -1;
+		if (op == SCMD_LINENUM)
+			line = code[pc + 1];
+		pc += sccmd_info[op].ArgCount;
+	}
+	return line;
+}
+
+static void cc_error_fixups(ccScript *scri, size_t pc, const char *fmt, ...) {
+	va_list ap;
+	va_start(ap, fmt);
+	String displbuf = String::FromFormatV(fmt, ap);
+	va_end(ap);
+	const char *scname = scri->numSections > 0 ? scri->sectionNames[0] : "?";
+	if (pc == -1) {
+		cc_error("in script %s: %s", scname, displbuf.GetCStr());
+	} else {
+		int line = DetermineScriptLine(scri->code, scri->codesize, pc);
+		cc_error("in script %s around line %d: %s", scname, line, displbuf.GetCStr());
+	}
+}
+
 bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 	code_fixups = new char[scri->codesize]();
 	for (int i = 0; i < scri->numfixups; ++i) {
@@ -1619,7 +1646,7 @@ bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 		case FIXUP_GLOBALDATA: {
 			ScriptVariable *gl_var = FindGlobalVar((int32_t)code[fixup]);
 			if (!gl_var) {
-				cc_error("cannot resolve global variable, key = %d", (int32_t)code[fixup]);
+				cc_error_fixups(scri.get(), fixup, "cannot resolve global variable (bytecode pos %d, key %d)", fixup, (int32_t)code[fixup]);
 				return false;
 			}
 			code[fixup] = (intptr_t)gl_var;
@@ -1637,7 +1664,7 @@ bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 			int import_index = resolved_imports[code[fixup]];
 			const ScriptImport *import = _GP(simp).getByIndex(import_index);
 			if (!import) {
-				cc_error("cannot resolve import, key = %d", import_index);
+				cc_error_fixups(scri.get(), fixup, "cannot resolve import (bytecode pos %d, key %d)", fixup, import_index);
 				return false;
 			}
 			code[fixup] = import_index;
@@ -1649,10 +1676,11 @@ bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 		}
 		break;
 		default:
-			cc_error("internal fixup index error: %d", scri->fixuptypes[i]);
+			cc_error_fixups(scri.get(), (size_t)-1, "unknown fixup type: %d (fixup num %d)", scri->fixuptypes[i], i);
 			return false;
 		}
 	}
+
 	return true;
 }
 


Commit: 429dab74752bba3e9c89c99b27dce12e706c28a5
    https://github.com/scummvm/scummvm/commit/429dab74752bba3e9c89c99b27dce12e706c28a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:09-07:00

Commit Message:
AGS: Updated build version (3.5.1.11)

>From upstream d27cd47d161ff7aec252cee7528de93b3b398c30

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 ad531799595..f50cd51be16 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.9"
+#define ACI_VERSION_STR      "3.6.0.11"
 #if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF  3,6,0,9
+#define ACI_VERSION_MSRC_DEF  3,6,0,11
 #endif
 
 #define SPECIAL_VERSION ""


Commit: 19e7035dedece9d7d96fb1dfa615ea1d895b0c25
    https://github.com/scummvm/scummvm/commit/19e7035dedece9d7d96fb1dfa615ea1d895b0c25
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:10-07:00

Commit Message:
AGS: Replaced few function params from PScript to ccScript*

>From upstream 432cbd2ee9fd76f7799336a5daee690ad9609a65

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


diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index e5e092488a3..c190d30e8ae 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -1392,13 +1392,13 @@ bool ccInstance::_Create(PScript scri, ccInstance *joined) {
 		resolved_imports = joined->resolved_imports;
 		code_fixups = joined->code_fixups;
 	} else {
-		if (!ResolveScriptImports(scri)) {
+		if (!ResolveScriptImports(scri.get())) {
 			return false;
 		}
-		if (!CreateGlobalVars(scri)) {
+		if (!CreateGlobalVars(scri.get())) {
 			return false;
 		}
-		if (!CreateRuntimeCodeFixups(scri)) {
+		if (!CreateRuntimeCodeFixups(scri.get())) {
 			return false;
 		}
 	}
@@ -1481,7 +1481,7 @@ void ccInstance::Free() {
 	code_fixups = nullptr;
 }
 
-bool ccInstance::ResolveScriptImports(PScript scri) {
+bool ccInstance::ResolveScriptImports(const ccScript *scri) {
 	// When the import is referenced in code, it's being addressed
 	// by it's index in the script imports array. That index is
 	// NOT unique and relative to script only.
@@ -1526,7 +1526,7 @@ bool ccInstance::ResolveScriptImports(PScript scri) {
 // certain accuracy after all global vars are registered. Each
 // global var's size would be limited by closest next var's ScAddress
 // and globaldatasize.
-bool ccInstance::CreateGlobalVars(PScript scri) {
+bool ccInstance::CreateGlobalVars(const ccScript *scri) {
 	ScriptVariable glvar;
 
 	// Step One: deduce global variables from fixups
@@ -1605,7 +1605,7 @@ ScriptVariable *ccInstance::FindGlobalVar(int32_t var_addr) {
 	return it != globalvars->end() ? &it->_value : nullptr;
 }
 
-static int DetermineScriptLine(int32_t *code, size_t codesz, size_t at_pc) {
+static int DetermineScriptLine(const int32_t *code, size_t codesz, size_t at_pc) {
 	int line = -1;
 	for (size_t pc = 0; (pc <= at_pc) && (pc < codesz); ++pc) {
 		int op = code[pc] & INSTANCE_ID_REMOVEMASK;
@@ -1618,7 +1618,7 @@ static int DetermineScriptLine(int32_t *code, size_t codesz, size_t at_pc) {
 	return line;
 }
 
-static void cc_error_fixups(ccScript *scri, size_t pc, const char *fmt, ...) {
+static void cc_error_fixups(const ccScript *scri, size_t pc, const char *fmt, ...) {
 	va_list ap;
 	va_start(ap, fmt);
 	String displbuf = String::FromFormatV(fmt, ap);
@@ -1632,7 +1632,7 @@ static void cc_error_fixups(ccScript *scri, size_t pc, const char *fmt, ...) {
 	}
 }
 
-bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
+bool ccInstance::CreateRuntimeCodeFixups(const ccScript *scri) {
 	code_fixups = new char[scri->codesize]();
 	for (int i = 0; i < scri->numfixups; ++i) {
 		if (scri->fixuptypes[i] == FIXUP_DATADATA) {
@@ -1646,7 +1646,7 @@ bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 		case FIXUP_GLOBALDATA: {
 			ScriptVariable *gl_var = FindGlobalVar((int32_t)code[fixup]);
 			if (!gl_var) {
-				cc_error_fixups(scri.get(), fixup, "cannot resolve global variable (bytecode pos %d, key %d)", fixup, (int32_t)code[fixup]);
+				cc_error_fixups(scri, fixup, "cannot resolve global variable (bytecode pos %d, key %d)", fixup, (int32_t)code[fixup]);
 				return false;
 			}
 			code[fixup] = (intptr_t)gl_var;
@@ -1664,7 +1664,7 @@ bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 			int import_index = resolved_imports[code[fixup]];
 			const ScriptImport *import = _GP(simp).getByIndex(import_index);
 			if (!import) {
-				cc_error_fixups(scri.get(), fixup, "cannot resolve import (bytecode pos %d, key %d)", fixup, import_index);
+				cc_error_fixups(scri, fixup, "cannot resolve import (bytecode pos %d, key %d)", fixup, import_index);
 				return false;
 			}
 			code[fixup] = import_index;
@@ -1676,7 +1676,7 @@ bool ccInstance::CreateRuntimeCodeFixups(PScript scri) {
 		}
 		break;
 		default:
-			cc_error_fixups(scri.get(), (size_t)-1, "unknown fixup type: %d (fixup num %d)", scri->fixuptypes[i], i);
+			cc_error_fixups(scri, (size_t)-1, "unknown fixup type: %d (fixup num %d)", scri->fixuptypes[i], i);
 			return false;
 		}
 	}
diff --git a/engines/ags/engine/script/cc_instance.h b/engines/ags/engine/script/cc_instance.h
index e4731204bac..8cc6b2fd1dd 100644
--- a/engines/ags/engine/script/cc_instance.h
+++ b/engines/ags/engine/script/cc_instance.h
@@ -179,11 +179,11 @@ protected:
 	// free the memory associated with the instance
 	void    Free();
 
-	bool    ResolveScriptImports(PScript scri);
-	bool    CreateGlobalVars(PScript scri);
+	bool    ResolveScriptImports(const ccScript *scri);
+	bool    CreateGlobalVars(const ccScript *scri);
 	bool    AddGlobalVar(const ScriptVariable &glvar);
 	ScriptVariable *FindGlobalVar(int32_t var_addr);
-	bool    CreateRuntimeCodeFixups(PScript scri);
+	bool    CreateRuntimeCodeFixups(const ccScript *scri);
 	//bool    ReadOperation(ScriptOperation &op, int32_t at_pc);
 
 	// Runtime fixups


Commit: 02a6600080d4f9acfa3d4810e0b3f7d491f17cfa
    https://github.com/scummvm/scummvm/commit/02a6600080d4f9acfa3d4810e0b3f7d491f17cfa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:10-07:00

Commit Message:
AGS: Fix potentially invalid frame during Character turning

>From upstream 84faeccb049883f6d55c0ba34c6a9f02f6bbdbe8

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


diff --git a/engines/ags/engine/ac/character_info_engine.cpp b/engines/ags/engine/ac/character_info_engine.cpp
index a9e95978116..1f203f3da6c 100644
--- a/engines/ags/engine/ac/character_info_engine.cpp
+++ b/engines/ags/engine/ac/character_info_engine.cpp
@@ -149,6 +149,8 @@ int CharacterInfo::update_character_walking(CharacterExtras *chex) {
 				} else break;
 			}
 			loop = turnlooporder[wantloop];
+			if (frame >= _GP(views)[view].loops[loop].numFrames)
+				frame = 0; // AVD: make sure the loop always has a valid frame
 			walking -= TURNING_AROUND;
 			// if still turning, wait for next frame
 			if (walking % TURNING_BACKWARDS >= TURNING_AROUND)


Commit: 6aa5960eed3f998179c979fbc236b02e01f53d6d
    https://github.com/scummvm/scummvm/commit/6aa5960eed3f998179c979fbc236b02e01f53d6d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:10-07:00

Commit Message:
AGS: Ensure quit() is called if engine startup was interrupted

>From upstream 099cb50246f3cde2df1ccfc13347607d77ccd094

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


diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 2a09c070afa..67619cfe469 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -1232,7 +1232,6 @@ int initialize_engine(const ConfigTree &startup_opts) {
 
 	initialize_start_and_play_game(_G(override_start_room), _G(loadSaveGameOnStartup));
 
-	quit("|bye!");
 	return EXIT_NORMAL;
 }
 


Commit: 394347a75dccd9ad880b93942a9d21e6e598c1d8
    https://github.com/scummvm/scummvm/commit/394347a75dccd9ad880b93942a9d21e6e598c1d8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:10-07:00

Commit Message:
AGS: Reimplemented room area debug display as a persistent overlay

>From upstream ba98628a146896664a70a51442765c35d9789514

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


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index bfebe2f6e21..e9f5dcfb2c3 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -416,6 +416,12 @@ void dispose_game_drawdata() {
 	_GP(guibgbmp).clear();
 }
 
+static void dispose_debug_room_drawdata() {
+	if (_G(debugRoomMaskDDB) != nullptr)
+		_G(gfxDriver)->DestroyDDB(_G(debugRoomMaskDDB));
+	_G(debugRoomMaskDDB) = nullptr;
+}
+
 void dispose_room_drawdata() {
 	_GP(CameraDrawData).clear();
 	dispose_invalid_regions(true);
@@ -452,6 +458,8 @@ void clear_drawobj_cache() {
 			_G(gfxDriver)->DestroyDDB(_GP(guibgbmp)[i]);
 		_GP(guibgbmp)[i] = nullptr;
 	}
+
+	dispose_debug_room_drawdata();
 }
 
 void on_mainviewport_changed() {
@@ -509,6 +517,10 @@ void sync_roomview(Viewport *view) {
 }
 
 void init_room_drawdata() {
+	// Update debug overlays, if any were on
+	debug_draw_room_mask(_G(debugRoomMask));
+
+	// Following data is only updated for software renderer
 	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	// Make sure all frame buffers are created for software drawing
@@ -703,8 +715,6 @@ void draw_game_screen_callback() {
 	construct_game_screen_overlay(false);
 }
 
-
-
 void putpixel_compensate(Bitmap *ds, int xx, int yy, int col) {
 	if ((ds->GetColorDepth() == 32) && (col != 0)) {
 		// ensure the alpha channel is preserved if it has one
@@ -714,9 +724,6 @@ void putpixel_compensate(Bitmap *ds, int xx, int yy, int col) {
 	ds->FillRect(Rect(xx, yy, xx + get_fixed_pixel_size(1) - 1, yy + get_fixed_pixel_size(1) - 1), col);
 }
 
-
-
-
 void draw_sprite_support_alpha(Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Bitmap *image, bool src_has_alpha,
                                BlendMode blend_mode, int alpha) {
 	if (alpha <= 0)
@@ -1853,6 +1860,10 @@ void prepare_room_sprites() {
 		}
 	}
 	_G(our_eip) = 36;
+
+	// Debug room overlay
+	if ((_G(debugRoomMask) != kRoomAreaNone) && _G(debugRoomMaskDDB))
+		add_thing_to_draw(_G(debugRoomMaskDDB), 0, 0);
 }
 
 // Draws the black surface behind (or rather between) the room viewports
@@ -2282,6 +2293,24 @@ static void update_shakescreen() {
 	}
 }
 
+void debug_draw_room_mask(RoomAreaMask mask) {
+	_G(debugRoomMask) = mask;
+	if (mask == kRoomAreaNone)
+		return;
+
+	Bitmap *mask_bmp;
+	switch (mask) {
+	case kRoomAreaHotspot: mask_bmp = _GP(thisroom).HotspotMask.get(); break;
+	case kRoomAreaWalkBehind: mask_bmp = _GP(thisroom).WalkBehindMask.get(); break;
+	case kRoomAreaWalkable: mask_bmp = prepare_walkable_areas(-1); break;
+	case kRoomAreaRegion: mask_bmp = _GP(thisroom).RegionMask.get(); break;
+	default: return;
+	}
+
+	_G(debugRoomMaskDDB) = recycle_ddb_bitmap(_G(debugRoomMaskDDB), mask_bmp, false, true);
+	_G(debugRoomMaskDDB)->SetTransparency(150);
+}
+
 // Draw everything
 void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY) {
 	// Don't render if skipping cutscene
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index fd3b0342a49..85e08e00ec0 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -26,6 +26,7 @@
 #include "ags/shared/core/types.h"
 #include "ags/shared/ac/common_defines.h"
 #include "ags/shared/gfx/gfx_def.h"
+#include "ags/shared/game/room_struct.h"
 
 namespace AGS3 {
 namespace AGS {
@@ -127,6 +128,8 @@ void construct_engine_overlay();
 // Clears black game borders in legacy letterbox mode
 void clear_letterbox_borders();
 
+void debug_draw_room_mask(RoomAreaMask mask);
+
 void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
 void draw_sprite_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Shared::Bitmap *image, bool src_has_alpha,
                                Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 3020e6d9de4..9cb23dcfaf6 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -583,6 +583,9 @@ public:
 	// GUI surfaces
 	std::vector<Shared::Bitmap *> *_guibg;
 	std::vector<Engine::IDriverDependantBitmap *> *_guibgbmp;
+	// For debugging room masks
+	RoomAreaMask _debugRoomMask = kRoomAreaNone;
+	Engine::IDriverDependantBitmap *_debugRoomMaskDDB = nullptr;
 
 	bool _current_background_is_dirty = false;
 	// Room background sprite


Commit: b0233b607eace83ff676f76b3b2738d5eaddc29b
    https://github.com/scummvm/scummvm/commit/b0233b607eace83ff676f76b3b2738d5eaddc29b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:10-07:00

Commit Message:
AGS: Update debug layer for walkable mask in realtime

>From upstream 22192bce19cea39ceeeb7200963f8ce9b919b3b7

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


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index e9f5dcfb2c3..ebc3b165bc9 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1862,6 +1862,7 @@ void prepare_room_sprites() {
 	_G(our_eip) = 36;
 
 	// Debug room overlay
+	update_room_debug();
 	if ((_G(debugRoomMask) != kRoomAreaNone) && _G(debugRoomMaskDDB))
 		add_thing_to_draw(_G(debugRoomMaskDDB), 0, 0);
 }
@@ -2311,6 +2312,14 @@ void debug_draw_room_mask(RoomAreaMask mask) {
 	_G(debugRoomMaskDDB)->SetTransparency(150);
 }
 
+void update_room_debug() {
+	if (_G(debugRoomMask) == kRoomAreaWalkable) {
+		Bitmap *mask_bmp = prepare_walkable_areas(-1);
+		_G(debugRoomMaskDDB) = recycle_ddb_bitmap(_G(debugRoomMaskDDB), mask_bmp, false, true);
+		_G(debugRoomMaskDDB)->SetTransparency(150);
+	}
+}
+
 // Draw everything
 void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY) {
 	// Don't render if skipping cutscene
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 85e08e00ec0..f55ef1943aa 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -129,6 +129,7 @@ void construct_engine_overlay();
 void clear_letterbox_borders();
 
 void debug_draw_room_mask(RoomAreaMask mask);
+void update_room_debug();
 
 void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
 void draw_sprite_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Shared::Bitmap *image, bool src_has_alpha,


Commit: cf62e3979b22d2994708045a42311149d375d469
    https://github.com/scummvm/scummvm/commit/cf62e3979b22d2994708045a42311149d375d469
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:10-07:00

Commit Message:
AGS: Reimplemented walk path display as a persistent overlay

>From upstream 92774437d3c454d16c7c0f51c6b32dabd1880c08

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


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index ebc3b165bc9..2f407abade0 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -41,6 +41,7 @@
 #include "ags/engine/ac/global_region.h"
 #include "ags/engine/ac/gui.h"
 #include "ags/engine/ac/mouse.h"
+#include "ags/engine/ac/move_list.h"
 #include "ags/engine/ac/object_cache.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/sys_events.h"
@@ -420,6 +421,11 @@ static void dispose_debug_room_drawdata() {
 	if (_G(debugRoomMaskDDB) != nullptr)
 		_G(gfxDriver)->DestroyDDB(_G(debugRoomMaskDDB));
 	_G(debugRoomMaskDDB) = nullptr;
+	delete _G(debugMoveListBmp);
+	_G(debugMoveListBmp) = nullptr;
+	if (_G(debugMoveListDDB) != nullptr)
+		_G(gfxDriver)->DestroyDDB(_G(debugMoveListDDB));
+	_G(debugMoveListDDB) = nullptr;
 }
 
 void dispose_room_drawdata() {
@@ -519,6 +525,7 @@ void sync_roomview(Viewport *view) {
 void init_room_drawdata() {
 	// Update debug overlays, if any were on
 	debug_draw_room_mask(_G(debugRoomMask));
+	debug_draw_movelist(_G(debugMoveListChar));
 
 	// Following data is only updated for software renderer
 	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
@@ -1865,6 +1872,8 @@ void prepare_room_sprites() {
 	update_room_debug();
 	if ((_G(debugRoomMask) != kRoomAreaNone) && _G(debugRoomMaskDDB))
 		add_thing_to_draw(_G(debugRoomMaskDDB), 0, 0);
+	if ((_G(debugMoveListChar) >= 0) && _G(debugMoveListDDB))
+		add_thing_to_draw(_G(debugMoveListDDB), 0, 0);
 }
 
 // Draws the black surface behind (or rather between) the room viewports
@@ -2312,12 +2321,35 @@ void debug_draw_room_mask(RoomAreaMask mask) {
 	_G(debugRoomMaskDDB)->SetTransparency(150);
 }
 
+void debug_draw_movelist(int charnum) {
+	_G(debugMoveListChar) = charnum;
+}
+
 void update_room_debug() {
 	if (_G(debugRoomMask) == kRoomAreaWalkable) {
 		Bitmap *mask_bmp = prepare_walkable_areas(-1);
 		_G(debugRoomMaskDDB) = recycle_ddb_bitmap(_G(debugRoomMaskDDB), mask_bmp, false, true);
 		_G(debugRoomMaskDDB)->SetTransparency(150);
 	}
+	if (_G(debugMoveListChar) >= 0) {
+		_G(debugMoveListBmp) = recycle_bitmap(_G(debugMoveListBmp), _GP(game).GetColorDepth(),
+			_GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight(), true);
+		if (_GP(game).chars[_G(debugMoveListChar)].walking > 0) {
+			int mlsnum = _GP(game).chars[_G(debugMoveListChar)].walking;
+			if (_GP(game).chars[_G(debugMoveListChar)].walking >= TURNING_AROUND)
+				mlsnum %= TURNING_AROUND;
+			const MoveList &cmls = _G(mls)[mlsnum];
+			for (int i = 0; i < cmls.numstage - 1; i++) {
+				short srcx = short((cmls.pos[i] >> 16) & 0x00ffff);
+				short srcy = short(cmls.pos[i] & 0x00ffff);
+				short targetx = short((cmls.pos[i + 1] >> 16) & 0x00ffff);
+				short targety = short(cmls.pos[i + 1] & 0x00ffff);
+				_G(debugMoveListBmp)->DrawLine(Line(srcx, srcy, targetx, targety), MakeColor(i + 1));
+			}
+		}
+		_G(debugMoveListDDB) = recycle_ddb_bitmap(_G(debugMoveListDDB), _G(debugMoveListBmp), false, false);
+		_G(debugMoveListDDB)->SetTransparency(150);
+	}
 }
 
 // Draw everything
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index f55ef1943aa..d6d4e09b9a8 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -129,6 +129,7 @@ void construct_engine_overlay();
 void clear_letterbox_borders();
 
 void debug_draw_room_mask(RoomAreaMask mask);
+void debug_draw_movelist(int charnum);
 void update_room_debug();
 
 void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 9cb23dcfaf6..f91f0dcd978 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -586,6 +586,9 @@ public:
 	// For debugging room masks
 	RoomAreaMask _debugRoomMask = kRoomAreaNone;
 	Engine::IDriverDependantBitmap *_debugRoomMaskDDB = nullptr;
+	int _debugMoveListChar = -1;
+	Shared::Bitmap *_debugMoveListBmp = nullptr;
+	Engine::IDriverDependantBitmap *_debugMoveListDDB = nullptr;
 
 	bool _current_background_is_dirty = false;
 	// Room background sprite


Commit: 3c062750ede859c240d169d5644fb217b51647aa
    https://github.com/scummvm/scummvm/commit/3c062750ede859c240d169d5644fb217b51647aa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-19T21:25:11-07:00

Commit Message:
AGS: Remove random limit of 50 walk speed and clamp to int16 limits

>From upstream c3b286539df21180300c282c415c15f56d444be4

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


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index e236a59730d..dff1918865c 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -843,18 +843,19 @@ void Character_SetOption(CharacterInfo *chaa, int flag, int yesorno) {
 		if (yesorno)
 			chaa->flags |= flag;
 	}
-
 }
 
 void Character_SetSpeed(CharacterInfo *chaa, int xspeed, int yspeed) {
-
-	if ((xspeed == 0) || (xspeed > 50) || (yspeed == 0) || (yspeed > 50))
+	if ((xspeed == 0) || (yspeed == 0))
 		quit("!SetCharacterSpeedEx: invalid speed value");
 	if (chaa->walking) {
 		debug_script_warn("Character_SetSpeed: cannot change speed while walking");
 		return;
 	}
 
+	xspeed = Math::Clamp(xspeed, (int)INT16_MIN, (int)INT16_MAX);
+	yspeed = Math::Clamp(yspeed, (int)INT16_MIN, (int)INT16_MAX);
+
 	chaa->walkspeed = xspeed;
 
 	if (yspeed == xspeed)




More information about the Scummvm-git-logs mailing list