committed patch #1221592, smush_codec 21/44 should match the original interpreter behaviour now (this allows to cleanup a bit the code and get rid of some hacks).

svn-id: r18407
This commit is contained in:
Gregory Montoir 2005-06-17 18:10:51 +00:00
parent db875d92e4
commit e3b40b5c24
4 changed files with 60 additions and 147 deletions

View File

@ -44,74 +44,34 @@ NutRenderer::~NutRenderer() {
}
}
int32 NutRenderer::decodeCodec44(byte *dst, const byte *src, uint32 length) {
byte val;
uint16 size_line, num;
int16 decoded_length = 0;
void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch);
do {
size_line = READ_LE_UINT16(src);
src += 2;
length -= 2;
while (size_line != 0) {
num = *src++;
val = *src++;
memset(dst, val, num);
dst += num;
decoded_length += num;
length -= 2;
size_line -= 2;
if (size_line != 0) {
num = READ_LE_UINT16(src) + 1;
src += 2;
memcpy(dst, src, num);
dst += num;
decoded_length += num;
src += num;
length -= num + 2;
size_line -= num + 2;
static void smush_decode_codec21(byte *dst, const byte *src, int width, int height, int pitch) {
while (height--) {
uint8 *dstPtrNext = dst + pitch;
const uint8 *srcPtrNext = src + 2 + READ_LE_UINT16(src); src += 2;
int len = width;
do {
int offs = READ_LE_UINT16(src); src += 2;
dst += offs;
len -= offs;
if (len <= 0) {
break;
}
}
dst--;
decoded_length--;
} while (length > 1);
return decoded_length;
}
static int32 codec1(byte *dst, byte *src, int height) {
byte val, code;
int32 length, decoded_length = 0;
int h = height, size_line;
for (h = 0; h < height; h++) {
size_line = READ_LE_UINT16(src);
src += 2;
while (size_line > 0) {
code = *src++;
size_line--;
length = (code >> 1) + 1;
if (code & 1) {
val = *src++;
size_line--;
if (val)
memset(dst, val, length);
dst += length;
decoded_length += length;
} else {
size_line -= length;
while (length--) {
val = *src++;
if (val)
*dst = val;
dst++;
decoded_length++;
}
int w = READ_LE_UINT16(src) + 1; src += 2;
len -= w;
if (len < 0) {
w += len;
}
}
// the original codec44 handles this part slightly differently (this is the only difference with codec21) :
// src bytes equal to 255 are replaced by 0 in dst
// src bytes equal to 1 are replaced by a color passed as an argument in the original function
// other src bytes values are copied as-is
memcpy(dst, src, w); dst += w; src += w;
} while (len > 0);
dst = dstPtrNext;
src = srcPtrNext;
}
return decoded_length;
}
bool NutRenderer::loadFont(const char *filename) {
@ -145,51 +105,41 @@ bool NutRenderer::loadFont(const char *filename) {
_numChars = READ_LE_UINT16(dataSrc + 10);
uint32 offset = 0;
int32 decoded_length;
for (int l = 0; l < _numChars; l++) {
offset += READ_BE_UINT32(dataSrc + offset + 4) + 8;
if (READ_BE_UINT32(dataSrc + offset) == 'FRME') {
offset += 8;
if (READ_BE_UINT32(dataSrc + offset) == 'FOBJ') {
int codec = READ_LE_UINT16(dataSrc + offset + 8);
_chars[l].xoffs = READ_LE_UINT16(dataSrc + offset + 10);
_chars[l].yoffs = READ_LE_UINT16(dataSrc + offset + 12);
_chars[l].width = READ_LE_UINT16(dataSrc + offset + 14);
_chars[l].height = READ_LE_UINT16(dataSrc + offset + 16);
_chars[l].src = new byte[(_chars[l].width + 2) * _chars[l].height + 1000];
// If characters have transparency, then bytes just get skipped and
// so there may appear some garbage. That's why we have to fill it
// with zeroes first.
memset(_chars[l].src, 0, (_chars[l].width + 2) * _chars[l].height + 1000);
if ((codec == 44) || (codec == 21))
decoded_length = decodeCodec44(_chars[l].src, dataSrc + offset + 22, READ_BE_UINT32(dataSrc + offset + 4) - 14);
else if (codec == 1) {
decoded_length = codec1(_chars[l].src, dataSrc + offset + 22, _chars[l].height);
} else
error("NutRenderer::loadFont: unknown codec: %d", codec);
// FIXME: This is used to work around wrong font file format in Russian
// version of FT. Font files there contain wrong information about
// glyphs width. See patch #823031.
if (_vm->_language == Common::RU_RUS) {
// try to rely on length of returned data
if (l > 127)
_chars[l].width = decoded_length / _chars[l].height;
// but even this not always works
if (l == 134 && !strcmp(filename, "titlfnt.nut"))
_chars[l].width--;
}
} else {
warning("NutRenderer::loadFont(%s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, l, offset);
break;
}
} else {
if (READ_BE_UINT32(dataSrc + offset) != 'FRME') {
warning("NutRenderer::loadFont(%s) there is no FRME chunk %d (offset %x)", filename, l, offset);
break;
}
offset += 8;
if (READ_BE_UINT32(dataSrc + offset) != 'FOBJ') {
warning("NutRenderer::loadFont(%s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, l, offset);
break;
}
int codec = READ_LE_UINT16(dataSrc + offset + 8);
_chars[l].xoffs = READ_LE_UINT16(dataSrc + offset + 10);
_chars[l].yoffs = READ_LE_UINT16(dataSrc + offset + 12);
_chars[l].width = READ_LE_UINT16(dataSrc + offset + 14);
_chars[l].height = READ_LE_UINT16(dataSrc + offset + 16);
const int srcSize = _chars[l].width * _chars[l].height;
_chars[l].src = new byte[srcSize];
// If characters have transparency, then bytes just get skipped and
// so there may appear some garbage. That's why we have to fill it
// with zeroes first.
memset(_chars[l].src, 0, srcSize);
const uint8 *fobjptr = dataSrc + offset + 22;
switch (codec) {
case 1:
smush_decode_codec1(_chars[l].src, fobjptr, 0, 0, _chars[l].width, _chars[l].height, _chars[l].width);
break;
case 21:
case 44:
smush_decode_codec21(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, _chars[l].width);
break;
default:
error("NutRenderer::loadFont: unknown codec: %d", codec);
}
}
free(dataSrc);
@ -227,38 +177,6 @@ int NutRenderer::getCharHeight(byte c) const {
return _chars[c].height;
}
int NutRenderer::getCharOffsX(byte c) const {
if (!_loaded) {
warning("NutRenderer::getCharOffsX() Font is not loaded");
return 0;
}
if (c >= 0x80 && _vm->_useCJKMode) {
return 0;
}
if (c >= _numChars)
error("invalid character in NutRenderer::getCharOffsX : %d (%d)", c, _numChars);
return _chars[c].xoffs;
}
int NutRenderer::getCharOffsY(byte c) const {
if (!_loaded) {
warning("NutRenderer::getCharOffsY() Font is not loaded");
return 0;
}
if (c >= 0x80 && _vm->_useCJKMode) {
return 0;
}
if (c >= _numChars)
error("invalid character in NutRenderer::getCharOffsY : %d (%d)", c, _numChars);
return _chars[c].yoffs;
}
void NutRenderer::drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow) {
if (!_loaded) {
warning("NutRenderer::drawShadowChar() Font is not loaded");

View File

@ -42,8 +42,6 @@ protected:
byte *src;
} _chars[256];
int32 decodeCodec44(byte *dst, const byte *src, uint32 length);
void drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color);
void draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color);
@ -59,9 +57,6 @@ public:
int getCharWidth(byte c) const;
int getCharHeight(byte c) const;
int getCharOffsX(byte c) const;
int getCharOffsY(byte c) const;
};
} // End of namespace Scumm

View File

@ -24,12 +24,12 @@
namespace Scumm {
void smush_decode_codec1(byte *dst, byte *src, int left, int top, int height, int width, int dstWidth) {
void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch) {
byte val, code;
int32 length;
int h = height, size_line;
dst += top * dstWidth;
dst += top * pitch;
for (h = 0; h < height; h++) {
size_line = READ_LE_UINT16(src);
src += 2;
@ -54,7 +54,7 @@ void smush_decode_codec1(byte *dst, byte *src, int left, int top, int height, in
}
}
}
dst += dstWidth - left - width;
dst += pitch - left - width;
}
}

View File

@ -724,7 +724,7 @@ void SmushPlayer::handleNewPalette(Chunk &b) {
setDirtyColors(0, 255);
}
void smush_decode_codec1(byte *dst, byte *src, int left, int top, int height, int width, int dstWidth);
void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch);
#ifdef USE_ZLIB
void SmushPlayer::handleZlibFrameObject(Chunk &b) {
@ -781,7 +781,7 @@ void SmushPlayer::handleZlibFrameObject(Chunk &b) {
switch (codec) {
case 1:
case 3:
smush_decode_codec1(_dst, fobjBuffer + 14, left, top, height, width, _vm->_screenWidth);
smush_decode_codec1(_dst, fobjBuffer + 14, left, top, width, height, _vm->_screenWidth);
break;
case 37:
_codec37.decode(_dst, fobjBuffer + 14);
@ -855,7 +855,7 @@ void SmushPlayer::handleFrameObject(Chunk &b) {
switch (codec) {
case 1:
case 3:
smush_decode_codec1(_dst, chunk_buffer, left, top, height, width, _vm->_screenWidth);
smush_decode_codec1(_dst, chunk_buffer, left, top, width, height, _vm->_screenWidth);
break;
case 37:
_codec37.decode(_dst, chunk_buffer);