File: localizer.cpp

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (127 lines) | stat: -rw-r--r-- 3,496 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "common/endian.h"
#include "scumm/he/localizer.h"
#include "common/file.h"
#include "common/debug.h"

namespace Scumm {

Localizer::Localizer() {
	Common::File _file;

	_isValid = false;

	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) {
		if (cur + 12 < _fileSize) {
		    _talkMap[READ_LE_UINT32(lkBig+cur+4)] = READ_LE_UINT32(lkBig+cur+12);
		} else {
			warning("Localizer: Skipped overflow bytes at 0x%x", cur);
		}
	}
}

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;
}

}