Index: scumm/charset.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/charset.cpp,v
retrieving revision 2.119
diff -u -r2.119 charset.cpp
--- scumm/charset.cpp	9 Oct 2004 00:33:35 -0000	2.119
+++ scumm/charset.cpp	16 Oct 2004 09:31:54 -0000
@@ -23,78 +23,81 @@
 #include "scumm/scumm.h"
 #include "scumm/nut_renderer.h"
 
+#include "scumm/cjkcode.h"
+
 namespace Scumm {
 
 void ScummEngine::loadCJKFont() {
 	_useCJKMode = false;
-	if ((_gameId == GID_DIG || _gameId == GID_CMI) && (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN)) {
+	if (_language == Common::JA_JPN && _version <= 5) { // FM-TOWNS v3 / v5 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", File::kFileReadMode, getGameDataPath())
+			|| 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) {
+		File fp;
+		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:
 			break;
 		}
-		if (fontFile && fp.open(fontFile)) {
+
+		char pathS[1024];
+		char pathV[1024];
+		sprintf(pathS, "%sresource/", getGameDataPath());
+		sprintf(pathV, "%svideo/", getGameDataPath());
+		if (fontFile && (fp.open(fontFile, File::kFileReadMode, getGameDataPath())
+				|| fp.open(fontFile, File::kFileReadMode, pathS)
+				|| fp.open(fontFile, File::kFileReadMode, pathV))) {
 			debug(2, "Loading CJK Font");
 			_useCJKMode = true;
 			fp.seek(2, SEEK_CUR);
 			_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 +118,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 +166,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 +248,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;
+	if (chr >= 0x80 && _vm->_useCJKMode)
+		return _vm->_2byteWidth / 2;
 	int spacing = 0;
 
 	int offs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
@@ -276,6 +300,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 +327,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 +367,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 +404,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 +1149,8 @@
 }
 
 int CharsetRendererV3::getCharWidth(byte chr) {
+	if (chr & 0x80 && _vm->_useCJKMode)
+		return _vm->_2byteWidth / 2;
 	int spacing = 0;
 
 	spacing = *(_widthTable + chr);
@@ -1129,10 +1175,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 +1188,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 +1215,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 +1224,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 +1247,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 +1285,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 +1474,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 +1625,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: scumm/charset.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/charset.h,v
retrieving revision 2.31
diff -u -r2.31 charset.h
--- scumm/charset.h	31 Aug 2004 07:40:28 -0000	2.31
+++ scumm/charset.h	16 Oct 2004 09:09:02 -0000
@@ -94,7 +94,7 @@
 
 	void setCurID(byte id);
 	
-	int getFontHeight() { return _fontPtr[1]; }
+	int getFontHeight();
 };
 
 class CharsetRendererClassic : public CharsetRendererCommon {
@@ -122,7 +122,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: scumm/nut_renderer.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/nut_renderer.cpp,v
retrieving revision 1.52
diff -u -r1.52 nut_renderer.cpp
--- scumm/nut_renderer.cpp	9 Oct 2004 00:47:47 -0000	1.52
+++ scumm/nut_renderer.cpp	16 Oct 2004 10:13:08 -0000
@@ -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: scumm/string.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/string.cpp,v
retrieving revision 1.258
diff -u -r1.258 string.cpp
--- scumm/string.cpp	1 Oct 2004 09:03:01 -0000	1.258
+++ scumm/string.cpp	16 Oct 2004 09:37:44 -0000
@@ -32,6 +32,8 @@
 #include "scumm/verbs.h"
 #include "scumm/sound.h"
 
+#include "scumm/cjkcode.h"
+
 namespace Scumm {
 
 void ScummEngine::printString(int m, const byte *msg) {
@@ -103,6 +105,8 @@
 	int code = (_heversion >= 80) ? 127 : 64;
 	char value[32];
 
+	bool cmi_pos_hack = false;
+
 	if (!_haveMsg)
 		return;
 
@@ -283,6 +287,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 +352,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 +378,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 +408,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 +512,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 +764,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);
Index: scumm/smush/smush_font.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/smush_font.cpp,v
retrieving revision 1.23
diff -u -r1.23 smush_font.cpp
--- scumm/smush/smush_font.cpp	18 Sep 2004 22:42:45 -0000	1.23
+++ scumm/smush/smush_font.cpp	16 Oct 2004 10:42:10 -0000
@@ -43,7 +43,11 @@
 
 	int width = 0;
 	while (*str) {
-		width += getCharWidth(*str++);
+		if(*str & 0x80 && g_scumm->_useCJKMode) {
+			width += g_scumm->_2byteWidth + 1;
+			str += 2;
+		} else
+			width += getCharWidth(*str++);
 	}
 	return width;
 }
@@ -118,18 +122,25 @@
 	int h = _vm->_2byteHeight;
 
 	byte *src = _vm->get2byteCharPtr(idx);
-	byte *dst = buffer + dst_width * (y + (_vm->_gameId == GID_CMI ? 7 : 2)) + x;
+	byte *dst = buffer + dst_width * (y + (_vm->_gameId == GID_CMI ? 7 : (_vm->_gameId == GID_DIG ? 2 : 0))) + x;
 	byte bits = 0;
 
 	char color = (_color != -1) ? _color : 1;
+
 	if (_new_colors)
-		color = (char)0xff; //FIXME;
+		color = (char)0xff;
+
+	if (g_scumm->_gameId == GID_FT)
+		color = 1;
+
 	for (int j = 0; j < h; j++) {
 		for (int i = 0; i < w; i++) {
 			if ((i % 8) == 0)
 				bits = *src++;
 			if (bits & revBitMask[i % 8]) {
 				dst[i + 1] = 0;
+				dst[dst_width + i] = 0;
+				dst[dst_width + i + 1] = 0;
 				dst[i] = color;
 			}
 		}
