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 	// WORKAROUND for bug #12635 ("KYRA: Missing subtitle(also in original game)")
810 	// This is a script bug that seems to be present in early English talkie versions, but
811 	// not in later versions (e. g. German talkie). Unfortunately it seems to have made its
812 	// way into several fan translations (e.g. Hebrew, Spanish), since these were based on
813 	// the bugged English version. The opcodes have to be rearranged a bit...
814 	if (_flags.isTalkie && !scumm_strnicmp("POTION.EMC", _scriptClick.dataPtr->filename, 12)) {
815 		assert(_scriptClick.dataPtr->dataSize >= 0x99E);
816 		uint16 *loc = &_scriptClick.dataPtr->data[0x4CA];
817 		if (*loc == 0x4e35) {
818 			for (int i = 0; i < 4; ++i)
819 				SWAP(loc[i], loc[i + 1]);
820 		}
821 	}
822 
823 	if (!_emc->start(&_scriptClick, 2))
824 		error("Could not start script function 2 of scene script");
825 
826 	_scriptClick.regs[7] = brandonAlive;
827 
828 	while (_emc->isValid(&_scriptClick))
829 		_emc->run(&_scriptClick);
830 
831 	setTextFadeTimerCountdown(-1);
832 
833 	if (_currentCharacter->sceneId == 210) {
834 		if (_itemInHand != kItemNone)
835 			magicOutMouseItem(2, -1);
836 
837 		_screen->hideMouse();
838 		for (int i = 0; i < 10; ++i) {
839 			if (_currentCharacter->inventoryItems[i] != kItemNone)
840 				magicOutMouseItem(2, i);
841 		}
842 		_screen->showMouse();
843 	}
844 }
845 
handleSceneChange(int xpos,int ypos,int unk1,int frameReset)846 int KyraEngine_LoK::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
847 	if (queryGameFlag(0xEF))
848 		unk1 = 0;
849 
850 	int sceneId = _currentCharacter->sceneId;
851 	_pathfinderFlag = 0;
852 
853 	if (xpos < 12) {
854 		if (_roomTable[sceneId].westExit != 0xFFFF) {
855 			xpos = 12;
856 			ypos = _sceneExits.westYPos;
857 			_pathfinderFlag = 7;
858 		}
859 	} else if (xpos >= 308) {
860 		if (_roomTable[sceneId].eastExit != 0xFFFF) {
861 			xpos = 307;
862 			ypos = _sceneExits.eastYPos;
863 			_pathfinderFlag = 13;
864 		}
865 	}
866 
867 	if (ypos <= (_northExitHeight & 0xFF) + 2) {
868 		if (_roomTable[sceneId].northExit != 0xFFFF) {
869 			xpos = _sceneExits.northXPos;
870 			ypos = _northExitHeight & 0xFF;
871 			_pathfinderFlag = 14;
872 		}
873 	} else if (ypos >= 136) {
874 		if (_roomTable[sceneId].southExit != 0xFFFF) {
875 			xpos = _sceneExits.southXPos;
876 			ypos = 136;
877 			_pathfinderFlag = 11;
878 		}
879 	}
880 
881 	int temp = xpos - _currentCharacter->x1;
882 	if (ABS(temp) < 4) {
883 		temp = ypos - _currentCharacter->y1;
884 		if (ABS(temp) < 2)
885 			return 0;
886 	}
887 
888 	int x = (int16)(_currentCharacter->x1 & 0xFFFC);
889 	int y = (int16)(_currentCharacter->y1 & 0xFFFE);
890 	xpos = (int16)(xpos & 0xFFFC);
891 	ypos = (int16)(ypos & 0xFFFE);
892 
893 	int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
894 	_pathfinderFlag = 0;
895 
896 	if (ret >= _lastFindWayRet)
897 		_lastFindWayRet = ret;
898 
899 	if (ret == 0x7D00 || ret == 0)
900 		return 0;
901 
902 	return processSceneChange(_movFacingTable, unk1, frameReset);
903 }
904 
processSceneChange(int * table,int unk1,int frameReset)905 int KyraEngine_LoK::processSceneChange(int *table, int unk1, int frameReset) {
906 	if (queryGameFlag(0xEF))
907 		unk1 = 0;
908 
909 	int *tableStart = table;
910 	_sceneChangeState = 0;
911 	_loopFlag2 = 0;
912 	bool running = true;
913 	int returnValue = 0;
914 	uint32 nextFrame = 0;
915 
916 	while (running) {
917 		bool forceContinue = false;
918 		switch (*table) {
919 		case 0: case 1: case 2:
920 		case 3: case 4: case 5:
921 		case 6: case 7:
922 			_currentCharacter->facing = getOppositeFacingDirection(*table);
923 			break;
924 
925 		case 8:
926 			forceContinue = true;
927 			running = false;
928 			break;
929 
930 		default:
931 			++table;
932 			forceContinue = true;
933 		}
934 
935 		returnValue = changeScene(_currentCharacter->facing);
936 		if (returnValue)
937 			running = false;
938 
939 		if (unk1) {
940 			if (skipFlag()) {
941 				resetSkipFlag(false);
942 				running = false;
943 				_sceneChangeState = 1;
944 			}
945 		}
946 
947 		if (forceContinue || !running)
948 			continue;
949 
950 		int temp = 0;
951 		if (table == tableStart || table[1] == 8)
952 			temp = setCharacterPosition(0, 0);
953 		else
954 			temp = setCharacterPosition(0, table);
955 
956 		if (temp)
957 			++table;
958 
959 		nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis();
960 		while (_system->getMillis() < nextFrame) {
961 			_timer->update();
962 
963 			if (_currentCharacter->sceneId == 210) {
964 				updateKyragemFading();
965 				if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
966 					*table = 8;
967 					running = false;
968 					break;
969 				}
970 			}
971 
972 			if ((nextFrame - _system->getMillis()) >= 10)
973 				delay(10, true);
974 		}
975 	}
976 
977 	if (frameReset && !(_brandonStatusBit & 2))
978 		_currentCharacter->currentAnimFrame = 7;
979 
980 	_animator->animRefreshNPC(0);
981 	_animator->updateAllObjectShapes();
982 	return returnValue;
983 }
984 
changeScene(int facing)985 int KyraEngine_LoK::changeScene(int facing) {
986 	if (queryGameFlag(0xEF)) {
987 		if (_currentCharacter->sceneId == 5)
988 			return 0;
989 	}
990 
991 	int xpos = _charAddXPosTable[facing] + _currentCharacter->x1;
992 	int ypos = _charAddYPosTable[facing] + _currentCharacter->y1;
993 
994 	if (xpos >= 12 && xpos <= 308) {
995 		if (!lineIsPassable(xpos, ypos))
996 			return false;
997 	}
998 
999 	if (_exitListPtr) {
1000 		int16 *ptr = _exitListPtr;
1001 		// this loop should be only entered one time, seems to be some hack in the original
1002 		while (true) {
1003 			if (*ptr == -1)
1004 				break;
1005 
1006 			if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
1007 				ptr += 10;
1008 				break;
1009 			}
1010 
1011 			_brandonPosX = ptr[6];
1012 			_brandonPosY = ptr[7];
1013 			uint16 sceneId = ptr[5];
1014 			facing = ptr[4];
1015 			int unk1 = ptr[8];
1016 			int unk2 = ptr[9];
1017 
1018 			if (sceneId == 0xFFFF) {
1019 				switch (facing) {
1020 				case 0:
1021 					sceneId = _roomTable[_currentCharacter->sceneId].northExit;
1022 					break;
1023 
1024 				case 2:
1025 					sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
1026 					break;
1027 
1028 				case 4:
1029 					sceneId = _roomTable[_currentCharacter->sceneId].southExit;
1030 					break;
1031 
1032 				case 6:
1033 					sceneId = _roomTable[_currentCharacter->sceneId].westExit;
1034 					break;
1035 
1036 				default:
1037 					break;
1038 				}
1039 			}
1040 
1041 			_currentCharacter->facing = facing;
1042 			_animator->animRefreshNPC(0);
1043 			_animator->updateAllObjectShapes();
1044 			enterNewScene(sceneId, facing, unk1, unk2, 0);
1045 			resetGameFlag(0xEE);
1046 			return 1;
1047 		}
1048 	}
1049 
1050 	int returnValue = 0;
1051 	facing = 0;
1052 
1053 	if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
1054 		facing = 0;
1055 		returnValue = 1;
1056 	}
1057 
1058 	if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
1059 		facing = 2;
1060 		returnValue = 1;
1061 	}
1062 
1063 	if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
1064 		facing = 4;
1065 		returnValue = 1;
1066 	}
1067 
1068 	if (xpos <= 12 || _currentCharacter->y1 <= 12) {
1069 		facing = 6;
1070 		returnValue = 1;
1071 	}
1072 
1073 	if (!returnValue)
1074 		return 0;
1075 
1076 	uint16 sceneId = 0xFFFF;
1077 	switch (facing) {
1078 	case 0:
1079 		sceneId = _roomTable[_currentCharacter->sceneId].northExit;
1080 		break;
1081 
1082 	case 2:
1083 		sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
1084 		break;
1085 
1086 	case 4:
1087 		sceneId = _roomTable[_currentCharacter->sceneId].southExit;
1088 		break;
1089 
1090 	default:
1091 		sceneId = _roomTable[_currentCharacter->sceneId].westExit;
1092 	}
1093 
1094 	if (sceneId == 0xFFFF)
1095 		return 0;
1096 
1097 	enterNewScene(sceneId, facing, 1, 1, 0);
1098 	return returnValue;
1099 }
1100 
setCharactersInDefaultScene()1101 void KyraEngine_LoK::setCharactersInDefaultScene() {
1102 	static const uint32 defaultSceneTable[][4] = {
1103 		{ 0xFFFF, 0x0004, 0x0003, 0xFFFF },
1104 		{ 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
1105 		{ 0xFFFF, 0x001D, 0x0021, 0xFFFF },
1106 		{ 0xFFFF, 0x0000, 0x0000, 0xFFFF }
1107 	};
1108 
1109 	for (int i = 1; i < 5; ++i) {
1110 		Character *cur = &_characterList[i];
1111 		//cur->field_20 = 0;
1112 
1113 		const uint32 *curTable = defaultSceneTable[i - 1];
1114 		cur->sceneId = curTable[0];
1115 
1116 		if (cur->sceneId == _currentCharacter->sceneId)
1117 			//++cur->field_20;
1118 			cur->sceneId = curTable[1/*cur->field_20*/];
1119 
1120 		//cur->field_23 = curTable[cur->field_20+1];
1121 	}
1122 }
1123 
setCharactersPositions(int character)1124 void KyraEngine_LoK::setCharactersPositions(int character) {
1125 	static const uint16 initXPosTable[] = {
1126 		0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
1127 		0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
1128 	};
1129 	static const uint8 initYPosTable[] = {
1130 		0x00, 0xA2, 0x00, 0x42, 0x00,
1131 		0x67, 0x67, 0x60, 0x5A, 0x71,
1132 		0x76
1133 	};
1134 
1135 	assert(character < ARRAYSIZE(initXPosTable));
1136 	Character *edit = &_characterList[character];
1137 	edit->x1 = edit->x2 = initXPosTable[character];
1138 	edit->y1 = edit->y2 = initYPosTable[character];
1139 }
1140 
1141 #pragma mark -
1142 #pragma mark - Pathfinder
1143 #pragma mark -
1144 
findWay(int x,int y,int toX,int toY,int * moveTable,int moveTableSize)1145 int KyraEngine_LoK::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
1146 	int ret = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize);
1147 	if (ret == 0x7D00)
1148 		return 0;
1149 	return getMoveTableSize(moveTable);
1150 }
1151 
lineIsPassable(int x,int y)1152 bool KyraEngine_LoK::lineIsPassable(int x, int y) {
1153 	if (queryGameFlag(0xEF)) {
1154 		if (_currentCharacter->sceneId == 5)
1155 			return true;
1156 	}
1157 
1158 	if (_pathfinderFlag & 2) {
1159 		if (x >= 312)
1160 			return false;
1161 	}
1162 
1163 	if (_pathfinderFlag & 4) {
1164 		if (y >= 136)
1165 			return false;
1166 	}
1167 
1168 	if (_pathfinderFlag & 8) {
1169 		if (x < 8)
1170 			return false;
1171 	}
1172 
1173 	if (_pathfinderFlag2) {
1174 		if (x <= 8 || x >= 312)
1175 			return true;
1176 		if (y < (_northExitHeight & 0xFF) || y > 135)
1177 			return true;
1178 	}
1179 
1180 	if (y > 137)
1181 		return false;
1182 
1183 	if (y < 0)
1184 		y = 0;
1185 
1186 	int ypos = 8;
1187 	if (_scaleMode) {
1188 		ypos = (_scaleTable[y] >> 5) + 1;
1189 		if (8 < ypos)
1190 			ypos = 8;
1191 	}
1192 
1193 	x -= (ypos >> 1);
1194 
1195 	int xpos = x;
1196 	int xtemp = xpos + ypos - 1;
1197 	if (x < 0)
1198 		xpos = 0;
1199 
1200 	if (xtemp > 319)
1201 		xtemp = 319;
1202 
1203 	for (; xpos < xtemp; ++xpos) {
1204 		if (!_screen->getShapeFlag1(xpos, y))
1205 			return false;
1206 	}
1207 	return true;
1208 }
1209 
1210 #pragma mark -
1211 
setupZanthiaPalette(int pal)1212 void KyraEngine_LoK::setupZanthiaPalette(int pal) {
1213 	uint8 r, g, b;
1214 
1215 	switch (pal - 17) {
1216 	case 0:
1217 		// 0x88F
1218 		r = 33;
1219 		g = 33;
1220 		b = 63;
1221 		break;
1222 
1223 	case 1:
1224 		// 0x00F
1225 		r = 0;
1226 		g = 0;
1227 		b = 63;
1228 		break;
1229 
1230 	case 2:
1231 		// 0xF88
1232 		r = 63;
1233 		g = 33;
1234 		b = 33;
1235 		break;
1236 
1237 	case 3:
1238 		// 0xF00
1239 		r = 63;
1240 		g = 0;
1241 		b = 0;
1242 		break;
1243 
1244 	case 4:
1245 		// 0xFF9
1246 		r = 63;
1247 		g = 63;
1248 		b = 37;
1249 		break;
1250 
1251 	case 5:
1252 		// 0xFF1
1253 		r = 63;
1254 		g = 63;
1255 		b = 4;
1256 		break;
1257 
1258 	default:
1259 		// 0xFFF
1260 		r = 63;
1261 		g = 63;
1262 		b = 63;
1263 	}
1264 
1265 	_screen->getPalette(4)[12 * 3 + 0] = r;
1266 	_screen->getPalette(4)[12 * 3 + 1] = g;
1267 	_screen->getPalette(4)[12 * 3 + 2] = b;
1268 }
1269 
1270 #pragma mark -
1271 
setupSceneResource(int sceneId)1272 void KyraEngine_LoK::setupSceneResource(int sceneId) {
1273 	if (!_flags.isTalkie)
1274 		return;
1275 
1276 	if (_currentRoom != 0xFFFF) {
1277 		assert(_currentRoom < _roomTableSize);
1278 		int tableId = _roomTable[_currentRoom].nameIndex;
1279 		assert(tableId < _roomFilenameTableSize);
1280 
1281 		// unload our old room
1282 		char file[64];
1283 		strcpy(file, _roomFilenameTable[tableId]);
1284 		strcat(file, ".VRM");
1285 		_res->unloadPakFile(file);
1286 
1287 		strcpy(file, _roomFilenameTable[tableId]);
1288 		strcat(file, ".PAK");
1289 		_res->unloadPakFile(file);
1290 
1291 		strcpy(file, _roomFilenameTable[tableId]);
1292 		strcat(file, ".APK");
1293 		_res->unloadPakFile(file);
1294 	}
1295 
1296 	assert(sceneId < _roomTableSize);
1297 	int tableId = _roomTable[sceneId].nameIndex;
1298 	assert(tableId < _roomFilenameTableSize);
1299 
1300 	// load our new room
1301 	char file[64];
1302 	strcpy(file, _roomFilenameTable[tableId]);
1303 	strcat(file, ".VRM");
1304 	if (_res->exists(file))
1305 		_res->loadPakFile(file);
1306 
1307 	strcpy(file, _roomFilenameTable[tableId]);
1308 	strcat(file, ".PAK");
1309 	if (_res->exists(file))
1310 		_res->loadPakFile(file);
1311 
1312 	strcpy(file, _roomFilenameTable[tableId]);
1313 	strcat(file, ".APK");
1314 	if (_res->exists(file))
1315 		_res->loadPakFile(file);
1316 }
1317 
1318 } // End of namespace Kyra
1319