aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorGregory Montoir2005-06-17 18:10:51 +0000
committerGregory Montoir2005-06-17 18:10:51 +0000
commite3b40b5c24b676ed67c39891dff2b41ee9300f98 (patch)
tree82c4c652949bc7b1a25fcf8971a8224f7f59a99b /scumm
parentdb875d92e4721290a03df268228ee49fa607dc59 (diff)
downloadscummvm-rg350-e3b40b5c24b676ed67c39891dff2b41ee9300f98.tar.gz
scummvm-rg350-e3b40b5c24b676ed67c39891dff2b41ee9300f98.tar.bz2
scummvm-rg350-e3b40b5c24b676ed67c39891dff2b41ee9300f98.zip
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
Diffstat (limited to 'scumm')
-rw-r--r--scumm/nut_renderer.cpp192
-rw-r--r--scumm/nut_renderer.h5
-rw-r--r--scumm/smush/codec1.cpp6
-rw-r--r--scumm/smush/smush_player.cpp6
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);