From 164f35b8788a43aaa3807ab9cc2c46f74e0a592d Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Sat, 25 Feb 2006 18:26:16 +0000 Subject: cleanup unpacking function and get rid of an old hack to prevent buffer overflows. svn-id: r20884 --- engines/cine/part.cpp | 8 +- engines/cine/sfx_player.cpp | 2 +- engines/cine/unpack.cpp | 180 +++++++++++++++++--------------------------- engines/cine/unpack.h | 10 ++- 4 files changed, 80 insertions(+), 120 deletions(-) (limited to 'engines') diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp index 7ad3998546..74069531a2 100644 --- a/engines/cine/part.cpp +++ b/engines/cine/part.cpp @@ -203,14 +203,10 @@ uint8 *readBundleFile(int16 foundFileIdx) { if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) { uint8 *unpackBuffer; - uint16 realSize; - unpackBuffer = (uint8 *)malloc(partBuffer[foundFileIdx].packedSize + 500); + unpackBuffer = (uint8 *)malloc(partBuffer[foundFileIdx].packedSize); readFromPart(foundFileIdx, unpackBuffer); - - realSize = READ_BE_UINT32(unpackBuffer + partBuffer[foundFileIdx].packedSize - 4); - - decomp(unpackBuffer + partBuffer[foundFileIdx].packedSize - 4, dataPtr + realSize, realSize); + delphineUnpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize); free(unpackBuffer); } else { readFromPart(foundFileIdx, dataPtr); diff --git a/engines/cine/sfx_player.cpp b/engines/cine/sfx_player.cpp index 0a23c1cb9c..299260eaad 100644 --- a/engines/cine/sfx_player.cpp +++ b/engines/cine/sfx_player.cpp @@ -117,7 +117,7 @@ static uint8 *snd_loadBasesonEntry(const char *entryName) { if (tempData) { snd_baseSndFile->seek(be->offset, SEEK_SET); snd_baseSndFile->read(tempData, be->size); - decomp(tempData + be->size - 4, entryData + be->unpackedSize, be->unpackedSize); + delphineUnpack(entryData, tempData, be->size); free(tempData); } } else { 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 diff --git a/engines/cine/unpack.h b/engines/cine/unpack.h index 5677f92248..1fe92c28c3 100644 --- a/engines/cine/unpack.h +++ b/engines/cine/unpack.h @@ -30,7 +30,15 @@ namespace Cine { -int decomp(uint8 *in, uint8 *out, int size); +struct UnpackCtx { + int size, datasize; + uint32 crc; + uint32 chk; + uint8 *dst; + const uint8 *src; +}; + +bool delphineUnpack(uint8 *dst, const uint8 *src, int len); } // End of namespace Cine -- cgit v1.2.3