[Scummvm-git-logs] scummvm master -> acad76683d27d2d407c2ca8b8fcf6f4e43df763d
NMIError
noreply at scummvm.org
Wed Nov 17 21:09:30 UTC 2021
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
649cb7b450 GROOVIE: Set correct Miles version for 11th Hour
d042315d0b GROOVIE: Stop current song before playing new song
07f91ec50e GROOVIE: Use game volume for 11th Hour MIDI control
b70ab20fc8 AUDIO: MIDI controller defaults on track start
cb97a47828 GROOVIE: Add MIDI controller defaults for T7G and 11H
acad76683d GROOVIE: Fix 11th Hour scripts loading savegame 0
Commit: 649cb7b450615171fd54e85966c84ebec98a79ad
https://github.com/scummvm/scummvm/commit/649cb7b450615171fd54e85966c84ebec98a79ad
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-11-17T21:53:43+01:00
Commit Message:
GROOVIE: Set correct Miles version for 11th Hour
This changes the Miles version for The 11th Hour to version 3. This sets the
pitch bend range to the correct 2 semitones.
Changed paths:
engines/groovie/music.cpp
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 9b1bbf59a4..e311cf5dda 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -461,12 +461,15 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName)
// Create the parser
_midiParser = MidiParser::createParser_XMIDI(nullptr, nullptr, 0);
+ _multisourceDriver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
+ _multisourceDriver->property(MidiDriver::PROP_MILES_VERSION,
+ _vm->getEngineVersion() == kGroovieT7G ? Audio::MILES_VERSION_2 : Audio::MILES_VERSION_3);
+
int result = _driver->open();
if (result > 0 && result != MidiDriver::MERR_ALREADY_OPEN)
error("Opening MidiDriver failed with error code %i", result);
_multisourceDriver->setSourceNeutralVolume(0, 100);
- _multisourceDriver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
// Set the parser's driver
_midiParser->setMidiDriver(this);
Commit: d042315d0b5d47b668aeaa89e74e39d14280fa0a
https://github.com/scummvm/scummvm/commit/d042315d0b5d47b668aeaa89e74e39d14280fa0a
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-11-17T21:53:44+01:00
Commit Message:
GROOVIE: Stop current song before playing new song
When playing a new song, ScummVM would update the volume to the standard value
before stopping playback of the current song. This would cause a volume change
right before stopping a song. This commit stops the current song before setting
the volume, which removes the unnecessary volume change.
Changed paths:
engines/groovie/music.cpp
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index e311cf5dda..f80f795a2a 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -58,6 +58,9 @@ MusicPlayer::~MusicPlayer() {
void MusicPlayer::playSong(uint32 fileref) {
Common::StackLock lock(_mutex);
+ if (_isPlaying)
+ unload();
+
// Set the volumes
_fadingEndVolume = 100;
_gameVolume = 100;
Commit: 07f91ec50e549cbb1ae901f810505a86de79f73b
https://github.com/scummvm/scummvm/commit/07f91ec50e549cbb1ae901f810505a86de79f73b
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-11-17T21:53:44+01:00
Commit Message:
GROOVIE: Use game volume for 11th Hour MIDI control
This prevents the 11th Hour MIDI control function from setting the user volume.
This volume setting is set by the user in the game config and the game should
not override this. For the playSong operation the volume setting is removed,
because playSong already sets the game volume. For case 3 the commented volume
setting has been replaced by an equivalent game volume call.
I've been unable to trigger either operation by playing through the first part
of the game, so these operations might not be used at all.
Changed paths:
engines/groovie/script.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index aac56ea63e..626c05beda 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1987,17 +1987,14 @@ void Script::o2_midicontrol() {
// Play song from index
debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Play song %d", arg1, arg2);
_vm->_musicPlayer->playSong(arg2);
- _vm->_musicPlayer->setUserVolume(100);
break;
case 3:
// TODO: Set Volume? Or is it some kind of fade in / out
debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Set volume/time: %d", arg1, arg2);
- //_vm->_musicPlayer->setUserVolume(arg2);
+ //_vm->_musicPlayer->setGameVolume(arg2, 0);
break;
}
-
- //_vm->_musicPlayer->setGameVolume(arg1, arg2);
}
void Script::o2_setbackgroundsong() {
uint32 fileref = readScript32bits();
Commit: b70ab20fc89fd3bf33fd68626c44155758c39dfc
https://github.com/scummvm/scummvm/commit/b70ab20fc89fd3bf33fd68626c44155758c39dfc
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-11-17T21:54:59+01:00
Commit Message:
AUDIO: MIDI controller defaults on track start
This commit adds a feature to the multisource MIDI drivers which allows setting
a default value for most controllers. This default is then applied at the start
of every new track, which ensures controllers are in the correct state.
This can be used for games which use some controller, but do not reset it at
the start of each track, which can lead to incorrect playback.
Changed paths:
audio/adlib_ms.cpp
audio/adlib_ms.h
audio/mididrv.h
audio/mididrv_ms.cpp
audio/mididrv_ms.h
audio/miles_adlib.cpp
audio/miles_midi.cpp
audio/mt32gm.cpp
audio/mt32gm.h
diff --git a/audio/adlib_ms.cpp b/audio/adlib_ms.cpp
index 6caa62b540..8d05282942 100644
--- a/audio/adlib_ms.cpp
+++ b/audio/adlib_ms.cpp
@@ -427,6 +427,7 @@ int MidiDriver_ADLIB_Multisource::open() {
for (int j = 0; j < MIDI_CHANNEL_COUNT; j++) {
_controlData[i][j].volume = _defaultChannelVolume;
}
+ applyControllerDefaults(i);
}
// Set default OPL register values.
@@ -771,6 +772,51 @@ void MidiDriver_ADLIB_Multisource::deinitSource(uint8 source) {
}
_allocationMutex.unlock();
+
+ applyControllerDefaults(source);
+}
+
+void MidiDriver_ADLIB_Multisource::applyControllerDefaults(uint8 source) {
+ if (source == 0xFF) {
+ // Apply controller defaults for all sources.
+ for (int i = 0; i < MAXIMUM_SOURCES; i++) {
+ applyControllerDefaults(i);
+ }
+ } else {
+ for (int i = 0; i < MIDI_CHANNEL_COUNT; i++) {
+ if (_controllerDefaults.program >= 0) {
+ _controlData[source][i].program = _controllerDefaults.program;
+ }
+ if (_controllerDefaults.channelPressure >= 0) {
+ _controlData[source][i].channelPressure = _controllerDefaults.channelPressure;
+ }
+ if (_controllerDefaults.pitchBend >= 0) {
+ _controlData[source][i].pitchBend = _controllerDefaults.pitchBend;
+ }
+ if (_controllerDefaults.modulation >= 0) {
+ _controlData[source][i].modulation = _controllerDefaults.modulation;
+ }
+ if (_controllerDefaults.volume >= 0) {
+ _controlData[source][i].volume = _controllerDefaults.volume;
+ }
+ if (_controllerDefaults.panning >= 0) {
+ _controlData[source][i].panning = _controllerDefaults.panning;
+ }
+ if (_controllerDefaults.expression >= 0) {
+ _controlData[source][i].expression = _controllerDefaults.expression;
+ }
+ if (_controllerDefaults.rpn >= 0) {
+ _controlData[source][i].rpn = _controllerDefaults.rpn;
+ }
+ if (_controllerDefaults.pitchBendSensitivity >= 0) {
+ _controlData[source][i].pitchBendSensitivity = _controllerDefaults.pitchBendSensitivity;
+ _controlData[source][i].pitchBendSensitivityCents = 0;
+ }
+ // Controller defaults not supported by this driver:
+ // instrument bank, drumkit.
+ // Sustain is turned of by deinitSource.
+ }
+ }
}
void MidiDriver_ADLIB_Multisource::modulation(uint8 channel, uint8 modulation, uint8 source) {
diff --git a/audio/adlib_ms.h b/audio/adlib_ms.h
index 539c616f02..bd50630ffd 100644
--- a/audio/adlib_ms.h
+++ b/audio/adlib_ms.h
@@ -560,6 +560,7 @@ public:
*/
MidiChannel *getPercussionChannel() override;
+ using MidiDriver_Multisource::send;
void send(int8 source, uint32 b) override;
void sysEx(const byte *msg, uint16 length) override;
void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
@@ -756,6 +757,17 @@ protected:
*/
virtual void allNotesOff(uint8 channel, uint8 source);
+ /**
+ * Applies the controller default settings to the controller data for the
+ * specified source.
+ * This will set all supported default values specified on _controllerDefaults
+ * except sustain, which is set by deinitSource.
+ *
+ * @param source The source triggering the default settings, or 0xFF to
+ * apply controller defaults for all sources.
+ */
+ virtual void applyControllerDefaults(uint8 source);
+
/**
* Recalculates and writes the frequencies of the active notes on the
* specified MIDI channel and source.
diff --git a/audio/mididrv.h b/audio/mididrv.h
index 8f9eb2ea90..1b7e0d62ca 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -146,6 +146,7 @@ public:
static const uint16 MIDI_MASTER_TUNING_FINE_DEFAULT = 0x2000;
static const uint8 MIDI_MASTER_TUNING_COARSE_DEFAULT = 0x40;
+ static const uint8 MT32_PITCH_BEND_SENSITIVITY_DEFAULT = 0x0C;
static const uint8 GM_PITCH_BEND_SENSITIVITY_DEFAULT = 0x02;
static const uint8 GS_RHYTHM_FIRST_NOTE = 0x1B;
diff --git a/audio/mididrv_ms.cpp b/audio/mididrv_ms.cpp
index dc1d5e7b68..3a8a34a994 100644
--- a/audio/mididrv_ms.cpp
+++ b/audio/mididrv_ms.cpp
@@ -37,6 +37,21 @@ MidiDriver_Multisource::MidiSource::MidiSource() :
fadePassedTime(0),
fadeDuration(0) { }
+MidiDriver_Multisource::ControllerDefaults::ControllerDefaults() :
+ // The -1 value indicates no default value should be set on the controller.
+ program(-1),
+ instrumentBank(-1),
+ drumkit(-1),
+ channelPressure(-1),
+ pitchBend(-1),
+ modulation(-1),
+ volume(-1),
+ panning(-1),
+ expression(-1),
+ sustain(-1),
+ rpn(-1),
+ pitchBendSensitivity(-1) { }
+
MidiDriver_Multisource::MidiDriver_Multisource() :
_userVolumeScaling(false),
_userMusicVolume(192),
@@ -185,6 +200,90 @@ void MidiDriver_Multisource::updateFading() {
_fadeDelay = FADING_DELAY;
}
+void MidiDriver_Multisource::setControllerDefault(ControllerDefaultType type) {
+ // Call the overload with the General MIDI default for the controller.
+ switch (type) {
+ case CONTROLLER_DEFAULT_PITCH_BEND:
+ setControllerDefault(type, MIDI_PITCH_BEND_DEFAULT);
+ break;
+ case CONTROLLER_DEFAULT_VOLUME:
+ setControllerDefault(type, 100);
+ break;
+ case CONTROLLER_DEFAULT_PANNING:
+ setControllerDefault(type, MIDI_PANNING_DEFAULT);
+ break;
+ case CONTROLLER_DEFAULT_EXPRESSION:
+ setControllerDefault(type, MIDI_EXPRESSION_DEFAULT);
+ break;
+ case CONTROLLER_DEFAULT_RPN:
+ setControllerDefault(type, MIDI_RPN_NULL);
+ break;
+ case CONTROLLER_DEFAULT_PITCH_BEND_SENSITIVITY:
+ setControllerDefault(type, GM_PITCH_BEND_SENSITIVITY_DEFAULT);
+ break;
+ case CONTROLLER_DEFAULT_PROGRAM:
+ case CONTROLLER_DEFAULT_INSTRUMENT_BANK:
+ case CONTROLLER_DEFAULT_DRUMKIT:
+ case CONTROLLER_DEFAULT_CHANNEL_PRESSURE:
+ case CONTROLLER_DEFAULT_MODULATION:
+ case CONTROLLER_DEFAULT_SUSTAIN:
+ default:
+ setControllerDefault(type, 0);
+ break;
+ }
+}
+
+void MidiDriver_Multisource::setControllerDefault(ControllerDefaultType type, int16 value) {
+ // Set the specified default value on _controllerDefaults on the field
+ // corresponding to the specified controller.
+ switch (type) {
+ case CONTROLLER_DEFAULT_PROGRAM:
+ _controllerDefaults.program = value;
+ break;
+ case CONTROLLER_DEFAULT_INSTRUMENT_BANK:
+ _controllerDefaults.instrumentBank = value;
+ break;
+ case CONTROLLER_DEFAULT_DRUMKIT:
+ _controllerDefaults.drumkit = value;
+ break;
+ case CONTROLLER_DEFAULT_CHANNEL_PRESSURE:
+ _controllerDefaults.channelPressure = value;
+ break;
+ case CONTROLLER_DEFAULT_PITCH_BEND:
+ _controllerDefaults.pitchBend = value;
+ break;
+ case CONTROLLER_DEFAULT_MODULATION:
+ _controllerDefaults.modulation = value;
+ break;
+ case CONTROLLER_DEFAULT_VOLUME:
+ _controllerDefaults.volume = value;
+ break;
+ case CONTROLLER_DEFAULT_PANNING:
+ _controllerDefaults.panning = value;
+ break;
+ case CONTROLLER_DEFAULT_EXPRESSION:
+ _controllerDefaults.expression = value;
+ break;
+ case CONTROLLER_DEFAULT_SUSTAIN:
+ _controllerDefaults.sustain = value;
+ break;
+ case CONTROLLER_DEFAULT_RPN:
+ _controllerDefaults.rpn = value;
+ break;
+ case CONTROLLER_DEFAULT_PITCH_BEND_SENSITIVITY:
+ _controllerDefaults.pitchBendSensitivity = value;
+ break;
+ default:
+ warning("MidiDriver_Multisource::setControllerDefault - Unknown controller default type %i", type);
+ break;
+ }
+}
+
+void MidiDriver_Multisource::clearControllerDefault(ControllerDefaultType type) {
+ // Reset the default value for this controller to -1.
+ setControllerDefault(type, -1);
+}
+
void MidiDriver_Multisource::deinitSource(uint8 source) {
abortFade(source, FADE_ABORT_TYPE_END_VOLUME);
diff --git a/audio/mididrv_ms.h b/audio/mididrv_ms.h
index bd20ca4aad..5fc96719e8 100644
--- a/audio/mididrv_ms.h
+++ b/audio/mididrv_ms.h
@@ -141,6 +141,25 @@ public:
FADE_ABORT_TYPE_START_VOLUME
};
+ /**
+ * The controllers and parameters for which a default value can be set
+ * using setControllerDefault.
+ */
+ enum ControllerDefaultType {
+ CONTROLLER_DEFAULT_PROGRAM,
+ CONTROLLER_DEFAULT_INSTRUMENT_BANK,
+ CONTROLLER_DEFAULT_DRUMKIT,
+ CONTROLLER_DEFAULT_CHANNEL_PRESSURE,
+ CONTROLLER_DEFAULT_PITCH_BEND,
+ CONTROLLER_DEFAULT_MODULATION,
+ CONTROLLER_DEFAULT_VOLUME,
+ CONTROLLER_DEFAULT_PANNING,
+ CONTROLLER_DEFAULT_EXPRESSION,
+ CONTROLLER_DEFAULT_SUSTAIN,
+ CONTROLLER_DEFAULT_RPN,
+ CONTROLLER_DEFAULT_PITCH_BEND_SENSITIVITY
+ };
+
protected:
// This stores data about a specific source of MIDI data.
struct MidiSource {
@@ -168,6 +187,28 @@ protected:
MidiSource();
};
+ // Stores the default values that should be set for each controller.
+ // -1 means no explicit default should be set for that controller.
+ struct ControllerDefaults {
+ int8 program;
+ int8 instrumentBank;
+ int8 drumkit;
+
+ int8 channelPressure;
+ int16 pitchBend;
+
+ int8 modulation;
+ int8 volume;
+ int8 panning;
+ int8 expression;
+ int8 sustain;
+ int16 rpn;
+
+ int8 pitchBendSensitivity;
+
+ ControllerDefaults();
+ };
+
public:
MidiDriver_Multisource();
@@ -288,6 +329,38 @@ public:
*/
bool isFading(uint8 source);
+ /**
+ * Specify a controller which should be reset to its General MIDI default
+ * value when a new track is started. See the overload for more details.
+ *
+ * @param type The controller which should be reset.
+ */
+ void setControllerDefault(ControllerDefaultType type);
+ /**
+ * Specify a default value for a controller which should be set when a new
+ * track is started. Use this if a game uses a MIDI controller, but does
+ * not consistently set it to a value at the start of every track, causing
+ * incorrect playback. Do not use this if a game depends on controller
+ * values carrying over to the next track for correct playback.
+ *
+ * This functionality will not work if the fallback MIDI source -1 is used.
+ * It is also necessary to call deinitSource whenever playback of a track
+ * is stopped, as this sets up the contoller reset.
+ *
+ * Use the setControllerDefault(ControllerDefaultType) overload if the
+ * General MIDI default value for the controller should be used.
+ *
+ * @param type The controller which should be reset.
+ * @param value The default value which should be set.
+ */
+ void setControllerDefault(ControllerDefaultType type, int16 value);
+ /**
+ * Clears a previously set default value for the specified controller.
+ *
+ * @param type The controller for which the default value should be cleared.
+ */
+ void clearControllerDefault(ControllerDefaultType type);
+
/**
* Applies the user volume settings to the MIDI driver. MIDI channel
* volumes will be scaled using the user volume.
@@ -348,6 +421,9 @@ protected:
// MIDI source data
MidiSource _sources[MAXIMUM_SOURCES];
+ // Default values for each controller
+ ControllerDefaults _controllerDefaults;
+
// True if the driver should scale MIDI channel volume to the user
// specified volume settings.
bool _userVolumeScaling;
diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp
index 2409350a12..a6cfdcfc1d 100644
--- a/audio/miles_adlib.cpp
+++ b/audio/miles_adlib.cpp
@@ -167,6 +167,7 @@ private:
struct MidiChannelEntry {
byte currentPatchBank;
const InstrumentEntry *currentInstrumentPtr;
+ byte currentProgram;
uint16 currentPitchBender;
byte currentPitchRange;
byte currentVoiceProtection;
@@ -183,6 +184,7 @@ private:
MidiChannelEntry() : currentPatchBank(0),
currentInstrumentPtr(nullptr),
+ currentProgram(0),
currentPitchBender(MIDI_PITCH_BEND_DEFAULT),
currentPitchRange(0),
currentVoiceProtection(0),
@@ -285,6 +287,8 @@ private:
const InstrumentEntry *searchInstrument(byte bankId, byte patchId);
void pitchBendChange(byte MIDIchannel, byte parameter1, byte parameter2);
+
+ void applyControllerDefaults(uint8 source);
};
MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount)
@@ -346,6 +350,7 @@ int MidiDriver_Miles_AdLib::open() {
_isOpen = true;
resetData();
+ applyControllerDefaults(0xFF);
_timerRate = getBaseTempo();
_opl->start(new Common::Functor0Mem<void, MidiDriver_Miles_AdLib>(this, &MidiDriver_Miles_AdLib::onTimer));
@@ -1155,6 +1160,7 @@ void MidiDriver_Miles_AdLib::programChange(byte midiChannel, byte patchId) {
// and remember it in that case for the current MIDI-channel
_midiChannels[midiChannel].currentInstrumentPtr = instrumentPtr;
+ _midiChannels[midiChannel].currentProgram = patchId;
}
const InstrumentEntry *MidiDriver_Miles_AdLib::searchInstrument(byte bankId, byte patchId) {
@@ -1206,6 +1212,40 @@ void MidiDriver_Miles_AdLib::deinitSource(uint8 source) {
// Stop fades and turn off non-sustained notes.
MidiDriver_Multisource::deinitSource(source);
+
+ applyControllerDefaults(source);
+}
+
+void MidiDriver_Miles_AdLib::applyControllerDefaults(uint8 source) {
+ if (!(source == 0 || source == 0xFF))
+ return;
+
+ for (int i = 0; i < MIDI_CHANNEL_COUNT; i++) {
+ if (_controllerDefaults.program >= 0) {
+ _midiChannels[i].currentProgram = _controllerDefaults.program;
+ }
+ if (_controllerDefaults.pitchBend >= 0) {
+ _midiChannels[i].currentPitchBender = _controllerDefaults.pitchBend;
+ }
+ if (_controllerDefaults.modulation >= 0) {
+ _midiChannels[i].currentModulation = _controllerDefaults.modulation;
+ }
+ if (_controllerDefaults.volume >= 0) {
+ _midiChannels[i].currentVolume = _controllerDefaults.volume;
+ }
+ if (_controllerDefaults.panning >= 0) {
+ _midiChannels[i].currentPanning = _controllerDefaults.panning;
+ }
+ if (_controllerDefaults.expression >= 0) {
+ _midiChannels[i].currentVolumeExpression = _controllerDefaults.expression;
+ }
+ if (_controllerDefaults.pitchBendSensitivity >= 0) {
+ _midiChannels[i].currentPitchRange = _controllerDefaults.pitchBendSensitivity;
+ }
+ // Controller defaults not supported by this driver:
+ // instrument bank, drumkit, channel pressure, RPN.
+ // Sustain is turned of by deinitSource.
+ }
}
void MidiDriver_Miles_AdLib::setRegister(int reg, int value) {
diff --git a/audio/miles_midi.cpp b/audio/miles_midi.cpp
index 1c8340cd13..04ed31bc77 100644
--- a/audio/miles_midi.cpp
+++ b/audio/miles_midi.cpp
@@ -177,6 +177,8 @@ void MidiDriver_Miles_Midi::send(int8 source, uint32 b) {
byte command = b & 0xf0;
byte dataChannel = b & 0xf;
+ byte op1 = (b >> 8) & 0xff;
+ byte op2 = (b >> 16) & 0xff;
byte outputChannel = source < 0 ? dataChannel : _channelMap[source][dataChannel];
MidiChannelEntry &outputChannelEntry = _midiChannels[outputChannel];
@@ -189,7 +191,17 @@ void MidiDriver_Miles_Midi::send(int8 source, uint32 b) {
MilesMidiChannelControlData &controlData = channelLockedByOtherSource ?
*outputChannelEntry.unlockData : *outputChannelEntry.currentData;
- processEvent(source, b, outputChannel, controlData, channelLockedByOtherSource);
+ if (command == MIDI_COMMAND_CONTROL_CHANGE && op1 == MILES_CONTROLLER_LOCK_CHANNEL) {
+ // The lock channel controller will allocate an output channel to use
+ // to send the events on this data channel. In this case, the data
+ // channel should not be assigned to the source, because it will not
+ // actually be used to send MIDI events. processEvent will assign the
+ // data channel to the source, so it is bypassed and controlChange is
+ // called directly.
+ controlChange(outputChannel, op1, op2, source, controlData, channelLockedByOtherSource);
+ } else {
+ processEvent(source, b, outputChannel, controlData, channelLockedByOtherSource);
+ }
if (command == MIDI_COMMAND_NOTE_OFF || command == MIDI_COMMAND_NOTE_ON || command == MIDI_COMMAND_PITCH_BEND ||
command == MIDI_COMMAND_POLYPHONIC_AFTERTOUCH || command == MIDI_COMMAND_CHANNEL_AFTERTOUCH) {
@@ -414,6 +426,10 @@ void MidiDriver_Miles_Midi::lockChannel(uint8 source, uint8 dataChannel) {
// Could not find a channel to lock
return;
+ // stopNotesOnChannel will turn off sustain, so record the current sustain
+ // value so it can be set on the unlock data.
+ bool currentSustain = _midiChannels[lockChannel].currentData->sustain;
+
stopNotesOnChannel(lockChannel);
_midiChannels[lockChannel].locked = true;
@@ -421,15 +437,14 @@ void MidiDriver_Miles_Midi::lockChannel(uint8 source, uint8 dataChannel) {
_channelMap[source][dataChannel] = lockChannel;
// Copy current controller values so they can be restored when unlocking the channel
*_midiChannels[lockChannel].unlockData = *_midiChannels[lockChannel].currentData;
+ _midiChannels[lockChannel].unlockData->sustain = currentSustain;
_midiChannels[lockChannel].currentData->source = source;
+ // Set any specified default controller values on the channel
+ applyControllerDefaults(source, *_midiChannels[lockChannel].currentData, lockChannel, false);
+
// Send volume change to apply the new source volume
controlChange(lockChannel, MIDI_CONTROLLER_VOLUME, 0x7F, source, *_midiChannels[lockChannel].currentData);
-
- // Note that other controller values might be "inherited" from the source
- // which was previously playing on the locked MIDI channel. The KYRA engine
- // does not seem to take any precautions against this.
- // Controllers could be set to default values here.
}
int8 MidiDriver_Miles_Midi::findLockChannel(bool useProtectedChannels) {
@@ -901,8 +916,6 @@ void MidiDriver_Miles_Midi::deinitSource(uint8 source) {
_midiChannels[i].lockProtected = false;
_midiChannels[i].protectedSource = -1;
}
- if (_midiChannels[i].currentData->source == source)
- _midiChannels[i].currentData->source = -1;
if (_midiChannels[i].unlockData->source == source)
_midiChannels[i].unlockData->source = -1;
}
diff --git a/audio/mt32gm.cpp b/audio/mt32gm.cpp
index 4f03197009..11ee737c11 100644
--- a/audio/mt32gm.cpp
+++ b/audio/mt32gm.cpp
@@ -197,6 +197,8 @@ void MidiDriver_MT32GM::initControlData() {
_controlData[i] = new MidiChannelControlData();
_controlData[i]->volume = _controlData[i]->scaledVolume =
(_nativeMT32 ? MT32_DEFAULT_CHANNEL_VOLUME : GM_DEFAULT_CHANNEL_VOLUME);
+ _controlData[i]->pitchBendSensitivity =
+ (_nativeMT32 ? MT32_PITCH_BEND_SENSITIVITY_DEFAULT : GM_PITCH_BEND_SENSITIVITY_DEFAULT);
if (_nativeMT32 && i >= 1 && i <= 8) {
_controlData[i]->program = MT32_DEFAULT_INSTRUMENTS[i - 1];
_controlData[i]->panPosition = MT32_DEFAULT_PANNING[i - 1];
@@ -417,6 +419,11 @@ void MidiDriver_MT32GM::processEvent(int8 source, uint32 b, uint8 outputChannel,
// A new source has sent an event on this channel.
controlData.sourceVolumeApplied = false;
controlData.source = source;
+
+ if (source >= 0)
+ // If the new source is a real MIDI source, apply controller
+ // default values.
+ applyControllerDefaults(source, controlData, outputChannel, channelLockedByOtherSource);
}
switch (command) {
@@ -426,12 +433,13 @@ void MidiDriver_MT32GM::processEvent(int8 source, uint32 b, uint8 outputChannel,
noteOnOff(outputChannel, command, op1, op2, source, controlData);
break;
case MIDI_COMMAND_PITCH_BEND:
- controlData.pitchWheel = ((uint16)op2 << 7) | (uint16)op1;
- // fall through
+ pitchBend(outputChannel, op1, op2, source, controlData, channelLockedByOtherSource);
+ break;
case MIDI_COMMAND_POLYPHONIC_AFTERTOUCH: // Not supported by MT-32 or GM
+ polyAftertouch(outputChannel, op1, op2, source, controlData, channelLockedByOtherSource);
+ break;
case MIDI_COMMAND_CHANNEL_AFTERTOUCH: // Not supported by MT-32
- if (!channelLockedByOtherSource)
- _driver->send(command | outputChannel, op1, op2);
+ channelAftertouch(outputChannel, op1, source, controlData, channelLockedByOtherSource);
break;
case MIDI_COMMAND_CONTROL_CHANGE:
controlChange(outputChannel, op1, op2, source, controlData, channelLockedByOtherSource);
@@ -449,6 +457,67 @@ void MidiDriver_MT32GM::processEvent(int8 source, uint32 b, uint8 outputChannel,
}
}
+void MidiDriver_MT32GM::applyControllerDefaults(uint8 source, MidiChannelControlData &controlData, uint8 outputChannel, bool channelLockedByOtherSource) {
+ if (outputChannel != MIDI_RHYTHM_CHANNEL) {
+ // Apply default bank and program only to melodic channels.
+ if (_controllerDefaults.instrumentBank >= 0 && controlData.instrumentBank != _controllerDefaults.instrumentBank) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_BANK_SELECT_MSB, _controllerDefaults.instrumentBank);
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_BANK_SELECT_LSB, 0);
+ }
+ if (_controllerDefaults.program >= 0 && controlData.program != _controllerDefaults.program) {
+ send(source, MIDI_COMMAND_PROGRAM_CHANGE | outputChannel, _controllerDefaults.program, 0);
+ }
+ } else {
+ // Apply default drumkit only to the rhythm channel.
+ if (_controllerDefaults.drumkit >= 0 && controlData.program != _controllerDefaults.drumkit) {
+ send(source, MIDI_COMMAND_PROGRAM_CHANGE | outputChannel, _controllerDefaults.drumkit, 0);
+ }
+ }
+ if (_controllerDefaults.channelPressure >= 0 && controlData.channelPressure != _controllerDefaults.channelPressure) {
+ send(source, MIDI_COMMAND_CHANNEL_AFTERTOUCH | outputChannel, _controllerDefaults.channelPressure, 0);
+ }
+ if (_controllerDefaults.pitchBend >= 0 && controlData.pitchWheel != _controllerDefaults.pitchBend) {
+ send(source, MIDI_COMMAND_PITCH_BEND | outputChannel, _controllerDefaults.pitchBend & 0x7F, _controllerDefaults.pitchBend >> 7);
+ }
+
+ if (_controllerDefaults.modulation >= 0 && controlData.modulation != _controllerDefaults.modulation) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_MODULATION, _controllerDefaults.modulation);
+ }
+ if (_controllerDefaults.volume >= 0 && controlData.volume != _controllerDefaults.volume) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_VOLUME, _controllerDefaults.volume);
+ }
+ if (_controllerDefaults.panning >= 0 && controlData.panPosition != _controllerDefaults.panning) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_PANNING, _controllerDefaults.panning);
+ }
+ if (_controllerDefaults.expression >= 0 && controlData.expression != _controllerDefaults.expression) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_EXPRESSION, _controllerDefaults.expression);
+ }
+
+ // RPN will be changed by setting pitch bend sensitivity, so store the
+ // current value.
+ uint16 rpn = controlData.rpn;
+ bool setRpn = false;
+ if (_controllerDefaults.pitchBendSensitivity >= 0 && controlData.pitchBendSensitivity != _controllerDefaults.pitchBendSensitivity) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_RPN_MSB, MIDI_RPN_PITCH_BEND_SENSITIVITY >> 8);
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_RPN_LSB, MIDI_RPN_PITCH_BEND_SENSITIVITY & 0xFF);
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_DATA_ENTRY_MSB, _controllerDefaults.pitchBendSensitivity);
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_DATA_ENTRY_LSB, 0);
+ if (rpn != controlData.rpn)
+ // Active RPN was changed; reset it to previous value (or default).
+ setRpn = true;
+ }
+ if (_controllerDefaults.rpn >= 0 && rpn != _controllerDefaults.rpn) {
+ // Set RPN to the specified default value.
+ rpn = _controllerDefaults.rpn;
+ setRpn = true;
+ }
+
+ if (setRpn) {
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_RPN_MSB, rpn >> 8);
+ send(source, MIDI_COMMAND_CONTROL_CHANGE | outputChannel, MIDI_CONTROLLER_RPN_LSB, rpn & 0xFF);
+ }
+}
+
void MidiDriver_MT32GM::noteOnOff(byte outputChannel, byte command, byte note, byte velocity, int8 source, MidiChannelControlData &controlData) {
if (!isOutputChannelUsed(outputChannel))
return;
@@ -470,6 +539,12 @@ void MidiDriver_MT32GM::noteOnOff(byte outputChannel, byte command, byte note, b
_driver->send(command | outputChannel, note, velocity);
}
+void MidiDriver_MT32GM::polyAftertouch(byte outputChannel, byte note, byte pressure,
+ int8 source, MidiChannelControlData &controlData, bool channelLockedByOtherSource) {
+ if (!channelLockedByOtherSource)
+ _driver->send(MIDI_COMMAND_CHANNEL_AFTERTOUCH | outputChannel, note, pressure);
+}
+
void MidiDriver_MT32GM::controlChange(byte outputChannel, byte controllerNumber, byte controllerValue, int8 source, MidiChannelControlData &controlData, bool channelLockedByOtherSource) {
assert(source < MAXIMUM_SOURCES);
@@ -482,6 +557,10 @@ void MidiDriver_MT32GM::controlChange(byte outputChannel, byte controllerNumber,
case MIDI_CONTROLLER_MODULATION:
controlData.modulation = controllerValue;
break;
+ case MIDI_CONTROLLER_DATA_ENTRY_MSB:
+ if (controlData.rpn == MIDI_RPN_PITCH_BEND_SENSITIVITY)
+ controlData.pitchBendSensitivity = controllerValue;
+ break;
case MIDI_CONTROLLER_VOLUME:
controlData.volume = controllerValue;
controlData.sourceVolumeApplied = true;
@@ -528,14 +607,24 @@ void MidiDriver_MT32GM::controlChange(byte outputChannel, byte controllerNumber,
removeActiveNotes(outputChannel, true);
}
break;
+ case MIDI_CONTROLLER_RPN_LSB:
+ controlData.rpn &= 0xFF00;
+ controlData.rpn |= controllerValue;
+ break;
+ case MIDI_CONTROLLER_RPN_MSB:
+ controlData.rpn &= 0x00FF;
+ controlData.rpn |= controllerValue << 8;
+ break;
case MIDI_CONTROLLER_RESET_ALL_CONTROLLERS:
+ controlData.channelPressure = 0;
controlData.pitchWheel = MIDI_PITCH_BEND_DEFAULT;
controlData.modulation = 0;
- controlData.expression = 0x7F;
+ controlData.expression = MIDI_EXPRESSION_DEFAULT;
controlData.sustain = false;
if (!channelLockedByOtherSource) {
removeActiveNotes(outputChannel, true);
}
+ controlData.rpn = MIDI_RPN_NULL;
break;
case MIDI_CONTROLLER_OMNI_ON:
case MIDI_CONTROLLER_OMNI_OFF:
@@ -750,6 +839,22 @@ byte MidiDriver_MT32GM::correctInstrumentBank(byte instrumentBank, byte patchId)
return instrumentBank != correctedBank ? correctedBank : 0xFF;
}
+void MidiDriver_MT32GM::channelAftertouch(byte outputChannel, byte pressure, int8 source,
+ MidiChannelControlData &controlData, bool channelLockedByOtherSource) {
+ controlData.channelPressure = pressure;
+
+ if (!channelLockedByOtherSource)
+ _driver->send(MIDI_COMMAND_CHANNEL_AFTERTOUCH | outputChannel, pressure, 0);
+}
+
+void MidiDriver_MT32GM::pitchBend(byte outputChannel, uint8 pitchBendLsb, uint8 pitchBendMsb,
+ int8 source, MidiChannelControlData &controlData, bool channelLockedByOtherSource) {
+ controlData.pitchWheel = ((uint16)pitchBendMsb << 7) | (uint16)pitchBendLsb;
+
+ if (!channelLockedByOtherSource)
+ _driver->send(MIDI_COMMAND_PITCH_BEND | outputChannel, pitchBendLsb, pitchBendMsb);
+}
+
void MidiDriver_MT32GM::sysEx(const byte *msg, uint16 length) {
uint16 delay = sysExNoDelay(msg, length);
@@ -972,17 +1077,21 @@ void MidiDriver_MT32GM::deinitSource(uint8 source) {
if (!isOutputChannelUsed(i))
continue;
- if (_controlData[i]->source == source)
+ if (_controlData[i]->source == source) {
+ // Set the sustain default value if it is specified (typically
+ // sustain would be turned off).
+ if (_controllerDefaults.sustain >= 0 && _controlData[i]->sustain != (_controllerDefaults.sustain >= 0x40)) {
+ send(-1, MIDI_COMMAND_CONTROL_CHANGE | i, MIDI_CONTROLLER_SUSTAIN, _controllerDefaults.sustain);
+ }
+
_controlData[i]->source = -1;
+ }
}
_availableChannels[source] = 0xFFFF;
// Reset the data to output channel mapping
for (int i = 0; i < MIDI_CHANNEL_COUNT; ++i) {
_channelMap[source][i] = i;
}
-
- // TODO Optionally reset some controllers to their
- // default values? Pitch wheel, volume, sustain...
}
void MidiDriver_MT32GM::applySourceVolume(uint8 source) {
diff --git a/audio/mt32gm.h b/audio/mt32gm.h
index 5410be3491..735ed36891 100644
--- a/audio/mt32gm.h
+++ b/audio/mt32gm.h
@@ -142,6 +142,7 @@ protected:
byte program;
// The Roland GS instrument bank
byte instrumentBank;
+ byte channelPressure;
byte modulation;
// The volume specified by the MIDI data
@@ -153,17 +154,24 @@ protected:
byte expression;
bool sustain;
+ // The currently selected Registered Parameter Number
+ uint16 rpn;
+ byte pitchBendSensitivity;
+
MidiChannelControlData() : source(-1),
sourceVolumeApplied(false),
pitchWheel(MIDI_PITCH_BEND_DEFAULT),
program(0),
instrumentBank(0),
+ channelPressure(0),
modulation(0),
volume(0),
scaledVolume(0),
- panPosition(0x40),
- expression(0x7F),
- sustain(false) { }
+ panPosition(MIDI_PANNING_DEFAULT),
+ expression(MIDI_EXPRESSION_DEFAULT),
+ sustain(false),
+ rpn(MIDI_RPN_NULL),
+ pitchBendSensitivity(0) { }
};
/**
@@ -370,6 +378,22 @@ protected:
*/
virtual void processEvent(int8 source, uint32 b, uint8 outputChannel,
MidiChannelControlData &controlData, bool channelLockedByOtherSource = false);
+ /**
+ * Applies the controller default settings to the specified output channel
+ * for the specified source.
+ * This will set all default values specified on _controllerDefaults on the
+ * channel except sustain, which is set by deinitSource.
+ *
+ * @param source The source triggering the default settings
+ * @param controlData The control data set to use when setting the defaults
+ * @param outputChannel The output channel on which the defaults should be
+ * set
+ * @param channelLockedByOtherSource True if the output channel is locked
+ * by another source. This will prevent the defaults from actually being
+ * sent to the MIDI device, but controlData will be updated. Default is
+ * false.
+ */
+ virtual void applyControllerDefaults(uint8 source, MidiChannelControlData &controlData, uint8 outputChannel, bool channelLockedByOtherSource);
/**
* Processes a note on or off MIDI event.
* This will apply source volume if necessary, update the active note
@@ -382,6 +406,20 @@ protected:
*/
virtual void noteOnOff(byte outputChannel, byte command, byte note, byte velocity,
int8 source, MidiChannelControlData &controlData);
+ /**
+ * Processes a polyphonic aftertouch MIDI event.
+ * This implementation will just send the event to the MIDI device.
+ *
+ * @param outputChannel The MIDI output channel for the event
+ * @param note The note on which aftertouch should be applied
+ * @param pressure The amount of pressure which should be applied
+ * @param source The source of the event
+ * @param controlData The control data set for the MIDI channel
+ * @param channelLockedByOtherSource True if the output channel is locked
+ * by another source. Default is false.
+ */
+ virtual void polyAftertouch(byte outputChannel, byte note, byte pressure,
+ int8 source, MidiChannelControlData &controlData, bool channelLockedByOtherSource = false);
/**
* Process a control change MIDI event.
* This will update the specified control data set and apply other
@@ -409,6 +447,36 @@ protected:
*/
virtual void programChange(byte outputChannel, byte patchId, int8 source,
MidiChannelControlData &controlData, bool channelLockedByOtherSource = false);
+ /**
+ * Processes a channel aftertouch MIDI event.
+ * This whil update the specified control data set and send the event to
+ * the MIDI device.
+ *
+ * @param outputChannel The MIDI output channel for the event
+ * @param pressure The amount of pressure which should be applied
+ * @param source The source of the event
+ * @param controlData The control data set for the MIDI channel
+ * @param channelLockedByOtherSource True if the output channel is locked
+ * by another source. Default is false.
+ */
+ virtual void channelAftertouch(byte outputChannel, byte pressure, int8 source,
+ MidiChannelControlData &controlData, bool channelLockedByOtherSource = false);
+ /**
+ * Processes a pitch bend MIDI event.
+ * This whil update the specified control data set and send the event to
+ * the MIDI device.
+ *
+ * @param outputChannel The MIDI output channel for the event
+ * @param pitchBendLsb The pitch bend LSB
+ * @param pitchBendMsb The pitch bend MSB
+ * @param source The source of the event
+ * @param controlData The control data set for the MIDI channel
+ * @param channelLockedByOtherSource True if the output channel is locked
+ * by another source. Default is false.
+ */
+ virtual void pitchBend(byte outputChannel, uint8 pitchBendLsb, uint8 pitchBendMsb,
+ int8 source, MidiChannelControlData &controlData, bool channelLockedByOtherSource = false);
+
/**
* Adds a note to the active note registration.
*/
Commit: cb97a47828e00ec94f23e4e44f5416d7c8777633
https://github.com/scummvm/scummvm/commit/cb97a47828e00ec94f23e4e44f5416d7c8777633
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-11-17T21:55:09+01:00
Commit Message:
GROOVIE: Add MIDI controller defaults for T7G and 11H
The 7th Guest uses the orchestra drumkit by setting it during initialization,
but not at the start of each track. Some tracks temporarily change the drumkit;
if these tracks are stopped at a bad moment, this changed drumkit remains in
effect. This commit sets the drumkit default to the orchestra drumkit to make
sure it is applied at the start of each track.
Some of the MIDI tracks of The 11th Hour use the modulation controller, but not
all tracks reset this controller at the start. This commit sets the modulation
default to 0 to make sure it is reset at the start of each track.
Changed paths:
engines/groovie/music.cpp
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index f80f795a2a..5ba783da3c 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -467,6 +467,19 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName)
_multisourceDriver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
_multisourceDriver->property(MidiDriver::PROP_MILES_VERSION,
_vm->getEngineVersion() == kGroovieT7G ? Audio::MILES_VERSION_2 : Audio::MILES_VERSION_3);
+ if (_vm->getEngineVersion() == kGroovieT7G && musicType == MT_GM)
+ // The 7th Guest GM init sets drumkit to 0x30 (Orchestra) and relies on
+ // this remaining set; tracks don't set this at start. Some tracks
+ // temporarily change the drumkit; if playback is stopped at the wrong
+ // time this will cause the changed drumkit to remain in effect.
+ // Set a default drumkit value to make sure it is set correctly at the
+ // start of each track.
+ _multisourceDriver->setControllerDefault(MidiDriver_Multisource::CONTROLLER_DEFAULT_DRUMKIT, 0x30);
+ if (_vm->getEngineVersion() == kGroovieT11H)
+ // Some The 11th Hour tracks use modulation, but not all tracks reset
+ // it at start. Set a default value to make sure it is reset at the
+ // start of each track.
+ _multisourceDriver->setControllerDefault(MidiDriver_Multisource::CONTROLLER_DEFAULT_MODULATION, 0);
int result = _driver->open();
if (result > 0 && result != MidiDriver::MERR_ALREADY_OPEN)
Commit: acad76683d27d2d407c2ca8b8fcf6f4e43df763d
https://github.com/scummvm/scummvm/commit/acad76683d27d2d407c2ca8b8fcf6f4e43df763d
Author: Coen Rampen (crampen at gmail.com)
Date: 2021-11-17T21:55:09+01:00
Commit Message:
GROOVIE: Fix 11th Hour scripts loading savegame 0
When The 11th Hour shows the load/restart dialog during the intro, it calls
loadgame with slot 0. It is not clear to me what this means, but it should not
load a savegame, because only slots 1-9 can be used with the original UI. In
ScummVM, this would load the autosave, which probably causes problems, though
the only thing I noticed is it stops the music, which does not happen in the
original interpreter.
This commit adds an exception for The 11th Hour to not load a savegame when
loadgame is called with slot 0. To still support loading the autosave form the
ScummVM UI, the slot is set to 0xFF in this case, which is interpreted by
loadgame to mean actually loading slot 0.
Changed paths:
engines/groovie/script.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 626c05beda..543c7e80f4 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -244,7 +244,14 @@ void Script::directGameLoad(int slot) {
midiInitScriptSize = sizeof(t7gMidiInitScript);
}
} else if (_version == kGroovieT11H) {
- setVariable(0xF, slot);
+ // WORKAROUND Slot 0 is sometimes loaded by scripts (f.e. showing the
+ // load/restart dialog during the intro). The intention is not clear to
+ // me, but it is not for loading a savegame (only slots 1-9 can be used
+ // in the original UI). In order to be able to distinguish this case
+ // from the case where the slot 0 savegame is loaded from the ScummVM
+ // UI, the slot variable is set to 0xFF here. This means that the slot
+ // 0 savegame should actually be loaded.
+ setVariable(0xF, slot == 0 ? 0xFF : slot);
_currentInstruction = 0xE78D;
return;
} else if (_version == kGroovieCDY) {
@@ -475,6 +482,23 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
}
void Script::loadgame(uint slot) {
+ // WORKAROUND The game scripts sometimes call loadgame with slot 0 (f.e.
+ // during the intro when showing the load/restart dialog). The meaning of
+ // this is not clear to me, but it is not for loading a savegame, because
+ // only slots 1-9 are usable with the original UI.
+ // In case slot 0 is loaded from the ScummVM UI, the slot parameter has
+ // been set to 0xFF.
+ if (_vm->getEngineVersion() == kGroovieT11H) {
+ if (slot == 0) {
+ // Loadgame slot 0 has been called by the game scripts.
+ // TODO Figure out if anything needs to be done.
+ return;
+ } else if (slot == 0xFF) {
+ // Slot 0 has been loaded from the ScummVM UI.
+ slot = 0;
+ }
+ }
+
_vm->_musicPlayer->stop();
Common::InSaveFile *file = SaveLoad::openForLoading(ConfMan.getActiveDomainName(), slot);
More information about the Scummvm-git-logs
mailing list