diff options
Diffstat (limited to 'engines/sci/sound')
-rw-r--r-- | engines/sci/sound/audio32.cpp | 47 | ||||
-rw-r--r-- | engines/sci/sound/audio32.h | 28 |
2 files changed, 70 insertions, 5 deletions
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp index b61bbd9a4e..f47002bb59 100644 --- a/engines/sci/sound/audio32.cpp +++ b/engines/sci/sound/audio32.cpp @@ -354,6 +354,20 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) { #pragma mark - #pragma mark Channel management +uint8 Audio32::getNumUnlockedChannels() const { + Common::StackLock lock(_mutex); + + uint8 numChannels = 0; + for (uint i = 0; i < _numActiveChannels; ++i) { + const AudioChannel &channel = getChannel(i); + if (!channel.robot && Common::find(_lockedResourceIds.begin(), _lockedResourceIds.end(), channel.id) == _lockedResourceIds.end()) { + ++numChannels; + } + } + + return numChannels; +} + int16 Audio32::findChannelByArgs(int argc, const reg_t *argv, const int startIndex, const reg_t soundNode) const { // NOTE: argc/argv are already reduced by one in our engine because // this call is always made from a subop, so no reduction for the @@ -420,6 +434,21 @@ int16 Audio32::findChannelById(const ResourceId resourceId, const reg_t soundNod return kNoExistingChannel; } +void Audio32::lockResource(const ResourceId resourceId, const bool lock) { + Common::StackLock slock(_mutex); + + LockList::iterator it = Common::find(_lockedResourceIds.begin(), _lockedResourceIds.end(), resourceId); + if (it != _lockedResourceIds.end()) { + if (!lock) { + _lockedResourceIds.erase(it); + } + } else { + if (lock) { + _lockedResourceIds.push_back(resourceId); + } + } +} + void Audio32::freeUnusedChannels() { Common::StackLock lock(_mutex); for (int channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) { @@ -1037,10 +1066,6 @@ bool Audio32::hasSignal() const { reg_t Audio32::kernelPlay(const bool autoPlay, const int argc, const reg_t *const argv) { Common::StackLock lock(_mutex); - if (argc == 0) { - return make_reg(0, _numActiveChannels); - } - const int16 channelIndex = findChannelByArgs(argc, argv, 0, NULL_REG); ResourceId resourceId; bool loop; @@ -1214,6 +1239,20 @@ void Audio32::printAudioList(Console *con) const { channel.stopChannelOnFade ? ", stopping" : ""); } } + + if (g_sci->_features->hasSci3Audio()) { + con->debugPrintf("\nLocks: "); + if (_lockedResourceIds.size()) { + const char *separator = ""; + for (LockList::const_iterator it = _lockedResourceIds.begin(); it != _lockedResourceIds.end(); ++it) { + con->debugPrintf("%s%s", separator, it->toString().c_str()); + separator = ", "; + } + } else { + con->debugPrintf("none"); + } + con->debugPrintf("\n"); + } } } // End of namespace Sci diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h index dd48b39865..27f7e8f3a1 100644 --- a/engines/sci/sound/audio32.h +++ b/engines/sci/sound/audio32.h @@ -157,11 +157,13 @@ enum AudioChannelIndex { * engine, since the system mixer does not support all the * features of SCI. */ -class Audio32 : public Audio::AudioStream { +class Audio32 : public Audio::AudioStream, public Common::Serializable { public: Audio32(ResourceManager *resMan); ~Audio32(); + virtual void saveLoadWithSerializer(Common::Serializer &s); + enum { /** * The maximum channel volume. @@ -205,6 +207,19 @@ public: } /** + * Gets the number of currently active channels that are playing from + * unlocked resources. + * + * @note In SSCI, this function would actually return the number of channels + * whose audio data were not loaded into memory. In practice, the signal for + * placing audio data into memory was a call to kLock, so since we do not + * follow how SSCI works when it comes to resource management, the lock + * state is used as an (apparently) successful proxy for this information + * instead. + */ + uint8 getNumUnlockedChannels() const; + + /** * Finds a channel that is already configured for the * given audio sample. * @@ -219,7 +234,13 @@ public: */ int16 findChannelById(const ResourceId resourceId, const reg_t soundNode = NULL_REG) const; + /** + * Sets or clears a lock on the given resource ID. + */ + void lockResource(const ResourceId resourceId, const bool lock); + private: + typedef Common::Array<ResourceId> LockList; typedef Common::Array<Resource *> UnlockList; /** @@ -252,6 +273,11 @@ private: UnlockList _resourcesToUnlock; /** + * The list of resource IDs that have been locked by game scripts. + */ + LockList _lockedResourceIds; + + /** * Gets the audio channel at the given index. */ inline AudioChannel &getChannel(const int16 channelIndex) { |