aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Kagerer2010-10-17 13:08:00 +0000
committerFlorian Kagerer2010-10-17 13:08:00 +0000
commitc841c3fb7c9b93d48512c4480753ca409770990f (patch)
tree8e54a799b750048d770f5778c7ad4d64b8ff4778
parent728a231d7b8b392b933e507f17f20afe91fd0eed (diff)
downloadscummvm-rg350-c841c3fb7c9b93d48512c4480753ca409770990f.tar.gz
scummvm-rg350-c841c3fb7c9b93d48512c4480753ca409770990f.tar.bz2
scummvm-rg350-c841c3fb7c9b93d48512c4480753ca409770990f.zip
SCUMM/FM-TOWNS: more improvements to japanese font drawing
- made use of LordHotos graphics/sjis code to reduce code duplication - japanese mode for version 3 and 5 works fine now with few exceptions (some line spacing glitches in MI1 intro etc.) svn-id: r53554
-rw-r--r--engines/kyra/screen.cpp6
-rw-r--r--engines/scumm/charset.cpp292
-rw-r--r--engines/scumm/charset.h12
-rw-r--r--engines/scumm/gfx.cpp16
-rw-r--r--engines/scumm/scumm.cpp3
-rw-r--r--engines/scumm/scumm.h3
-rw-r--r--engines/scumm/string.cpp12
-rw-r--r--graphics/sjis.cpp23
-rw-r--r--graphics/sjis.h24
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;