Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 76 additions & 30 deletions bank.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ bool Bank::read(const MemEntry *me, uint8_t *buf) {
return ret;
}

void Bank::decUnk1(uint8_t numChunks, uint8_t addCount) {
uint16_t count = getCode(numChunks) + addCount + 1;
debug(DBG_BANK, "Bank::decUnk1(%d, %d) count=%d", numChunks, addCount, count);
void Bank::decodeByteSequence(uint8_t minSize, uint8_t sizeBits) {
uint16_t count = getCode(sizeBits) + minSize;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change doesn't look right (line 57): wrong parameter called.

debug(DBG_BANK, "Bank::decodeByteSequence(minSize=%d, sizeBits=%d) count=%d", minSize, sizeBits, count);
_unpCtx.datasize -= count;
while (count--) {
assert(_oBuf >= _iBuf && _oBuf >= _startBuf);
Expand All @@ -65,16 +65,24 @@ void Bank::decUnk1(uint8_t numChunks, uint8_t addCount) {
}

/*
Note from fab: This look like run-length encoding.
Note from fab:
This look like run-length encoding.

Note from Felipe Sanches:
This function decodes a portion of the data by making a copy of a chunk of data that is already present in a region of the previously decoded data.

The size of the data chunk is given by the first parameter: <size>.
The position from where data is copied is defined by an offset that is
read from the encoded data stream by reading its next <offsetBits> bits.

*/
void Bank::decUnk2(uint8_t numChunks) {
uint16_t i = getCode(numChunks);
uint16_t count = _unpCtx.size + 1;
debug(DBG_BANK, "Bank::decUnk2(%d) i=%d count=%d", numChunks, i, count);
void Bank::CopyPattern(uint16_t count, uint8_t offsetBits) {
uint16_t offset = getCode(offsetBits);
debug(DBG_BANK, "Bank::CopyPattern(count=%d, offsetBits=%d) offset=%d", count, offsetBits, offset);
_unpCtx.datasize -= count;
while (count--) {
assert(_oBuf >= _iBuf && _oBuf >= _startBuf);
*_oBuf = *(_oBuf + i);
*_oBuf = *(_oBuf + offset);
--_oBuf;
}
}
Expand All @@ -83,50 +91,88 @@ void Bank::decUnk2(uint8_t numChunks) {
Most resource in the banks are compacted.
*/
bool Bank::unpack() {
_unpCtx.size = 0;
_unpCtx.datasize = READ_BE_UINT32(_iBuf); _iBuf -= 4;
_oBuf = _startBuf + _unpCtx.datasize - 1;
_unpCtx.crc = READ_BE_UINT32(_iBuf); _iBuf -= 4;
_unpCtx.chk = READ_BE_UINT32(_iBuf); _iBuf -= 4;
_unpCtx.crc ^= _unpCtx.chk;
do {
if (!nextChunk()) {
_unpCtx.size = 1;
if (!nextChunk()) {
decUnk1(3, 0);
if (!nextBit()) {
if (!nextBit()) {
decodeByteSequence(1, 3); // 1 + [3bits] == decode at least 1 byte / up to 8 bytes

//Packing efficiency: between 1,04 and 1,60
//Efficiency Formula: (8 + 8N)/(5 + 8N) for N=[0 to 7]
//Data size: 1+N bytes

//It takes 2 + 3 + 8*[0 to 2^3-1] = 5 to 61 bits of encoded data to represent
// at least 8 bits / up to 64 bits of raw data.
} else {
decUnk2(8);
//copy 2 bytes previously occurring in the decoded data
CopyPattern(2, 8); //up to 2^8-1 = 255 bytes far away

//Packing efficiency: 1,60
//It takes 10 bits of encoded data to represent 16 bits of raw data.
}
} else {
uint16_t c = getCode(2);
if (c == 3) {
decUnk1(8, 8);
} else {
if (c < 2) {
_unpCtx.size = c + 2;
decUnk2(c + 9);
} else {
_unpCtx.size = getCode(8);
decUnk2(12);
}
}
switch(c){
case 0:
//copy 3 bytes from a pattern previously occurring in the decoded data
CopyPattern(3, 9); //up to 2^9 = 512 bytes far away

//Packing efficiency: 2,00
//It takes 12 bits to encode 24bits
break;
case 1:
//copy 4 bytes from a pattern previously occurring in the decoded data
CopyPattern(4, 10); //up to 2^10 = 1kbytes far away

//Packing efficiency: 2,46
//It takes 13 bits to encode 32bits
break;
case 2:
//copy up to 256 bytes (ammount defined by 8bit code)
// from a pattern previously occurring in the decoded data
CopyPattern(getCode(8)+1, 12); //up to 2^12 = 4kbytes far away

//Packing efficiency: 1,21 up to 62,06
//Efficiency Fórmula: 8N / 33 for N=[1 to 256]
//Data size: N bytes

//It takes 3+8+12 = 33 bits to encode 8 bits up to 8*256 bits
//This is only useful for encoding a sequence of at least 5 bytes, otherwise, the resulting encoded data would take up more space than the raw data.
break;
case 3:
decodeByteSequence(9, 8); // 9 + [8bits] == decode at least 9 bytes /
// up to 9+255 = 264 bytes

//Packing efficiency: between 1,02 and 6,54
//Efficiency Fórmula: (72 + 8N) / (11 + 8N) for N=[0 to 255]
//Data size: 9+N bytes

//It takes 3 + 8 + 8*[0 to 2^8-1] = 11 + 8*[0 to 255] bits
// of encoded data to represent
// at least 9*8=72 bits / up to 264*8 bits of raw data.
break;
}
}
} while (_unpCtx.datasize > 0);
return (_unpCtx.crc == 0);
}

uint16_t Bank::getCode(uint8_t numChunks) {
uint16_t Bank::getCode(uint8_t numBits) {
uint16_t c = 0;
while (numChunks--) {
while (numBits--) {
c <<= 1;
if (nextChunk()) {
if (nextBit()) {
c |= 1;
}
}
return c;
}

bool Bank::nextChunk() {
bool Bank::nextBit() {
bool CF = rcr(false);
if (_unpCtx.chk == 0) {
assert(_iBuf >= _startBuf);
Expand Down
9 changes: 4 additions & 5 deletions bank.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
struct MemEntry;

struct UnpackContext {
uint16_t size;
uint32_t crc;
uint32_t chk;
int32_t datasize;
Expand All @@ -38,11 +37,11 @@ struct Bank {
Bank(const char *dataDir);

bool read(const MemEntry *me, uint8_t *buf);
void decUnk1(uint8_t numChunks, uint8_t addCount);
void decUnk2(uint8_t numChunks);
void decodeByteSequence(uint8_t minSize, uint8_t sizeBits);
void CopyPattern(uint16_t size, uint8_t offsetBits);
bool unpack();
uint16_t getCode(uint8_t numChunks);
bool nextChunk();
uint16_t getCode(uint8_t numBits);
bool nextBit();
bool rcr(bool CF);
};

Expand Down