From 97463309ba623606850b5d3b0baf7c9bdf9b6fba Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Tue, 19 Aug 2008 11:55:20 +0000 Subject: Fix for bug #2057637: FW: Spaceship glitches in demo (regression). This was caused by assuming in-place decompression is ok, it wasn't, although AFAIK the original did decompression in-place too. Changed unpacking to be done not in-place and the glitch vanished. Also changed the unpacker to also handle uncompressed input data. svn-id: r34034 --- engines/cine/part.cpp | 31 ++++++++++++++----------------- engines/cine/unpack.cpp | 8 ++++++++ engines/cine/unpack.h | 6 +++--- 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp index 657471be4e..7679d9d380 100644 --- a/engines/cine/part.cpp +++ b/engines/cine/part.cpp @@ -123,13 +123,13 @@ void CineEngine::readVolCnf() { unpackedSize = packedSize = f.size(); } uint8 *buf = new uint8[unpackedSize]; - f.read(buf, packedSize); - if (packedSize != unpackedSize) { - CineUnpacker cineUnpacker; - if (!cineUnpacker.unpack(buf, packedSize, buf, unpackedSize)) { - error("Error while unpacking 'vol.cnf' data"); - } + uint8 *packedBuf = new uint8[packedSize]; + f.read(packedBuf, packedSize); + CineUnpacker cineUnpacker; + if (!cineUnpacker.unpack(packedBuf, packedSize, buf, unpackedSize)) { + error("Error while unpacking 'vol.cnf' data"); } + delete[] packedBuf; uint8 *p = buf; int resourceFilesCount = READ_BE_UINT16(p); p += 2; int entrySize = READ_BE_UINT16(p); p += 2; @@ -211,26 +211,23 @@ int16 findFileInBundle(const char *fileName) { } void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize) { + assert(maxSize >= partBuffer[idx].packedSize); setMouseCursor(MOUSE_CURSOR_DISK); g_cine->_partFileHandle.seek(partBuffer[idx].offset, SEEK_SET); - g_cine->_partFileHandle.read(dataPtr, MIN(partBuffer[idx].packedSize, maxSize)); + g_cine->_partFileHandle.read(dataPtr, partBuffer[idx].packedSize); } byte *readBundleFile(int16 foundFileIdx, uint32 *size) { assert(foundFileIdx >= 0 && foundFileIdx < (int32)partBuffer.size()); bool error = false; byte *dataPtr = (byte *)calloc(partBuffer[foundFileIdx].unpackedSize, 1); - readFromPart(foundFileIdx, dataPtr, partBuffer[foundFileIdx].unpackedSize); - if (partBuffer[foundFileIdx].unpackedSize > partBuffer[foundFileIdx].packedSize) { - CineUnpacker cineUnpacker; - error = !cineUnpacker.unpack(dataPtr, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize); - } else if (partBuffer[foundFileIdx].unpackedSize < partBuffer[foundFileIdx].packedSize) { - // Unpacked size of a file should never be less than its packed size - error = true; - } else { // partBuffer[foundFileIdx].unpackedSize == partBuffer[foundFileIdx].packedSize - debugC(5, kCineDebugPart, "Loaded non-compressed file '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName); - } + byte *packedData = (byte *)calloc(partBuffer[foundFileIdx].packedSize, 1); + assert(dataPtr && packedData); + readFromPart(foundFileIdx, packedData, partBuffer[foundFileIdx].packedSize); + CineUnpacker cineUnpacker; + error = !cineUnpacker.unpack(packedData, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize); + free(packedData); if (error) { warning("Error unpacking '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName); diff --git a/engines/cine/unpack.cpp b/engines/cine/unpack.cpp index 5d85ff6cab..7915fd1cf8 100644 --- a/engines/cine/unpack.cpp +++ b/engines/cine/unpack.cpp @@ -100,6 +100,14 @@ bool CineUnpacker::unpack(const byte *src, uint srcLen, byte *dst, uint dstLen) _dstBegin = dst; _dstEnd = dst + dstLen; + // Handle already unpacked data here + if (srcLen == dstLen) { + // Source length is same as destination length so the source + // data is already unpacked. Let's just copy it then. + memcpy(dst, src, srcLen); + return true; + } + // Initialize other variables _src = _srcBegin + srcLen - 4; uint32 unpackedLength = readSource(); // Unpacked length in bytes diff --git a/engines/cine/unpack.h b/engines/cine/unpack.h index e16cb594a9..2355df5ee1 100644 --- a/engines/cine/unpack.h +++ b/engines/cine/unpack.h @@ -35,14 +35,14 @@ namespace Cine { * A LZ77 style decompressor for Delphine's data files * used in at least Future Wars and Operation Stealth. * @note Works backwards in the source and destination buffers. - * @note Can work with source and destination in the same buffer if there's space. + * @warning Having the source and destination in the same buffer when unpacking can cause errors! */ class CineUnpacker { public: /** * Unpacks packed data from the source buffer to the destination buffer. - * @warning Do NOT call this on data that is not packed. - * @note Source and destination buffer pointers can be the same as long as there's space for the unpacked data. + * @note You may call this on already unpacked data but then source length must be equal to destination length. + * @warning The source and destination should not point to the same buffer. If they do, errors may occur! * @param src Pointer to the source buffer. * @param srcLen Length of the source buffer. * @param dst Pointer to the destination buffer. -- cgit v1.2.3