1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM 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 "hopkins/talk.h"
24 
25 #include "hopkins/files.h"
26 #include "hopkins/globals.h"
27 #include "hopkins/graphics.h"
28 #include "hopkins/hopkins.h"
29 #include "hopkins/objects.h"
30 
31 #include "common/system.h"
32 #include "common/endian.h"
33 #include "common/file.h"
34 #include "common/textconsole.h"
35 
36 namespace Hopkins {
37 
TalkManager(HopkinsEngine * vm)38 TalkManager::TalkManager(HopkinsEngine *vm) {
39 	_vm = vm;
40 	_characterBuffer = NULL;
41 	_characterPalette = NULL;
42 	_characterSprite = NULL;
43 	_characterAnim = NULL;
44 	_characterSize = 0;
45 	_dialogueMesgId1 = _dialogueMesgId2 = _dialogueMesgId3 = _dialogueMesgId4 = 0;
46 	_paletteBufferIdx = 0;
47 }
48 
startAnimatedCharacterDialogue(const Common::String & filename)49 void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename) {
50 	Common::String spriteFilename;
51 
52 	_vm->_fontMan->hideText(5);
53 	_vm->_fontMan->hideText(9);
54 	_vm->_events->refreshScreenAndEvents();
55 	_vm->_graphicsMan->_scrollStatus = 1;
56 	bool oldDisableInventFl = _vm->_globals->_disableInventFl;
57 	_vm->_globals->_disableInventFl = true;
58 	bool fileFoundFl = false;
59 	_characterBuffer = _vm->_fileIO->searchCat(filename, RES_PER, fileFoundFl);
60 	_characterSize = _vm->_fileIO->_catalogSize;
61 	if (!fileFoundFl) {
62 		_characterBuffer = _vm->_fileIO->loadFile(filename);
63 		_characterSize = _vm->_fileIO->fileSize(filename);
64 	}
65 
66 	_vm->_globals->_saveData->_data[svDialogField4] = 0;
67 
68 	getStringFromBuffer(40, spriteFilename, (const char *)_characterBuffer);
69 	getStringFromBuffer(0, _questionsFilename, (const char *)_characterBuffer);
70 	getStringFromBuffer(20, _answersFilename, (const char *)_characterBuffer);
71 
72 	switch (_vm->_globals->_language) {
73 	case LANG_FR:
74 		_answersFilename = _questionsFilename = "RUE.TXT";
75 		break;
76 	case LANG_EN:
77 		_answersFilename = _questionsFilename = "RUEAN.TXT";
78 		break;
79 	case LANG_SP:
80 		_answersFilename = _questionsFilename = "RUEES.TXT";
81 		break;
82 	}
83 	_dialogueMesgId1 = READ_LE_INT16((uint16 *)_characterBuffer + 40);
84 	_paletteBufferIdx = 20 * READ_LE_INT16((uint16 *)_characterBuffer + 42) + 110;
85 	fileFoundFl = false;
86 	_characterSprite = _vm->_fileIO->searchCat(spriteFilename, RES_SAN, fileFoundFl);
87 	if (!fileFoundFl) {
88 		_characterSprite = _vm->_objectsMan->loadSprite(spriteFilename);
89 	} else {
90 		_characterSprite = _vm->_objectsMan->loadSprite("RES_SAN.RES");
91 	}
92 
93 	_vm->_graphicsMan->backupScreen();
94 
95 	if (!_vm->_graphicsMan->_lineNbr)
96 		_vm->_graphicsMan->_scrollOffset = 0;
97 	_vm->_graphicsMan->displayScreen(true);
98 	_vm->_objectsMan->_charactersEnabledFl = true;
99 	searchCharacterPalette(_paletteBufferIdx, false);
100 	startCharacterAnim0(_paletteBufferIdx, false);
101 	initCharacterAnim();
102 	_dialogueMesgId2 = _dialogueMesgId1 + 1;
103 	_dialogueMesgId3 = _dialogueMesgId1 + 2;
104 	_dialogueMesgId4 = _dialogueMesgId1 + 3;
105 	int oldMouseCursorId = _vm->_events->_mouseCursorId;
106 	_vm->_events->_mouseCursorId = 4;
107 	_vm->_events->changeMouseCursor(0);
108 	if (!_vm->_globals->_introSpeechOffFl) {
109 		int answer = 0;
110 		int dlgAnswer;
111 		do {
112 			dlgAnswer = dialogQuestion(false);
113 			if (dlgAnswer != _dialogueMesgId4)
114 				answer = dialogAnswer(dlgAnswer, false);
115 			if (answer == -1)
116 				dlgAnswer = _dialogueMesgId4;
117 			_vm->_events->refreshScreenAndEvents();
118 		} while (dlgAnswer != _dialogueMesgId4);
119 	}
120 	if (_vm->_globals->_introSpeechOffFl) {
121 		int idx = 1;
122 		int answer;
123 		do {
124 			answer = dialogAnswer(idx++, false);
125 		} while (answer != -1);
126 	}
127 	clearCharacterAnim();
128 	_vm->_globals->_introSpeechOffFl = false;
129 	_characterBuffer = _vm->_globals->freeMemory(_characterBuffer);
130 	_characterSprite = _vm->_globals->freeMemory(_characterSprite);
131 	_vm->_graphicsMan->displayScreen(false);
132 
133 	_vm->_graphicsMan->restoreScreen();
134 
135 	_vm->_objectsMan->_charactersEnabledFl = false;
136 	_vm->_events->_mouseCursorId = oldMouseCursorId;
137 
138 	_vm->_events->changeMouseCursor(oldMouseCursorId);
139 	_vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
140 
141 	if (_vm->getIsDemo() == false)
142 		_vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
143 
144 	_vm->_graphicsMan->initColorTable(145, 150, _vm->_graphicsMan->_palette);
145 	_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
146 	_vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_backBuffer, _vm->_events->_startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
147 	memcpy(_vm->_graphicsMan->_frontBuffer, _vm->_graphicsMan->_backBuffer, 614399);
148 	_vm->_globals->_disableInventFl = oldDisableInventFl;
149 	_vm->_graphicsMan->updateScreen();
150 	for (int i = 0; i <= 4; i++)
151 		_vm->_events->refreshScreenAndEvents();
152 	_vm->_graphicsMan->_scrollStatus = 0;
153 }
154 
startStaticCharacterDialogue(const Common::String & filename)155 void TalkManager::startStaticCharacterDialogue(const Common::String &filename) {
156 	// TODO: The original disables the mouse cursor here
157 	bool oldDisableInventFl = _vm->_globals->_disableInventFl;
158 	_vm->_globals->_disableInventFl = true;
159 	bool fileFoundFl = false;
160 	_characterBuffer = _vm->_fileIO->searchCat(filename, RES_PER, fileFoundFl);
161 	_characterSize = _vm->_fileIO->_catalogSize;
162 	if (!fileFoundFl) {
163 		_characterBuffer = _vm->_fileIO->loadFile(filename);
164 		_characterSize = _vm->_fileIO->fileSize(filename);
165 	}
166 
167 	_vm->_globals->_saveData->_data[svDialogField4] = 0;
168 
169 	getStringFromBuffer(0, _questionsFilename, (const char *)_characterBuffer);
170 	getStringFromBuffer(20, _answersFilename, (const char *)_characterBuffer);
171 
172 	switch (_vm->_globals->_language) {
173 	case LANG_EN:
174 		_questionsFilename = "RUEAN.TXT";
175 		_answersFilename = "RUEAN.TXT";
176 		break;
177 	case LANG_FR:
178 		_questionsFilename = "RUE.TXT";
179 		_answersFilename = "RUE.TXT";
180 		break;
181 	case LANG_SP:
182 		_questionsFilename = "RUEES.TXT";
183 		_answersFilename = "RUEES.TXT";
184 		break;
185 	}
186 
187 	_dialogueMesgId1 = READ_LE_INT16((uint16 *)_characterBuffer + 40);
188 	_paletteBufferIdx = 20 * READ_LE_INT16((uint16 *)_characterBuffer + 42) + 110;
189 	searchCharacterPalette(_paletteBufferIdx, false);
190 	_dialogueMesgId2 = _dialogueMesgId1 + 1;
191 	_dialogueMesgId3 = _dialogueMesgId1 + 2;
192 	_dialogueMesgId4 = _dialogueMesgId1 + 3;
193 	int oldMouseCursorId = _vm->_events->_mouseCursorId;
194 	_vm->_events->_mouseCursorId = 4;
195 	_vm->_events->changeMouseCursor(0);
196 
197 	if (!_vm->_globals->_introSpeechOffFl) {
198 		int answer;
199 		do {
200 			answer = dialogQuestion(true);
201 			if (answer != _dialogueMesgId4) {
202 				if (dialogAnswer(answer, true) == -1)
203 					answer = _dialogueMesgId4;
204 			}
205 		} while (answer != _dialogueMesgId4);
206 	}
207 
208 	if (_vm->_globals->_introSpeechOffFl) {
209 		int idx = 1;
210 		int answer;
211 		do {
212 			answer = dialogAnswer(idx++, true);
213 		} while (answer != -1);
214 	}
215 
216 	_characterBuffer = _vm->_globals->freeMemory(_characterBuffer);
217 	_vm->_events->_mouseCursorId = oldMouseCursorId;
218 
219 	_vm->_events->changeMouseCursor(oldMouseCursorId);
220 	_vm->_graphicsMan->initColorTable(145, 150, _vm->_graphicsMan->_palette);
221 	_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
222 	// TODO: The original re-enables the mouse cursor here
223 	_vm->_globals->_disableInventFl = oldDisableInventFl;
224 }
225 
getStringFromBuffer(int srcStart,Common::String & dest,const char * srcData)226 void TalkManager::getStringFromBuffer(int srcStart, Common::String &dest, const char *srcData) {
227 	dest = Common::String(srcData + srcStart);
228 }
229 
dialogQuestion(bool animatedFl)230 int TalkManager::dialogQuestion(bool animatedFl) {
231 	if (animatedFl) {
232 		uint16 *bufPtr = (uint16 *)_characterBuffer + 48;
233 		int curVal = READ_LE_INT16(bufPtr);
234 		if (curVal != 0)
235 			_vm->_objectsMan->setBobAnimation(curVal);
236 		if (curVal != 1)
237 			_vm->_objectsMan->setBobAnimation(READ_LE_INT16(bufPtr + 1));
238 		if (curVal != 2)
239 			_vm->_objectsMan->setBobAnimation(READ_LE_INT16(bufPtr + 2));
240 		if (curVal != 3)
241 			_vm->_objectsMan->setBobAnimation(READ_LE_INT16(bufPtr + 3));
242 		if (curVal != 4)
243 			_vm->_objectsMan->setBobAnimation(READ_LE_INT16(bufPtr + 4));
244 	} else {
245 		dialogWait();
246 	}
247 
248 	int sentence1LineNumb = countBoxLines(_dialogueMesgId1, _questionsFilename);
249 	int sentence2LineNumb = countBoxLines(_dialogueMesgId2, _questionsFilename);
250 	int sentence3LineNumb = countBoxLines(_dialogueMesgId3, _questionsFilename);
251 	int sentence4LineNumb = countBoxLines(_dialogueMesgId4, _questionsFilename);
252 
253 	int sentence4PosY = 420 - 20 * sentence4LineNumb;
254 	int sentence3PosY = sentence4PosY - 20 * sentence3LineNumb;
255 	int sentence2PosY = sentence3PosY - 20 * sentence2LineNumb;
256 	int sentence1PosY = sentence2PosY - 20 * sentence1LineNumb;
257 
258 	_vm->_fontMan->initTextBuffers(5, _dialogueMesgId1, _questionsFilename, 5, sentence1PosY, 0, 65, 255);
259 	_vm->_fontMan->initTextBuffers(6, _dialogueMesgId2, _questionsFilename, 5, sentence2PosY, 0, 65, 255);
260 	_vm->_fontMan->initTextBuffers(7, _dialogueMesgId3, _questionsFilename, 5, sentence3PosY, 0, 65, 255);
261 	_vm->_fontMan->initTextBuffers(8, _dialogueMesgId4, _questionsFilename, 5, sentence4PosY, 0, 65, 255);
262 	_vm->_fontMan->showText(5);
263 	_vm->_fontMan->showText(6);
264 	_vm->_fontMan->showText(7);
265 	_vm->_fontMan->showText(8);
266 
267 	int retVal = -1;
268 	bool loopCond = false;
269 	do {
270 		int mousePosY = _vm->_events->getMouseY();
271 		if (sentence1PosY < mousePosY && mousePosY < (sentence2PosY - 1)) {
272 			_vm->_fontMan->setOptimalColor(6, 7, 8, 5);
273 			retVal = _dialogueMesgId1;
274 		}
275 		if (sentence2PosY < mousePosY && mousePosY < (sentence3PosY - 1)) {
276 			_vm->_fontMan->setOptimalColor(5, 7, 8, 6);
277 			retVal = _dialogueMesgId2;
278 		}
279 		if (sentence3PosY < mousePosY && mousePosY < (sentence4PosY - 1)) {
280 			_vm->_fontMan->setOptimalColor(5, 6, 8, 7);
281 			retVal = _dialogueMesgId3;
282 		}
283 		if (sentence4PosY < mousePosY && mousePosY < 419) {
284 			_vm->_fontMan->setOptimalColor(5, 6, 7, 8);
285 			retVal = _dialogueMesgId4;
286 		}
287 
288 		_vm->_events->refreshScreenAndEvents();
289 		if (_vm->_events->getMouseButton())
290 			loopCond = true;
291 		if (retVal == -1)
292 			loopCond = false;
293 	} while (!_vm->shouldQuit() && !loopCond);
294 
295 	_vm->_soundMan->mixVoice(retVal, 1);
296 	_vm->_fontMan->hideText(5);
297 	_vm->_fontMan->hideText(6);
298 	_vm->_fontMan->hideText(7);
299 	_vm->_fontMan->hideText(8);
300 
301 	if (animatedFl) {
302 		uint16 *bufPtr = (uint16 *)_characterBuffer + 48;
303 
304 		int curVal = READ_LE_INT16(bufPtr);
305 		if (curVal != 0)
306 			_vm->_objectsMan->stopBobAnimation(curVal);
307 
308 		curVal = READ_LE_INT16(bufPtr + 1);
309 		if (curVal != 1)
310 			_vm->_objectsMan->stopBobAnimation(curVal);
311 
312 		curVal = READ_LE_INT16(bufPtr + 2);
313 		if (curVal != 2)
314 			_vm->_objectsMan->stopBobAnimation(curVal);
315 
316 		curVal = READ_LE_INT16(bufPtr + 3);
317 		if (curVal != 3)
318 			_vm->_objectsMan->stopBobAnimation(curVal);
319 
320 		curVal = READ_LE_INT16(bufPtr + 4);
321 		if (curVal != 4)
322 			_vm->_objectsMan->stopBobAnimation(curVal);
323 	} else {
324 		dialogTalk();
325 	}
326 
327 	_vm->_events->refreshScreenAndEvents();
328   return retVal;
329 }
330 
dialogAnswer(int idx,bool animatedFl)331 int TalkManager::dialogAnswer(int idx, bool animatedFl) {
332 	int charIdx;
333 	byte *charBuf;
334 	for (charBuf = _characterBuffer + 110, charIdx = 0; READ_LE_INT16(charBuf) != idx; charBuf += 20) {
335 		++charIdx;
336 		if (READ_LE_INT16((uint16 *)_characterBuffer + 42) < charIdx)
337 			return -1;
338 	}
339 
340 	int mesgId = READ_LE_INT16((uint16 *)charBuf + 1);
341 	int mesgPosX = READ_LE_INT16((uint16 *)charBuf + 2);
342 	int mesgPosY = READ_LE_INT16((uint16 *)charBuf + 3);
343 	int mesgLength = READ_LE_INT16((uint16 *)charBuf + 4);
344 	_dialogueMesgId1 = READ_LE_INT16((uint16 *)charBuf + 5);
345 	_dialogueMesgId2 = READ_LE_INT16((uint16 *)charBuf + 6);
346 	_dialogueMesgId3 = READ_LE_INT16((uint16 *)charBuf + 7);
347 	int frameNumb = READ_LE_INT16((uint16 *)charBuf + 8);
348 
349 	int curBufVal = READ_LE_INT16((uint16 *)charBuf + 9);
350 	if (curBufVal)
351 		_vm->_globals->_saveData->_data[svDialogField4] = curBufVal;
352 
353 	if (!frameNumb)
354 		frameNumb = 10;
355 	if (animatedFl) {
356 		uint16 *bufPtr = (uint16 *)_characterBuffer + 43;
357 		int curVal = READ_LE_INT16(bufPtr);
358 		if (curVal)
359 			_vm->_objectsMan->stopBobAnimation(curVal);
360 
361 		curVal = READ_LE_INT16(bufPtr + 1);
362 		if (curVal)
363 			_vm->_objectsMan->stopBobAnimation(curVal);
364 
365 		curVal = READ_LE_INT16(bufPtr + 2);
366 		if (curVal)
367 			_vm->_objectsMan->stopBobAnimation(curVal);
368 
369 		curVal = READ_LE_INT16(bufPtr + 3);
370 		if (curVal)
371 			_vm->_objectsMan->stopBobAnimation(curVal);
372 
373 		curVal = READ_LE_INT16(bufPtr + 4);
374 		if (curVal)
375 			_vm->_objectsMan->stopBobAnimation(curVal);
376 	} else {
377 		dialogAnim();
378 	}
379 
380 	bool displayedTxtFl = false;
381 	if (!_vm->_soundMan->_textOffFl) {
382 		_vm->_fontMan->initTextBuffers(9, mesgId, _answersFilename, mesgPosX, mesgPosY, 5, mesgLength, 252);
383 		_vm->_fontMan->showText(9);
384 		displayedTxtFl = true;
385 	}
386 	if (!_vm->_soundMan->mixVoice(mesgId, 1, displayedTxtFl)) {
387 		_vm->_events->_curMouseButton = 0;
388 		_vm->_events->_mouseButton = 0;
389 
390 		if (_vm->getIsDemo()) {
391 			for (int i = 0; i < frameNumb; i++) {
392 				_vm->_events->refreshScreenAndEvents();
393 			}
394 		} else {
395 			for (int i = 0; i < frameNumb; i++) {
396 				_vm->_events->refreshScreenAndEvents();
397 				if (_vm->_events->_mouseButton || _vm->_events->_curMouseButton)
398 					break;
399 				if (_vm->_events->getMouseButton() && i + 1 > abs(frameNumb / 5))
400 					break;
401 			}
402 		}
403 	}
404 
405 	if (!_vm->_soundMan->_textOffFl)
406 		_vm->_fontMan->hideText(9);
407 	if (animatedFl) {
408 		uint16 *bufPtr = (uint16 *)_characterBuffer + 43;
409 		int curVal = READ_LE_INT16(bufPtr);
410 		if (curVal)
411 			_vm->_objectsMan->stopBobAnimation(curVal);
412 
413 		curVal = READ_LE_INT16(bufPtr + 1);
414 		if (curVal)
415 			_vm->_objectsMan->stopBobAnimation(curVal);
416 
417 		curVal = READ_LE_INT16(bufPtr + 2);
418 		if (curVal)
419 			_vm->_objectsMan->stopBobAnimation(curVal);
420 
421 		curVal = READ_LE_INT16(bufPtr + 3);
422 		if (curVal)
423 			_vm->_objectsMan->stopBobAnimation(curVal);
424 
425 		curVal = READ_LE_INT16(bufPtr + 4);
426 		if (curVal)
427 			_vm->_objectsMan->stopBobAnimation(curVal);
428 	} else {
429 		dialogEndTalk();
430 	}
431 	int result = 0;
432 	if (!_dialogueMesgId1)
433 		result = -1;
434 
435 	return result;
436 }
437 
searchCharacterPalette(int startIdx,bool dark)438 void TalkManager::searchCharacterPalette(int startIdx, bool dark) {
439 	int palettePos = 0;
440 	size_t curIdx = startIdx;
441 	for (;;) {
442 		if (READ_BE_UINT24(&_characterBuffer[curIdx]) == MKTAG24('P', 'A', 'L')) {
443 			palettePos = curIdx;
444 			break;
445 		}
446 		++curIdx;
447 		if (_characterSize == curIdx)
448 			return;
449 	}
450 
451 	_characterPalette = _characterBuffer + palettePos + 5;
452 	_characterPalette[0] = 0;
453 	_characterPalette[1] = 0;
454 	_characterPalette[2] = 0;
455 	_characterPalette[759] = 255;
456 	_characterPalette[760] = 255;
457 	_characterPalette[762] = 0;
458 	_characterPalette[763] = 0;
459 	_characterPalette[764] = 0;
460 	_characterPalette[765] = 224;
461 	_characterPalette[766] = 224;
462 	_characterPalette[767] = 255;
463 
464 	if (!dark)
465 		_characterPalette[761] = 86;
466 	else
467 		_characterPalette[761] = 255;
468 
469 	_vm->_graphicsMan->setPaletteVGA256(_characterPalette);
470 	_vm->_graphicsMan->initColorTable(145, 150, _characterPalette);
471 }
472 
dialogWait()473 void TalkManager::dialogWait() {
474 	for (int idx = 26; idx <= 30; ++idx) {
475 		if (_vm->_animMan->_animBqe[idx]._enabledFl)
476 			displayBobDialogAnim(idx);
477 	}
478 }
479 
dialogTalk()480 void TalkManager::dialogTalk() {
481 	for (int idx = 26; idx <= 30; ++idx) {
482 		if (_vm->_animMan->_animBqe[idx]._enabledFl)
483 			_vm->_objectsMan->hideBob(idx);
484 	}
485 
486 	for (int idx = 26; idx <= 30; ++idx) {
487 		if (_vm->_animMan->_animBqe[idx]._enabledFl)
488 			_vm->_objectsMan->resetBob(idx);
489 	}
490 }
491 
dialogEndTalk()492 void TalkManager::dialogEndTalk() {
493 	for (int idx = 21; idx <= 25; ++idx) {
494 		if (_vm->_animMan->_animBqe[idx]._enabledFl)
495 			_vm->_objectsMan->hideBob(idx);
496 	}
497 
498 	_vm->_events->refreshScreenAndEvents();
499 	_vm->_events->refreshScreenAndEvents();
500 
501 	for (int idx = 21; idx <= 25; ++idx) {
502 		if (_vm->_animMan->_animBqe[idx]._enabledFl)
503 			_vm->_objectsMan->resetBob(idx);
504 	}
505 }
506 
countBoxLines(int idx,const Common::String & file)507 int TalkManager::countBoxLines(int idx, const Common::String &file) {
508 	_vm->_fontMan->_fontFixedWidth = 11;
509 
510 	// Build up the filename
511 	Common::String filename;
512 	Common::String dest;
513 	filename = dest = file;
514 	while (filename.lastChar() != '.')
515 		filename.deleteLastChar();
516 	filename += "IND";
517 
518 	Common::File f;
519 	if (!f.open(filename))
520 		error("Could not open file - %s", filename.c_str());
521 	int filesize = f.size();
522 	assert(filesize < 16188);
523 
524 	uint32 indexData[4047];
525 	for (int i = 0; i < (filesize / 4); ++i)
526 		indexData[i] = f.readUint32LE();
527 	f.close();
528 
529 	if (!f.open(dest))
530 		error("Error opening file - %s", dest.c_str());
531 
532 	f.seek(indexData[idx]);
533 	byte *decryptBuf = _vm->_globals->allocMemory(2058);
534 	assert(decryptBuf);
535 
536 	f.read(decryptBuf, 2048);
537 	f.close();
538 
539 	// Decrypt buffer
540 	byte *curDecryptPtr = decryptBuf;
541 	for (int i = 0; i < 2048; i++) {
542 		char curByte = *curDecryptPtr;
543 		if ((byte)(curByte + 46) > 27) {
544 			if ((byte)(curByte + 80) > 27) {
545 				if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
546 					curByte = ' ';
547 			} else {
548 				curByte -= 79;
549 			}
550 		} else {
551 			curByte += 111;
552 		}
553 		*curDecryptPtr = curByte;
554 		curDecryptPtr++;
555 	}
556 
557 	// Separate strings
558 	for (int i = 0; i < 2048; i++) {
559 		if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
560 			decryptBuf[i] = 0;
561 	}
562 
563 	// Check size of each strings in order to compute box width
564 	int curBufIndx = 0;
565 	int lineCount = 0;
566 	int lineSize = 0;
567 	char curChar;
568 	do {
569 		int curLineSize = 0;
570 		for (;;) {
571 			lineSize = curLineSize;
572 			do {
573 				curChar = decryptBuf[curBufIndx + curLineSize];
574 				++curLineSize;
575 			} while (curChar != ' ' && curChar != '%');
576 
577 			if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
578 				if (curChar == '%')
579 					curChar = ' ';
580 				break;
581 			}
582 
583 			if (curChar == '%') {
584 				lineSize = curLineSize;
585 				break;
586 			}
587 		}
588 		++lineCount;
589 		curBufIndx += lineSize;
590 	} while (curChar != '%');
591 	_vm->_globals->freeMemory(decryptBuf);
592 	return lineCount;
593 }
594 
dialogAnim()595 void TalkManager::dialogAnim() {
596 	for (int idx = 21; idx <= 25; ++idx) {
597 		if (_vm->_animMan->_animBqe[idx]._enabledFl)
598 			displayBobDialogAnim(idx);
599 	}
600 }
601 
displayBobDialogAnim(int idx)602 void TalkManager::displayBobDialogAnim(int idx) {
603 	_vm->_objectsMan->_priorityFl = true;
604 	if (!_vm->_objectsMan->_bob[idx]._bobMode) {
605 		_vm->_objectsMan->resetBob(idx);
606 		byte *bqeData = _vm->_animMan->_animBqe[idx]._data;
607 		int newMode = READ_LE_INT16(bqeData + 2);
608 		if (!newMode)
609 			newMode = 1;
610 		if (READ_LE_INT16(bqeData + 24)) {
611 			_vm->_objectsMan->_bob[idx]._isSpriteFl = true;
612 			_vm->_objectsMan->_bob[idx]._zoomFactor = 0;
613 			_vm->_objectsMan->_bob[idx]._flipFl = false;
614 			_vm->_objectsMan->_bob[idx]._animData = _vm->_animMan->_animBqe[idx]._data;
615 			_vm->_objectsMan->_bob[idx]._bobMode = 10;
616 			_vm->_objectsMan->_bob[idx]._spriteData = _characterSprite;
617 			_vm->_objectsMan->_bob[idx]._bobModeChange = newMode;
618 			_vm->_objectsMan->_bob[idx]._modeChangeCtr = -1;
619 			_vm->_objectsMan->_bob[idx]._modeChangeUnused = 0;
620 		}
621 	}
622 }
623 
startCharacterAnim0(int startIdx,bool readOnlyFl)624 void TalkManager::startCharacterAnim0(int startIdx, bool readOnlyFl) {
625 	int animIdx = 0;
626 	size_t curIdx = startIdx;
627 	for (;;) {
628 		if (READ_BE_UINT32(&_characterBuffer[curIdx]) == MKTAG('A', 'N', 'I', 'M') && _characterBuffer[curIdx + 4] == 1) {
629 			animIdx = curIdx;
630 			break;
631 		}
632 		++curIdx;
633 		if (_characterSize == curIdx)
634 			return;
635 	}
636 	_characterAnim = _characterBuffer + animIdx + 25;
637 	if (!readOnlyFl) {
638 		int idx = 0;
639 		do {
640 			if (!READ_LE_INT16(&_characterAnim[2 * idx + 4]))
641 				break;
642 			if (_vm->_globals->_speed != 501)
643 				_vm->_graphicsMan->fastDisplay(_characterSprite, _vm->_events->_startPos.x + READ_LE_INT16(&_characterAnim[2 * idx]),
644 				    READ_LE_INT16(&_characterAnim[2 * idx + 2]), _characterAnim[2 * idx + 8]);
645 			idx += 5;
646 		} while (_vm->_globals->_speed != 501);
647 	}
648 }
649 
650 /**
651  * Initialize character animation
652  */
initCharacterAnim()653 void TalkManager::initCharacterAnim() {
654 	uint16 *bufPtr = (uint16 *)_characterBuffer + 43;
655 	byte *animPtr = _characterBuffer + 110;
656 	int curVal = READ_LE_INT16(bufPtr);
657 	if (curVal)
658 		searchCharacterAnim(21, animPtr, curVal, _characterSize);
659 
660 	curVal = READ_LE_INT16(bufPtr + 1);
661 	if (curVal)
662 		searchCharacterAnim(22, animPtr, curVal, _characterSize);
663 
664 	curVal = READ_LE_INT16(bufPtr + 2);
665 	if (curVal)
666 		searchCharacterAnim(23, animPtr, curVal, _characterSize);
667 
668 	curVal = READ_LE_INT16(bufPtr + 3);
669 	if (curVal)
670 		searchCharacterAnim(24, animPtr, curVal, _characterSize);
671 
672 	curVal = READ_LE_INT16(bufPtr + 4);
673 	if (curVal)
674 		searchCharacterAnim(25, animPtr, curVal, _characterSize);
675 
676 	curVal = READ_LE_INT16(bufPtr + 5);
677 	if (curVal)
678 		searchCharacterAnim(26, animPtr, curVal, _characterSize);
679 
680 	curVal = READ_LE_INT16(bufPtr + 6);
681 	if (curVal)
682 		searchCharacterAnim(27, animPtr, curVal, _characterSize);
683 
684 	curVal = READ_LE_INT16(bufPtr + 7);
685 	if (curVal)
686 		searchCharacterAnim(28, animPtr, curVal, _characterSize);
687 
688 	curVal = READ_LE_INT16(bufPtr + 8);
689 	if (curVal)
690 		searchCharacterAnim(29, animPtr, curVal, _characterSize);
691 
692 	curVal = READ_LE_INT16(bufPtr + 9);
693 	if (curVal)
694 		searchCharacterAnim(30, animPtr, curVal, _characterSize);
695 }
696 
clearCharacterAnim()697 void TalkManager::clearCharacterAnim() {
698 	for (int idx = 21; idx <= 34; ++idx) {
699 		_vm->_animMan->_animBqe[idx]._data = _vm->_globals->freeMemory(_vm->_animMan->_animBqe[idx]._data);
700 		_vm->_animMan->_animBqe[idx]._enabledFl = false;
701 	}
702 }
703 
searchCharacterAnim(int idx,const byte * bufPerso,int animId,int bufferSize)704 bool TalkManager::searchCharacterAnim(int idx, const byte *bufPerso, int animId, int bufferSize) {
705 	bool result = false;
706 
707 	for (int bufPos = 0; bufPos <= bufferSize; bufPos++) {
708 		if (READ_BE_UINT32(bufPerso + bufPos) == MKTAG('A', 'N', 'I', 'M') && bufPerso[bufPos + 4] == animId) {
709 			int bufIndx = bufPos + 5;
710 			const byte *curPtr = bufPerso + bufIndx;
711 			int animLength = 0;
712 			bool loopCond = false;
713 			do {
714 				if (READ_BE_UINT32(curPtr) == MKTAG('A', 'N', 'I', 'M') || READ_BE_UINT24(curPtr) == MKTAG24('F', 'I', 'N'))
715 					loopCond = true;
716 				if (bufIndx > bufferSize) {
717 					_vm->_animMan->_animBqe[idx]._enabledFl = false;
718 					_vm->_animMan->_animBqe[idx]._data = NULL;
719 					return false;
720 				}
721 				++bufIndx;
722 				++animLength;
723 				++curPtr;
724 			} while (!loopCond);
725 			_vm->_animMan->_animBqe[idx]._data = _vm->_globals->allocMemory(animLength + 50);
726 			_vm->_animMan->_animBqe[idx]._enabledFl = true;
727 			memcpy(_vm->_animMan->_animBqe[idx]._data, (const byte *)(bufPerso + bufPos + 5), 20);
728 			int bqeVal = READ_LE_INT16(bufPos + bufPerso + 29);
729 			WRITE_LE_UINT16(_vm->_animMan->_animBqe[idx]._data + 20, READ_LE_INT16(bufPos + bufPerso + 25));
730 			WRITE_LE_UINT16(_vm->_animMan->_animBqe[idx]._data + 22, READ_LE_INT16(bufPos + bufPerso + 27));
731 			WRITE_LE_UINT16(_vm->_animMan->_animBqe[idx]._data + 24, bqeVal);
732 			WRITE_LE_UINT16(_vm->_animMan->_animBqe[idx]._data + 26, READ_LE_INT16(bufPos + bufPerso + 31));
733 			_vm->_animMan->_animBqe[idx]._data[28] = bufPerso[bufPos + 33];
734 			_vm->_animMan->_animBqe[idx]._data[29] = bufPerso[bufPos + 34];
735 			byte *bqeCurData = _vm->_animMan->_animBqe[idx]._data + 20;
736 			const byte *curBufPerso = bufPos + bufPerso + 25;
737 			for (int i = 1; i < 5000; i++) {
738 				bqeCurData += 10;
739 				curBufPerso += 10;
740 				if (!bqeVal)
741 					break;
742 				bqeVal = READ_LE_INT16(curBufPerso + 4);
743 				WRITE_LE_UINT16(bqeCurData, READ_LE_INT16(curBufPerso));
744 				WRITE_LE_UINT16(bqeCurData + 2, READ_LE_INT16(curBufPerso + 2));
745 				WRITE_LE_UINT16(bqeCurData + 4, bqeVal);
746 				WRITE_LE_UINT16(bqeCurData + 6, READ_LE_INT16(curBufPerso + 6));
747 				bqeCurData[8] = curBufPerso[8];
748 				bqeCurData[9] = curBufPerso[9];
749 			}
750 			result = true;
751 		}
752 		if (READ_BE_UINT24(&bufPerso[bufPos]) == MKTAG24('F', 'I', 'N'))
753 			result = true;
754 
755 		if (result)
756 			break;
757 	}
758 
759 	return result;
760 }
761 
handleAnswer(int zone,int verb)762 void TalkManager::handleAnswer(int zone, int verb) {
763 	byte zoneObj = zone;
764 	byte verbObj = verb;
765 
766 	bool outerLoopFl;
767 	byte *ptr = NULL;
768 	do {
769 		outerLoopFl = false;
770 		bool tagFound = false;
771 		if (_vm->_globals->_answerBuffer == NULL)
772 			return;
773 
774 		byte *curAnswerBuf = _vm->_globals->_answerBuffer;
775 		for (;;) {
776 			if (READ_BE_UINT24(curAnswerBuf) == MKTAG24('F', 'I', 'N'))
777 				return;
778 			if (READ_BE_UINT24(curAnswerBuf) == MKTAG24('C', 'O', 'D')) {
779 				if (curAnswerBuf[3] == zoneObj && curAnswerBuf[4] == verbObj)
780 					tagFound = true;
781 			}
782 			if (!tagFound)
783 				curAnswerBuf++;
784 			else
785 				break;
786 		}
787 
788 		// 'COD' tag found
789 		curAnswerBuf += 5;
790 		ptr = _vm->_globals->allocMemory(620);
791 		assert(ptr);
792 		memset(ptr, 0, 620);
793 		uint16 curAnswerIdx = 0;
794 		int idx = 0;
795 		bool innerLoopCond = false;
796 		do {
797 			tagFound = false;
798 			if (READ_BE_UINT16(&curAnswerBuf[curAnswerIdx]) == MKTAG16('F', 'C')) {
799 				++idx;
800 				assert(idx < (620 / 20));
801 
802 				byte *answerBuf = (ptr + 20 * idx);
803 				uint16 anwerIdx = 0;
804 				do {
805 					assert(anwerIdx < 20);
806 					answerBuf[anwerIdx++] = curAnswerBuf[curAnswerIdx++];
807 					if (READ_BE_UINT16(&curAnswerBuf[curAnswerIdx]) == MKTAG16('F', 'F')) {
808 						tagFound = true;
809 						answerBuf[anwerIdx] = 'F';
810 						answerBuf[anwerIdx + 1] = 'F';
811 						++curAnswerIdx;
812 					}
813 				} while (!tagFound);
814 			}
815 			if (!tagFound) {
816 				uint32 signature24 = READ_BE_UINT24(&curAnswerBuf[curAnswerIdx]);
817 				if (signature24 == MKTAG24('C', 'O', 'D') || signature24 == MKTAG24('F', 'I', 'N'))
818 					innerLoopCond = true;
819 			}
820 			curAnswerBuf += curAnswerIdx + 1;
821 			curAnswerIdx = 0;
822 		} while (!innerLoopCond);
823 		innerLoopCond = false;
824 		int lastOpcodeResult = 1;
825 		do {
826 			int opcodeType = _vm->_script->handleOpcode(ptr + 20 * lastOpcodeResult);
827 			if (opcodeType == -1 || _vm->shouldQuit())
828 				return;
829 
830 			if (opcodeType == 2)
831 				// GOTO
832 				lastOpcodeResult =  _vm->_script->handleGoto(ptr + 20 * lastOpcodeResult);
833 			else if (opcodeType == 3)
834 				// IF
835 				lastOpcodeResult =  _vm->_script->handleIf(ptr, lastOpcodeResult);
836 
837 			if (lastOpcodeResult == -1)
838 				error("Invalid IFF function");
839 
840 			if (opcodeType == 1 || opcodeType == 4)
841 				// Already handled opcode or END IF
842 				++lastOpcodeResult;
843 			else if (!opcodeType || opcodeType == 5)
844 				// EXIT
845 				innerLoopCond = true;
846 			else if (opcodeType == 6) {
847 				// JUMP
848 				_vm->_globals->freeMemory(ptr);
849 				zoneObj = _vm->_objectsMan->_jumpZone;
850 				verbObj = _vm->_objectsMan->_jumpVerb;
851 				outerLoopFl = true;
852 				break;
853 			}
854 		} while (!innerLoopCond);
855 	} while (outerLoopFl);
856 	_vm->_globals->freeMemory(ptr);
857 	_vm->_globals->_saveData->_data[svLastZoneNum] = 0;
858 	return;
859 }
860 
handleForestAnswser(int zone,int verb)861 void TalkManager::handleForestAnswser(int zone, int verb) {
862 	int indx = 0;
863 	if (verb != 5 || _vm->_globals->_saveData->_data[svLastObjectIndex] != 4)
864 		return;
865 
866 	if (zone == 22 || zone == 23) {
867 		_vm->_objectsMan->setFlipSprite(0, false);
868 		_vm->_objectsMan->setSpriteIndex(0, 62);
869 		_vm->_objectsMan->showSpecialActionAnimationWithFlip(_vm->_objectsMan->_forestSprite, "2,3,4,5,6,7,8,9,10,11,12,-1,", 4, false);
870 		if (zone == 22) {
871 			_vm->_objectsMan->lockAnimX(6, _vm->_objectsMan->getBobPosX(3));
872 			_vm->_objectsMan->lockAnimX(8, _vm->_objectsMan->getBobPosX(3));
873 		} else { // zone == 23
874 			_vm->_objectsMan->lockAnimX(6, _vm->_objectsMan->getBobPosX(4));
875 			_vm->_objectsMan->lockAnimX(8, _vm->_objectsMan->getBobPosX(4));
876 		}
877 		_vm->_objectsMan->stopBobAnimation(3);
878 		_vm->_objectsMan->stopBobAnimation(4);
879 		_vm->_objectsMan->setBobAnimation(6);
880 		_vm->_soundMan->playSample(1);
881 		_vm->_objectsMan->showSpecialActionAnimation(_vm->_objectsMan->_forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 4);
882 		do {
883 			_vm->_events->refreshScreenAndEvents();
884 		} while (_vm->_objectsMan->getBobAnimDataIdx(6) < 12);
885 		_vm->_objectsMan->stopBobAnimation(6);
886 		_vm->_objectsMan->setBobAnimation(8);
887 
888 		switch (_vm->_globals->_screenId) {
889 		case 35:
890 			indx = 201;
891 			break;
892 		case 36:
893 			indx = 203;
894 			break;
895 		case 37:
896 			indx = 205;
897 			break;
898 		case 38:
899 			indx = 207;
900 			break;
901 		case 39:
902 			indx = 209;
903 			break;
904 		case 40:
905 			indx = 211;
906 			break;
907 		case 41:
908 			indx = 213;
909 			break;
910 		}
911 		_vm->_globals->_saveData->_data[indx] = 2;
912 		_vm->_linesMan->disableZone(22);
913 		_vm->_linesMan->disableZone(23);
914 	} else if (zone == 20 || zone == 21) {
915 		_vm->_objectsMan->setFlipSprite(0, true);
916 		_vm->_objectsMan->setSpriteIndex(0, 62);
917 		_vm->_objectsMan->showSpecialActionAnimationWithFlip(_vm->_objectsMan->_forestSprite, "2,3,4,5,6,7,8,9,10,11,12,-1,", 4, true);
918 		if (zone == 20) {
919 			_vm->_objectsMan->lockAnimX(5, _vm->_objectsMan->getBobPosX(1));
920 			_vm->_objectsMan->lockAnimX(7, _vm->_objectsMan->getBobPosX(1));
921 		} else { // zone == 21
922 			_vm->_objectsMan->lockAnimX(5, _vm->_objectsMan->getBobPosX(2));
923 			_vm->_objectsMan->lockAnimX(7, _vm->_objectsMan->getBobPosX(2));
924 		}
925 		_vm->_objectsMan->stopBobAnimation(1);
926 		_vm->_objectsMan->stopBobAnimation(2);
927 		_vm->_objectsMan->setBobAnimation(5);
928 		_vm->_soundMan->playSample(1);
929 		_vm->_objectsMan->showSpecialActionAnimation(_vm->_objectsMan->_forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 4);
930 		do {
931 			_vm->_events->refreshScreenAndEvents();
932 		} while (_vm->_objectsMan->getBobAnimDataIdx(5) < 12);
933 		_vm->_objectsMan->stopBobAnimation(5);
934 		_vm->_objectsMan->setBobAnimation(7);
935 		switch (_vm->_globals->_screenId) {
936 		case 35:
937 			indx = 200;
938 			break;
939 		case 36:
940 			indx = 202;
941 			break;
942 		case 37:
943 			indx = 204;
944 			break;
945 		case 38:
946 			indx = 206;
947 			break;
948 		case 39:
949 			indx = 208;
950 			break;
951 		case 40:
952 			indx = 210;
953 			break;
954 		case 41:
955 			indx = 212;
956 			break;
957 		}
958 		_vm->_globals->_saveData->_data[indx] = 2;
959 		_vm->_linesMan->disableZone(21);
960 		_vm->_linesMan->disableZone(20);
961 	}
962 }
963 
animateObject(const Common::String & filename)964 void TalkManager::animateObject(const Common::String &filename) {
965 	_vm->_fontMan->hideText(5);
966 	_vm->_fontMan->hideText(9);
967 	_vm->_events->refreshScreenAndEvents();
968 	_vm->_graphicsMan->_scrollStatus = 1;
969 	_vm->_linesMan->clearAllZones();
970 	_vm->_linesMan->resetLines();
971 	_vm->_objectsMan->resetHidingItems();
972 
973 	for (int i = 0; i <= 44; i++)
974 		_vm->_linesMan->_bobZone[i] = 0;
975 
976 	_vm->_objectsMan->_zoneNum = -1;
977 	_vm->_events->_mouseCursorId = 4;
978 	_vm->_events->changeMouseCursor(0);
979 	bool fileFoundFl = false;
980 	_characterBuffer = _vm->_fileIO->searchCat(filename, RES_PER, fileFoundFl);
981 	_characterSize = _vm->_fileIO->_catalogSize;
982 	if (!fileFoundFl) {
983 		_characterBuffer = _vm->_fileIO->loadFile(filename);
984 		_characterSize = _vm->_fileIO->fileSize(filename);
985 	}
986 	Common::String screenFilename;
987 	Common::String spriteFilename;
988 	Common::String curScreenFilename;
989 	getStringFromBuffer(40, spriteFilename, (const char *)_characterBuffer);
990 	getStringFromBuffer(0, screenFilename, (const char *)_characterBuffer);
991 	getStringFromBuffer(20, curScreenFilename, (const char *)_characterBuffer);
992 
993 	if (curScreenFilename == "NULL")
994 		curScreenFilename = Common::String::format("IM%d", _vm->_globals->_screenId);
995 
996 	fileFoundFl = false;
997 	_characterSprite = _vm->_fileIO->searchCat(spriteFilename, RES_SAN, fileFoundFl);
998 	if (!fileFoundFl)
999 		_characterSprite = _vm->_objectsMan->loadSprite(spriteFilename);
1000 	else
1001 		_characterSprite = _vm->_objectsMan->loadSprite("RES_SAN.RES");
1002 
1003 	_vm->_graphicsMan->backupScreen();
1004 
1005 	if (!_vm->_graphicsMan->_lineNbr)
1006 		_vm->_graphicsMan->_scrollOffset = 0;
1007 	_vm->_graphicsMan->displayScreen(true);
1008 	_paletteBufferIdx = 20 * READ_LE_INT16((uint16 *)_characterBuffer + 42) + 110;
1009 	_vm->_graphicsMan->displayScreen(true);
1010 	_vm->_objectsMan->_charactersEnabledFl = true;
1011 	searchCharacterPalette(_paletteBufferIdx, true);
1012 	startCharacterAnim0(_paletteBufferIdx, false);
1013 	byte *oldAnswerBufferPtr = _vm->_globals->_answerBuffer;
1014 	_vm->_globals->_answerBuffer = NULL;
1015 	_vm->_globals->_freezeCharacterFl = true;
1016 	_vm->_objectsMan->loadLinkFile(screenFilename);
1017 	_vm->_objectsMan->_charactersEnabledFl = true;
1018 	_vm->_globals->_actionMoveTo = false;
1019 	_vm->_objectsMan->_zoneNum = -1;
1020 	initCharacterAnim();
1021 	dialogAnim();
1022 	dialogWait();
1023 	_vm->_graphicsMan->initScreen(screenFilename, 2, true);
1024 	_vm->_globals->_freezeCharacterFl = true;
1025 	_vm->_objectsMan->_forceZoneFl = true;
1026 	_vm->_objectsMan->_zoneNum = -1;
1027 	do {
1028 		int mouseButton = _vm->_events->getMouseButton();
1029 		if (mouseButton == 1)
1030 			_vm->_objectsMan->handleLeftButton();
1031 		else if (mouseButton == 2)
1032 			_vm->_objectsMan->handleRightButton();
1033 
1034 		_vm->_linesMan->checkZone();
1035 		if (_vm->_globals->_actionMoveTo)
1036 			_vm->_objectsMan->paradise();
1037 		_vm->_events->refreshScreenAndEvents();
1038 	} while (!_vm->_globals->_exitId);
1039 	dialogEndTalk();
1040 	dialogTalk();
1041 	clearCharacterAnim();
1042 	clearCharacterAnim();
1043 	_vm->_globals->_introSpeechOffFl = false;
1044 	_characterBuffer = _vm->_globals->freeMemory(_characterBuffer);
1045 	_characterSprite = _vm->_globals->freeMemory(_characterSprite);
1046 	_vm->_graphicsMan->displayScreen(false);
1047 	_vm->_linesMan->clearAllZones();
1048 	_vm->_linesMan->resetLines();
1049 	_vm->_objectsMan->resetHidingItems();
1050 	for (int i = 0; i <= 44; i++)
1051 		_vm->_linesMan->_bobZone[i] = 0;
1052 
1053 	_vm->_globals->freeMemory(_vm->_globals->_answerBuffer);
1054 	_vm->_globals->_answerBuffer = oldAnswerBufferPtr;
1055 	_vm->_objectsMan->_disableFl = true;
1056 	_vm->_objectsMan->loadLinkFile(curScreenFilename);
1057 	_vm->_graphicsMan->initScreen(curScreenFilename, 2, true);
1058 	_vm->_objectsMan->_disableFl = false;
1059 	_vm->_globals->_freezeCharacterFl = false;
1060 	if (_vm->_globals->_exitId == 101)
1061 		_vm->_globals->_exitId = 0;
1062 
1063 	_vm->_graphicsMan->restoreScreen();
1064 
1065 	_vm->_objectsMan->_charactersEnabledFl = false;
1066 	_vm->_events->_mouseCursorId = 4;
1067 	_vm->_events->changeMouseCursor(4);
1068 	_vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
1069 
1070 	if (!_vm->getIsDemo())
1071 		_vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
1072 
1073 	_vm->_graphicsMan->initColorTable(145, 150, _vm->_graphicsMan->_palette);
1074 	_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
1075 	_vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_backBuffer, _vm->_events->_startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
1076 	_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
1077 	memcpy(_vm->_graphicsMan->_frontBuffer, _vm->_graphicsMan->_backBuffer, 614399);
1078 	_vm->_globals->_disableInventFl = false;
1079 	_vm->_graphicsMan->updateScreen();
1080 	for (int i = 0; i <= 4; i++)
1081 		_vm->_events->refreshScreenAndEvents();
1082 	_vm->_graphicsMan->_scrollStatus = 0;
1083 }
1084 
1085 } // End of namespace Hopkins
1086