[Scummvm-git-logs] scummvm master -> 7ebf5e4f6d24583008ad6f384928f1d22a871c17

AndywinXp noreply at scummvm.org
Sat Dec 2 10:38:46 UTC 2023


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

Summary:
7ebf5e4f6d SWORD1: Fix support for Korean translation


Commit: 7ebf5e4f6d24583008ad6f384928f1d22a871c17
    https://github.com/scummvm/scummvm/commit/7ebf5e4f6d24583008ad6f384928f1d22a871c17
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-12-02T11:38:40+01:00

Commit Message:
SWORD1: Fix support for Korean translation

>From british-choi ScummVM fork

Changed paths:
    engines/sword1/detection_tables.h
    engines/sword1/resman.cpp
    engines/sword1/resman.h
    engines/sword1/sword1.cpp
    engines/sword1/text.cpp
    engines/sword1/text.h


diff --git a/engines/sword1/detection_tables.h b/engines/sword1/detection_tables.h
index fcaf1a2d024..f4db4531a17 100644
--- a/engines/sword1/detection_tables.h
+++ b/engines/sword1/detection_tables.h
@@ -502,6 +502,21 @@ static const ADGameDescription gameDescriptions[] = {
 		GUIO0()
 	},
 
+	{ // Korean fan translation
+		"sword1",
+		"",
+		AD_ENTRY6s("clusters/scripts.clu",  "72b10193714e8c6e4daca51791c0db0c", 1087240,
+				   "clusters/swordres.rif", "d21d6321ee2dbb2d7d7ca2d2a940c34a", 58916,
+				   "clusters/text.clu",     "76f93f5feecc8915435105478f3c6615", 2704592,
+				   "smackshi/intro.smk",    "d82a7869ace8fcecaa519c04c4bfc483", 13233268,
+				   "bs1k.fnt",              NULL,                               1222000,
+				   "korean.clu",            NULL,                               -1),
+		Common::KO_KOR,
+		Common::kPlatformWindows,
+		ADGF_NO_FLAGS,
+		GUIO0()
+	},
+
 	{
 		"sword1",
 		"",
diff --git a/engines/sword1/resman.cpp b/engines/sword1/resman.cpp
index e0896268614..2b6b27a59eb 100644
--- a/engines/sword1/resman.cpp
+++ b/engines/sword1/resman.cpp
@@ -43,10 +43,11 @@ void guiFatalError(char *msg) {
 
 #define MAX_PATH_LEN 260
 
-ResMan::ResMan(const char *fileName, bool isMacFile) {
+ResMan::ResMan(const char *fileName, bool isMacFile, bool isKorean) {
 	_openCluStart = _openCluEnd = nullptr;
 	_openClus = 0;
 	_isBigEndian = isMacFile;
+	_isKorTrs = isKorean;
 	_memMan = new MemMan();
 	loadCluDescript(fileName);
 }
@@ -139,6 +140,25 @@ void ResMan::loadCluDescript(const char *fileName) {
 	if (_prj.clu[3].grp[5].noRes == 29)
 		for (uint8 cnt = 0; cnt < 29; cnt++)
 			_srIdList[cnt] = 0x04050000 | cnt;
+
+	if (_isKorTrs) {
+		Common::File *cluFile = new Common::File();
+		cluFile->open("korean.clu");
+		if (cluFile->isOpen()) {
+			for (uint32 resCnt = 0, resOffset = 0; resCnt < _prj.clu[2].grp[0].noRes; resCnt++) {
+				Header header;
+				cluFile->read(&header, sizeof(Header));
+				_prj.clu[2].grp[0].offset[resCnt] = resOffset;
+				_prj.clu[2].grp[0].length[resCnt] = header.comp_length;
+				resOffset += header.comp_length;
+				cluFile->seek(header.decomp_length, SEEK_CUR);
+			}
+			cluFile->close();
+			Common::strcpy_s(_prj.clu[2].label, "korean");
+		} else {
+			_isKorTrs = false;
+		}
+	}
 }
 
 void ResMan::freeCluDescript() {
@@ -255,14 +275,40 @@ void ResMan::resOpen(uint32 id) {  // load resource ID into memory
 	if (!memHandle)
 		return;
 	if (memHandle->cond == MEM_FREED) { // memory has been freed
-		uint32 size = resLength(id);
-		_memMan->alloc(memHandle, size);
-		Common::File *clusFile = resFile(id);
-		assert(clusFile);
-		clusFile->seek(resOffset(id));
-		clusFile->read(memHandle->data, size);
-		if (clusFile->err() || clusFile->eos()) {
-			error("Can't read %d bytes from offset %d from cluster file %s\nResource ID: %d (%08X)", size, resOffset(id), _prj.clu[(id >> 24) - 1].label, id, id);
+		if (id == GAME_FONT && _isKorTrs) {
+			// Load Korean Font
+			uint32 size = resLength(id);
+			uint32 korFontSize = 0;
+			Common::File *korFontFile = NULL;
+
+			korFontFile = new Common::File();
+			korFontFile->open("bs1k.fnt");
+			if (korFontFile->isOpen()) {
+				korFontSize = korFontFile->size();
+			}
+			_memMan->alloc(memHandle, size + korFontSize);
+			Common::File *clusFile = resFile(id);
+			assert(clusFile);
+			clusFile->seek(resOffset(id));
+			clusFile->read(memHandle->data, size);
+			if (clusFile->err() || clusFile->eos()) {
+				error("Can't read %d bytes from offset %d from cluster file %s\nResource ID: %d (%08X)", size, resOffset(id), _prj.clu[(id >> 24) - 1].label, id, id);
+			}
+
+			if (korFontSize > 0) {
+				korFontFile->read((uint8 *)memHandle->data + size, korFontSize);
+				korFontFile->close();
+			}
+		} else {
+			uint32 size = resLength(id);
+			_memMan->alloc(memHandle, size);
+			Common::File *clusFile = resFile(id);
+			assert(clusFile);
+			clusFile->seek(resOffset(id));
+			clusFile->read(memHandle->data, size);
+			if (clusFile->err() || clusFile->eos()) {
+				error("Can't read %d bytes from offset %d from cluster file %s\nResource ID: %d (%08X)", size, resOffset(id), _prj.clu[(id >> 24) - 1].label, id, id);
+			}
 		}
 	} else
 		_memMan->setCondition(memHandle, MEM_DONT_FREE);
diff --git a/engines/sword1/resman.h b/engines/sword1/resman.h
index 0154e738748..999ed4da7c5 100644
--- a/engines/sword1/resman.h
+++ b/engines/sword1/resman.h
@@ -64,7 +64,7 @@ struct Prj {
 
 class ResMan {
 public:
-	ResMan(const char *fileName, bool isMacFile);
+	ResMan(const char *fileName, bool isMacFile, bool isKorean);
 	~ResMan();
 	void flush();
 	void resClose(uint32 id);
@@ -126,6 +126,7 @@ private:
 	Clu *_openCluStart, *_openCluEnd;
 	int  _openClus;
 	bool _isBigEndian;
+	bool _isKorTrs = false;
 
 	Common::Mutex _resourceAccessMutex;
 
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 26347c5eff7..7bf03562525 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -93,7 +93,8 @@ Common::Error SwordEngine::init() {
 	checkCdFiles();
 
 	debug(5, "Starting resource manager");
-	_resMan = new ResMan("swordres.rif", _systemVars.platform == Common::kPlatformMacintosh);
+	_resMan = new ResMan("swordres.rif", _systemVars.platform == Common::kPlatformMacintosh,
+		Common::parseLanguage(ConfMan.get("language")) == Common::KO_KOR);
 	debug(5, "Starting object manager");
 	_objectMan = new ObjectMan(_resMan);
 	_mouse = new Mouse(_system, _resMan, _objectMan);
diff --git a/engines/sword1/text.cpp b/engines/sword1/text.cpp
index 46ecd0f66aa..c7fea7aadd3 100644
--- a/engines/sword1/text.cpp
+++ b/engines/sword1/text.cpp
@@ -130,12 +130,18 @@ void Text::makeTextSprite(uint8 slot, const uint8 *text, uint16 maxWidth, uint8
 			curTextLine = (const uint8 *)textString.c_str();
 		}
 		for (uint16 pos = 0; pos < lines[lineCnt].length; pos++) {
-			sprPtr += copyChar(*curTextLine++, sprPtr, sprWidth, pen);
-
-			if (!SwordEngine::_systemVars.isDemo) {
-				sprPtr -= OVERLAP;
+			if (isKoreanChar(*curTextLine, *(curTextLine + 1))) {
+				sprPtr += copyWChar(*curTextLine, *(curTextLine + 1), sprPtr, sprWidth, pen) - OVERLAP;
+				curTextLine += 2;
+				pos++;
 			} else {
-				sprPtr -= DEMO_OVERLAP;
+				sprPtr += copyChar(*curTextLine++, sprPtr, sprWidth, pen);
+
+				if (!SwordEngine::_systemVars.isDemo) {
+					sprPtr -= OVERLAP;
+				} else {
+					sprPtr -= DEMO_OVERLAP;
+				}
 			}
 		}
 
@@ -167,16 +173,22 @@ uint16 Text::analyzeSentence(const uint8 *text, uint16 maxWidth, LineInfo *line)
 		uint16 wordLength = 0;
 
 		while ((*text != SPACE) && *text) {
-			wordWidth += charWidth(*text);
-
-			if (!SwordEngine::_systemVars.isDemo) {
-				wordWidth -= OVERLAP;
+			if (isKoreanChar(*text, *(text + 1))) {
+				wordWidth += wCharWidth(*text, *(text + 1)) - OVERLAP;
+				wordLength += 2;
+				text += 2;
 			} else {
-				wordWidth -= DEMO_OVERLAP;
-			}
+				wordWidth += charWidth(*text);
 
-			wordLength++;
-			text++;
+				if (!SwordEngine::_systemVars.isDemo) {
+					wordWidth -= OVERLAP;
+				} else {
+					wordWidth -= DEMO_OVERLAP;
+				}
+
+				wordLength++;
+				text++;
+			}
 		}
 
 		if (*text == SPACE)
@@ -306,4 +318,43 @@ void Text::printDebugLine(uint8 *ascii, uint8 first, int x, int y) {
 	} while (*ascii);
 }
 
+uint16 Text::wCharWidth(uint8 hi, uint8 lo) {
+	if (isKoreanChar(hi, lo)) {
+		return 20; // fixed width : 20
+	}
+	return charWidth(hi) + charWidth(lo);
+}
+
+uint16 Text::copyWChar(uint8 hi, uint8 lo, uint8 *sprPtr, uint16 sprWidth, uint8 pen) {
+	if (!isKoreanChar(hi, lo)) {
+		return copyChar(hi, sprPtr, sprWidth, pen) + copyChar(lo, sprPtr, sprWidth, pen);
+	}
+
+	uint16 frameWidth = 20;
+	uint16 frameHeight = 26;
+	FrameHeader *chFrame = _resMan->fetchFrame(_font, 0xFF - SPACE);
+	uint8 *dest = sprPtr;
+	uint8 *decChr = ((uint8 *)chFrame) + sizeof(FrameHeader) + chFrame->width * chFrame->height + ((hi - 0xB0) * 94 + (lo - 0xA1)) * frameWidth * frameHeight;
+
+	for (uint16 cnty = 0; cnty < frameHeight; cnty++) {
+		for (uint16 cntx = 0; cntx < frameWidth; cntx++) {
+			if (*decChr == LETTER_COL)
+				dest[cntx] = pen;
+			else if (((*decChr == BORDER_COL) || (*decChr == BORDER_COL_PSX)) && (!dest[cntx])) // don't do a border if there's already a color underneath (chars can overlap)
+				dest[cntx] = BORDER_COL;
+			decChr++;
+		}
+		dest += sprWidth;
+	}
+	return frameWidth;
+}
+
+bool Text::isKoreanChar(uint8 hi, uint8 lo) {
+	if (SwordEngine::_systemVars.realLanguage != Common::KO_KOR)
+		return false;
+	if (hi >= 0xB0 && hi <= 0xC8 && lo >= 0xA1 && lo <= 0xFE)
+		return true;
+	return false;
+}
+
 } // End of namespace Sword1
diff --git a/engines/sword1/text.h b/engines/sword1/text.h
index 1cee43bba7b..39defa314e9 100644
--- a/engines/sword1/text.h
+++ b/engines/sword1/text.h
@@ -58,7 +58,10 @@ public:
 private:
 	uint16 analyzeSentence(const uint8 *text, uint16 maxWidth, LineInfo *info);
 	uint16 charWidth(uint8 ch);
+	uint16 wCharWidth(uint8 hi, uint8 lo);
 	uint16 copyChar(uint8 ch, uint8 *sprPtr, uint16 sprWidth, uint8 pen);
+	uint16 copyWChar(uint8 hi, uint8 lo, uint8 *sprPtr, uint16 sprWidth, uint8 pen);
+	bool isKoreanChar(uint8 hi, uint8 lo);
 
 	uint8 *_font;
 	uint8 _textCount;




More information about the Scummvm-git-logs mailing list