aboutsummaryrefslogtreecommitdiff
path: root/engines/cine/unpack.cpp
diff options
context:
space:
mode:
authorGregory Montoir2006-02-25 18:26:16 +0000
committerGregory Montoir2006-02-25 18:26:16 +0000
commit164f35b8788a43aaa3807ab9cc2c46f74e0a592d (patch)
treee64d5b469af7a44fcf4ddad17f679329a6687d74 /engines/cine/unpack.cpp
parentbb4d4631385dbd9bec4dc67f9040878c92f41b26 (diff)
downloadscummvm-rg350-164f35b8788a43aaa3807ab9cc2c46f74e0a592d.tar.gz
scummvm-rg350-164f35b8788a43aaa3807ab9cc2c46f74e0a592d.tar.bz2
scummvm-rg350-164f35b8788a43aaa3807ab9cc2c46f74e0a592d.zip
cleanup unpacking function and get rid of an old hack to prevent buffer overflows.
svn-id: r20884
Diffstat (limited to 'engines/cine/unpack.cpp')
-rw-r--r--engines/cine/unpack.cpp180
1 files changed, 68 insertions, 112 deletions
diff --git a/engines/cine/unpack.cpp b/engines/cine/unpack.cpp
index bd09180289..5eb8bc32fb 100644
--- a/engines/cine/unpack.cpp
+++ b/engines/cine/unpack.cpp
@@ -26,130 +26,86 @@
namespace Cine {
-uint32 crc; // variable at 5C5A
-uint32 bitbucket; // dx:bx
-
-uint16 swap16(uint16 r) {
- return (r >> 8) | (r << 8);
+static int rcr(UnpackCtx *uc, int CF) {
+ int rCF = (uc->chk & 1);
+ uc->chk >>= 1;
+ if (CF) {
+ uc->chk |= 0x80000000;
+ }
+ return rCF;
}
-#define loadd(p, d) {\
- d = *(--p);\
- d |= (*(--p)) << 8;\
- d |= (*(--p)) << 16;\
- d |= (*(--p)) << 24;\
-}
-#define store(p, b) *(--p) = b
-#define getbit(p, b) { \
- b = bitbucket & 1; \
- bitbucket >>= 1; \
- if (!bitbucket) { \
- loadd(p, bitbucket); \
- crc ^= bitbucket; \
- b = bitbucket & 1; \
- bitbucket >>= 1; \
- bitbucket |= 0x80000000;\
- } \
+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);
+ }
+ return CF;
}
-#define loadbits(p, b) { \
- b = 0; \
- do { \
- getbit(p, bit); \
- b <<= 1; \
- b |= bit; \
- nbits--; \
- } while (nbits); \
+static uint16 getCode(UnpackCtx *uc, uint8 numChunks) {
+ uint16 c = 0;
+ while (numChunks--) {
+ c <<= 1;
+ if (nextChunk(uc)) {
+ c |= 1;
+ }
+ }
+ return c;
}
-int decomp(uint8 *in, uint8 *out, int size) {
- uint8 bit; // Carry flag
- uint8 nbits; // cl
- uint8 byte = 0; // ch
- uint16 counter; // bp
- uint16 var = 0; // variable at 5C58
- uint16 ptr;
- uint16 flags;
-
- enum {
- DO_COPY,
- DO_UNPACK
- } action;
+static void unpackHelper1(UnpackCtx *uc, uint8 numChunks, uint8 addCount) {
+ uint16 count = getCode(uc, numChunks) + addCount + 1;
+ uc->datasize -= count;
+ while (count--) {
+ *uc->dst = (uint8)getCode(uc, 8);
+ --uc->dst;
+ }
+}
- loadd(in, crc);
- loadd(in, bitbucket);
- crc ^= bitbucket;
+static void unpackHelper2(UnpackCtx *uc, uint8 numChunks) {
+ uint16 i = getCode(uc, numChunks);
+ uint16 count = uc->size + 1;
+ uc->datasize -= count;
+ while (count--) {
+ *uc->dst = *(uc->dst + i);
+ --uc->dst;
+ }
+}
- do { // 5A4C
- getbit(in, bit);
- if (!bit) { // 5A94
- getbit(in, bit);
- if (!bit) { // 5AC8
- nbits = 3;
- byte = 0;
- action = DO_COPY;
- } else { // 5ACA
- var = 1;
- nbits = 8;
- action = DO_UNPACK;
+bool delphineUnpack(uint8 *dst, const uint8 *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;
+ do {
+ if (!nextChunk(&uc)) {
+ uc.size = 1;
+ if (!nextChunk(&uc)) {
+ unpackHelper1(&uc, 3, 0);
+ } else {
+ unpackHelper2(&uc, 8);
}
- } else { // 5B4F
- nbits = 2;
- loadbits(in, flags);
- if (flags < 2) {
- nbits = flags + 9; // 5BC3
- var = flags + 2;
- action = DO_UNPACK;
- } else if (flags == 3) {
- nbits = 8; // 5B4A
- byte = 8;
- action = DO_COPY;
+ } else {
+ uint16 c = getCode(&uc, 2);
+ if (c == 3) {
+ unpackHelper1(&uc, 8, 8);
+ } else if (c < 2) {
+ uc.size = c + 2;
+ unpackHelper2(&uc, c + 9);
} else {
- nbits = 8;
- loadbits(in, var);
- nbits = 12;
- action = DO_UNPACK;
+ uc.size = getCode(&uc, 8);
+ unpackHelper2(&uc, 12);
}
}
-
- switch (action) {
- case DO_COPY:
- {
- // 5AD1
- loadbits(in, counter); // 5AFD
- counter += byte;
- counter++;
- size -= counter;
- do {
- nbits = 8;
- loadbits(in, byte); // 5B3F
- store(out, byte);
- counter--;
- } while (counter); // 5B45
- break;
- }
-
- case DO_UNPACK:
-
- // 5BD3
- loadbits(in, ptr); // 5BFF
- counter = var + 1;
- size -= counter;
- do {
- byte = *(out + ptr - 1);
- store(out, byte);
- counter--;
- } while (counter);
- }
- } while (size > 0);
-
- // 5C32
- // ???
- if (crc) {
- return -1;
- } else {
- return 0;
- }
+ } while (uc.datasize > 0);
+ return uc.crc == 0;
}
} // End of namespace Cine