COMMON: Uplift rnc decoder from toon to common
Toon has a RNC implementation with 2 differences from the one taken from SKY: 1. Protection against overread. Add it to common version and adjust callers in sky. 2. Lack of key parameter for obfuscation. We ignore it anyway and don't support obfuscation, so delete it in common version as well
This commit is contained in:
parent
074888e6b8
commit
c5373134d2
7 changed files with 187 additions and 467 deletions
|
@ -37,6 +37,13 @@ namespace Common {
|
||||||
|
|
||||||
RncDecoder::RncDecoder() {
|
RncDecoder::RncDecoder() {
|
||||||
initCrc();
|
initCrc();
|
||||||
|
|
||||||
|
_bitBuffl = 0;
|
||||||
|
_bitBuffh = 0;
|
||||||
|
_bitCount = 0;
|
||||||
|
_srcPtr = nullptr;
|
||||||
|
_dstPtr = nullptr;
|
||||||
|
_inputByteLeft = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RncDecoder::~RncDecoder() { }
|
RncDecoder::~RncDecoder() { }
|
||||||
|
@ -94,7 +101,16 @@ uint16 RncDecoder::inputBits(uint8 amount) {
|
||||||
newBitBuffl >>= newBitCount;
|
newBitBuffl >>= newBitCount;
|
||||||
newBitBuffl |= remBits;
|
newBitBuffl |= remBits;
|
||||||
_srcPtr += 2;
|
_srcPtr += 2;
|
||||||
newBitBuffh = READ_LE_UINT16(_srcPtr);
|
|
||||||
|
// added some more check here to prevent reading in the buffer
|
||||||
|
// if there are no bytes anymore.
|
||||||
|
_inputByteLeft -= 2;
|
||||||
|
if (_inputByteLeft <= 0)
|
||||||
|
newBitBuffh = 0;
|
||||||
|
else if (_inputByteLeft == 1)
|
||||||
|
newBitBuffh = *_srcPtr;
|
||||||
|
else
|
||||||
|
newBitBuffh = READ_LE_UINT16(_srcPtr);
|
||||||
amount -= newBitCount;
|
amount -= newBitCount;
|
||||||
newBitCount = 16 - amount;
|
newBitCount = 16 - amount;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +177,18 @@ uint16 RncDecoder::inputValue(uint16 *table) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 RncDecoder::unpackM1(const void *input, void *output, uint16 key) {
|
int RncDecoder::getbit() {
|
||||||
|
if (_bitCount == 0) {
|
||||||
|
_bitBuffl = *_srcPtr++;
|
||||||
|
_bitCount = 8;
|
||||||
|
}
|
||||||
|
byte temp = (_bitBuffl & 0x80) >> 7;
|
||||||
|
_bitBuffl <<= 1;
|
||||||
|
_bitCount--;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 RncDecoder::unpackM1(const void *input, uint inputSize, void *output) {
|
||||||
uint8 *outputLow, *outputHigh;
|
uint8 *outputLow, *outputHigh;
|
||||||
const uint8 *inputHigh, *inputptr = (const uint8 *)input;
|
const uint8 *inputHigh, *inputptr = (const uint8 *)input;
|
||||||
|
|
||||||
|
@ -172,12 +199,13 @@ int32 RncDecoder::unpackM1(const void *input, void *output, uint16 key) {
|
||||||
uint16 crcPacked = 0;
|
uint16 crcPacked = 0;
|
||||||
|
|
||||||
|
|
||||||
|
_inputByteLeft = inputSize;
|
||||||
_bitBuffl = 0;
|
_bitBuffl = 0;
|
||||||
_bitBuffh = 0;
|
_bitBuffh = 0;
|
||||||
_bitCount = 0;
|
_bitCount = 0;
|
||||||
|
|
||||||
//Check for "RNC "
|
//Check for "RNC "
|
||||||
if (READ_BE_UINT32(inputptr) != kRncSignature)
|
if (READ_BE_UINT32(inputptr) != kRnc1Signature)
|
||||||
return NOT_PACKED;
|
return NOT_PACKED;
|
||||||
|
|
||||||
inputptr += 4;
|
inputptr += 4;
|
||||||
|
@ -210,6 +238,8 @@ int32 RncDecoder::unpackM1(const void *input, void *output, uint16 key) {
|
||||||
_srcPtr = (_dstPtr-packLen);
|
_srcPtr = (_dstPtr-packLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_inputByteLeft -= HEADER_LEN;
|
||||||
|
|
||||||
_dstPtr = (uint8 *)output;
|
_dstPtr = (uint8 *)output;
|
||||||
_bitCount = 0;
|
_bitCount = 0;
|
||||||
|
|
||||||
|
@ -228,11 +258,28 @@ int32 RncDecoder::unpackM1(const void *input, void *output, uint16 key) {
|
||||||
uint32 inputOffset;
|
uint32 inputOffset;
|
||||||
|
|
||||||
if (inputLength) {
|
if (inputLength) {
|
||||||
|
if (_inputByteLeft < (int32) inputLength || inputLength > 0xff000000) {
|
||||||
|
return NOT_PACKED;
|
||||||
|
}
|
||||||
memcpy(_dstPtr, _srcPtr, inputLength); //memcpy is allowed here
|
memcpy(_dstPtr, _srcPtr, inputLength); //memcpy is allowed here
|
||||||
_dstPtr += inputLength;
|
_dstPtr += inputLength;
|
||||||
_srcPtr += inputLength;
|
_srcPtr += inputLength;
|
||||||
uint16 a = READ_LE_UINT16(_srcPtr);
|
_inputByteLeft -= inputLength;
|
||||||
uint16 b = READ_LE_UINT16(_srcPtr + 2);
|
uint16 a;
|
||||||
|
if (_inputByteLeft <= 0)
|
||||||
|
a = 0;
|
||||||
|
else if (_inputByteLeft == 1)
|
||||||
|
a = *_srcPtr;
|
||||||
|
else
|
||||||
|
a = READ_LE_UINT16(_srcPtr);
|
||||||
|
|
||||||
|
uint16 b;
|
||||||
|
if (_inputByteLeft <= 2)
|
||||||
|
b = 0;
|
||||||
|
else if (_inputByteLeft == 3)
|
||||||
|
b = *(_srcPtr + 2);
|
||||||
|
else
|
||||||
|
b = READ_LE_UINT16(_srcPtr + 2);
|
||||||
|
|
||||||
_bitBuffl &= ((1 << _bitCount) - 1);
|
_bitBuffl &= ((1 << _bitCount) - 1);
|
||||||
_bitBuffl |= (a << _bitCount);
|
_bitBuffl |= (a << _bitCount);
|
||||||
|
@ -258,4 +305,124 @@ int32 RncDecoder::unpackM1(const void *input, void *output, uint16 key) {
|
||||||
return unpackLen;
|
return unpackLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 RncDecoder::unpackM2(const void *input, void *output) {
|
||||||
|
const uint8 *inputptr = (const uint8 *)input;
|
||||||
|
|
||||||
|
uint32 unpackLen = 0;
|
||||||
|
uint32 packLen = 0;
|
||||||
|
uint16 crcUnpacked = 0;
|
||||||
|
uint16 crcPacked = 0;
|
||||||
|
|
||||||
|
_bitBuffl = 0;
|
||||||
|
_bitCount = 0;
|
||||||
|
|
||||||
|
// Check for "RNC "
|
||||||
|
if (READ_BE_UINT32(inputptr) != kRnc2Signature)
|
||||||
|
return NOT_PACKED;
|
||||||
|
|
||||||
|
inputptr += 4;
|
||||||
|
|
||||||
|
// Read unpacked/packed file length
|
||||||
|
unpackLen = READ_BE_UINT32(inputptr);
|
||||||
|
inputptr += 4;
|
||||||
|
packLen = READ_BE_UINT32(inputptr);
|
||||||
|
inputptr += 4;
|
||||||
|
|
||||||
|
// Read CRCs
|
||||||
|
crcUnpacked = READ_BE_UINT16(inputptr);
|
||||||
|
inputptr += 2;
|
||||||
|
crcPacked = READ_BE_UINT16(inputptr);
|
||||||
|
inputptr += 2;
|
||||||
|
inputptr = (inputptr + HEADER_LEN - 16);
|
||||||
|
|
||||||
|
if (crcBlock(inputptr, packLen) != crcPacked)
|
||||||
|
return PACKED_CRC;
|
||||||
|
|
||||||
|
inputptr = (((const uint8 *)input) + HEADER_LEN);
|
||||||
|
_srcPtr = inputptr;
|
||||||
|
_dstPtr = (uint8 *)output;
|
||||||
|
|
||||||
|
uint16 ofs, len;
|
||||||
|
byte ofs_hi, ofs_lo;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
ofs_hi = 0;
|
||||||
|
ofs_lo = 0;
|
||||||
|
|
||||||
|
getbit();
|
||||||
|
getbit();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
bool loadVal = false;
|
||||||
|
|
||||||
|
while (getbit() == 0)
|
||||||
|
*_dstPtr++ = *_srcPtr++;
|
||||||
|
|
||||||
|
len = 2;
|
||||||
|
ofs_hi = 0;
|
||||||
|
if (getbit() == 0) {
|
||||||
|
len = (len << 1) | getbit();
|
||||||
|
if (getbit() == 1) {
|
||||||
|
len--;
|
||||||
|
len = (len << 1) | getbit();
|
||||||
|
if (len == 9) {
|
||||||
|
len = 4;
|
||||||
|
while (len--)
|
||||||
|
ofs_hi = (ofs_hi << 1) | getbit();
|
||||||
|
len = (ofs_hi + 3) * 4;
|
||||||
|
while (len--)
|
||||||
|
*_dstPtr++ = *_srcPtr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadVal = true;
|
||||||
|
} else {
|
||||||
|
if (getbit() == 1) {
|
||||||
|
len++;
|
||||||
|
if (getbit() == 1) {
|
||||||
|
len = *_srcPtr++;
|
||||||
|
if (len == 0) {
|
||||||
|
if (getbit() == 1)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len += 8;
|
||||||
|
}
|
||||||
|
loadVal = true;
|
||||||
|
} else {
|
||||||
|
loadVal = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadVal) {
|
||||||
|
if (getbit() == 1) {
|
||||||
|
ofs_hi = (ofs_hi << 1) | getbit();
|
||||||
|
if (getbit() == 1) {
|
||||||
|
ofs_hi = ((ofs_hi << 1) | getbit()) | 4;
|
||||||
|
if (getbit() == 0)
|
||||||
|
ofs_hi = (ofs_hi << 1) | getbit();
|
||||||
|
} else if (ofs_hi == 0) {
|
||||||
|
ofs_hi = 2 | getbit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ofs_lo = *_srcPtr++;
|
||||||
|
ofs = (ofs_hi << 8) | ofs_lo;
|
||||||
|
while (len--) {
|
||||||
|
*_dstPtr = *(byte *)(_dstPtr - ofs - 1);
|
||||||
|
_dstPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crcBlock((uint8 *)output, unpackLen) != crcUnpacked)
|
||||||
|
return UNPACKED_CRC;
|
||||||
|
|
||||||
|
// all is done..return the amount of unpacked bytes
|
||||||
|
return unpackLen;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
|
@ -41,12 +41,16 @@ protected:
|
||||||
const uint8 *_srcPtr;
|
const uint8 *_srcPtr;
|
||||||
uint8 *_dstPtr;
|
uint8 *_dstPtr;
|
||||||
|
|
||||||
|
int32 _inputByteLeft;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RncDecoder();
|
RncDecoder();
|
||||||
~RncDecoder();
|
~RncDecoder();
|
||||||
int32 unpackM1(const void *input, void *output, uint16 key);
|
int32 unpackM1(const void *input, uint inputSize, void *output);
|
||||||
|
int32 unpackM2(const void *input, void *output);
|
||||||
|
|
||||||
static const uint32 kRncSignature = 0x524E4301; // "RNC\001"
|
static const uint32 kRnc1Signature = 0x524E4301; // "RNC\001"
|
||||||
|
static const uint32 kRnc2Signature = 0x524E4302; // "RNC\002"
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void initCrc();
|
void initCrc();
|
||||||
|
@ -54,7 +58,7 @@ protected:
|
||||||
uint16 inputBits(uint8 amount);
|
uint16 inputBits(uint8 amount);
|
||||||
void makeHufftable(uint16 *table);
|
void makeHufftable(uint16 *table);
|
||||||
uint16 inputValue(uint16 *table);
|
uint16 inputValue(uint16 *table);
|
||||||
|
int getbit();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
|
@ -132,7 +132,7 @@ uint8 *Disk::loadFile(uint16 fileNr) {
|
||||||
if ((fileFlags >> 22) & 0x1) { //do we include the header?
|
if ((fileFlags >> 22) & 0x1) { //do we include the header?
|
||||||
// don't return the file's header
|
// don't return the file's header
|
||||||
output = uncompDest;
|
output = uncompDest;
|
||||||
unpackLen = _rncDecoder.unpackM1(input, output, 0);
|
unpackLen = _rncDecoder.unpackM1(input, fileSize - sizeof(DataFileHeader), output);
|
||||||
} else {
|
} else {
|
||||||
#ifdef SCUMM_BIG_ENDIAN
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
// Convert DataFileHeader to BE (it only consists of 16 bit words)
|
// Convert DataFileHeader to BE (it only consists of 16 bit words)
|
||||||
|
@ -143,7 +143,7 @@ uint8 *Disk::loadFile(uint16 fileNr) {
|
||||||
|
|
||||||
memcpy(uncompDest, fileDest, sizeof(DataFileHeader));
|
memcpy(uncompDest, fileDest, sizeof(DataFileHeader));
|
||||||
output = uncompDest + sizeof(DataFileHeader);
|
output = uncompDest + sizeof(DataFileHeader);
|
||||||
unpackLen = _rncDecoder.unpackM1(input, output, 0);
|
unpackLen = _rncDecoder.unpackM1(input, fileSize - sizeof(DataFileHeader), output);
|
||||||
if (unpackLen)
|
if (unpackLen)
|
||||||
unpackLen += sizeof(DataFileHeader);
|
unpackLen += sizeof(DataFileHeader);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/rnc_deco.h"
|
||||||
|
|
||||||
#include "toon/hotspot.h"
|
#include "toon/hotspot.h"
|
||||||
#include "toon/tools.h"
|
|
||||||
|
|
||||||
namespace Toon {
|
namespace Toon {
|
||||||
|
|
||||||
|
@ -123,10 +123,10 @@ bool Hotspots::loadRif(const Common::String &rifName, const Common::String &addi
|
||||||
_items = new HotspotData[_numItems];
|
_items = new HotspotData[_numItems];
|
||||||
|
|
||||||
// RIFs are compressed in RNC1
|
// RIFs are compressed in RNC1
|
||||||
RncDecoder decoder;
|
Common::RncDecoder decoder;
|
||||||
decoder.unpackM1(rifData, size, _items);
|
decoder.unpackM1(rifData, size, _items);
|
||||||
if (rifsize2) {
|
if (rifsize2) {
|
||||||
RncDecoder decoder2;
|
Common::RncDecoder decoder2;
|
||||||
decoder2.unpackM1(rifData2 , size2, _items + (rifsize >> 9));
|
decoder2.unpackM1(rifData2 , size2, _items + (rifsize >> 9));
|
||||||
for (int32 i = 0; i < (rifsize2 >> 9); i++) {
|
for (int32 i = 0; i < (rifsize2 >> 9); i++) {
|
||||||
HotspotData *hot = _items + (rifsize >> 9) + i;
|
HotspotData *hot = _items + (rifsize >> 9) + i;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/rect.h"
|
#include "common/rect.h"
|
||||||
|
#include "common/rnc_deco.h"
|
||||||
#include "common/stack.h"
|
#include "common/stack.h"
|
||||||
|
|
||||||
namespace Toon {
|
namespace Toon {
|
||||||
|
@ -92,7 +93,7 @@ bool Picture::loadPicture(const Common::String &file) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case kCompRNC1: {
|
case kCompRNC1: {
|
||||||
Toon::RncDecoder rnc;
|
Common::RncDecoder rnc;
|
||||||
|
|
||||||
// allocate enough place
|
// allocate enough place
|
||||||
uint32 decSize = READ_BE_UINT32(fileData + 4);
|
uint32 decSize = READ_BE_UINT32(fileData + 4);
|
||||||
|
@ -111,7 +112,7 @@ bool Picture::loadPicture(const Common::String &file) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case kCompRNC2: {
|
case kCompRNC2: {
|
||||||
Toon::RncDecoder rnc;
|
Common::RncDecoder rnc;
|
||||||
|
|
||||||
// allocate enough place
|
// allocate enough place
|
||||||
uint32 decSize = READ_BE_UINT32(fileData + 4);
|
uint32 decSize = READ_BE_UINT32(fileData + 4);
|
||||||
|
|
|
@ -123,421 +123,4 @@ uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize) {
|
||||||
return (dstp - dst);
|
return (dstp - dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
//return codes
|
|
||||||
#define NOT_PACKED 0
|
|
||||||
#define PACKED_CRC -1
|
|
||||||
#define UNPACKED_CRC -2
|
|
||||||
|
|
||||||
//other defines
|
|
||||||
#define TABLE_SIZE (16 * 8)
|
|
||||||
#define MIN_LENGTH 2
|
|
||||||
#define HEADER_LEN 18
|
|
||||||
|
|
||||||
RncDecoder::RncDecoder() {
|
|
||||||
initCrc();
|
|
||||||
|
|
||||||
_bitBuffl = 0;
|
|
||||||
_bitBuffh = 0;
|
|
||||||
_bitCount = 0;
|
|
||||||
_srcPtr = nullptr;
|
|
||||||
_dstPtr = nullptr;
|
|
||||||
_inputByteLeft = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
RncDecoder::~RncDecoder() { }
|
|
||||||
|
|
||||||
void RncDecoder::initCrc() {
|
|
||||||
debugC(1, kDebugTools, "initCrc()");
|
|
||||||
|
|
||||||
uint16 cnt = 0;
|
|
||||||
uint16 tmp1 = 0;
|
|
||||||
uint16 tmp2 = 0;
|
|
||||||
|
|
||||||
for (tmp2 = 0; tmp2 < 0x100; tmp2++) {
|
|
||||||
tmp1 = tmp2;
|
|
||||||
for (cnt = 8; cnt > 0; cnt--) {
|
|
||||||
if (tmp1 % 2) {
|
|
||||||
tmp1 >>= 1;
|
|
||||||
tmp1 ^= 0x0a001;
|
|
||||||
} else
|
|
||||||
tmp1 >>= 1;
|
|
||||||
}
|
|
||||||
_crcTable[tmp2] = tmp1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate 16 bit crc of a block of memory
|
|
||||||
uint16 RncDecoder::crcBlock(const uint8 *block, uint32 size) {
|
|
||||||
debugC(1, kDebugTools, "crcBlock(block, %d)", size);
|
|
||||||
|
|
||||||
uint16 crc = 0;
|
|
||||||
uint8 *crcTable8 = (uint8 *)_crcTable; //make a uint8* to crc_table
|
|
||||||
uint8 tmp;
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
tmp = *block++;
|
|
||||||
crc ^= tmp;
|
|
||||||
tmp = (uint8)((crc >> 8) & 0x00FF);
|
|
||||||
crc &= 0x00FF;
|
|
||||||
crc = *(uint16 *)&crcTable8[crc << 1];
|
|
||||||
crc ^= tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 RncDecoder::inputBits(uint8 amount) {
|
|
||||||
debugC(5, kDebugTools, "inputBits(%d)", amount);
|
|
||||||
|
|
||||||
uint16 newBitBuffh = _bitBuffh;
|
|
||||||
uint16 newBitBuffl = _bitBuffl;
|
|
||||||
int16 newBitCount = _bitCount;
|
|
||||||
uint16 remBits, returnVal;
|
|
||||||
|
|
||||||
returnVal = ((1 << amount) - 1) & newBitBuffl;
|
|
||||||
newBitCount -= amount;
|
|
||||||
|
|
||||||
if (newBitCount < 0) {
|
|
||||||
newBitCount += amount;
|
|
||||||
remBits = (newBitBuffh << (16 - newBitCount));
|
|
||||||
newBitBuffh >>= newBitCount;
|
|
||||||
newBitBuffl >>= newBitCount;
|
|
||||||
newBitBuffl |= remBits;
|
|
||||||
_srcPtr += 2;
|
|
||||||
|
|
||||||
// added some more check here to prevent reading in the buffer
|
|
||||||
// if there are no bytes anymore.
|
|
||||||
_inputByteLeft -= 2;
|
|
||||||
if (_inputByteLeft <= 0)
|
|
||||||
newBitBuffh = 0;
|
|
||||||
else if (_inputByteLeft == 1)
|
|
||||||
newBitBuffh = *_srcPtr;
|
|
||||||
else
|
|
||||||
newBitBuffh = READ_LE_UINT16(_srcPtr);
|
|
||||||
amount -= newBitCount;
|
|
||||||
newBitCount = 16 - amount;
|
|
||||||
}
|
|
||||||
remBits = (newBitBuffh << (16 - amount));
|
|
||||||
_bitBuffh = newBitBuffh >> amount;
|
|
||||||
_bitBuffl = (newBitBuffl >> amount) | remBits;
|
|
||||||
_bitCount = (uint8)newBitCount;
|
|
||||||
|
|
||||||
return returnVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RncDecoder::makeHufftable(uint16 *table) {
|
|
||||||
debugC(1, kDebugTools, "makeHufftable(table)");
|
|
||||||
|
|
||||||
uint16 bitLength, i, j;
|
|
||||||
uint16 numCodes = inputBits(5);
|
|
||||||
|
|
||||||
if (!numCodes)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint8 huffLength[16];
|
|
||||||
for (i = 0; i < numCodes; i++)
|
|
||||||
huffLength[i] = (uint8)(inputBits(4) & 0x00FF);
|
|
||||||
|
|
||||||
uint16 huffCode = 0;
|
|
||||||
|
|
||||||
for (bitLength = 1; bitLength < 17; bitLength++) {
|
|
||||||
for (i = 0; i < numCodes; i++) {
|
|
||||||
if (huffLength[i] == bitLength) {
|
|
||||||
*table++ = (1 << bitLength) - 1;
|
|
||||||
|
|
||||||
uint16 b = huffCode >> (16 - bitLength);
|
|
||||||
uint16 a = 0;
|
|
||||||
|
|
||||||
for (j = 0; j < bitLength; j++)
|
|
||||||
a |= ((b >> j) & 1) << (bitLength - j - 1);
|
|
||||||
*table++ = a;
|
|
||||||
|
|
||||||
*(table + 0x1e) = (huffLength[i] << 8) | (i & 0x00FF);
|
|
||||||
huffCode += 1 << (16 - bitLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 RncDecoder::inputValue(uint16 *table) {
|
|
||||||
debugC(5, kDebugTools, "inputValue(table)");
|
|
||||||
|
|
||||||
uint16 valOne, valTwo, value = _bitBuffl;
|
|
||||||
|
|
||||||
do {
|
|
||||||
valTwo = (*table++) & value;
|
|
||||||
valOne = *table++;
|
|
||||||
} while (valOne != valTwo);
|
|
||||||
|
|
||||||
value = *(table + 0x1e);
|
|
||||||
inputBits((uint8)((value >> 8) & 0x00FF));
|
|
||||||
value &= 0x00FF;
|
|
||||||
|
|
||||||
if (value >= 2) {
|
|
||||||
value--;
|
|
||||||
valOne = inputBits((uint8)value & 0x00FF);
|
|
||||||
valOne |= (1 << value);
|
|
||||||
value = valOne;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RncDecoder::getbit() {
|
|
||||||
debugC(6, kDebugTools, "getbits()");
|
|
||||||
|
|
||||||
if (_bitCount == 0) {
|
|
||||||
_bitBuffl = *_srcPtr++;
|
|
||||||
_bitCount = 8;
|
|
||||||
}
|
|
||||||
byte temp = (_bitBuffl & 0x80) >> 7;
|
|
||||||
_bitBuffl <<= 1;
|
|
||||||
_bitCount--;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 RncDecoder::unpackM1(const void *input, uint16 inputSize, void *output) {
|
|
||||||
debugC(1, kDebugTools, "unpackM1(input, output)");
|
|
||||||
|
|
||||||
uint8 *outputLow, *outputHigh;
|
|
||||||
const uint8 *inputHigh, *inputptr = (const uint8 *)input;
|
|
||||||
|
|
||||||
uint32 unpackLen = 0;
|
|
||||||
uint32 packLen = 0;
|
|
||||||
uint16 counts = 0;
|
|
||||||
uint16 crcUnpacked = 0;
|
|
||||||
uint16 crcPacked = 0;
|
|
||||||
|
|
||||||
|
|
||||||
_inputByteLeft = inputSize;
|
|
||||||
_bitBuffl = 0;
|
|
||||||
_bitBuffh = 0;
|
|
||||||
_bitCount = 0;
|
|
||||||
|
|
||||||
//Check for "RNC "
|
|
||||||
if (READ_BE_UINT32(inputptr) != RNC1_SIGNATURE)
|
|
||||||
return NOT_PACKED;
|
|
||||||
|
|
||||||
inputptr += 4;
|
|
||||||
|
|
||||||
// read unpacked/packed file length
|
|
||||||
unpackLen = READ_BE_UINT32(inputptr);
|
|
||||||
inputptr += 4;
|
|
||||||
packLen = READ_BE_UINT32(inputptr);
|
|
||||||
inputptr += 4;
|
|
||||||
|
|
||||||
uint8 blocks = *(inputptr + 5);
|
|
||||||
|
|
||||||
//read CRC's
|
|
||||||
crcUnpacked = READ_BE_UINT16(inputptr);
|
|
||||||
inputptr += 2;
|
|
||||||
crcPacked = READ_BE_UINT16(inputptr);
|
|
||||||
inputptr += 2;
|
|
||||||
inputptr = (inputptr + HEADER_LEN - 16);
|
|
||||||
|
|
||||||
if (crcBlock(inputptr, packLen) != crcPacked)
|
|
||||||
return PACKED_CRC;
|
|
||||||
|
|
||||||
inputptr = (((const uint8 *)input) + HEADER_LEN);
|
|
||||||
_srcPtr = inputptr;
|
|
||||||
|
|
||||||
inputHigh = ((const uint8 *)input) + packLen + HEADER_LEN;
|
|
||||||
outputLow = (uint8 *)output;
|
|
||||||
outputHigh = *(((const uint8 *)input) + 16) + unpackLen + outputLow;
|
|
||||||
|
|
||||||
if (!((inputHigh <= outputLow) || (outputHigh <= inputHigh))) {
|
|
||||||
_srcPtr = inputHigh;
|
|
||||||
_dstPtr = outputHigh;
|
|
||||||
memcpy((_dstPtr - packLen), (_srcPtr - packLen), packLen);
|
|
||||||
_srcPtr = (_dstPtr - packLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
_inputByteLeft -= HEADER_LEN;
|
|
||||||
|
|
||||||
_dstPtr = (uint8 *)output;
|
|
||||||
_bitCount = 0;
|
|
||||||
|
|
||||||
|
|
||||||
_bitBuffl = READ_LE_UINT16(_srcPtr);
|
|
||||||
inputBits(2);
|
|
||||||
|
|
||||||
do {
|
|
||||||
makeHufftable(_rawTable);
|
|
||||||
makeHufftable(_posTable);
|
|
||||||
makeHufftable(_lenTable);
|
|
||||||
|
|
||||||
counts = inputBits(16);
|
|
||||||
|
|
||||||
do {
|
|
||||||
uint32 inputLength = inputValue(_rawTable);
|
|
||||||
uint32 inputOffset;
|
|
||||||
|
|
||||||
if (inputLength) {
|
|
||||||
memcpy(_dstPtr, _srcPtr, inputLength); //memcpy is allowed here
|
|
||||||
_dstPtr += inputLength;
|
|
||||||
_srcPtr += inputLength;
|
|
||||||
_inputByteLeft -= inputLength;
|
|
||||||
uint16 a;
|
|
||||||
if (_inputByteLeft <= 0)
|
|
||||||
a = 0;
|
|
||||||
else if (_inputByteLeft == 1)
|
|
||||||
a = *_srcPtr;
|
|
||||||
else
|
|
||||||
a = READ_LE_UINT16(_srcPtr);
|
|
||||||
|
|
||||||
uint16 b;
|
|
||||||
if (_inputByteLeft <= 2)
|
|
||||||
b = 0;
|
|
||||||
else if (_inputByteLeft == 3)
|
|
||||||
b = *(_srcPtr + 2);
|
|
||||||
else
|
|
||||||
b = READ_LE_UINT16(_srcPtr + 2);
|
|
||||||
|
|
||||||
_bitBuffl &= ((1 << _bitCount) - 1);
|
|
||||||
_bitBuffl |= (a << _bitCount);
|
|
||||||
_bitBuffh = (a >> (16 - _bitCount)) | (b << _bitCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counts > 1) {
|
|
||||||
inputOffset = inputValue(_posTable) + 1;
|
|
||||||
inputLength = inputValue(_lenTable) + MIN_LENGTH;
|
|
||||||
|
|
||||||
// Don't use memcpy here! because input and output overlap.
|
|
||||||
uint8 *tmpPtr = (_dstPtr - inputOffset);
|
|
||||||
while (inputLength--)
|
|
||||||
*_dstPtr++ = *tmpPtr++;
|
|
||||||
}
|
|
||||||
} while (--counts);
|
|
||||||
} while (--blocks);
|
|
||||||
|
|
||||||
if (crcBlock((uint8 *)output, unpackLen) != crcUnpacked)
|
|
||||||
return UNPACKED_CRC;
|
|
||||||
|
|
||||||
// all is done..return the amount of unpacked bytes
|
|
||||||
return unpackLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 RncDecoder::unpackM2(const void *input, void *output) {
|
|
||||||
debugC(1, kDebugTools, "unpackM2(input, output)");
|
|
||||||
|
|
||||||
const uint8 *inputptr = (const uint8 *)input;
|
|
||||||
|
|
||||||
uint32 unpackLen = 0;
|
|
||||||
uint32 packLen = 0;
|
|
||||||
uint16 crcUnpacked = 0;
|
|
||||||
uint16 crcPacked = 0;
|
|
||||||
|
|
||||||
_bitBuffl = 0;
|
|
||||||
_bitCount = 0;
|
|
||||||
|
|
||||||
//Check for "RNC "
|
|
||||||
if (READ_BE_UINT32(inputptr) != RNC2_SIGNATURE)
|
|
||||||
return NOT_PACKED;
|
|
||||||
|
|
||||||
inputptr += 4;
|
|
||||||
|
|
||||||
// read unpacked/packed file length
|
|
||||||
unpackLen = READ_BE_UINT32(inputptr);
|
|
||||||
inputptr += 4;
|
|
||||||
packLen = READ_BE_UINT32(inputptr);
|
|
||||||
inputptr += 4;
|
|
||||||
|
|
||||||
//read CRC's
|
|
||||||
crcUnpacked = READ_BE_UINT16(inputptr);
|
|
||||||
inputptr += 2;
|
|
||||||
crcPacked = READ_BE_UINT16(inputptr);
|
|
||||||
inputptr += 2;
|
|
||||||
inputptr = (inputptr + HEADER_LEN - 16);
|
|
||||||
|
|
||||||
if (crcBlock(inputptr, packLen) != crcPacked)
|
|
||||||
return PACKED_CRC;
|
|
||||||
|
|
||||||
inputptr = (((const uint8 *)input) + HEADER_LEN);
|
|
||||||
_srcPtr = inputptr;
|
|
||||||
_dstPtr = (uint8 *)output;
|
|
||||||
|
|
||||||
uint16 ofs, len;
|
|
||||||
byte ofs_hi, ofs_lo;
|
|
||||||
|
|
||||||
len = 0;
|
|
||||||
ofs_hi = 0;
|
|
||||||
ofs_lo = 0;
|
|
||||||
|
|
||||||
getbit();
|
|
||||||
getbit();
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
bool loadVal = false;
|
|
||||||
|
|
||||||
while (getbit() == 0)
|
|
||||||
*_dstPtr++ = *_srcPtr++;
|
|
||||||
|
|
||||||
len = 2;
|
|
||||||
ofs_hi = 0;
|
|
||||||
if (getbit() == 0) {
|
|
||||||
len = (len << 1) | getbit();
|
|
||||||
if (getbit() == 1) {
|
|
||||||
len--;
|
|
||||||
len = (len << 1) | getbit();
|
|
||||||
if (len == 9) {
|
|
||||||
len = 4;
|
|
||||||
while (len--)
|
|
||||||
ofs_hi = (ofs_hi << 1) | getbit();
|
|
||||||
len = (ofs_hi + 3) * 4;
|
|
||||||
while (len--)
|
|
||||||
*_dstPtr++ = *_srcPtr++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadVal = true;
|
|
||||||
} else {
|
|
||||||
if (getbit() == 1) {
|
|
||||||
len++;
|
|
||||||
if (getbit() == 1) {
|
|
||||||
len = *_srcPtr++;
|
|
||||||
if (len == 0) {
|
|
||||||
if (getbit() == 1)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len += 8;
|
|
||||||
}
|
|
||||||
loadVal = true;
|
|
||||||
} else {
|
|
||||||
loadVal = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadVal) {
|
|
||||||
if (getbit() == 1) {
|
|
||||||
ofs_hi = (ofs_hi << 1) | getbit();
|
|
||||||
if (getbit() == 1) {
|
|
||||||
ofs_hi = ((ofs_hi << 1) | getbit()) | 4;
|
|
||||||
if (getbit() == 0)
|
|
||||||
ofs_hi = (ofs_hi << 1) | getbit();
|
|
||||||
} else if (ofs_hi == 0) {
|
|
||||||
ofs_hi = 2 | getbit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ofs_lo = *_srcPtr++;
|
|
||||||
ofs = (ofs_hi << 8) | ofs_lo;
|
|
||||||
while (len--) {
|
|
||||||
*_dstPtr = *(byte *)(_dstPtr - ofs - 1);
|
|
||||||
_dstPtr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crcBlock((uint8 *)output, unpackLen) != crcUnpacked)
|
|
||||||
return UNPACKED_CRC;
|
|
||||||
|
|
||||||
// all is done..return the amount of unpacked bytes
|
|
||||||
return unpackLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Toon
|
} // End of namespace Toon
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
#include "common/scummsys.h"
|
#include "common/scummsys.h"
|
||||||
#include "common/endian.h"
|
#include "common/endian.h"
|
||||||
|
|
||||||
#define RNC1_SIGNATURE 0x524E4301 // "RNC\001"
|
|
||||||
#define RNC2_SIGNATURE 0x524E4302 // "RNC\002"
|
|
||||||
|
|
||||||
namespace Toon {
|
namespace Toon {
|
||||||
|
|
||||||
const uint32 kCompLZSS = 0x4C5A5353;
|
const uint32 kCompLZSS = 0x4C5A5353;
|
||||||
|
@ -38,38 +35,6 @@ const uint32 kCompRNC2 = 0x524E4302;
|
||||||
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize);
|
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize);
|
||||||
uint32 decompressLZSS(byte *src, byte *dst, int dstsize);
|
uint32 decompressLZSS(byte *src, byte *dst, int dstsize);
|
||||||
|
|
||||||
class RncDecoder {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
uint16 _rawTable[64];
|
|
||||||
uint16 _posTable[64];
|
|
||||||
uint16 _lenTable[64];
|
|
||||||
uint16 _crcTable[256];
|
|
||||||
|
|
||||||
uint16 _bitBuffl;
|
|
||||||
uint16 _bitBuffh;
|
|
||||||
uint8 _bitCount;
|
|
||||||
|
|
||||||
const uint8 *_srcPtr;
|
|
||||||
uint8 *_dstPtr;
|
|
||||||
|
|
||||||
int16 _inputByteLeft;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RncDecoder();
|
|
||||||
~RncDecoder();
|
|
||||||
int32 unpackM1(const void *input, uint16 inputSize, void *output);
|
|
||||||
int32 unpackM2(const void *input, void *output);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initCrc();
|
|
||||||
uint16 crcBlock(const uint8 *block, uint32 size);
|
|
||||||
uint16 inputBits(uint8 amount);
|
|
||||||
void makeHufftable(uint16 *table);
|
|
||||||
uint16 inputValue(uint16 *table);
|
|
||||||
int getbit();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // End of namespace Toon
|
} // End of namespace Toon
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue