aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-07-23 23:05:31 -0500
committerColin Snover2017-07-24 19:36:28 -0500
commit4c316d45fd2181517ee40aeff1b0b749ec62bf42 (patch)
treebee89ff80b6d7e12b5baef44636c4c26815dfbf9
parent64cbcba420843aa1bb0888b15592ad08fa17dc59 (diff)
downloadscummvm-rg350-4c316d45fd2181517ee40aeff1b0b749ec62bf42.tar.gz
scummvm-rg350-4c316d45fd2181517ee40aeff1b0b749ec62bf42.tar.bz2
scummvm-rg350-4c316d45fd2181517ee40aeff1b0b749ec62bf42.zip
SCI32: Fix ResourceManager::changeAudioDirectory
Fixes Trac#9577.
-rw-r--r--engines/sci/resource.h5
-rw-r--r--engines/sci/resource_audio.cpp115
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();