diff options
author | Johannes Schickel | 2014-06-04 01:49:31 +0200 |
---|---|---|
committer | Johannes Schickel | 2014-06-04 01:49:31 +0200 |
commit | 02f47dd497710330f89c28d640e21623da180c06 (patch) | |
tree | 2d0d829df0147249bfcfcf83f7b58401fa9ef8c1 /engines/scumm/players | |
parent | b5ca6b01f9e6748908f5acdcdb08e0dd448e60f1 (diff) | |
download | scummvm-rg350-02f47dd497710330f89c28d640e21623da180c06.tar.gz scummvm-rg350-02f47dd497710330f89c28d640e21623da180c06.tar.bz2 scummvm-rg350-02f47dd497710330f89c28d640e21623da180c06.zip |
SCUMM: Allow multiple SFX to be played at once with AD.
Actually, even before this change it was possible. However, since we formerly
used the original channel specification it was not possible when two sfx were
started on the same channel. Now we can play such sounds simultaneously again.
This is a first step towards a AdLib support level we had when we tried to
convert SFX to MIDI to play it through iMuse. However, now we still play the
sound effects properly, i.e. they still sound like in the original.
Diffstat (limited to 'engines/scumm/players')
-rw-r--r-- | engines/scumm/players/player_ad.cpp | 54 | ||||
-rw-r--r-- | engines/scumm/players/player_ad.h | 1 |
2 files changed, 34 insertions, 21 deletions
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp index 3f805fe3ae..33dbd0b55e 100644 --- a/engines/scumm/players/player_ad.cpp +++ b/engines/scumm/players/player_ad.cpp @@ -108,34 +108,26 @@ void Player_AD::startSound(int sound) { // Only try to start a sfx when no music is playing. if (_soundPlaying == -1) { const byte priority = res[0]; - const byte channel = res[1]; - - // Check for out of bounds access - if (channel >= 3) { - warning("AdLib sfx resource %d uses channel %d", sound, channel); + // The original specified the channel to use in the sound + // resource. However, since we play as much as possible we sill + // ignore it and simply use the priority value to determine + // whether the sfx can be played or not. + //const byte channel = res[1]; + + // Try to allocate a sfx slot for playback. + SfxSlot *sfx = allocateSfxSlot(priority); + if (!sfx) { + ::debugC(3, DEBUG_SOUND, "AdLib: No free sfx slot for sound %d", sound); return; } - // Check whether the channel is free or the priority of the new - // sfx resource is above the old one. - if (_sfx[channel].resource != -1) { - if (_sfx[channel].priority > priority) { - return; - } else { - // If we overwrite a channel we will properly stop the old - // sfx slot first. This makes sure that the resource is - // unlocked properly. - stopSfx(&_sfx[channel]); - } - } - // Lock the new resource - _sfx[channel].resource = sound; - _sfx[channel].priority = priority; + sfx->resource = sound; + sfx->priority = priority; _vm->_res->lock(rtSound, sound); // Start the actual sfx resource - startSfx(&_sfx[channel], res); + startSfx(sfx, res); } } @@ -537,6 +529,26 @@ const uint Player_AD::_rhythmChannelTable[6] = { // SFX +Player_AD::SfxSlot *Player_AD::allocateSfxSlot(int priority) { + // First pass: Check whether there's a unused slot + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + if (_sfx[i].resource == -1) { + return &_sfx[i]; + } + } + + // Second pass: Look for a slot with lower priority + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + if (_sfx[i].priority <= priority) { + // Stop the old sfx + stopSfx(&_sfx[i]); + return &_sfx[i]; + } + } + + return nullptr; +} + void Player_AD::startSfx(SfxSlot *sfx, const byte *resource) { writeReg(0xBD, 0x00); diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h index c4292fcaf5..73f3f86cea 100644 --- a/engines/scumm/players/player_ad.h +++ b/engines/scumm/players/player_ad.h @@ -172,6 +172,7 @@ private: Channel channels[3]; } _sfx[3]; + SfxSlot *allocateSfxSlot(int priority); void startSfx(SfxSlot *sfx, const byte *resource); void stopSfx(SfxSlot *sfx); |