aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorJohannes Schickel2014-06-22 16:51:27 +0200
committerJohannes Schickel2014-06-22 16:51:27 +0200
commite3aad13cd75e800e6890868c2a625da4cfd774d6 (patch)
tree1871f7e02125cc7366361957fd12c799287d3960 /engines/scumm
parenta21c9ef913179fcceef82e2e926e8fc78665f8b0 (diff)
downloadscummvm-rg350-e3aad13cd75e800e6890868c2a625da4cfd774d6.tar.gz
scummvm-rg350-e3aad13cd75e800e6890868c2a625da4cfd774d6.tar.bz2
scummvm-rg350-e3aad13cd75e800e6890868c2a625da4cfd774d6.zip
SCUMM: Change channel/slot (re)allocation strategy in AD player.
This makes sure that always the channel/slot with the lowest priority is reallocated in case none is free. This fixes some music oddities in Indy3.
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/players/player_ad.cpp67
1 files changed, 37 insertions, 30 deletions
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index a8d9dbfc6a..ba75bdd922 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -302,37 +302,41 @@ void Player_AD::setupVolume() {
}
int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) {
- // First pass: Check whether there's any unallocated channel
+ // We always reaLlocate the channel with the lowest priority in case none
+ // is free.
+ int channel = -1;
+ int minPrio = priority;
+
for (int i = 0; i < _numHWChannels; ++i) {
if (!_hwChannels[i].allocated) {
- _hwChannels[i].allocated = true;
- _hwChannels[i].priority = priority;
- _hwChannels[i].sfxOwner = owner;
- return i;
+ channel = i;
+ break;
}
- }
- // Second pass: Reassign channels based on priority
- for (int i = 0; i < _numHWChannels; ++i) {
// We don't allow SFX to reallocate their own channels. Otherwise we
// would call stopSfx in the midst of startSfx and that can lead to
// horrible states...
- if (_hwChannels[i].priority <= priority && (!owner || _hwChannels[i].sfxOwner != owner)) {
- // In case the HW channel belongs to a SFX we will completely
- // stop playback of that SFX.
- // TODO: Maybe be more fine grained in the future and allow
- // detachment of individual channels of a SFX?
- if (_hwChannels[i].sfxOwner) {
- stopSfx(_hwChannels[i].sfxOwner);
- }
- _hwChannels[i].allocated = true;
- _hwChannels[i].priority = priority;
- _hwChannels[i].sfxOwner = owner;
- return i;
+ if (_hwChannels[i].priority <= minPrio && (!owner || _hwChannels[i].sfxOwner != owner)) {
+ minPrio = _hwChannels[i].priority;
+ channel = i;
+ }
+ }
+
+ if (channel != -1) {
+ // In case the HW channel belongs to a SFX we will completely
+ // stop playback of that SFX.
+ // TODO: Maybe be more fine grained in the future and allow
+ // detachment of individual channels of a SFX?
+ if (_hwChannels[channel].allocated && _hwChannels[channel].sfxOwner) {
+ stopSfx(_hwChannels[channel].sfxOwner);
}
+
+ _hwChannels[channel].allocated = true;
+ _hwChannels[channel].priority = priority;
+ _hwChannels[channel].sfxOwner = owner;
}
- return -1;
+ return channel;
}
void Player_AD::freeHWChannel(int channel) {
@@ -762,23 +766,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
+ // We always reaLlocate the slot with the lowest priority in case none is
+ // free.
+ SfxSlot *sfx = nullptr;
+ int minPrio = priority;
+
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
if (_sfx[i].resource == -1) {
return &_sfx[i];
+ } else if (_sfx[i].priority <= minPrio) {
+ minPrio = _sfx[i].priority;
+ sfx = &_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];
- }
+ // In case we reallocate a slot stop the old one.
+ if (sfx) {
+ stopSfx(sfx);
}
- return nullptr;
+ return sfx;
}
bool Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {