diff options
| -rw-r--r-- | engines/scumm/charset.cpp | 129 | ||||
| -rw-r--r-- | engines/scumm/charset.h | 7 | ||||
| -rw-r--r-- | graphics/sjis.cpp | 174 | ||||
| -rw-r--r-- | graphics/sjis.h | 57 | 
4 files changed, 252 insertions, 115 deletions
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 8adeaa076c..bba29bbe84 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -54,30 +54,25 @@ void ScummEngine::loadCJKFont() {  		error("FM-Towns Kanji font drawing requires dual graphics layer support which is disabled in this build");  #else  		// use FM-TOWNS font rom, since game files don't have kanji font resources -		_cjkFont = Graphics::FontSJIS::createFont(Common::kPlatformFMTowns); +		_cjkFont = Graphics::FontSJIS::createFont(_game.platform);  		if (!_cjkFont)  			error("SCUMM::Font: Could not open file 'FMT_FNT.ROM'");  		_textSurfaceMultiplier = 2;  		_useCJKMode = true;  #endif  	} else if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine && _language == Common::JA_JPN) { -		int numChar = 3418; -		_2byteWidth = 12; -		_2byteHeight = 12;  		// use PC-Engine System Card, since game files don't have kanji font resources -		if (!fp.open("pce.cdbios")) { -			error("SCUMM::Font: Could not open System Card pce.cdbios"); -		} else { -			_useCJKMode = true; -			debug(2, "Loading PC-Engine System Card"); +		_cjkFont = Graphics::FontSJIS::createFont(_game.platform); +		if (!_cjkFont) +			error("SCUMM::Font: Could not open file 'pce.cdbios'"); -			// A 0x200 byte header can be present at the beginning of the syscard. Seek past it too. -			fp.seek((fp.size() & 0x200) ? 0x30200 : 0x30000); +		_cjkFont->setDrawingMode(Graphics::FontSJIS::kShadowMode); +		_cjkFont->setCharSpacing(-1); +		_cjkFont->setLineSpacing(-1); +		_2byteWidth = _cjkFont->getMaxFontWidth(); +		_2byteHeight = _cjkFont->getFontHeight(); +		_useCJKMode = true;		 -			_2byteFontPtr = new byte[_2byteWidth * _2byteHeight * numChar / 8]; -			fp.read(_2byteFontPtr, _2byteWidth * _2byteHeight * numChar / 8); -			fp.close(); -		}  	} else if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD && _language == Common::JA_JPN) {  		int numChar = 1413;  		_2byteWidth = 16; @@ -161,63 +156,8 @@ void ScummEngine::loadCJKFont() {  	}  } -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. -	const int rangeCnt = 45; -	static const uint16 rangeTbl[rangeCnt][2] = { -		// Symbols -		{0x8140,0x817E},{0x8180,0x81AC}, -		// 0-9 -		{0x824F,0x8258}, -		// Latin upper -		{0x8260,0x8279}, -		// Latin lower -		{0x8281,0x829A}, -		// Kana -		{0x829F,0x82F1},{0x8340,0x837E},{0x8380,0x8396}, -		// Greek upper -		{0x839F,0x83B6}, -		// Greek lower -		{0x83BF,0x83D6}, -		// Cyrillic upper -		{0x8440,0x8460}, -		// Cyrillic lower -		{0x8470,0x847E},{0x8480,0x8491}, -		// Kanji -		{0x889F,0x88FC}, -		{0x8940,0x897E},{0x8980,0x89FC}, -		{0x8A40,0x8A7E},{0x8A80,0x8AFC}, -		{0x8B40,0x8B7E},{0x8B80,0x8BFC}, -		{0x8C40,0x8C7E},{0x8C80,0x8CFC}, -		{0x8D40,0x8D7E},{0x8D80,0x8DFC}, -		{0x8E40,0x8E7E},{0x8E80,0x8EFC}, -		{0x8F40,0x8F7E},{0x8F80,0x8FFC}, -		{0x9040,0x907E},{0x9080,0x90FC}, -		{0x9140,0x917E},{0x9180,0x91FC}, -		{0x9240,0x927E},{0x9280,0x92FC}, -		{0x9340,0x937E},{0x9380,0x93FC}, -		{0x9440,0x947E},{0x9480,0x94FC}, -		{0x9540,0x957E},{0x9580,0x95FC}, -		{0x9640,0x967E},{0x9680,0x96FC}, -		{0x9740,0x977E},{0x9780,0x97FC}, -		{0x9840,0x9872} -	}; - -	int ch = (f << 8) | (s & 0xFF); -	int offset = 0; -	for (int i = 0; i < rangeCnt; ++i) { -		if (ch >= rangeTbl[i][0] && ch <= rangeTbl[i][1]) -			return offset + ch - rangeTbl[i][0]; -		offset += rangeTbl[i][1] - rangeTbl[i][0] + 1; -	} - -	debug(4, "Invalid Char: 0x%x", ch); -	return 0; -} -  byte *ScummEngine::get2byteCharPtr(int idx) { -	if (_game.platform == Common::kPlatformFMTowns) +	if (_game.platform == Common::kPlatformFMTowns || _game.platform == Common::kPlatformPCEngine)  		return 0;  	switch (_language) { @@ -225,10 +165,7 @@ byte *ScummEngine::get2byteCharPtr(int idx) {  		idx = ((idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1;  		break;  	case Common::JA_JPN: -		if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine) { -			idx = SJIStoPCEChunk((idx % 256), (idx / 256)); -			return _2byteFontPtr + (_2byteWidth * _2byteHeight / 8) * idx; -		} else if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD && _language == Common::JA_JPN) { +		if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD && _language == Common::JA_JPN) {  			// init pointer to charset resource  			if (_2byteFontPtr[0] == 0xFF) {  				int charsetId = 5; @@ -672,13 +609,13 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {  	height = getDrawHeightIntern(chr);  	setDrawCharIntern(chr); +	origWidth = width; +	origHeight = height; +  	// Clip at the right side (to avoid drawing "outside" the screen bounds).  	if (_left + origWidth > _right + 1)  		return; -	origWidth = width; -	origHeight = height; -  	if (_shadowMode) {  		width++;  		height++; @@ -1139,15 +1076,25 @@ void CharsetRendererTownsV3::setDrawCharIntern(uint16 chr) {  #ifdef USE_RGB_COLOR  void CharsetRendererPCE::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height, uint8 bitDepth) { +	if (_sjisCurChar) { +		assert(_vm->_cjkFont); +		uint16 col1 = _color; +		uint16 col2 = _shadowColor; + +		if (s.format.bytesPerPixel == 2) { +			col1 = _vm->_16BitPalette[col1]; +			col2 = _vm->_16BitPalette[col2]; +		} + +		_vm->_cjkFont->drawChar(dst, _sjisCurChar, s.pitch, s.format.bytesPerPixel, col1, col2, -1, -1); +		return; +	} +  	int y, x; -	int bitCount = 0;  	byte bits = 0; -	const bool resetLineBitCount = (_vm->_language != Common::JA_JPN || width != 12); -  	for (y = 0; y < height && y + drawTop < s.h; y++) { -		if (resetLineBitCount) -			bitCount = 0; +		int bitCount = 0;  		for (x = 0; x < width; x++) {  			if ((bitCount % 8) == 0)  				bits = *src++; @@ -1171,16 +1118,24 @@ void CharsetRendererPCE::drawBits1(const Graphics::Surface &s, byte *dst, const  }  int CharsetRendererPCE::getDrawWidthIntern(uint16 chr) { -	if (_vm->_useCJKMode && chr > 127) -		return  _vm->_2byteWidth; +	if (_vm->_useCJKMode && chr > 127) { +		assert(_vm->_cjkFont); +		return _vm->_cjkFont->getCharWidth(chr); +	}  	return CharsetRendererV3::getDrawWidthIntern(chr);  }  int CharsetRendererPCE::getDrawHeightIntern(uint16 chr) { -	if (_vm->_useCJKMode && chr > 127) -		return _vm->_2byteHeight; +	if (_vm->_useCJKMode && chr > 127) { +		assert(_vm->_cjkFont); +		return _vm->_cjkFont->getFontHeight(); +	}  	return CharsetRendererV3::getDrawHeightIntern(chr);  } + +void CharsetRendererPCE::setDrawCharIntern(uint16 chr) { +	_sjisCurChar = (_vm->_useCJKMode && chr > 127) ? chr : 0; +}  #endif  #ifdef ENABLE_SCUMM_7_8 diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index 13e40ffe62..4a5799688c 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -205,14 +205,17 @@ private:  #ifdef USE_RGB_COLOR  class CharsetRendererPCE : public CharsetRendererV3 { -protected: +private:  	void drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height, uint8 bitDepth);  	int getDrawWidthIntern(uint16 chr);  	int getDrawHeightIntern(uint16 chr); +	void setDrawCharIntern(uint16 chr); + +	uint16 _sjisCurChar;  public: -	CharsetRendererPCE(ScummEngine *vm) : CharsetRendererV3(vm) {} +	CharsetRendererPCE(ScummEngine *vm) : CharsetRendererV3(vm), _sjisCurChar(0) {}  	void setColor(byte color);  }; diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp index 10c780b156..03c3cede79 100644 --- a/graphics/sjis.cpp +++ b/graphics/sjis.cpp @@ -40,10 +40,27 @@ FontSJIS *FontSJIS::createFont(const Common::Platform platform) {  	// Try the font ROM of the specified platform  	if (platform == Common::kPlatformFMTowns) {  		ret = new FontTowns(); -		if (ret && ret->loadData()) -			return ret; +		if (ret) { +			if (ret->loadData()) +				return ret; +		}  		delete ret; -	} +	} else if (platform == Common::kPlatformPCEngine) { +		ret = new FontPCEngine(); +		if (ret) { +			if (ret->loadData()) +				return ret; +		} +		delete ret; +	} // TODO: PC98 font rom support +	  /* else if (platform == Common::kPlatformPC98) {		 +		ret = new FontPC98(); +		if (ret) { +			if (ret->loadData()) +				return ret; +		} +		delete ret; +	}*/  	// Try ScummVM's font.  	ret = new FontSjisSVM(platform); @@ -59,65 +76,83 @@ void FontSJIS::drawChar(Graphics::Surface &dst, uint16 ch, int x, int y, uint32  }  FontSJISBase::FontSJISBase() -	: _drawMode(kDefaultMode), _flippedMode(false), _fontWidth(16), _fontHeight(16) { +	: _drawMode(kDefaultMode), _flippedMode(false), _fontWidth(16), _fontHeight(16), _charSpacing(0), _lineSpacing(0), _bitPosNewLineMask(0) {  }  void FontSJISBase::setDrawingMode(DrawingMode mode) { -	_drawMode = mode; +	if (hasFeature(1 << mode)) +		_drawMode = mode; +	else +		warning("Unsupported drawing mode selected");  }  void FontSJISBase::toggleFlippedMode(bool enable) { -	_flippedMode = enable; +	if (hasFeature(kFeatFlipped)) +		_flippedMode = enable; +	else +		warning("Flipped mode unsupported by this font");	 +} + +void FontSJISBase::setCharSpacing(int spacing) { +	_charSpacing = spacing; +} + +void FontSJISBase::setLineSpacing(int spacing) { +	_lineSpacing = spacing;  }  uint FontSJISBase::getFontHeight() const {  	switch (_drawMode) {  	case kOutlineMode: -		return _fontHeight + 2; +		return _fontHeight + _lineSpacing + 2;  	case kDefaultMode: -		return _fontHeight; +		return _fontHeight + _lineSpacing;  	default: -		return _fontHeight + 1; +		return _fontHeight + _lineSpacing + 1;  	}  }  uint FontSJISBase::getMaxFontWidth() const {  	switch (_drawMode) {  	case kOutlineMode: -		return _fontWidth + 2; +		return _fontWidth + _charSpacing + 2;  	case kDefaultMode: -		return _fontWidth; +		return _fontWidth + _charSpacing;  	default: -		return _fontWidth + 1; +		return _fontWidth + _charSpacing + 1;  	}  }  uint FontSJISBase::getCharWidth(uint16 ch) const {  	if (isASCII(ch)) -		return (_drawMode == kOutlineMode) ? 10 : (_drawMode == kDefaultMode ? 8 : 9); +		return ((_drawMode == kOutlineMode) ? 10 : (_drawMode == kDefaultMode ? 8 : 9)) + _charSpacing;  	else  		return getMaxFontWidth();  }  template<typename Color>  void FontSJISBase::blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c) const { +	uint8 bitPos = 0; +	uint8 mask = 0; +  	for (int y = 0; y < h; ++y) {  		Color *d = (Color *)dst;  		dst += pitch; -		uint8 mask = 0; +		bitPos &= _bitPosNewLineMask;  		for (int x = 0; x < w; ++x) { -			if (!(x % 8)) +			if (!(bitPos % 8))  				mask = *glyph++;  			if (mask & 0x80)  				*d = c;  			++d; +			++bitPos;  			mask <<= 1;  		}  	} @@ -176,9 +211,6 @@ const uint8 *FontSJISBase::flipCharacter(const uint8 *glyph, const int w) const  		0x0F, 0x8F, 0x4F, 0xC7, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x97, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF  	}; -	// TODO: This code looks like it will only work with 16 pixel wide -	// characters we should really take care that we only call it on these -	// or we fix this to support a generic width.  	for (int i = 0; i < w; i++) {  		_tempGlyph[i] = flipData[glyph[(w * 2 - 1) - i]];  		_tempGlyph[(w * 2 - 1) - i] = flipData[glyph[i]]; @@ -225,9 +257,6 @@ void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1,  	}  #ifndef DISABLE_FLIPPED_MODE -	// TODO: This code inside flopCharater looks like it will only work with -	// 16 pixel wide characters we should really take care that we only call -	// it on these or we fix it to support a generic width.  	if (_flippedMode)  		glyphSource = flipCharacter(glyphSource, width);  #endif @@ -303,7 +332,7 @@ const uint8 *FontTowns::getCharData(uint16 ch) const {  		uint8 f = ch & 0xFF;  		uint8 s = ch >> 8; -		// copied from scumm\charset.cpp +		// moved from scumm\charset.cpp  		enum {  			KANA = 0,  			KANJI = 1, @@ -392,6 +421,98 @@ const uint8 *FontTowns::getCharData(uint16 ch) const {  	}  } +bool FontTowns::hasFeature(int feat) const { +	static const int features = kFeatDefault | kFeatOutline | kFeatShadow | kFeatFMTownsShadow | kFeatFlipped; +	return (features & feat) ? true : false; +} + +// PC-Engine ROM font + +bool FontPCEngine::loadData() { +	Common::SeekableReadStream *data = SearchMan.createReadStreamForMember("pce.cdbios"); +	if (!data) +		return false; +	 +	data->seek((data->size() & 0x200) ? 0x30200 : 0x30000); +	data->read(_fontData12x12, kFont12x12Chars * 18); +	 +	_fontWidth = _fontHeight = 12; +	_bitPosNewLineMask = _fontWidth & 7; + +	bool retValue = !data->err(); +	delete data; +	return retValue; +} + +const uint8 *FontPCEngine::getCharData(uint16 ch) const { +	// Converts sjis code to pce font offset +	// (moved from scumm\charset.cpp). +	// rangeTbl maps SJIS char-codes to the PCE System Card font rom. +	// Each pair {<upperBound>,<lowerBound>} in the array represents a SJIS range. +	const int rangeCnt = 45; +	static const uint16 rangeTbl[rangeCnt][2] = { +		// Symbols +		{0x8140,0x817E},{0x8180,0x81AC}, +		// 0-9 +		{0x824F,0x8258}, +		// Latin upper +		{0x8260,0x8279}, +		// Latin lower +		{0x8281,0x829A}, +		// Kana +		{0x829F,0x82F1},{0x8340,0x837E},{0x8380,0x8396}, +		// Greek upper +		{0x839F,0x83B6}, +		// Greek lower +		{0x83BF,0x83D6}, +		// Cyrillic upper +		{0x8440,0x8460}, +		// Cyrillic lower +		{0x8470,0x847E},{0x8480,0x8491}, +		// Kanji +		{0x889F,0x88FC}, +		{0x8940,0x897E},{0x8980,0x89FC}, +		{0x8A40,0x8A7E},{0x8A80,0x8AFC}, +		{0x8B40,0x8B7E},{0x8B80,0x8BFC}, +		{0x8C40,0x8C7E},{0x8C80,0x8CFC}, +		{0x8D40,0x8D7E},{0x8D80,0x8DFC}, +		{0x8E40,0x8E7E},{0x8E80,0x8EFC}, +		{0x8F40,0x8F7E},{0x8F80,0x8FFC}, +		{0x9040,0x907E},{0x9080,0x90FC}, +		{0x9140,0x917E},{0x9180,0x91FC}, +		{0x9240,0x927E},{0x9280,0x92FC}, +		{0x9340,0x937E},{0x9380,0x93FC}, +		{0x9440,0x947E},{0x9480,0x94FC}, +		{0x9540,0x957E},{0x9580,0x95FC}, +		{0x9640,0x967E},{0x9680,0x96FC}, +		{0x9740,0x977E},{0x9780,0x97FC}, +		{0x9840,0x9872} +	}; + +	ch = (ch << 8) | (ch >> 8); +	int offset = 0; +	for (int i = 0; i < rangeCnt; ++i) { +		if (ch >= rangeTbl[i][0] && ch <= rangeTbl[i][1]) { +			return _fontData12x12 + 18 * (offset + ch - rangeTbl[i][0]); +			break; +		} +		offset += rangeTbl[i][1] - rangeTbl[i][0] + 1; +	} +	 +	debug(4, "Invalid Char: 0x%x", ch); +	return 0; +} + +bool FontPCEngine::hasFeature(int feat) const { +	// Outline mode not supported due to use of _bitPosNewLineMask. This could be implemented, +	// but is not needed for any particular target at the moment. +	// Flipped mode is also not supported since the hard coded table (taken from SCUMM 5 FM-TOWNS) +	// is set up for font sizes of 8/16. This mode is also not required at the moment, since +	// there aren't any SCUMM 5 PC-Engine games. +	static const int features = kFeatDefault | kFeatShadow | kFeatFMTownsShadow; +	return (features & feat) ? true : false; +} +  // ScummVM SJIS font  FontSjisSVM::FontSjisSVM(const Common::Platform platform) @@ -464,6 +585,15 @@ const uint8 *FontSjisSVM::getCharData(uint16 c) const {  		return getCharDataDefault(c);  } +bool FontSjisSVM::hasFeature(int feat) const { +	// Flipped mode is not supported since the hard coded table (taken from SCUMM 5 FM-TOWNS) +	// is set up for font sizes of 8/16. This mode is also not required at the moment, since +	// there aren't any SCUMM 5 PC-Engine games. +	static const int features16 = kFeatDefault | kFeatOutline | kFeatShadow | kFeatFMTownsShadow | kFeatFlipped; +	static const int features12 = kFeatDefault | kFeatOutline | kFeatShadow | kFeatFMTownsShadow; +	return (((_fontWidth == 12) ? features12 : features16) & feat) ? true : false; +} +  const uint8 *FontSjisSVM::getCharDataPCE(uint16 c) const {  	if (isASCII(c))  		return 0; diff --git a/graphics/sjis.h b/graphics/sjis.h index 62e68013da..de2d4b325c 100644 --- a/graphics/sjis.h +++ b/graphics/sjis.h @@ -75,7 +75,7 @@ public:  	virtual bool loadData() = 0;  	/** -	 * Enable drawing with outline or shadow. +	 * Enable drawing with outline or shadow if supported by the Font.  	 *  	 * After changing outline state, getFontHeight and getMaxFontWidth / getCharWidth might return  	 * different values! @@ -90,11 +90,17 @@ public:  	virtual void setDrawingMode(DrawingMode mode) {}  	/** -	 * Enable flipped character drawing (e.g. in the MI1 circus scene after Guybrush gets shot out of the cannon). +	 * Enable flipped character drawing if supported by the Font (e.g. in the MI1 circus scene after Guybrush gets shot out of the cannon).  	 */  	virtual void toggleFlippedMode(bool enable) {}  	/** +	 * Set spacing between characters and lines. This affects font height / char width +	 */ +	virtual void setCharSpacing(int spacing) {} +	virtual void setLineSpacing(int spacing) {} + +	/**  	 * Returns the height of the font.  	 */  	virtual uint getFontHeight() const = 0; @@ -140,6 +146,10 @@ public:  	virtual void toggleFlippedMode(bool enable); +	virtual void setCharSpacing(int spacing); + +	virtual void setLineSpacing(int spacing); +  	virtual uint getFontHeight() const;  	virtual uint getMaxFontWidth() const; @@ -162,16 +172,28 @@ protected:  	DrawingMode _drawMode;  	bool _flippedMode;  	int _fontWidth, _fontHeight; - +	int _charSpacing, _lineSpacing; +	uint8 _bitPosNewLineMask; +	  	bool isASCII(uint16 ch) const;  	virtual const uint8 *getCharData(uint16 c) const = 0; + +	enum DrawingFeature { +		kFeatDefault		= 1 << 0, +		kFeatOutline		= 1 << 1, +		kFeatShadow			= 1 << 2, +		kFeatFMTownsShadow	= 1 << 3, +		kFeatFlipped		= 1 << 4 +	}; + +	virtual bool hasFeature(int feat) const = 0;  };  /**   * FM-TOWNS ROM based SJIS compatible font.   * - * This is used in KYRA and SCI. + * This is used in KYRA, SCUMM and SCI.   */  class FontTowns : public FontSJISBase {  public: @@ -189,6 +211,31 @@ private:  	uint8 _fontData8x16[kFont8x16Chars * 32];  	virtual const uint8 *getCharData(uint16 c) const; + +	bool hasFeature(int feat) const; +}; + +/** + * PC-Engine System Card based SJIS compatible font. + * + * This is used in LOOM. + */ +class FontPCEngine : public FontSJISBase { +public: +	/** +	 * Loads the ROM data from "pce.cdbios". +	 */ +	bool loadData(); +private: +	enum { +		kFont12x12Chars = 3418 +	}; + +	uint8 _fontData12x12[kFont12x12Chars * 18]; + +	virtual const uint8 *getCharData(uint16 c) const; + +	bool hasFeature(int feat) const;  };  /** @@ -215,6 +262,8 @@ private:  	virtual const uint8 *getCharData(uint16 c) const; +	bool hasFeature(int feat) const; +  	const uint8 *getCharDataPCE(uint16 c) const;  	const uint8 *getCharDataDefault(uint16 c) const;  | 
