[Scummvm-git-logs] scummvm master -> 58d710d10fec3f73f1f3e7a6ea0845f61edb6e59
criezy
criezy at scummvm.org
Sun Dec 6 16:37:24 UTC 2020
This automated email contains information about 18 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3d550b8535 LURE: Added MT-32 SysEx loading
3dd3776cfd LURE: Fix wrong MT-32 MIDI channels for music
945c6c1643 LURE: Remove default MIDI volume
a994870fb3 LURE: Disable All Notes Off from parser
991061ee1b LURE: Fix music/SFX distinction
c57ad9c1f5 LURE: Fix MT-32 sound volume
288ffbedf4 LURE: Fix MT-32 channel assignments
93abb89ec1 LURE: Remove Note Off velocity
ffcf4976b7 LURE: Fix looping sound effects
4720253031 LURE: Running water sound effect workaround
f45a55d809 LURE: Add audio initialization icon
887dcf8c13 LURE: Remove TrashReverb
89e6ffc2e6 LURE: Use MT-32/GM MidiDriver
81c514ac8f LURE: Add MT-32 initialization icon blinking
20d5307bb9 LURE: Stop MIDI notes when pausing
f134e41b8c LURE: Don't send aftertouch to MT-32
ae3c9777a9 LURE: Fix warnings for missing init and unsigned/signed
58d710d10f LURE: Update lure.dat with music icon and water sound fix
Commit: 3d550b853563645d0d844e92ffc0c7289499c522
https://github.com/scummvm/scummvm/commit/3d550b853563645d0d844e92ffc0c7289499c522
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Added MT-32 SysEx loading
Changed paths:
engines/lure/intro.cpp
engines/lure/intro.h
engines/lure/lure.cpp
engines/lure/luredefs.h
engines/lure/sound.cpp
engines/lure/sound.h
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index 56f115e02b..07aa63960e 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -50,7 +50,7 @@ static const AnimRecord anim_screens[] = {
// with a palette in the following resource. Returns true if the introduction
// should be aborted
-bool Introduction::showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize) {
+bool Introduction::showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize, bool fadeOut) {
Screen &screen = Screen::getReference();
bool isEGA = LureEngine::getReference().isEGA();
screen.screen().loadScreen(screenId);
@@ -65,7 +65,7 @@ bool Introduction::showScreen(uint16 screenId, uint16 paletteId, uint16 delaySiz
bool result = interruptableDelay(delaySize);
if (LureEngine::getReference().shouldQuit()) return true;
- if (!isEGA)
+ if (fadeOut && !isEGA)
screen.paletteFadeOut();
return result;
@@ -100,10 +100,21 @@ bool Introduction::show() {
// Initial game company and then game screen
- for (int ctr = 0; start_screens[ctr]; ++ctr)
+ for (int ctr = 0; ctr < 3; ++ctr)
if (showScreen(start_screens[ctr], start_screens[ctr] + 1, 5000))
return true;
+ // Title screen
+ if (showScreen(start_screens[3], start_screens[3] + 1, 5000, false))
+ return true;
+
+ // TODO Original interpreter flashes a note icon in the lower left corner while doing this
+ Sound.initCustomTimbres();
+
+ // Fade out title screen
+ if (!isEGA)
+ screen.paletteFadeOut();
+
PaletteCollection coll(0x32);
Palette EgaPalette(0x1D);
diff --git a/engines/lure/intro.h b/engines/lure/intro.h
index bde073e43c..147ebff359 100644
--- a/engines/lure/intro.h
+++ b/engines/lure/intro.h
@@ -29,7 +29,7 @@ namespace Lure {
class Introduction {
private:
- bool showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize);
+ bool showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize, bool fadeOut = true);
bool interruptableDelay(uint32 milliseconds);
public:
bool show();
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index d6eccb1f30..5ecdc06ce8 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -158,6 +158,15 @@ Common::Error LureEngine::go() {
// Play the game
if (!shouldQuit()) {
+ _screen->empty();
+
+ if (Sound.hasNativeMT32()) {
+ // Initialize Roland MT-32 timbres
+ Sound.loadSection(ROLAND_MAIN_SYSEX_RESOURCE_ID);
+ // TODO Original interpreter flashes a note icon in the lower left corner while doing this
+ Sound.initCustomTimbres();
+ }
+
// Play the game
_saveLoadAllowed = true;
Sound.loadSection(Sound.isRoland() ? ROLAND_MAIN_SOUND_RESOURCE_ID : ADLIB_MAIN_SOUND_RESOURCE_ID);
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index 635b292177..b87cb97ab0 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -230,6 +230,7 @@ enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2,
// Miscellaneous resources
#define NAMES_RESOURCE_ID 9
+#define ROLAND_MAIN_SYSEX_RESOURCE_ID 0xB
#define ROLAND_MAIN_SOUND_RESOURCE_ID 0xC
#define ADLIB_MAIN_SOUND_RESOURCE_ID 0xD
#define ROLAND_INTRO_SOUND_RESOURCE_ID 0x30
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 4d0dd129c9..cdb32c8617 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -143,6 +143,122 @@ void SoundManager::loadSection(uint16 sectionId) {
_driver->setTimerCallback(this, &onTimer);
}
+void SoundManager::initCustomTimbres() {
+ if (!_isRoland || !_nativeMT32 || _driver == NULL)
+ return;
+
+ if (!_soundData)
+ error("SoundManager::initCustomTimbres - sound section has not been specified");
+
+ // Locate timbre data
+ uint32 headerSize = READ_LE_UINT32(_soundData->data() + 2); // Skip past the number of sounds
+ uint16 timbreDataHeaderOffset = _soundsTotal * 4 + 2;
+ if (timbreDataHeaderOffset + 6 > headerSize) {
+ warning("SoundManager::initCustomTimbres - could not find timbre data header");
+ return;
+ }
+
+ uint32 timbreDataOffset = READ_LE_UINT32(_soundData->data() + timbreDataHeaderOffset + 2); // Skip past end of header mark
+ if (timbreDataOffset + 17259 > _soundData->size()) {
+ warning("SoundManager::initCustomTimbres - timbre data smaller than expected");
+ return;
+ }
+ byte *timbreData = _soundData->data() + timbreDataOffset;
+
+ // Send SysExes
+
+ // System Area
+ uint32 address = 0x10 << 14; // 10 00 00
+ static const uint8 systemAreaSysExLengths[5] = { 1, 3, 9, 9, 1 };
+ for (int i = 0; i < 5; ++i) {
+ mt32SysEx(address, timbreData, systemAreaSysExLengths[i]);
+ address += systemAreaSysExLengths[i];
+ timbreData += systemAreaSysExLengths[i];
+ }
+ // Patch Temporary Area
+ address = 0x03 << 14; // 03 00 00
+ int sysexLength = 16;
+ for (int i = 0; i < 8; ++i) {
+ mt32SysEx(address, timbreData, sysexLength);
+ address += sysexLength;
+ timbreData += sysexLength;
+ }
+ // Timbre Memory
+ address = 0x08 << 14; // 08 00 00
+ sysexLength = 246;
+ for (int i = 0; i < 64; ++i) {
+ mt32SysEx(address, timbreData, sysexLength);
+ address += 256;
+ timbreData += sysexLength;
+ }
+ // Patch Memory
+ address = 0x05 << 14; // 05 00 00
+ sysexLength = 8;
+ for (int i = 0; i < 128; ++i) {
+ mt32SysEx(address, timbreData, sysexLength);
+ address += sysexLength;
+ timbreData += sysexLength;
+ }
+ // Rhythm Part Setup Temporary Area
+ address = 0x03 << 14 | 0x01 << 7 | 0x10; // 03 01 10
+ sysexLength = 4;
+ for (int i = 0; i < 85; ++i) {
+ mt32SysEx(address, timbreData, sysexLength);
+ address += sysexLength;
+ timbreData += sysexLength;
+ }
+}
+
+void SoundManager::mt32SysEx(const uint32 targetAddress, const byte *dataPtr, uint8 length) {
+ byte sysExMessage[270];
+ uint16 sysExPos = 0;
+ byte sysExByte;
+ uint16 sysExChecksum = 0;
+
+ memset(&sysExMessage, 0, sizeof(sysExMessage));
+
+ sysExMessage[0] = 0x41; // Roland
+ sysExMessage[1] = 0x10;
+ sysExMessage[2] = 0x16; // Model MT32
+ sysExMessage[3] = 0x12; // Command DT1
+
+ sysExChecksum = 0;
+
+ sysExMessage[4] = (targetAddress >> 14) & 0x7F;
+ sysExMessage[5] = (targetAddress >> 7) & 0x7F;
+ sysExMessage[6] = targetAddress & 0x7F;
+
+ for (byte targetAddressByte = 4; targetAddressByte < 7; targetAddressByte++) {
+ assert(sysExMessage[targetAddressByte] < 0x80); // security check
+ sysExChecksum -= sysExMessage[targetAddressByte];
+ }
+
+ sysExPos = 7;
+ for (int i = 0; i < length; ++i) {
+ sysExByte = *dataPtr++;
+
+ assert(sysExPos < sizeof(sysExMessage));
+ assert(sysExByte < 0x80); // security check
+ sysExMessage[sysExPos++] = sysExByte;
+ sysExChecksum -= sysExByte;
+ }
+
+ // Calculate checksum
+ assert(sysExPos < sizeof(sysExMessage));
+ sysExMessage[sysExPos++] = sysExChecksum & 0x7F;
+
+ _driver->sysEx(sysExMessage, sysExPos);
+
+ // Wait the time it takes to send the SysEx data
+ uint32 delay = (length + 2) * 1000 / 3125;
+
+ // Plus an additional delay for the MT-32 rev00
+ if (_nativeMT32)
+ delay += 40;
+
+ g_system->delayMillis(delay);
+}
+
void SoundManager::bellsBodge() {
debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::bellsBodge");
Resources &res = Resources::getReference();
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index b5cd4e0af9..21b7be6fb7 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -123,6 +123,7 @@ private:
void musicInterface_TidySounds();
static void onTimer(void *data);
void doTimer();
+ void mt32SysEx(const uint32 targetAddress, const byte *dataPtr, uint8 length);
public:
SoundManager();
@@ -132,6 +133,7 @@ public:
void loadFromStream(Common::ReadStream *stream);
void loadSection(uint16 sectionId);
+ void initCustomTimbres();
void killSounds();
void addSound(uint8 soundIndex, bool tidyFlag = true);
void addSound2(uint8 soundIndex);
Commit: 3dd3776cfd128def30a4d27a0f78683a3961e310
https://github.com/scummvm/scummvm/commit/3dd3776cfd128def30a4d27a0f78683a3961e310
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Fix wrong MT-32 MIDI channels for music
The MIDI player remaps the channels in the MIDI data to the available channels
on the MIDI device. In case of MT-32 music, this does not work, because the
percussion channel gets remapped to an instrument channel. The original
interpreter does not remap the channels of the music at all.
I've turned off channel remapping for all MT-32 MIDI data marked as music.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index cdb32c8617..ebe21147be 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -787,15 +787,22 @@ void MidiMusic::playMusic() {
}
void MidiMusic::send(uint32 b) {
+ byte channel;
+ if (Sound.isRoland() && _isMusic) {
+ // Use the channel as defined in the MIDI data
+ channel = b & 0x0F;
+ } else {
+ // Remap data channel to (one of) the channel(s) assigned to this player
#ifdef SOUND_CROP_CHANNELS
- if ((b & 0xF) >= _numChannels) return;
- byte channel = _channelNumber + (byte)(b & 0x0F);
+ if ((b & 0xF) >= _numChannels) return;
+ channel = _channelNumber + (byte)(b & 0x0F);
#else
- byte channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
+ channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
#endif
- if ((channel >= NUM_CHANNELS) || (_channels[channel].midiChannel == NULL))
- return;
+ if ((channel >= NUM_CHANNELS) || (_channels[channel].midiChannel == NULL))
+ return;
+ }
if ((b & 0xFFF0) == 0x07B0) {
// Adjust volume changes by song and master volume
@@ -805,15 +812,18 @@ void MidiMusic::send(uint32 b) {
volume = volume * _volume * master_volume / 65025;
b = (b & 0xFF00FFFF) | (volume << 16);
} else if ((b & 0xF0) == 0xC0) {
- if (Sound.isRoland() && !Sound.hasNativeMT32()) {
+ if (Sound.isRoland() && !Sound.hasNativeMT32() && channel != 9) {
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
}
- }
- else if ((b & 0xFFF0) == 0x007BB0) {
+ } else if ((b & 0xFFF0) == 0x007BB0) {
// No implementation
}
- _channels[channel].midiChannel->send(b);
+ if (Sound.isRoland() && _isMusic) {
+ _driver->send(b);
+ } else {
+ _channels[channel].midiChannel->send(b);
+ }
}
void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
Commit: 945c6c1643dc24c9f31f0de71a7ebc764e028594
https://github.com/scummvm/scummvm/commit/945c6c1643dc24c9f31f0de71a7ebc764e028594
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Remove default MIDI volume
Some music tracks (f.e. the 2nd introduction track) do not properly set the
volume on all channels and rely on the volume set by the previous track.
ScummVM would reset the volume on all channels between tracks, which caused
wrong volumes on some channels. I've removed this.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index ebe21147be..e8b692d73d 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -712,10 +712,6 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
_numChannels = numChannels;
_volume = 0;
- for (int i = 0; i < _numChannels; ++i) {
- /* 90 is power on default for midi compliant devices */
- _channels[_channelNumber + i].volume = 90;
- }
if (_isMusic)
setVolume(Sound.musicVolume());
Commit: a994870fb3d221549db6f1ed70833c00c0648683
https://github.com/scummvm/scummvm/commit/a994870fb3d221549db6f1ed70833c00c0648683
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Disable All Notes Off from parser
Lure uses multiple MIDI parsers simultaneously, so having a parser send All
Notes Off events on all channels does not work.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index e8b692d73d..91039f8ba3 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -721,6 +721,8 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
_parser = MidiParser::createParser_SMF();
_parser->setMidiDriver(this);
_parser->setTimerRate(_driver->getBaseTempo());
+ // All Notes Off on all channels does not work with multiple MIDI sources
+ _parser->property(MidiParser::mpDisableAllNotesOffMidiEvents, 1);
_soundData = (uint8 *)soundData;
_soundSize = size;
Commit: 991061ee1b027e31f5d0a1efd3479b06c43ca0af
https://github.com/scummvm/scummvm/commit/991061ee1b027e31f5d0a1efd3479b06c43ca0af
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Fix music/SFX distinction
Distinction between music and SFX was made based on the most significant bit in
the sound number byte. This does not accurately reflect which MIDI sequences
are music or a sound effect.
Instead, I've added a flag which can be passed to
SoundManager::musicInterface_Play to indicate whether the sound is music or a
sound effect. All music is started from hard-coded animation sequences, so this
flag can be passed from ScummVM code when appropriate.
Changed paths:
engines/lure/animseq.cpp
engines/lure/animseq.h
engines/lure/game.cpp
engines/lure/intro.cpp
engines/lure/scripts.cpp
engines/lure/sound.cpp
engines/lure/sound.h
engines/lure/surface.cpp
diff --git a/engines/lure/animseq.cpp b/engines/lure/animseq.cpp
index 690c3e6f2b..059c710624 100644
--- a/engines/lure/animseq.cpp
+++ b/engines/lure/animseq.cpp
@@ -234,7 +234,7 @@ AnimAbortType AnimationSequence::show() {
if ((soundFrame != NULL) && (frameCtr == 0))
Sound.musicInterface_Play(
Sound.isRoland() ? soundFrame->rolandSoundId : soundFrame->adlibSoundId,
- soundFrame->channelNum);
+ soundFrame->channelNum, soundFrame->music);
if (_isEGA)
egaDecodeFrame(_pPixels);
diff --git a/engines/lure/animseq.h b/engines/lure/animseq.h
index a220356f92..dcc18603fc 100644
--- a/engines/lure/animseq.h
+++ b/engines/lure/animseq.h
@@ -34,6 +34,7 @@ struct AnimSoundSequence {
uint8 adlibSoundId;
uint8 rolandSoundId;
uint8 channelNum;
+ bool music;
};
class AnimationSequence {
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp
index 5d9f489216..f469c6acfe 100644
--- a/engines/lure/game.cpp
+++ b/engines/lure/game.cpp
@@ -388,7 +388,7 @@ void Game::displayChuteAnimation() {
mouse.cursorOff();
Sound.killSounds();
- Sound.musicInterface_Play(0x40, 0);
+ Sound.musicInterface_Play(0x40, 0, true);
AnimationSequence *anim = new AnimationSequence(CHUTE_ANIM_ID, palette, false);
anim->show();
@@ -417,7 +417,7 @@ void Game::displayBarrelAnimation() {
mouse.cursorOff();
Sound.killSounds();
- Sound.musicInterface_Play(0x3B, 0);
+ Sound.musicInterface_Play(0x3B, 0, true);
anim->show();
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index 07aa63960e..b4bfba0fc2 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -132,7 +132,7 @@ bool Introduction::show() {
Sound.musicInterface_KillAll();
currentSound = curr_anim->soundNumber;
- Sound.musicInterface_Play(currentSound, 0);
+ Sound.musicInterface_Play(currentSound, 0, true);
}
bool fadeIn = curr_anim == anim_screens;
diff --git a/engines/lure/scripts.cpp b/engines/lure/scripts.cpp
index f7dc06033a..1088b81cc4 100644
--- a/engines/lure/scripts.cpp
+++ b/engines/lure/scripts.cpp
@@ -46,9 +46,9 @@ static const uint16 *hotspot_dealloc_set[4] = {&dealloc_list_1[0], &dealloc_list
// Details used for co-ordination of sounds during the endgame sequence
static const AnimSoundSequence soundList[] = {
- {9, 0x45, 2, 0}, {27, 0x48, 5, 0}, {24, 0x46, 3, 0}, {24, 0x37, 1, 0}, {3, 0x37, 1, 1},
- {3, 0x37, 1, 2}, {3, 0x37, 1, 3}, {3, 0x37, 1, 4}, {4, 0x37, 1, 5}, {7, 0x47, 4, 6},
- {31, 0x00, 6, 0}, {0, 0, 0, 0}
+ {9, 0x45, 2, 0, true}, {27, 0x48, 5, 0, false}, {24, 0x46, 3, 0, false}, {24, 0x37, 1, 0, false}, {3, 0x37, 1, 1, false},
+ {3, 0x37, 1, 2, false}, {3, 0x37, 1, 3, false}, {3, 0x37, 1, 4, false}, {4, 0x37, 1, 5, false}, {7, 0x47, 4, 6, false},
+ {31, 0x00, 6, 0, true}, {0, 0, 0, 0}
};
/*------------------------------------------------------------------------*/
@@ -207,7 +207,7 @@ void Script::endgameSequence(uint16 v1, uint16 v2, uint16 v3) {
delete anim;
Sound.killSounds();
- Sound.musicInterface_Play(6, 0);
+ Sound.musicInterface_Play(6, 0, true);
anim = new AnimationSequence(ENDGAME_ANIM_ID + 2, p, false);
anim->show();
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 91039f8ba3..c2d4eb6beb 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -348,7 +348,7 @@ void SoundManager::addSound(uint8 soundIndex, bool tidyFlag) {
_activeSounds.push_back(SoundList::value_type(newEntry));
- musicInterface_Play(rec.soundNumber, channelCtr, numChannels);
+ musicInterface_Play(rec.soundNumber, channelCtr, false, numChannels);
musicInterface_SetVolume(channelCtr, newEntry->volume);
}
@@ -487,7 +487,7 @@ void SoundManager::restoreSounds() {
if ((rec.numChannels != 0) && ((rec.flags & SF_RESTORE) != 0)) {
Common::fill(_channelsInUse + rec.channel, _channelsInUse + rec.channel + rec.numChannels, true);
- musicInterface_Play(rec.soundNumber, rec.channel, rec.numChannels);
+ musicInterface_Play(rec.soundNumber, rec.channel, false, rec.numChannels);
musicInterface_SetVolume(rec.channel, rec.volume);
}
@@ -529,7 +529,7 @@ void SoundManager::fadeOut() {
// musicInterface_Play
// Play the specified sound
-void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, uint8 numChannels) {
+void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, bool isMusic, uint8 numChannels) {
debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_Play soundNumber=%d, channel=%d",
soundNumber, channelNumber);
Game &game = Game::getReference();
@@ -545,7 +545,8 @@ void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, u
// Only play sounds if a sound driver is active
return;
- bool isMusic = (soundNumber & 0x80) != 0;
+ // TODO Figure out what this represents
+ //bool isMusic = (soundNumber & 0x80) != 0;
if (!game.soundFlag())
// Don't play sounds if sound is turned off
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index 21b7be6fb7..6a462cc96b 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -157,7 +157,7 @@ public:
// The following methods implement the external sound player module
void musicInterface_Initialize();
- void musicInterface_Play(uint8 soundNumber, uint8 channelNumber, uint8 numChannels = 4);
+ void musicInterface_Play(uint8 soundNumber, uint8 channelNumber, bool isMusic = false, uint8 numChannels = 4);
void musicInterface_Stop(uint8 soundNumber);
bool musicInterface_CheckPlaying(uint8 soundNumber);
void musicInterface_SetVolume(uint8 channelNum, uint8 volume);
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index ad5d0e4d96..41eae39583 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -1146,7 +1146,7 @@ bool RestartRestoreDialog::show() {
LureEngine &engine = LureEngine::getReference();
Sound.killSounds();
- Sound.musicInterface_Play(60, 0);
+ Sound.musicInterface_Play(60, 0, true);
mouse.setCursorNum(CURSOR_ARROW);
// See if there are any savegames that can be restored
Commit: c57ad9c1f5ae5d6716db15087cfdae2efce39563
https://github.com/scummvm/scummvm/commit/c57ad9c1f5ae5d6716db15087cfdae2efce39563
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Fix MT-32 sound volume
Lure of the Temptress defines a volume level for each sound resource. This is a
byte value which can increase or decrease the volume of the sound as specified
in the MIDI data (80h is the neutral value). The original interpreter applies
this as a scaling factor to the Note On velocity for the MT-32. ScummVM used it
to scale the MIDI volume control change values instead, causing incorrect
volume levels.
This change applies the sound resource volume to note velocity instead, which
results in the same volume as the original interpreter. I've left the old
method in place for AdLib, because I'm not sure how the original interpeter
handles sound resource volume in this case.
Changed paths:
engines/lure/sound.cpp
engines/lure/sound.h
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index c2d4eb6beb..ac8a0d9a35 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -410,12 +410,14 @@ void SoundManager::syncSounds() {
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
- _musicVolume = mute ? 0 : MIN(255, ConfMan.getInt("music_volume"));
- _sfxVolume = mute ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
+ _musicVolume = mute ? 0 : MIN(256, ConfMan.getInt("music_volume"));
+ _sfxVolume = mute ? 0 : MIN(256, ConfMan.getInt("sfx_volume"));
_soundMutex.lock();
MusicListIterator i;
for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ // FIXME This should not override the sound resource volume
+ // on the MidiMusic object.
if ((*i)->isMusic())
(*i)->setVolume(_musicVolume);
else
@@ -714,10 +716,9 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
_numChannels = numChannels;
_volume = 0;
- if (_isMusic)
- setVolume(Sound.musicVolume());
- else
- setVolume(Sound.sfxVolume());
+ // Default sound resource volume: 80h (neutral).
+ // TODO AdLib does not use sound resource volume, so use fixed 240.
+ setVolume(Sound.isRoland() ? 0x80 : 240);
_parser = MidiParser::createParser_SMF();
_parser->setMidiDriver(this);
@@ -768,13 +769,17 @@ void MidiMusic::setVolume(int volume) {
_volume = volume;
- volume *= _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
+ // MT-32 MIDI data sets channel volume using control change,
+ // so this is only needed for AdLib.
+ if (!Sound.isRoland()) {
+ volume *= _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
- for (int i = 0; i < _numChannels; ++i) {
- if (_channels[_channelNumber + i].midiChannel != NULL)
- _channels[_channelNumber + i].midiChannel->volume(
- _channels[_channelNumber + i].volume *
- volume / 65025);
+ for (int i = 0; i < _numChannels; ++i) {
+ if (_channels[_channelNumber + i].midiChannel != NULL)
+ _channels[_channelNumber + i].midiChannel->volume(
+ _channels[_channelNumber + i].volume *
+ volume / 65025);
+ }
}
}
@@ -796,7 +801,7 @@ void MidiMusic::send(uint32 b) {
if ((b & 0xF) >= _numChannels) return;
channel = _channelNumber + (byte)(b & 0x0F);
#else
- channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
+ channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
#endif
if ((channel >= NUM_CHANNELS) || (_channels[channel].midiChannel == NULL))
@@ -807,8 +812,16 @@ void MidiMusic::send(uint32 b) {
// Adjust volume changes by song and master volume
byte volume = (byte)((b >> 16) & 0x7F);
_channels[channel].volume = volume;
- int master_volume = _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
- volume = volume * _volume * master_volume / 65025;
+ uint16 master_volume = _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
+ if (Sound.isRoland()) {
+ // MT-32 sound resource volume is applied to note velocity,
+ // so scale MIDI data volume only with ScummVM master volume.
+ volume = (volume * master_volume) >> 8;
+ } else {
+ // TODO AdLib might use velocity for sound resource volume
+ // as well.
+ volume = volume * _volume * master_volume / 65025;
+ }
b = (b & 0xFF00FFFF) | (volume << 16);
} else if ((b & 0xF0) == 0xC0) {
if (Sound.isRoland() && !Sound.hasNativeMT32() && channel != 9) {
@@ -816,6 +829,15 @@ void MidiMusic::send(uint32 b) {
}
} else if ((b & 0xFFF0) == 0x007BB0) {
// No implementation
+ } else if (((b & 0xF0) == 0x90)) {
+ // Note On
+ if (Sound.isRoland()) {
+ // Scale velocity with sound resource volume
+ byte velocity = (b >> 16) & 0x7F;
+ velocity = (velocity * _volume) >> 7;
+ if (velocity > 0x7F) velocity = 0x7F;
+ b = (b & 0xFF00FFFF) | (velocity << 16);
+ }
}
if (Sound.isRoland() && _isMusic) {
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index 6a462cc96b..d5803df623 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -115,8 +115,8 @@ private:
Common::Mutex _soundMutex;
bool _paused;
- uint _musicVolume;
- uint _sfxVolume;
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
// Internal support methods
void bellsBodge();
@@ -152,8 +152,8 @@ public:
bool getPaused() const { return _paused; }
bool hasNativeMT32() const { return _nativeMT32; }
bool isRoland() const { return _isRoland; }
- uint musicVolume() const { return _musicVolume; }
- uint sfxVolume() const { return _sfxVolume; }
+ uint16 musicVolume() const { return _musicVolume; }
+ uint16 sfxVolume() const { return _sfxVolume; }
// The following methods implement the external sound player module
void musicInterface_Initialize();
Commit: 288ffbedf482d1979808fa0780f99ce18ba5148d
https://github.com/scummvm/scummvm/commit/288ffbedf482d1979808fa0780f99ce18ba5148d
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Fix MT-32 channel assignments
ScummVM would add one to the number of MIDI channels specified for a sound
resource, but this does not match the actual number of channels used in the
MIDI data. Additionally, it would not take into account the fact that the first
MIDI channel used in the MT-32 data is channel 1 instead of 0. This change
corrects this; the MIDI channels used now match those of the original
interpreter.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index ac8a0d9a35..79ca0ac4cb 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -312,7 +312,7 @@ void SoundManager::addSound(uint8 soundIndex, bool tidyFlag) {
int numChannels;
if (_isRoland)
- numChannels = (rec.numChannels & 3) + 1;
+ numChannels = (rec.numChannels & 3);
else
numChannels = ((rec.numChannels >> 2) & 3) + 1;
@@ -801,7 +801,13 @@ void MidiMusic::send(uint32 b) {
if ((b & 0xF) >= _numChannels) return;
channel = _channelNumber + (byte)(b & 0x0F);
#else
+ if (Sound.isRoland()) {
+ // Roland channels start at 1
+ channel = _channelNumber + (((byte)(b & 0x0F) - 1) % _numChannels);
+ } else {
+ // AdLib channels start at 0
channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
+ }
#endif
if ((channel >= NUM_CHANNELS) || (_channels[channel].midiChannel == NULL))
Commit: 93abb89ec1b598382ce333337686b27a2769e765
https://github.com/scummvm/scummvm/commit/93abb89ec1b598382ce333337686b27a2769e765
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Remove Note Off velocity
The LotT MT-32 MIDI data specifies a velocity value for the Note Off events,
but this is not sent to the MT-32 by the original interpreter. This removes the
velocity from the Note Off events, so it matches the MIDI output of the
original interpreter.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 79ca0ac4cb..a0bca9fa6e 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -844,6 +844,12 @@ void MidiMusic::send(uint32 b) {
if (velocity > 0x7F) velocity = 0x7F;
b = (b & 0xFF00FFFF) | (velocity << 16);
}
+ } else if (((b & 0xF0) == 0x80)) {
+ // Note Off
+ if (Sound.isRoland()) {
+ // Strip velocity
+ b &= 0xFF00FFFF;
+ }
}
if (Sound.isRoland() && _isMusic) {
Commit: ffcf4976b761f95c5e4b9c6d1274346fe281f1be
https://github.com/scummvm/scummvm/commit/ffcf4976b761f95c5e4b9c6d1274346fe281f1be
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Fix looping sound effects
Some sound effects in LotT loop, like the thunderstorm in the beginning of the
game. This is indicated by the high bit of the sound number. This change adds
support for these looping sound effects.
Changed paths:
engines/lure/intro.cpp
engines/lure/sound.cpp
engines/lure/sound.h
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index b4bfba0fc2..a1c70289fe 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -38,11 +38,11 @@ struct AnimRecord {
static const uint16 start_screens[] = {0x18, 0x1A, 0x1E, 0x1C, 0};
static const AnimRecord anim_screens[] = {
- {0x40, 0, 0x35A, 0x2C8, 0x80}, // The kingdom was at peace
- {0x42, 1, 0, 0x5FA, 0x81}, // Cliff overhang
- {0x44, 2, 0, 0, 0x82}, // Siluette in moonlight
+ {0x40, 0, 0x35A, 0x2C8, 0x00}, // The kingdom was at peace
+ {0x42, 1, 0, 0x5FA, 0x01}, // Cliff overhang
+ {0x44, 2, 0, 0, 0x02}, // Siluette in moonlight
{0x24, 3, 0, 0x328 + 0x24, 0xff}, // Exposition of reaching town
- {0x46, 3, 0, 0, 0x83}, // Skorl approaches
+ {0x46, 3, 0, 0, 0x03}, // Skorl approaches
{0, 0, 0, 0, 0xff}};
// showScreen
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index a0bca9fa6e..8ba068cc06 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -547,8 +547,8 @@ void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, b
// Only play sounds if a sound driver is active
return;
- // TODO Figure out what this represents
- //bool isMusic = (soundNumber & 0x80) != 0;
+ // Most significant bit indicates if the track should loop or not
+ bool loop = (soundNumber & 0x80) != 0;
if (!game.soundFlag())
// Don't play sounds if sound is turned off
@@ -567,7 +567,7 @@ void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, b
_soundMutex.lock();
MidiMusic *sound = new MidiMusic(_driver, _channelsInner, channelNumber, soundNum,
- isMusic, numChannels, soundStart, dataSize);
+ isMusic, loop, numChannels, soundStart, dataSize);
_playingSounds.push_back(MusicList::value_type(sound));
_soundMutex.unlock();
}
@@ -705,13 +705,14 @@ void SoundManager::doTimer() {
/*------------------------------------------------------------------------*/
MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
- uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size) {
+ uint8 channelNum, uint8 soundNum, bool isMus, bool loop, uint8 numChannels, void *soundData, uint32 size) {
_driver = driver;
assert(_driver);
_channels = channels;
_soundNumber = soundNum;
_channelNumber = channelNum;
_isMusic = isMus;
+ _loop = loop;
_numChannels = numChannels;
_volume = 0;
@@ -725,6 +726,7 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
_parser->setTimerRate(_driver->getBaseTempo());
// All Notes Off on all channels does not work with multiple MIDI sources
_parser->property(MidiParser::mpDisableAllNotesOffMidiEvents, 1);
+ _parser->property(MidiParser::mpAutoLoop, _loop);
_soundData = (uint8 *)soundData;
_soundSize = size;
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index d5803df623..e58eb7274e 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -58,6 +58,7 @@ private:
MidiParser *_parser;
ChannelEntry *_channels;
bool _isMusic;
+ bool _loop;
bool _isPlaying;
void queueUpdatePos();
@@ -67,7 +68,7 @@ private:
public:
MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
- uint8 channelNum, uint8 soundNum, bool isMus, uint8 numChannels, void *soundData, uint32 size);
+ uint8 channelNum, uint8 soundNum, bool isMus, bool loop, uint8 numChannels, void *soundData, uint32 size);
~MidiMusic() override;
void setVolume(int volume);
int getVolume() const { return _volume; }
Commit: 472025303170b2c9a2c210783101ad8e2168ebc6
https://github.com/scummvm/scummvm/commit/472025303170b2c9a2c210783101ad8e2168ebc6
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Running water sound effect workaround
The sound effects for running water have 2 channels listed for MT-32 in their
sound resource, but the MIDI data actually uses 3 channels. Added a patch to
this sound resource in lure.dat so the sound effects can play without channel
3 overriding channel 1.
Changed paths:
devtools/create_lure/create_lure_dat.cpp
diff --git a/devtools/create_lure/create_lure_dat.cpp b/devtools/create_lure/create_lure_dat.cpp
index 0ac07c460d..67580fa433 100644
--- a/devtools/create_lure/create_lure_dat.cpp
+++ b/devtools/create_lure/create_lure_dat.cpp
@@ -1408,6 +1408,13 @@ void save_sound_desc_data(byte *&data, uint16 &totalSize) {
totalSize = SOUND_DESCS_SIZE;
data = (byte *) malloc(totalSize);
lureExe.read(data, totalSize);
+
+ // WORKAROUND Sounds 0 and 12 (running water) use 3 channels
+ // on MT-32, but sound resource lists 2.
+ if ((data[2] & 3) == 2) {
+ data[2] |= 3;
+ data[(12 * 5) + 2] |= 3;
+ }
}
struct DecoderEntry {
Commit: f45a55d8098c9a203167216c77d2d8fd6711cb1b
https://github.com/scummvm/scummvm/commit/f45a55d8098c9a203167216c77d2d8fd6711cb1b
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Add audio initialization icon
When sending SysEx data to the MT-32, the game blinks an icon in the lower left
corner of the screen. This change adds that icon. It is stored in the
executable, so I added code to create_lure_dat to extract the icon and add it
to the ScummVM data file. The new version of this file is now required to run
the game.
Changed paths:
devtools/create_lure/create_lure_dat.cpp
devtools/create_lure/create_lure_dat.h
engines/lure/intro.cpp
engines/lure/lure.cpp
engines/lure/luredefs.h
engines/lure/sound.cpp
engines/lure/surface.cpp
engines/lure/surface.h
diff --git a/devtools/create_lure/create_lure_dat.cpp b/devtools/create_lure/create_lure_dat.cpp
index 67580fa433..d8247d3e9d 100644
--- a/devtools/create_lure/create_lure_dat.cpp
+++ b/devtools/create_lure/create_lure_dat.cpp
@@ -1640,6 +1640,20 @@ void save_string_decoder_data(byte *&data, uint16 &totalSize) {
*pDest = (char) 0xff;
}
+void save_audio_init_icon(byte *&data, uint16 &totalSize) {
+ uint32 dataStart = 0x131E0;
+ if (language == IT_ITA) dataStart = 0x132A0;
+ else if (language == FR_FRA) dataStart = 0x132C0;
+ else if (language == DE_DEU) dataStart = 0x132F0;
+ else if (language == ES_ESP) dataStart = 0x132C0;
+ else if (language != EN_ANY) errorExit("save_audio_init_icon: Unknown language");
+ lureExe.seek(dataSegment + dataStart);
+
+ totalSize = AUDIO_INIT_ICON_SIZE;
+ data = (byte *)malloc(totalSize);
+ lureExe.read(data, totalSize);
+}
+
void getEntry(uint8 entryIndex, uint16 &resourceId, byte *&data, uint16 &size) {
resourceId = 0x3f01 + entryIndex;
printf("Get resource #%d\n", entryIndex);
@@ -1769,6 +1783,11 @@ void getEntry(uint8 entryIndex, uint16 &resourceId, byte *&data, uint16 &size) {
save_string_decoder_data(data, size);
break;
+ case 25:
+ // Save the audio init icon
+ save_audio_init_icon(data, size);
+ break;
+
default:
data = NULL;
size = 0;
diff --git a/devtools/create_lure/create_lure_dat.h b/devtools/create_lure/create_lure_dat.h
index ed713dd4f3..9ec0d3e176 100644
--- a/devtools/create_lure/create_lure_dat.h
+++ b/devtools/create_lure/create_lure_dat.h
@@ -28,7 +28,7 @@
#include "common/util.h"
#define VERSION_MAJOR 1
-#define VERSION_MINOR 29
+#define VERSION_MINOR 30
#define DIALOG_SIZE 0x150
@@ -68,6 +68,8 @@
#define SOUND_DESCS_SIZE 265
+#define AUDIO_INIT_ICON_SIZE 14 * 14
+
#include "common/pack-start.h" // START STRUCT PACKING
// FIXME: Add PACKED_STRUCT to all structs which actually need packing,
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index a1c70289fe..9a4451f7b0 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -108,7 +108,6 @@ bool Introduction::show() {
if (showScreen(start_screens[3], start_screens[3] + 1, 5000, false))
return true;
- // TODO Original interpreter flashes a note icon in the lower left corner while doing this
Sound.initCustomTimbres();
// Fade out title screen
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index 5ecdc06ce8..6a4795498a 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -160,10 +160,9 @@ Common::Error LureEngine::go() {
if (!shouldQuit()) {
_screen->empty();
- if (Sound.hasNativeMT32()) {
+ if (Sound.isRoland() && Sound.hasNativeMT32()) {
// Initialize Roland MT-32 timbres
Sound.loadSection(ROLAND_MAIN_SYSEX_RESOURCE_ID);
- // TODO Original interpreter flashes a note icon in the lower left corner while doing this
Sound.initCustomTimbres();
}
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index b87cb97ab0..a62b50943c 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -31,7 +31,7 @@ namespace Lure {
#define SUPPORT_FILENAME "lure.dat"
#define LURE_DAT_MAJOR 1
-#define LURE_DAT_MINOR 29
+#define LURE_DAT_MINOR 30
#define LURE_MIN_SAVEGAME_MINOR 25
#define LURE_SAVEGAME_MINOR 33
@@ -224,6 +224,7 @@ enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2,
#define STRING_LIST_RESOURCE_ID 0x3f17
#define SOUND_DESC_RESOURCE_ID 0x3f18
#define STRING_DECODER_RESOURCE_ID 0x3f19
+#define AUDIO_INIT_ICON_RESOURCE_ID 0x3F1A
// Script constants
#define STARTUP_SCRIPT 0x23FC
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 8ba068cc06..85a504d8d0 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -25,6 +25,7 @@
#include "lure/memory.h"
#include "lure/res.h"
#include "lure/room.h"
+#include "lure/surface.h"
#include "common/algorithm.h"
#include "common/config-manager.h"
@@ -165,6 +166,9 @@ void SoundManager::initCustomTimbres() {
}
byte *timbreData = _soundData->data() + timbreDataOffset;
+ AudioInitIcon *icon = new AudioInitIcon();
+ icon->show();
+
// Send SysExes
// System Area
@@ -207,6 +211,9 @@ void SoundManager::initCustomTimbres() {
address += sysexLength;
timbreData += sysexLength;
}
+
+ icon->hide();
+ delete icon;
}
void SoundManager::mt32SysEx(const uint32 targetAddress, const byte *dataPtr, uint8 length) {
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index 41eae39583..3390185d61 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -1435,4 +1435,47 @@ void CopyProtectionDialog::chooseCharacters() {
screen.update();
}
+AudioInitIcon::AudioInitIcon() {
+ if (LureEngine::getReference().isEGA()) {
+ // The icon is not shown on EGA
+ _iconSurface = 0;
+ } else {
+ // Load icon
+ _iconSurface = new Surface(Disk::getReference().getEntry(AUDIO_INIT_ICON_RESOURCE_ID), 14, 14);
+
+ Screen &screen = Screen::getReference();
+
+ // Add the colors needed for displaying the icon to the current palette
+ Palette combinedPalette;
+ Palette defaultPalette(GAME_PALETTE_RESOURCE_ID);
+ combinedPalette.palette()->copyFrom(screen.getPalette().palette(), 0, 0, 4 * 0xF8);
+ combinedPalette.palette()->copyFrom(defaultPalette.palette(), 4 * 0xF8, 4 * 0xF8, 4 * 6);
+ screen.setPalette(&combinedPalette);
+ }
+}
+
+AudioInitIcon::~AudioInitIcon() {
+ if (_iconSurface)
+ delete _iconSurface;
+}
+
+void AudioInitIcon::show() {
+ // TODO The icon should blink
+ if (!LureEngine::getReference().isEGA()) {
+ Screen &screen = Screen::getReference();
+
+ _iconSurface->copyTo(&screen.screen(), 0, 185);
+ screen.update();
+ }
+}
+
+void AudioInitIcon::hide() {
+ if (!LureEngine::getReference().isEGA()) {
+ Screen &screen = Screen::getReference();
+
+ screen.screen().fillRect(Common::Rect(0, 185, 14, 199), 0);
+ screen.update();
+ }
+}
+
} // End of namespace Lure
diff --git a/engines/lure/surface.h b/engines/lure/surface.h
index 3cda09bf56..60ff1e22b8 100644
--- a/engines/lure/surface.h
+++ b/engines/lure/surface.h
@@ -145,6 +145,17 @@ public:
bool show();
};
+class AudioInitIcon {
+private:
+ Surface *_iconSurface;
+
+public:
+ AudioInitIcon();
+ ~AudioInitIcon();
+ void show();
+ void hide();
+};
+
} // End of namespace Lure
#endif
Commit: 887dcf8c136cf11d9324c72cdbc091bf46143a0e
https://github.com/scummvm/scummvm/commit/887dcf8c136cf11d9324c72cdbc091bf46143a0e
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Remove TrashReverb
The original interpreter sends out a SysEx to turn off the MT-32 reverb when
opening a door while outside. This does not seem to work properly in the
original interpreter, and it is unclear what the developer's intentions were
with this function, so I've added a comment and removed the functionality.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 85a504d8d0..ad6f852bb2 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -663,12 +663,58 @@ void SoundManager::musicInterface_ContinuePlaying() {
// No implementation needed
}
+/*
+ * TL;DR: TrashReverb does not seem to work correctly in the original interpreter
+ * and I don't know what the developer's intentions were, so I've disabled it in
+ * ScummVM.
+ *
+ * In the original interpreter, TrashReverb sends a SysEx to the MT-32 which sets
+ * the reverb parameters to mode Room, time 1, level 0. This practically turns off
+ * reverb. It is triggered by opening a door in an outdoors location in the town.
+ * The SysEx is sent when the door sound starts, and again 40ms after the first
+ * one. TrashReverb also seems to be triggered when a door is opened offscreen (by
+ * an NPC).
+ * This means that, as soon as you enter town, reverb is turned off when the first
+ * door is opened. It is not turned back on. Reverb is restored only when you quit
+ * and restart the game (during MT-32 initialization); it is then turned off again
+ * when the first door outside in town is opened. Turning off the reverb
+ * repeatedly (twice whenever a door is opened) does not seem to accomplish
+ * anything.
+ * The best explanation for this behavior I can come up with is that the developer
+ * intended to disable reverb while playing a door opening sound outdoors. The
+ * second SysEx when opening a door was meant to turn reverb back on, but turns it
+ * off again because of a bug. Also, TrashReverb being triggered by doors opening
+ * offscreen would be a bug. There is a third problem: the door opening sound lasts
+ * much longer than 40 ms, so turning reverb back on 40 ms after starting the door
+ * opening sound still results in a noticable reverb. All in all this explanation
+ * is not entirely convicing.
+ * Another explanation would be that reverb was only meant to be on for the first
+ * part of the game and should be turned off from the town onwards (this is what
+ * the implementation in the original interpreter effectively does). However, why
+ * disable reverb when opening a door, and not f.e. when the player first enters
+ * a town screen? And why is it not immediately turned off when a player loads a
+ * savegame of a point later in the game? And why is reverb repeatedly disabled?
+ * This does not make much sense either.
+ * All in all, I am convinced that this functionality does not work correctly in
+ * the original interpreter, but I don't know what the developer's intentions
+ * were either. So I can't make a proper implementation for this, and I think it
+ * is best left disabled.
+ */
+
// musicInterface_TrashReverb
// Trashes reverb on actively playing sounds
void SoundManager::musicInterface_TrashReverb() {
- // TODO: Handle support for trashing reverb
debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_TrashReverb");
+
+ /*
+ // TODO Should this do anything on AdLib? It does not have reverb AFAIK
+ if (_isRoland) {
+ // Set reverb parameters to mode Room, time 1, level 0
+ static const byte sysExData[] = { 0x00, 0x00, 0x00 };
+ mt32SysEx(0x10 << 14 | 0x00 << 7 | 0x01, sysExData, 3);
+ }
+ */
}
// musicInterface_KillAll
Commit: 89e6ffc2e6153e6f860c0ca4232460e3cbd0d69a
https://github.com/scummvm/scummvm/commit/89e6ffc2e6153e6f860c0ca4232460e3cbd0d69a
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Use MT-32/GM MidiDriver
This change adds the MT-32/GM multisource MidiDriver to LotT. This adds the
following functionality:
- MT-32 initialization using the SysEx queue. ScummVM will remain responsive
while the SysExes are sent and the user can abort the process when skipping the
introduction or quitting the game.
- Use of Roland GS MT-32 instrument mapping.
It also allows for a proper implementation of music fade-outs. Some
functionality previously implemented in SoundManager is now done by the driver.
Changed paths:
engines/lure/intro.cpp
engines/lure/lure.cpp
engines/lure/sound.cpp
engines/lure/sound.h
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index 9a4451f7b0..5b3d58acda 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -108,7 +108,9 @@ bool Introduction::show() {
if (showScreen(start_screens[3], start_screens[3] + 1, 5000, false))
return true;
- Sound.initCustomTimbres();
+ bool result = Sound.initCustomTimbres(true);
+ if (result)
+ return true;
// Fade out title screen
if (!isEGA)
@@ -120,7 +122,6 @@ bool Introduction::show() {
// Animated screens
AnimationSequence *anim;
- bool result;
uint8 currentSound = 0xff;
const AnimRecord *curr_anim = anim_screens;
for (; curr_anim->resourceId; ++curr_anim) {
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index 6a4795498a..6f1634d420 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -165,7 +165,9 @@ Common::Error LureEngine::go() {
Sound.loadSection(ROLAND_MAIN_SYSEX_RESOURCE_ID);
Sound.initCustomTimbres();
}
+ }
+ if (!shouldQuit()) {
// Play the game
_saveLoadAllowed = true;
Sound.loadSection(Sound.isRoland() ? ROLAND_MAIN_SOUND_RESOURCE_ID : ADLIB_MAIN_SOUND_RESOURCE_ID);
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index ad6f852bb2..347e41b64a 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -22,6 +22,7 @@
#include "lure/sound.h"
#include "lure/game.h"
+#include "lure/lure.h"
#include "lure/memory.h"
#include "lure/res.h"
#include "lure/room.h"
@@ -54,21 +55,18 @@ SoundManager::SoundManager() {
_nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
Common::fill(_channelsInUse, _channelsInUse + NUM_CHANNELS, false);
+ Common::fill(_sourcesInUse, _sourcesInUse + LURE_MAX_SOURCES, false);
- _driver = MidiDriver::createMidi(dev);
- int statusCode = _driver->open();
- if (statusCode) {
- warning("Sound driver returned error code %d", statusCode);
- _driver = NULL;
-
+ if (_isRoland) {
+ _driver = _mt32Driver = new MidiDriver_MT32GM(MT_MT32);
} else {
- if (_nativeMT32) {
- _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- _driver->sendMT32Reset();
- } else {
- _driver->sendGMReset();
- }
+ _driver = MidiDriver::createMidi(dev);
+ }
+ int statusCode = _driver->open();
+ if (statusCode)
+ error("Sound driver returned error code %d", statusCode);
+ if (!_isRoland) {
for (index = 0; index < NUM_CHANNELS; ++index) {
_channelsInner[index].midiChannel = _driver->allocateChannel();
/* 90 is power on default for midi compliant devices */
@@ -144,9 +142,9 @@ void SoundManager::loadSection(uint16 sectionId) {
_driver->setTimerCallback(this, &onTimer);
}
-void SoundManager::initCustomTimbres() {
- if (!_isRoland || !_nativeMT32 || _driver == NULL)
- return;
+bool SoundManager::initCustomTimbres(bool canAbort) {
+ if (!_isRoland || !_nativeMT32 || _mt32Driver == NULL)
+ return false;
if (!_soundData)
error("SoundManager::initCustomTimbres - sound section has not been specified");
@@ -156,13 +154,13 @@ void SoundManager::initCustomTimbres() {
uint16 timbreDataHeaderOffset = _soundsTotal * 4 + 2;
if (timbreDataHeaderOffset + 6 > headerSize) {
warning("SoundManager::initCustomTimbres - could not find timbre data header");
- return;
+ return false;
}
uint32 timbreDataOffset = READ_LE_UINT32(_soundData->data() + timbreDataHeaderOffset + 2); // Skip past end of header mark
if (timbreDataOffset + 17259 > _soundData->size()) {
warning("SoundManager::initCustomTimbres - timbre data smaller than expected");
- return;
+ return false;
}
byte *timbreData = _soundData->data() + timbreDataOffset;
@@ -175,7 +173,7 @@ void SoundManager::initCustomTimbres() {
uint32 address = 0x10 << 14; // 10 00 00
static const uint8 systemAreaSysExLengths[5] = { 1, 3, 9, 9, 1 };
for (int i = 0; i < 5; ++i) {
- mt32SysEx(address, timbreData, systemAreaSysExLengths[i]);
+ _mt32Driver->sysExMT32(timbreData, systemAreaSysExLengths[i], address, true);
address += systemAreaSysExLengths[i];
timbreData += systemAreaSysExLengths[i];
}
@@ -183,7 +181,7 @@ void SoundManager::initCustomTimbres() {
address = 0x03 << 14; // 03 00 00
int sysexLength = 16;
for (int i = 0; i < 8; ++i) {
- mt32SysEx(address, timbreData, sysexLength);
+ _mt32Driver->sysExMT32(timbreData, sysexLength, address, true);
address += sysexLength;
timbreData += sysexLength;
}
@@ -191,7 +189,7 @@ void SoundManager::initCustomTimbres() {
address = 0x08 << 14; // 08 00 00
sysexLength = 246;
for (int i = 0; i < 64; ++i) {
- mt32SysEx(address, timbreData, sysexLength);
+ _mt32Driver->sysExMT32(timbreData, sysexLength, address, true);
address += 256;
timbreData += sysexLength;
}
@@ -199,7 +197,7 @@ void SoundManager::initCustomTimbres() {
address = 0x05 << 14; // 05 00 00
sysexLength = 8;
for (int i = 0; i < 128; ++i) {
- mt32SysEx(address, timbreData, sysexLength);
+ _mt32Driver->sysExMT32(timbreData, sysexLength, address, true);
address += sysexLength;
timbreData += sysexLength;
}
@@ -207,63 +205,31 @@ void SoundManager::initCustomTimbres() {
address = 0x03 << 14 | 0x01 << 7 | 0x10; // 03 01 10
sysexLength = 4;
for (int i = 0; i < 85; ++i) {
- mt32SysEx(address, timbreData, sysexLength);
+ _mt32Driver->sysExMT32(timbreData, sysexLength, address, true);
address += sysexLength;
timbreData += sysexLength;
}
- icon->hide();
- delete icon;
-}
-
-void SoundManager::mt32SysEx(const uint32 targetAddress, const byte *dataPtr, uint8 length) {
- byte sysExMessage[270];
- uint16 sysExPos = 0;
- byte sysExByte;
- uint16 sysExChecksum = 0;
-
- memset(&sysExMessage, 0, sizeof(sysExMessage));
-
- sysExMessage[0] = 0x41; // Roland
- sysExMessage[1] = 0x10;
- sysExMessage[2] = 0x16; // Model MT32
- sysExMessage[3] = 0x12; // Command DT1
-
- sysExChecksum = 0;
-
- sysExMessage[4] = (targetAddress >> 14) & 0x7F;
- sysExMessage[5] = (targetAddress >> 7) & 0x7F;
- sysExMessage[6] = targetAddress & 0x7F;
-
- for (byte targetAddressByte = 4; targetAddressByte < 7; targetAddressByte++) {
- assert(sysExMessage[targetAddressByte] < 0x80); // security check
- sysExChecksum -= sysExMessage[targetAddressByte];
- }
-
- sysExPos = 7;
- for (int i = 0; i < length; ++i) {
- sysExByte = *dataPtr++;
-
- assert(sysExPos < sizeof(sysExMessage));
- assert(sysExByte < 0x80); // security check
- sysExMessage[sysExPos++] = sysExByte;
- sysExChecksum -= sysExByte;
+ // Wait until SysExes have been transmitted.
+ bool result = false;
+ while (!_mt32Driver->isReady()) {
+ Events &events = Events::getReference();
+
+ if (events.interruptableDelay(100)) {
+ if (LureEngine::getReference().shouldQuit() ||
+ (canAbort && events.type() == Common::EVENT_KEYDOWN && events.event().kbd.keycode == 27)) {
+ // User has quit the game or pressed Escape.
+ _mt32Driver->clearSysExQueue();
+ result = true;
+ break;
+ }
+ }
}
- // Calculate checksum
- assert(sysExPos < sizeof(sysExMessage));
- sysExMessage[sysExPos++] = sysExChecksum & 0x7F;
-
- _driver->sysEx(sysExMessage, sysExPos);
-
- // Wait the time it takes to send the SysEx data
- uint32 delay = (length + 2) * 1000 / 3125;
-
- // Plus an additional delay for the MT-32 rev00
- if (_nativeMT32)
- delay += 40;
+ icon->hide();
+ delete icon;
- g_system->delayMillis(delay);
+ return result;
}
void SoundManager::bellsBodge() {
@@ -420,17 +386,21 @@ void SoundManager::syncSounds() {
_musicVolume = mute ? 0 : MIN(256, ConfMan.getInt("music_volume"));
_sfxVolume = mute ? 0 : MIN(256, ConfMan.getInt("sfx_volume"));
- _soundMutex.lock();
- MusicListIterator i;
- for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
- // FIXME This should not override the sound resource volume
- // on the MidiMusic object.
- if ((*i)->isMusic())
- (*i)->setVolume(_musicVolume);
- else
- (*i)->setVolume(_sfxVolume);
+ if (_isRoland) {
+ _mt32Driver->syncSoundSettings();
+ } else {
+ _soundMutex.lock();
+ MusicListIterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ // FIXME This should not override the sound resource volume
+ // on the MidiMusic object.
+ if ((*i)->isMusic())
+ (*i)->setVolume(_musicVolume);
+ else
+ (*i)->setVolume(_sfxVolume);
+ }
+ _soundMutex.unlock();
}
- _soundMutex.unlock();
}
SoundDescResource *SoundManager::findSound(uint8 soundNumber) {
@@ -573,8 +543,25 @@ void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber, b
}
_soundMutex.lock();
+ int8 source = -1;
+ if (_isRoland) {
+ if (isMusic) {
+ source = 0;
+ } else {
+ for (int i = 1; i < LURE_MAX_SOURCES; ++i) {
+ if (!_sourcesInUse[i]) {
+ source = i;
+ break;
+ }
+ }
+ }
+ if (source == -1)
+ warning("Insufficient sources to play sound %i", soundNumber);
+ else
+ _sourcesInUse[source] = true;
+ }
MidiMusic *sound = new MidiMusic(_driver, _channelsInner, channelNumber, soundNum,
- isMusic, loop, numChannels, soundStart, dataSize);
+ isMusic, loop, source, numChannels, soundStart, dataSize);
_playingSounds.push_back(MusicList::value_type(sound));
_soundMutex.unlock();
}
@@ -591,6 +578,8 @@ void SoundManager::musicInterface_Stop(uint8 soundNumber) {
MusicListIterator i;
for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
if ((*i)->soundNumber() == soundNum) {
+ if ((*i)->source() >= 0)
+ _sourcesInUse[(*i)->source()] = false;
_playingSounds.erase(i);
break;
}
@@ -651,6 +640,7 @@ void SoundManager::musicInterface_KillAll() {
(*i)->stopMusic();
}
+ Common::fill(_sourcesInUse, _sourcesInUse + LURE_MAX_SOURCES, false);
_playingSounds.clear();
_activeSounds.clear();
_soundMutex.unlock();
@@ -712,7 +702,7 @@ void SoundManager::musicInterface_TrashReverb() {
if (_isRoland) {
// Set reverb parameters to mode Room, time 1, level 0
static const byte sysExData[] = { 0x00, 0x00, 0x00 };
- mt32SysEx(0x10 << 14 | 0x00 << 7 | 0x01, sysExData, 3);
+ _mt32Driver->sysExMT32(sysExData, 3, 0x10 << 14 | 0x00 << 7 | 0x01);
}
*/
}
@@ -726,10 +716,13 @@ void SoundManager::musicInterface_TidySounds() {
_soundMutex.lock();
MusicListIterator i = _playingSounds.begin();
while (i != _playingSounds.end()) {
- if (!(*i)->isPlaying())
+ if (!(*i)->isPlaying()) {
+ if ((*i)->source() >= 0)
+ _sourcesInUse[(*i)->source()] = false;
i = _playingSounds.erase(i);
- else
+ } else {
++i;
+ }
}
_soundMutex.unlock();
}
@@ -758,9 +751,12 @@ void SoundManager::doTimer() {
/*------------------------------------------------------------------------*/
MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
- uint8 channelNum, uint8 soundNum, bool isMus, bool loop, uint8 numChannels, void *soundData, uint32 size) {
+ uint8 channelNum, uint8 soundNum, bool isMus, bool loop, int8 source, uint8 numChannels, void *soundData, uint32 size) {
_driver = driver;
assert(_driver);
+ _mt32Driver = dynamic_cast<MidiDriver_MT32GM *>(_driver);
+ assert(!Sound.isRoland() || _mt32Driver);
+ _source = source;
_channels = channels;
_soundNumber = soundNum;
_channelNumber = channelNum;
@@ -774,7 +770,7 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
// TODO AdLib does not use sound resource volume, so use fixed 240.
setVolume(Sound.isRoland() ? 0x80 : 240);
- _parser = MidiParser::createParser_SMF();
+ _parser = MidiParser::createParser_SMF(source);
_parser->setMidiDriver(this);
_parser->setTimerRate(_driver->getBaseTempo());
// All Notes Off on all channels does not work with multiple MIDI sources
@@ -812,6 +808,8 @@ MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
MidiMusic::~MidiMusic() {
_parser->unloadMusic();
+ if (Sound.isRoland() && _isPlaying)
+ _mt32Driver->deinitSource(_source);
delete _parser;
delete _decompressedSound;
}
@@ -840,15 +838,21 @@ void MidiMusic::setVolume(int volume) {
void MidiMusic::playMusic() {
debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::PlayMusic playing sound %d", _soundNumber);
+ if (Sound.isRoland() && !_isMusic)
+ _mt32Driver->allocateSourceChannels(_source, _numChannels);
_parser->loadMusic(_soundData, _soundSize);
_parser->setTrack(0);
_isPlaying = true;
}
void MidiMusic::send(uint32 b) {
+ send(-1, b);
+}
+
+void MidiMusic::send(int8 source, uint32 b) {
byte channel;
- if (Sound.isRoland() && _isMusic) {
- // Use the channel as defined in the MIDI data
+ if (Sound.isRoland()) {
+ // Channel mapping is handled by the driver
channel = b & 0x0F;
} else {
// Remap data channel to (one of) the channel(s) assigned to this player
@@ -856,13 +860,7 @@ void MidiMusic::send(uint32 b) {
if ((b & 0xF) >= _numChannels) return;
channel = _channelNumber + (byte)(b & 0x0F);
#else
- if (Sound.isRoland()) {
- // Roland channels start at 1
- channel = _channelNumber + (((byte)(b & 0x0F) - 1) % _numChannels);
- } else {
- // AdLib channels start at 0
- channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
- }
+ channel = _channelNumber + ((byte)(b & 0x0F) % _numChannels);
#endif
if ((channel >= NUM_CHANNELS) || (_channels[channel].midiChannel == NULL))
@@ -873,21 +871,22 @@ void MidiMusic::send(uint32 b) {
// Adjust volume changes by song and master volume
byte volume = (byte)((b >> 16) & 0x7F);
_channels[channel].volume = volume;
- uint16 master_volume = _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
- if (Sound.isRoland()) {
+ if (!Sound.isRoland()) {
+ // Scale volume for AdLib only.
// MT-32 sound resource volume is applied to note velocity,
- // so scale MIDI data volume only with ScummVM master volume.
- volume = (volume * master_volume) >> 8;
- } else {
+ // and user volume scaling is handled by the driver.
// TODO AdLib might use velocity for sound resource volume
// as well.
+ uint16 master_volume = _isMusic ? Sound.musicVolume() : Sound.sfxVolume();
volume = volume * _volume * master_volume / 65025;
}
b = (b & 0xFF00FFFF) | (volume << 16);
- } else if ((b & 0xF0) == 0xC0) {
- if (Sound.isRoland() && !Sound.hasNativeMT32() && channel != 9) {
- b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
- }
+ } else if ((b & 0xFFF0) == 0x18B0) {
+ if (Sound.isRoland())
+ // Some tracks use CC 18. This is undefined in the MIDI standard
+ // and does nothing on an MT-32. Not sending this to the device
+ // in case it is a GM device with non-standard behavior for this CC.
+ return;
} else if ((b & 0xFFF0) == 0x007BB0) {
// No implementation
} else if (((b & 0xF0) == 0x90)) {
@@ -907,18 +906,23 @@ void MidiMusic::send(uint32 b) {
}
}
- if (Sound.isRoland() && _isMusic) {
- _driver->send(b);
+ if (Sound.isRoland()) {
+ _driver->send(source, b);
} else {
_channels[channel].midiChannel->send(b);
}
}
void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
+ metaEvent(-1, type, data, length);
+}
+
+void MidiMusic::metaEvent(int8 source, byte type, byte *data, uint16 length) {
//Only thing we care about is End of Track.
if (type != 0x2F)
return;
+ _driver->metaEvent(source, type, data, length);
stopMusic();
}
@@ -931,6 +935,8 @@ void MidiMusic::stopMusic() {
debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::stopMusic sound %d", _soundNumber);
_isPlaying = false;
_parser->unloadMusic();
+ if (Sound.isRoland())
+ _mt32Driver->deinitSource(_source);
}
} // End of namespace Lure
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index e58eb7274e..a863ffd094 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -32,6 +32,7 @@
#include "common/ptr.h"
#include "audio/mididrv.h"
+#include "audio/mt32gm.h"
class MidiParser;
class MidiChannel;
@@ -39,6 +40,7 @@ class MidiChannel;
namespace Lure {
#define NUM_CHANNELS 16
+#define LURE_MAX_SOURCES 10
struct ChannelEntry {
MidiChannel *midiChannel;
@@ -55,6 +57,8 @@ private:
uint8 *_soundData;
uint8 _soundSize;
MidiDriver *_driver;
+ MidiDriver_MT32GM *_mt32Driver;
+ int8 _source;
MidiParser *_parser;
ChannelEntry *_channels;
bool _isMusic;
@@ -68,7 +72,7 @@ private:
public:
MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS],
- uint8 channelNum, uint8 soundNum, bool isMus, bool loop, uint8 numChannels, void *soundData, uint32 size);
+ uint8 channelNum, uint8 soundNum, bool isMus, bool loop, int8 source, uint8 numChannels, void *soundData, uint32 size);
~MidiMusic() override;
void setVolume(int volume);
int getVolume() const { return _volume; }
@@ -83,12 +87,15 @@ public:
// MidiDriver_BASE interface implementation
void send(uint32 b) override;
+ void send(int8 source, uint32 b) override;
void metaEvent(byte type, byte *data, uint16 length) override;
+ void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
void onTimer();
uint8 channelNumber() const { return _channelNumber; }
uint8 soundNumber() const { return _soundNumber; }
+ int8 source() const { return _source; }
bool isPlaying() const { return _isPlaying; }
bool isMusic() const { return _isMusic; }
};
@@ -102,6 +109,7 @@ private:
int _numDescs;
SoundDescResource *soundDescs() { return (SoundDescResource *) _descs->data(); }
MidiDriver *_driver;
+ MidiDriver_MT32GM *_mt32Driver;
typedef Common::List<Common::SharedPtr<SoundDescResource> > SoundList;
typedef SoundList::iterator SoundListIterator;
SoundList _activeSounds;
@@ -110,6 +118,7 @@ private:
MusicList _playingSounds;
ChannelEntry _channelsInner[NUM_CHANNELS];
bool _channelsInUse[NUM_CHANNELS];
+ bool _sourcesInUse[LURE_MAX_SOURCES];
bool _isPlaying;
bool _nativeMT32;
bool _isRoland;
@@ -124,7 +133,6 @@ private:
void musicInterface_TidySounds();
static void onTimer(void *data);
void doTimer();
- void mt32SysEx(const uint32 targetAddress, const byte *dataPtr, uint8 length);
public:
SoundManager();
@@ -134,7 +142,7 @@ public:
void loadFromStream(Common::ReadStream *stream);
void loadSection(uint16 sectionId);
- void initCustomTimbres();
+ bool initCustomTimbres(bool canAbort = false);
void killSounds();
void addSound(uint8 soundIndex, bool tidyFlag = true);
void addSound2(uint8 soundIndex);
@@ -157,7 +165,7 @@ public:
uint16 sfxVolume() const { return _sfxVolume; }
// The following methods implement the external sound player module
- void musicInterface_Initialize();
+ //void musicInterface_Initialize();
void musicInterface_Play(uint8 soundNumber, uint8 channelNumber, bool isMusic = false, uint8 numChannels = 4);
void musicInterface_Stop(uint8 soundNumber);
bool musicInterface_CheckPlaying(uint8 soundNumber);
Commit: 81c514ac8f263604148b9478e3ae42d6dc37f5be
https://github.com/scummvm/scummvm/commit/81c514ac8f263604148b9478e3ae42d6dc37f5be
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Add MT-32 initialization icon blinking
Changed paths:
engines/lure/sound.cpp
engines/lure/surface.cpp
engines/lure/surface.h
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 347e41b64a..c82f3c466f 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -166,6 +166,7 @@ bool SoundManager::initCustomTimbres(bool canAbort) {
AudioInitIcon *icon = new AudioInitIcon();
icon->show();
+ uint32 iconTime = g_system->getMillis();
// Send SysExes
@@ -215,7 +216,7 @@ bool SoundManager::initCustomTimbres(bool canAbort) {
while (!_mt32Driver->isReady()) {
Events &events = Events::getReference();
- if (events.interruptableDelay(100)) {
+ if (events.interruptableDelay(10)) {
if (LureEngine::getReference().shouldQuit() ||
(canAbort && events.type() == Common::EVENT_KEYDOWN && events.event().kbd.keycode == 27)) {
// User has quit the game or pressed Escape.
@@ -224,6 +225,12 @@ bool SoundManager::initCustomTimbres(bool canAbort) {
break;
}
}
+
+ // Blink the audio initialization icon every 500 ms
+ if (g_system->getMillis() > iconTime + 500) {
+ icon->toggleVisibility();
+ iconTime = g_system->getMillis();
+ }
}
icon->hide();
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index 3390185d61..b48d6b7fd6 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -1435,7 +1435,7 @@ void CopyProtectionDialog::chooseCharacters() {
screen.update();
}
-AudioInitIcon::AudioInitIcon() {
+AudioInitIcon::AudioInitIcon() : _visible(false) {
if (LureEngine::getReference().isEGA()) {
// The icon is not shown on EGA
_iconSurface = 0;
@@ -1460,12 +1460,12 @@ AudioInitIcon::~AudioInitIcon() {
}
void AudioInitIcon::show() {
- // TODO The icon should blink
if (!LureEngine::getReference().isEGA()) {
Screen &screen = Screen::getReference();
_iconSurface->copyTo(&screen.screen(), 0, 185);
screen.update();
+ _visible = true;
}
}
@@ -1475,6 +1475,15 @@ void AudioInitIcon::hide() {
screen.screen().fillRect(Common::Rect(0, 185, 14, 199), 0);
screen.update();
+ _visible = false;
+ }
+}
+
+void AudioInitIcon::toggleVisibility() {
+ if (_visible) {
+ hide();
+ } else {
+ show();
}
}
diff --git a/engines/lure/surface.h b/engines/lure/surface.h
index 60ff1e22b8..239a37635c 100644
--- a/engines/lure/surface.h
+++ b/engines/lure/surface.h
@@ -148,10 +148,13 @@ public:
class AudioInitIcon {
private:
Surface *_iconSurface;
+ bool _visible;
public:
AudioInitIcon();
~AudioInitIcon();
+
+ void toggleVisibility();
void show();
void hide();
};
Commit: 20d5307bb99a952f1653d820067fae4ab41cedd3
https://github.com/scummvm/scummvm/commit/20d5307bb99a952f1653d820067fae4ab41cedd3
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Stop MIDI notes when pausing
When pausing the game by bringing up the ScummVM menu, the MIDI notes would
hang. I've added code to pause and resume the active MIDI parsers, which stops
the active notes.
Changed paths:
engines/lure/sound.cpp
engines/lure/sound.h
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index c82f3c466f..18b6b2d437 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -92,6 +92,7 @@ SoundManager::~SoundManager() {
delete _soundData;
if (_driver) {
+ _driver->stopAllNotes();
_driver->close();
delete _driver;
_driver = NULL;
@@ -510,6 +511,35 @@ void SoundManager::fadeOut() {
musicInterface_KillAll();
}
+void SoundManager::pause() {
+ _paused = true;
+
+ _soundMutex.lock();
+
+ MusicListIterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ (**i).pauseMusic();
+ }
+
+ _soundMutex.unlock();
+
+ // Terminate any hanging notes, just in case
+ _driver->stopAllNotes();
+}
+
+void SoundManager::resume() {
+ _paused = false;
+
+ _soundMutex.lock();
+
+ MusicListIterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ (**i).resumeMusic();
+ }
+
+ _soundMutex.unlock();
+}
+
/*------------------------------------------------------------------------*/
// musicInterface_Play
@@ -946,4 +976,12 @@ void MidiMusic::stopMusic() {
_mt32Driver->deinitSource(_source);
}
+void MidiMusic::pauseMusic() {
+ _parser->pausePlaying();
+}
+
+void MidiMusic::resumeMusic() {
+ _parser->resumePlaying();
+}
+
} // End of namespace Lure
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index a863ffd094..68a985ea3e 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -81,6 +81,8 @@ public:
void stopSong() { stopMusic(); }
void playMusic();
void stopMusic();
+ void pauseMusic();
+ void resumeMusic();
void queueTuneList(int16 tuneList);
bool queueSong(uint16 songNum);
void toggleVChange();
@@ -156,8 +158,8 @@ public:
void removeSounds();
void restoreSounds();
void fadeOut();
- void pause() { _paused = true; }
- void resume() { _paused = false; }
+ void pause();
+ void resume();
bool getPaused() const { return _paused; }
bool hasNativeMT32() const { return _nativeMT32; }
bool isRoland() const { return _isRoland; }
Commit: f134e41b8cbd85a29a8f446c891f09402ce33ebf
https://github.com/scummvm/scummvm/commit/f134e41b8cbd85a29a8f446c891f09402ce33ebf
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Don't send aftertouch to MT-32
Some tracks in LotT contain channel aftertouch events. These are not supported
by the MT-32 and the original interpreter does not send them to the MIDI
device. This change removes them from the MIDI output.
Changed paths:
engines/lure/sound.cpp
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 18b6b2d437..f0b8766fa5 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -941,6 +941,14 @@ void MidiMusic::send(int8 source, uint32 b) {
// Strip velocity
b &= 0xFF00FFFF;
}
+ } else if (((b & 0xF0) == 0xD0)) {
+ // Channel aftertouch
+ if (Sound.isRoland()) {
+ // Some tracks contain aftertouch events, but the MT-32 does
+ // not support this and the original interpreter does not send
+ // them to the device.
+ return;
+ }
}
if (Sound.isRoland()) {
Commit: ae3c9777a919f4fa2e1addebdd7f4e5e892ff3e4
https://github.com/scummvm/scummvm/commit/ae3c9777a919f4fa2e1addebdd7f4e5e892ff3e4
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Fix warnings for missing init and unsigned/signed
Changed paths:
engines/lure/scripts.cpp
engines/lure/sound.cpp
diff --git a/engines/lure/scripts.cpp b/engines/lure/scripts.cpp
index 1088b81cc4..9a6486983c 100644
--- a/engines/lure/scripts.cpp
+++ b/engines/lure/scripts.cpp
@@ -48,7 +48,7 @@ static const uint16 *hotspot_dealloc_set[4] = {&dealloc_list_1[0], &dealloc_list
static const AnimSoundSequence soundList[] = {
{9, 0x45, 2, 0, true}, {27, 0x48, 5, 0, false}, {24, 0x46, 3, 0, false}, {24, 0x37, 1, 0, false}, {3, 0x37, 1, 1, false},
{3, 0x37, 1, 2, false}, {3, 0x37, 1, 3, false}, {3, 0x37, 1, 4, false}, {4, 0x37, 1, 5, false}, {7, 0x47, 4, 6, false},
- {31, 0x00, 6, 0, true}, {0, 0, 0, 0}
+ {31, 0x00, 6, 0, true}, {0, 0, 0, 0, false}
};
/*------------------------------------------------------------------------*/
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index f0b8766fa5..96fc1c8d87 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -153,7 +153,7 @@ bool SoundManager::initCustomTimbres(bool canAbort) {
// Locate timbre data
uint32 headerSize = READ_LE_UINT32(_soundData->data() + 2); // Skip past the number of sounds
uint16 timbreDataHeaderOffset = _soundsTotal * 4 + 2;
- if (timbreDataHeaderOffset + 6 > headerSize) {
+ if (timbreDataHeaderOffset + 6u > headerSize) {
warning("SoundManager::initCustomTimbres - could not find timbre data header");
return false;
}
Commit: 58d710d10fec3f73f1f3e7a6ea0845f61edb6e59
https://github.com/scummvm/scummvm/commit/58d710d10fec3f73f1f3e7a6ea0845f61edb6e59
Author: NMIError (crampen at gmail.com)
Date: 2020-12-06T16:37:08Z
Commit Message:
LURE: Update lure.dat with music icon and water sound fix
Changed paths:
dists/engine-data/lure.dat
diff --git a/dists/engine-data/lure.dat b/dists/engine-data/lure.dat
index 8ca69224da..1855613dee 100644
Binary files a/dists/engine-data/lure.dat and b/dists/engine-data/lure.dat differ
More information about the Scummvm-git-logs
mailing list