[Scummvm-cvs-logs] SF.net SVN: scummvm:[44488] scummvm/trunk/engines/kyra

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Wed Sep 30 16:53:57 CEST 2009


Revision: 44488
          http://scummvm.svn.sourceforge.net/scummvm/?rev=44488&view=rev
Author:   lordhoto
Date:     2009-09-30 14:53:57 +0000 (Wed, 30 Sep 2009)

Log Message:
-----------
Adapt KYRA engine to use the ASCII and half-width katakana support of the SJIS font. (required for LoL PC98)

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/screen.cpp
    scummvm/trunk/engines/kyra/screen.h

Modified: scummvm/trunk/engines/kyra/screen.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen.cpp	2009-09-30 14:53:34 UTC (rev 44487)
+++ scummvm/trunk/engines/kyra/screen.cpp	2009-09-30 14:53:57 UTC (rev 44488)
@@ -47,7 +47,6 @@
 	_drawShapeVar4 = 0;
 	_drawShapeVar5 = 0;
 
-	_sjisFont = 0;
 	memset(_fonts, 0, sizeof(_fonts));
 
 	_currentFont = FID_8_FNT;
@@ -63,7 +62,6 @@
 	for (int f = 0; f < ARRAYSIZE(_fonts); ++f)
 		delete _fonts[f];
 
-	delete _sjisFont;
 	delete _screenPalette;
 	delete _internFadePalette;
 	delete[] _decodeShapeBuffer;
@@ -83,6 +81,7 @@
 	_useSJIS = false;
 	_use16ColorMode = _vm->gameFlags().use16ColorMode;
 	_isAmiga = (_vm->gameFlags().platform == Common::kPlatformAmiga);
+	memset(_fonts, 0, sizeof(_fonts));
 
 	if (_vm->gameFlags().useHiResOverlay) {
 		_useOverlays = true;
@@ -98,11 +97,12 @@
 		}
 
 		if (_useSJIS) {
-			_sjisFont = Graphics::FontSJIS::createFont(_vm->gameFlags().platform);
+			Graphics::FontSJIS *font = Graphics::FontSJIS::createFont(_vm->gameFlags().platform);
 
-			if (!_sjisFont)
+			if (!font)
 				error("Could not load any SJIS font, neither the original nor ScummVM's 'SJIS.FNT'");
-			_sjisFont->enableOutline(!_use16ColorMode);
+
+			_fonts[FID_SJIS_FNT] = new SJISFont(font, _sjisInvisibleColor, _use16ColorMode);
 		}
 	}
 
@@ -140,7 +140,7 @@
 
 		for (int i = 0; i < 8; ++i) {
 			palette[i * 4 + 0] = ((i >> 1) & 1) * 0xFF;
-			palette[i * 4 + 1] = ((i >> 2) & 1)	* 0xFF;
+			palette[i * 4 + 1] = ((i >> 2) & 1) * 0xFF;
 			palette[i * 4 + 2] = ((i >> 0) & 1) * 0xFF;
 			palette[i * 4 + 3] = 0;
 
@@ -151,7 +151,6 @@
 	_curDim = 0;
 	_charWidth = 0;
 	_charOffset = 0;
-	memset(_fonts, 0, sizeof(_fonts));
 	for (int i = 0; i < ARRAYSIZE(_textColorsMap); ++i)
 		_textColorsMap[i] = i;
 	_decodeShapeBuffer = NULL;
@@ -1081,9 +1080,21 @@
 
 void Screen::setTextColor(const uint8 *cmap, int a, int b) {
 	memcpy(&_textColorsMap[a], cmap, b-a+1);
+
+	// We need to update the color tables of all fonts, we
+	// setup so far here.
+	for (int i = 0; i < FID_NUM; ++i) {
+		if (_fonts[i])
+			_fonts[i]->setColorMap(_textColorsMap);
+	}
 }
 
 bool Screen::loadFont(FontId fontId, const char *filename) {
+	if (fontId == FID_SJIS_FNT) {
+		warning("Trying to replace system SJIS font.");
+		return true;
+	}
+
 	Font *&fnt = _fonts[fontId];
 
 	if (!fnt) {
@@ -1110,7 +1121,6 @@
 	_currentFont = fontId;
 
 	assert(_fonts[_currentFont]);
-
 	return prev;
 }
 
@@ -1123,18 +1133,19 @@
 }
 
 int Screen::getCharWidth(uint16 c) const {
-	if ((c & 0xFF00) && _sjisFont)
-		return _sjisFont->getMaxFontWidth() >> 1;
-
-	return _fonts[_currentFont]->getCharWidth(c) + _charWidth;
+	if (isSJISChar(c))
+		return _fonts[FID_SJIS_FNT]->getCharWidth(c) + _charWidth;
+	else
+		return _fonts[_currentFont]->getCharWidth(c) + _charWidth;
 }
 
 int Screen::getTextWidth(const char *str) const {
 	int curLineLen = 0;
 	int maxLineLen = 0;
+
 	while (1) {
-		uint c = *str++;
-		c &= 0xFF;
+		uint c = fetchChar(str);
+
 		if (c == 0) {
 			break;
 		} else if (c == '\r') {
@@ -1143,13 +1154,7 @@
 			else
 				curLineLen = 0;
 		} else {
-			if (c <= 0x7F || !_useSJIS) {
-				curLineLen += getCharWidth(c);
-			} else {
-				c = READ_LE_UINT16(str - 1);
-				++str;
-				curLineLen += getCharWidth(c);
-			}
+			curLineLen += getCharWidth(c);
 		}
 	}
 
@@ -1162,8 +1167,11 @@
 	cmap[1] = color1;
 	setTextColor(cmap, 0, 1);
 
+	FontId oldFont = FID_NUM;
+	if (requiresSJISFont(str))
+		oldFont = setFont(FID_SJIS_FNT);
+
 	const uint8 charHeightFnt = getFontHeight();
-	uint8 charHeight = 0;
 
 	if (x < 0)
 		x = 0;
@@ -1177,51 +1185,73 @@
 		return;
 
 	while (1) {
-		uint c = *str++;
-		c &= 0xFF;
+		uint c = fetchChar(str);
 
 		if (c == 0) {
 			break;
 		} else if (c == '\r') {
 			x = x_start;
-			y += charHeight + _charOffset;
+			y += charHeightFnt + _charOffset;
 		} else {
 			int charWidth = getCharWidth(c);
 			if (x + charWidth > SCREEN_W) {
 				x = x_start;
-				y += charHeight + _charOffset;
+				y += charHeightFnt + _charOffset;
 				if (y >= SCREEN_H)
 					break;
 			}
 
-			if (!_useSJIS) {
-				drawCharANSI(c, x, y);
-				charHeight = charHeightFnt;
-			} else {
-				if (c <= 0x7F) {
-					// draw ANSI chars through the setup font
-					drawCharANSI(c, x, y);
-					charHeight = charHeightFnt;
-				} else if (c >= 0xA1 && c <= 0xDF) {
-					warning("Use of unsupported half-width katakana %.2X", c);
-				} else {
-					c = READ_LE_UINT16(str - 1);
-					++str;
-					charWidth = getCharWidth(c);
-					charHeight = _sjisFont->getFontHeight() >> 1;
-					drawCharSJIS(c, x, y);
-				}
-			}
-
+			drawChar(c, x, y);
 			x += charWidth;
 		}
 	}
+
+	if (oldFont != FID_NUM)
+		setFont(oldFont);
 }
 
-void Screen::drawCharANSI(uint8 c, int x, int y) {
+bool Screen::isSJISChar(uint16 c) const {
+	if (!_useSJIS)
+		return false;
+
+	if (c & 0xFF00)
+		return true;
+	else if ((c & 0xFF) >= 0xA1 && (c & 0xFF) <= 0xDF)
+		return true;
+
+	return false;
+}
+
+bool Screen::requiresSJISFont(const char *s) const {
+	if (!_useSJIS)
+		return false;
+
+	while (*s) {
+		if (isSJISChar(fetchChar(s)))
+			return true;
+	}
+
+	return false;
+}
+
+uint16 Screen::fetchChar(const char *&s) const {
+	if (!_useSJIS)
+		return (uint8)*s++;
+
+	uint16 ch = (uint8)*s++;
+
+	if (ch <= 0x7F || (ch >= 0xA1 && ch <= 0xDF))
+		return ch;
+
+	ch |= (uint8)(*s++) << 8;
+	return ch;
+}
+
+void Screen::drawChar(uint16 c, int x, int y) {
 	Font *fnt = _fonts[_currentFont];
 	assert(fnt);
 
+	const bool useOverlay = fnt->usesOverlay();
 	const int charWidth = fnt->getCharWidth(c);
 	const int charHeight = fnt->getHeight();
 
@@ -1230,8 +1260,20 @@
 	if (x + charWidth > SCREEN_W || y + charHeight > SCREEN_H)
 		return;
 
-	fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W);
+	if (useOverlay) {
+		uint8 *destPage = getOverlayPtr(_curPage);
+		if (!destPage) {
+			warning("trying to draw SJIS char on unsupported page %d", _curPage);
+			return;
+		}
 
+		destPage += (y * 2) * 640 + (x * 2);
+
+		fnt->drawChar(c, destPage, 640);
+	} else {
+		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W);
+	}
+
 	if (_curPage == 0 || _curPage == 1)
 		addDirtyRect(x, y, charWidth, charHeight);
 }
@@ -3063,41 +3105,6 @@
 	}
 }
 
-void Screen::drawCharSJIS(uint16 c, int x, int y) {
-	int color1, color2;
-
-	if (_use16ColorMode) {
-		// PC98 16 color games specify a color value which is for the
-		// PC98 text mode palette, thus we need to remap it.
-		color1 = ((_textColorsMap[1] >> 5) & 0x7) + 16; 
-		color2 = ((_textColorsMap[0] >> 5) & 0x7) + 16;
-	} else {
-		color1 = _textColorsMap[1];
-		color2 = _textColorsMap[0];
-
-		if (color2 == _sjisInvisibleColor)
-			_sjisFont->enableOutline(false);
-	}
-
-	if (_curPage == 0 || _curPage == 1)
-		addDirtyRect(x, y, _sjisFont->getMaxFontWidth() >> 1, _sjisFont->getFontHeight() >> 1);
-
-	x <<= 1;
-	y <<= 1;
-
-	uint8 *destPage = getOverlayPtr(_curPage);
-	if (!destPage) {
-		warning("trying to draw SJIS char on unsupported page %d", _curPage);
-		return;
-	}
-
-	destPage += y * 640 + x;
-
-	_sjisFont->drawChar(destPage, c, 640, 1, color1, color2);
-
-	_sjisFont->enableOutline(!_use16ColorMode);
-}
-
 #pragma mark -
 
 DOSFont::DOSFont() {
@@ -3140,13 +3147,13 @@
 	return true;
 }
 
-int DOSFont::getCharWidth(uint8 c) const {
+int DOSFont::getCharWidth(uint16 c) const {
 	if (c >= _numGlyphs)
 		return 0;
 	return _widthTable[c];
 }
 
-void DOSFont::drawChar(uint8 c, byte *dst, int pitch) const {
+void DOSFont::drawChar(uint16 c, byte *dst, int pitch) const {
 	if (c >= _numGlyphs)
 		return;
 
@@ -3282,13 +3289,13 @@
 	return !file.err();
 }
 
-int AMIGAFont::getCharWidth(uint8 c) const {
+int AMIGAFont::getCharWidth(uint16 c) const {
 	if (c >= 255)
 		return 0;
 	return _chars[c].width;
 }
 
-void AMIGAFont::drawChar(uint8 c, byte *dst, int pitch) const {
+void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch) const {
 	if (c >= 255)
 		return;
 
@@ -3322,6 +3329,56 @@
 	memset(_chars, 0, sizeof(_chars));
 }
 
+SJISFont::SJISFont(Graphics::FontSJIS *font, const uint8 invisColor, bool is16Color)
+    : _colorMap(0), _font(font), _invisColor(invisColor), _is16Color(is16Color) {
+	assert(_font);
+	_font->enableOutline(!is16Color);
+}
+
+void SJISFont::unload() {
+	delete _font;
+	_font = 0;
+}
+
+int SJISFont::getHeight() const {
+	return _font->getFontHeight() >> 1;
+}
+
+int SJISFont::getWidth() const {
+	return _font->getMaxFontWidth() >> 1;
+}
+
+int SJISFont::getCharWidth(uint16 c) const {
+	return _font->getCharWidth(c) >> 1;
+}
+
+void SJISFont::setColorMap(const uint8 *src) {
+	_colorMap = src;
+
+	if (!_is16Color) {
+		if (_colorMap[0] == _invisColor)
+			_font->enableOutline(false);
+		else
+			_font->enableOutline(true);
+	}
+}
+
+void SJISFont::drawChar(uint16 c, byte *dst, int pitch) const {
+	uint8 color1, color2;
+
+	if (_is16Color) {
+		// PC98 16 color games specify a color value which is for the
+		// PC98 text mode palette, thus we need to remap it.
+		color1 = ((_colorMap[1] >> 5) & 0x7) + 16; 
+		color2 = ((_colorMap[0] >> 5) & 0x7) + 16;
+	} else {
+		color1 = _colorMap[1];
+		color2 = _colorMap[0];
+	}
+
+	_font->drawChar(dst, c, 640, 1, color1, color2);
+}
+
 #pragma mark -
 
 Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) {

Modified: scummvm/trunk/engines/kyra/screen.h
===================================================================
--- scummvm/trunk/engines/kyra/screen.h	2009-09-30 14:53:34 UTC (rev 44487)
+++ scummvm/trunk/engines/kyra/screen.h	2009-09-30 14:53:57 UTC (rev 44488)
@@ -69,6 +69,11 @@
 	virtual bool load(Common::SeekableReadStream &file) = 0;
 
 	/**
+	 * Whether the font draws on the overlay.
+	 */
+	virtual bool usesOverlay() const { return false; }
+
+	/**
 	 * The font height.
 	 */
 	virtual int getHeight() const = 0;
@@ -82,7 +87,7 @@
 	/**
 	 * Gets the width of a specific character.
 	 */
-	virtual int getCharWidth(uint8 c) const = 0;
+	virtual int getCharWidth(uint16 c) const = 0;
 
 	/**
 	 * Sets a text palette map. The map contains 16 entries.
@@ -97,7 +102,7 @@
 	 * We use this API, since it's hard to assure dirty rect
 	 * handling from outside Screen.
 	 */
-	virtual void drawChar(uint8 c, byte *dst, int pitch) const = 0;
+	virtual void drawChar(uint16 c, byte *dst, int pitch) const = 0;
 };
 
 /**
@@ -114,9 +119,9 @@
 	bool load(Common::SeekableReadStream &file);
 	int getHeight() const { return _height; }
 	int getWidth() const { return _width; }
-	int getCharWidth(uint8 c) const;
+	int getCharWidth(uint16 c) const;
 	void setColorMap(const uint8 *src) { _colorMap = src; }
-	void drawChar(uint8 c, byte *dst, int pitch) const;
+	void drawChar(uint16 c, byte *dst, int pitch) const;
 
 private:
 	void unload();
@@ -145,9 +150,9 @@
 	bool load(Common::SeekableReadStream &file);
 	int getHeight() const { return _height; }
 	int getWidth() const { return _width; }
-	int getCharWidth(uint8 c) const;
+	int getCharWidth(uint16 c) const;
 	void setColorMap(const uint8 *src) {}
-	void drawChar(uint8 c, byte *dst, int pitch) const;
+	void drawChar(uint16 c, byte *dst, int pitch) const;
 
 private:
 	void unload();
@@ -167,6 +172,32 @@
 };
 
 /**
+ * Implementation of the Font interface for FM-Towns/PC98 fonts
+ */
+class SJISFont : public Font {
+public:
+	SJISFont(Graphics::FontSJIS *font, const uint8 invisColor, bool is16Color);
+	~SJISFont() { unload(); }
+
+	bool usesOverlay() const { return true; }
+
+	bool load(Common::SeekableReadStream &) { return true; }
+	int getHeight() const;
+	int getWidth() const;
+	int getCharWidth(uint16 c) const;
+	void setColorMap(const uint8 *src);
+	void drawChar(uint16 c, byte *dst, int pitch) const;
+private:
+	void unload();
+
+	const uint8 *_colorMap;
+
+	Graphics::FontSJIS *_font;
+	const uint8 _invisColor;
+	const bool _is16Color;
+};
+
+/**
  * A class that manages KYRA palettes.
  *
  * This class stores the palette data as VGA RGB internally.
@@ -298,6 +329,7 @@
 		FID_BOOKFONT_FNT,
 		FID_GOLDFONT_FNT,
 		FID_INTRO_FNT,
+		FID_SJIS_FNT,
 		FID_NUM
 	};
 
@@ -460,8 +492,10 @@
 	void copyOverlayRegion(int x, int y, int x2, int y2, int w, int h, int srcPage, int dstPage);
 
 	// font/text specific
-	void drawCharANSI(uint8 c, int x, int y);
-	void drawCharSJIS(uint16 c, int x, int y);
+	bool isSJISChar(uint16 ch) const;
+	bool requiresSJISFont(const char *s) const;
+	uint16 fetchChar(const char *&s) const;
+	void drawChar(uint16 c, int x, int y);
 
 	int16 encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size);
 
@@ -476,7 +510,6 @@
 	bool _use16ColorMode;
 	bool _isAmiga;
 
-	Graphics::FontSJIS *_sjisFont;
 	uint8 _sjisInvisibleColor;
 
 	Palette *_screenPalette;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list