aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/cine/part.cpp6
-rw-r--r--engines/cine/unpack.cpp101
-rw-r--r--engines/cine/unpack.h20
3 files changed, 72 insertions, 55 deletions
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index 0ce8dfdb21..535bf841d5 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -127,7 +127,8 @@ void CineEngine::readVolCnf() {
uint8 *buf = new uint8[unpackedSize];
f.read(buf, packedSize);
if (packedSize != unpackedSize) {
- if (!delphineUnpack(buf, buf, packedSize)) {
+ CineUnpacker cineUnpacker;
+ if (!cineUnpacker.unpack(buf, buf, packedSize)) {
error("Error while unpacking 'vol.cnf' data");
}
}
@@ -224,7 +225,8 @@ byte *readBundleFile(int16 foundFileIdx) {
if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) {
byte *unpackBuffer = (byte *)malloc(partBuffer[foundFileIdx].packedSize);
readFromPart(foundFileIdx, unpackBuffer);
- delphineUnpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize);
+ CineUnpacker cineUnpacker;
+ cineUnpacker.unpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize);
free(unpackBuffer);
} else {
readFromPart(foundFileIdx, dataPtr);
diff --git a/engines/cine/unpack.cpp b/engines/cine/unpack.cpp
index 4409af4b07..ef761e87f1 100644
--- a/engines/cine/unpack.cpp
+++ b/engines/cine/unpack.cpp
@@ -30,94 +30,91 @@
namespace Cine {
-struct UnpackCtx {
- int size, datasize;
- uint32 crc;
- uint32 chk;
- byte *dst;
- const byte *src;
-};
+uint32 CineUnpacker::readSource() {
+ uint32 value = READ_BE_UINT32(_src);
+ _src -= 4;
+ return value;
+}
-static int rcr(UnpackCtx *uc, int CF) {
- int rCF = (uc->chk & 1);
- uc->chk >>= 1;
+int CineUnpacker::rcr(int CF) {
+ int rCF = (_chk & 1);
+ _chk >>= 1;
if (CF) {
- uc->chk |= 0x80000000;
+ _chk |= 0x80000000;
}
return rCF;
}
-static int nextChunk(UnpackCtx *uc) {
- int CF = rcr(uc, 0);
- if (uc->chk == 0) {
- uc->chk = READ_BE_UINT32(uc->src); uc->src -= 4;
- uc->crc ^= uc->chk;
- CF = rcr(uc, 1);
+int CineUnpacker::nextChunk() {
+ int CF = rcr(0);
+ if (_chk == 0) {
+ _chk = readSource();
+ _crc ^= _chk;
+ CF = rcr(1);
}
return CF;
}
-static uint16 getCode(UnpackCtx *uc, byte numChunks) {
+uint16 CineUnpacker::getCode(byte numChunks) {
uint16 c = 0;
while (numChunks--) {
c <<= 1;
- if (nextChunk(uc)) {
+ if (nextChunk()) {
c |= 1;
}
}
return c;
}
-static void unpackHelper1(UnpackCtx *uc, byte numChunks, byte addCount) {
- uint16 count = getCode(uc, numChunks) + addCount + 1;
- uc->datasize -= count;
+void CineUnpacker::unpackHelper1(byte numChunks, byte addCount) {
+ uint16 count = getCode(numChunks) + addCount + 1;
+ _datasize -= count;
while (count--) {
- *uc->dst = (byte)getCode(uc, 8);
- --uc->dst;
+ *_dst = (byte)getCode(8);
+ --_dst;
}
}
-static void unpackHelper2(UnpackCtx *uc, byte numChunks) {
- uint16 i = getCode(uc, numChunks);
- uint16 count = uc->size + 1;
- uc->datasize -= count;
+void CineUnpacker::unpackHelper2(byte numChunks) {
+ uint16 i = getCode(numChunks);
+ uint16 count = _size + 1;
+ _datasize -= count;
while (count--) {
- *uc->dst = *(uc->dst + i);
- --uc->dst;
+ *_dst = *(_dst + i);
+ --_dst;
}
}
-bool delphineUnpack(byte *dst, const byte *src, int len) {
- UnpackCtx uc;
- uc.src = src + len - 4;
- uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4;
- uc.dst = dst + uc.datasize - 1;
- uc.size = 0;
- uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4;
- uc.chk = READ_BE_UINT32(uc.src); uc.src -= 4;
- uc.crc ^= uc.chk;
+bool CineUnpacker::unpack(byte *dst, const byte *src, int srcLen) {
+ _src = src + srcLen - 4;
+ _datasize = readSource();
+ _dst = dst + _datasize - 1;
+ _size = 0;
+ _crc = readSource();
+ _chk = readSource();
+ _crc ^= _chk;
do {
- if (!nextChunk(&uc)) {
- uc.size = 1;
- if (!nextChunk(&uc)) {
- unpackHelper1(&uc, 3, 0);
+ if (!nextChunk()) {
+ _size = 1;
+ if (!nextChunk()) {
+ unpackHelper1(3, 0);
} else {
- unpackHelper2(&uc, 8);
+ unpackHelper2(8);
}
} else {
- uint16 c = getCode(&uc, 2);
+ uint16 c = getCode(2);
if (c == 3) {
- unpackHelper1(&uc, 8, 8);
+ unpackHelper1(8, 8);
} else if (c < 2) {
- uc.size = c + 2;
- unpackHelper2(&uc, c + 9);
+ _size = c + 2;
+ unpackHelper2(c + 9);
} else {
- uc.size = getCode(&uc, 8);
- unpackHelper2(&uc, 12);
+ _size = getCode(8);
+ unpackHelper2(12);
}
}
- } while (uc.datasize > 0 && uc.src >= src - 4);
- return uc.crc == 0;
+ } while (_datasize > 0 && _src >= src - 4);
+ return _crc == 0;
}
} // End of namespace Cine
diff --git a/engines/cine/unpack.h b/engines/cine/unpack.h
index 5f57a3531b..9433fafa58 100644
--- a/engines/cine/unpack.h
+++ b/engines/cine/unpack.h
@@ -31,7 +31,25 @@
namespace Cine {
-bool delphineUnpack(byte *dst, const byte *src, int len);
+class CineUnpacker {
+public:
+ /** Returns true if unpacking was successful, otherwise false. */
+ bool unpack(byte *dst, const byte *src, int srcLen);
+private:
+ /** Reads a single big endian 32-bit integer from the source and goes backwards 4 bytes. */
+ uint32 readSource();
+ int rcr(int CF);
+ int nextChunk();
+ uint16 getCode(byte numChunks);
+ void unpackHelper1(byte numChunks, byte addCount);
+ void unpackHelper2(byte numChunks);
+private:
+ int _size, _datasize;
+ uint32 _crc;
+ uint32 _chk;
+ byte *_dst;
+ const byte *_src;
+};
} // End of namespace Cine