diff options
-rw-r--r-- | engines/kyra/screen.cpp | 6 | ||||
-rw-r--r-- | engines/scumm/charset.cpp | 292 | ||||
-rw-r--r-- | engines/scumm/charset.h | 12 | ||||
-rw-r--r-- | engines/scumm/gfx.cpp | 16 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 3 | ||||
-rw-r--r-- | engines/scumm/scumm.h | 3 | ||||
-rw-r--r-- | engines/scumm/string.cpp | 12 | ||||
-rw-r--r-- | graphics/sjis.cpp | 23 | ||||
-rw-r--r-- | graphics/sjis.h | 24 |
9 files changed, 187 insertions, 204 deletions
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index b7e01f31aa..f08fb4e7ef 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -3313,7 +3313,7 @@ SJISFont::SJISFont(Screen *s, Graphics::FontSJIS *font, const uint8 invisColor, : _colorMap(0), _font(font), _invisColor(invisColor), _is16Color(is16Color), _screen(s) { assert(_font); - _font->enableOutline(outlineSize); + _font->setShadowMode(outlineSize ? Graphics::FontSJIS::kShadowTypeOutline : Graphics::FontSJIS::kShadowTypeNone); _sjisWidth = _font->getMaxFontWidth() >> 1; _fontHeight = _font->getFontHeight() >> 1; @@ -3345,9 +3345,9 @@ void SJISFont::setColorMap(const uint8 *src) { if (!_is16Color) { if (_colorMap[0] == _invisColor) - _font->enableOutline(false); + _font->setShadowMode(Graphics::FontSJIS::kShadowTypeNone); else - _font->enableOutline(true); + _font->setShadowMode(Graphics::FontSJIS::kShadowTypeOutline); } } diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index a62fabe2b6..e0ab9edd5e 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -55,20 +55,12 @@ void ScummEngine::loadCJKFont() { #ifdef DISABLE_TOWNS_DUAL_LAYER_MODE error("FM-Towns Kanji font drawing requires dual graphics layer support which is disabled in this build"); #endif - int numChar = 256 * 32; - _2byteWidth = 16; - _2byteHeight = 16; - // use FM-TOWNS font rom, since game files don't have kanji font resources - if (!fp.open("fmt_fnt.rom")) { - error("SCUMM::Font: Couldn't open fmt_fnt.rom"); - } else { - _useCJKMode = true; - debug(2, "Loading FM-TOWNS Kanji rom"); - _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar]; - fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); - fp.close(); - } + // use FM-TOWNS font rom, since game files don't have kanji font resources + _cjkFont = Graphics::FontSJIS::createFont(Common::kPlatformFMTowns); + if (!_cjkFont) + error("SCUMM::Font: Couldn't open file 'FMT_FNT.ROM'"); _textSurfaceMultiplier = 2; + _useCJKMode = true; } else if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN) { int numChar = 3418; _2byteWidth = 12; @@ -170,90 +162,6 @@ void ScummEngine::loadCJKFont() { } } -static int SJIStoFMTChunk(int f, int s) { //converts sjis code to fmt font offset - enum { - KANA = 0, - KANJI = 1, - EKANJI = 2 - }; - int base = s - ((s + 1) % 32); - int c = 0, p = 0, chunk_f = 0, chunk = 0, cr = 0, kanjiType = KANA; - - if (f >= 0x81 && f <= 0x84) kanjiType = KANA; - if (f >= 0x88 && f <= 0x9f) kanjiType = KANJI; - if (f >= 0xe0 && f <= 0xea) kanjiType = EKANJI; - - if ((f > 0xe8 || (f == 0xe8 && base >= 0x9f)) || (f > 0x90 || (f == 0x90 && base >= 0x9f))) { - c = 48; //correction - p = -8; //correction - } - - if (kanjiType == KANA) {//Kana - chunk_f = (f - 0x81) * 2; - } else if (kanjiType == KANJI) {//Standard Kanji - p += f - 0x88; - chunk_f = c + 2 * p; - } else if (kanjiType == EKANJI) {//Enhanced Kanji - p += f - 0xe0; - chunk_f = c + 2 * p; - } - - // Base corrections - if (base == 0x7f && s == 0x7f) - base -= 0x20; - if (base == 0x9f && s == 0xbe) - base += 0x20; - if (base == 0xbf && s == 0xde) - base += 0x20; - //if (base == 0x7f && s == 0x9e) - // base += 0x20; - - switch (base) { - case 0x3f: - cr = 0; //3f - if (kanjiType == KANA) chunk = 1; - else if (kanjiType == KANJI) chunk = 31; - else if (kanjiType == EKANJI) chunk = 111; - break; - case 0x5f: - cr = 0; //5f - if (kanjiType == KANA) chunk = 17; - else if (kanjiType == KANJI) chunk = 47; - else if (kanjiType == EKANJI) chunk = 127; - break; - case 0x7f: - cr = -1; //80 - if (kanjiType == KANA) chunk = 9; - else if (kanjiType == KANJI) chunk = 63; - else if (kanjiType == EKANJI) chunk = 143; - break; - case 0x9f: - cr = 1; //9e - if (kanjiType == KANA) chunk = 2; - else if (kanjiType == KANJI) chunk = 32; - else if (kanjiType == EKANJI) chunk = 112; - break; - case 0xbf: - cr = 1; //be - if (kanjiType == KANA) chunk = 18; - else if (kanjiType == KANJI) chunk = 48; - else if (kanjiType == EKANJI) chunk = 128; - break; - case 0xdf: - cr = 1; //de - if (kanjiType == KANA) chunk = 10; - else if (kanjiType == KANJI) chunk = 64; - else if (kanjiType == EKANJI) chunk = 144; - break; - default: - debug(4, "Invalid Char! f %x s %x base %x c %d p %d", f, s, base, c, p); - return 0; - } - - debug(6, "Kanji: %c%c f 0x%x s 0x%x base 0x%x c %d p %d chunk %d cr %d index %d", f, s, f, s, base, c, p, chunk, cr, ((chunk_f + chunk) * 32 + (s - base)) + cr); - return ((chunk_f + chunk) * 32 + (s - base)) + cr; -} - static int SJIStoPCEChunk(int f, int s) { //converts sjis code to pce font offset // rangeTbl maps SJIS char-codes to the PCE System Card font rom. // Each pair {<upperBound>,<lowerBound>} in the array represents a SJIS range. @@ -330,9 +238,8 @@ byte *ScummEngine::get2byteCharPtr(int idx) { } idx = (SWAP_CONSTANT_16(idx) & 0x7fff) - 1; - } else { - idx = SJIStoFMTChunk((idx % 256), (idx / 256)); } + break; case Common::ZH_TWN: { @@ -458,9 +365,9 @@ void CharsetRendererV3::setCurID(int32 id) { int CharsetRendererCommon::getFontHeight() { if (_vm->_useCJKMode) { if (_vm->_game.platform == Common::kPlatformFMTowns) { - static const uint8 sjisFontHeightM1[] = { 0, 9, 10, 9, 10, 9, 10, 0, 0 }; - static const uint8 sjisFontHeightM2[] = { 8, 8, 9, 9, 9, 8, 9, 9, 9, 8 }; - static const uint8 sjisFontHeightI4[] = { 8, 8, 9, 9, 9, 8, 8, 8, 8, 8 }; + static const uint8 sjisFontHeightM1[] = { 0, 8, 10, 9, 10, 9, 10, 0, 0 }; + static const uint8 sjisFontHeightM2[] = { 0, 8, 9, 9, 9, 8, 9, 9, 9, 8 }; + static const uint8 sjisFontHeightI4[] = { 0, 8, 9, 9, 9, 8, 8, 8, 8, 8 }; const uint8 *htbl = (_vm->_game.id == GID_MONKEY) ? sjisFontHeightM1 : ((_vm->_game.id == GID_INDY4) ? sjisFontHeightI4 : sjisFontHeightM2); return (_vm->_game.version == 3) ? 8 : htbl[_curId]; } else { @@ -479,17 +386,19 @@ int CharsetRendererClassic::getCharWidth(uint16 chr) { if ((chr & 0xff00) == 0xfd00) { chr &= 0xff; } else if (chr >= 256) { - spacing = 9; - } else if (chr >= 128) { - spacing = 5; + spacing = 8; + } else if (useTownsFontRomCharacter(chr)) { + spacing = 4; } if (spacing) { - static const uint8 sjisWidthM1[] = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; - static const uint8 sjisWidthM2[] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 }; - static const uint8 sjisWidthI4[] = { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 }; - const uint8 *wtbl = (_vm->_game.id == GID_MONKEY) ? sjisWidthM1 : ((_vm->_game.id == GID_INDY4) ? sjisWidthI4 : sjisWidthM2); - spacing += wtbl[_curId]; + if (_vm->_game.id == GID_MONKEY) { + spacing++; + if (_curId == 2) + spacing++; + } else if (_vm->_game.id != GID_INDY4 && _curId == 1) { + spacing++; + } } } else if (chr >= 0x80) { @@ -507,6 +416,22 @@ int CharsetRendererClassic::getCharWidth(uint16 chr) { return spacing; } +bool CharsetRendererClassic::useTownsFontRomCharacter(uint16 chr) { +#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE + if (_vm->_game.platform != Common::kPlatformFMTowns || !_vm->_useCJKMode) + return false; + + if (chr < 128) { + if (((_vm->_game.id == GID_MONKEY2 && _curId != 0) || (_vm->_game.id == GID_INDY4 && _curId != 3)) && (chr > 31 && chr != 94 && chr != 95 && chr != 126 && chr != 127)) + return true; + return false; + } + return true; +#else + return false; +#endif +} + int CharsetRenderer::getStringWidth(int arg, const byte *text) { int pos = 0; int width = 1; @@ -736,11 +661,22 @@ void CharsetRendererPCE::setColor(byte color) { void CharsetRendererCommon::enableShadow(bool enable) { if (enable) { if (_vm->_game.platform == Common::kPlatformFMTowns) { - _shadowColor = + _shadowColor = 8; #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE - _vm->_game.version == 5 ? _vm->_townsCharsetColorMap[0] : 0x88; -#else - 8; + _shadowColor = _vm->_game.version == 5 ? _vm->_townsCharsetColorMap[0] : 0x88; + if (_vm->_cjkFont) { + if (_vm->_game.version == 5) { + if (_vm->_game.id == GID_MONKEY) { + _vm->_cjkFont->setShadowMode((_curId == 2 || _curId == 4 || _curId == 6) ? Graphics::FontSJIS::kShadowTypeOutline : Graphics::FontSJIS::kShadowTypeNone); + } else if (_vm->_game.id == GID_MONKEY2) { + _vm->_cjkFont->setShadowMode((_curId != 1 && _curId != 3 && _curId != 5) ? Graphics::FontSJIS::kShadowTypeOutline : Graphics::FontSJIS::kShadowTypeNone); + } else if (_vm->_game.id == GID_INDY4) { + _vm->_cjkFont->setShadowMode((_curId == 2 || _curId == 3 || _curId == 4) ? Graphics::FontSJIS::kShadowTypeOutline : Graphics::FontSJIS::kShadowTypeNone); + } + } else { + _vm->_cjkFont->setShadowMode(Graphics::FontSJIS::kShadowTypeScumm3Towns); + } + } #endif _shadowMode = kFMTOWNSShadowMode; } else { @@ -748,6 +684,8 @@ void CharsetRendererCommon::enableShadow(bool enable) { _shadowMode = kNormalShadowMode; } } else { + if (_vm->_cjkFont) + _vm->_cjkFont->setShadowMode(Graphics::FontSJIS::kShadowTypeNone); _shadowMode = kNoShadowMode; } } @@ -775,12 +713,14 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { return; if (_vm->_useCJKMode && chr > 127) { - charPtr = _vm->get2byteCharPtr(chr); - width = _vm->_2byteWidth; - height = _vm->_2byteHeight; - if (!is2byte) { - width >>= 1; - height >>= 1; + if (_vm->_game.platform == Common::kPlatformFMTowns) { + charPtr = 0; + width = _vm->_cjkFont->getCharWidth(chr); + height = _vm->_cjkFont->getFontHeight(); + } else { + width = _vm->_2byteWidth; + height = _vm->_2byteHeight; + charPtr = _vm->get2byteCharPtr(chr); } } else { charPtr = _fontPtr + chr * 8; @@ -796,8 +736,8 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { origHeight = height; if (_shadowMode != kNoShadowMode) { - width += _vm->_textSurfaceMultiplier; - height += _vm->_textSurfaceMultiplier; + width++; + height++; } if (_firstChar) { @@ -823,10 +763,16 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { #endif (ignoreCharsetMask || !vs->hasTwoBuffers)) { dst = vs->getPixels(_left, drawTop); - drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel); + 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); } else { dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier); - drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.bytesPerPixel, (_vm->_textSurfaceMultiplier == 2 && !is2byte)); + 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); if (is2byte) origWidth /= _vm->_textSurfaceMultiplier; } @@ -852,9 +798,17 @@ void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int int width, height; int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; if (is2byte) { - charPtr = _vm->get2byteCharPtr(chr); - width = _vm->_2byteWidth; - height = _vm->_2byteHeight; + 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); + return; + } else { + charPtr = _vm->get2byteCharPtr(chr); + width = _vm->_2byteWidth; + height = _vm->_2byteHeight; + } } else { charPtr = _fontPtr + chr * 8; // width = height = 8; @@ -940,19 +894,31 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE processTownsCharsetColors(_bytesPerPixel); -#endif - if (_vm->_useCJKMode && chr >= 256) { - charPtr = _vm->get2byteCharPtr(chr); + if (_vm->_game.platform == Common::kPlatformFMTowns && _vm->_useCJKMode) { + if ((chr & 0xff00) == 0xfd00) + chr &= 0xff; + } + + if (useTownsFontRomCharacter(chr)) { + charPtr = 0; + _vm->_cjkChar = chr; enableShadow(true); - if (chr >= 256) { - width = _vm->_2byteWidth; - height = _vm->_2byteHeight; - } else { - width = _vm->_2byteWidth / 2; - height = _vm->_2byteHeight / 2; - } + origWidth = width = getCharWidth(chr); + origHeight = height = getFontHeight(); + offsX = offsY = 0; + } else +#endif + if (_vm->_useCJKMode && (chr >= 128)) { + enableShadow(true); + origWidth = width = _vm->_2byteWidth; + origHeight = height = _vm->_2byteHeight; + charPtr = _vm->get2byteCharPtr(chr); offsX = offsY = 0; + if (_shadowMode != kNoShadowMode) { + width++; + height++; + } } else { uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); assert(charOffs < 0x14000); @@ -960,9 +926,9 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { return; charPtr = _fontPtr + charOffs; - width = charPtr[0]; - height = charPtr[1]; - + width = origWidth = charPtr[0]; + height = origHeight = charPtr[1]; + if (_disableOffsX) { offsX = 0; } else { @@ -973,13 +939,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { charPtr += 4; // Skip over char header } - origWidth = width; - origHeight = height; - if (_shadowMode != kNoShadowMode) { - width += _vm->_textSurfaceMultiplier; - height += _vm->_textSurfaceMultiplier; - } if (_firstChar) { _str.left = 0; _str.top = 0; @@ -990,16 +950,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { _top += offsY; _left += offsX; - int boxWidth = origWidth; - int boxHeight = origHeight; - - if (is2byte) { - boxWidth /= _vm->_textSurfaceMultiplier; - boxHeight /= _vm->_textSurfaceMultiplier; - } - - if (_left + boxWidth > _right + 1 || _left < 0) { - _left += boxWidth; + if (_left + origWidth > _right + 1 || _left < 0) { + _left += origWidth; _top -= offsY; return; } @@ -1037,16 +989,16 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { printCharIntern(is2byte, charPtr, origWidth, origHeight, width, height, vs, ignoreCharsetMask); - _left += boxWidth; + _left += origWidth; if (_str.right < _left) { _str.right = _left; - if (_shadowMode != kNoShadowMode) + if (_vm->_game.platform != Common::kPlatformFMTowns && _shadowMode != kNoShadowMode) _str.right++; } - if (_str.bottom < _top + boxHeight) - _str.bottom = _top + boxHeight; + if (_str.bottom < _top + origHeight) + _str.bottom = _top + origHeight; _top -= offsY; } @@ -1109,10 +1061,12 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, drawTop = _top - _vm->_screenTop; } - if (is2byte) { + if (!charPtr && _vm->_cjkFont) + _vm->_cjkFont->drawChar(dstPtr, _vm->_cjkChar, dstSurface.pitch, dstSurface.bytesPerPixel, _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->_useCJKMode); + drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight, _vm->_textSurfaceMultiplier == 2); } if (_blitAlso && vs->hasTwoBuffers) { @@ -1160,9 +1114,17 @@ void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x if (is2byte) { enableShadow(true); - charPtr = _vm->get2byteCharPtr(chr); - width = _vm->_2byteWidth; - height = _vm->_2byteHeight; + 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); + return; + } else { + charPtr = _vm->get2byteCharPtr(chr); + width = _vm->_2byteWidth; + height = _vm->_2byteHeight; + } } else { uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); assert(charOffs < 0x10000); diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index d0728e13ac..991ea2c8ad 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -38,9 +38,9 @@ class NutRenderer; struct VirtScreen; static inline bool checkSJISCode(byte c) { - if ((c > 0x84 && c < 0x88) || (c > 0x9f && c < 0xe0) || (c > 0xea /* && c <= 0xff */)) - return false; - return true; + if ((c >= 0x80 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfd)) + return true; + return false; } @@ -115,6 +115,7 @@ protected: void enableShadow(bool enable); virtual void drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height, uint8 bitDepth, bool scale2x = false); + public: CharsetRendererCommon(ScummEngine *vm); @@ -136,6 +137,11 @@ public: void drawChar(int chr, const Graphics::Surface &s, int x, int y); int getCharWidth(uint16 chr); + + // Some SCUMM 5 games contain hard coded logic to determine whether to use + // the SCUMM fonts or the FM-Towns font rom to draw a character. For the other + // games we will simply check for a character greater 127. + bool useTownsFontRomCharacter(uint16 chr); }; class CharsetRendererNES : public CharsetRendererCommon { diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index e7c81bd418..50d6117dc7 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -1013,11 +1013,6 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { if (rect.left > vs->w) return; - -#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE - if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154) - rect.right = 320; -#endif // Convert 'rect' to local (virtual screen) coordinates rect.top -= vs->topline; @@ -1025,13 +1020,18 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { rect.clip(vs->w, vs->h); + const int height = rect.height(); + const int width = rect.width(); + +#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE + if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154) + rect.right = 320; +#endif + markRectAsDirty(vs->number, rect, USAGE_BIT_RESTORED); screenBuf = vs->getPixels(rect.left, rect.top); - const int height = rect.height(); - const int width = rect.width(); - if (!height) return; diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 6d3808c653..86bb772c7a 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -281,6 +281,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE _townsScreen = 0; #endif + _cjkFont = 0; + _cjkChar = 0; _shadowPalette = NULL; _shadowPaletteSize = 0; memset(_currentPalette, 0, sizeof(_currentPalette)); @@ -631,6 +633,7 @@ ScummEngine::~ScummEngine() { #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE delete _townsScreen; #endif + delete _cjkFont; delete _debugger; diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 3de7d5257c..26cbda222e 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -36,6 +36,7 @@ #include "common/rect.h" #include "common/str.h" #include "graphics/surface.h" +#include "graphics/sjis.h" #include "scumm/gfx.h" #include "scumm/detection.h" @@ -1421,6 +1422,8 @@ public: bool towns_isRectInStringBox(int x1, int y1, int x2, int y2); byte _townsPaletteFlags; byte _townsCharsetColorMap[16]; + Graphics::FontSJIS *_cjkFont; + uint16 _cjkChar; protected: void towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, int srcX, int srcY, int w, int h); diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index 5eb2b9d159..6d90d55f71 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -634,9 +634,7 @@ void ScummEngine::CHARSET_1() { #endif } else { if (c & 0x80 && _useCJKMode) { - if (_language == Common::JA_JPN && !checkSJISCode(c)) { - c = 0x20; //not in S-JIS - } else { + if (checkSJISCode(c)) { byte *buffer = _charsetBuffer + _charsetBufPos; c += *buffer++ * 256; //LE _charsetBufPos = buffer - _charsetBuffer; @@ -993,11 +991,8 @@ void ScummEngine::drawString(int a, const byte *msg) { } } if (c & 0x80 && _useCJKMode) { - if (_language == Common::JA_JPN && !checkSJISCode(c)) { - c = 0x20; //not in S-JIS - } else { + if (checkSJISCode(c)) c += buf[i++] * 256; - } } _charset->printChar(c, true); _charset->_blitAlso = false; @@ -1129,7 +1124,8 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize) // Skip these characters } else { if (!(chr == '@') || (_game.id == GID_CMI && _language == Common::ZH_TWN) || - (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN)) + (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN) || + (_game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN)) { *dst++ = chr; } diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp index af286346ca..97375c884b 100644 --- a/graphics/sjis.cpp +++ b/graphics/sjis.cpp @@ -53,7 +53,7 @@ FontSJIS *FontSJIS::createFont(const Common::Platform platform) { } template<typename Color> -void FontSJISBase::blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c) const { +void FontSJISBase::blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c1, Color c2) const { for (int y = 0; y < h; ++y) { Color *d = (Color *)dst; dst += pitch; @@ -63,8 +63,13 @@ void FontSJISBase::blitCharacter(const uint8 *glyph, const int w, const int h, u if (!(x % 8)) mask = *glyph++; - if (mask & 0x80) - *d = c; + if (mask & 0x80) { + *d = c1; + if (_shadowType == kShadowTypeScumm3 || _shadowType == kShadowTypeScumm3Towns) + d[1] = d[pitch] = c2; + if (_shadowType == kShadowTypeScumm3) + d[pitch + 1] = c2; + } ++d; mask <<= 1; } @@ -122,24 +127,24 @@ void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, } uint8 outline[18 * 18]; - if (_outlineEnabled) { + if (_shadowType == kShadowTypeOutline) { memset(outline, 0, sizeof(outline)); createOutline(outline, glyphSource, width, height); } if (bpp == 1) { - if (_outlineEnabled) { + if (_shadowType == kShadowTypeOutline) { blitCharacter<uint8>(outline, width + 2, height + 2, (uint8 *)dst, pitch, c2); blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst + pitch + 1, pitch, c1); } else { - blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst, pitch, c1); + blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst, pitch, c1, c2); } } else if (bpp == 2) { - if (_outlineEnabled) { + if (_shadowType == kShadowTypeOutline) { blitCharacter<uint16>(outline, width + 2, height + 2, (uint8 *)dst, pitch, c2); blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst + pitch + 2, pitch, c1); } else { - blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst, pitch, c1); + blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst, pitch, c1, c2); } } else { error("FontSJISBase::drawChar: unsupported bpp: %d", bpp); @@ -148,7 +153,7 @@ void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint FontSJISBase::getCharWidth(uint16 ch) const { if (is8x16(ch)) - return _outlineEnabled ? 10 : 8; + return (_shadowType == kShadowTypeOutline) ? 10 : (_shadowType == kShadowTypeNone ? 8 : 9); else return getMaxFontWidth(); } diff --git a/graphics/sjis.h b/graphics/sjis.h index e0b760fc78..b6e99c7f91 100644 --- a/graphics/sjis.h +++ b/graphics/sjis.h @@ -71,12 +71,19 @@ public: virtual bool loadData() = 0; /** - * Enable outline drawing. + * Enable outline/shadow drawing. * * After changing outline state, getFontHeight and getMaxFontWidth / getCharWidth might return * different values! */ - virtual void enableOutline(bool enable) {} + enum ShadowType { + kShadowTypeNone, + kShadowTypeOutline, + kShadowTypeScumm3, + kShadowTypeScumm3Towns + }; + + virtual void setShadowMode(ShadowType type) {} /** * Returns the height of the font. @@ -122,22 +129,23 @@ public: */ class FontSJISBase : public FontSJIS { public: - FontSJISBase() : _outlineEnabled(false) {} + FontSJISBase() : _shadowType(kShadowTypeNone) {} - void enableOutline(bool enable) { _outlineEnabled = enable; } + void setShadowMode(ShadowType type) { _shadowType = type; } - uint getFontHeight() const { return _outlineEnabled ? 18 : 16; } - uint getMaxFontWidth() const { return _outlineEnabled ? 18 : 16; } + uint getFontHeight() const { return (_shadowType == kShadowTypeOutline) ? 18 : (_shadowType == kShadowTypeNone ? 16 : 17); } + + uint getMaxFontWidth() const { return (_shadowType == kShadowTypeOutline) ? 18 : (_shadowType == kShadowTypeNone ? 16 : 17); } uint getCharWidth(uint16 ch) const; void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; private: template<typename Color> - void blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c) const; + void blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c1, Color c2 = 0) const; void createOutline(uint8 *outline, const uint8 *glyph, const int w, const int h) const; protected: - bool _outlineEnabled; + ShadowType _shadowType; bool is8x16(uint16 ch) const; |