[Scummvm-git-logs] scummvm master -> 5c91fb8d6a5733baf847e40111a86146045d3e4c

sev- sev at scummvm.org
Mon Dec 7 22:01:42 UTC 2020


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:
5c91fb8d6a SCUMM: Support Lokalizator plugin.


Commit: 5c91fb8d6a5733baf847e40111a86146045d3e4c
    https://github.com/scummvm/scummvm/commit/5c91fb8d6a5733baf847e40111a86146045d3e4c
Author: Vladimir Serbinenko (phcoder at google.com)
Date: 2020-12-07T23:01:38+01:00

Commit Message:
SCUMM: Support Lokalizator plugin.

This was used by Russian translation of Pajama Sam 2 and Spy Fox 3

Changed paths:
  A engines/scumm/he/localizer.cpp
  A engines/scumm/he/localizer.h
    engines/scumm/he/script_v72he.cpp
    engines/scumm/metaengine.cpp
    engines/scumm/module.mk
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h
    engines/scumm/string.cpp


diff --git a/engines/scumm/he/localizer.cpp b/engines/scumm/he/localizer.cpp
new file mode 100644
index 0000000000..f5289531ea
--- /dev/null
+++ b/engines/scumm/he/localizer.cpp
@@ -0,0 +1,122 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/endian.h"
+#include "scumm/he/localizer.h"
+#include "common/file.h"
+#include "common/debug.h"
+
+namespace Scumm {
+
+Localizer::Localizer() {
+	Common::File _file;
+
+	if (!_file.open("lokalizator.big"))
+		return;
+
+	uint _fileSize = _file.size();
+	if (_fileSize < 0x18)
+		return;
+	byte *lkBig = new byte[_fileSize];
+	_file.read(lkBig, _fileSize);
+	// Obfuscation round 1
+	for (uint i = 0; i < _fileSize; i++)
+		lkBig[i] ^= (214013 * i + 2531011) >> 16;
+
+	uint32 numFiles = READ_LE_UINT32(lkBig + 0x14);
+	uint32 localeMsgOffset = 0, localeMsgSize = 0;
+	uint32 talkieDatOffset = 0, talkieDatSize = 0;
+
+	for (uint i = 0; i < numFiles; i++) {
+		byte *fileHdr = lkBig + 0x18 + 0x4c * i;
+		if (strcmp((char *) fileHdr, "locale.msg") == 0) {
+			localeMsgOffset = READ_LE_UINT32(fileHdr + 0x48);
+			localeMsgSize = READ_LE_UINT32(fileHdr + 0x44);
+			continue;
+		}
+		if (strcmp((char *) fileHdr, "talkie.dat") == 0) {
+			talkieDatOffset = READ_LE_UINT32(fileHdr + 0x48);
+			talkieDatSize = READ_LE_UINT32(fileHdr + 0x44);
+			continue;
+		}
+	}
+
+	_isValid = true;
+
+	if (localeMsgSize > 4) {
+		uint32 msgCount = READ_LE_UINT32(lkBig + localeMsgOffset);
+		// Obfuscation round 2
+		uint32 st = 0x12345678;
+		for (uint i = 0; i < localeMsgSize - 4; i++) {
+			byte x = 0;
+			switch (i & 3) {
+			case 0:
+				x = st;
+				break;
+			case 1:
+				x = st + 35;
+				break;
+			case 2:
+				x = st + 70;
+				break;
+			case 3:
+				x = st + 105;
+				st += 45707404;
+				break;
+			}
+			lkBig[i + localeMsgOffset + 4] ^= x;
+		}
+
+		uint32 cur = localeMsgOffset + 4;
+
+		for (uint i = 0; i < msgCount && cur < localeMsgOffset + localeMsgSize; i++) {
+			cur += 4; // Domain id or something like this, always zero
+			uint32 lenOrig = READ_LE_UINT32(lkBig + cur); cur += 4;
+			Common::String orig((char *) lkBig + cur, (char *) lkBig + cur + lenOrig);
+			cur += lenOrig;
+			uint32 lenTrans = READ_LE_UINT32(lkBig + cur); cur += 4;
+			Common::String trans((char *) lkBig + cur, (char *) lkBig + cur + lenTrans);
+			cur += lenTrans;
+			_translationMap[orig] = trans;
+		}
+	}
+
+	for (uint32 cur = talkieDatOffset; cur < talkieDatOffset + talkieDatSize; cur += 16) {
+	    _talkMap[READ_LE_UINT32(lkBig+cur+4)] = READ_LE_UINT32(lkBig+cur+12);
+	}
+}
+
+Common::String Localizer::translate(const Common::String &orig) {
+	if (_translationMap.contains(orig)) {
+		return _translationMap[orig];
+	}
+	return orig;
+}
+
+uint32 Localizer::mapTalk(uint32 orig) {
+	if (_talkMap.contains(orig)) {
+		return _talkMap[orig];
+	}
+	return orig;
+}
+
+}
diff --git a/engines/scumm/he/localizer.h b/engines/scumm/he/localizer.h
new file mode 100644
index 0000000000..25be5eeabf
--- /dev/null
+++ b/engines/scumm/he/localizer.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_LOCALIZER_H
+#define SCUMM_LOCALIZER_H
+
+#include "common/str.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace Scumm {
+
+class Localizer {
+public:
+	Localizer();
+	Common::String translate(const Common::String &original);
+	uint32 mapTalk(uint32 orig);
+	bool isValid() {
+		return _isValid;
+	}
+private:
+	Common::HashMap<Common::String, Common::String> _translationMap;
+	Common::HashMap<uint32, uint32> _talkMap;
+	bool _isValid;
+};
+
+}
+
+#endif
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 304e76faf2..2b21f3cdfa 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -31,6 +31,7 @@
 #include "scumm/dialogs.h"
 #include "scumm/file.h"
 #include "scumm/he/intern_he.h"
+#include "scumm/he/localizer.h"
 #include "scumm/object.h"
 #include "scumm/resource.h"
 #include "scumm/scumm.h"
@@ -317,6 +318,7 @@ void ScummEngine_v72he::decodeScriptString(byte *dst, bool scriptString) {
 	int args[31];
 	int num, len, val;
 	byte chr, string[1024];
+	byte *dst0 = dst;
 	memset(args, 0, sizeof(args));
 	memset(string, 0, sizeof(string));
 
@@ -335,6 +337,10 @@ void ScummEngine_v72he::decodeScriptString(byte *dst, bool scriptString) {
 		len = resStrLen(string) + 1;
 	}
 
+	if (_localizer) {
+		strncpy((char *) string, _localizer->translate((char *) string).c_str(), sizeof(string) - 1);
+	}
+
 	// Decode string
 	num = 0;
 	val = 0;
@@ -372,6 +378,10 @@ void ScummEngine_v72he::decodeScriptString(byte *dst, bool scriptString) {
 		}
 	}
 	*dst = 0;
+
+	if (_localizer) {
+		strncpy((char *) dst0, _localizer->translate((char *) dst0).c_str(), sizeof(string) - 1);
+	}
 }
 
 int ScummEngine_v72he::findObject(int x, int y, int num, int *args) {
diff --git a/engines/scumm/metaengine.cpp b/engines/scumm/metaengine.cpp
index 58bcf9201c..aaeb667715 100644
--- a/engines/scumm/metaengine.cpp
+++ b/engines/scumm/metaengine.cpp
@@ -333,13 +333,6 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
 		return Common::kUnsupportedGameidError;
 	}
 
-	// We don't support yet the
-	// the full game.
-	if (!strcmp(res.game.gameid, "pajama2") && !strcmp(res.extra, "Russobit")) {
-		GUIErrorMessage(_("The Russian version of Pajama Sam 2 is not supported yet due to incomplete code."));
-		return Common::kUnsupportedGameidError;
-	}
-
 	// If the GUI options were updated, we catch this here and update them in the users config
 	// file transparently.
 	Common::updateGameGUIOptions(res.game.guioptions, getGameGUIOptionsDescriptionLanguage(res.language));
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index b12597be23..36d7871da8 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -137,6 +137,7 @@ MODULE_OBJS += \
 	he/script_v100he.o \
 	he/sprite_he.o \
 	he/wiz_he.o \
+	he/localizer.o \
 	he/logic/baseball2001.o \
 	he/logic/basketball.o \
 	he/logic/football.o \
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 5afa175515..6b60875b2b 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -72,6 +72,7 @@
 #include "scumm/scumm_v8.h"
 #include "scumm/sound.h"
 #include "scumm/imuse/sysex.h"
+#include "scumm/he/localizer.h"
 #include "scumm/he/sprite_he.h"
 #include "scumm/he/cup_player_he.h"
 #include "scumm/util.h"
@@ -124,6 +125,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
 	  _rnd("scumm")
 	  {
 
+	_localizer = nullptr;
+
 #ifdef USE_RGB_COLOR
 	if (_game.features & GF_16BIT_COLOR) {
 		if (_game.platform == Common::kPlatformPCEngine)
@@ -1337,6 +1340,14 @@ Common::Error ScummEngine::init() {
 			}
 	}
 
+#ifdef ENABLE_HE
+	Localizer *loc = new Localizer();
+	if (!loc->isValid())
+		delete loc;
+	else
+		_localizer = loc;
+#endif
+
 	_outputPixelFormat = _system->getScreenFormat();
 
 	setupScumm();
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index eb8aa5d151..d8f4351d59 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -90,6 +90,7 @@ class Player_Towns;
 class ScummEngine;
 class ScummDebugger;
 class Sound;
+class Localizer;
 
 struct Box;
 struct BoxCoords;
@@ -1108,6 +1109,8 @@ protected:
 
 	int _nextLeft, _nextTop;
 
+	Localizer *_localizer;
+
 	void restoreCharsetBg();
 	void clearCharsetMask();
 	void clearTextSurface();
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 755396c271..26c19cd6d6 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -32,6 +32,7 @@
 #include "scumm/imuse_digi/dimuse.h"
 #ifdef ENABLE_HE
 #include "scumm/he/intern_he.h"
+#include "scumm/he/localizer.h"
 #endif
 #include "scumm/resource.h"
 #include "scumm/scumm.h"
@@ -336,7 +337,11 @@ bool ScummEngine::handleNextCharsetCode(Actor *a, int *code) {
 			talk_sound_b = buffer[8] | (buffer[9] << 8) | (buffer[12] << 16) | (buffer[13] << 24);
 			buffer += 14;
 			if (_game.heversion >= 60) {
+#ifdef ENABLE_HE
+				((SoundHE *)_sound)->startHETalkSound(_localizer ? _localizer->mapTalk(talk_sound_a) : talk_sound_a);
+#else
 				((SoundHE *)_sound)->startHETalkSound(talk_sound_a);
+#endif
 			} else {
 				_sound->talkSound(talk_sound_a, talk_sound_b, 2);
 			}
@@ -406,7 +411,7 @@ bool ScummEngine_v72he::handleNextCharsetCode(Actor *a, int *code) {
 			}
 			value[i] = 0;
 			//talk_sound_b = atoi(value);
-			((SoundHE *)_sound)->startHETalkSound(talk_sound_a);
+			((SoundHE *)_sound)->startHETalkSound(_localizer ? _localizer->mapTalk(talk_sound_a) : talk_sound_a);
 			break;
 		case 104:
 			_haveMsg = 0;
@@ -429,7 +434,7 @@ bool ScummEngine_v72he::handleNextCharsetCode(Actor *a, int *code) {
 			value[i] = 0;
 			talk_sound_a = atoi(value);
 			//talk_sound_b = 0;
-			((SoundHE *)_sound)->startHETalkSound(talk_sound_a);
+			((SoundHE *)_sound)->startHETalkSound(_localizer ? _localizer->mapTalk(talk_sound_a) : talk_sound_a);
 			break;
 		case 119:
 			_haveMsg = 0xFF;




More information about the Scummvm-git-logs mailing list