diff options
-rw-r--r-- | scumm/nut_renderer.cpp | 192 | ||||
-rw-r--r-- | scumm/nut_renderer.h | 5 | ||||
-rw-r--r-- | scumm/smush/codec1.cpp | 6 | ||||
-rw-r--r-- | scumm/smush/smush_player.cpp | 6 |
4 files changed, 61 insertions, 148 deletions
diff --git a/scumm/nut_renderer.cpp b/scumm/nut_renderer.cpp index 9cbce81c4b..ad534f0894 100644 --- a/scumm/nut_renderer.cpp +++ b/scumm/nut_renderer.cpp @@ -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; - - 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; +void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch); + +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"); diff --git a/scumm/nut_renderer.h b/scumm/nut_renderer.h index 1cf3ebe09c..5c47e7edb2 100644 --- a/scumm/nut_renderer.h +++ b/scumm/nut_renderer.h @@ -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 diff --git a/scumm/smush/codec1.cpp b/scumm/smush/codec1.cpp index b771c57982..fb10bb5a6b 100644 --- a/scumm/smush/codec1.cpp +++ b/scumm/smush/codec1.cpp @@ -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; } } diff --git a/scumm/smush/smush_player.cpp b/scumm/smush/smush_player.cpp index e55aa258f1..fd5bc55315 100644 --- a/scumm/smush/smush_player.cpp +++ b/scumm/smush/smush_player.cpp @@ -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); |