aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sword1/sound.cpp49
1 files changed, 37 insertions, 12 deletions
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 319a9f27a5..d994ebf69b 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -262,29 +262,54 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
headerPos++;
if (headerPos < 100) {
int32 resSize;
+ int16 *srcData;
+ uint32 srcPos;
+ int16 length;
+ cSize /= 2;
headerPos += 4; // skip 'data' tag
if (_cowMode != CowDemo) {
resSize = READ_LE_UINT32(fBuf + headerPos) >> 1;
headerPos += 4;
} else {
- // the demo speech files have the uncompressed size embedded
- // in the compressed stream *sigh*
- if (READ_LE_UINT16(fBuf + headerPos) == 1) {
- resSize = READ_LE_UINT16(fBuf + headerPos + 2);
- resSize |= READ_LE_UINT16(fBuf + headerPos + 6) << 16;
- } else
- resSize = READ_LE_UINT32(fBuf + headerPos + 2);
- resSize >>= 1;
+ // the demo speech files have the uncompressed size
+ // embedded in the compressed stream *sigh*
+ //
+ // But not always, apparently. See bug #2182450. Is
+ // there any way to figure out the size other than
+ // decoding the sound in that case?
+
+ if (fBuf[headerPos + 1] == 0) {
+ if (READ_LE_UINT16(fBuf + headerPos) == 1) {
+ resSize = READ_LE_UINT16(fBuf + headerPos + 2);
+ resSize |= READ_LE_UINT16(fBuf + headerPos + 6) << 16;
+ } else
+ resSize = READ_LE_UINT32(fBuf + headerPos + 2);
+ resSize >>= 1;
+ } else {
+ resSize = 0;
+ srcData = (int16*)fBuf;
+ srcPos = headerPos >> 1;
+ while (srcPos < cSize) {
+ length = (int16)READ_LE_UINT16(srcData + srcPos);
+ srcPos++;
+ if (length < 0) {
+ resSize -= length;
+ srcPos++;
+ } else {
+ resSize += length;
+ srcPos += length;
+ }
+ }
+ }
}
assert(!(headerPos & 1));
- int16 *srcData = (int16*)fBuf;
- uint32 srcPos = headerPos >> 1;
- cSize /= 2;
+ srcData = (int16*)fBuf;
+ srcPos = headerPos >> 1;
uint32 dstPos = 0;
int16 *dstData = (int16*)malloc(resSize * 2);
int32 samplesLeft = resSize;
while (srcPos < cSize && samplesLeft > 0) {
- int16 length = (int16)READ_LE_UINT16(srcData + srcPos);
+ length = (int16)READ_LE_UINT16(srcData + srcPos);
srcPos++;
if (length < 0) {
length = -length;