VIDEO: Add range checks to deLZ77()
svn-id: r55258
This commit is contained in:
parent
23c1184d80
commit
afd101c526
2 changed files with 74 additions and 46 deletions
|
@ -268,23 +268,28 @@ bool CoktelDecoder::hasDirtyPalette() const {
|
||||||
return (_features & kFeaturesPalette) && _paletteDirty;
|
return (_features & kFeaturesPalette) && _paletteDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoktelDecoder::deLZ77(byte *dest, byte *src) {
|
uint32 CoktelDecoder::deLZ77(byte *dest, const byte *src, uint32 srcSize, uint32 destSize) {
|
||||||
int i;
|
uint32 frameLength = READ_LE_UINT32(src);
|
||||||
byte buf[4370];
|
if (frameLength > destSize) {
|
||||||
uint16 chunkLength;
|
warning("CoktelDecoder::deLZ77(): Uncompressed size bigger than buffer size (%d > %d)", frameLength, destSize);
|
||||||
uint32 frameLength;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(srcSize >= 4);
|
||||||
|
|
||||||
|
uint32 realSize = frameLength;
|
||||||
|
|
||||||
|
src += 4;
|
||||||
|
srcSize -= 4;
|
||||||
|
|
||||||
uint16 bufPos1;
|
uint16 bufPos1;
|
||||||
uint16 bufPos2;
|
|
||||||
uint16 tmp;
|
|
||||||
uint8 chunkBitField;
|
|
||||||
uint8 chunkCount;
|
|
||||||
bool mode;
|
bool mode;
|
||||||
|
|
||||||
frameLength = READ_LE_UINT32(src);
|
|
||||||
src += 4;
|
|
||||||
|
|
||||||
if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
|
if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
|
||||||
|
assert(srcSize >= 4);
|
||||||
|
|
||||||
src += 4;
|
src += 4;
|
||||||
|
srcSize -= 4;
|
||||||
|
|
||||||
bufPos1 = 273;
|
bufPos1 = 273;
|
||||||
mode = 1; // 123Ch (cmp al, 12h)
|
mode = 1; // 123Ch (cmp al, 12h)
|
||||||
} else {
|
} else {
|
||||||
|
@ -292,40 +297,54 @@ void CoktelDecoder::deLZ77(byte *dest, byte *src) {
|
||||||
mode = 0; // 275h (jnz +2)
|
mode = 0; // 275h (jnz +2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte buf[4370];
|
||||||
memset(buf, 32, bufPos1);
|
memset(buf, 32, bufPos1);
|
||||||
chunkCount = 1;
|
|
||||||
chunkBitField = 0;
|
uint8 chunkCount = 1;
|
||||||
|
uint8 chunkBitField = 0;
|
||||||
|
|
||||||
while (frameLength > 0) {
|
while (frameLength > 0) {
|
||||||
chunkCount--;
|
chunkCount--;
|
||||||
|
|
||||||
if (chunkCount == 0) {
|
if (chunkCount == 0) {
|
||||||
tmp = *src++;
|
|
||||||
chunkCount = 8;
|
chunkCount = 8;
|
||||||
chunkBitField = tmp;
|
chunkBitField = *src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunkBitField % 2) {
|
if (chunkBitField % 2) {
|
||||||
|
assert(srcSize >= 1);
|
||||||
|
|
||||||
chunkBitField >>= 1;
|
chunkBitField >>= 1;
|
||||||
buf[bufPos1] = *src;
|
buf[bufPos1] = *src;
|
||||||
*dest++ = *src++;
|
*dest++ = *src++;
|
||||||
bufPos1 = (bufPos1 + 1) % 4096;
|
bufPos1 = (bufPos1 + 1) % 4096;
|
||||||
frameLength--;
|
frameLength--;
|
||||||
|
srcSize--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
chunkBitField >>= 1;
|
chunkBitField >>= 1;
|
||||||
|
|
||||||
tmp = READ_LE_UINT16(src);
|
assert(srcSize >= 2);
|
||||||
|
|
||||||
|
uint16 tmp = READ_LE_UINT16(src);
|
||||||
|
uint16 chunkLength = ((tmp & 0xF00) >> 8) + 3;
|
||||||
|
|
||||||
src += 2;
|
src += 2;
|
||||||
chunkLength = ((tmp & 0xF00) >> 8) + 3;
|
srcSize -= 2;
|
||||||
|
|
||||||
if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
|
if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
|
||||||
(!mode && (chunkLength == 0)))
|
(!mode && (chunkLength == 0))) {
|
||||||
chunkLength = *src++ + 0x12;
|
assert(srcSize >= 1);
|
||||||
|
|
||||||
bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
|
chunkLength = *src++ + 0x12;
|
||||||
|
srcSize--;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
|
||||||
if (((tmp + chunkLength) >= 4096) ||
|
if (((tmp + chunkLength) >= 4096) ||
|
||||||
((chunkLength + bufPos1) >= 4096)) {
|
((chunkLength + bufPos1) >= 4096)) {
|
||||||
|
|
||||||
for (i = 0; i < chunkLength; i++, dest++) {
|
for (int i = 0; i < chunkLength; i++, dest++) {
|
||||||
*dest = buf[bufPos2];
|
*dest = buf[bufPos2];
|
||||||
buf[bufPos1] = buf[bufPos2];
|
buf[bufPos1] = buf[bufPos2];
|
||||||
bufPos1 = (bufPos1 + 1) % 4096;
|
bufPos1 = (bufPos1 + 1) % 4096;
|
||||||
|
@ -344,7 +363,7 @@ void CoktelDecoder::deLZ77(byte *dest, byte *src) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
|
for (int i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
|
||||||
*dest = buf[bufPos2];
|
*dest = buf[bufPos2];
|
||||||
buf[bufPos1] = buf[bufPos2];
|
buf[bufPos1] = buf[bufPos2];
|
||||||
}
|
}
|
||||||
|
@ -353,6 +372,8 @@ void CoktelDecoder::deLZ77(byte *dest, byte *src) {
|
||||||
frameLength -= chunkLength;
|
frameLength -= chunkLength;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return realSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoktelDecoder::deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen) {
|
void CoktelDecoder::deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen) {
|
||||||
|
@ -1317,6 +1338,7 @@ bool IMDDecoder::renderFrame(Common::Rect &rect) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
byte *dataPtr = _videoBuffer[0];
|
byte *dataPtr = _videoBuffer[0];
|
||||||
|
uint32 dataSize = _videoBufferLen[0] - 1;
|
||||||
|
|
||||||
uint8 type = *dataPtr++;
|
uint8 type = *dataPtr++;
|
||||||
|
|
||||||
|
@ -1331,6 +1353,7 @@ bool IMDDecoder::renderFrame(Common::Rect &rect) {
|
||||||
_palette[index * 3 + i] = dataPtr[i] << 2;
|
_palette[index * 3 + i] = dataPtr[i] << 2;
|
||||||
|
|
||||||
dataPtr += 48;
|
dataPtr += 48;
|
||||||
|
dataSize -= 49;
|
||||||
type ^= 0x10;
|
type ^= 0x10;
|
||||||
|
|
||||||
_paletteDirty = true;
|
_paletteDirty = true;
|
||||||
|
@ -1343,13 +1366,15 @@ bool IMDDecoder::renderFrame(Common::Rect &rect) {
|
||||||
|
|
||||||
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
|
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
|
||||||
// Directly uncompress onto the video surface
|
// Directly uncompress onto the video surface
|
||||||
deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr);
|
deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr, dataSize,
|
||||||
|
_surface.w * _surface.h * _surface.bytesPerPixel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
deLZ77(_videoBuffer[1], dataPtr);
|
_videoBufferLen[1] = deLZ77(_videoBuffer[1], dataPtr, dataSize, _videoBufferSize);
|
||||||
|
|
||||||
dataPtr = _videoBuffer[1];
|
dataPtr = _videoBuffer[1];
|
||||||
|
dataSize = _videoBufferLen[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the block type
|
// Evaluate the block type
|
||||||
|
@ -2134,6 +2159,7 @@ bool VMDDecoder::renderFrame(Common::Rect &rect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *dataPtr = _videoBuffer[0];
|
byte *dataPtr = _videoBuffer[0];
|
||||||
|
uint32 dataSize = _videoBufferLen[0] - 1;
|
||||||
|
|
||||||
uint8 type = *dataPtr++;
|
uint8 type = *dataPtr++;
|
||||||
|
|
||||||
|
@ -2144,13 +2170,15 @@ bool VMDDecoder::renderFrame(Common::Rect &rect) {
|
||||||
|
|
||||||
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
|
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
|
||||||
// Directly uncompress onto the video surface
|
// Directly uncompress onto the video surface
|
||||||
deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr);
|
deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr, dataSize,
|
||||||
|
_surface.w * _surface.h * _surface.bytesPerPixel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
deLZ77(_videoBuffer[1], dataPtr);
|
_videoBufferLen[1] = deLZ77(_videoBuffer[1], dataPtr, dataSize, _videoBufferSize);
|
||||||
|
|
||||||
dataPtr = _videoBuffer[1];
|
dataPtr = _videoBuffer[1];
|
||||||
|
dataSize = _videoBufferLen[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the block type
|
// Evaluate the block type
|
||||||
|
|
|
@ -191,7 +191,7 @@ protected:
|
||||||
void freeSurface();
|
void freeSurface();
|
||||||
|
|
||||||
// Decompression
|
// Decompression
|
||||||
void deLZ77(byte *dest, byte *src);
|
uint32 deLZ77(byte *dest, const byte *src, uint32 srcSize, uint32 destSize);
|
||||||
void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen);
|
void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen);
|
||||||
|
|
||||||
// Block rendering
|
// Block rendering
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue