1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/file.h"
24 #include "common/md5.h"
25 #include "common/translation.h"
26 
27 #include "gui/error.h"
28 
29 #include "engines/grim/md5check.h"
30 #include "engines/grim/grim.h"
31 
32 namespace Grim {
33 
34 // Grim retail
35 
36 const char *gfupd101[] = {
37 	"bc57c4db2ab814f3bb115ec5702b62f4"
38 };
39 const char *year4mus[] = {
40 	"939e041887c1b14f99ad951ac8e3cb25" //english unpatched
41 };
42 const char *year3mus[] = {
43 	"df556a8fc151f6f48bb68a8cef855e7d" //english unpatched
44 };
45 const char *year2mus[] = {
46 	"775376fccf0415258be6b33e7e6e4985" //english unpatched
47 };
48 const char *year1mus[] = {
49 	"c555c95b0f7557617da364091589d6ea" //english unpatched
50 };
51 const char *year0mus[] = {
52 	"fea10f11abe3ac32d53e4798f80d5ba0" //english unpatched
53 };
54 const char *vox0004[] = {
55 	"ae53a36f77eb0d42a28653b28c345439", //english unpatched
56 	"57915d4dd3aa5aa44817477b7bd41ce6", //italian unpatched
57 	"bae246c5335c1d139b97a48277ee8841", //german unpatched
58 	"a49dce6e1bb83ad40b47e03903aaff1b", //french unpatched
59 	"3577a8b6cf013bc5b9c9133e29d1f4f0" //spanish unpatched
60 };
61 const char *vox0003[] = {
62 	"7c88ad7c949a516793b584299f33ed23", //english unpatched
63 	"f900cb063fbd0ef2a0516e9a00291d13", //italian unpatched
64 	"5bda9a36181c1fea368491b842c11efe", //german unpatched
65 	"c4aa2c45b24f351e8fce40a141084fb0", //french unpatched
66 	"1d4e94e3d3fd803a02c9993412359082" //spanish unpatched
67 };
68 const char *vox0002[] = {
69 	"70419878e32377d9d2906fbcb2cb59b5", //english unpatched
70 	"616e4147c39268b650ce112bf79ea3a1", //italian unpatched
71 	"5ea9fde04f3315a51fe1fe9c5bdb9d0d", //german unpatched
72 	"24bbf1f6d3d63ae07ad2dd06bd7dad8c", //french unpatched
73 	"c4484dadd4a33066290e1847523d7d64" //spanish unpatched
74 };
75 const char *vox0001[] = {
76 	"40beb2e0a6572dc89fddb21f282bc237", //english pre-patched
77 	"6a32f8079d2d98d1c10ec8364765fd4b", //english unpatched
78 	"a0455d5d883ed46f0bda5030e4b5654c", //italian unpatched
79 	"e13eb421b9490cbaeef66f0cf6156764", //german unpatched
80 	"e940d5a4a4f2229f0a6674bf45464457", //french unpatched
81 	"77cdd6f02bc3f7085bff17c454066de3" //spanish unpatched
82 };
83 const char *vox0000[] = {
84 	"c7900f32d48d7e265629bd355a21c795", //english pre-patched
85 	"67627f2d9314f9c0ae55dd2099fc052f", //english unpatched
86 	"c9e1a755f280b3ebff58578c4e5f1e52", //italian unpatched
87 	"e884221099ba62dacf04a35be8428419", //german unpatched
88 	"dbe35af39eec29db21a4c6e1c228cc9d", //french unpatched
89 	"076bf048de229ad8cefcb3d7c0bfd134" //spanish unpatched
90 };
91 const char *movie04[] = {
92 	"605d6f2cc4d21fbe702d8e637b5bcfa1", //english unpatched
93 	"7c8d7e0f4beaca3910658290e8b14cf8", //italian unpatched
94 	"f1b8c1de4f82099ab080f9cbe2b02da6", //german unpatched
95 	"7e2a4578010cdf5407bb24dcfb6705e4", //french unpatched
96 	"2daf2ec272a7be49cbfde053482f182c" //spanish unpatched
97 };
98 const char *movie03[] = {
99 	"113a768e7206016df72f9d2f5c1851b7", //english unpatched
100 	"0fdb7dda9ebc049eac386d29bface366", //italian unpatched
101 	"d2aae2e27616f78016a71818e528acda", //german unpatched
102 	"c2ba7adbf09b7a4f69c180f1c74297ee", //french unpatched
103 	"fb87d5a9e3a81d3ffd521dee4432c4da" //spanish unpatched
104 };
105 const char *movie02[] = {
106 	"24a8704a331a03097d195f3597fe21e1", //english unpatched
107 	"129dad4e40987e91c5549c819d0dad1d", //italian unpatched
108 	"a4d5c108a167afb0674e26790edf65e6", //german unpatched
109 	"90fce3e6e1f91455d92b072f773f0a67", //french unpatched
110 	"f5879c544f4c1f1f2e2d2e92c026c245" //spanish unpatched
111 };
112 const char *movie01[] = {
113 	"548a19a0a4d4ccb8660966d646210820", //english unpatched
114 	"9fd30d0289f9b4d5c09e821a0a478db5", //italian unpatched
115 	"500bc51ce211d528f6c7170f479c9525", //german unpatched
116 	"16674e1496e4fb3f0f5f173f12e30617", //french unpatched
117 	"ede9fb7d035a5d4af496f23f811707a2" //spanish unpatched
118 };
119 const char *movie00[] = {
120 	"0c6b8e4fa74024c4afdf7758f8d8b1a0" //english unpatched
121 };
122 const char *data004[] = {
123 	"2cdb79d3606965a9a0a3378507488dd7" //english unpatched
124 };
125 const char *data003[] = {
126 	"76dcfc2c21f3412415674c65611fb76d", //english unpatched
127 	"7f76c20f1d77db287473ffef10b8b309" //german unpatched
128 };
129 const char *data002[] = {
130 	"d236403c0d860961963db0134380001f" //english unpatched
131 };
132 const char *data001[] = {
133 	"84cf3072586fe2840ae16774adb6f5cb" //english unpatched
134 };
135 const char *data000[] = {
136 	"2069b8bf113119910df8219e787e7e94", //english pre-patched
137 	"08e2505a6a7fd90d3920131b1297c60f" //english unpatched
138 };
139 const char *credits[] = {
140 	"6dcecad8f01657184f8576aab8fb3f00", //english unpatched
141 	"1827307248d55c07642342c9213a4723", //italian unpatched
142 	"2e6319c2ec5772ced5dc9f8b41eb5de7", //german unpatched
143 	"cd71ca4e600198277f22e944988f7516", //french unpatched
144 	"836a2081d5e57ed6ef5eaade7f770b0e" //spanish unpatched
145 };
146 const char *local[] = {
147 	"6142624ce13ea3c9079aa80918010c4a", //italian unpatched
148 	"27c961c16f9eaf0260781883150e5611", //german unpatched
149 	"c9dd41f66883959de27f80bbe457f30d", //french unpatched
150 	"d22648d6787c2f8f0a789ee3ed0c08f7" //spanish unpatched
151 };
152 
153 
154 // Grim demo
155 
156 const char *gfdemo01[] = {
157 	"25d831d57a93eb3ab8edbb07b7b63943"
158 };
159 const char *gdemo001[] = {
160 	"aa44d6c01a1b03d4607901933635d385"
161 };
162 const char *gfdemo01ger[] = {
163 	"fd728f040557118b7ca436f8205029e5"
164 };
165 const char *gfdemo01fra[] = {
166 	"fd728f040557118b7ca436f8205029e5" // Same as german
167 };
168 const char *gfdemo01ita[] = {
169 	"fd728f040557118b7ca436f8205029e5" // Same as german
170 };
171 const char *gfdemo01spa[] = {
172 	"fd728f040557118b7ca436f8205029e5" // Same as german
173 };
174 const char *grimdemo[] = {
175 	"3ba28e7e36a49b5fd01ba98e3c772fe8"
176 };
177 const char *sound001[] = {
178 	"c91a7d405d15fb198a9cb31f89637026"
179 };
180 const char *voice001[] = {
181 	"f24a45079394fee296a0f7fad07c7fad"
182 };
183 const char *voice001ger[] = {
184 	"d1d68735ae10148ecccb6b5000a4db96"
185 };
186 const char *voice001fra[] = {
187 	"43f56fca727e117b724051c740202c26"
188 };
189 const char *voice001ita[] = {
190 	"412bd831ec42d226fa173e0f55cb47cd"
191 };
192 const char *voice001spa[] = {
193 	"00cb825deca33b96719bc157a5427c40"
194 };
195 
196 // EMI retail PC version
197 
198 const char *emi_artAll[] = {
199 	"8c7db9dab564854f2c4bab0571104780", // english patched
200 	"7c1da307c5c3eb1ba65b7c1a2e6b5bce", // german patched
201 	"f2ec4854639cd25792dd3e88fb08a1e6", // spanish patched
202 	"e0fbba846efca842553bb1a726a25dcf", // french patched
203 	"b9838ab13a672a42b1fbc8893b94ca26", // italian patched
204 };
205 const char *emi_artJam[] = {
206 	"e5ff286dbf7b23d1ad41dd8defe48291", // english patched
207 	"f0bcfa22f77d12e25920148d405a9615", // german patched
208 	"86ceeb03620d316f2dba86f68e40bebb", // spanish patched
209 	"6b9c6c88a0cd95f92f60db823fca4baa", // french patched
210 	"70a6fe11cc2de45f7b0650c8ea749156", // italian patched
211 	"10cb2cf22497d0007263116db68692a6", // Mac version
212 };
213 const char *emi_artLuc[] = {
214 	"1fcaef5755e6f6c3c30c89536022bd72", // english patched
215 	"0f6bcf8997ddd3cbdf161132103f769d", // german patched
216 	"cc956c2b6e99329bb970c9c18ed63b80", // spanish patched
217 	"1d388d0c12f99ba9af540f1b8b98e34b", // french patched
218 	"24216ef38709dc0be3771755bd274b79", // italian patched
219 };
220 const char *emi_artMel[] = {
221 	"66144e92a0742fdc9cc6c4f892c53e84", // english patched
222 	"ed1d2548374339775110bf5826db9f6d", // german patched
223 	"9b49161e7bb4db1dd3cb66d33940c22f", // spanish patched
224 	"33f3dc6eaf6ec50a9dbad3858dc00876", // french patched
225 	"640559d6854c3aa5b63bfad1a9afd60e", // italian patched
226 };
227 const char *emi_artMon[] = {
228 	"3510567bda8a4e8c5aee4c3b3bb1f98e", // english patched
229 	"5ff8b38e44fe1d3aeeb277f35f932d7b", // german patched
230 	"1d69547c39a9a85bfb1bf50c503f479d", // spanish patched
231 	"408a55615fef4282b9996aa0df8373e3", // french patched
232 	"a27c1a33652473d7caf26c069520a765", // italian patched
233 };
234 const char *emi_lip[] = {
235 	"57eceeae6b82028243ede6c97c334c57", // english patched
236 	"0ad24338f33f8ed9b4ab21e43f99aff0", // german patched
237 	"c0e9f1197338440b005431d2b365d287", // spanish patched
238 	"53973abc64a8ecaf963ba7e2dc6f7b42", // french patched
239 	"9b64f65a9473d11e34055137c4d978d1", // italian patched
240 };
241 const char *emi_local[] = {
242 	"c3b694d941c05264e8c37dc2be75ca1c", // english patched
243 };
244 const char *emi_patch[] = {
245 	"067100a100b3ca9283b796480aa39b52", // english patched
246 };
247 const char *emi_update[] = {
248 	"7c7dbd2349d49e382a2dea40bed448e0", // english
249 	"dc1376baf7c8be28854a6fa620ad2278", // german
250 	"12c5db7d07d198d1506ab8b141dd594d", // spanish
251 	"cc5ff3bb8f78a0eb4b8e0feb9cdd2e87", // french
252 	"943ad57c2873b5eb9928e6b04a5b48d4", // italian
253 	"6d2516abcdce4266ad3ae873040258ab", // portuguese
254 };
255 const char *emi_sfx[] = {
256 	"a5d2ded26255518b82030466c2368168", // english patched
257 };
258 const char *emi_voiceAll[] = {
259 	"18d3996c7de4d460b4cd4ee5897a90ae", // english patched
260 	"e65a13f2906899ab6eca2cce3c4cb514", // german patched
261 	"073ecbe5f23d17536dce591174bac593", // spanish patched
262 	"86126ac852312452ee79558a5e76d7fd", // french patched
263 	"9b6b4748e872712c267d65778a3ed2da", // italian patched
264 };
265 const char *emi_voiceJam[] = {
266 	"2318a4680a89b93f1f71b09e66c65c86", // english patched
267 	"3df7d4964fe33f22be67920b21d65710", // german patched
268 	"173b1b949a84746d51d51ccbf7e9856e", // spanish patched
269 	"89947e7e6064356ebfde10b644f3d612", // french patched
270 	"a50b0d5d7f3aecd8629bd5e8c0647bcc", // italian patched
271 };
272 const char *emi_voiceLuc[] = {
273 	"d5e4842e421bdb891e6cbf88741e9119", // english patched
274 	"60d96bb92042729037b37c0056f93267", // german patched
275 	"2e0279b8753129f6ce167cc0823a4865", // spanish patched
276 	"ab9fe90e177cd03af1e34059117cc995", // french patched
277 	"c6ed446d4448de214dbdcbb6cbcca41b", // italian patched
278 };
279 const char *emi_voiceMel[] = {
280 	"b8b19fc4a9438f51a99f7cf3cad9c419", // english patched
281 	"0511a19405b763e2dd9ab5b0637757ee", // german patched
282 	"15154f16af25c55d7b797174032abe8a", // spanish patched
283 	"3e678cef88037ebd6c52988744401c03", // french patched
284 	"d1af7a4f0a2bed25c43d3fd197b6df3b", // italian patched
285 };
286 const char *emi_voiceMon[] = {
287 	"9327a6bea951b28bac31bdb52007dc41", // english patched
288 	"e3046478916f0000a657f9ebf498e120", // german patched
289 	"eda144022632cafc45c3174abc774468", // spanish patched
290 	"ef130c43a84c9d88a3e95abc51839292", // french patched
291 	"bc4d8ab5231f620c46117205578a2642", // italian patched
292 };
293 
294 // EMI retail PS2 version
295 
296 const char *emiPS2_artAll[] = {
297 	"7bed6dd54ea6509b708e93017c14df8d", // english
298 };
299 const char *emiPS2_artJam[] = {
300 	"199c713bbfc22ae941502ffd60ea794d", // english
301 };
302 const char *emiPS2_artLuc[] = {
303 	"7add9758294c2118621e900940e66838", // english
304 };
305 const char *emiPS2_artMel[] = {
306 	"514f1a684022831c178a18d13a16b6ad", // english PAL?
307 	"c4f51395440049942fae39bf6155e82c", // english NTSC
308 };
309 const char *emiPS2_artMon[] = {
310 	"db945bd9d5fa990447bbabf6a1e00e5b", // english
311 };
312 const char *emiPS2_lip[] = {
313 	"57eceeae6b82028243ede6c97c334c57", // english
314 };
315 const char *emiPS2_local[] = {
316 	"da26ad3a739f2fa341988901ce8dfa49", // english
317 };
318 /*
319 const char *emiPS2_music1[] = {
320     "a44753d9aaed016e6c7b398b55c97d3d", // english
321 };
322 const char *emiPS2_music2[] = {
323     "204cb3d451e4bf71ae5432ab33ca3a49", // english
324 };
325 */
326 const char *emiPS2_sfx[] = {
327 	"877e90e1329182caaf27d2ce4d3c9c42", // english
328 };
329 const char *emiPS2_voiceAll[] = {
330 	"194a1e545a348df0fe488012bc703338", // english
331 };
332 const char *emiPS2_voiceJam[] = {
333 	"686b45178a4b2fdb5bee2097739feea9", // english
334 };
335 const char *emiPS2_voiceLuc[] = {
336 	"c5e8e0ce9986385b6c1f31b68768be47", // english
337 };
338 const char *emiPS2_voiceMel[] = {
339 	"54663fc82520f1f02d7f3d9b29894540", // english
340 };
341 const char *emiPS2_voiceMon[] = {
342 	"b4a938b9c116e9370e992c8edfb00c35", // english
343 };
344 
345 // EMI demo
346 
347 const char *emid_i9n[] = {
348 	"d913504ec3a2fe52ee02a20a154a2b17", // english patched
349 	"1cd0547b7cb26082274624b146dab3f1", // french
350 	"0e011c72372acc4baeac259b46ae30f4", // german
351 	"25523ee7687096382cbd3f3b6d30b84c", // spanish
352 };
353 const char *emid_lip[] = {
354 	"0a145aa7acc1a68a738c7a6f27d23283", // english patched
355 };
356 const char *emid_MagDemo[] = {
357 	"0a7f0e72d3fab641f0d7b0efbaa15cdc", // english patched
358 };
359 const char *emid_tile[] = {
360 	"23fdff61743c5621963ca04e8ca43000", // english patched
361 };
362 const char *emid_voice[] = {
363 	"7f9867d48b5e0af5cb3fbd8d79741f5d", // english patched
364 };
365 
366 // EMI Macintosh
367 const char *emi_installer[] = {
368 	"93a639e3221405862dc46e9706216c00", // German (EFMI Installer)
369 	"a42f8aa079a6d23c285fceba191e67a4", // English (Monkey Island 4 Installer)
370 };
371 
372 bool MD5Check::_initted = false;
373 Common::Array<MD5Check::MD5Sum> *MD5Check::_files = nullptr;
374 int MD5Check::_iterator = -1;
375 
init()376 void MD5Check::init() {
377 	if (_initted) {
378 		return;
379 	}
380 	_initted = true;
381 	_files = new Common::Array<MD5Sum>();
382 
383 	#define MD5SUM(filename, sums) _files->push_back(MD5Sum(filename, sums, sizeof(sums) / sizeof(const char *)));
384 
385 	if (g_grim->getGameType() == GType_GRIM) {
386 		if (g_grim->getGameFlags() & ADGF_DEMO) {
387 			bool isDemoWithVideo = false;
388 			if (g_grim->getGameLanguage() == Common::DE_DEU) {
389 				MD5SUM("gfdemo01.lab", gfdemo01ger)
390 				MD5SUM("voice001.lab", voice001ger)
391 			} else if (g_grim->getGameLanguage() == Common::FR_FRA) {
392 				MD5SUM("gfdemo01.lab", gfdemo01fra)
393 				MD5SUM("voice001.lab", voice001fra)
394 			} else if (g_grim->getGameLanguage() == Common::IT_ITA) {
395 				MD5SUM("gfdemo01.lab", gfdemo01ita)
396 				MD5SUM("voice001.lab", voice001ita)
397 			} else if (g_grim->getGameLanguage() == Common::ES_ESP) {
398 				MD5SUM("gfdemo01.lab", gfdemo01spa)
399 				MD5SUM("voice001.lab", voice001spa)
400 			} else {
401 				// Check which version we have
402 				Common::File test;
403 				if (!test.open("gfdemo01.lab")) {
404 					isDemoWithVideo = true;
405 					MD5SUM("gdemo001.lab", gdemo001);
406 				} else {
407 					MD5SUM("gfdemo01.lab", gfdemo01)
408 					MD5SUM("voice001.lab", voice001)
409 				}
410 			}
411 			if (!isDemoWithVideo) {
412 				MD5SUM("sound001.lab", sound001)
413 			}
414 			MD5SUM("grimdemo.mus", grimdemo)
415 		} else {
416 			MD5SUM("gfupd101.exe", gfupd101)
417 			MD5SUM("year4mus.lab", year4mus)
418 			MD5SUM("year3mus.lab", year3mus)
419 			MD5SUM("year2mus.lab", year2mus)
420 			MD5SUM("year1mus.lab", year1mus)
421 			MD5SUM("year0mus.lab", year0mus)
422 			MD5SUM("vox0004.lab", vox0004)
423 			MD5SUM("vox0003.lab", vox0003)
424 			MD5SUM("vox0002.lab", vox0002)
425 			MD5SUM("vox0001.lab", vox0001)
426 			MD5SUM("vox0000.lab", vox0000)
427 			MD5SUM("movie04.lab", movie04)
428 			MD5SUM("movie03.lab", movie03)
429 			MD5SUM("movie02.lab", movie02)
430 			MD5SUM("movie01.lab", movie01)
431 			MD5SUM("movie00.lab", movie00)
432 			MD5SUM("data004.lab", data004)
433 			MD5SUM("data003.lab", data003)
434 			MD5SUM("data002.lab", data002)
435 			MD5SUM("data001.lab", data001)
436 			MD5SUM("data000.lab", data000)
437 			MD5SUM("credits.lab", credits)
438 			if (g_grim->getGameLanguage() != Common::EN_ANY) {
439 				MD5SUM("local.lab", local)
440 			}
441 		}
442 	} else {
443 		if (g_grim->getGameFlags() & ADGF_DEMO) {
444 			MD5SUM("i9n.lab", emid_i9n)
445 			MD5SUM("lip.lab", emid_lip)
446 			MD5SUM("MagDemo.lab", emid_MagDemo)
447 			MD5SUM("tile.lab", emid_tile)
448 			MD5SUM("voice.lab", emid_voice)
449 		} else if (g_grim->getGamePlatform() == Common::kPlatformPS2) {
450 			MD5SUM("artAll.m4b", emiPS2_artAll)
451 			MD5SUM("artJam.m4b", emiPS2_artJam)
452 			MD5SUM("artLuc.m4b", emiPS2_artLuc)
453 			MD5SUM("artMel.m4b", emiPS2_artMel)
454 			MD5SUM("artMon.m4b", emiPS2_artMon)
455 			MD5SUM("lip.m4b", emiPS2_lip)
456 			MD5SUM("local.m4b", emiPS2_local)
457 			MD5SUM("sfx.m4b", emiPS2_sfx)
458 			MD5SUM("voiceAll.m4b", emiPS2_voiceAll)
459 			MD5SUM("voiceJam.m4b", emiPS2_voiceJam)
460 			MD5SUM("voiceLuc.m4b", emiPS2_voiceLuc)
461 			MD5SUM("voiceMel.m4b", emiPS2_voiceMel)
462 			MD5SUM("voiceMon.m4b", emiPS2_voiceMon)
463 		} else {
464 			if (g_grim->getGamePlatform() == Common::kPlatformMacintosh) {
465 				if (g_grim->getGameLanguage() == Common::DE_DEU) {
466 					// Known to be the correct filename for german
467 					MD5SUM("EFMI Installer", emi_installer)
468 				} else {
469 					// Known to be the correct filename for english
470 					MD5SUM("Monkey Island 4 Installer", emi_installer)
471 				}
472 			}
473 			MD5SUM("artAll.m4b", emi_artAll)
474 			MD5SUM("artJam.m4b", emi_artJam)
475 			MD5SUM("artLuc.m4b", emi_artLuc)
476 			MD5SUM("artMel.m4b", emi_artMel)
477 			MD5SUM("artMon.m4b", emi_artMon)
478 			MD5SUM("lip.m4b", emi_lip)
479 			MD5SUM("local.m4b", emi_local)
480 			MD5SUM("sfx.m4b", emi_sfx)
481 			MD5SUM("voiceAll.m4b", emi_voiceAll)
482 			MD5SUM("voiceJam.m4b", emi_voiceJam)
483 			MD5SUM("voiceLuc.m4b", emi_voiceLuc)
484 			MD5SUM("voiceMel.m4b", emi_voiceMel)
485 			MD5SUM("voiceMon.m4b", emi_voiceMon)
486 
487 			const char *updateFilename = g_grim->getUpdateFilename();
488 			if (updateFilename)
489 				MD5SUM(updateFilename, emi_update)
490 		}
491 	}
492 
493 	#undef MD5SUM
494 }
495 
clear()496 void MD5Check::clear() {
497 	delete _files;
498 	_files = nullptr;
499 	_initted = false;
500 }
501 
checkMD5(const MD5Sum & sums,const char * md5)502 bool MD5Check::checkMD5(const MD5Sum &sums, const char *md5) {
503 	for (int i = 0; i < sums.numSums; ++i) {
504 		if (strcmp(sums.sums[i], md5) == 0) {
505 			return true;
506 		}
507 	}
508 	return false;
509 }
510 
checkFiles()511 bool MD5Check::checkFiles() {
512 	startCheckFiles();
513 	bool ok = true;
514 	while (_iterator != -1) {
515 		ok = advanceCheck() && ok;
516 	}
517 
518 	return ok;
519 }
520 
startCheckFiles()521 void MD5Check::startCheckFiles() {
522 	init();
523 	_iterator = 0;
524 }
525 
advanceCheck(int * pos,int * total)526 bool MD5Check::advanceCheck(int *pos, int *total) {
527 	if (_iterator < 0) {
528 		return false;
529 	}
530 
531 	const MD5Sum &sum = (*_files)[_iterator++];
532 	if (pos) {
533 		*pos = _iterator;
534 	}
535 	if (total) {
536 		*total = _files->size();
537 	}
538 	if ((uint32)_iterator == _files->size()) {
539 		_iterator = -1;
540 	}
541 
542 	Common::File file;
543 	if (file.open(sum.filename)) {
544 		Common::String md5 = Common::computeStreamMD5AsString(file);
545 		if (!checkMD5(sum, md5.c_str())) {
546 			warning(_("'%s' may be corrupted. MD5: '%s'"), sum.filename, md5.c_str());
547 			GUI::displayErrorDialog(Common::String::format(_("The game data file %s may be corrupted.\nIf you are sure it is "
548 									"not please provide the ResidualVM team the following code, along with the file name, the language and a "
549 									"description of your game version (i.e. dvd-box or jewelcase):\n%s"), sum.filename, md5.c_str()).c_str());
550 			return false;
551 		}
552 	} else {
553 		warning(_("Could not open %s for checking"), sum.filename);
554 		GUI::displayErrorDialog(Common::String::format(_("Could not open the file %s for checking.\nIt may be missing or "
555 								"you may not have the rights to open it.\nGo to http://wiki.residualvm.org/index.php/Datafiles to see a list "
556 								"of the needed files."), sum.filename).c_str());
557 		return false;
558 	}
559 
560 	return true;
561 }
562 
563 }
564