[Scummvm-git-logs] scummvm master -> 67b72cc5a81b64697efc30098b3a36f2b102f3bb

csnover csnover at users.noreply.github.com
Wed May 10 17:55:27 CEST 2017


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
dd13c3be43 SCI: Fix support for ScummVM compressed audio volumes
67b72cc5a8 SCI: Remove unused Robot code from SCI16 audio code


Commit: dd13c3be43b2566d7ee6449be7918a86428bb4da
    https://github.com/scummvm/scummvm/commit/dd13c3be43b2566d7ee6449be7918a86428bb4da
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-05-10T10:55:00-05:00

Commit Message:
SCI: Fix support for ScummVM compressed audio volumes

The runtime code for this had previously relied on hot patching
volume file offsets at the moment that a resource was loaded,
instead of correcting file offsets when reading audio maps. The
code added for sanity checking audio volumes started to report
warnings because the offsets being received were for the original
uncompressed audio volume, which (naturally) is larger than the
compressed audio volume.

This commit also deduplicates code between addResource and
updateResource, and tweaks a validation-related error message for
improved clarity.

Fixes Trac#9764.

Changed paths:
    engines/sci/resource.cpp
    engines/sci/resource_audio.cpp
    engines/sci/resource_intern.h


diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 91cceb5..2f34f8f 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -2013,20 +2013,7 @@ bool ResourceManager::validateResource(const ResourceId &resourceId, const Commo
 void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::String &sourceMapLocation) {
 	// Adding new resource only if it does not exist
 	if (_resMap.contains(resId) == false) {
-		Common::SeekableReadStream *volumeFile = getVolumeFile(src);
-		if (volumeFile == nullptr) {
-			error("Could not open %s for reading", src->getLocationName().c_str());
-		}
-
-		if (validateResource(resId, sourceMapLocation, src->getLocationName(), offset, size, volumeFile->size())) {
-			Resource *res = new Resource(this, resId);
-			_resMap.setVal(resId, res);
-			res->_source = src;
-			res->_fileOffset = offset;
-			res->_size = size;
-		} else {
-			_hasBadResources = true;
-		}
+		updateResource(resId, src, offset, size, sourceMapLocation);
 	}
 }
 
@@ -2048,6 +2035,13 @@ Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src,
 		error("Could not open %s for reading", src->getLocationName().c_str());
 	}
 
+	AudioVolumeResourceSource *avSrc = dynamic_cast<AudioVolumeResourceSource *>(src);
+	if (avSrc != nullptr && !avSrc->relocateMapOffset(offset, size)) {
+		warning("Compressed volume %s does not contain a valid entry for %s (map offset %u)", src->getLocationName().c_str(), resId.toString().c_str(), offset);
+		_hasBadResources = true;
+		return res;
+	}
+
 	if (validateResource(resId, sourceMapLocation, src->getLocationName(), offset, size, volumeFile->size())) {
 		if (res == nullptr) {
 			res = new Resource(this, resId);
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index a5501cd..2cd157a 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -36,7 +36,6 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, co
 	: VolumeResourceSource(name, map, volNum, kSourceAudioVolume) {
 
 	_audioCompressionType = 0;
-	_audioCompressionOffsetMapping = NULL;
 
 	/*
 	 * Check if this audio volume got compressed by our tool. If that is the
@@ -49,36 +48,37 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, co
 		return;
 
 	fileStream->seek(0, SEEK_SET);
-	uint32 compressionType = fileStream->readUint32BE();
+	const uint32 compressionType = fileStream->readUint32BE();
 	switch (compressionType) {
 	case MKTAG('M','P','3',' '):
 	case MKTAG('O','G','G',' '):
 	case MKTAG('F','L','A','C'):
-		// Detected a compressed audio volume
 		_audioCompressionType = compressionType;
-		// Now read the whole offset mapping table for later usage
-		int32 recordCount = fileStream->readUint32LE();
-		if (!recordCount)
-			error("compressed audio volume doesn't contain any entries");
-		int32 *offsetMapping = new int32[(recordCount + 1) * 2];
-		_audioCompressionOffsetMapping = offsetMapping;
-		for (int recordNo = 0; recordNo < recordCount; recordNo++) {
-			*offsetMapping++ = fileStream->readUint32LE();
-			*offsetMapping++ = fileStream->readUint32LE();
+		const uint32 numEntries = fileStream->readUint32LE();
+		if (!numEntries) {
+			error("Compressed audio volume %s has no relocation table entries", name.c_str());
 		}
-		// Put ending zero
-		*offsetMapping++ = 0;
-		*offsetMapping++ = fileStream->size();
+
+		CompressedTableEntry *lastEntry = nullptr;
+		for (uint i = 0; i < numEntries; ++i) {
+			CompressedTableEntry nextEntry;
+			const uint32 sourceOffset = fileStream->readUint32LE();
+			nextEntry.offset = fileStream->readUint32LE();
+			if (lastEntry != nullptr) {
+				lastEntry->size = nextEntry.offset - lastEntry->offset;
+			}
+
+			_compressedOffsets.setVal(sourceOffset, nextEntry);
+			lastEntry = &_compressedOffsets.getVal(sourceOffset);
+		}
+
+		lastEntry->size = fileStream->size() - lastEntry->offset;
 	}
 
 	if (_resourceFile)
 		delete fileStream;
 }
 
-AudioVolumeResourceSource::~AudioVolumeResourceSource() {
-	delete[] _audioCompressionOffsetMapping;
-}
-
 bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) {
 	byte *ptr = new byte[_size];
 	_data = ptr;
@@ -315,7 +315,7 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
 	Common::SeekableReadStream *fileStream = getVolumeFile(src);
 
 	if (!fileStream) {
-		warning("Failed to open file stream for %s", mapResId.toString().c_str());
+		warning("Failed to open file stream for %s", src->getLocationName().c_str());
 		return SCI_ERROR_NO_RESOURCE_FILES_FOUND;
 	}
 
@@ -383,17 +383,21 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
 			offset = ptr.getUint32LE();
 			ptr += 4;
 
-			// The size is not stored in the map and the entries have no order.
-			// We need to dig into the audio resource in the volume to get the size.
-			stream->seek(offset + 1);
-			byte headerSize = stream->readByte();
-			if (headerSize != 11 && headerSize != 12) {
-				error("Unexpected header size in %s: should be 11 or 12, got %d", audioResId.toString().c_str(), headerSize);
-			}
-
-			stream->skip(7);
-			uint32 size = stream->readUint32LE() + headerSize + 2;
+			uint32 size;
+			if (src->getAudioCompressionType() == 0) {
+				// The size is not stored in the map and the entries have no order.
+				// We need to dig into the audio resource in the volume to get the size.
+				stream->seek(offset + 1);
+				byte headerSize = stream->readByte();
+				if (headerSize != 11 && headerSize != 12) {
+					error("Unexpected header size in %s: should be 11 or 12, got %d", audioResId.toString().c_str(), headerSize);
+				}
 
+				stream->skip(7);
+				size = stream->readUint32LE() + headerSize + 2;
+			} else {
+				size = 0;
+			}
 			addResource(audioResId, src, offset, size, map->getLocationName());
 		}
 	} else {
@@ -406,7 +410,7 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
 
 		while (ptr != mapRes->cend()) {
 			uint32 n = ptr.getUint32BE();
-			int syncSize = 0;
+			uint32 syncSize = 0;
 			ptr += 4;
 
 			if (n == 0xffffffff)
@@ -436,7 +440,7 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
 			if (g_sci->getGameId() == GID_KQ6 && (n & 0x40)) {
 				// This seems to define the size of raw lipsync data (at least
 				// in KQ6 CD Windows).
-				int kq6HiresSyncSize = ptr.getUint16LE();
+				uint32 kq6HiresSyncSize = ptr.getUint16LE();
 				ptr += 2;
 
 				if (kq6HiresSyncSize > 0) {
@@ -924,52 +928,16 @@ void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource *
 	if (!fileStream)
 		return;
 
-	if (_audioCompressionType) {
-		// this file is compressed, so lookup our offset in the offset-translation table and get the new offset
-		//  also calculate the compressed size by using the next offset
-		int32 *mappingTable = _audioCompressionOffsetMapping;
-		int32 compressedOffset = 0;
-
-		do {
-			if (*mappingTable == res->_fileOffset) {
-				mappingTable++;
-				compressedOffset = *mappingTable;
-				// Go to next compressed offset and use that to calculate size of compressed sample
-				switch (res->getType()) {
-				case kResourceTypeSync:
-				case kResourceTypeSync36:
-				case kResourceTypeRave:
-					// we should already have a (valid) size
-					break;
-				default:
-					mappingTable += 2;
-					res->_size = *mappingTable - compressedOffset;
-				}
-				break;
-			}
-			mappingTable += 2;
-		} while (*mappingTable);
-
-		if (!compressedOffset)
-			error("could not translate offset to compressed offset in audio volume");
-		fileStream->seek(compressedOffset, SEEK_SET);
-
-		switch (res->getType()) {
-		case kResourceTypeAudio:
-		case kResourceTypeAudio36:
-			// Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1
-			res->loadFromAudioVolumeSCI1(fileStream);
-			if (_resourceFile)
-				delete fileStream;
-			return;
-		default:
-			break;
-		}
-	} else {
-		// original file, directly seek to given offset and get SCI1/SCI1.1 audio resource
-		fileStream->seek(res->_fileOffset, SEEK_SET);
-	}
-	if (getSciVersion() < SCI_VERSION_1_1)
+	fileStream->seek(res->_fileOffset, SEEK_SET);
+
+	// For compressed audio, using loadFromAudioVolumeSCI1 is a hack to bypass
+	// the resource type checking in loadFromAudioVolumeSCI11 (since
+	// loadFromAudioVolumeSCI1 does nothing more than read raw data)
+	if (_audioCompressionType != 0 &&
+		(res->getType() == kResourceTypeAudio ||
+		 res->getType() == kResourceTypeAudio36)) {
+		res->loadFromAudioVolumeSCI1(fileStream);
+	} else if (getSciVersion() < SCI_VERSION_1_1)
 		res->loadFromAudioVolumeSCI1(fileStream);
 	else
 		res->loadFromAudioVolumeSCI11(fileStream);
diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h
index f198edd..ea3e056 100644
--- a/engines/sci/resource_intern.h
+++ b/engines/sci/resource_intern.h
@@ -144,17 +144,35 @@ public:
 
 class AudioVolumeResourceSource : public VolumeResourceSource {
 protected:
+	struct CompressedTableEntry {
+		uint32 offset;
+		uint32 size;
+	};
+
 	uint32 _audioCompressionType;
-	int32 *_audioCompressionOffsetMapping;
+	Common::HashMap<uint32, CompressedTableEntry> _compressedOffsets;
 
 public:
 	AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum);
 
-	virtual ~AudioVolumeResourceSource();
-
 	virtual void loadResource(ResourceManager *resMan, Resource *res);
 
 	virtual uint32 getAudioCompressionType() const;
+
+	bool relocateMapOffset(uint32 &offset, uint32 &size) const {
+		if (_audioCompressionType == 0) {
+			return true;
+		}
+
+		if (!_compressedOffsets.contains(offset)) {
+			return false;
+		}
+
+		const CompressedTableEntry &entry = _compressedOffsets.getVal(offset);
+		offset = entry.offset;
+		size = entry.size;
+		return true;
+	}
 };
 
 class ExtAudioMapResourceSource : public ResourceSource {


Commit: 67b72cc5a81b64697efc30098b3a36f2b102f3bb
    https://github.com/scummvm/scummvm/commit/67b72cc5a81b64697efc30098b3a36f2b102f3bb
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-05-10T10:55:00-05:00

Commit Message:
SCI: Remove unused Robot code from SCI16 audio code

Changed paths:
    engines/sci/sound/audio.cpp
    engines/sci/sound/audio.h


diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index 273c4c1..ad5dec6 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -329,11 +329,6 @@ static byte *readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size,
 	return buffer;
 }
 
-byte *AudioPlayer::getDecodedRobotAudioFrame(Common::SeekableReadStream *str, uint32 encodedSize) {
-	byte flags = 0;
-	return readSOLAudio(str, encodedSize, kSolFlagCompressed | kSolFlag16Bit, flags);
-}
-
 Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 volume, int *sampleLen) {
 	Audio::SeekableAudioStream *audioSeekStream = 0;
 	Audio::RewindableAudioStream *audioStream = 0;
diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h
index 3d25dca..4d0d311 100644
--- a/engines/sci/sound/audio.h
+++ b/engines/sci/sound/audio.h
@@ -61,7 +61,6 @@ public:
 	void setAudioRate(uint16 rate) { _audioRate = rate; }
 	Audio::SoundHandle *getAudioHandle() { return &_audioHandle; }
 	Audio::RewindableAudioStream *getAudioStream(uint32 number, uint32 volume, int *sampleLen);
-	byte *getDecodedRobotAudioFrame(Common::SeekableReadStream *str, uint32 encodedSize);
 	int getAudioPosition();
 	int startAudio(uint16 module, uint32 tuple);
 	int wPlayAudio(uint16 module, uint32 tuple);





More information about the Scummvm-git-logs mailing list