[Scummvm-cvs-logs] CVS: scummvm/scumm charset.cpp,2.120,2.121 charset.h,2.31,2.32 nut_renderer.cpp,1.52,1.53 string.cpp,1.259,1.260
Max Horn
fingolfin at users.sourceforge.net
Sat Oct 23 16:10:01 CEST 2004
Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14363
Modified Files:
charset.cpp charset.h nut_renderer.cpp string.cpp
Log Message:
Patch #1048283 (Improved CJK / FM-TOWNS support & some documention)
Index: charset.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/charset.cpp,v
retrieving revision 2.120
retrieving revision 2.121
diff -u -d -r2.120 -r2.121
--- charset.cpp 22 Oct 2004 10:25:55 -0000 2.120
+++ charset.cpp 23 Oct 2004 23:08:50 -0000 2.121
@@ -26,20 +26,37 @@
namespace Scumm {
void ScummEngine::loadCJKFont() {
+ File fp;
_useCJKMode = false;
- if ((_gameId == GID_DIG || _gameId == GID_CMI) && (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN)) {
- File fp;
+ if (_language == Common::JA_JPN && _version <= 5) { // FM-TOWNS v3 / v5 Kanji
+ 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", File::kFileReadMode)) {
+ _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();
+ }
+ } else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) {
+ int numChar = 0;
const char *fontFile = NULL;
+
switch (_language) {
case Common::KO_KOR:
fontFile = "korean.fnt";
+ numChar = 2350;
break;
case Common::JA_JPN:
fontFile = (_gameId == GID_DIG) ? "kanji16.fnt" : "japanese.fnt";
+ numChar = 1024; //FIXME
break;
case Common::ZH_TWN:
if (_gameId == GID_CMI) {
fontFile = "chinese.fnt";
+ numChar = 1; //FIXME
}
break;
default:
@@ -52,49 +69,23 @@
_2byteWidth = fp.readByte();
_2byteHeight = fp.readByte();
- int numChar = 0;
- switch (_language) {
- case Common::KO_KOR:
- numChar = 2350;
- break;
- case Common::JA_JPN:
- numChar = (_gameId == GID_DIG) ? 1024 : 2048; //FIXME
- break;
- case Common::ZH_TWN:
- numChar = 1; //FIXME
- break;
- default:
- break;
- }
- _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar];
- fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar);
- fp.close();
- }
- } else if (_language == Common::JA_JPN && _version == 5) { // FM-TOWNS Kanji
- File fp;
- 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")) {
- _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();
+ } else {
+ warning("Couldn't load any font");
}
}
}
-static int SJIStoFMTChunk(int f, int s) //convert sjis code to fmt font offset
-{
+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 % 32) - 1;
- int c = 0, p = 0, chunk_f = 0, chunk = 0, cr, kanjiType = KANA;
+ 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;
@@ -115,10 +106,15 @@
chunk_f = c + 2 * p;
}
+ // Base corrections
if (base == 0x7f && s == 0x7f)
- base -= 0x20; //correction
- if ((base == 0x7f && s == 0x9e) || (base == 0x9f && s == 0xbe) || (base == 0xbf && s == 0xde))
- base += 0x20; //correction
+ 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:
@@ -158,9 +154,11 @@
else if (kanjiType == EKANJI) chunk = 144;
break;
default:
+ warning("Invaild 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;
}
@@ -238,10 +236,24 @@
_fontPtr += _numChars;
}
+int CharsetRendererCommon::getFontHeight() {
+ if(_vm->_useCJKMode)
+ return MAX(_vm->_2byteHeight + 1, (int)_fontPtr[1]);
+ else
+ return _fontPtr[1];
+}
+
+int CharsetRendererV3::getFontHeight() {
+ if(_vm->_useCJKMode)
+ return MAX(_vm->_2byteHeight + 1, 8);
+ else
+ return 8;
+}
+
// do spacing for variable width old-style font
int CharsetRendererClassic::getCharWidth(byte chr) {
if (chr >= 0x80 && _vm->_useCJKMode)
- return 6;
+ return _vm->_2byteWidth / 2;
int spacing = 0;
int offs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
@@ -276,6 +288,10 @@
if (chr == 0xD)
break;
if (chr == 254 || chr == 255) {
+ //process in LE
+ if(chr == 254 && checkKSCode(text[pos], chr) && _vm->_useCJKMode) {
+ goto loc_avoid_ks_fe;
+ }
chr = text[pos++];
if (chr == 3) // 'WAIT'
break;
@@ -299,7 +315,13 @@
continue;
}
}
- width += getCharWidth(chr);
+loc_avoid_ks_fe:
+ if ((chr & 0x80) && _vm->_useCJKMode) {
+ pos++;
+ width += _vm->_2byteWidth;
+ } else {
+ width += getCharWidth(chr);
+ }
}
setCurID(oldID);
@@ -333,6 +355,10 @@
} else if (chr == '@')
continue;
if (chr == 254 || chr == 255) {
+ //process in LE
+ if(chr == 254 && checkKSCode(str[pos], chr) && _vm->_useCJKMode) {
+ goto loc_avoid_ks_fe;
+ }
chr = str[pos++];
if (chr == 3) // 'Wait'
break;
@@ -366,7 +392,13 @@
if (chr == ' ')
lastspace = pos - 1;
- curw += getCharWidth(chr);
+loc_avoid_ks_fe:
+ if ((chr & 0x80) && _vm->_useCJKMode) {
+ pos++;
+ curw += _vm->_2byteWidth;
+ } else {
+ curw += getCharWidth(chr);
+ }
if (lastspace == -1)
continue;
if (curw > maxwidth) {
@@ -1105,6 +1137,8 @@
}
int CharsetRendererV3::getCharWidth(byte chr) {
+ if (chr & 0x80 && _vm->_useCJKMode)
+ return _vm->_2byteWidth / 2;
int spacing = 0;
spacing = *(_widthTable + chr);
@@ -1129,10 +1163,10 @@
void CharsetRendererV3::printChar(int chr) {
// Indy3 / Zak256 / Loom
+ int width, height, origWidth, origHeight;
VirtScreen *vs;
- byte *char_ptr, *dest_ptr;
- int width, height;
- int drawTop;
+ byte *charPtr, *dst;
+ int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0;
checkRange(_vm->_numCharsets - 1, 0, _curId, "Printing with bad charset %d");
@@ -1142,6 +1176,25 @@
if (chr == '@')
return;
+ if (is2byte) {
+ charPtr = _vm->get2byteCharPtr(chr);
+ width = _vm->_2byteWidth;
+ height = _vm->_2byteHeight;
+ } else {
+ charPtr = _fontPtr + chr * 8;
+// width = height = 8;
+ width = getCharWidth(chr);
+ height = 8;
+ }
+
+ origWidth = width;
+ origHeight = height;
+
+ if (_dropShadow) {
+ width++;
+ height++;
+ }
+
if (_firstChar) {
_str.left = _left;
_str.top = _top;
@@ -1150,14 +1203,7 @@
_firstChar = false;
}
- width = height = 8;
- if (_dropShadow) {
- width++;
- height++;
- }
-
- drawTop = _top - vs->topline;
- char_ptr = _fontPtr + chr * 8;
+ int drawTop = _top - vs->topline;
_vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height);
@@ -1166,17 +1212,17 @@
_textScreenID = vs->number;
}
if (_ignoreCharsetMask || !vs->hasTwoBuffers) {
- dest_ptr = vs->getPixels(_left, drawTop);
- drawBits1(*vs, dest_ptr, char_ptr, drawTop, 8, 8);
+ dst = vs->getPixels(_left, drawTop);
+ drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight);
} else {
- dest_ptr = (byte *)_vm->gdi._textSurface.pixels + _top * _vm->gdi._textSurface.pitch + _left;
- drawBits1(_vm->gdi._textSurface, dest_ptr, char_ptr, drawTop, 8, 8);
+ dst = (byte *)_vm->gdi._textSurface.pixels + _top * _vm->gdi._textSurface.pitch + _left;
+ drawBits1(_vm->gdi._textSurface, dst, charPtr, drawTop, origWidth, origHeight);
}
if (_str.left > _left)
_str.left = _left;
- _left += getCharWidth(chr);
+ _left += origWidth;
if (_str.right < _left) {
_str.right = _left;
@@ -1189,10 +1235,21 @@
}
void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
- byte *char_ptr, *dest_ptr;
- char_ptr = _fontPtr + chr * 8;
- dest_ptr = (byte *)s.pixels + y * s.pitch + x;
- drawBits1(s, dest_ptr, char_ptr, y, 8, 8);
+ byte *charPtr, *dst;
+ int width, height;
+ int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0;
+ if (is2byte) {
+ charPtr = _vm->get2byteCharPtr(chr);
+ width = _vm->_2byteWidth;
+ height = _vm->_2byteHeight;
+ } else {
+ charPtr = _fontPtr + chr * 8;
+// width = height = 8;
+ width = getCharWidth(chr);
+ height = 8;
+ }
+ dst = (byte *)s.pixels + y * s.pitch + x;
+ drawBits1(s, dst, charPtr, y, width, height);
}
@@ -1216,6 +1273,7 @@
int type = *_fontPtr;
if (is2byte) {
_dropShadow = true;
+ _shadowColor = (_vm->_features & GF_FMTOWNS) ? 8 : 0;
charPtr = _vm->get2byteCharPtr(chr);
width = _vm->_2byteWidth;
height = _vm->_2byteHeight;
@@ -1404,20 +1462,35 @@
void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
const byte *charPtr;
byte *dst;
+ int width, height;
+ int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0;
- uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
- assert(charOffs < 0x10000);
- if (!charOffs)
- return;
- charPtr = _fontPtr + charOffs;
-
- int width = charPtr[0];
- int height = charPtr[1];
+ if (is2byte) {
+ _dropShadow = true;
+ _shadowColor = (_vm->_features & GF_FMTOWNS) ? 8 : 0;
+ charPtr = _vm->get2byteCharPtr(chr);
+ width = _vm->_2byteWidth;
+ height = _vm->_2byteHeight;
+ } else {
+ uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
+ assert(charOffs < 0x10000);
+ if (!charOffs)
+ return;
+ charPtr = _fontPtr + charOffs;
+
+ width = charPtr[0];
+ height = charPtr[1];
- charPtr += 4; // Skip over char header
+ charPtr += 4; // Skip over char header
+ }
dst = (byte *)s.pixels + y * s.pitch + x;
- drawBitsN(s, dst, charPtr, *_fontPtr, y, width, height);
+
+ if (is2byte) {
+ drawBits1(s, dst, charPtr, y, width, height);
+ } else {
+ drawBitsN(s, dst, charPtr, *_fontPtr, y, width, height);
+ }
}
void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) {
@@ -1540,7 +1613,7 @@
int height = _current->getCharHeight(chr);
if (chr >= 256 && _vm->_useCJKMode)
- width = 16;
+ width = _vm->_2byteWidth;
shadow.right = _left + width + 2;
shadow.bottom = _top + height + 2;
Index: charset.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/charset.h,v
retrieving revision 2.31
retrieving revision 2.32
diff -u -d -r2.31 -r2.32
--- charset.h 31 Aug 2004 07:40:28 -0000 2.31
+++ charset.h 23 Oct 2004 23:08:51 -0000 2.32
@@ -31,6 +31,25 @@
class NutRenderer;
struct VirtScreen;
+static inline bool checkKSCode(byte hi, byte lo) {
+ //hi : xx
+ //lo : yy
+ if ((0xA1 > lo) || (0xFE < lo)) {
+ return false;
+ }
+ if ((hi >= 0xB0) && (hi <= 0xC8)) {
+ return true;
+ }
+ return false;
+}
+
+static inline bool checkSJISCode(byte c) {
+ if ((c > 0x84 && c < 0x88) || (c > 0x9f && c < 0xe0) || (c > 0xea /* && c <= 0xff */))
+ return false;
+ return true;
+}
+
+
class CharsetRenderer {
public:
@@ -94,7 +113,7 @@
void setCurID(byte id);
- int getFontHeight() { return _fontPtr[1]; }
+ int getFontHeight();
};
class CharsetRendererClassic : public CharsetRendererCommon {
@@ -122,7 +141,7 @@
void drawChar(int chr, const Graphics::Surface &s, int x, int y);
void setCurID(byte id);
void setColor(byte color);
- int getFontHeight() { return 8; }
+ int getFontHeight();
int getCharWidth(byte chr);
};
Index: nut_renderer.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/nut_renderer.cpp,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- nut_renderer.cpp 9 Oct 2004 00:47:47 -0000 1.52
+++ nut_renderer.cpp 23 Oct 2004 23:08:51 -0000 1.53
@@ -204,13 +204,8 @@
return 0;
}
- if (c >= 0x80 && _vm->_useCJKMode) {
- if (_vm->_gameId == GID_CMI)
- return 8;
- if (_vm->_gameId == GID_DIG)
- return 6;
- return 0;
- }
+ if (c >= 0x80 && _vm->_useCJKMode)
+ return _vm->_2byteWidth / 2;
if (c >= _numChars)
error("invalid character in NutRenderer::getCharWidth : %d (%d)", c, _numChars);
@@ -225,13 +220,8 @@
return 0;
}
- if (c >= 0x80 && _vm->_useCJKMode) {
- if (_vm->_gameId == GID_CMI)
- return 16;
- if (_vm->_gameId == GID_DIG)
- return 10;
- return 0;
- }
+ if (c >= 0x80 && _vm->_useCJKMode)
+ return _vm->_2byteHeight;
if (c >= _numChars)
error("invalid character in NutRenderer::getCharHeight : %d (%d)", c, _numChars);
Index: string.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/string.cpp,v
retrieving revision 1.259
retrieving revision 1.260
diff -u -d -r1.259 -r1.260
--- string.cpp 22 Oct 2004 10:25:56 -0000 1.259
+++ string.cpp 23 Oct 2004 23:08:51 -0000 1.260
@@ -103,6 +103,8 @@
int code = (_heversion >= 80) ? 127 : 64;
char value[32];
+ bool cmi_pos_hack = false;
+
if (!_haveMsg)
return;
@@ -283,6 +285,11 @@
warning("CHARSET_1: invalid code %d", c);
}
} else if (c == 0xFE || c == 0xFF) {
+ //WORKAROUND
+ //to avoid korean code 0xfe treated as charset message code.
+ if(c == 0xFE && checkKSCode(*(buffer + 1), c) && _useCJKMode) {
+ goto loc_avoid_ks_fe;
+ }
c = *buffer++;
switch (c) {
case 1:
@@ -343,13 +350,19 @@
warning("CHARSET_1: invalid code %d", c);
}
} else {
+loc_avoid_ks_fe:
_charset->_left = _charset->_nextLeft;
_charset->_top = _charset->_nextTop;
if (c & 0x80 && _useCJKMode)
- if (_language == 6 && ((c > 0x84 && c < 0x88) || (c > 0x9f && c < 0xe0) || (c > 0xea && c <= 0xff)))
+ if (_language == Common::JA_JPN && !checkSJISCode(c)) {
c = 0x20; //not in S-JIS
- else
- c += *buffer++ * 256;
+ } else {
+ c += *buffer++ * 256; //LE
+ if(_gameId == GID_CMI) { //HACK: This fixes korean text position in COMI (off by 6 pixel)
+ cmi_pos_hack = true;
+ _charset->_top += 6;
+ }
+ }
if (_version <= 3) {
_charset->printChar(c);
} else {
@@ -363,6 +376,10 @@
} else
_charset->printChar(c);
}
+ if(cmi_pos_hack) {
+ cmi_pos_hack = false;
+ _charset->_top -= 6;
+ }
_charset->_nextLeft = _charset->_left;
_charset->_nextTop = _charset->_top;
@@ -389,6 +406,8 @@
uint color;
int code = (_heversion >= 80) ? 127 : 64;
+ bool cmi_pos_hack = false;
+
addMessageToStack(msg, buf, sizeof(buf));
_charset->_top = _string[a].ypos + _screenTop;
@@ -491,10 +510,24 @@
_charset->_blitAlso = true;
}
}
- if (c >= 0x80 && _useCJKMode)
- c += buf[i++] * 256;
+ if (c & 0x80 && _useCJKMode) {
+ if (_language == Common::JA_JPN && !checkSJISCode(c)) {
+ c = 0x20; //not in S-JIS
+ } else {
+ c += buf[i++] * 256;
+ if(_gameId == GID_CMI) {
+ cmi_pos_hack = true;
+ _charset->_top += 6;
+ }
+ }
+ }
_charset->printChar(c);
_charset->_blitAlso = false;
+
+ if(cmi_pos_hack) {
+ cmi_pos_hack = false;
+ _charset->_top -= 6;
+ }
}
}
@@ -729,8 +762,13 @@
do {
c = *buf++;
if (c != 0 && c != 0xFF) {
- if (c >= 0x80 && _useCJKMode)
- c += *buf++ * 256;
+ if (c & 0x80 && _useCJKMode) {
+ if (_language == Common::JA_JPN && !checkSJISCode(c)) {
+ c = 0x20; //not in S-JIS
+ } else {
+ c += *buf++ * 256;
+ }
+ }
_charset->printChar(c);
}
} while (c);
More information about the Scummvm-git-logs
mailing list