mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
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:
parent
db875d92e4
commit
e3b40b5c24
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user