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 "kyra/engine/kyra_lok.h"
24 #include "kyra/resource/resource.h"
25 #include "kyra/sound/sound.h"
26 #include "kyra/engine/sprites.h"
27 #include "kyra/graphics/animator_lok.h"
28 #include "kyra/engine/timer.h"
29 
30 #include "common/system.h"
31 
32 namespace Kyra {
33 
enterNewScene(int sceneId,int facing,int unk1,int unk2,int brandonAlive)34 void KyraEngine_LoK::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
35 	int unkVar1 = 1;
36 	_screen->hideMouse();
37 
38 	// TODO: Check how the original handled sfx still playing
39 	_sound->stopAllSoundEffects();
40 
41 	if (_flags.platform == Common::kPlatformFMTowns) {
42 		int newSfxFile = -1;
43 		if (_currentCharacter->sceneId == 7 && sceneId == 24)
44 			newSfxFile = 2;
45 		else if (_currentCharacter->sceneId == 25 && sceneId == 109)
46 			newSfxFile = 3;
47 		else if (_currentCharacter->sceneId == 120 && sceneId == 37)
48 			newSfxFile = 4;
49 		else if (_currentCharacter->sceneId == 52 && sceneId == 199)
50 			newSfxFile = 5;
51 		else if (_currentCharacter->sceneId == 37 && sceneId == 120)
52 			newSfxFile = 3;
53 		else if (_currentCharacter->sceneId == 109 && sceneId == 25)
54 			newSfxFile = 2;
55 		else if (_currentCharacter->sceneId == 24 && sceneId == 7)
56 			newSfxFile = 1;
57 
58 		if (newSfxFile != -1) {
59 			_curSfxFile = newSfxFile;
60 			_sound->loadSoundFile(_curSfxFile);
61 		}
62 	}
63 
64 	switch (_currentCharacter->sceneId) {
65 	case 1:
66 		if (sceneId == 0) {
67 			moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
68 			unkVar1 = 0;
69 		}
70 		break;
71 
72 	case 3:
73 		if (sceneId == 2) {
74 			moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
75 			unkVar1 = 0;
76 		}
77 		break;
78 
79 	case 26:
80 		if (sceneId == 27) {
81 			moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
82 			unkVar1 = 0;
83 		}
84 		break;
85 
86 	case 44:
87 		if (sceneId == 45) {
88 			moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
89 			unkVar1 = 0;
90 		}
91 		break;
92 
93 	default:
94 		break;
95 	}
96 
97 	if (unkVar1 && unk1) {
98 		int xpos = _currentCharacter->x1;
99 		int ypos = _currentCharacter->y1;
100 		switch (facing) {
101 		case 0:
102 			ypos = _currentCharacter->y1 - 6;
103 			break;
104 
105 		case 2:
106 			xpos = 336;
107 			break;
108 
109 		case 4:
110 			ypos = 143;
111 			break;
112 
113 		case 6:
114 			xpos = -16;
115 			break;
116 
117 		default:
118 			break;
119 		}
120 
121 		moveCharacterToPos(0, facing, xpos, ypos);
122 	}
123 
124 	for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i)
125 		_movieObjects[i]->close();
126 
127 	if (!brandonAlive) {
128 		_emc->init(&_scriptClick, &_scriptClickData);
129 		_emc->start(&_scriptClick, 5);
130 		while (_emc->isValid(&_scriptClick))
131 			_emc->run(&_scriptClick);
132 	}
133 
134 	memset(_entranceMouseCursorTracks, 0xFF, sizeof(_entranceMouseCursorTracks));
135 	_currentCharacter->sceneId = sceneId;
136 
137 	assert(sceneId < _roomTableSize);
138 	assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
139 
140 	Room *currentRoom = &_roomTable[sceneId];
141 
142 	setupSceneResource(sceneId);
143 
144 	_currentRoom = sceneId;
145 
146 	int tableId = _roomTable[sceneId].nameIndex;
147 	char fileNameBuffer[32];
148 	strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
149 	strcat(fileNameBuffer, ".DAT");
150 	_sprites->loadDat(fileNameBuffer, _sceneExits);
151 	_sprites->setupSceneAnims();
152 	_emc->unload(&_scriptClickData);
153 	loadSceneMsc();
154 
155 	_walkBlockNorth = currentRoom->northExit;
156 	_walkBlockEast = currentRoom->eastExit;
157 	_walkBlockSouth = currentRoom->southExit;
158 	_walkBlockWest = currentRoom->westExit;
159 
160 	if (_walkBlockNorth == 0xFFFF)
161 		_screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF) + 3);
162 	if (_walkBlockEast == 0xFFFF)
163 		_screen->blockOutRegion(312, 0, 8, 139);
164 	if (_walkBlockSouth == 0xFFFF)
165 		_screen->blockOutRegion(0, 135, 320, 8);
166 	if (_walkBlockWest == 0xFFFF)
167 		_screen->blockOutRegion(0, 0, 8, 139);
168 
169 	if (!brandonAlive)
170 		updatePlayerItemsForScene();
171 
172 	startSceneScript(brandonAlive);
173 	setupSceneItems();
174 
175 	initSceneData(facing, unk2, brandonAlive);
176 
177 	setTextFadeTimerCountdown(-1);
178 	_scriptClick.regs[3] = 1;
179 
180 	_loopFlag2 = 0;
181 	_screen->showMouse();
182 	if (!brandonAlive)
183 		seq_poisonDeathNow(0);
184 	updateMousePointer(true);
185 	_changedScene = true;
186 }
187 
transcendScenes(int roomIndex,int roomName)188 void KyraEngine_LoK::transcendScenes(int roomIndex, int roomName) {
189 	assert(roomIndex < _roomTableSize);
190 
191 	if (_flags.isTalkie) {
192 		char file[32];
193 		assert(roomIndex < _roomTableSize);
194 		int tableId = _roomTable[roomIndex].nameIndex;
195 		assert(tableId < _roomFilenameTableSize);
196 		strcpy(file, _roomFilenameTable[tableId]);
197 		strcat(file, ".VRM");
198 		_res->unloadPakFile(file);
199 	}
200 
201 	_roomTable[roomIndex].nameIndex = roomName;
202 	_unkScreenVar2 = 1;
203 	_unkScreenVar3 = 1;
204 	_unkScreenVar1 = 0;
205 	_brandonPosX = _currentCharacter->x1;
206 	_brandonPosY = _currentCharacter->y1;
207 	enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
208 	_unkScreenVar1 = 1;
209 	_unkScreenVar2 = 0;
210 	_unkScreenVar3 = 0;
211 }
212 
setSceneFile(int roomIndex,int roomName)213 void KyraEngine_LoK::setSceneFile(int roomIndex, int roomName) {
214 	assert(roomIndex < _roomTableSize);
215 	_roomTable[roomIndex].nameIndex = roomName;
216 }
217 
moveCharacterToPos(int character,int facing,int xpos,int ypos)218 void KyraEngine_LoK::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
219 	Character *ch = &_characterList[character];
220 	ch->facing = facing;
221 	_screen->hideMouse();
222 	xpos = (int16)(xpos & 0xFFFC);
223 	ypos = (int16)(ypos & 0xFFFE);
224 	_timer->disable(19);
225 	_timer->disable(14);
226 	_timer->disable(18);
227 	uint32 nextFrame = 0;
228 
229 	switch (facing) {
230 	case 0:
231 		while (ypos < ch->y1) {
232 			nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
233 			setCharacterPositionWithUpdate(character);
234 			delayUntil(nextFrame, true);
235 		}
236 		break;
237 
238 	case 2:
239 		while (ch->x1 < xpos) {
240 			nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
241 			setCharacterPositionWithUpdate(character);
242 			delayUntil(nextFrame, true);
243 		}
244 		break;
245 
246 	case 4:
247 		while (ypos > ch->y1) {
248 			nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
249 			setCharacterPositionWithUpdate(character);
250 			delayUntil(nextFrame, true);
251 		}
252 		break;
253 
254 	case 6:
255 		while (ch->x1 > xpos) {
256 			nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
257 			setCharacterPositionWithUpdate(character);
258 			delayUntil(nextFrame, true);
259 		}
260 		break;
261 
262 	default:
263 		break;
264 	}
265 
266 	_timer->enable(19);
267 	_timer->enable(14);
268 	_timer->enable(18);
269 	_screen->showMouse();
270 }
271 
setCharacterPositionWithUpdate(int character)272 void KyraEngine_LoK::setCharacterPositionWithUpdate(int character) {
273 	setCharacterPosition(character, 0);
274 	_sprites->updateSceneAnims();
275 	_timer->update();
276 	_animator->updateAllObjectShapes();
277 	updateTextFade();
278 
279 	if (_currentCharacter->sceneId == 210)
280 		updateKyragemFading();
281 }
282 
setCharacterPosition(int character,int * facingTable)283 int KyraEngine_LoK::setCharacterPosition(int character, int *facingTable) {
284 	if (character == 0) {
285 		_currentCharacter->x1 += _charAddXPosTable[_currentCharacter->facing];
286 		_currentCharacter->y1 += _charAddYPosTable[_currentCharacter->facing];
287 		setCharacterPositionHelper(0, facingTable);
288 		return 1;
289 	} else {
290 		_characterList[character].x1 += _charAddXPosTable[_characterList[character].facing];
291 		_characterList[character].y1 += _charAddYPosTable[_characterList[character].facing];
292 		if (_characterList[character].sceneId == _currentCharacter->sceneId)
293 			setCharacterPositionHelper(character, 0);
294 	}
295 	return 0;
296 }
297 
setCharacterPositionHelper(int character,int * facingTable)298 void KyraEngine_LoK::setCharacterPositionHelper(int character, int *facingTable) {
299 	Character *ch = &_characterList[character];
300 	++ch->currentAnimFrame;
301 	int facing = ch->facing;
302 	if (facingTable) {
303 		if (*facingTable != *(facingTable - 1)) {
304 			if (*(facingTable - 1) == *(facingTable + 1)) {
305 				facing = getOppositeFacingDirection(*(facingTable - 1));
306 				*facingTable = *(facingTable - 1);
307 			}
308 		}
309 	}
310 
311 	if (facing == 0) {
312 		++_characterFacingZeroCount[character];
313 	} else {
314 		bool resetTables = false;
315 		if (facing != 7) {
316 			if (facing - 1 != 0) {
317 				if (facing != 4) {
318 					if (facing == 3 || facing == 5) {
319 						if (_characterFacingFourCount[character] > 2)
320 							facing = 4;
321 						resetTables = true;
322 					}
323 				} else {
324 					++_characterFacingFourCount[character];
325 				}
326 			} else {
327 				if (_characterFacingZeroCount[character] > 2)
328 					facing = 0;
329 				resetTables = true;
330 			}
331 		} else {
332 			if (_characterFacingZeroCount[character] > 2)
333 				facing = 0;
334 			resetTables = true;
335 		}
336 
337 		if (resetTables) {
338 			_characterFacingZeroCount[character] = 0;
339 			_characterFacingFourCount[character] = 0;
340 		}
341 	}
342 
343 	static const uint16 maxAnimationFrame[] = {
344 		0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
345 		0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
346 		0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
347 		0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
348 		0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
349 		0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
350 		0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
351 	};
352 
353 	if (facing == 0) {
354 		if (maxAnimationFrame[36 + character] > ch->currentAnimFrame)
355 			ch->currentAnimFrame = maxAnimationFrame[36 + character];
356 		if (maxAnimationFrame[30 + character] < ch->currentAnimFrame)
357 			ch->currentAnimFrame = maxAnimationFrame[36 + character];
358 	} else if (facing == 4) {
359 		if (maxAnimationFrame[18 + character] > ch->currentAnimFrame)
360 			ch->currentAnimFrame = maxAnimationFrame[18 + character];
361 		if (maxAnimationFrame[12 + character] < ch->currentAnimFrame)
362 			ch->currentAnimFrame = maxAnimationFrame[18 + character];
363 	} else {
364 		if (maxAnimationFrame[18 + character] < ch->currentAnimFrame)
365 			ch->currentAnimFrame = maxAnimationFrame[30 + character];
366 		if (maxAnimationFrame[character] == ch->currentAnimFrame)
367 			ch->currentAnimFrame = maxAnimationFrame[6 + character];
368 		if (maxAnimationFrame[character] < ch->currentAnimFrame)
369 			ch->currentAnimFrame = maxAnimationFrame[6 + character] + 2;
370 	}
371 
372 	if (character == 0 && (_brandonStatusBit & 0x10))
373 		ch->currentAnimFrame = 88;
374 
375 	_animator->animRefreshNPC(character);
376 }
377 
loadSceneMsc()378 void KyraEngine_LoK::loadSceneMsc() {
379 	assert(_currentCharacter->sceneId < _roomTableSize);
380 	int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
381 	assert(tableId < _roomFilenameTableSize);
382 	char fileNameBuffer[32];
383 	strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
384 	strcat(fileNameBuffer, ".MSC");
385 	_screen->fillRect(0, 0, 319, 199, 0, 5);
386 	_res->exists(fileNameBuffer, true);
387 	_screen->loadBitmap(fileNameBuffer, 3, 5, 0);
388 }
389 
startSceneScript(int brandonAlive)390 void KyraEngine_LoK::startSceneScript(int brandonAlive) {
391 	assert(_currentCharacter->sceneId < _roomTableSize);
392 	int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
393 	assert(tableId < _roomFilenameTableSize);
394 	char fileNameBuffer[32];
395 	strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
396 	strcat(fileNameBuffer, ".CPS");
397 	_screen->clearPage(3);
398 	_res->exists(fileNameBuffer, true);
399 	// FIXME: check this hack for amiga version
400 	_screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? &_screen->getPalette(0) : 0));
401 	_sprites->loadSceneShapes();
402 	_exitListPtr = 0;
403 
404 	_scaleMode = 1;
405 	for (int i = 0; i < 145; ++i)
406 		_scaleTable[i] = 256;
407 
408 	clearNoDropRects();
409 	_emc->init(&_scriptClick, &_scriptClickData);
410 	strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
411 	strcat(fileNameBuffer, ".EMC");
412 	_res->exists(fileNameBuffer, true);
413 	_emc->unload(&_scriptClickData);
414 	_emc->load(fileNameBuffer, &_scriptClickData, &_opcodes);
415 	_emc->start(&_scriptClick, 0);
416 	_scriptClick.regs[0] = _currentCharacter->sceneId;
417 	_scriptClick.regs[7] = brandonAlive;
418 
419 	while (_emc->isValid(&_scriptClick))
420 		_emc->run(&_scriptClick);
421 }
422 
initSceneData(int facing,int unk1,int brandonAlive)423 void KyraEngine_LoK::initSceneData(int facing, int unk1, int brandonAlive) {
424 	int16 xpos2 = 0;
425 	int setFacing = 1;
426 
427 	int16 xpos = 0, ypos = 0;
428 
429 	if (_brandonPosX == -1 && _brandonPosY == -1) {
430 		switch (facing + 1) {
431 		case 0:
432 			xpos = ypos = -1;
433 			break;
434 
435 		case 1: case 2: case 8:
436 			xpos = _sceneExits.southXPos;
437 			ypos = _sceneExits.southYPos;
438 			break;
439 
440 		case 3:
441 			xpos = _sceneExits.westXPos;
442 			ypos = _sceneExits.westYPos;
443 			break;
444 
445 		case 4: case 5: case 6:
446 			xpos = _sceneExits.northXPos;
447 			ypos = _sceneExits.northYPos;
448 			break;
449 
450 		case 7:
451 			xpos = _sceneExits.eastXPos;
452 			ypos = _sceneExits.eastYPos;
453 			break;
454 
455 		default:
456 			break;
457 		}
458 
459 		if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos)
460 			ypos = (_northExitHeight & 0xFF) + 4;
461 		if (xpos >= 308)
462 			xpos = 304;
463 		if ((uint8)(_northExitHeight >> 8) - 2 <= ypos)
464 			ypos = (_northExitHeight >> 8) - 4;
465 		if (xpos <= 12)
466 			xpos = 16;
467 	}
468 
469 	if (_brandonPosX > -1)
470 		xpos = _brandonPosX;
471 	if (_brandonPosY > -1)
472 		ypos = _brandonPosY;
473 
474 	int16 ypos2 = 0;
475 	if (_brandonPosX > -1 && _brandonPosY > -1) {
476 		switch (_currentCharacter->sceneId) {
477 		case 1:
478 			_currentCharacter->x1 = xpos;
479 			_currentCharacter->x2 = xpos;
480 			_currentCharacter->y1 = ypos;
481 			_currentCharacter->y2 = ypos;
482 			facing = 4;
483 			xpos2 = 192;
484 			ypos2 = 104;
485 			setFacing = 0;
486 			unk1 = 1;
487 			break;
488 
489 		case 3:
490 			_currentCharacter->x1 = xpos;
491 			_currentCharacter->x2 = xpos;
492 			_currentCharacter->y1 = ypos;
493 			_currentCharacter->y2 = ypos;
494 			facing = 2;
495 			xpos2 = 204;
496 			ypos2 = 94;
497 			setFacing = 0;
498 			unk1 = 1;
499 			break;
500 
501 		case 26:
502 			_currentCharacter->x1 = xpos;
503 			_currentCharacter->x2 = xpos;
504 			_currentCharacter->y1 = ypos;
505 			_currentCharacter->y2 = ypos;
506 			facing = 2;
507 			xpos2 = 192;
508 			ypos2 = 128;
509 			setFacing = 0;
510 			unk1 = 1;
511 			break;
512 
513 		case 44:
514 			_currentCharacter->x1 = xpos;
515 			_currentCharacter->x2 = xpos;
516 			_currentCharacter->y1 = ypos;
517 			_currentCharacter->y2 = ypos;
518 			facing = 6;
519 			xpos2 = 156;
520 			ypos2 = 96;
521 			setFacing = 0;
522 			unk1 = 1;
523 			break;
524 
525 		case 37:
526 			_currentCharacter->x1 = xpos;
527 			_currentCharacter->x2 = xpos;
528 			_currentCharacter->y1 = ypos;
529 			_currentCharacter->y2 = ypos;
530 			facing = 2;
531 			xpos2 = 148;
532 			ypos2 = 114;
533 			setFacing = 0;
534 			unk1 = 1;
535 			break;
536 
537 		default:
538 			break;
539 		}
540 	}
541 
542 	_brandonPosX = _brandonPosY = -1;
543 
544 	if (unk1 && setFacing) {
545 		ypos2 = ypos;
546 		xpos2 = xpos;
547 		switch (facing) {
548 		case 0:
549 			ypos = 142;
550 			break;
551 
552 		case 2:
553 			xpos = -16;
554 			break;
555 
556 		case 4:
557 			ypos = (uint8)(_northExitHeight & 0xFF) - 4;
558 			break;
559 
560 		case 6:
561 			xpos = 336;
562 			break;
563 
564 		default:
565 			break;
566 		}
567 	}
568 
569 	xpos2 = (int16)(xpos2 & 0xFFFC);
570 	ypos2 = (int16)(ypos2 & 0xFFFE);
571 	xpos = (int16)(xpos & 0xFFFC);
572 	ypos = (int16)(ypos & 0xFFFE);
573 	_currentCharacter->facing = facing;
574 	_currentCharacter->x1 = xpos;
575 	_currentCharacter->x2 = xpos;
576 	_currentCharacter->y1 = ypos;
577 	_currentCharacter->y2 = ypos;
578 
579 	initSceneObjectList(brandonAlive);
580 
581 	if (unk1 && brandonAlive == 0)
582 		moveCharacterToPos(0, facing, xpos2, ypos2);
583 
584 	_scriptClick.regs[4] = _itemInHand;
585 	_scriptClick.regs[7] = brandonAlive;
586 	_emc->start(&_scriptClick, 3);
587 	while (_emc->isValid(&_scriptClick))
588 		_emc->run(&_scriptClick);
589 }
590 
initSceneObjectList(int brandonAlive)591 void KyraEngine_LoK::initSceneObjectList(int brandonAlive) {
592 	for (int i = 0; i < 28; ++i)
593 		_animator->actors()[i].active = 0;
594 
595 	int startAnimFrame = 0;
596 
597 	Animator_LoK::AnimObject *curAnimState = _animator->actors();
598 	curAnimState->active = 1;
599 	curAnimState->drawY = _currentCharacter->y1;
600 	curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame];
601 	curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
602 	startAnimFrame = _currentCharacter->currentAnimFrame - 7;
603 	int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
604 	int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
605 
606 	if (_scaleMode) {
607 		curAnimState->x1 = _currentCharacter->x1;
608 		curAnimState->y1 = _currentCharacter->y1;
609 
610 		_animator->_brandonScaleX = _scaleTable[_currentCharacter->y1];
611 		_animator->_brandonScaleY = _scaleTable[_currentCharacter->y1];
612 
613 		curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
614 		curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
615 	} else {
616 		curAnimState->x1 = _currentCharacter->x1 + xOffset;
617 		curAnimState->y1 = _currentCharacter->y1 + yOffset;
618 	}
619 
620 	curAnimState->x2 = curAnimState->x1;
621 	curAnimState->y2 = curAnimState->y1;
622 	curAnimState->refreshFlag = 1;
623 	curAnimState->bkgdChangeFlag = 1;
624 	_animator->clearQueue();
625 	_animator->addObjectToQueue(curAnimState);
626 
627 	int listAdded = 0;
628 	int addedObjects = 1;
629 
630 	for (int i = 1; i < 5; ++i) {
631 		Character *ch = &_characterList[i];
632 		curAnimState = &_animator->actors()[addedObjects];
633 		if (ch->sceneId != _currentCharacter->sceneId) {
634 			curAnimState->active = 0;
635 			curAnimState->refreshFlag = 0;
636 			curAnimState->bkgdChangeFlag = 0;
637 			++addedObjects;
638 			continue;
639 		}
640 
641 		curAnimState->drawY = ch->y1;
642 		curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame];
643 		curAnimState->animFrameNumber = ch->currentAnimFrame;
644 		startAnimFrame = ch->currentAnimFrame - 7;
645 		xOffset = _defaultShapeTable[startAnimFrame].xOffset;
646 		yOffset = _defaultShapeTable[startAnimFrame].yOffset;
647 		if (_scaleMode) {
648 			curAnimState->x1 = ch->x1;
649 			curAnimState->y1 = ch->y1;
650 
651 			_animator->_brandonScaleX = _scaleTable[ch->y1];
652 			_animator->_brandonScaleY = _scaleTable[ch->y1];
653 
654 			curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
655 			curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
656 		} else {
657 			curAnimState->x1 = ch->x1 + xOffset;
658 			curAnimState->y1 = ch->y1 + yOffset;
659 		}
660 		curAnimState->x2 = curAnimState->x1;
661 		curAnimState->y2 = curAnimState->y1;
662 		curAnimState->active = 1;
663 		curAnimState->refreshFlag = 1;
664 		curAnimState->bkgdChangeFlag = 1;
665 
666 		if (ch->facing >= 1 && ch->facing <= 3)
667 			curAnimState->flags |= 1;
668 		else if (ch->facing >= 5 && ch->facing <= 7)
669 			curAnimState->flags &= 0xFFFFFFFE;
670 
671 		_animator->addObjectToQueue(curAnimState);
672 
673 		++addedObjects;
674 		++listAdded;
675 		if (listAdded < 2)
676 			i = 5;
677 	}
678 
679 	for (int i = 0; i < 11; ++i) {
680 		curAnimState = &_animator->sprites()[i];
681 
682 		if (_sprites->_anims[i].play) {
683 			curAnimState->active = 1;
684 			curAnimState->refreshFlag = 1;
685 			curAnimState->bkgdChangeFlag = 1;
686 		} else {
687 			curAnimState->active = 0;
688 			curAnimState->refreshFlag = 0;
689 			curAnimState->bkgdChangeFlag = 0;
690 		}
691 		curAnimState->height = _sprites->_anims[i].height;
692 		curAnimState->height2 = _sprites->_anims[i].height2;
693 		curAnimState->width = _sprites->_anims[i].width + 1;
694 		curAnimState->width2 = _sprites->_anims[i].width2;
695 		curAnimState->drawY = _sprites->_anims[i].drawY;
696 		curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
697 		curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
698 		curAnimState->background = _sprites->_anims[i].background;
699 		curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
700 
701 		curAnimState->disable = _sprites->_anims[i].disable;
702 
703 		if (_sprites->_anims[i].unk2)
704 			curAnimState->flags = 0x800;
705 		else
706 			curAnimState->flags = 0;
707 
708 		if (_sprites->_anims[i].flipX)
709 			curAnimState->flags |= 0x1;
710 
711 		_animator->addObjectToQueue(curAnimState);
712 	}
713 
714 	for (int i = 0; i < 12; ++i) {
715 		curAnimState = &_animator->items()[i];
716 		Room *curRoom = &_roomTable[_currentCharacter->sceneId];
717 		byte curItem = curRoom->itemsTable[i];
718 		if (curItem != 0xFF) {
719 			curAnimState->drawY = curRoom->itemsYPos[i];
720 			curAnimState->sceneAnimPtr = _shapes[216 + curItem];
721 			curAnimState->animFrameNumber = (int16)0xFFFF;
722 			curAnimState->y1 = curRoom->itemsYPos[i];
723 			curAnimState->x1 = curRoom->itemsXPos[i];
724 
725 			curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
726 			curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
727 
728 			curAnimState->x2 = curAnimState->x1;
729 			curAnimState->y2 = curAnimState->y1;
730 
731 			curAnimState->active = 1;
732 			curAnimState->refreshFlag = 1;
733 			curAnimState->bkgdChangeFlag = 1;
734 
735 			_animator->addObjectToQueue(curAnimState);
736 		} else {
737 			curAnimState->active = 0;
738 			curAnimState->refreshFlag = 0;
739 			curAnimState->bkgdChangeFlag = 0;
740 		}
741 	}
742 
743 	_animator->preserveAnyChangedBackgrounds();
744 	curAnimState = _animator->actors();
745 	curAnimState->bkgdChangeFlag = 1;
746 	curAnimState->refreshFlag = 1;
747 	for (int i = 1; i < 28; ++i) {
748 		curAnimState = &_animator->objects()[i];
749 		if (curAnimState->active) {
750 			curAnimState->bkgdChangeFlag = 1;
751 			curAnimState->refreshFlag = 1;
752 		}
753 	}
754 	_animator->restoreAllObjectBackgrounds();
755 	_animator->preserveAnyChangedBackgrounds();
756 	_animator->prepDrawAllObjects();
757 	initSceneScreen(brandonAlive);
758 	_animator->copyChangedObjectsForward(0);
759 }
760 
initSceneScreen(int brandonAlive)761 void KyraEngine_LoK::initSceneScreen(int brandonAlive) {
762 	if (_flags.platform == Common::kPlatformAmiga) {
763 		if (_unkScreenVar1 && !queryGameFlag(0xF0)) {
764 			_screen->getPalette(2).clear();
765 			if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3))
766 				_screen->setScreenPalette(_screen->getPalette(2));
767 		}
768 
769 		if (_unkScreenVar2 == 1)
770 			_screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
771 		else
772 			_screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK);
773 
774 		if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
775 			if (_currentCharacter->sceneId == 45 && _cauldronState)
776 				_screen->getPalette(0).copy(_screen->getPalette(4), 12, 1);
777 
778 			if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1))
779 				_screen->copyPalette(0, 10);
780 
781 			_screen->setScreenPalette(_screen->getPalette(0));
782 		}
783 	} else {
784 		if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
785 			for (int i = 0; i < 60; ++i) {
786 				uint16 col = _screen->getPalette(0)[684 + i];
787 				col += _screen->getPalette(1)[684 + i] << 1;
788 				col >>= 2;
789 				_screen->getPalette(0)[684 + i] = col;
790 			}
791 			_screen->setScreenPalette(_screen->getPalette(0));
792 		}
793 
794 		if (_unkScreenVar2 == 1)
795 			_screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
796 		else
797 			_screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
798 
799 		if (_unkScreenVar1 && _paletteChanged) {
800 			if (!queryGameFlag(0xA0)) {
801 				_screen->getPalette(0).copy(_screen->getPalette(1), 228, 20);
802 				_screen->setScreenPalette(_screen->getPalette(0));
803 			} else {
804 				_screen->getPalette(0).clear();
805 			}
806 		}
807 	}
808 
809 	if (!_emc->start(&_scriptClick, 2))
810 		error("Could not start script function 2 of scene script");
811 
812 	_scriptClick.regs[7] = brandonAlive;
813 
814 	while (_emc->isValid(&_scriptClick))
815 		_emc->run(&_scriptClick);
816 
817 	setTextFadeTimerCountdown(-1);
818 
819 	if (_currentCharacter->sceneId == 210) {
820 		if (_itemInHand != kItemNone)
821 			magicOutMouseItem(2, -1);
822 
823 		_screen->hideMouse();
824 		for (int i = 0; i < 10; ++i) {
825 			if (_currentCharacter->inventoryItems[i] != kItemNone)
826 				magicOutMouseItem(2, i);
827 		}
828 		_screen->showMouse();
829 	}
830 }
831 
handleSceneChange(int xpos,int ypos,int unk1,int frameReset)832 int KyraEngine_LoK::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
833 	if (queryGameFlag(0xEF))
834 		unk1 = 0;
835 
836 	int sceneId = _currentCharacter->sceneId;
837 	_pathfinderFlag = 0;
838 
839 	if (xpos < 12) {
840 		if (_roomTable[sceneId].westExit != 0xFFFF) {
841 			xpos = 12;
842 			ypos = _sceneExits.westYPos;
843 			_pathfinderFlag = 7;
844 		}
845 	} else if (xpos >= 308) {
846 		if (_roomTable[sceneId].eastExit != 0xFFFF) {
847 			xpos = 307;
848 			ypos = _sceneExits.eastYPos;
849 			_pathfinderFlag = 13;
850 		}
851 	}
852 
853 	if (ypos <= (_northExitHeight & 0xFF) + 2) {
854 		if (_roomTable[sceneId].northExit != 0xFFFF) {
855 			xpos = _sceneExits.northXPos;
856 			ypos = _northExitHeight & 0xFF;
857 			_pathfinderFlag = 14;
858 		}
859 	} else if (ypos >= 136) {
860 		if (_roomTable[sceneId].southExit != 0xFFFF) {
861 			xpos = _sceneExits.southXPos;
862 			ypos = 136;
863 			_pathfinderFlag = 11;
864 		}
865 	}
866 
867 	int temp = xpos - _currentCharacter->x1;
868 	if (ABS(temp) < 4) {
869 		temp = ypos - _currentCharacter->y1;
870 		if (ABS(temp) < 2)
871 			return 0;
872 	}
873 
874 	int x = (int16)(_currentCharacter->x1 & 0xFFFC);
875 	int y = (int16)(_currentCharacter->y1 & 0xFFFE);
876 	xpos = (int16)(xpos & 0xFFFC);
877 	ypos = (int16)(ypos & 0xFFFE);
878 
879 	int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
880 	_pathfinderFlag = 0;
881 
882 	if (ret >= _lastFindWayRet)
883 		_lastFindWayRet = ret;
884 
885 	if (ret == 0x7D00 || ret == 0)
886 		return 0;
887 
888 	return processSceneChange(_movFacingTable, unk1, frameReset);
889 }
890 
processSceneChange(int * table,int unk1,int frameReset)891 int KyraEngine_LoK::processSceneChange(int *table, int unk1, int frameReset) {
892 	if (queryGameFlag(0xEF))
893 		unk1 = 0;
894 
895 	int *tableStart = table;
896 	_sceneChangeState = 0;
897 	_loopFlag2 = 0;
898 	bool running = true;
899 	int returnValue = 0;
900 	uint32 nextFrame = 0;
901 
902 	while (running) {
903 		bool forceContinue = false;
904 		switch (*table) {
905 		case 0: case 1: case 2:
906 		case 3: case 4: case 5:
907 		case 6: case 7:
908 			_currentCharacter->facing = getOppositeFacingDirection(*table);
909 			break;
910 
911 		case 8:
912 			forceContinue = true;
913 			running = false;
914 			break;
915 
916 		default:
917 			++table;
918 			forceContinue = true;
919 		}
920 
921 		returnValue = changeScene(_currentCharacter->facing);
922 		if (returnValue)
923 			running = false;
924 
925 		if (unk1) {
926 			if (skipFlag()) {
927 				resetSkipFlag(false);
928 				running = false;
929 				_sceneChangeState = 1;
930 			}
931 		}
932 
933 		if (forceContinue || !running)
934 			continue;
935 
936 		int temp = 0;
937 		if (table == tableStart || table[1] == 8)
938 			temp = setCharacterPosition(0, 0);
939 		else
940 			temp = setCharacterPosition(0, table);
941 
942 		if (temp)
943 			++table;
944 
945 		nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis();
946 		while (_system->getMillis() < nextFrame) {
947 			_timer->update();
948 
949 			if (_currentCharacter->sceneId == 210) {
950 				updateKyragemFading();
951 				if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
952 					*table = 8;
953 					running = false;
954 					break;
955 				}
956 			}
957 
958 			if ((nextFrame - _system->getMillis()) >= 10)
959 				delay(10, true);
960 		}
961 	}
962 
963 	if (frameReset && !(_brandonStatusBit & 2))
964 		_currentCharacter->currentAnimFrame = 7;
965 
966 	_animator->animRefreshNPC(0);
967 	_animator->updateAllObjectShapes();
968 	return returnValue;
969 }
970 
changeScene(int facing)971 int KyraEngine_LoK::changeScene(int facing) {
972 	if (queryGameFlag(0xEF)) {
973 		if (_currentCharacter->sceneId == 5)
974 			return 0;
975 	}
976 
977 	int xpos = _charAddXPosTable[facing] + _currentCharacter->x1;
978 	int ypos = _charAddYPosTable[facing] + _currentCharacter->y1;
979 
980 	if (xpos >= 12 && xpos <= 308) {
981 		if (!lineIsPassable(xpos, ypos))
982 			return false;
983 	}
984 
985 	if (_exitListPtr) {
986 		int16 *ptr = _exitListPtr;
987 		// this loop should be only entered one time, seems to be some hack in the original
988 		while (true) {
989 			if (*ptr == -1)
990 				break;
991 
992 			if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
993 				ptr += 10;
994 				break;
995 			}
996 
997 			_brandonPosX = ptr[6];
998 			_brandonPosY = ptr[7];
999 			uint16 sceneId = ptr[5];
1000 			facing = ptr[4];
1001 			int unk1 = ptr[8];
1002 			int unk2 = ptr[9];
1003 
1004 			if (sceneId == 0xFFFF) {
1005 				switch (facing) {
1006 				case 0:
1007 					sceneId = _roomTable[_currentCharacter->sceneId].northExit;
1008 					break;
1009 
1010 				case 2:
1011 					sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
1012 					break;
1013 
1014 				case 4:
1015 					sceneId = _roomTable[_currentCharacter->sceneId].southExit;
1016 					break;
1017 
1018 				case 6:
1019 					sceneId = _roomTable[_currentCharacter->sceneId].westExit;
1020 					break;
1021 
1022 				default:
1023 					break;
1024 				}
1025 			}
1026 
1027 			_currentCharacter->facing = facing;
1028 			_animator->animRefreshNPC(0);
1029 			_animator->updateAllObjectShapes();
1030 			enterNewScene(sceneId, facing, unk1, unk2, 0);
1031 			resetGameFlag(0xEE);
1032 			return 1;
1033 		}
1034 	}
1035 
1036 	int returnValue = 0;
1037 	facing = 0;
1038 
1039 	if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
1040 		facing = 0;
1041 		returnValue = 1;
1042 	}
1043 
1044 	if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
1045 		facing = 2;
1046 		returnValue = 1;
1047 	}
1048 
1049 	if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
1050 		facing = 4;
1051 		returnValue = 1;
1052 	}
1053 
1054 	if (xpos <= 12 || _currentCharacter->y1 <= 12) {
1055 		facing = 6;
1056 		returnValue = 1;
1057 	}
1058 
1059 	if (!returnValue)
1060 		return 0;
1061 
1062 	uint16 sceneId = 0xFFFF;
1063 	switch (facing) {
1064 	case 0:
1065 		sceneId = _roomTable[_currentCharacter->sceneId].northExit;
1066 		break;
1067 
1068 	case 2:
1069 		sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
1070 		break;
1071 
1072 	case 4:
1073 		sceneId = _roomTable[_currentCharacter->sceneId].southExit;
1074 		break;
1075 
1076 	default:
1077 		sceneId = _roomTable[_currentCharacter->sceneId].westExit;
1078 	}
1079 
1080 	if (sceneId == 0xFFFF)
1081 		return 0;
1082 
1083 	enterNewScene(sceneId, facing, 1, 1, 0);
1084 	return returnValue;
1085 }
1086 
setCharactersInDefaultScene()1087 void KyraEngine_LoK::setCharactersInDefaultScene() {
1088 	static const uint32 defaultSceneTable[][4] = {
1089 		{ 0xFFFF, 0x0004, 0x0003, 0xFFFF },
1090 		{ 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
1091 		{ 0xFFFF, 0x001D, 0x0021, 0xFFFF },
1092 		{ 0xFFFF, 0x0000, 0x0000, 0xFFFF }
1093 	};
1094 
1095 	for (int i = 1; i < 5; ++i) {
1096 		Character *cur = &_characterList[i];
1097 		//cur->field_20 = 0;
1098 
1099 		const uint32 *curTable = defaultSceneTable[i - 1];
1100 		cur->sceneId = curTable[0];
1101 
1102 		if (cur->sceneId == _currentCharacter->sceneId)
1103 			//++cur->field_20;
1104 			cur->sceneId = curTable[1/*cur->field_20*/];
1105 
1106 		//cur->field_23 = curTable[cur->field_20+1];
1107 	}
1108 }
1109 
setCharactersPositions(int character)1110 void KyraEngine_LoK::setCharactersPositions(int character) {
1111 	static const uint16 initXPosTable[] = {
1112 		0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
1113 		0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
1114 	};
1115 	static const uint8 initYPosTable[] = {
1116 		0x00, 0xA2, 0x00, 0x42, 0x00,
1117 		0x67, 0x67, 0x60, 0x5A, 0x71,
1118 		0x76
1119 	};
1120 
1121 	assert(character < ARRAYSIZE(initXPosTable));
1122 	Character *edit = &_characterList[character];
1123 	edit->x1 = edit->x2 = initXPosTable[character];
1124 	edit->y1 = edit->y2 = initYPosTable[character];
1125 }
1126 
1127 #pragma mark -
1128 #pragma mark - Pathfinder
1129 #pragma mark -
1130 
findWay(int x,int y,int toX,int toY,int * moveTable,int moveTableSize)1131 int KyraEngine_LoK::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
1132 	int ret = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize);
1133 	if (ret == 0x7D00)
1134 		return 0;
1135 	return getMoveTableSize(moveTable);
1136 }
1137 
lineIsPassable(int x,int y)1138 bool KyraEngine_LoK::lineIsPassable(int x, int y) {
1139 	if (queryGameFlag(0xEF)) {
1140 		if (_currentCharacter->sceneId == 5)
1141 			return true;
1142 	}
1143 
1144 	if (_pathfinderFlag & 2) {
1145 		if (x >= 312)
1146 			return false;
1147 	}
1148 
1149 	if (_pathfinderFlag & 4) {
1150 		if (y >= 136)
1151 			return false;
1152 	}
1153 
1154 	if (_pathfinderFlag & 8) {
1155 		if (x < 8)
1156 			return false;
1157 	}
1158 
1159 	if (_pathfinderFlag2) {
1160 		if (x <= 8 || x >= 312)
1161 			return true;
1162 		if (y < (_northExitHeight & 0xFF) || y > 135)
1163 			return true;
1164 	}
1165 
1166 	if (y > 137)
1167 		return false;
1168 
1169 	if (y < 0)
1170 		y = 0;
1171 
1172 	int ypos = 8;
1173 	if (_scaleMode) {
1174 		ypos = (_scaleTable[y] >> 5) + 1;
1175 		if (8 < ypos)
1176 			ypos = 8;
1177 	}
1178 
1179 	x -= (ypos >> 1);
1180 
1181 	int xpos = x;
1182 	int xtemp = xpos + ypos - 1;
1183 	if (x < 0)
1184 		xpos = 0;
1185 
1186 	if (xtemp > 319)
1187 		xtemp = 319;
1188 
1189 	for (; xpos < xtemp; ++xpos) {
1190 		if (!_screen->getShapeFlag1(xpos, y))
1191 			return false;
1192 	}
1193 	return true;
1194 }
1195 
1196 #pragma mark -
1197 
setupZanthiaPalette(int pal)1198 void KyraEngine_LoK::setupZanthiaPalette(int pal) {
1199 	uint8 r, g, b;
1200 
1201 	switch (pal - 17) {
1202 	case 0:
1203 		// 0x88F
1204 		r = 33;
1205 		g = 33;
1206 		b = 63;
1207 		break;
1208 
1209 	case 1:
1210 		// 0x00F
1211 		r = 0;
1212 		g = 0;
1213 		b = 63;
1214 		break;
1215 
1216 	case 2:
1217 		// 0xF88
1218 		r = 63;
1219 		g = 33;
1220 		b = 33;
1221 		break;
1222 
1223 	case 3:
1224 		// 0xF00
1225 		r = 63;
1226 		g = 0;
1227 		b = 0;
1228 		break;
1229 
1230 	case 4:
1231 		// 0xFF9
1232 		r = 63;
1233 		g = 63;
1234 		b = 37;
1235 		break;
1236 
1237 	case 5:
1238 		// 0xFF1
1239 		r = 63;
1240 		g = 63;
1241 		b = 4;
1242 		break;
1243 
1244 	default:
1245 		// 0xFFF
1246 		r = 63;
1247 		g = 63;
1248 		b = 63;
1249 	}
1250 
1251 	_screen->getPalette(4)[12 * 3 + 0] = r;
1252 	_screen->getPalette(4)[12 * 3 + 1] = g;
1253 	_screen->getPalette(4)[12 * 3 + 2] = b;
1254 }
1255 
1256 #pragma mark -
1257 
setupSceneResource(int sceneId)1258 void KyraEngine_LoK::setupSceneResource(int sceneId) {
1259 	if (!_flags.isTalkie)
1260 		return;
1261 
1262 	if (_currentRoom != 0xFFFF) {
1263 		assert(_currentRoom < _roomTableSize);
1264 		int tableId = _roomTable[_currentRoom].nameIndex;
1265 		assert(tableId < _roomFilenameTableSize);
1266 
1267 		// unload our old room
1268 		char file[64];
1269 		strcpy(file, _roomFilenameTable[tableId]);
1270 		strcat(file, ".VRM");
1271 		_res->unloadPakFile(file);
1272 
1273 		strcpy(file, _roomFilenameTable[tableId]);
1274 		strcat(file, ".PAK");
1275 		_res->unloadPakFile(file);
1276 
1277 		strcpy(file, _roomFilenameTable[tableId]);
1278 		strcat(file, ".APK");
1279 		_res->unloadPakFile(file);
1280 	}
1281 
1282 	assert(sceneId < _roomTableSize);
1283 	int tableId = _roomTable[sceneId].nameIndex;
1284 	assert(tableId < _roomFilenameTableSize);
1285 
1286 	// load our new room
1287 	char file[64];
1288 	strcpy(file, _roomFilenameTable[tableId]);
1289 	strcat(file, ".VRM");
1290 	if (_res->exists(file))
1291 		_res->loadPakFile(file);
1292 
1293 	strcpy(file, _roomFilenameTable[tableId]);
1294 	strcat(file, ".PAK");
1295 	if (_res->exists(file))
1296 		_res->loadPakFile(file);
1297 
1298 	strcpy(file, _roomFilenameTable[tableId]);
1299 	strcat(file, ".APK");
1300 	if (_res->exists(file))
1301 		_res->loadPakFile(file);
1302 }
1303 
1304 } // End of namespace Kyra
1305