[Scummvm-git-logs] scummvm master -> d2c3387c6ab0f55e93dc6d6b6dafc5665ed7f1b0

sev- noreply at scummvm.org
Wed Mar 8 00:05:39 UTC 2023


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

Summary:
301e8805c2 SWORD2: Add detection entry for Chinese Broken Sword 2
b7a429afdd SWORD2: Make read methods accept const byte *.
d2c3387c6a SWORD2: Support Chinese translation


Commit: 301e8805c2c8c5ed8160ac2d2e8fabad4b869409
    https://github.com/scummvm/scummvm/commit/301e8805c2c8c5ed8160ac2d2e8fabad4b869409
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-03-08T01:05:32+01:00

Commit Message:
SWORD2: Add detection entry for Chinese Broken Sword 2

This entry is not strictly necessarry, just needed for better game
language reporting.

Changed paths:
    engines/sword2/detection.cpp
    engines/sword2/detection_tables.h


diff --git a/engines/sword2/detection.cpp b/engines/sword2/detection.cpp
index 16f9fd118c9..7d36a2c6c05 100644
--- a/engines/sword2/detection.cpp
+++ b/engines/sword2/detection.cpp
@@ -37,6 +37,7 @@ static const PlainGameDescriptor sword2Games[] = {
 static const char *const directoryGlobs[] = {
 	"clusters",
 	"smacks",
+	"sub",
 	"video",
 	"extras", // GOG.com
 	nullptr
diff --git a/engines/sword2/detection_tables.h b/engines/sword2/detection_tables.h
index 700e460e02a..2603746759e 100644
--- a/engines/sword2/detection_tables.h
+++ b/engines/sword2/detection_tables.h
@@ -95,6 +95,20 @@ static const ADGameDescription gameDescriptions[] = {
 		GUIO0()
 	},
 
+	{
+		"sword2",
+		"",
+		AD_ENTRY5s("general.clu", "31db8564f9187538f24d9fda0677f666", 7059728,
+				   "text.clu",    "9b344d976ca8d19a1cf5aa4413397f6b", 304968,
+				   "speech1.clu", "a403904a0e825356107d228f8f74092e", 176260048,
+				   "docks.clu",   "b39246fbb5b955a29f9a207c69bfc318", 20262263,
+				   "bs2.dat",   "c8238e7d017faa3b48d98df3f42a63e6", 336246),
+		Common::ZH_CHN,
+		Common::kPlatformWindows,
+		ADGF_NO_FLAGS,
+		GUIO0()
+	},
+
 	{
 		"sword2",
 		"1CD release",


Commit: b7a429afdd2eca900be0bcf59f2af9637b8cf999
    https://github.com/scummvm/scummvm/commit/b7a429afdd2eca900be0bcf59f2af9637b8cf999
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-03-08T01:05:32+01:00

Commit Message:
SWORD2: Make read methods accept const byte *.

Changed paths:
    engines/sword2/header.cpp
    engines/sword2/header.h
    engines/sword2/object.h
    engines/sword2/screen.h


diff --git a/engines/sword2/header.cpp b/engines/sword2/header.cpp
index 00894c3be80..1ca3f428d4a 100644
--- a/engines/sword2/header.cpp
+++ b/engines/sword2/header.cpp
@@ -29,7 +29,7 @@
 
 namespace Sword2 {
 
-void ResHeader::read(byte *addr) {
+void ResHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	fileType = readS.readByte();
@@ -49,7 +49,7 @@ void ResHeader::write(byte *addr) {
 	writeS.write(name, NAME_LEN);
 }
 
-void AnimHeader::read(byte *addr) {
+void AnimHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	if (Sword2Engine::isPsx()) {
@@ -96,7 +96,7 @@ int CdtEntry::size() {
 		return 9;
 }
 
-void CdtEntry::read(byte *addr) {
+void CdtEntry::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	if (Sword2Engine::isPsx()) {
@@ -122,7 +122,7 @@ void CdtEntry::write(byte *addr) {
 	writeS.writeByte(frameType);
 }
 
-void FrameHeader::read(byte *addr) {
+void FrameHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	compSize = readS.readUint32LE();
@@ -143,7 +143,7 @@ void FrameHeader::write(byte *addr) {
 	writeS.writeUint16LE(height);
 }
 
-void MultiScreenHeader::read(byte *addr) {
+void MultiScreenHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	palette = readS.readUint32LE();
@@ -171,7 +171,7 @@ void MultiScreenHeader::write(byte *addr) {
 	writeS.writeUint32LE(maskOffset);
 }
 
-void ScreenHeader::read(byte *addr) {
+void ScreenHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	width = readS.readUint16LE();
@@ -187,7 +187,7 @@ void ScreenHeader::write(byte *addr) {
 	writeS.writeUint16LE(noLayers);
 }
 
-void LayerHeader::read(byte *addr) {
+void LayerHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	x = readS.readUint16LE();
@@ -209,7 +209,7 @@ void LayerHeader::write(byte *addr) {
 	writeS.writeUint32LE(offset);
 }
 
-void TextHeader::read(byte *addr) {
+void TextHeader::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	noOfLines = readS.readUint32LE();
@@ -221,7 +221,7 @@ void TextHeader::write(byte *addr) {
 	writeS.writeUint32LE(noOfLines);
 }
 
-void PSXScreensEntry::read(byte *addr) {
+void PSXScreensEntry::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	bgPlxXres = readS.readUint16LE();
@@ -255,7 +255,7 @@ void PSXScreensEntry::write(byte *addr) {
 	writeS.writeUint32LE(fgPlxSize);
 }
 
-void PSXFontEntry::read(byte *addr) {
+void PSXFontEntry::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	offset = readS.readUint16LE() / 2;
@@ -273,7 +273,7 @@ void PSXFontEntry::write(byte *addr) {
 	writeS.writeUint16LE(charHeight);
 }
 
-void Parallax::read(byte *addr) {
+void Parallax::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	w = readS.readUint16LE();
@@ -287,7 +287,7 @@ void Parallax::write(byte *addr) {
 	writeS.writeUint16LE(h);
 }
 
-void ObjectMouse::read(byte *addr) {
+void ObjectMouse::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	x1 = readS.readSint32LE();
@@ -309,7 +309,7 @@ void ObjectMouse::write(byte *addr) {
 	writeS.writeSint32LE(pointer);
 }
 
-void ObjectWalkdata::read(byte *addr) {
+void ObjectWalkdata::read(const byte *addr) {
 	Common::MemoryReadStream readS(addr, size());
 
 	nWalkFrames = readS.readUint32LE();
diff --git a/engines/sword2/header.h b/engines/sword2/header.h
index 2c77ac693a3..3914f30aaf4 100644
--- a/engines/sword2/header.h
+++ b/engines/sword2/header.h
@@ -55,7 +55,7 @@ struct ResHeader {
 		return 44;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -134,7 +134,7 @@ struct AnimHeader {
 		return 15;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 
 };
@@ -164,7 +164,7 @@ struct CdtEntry {
 
 	static int size();
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -190,7 +190,7 @@ struct FrameHeader {
 		return 8;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -226,7 +226,7 @@ struct MultiScreenHeader {
 		return 36;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -241,7 +241,7 @@ struct ScreenHeader {
 		return 6;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -263,7 +263,7 @@ struct LayerHeader {
 		return 16;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -349,7 +349,7 @@ struct TextHeader {
 		return 4;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -396,7 +396,7 @@ struct PSXScreensEntry {
 		return 36;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -413,7 +413,7 @@ struct PSXFontEntry {
 		return 8;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
diff --git a/engines/sword2/object.h b/engines/sword2/object.h
index c2fc55bb67f..89f6061f468 100644
--- a/engines/sword2/object.h
+++ b/engines/sword2/object.h
@@ -47,7 +47,7 @@ struct ObjectMouse {
 		return 24;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
@@ -271,7 +271,7 @@ struct ObjectWalkdata {
 		return 916;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 
diff --git a/engines/sword2/screen.h b/engines/sword2/screen.h
index aa2a2b2e97d..e3c8923a576 100644
--- a/engines/sword2/screen.h
+++ b/engines/sword2/screen.h
@@ -188,7 +188,7 @@ struct Parallax {
 		return 4;
 	}
 
-	void read(byte *addr);
+	void read(const byte *addr);
 	void write(byte *addr);
 };
 


Commit: d2c3387c6ab0f55e93dc6d6b6dafc5665ed7f1b0
    https://github.com/scummvm/scummvm/commit/d2c3387c6ab0f55e93dc6d6b6dafc5665ed7f1b0
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-03-08T01:05:32+01:00

Commit Message:
SWORD2: Support Chinese translation

This includes both the translation itself and the font rendering

Changed paths:
    engines/sword2/maketext.cpp
    engines/sword2/maketext.h
    engines/sword2/sword2.cpp


diff --git a/engines/sword2/maketext.cpp b/engines/sword2/maketext.cpp
index f19fc153bcf..71970d45a7a 100644
--- a/engines/sword2/maketext.cpp
+++ b/engines/sword2/maketext.cpp
@@ -43,6 +43,7 @@
 #include "common/system.h"
 #include "common/unicode-bidi.h"
 #include "common/textconsole.h"
+#include "common/file.h"
 
 #include "sword2/sword2.h"
 #include "sword2/defs.h"
@@ -68,6 +69,42 @@ namespace Sword2 {
 #define DUD		64	// the first "chequered flag" (dud) symbol in
 				// our character set is in the '@' position
 
+namespace {
+Common::String readLine(Common::ReadStream &stream) {
+	Common::String ret = stream.readString('\n');
+	if (ret.hasSuffix("\r"))
+		ret = ret.substr(0, ret.size() - 1);
+	return ret;
+}
+}  // end of anonymous namespace
+
+void FontRenderer::loadTranslations() {
+	Common::File bs2en, bs2, font;
+
+	if(bs2en.open("sub/bs2_en.dat") && bs2.open("sub/bs2.dat") && font.open("font/bs1.fnt")) {
+		while (!bs2.eos() && !bs2en.eos()) {
+			Common::String id = readLine(bs2);
+			Common::String val = readLine(bs2);
+			Common::String valen = readLine(bs2en);
+			Common::String iden = readLine(bs2en);
+			if (val.empty() || valen.empty())
+				continue;
+			debug(5, "id: %s->%s", Common::U32String(iden, Common::CodePage::kWindows936).encode().c_str(),
+			      Common::U32String(id, Common::CodePage::kWindows936).encode().c_str());
+			debug(5, "val: %s->%s", Common::U32String(valen, Common::CodePage::kWindows936).encode().c_str(),
+			      Common::U32String(val, Common::CodePage::kWindows936).encode().c_str());
+			_subTranslations[valen] = val;
+		}
+
+		while (!font.eos()) {
+			ChineseGlyph glyph;
+			if (font.read(glyph.bitmap, sizeof (glyph.bitmap)) != sizeof (glyph.bitmap))
+				break;
+			_chineseFont.push_back(glyph);
+		}
+	}
+}
+
 /**
  * This function creates a new text sprite. The sprite data contains a
  * FrameHeader, but not a standard file header.
@@ -84,10 +121,26 @@ namespace Sword2 {
  */
 
 byte *FontRenderer::makeTextSprite(const byte *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes, uint8 border) {
+	// Keep this at the function scope to make sure we hold a reference even in case of unintentional copies.
+	// Normally we should keep using the copy from hashmap.
+	Common::String translatedSentence;
+
 	debug(5, "makeTextSprite(\"%s\", maxWidth=%u)", sentence, maxWidth);
 
+	bool isTranslated = false;
+
 	_borderPen = border;
 
+	if (!_subTranslations.empty()) {
+		if (_subTranslations.tryGetVal(Common::String((const char *)sentence), translatedSentence)) {
+			isTranslated = true;
+			debug(5, "Translating <%s> -> <%s>", sentence, translatedSentence.decode(Common::CodePage::kWindows936).encode().c_str());
+			sentence = (const byte *)translatedSentence.c_str();
+		} else {
+			debug(5, "Keeping <%s> untranslated", sentence);
+		}
+	}
+
 	// Line- and character spacing are hard-wired, rather than being part
 	// of the resource.
 
@@ -112,18 +165,18 @@ byte *FontRenderer::makeTextSprite(const byte *sentence, uint16 maxWidth, uint8
 	// Get details of sentence breakdown into array of LineInfo structures
 	// and get the number of lines involved
 
-	uint16 noOfLines = analyzeSentence(sentence, maxWidth, fontRes, (LineInfo *)line);
+	uint16 noOfLines = analyzeSentence(sentence, maxWidth, fontRes, (LineInfo *)line, isTranslated);
 
 	// Construct the sprite based on the info gathered - returns floating
 	// mem block
 
-	byte *textSprite = buildTextSprite(sentence, fontRes, pen, (LineInfo *)line, noOfLines);
+	byte *textSprite = buildTextSprite(sentence, fontRes, pen, (LineInfo *)line, noOfLines, isTranslated);
 
 	free(line);
 	return textSprite;
 }
 
-uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line) {
+uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line, bool isChinese) {
 	// joinWidth = how much extra space is needed to append a word to a
 	// line. NB. SPACE requires TWICE the '_charSpacing' to join a word
 	// to line
@@ -134,20 +187,31 @@ uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint
 	uint16 pos = 0;
 	bool firstWord = true;
 
-	byte ch;
+	line[0].skipSpace = false;
+	line[0].width = 0;
+	line[0].length = 0;
 
 	do {
 		uint16 wordWidth = 0;
 		uint16 wordLength = 0;
 
 		// Calculate the width of the word.
-
-		ch = sentence[pos++];
-
-		while (ch && ch != SPACE) {
-			wordWidth += charWidth(ch, fontRes) + _charSpacing;
-			wordLength++;
-			ch = sentence[pos++];
+		while (1) {
+			byte ch = sentence[pos];
+			if (ch == 0 || ch == SPACE)
+				break;
+			int w = 0, l = 0;
+			if (isChinese && (ch & 0x80)) {
+				w = kChineseWidth + _charSpacing;
+				l = 2;
+			} else {
+				w = charWidth(ch, fontRes) + _charSpacing;
+				l = 1;
+			}
+				
+			wordWidth += w;
+			wordLength += l;
+			pos += l;
 		}
 
 		// Don't include any character spacing at the end of the word.
@@ -156,12 +220,77 @@ uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint
 		// 'ch' is now the SPACE or NULL following the word
 		// 'pos' indexes to the position following 'ch'
 
+		// Word longer than line. Happens for Chinese since it doesn't use spaces.
+		if (wordWidth > maxWidth) {
+			pos -= wordLength;
+			// Add separator if needed.
+			if (!firstWord) {
+				byte ch = sentence[pos];
+				uint16 spaceNeededForOneCharacter = joinWidth;
+
+				if (isChinese && (ch & 0x80)) {
+					spaceNeededForOneCharacter += kChineseWidth + _charSpacing;
+				}
+				spaceNeededForOneCharacter += charWidth(ch, fontRes) + _charSpacing;
+
+				if (line[lineNo].width + spaceNeededForOneCharacter <= maxWidth) {
+					// The separator fits on this line.
+					line[lineNo].width += spaceNeededForOneCharacter;
+					line[lineNo].length += (1 + spaceNeededForOneCharacter);
+					line[lineNo].skipSpace = false;
+				} else {
+					// The word spills over to the next line, i.e.
+					// no separating space.
+					line[lineNo].skipSpace = true;
+					
+					lineNo++;
+
+					assert(lineNo < MAX_LINES);
+
+					line[lineNo].width = wordWidth;
+					line[lineNo].length = wordLength;
+					line[lineNo].skipSpace = false;
+				}
+			}
+
+			while (1) {
+				byte ch = sentence[pos];
+				if (ch == 0 || ch == SPACE)
+					break;
+				int w = 0, l = 0;
+				if (isChinese && (ch & 0x80)) {
+					w = kChineseWidth + _charSpacing;
+					l = 2;
+				} else {
+					w = charWidth(ch, fontRes) + _charSpacing;
+					l = 1;
+				}
+				if (line[lineNo].width + w <= maxWidth) {
+					line[lineNo].width += w;
+					line[lineNo].length += l;
+				} else {
+					line[lineNo].skipSpace = false;
+					lineNo++;
+					line[lineNo].skipSpace = false;
+					line[lineNo].width = w;
+					line[lineNo].length = l;
+				}
+				pos += l;
+			}
+
+			continue;
+		}
+
+		while (sentence[pos] == SPACE)
+			pos++;
+
 		if (firstWord) {
 			// This is the first word on the line, so no separating
 			// space is needed.
 
 			line[0].width = wordWidth;
 			line[0].length = wordLength;
+			line[0].skipSpace = false;
 			firstWord = false;
 		} else {
 			// See how much extra space this word will need to
@@ -177,6 +306,7 @@ uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint
 			} else {
 				// The word spills over to the next line, i.e.
 				// no separating space.
+				line[lineNo].skipSpace = true;
 
 				lineNo++;
 
@@ -184,9 +314,10 @@ uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint
 
 				line[lineNo].width = wordWidth;
 				line[lineNo].length = wordLength;
+				line[lineNo].skipSpace = false;
 			}
 		}
-	} while (ch);
+	} while (sentence[pos]);
 
 	return lineNo + 1;
 }
@@ -207,7 +338,7 @@ uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint
  *         error-signal character (chequered flag)
  */
 
-byte *FontRenderer::buildTextSprite(const byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines) {
+byte *FontRenderer::buildTextSprite(const byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines, bool isChinese) {
 	uint16 i;
 
 	// Find the width of the widest line in the output text
@@ -282,7 +413,28 @@ byte *FontRenderer::buildTextSprite(const byte *sentence, uint32 fontRes, uint8
 		// width minus the 'overlap'
 
 		for (uint j = 0; j < line[i].length; j++) {
-			byte *charPtr = findChar(*currTxtLine++, charSet);
+			byte ch = *currTxtLine++;
+			if (isChinese && (ch & 0x80)) {
+				byte low = *currTxtLine++;
+				int fullidx;
+				j++;
+				if (ch >= 0xa1 && ch <= 0xfe
+				    && low >= 0xa1 && low <= 0xfe)
+					fullidx = (ch - 0xa1) * 94 + (low - 0xa1);
+				else
+					fullidx = -1;
+				if (fullidx < 0 || fullidx >= (int)_chineseFont.size())
+					fullidx = 2 * 94 + 30; // Question mark
+
+				assert(kChineseHeight == char_height);
+
+				copyCharRaw(_chineseFont[fullidx].bitmap, kChineseWidth, kChineseHeight, spritePtr, spriteWidth, pen);
+
+				spritePtr += kChineseWidth + _charSpacing;
+
+				continue;
+			}
+			byte *charPtr = findChar(ch, charSet);
 
 			frame_head.read(charPtr);
 
@@ -298,8 +450,10 @@ byte *FontRenderer::buildTextSprite(const byte *sentence, uint32 fontRes, uint8
 			spritePtr += frame_head.width + _charSpacing;
 		}
 
+		sentence += line[i].length;
 		// Skip space at end of last word in this line
-		sentence += line[i].length + 1;
+		if (line[i].skipSpace)
+			sentence++;
 
 		if (Sword2Engine::isPsx())
 			linePtr += (char_height / 2 + _lineSpacing) * spriteWidth;
@@ -455,20 +609,23 @@ byte *FontRenderer::findChar(byte ch, byte *charSet) {
  *                    LETTER_COL to pen.
  */
 
-void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
+void FontRenderer::copyChar(const byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
 	FrameHeader frame;
 
 	frame.read(charPtr);
 
-	byte *source = charPtr + FrameHeader::size();
+	copyCharRaw(charPtr + FrameHeader::size(), frame.width, frame.height, spritePtr, spriteWidth, pen);
+}
+
+void FontRenderer::copyCharRaw(const byte *source, uint16 charWidth, uint16 charHeight, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
 	byte *rowPtr = spritePtr;
 
-	for (uint i = 0; i < frame.height; i++) {
+	for (uint i = 0; i < charHeight; i++) {
 		byte *dest = rowPtr;
 
 		if (pen) {
 			// Use the specified colors
-			for (uint j = 0; j < frame.width; j++) {
+			for (uint j = 0; j < charWidth; j++) {
 				switch (*source++) {
 				case 0:
 					// Do nothing if source pixel is zero,
@@ -494,8 +651,8 @@ void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth,
 			// Pen is zero, so just copy character sprites
 			// directly into text sprite without remapping colors.
 			// Apparently overlapping is never considered here?
-			memcpy(dest, source, frame.width);
-			source += frame.width;
+			memcpy(dest, source, charWidth);
+			source += charWidth;
 		}
 		rowPtr += spriteWidth;
 	}
diff --git a/engines/sword2/maketext.h b/engines/sword2/maketext.h
index 3dd63c8d662..97db81644b2 100644
--- a/engines/sword2/maketext.h
+++ b/engines/sword2/maketext.h
@@ -74,6 +74,7 @@ enum {
 struct LineInfo {
 	uint16 width;	// Width in pixels
 	uint16 length;	// Length in characters
+	bool skipSpace; // Whether there is a trailing space
 };
 
 class FontRenderer {
@@ -91,12 +92,21 @@ private:
 				// each line - negative for overlap
 	uint8 _borderPen;	// output pen color of character borders
 
-	uint16 analyzeSentence(const byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line);
-	byte *buildTextSprite(const byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines);
+	Common::HashMap<Common::String, Common::String> _subTranslations;
+	static const int kChineseWidth = 20;
+	static const int kChineseHeight = 26;
+	struct ChineseGlyph {
+		byte bitmap[kChineseWidth * kChineseHeight];
+	};
+	Common::Array<ChineseGlyph> _chineseFont;
+
+	uint16 analyzeSentence(const byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line, bool isChinese);
+	byte *buildTextSprite(const byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines, bool isChinese);
 	uint16 charWidth(byte ch, uint32 fontRes);
 	uint16 charHeight(uint32 fontRes);
 	byte *findChar(byte ch, byte *charSet);
-	void copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
+	void copyChar(const byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
+	void copyCharRaw(const byte *source, uint16 charWidth, uint16 charHeight, byte *spritePtr, uint16 spriteWidth, uint8 pen);
 
 public:
 	FontRenderer(Sword2Engine *vm) : _vm(vm) {
@@ -115,6 +125,8 @@ public:
 	void printTextBlocs();
 
 	uint32 buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification);
+
+	void loadTranslations();
 };
 
 } // End of namespace Sword2
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 6a354eacfdb..13a9db96e45 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -204,6 +204,8 @@ Common::Error Sword2Engine::run() {
 	_fontRenderer = new FontRenderer(this);
 	_sound = new Sound(this);
 	_mouse = new Mouse(this);
+	
+	_fontRenderer->loadTranslations();
 
 	registerDefaultSettings();
 	readSettings();




More information about the Scummvm-git-logs mailing list