diff options
author | Florian Kagerer | 2010-11-05 00:36:23 +0000 |
---|---|---|
committer | Florian Kagerer | 2010-11-05 00:36:23 +0000 |
commit | 206971d16b56ff37a6a81ff85a1b488fdc60c627 (patch) | |
tree | 297c170bace8de89f30a5065f2a3654998ec59a2 | |
parent | 8c997e26088481340927a779d16d2eb482c14293 (diff) | |
download | scummvm-rg350-206971d16b56ff37a6a81ff85a1b488fdc60c627.tar.gz scummvm-rg350-206971d16b56ff37a6a81ff85a1b488fdc60c627.tar.bz2 scummvm-rg350-206971d16b56ff37a6a81ff85a1b488fdc60c627.zip |
SCUMM/FM-TOWNS JAPANESE: fix out of bounds text drawing
(could cause invalid memory access in MI1)
svn-id: r54079
-rw-r--r-- | engines/scumm/charset.cpp | 26 | ||||
-rw-r--r-- | engines/scumm/charset.h | 8 | ||||
-rw-r--r-- | engines/scumm/gfx.cpp | 2 | ||||
-rw-r--r-- | graphics/sjis.cpp | 28 | ||||
-rw-r--r-- | graphics/sjis.h | 12 |
5 files changed, 43 insertions, 33 deletions
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index e75a45212e..8d7f9c9e9f 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -773,13 +773,13 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { if (charPtr) drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel); else if (_vm->_cjkFont) - _vm->_cjkFont->drawChar(dst, chr, vs->pitch, vs->bytesPerPixel, _color, _shadowColor); + _vm->_cjkFont->drawChar(vs, chr, _left, drawTop, _color, _shadowColor); } else { dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier); if (charPtr) drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.bytesPerPixel, (_vm->_textSurfaceMultiplier == 2 && !is2byte)); else if (_vm->_cjkFont) - _vm->_cjkFont->drawChar(dst, chr, _vm->_textSurface.pitch, vs->bytesPerPixel, _color, _shadowColor); + _vm->_cjkFont->drawChar(_vm->_textSurface, chr, _left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier, _color, _shadowColor); if (is2byte) origWidth /= _vm->_textSurfaceMultiplier; } @@ -799,17 +799,14 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { _str.bottom = _top + height / _vm->_textSurfaceMultiplier; } -void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) { +void CharsetRendererV3::drawChar(int chr, Graphics::Surface &s, int x, int y) { const byte *charPtr; byte *dst; int width, height; int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; if (is2byte) { if (_vm->_game.platform == Common::kPlatformFMTowns) { - width = _vm->_cjkFont->getCharWidth(chr); - height = _vm->_cjkFont->getFontHeight(); - dst = (byte *)s.pixels + y * s.pitch + x; - _vm->_cjkFont->drawChar(dst, chr, s.pitch, s.bytesPerPixel, _color, _shadowColor); + _vm->_cjkFont->drawChar(s, chr, x * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, _color, _shadowColor); return; } else { charPtr = _vm->get2byteCharPtr(chr); @@ -1079,9 +1076,9 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, drawTop = _top - _vm->_screenTop; } - if (!charPtr && _vm->_cjkFont) - _vm->_cjkFont->drawChar(dstPtr, _vm->_cjkChar, dstSurface.pitch, dstSurface.bytesPerPixel, _vm->_townsCharsetColorMap[1], _shadowColor); - else if (is2byte) { + if (!charPtr && _vm->_cjkFont) { + _vm->_cjkFont->drawChar(dstSurface, _vm->_cjkChar, _left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier, _vm->_townsCharsetColorMap[1], _shadowColor); + } else if (is2byte) { drawBits1(dstSurface, dstPtr, charPtr, drawTop, origWidth, origHeight, dstSurface.bytesPerPixel); } else { drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight, _vm->_textSurfaceMultiplier == 2); @@ -1124,7 +1121,7 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, } } -void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x, int y) { +void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) { const byte *charPtr; byte *dst; int width, height; @@ -1133,10 +1130,7 @@ void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x if (is2byte) { enableShadow(true); if (_vm->_game.platform == Common::kPlatformFMTowns) { - width = _vm->_cjkFont->getCharWidth(chr); - height = _vm->_cjkFont->getFontHeight(); - dst = (byte *)s.pixels + y * s.pitch + x; - _vm->_cjkFont->drawChar(dst, chr, s.pitch, s.bytesPerPixel, _color, _shadowColor); + _vm->_cjkFont->drawChar(s, chr, x * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, _color, _shadowColor); return; } else { charPtr = _vm->get2byteCharPtr(chr); @@ -1525,7 +1519,7 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) { _str.bottom = _top + height; } -void CharsetRendererNES::drawChar(int chr, const Graphics::Surface &s, int x, int y) { +void CharsetRendererNES::drawChar(int chr, Graphics::Surface &s, int x, int y) { byte *charPtr, *dst; int width, height; diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index 991ea2c8ad..4b2e053c6d 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -75,7 +75,7 @@ public: virtual ~CharsetRenderer(); virtual void printChar(int chr, bool ignoreCharsetMask) = 0; - virtual void drawChar(int chr, const Graphics::Surface &s, int x, int y) {} + virtual void drawChar(int chr, Graphics::Surface &s, int x, int y) {} int getStringWidth(int a, const byte *str); void addLinebreaks(int a, byte *str, int pos, int maxwidth); @@ -134,7 +134,7 @@ public: CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {} void printChar(int chr, bool ignoreCharsetMask); - void drawChar(int chr, const Graphics::Surface &s, int x, int y); + void drawChar(int chr, Graphics::Surface &s, int x, int y); int getCharWidth(uint16 chr); @@ -155,7 +155,7 @@ public: void setCurID(int32 id) {} void printChar(int chr, bool ignoreCharsetMask); - void drawChar(int chr, const Graphics::Surface &s, int x, int y); + void drawChar(int chr, Graphics::Surface &s, int x, int y); int getFontHeight() { return 8; } int getCharWidth(uint16 chr) { return 8; } @@ -169,7 +169,7 @@ public: CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {} void printChar(int chr, bool ignoreCharsetMask); - void drawChar(int chr, const Graphics::Surface &s, int x, int y); + void drawChar(int chr, Graphics::Surface &s, int x, int y); void setCurID(int32 id); void setColor(byte color); int getCharWidth(uint16 chr); diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 8daee06a88..313e8b88c0 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -1025,7 +1025,7 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154) - rect.right = 320; + rect.right = 319; #endif markRectAsDirty(vs->number, rect, USAGE_BIT_RESTORED); diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp index b9d0d8332f..6e758051a3 100644 --- a/graphics/sjis.cpp +++ b/graphics/sjis.cpp @@ -138,9 +138,12 @@ const uint8 *FontSJISBase::flipCharacter(const uint8 *glyph, const int w) const } #endif -void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const { +void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW, int maxH) const { const uint8 *glyphSource = 0; int width = 0, height = 0; + int outlineExtraWidth = 2, outlineExtraHeight = 2; + int outlineXOffset = 0, outlineYOffset = 0; + if (is8x16(ch)) { glyphSource = getCharData8x16(ch); width = 8; @@ -151,6 +154,21 @@ void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, height = 16; } + if (maxW != -1 && maxW < width) { + width = maxW; + outlineExtraWidth = 0; + outlineXOffset = 1; + } + + if (maxH != -1 && maxH < height) { + height = maxH; + outlineExtraHeight = 0; + outlineYOffset = 1; + } + + if (width <= 0 || height <= 0) + return; + if (!glyphSource) { warning("FontSJISBase::drawChar: Font does not offer data for %02X %02X", ch & 0xFF, ch >> 8); return; @@ -169,15 +187,15 @@ void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, if (bpp == 1) { if (_drawMode == kOutlineMode) { - blitCharacter<uint8>(outline, width + 2, height + 2, (uint8 *)dst, pitch, c2); - blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst + pitch + 1, pitch, c1); + blitCharacter<uint8>(outline, width + outlineExtraWidth, height + outlineExtraHeight, (uint8 *)dst, pitch, c2); + blitCharacter<uint8>(glyphSource, width - outlineXOffset, height - outlineYOffset, (uint8 *)dst + pitch + 1, pitch, c1); } else { blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst, pitch, c1, c2); } } else if (bpp == 2) { if (_drawMode == kOutlineMode) { - blitCharacter<uint16>(outline, width + 2, height + 2, (uint8 *)dst, pitch, c2); - blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst + pitch + 2, pitch, c1); + blitCharacter<uint16>(outline, width + outlineExtraWidth, height + outlineExtraHeight, (uint8 *)dst, pitch, c2); + blitCharacter<uint16>(glyphSource, width - outlineXOffset, height - outlineYOffset, (uint8 *)dst + pitch + 2, pitch, c1); } else { blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst, pitch, c1, c2); } diff --git a/graphics/sjis.h b/graphics/sjis.h index 4ade2f5278..3ba07230da 100644 --- a/graphics/sjis.h +++ b/graphics/sjis.h @@ -115,13 +115,9 @@ public: /** * Draws a SJIS encoded character on the given surface. - * - * TODO: Currently there is no assurance, that this method will only draw within - * the surface boundaries. Thus the caller has to assure the glyph will fit at - * the specified position. */ void drawChar(Graphics::Surface &dst, uint16 ch, int x, int y, uint32 c1, uint32 c2) const { - drawChar(dst.getBasePtr(x, y), ch, c1, c2, dst.pitch, dst.bytesPerPixel); + drawChar(dst.getBasePtr(x, y), ch, dst.pitch, dst.bytesPerPixel, c1, c2, dst.w - x, dst.h - y); } /** @@ -133,8 +129,10 @@ public: * @param bpp bytes per pixel of the destination buffer * @param c1 forground color * @param c2 outline color + * @param maxW max draw width (to ensure that character drawing takes place within surface boundaries) + * @param maxH max draw height (to ensure that character drawing takes place within surface boundaries) */ - virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const = 0; + virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW = -1, int maxH = -1) const = 0; }; /** @@ -154,7 +152,7 @@ public: uint getCharWidth(uint16 ch) const; - void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; + void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW = -1, int maxH = -1) const; private: template<typename Color> void blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c1, Color c2 = 0) const; |