[Scummvm-git-logs] scummvm master -> 08185645313ce511e91ea1fab8a0f334c2d29a6e

sev- sev at scummvm.org
Fri Nov 6 18:29:52 UTC 2020


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
345771f574 SCUMM: Add multi-font support for Korean fan translated games
0818564531 SCUMM: Fix deepcode warning from multifont load method


Commit: 345771f574af482f18a0b9ed6046f1d697479717
    https://github.com/scummvm/scummvm/commit/345771f574af482f18a0b9ed6046f1d697479717
Author: wonst719 (wonst719 at gmail.com)
Date: 2020-11-06T19:29:47+01:00

Commit Message:
SCUMM: Add multi-font support for Korean fan translated games

Changed paths:
    engines/scumm/charset.cpp
    engines/scumm/charset.h
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h


diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 3acfbb3154..05cdddc318 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -42,6 +42,12 @@ The advantage will be cleaner coder (easier to debug, in particular), and a
 better separation of the various modules.
 */
 
+bool CharsetRenderer::isScummvmKorTarget() {
+	if (_vm->_language == Common::KO_KOR && (_vm->_game.version < 7 || _vm->_game.id == GID_FT)) {
+		return true;
+	}
+	return false;
+}
 
 void ScummEngine::loadCJKFont() {
 	Common::File fp;
@@ -49,6 +55,69 @@ void ScummEngine::loadCJKFont() {
 	_textSurfaceMultiplier = 1;
 	_newLineCharacter = 0;
 
+	_useMultiFont = 0;	// Korean Multi-Font
+
+	// Special case for Korean
+	if (_language == Common::KO_KOR && (_game.version < 7 || _game.id == GID_FT)) {
+		int numChar = 2350;
+		_useCJKMode = true;
+
+		if (_game.version < 7 || _game.id == GID_FT)
+			_useMultiFont = 1;
+
+		if (_useMultiFont) {
+			debug("Loading Korean Multi Font System");
+			_numLoadedFont = 0;
+			_2byteFontPtr = NULL;
+			_2byteWidth = 0;
+			_2byteHeight = 0;
+			for (int i = 0; i < 20; i++) {
+				char fontFile[256];
+				sprintf(fontFile, "korean%02d.fnt", i);
+				_2byteMultiFontPtr[i] = NULL;
+				if (fp.open(fontFile)) {
+					_numLoadedFont++;
+					fp.readByte();
+					_2byteMultiShadow[i] = fp.readByte();
+					_2byteMultiWidth[i] = fp.readByte();
+					_2byteMultiHeight[i] = fp.readByte();
+
+					int fontSize = ((_2byteMultiWidth[i] + 7) / 8) * _2byteMultiHeight[i] * numChar;
+					_2byteMultiFontPtr[i] = new byte[fontSize];
+					warning("#%d, size %d, height =%d", i, fontSize, _2byteMultiHeight[i]);
+					fp.read(_2byteMultiFontPtr[i], fontSize);
+					fp.close();
+					if (_2byteFontPtr == NULL) {	// for non-initialized Smushplayer drawChar
+						_2byteFontPtr = _2byteMultiFontPtr[i];
+						_2byteWidth = _2byteMultiWidth[i];
+						_2byteHeight = _2byteMultiHeight[i];
+						_2byteShadow = _2byteMultiShadow[i];
+					}
+				}
+			}
+			if(_numLoadedFont == 0) {
+				warning("Cannot load any font for multi font");
+				_useMultiFont = 0;
+			} else
+				debug("%d fonts are loaded", _numLoadedFont);
+		}
+
+		if (!_useMultiFont) {
+			debug("Loading Korean Single Font System");
+			if (fp.open("korean.fnt")) {
+				fp.seek(2, SEEK_CUR);
+				_2byteWidth = fp.readByte();
+				_2byteHeight = fp.readByte();
+				_2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar];
+				fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar);
+				fp.close();
+			} else {
+				error("Couldn't load any font: %s", fp.getName());
+			}
+		}
+		return;
+	}
+
 	if (_game.version <= 5 && _game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) { // FM-TOWNS v3 / v5 Kanji
 #if defined(DISABLE_TOWNS_DUAL_LAYER_MODE) || !defined(USE_RGB_COLOR)
 		GUIErrorMessage("FM-Towns Kanji font drawing requires dual graphics layer support which is disabled in this build");
@@ -280,6 +349,35 @@ void CharsetRendererCommon::setCurID(int32 id) {
 	_bytesPerPixel = _fontPtr[0];
 	_fontHeight = _fontPtr[1];
 	_numChars = READ_LE_UINT16(_fontPtr + 2);
+
+	if(_vm->_useMultiFont) {
+		if (id == 6) {	// HACK: Fix inventory font error
+			_vm->_2byteFontPtr = _vm->_2byteMultiFontPtr[0];
+			_vm->_2byteWidth = _vm->_2byteMultiWidth[0];
+			_vm->_2byteHeight = _vm->_2byteMultiHeight[0];
+			_vm->_2byteShadow = _vm->_2byteMultiShadow[0];
+		} else if (_vm->_2byteMultiFontPtr[id]) {
+			_vm->_2byteFontPtr = _vm->_2byteMultiFontPtr[id];
+			_vm->_2byteWidth = _vm->_2byteMultiWidth[id];
+			_vm->_2byteHeight = _vm->_2byteMultiHeight[id];
+			_vm->_2byteShadow = _vm->_2byteMultiShadow[id];
+		} else {
+			// Get nearest font set (by height)
+			debug(7, "Cannot find matching font set for charset #%d, use nearest font set", id);
+			int dstHeight = _fontHeight;
+			int nearest = 0;
+			for (int i = 0; i < _vm->_numLoadedFont; i++) {
+				if (ABS(_vm->_2byteMultiHeight[i] - dstHeight) <= ABS(_vm->_2byteMultiHeight[nearest] - dstHeight)) {
+					nearest = i;
+				}
+			}
+			debug(7, "Found #%d", nearest);
+			_vm->_2byteFontPtr = _vm->_2byteMultiFontPtr[nearest];
+			_vm->_2byteWidth = _vm->_2byteMultiWidth[nearest];
+			_vm->_2byteHeight = _vm->_2byteMultiHeight[nearest];
+			_vm->_2byteShadow = _vm->_2byteMultiShadow[nearest];
+		}
+	}
 }
 
 void CharsetRendererV3::setCurID(int32 id) {
@@ -301,6 +399,35 @@ void CharsetRendererV3::setCurID(int32 id) {
 	_fontPtr += 6;
 	_widthTable = _fontPtr;
 	_fontPtr += _numChars;
+
+	if(_vm->_useMultiFont) {
+		if (id == 6) {	// HACK: Fix inventory font error
+			_vm->_2byteFontPtr = _vm->_2byteMultiFontPtr[0];
+			_vm->_2byteWidth = _vm->_2byteMultiWidth[0];
+			_vm->_2byteHeight = _vm->_2byteMultiHeight[0];
+			_vm->_2byteShadow = _vm->_2byteMultiShadow[0];
+		} else if (_vm->_2byteMultiFontPtr[id]) {
+			_vm->_2byteFontPtr = _vm->_2byteMultiFontPtr[id];
+			_vm->_2byteWidth = _vm->_2byteMultiWidth[id];
+			_vm->_2byteHeight = _vm->_2byteMultiHeight[id];
+			_vm->_2byteShadow = _vm->_2byteMultiShadow[id];
+		} else {
+			// Get nearest font set (by height)
+			debug(7, "Cannot find matching font set for charset #%d, use nearest font set", id);
+			int dstHeight = _fontHeight;
+			int nearest = 0;
+			for (int i = 0; i < _vm->_numLoadedFont; i++) {
+				if (ABS(_vm->_2byteMultiHeight[i] - dstHeight) <= ABS(_vm->_2byteMultiHeight[nearest] - dstHeight)) {
+					nearest = i;
+				}
+			}
+			debug(7, "Found #%d", nearest);
+			_vm->_2byteFontPtr = _vm->_2byteMultiFontPtr[nearest];
+			_vm->_2byteWidth = _vm->_2byteMultiWidth[nearest];
+			_vm->_2byteHeight = _vm->_2byteMultiHeight[nearest];
+			_vm->_2byteShadow = _vm->_2byteMultiShadow[nearest];
+		}
+	}
 }
 
 int CharsetRendererCommon::getFontHeight() {
@@ -536,6 +663,64 @@ void CharsetRendererPC::enableShadow(bool enable) {
 void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
 	byte *dst = (byte *)dest.getBasePtr(x, y);
 
+	if (_vm->_useCJKMode && isScummvmKorTarget()) {
+		int y, x;
+		byte bits = 0;
+
+		// HACK: Since Korean fonts don't have shadow/stroke information,
+		//	   we use NUT-Renderer-like shadow drawing method.
+		bool useOldShadow = false;
+
+		int offsetX[14] = {-2, -2, -2, -1, 0, -1, 0, 1, -1, 1, -1, 0, 1, 0};
+		int offsetY[14] = {0, 1, 2, 2, 2, -1, -1, -1, 0, 0, 1, 1, 1, 0};
+		int cTable[14] = {_shadowColor, _shadowColor, _shadowColor,
+		                  _shadowColor, _shadowColor, _shadowColor, _shadowColor,
+		                  _shadowColor, _shadowColor, _shadowColor, _shadowColor,
+		                  _shadowColor, _shadowColor, _color};
+		int i = 0;
+
+		switch (_vm->_2byteShadow) {
+		case 1: // No shadow
+			i = 13;
+			break;
+		case 2: // SE direction shadow
+			i = 12;
+			break;
+		case 3: // Stroke & SW direction shadow ("Monkey2", "Indy4")
+			i = 0;
+			break;
+		default: // Stroke
+			i = 5;
+		}
+
+		const byte *origSrc = src;
+		byte *origDst = dst;
+
+		for (; i < 14; i++) {
+			src = origSrc;
+			dst = origDst;
+
+			for (y = 0; y < height && y + drawTop + offsetY[i] < dest.h; y++) {
+				for (x = 0; x < width && x + offsetY[i] < dest.w; x++) {
+					if ((x % 8) == 0)
+						bits = *src++;
+					if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
+						if (_enableShadow) {
+							*(dst + 1) = _shadowColor;
+							*(dst + dest.pitch) = _shadowColor;
+							*(dst + dest.pitch + 1) = _shadowColor;
+						}
+						*(dst + (dest.pitch * offsetY[i]) + offsetX[i]) = cTable[i];
+					}
+					dst++;
+				}
+
+				dst += dest.pitch - width;
+			}
+		}
+		return;
+	}
+
 	byte bits = 0;
 	uint8 col = _color;
 	int pitch = dest.pitch - width * dest.format.bytesPerPixel;
@@ -628,9 +813,21 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
 	if (chr == '@')
 		return;
 
-	charPtr = (_vm->_useCJKMode && chr > 127) ? _vm->get2byteCharPtr(chr) : _fontPtr + chr * 8;
-	width = getDrawWidthIntern(chr);
-	height = getDrawHeightIntern(chr);
+	if (isScummvmKorTarget()) {
+		if (is2byte) {
+			charPtr = _vm->get2byteCharPtr(chr);
+			width = _vm->_2byteWidth;
+			height = _vm->_2byteHeight;
+		} else {
+			charPtr = _fontPtr + chr * 8;
+			width = getDrawWidthIntern(chr);
+			height = getDrawHeightIntern(chr);
+		}
+	} else {
+		charPtr = (_vm->_useCJKMode && chr > 127) ? _vm->get2byteCharPtr(chr) : _fontPtr + chr * 8;
+		width = getDrawWidthIntern(chr);
+		height = getDrawHeightIntern(chr);
+	}
 	setDrawCharIntern(chr);
 
 	origWidth = width;
@@ -692,9 +889,26 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
 }
 
 void CharsetRendererV3::drawChar(int chr, Graphics::Surface &s, int x, int y) {
-	const byte *charPtr = (_vm->_useCJKMode && chr > 127) ? _vm->get2byteCharPtr(chr) : _fontPtr + chr * 8;
-	int width = getDrawWidthIntern(chr);
-	int height = getDrawHeightIntern(chr);
+	const byte *charPtr;
+	int width;
+	int height;
+	int is2byte = (chr > 0xff && _vm->_useCJKMode) ? 1 : 0;
+
+	if (isScummvmKorTarget()) {
+		if (is2byte) {
+			charPtr = _vm->get2byteCharPtr(chr);
+			width = _vm->_2byteWidth;
+			height = _vm->_2byteHeight;
+		} else {
+			charPtr = _fontPtr + chr * 8;
+			width = getDrawWidthIntern(chr);
+			height = getDrawHeightIntern(chr);
+		}
+	} else {
+		charPtr = (_vm->_useCJKMode && chr > 127) ? _vm->get2byteCharPtr(chr) : _fontPtr + chr * 8;
+		width = getDrawWidthIntern(chr);
+		height = getDrawHeightIntern(chr);
+	}
 	setDrawCharIntern(chr);
 	drawBits1(s, x, y, charPtr, y, width, height);
 }
@@ -740,9 +954,21 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
 	translateColor();
 
 	_vm->_charsetColorMap[1] = _color;
+	if (isScummvmKorTarget() && is2byte) {
+		enableShadow(true);
+		_charPtr = _vm->get2byteCharPtr(chr);
+		_width = _vm->_2byteWidth;
+		_height = _vm->_2byteHeight;
+		_offsX = _offsY = 0;
+	} else {
+		if (!prepareDraw(chr))
+			return;
+	}
 
-	if (!prepareDraw(chr))
-		return;
+	if (isScummvmKorTarget()) {
+		_origWidth = _width;
+		_origHeight = _height;
+	}
 
 	if (_firstChar) {
 		_str.left = 0;
@@ -1014,6 +1240,10 @@ CharsetRendererTownsV3::CharsetRendererTownsV3(ScummEngine *vm) : CharsetRendere
 }
 
 int CharsetRendererTownsV3::getCharWidth(uint16 chr) {
+	if (isScummvmKorTarget()) {
+		return CharsetRendererV3::getCharWidth(chr);
+	}
+
 	int spacing = 0;
 
 	if (_vm->_useCJKMode) {
@@ -1030,10 +1260,19 @@ int CharsetRendererTownsV3::getCharWidth(uint16 chr) {
 }
 
 int CharsetRendererTownsV3::getFontHeight() {
+	if (isScummvmKorTarget()) {
+		return CharsetRendererV3::getFontHeight();
+	}
+
 	return _vm->_useCJKMode ? 8 : _fontHeight;
 }
 
 void CharsetRendererTownsV3::enableShadow(bool enable) {
+	if (isScummvmKorTarget()) {
+		CharsetRendererV3::enableShadow(enable);
+		return;
+	}
+
 	_shadowColor = 8;
 	_enableShadow = enable;
 
@@ -1047,6 +1286,11 @@ void CharsetRendererTownsV3::enableShadow(bool enable) {
 }
 
 void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
+	if (isScummvmKorTarget()) {
+		CharsetRendererV3::drawBits1(dest, x, y, src, drawTop, width, height);
+		return;
+	}
+
 #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
 #ifdef USE_RGB_COLOR
 	if (_sjisCurChar) {
@@ -1127,6 +1371,10 @@ void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, co
 }
 #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
 int CharsetRendererTownsV3::getDrawWidthIntern(uint16 chr) {
+	if (isScummvmKorTarget()) {
+		return CharsetRendererV3::getDrawWidthIntern(chr);
+	}
+
 #ifdef USE_RGB_COLOR
 	if (_vm->_useCJKMode && chr > 127) {
 		assert(_vm->_cjkFont);
@@ -1137,6 +1385,10 @@ int CharsetRendererTownsV3::getDrawWidthIntern(uint16 chr) {
 }
 
 int CharsetRendererTownsV3::getDrawHeightIntern(uint16 chr) {
+	if (isScummvmKorTarget()) {
+		return CharsetRendererV3::getDrawHeightIntern(chr);
+	}
+
 #ifdef USE_RGB_COLOR
 	if (_vm->_useCJKMode && chr > 127) {
 		assert(_vm->_cjkFont);
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 2c52f81924..688843cd75 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -97,6 +97,8 @@ public:
 
 	virtual void setColor(byte color) { _color = color; translateColor(); }
 
+	bool isScummvmKorTarget();
+
 	void saveLoadWithSerializer(Common::Serializer &ser);
 };
 
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 6bc433fa51..08759d67ea 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -325,6 +325,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
 	_costumeRenderer = NULL;
 	_2byteFontPtr = 0;
 	_V1TalkingActor = 0;
+	for (int i = 0; i < 20; i++)
+		_2byteMultiFontPtr[i] = NULL;
 	_NESStartStrip = 0;
 
 	_skipDrawObject = 0;
@@ -614,7 +616,11 @@ ScummEngine::~ScummEngine() {
 
 	delete[] _sortedActors;
 
-	delete[] _2byteFontPtr;
+	if (_2byteFontPtr && !_useMultiFont)
+		delete _2byteFontPtr;
+	for (int i = 0; i < 20; i++)
+		if (_2byteMultiFontPtr[i])
+			delete _2byteMultiFontPtr[i];
 	delete _charset;
 	delete _messageDialog;
 	delete _pauseDialog;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index cb9daad229..cb5ab69ea6 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1137,13 +1137,22 @@ public:
 
 	// Somewhat hackish stuff for 2 byte support (Chinese/Japanese/Korean)
 	bool _useCJKMode;
+	bool _useMultiFont;
+	int _numLoadedFont;
+	int _currentFont;
+	int _2byteShadow;
+
 	int _2byteHeight;
 	int _2byteWidth;
 	byte _newLineCharacter;
 	byte *get2byteCharPtr(int idx);
 
-protected:
+//protected:
 	byte *_2byteFontPtr;
+	byte *_2byteMultiFontPtr[20];
+	int _2byteMultiHeight[20];
+	int _2byteMultiWidth[20];
+	int _2byteMultiShadow[20];
 
 public:
 


Commit: 08185645313ce511e91ea1fab8a0f334c2d29a6e
    https://github.com/scummvm/scummvm/commit/08185645313ce511e91ea1fab8a0f334c2d29a6e
Author: wonst719 (wonst719 at gmail.com)
Date: 2020-11-06T19:29:47+01:00

Commit Message:
SCUMM: Fix deepcode warning from multifont load method

- use snprintf() instead of sprintf()

Changed paths:
    engines/scumm/charset.cpp


diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 05cdddc318..36e297b30d 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -73,7 +73,7 @@ void ScummEngine::loadCJKFont() {
 			_2byteHeight = 0;
 			for (int i = 0; i < 20; i++) {
 				char fontFile[256];
-				sprintf(fontFile, "korean%02d.fnt", i);
+				snprintf(fontFile, sizeof(fontFile), "korean%02d.fnt", i);
 				_2byteMultiFontPtr[i] = NULL;
 				if (fp.open(fontFile)) {
 					_numLoadedFont++;




More information about the Scummvm-git-logs mailing list