diff options
-rw-r--r-- | engines/kyra/sound_adlib.cpp | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp index 983d3b6031..94a285d729 100644 --- a/engines/kyra/sound_adlib.cpp +++ b/engines/kyra/sound_adlib.cpp @@ -360,13 +360,17 @@ private: uint8 *_soundData; struct QueueEntry { + QueueEntry() : data(0), id(0), volume(0) {} + QueueEntry(uint8 *ptr, uint8 track, uint8 vol) : data(ptr), id(track), volume(vol) {} uint8 *data; + uint8 id; uint8 volume; }; QueueEntry _programQueue[16]; int _programStartTimeout; int _programQueueStart, _programQueueEnd; + bool _retrySounds; void adjustSfxData(uint8 *data, int volume); uint8 *_sfxPointer; @@ -450,6 +454,7 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) { _sfxPointer = 0; _programQueueStart = _programQueueEnd = 0; + _retrySounds = false; } AdLibDriver::~AdLibDriver() { @@ -545,8 +550,7 @@ void AdLibDriver::queueTrack(int track, int volume) { return; } - _programQueue[_programQueueEnd].data = trackData; - _programQueue[_programQueueEnd].volume = volume; + _programQueue[_programQueueEnd] = QueueEntry(trackData, track, volume); _programQueueEnd = (_programQueueEnd + 1) & 15; } @@ -570,6 +574,7 @@ void AdLibDriver::stopAllChannels() { if (channel != 9) noteOff(chan); } + _retrySounds = false; } // timer callback @@ -598,13 +603,25 @@ void AdLibDriver::setupPrograms() { return; uint8 *ptr = _programQueue[_programQueueStart].data; - // Clear the queue entry - _programQueue[_programQueueStart].data = 0; - _programQueueStart = (_programQueueStart + 1) & 15; + + // The AdLib driver (in its old versions used for EOB) is not suitable for modern (fast) CPUs. + // The stop sound track (track 0 which has a priority of 50) will often still be busy when the + // next sound (with a lower priority) starts which will cause that sound to be skipped. We simply + // restart incoming sounds during stop sound execution. + // UPDATE: This stilly applies after introduction of the _programQueue. + QueueEntry retrySound; + if (_version < 3 && _programQueue[_programQueueStart].id == 0) + _retrySounds = true; + else if (_retrySounds) + retrySound = _programQueue[_programQueueStart]; // Adjust data in case we hit a sound effect. adjustSfxData(ptr, _programQueue[_programQueueStart].volume); + // Clear the queue entry + _programQueue[_programQueueStart].data = 0; + _programQueueStart = (_programQueueStart + 1) & 15; + const int chan = *ptr++; const int priority = *ptr++; @@ -632,6 +649,13 @@ void AdLibDriver::setupPrograms() { // This is (probably) required to assure that the sfx are started with // the correct priority and velocity. _programStartTimeout = 2; + + retrySound = QueueEntry(); + } + + if (retrySound.data) { + debugC(9, kDebugLevelSound, "AdLibDriver::setupPrograms(): WORKAROUND - Restarting skipped sound %d)", retrySound.id); + queueTrack(retrySound.id, retrySound.volume); } } |