aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2014-06-04 01:49:31 +0200
committerJohannes Schickel2014-06-04 01:49:31 +0200
commit02f47dd497710330f89c28d640e21623da180c06 (patch)
tree2d0d829df0147249bfcfcf83f7b58401fa9ef8c1
parentb5ca6b01f9e6748908f5acdcdb08e0dd448e60f1 (diff)
downloadscummvm-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.
-rw-r--r--engines/scumm/players/player_ad.cpp54
-rw-r--r--engines/scumm/players/player_ad.h1
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);