From 0826501ef63c5b8e6b40299d25142a3562c6fde9 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Sun, 8 Jan 2017 22:59:30 -0600 Subject: SCI32: Fix audio, wave, VMD, Duck, CLUT, TGA, ZZZ, Etc patches Specifically, audio patches are used in at least PQ:SWAT (40103.AUD), Lighthouse (9103.AUD), and the GK2 demo (300.AUD). --- engines/sci/resource.cpp | 101 +++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 39 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 921c8c91ef..d71f4353da 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -335,8 +335,7 @@ bool Resource::loadFromPatchFile() { unalloc(); return false; } - // Skip resourceid and header size byte - file.seek(2, SEEK_SET); + file.seek(0, SEEK_SET); return loadPatch(&file); } @@ -1401,21 +1400,56 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource return; } - byte patchType = convertResType(fileStream->readByte()); - int32 patchDataOffset; - if (_volVersion < kResVersionSci2) { - patchDataOffset = fileStream->readByte(); - } else if (patchType == kResourceTypeView) { - fileStream->seek(3, SEEK_SET); - patchDataOffset = fileStream->readByte() + 22 + 2; - } else if (patchType == kResourceTypePic) { - patchDataOffset = 2; - } else if (patchType == kResourceTypePalette) { - fileStream->seek(3, SEEK_SET); - patchDataOffset = fileStream->readByte() + 2; + byte patchType; + if (fileStream->readUint32BE() == MKTAG('R','I','F','F')) { + fileStream->seek(-4, SEEK_CUR); + patchType = kResourceTypeAudio; } else { - patchDataOffset = 0; + fileStream->seek(-4, SEEK_CUR); + patchType = convertResType(fileStream->readByte()); + } + + enum { + kExtraHeaderSize = 2, ///< extra header used in gfx resources + kViewHeaderSize = 22 ///< extra header used in view resources + }; + + int32 patchDataOffset = kResourceHeaderSize; + if (_volVersion < kResVersionSci2) { + patchDataOffset += fileStream->readByte(); + } +#ifdef ENABLE_SCI32 + else { + switch (patchType) { + case kResourceTypeView: + fileStream->seek(3, SEEK_SET); + patchDataOffset += fileStream->readByte() + kViewHeaderSize + kExtraHeaderSize; + break; + case kResourceTypePic: + patchDataOffset += kExtraHeaderSize; + break; + case kResourceTypePalette: + fileStream->seek(3, SEEK_SET); + patchDataOffset += fileStream->readByte() + kExtraHeaderSize; + break; + case kResourceTypeWave: + case kResourceTypeAudio: + case kResourceTypeAudio36: + case kResourceTypeVMD: + case kResourceTypeDuck: + case kResourceTypeClut: + case kResourceTypeTGA: + case kResourceTypeZZZ: + case kResourceTypeEtc: + patchDataOffset = 0; + break; + default: + fileStream->seek(1, SEEK_SET); + patchDataOffset += fileStream->readByte(); + break; + } } +#endif delete fileStream; @@ -1427,15 +1461,15 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly if (patchDataOffset & 0x80) { - switch (patchDataOffset & 0x7F) { + switch ((patchDataOffset - kResourceHeaderSize) & 0x7F) { case 0: - patchDataOffset = 24; + patchDataOffset = kResourceHeaderSize + 24; break; case 1: - patchDataOffset = 2; + patchDataOffset = kResourceHeaderSize + 2; break; case 4: - patchDataOffset = 8; + patchDataOffset = kResourceHeaderSize + 8; break; default: error("Resource patch unsupported special case %X", patchDataOffset & 0x7F); @@ -1443,15 +1477,15 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource } } - if (patchDataOffset + 2 >= fsize) { + if (patchDataOffset >= fsize) { debug("Patching %s failed - patch starting at offset %d can't be in file of size %d", - source->getLocationName().c_str(), patchDataOffset + 2, fsize); + source->getLocationName().c_str(), patchDataOffset, fsize); delete source; return; } // Overwrite everything, because we're patching - newrsc = updateResource(resId, source, fsize - patchDataOffset - 2); + newrsc = updateResource(resId, source, fsize - patchDataOffset); newrsc->_headerSize = patchDataOffset; newrsc->_fileOffset = 0; @@ -2084,28 +2118,17 @@ int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file _data = ptr; _status = kResStatusAllocated; errorNum = ptr ? dec->unpack(file, ptr, szPacked, _size) : SCI_ERROR_RESOURCE_TOO_BIG; - if (errorNum) + if (errorNum) { unalloc(); - else { + } else { // At least Lighthouse puts sound effects in RESSCI.00n/RESSCI.PAT // instead of using a RESOURCE.SFX if (getType() == kResourceTypeAudio) { - _headerSize = ptr[1]; - assert(_headerSize == 12); + const uint8 headerSize = ptr[1]; + assert(headerSize >= 11); uint32 audioSize = READ_LE_UINT32(ptr + 9); - assert(audioSize + _headerSize + 2 == _size); - _size = audioSize; - - // TODO: This extra memory copying is necessary because - // AudioVolumeResourceSource splits the audio header from the rest - // of the data; fix AudioVolumeResourceSource to stop doing this and - // then this extra copying can be eliminated too - byte *dataPtr = new byte[_size]; - _data = dataPtr; - _header = new byte[_headerSize]; - memcpy(_header, ptr + 2, _headerSize); - memcpy(dataPtr, ptr + 2 + _headerSize, _size); - delete[] ptr; + assert(audioSize + headerSize + kResourceHeaderSize == _size); + _size = headerSize + audioSize; } } -- cgit v1.2.3