diff options
-rw-r--r-- | engines/sci/resource.h | 5 | ||||
-rw-r--r-- | engines/sci/resource_audio.cpp | 115 |
2 files changed, 76 insertions, 44 deletions
diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 8e91a601dc..bdf46efc62 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -380,7 +380,7 @@ public: void setAudioLanguage(int language); int getAudioLanguage() const; - void changeAudioDirectory(const Common::String &path); + void changeAudioDirectory(Common::String path); bool isGMTrackIncluded(); bool isSci11Mac() const { return _volVersion == kResVersionSci11Mac; } ViewType getViewType() const { return _viewType; } @@ -465,7 +465,8 @@ protected: int _maxMemoryLRU; ViewType _viewType; // Used to determine if the game has EGA or VGA graphics - Common::List<ResourceSource *> _sources; + typedef Common::List<ResourceSource *> SourcesList; + SourcesList _sources; int _memoryLocked; ///< Amount of resource bytes in locked memory int _memoryLRU; ///< Amount of resource bytes under LRU control Common::List<Resource *> _LRU; ///< Last Resource Used list diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 741968b293..9fd5dc00e6 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -991,62 +991,93 @@ bool ResourceManager::addAudioSources() { return true; } -void ResourceManager::changeAudioDirectory(const Common::String &path) { - // Resources must be cleared before ResourceSources because the destructor - // of a Resource accesses its own ResourceSource - ResourceMap::iterator resIt = _resMap.begin(); - while (resIt != _resMap.end()) { - Resource *resource = resIt->_value; - ResourceType type = resource->getType(); - if (type == kResourceTypeMap || - type == kResourceTypeAudio36 || - type == kResourceTypeSync36) { - - if (type == kResourceTypeMap && resource->getNumber() == 65535) { - ++resIt; +void ResourceManager::changeAudioDirectory(Common::String path) { + if (!path.empty()) { + path += "/"; + } + + const Common::String resAudPath = path + "RESOURCE.AUD"; + + if (!SearchMan.hasFile(resAudPath)) { + error("Could not find %s", resAudPath.c_str()); + } + + // When a IntMapResourceSource is scanned, it will not update existing + // resources. There is also no guarantee that there are exactly the same + // number of audio36/sync36/map resources in each audio directory. + // Therefore, all of these resources must be deleted before scanning. + for (ResourceMap::iterator it = _resMap.begin(); it != _resMap.end(); ++it) { + const ResourceType type = it->_key.getType(); + + if (type == kResourceTypeMap || type == kResourceTypeAudio36 || type == kResourceTypeSync36) { + if (type == kResourceTypeMap && it->_key.getNumber() == 65535) { continue; } - if (resource->_status == kResStatusLocked) { - resource->_lockers = 1; - unlockResource(resource); - } - if (resource->_status == kResStatusEnqueued) { - removeFromLRU(resource); + Resource *resource = it->_value; + if (resource) { + // If one of these resources ends up being locked here, it + // probably means Audio32 is using it and we need to stop + // playback of audio before switching directories + assert(!resource->isLocked()); + + if (resource->_status == kResStatusEnqueued) { + removeFromLRU(resource); + } + + // A PatchResourceSource is not added to _sources and is + // automatically deleted when the corresponding Resource is + // deleted + delete resource; } - delete resource; - _resMap.erase(resIt); - } - ++resIt; + _resMap.erase(it); + } } - Common::List<ResourceSource *>::iterator sourceIt = _sources.begin(); - while (sourceIt != _sources.end()) { - ResourceSource *source = *sourceIt; - ResSourceType sourceType = source->getSourceType(); - if ((sourceType == kSourceIntMap && source->_volumeNumber != 65535) || - (sourceType == kSourceAudioVolume && source->getLocationName() != "RESOURCE.SFX")) { + for (SourcesList::iterator it = _sources.begin(); it != _sources.end(); ) { + IntMapResourceSource *mapSource = dynamic_cast<IntMapResourceSource *>(*it); + if (mapSource && mapSource->_mapNumber != 65535) { + delete *it; + it = _sources.erase(it); + continue; + } - sourceIt = _sources.erase(sourceIt); - delete source; - } else { - ++sourceIt; + AudioVolumeResourceSource *volSource = dynamic_cast<AudioVolumeResourceSource *>(*it); + if (volSource && volSource->getLocationName().contains("RESOURCE.AUD")) { + delete volSource; + it = _sources.erase(it); + continue; } + + ++it; } - const Common::String audioResourceName = (path.empty() ? "" : path + "/") + "RESOURCE.AUD"; + // # is used as the first pattern character to avoid matching non-audio maps + // like RESOURCE.MAP + Common::ArchiveMemberList mapFiles; + SearchMan.listMatchingMembers(mapFiles, path + "#*.MAP"); - Common::List<ResourceId> resources = listResources(kResourceTypeMap); - Common::List<ResourceId>::iterator it; - for (it = resources.begin(); it != resources.end(); ++it) { - // Don't readd 65535.map or resource.sfx - if (it->getNumber() == 65535) + for (Common::ArchiveMemberList::const_iterator it = mapFiles.begin(); it != mapFiles.end(); ++it) { + const Common::ArchiveMemberPtr &file = *it; + assert(file); + + const Common::String fileName = file->getName(); + const int mapNo = atoi(fileName.c_str()); + + // Sound effects are the same across all audio directories, so ignore + // any new SFX map + if (mapNo == 65535) { continue; + } + + ResourceSource *newSource = new PatchResourceSource(path + fileName); + processPatch(newSource, kResourceTypeMap, mapNo); + Resource *mapResource = _resMap.getVal(ResourceId(kResourceTypeMap, mapNo)); + assert(mapResource); - const Resource *mapResource = _resMap.getVal(*it); - ResourceSource *src = addSource(new IntMapResourceSource(mapResource->getResourceLocation(), 0, it->getNumber())); - addSource(new AudioVolumeResourceSource(this, audioResourceName, src, 0)); + ResourceSource *audioMap = addSource(new IntMapResourceSource(mapResource->getResourceLocation(), 0, mapNo)); + addSource(new AudioVolumeResourceSource(this, resAudPath, audioMap, 0)); } scanNewSources(); |