[Scummvm-git-logs] scummvm master -> 5369ed6ecc3b63ff5e4a94b497f6b650e2f63ad1

NMIError 60350957+NMIError at users.noreply.github.com
Sat Oct 9 15:30:44 UTC 2021


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

Summary:
69629944e5 MADE: Use SFX sound type for sampled audio
111b237e02 AUDIO: Fix Roland GS emulation not using MT-32 drumkit
d8491ecea4 AUDIO: Add default for OPL channel volume
2d5e8dbee6 MADE: New MIDI player
0a702a6e3f MADE: Pause MIDI music when pausing engine
30a6c8428c MADE: Fix audible gap when sounds loop
8ec8f65d5f MADE: Improve unpausing game when movie is playing
245c4cc923 MADE: Display MT-32 quit message
5369ed6ecc MADE: Add option for MIDI introduction music


Commit: 69629944e5c4f55d1a68cb9bca26cc547b6bc360
    https://github.com/scummvm/scummvm/commit/69629944e5c4f55d1a68cb9bca26cc547b6bc360
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:44+02:00

Commit Message:
MADE: Use SFX sound type for sampled audio

The engine used the plain sound type for sampled sound effects and movie audio
and applied the SFX user volume control to the plain sound type. This caused
emulators like the AdLib emulator and Munt to be affected by the SFX user
volume control, because they use the plain sound type. This commit fixes this
by using the SFX sound type instead of the plain sound type. User volume is
applied by Engine::syncSoundSettings.

This commit also fixes the setSoundVolume script function. Volume was
previously applied to the SFX and speech sound types, which were not used.
Also, by directly using Mixer::setVolumeForSoundType, it would override the
user volume setting. This is fixed by storing the game sound volume in a field
and applying this to the current and future audio streams. This fixes bug
#6444.

Changed paths:
    engines/made/made.cpp
    engines/made/pmvplayer.cpp
    engines/made/scriptfuncs.cpp
    engines/made/scriptfuncs.h


diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index cdcc3cd8dc..441eb4179f 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -114,8 +114,6 @@ void MadeEngine::syncSoundSettings() {
 		mute = ConfMan.getBool("mute");
 
 	_music->setVolume(mute ? 0 : ConfMan.getInt("music_volume"));
-	_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType,
-									mute ? 0 : ConfMan.getInt("sfx_volume"));
 }
 
 int16 MadeEngine::getTicks() {
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
index 8676800c18..6ec5943601 100644
--- a/engines/made/pmvplayer.cpp
+++ b/engines/made/pmvplayer.cpp
@@ -189,7 +189,7 @@ bool PmvPlayer::play(const char *filename) {
 		decompressMovieImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize);
 
 		if (firstTime) {
-			_mixer->playStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);
+			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_audioStreamHandle, _audioStream);
 			soundStartTime = g_system->getMillis();
 			skipFrames = 0;
 			firstTime = false;
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index bcc08e0dcc..9035ec0c6b 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -36,7 +36,7 @@
 
 namespace Made {
 
-ScriptFunctions::ScriptFunctions(MadeEngine *vm) : _vm(vm), _soundStarted(false) {
+ScriptFunctions::ScriptFunctions(MadeEngine *vm) : _vm(vm), _soundStarted(false), _gameAudioVolume(Audio::Mixer::kMaxChannelVolume) {
 	// Initialize the two tone generators
 	_pcSpeaker1 = new Audio::PCSpeaker();
 	_pcSpeaker2 = new Audio::PCSpeaker();
@@ -252,8 +252,8 @@ int16 ScriptFunctions::sfPlaySound(int16 argc, int16 *argv) {
 	}
 	if (soundNum > 0) {
 		SoundResource *soundRes = _vm->_res->getSound(soundNum);
-		_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle,
-			soundRes->getAudioStream(_vm->_soundRate, false));
+		_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_audioStreamHandle,
+			soundRes->getAudioStream(_vm->_soundRate, false), -1, _gameAudioVolume);
 		_vm->_soundEnergyArray = soundRes->getSoundEnergyArray();
 		_vm->_soundEnergyIndex = 0;
 		_soundStarted = true;
@@ -641,8 +641,8 @@ int16 ScriptFunctions::sfPlayVoice(int16 argc, int16 *argv) {
 	stopSound();
 	if (soundNum > 0) {
 		_soundResource = _vm->_res->getSound(soundNum);
-		_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle,
-			_soundResource->getAudioStream(_vm->_soundRate, false));
+		_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_audioStreamHandle,
+			_soundResource->getAudioStream(_vm->_soundRate, false), -1, _gameAudioVolume);
 		_vm->_autoStopSound = true;
 		_soundStarted = true;
 	}
@@ -1013,8 +1013,9 @@ int16 ScriptFunctions::sfPlaceMenu(int16 argc, int16 *argv) {
 }
 
 int16 ScriptFunctions::sfSetSoundVolume(int16 argc, int16 *argv) {
-	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, argv[0] * 25);
-	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[0] * 25);
+	_gameAudioVolume = argv[0] * 25;
+	if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle))
+		_vm->_mixer->setChannelVolume(_audioStreamHandle, _gameAudioVolume);
 	return 0;
 }
 
diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h
index 9db5586adf..b47e67dfde 100644
--- a/engines/made/scriptfuncs.h
+++ b/engines/made/scriptfuncs.h
@@ -63,6 +63,8 @@ protected:
 	Audio::SoundHandle _voiceStreamHandle;
 	SoundResource* _soundResource;
 	bool _soundStarted;
+	// The audio volume set by the game scripts.
+	uint8 _gameAudioVolume;
 
 	// PlayNote/StopNote and PlayTele/StopTele wave generators
 	Audio::SoundHandle _pcSpeakerHandle1, _pcSpeakerHandle2;


Commit: 111b237e02c31f753269a4345bc1f41e50846c3e
    https://github.com/scummvm/scummvm/commit/111b237e02c31f753269a4345bc1f41e50846c3e
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:44+02:00

Commit Message:
AUDIO: Fix Roland GS emulation not using MT-32 drumkit

The Roland GS MT-32 emulation option would not select the MT-32 drumkit on the
GS device, because the drumkit change was filtered out in the MT32GM driver.
This commit fixes this by adding an exception for this drumkit change when GS
MT-32 emulation is active.

Changed paths:
    audio/mt32gm.cpp


diff --git a/audio/mt32gm.cpp b/audio/mt32gm.cpp
index 98e416c21f..ae8827b995 100644
--- a/audio/mt32gm.cpp
+++ b/audio/mt32gm.cpp
@@ -314,7 +314,7 @@ void MidiDriver_MT32GM::initGM(bool initForMT32, bool enableGS) {
 				getPercussionChannel()->controlChange(MIDI_CONTROLLER_BANK_SELECT_LSB, 1);
 			}
 			// Patch change: 127 (CM-64/32L)
-			send(127 << 8 | MIDI_COMMAND_PROGRAM_CHANGE | 9);
+			send((127 << 8) | MIDI_COMMAND_PROGRAM_CHANGE | 9);
 
 			// Set Channels 1-16 to SC-55 Map, then CM-64/32L Variation
 			for (i = 0; i < 16; ++i) {
@@ -633,10 +633,14 @@ void MidiDriver_MT32GM::programChange(byte outputChannel, byte patchId, int8 sou
 		return;
 
 	if (_midiType == MT_MT32) {
-		if (outputChannel == MIDI_RHYTHM_CHANNEL)
+		if (outputChannel == MIDI_RHYTHM_CHANNEL &&
+				!(!_nativeMT32 && _enableGS && patchId == 0x7F)) {
 			// Patch changes on the rhythm channel do nothing on an MT-32.
 			// On GM/GS devices they might unintentionally change the drumkit.
+			// Exception: changing the drumkit to the MT-32 drumkit on a GS
+			// device.
 			return;
+		}
 
 		if (!_nativeMT32 && !_enableGS) {
 			// GM device: map the patch to GM equivalent


Commit: d8491ecea444ea42a7d5b77c37b348b306526834
    https://github.com/scummvm/scummvm/commit/d8491ecea444ea42a7d5b77c37b348b306526834
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:44+02:00

Commit Message:
AUDIO: Add default for OPL channel volume

This adds an option to the AdLib multisource driver to set the MIDI channel
volume that will be used to initialize to OPL 4x registers.

Changed paths:
    audio/adlib_ms.cpp
    audio/adlib_ms.h


diff --git a/audio/adlib_ms.cpp b/audio/adlib_ms.cpp
index c504371872..2a05971a92 100644
--- a/audio/adlib_ms.cpp
+++ b/audio/adlib_ms.cpp
@@ -377,6 +377,7 @@ MidiDriver_ADLIB_Multisource::MidiDriver_ADLIB_Multisource(OPL::Config::OplType
 		_isOpen(false),
 		_accuracyMode(ACCURACY_MODE_SB16_WIN95),
 		_allocationMode(ALLOCATION_MODE_DYNAMIC),
+		_defaultChannelVolume(0),
 		_noteSelect(NOTE_SELECT_MODE_0),
 		_modulationDepth(MODULATION_DEPTH_HIGH),
 		_vibratoDepth(VIBRATO_DEPTH_HIGH),
@@ -421,6 +422,13 @@ int MidiDriver_ADLIB_Multisource::open() {
 	if (!_opl->init())
 		return MERR_CANNOT_CONNECT;
 
+	// Set default MIDI channel volume on control data.
+	for (int i = 0; i < MAXIMUM_SOURCES; i++) {
+		for (int j = 0; j < MIDI_CHANNEL_COUNT; j++) {
+			_controlData[i][j].volume = _defaultChannelVolume;
+		}
+	}
+
 	// Set default OPL register values.
 	initOpl();
 
@@ -987,8 +995,9 @@ void MidiDriver_ADLIB_Multisource::initOpl() {
 			break;
 		case 1:
 			baseReg = OPL_REGISTER_BASE_LEVEL;
-			// Set default volume to 3F (maximum attenuation).
-			value = OPL_LEVEL_DEFAULT;
+			// Set volume to the default MIDI channel volume.
+			// Convert from MIDI to OPL register value.
+			value = 0x3F - (_defaultChannelVolume >> 1);
 			break;
 		case 2:
 			baseReg = OPL_REGISTER_BASE_DECAY_ATTACK;
diff --git a/audio/adlib_ms.h b/audio/adlib_ms.h
index 919d54d590..539c616f02 100644
--- a/audio/adlib_ms.h
+++ b/audio/adlib_ms.h
@@ -1006,6 +1006,9 @@ protected:
 	// Controls the OPL channel allocation behavior.
 	ChannelAllocationMode _allocationMode;
 
+	// The default MIDI channel volume (set when opening the driver).
+	uint8 _defaultChannelVolume;
+
 	// OPL global settings. Set these, then call oplInit or open to apply the
 	// new values.
 	NoteSelectMode _noteSelect;


Commit: 2d5e8dbee6a68ca634bef8ddf3447ae58cf8a22c
    https://github.com/scummvm/scummvm/commit/2d5e8dbee6a68ca634bef8ddf3447ae58cf8a22c
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:44+02:00

Commit Message:
MADE: New MIDI player

This rewrites the MADE music player to remove the use of the MidiPlayer. This
fixes the following issues in Return to Zork:
- User music volume control did not work for AdLib.
- MIDI channels were remapped; sometimes channels were missing (f.e. at the
  lighthouse exterior).
- Some music tracks did not play because the current track had to be stopped
  before playing a new track (f.e. the music over the credits after the intro).
- MIDI played at half volume and volume control would reset when a new track
  started playing.
- "Native MT-32" flag was not checked, so the Miles driver was not used for
  hardware MT-32.
- MT-32 to GM instrument mapping did not work.
- Roland GS mode now works.

Changed paths:
    engines/made/made.cpp
    engines/made/music.cpp
    engines/made/music.h


diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 441eb4179f..143bd959a4 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -109,11 +109,7 @@ MadeEngine::~MadeEngine() {
 void MadeEngine::syncSoundSettings() {
 	Engine::syncSoundSettings();
 
-	bool mute = false;
-	if (ConfMan.hasKey("mute"))
-		mute = ConfMan.getBool("mute");
-
-	_music->setVolume(mute ? 0 : ConfMan.getInt("music_volume"));
+	_music->syncSoundSettings();
 }
 
 int16 MadeEngine::getTicks() {
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index f57da833c2..488332aba0 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -20,31 +20,32 @@
  *
  */
 
-// FIXME: This code is taken from SAGA and needs more work (e.g. setVolume).
-
-// MIDI and digital music class
+// MIDI music class
 
 #include "made/music.h"
 #include "made/redreader.h"
 #include "made/resource.h"
 
+#include "audio/adlib_ms.h"
 #include "audio/midiparser.h"
 #include "audio/miles.h"
 
+#include "common/config-manager.h"
 #include "common/file.h"
 #include "common/stream.h"
 
 namespace Made {
 
-MusicPlayer::MusicPlayer(bool milesAudio) : _isGM(false),_milesAudioMode(false) {
-	MusicType musicType = MT_INVALID;
-	if (milesAudio) {
-		MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
-		musicType = MidiDriver::getMusicType(dev);
-		Common::SeekableReadStream *adLibInstrumentStream = nullptr;
-		switch (musicType) {
-		case MT_ADLIB:
-			_milesAudioMode = true;
+MusicPlayer::MusicPlayer(bool milesAudio) : _parser(0) {
+	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
+	_driverType = MidiDriver::getMusicType(dev);
+	if (_driverType == MT_GM && ConfMan.getBool("native_mt32"))
+		_driverType = MT_MT32;
+
+	Common::SeekableReadStream *adLibInstrumentStream = nullptr;
+	switch (_driverType) {
+	case MT_ADLIB:
+		if (milesAudio) {
 			if (Common::File::exists("rtzcd.red")) {
 				// Installing Return to Zork produces both a SAMPLE.AD and
 				// a SAMPLE.OPL file, but they are identical. The resource
@@ -53,115 +54,115 @@ MusicPlayer::MusicPlayer(bool milesAudio) : _isGM(false),_milesAudioMode(false)
 			}
 			_driver = Audio::MidiDriver_Miles_AdLib_create("SAMPLE.AD", "SAMPLE.OPL", adLibInstrumentStream);
 			delete adLibInstrumentStream;
-			break;
-		case MT_MT32:
-			_milesAudioMode = true;
-			_driver = Audio::MidiDriver_Miles_MT32_create("");
-			break;
-		default:
-			_milesAudioMode = false;
-			MidiPlayer::createDriver();
-			break;
+		} else {
+			_driver = new MidiDriver_ADLIB_MADE(OPL::Config::kOpl2);
 		}
-	} else {
-			MidiPlayer::createDriver();
+		break;
+	case MT_GM:
+	case MT_MT32:
+		if (milesAudio) {
+			_driver = Audio::MidiDriver_Miles_MIDI_create(MT_MT32, "");
+		} else {
+			_driver = new MidiDriver_MT32GM(MT_MT32);
+		}
+		break;
+	default:
+		_driver = new MidiDriver_NULL_Multisource();
+		break;
 	}
 
-	int ret = _driver->open();
-	if (ret == 0) {
-		if (musicType != MT_ADLIB) {
-			if (_nativeMT32)
-				_driver->sendMT32Reset();
-			else
-				_driver->sendGMReset();
-		}
+	if (_driver) {
+		_driver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
+		if (_driver->open() != 0)
+			error("Failed to open MIDI driver.");
 
 		_driver->setTimerCallback(this, &timerCallback);
 	}
+
+	syncSoundSettings();
 }
 
-void MusicPlayer::send(uint32 b) {
-	if (_milesAudioMode) {
-		_driver->send(b);
-		return;
+MusicPlayer::~MusicPlayer() {
+	if (_parser) {
+		_parser->stopPlaying();
+		delete _parser;
 	}
-
-	if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
-		b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+	if (_driver) {
+		_driver->setTimerCallback(0, 0);
+		_driver->close();
+		delete _driver;
 	}
-
-	Audio::MidiPlayer::send(b);
 }
 
-void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) {
-	Common::StackLock lock(_mutex);
-
-	if (_isPlaying)
-		return;
+void MusicPlayer::playXMIDI(GenericResource *midiResource) {
+	if (_parser) {
+		_parser->unloadMusic();
+	} else {
+		_parser = MidiParser::createParser_XMIDI(0, 0, 0);
 
-	stop();
+		_parser->setMidiDriver(_driver);
+		_parser->setTimerRate(_driver->getBaseTempo());
+		_parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
+	}
 
 	// Load XMID resource data
 
-	_isGM = true;
-
-	MidiParser *parser = MidiParser::createParser_XMIDI();
-	if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) {
-		parser->setTrack(0);
-		parser->setMidiDriver(this);
-		parser->setTimerRate(_driver->getBaseTempo());
-		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
-		parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
-
-		_parser = parser;
-
-		setVolume(127);
+	_parser->loadMusic(midiResource->getData(), midiResource->getSize());
+}
 
-		_isLooping = flags & MUSIC_LOOP;
-		_isPlaying = true;
+void MusicPlayer::playSMF(GenericResource *midiResource) {
+	if (_parser) {
+		_parser->unloadMusic();
 	} else {
-		delete parser;
-	}
-}
+		_parser = MidiParser::createParser_SMF(0);
 
-void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) {
-	Common::StackLock lock(_mutex);
+		_parser->setMidiDriver(_driver);
+		_parser->setTimerRate(_driver->getBaseTempo());
+		_parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+	}
 
-	if (_isPlaying)
-		return;
+	// Load MIDI resource data
 
-	stop();
+	_parser->loadMusic(midiResource->getData(), midiResource->getSize());
+}
 
-	// Load MIDI resource data
+void MusicPlayer::pause() {
+	if (_parser)
+		_parser->pausePlaying();
+}
 
-	_isGM = true;
+void MusicPlayer::resume() {
+	if (_parser)
+		_parser->resumePlaying();
+}
 
-	MidiParser *parser = MidiParser::createParser_SMF();
-	if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) {
-		parser->setTrack(0);
-		parser->setMidiDriver(this);
-		parser->setTimerRate(_driver->getBaseTempo());
-		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+void MusicPlayer::stop() {
+	if (_parser)
+		_parser->stopPlaying();
+}
 
-		_parser = parser;
+bool MusicPlayer::isPlaying() {
+	return _parser ? _parser->isPlaying() : false;
+}
 
-		setVolume(127);
+void MusicPlayer::syncSoundSettings() {
+	if (_driver)
+		_driver->syncSoundSettings();
+}
 
-		_isLooping = flags & MUSIC_LOOP;
-		_isPlaying = true;
-	} else {
-		delete parser;
-	}
+void MusicPlayer::onTimer() {
+	if (_parser)
+		_parser->onTimer();
 }
 
-void MusicPlayer::pause() {
-	setVolume(-1);
-	_isPlaying = false;
+void MusicPlayer::timerCallback(void *data) {
+	((MusicPlayer *)data)->onTimer();
 }
 
-void MusicPlayer::resume() {
-	setVolume(127);
-	_isPlaying = true;
+MidiDriver_ADLIB_MADE::MidiDriver_ADLIB_MADE(OPL::Config::OplType oplType) : MidiDriver_ADLIB_Multisource(oplType) {
+	_modulationDepth = MODULATION_DEPTH_LOW;
+	_vibratoDepth = VIBRATO_DEPTH_LOW;
+	_defaultChannelVolume = 0x7F;
 }
 
 } // End of namespace Made
diff --git a/engines/made/music.h b/engines/made/music.h
index 4327b797e3..aeadce3128 100644
--- a/engines/made/music.h
+++ b/engines/made/music.h
@@ -25,33 +25,44 @@
 #ifndef MADE_MUSIC_H
 #define MADE_MUSIC_H
 
-#include "audio/midiplayer.h"
+#include "audio/adlib_ms.h"
+#include "audio/mididrv.h"
+#include "audio/mididrv_ms.h"
+#include "audio/midiparser.h"
 
 namespace Made {
 
 class GenericResource;
 
-enum MusicFlags {
-	MUSIC_NORMAL = 0,
-	MUSIC_LOOP = 1
-};
-
-class MusicPlayer : public Audio::MidiPlayer {
+class MusicPlayer {
 public:
 	MusicPlayer(bool milesAudio);
+	~MusicPlayer();
+
+	void playXMIDI(GenericResource *midiResource);
+	void playSMF(GenericResource *midiResource);
+	void stop();
+	void pause();
+	void resume();
+
+	bool isPlaying();
+	void syncSoundSettings();
 
-	void playXMIDI(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
-	void playSMF(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL);
-//	void stop();
-	void pause() override;
-	void resume() override;
+private:
+	MidiParser *_parser;
+	MidiDriver_Multisource *_driver;
 
-	// MidiDriver_BASE interface implementation
-	void send(uint32 b) override;
+	MusicType _driverType;
+
+	static void timerCallback(void *refCon);
+	void onTimer();
+};
+
+class MidiDriver_ADLIB_MADE : public MidiDriver_ADLIB_Multisource {
+public:
+	MidiDriver_ADLIB_MADE(OPL::Config::OplType oplType);
 
-protected:
-	bool _isGM;
-	bool _milesAudioMode;
+	// TODO Implement AdLib driver logic for Manhole / LGoP2
 };
 
 } // End of namespace Made


Commit: 0a702a6e3f1e06facc78a4134c2c056fd0512040
    https://github.com/scummvm/scummvm/commit/0a702a6e3f1e06facc78a4134c2c056fd0512040
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:45+02:00

Commit Message:
MADE: Pause MIDI music when pausing engine

The MIDI music on external softsynths and devices would keep playing while the
engine was paused. This commit fixes this by implementing the
Engine::pauseEngineIntern method to pause the MIDI music when the engine is
paused.

Changed paths:
    engines/made/made.cpp
    engines/made/made.h


diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 143bd959a4..10456bdfca 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -310,4 +310,16 @@ Common::Error MadeEngine::run() {
 	return Common::kNoError;
 }
 
+void MadeEngine::pauseEngineIntern(bool pause) {
+	Engine::pauseEngineIntern(pause);
+
+	if (pause) {
+		if (_music)
+			_music->pause();
+	} else {
+		if (_music)
+			_music->resume();
+	}
+}
+
 } // End of namespace Made
diff --git a/engines/made/made.h b/engines/made/made.h
index 5950812740..d061e7a1f6 100644
--- a/engines/made/made.h
+++ b/engines/made/made.h
@@ -107,6 +107,8 @@ public:
 
 	void handleEvents();
 
+protected:
+	void pauseEngineIntern(bool pause);
 };
 
 } // End of namespace Made


Commit: 30a6c8428cc3979f3fecd44c5a58ea3a8c0c34fe
    https://github.com/scummvm/scummvm/commit/30a6c8428cc3979f3fecd44c5a58ea3a8c0c34fe
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:45+02:00

Commit Message:
MADE: Fix audible gap when sounds loop

For looping sounds the game script regularly checks if the sound has finished
playing, then plays it again. This works in the original interpreter (possibly
because it checks the first buffer of double-buffered sound output); it does
not work in ScummVM because the mixer will return if the sound has actually
stopped playing. This causes an audible gap when the sound loops.

This commit alters the sfSoundPlaying function to check if the current elapsed
playing time is less than 100ms before the end of the sound, which fixes the
issue. Not sure if this change is necessary or desirable for games other than
Return to Zork. This fixes issue #6443.

Changed paths:
    engines/made/resource.h
    engines/made/scriptfuncs.cpp
    engines/made/scriptfuncs.h


diff --git a/engines/made/resource.h b/engines/made/resource.h
index 4ad54aec19..7df6357bf0 100644
--- a/engines/made/resource.h
+++ b/engines/made/resource.h
@@ -123,6 +123,7 @@ public:
 	virtual void load(byte *source, int size);
 	Audio::AudioStream *getAudioStream(int soundRate, bool loop = false);
 	SoundEnergyArray *getSoundEnergyArray() const { return _soundEnergyArray; }
+	int getSoundSize() const { return _soundSize; }
 protected:
 	byte *_soundData;
 	int _soundSize;
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index 9035ec0c6b..1ce00fd957 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -258,6 +258,11 @@ int16 ScriptFunctions::sfPlaySound(int16 argc, int16 *argv) {
 		_vm->_soundEnergyIndex = 0;
 		_soundStarted = true;
 		_soundResource = soundRes;
+		// The sound length in milliseconds for purpose of checking if the
+		// sound is still playing. This is 100 ms shorter than the actual
+		// length (see sfSoundPlaying).
+		uint32 soundLength = (_soundResource->getSoundSize() * 1000 / _vm->_soundRate);
+		_soundCheckLength = soundLength > 100 ? soundLength - 100 : 0;
 	}
 	return 0;
 }
@@ -614,10 +619,28 @@ int16 ScriptFunctions::sfSetSpriteMask(int16 argc, int16 *argv) {
 }
 
 int16 ScriptFunctions::sfSoundPlaying(int16 argc, int16 *argv) {
-	if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle))
-		return 1;
-	else
-		return 0;
+	if (_vm->getGameID() == GID_RTZ) {
+		if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle))
+			return 0;
+
+		// For looping sounds the game script regularly checks if the sound has
+		// finished playing, then plays it again. This works in the original
+		// interpreter (possibly because it checks the first buffer of double-
+		// buffered sound output); it does not work in ScummVM because the
+		// mixer will return if the sound has actually stopped playing. This
+		// causes an audible gap when the sound loops.
+		// For this reason this function checks against the sound check length,
+		// which is 100ms less than the actual sound length. Not sure if this
+		// is necessary or desirable for games other than Return to Zork.
+		int playedMsec = _vm->_mixer->getElapsedTime(_audioStreamHandle).msecs();
+		return playedMsec > _soundCheckLength ? 0 : 1;
+	} else {
+		if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle))
+			return 1;
+		else
+			return 0;
+	}
+
 }
 
 void ScriptFunctions::stopSound() {
diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h
index b47e67dfde..700ada3107 100644
--- a/engines/made/scriptfuncs.h
+++ b/engines/made/scriptfuncs.h
@@ -63,6 +63,9 @@ protected:
 	Audio::SoundHandle _voiceStreamHandle;
 	SoundResource* _soundResource;
 	bool _soundStarted;
+	// The sound length in milliseconds for purpose of checking if the sound is
+	// still playing.
+	int _soundCheckLength;
 	// The audio volume set by the game scripts.
 	uint8 _gameAudioVolume;
 


Commit: 8ec8f65d5f4f3e6eaf72cb92d5dffa3b27b3191e
    https://github.com/scummvm/scummvm/commit/8ec8f65d5f4f3e6eaf72cb92d5dffa3b27b3191e
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:45+02:00

Commit Message:
MADE: Improve unpausing game when movie is playing

The movie player would use OSystem::getMillis to check the elapsed playing time
to keep audio and video in sync. This would go wrong when the game was paused
during movie playback, as the player would try to make up for the pause time,
fast forwarding the movie and breaking A/V sync.
This commit improves this by using Engine::getTotalPlayTime, which subtracts
pause time, and Mixer::getElapsedTime, which returns the actual length of audio
played. The player seems to restart later than the audio when unpausing, so it
still catches up for about 10 frames, but it's not as bad as before and it does
not lose A/V sync.

Changed paths:
    engines/made/pmvplayer.cpp


diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
index 6ec5943601..8cc87a10a6 100644
--- a/engines/made/pmvplayer.cpp
+++ b/engines/made/pmvplayer.cpp
@@ -108,7 +108,7 @@ bool PmvPlayer::play(const char *filename) {
 	byte *frameData = 0, *audioData, *soundData, *palData, *imageData;
 	bool firstTime = true;
 
-	uint32 soundStartTime = 0, skipFrames = 0;
+	uint32 skipFrames = 0;
 
 	uint32 bytesRead;
 	uint16 width, height, cmdOffs, pixelOffs, maskOffs, lineSize;
@@ -122,7 +122,7 @@ bool PmvPlayer::play(const char *filename) {
 
 	while (!_vm->shouldQuit() && !_aborted && !_fd->eos() && frameNumber < frameCount) {
 
-		int32 frameTime = _vm->_system->getMillis();
+		int32 frameTime = _vm->getTotalPlayTime();
 
 		readChunk(chunkType, chunkSize);
 		if (chunkType != MKTAG('M','F','R','M')) {
@@ -190,7 +190,6 @@ bool PmvPlayer::play(const char *filename) {
 
 		if (firstTime) {
 			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_audioStreamHandle, _audioStream);
-			soundStartTime = g_system->getMillis();
 			skipFrames = 0;
 			firstTime = false;
 		}
@@ -199,8 +198,9 @@ bool PmvPlayer::play(const char *filename) {
 		updateScreen();
 
 		if (skipFrames == 0) {
+			uint32 soundElapsedTime = _vm->_mixer->getElapsedTime(_audioStreamHandle).msecs();
 			int32 waitTime = (frameNumber * frameDelay) -
-				(g_system->getMillis() - soundStartTime) - (_vm->_system->getMillis() - frameTime);
+				soundElapsedTime - (_vm->getTotalPlayTime() - frameTime);
 
 			if (waitTime < 0) {
 				skipFrames = -waitTime / frameDelay;


Commit: 245c4cc9239eeae17ab8ccadea84216c52127937
    https://github.com/scummvm/scummvm/commit/245c4cc9239eeae17ab8ccadea84216c52127937
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:45+02:00

Commit Message:
MADE: Display MT-32 quit message

This commit adds the message displayed on the MT-32 display when the game quits.

Changed paths:
    engines/made/made.cpp
    engines/made/music.cpp
    engines/made/music.h


diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 10456bdfca..741a16a5e6 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -248,7 +248,7 @@ void MadeEngine::handleEvents() {
 }
 
 Common::Error MadeEngine::run() {
-	_music = new MusicPlayer(getGameID() == GID_RTZ);
+	_music = new MusicPlayer(this, getGameID() == GID_RTZ);
 	syncSoundSettings();
 
 	// Initialize backend
@@ -307,6 +307,8 @@ Common::Error MadeEngine::run() {
 	_script->runScript(_dat->getMainCodeObjectIndex());
 #endif
 
+	_music->close();
+
 	return Common::kNoError;
 }
 
diff --git a/engines/made/music.cpp b/engines/made/music.cpp
index 488332aba0..166008a040 100644
--- a/engines/made/music.cpp
+++ b/engines/made/music.cpp
@@ -36,7 +36,9 @@
 
 namespace Made {
 
-MusicPlayer::MusicPlayer(bool milesAudio) : _parser(0) {
+const uint8 MusicPlayer::MT32_GOODBYE_MSG[] = { 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x54, 0x6F, 0x20, 0x5A, 0x6F, 0x72, 0x6B, 0x20, 0x53, 0x6F, 0x6F, 0x6E, 0x21 };
+
+MusicPlayer::MusicPlayer(MadeEngine *vm, bool milesAudio) : _vm(vm), _parser(0) {
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
 	_driverType = MidiDriver::getMusicType(dev);
 	if (_driverType == MT_GM && ConfMan.getBool("native_mt32"))
@@ -94,6 +96,18 @@ MusicPlayer::~MusicPlayer() {
 	}
 }
 
+void MusicPlayer::close() {
+	if (_parser)
+		_parser->stopPlaying();
+
+	if (_vm->getGameID() == GID_RTZ && _vm->getPlatform() == Common::kPlatformDOS && _driver) {
+		MidiDriver_MT32GM *mt32Driver = dynamic_cast<MidiDriver_MT32GM *>(_driver);
+		if (mt32Driver)
+			mt32Driver->sysExMT32(MT32_GOODBYE_MSG, MidiDriver_MT32GM::MT32_DISPLAY_NUM_CHARS,
+				MidiDriver_MT32GM::MT32_DISPLAY_MEMORY_ADDRESS, false, false);
+	}
+}
+
 void MusicPlayer::playXMIDI(GenericResource *midiResource) {
 	if (_parser) {
 		_parser->unloadMusic();
diff --git a/engines/made/music.h b/engines/made/music.h
index aeadce3128..7ab5dbd1e1 100644
--- a/engines/made/music.h
+++ b/engines/made/music.h
@@ -25,9 +25,12 @@
 #ifndef MADE_MUSIC_H
 #define MADE_MUSIC_H
 
+#include "made.h"
+
 #include "audio/adlib_ms.h"
 #include "audio/mididrv.h"
 #include "audio/mididrv_ms.h"
+#include "audio/mt32gm.h"
 #include "audio/midiparser.h"
 
 namespace Made {
@@ -35,10 +38,15 @@ namespace Made {
 class GenericResource;
 
 class MusicPlayer {
+private:
+	static const uint8 MT32_GOODBYE_MSG[MidiDriver_MT32GM::MT32_DISPLAY_NUM_CHARS];
+
 public:
-	MusicPlayer(bool milesAudio);
+	MusicPlayer(MadeEngine *vm, bool milesAudio);
 	~MusicPlayer();
 
+	void close();
+
 	void playXMIDI(GenericResource *midiResource);
 	void playSMF(GenericResource *midiResource);
 	void stop();
@@ -49,6 +57,7 @@ public:
 	void syncSoundSettings();
 
 private:
+	MadeEngine *_vm;
 	MidiParser *_parser;
 	MidiDriver_Multisource *_driver;
 


Commit: 5369ed6ecc3b63ff5e4a94b497f6b650e2f63ad1
    https://github.com/scummvm/scummvm/commit/5369ed6ecc3b63ff5e4a94b497f6b650e2f63ad1
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-10-09T16:59:45+02:00

Commit Message:
MADE: Add option for MIDI introduction music

The Return to Zork installer has an option to turn off the digital music during
the introduction and play MIDI music instead. ScummVM would always play the
digital music. This commit adds the installer option to the launcher GUI.

Changed paths:
    engines/made/detection.cpp
    engines/made/made.cpp
    engines/made/made.h
    engines/made/scriptfuncs.cpp


diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index 95fe8e011b..15b7db9929 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -25,6 +25,8 @@
 
 #include "made/detection.h"
 
+#include "common/config-manager.h"
+
 static const PlainGameDescriptor madeGames[] = {
 	{"manhole", "The Manhole"},
 	{"rtz", "Return to Zork"},
@@ -52,9 +54,29 @@ public:
 		return "MADE Engine (C) Activision";
 	}
 
+	const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const override;
+
 	ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist, ADDetectedGameExtraInfo **extra) const override;
 };
 
+static const ExtraGuiOption introMusicDigital = {
+	_s("Play a digital soundtrack during the opening movie"),
+	_s("If selected, the game will use a digital soundtrack during the introduction. Otherwise, it will play MIDI music."),
+	"intro_music_digital",
+	true
+};
+
+const ExtraGuiOptions MadeMetaEngineDetection::getExtraGuiOptions(const Common::String &target) const {
+	const Common::String gameid = ConfMan.get("gameid", target);
+	const Common::String extra = ConfMan.get("extra", target);
+
+	ExtraGuiOptions options;
+	if (target.empty() || (gameid == "rtz" && extra.contains("CD"))) {
+		options.push_back(introMusicDigital);
+	}
+	return options;
+}
+
 ADDetectedGame MadeMetaEngineDetection::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist, ADDetectedGameExtraInfo **extra) const {
 	// Set the default values for the fallback descriptor's ADGameDescription part.
 	Made::g_fallbackDesc.desc.language = Common::UNK_LANG;
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
index 741a16a5e6..e9af8225cf 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -50,6 +50,9 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
 	_soundEnergyArray = 0;
 	_musicBeatStart = 0;
 	_cdTimeStart = 0;
+	_introMusicDigital = true;
+	if (ConfMan.hasKey("intro_music_digital"))
+		_introMusicDigital = ConfMan.getBool("intro_music_digital");
 
 	_rnd = new Common::RandomSource("made");
 
diff --git a/engines/made/made.h b/engines/made/made.h
index d061e7a1f6..3d153fa5da 100644
--- a/engines/made/made.h
+++ b/engines/made/made.h
@@ -92,6 +92,7 @@ public:
 
 	uint32 _musicBeatStart;
 	uint32 _cdTimeStart;
+	bool _introMusicDigital;
 
 	int32 _timers[50];
 	int16 getTicks();
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index 1ce00fd957..3cde7fe2fe 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -1063,7 +1063,7 @@ int16 ScriptFunctions::sfIsSlowSystem(int16 argc, int16 *argv) {
 	// There are 2 versions of each video: one with sound, and one without
 	// An example is FINTRO00.PMV (with sound) and FINTRO01.PMV (without sound)
 	// One could maybe think about returning 1 here on actually slower systems.
-	return 0;
+	return _vm->_introMusicDigital ? 0 : 1;
 }
 
 } // End of namespace Made




More information about the Scummvm-git-logs mailing list