diff options
author | Willem Jan Palenstijn | 2013-04-18 23:34:29 +0200 |
---|---|---|
committer | Willem Jan Palenstijn | 2013-05-08 20:39:44 +0200 |
commit | 01f3f3a8dd0ad2891939d03b0ce47cbf36ea9bc6 (patch) | |
tree | 544b07f3aa41abe7907bcd2040cdad11ebc324bb /engines/sci/sound | |
parent | 9cf2c83e5e5a35816ab153bf8443dac691829ea8 (diff) | |
parent | a41d72a44a660c72fdadbc3a8ef580e5e03cb890 (diff) | |
download | scummvm-rg350-01f3f3a8dd0ad2891939d03b0ce47cbf36ea9bc6.tar.gz scummvm-rg350-01f3f3a8dd0ad2891939d03b0ce47cbf36ea9bc6.tar.bz2 scummvm-rg350-01f3f3a8dd0ad2891939d03b0ce47cbf36ea9bc6.zip |
Merge branch 'master'
Diffstat (limited to 'engines/sci/sound')
-rw-r--r-- | engines/sci/sound/drivers/cms.cpp | 1 | ||||
-rw-r--r-- | engines/sci/sound/drivers/gm_names.h | 4 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.cpp | 23 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 7 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.cpp | 112 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.h | 4 |
6 files changed, 98 insertions, 53 deletions
diff --git a/engines/sci/sound/drivers/cms.cpp b/engines/sci/sound/drivers/cms.cpp index ace96ba499..dbcbf3d431 100644 --- a/engines/sci/sound/drivers/cms.cpp +++ b/engines/sci/sound/drivers/cms.cpp @@ -813,4 +813,3 @@ MidiPlayer *MidiPlayer_CMS_create(SciVersion version) { } } // End of namespace SCI - diff --git a/engines/sci/sound/drivers/gm_names.h b/engines/sci/sound/drivers/gm_names.h index bfe5ff88c7..fbfa413a4a 100644 --- a/engines/sci/sound/drivers/gm_names.h +++ b/engines/sci/sound/drivers/gm_names.h @@ -30,7 +30,7 @@ namespace Sci { // is defined #ifndef REDUCE_MEMORY_USAGE -static const char *GmInstrumentNames[] = { +static const char *const GmInstrumentNames[] = { /*000*/ "Acoustic Grand Piano", /*001*/ "Bright Acoustic Piano", /*002*/ "Electric Grand Piano", @@ -162,7 +162,7 @@ static const char *GmInstrumentNames[] = { }; // The GM Percussion map is downwards compatible to the MT32 map, which is used in SCI -static const char *GmPercussionNames[] = { +static const char *const GmPercussionNames[] = { /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 95b165468d..ad7ba7ca36 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -480,11 +480,18 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { info.basic.param2 = 0; if (info.channel() == 0xF) {// SCI special case if (info.basic.param1 != kSetSignalLoop) { - // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately - // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to - // get immediately removed, so we currently filter it. - // Sierra SCI ignores them as well at that time - if ((_position._play_tick) || (info.delta)) { + // At least in kq5/french&mac the first scene in the intro has + // a song that sets signal to 4 immediately on tick 0. Signal + // isn't set at that point by sierra sci and it would cause the + // castle daventry text to get immediately removed, so we + // currently filter it. Sierra SCI ignores them as well at that + // time. However, this filtering should only be performed for + // SCI1 and newer games. Signalling is done differently in SCI0 + // though, so ignoring these signals in SCI0 games will result + // in glitches (e.g. the intro of LB1 Amiga gets stuck - bug + // #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp. + if (_soundVersion <= SCI_VERSION_0_LATE || + _position._play_tick || info.delta) { _signalSet = true; _signalToSet = info.basic.param1; } @@ -626,7 +633,11 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { if (info.ext.type == 0x2F) {// end of track reached if (_pSnd->loop) _pSnd->loop--; - if (_pSnd->loop) { + // QFG3 abuses the hold flag. Its scripts call kDoSoundSetHold, + // but sometimes there's no hold marker in the associated songs + // (e.g. song 110, during the intro). The original interpreter + // treats this case as an infinite loop (bug #3311911). + if (_pSnd->loop || _pSnd->hold > 0) { // We need to play it again... jumpToTick(_loopTick); } else { diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 2afab3858d..9610b6f847 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -63,12 +63,13 @@ void SciMusic::init() { // SCI sound init _dwTempo = 0; - // Default to MIDI in SCI2.1+ games, as many don't have AdLib support. Common::Platform platform = g_sci->getPlatform(); - uint32 deviceFlags = MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI; - if (getSciVersion() >= SCI_VERSION_2_1) + // Default to MIDI in SCI2.1+ games, as many don't have AdLib support. + // Also, default to MIDI for Windows versions of SCI1.1 games, as their + // soundtrack is written for GM. + if (getSciVersion() >= SCI_VERSION_2_1 || g_sci->_features->useAltWinGMSound()) deviceFlags |= MDT_PREFER_GM; // Currently our CMS implementation only supports SCI1(.1) diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 4ea290ff9e..274c532779 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -37,6 +37,15 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM _music = new SciMusic(_soundVersion); _music->init(); + // Check if the user wants synthesized or digital sound effects in SCI1.1 + // or later games + _bMultiMidi = ConfMan.getBool("multi_midi"); + // In SCI2 and later games, this check should always be true - there was + // always only one version of each sound effect or digital music track + // (e.g. the menu music in GK1 - there is a sound effect with the same + // resource number, but it's totally unrelated to the menu music). + if (getSciVersion() >= SCI_VERSION_2) + _bMultiMidi = true; } SoundCommandParser::~SoundCommandParser() { @@ -49,11 +58,54 @@ reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) { return acc; } -void SoundCommandParser::processInitSound(reg_t obj) { - int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number)); +int SoundCommandParser::getSoundResourceId(reg_t obj) { + int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did. - if (g_sci && g_sci->_features->useAltWinGMSound()) - resourceId += 1000; + if (g_sci && g_sci->_features->useAltWinGMSound()) { + // Check if the alternate MIDI song actually exists... + // There are cases where it just doesn't exist (e.g. SQ4, room 530 - + // bug #3392767). In these cases, use the DOS tracks instead. + if (resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, resourceId + 1000))) + resourceId += 1000; + } + + return resourceId; +} + +void SoundCommandParser::initSoundResource(MusicEntry *newSound) { + if (newSound->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, newSound->resourceId))) + newSound->soundRes = new SoundResource(newSound->resourceId, _resMan, _soundVersion); + else + newSound->soundRes = 0; + + // In SCI1.1 games, sound effects are started from here. If we can find + // a relevant audio resource, play it, otherwise switch to synthesized + // effects. If the resource exists, play it using map 65535 (sound + // effects map) + bool checkAudioResource = getSciVersion() >= SCI_VERSION_1_1; + // Hoyle 4 has garbled audio resources in place of the sound resources. + // The demo of GK1 has no alternate sound effects. + if ((g_sci->getGameId() == GID_HOYLE4) || + (g_sci->getGameId() == GID_GK1 && g_sci->isDemo())) + checkAudioResource = false; + + if (checkAudioResource && _resMan->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId))) { + // Found a relevant audio resource, create an audio stream if there is + // no associated sound resource, or if both resources exist and the + // user wants the digital version. + if (_bMultiMidi || !newSound->soundRes) { + int sampleLen; + newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen); + newSound->soundType = Audio::Mixer::kSpeechSoundType; + } + } + + if (!newSound->pStreamAud && newSound->soundRes) + _music->soundInitSnd(newSound); +} + +void SoundCommandParser::processInitSound(reg_t obj) { + int resourceId = getSoundResourceId(obj); // Check if a track with the same sound object is already playing MusicEntry *oldSound = _music->getSlot(obj); @@ -62,11 +114,6 @@ void SoundCommandParser::processInitSound(reg_t obj) { MusicEntry *newSound = new MusicEntry(); newSound->resourceId = resourceId; - if (resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, resourceId))) - newSound->soundRes = new SoundResource(resourceId, _resMan, _soundVersion); - else - newSound->soundRes = 0; - newSound->soundObj = obj; newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF; @@ -77,25 +124,7 @@ void SoundCommandParser::processInitSound(reg_t obj) { debugC(kDebugLevelSound, "kDoSound(init): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), resourceId, newSound->loop, newSound->priority, newSound->volume); - // In SCI1.1 games, sound effects are started from here. If we can find - // a relevant audio resource, play it, otherwise switch to synthesized - // effects. If the resource exists, play it using map 65535 (sound - // effects map) - bool checkAudioResource = getSciVersion() >= SCI_VERSION_1_1; - if (g_sci->getGameId() == GID_HOYLE4) - checkAudioResource = false; // hoyle 4 has garbled audio resources in place of the sound resources - // if we play those, we will only make the user deaf and break speakers. Sierra SCI doesn't play anything - // on soundblaster. FIXME: check, why this is - - if (checkAudioResource && _resMan->testResource(ResourceId(kResourceTypeAudio, resourceId))) { - // Found a relevant audio resource, play it - int sampleLen; - newSound->pStreamAud = _audio->getAudioStream(resourceId, 65535, &sampleLen); - newSound->soundType = Audio::Mixer::kSpeechSoundType; - } else { - if (newSound->soundRes) - _music->soundInitSnd(newSound); - } + initSoundResource(newSound); _music->pushBackSlot(newSound); @@ -105,8 +134,6 @@ void SoundCommandParser::processInitSound(reg_t obj) { writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized); else writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); - - writeSelector(_segMan, obj, SELECTOR(handle), obj); } } @@ -119,14 +146,17 @@ reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { void SoundCommandParser::processPlaySound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("kDoSound(play): Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(play): Slot not found (%04x:%04x), initializing it manually", PRINT_REG(obj)); + // The sound hasn't been initialized for some reason, so initialize it + // here. Happens in KQ6, room 460, when giving the creature (child) to + // the bookworm. Fixes bugs #3413301 and #3421098. + processInitSound(obj); + musicSlot = _music->getSlot(obj); + if (!musicSlot) + error("Failed to initialize uninitialized sound slot"); } - int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; - // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did. - if (g_sci && g_sci->_features->useAltWinGMSound()) - resourceId += 1000; + int resourceId = getSoundResourceId(obj); if (musicSlot->resourceId != resourceId) { // another sound loaded into struct processDisposeSound(obj); @@ -149,6 +179,9 @@ void SoundCommandParser::processPlaySound(reg_t obj) { musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); + // Reset hold when starting a new song. kDoSoundSetHold is always called after + // kDoSoundPlay to set it properly, if needed. Fixes bug #3413589. + musicSlot->hold = -1; if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); @@ -618,13 +651,10 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) } if (value == -1) { - uint16 resourceNr = musicSlot->resourceId; - // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did. - if (g_sci && g_sci->_features->useAltWinGMSound()) - resourceNr += 1000; + uint16 resourceId = musicSlot->resourceId; // Set priority from the song data - Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), 0); + Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0); if (song->data[0] == 0xf0) _music->soundSetPriority(musicSlot, song->data[1]); else diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index a542a8b384..c1dce014d2 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -32,6 +32,7 @@ namespace Sci { class Console; class SciMusic; class SoundCommandParser; +class MusicEntry; //typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value); //struct MusicEntryCommand { @@ -64,6 +65,7 @@ public: void processPlaySound(reg_t obj); void processStopSound(reg_t obj, bool sampleFinishedPlaying); + void initSoundResource(MusicEntry *newSound); MusicType getMusicType() const; @@ -109,10 +111,12 @@ private: SciMusic *_music; AudioPlayer *_audio; SciVersion _soundVersion; + bool _bMultiMidi; void processInitSound(reg_t obj); void processDisposeSound(reg_t obj); void processUpdateCues(reg_t obj); + int getSoundResourceId(reg_t obj); }; } // End of namespace Sci |