/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "dragons/cutscene.h"
#include "dragons/dragons.h"
#include "dragons/actor.h"
#include "dragons/actorresource.h"
#include "dragons/background.h"
#include "dragons/inventory.h"
#include "dragons/cursor.h"
#include "dragons/dragonini.h"
#include "dragons/scene.h"
#include "dragons/screen.h"
#include "dragons/talk.h"

namespace Dragons {

CutScene::CutScene(DragonsEngine *vm): _vm(vm) {
	loadPalettes();
}

CutScene::~CutScene() {
	if (_palettes) {
		free(_palettes);
	}
}

void CutScene::scene1() {
	// TODO spcLoadScene1 knights around the table.
	bool isFlag10Set = _vm->isFlagSet(ENGINE_FLAG_10);

	DragonINI *flicker = _vm->_dragonINIResource->getFlickerRecord();

	_actor_80063514 = 0xb00;
	_vm->_dragonINIResource->setFlickerRecord(nullptr);

	_vm->setUnkFlags(ENGINE_UNK1_FLAG_2);
	_vm->fadeToBlack();
	_vm->clearFlags(ENGINE_FLAG_10);

	_vm->_inventory->setActorFlag400();
	_vm->_cursor->setActorFlag400();

//	scr_tilemap1_w = 0x28;
//	_actor_8006a3f0 = _actor_8006a3ec;

//	load_actor_file(0x81);
//	load_actor_file(0x7d);
//	load_actor_file(0x7e);
//	load_actor_file(0x8f);
//	load_actor_file(0xaa);
	_vm->setFlags(ENGINE_FLAG_20000);
	wideAngleEveryoneAtTable();
	_vm->waitForFrames(0x5a);
	closeUpShotOnActor(0xd3, 0, 0x233, 0x17a); //close up on king
	//playSoundFromTxtIndex(0x4e26);

	while (1) {	// In order to avoid gotos
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 4, 0, 0x4e26, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60); // cut to flicker
		//playSoundFromTxtIndex(0x4ea2);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 2, 0, 0x4ea2, 0x701) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd3, 0, 0x233, 0x17a); //close up on king
		//playSoundFromTxtIndex(0x4eec);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 5, 0, 0x4eec, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		wideAngleEveryoneAtTable();  // shot of whole room

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 4, 0, 0x5000, 0x2e01) == 2 ||
			_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_800830c0, 0x1d, 0x1c, 0x5074, 0x501) == 2 ||
			_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072df0, 9, 5, 0x511c, 0xc01) == 2 ||
			_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_800830c0, 0x1d, 0x1c, 0x5138, 0x501) == 2)
			break;

		closeUpShotOnActor(0xd7, 0, 0x312, 0x260); //close up on flame
		//playSoundFromTxtIndex(0x5152);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 2, 0, 0x5152, 0x3e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60); //close up flicker
		//playSoundFromTxtIndex(0x51fc);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 3, 0, 0x51fc, 0x701) == 2)
			break;

		_vm->playOrStopSound(0x8004);
		_vm->waitForFrames(0x28);
		_vm->playOrStopSound(0x8003);
		fadeScreenAndResetActor(_actor_80072de8);
		_actor_80063514 = _actor_80063514 | 0x40;
		fun_8003d8e8(0xd6, 0, 0x37a, 0x280);
		_actor_80072dec = _vm->_actorManager->loadActor(0xd5, 0, 0x2d6, 0xc6, 3); //load humans
		_actor_80072df0 = _vm->_actorManager->loadActor(0xd3, 2, 0x87, 199, 3);
		_vm->waitForFramesAllowSkip(4);
		_vm->fadeFromBlack();

		if (fun_8003dab8(0x52d6, 0, 0, 0x701, 1) == 2)
			break;

		_vm->clearAllText();
		//playSoundFromTxtIndex(0x530c);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 2, 0, 0x530c, 0x3c01) == 2)
			break;

		while (0x10 < _vm->_scene->_camera.x) {
			_vm->_scene->_camera.x = _vm->_scene->_camera.x + -0x10;
			_vm->waitForFrames(1);
		}

		_vm->_scene->_camera.x = 0;
		//playSoundFromTxtIndex(0x54dc);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072df0, 6, 2, 0x54dc, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		fadeScreenAndResetActor(_actor_80072dec);
		fadeScreenAndResetActor(_actor_80072df0);
		wideAngleEveryoneAtTable();

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072e08, 3, 2, 0x55d4, 0xc01) == 2)
			break;

		closeUpShotOnActor(0xd4, 0, 0x8a, 0); //close up chancellor
		//playSoundFromTxtIndex(0x562c);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 2, 0, 0x562c, 0xc01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		fun_8003d8e8(0xd6, 0, 0x37a, 0x280);
		_actor_80072dec = _vm->_actorManager->loadActor(0xd5, 4, 0x2d6, 0xc6, 3);
		_vm->waitForFramesAllowSkip(4);
		_vm->fadeFromBlack();

		if (fun_8003dab8(0x5780, 0x14, 0, 0xc01, 1) == 2)
			break;

		_actor_80063514 = _actor_80063514 | 0x40;
		fadeScreenAndResetActor(_actor_80072de8);
		fadeScreenAndResetActor(_actor_80072dec);
		closeUpShotOnActor(0xd7, 0, 0x312, 0x260); // close up flame
		//playSoundFromTxtIndex(0x581c);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 3, 0, 0x581c, 0x3e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd4, 0, 0x8a, 0); //close up chancellor
		//playSoundFromTxtIndex(0x5942);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 4, 0, 0x5942, 0xc01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd3, 2, 0x87, 0); // close up king
		//playSoundFromTxtIndex(0x5aaa);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 7, 2, 0x5aaa, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		fun_8003d8e8(0xd6, 0, 0x37a, 0x280);
		_actor_80072dec = _vm->_actorManager->loadActor(0xd5, 0, 0x2d6, 0xc6, 3);
		_vm->waitForFramesAllowSkip(4);
		_vm->fadeFromBlack();
		//playSoundFromTxtIndex(0x5afc);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 3, 0, 0x5afc, 0x3c01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		fadeScreenAndResetActor(_actor_80072dec);
		_actor_80063514 = _actor_80063514 & 0xffbf;
		closeUpKnightsAtTable(); // close up of knights at table.
		_vm->playOrStopSound(0x8003);
		//playSoundFromTxtIndex(0x5b96);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 8, 4, 0x5b96, 0xc01) == 2)
			break;

		//playSoundFromTxtIndex(0x5c4a);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 2, 0, 0x5c4a, 0x2e01) == 2)
			break;

		//playSoundFromTxtIndex(0x5dc8);
		_actor_80072df0->updateSequence(0xf);
		_actor_80072df4->updateSequence(0xd);
		_actor_80072df8->updateSequence(0xe);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 0xc, 4, 0x5dc8, 0xc01) == 2)
			break;

		_actor_80072df0->updateSequence(6);
		_actor_80072df4->updateSequence(0);
		_actor_80072df8->updateSequence(2);
		fun_8003d8e8(0xd3, 2, 0x28d, 0x250);
		_actor_80072dec = _vm->_actorManager->loadActor(0xd7, 0, 0x348, 199, 3);
		_vm->waitForFramesAllowSkip(4); // close up of king and flame
		_vm->fadeFromBlack();
		//playSoundFromTxtIndex(0x5ef2);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 4, 0, 0x5ef2, 0x3e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		fadeScreenAndResetActor(_actor_80072dec);
		closeUpShotOnActor(0xd3, 0, 0x233, 0x17a); // close up of king
		//playSoundFromTxtIndex(0x6000);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 8, 0, 0x6000, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpKnightsAtTable(); // close up knights at table
		//playSoundFromTxtIndex(0x7dcc);
		_actor_80072df0->updateSequence(0x13);
		_actor_80072df4->updateSequence(0x10);
		_actor_80072df8->updateSequence(0x11);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 0x12, 6, 0x7dcc, 0xc01) == 2)
			break;

		wideAngleEveryoneAtTable(); //whole room shot

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0x17, 0x16, 0x60ee, 0x701) == 2)
			break;

		closeUpKnightsAtTable();
		_actor_80072df0->updateSequence(6);
		_actor_80072df4->updateSequence(0);
		_actor_80072df8->updateSequence(2);
		_actor_80072dec->updateSequence(4);
		//playSoundFromTxtIndex(0x5de8);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072df8, 0xb, 2, 0x5de8, 0xc01) == 2)
			break;

		wideAngleEveryoneAtTable();
		_vm->playOrStopSound(1);
		_actor_80072df0->updateSequence(8);
		_actor_80072df4->updateSequence(0xd);
		_actor_80072df8->updateSequence(0x11);
		_actor_80072dfc->updateSequence(0x15);
		_actor_80072df0->waitUntilFlag8And4AreSet();
		_actor_80072df4->waitUntilFlag8And4AreSet();
		_actor_80072df8->waitUntilFlag8And4AreSet();
		_actor_80072dfc->waitUntilFlag8And4AreSet();
		// DisableVSyncEvent();
		// TODO load_actor_file(0x82);
		// EnableVSyncEvent();
		_vm->waitForFramesAllowSkip(0x3b);
		_vm->clearFlags(ENGINE_FLAG_20000);
		_vm->fadeToBlack();
		// DisableVSyncEvent();
		_vm->_scene->getScaleLayer()->clearAll();
		_vm->_scene->getScaleLayer()->setValue(0, 0, 17);
		_vm->_scene->getScaleLayer()->setValue(1, 199, 1);

		// EnableVSyncEvent();
		changeBackgroundPosition(2, 0);
		_vm->_actorManager->clearActorFlags(2);
		_actor_80072de8 = _vm->_actorManager->loadActor(0x82, 0, 0x60, 0x114, 1);
		_actor_80072dec = _vm->_actorManager->loadActor(0x82, 2, 0x91, 0x113, 1);
		_actor_80072df0 = _vm->_actorManager->loadActor(0x82, 1, 0xd0, 199, 1);
		_actor_80072df4 = _vm->_actorManager->loadActor(0x82, 3, 0xb6, 0x113, 1);
		_actor_80072df8 = _vm->_actorManager->loadActor(0x82, 4, 0x98, 0x40, 1);

		_actor_80072de8->setFlag(ACTOR_FLAG_100);
		_actor_80072de8->setFlag(ACTOR_FLAG_800);
		_actor_80072de8->setFlag(ACTOR_FLAG_8000);
		_actor_80072de8->_walkSpeed = 0x20000;
		_actor_80072de8->_priorityLayer = 3;

		_actor_80072dec->setFlag(ACTOR_FLAG_100);
		_actor_80072dec->setFlag(ACTOR_FLAG_800);
		_actor_80072dec->setFlag(ACTOR_FLAG_8000);
		_actor_80072dec->_walkSpeed = 0x18000;
		_actor_80072dec->_priorityLayer = 3;

		_actor_80072df0->setFlag(ACTOR_FLAG_100);
		_actor_80072df0->setFlag(ACTOR_FLAG_800);
		_actor_80072df0->setFlag(ACTOR_FLAG_8000);
		_actor_80072df0->_walkSpeed = 0x14000;
		_actor_80072df0->_priorityLayer = 3;

		_actor_80072df4->setFlag(ACTOR_FLAG_100);
		_actor_80072df4->setFlag(ACTOR_FLAG_800);
		_actor_80072df4->setFlag(ACTOR_FLAG_8000);
		_actor_80072df4->_walkSpeed = 0x1c000;
		_actor_80072df4->_priorityLayer = 3;

		_actor_80072df8->setFlag(ACTOR_FLAG_80);
		_actor_80072df8->setFlag(ACTOR_FLAG_100);
		_actor_80072df8->setFlag(ACTOR_FLAG_800);
		_actor_80072df8->setFlag(ACTOR_FLAG_8000);
		_actor_80072df8->_priorityLayer = 3;

		_vm->waitForFramesAllowSkip(0xe);
		_vm->fadeFromBlack();
		_actor_80072df0->startWalk(0xe8, 0xa8, 2);
		_actor_80072df0->waitForWalkToFinish();
		_actor_80072de8->startWalk(0x97, 0x37, 2);
		_actor_80072dec->startWalk(0x97, 0x37, 2);
		_actor_80072df4->startWalk(0x97, 0x37, 2);
		_actor_80072df0->waitUntilFlag8SetThenSet1000AndWaitFor4();
		_actor_80072df0->updateSequence(6);
		uint16 dialog[2000];
		dialog[0] = 0;
		_vm->_talk->loadText(_vm->getDialogTextId(0x5ea2), dialog, 2000);

		_vm->_talk->displayDialogAroundPoint(dialog, 0x27, 0xc, 0xc01, 0, _vm->getDialogTextId(0x5ea2));
		_actor_80072df0->waitUntilFlag8And4AreSet();
		_actor_80072df0->_x_pos = 0xcf;
		_actor_80072df0->_y_pos = 0x90;
		_actor_80072df0->startWalk(0x97, 0x37, 2);
		_actor_80072df0->updateSequence(7);
		_vm->_talk->FUN_8001a7c4_clearDialogBoxMaybe();

		dialog[0] = 0;
		_vm->_talk->loadText(_vm->getDialogTextId(0x5ecc), dialog, 2000);
		_vm->_talk->displayDialogAroundPoint(dialog, 0x14, 6, 0xc01, 0, _vm->getDialogTextId(0x5ecc));
		_vm->waitForFrames(0x3c);

		break;	// we do not need to loop in fact
	}

	_vm->_talk->FUN_8001a7c4_clearDialogBoxMaybe();
	_vm->fadeToBlack();
	_vm->clearFlags(ENGINE_FLAG_20000);
	// DisableVSyncEvent();
	//file_read_to_buffer(s_cursor.act_80011c44, actor_dictionary);
	// EnableVSyncEvent();
	if (isFlag10Set) {
		_vm->setFlags(ENGINE_FLAG_10);
	} else {
		_vm->clearFlags(ENGINE_FLAG_10);
	}

	_vm->_dragonINIResource->setFlickerRecord(flicker);
	cursorInventoryClearFlag400();
	_vm->clearUnkFlags(ENGINE_UNK1_FLAG_2);

}

//fadeScreenAndResetActor
void CutScene::fadeScreenAndResetActor(Actor *actor) {
	_vm->fadeToBlack();
	//DisableVSyncEvent();
	actor->reset_maybe();
	//EnableVSyncEvent();

}

void CutScene::closeUpShotOnActor(uint16 resourceId, uint16 sequenceId, int16 x, uint32 param_4) {
	fun_8003d8e8(resourceId, sequenceId, x, param_4);
	_vm->waitForFrames(5);
	_vm->fadeFromBlack();
}

void CutScene::fun_8003d8e8(uint16 resourceId, uint16 sequenceId, int16 x, uint32 param_4) {
	_vm->fadeToBlack();
	_vm->_actorManager->clearActorFlags(2);
	//DisableVSyncEvent();
	_actor_80072de8 = _vm->_actorManager->loadActor(resourceId, sequenceId, x, 199, 3);
	//EnableVSyncEvent();
	changeBackgroundPosition(3, param_4);
}

void CutScene::wideAngleEveryoneAtTable() {
	fun_8003d388();
	_vm->fadeFromBlack();
}

void CutScene::fun_8003d388() {
	uint sequenceId;

	_vm->fadeToBlack();
	_vm->_actorManager->clearActorFlags(2);
	if ((_actor_80063514 & 0x80) == 0) {
		_actor_80072de8 = _vm->_actorManager->loadActor(0x7e, 0x16, 0x40, 0xa0, 1);
	}
	_actor_80072dec = _vm->_actorManager->loadActor(0x7e, 0, 0xbf, 0xba, 1);
	if ((_actor_80063514 & 8) == 0) {
		_actor_80072df0 = _vm->_actorManager->loadActor(0x7e, 5, 0x94, 0x82, 1);
	}
	if ((_actor_80063514 & 0x10) == 0) {
		_actor_80072df4 = _vm->_actorManager->loadActor(0x7e, 10, 0x6f, 0x95, 1);
	}
	if ((_actor_80063514 & 4) == 0) {
		_actor_80072df8 = _vm->_actorManager->loadActor(0x7e, 0xe, 0xa9, 0x87, 1);
	}
	if ((_actor_80063514 & 0x20) == 0) {
		_actor_80072dfc = _vm->_actorManager->loadActor(0x7e, 0x12, 0xcd, 0x8e, 1);
	}
	if ((_actor_80063514 & 1) == 0) {
		_flameActor = _vm->_actorManager->loadActor(0x7e, 0x19, 0x10e, 0x89, 1);
	}
	if ((_actor_80063514 & 2) == 0) {
		_actor_80072e08 = _vm->_actorManager->loadActor(0x8f, 2, 100, 0xbc, 1);
	}
	if ((_actor_80063514 & 0x40) != 0) {
		_actor_80072e0c = _vm->_actorManager->loadActor(0x8f, 0, 0xd2, 100, 1);
		_actor_800830a0 = _vm->_actorManager->loadActor(0x8f, 1, 0xe6, 0x6e, 1);
	}
	_actor_800830b8 = _vm->_actorManager->loadActor(0xaa, 0, 0x2e, 0x2d, 1);
	_actor_800830b8->setFlag(ACTOR_FLAG_8000);
	_actor_800830bc = _vm->_actorManager->loadActor(0xaa, 1, 0x115, 0x22, 1);
	_actor_800830bc->setFlag(ACTOR_FLAG_100);
	_actor_800830bc->setFlag(ACTOR_FLAG_8000);
	_actor_800830bc->_priorityLayer = 4;
	if ((_actor_80063514 & 0x100) != 0) {
		_actor_800830c0 = _vm->_actorManager->loadActor(0x7e, 0x1c, 0x21, 0x87, 1);
	}
	if ((_actor_80063514 & 0x200) != 0) {
		if ((_actor_80063514 & 0x800) == 0) {
			sequenceId = 2;
		} else {
			sequenceId = 4;
		}
		_actor_800830d4 = _vm->_actorManager->loadActor(0xaa, sequenceId, 0xf4, 199, 1);
		_actor_800830d4->setFlag(ACTOR_FLAG_8000);
	}
	if ((_actor_80063514 & 0x400) != 0) {
		_actor_800830dc = _vm->_actorManager->loadActor(0xaa, 3, 0xf4, 199, 1);
		_actor_800830dc->setFlag(ACTOR_FLAG_8000);
	}
	changeBackgroundPosition(0, 0);
	_vm->waitForFramesAllowSkip(0xe);
}


void CutScene::closeUpKnightsAtTable() {
	_vm->fadeToBlack();
	_vm->_actorManager->clearActorFlags(2);
	_actor_80072de8 = _vm->_actorManager->loadActor(0x7d, 0, 2, 199, 1);
	_actor_80072dec = _vm->_actorManager->loadActor(0x81, 4, 2, 199, 1);
	_actor_80072df0 = _vm->_actorManager->loadActor(0x81, 6, 2, 199, 1);
	_actor_80072df4 = _vm->_actorManager->loadActor(0x81, 0, 2, 199, 1);
	_actor_80072df8 = _vm->_actorManager->loadActor(0x81, 2, 2, 199, 1);
	changeBackgroundPosition(1, 0);
	_vm->waitForFrames(0xf);
	_vm->fadeFromBlack();

}

uint16 CutScene::fun_8003dab8(uint32 textId, uint16 x, uint16 y, uint16 param_4, int16 param_5) {
	uint16 dialog[2000];
	dialog[0] = 0;
	textId = _vm->getDialogTextId(textId);
	_vm->_talk->loadText(textId, dialog, 2000);

	_vm->_talk->displayDialogAroundPoint(dialog, x, y, param_4, param_5, textId);
	return 1; //TODO this should return (uint)dialogText & 0xffff;
}

void CutScene::cursorInventoryClearFlag400() {
	_vm->_cursor->clearActorFlag400();
	_vm->_inventory->clearActorFlag400();
}

void CutScene::changeBackgroundPosition(uint16 newPosition, int16 sParm2) {
	switch (newPosition) {
	case 0:
		_vm->_screen->loadPalette(0, _palettes + 0 * 512);
		_vm->_scene->setMgLayerPriority(0);
		_vm->_scene->setFgLayerPriority(0);
		_vm->_scene->_camera.x = 0;
		_vm->_scene->setBgLayerPriority(1);
		break;

	case 1:
		_vm->_scene->setBgLayerPriority(0); //TODO investigate why this is 0 not 1
		_vm->_scene->setMgLayerPriority(1); //TODO investigate why this is 1 not 2
		_vm->_scene->_camera.x = sParm2 + 0x3c0;
		_vm->_scene->setFgLayerPriority(0);
		_vm->_screen->loadPalette(0, _palettes + 2 * 512);
		for (int i = 2; i < 0x17; i++) {
			Actor *actor = _vm->_actorManager->getActor(i);
			actor->_x_pos += 0x3c0;
		}
		break;

	case 2:
		_vm->_screen->loadPalette(0, _palettes + 3 * 512);
		_vm->_scene->setMgLayerPriority(2);
		_vm->_scene->setFgLayerPriority(3);
		_vm->_scene->_camera.x = 0;
		_vm->_scene->setBgLayerPriority(1);
		break;

	case 3:
		_vm->_screen->loadPalette(0, _palettes + 1 * 512);
		_vm->_scene->setMgLayerPriority(2);
		_vm->_scene->setFgLayerPriority(0);
		_vm->_scene->_camera.x = sParm2;
		_vm->_scene->setBgLayerPriority(1);
		break;

	default:
		break;
	}
}

void CutScene::diamondScene() {
	Actor *actorId;
	Actor *actorId_00;
	Actor *actorId_01;
	Actor *actorId_02;
	Actor *actorId_03;
	byte palette[512];

	_vm->setUnkFlags(ENGINE_UNK1_FLAG_2);
	actorId = _vm->getINI(0x257)->actor;
	actorId_03 = _vm->getINI(0x259)->actor;
	actorId_01 = _vm->getINI(0x258)->actor;
	actorId_03->setFlag(ACTOR_FLAG_100);
	actorId_03->_priorityLayer = 4;
	actorId_00 = _vm->getINI(0x256)->actor;
	_vm->setFlags(ENGINE_FLAG_20000);
	actorId_02 = _vm->getINI(0x25a)->actor;
	if ((_vm->_talk->somethingTextAndSpeechAndAnimRelated(actorId_02, 1, 0, 0x4294a, 0x2601) != 2) && !actorId->actorSetSequenceAndWaitAllowSkip(2)) {
		actorId->updateSequence(3);
		if (!actorId_01->actorSetSequenceAndWaitAllowSkip(0x18)) {
			_vm->waitForFramesAllowSkip(0x2c);
			_vm->fadeToBlack();
			memcpy(palette, _vm->_scene->getPalette(), 512);
			_vm->_screen->loadPalette(0, actorId_00->_actorResource->getPalette());
			_vm->_scene->_camera.x = 0x140;
			_vm->fadeFromBlack();
			if (!actorId_00->actorSetSequenceAndWaitAllowSkip(0)) {
				// TODO is this needed playSoundFromTxtIndex(0x42A66);
				if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(actorId_00, 1, 2, 0x42a66, 0x3c01) != 2) {
					_vm->waitForFramesAllowSkip(0x13);
					_vm->fadeToBlack();
					_vm->_screen->loadPalette(0, palette);
					_vm->_scene->_camera.x = 0;
					_vm->fadeFromBlack();
					actorId_01->updateSequence(0x19);
					_vm->waitForFramesAllowSkip(0xf);
					actorId->updateSequence(4);
					_vm->waitForFramesAllowSkip(0x17);
					actorId_03->updateSequence(9);
					actorId_03->_x_pos = 0x82;
					actorId_03->_y_pos = 0xc4;
					actorId_03->_priorityLayer = 4;
					if (!actorId->waitUntilFlag4IsSetAllowSkip()) {
						actorId->updateSequence(5);
						if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(actorId_01, 0x10, 2, 0x42ac2, 0x3c01) != 2 &&
							_vm->_talk->somethingTextAndSpeechAndAnimRelated(actorId_02, 1, 0, 0x42b56, 0x2601) != 2) {
							_vm->waitForFramesAllowSkip(0x3b);
						}
					}
				}
			}
		}
	}
	_vm->clearUnkFlags(ENGINE_UNK1_FLAG_2);
	_vm->clearFlags(ENGINE_FLAG_20000);
}

void CutScene::knightsSavedBackAtCastle() {
	DragonINI *uVar1;
	uint actorId;
	bool isFlag0x10Set;

	uVar1 = _vm->_dragonINIResource->getFlickerRecord();
	_actor_80063514 = 0xa00;
	_vm->_dragonINIResource->setFlickerRecord(nullptr);
	_vm->setUnkFlags(ENGINE_UNK1_FLAG_2);
	isFlag0x10Set = _vm->isFlagSet(ENGINE_FLAG_10);
	_vm->fadeToBlack();
	_vm->clearFlags(ENGINE_FLAG_10);
	_vm->_inventory->setActorFlag400();
	_vm->_cursor->setActorFlag400();

//	scr_tilemap1_w = 0x28;
//	_actor_8006a3f0 = _actor_8006a3ec;
//	load_actor_file(0x81);
//	load_actor_file(0x7d);
//	load_actor_file(0x7e);
//	load_actor_file(0x8f);
//	load_actor_file(0xaa);

	_vm->setFlags(ENGINE_FLAG_20000);
	closeUpKnightsAtTable();
//	playSoundFromTxtIndex(0x7854);

	while (1) {	// In order to avoid gotos
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 10, 4, 0x7854, 0xc01) == 2)
			break;

		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60);
		//playSoundFromTxtIndex(0x78c6);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 4, 0, 0x78c6, 0x701) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpKnightsAtTable();
		//playSoundFromTxtIndex(0x78e8);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 3, 0, 0x78e8, 0x2e01) == 2)
			break;

		wideAngleEveryoneAtTable();

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_flameActor, 0x1a, 0x19, 0x7a1e, 0x3e01) == 2)
			break;

		_flameActor->_walkSpeed = 0x10000;
		_flameActor->setFlag(ACTOR_FLAG_800);
		_flameActor->updateSequence(0x21);
		_flameActor->startWalk(0x13f, 0x6e, 2);
		// wait for pathfinding to complete
		_flameActor->waitForWalkToFinish();
		_actor_80063514 = _actor_80063514 | 1;
		closeUpShotOnActor(0xd3, 0, 0x233, 0x17a);
		//playSoundFromTxtIndex(0x7aba);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 9, 0, 0x7aba, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60);
		//playSoundFromTxtIndex(0x7b60);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 5, 0, 0x7b60, 0x701) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		wideAngleEveryoneAtTable();
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072df0, 9, 5, 0x7c20, 0xc01) == 2 ||
			_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0x17, 0x16, 0x7c9c, 0x701) == 2)
			break;

		_vm->playOrStopSound(0x800f);
		_vm->waitForFrames(10);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0x17, 0x16, 0x7cf2, 0x701) == 2)
			break;

		closeUpKnightsAtTable();
		//playSoundFromTxtIndex(0x7dcc);
		_actor_80072df0->updateSequence(0x13);
		_actor_80072df4->updateSequence(0x10);
		_actor_80072df8->updateSequence(0x11);
		actorId = _vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 0x12, 6, 0x7dcc, 0xc01);

		if ((actorId & 0xffff) == 2)
			break;

		closeUpShotOnActor(0xd3, 0, 0x233, 0x17a);
		//playSoundFromTxtIndex(0x7e1a);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 10, 0, 0x7e1a, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		wideAngleEveryoneAtTable();

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 4, 0, 0x7e96, 0x2e01) == 2)
			break;

		_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0x17, 0x16, 0x7f0a, 0x701);

		break; // we do not want to loop
	}
	_vm->fadeToBlack();
	//DisableVSyncEvent();
//	file_read_to_buffer(s_cursor.act_80011c44, actor_dictionary);
	//EnableVSyncEvent();
	if (isFlag0x10Set) {
		_vm->setFlags(ENGINE_FLAG_10);
	}
	_vm->clearFlags(ENGINE_FLAG_20000);
	_vm->_dragonINIResource->setFlickerRecord(uVar1);
	cursorInventoryClearFlag400();
	_vm->clearUnkFlags(ENGINE_UNK1_FLAG_2);
}

void CutScene::loadPalettes() {
	Common::File fd;
	if (!fd.open("dragon.exe")) {
		error("Failed to open dragon.exe");
	}
	fd.seek(_vm->getCutscenePaletteOffsetFromDragonEXE());

	_palettes = (byte *)malloc(256 * 2 * 4);
	fd.read(_palettes, 256 * 2 * 4);
}

void CutScene::flameReturnsCutScene() {
	DragonINI *uVar1;
	uint engineFlag10Set;

	uVar1 = _vm->_dragonINIResource->getFlickerRecord();
	_actor_80063514 = 0x3f;
	_vm->_dragonINIResource->setFlickerRecord(nullptr);
	_vm->setUnkFlags(ENGINE_UNK1_FLAG_2);
	engineFlag10Set = _vm->isFlagSet(ENGINE_FLAG_10);
	_vm->fadeToBlack();
	_vm->clearFlags(ENGINE_FLAG_10);
	_vm->_cursor->setActorFlag400();
	_vm->_inventory->setActorFlag400();
//	scr_tilemap1_w = 0x28;
//	_actor_8006a3f0 = _actor_8006a3ec;
//	load_actor_file(0x81);
//	load_actor_file(0x7d);
//	load_actor_file(0x7e);
//	load_actor_file(0x8f);
//	load_actor_file(0xaa);
	_actor_80063514 = (_actor_80063514 & 0xfffe) | 0x600;
	fun_8003d388();
	_actor_80072de8->updateSequence(0x1f);
	_flameActor->_x_pos = 0x10b;
	_flameActor->_y_pos = 99;
	_actor_80072de8->_x_pos = 0x10a;
	_actor_80072de8->_y_pos = 0x5a;
	_actor_80072de8->_walkSpeed = 0x10000;
	_flameActor->_walkSpeed = 0x10000;
	_actor_80072de8->setFlag(ACTOR_FLAG_800);
	_flameActor->setFlag(ACTOR_FLAG_800);
	_vm->fadeFromBlack();
	_vm->setFlags(ENGINE_FLAG_20000);

	while (1) {	// In order to avoid gotos
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 4, 0, 0x8ab2, 0x2e01) == 2)
			break;

		_actor_80072de8->updateSequence(0x1e);
		_actor_80072de8->startWalk(0xb0, 0x6b, 2);
		_actor_80072de8->waitForWalkToFinish();
		_actor_80072de8->updateSequence(0x1f);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 4, 0, 0x8b40, 0x2e01) == 2)
			break;

		_flameActor->updateSequence(0x1b);
		_flameActor->startWalk(0xd5, 0x6b, 2);
		_flameActor->waitForWalkToFinish();

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_flameActor, 0x1a, 0x19, 0x8bb6, 0x3e01) == 2 ||
			_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 4, 0, 0x8bd8, 0x2e01) == 2)
			break;

		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60);
		//playSoundFromTxtIndex(0x8c70);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 7, 0, 0x8c70, 0x701) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd3, 0, 0x233, 0x17a);
		//playSoundFromTxtIndex(0x8cd2);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0xc, 0, 0x8cd2, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd7, 0, 0x312, 0x260);
		//playSoundFromTxtIndex(0x8e1e);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 5, 0, 0x8e1e, 0x3e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);

		break; // We do not want to loop
	}
	_vm->fadeToBlack();
//	DisableVSyncEvent();
//	file_read_to_buffer(s_cursor.act_80011c44, actor_dictionary);
//	EnableVSyncEvent();
	_vm->clearFlags(ENGINE_FLAG_20000);
	if (engineFlag10Set) {
		_vm->setFlags(ENGINE_FLAG_10);
	}
	_vm->_dragonINIResource->setFlickerRecord(uVar1);
	cursorInventoryClearFlag400();
	_vm->clearUnkFlags(ENGINE_UNK1_FLAG_2);
}

void CutScene::knightsSavedAgain() {
	DragonINI *flicker;
	bool engineFlag10Set;

	flicker = _vm->_dragonINIResource->getFlickerRecord();
	_actor_80063514 = 0;
	_vm->_dragonINIResource->setFlickerRecord(nullptr);
	_vm->setUnkFlags(ENGINE_UNK1_FLAG_2);
	engineFlag10Set = _vm->isFlagSet(ENGINE_FLAG_10);
	_vm->fadeToBlack();

	_vm->clearFlags(ENGINE_FLAG_10);
	_vm->_cursor->setActorFlag400();
	_vm->_inventory->setActorFlag400();

//	scr_tilemap1_w = 0x28;
//TODO what is this?	_actor_8006a3f0 = _actor_8006a3ec;

//	load_actor_file(0x81);
//	load_actor_file(0x7d);
//	load_actor_file(0x7e);
//	load_actor_file(0x8f);
//	load_actor_file(0xaa);
	wideAngleEveryoneAtTable();
	_vm->setFlags(ENGINE_FLAG_20000);
	_vm->waitForFramesAllowSkip(0x3b);
	closeUpShotOnActor(0xd3, 0, 0x233, 0x17a);
	//playSoundFromTxtIndex(0x9000);

	while (1) {	// In order to avoid gotos
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0xd, 0, 0x9000, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpKnightsAtTable();
		//playSoundFromTxtIndex(0x90de);
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 4, 0, 0x90de, 0x2e01) == 2)
			break;

		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60);
		//playSoundFromTxtIndex(0x921c);
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 8, 0, 0x921c, 0x701) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpKnightsAtTable();

		//playSoundFromTxtIndex(0x92aa);
		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 9, 4, 0x92aa, 0xc01) == 2)
			break;

		closeUpShotOnActor(0xd7, 0, 0x312, 0x260);
		//playSoundFromTxtIndex(0x932c);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 6, 0, 0x932c, 0x3e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpShotOnActor(0xd3, 2, 0x87, 0);
		//playSoundFromTxtIndex(0x93d6);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 0xe, 2, 0x93d6, 0x2e01) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		closeUpKnightsAtTable();
		//playSoundFromTxtIndex(0x7dcc);
		_actor_80072df0->updateSequence(0x13);
		_actor_80072df4->updateSequence(0x10);
		_actor_80072df8->updateSequence(0x11);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072dec, 0x12, 6, 0x7dcc, 0xc01) == 2)
			break;

		closeUpShotOnActor(0xd8, 0, 0xfd, 0x60);
		//playSoundFromTxtIndex(0x948c);

		if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(_actor_80072de8, 9, 0, 0x948c, 0x701) == 2)
			break;

		fadeScreenAndResetActor(_actor_80072de8);
		_vm->waitForFramesAllowSkip(0x3b);

		break; // We do not want to loop
	}
	_vm->fadeToBlack();
//	DisableVSyncEvent();
//	file_read_to_buffer(s_cursor.act_80011c44, actor_dictionary);
//	EnableVSyncEvent();
	_vm->clearFlags(ENGINE_FLAG_20000);
	if (engineFlag10Set) {
		_vm->setFlags(ENGINE_FLAG_10);
	}
	_vm->_dragonINIResource->setFlickerRecord(flicker);
	cursorInventoryClearFlag400();
	_vm->clearUnkFlags(ENGINE_UNK1_FLAG_2);
}

static uint16 tournamentUpdateCameraX = 0;

void tournamentUpdateFunction() {
	tournamentUpdateCameraX++;
	if (tournamentUpdateCameraX > 0x280) {
		return;
	}
	getEngine()->_scene->_camera.x = tournamentUpdateCameraX;
}

void CutScene::tournamentCutScene() {
	uint16 dialogText[1000];

	tournamentUpdateCameraX = 0x140;
	_vm->setVsyncUpdateFunction(tournamentUpdateFunction);
	_vm->_talk->loadText(_vm->getDialogTextId(0x4C40C), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0x1e01, 1, _vm->getDialogTextId(0x4C40C));

	_vm->_talk->loadText(_vm->getDialogTextId(0x4C530), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0xc01, 1, _vm->getDialogTextId(0x4C530));

	_vm->_talk->loadText(_vm->getDialogTextId(0x4C588), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0x1e01, 1, _vm->getDialogTextId(0x4C588));

	_vm->_talk->loadText(_vm->getDialogTextId(0x4C6B0), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0xc01, 1, _vm->getDialogTextId(0x4C6B0));

	_vm->_talk->loadText(_vm->getDialogTextId(0x4C6E8), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0x1e01, 1, _vm->getDialogTextId(0x4C6E8));
	_vm->setVsyncUpdateFunction(nullptr);
	_vm->setFlags(ENGINE_FLAG_20000);
	_vm->fadeToBlack();
	Actor *actor = _vm->_dragonINIResource->getRecord(0x02BE)->actor;
	_vm->_screen->loadPalette(0, actor->_actorResource->getPalette());
	_vm->_scene->_camera.x = 0;
	_vm->playOrStopSound(0);
	_vm->fadeFromBlack();
	_vm->waitForFrames(300);
	actor->setFlag(ACTOR_FLAG_1000);
	actor->waitUntilFlag8And4AreSet();
	_vm->waitForFrames(0x3c);
	_vm->fadeToBlack();
	_vm->_screen->loadPalette(0, _vm->_scene->getPalette());
	_vm->playOrStopSound(0x4000);
	_vm->_scene->_camera.x = 0x3c0;
	_vm->fadeFromBlack();
	_vm->_talk->loadText(_vm->getDialogTextId(0x4C814), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0xc01, 1, _vm->getDialogTextId(0x4C814));
	_vm->_talk->loadText(_vm->getDialogTextId(0x4C852), dialogText, 1000);
	_vm->_talk->displayDialogAroundPoint(dialogText, 0, 0, 0x1e01, 1, _vm->getDialogTextId(0x4C852));
	_vm->setFlags(ENGINE_FLAG_20000);
	_vm->fadeToBlack();
}


} // End of namespace Dragons
