[Scummvm-git-logs] scummvm master -> 8bd72c374ce4e35549acd70d0a01cc05abe190bb

sev- noreply at scummvm.org
Mon Nov 28 23:18:45 UTC 2022


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

Summary:
1210e839f8 SHERLOCK: Move members in Fonts to private from protected
9e68776b33 SHERLOCK: Fix crash in Chinese version
fa25e7267d SHERLOCK: Support Chinese rendering in the Rose Tatoo
5fae569597 SHERLOCK: Handle word wrapping for EUC-CN
00afc84492 SHERLOCK: Import all fixed strings for Chinese version of Tattoo
23f88cfc28 SHERLOCK: Remove unstable flag from Chinese Rose Tattoo
8bd72c374c NEWS: Add mention of Chinese Rose Tattoo


Commit: 1210e839f8b9e18e279b855833f84e4550abc7f3
    https://github.com/scummvm/scummvm/commit/1210e839f8b9e18e279b855833f84e4550abc7f3
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
SHERLOCK: Move members in Fonts to private from protected

Changed paths:
    engines/sherlock/fonts.h
    engines/sherlock/screen.cpp


diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h
index 9b53612ac56..b05733c4d44 100644
--- a/engines/sherlock/fonts.h
+++ b/engines/sherlock/fonts.h
@@ -36,17 +36,18 @@ class Fonts {
 private:
 	static ImageFile *_font;
 	static byte _yOffsets[255];
-protected:
-	static SherlockEngine *_vm;
 	static int _fontNumber;
 	static int _fontHeight;
 	static int _widestChar;
 	static uint16 _charCount;
 
+	static inline byte translateChar(byte c);
+protected:
+	static SherlockEngine *_vm;
+
 	static void writeString(BaseSurface *surface, const Common::String &str,
 		const Common::Point &pt, int overrideColor = 0);
 
-	static inline byte translateChar(byte c);
 public:
 	/**
 	 * Initialise the font manager
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 4a7148e8971..bc02ca52f8b 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -297,11 +297,11 @@ void Screen::print(const Common::Point &pt, uint color, const char *formatStr, .
 		// Center text horizontally
 		pos.x = (this->width() - width_) / 2;
 
-	Common::Rect textBounds(pos.x, pos.y, pos.x + width_, pos.y + _fontHeight);
+	Common::Rect textBounds(pos.x, pos.y, pos.x + width_, pos.y + fontHeight());
 	if (textBounds.right > this->width())
 		textBounds.moveTo(this->width() - width_, textBounds.top);
 	if (textBounds.bottom > this->height())
-		textBounds.moveTo(textBounds.left, this->height() - _fontHeight);
+		textBounds.moveTo(textBounds.left, this->height() - fontHeight());
 
 	// Write out the string at the given position
 	writeString(str, Common::Point(textBounds.left, textBounds.top), color);
@@ -345,7 +345,7 @@ Common::Rect Screen::getDisplayBounds() {
 }
 
 void Screen::synchronize(Serializer &s) {
-	int fontNumb = _fontNumber;
+	int fontNumb = fontNumber();
 	s.syncAsByte(fontNumb);
 	if (s.isLoading())
 		setFont(fontNumb);


Commit: 9e68776b331ef3ec7308bf3995fe4f3ce4b9df31
    https://github.com/scummvm/scummvm/commit/9e68776b331ef3ec7308bf3995fe4f3ce4b9df31
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
SHERLOCK: Fix crash in Chinese version

Changed paths:
    engines/sherlock/scene.cpp


diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 6d1c22b58dc..9dfd7cdf6ec 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -478,7 +478,10 @@ bool Scene::loadScene(const Common::String &filename) {
 				_bgShapes[idx]._imageFrame = !_bgShapes[idx]._images ? (ImageFrame *)nullptr :
 					&(*_bgShapes[idx]._images)[0];
 
-				_bgShapes[idx]._examine = Common::String(&_descText[_bgShapes[idx]._descOffset]);
+				if (_bgShapes[idx]._descOffset >= _descText.size())
+					_bgShapes[idx]._examine = "";
+				else
+					_bgShapes[idx]._examine = Common::String(&_descText[_bgShapes[idx]._descOffset]);
 				_bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset];
 				_bgShapes[idx]._misc = 0;
 				_bgShapes[idx]._seqCounter = 0;


Commit: fa25e7267df2a3263cb428a7d65438d455847cef
    https://github.com/scummvm/scummvm/commit/fa25e7267df2a3263cb428a7d65438d455847cef
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
SHERLOCK: Support Chinese rendering in the Rose Tatoo

Serrated scalpel is not covered as it uses both a different encoding
(Big5 instead of EUC-CN) and different font format (it uses some obfuscation).

Changed paths:
    engines/sherlock/fonts.cpp
    engines/sherlock/fonts.h
    engines/sherlock/surface.cpp
    engines/sherlock/surface.h


diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 4df0217077d..7848771726f 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -35,15 +35,20 @@ int Fonts::_fontHeight;
 int Fonts::_widestChar;
 uint16 Fonts::_charCount;
 byte Fonts::_yOffsets[255];
+bool Fonts::_isModifiedEucCn;
+byte *Fonts::_chineseFont;
 
 void Fonts::setVm(SherlockEngine *vm) {
 	_vm = vm;
 	_font = nullptr;
 	_charCount = 0;
+	_isModifiedEucCn = _vm->getLanguage() == Common::Language::ZH_ANY && _vm->getGameID() == GameType::GType_RoseTattoo;
 }
 
 void Fonts::freeFont() {
 	delete _font;
+	delete _chineseFont;
+	_chineseFont = nullptr;
 }
 
 void Fonts::setFont(int fontNum) {
@@ -63,6 +68,16 @@ void Fonts::setFont(int fontNum) {
 
 	Common::String fontFilename;
 
+	if (_isModifiedEucCn && _chineseFont == nullptr) {
+		Common::File hzk;
+		if (!hzk.open("Hzk16.lib")) {
+			_isModifiedEucCn = false;
+		} else {
+			_chineseFont = new byte[hzk.size()];
+			hzk.read(_chineseFont, hzk.size());
+		}
+	}
+
 	if (_vm->getPlatform() != Common::kPlatform3DO) {
 		// PC
 		// use FONT[number].VGS, which is a regular sherlock graphic file
@@ -201,8 +216,39 @@ void Fonts::writeString(BaseSurface *surface, const Common::String &str,
 	if (!_font)
 		return;
 
+	bool isInEucEscape = false;
+
 	for (const char *curCharPtr = str.c_str(); *curCharPtr; ++curCharPtr) {
 		byte curChar = *curCharPtr;
+		byte nextChar = curCharPtr[1];
+
+		if (_isModifiedEucCn && !isInEucEscape && curChar == '@' && nextChar == '$') {
+			charPos.x += 10;
+			curCharPtr++;
+			isInEucEscape = true;
+			continue;
+		}
+
+		if (_isModifiedEucCn && isInEucEscape && curChar == '$' && nextChar == '@') {
+			charPos.x += 10;
+			curCharPtr++;
+			isInEucEscape = false;
+			continue;
+		}
+
+		if (_isModifiedEucCn && curChar >= 0x41 && nextChar >= 0x41 && (isInEucEscape || ((curChar >= 0xa1) && (nextChar >= 0xa1)))) {
+			int a = curChar >= 0xa1 ? curChar - 0xa1 : curChar - 0x41;
+			int b = nextChar >= 0xa1 ? nextChar - 0xa1 : nextChar - 0x41;
+			curCharPtr++;
+			if (a >= 0 && a <= 93 && b >= 0 && b <= 93) {
+				surface->SHbitmapBlitFrom(_chineseFont + 32 * (94 * a + b), kChineseWidth, kChineseHeight, kChineseWidth / 8,
+							  Common::Point(charPos.x, charPos.y), overrideColor);
+				charPos.x += kChineseWidth;
+				continue;
+			} else {
+				curChar = '?';
+			}
+		}
 
 		if (curChar == ' ') {
 			charPos.x += 5; // hardcoded space
@@ -226,8 +272,34 @@ int Fonts::stringWidth(const Common::String &str) {
 	if (!_font)
 		return 0;
 
-	for (const char *c = str.c_str(); *c; ++c)
+	bool isInEucEscape = false;
+
+	for (const char *c = str.c_str(); *c; ++c) {
+		byte curChar = *c;
+		byte nextChar = c[1];
+
+		if (_isModifiedEucCn && !isInEucEscape && curChar == '@' && nextChar == '$') {
+			width += charWidth(' ');
+			c++;
+			isInEucEscape = true;
+			continue;
+		}
+
+		if (_isModifiedEucCn && isInEucEscape && curChar == '$' && nextChar == '@') {
+			width += charWidth(' ');
+			c++;
+			isInEucEscape = false;
+			continue;
+		}
+
+		if (_isModifiedEucCn && curChar >= 0x41 && nextChar >= 0x41 && (isInEucEscape || ((curChar >= 0xa1) && (nextChar >= 0xa1)))) {
+			width += kChineseWidth;
+			c++;
+			continue;
+		}
+
 		width += charWidth(*c);
+	}
 
 	return width;
 }
@@ -238,8 +310,34 @@ int Fonts::stringHeight(const Common::String &str) {
 	if (!_font)
 		return 0;
 
-	for (const char *c = str.c_str(); *c; ++c)
+	bool isInEucEscape = false;
+
+	for (const char *c = str.c_str(); *c; ++c) {
+		byte curChar = *c;
+		byte nextChar = c[1];
+		
+		if (_isModifiedEucCn && !isInEucEscape && curChar == '@' && nextChar == '$') {
+			height = MAX(height, charHeight(' '));
+			c++;
+			isInEucEscape = true;
+			continue;
+		}
+
+		if (_isModifiedEucCn && isInEucEscape && curChar == '$' && nextChar == '@') {
+			height = MAX(height, charHeight(' '));
+			c++;
+			isInEucEscape = false;
+			continue;
+		}
+
+		if (_isModifiedEucCn && curChar >= 0x41 && nextChar >= 0x41 && (isInEucEscape || ((curChar >= 0xa1) && (nextChar >= 0xa1)))) {
+			height = MAX(height, kChineseHeight);
+			c++;
+			continue;
+		}
+
 		height = MAX(height, charHeight(*c));
+	}
 
 	return height;
 }
diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h
index b05733c4d44..773d2e75cc4 100644
--- a/engines/sherlock/fonts.h
+++ b/engines/sherlock/fonts.h
@@ -35,11 +35,13 @@ class BaseSurface;
 class Fonts {
 private:
 	static ImageFile *_font;
+	static byte *_chineseFont;
 	static byte _yOffsets[255];
 	static int _fontNumber;
 	static int _fontHeight;
 	static int _widestChar;
 	static uint16 _charCount;
+	static bool _isModifiedEucCn;
 
 	static inline byte translateChar(byte c);
 protected:
@@ -49,6 +51,9 @@ protected:
 		const Common::Point &pt, int overrideColor = 0);
 
 public:
+	static const int kChineseWidth = 16;
+	static const int kChineseHeight = 16;
+
 	/**
 	 * Initialise the font manager
 	 */
@@ -87,7 +92,7 @@ public:
 	/**
 	 * Return the font height
 	 */
-	int fontHeight() const { return _fontHeight; }
+	int fontHeight() const { return _chineseFont ? MAX(_fontHeight, 16) : _fontHeight; }
 
 	/**
 	 * Return the width of the widest character in the font
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index d474f34cfac..514f6683149 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -70,5 +70,28 @@ void BaseSurface::SHtransBlitFrom(const Graphics::Surface &src, const Common::Po
 		flipped, overrideColor);
 }
 
+void BaseSurface::SHbitmapBlitFrom(const byte *src, int widthSrc, int heightSrc, int pitchSrc, const Common::Point &pt,
+				   int overrideColor) {
+	const byte *ptr = src;
+	int yin = 0, yout = pt.y;
+	int xin = 0, xout = pt.x;
+	byte bit = 0x80;
+	int ymax = MIN(heightSrc, h - pt.y);
+	int xmax = MIN(widthSrc, w - pt.x);
+	int pitchskip = pitchSrc - (xmax / 8);
+	for (yin = 0; yin < ymax; yin++, yout++) {
+		bit = 0x80;
+		for (xin = 0, xout = pt.x; xin < xmax; xin++, xout++) {
+			if (*ptr & bit)
+				setPixel(xout, yout, overrideColor);
+			bit >>= 1;
+			if (!bit) {
+				bit = 0x80;
+				ptr++;
+			}
+		}
+		ptr += pitchskip;
+	}
+}
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h
index a9fb2f6bf25..82b323dde9c 100644
--- a/engines/sherlock/surface.h
+++ b/engines/sherlock/surface.h
@@ -72,6 +72,9 @@ public:
 		Graphics::ManagedSurface::blitFrom(src, srcBounds, destPos);
 	}
 
+	virtual void SHbitmapBlitFrom(const byte *src, int width, int height, int pitchSrc, const Common::Point &pt,
+				      int overrideColor = 0);
+
 	/**
 	 * Draws an image frame at a given position within this surface with transparency
 	 */


Commit: 5fae569597a253504f6c014b40ad97105e8e0172
    https://github.com/scummvm/scummvm/commit/5fae569597a253504f6c014b40ad97105e8e0172
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
SHERLOCK: Handle word wrapping for EUC-CN

Changed paths:
    engines/sherlock/fonts.cpp
    engines/sherlock/fonts.h
    engines/sherlock/tattoo/widget_base.cpp
    engines/sherlock/tattoo/widget_tooltip.cpp


diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 7848771726f..59d7bf5b959 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -209,6 +209,42 @@ inline byte Fonts::translateChar(byte c) {
 	}
 }
 
+Common::String Fonts::unescape(const Common::String& in) {
+	if (!_isModifiedEucCn)
+		return in;
+
+	bool isInEucEscape = false;
+	Common::String out;
+
+	for (const char *curCharPtr = in.c_str(); *curCharPtr; ++curCharPtr) {
+		byte curChar = *curCharPtr;
+		byte nextChar = curCharPtr[1];
+
+		if (_isModifiedEucCn && !isInEucEscape && curChar == '@' && nextChar == '$') {
+			curCharPtr++;
+			isInEucEscape = true;
+			out += ' ';
+			continue;
+		}
+
+		if (_isModifiedEucCn && isInEucEscape && curChar == '$' && nextChar == '@') {
+			curCharPtr++;
+			isInEucEscape = false;
+			out += ' ';
+			continue;
+		}
+
+		if (_isModifiedEucCn && curChar >= 0x41 && curChar < 0xa0) {
+			out += curChar + 0x60;
+			continue;
+		}
+
+		out += curChar;
+	}
+
+	return out;
+}
+
 void Fonts::writeString(BaseSurface *surface, const Common::String &str,
 		const Common::Point &pt, int overrideColor) {
 	Common::Point charPos = pt;
diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h
index 773d2e75cc4..d5e52196788 100644
--- a/engines/sherlock/fonts.h
+++ b/engines/sherlock/fonts.h
@@ -64,6 +64,8 @@ public:
 	 */
 	static void freeFont();
 
+	static bool isModifiedEucCn() { return _isModifiedEucCn; }
+
 	/**
 	 * Set the font to use for writing text on the screen
 	 */
@@ -79,6 +81,8 @@ public:
 	 */
 	int stringHeight(const Common::String &str);
 
+	static Common::String unescape(const Common::String& in);
+
 	/**
 	 * Returns the width of a character in pixels
 	 */
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index fc62355000b..d002c638e33 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -136,32 +136,94 @@ void WidgetBase::drawBackground() {
 Common::String WidgetBase::splitLines(const Common::String &str, Common::StringArray &lines, int maxWidth, uint maxLines) {
 	Talk &talk = *_vm->_talk;
 	const char *strP = str.c_str();
+	bool isModifiedEucCn = Fonts::isModifiedEucCn();
+
+	bool isInEucEscape = false;
 
 	// Loop counting up lines
 	lines.clear();
 	do {
 		int width = 0;
 		const char *spaceP = nullptr;
+		bool spacePNeedsEndEscape = false;
+		bool spacePNeedsBeginEscape = false;
 		const char *lineStartP = strP;
+		// Invariant: lastCharP is either nullptr
+		// or is exactly one character behind strP
+		// and in the same escape state.
+		const char *lastCharP = nullptr;
+		bool isLineStartPInEucEscape = isInEucEscape;
 
 		// Find how many characters will fit on the next line
 		while (width < maxWidth && *strP && ((byte)*strP < talk._opcodes[OP_SWITCH_SPEAKER] ||
 				(byte)*strP == talk._opcodes[OP_NULL])) {
+			if (isModifiedEucCn) {
+				byte curChar = *strP;
+				byte nextChar = strP[1];
+				if (!isInEucEscape && curChar == '@' && nextChar == '$') {
+					width += _surface.charWidth(' ');
+					if (lineStartP != strP) {
+						spaceP = strP;
+						spacePNeedsEndEscape = isInEucEscape;
+						spacePNeedsBeginEscape = true;
+					}
+					lastCharP = nullptr;
+					strP += 2;
+					isInEucEscape = true;
+					continue;
+				}
+				
+				if (isInEucEscape && curChar == '$' && nextChar == '@') {
+					width += _surface.charWidth(' ');
+					spaceP = strP;
+					lastCharP = nullptr;
+					strP += 2;
+					spacePNeedsEndEscape = isInEucEscape;
+					spacePNeedsBeginEscape = false;
+					isInEucEscape = false;
+					continue;
+				}
+
+				if (curChar >= 0x41 && nextChar >= 0x41 && (isInEucEscape || ((curChar >= 0xa1) && (nextChar >= 0xa1)))) {
+					width += Fonts::kChineseWidth;
+					lastCharP = strP;
+					strP += 2;
+					continue;
+				}
+			}
 			width += _surface.charWidth(*strP);
 
 			// Keep track of the last space
-			if (*strP == ' ')
+			if (*strP == ' ') {
+				spacePNeedsEndEscape = isInEucEscape;
+				spacePNeedsBeginEscape = isInEucEscape;
 				spaceP = strP;
+			}
+			lastCharP = strP;
 			++strP;
 		}
 
+		bool previousEucEscape = isInEucEscape;
+
 		// If the line was too wide to fit on a single line, go back to the last space
 		// if there was one, or otherwise simply break the line at this point
-		if (width >= maxWidth && spaceP != nullptr)
+		if (width >= maxWidth && spaceP != nullptr) {
+			previousEucEscape = spacePNeedsEndEscape;
+			isInEucEscape = spacePNeedsBeginEscape;
 			strP = spaceP;
+		} else if (width >= maxWidth && lastCharP != nullptr && lastCharP != lineStartP) {
+			strP = lastCharP;
+		}
+
+		Common::String line(lineStartP, strP);
+		if (!line.hasPrefix("@$") && isLineStartPInEucEscape)
+			line = "@$" + line;
+
+		if (!line.hasSuffix("$@") && previousEucEscape)
+			line = line + "$@";		
 
 		// Add the line to the output array
-		lines.push_back(Common::String(lineStartP, strP));
+		lines.push_back(line);
 
 		// Move the string ahead to the next line
 		if (*strP == ' ' || *strP == 13)
diff --git a/engines/sherlock/tattoo/widget_tooltip.cpp b/engines/sherlock/tattoo/widget_tooltip.cpp
index 9ba785fef5d..28cdab9b6b5 100644
--- a/engines/sherlock/tattoo/widget_tooltip.cpp
+++ b/engines/sherlock/tattoo/widget_tooltip.cpp
@@ -71,10 +71,11 @@ void WidgetTooltipBase::erase() {
 WidgetTooltip::WidgetTooltip(SherlockEngine *vm) : WidgetTooltipBase (vm), _offsetY(0) {
 }
 
-void WidgetTooltip::setText(const Common::String &str) {
+void WidgetTooltip::setText(const Common::String &strIn) {
 	Events &events = *_vm->_events;
 	Common::Point mousePos = events.mousePos();
 	bool reset = false;
+	Common::String str = Fonts::unescape(strIn);
 
 	// Make sure that the description is present
 	if (!str.empty()) {


Commit: 00afc844926ae73ebe17195455df70693480effd
    https://github.com/scummvm/scummvm/commit/00afc844926ae73ebe17195455df70693480effd
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
SHERLOCK: Import all fixed strings for Chinese version of Tattoo

Changed paths:
    engines/sherlock/tattoo/tattoo_fixed_text.cpp


diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.cpp b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
index e02e467a8db..b14dc4c6eac 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.cpp
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
@@ -770,11 +770,195 @@ static const char *const fixedTextES[] = {
 	"Cochero"
 };
 
+static const char *const fixedTextZH[] = {
+	"Money", /* Used as id, not shown, not translated.  */
+	"\xc7\xae", /* é’±; Money */
+	"Card", /* Used as id, not shown, not translated.  */
+	"\xc3\xfb\xc6\xac", /* 名片; Card */
+	"Tobacco", /* Used as id, not shown, not translated.  */
+	"\xd1\xcc\xb6\xb7", /* 烟斗; Tobacco */
+	"Timetable", /* Used as id, not shown, not translated.  */
+	"\xca\xb1\xbf\xcc\xb1\xed", /* 时刻表; Timetable */
+	"Summons", /* Used as id, not shown, not translated.  */
+	"\xb1\xe3\xcc\xf5", /* 便条; Summons */
+	"Foolscap", /* Used as id, not shown, not translated.  */
+	"\xbb\xee\xd2\xb3\xd6\xbd", /* 活页纸; Foolscap */
+	"Damp Paper", /* Used as id, not shown, not translated.  */
+	"\xca\xaa\xbb\xee\xd2\xb3\xd6\xbd", /* 湿活页纸; Foolscap */
+	"Bull's Eye", /* Used as id, not shown, not translated.  */
+	"\xc5\xa3\xd1\xdb\xbf\xf3\xb5\xc6", /* 牛眼矿灯; Bull's Eye Lantern */
+
+	"\xb4\xf2\xbf\xaa", /* 打开; Open */
+	"\xb9\xdb\xb2\xec", /* 观察; Look */
+	"\xbd\xbb\xcc\xb8", /* 交谈; Talk */
+	"\xca\xb9\xd3\xc3", /* 使用; Use */
+	"\xca\xd6\xbc\xc7", /* 手记; Journal */
+	"\xce\xef\xc6\xb7", /* 物品; Inventory */
+	"\xd1\xa1\xcf\xee", /* 选项; Options */
+	"\xbd\xe2\xbe\xf6", /* 解决; Solve */
+	"\xd3\xda", /* 于; with */
+	"\xc3\xbb\xd3\xd0\xd0\xa7\xb9\xfb", /* 没有效果; No effect... */
+	"\xd5\xe2\xb8\xf6\xc8\xcb\xcf\xd6\xd4\xda\xc3\xbb\xd3\xd0\xbb\xb0\xcb\xb5\xa1\xa3", /* 这个人现在没有话说。; This person has nothing to say at the moment */
+	"\xbc\xf1\xc6\xf0", /* 捡起; Picked up*/
+
+	"\xd2\xb3 %d", /* 页 %d; Page %d */
+	"\xba\xcf\xc9\xcf\xca\xd6\xbc\xc7", /* 合上手记; Close Journal */
+	"\xb2\xe9\xbf\xb4\xca\xd6\xbc\xc7", /* 查看手记; Search Journal */
+	"\xb4\xe6\xb4\xa2\xca\xd6\xbc\xc7", /* 存储手记; Save Journal */
+	"\xb7\xc5\xc6\xfa\xcb\xd1\xcb\xf7", /* 放弃搜索; Abort search */
+	"\xcf\xf2\xba\xf3\xcb\xd1\xcb\xf7", /* 向后搜索; Search Backwards  */
+	"\xcf\xf2\xc7\xb0\xcb\xd1\xcb\xf7", /* 向前搜索; Search Forwards  */
+	"\xd3\xd0\xb9\xd8\xce\xc4\xd7\xd6\xce\xb4\xb1\xbb\xb7\xa2\xcf\xd6 !", /* 有关文字未被发现 !; Text not found */
+	// Darts
+	"\xb8\xa3\xb6\xfb\xc4\xa6\xcb\xb9", /* 福尔摩斯; Holmes */
+	"\xd5\xd1\xbf\xcb", /* 昭克; Jock */
+	"Bull", // Untranslated in the original
+	"\xc2\xd6\xca\xfd\x3a %d", /* 轮数: %d; Round: %d  */
+	"\xb1\xbe\xc2\xd6\xd7\xdc\xb5\xc3\xb7\xd6\x3a %d", /* 本轮总得分: %d; Turn Total: %d */
+	"\xb7\xc9\xef\xda \x23 %d", /* 飞镖 # %d; Dart # %d */
+	// Following three looks like they are reordered to always give 按任一键开始 (Press any key to start)
+	"\xb0\xb4\xc8\xce\xd2\xbb\xbc\xfc", /* 按任一键; Hit a key */
+	"\xb0\xb4\xc8\xce\xd2\xbb\xbc\xfc", /* 按任一键; To start */
+	"\xbf\xaa\xca\xbc", /* 开始; Press a key */
+	"\xd3\xce\xcf\xb7\xbd\xe1\xca\xf8!", /* 游戏结束!; GAME OVER! */
+	"\xca\xa7\xb0\xdc!", /* 失败!; BUSTED! */
+	"%s \xca\xa4\xc0\xfb\x21", /* %s 胜利!; %s Wins */
+	"\xb5\xc3 %d \xb5\xe3", /* 得 %d 点; Scored %d point.  */
+	"\xb5\xc3 %d \xb5\xe3", /* 得 %d 点; Scored %d point.  */
+	"\xb4\xf2\xd6\xd0 %d", /* 打中 %d; Hit a %d */
+	"\xb4\xf2\xd6\xd0 \xcb\xab\xb1\xb6 %d", /* 打中 双倍 %d; Hit double %d */
+	"\xb4\xf2\xd6\xd0 \xc8\xfd\xb1\xb6 %d", /* 打中 三倍 %d; Hit triple %d */
+	"\xb4\xf2\xd6\xd0 \xc5\xa3\xd1\xdb", /* 打中 牛眼; Hit a bullseye */
+	"\xb4\xf2\xd6\xd0 \xcb\xab\xb1\xb6 \xc5\xa3\xd1\xdb", /* 打中 双倍 牛眼; Hit double bullseye */
+	"\xb4\xf2\xd6\xd0 \xc8\xfd\xb1\xb6 \xc5\xa3\xd1\xdb", /* 打中 三倍 牛眼; Hit triple bullseye */
+
+	"Apply", // Was not translated in the original
+	"Water", // Was not translated in the original
+	"Heat", // Was not translated in the original
+	"@$txh\x8b]\x98Vh$@", /* 载入进度; Load Game. */
+	"@$TBT\x86]\x98Vh$@", /* 储存进度; Save game. */
+	"\xd2\xf4\xc0\xd6", /* 音乐; Music */
+	"\xd2\xf4\xd0\xa7", /* 音效; Sound Effects */
+	"\xd3\xef\xd2\xf4", /* 语音; Voices */
+	"\xb6\xd4\xbb\xb0\xb4\xb0\xbf\xda", /* 对话窗口; Text Windows */
+	"\xcd\xb8\xc3\xf7\xb2\xcb\xb5\xa5", /* 透明菜单; Transparent menus  */
+	"\xb8\xc4\xb1\xe4\xd7\xd6\xcc\xe5\xb7\xe7\xb8\xf1", /* 改变字体风格; Change Font Style  */
+	"\xb9\xd8", /* å…³ ; Off  */
+	"\xbf\xaa", /* å¼€ ; On */
+	"\xcd\xcb\xb3\xf6", /* 退出; Quit  */
+	"\xc4\xe3\xc8\xb7\xb6\xa8\xd2\xaa", /* 你确定要; Are you sure you */
+	"\xcd\xcb\xb3\xf6\xc2\xf0\x3f", /* 退出吗?; wish to Quit ? */
+	"\xc8\xb7\xb6\xa8", /* 确定; Yes */
+	"\xb7\xc5\xc6\xfa", /* 放弃; No */
+	"\xca\xe4\xc8\xeb\xc3\xdc\xc2\xeb", /* 输入密码; Enter password */
+	"Going East", // correct password, was not and should not to be translated
+	"\xbb\xaa\xc9\xfa\xb5\xc4\xca\xd6\xbc\xc7", /* 华生的手记; Watson's Journal */
+	"\xca\xd6\xbc\xc7\xd2\xd1\xb1\xbb\xb3\xc9\xb9\xa6\xb5\xc4\xb4\xa2\xb4\xe6\xd6\xc1 journal.txt", // 手记已被成功的储存至 journal.txt; Journal saved as journal.txt. */
+	// SH2: People names
+	"\xd0\xaa\xc2\xe5\xbf\xcb\xa1\xa4\xb8\xa3\xb6\xfb\xc4\xa6\xcb\xb9", /* 歇洛克・福尔摩斯; Sherlock Holmes */
+	"\xbb\xaa\xc9\xfa\xd2\xbd\xc9\xfa", /* 华生医生; Dr. Watson */
+	"\xb9\xfe\xb5\xc2\xd1\xb7\xcc\xab\xcc\xab", /* 哈德逊太太; Mrs. Hudson */
+	"\xcb\xb9\xcc\xb9\xc0\xfb\xa1\xa4\xb8\xa3\xb2\xbc\xcb\xb9", /* 斯坦利・福布斯; Stanley Forbes */
+	"\xc2\xf5\xbf\xcb\xc2\xde\xb7\xf2\xcc\xd8\xa1\xa4\xb8\xa3\xb6\xfb\xc4\xa6\xcb\xb9", /* 迈克罗夫特・福尔摩斯; Mycroft Holmes */
+	"\xce\xac\xbd\xf0\xcb\xb9", /* 维金斯; Wiggins */
+	"\xb2\xae\xb6\xf7\xbe\xaf\xb9\xd9", /* 伯恩警官; Police Constable Burns */
+	"\xb0\xc2\xbc\xaa\xa1\xa4\xb4\xba\xb2\xae", /* 奥吉・春伯; Augustus Trimble */
+	"\xb5\xc2\xc0\xfb\xbe\xaf\xb9\xd9", /* 德利警官; Police Constable Daley */
+	"\xbb\xa4\xca\xbf\xb3\xa4", /* 护士长; Matron (lit. HEad nurse) */
+	"\xb8\xf1\xc0\xd7\xcb\xb9\xd0\xde\xc5\xae", /* 格雷斯修女; Sister Grace */
+	"\xc6\xd5\xc0\xd7\xcb\xb9\xb6\xd9\xa1\xa4\xc2\xf3\xbf\xcb\xb1\xc8", /* 普雷斯顿・麦克比; Preston McCabe */
+	"\xb1\xab\xb2\xaa\xa1\xa4\xbf\xc2\xc0\xd5\xc8\xf0", /* 鲍勃・柯勒瑞; Bob Colleran */
+	"\xc7\xed\xc4\xc7\xcb\xb9\xa1\xa4\xc8\xf0\xb8\xf1\xb1\xc8", /* 琼那斯・瑞格比; Jonas Rigby */
+	"\xc2\xde\xb3\xb9\xbe\xaf\xb9\xd9", /* 罗彻警官; Police Constable Roach */
+	"\xd5\xb2\xc4\xb7\xcb\xb9\xa1\xa4\xb5\xcf\xce\xd6", /* 詹姆斯・迪沃; James Dewar */
+	"\xd5\xab\xc3\xdc\xa1\xa4\xb5\xcb\xbf\xcf\xbe\xaf\xb9\xd9", /* 斋密・邓肯警官; Sergeant Jeremy Duncan */
+	"\xb8\xf1\xc0\xd7\xc9\xad\xbe\xaf\xb3\xa4", /* 格雷森警长; Inspector Gregson */
+	"\xc0\xd5\xb5\xc2\xbe\xaf\xb3\xa4", /* 勒德警长; Inspector Lestrade */
+	"\xbd\xdc\xce\xf7\xa1\xa4\xc4\xe1\xba\xd5", /* 杰西・尼赫; Jesse Needhem */
+	"\xd1\xc7\xc9\xaa\xa1\xa4\xb8\xa5\xc0\xb3\xc3\xf7", /* 亚瑟・弗莱明; Arthur Fleming */
+	"\xcd\xd0\xc2\xed\xcb\xb9\xa1\xa4\xc6\xd5\xc0\xb3\xcc\xd8\xcf\xc8\xc9\xfa", /* 托马斯・普莱特先生; Mr. Thomas Pratt */
+	"\xc2\xea\xc9\xaa\xb4\xef\xa1\xa4\xc3\xb7\xc9\xad", /* 玛瑟达・梅森; Mathilda (Tillie) Mason */
+	"\xb0\xac\xb5\xc7\xa1\xa4\xc2\xde\xc8\xfb\xb6\xfb", /* 艾登・罗塞尔; Adrian Russell */
+	"\xb0\xa3\xc6\xe6\xa1\xa4\xbb\xdd\xcc\xd8\xc4\xe1", /* 埃奇・惠特尼; Eldridge Whitney */
+	"\xba\xa3\xc6\xd5\xce\xac", /* 海普维; Hepplethwaite */
+	"\xba\xc9\xc0\xb3\xca\xbf\xa1\xa4\xcb\xb9\xce\xac\xb2\xbc\xc8\xf0\xc6\xe6", /* 荷莱士・斯维布瑞奇; Horace Silverbridge */
+	"\xc0\xcf\xc9\xe1\xc2\xfc", /* 老舍曼; Old Sherman */
+	"\xc2\xf3\xb6\xfb\xa1\xa4\xce\xac\xc4\xc7", /* 麦尔・维那; Maxwell Verner */
+	"\xd6\xec\xee\xc8\xa1\xa4\xc8\xf0\xb6\xa1", /* 朱钊・瑞丁; Millicent Redding */
+	"\xce\xac\xbc\xaa\xb6\xfb\xa1\xa4\xcb\xb9\xce\xac\xb2\xbc\xc8\xf0\xc6\xe6", /* 维吉尔・斯维布瑞奇; Virgil Silverbridge */
+	"\xc7\xc7\xd6\xce\xa1\xa4\xb0\xc2\xbb\xf9\xb7\xf2", /* 乔治・奥基夫; George O'Keefe */
+	"\xb5\xa4\xc4\xe1\xcb\xb9\xa1\xa4\xc2\xe5\xb6\xd9\xd1\xab\xbe\xf4", /* 丹尼斯・洛顿勋爵; Lord Denys Lawton */
+	"\xbd\xdc\xbd\xf0\xcb\xb9", /* 杰金斯; Jenkins */
+	"\xd5\xd1\xbf\xcb\xa1\xa4\xc2\xf3\xb9\xfe\xc4\xe1", /* 昭克・麦哈尼; Jock Mahoney */
+	"\xbe\xc6\xb0\xc9\xc0\xcf\xb0\xe5", /* 酒吧老板; Bartender (lit. bar owner) */
+	"\xbf\xc2\xf7\xec\xc0\xf2\xd1\xc7\xa1\xa4\xc2\xe5\xbf\xcb\xc8\xf0\xc6\xe6\xd0\xa1\xbd\xe3", /* 柯黛莉亚・洛克瑞奇小姐; Lady Cordelia Lockridge */
+	"\xc5\xc1\xcc\xe1\xb8\xf1\xc2\xb7", /* 帕提格路; Pettigrew */
+	"\xb0\xac\xb7\xf0\xc8\xf0\xa1\xa4\xb7\xb6\xd0\xa4\xbe\xf4\xca\xbf", /* 艾佛瑞・范肖爵士; Sir Avery Fanshawe */
+	"\xbb\xf4\xbd\xf0\xcb\xb9", /* 霍金斯; Hodgkins */
+	"\xcd\xfe\xb6\xfb\xb2\xa9\xa1\xa4\xba\xda\xce\xe9\xa1\xb0\xc4\xf1\xcd\xb7\xb6\xf9\xa1\xb1", /* 威尔博・黑伍“鸟头儿”; Wilbur "Birdy" Heywood */
+	"\xd1\xc5\xbf\xc9\xb2\xbc\xa1\xa4\xb7\xa8\xd0\xc2\xb6\xd9", /* 雅可布・法新顿; Jacob Farthington */
+	"\xb7\xc6\xc0\xfb\xa1\xa4\xb2\xbc\xc0\xb3\xcb\xd5", /* 菲利・布莱苏; Philip Bledsoe */
+	"\xcb\xb9\xc4\xe1\xa1\xa4\xb8\xa3\xc0\xd5", /* 斯尼・福勒; Sidney Fowler */
+	"\xcb\xb9\xb6\xe0\xa1\xa4\xcd\xd0\xc2\xfc\xbd\xcc\xca\xda", /* 斯多・托曼教授; Professor Theodore Totman */
+	"\xc2\xde\xcb\xb9\xa1\xa4\xd0\xc1\xb3\xbc", /* 罗斯・辛臣; Rose Hinchem */
+	"\xcd\xd0\xb2\xa8\xd2\xc1", /* 托波伊; Tallboy */
+	"\xd2\xc0\xc0\xd5\xb2\xa9\xa1\xa4\xc8\xf0\xc9\xad\xa1\xb0\xb2\xc3\xb7\xec\xa1\xb1", /* 依勒博・瑞森“裁缝”; Ethlebert "Stitch" Rumsey */
+	"\xb2\xe9\xb6\xfb\xcb\xb9\xa1\xa4\xb8\xa5\xc0\xef\xb5\xc2\xc2\xfc", /* 查尔斯・弗里德曼; Charles Freedman */
+	"\xc4\xe1\xbc\xaa\xb6\xfb\xa1\xa4\xba\xa3\xc3\xf7\xcb\xb9", /* 尼吉尔・海明斯; Nigel Hemmings */
+	"\xb7\xa8\xb6\xfb\xa1\xa4\xbf\xa8\xb6\xfb\xcc\xd8", /* 法尔・卡尔特; Fairfax Carter */
+	"\xcd\xfe\xba\xd5\xb6\xfe\xca\xc0", /* 威赫二世; Wilhelm II */
+	"\xce\xd6\xc9\xad", /* 沃森; Wachthund */
+	"\xc7\xed\xc4\xc7\xa1\xa4\xcd\xfe\xb6\xfb\xd1\xb7", /* 琼那・威尔逊; Jonathan Wilson */
+	"\xb4\xf3\xce\xc0\xa1\xa4\xc2\xde\xd2\xc1\xa1\xa4\xc7\xed\xcb\xb9", /* 大卫・罗伊・琼斯; David Lloyd-Jones */
+	"\xb0\xae\xb5\xc2\xbb\xaa\xa1\xa4\xb9\xfe\xb8\xf1\xc8\xf0\xb8\xa5", /* 爱德华・哈格瑞弗; Edward Hargrove */
+	"\xc3\xdc\xcb\xb9\xcc\xd8\xc8\xf0", /* 密斯特瑞; Misteray */
+	"\xc0\xad\xcb\xb9\xbf\xa8", /* 拉斯卡; The Lascar */
+	"\xf0\xd0\xf0\xc4", /* 鹦鹉; Parrot */
+	"\xce\xc4\xc9\xad\xcc\xd8\xa1\xa4\xcb\xb9\xbf\xa8\xc0\xd7\xcc\xd8", /* 文森特・斯卡雷特; Vincent Scarrett */
+	"\xd1\xc7\xc0\xfa\xc9\xa3\xb5\xc2\xc0\xad", /* 亚历桑德拉; Alexandra */
+	"\xce\xac\xb6\xe0\xc0\xfb\xd1\xc7\xc5\xae\xcd\xf5", /* 维多利亚女王; Queen Victoria */
+	"\xd4\xbc\xba\xb2\xa1\xa4\xb2\xbc\xc0\xca", /* 约翰・布朗; John Brown */
+	"\xb2\xa1\xc8\xcb", /* 病人; A patient */
+	"\xb2\xa1\xc8\xcb", /* 病人; A patient */
+	"\xb9\xcb\xbf\xcd", /* 顾客; Patron */
+	"\xce\xac\xb6\xe0\xc0\xfb\xd1\xc7\xc5\xae\xcd\xf5", /* 维多利亚女王; Queen Victoria */
+	"\xc8\xab\xc9\xed\xb9\xfc\xb0\xd7\xb5\xc4\xb2\xa1\xc8\xcb", /* 全身裹白的病人; Patient in white */
+	"\xd7\xed\xba\xba", /* 醉汉; Lush */
+	"\xd7\xed\xba\xba", /* 醉汉; Drunk */
+	"\xbc\xcb\xc5\xae", /* 妓女; Prostitute */
+	"\xc2\xea\xb5\xc2\xc0\xad\xbf\xc2", /* 玛德拉柯; Mudlark */
+	"\xd0\xde\xb2\xb9\xbd\xb3", /* 修补匠; Grinder */
+	"\xbe\xde\xc8\xcb", /* 巨人; Bouncer */
+	"\xb0\xa3\xc4\xe1\xa1\xa4\xc2\xde\xc7\xd0\xcc\xd8", /* 埃尼・罗切特; Agnes Ratchet */
+	"\xb0\xa2\xc2\xe5\xce\xf7\xb6\xfb\xcb\xb9\xa1\xa4\xc2\xde\xc7\xd0\xcc\xd8", /* 阿洛西尔斯・罗切特; Aloysius Ratchet */
+	"\xbb\xca\xbc\xd2\xb7\xbf\xb5\xd8\xb2\xfa\xb4\xfa\xc0\xed\xc8\xcb", /* 皇家房地产代理人; Real Estate Agent */
+	"\xd6\xb0\xd4\xb1", /* 职员; Candy Clerk */
+	"\xd0\xa1\xc0\xf4", /* 小吏; Beadle */
+	"\xc6\xd5\xc2\xb3\xca\xbf\xc8\xcb", /* 普鲁士人; Prussian */
+	"\xc2\xde\xb2\xae\xb6\xd9\xb7\xf2\xc8\xcb", /* 罗伯顿夫人; Mrs. Rowbottom */
+	"\xc2\xde\xd2\xc1\xa1\xa4\xc7\xed\xcb\xb9\xd0\xa1\xbd\xe3", /* 罗伊・琼斯小姐; Lloyd-Jones */
+	"\xbe\xc6\xb5\xea\xb9\xcb\xbf\xcd", /* 酒店顾客; Tavern patron */
+	"\xca\xb9\xd3\xc3\xd5\xdf", /* 使用者; User */
+	"\xcd\xd0\xb1\xc8", /* 托比; Toby */
+	"\xce\xc4\xbe\xdf\xc9\xcc", /* 文具商; Stationer */
+	"\xd6\xb0\xd4\xb1", /* 职员; Law Clerk */
+	"\xd6\xb0\xd4\xb1", /* 职员; Ministry Clerk */
+	"\xe3\xe5\xd4\xa1\xd5\xdf", /* 沐浴者; Bather */
+	"\xca\xcc\xc5\xae", /* 侍女; Maid */
+	"\xb7\xb6\xd0\xa4\xcc\xab\xcc\xab", /* 范肖太太; Lady Fanshawe */
+	"\xcb\xb9\xc4\xe1\xa1\xa4\xc2\xde\xc7\xd0\xcc\xd8", /* 斯尼・罗切特; Sidney Ratchet */
+	"\xc4\xd0\xba\xa2", /* ç”·å­©; Boy */
+	"\xb9\xcb\xbf\xcd", /* 顾客; Patron */
+	"\xb2\xbc\xc8\xf0\xcc\xd8\xbe\xaf\xb9\xd9", /* 布瑞特警官; Constable Brit */
+	"\xc2\xed\xb3\xb5\xb3\xb5\xb7\xf2", /* 马车车夫; Wagon Driver */
+};
+
 static const FixedTextLanguageEntry fixedTextLanguages[] = {
 	{ Common::DE_DEU,   fixedTextDE },
 	{ Common::ES_ESP,   fixedTextES },
 	{ Common::EN_ANY,   fixedTextEN },
 	{ Common::FR_FRA,   fixedTextFR },
+	{ Common::ZH_ANY,   fixedTextZH },
 	{ Common::UNK_LANG, fixedTextEN }
 };
 


Commit: 23f88cfc28e69ede8567fdf225d1723c3e59256c
    https://github.com/scummvm/scummvm/commit/23f88cfc28e69ede8567fdf225d1723c3e59256c
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
SHERLOCK: Remove unstable flag from Chinese Rose Tattoo

Changed paths:
    engines/sherlock/detection_tables.h


diff --git a/engines/sherlock/detection_tables.h b/engines/sherlock/detection_tables.h
index a7d2e6177c2..25aa978151d 100644
--- a/engines/sherlock/detection_tables.h
+++ b/engines/sherlock/detection_tables.h
@@ -298,7 +298,7 @@ static const SherlockGameDescription gameDescriptions[] = {
 			AD_ENTRY1s("talk.lib", "dfd699efdce02a045f46d15da2d44b76", 582381),
 			Common::ZH_ANY,
 			Common::kPlatformDOS,
-			ADGF_UNSTABLE,
+			ADGF_NO_FLAGS,
 			GUIO3(GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_HELP_STYLE, GAMEOPTION_TRANSPARENT_WINDOWS)
 		},
 		GType_RoseTattoo,


Commit: 8bd72c374ce4e35549acd70d0a01cc05abe190bb
    https://github.com/scummvm/scummvm/commit/8bd72c374ce4e35549acd70d0a01cc05abe190bb
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T00:18:39+01:00

Commit Message:
NEWS: Add mention of Chinese Rose Tattoo

Changed paths:
    NEWS.md


diff --git a/NEWS.md b/NEWS.md
index 91c280509f8..6c63fa693cd 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -308,6 +308,7 @@ For a more comprehensive changelog of the latest experimental code, see:
    - Fixed slowdown in Serrated Scalpel intro when playing the game from a small
      installation.
    - Fixed UI glitches in Serrated Scalpel.
+   - Added support for Chinese Rose Tattoo.
 
  Titanic:
    - Fixed not being able to see House in Starfield puzzle.




More information about the Scummvm-git-logs mailing list