From a9b25b53d7a7084941553166abd20a602e83e184 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 31 Jan 2016 22:14:35 +0100 Subject: AGI: properly implement volume control + sync Original code did assume that AGI volume level is 0-15 (0 for silence, 15 for maximum volume). It actually is the other way. 0 is maximum, 15 is silence. Fixed that. Also implemented sync with ScummVM settings dialog. In case "mute" is enabled by the user, any volume changes done by scripts are ignored. Fixes Manhunter 1 Apple IIgs not getting sound anymore since the VM Var cleanup (the script volume change by the scripts didn't reach us before) --- engines/agi/agi.cpp | 6 +++++ engines/agi/agi.h | 4 +++ engines/agi/global.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++-- engines/agi/saveload.cpp | 3 +++ 4 files changed, 77 insertions(+), 2 deletions(-) (limited to 'engines/agi') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index c8490d4a89..9c66c38487 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -184,6 +184,12 @@ int AgiEngine::agiInit() { _game.mouseFence.setWidth(0); // Reset + // Reset in-game timer + inGameTimerReset(); + + // Sync volume settings from ScummVM system settings + setVolumeViaSystemSetting(); + return ec; } diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 7e1505f8f7..f1aec3ee21 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -824,6 +824,10 @@ public: byte getVar(int16 varNr); void setVar(int16 varNr, byte newValue); +private: + void setVolumeViaScripts(byte newVolume); + void setVolumeViaSystemSetting(); + public: void decrypt(uint8 *mem, int len); void releaseSprites(); diff --git a/engines/agi/global.cpp b/engines/agi/global.cpp index 3cc8ffc6f8..e1172597e5 100644 --- a/engines/agi/global.cpp +++ b/engines/agi/global.cpp @@ -20,6 +20,8 @@ * */ +#include "common/config-manager.h" + #include "agi/agi.h" namespace Agi { @@ -52,8 +54,7 @@ void AgiEngine::setVar(int16 varNr, byte newValue) { _game.vars[varNr] = newValue; if (varNr == VM_VAR_VOLUME) { - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, newValue * 17); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, newValue * 17); + setVolumeViaScripts(newValue); } } @@ -73,6 +74,67 @@ byte AgiEngine::getVar(int16 varNr) { return _game.vars[varNr]; } +// sets volume based on script value +// 0 - maximum volume +// 15 - mute +void AgiEngine::setVolumeViaScripts(byte newVolume) { + newVolume = CLIP(newVolume, 0, 15); + newVolume = 15 - newVolume; // turn volume around + + int scummVMVolume = newVolume * Audio::Mixer::kMaxMixerVolume / 15; + bool scummVMMute = false; + + // Set ScummVM setting + // We do not set "mute". In case "mute" is set, we will not apply the scripts wishes + ConfMan.setInt("music_volume", scummVMVolume); + ConfMan.setInt("sfx_volume", scummVMVolume); + + if (ConfMan.hasKey("mute")) + scummVMMute = ConfMan.getBool("mute"); + + if (!scummVMMute) { + // Also change volume directly + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, scummVMVolume); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, scummVMVolume); + } +} + +void AgiEngine::setVolumeViaSystemSetting() { + int scummVMVolumeMusic = ConfMan.getInt("music_volume"); + int scummVMVolumeSfx = ConfMan.getInt("sfx_volume"); + bool scummVMMute = false; + int internalVolume = 0; + + if (ConfMan.hasKey("mute")) + scummVMMute = ConfMan.getBool("mute"); + + // Clip user system setting + scummVMVolumeMusic = CLIP(scummVMVolumeMusic, 0, Audio::Mixer::kMaxMixerVolume); + scummVMVolumeSfx = CLIP(scummVMVolumeSfx, 0, Audio::Mixer::kMaxMixerVolume); + + if (scummVMMute) { + scummVMVolumeMusic = 0; + scummVMVolumeSfx = 0; + } + + // Now actually set it + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, scummVMVolumeMusic); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, scummVMVolumeSfx); + + // Take lowest volume to the scripts + if (scummVMVolumeMusic < scummVMVolumeSfx) { + internalVolume = scummVMVolumeMusic; + } else { + internalVolume = scummVMVolumeSfx; + } + // Change it to 0-15 range + internalVolume = (internalVolume + 1) * 15 / Audio::Mixer::kMaxMixerVolume; + // Reverse it + internalVolume = 15 - internalVolume; + // Put it into the VM variable. Directly set it, otherwise it would call a volume set call + _game.vars[VM_VAR_VOLUME] = internalVolume; +} + // In-Game timer, used for timer VM Variables void AgiEngine::inGameTimerReset(uint32 newPlayTime) { _passedPlayTimeCycles = 0; diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index b47a0cf43f..6b1b5495f7 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -703,6 +703,9 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) { // copy everything over (we should probably only copy over the remaining parts of the screen w/o play screen _gfx->copyDisplayRectToScreen(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); + // Sync volume settings from ScummVM system settings, so that VM volume variable is overwritten + setVolumeViaSystemSetting(); + return errOK; } -- cgit v1.2.3