#include "data/dungeon_frame.h"


const unsigned char dungeon_palette_bg [16]={ 0x0f,0x0b,0x1a,0x29,0x0f,0x18,0x1a,0x29,0x0f,0x0f,0x0f,0x0f,0x0f,0x00,0x10,0x30 };
const unsigned char dungeon_palette_spr[16]={ 0x0f,0x06,0x16,0x30,0x0f,0x11,0x16,0x07,0x0f,0x11,0x16,0x30,0x0f,0x07,0x16,0x37 };






#define DUNGEON_NT_ADR	0x20e2

#define P_FWD		7
#define P_ROT		8
#define P_END		255
#define C_FWD		CHR_DUNGEON_FWD
#define C_ROT		CHR_DUNGEON_ROT

//prg, chr, frame number, palette inversion


const unsigned char ed_seq_start[]={
	P_FWD,C_FWD,0,0,
	P_END,
};

const unsigned char ed_seq_fwd_a[]={
	P_FWD,C_FWD,1,0,
	P_FWD,C_FWD,2,0,
	P_FWD,C_FWD,3,0,
	P_FWD,C_FWD,4,0,
	P_FWD,C_FWD,5,0,
	P_FWD,C_FWD,6,0,
	P_FWD,C_FWD,7,0,
	P_FWD,C_FWD,8,0,
	P_FWD,C_FWD,9,0,
	P_FWD,C_FWD,10,0,
	P_FWD,C_FWD,11,0,
	P_FWD,C_FWD,12,0,
	P_FWD,C_FWD,13,0,
	P_FWD,C_FWD,14,0,
	P_FWD,C_FWD,15,0,
	P_FWD,C_FWD,0,0,
	P_END
};

const unsigned char ed_seq_fwd_door_a[]={
	P_FWD,C_FWD,16,0,
	P_FWD,C_FWD,17,0,
	P_FWD,C_FWD,18,0,
	P_FWD,C_FWD,19,0,
	P_FWD,C_FWD,20,0,
	P_FWD,C_FWD,21,0,
	P_FWD,C_FWD,22,0,
	P_FWD,C_FWD,23,0,
	P_FWD,C_FWD,24,0,
	P_END
};

const unsigned char ed_seq_fwd_door_b[]={
	P_FWD,C_FWD,16,1,
	P_FWD,C_FWD,17,1,
	P_FWD,C_FWD,18,1,
	P_FWD,C_FWD,19,1,
	P_FWD,C_FWD,20,1,
	P_FWD,C_FWD,21,1,
	P_FWD,C_FWD,22,1,
	P_FWD,C_FWD,23,1,
	P_FWD,C_FWD,24,1,
	P_END
};

const unsigned char ed_seq_fwd_b[]={
	P_FWD,C_FWD,1,1,
	P_FWD,C_FWD,2,1,
	P_FWD,C_FWD,3,1,
	P_FWD,C_FWD,4,1,
	P_FWD,C_FWD,5,1,
	P_FWD,C_FWD,6,1,
	P_FWD,C_FWD,7,1,
	P_FWD,C_FWD,8,1,
	P_FWD,C_FWD,9,1,
	P_FWD,C_FWD,10,1,
	P_FWD,C_FWD,11,1,
	P_FWD,C_FWD,12,1,
	P_FWD,C_FWD,13,1,
	P_FWD,C_FWD,14,1,
	P_FWD,C_FWD,15,1,
	P_FWD,C_FWD,0,1,
	P_END
};

const unsigned char ed_seq_rot_left_a[]={
	P_ROT,C_ROT,0,0,
	P_ROT,C_ROT,1,0,
	P_ROT,C_ROT,2,0,
	P_ROT,C_ROT,3,0,
	P_ROT,C_ROT,4,0,
	P_ROT,C_ROT,5,0,
	P_ROT,C_ROT,6,0,
	P_ROT,C_ROT,7,0,
	P_ROT,C_ROT,8,0,
	P_ROT,C_ROT,9,0,
	P_ROT,C_ROT,10,0,
	P_ROT,C_ROT,11,0,
	P_ROT,C_ROT,0,1,
	P_END
};

const unsigned char ed_seq_rot_left_b[]={
	P_ROT,C_ROT,0,1,
	P_ROT,C_ROT,1,1,
	P_ROT,C_ROT,2,1,
	P_ROT,C_ROT,3,1,
	P_ROT,C_ROT,4,1,
	P_ROT,C_ROT,5,1,
	P_ROT,C_ROT,6,1,
	P_ROT,C_ROT,7,1,
	P_ROT,C_ROT,8,1,
	P_ROT,C_ROT,9,1,
	P_ROT,C_ROT,10,1,
	P_ROT,C_ROT,11,1,
	P_ROT,C_ROT,0,0,
	P_END
};

const unsigned char ed_seq_rot_left_to_wall_a[]={
	P_ROT,C_ROT,1,0,
	P_ROT,C_ROT,2,0,
	P_ROT,C_ROT,3,0,
	P_ROT,C_ROT,4,0,
	P_ROT,C_ROT,5,0,
	P_ROT,C_ROT,19,0,
	P_ROT,C_ROT,20,0,
	P_ROT,C_ROT,21,0,
	P_ROT,C_ROT,22,0,
	P_ROT,C_ROT,23,0,
	P_ROT,C_ROT,24,0,
	P_ROT,C_ROT,25,0,
	P_END
};

const unsigned char ed_seq_rot_left_door_a[]={
	P_ROT,C_ROT,0,0,
	P_ROT,C_ROT,1,0,
	P_ROT,C_ROT,2,0,
	P_ROT,C_ROT,3,0,
	P_ROT,C_ROT,4,0,
	P_ROT,C_ROT,5,0,
	P_ROT,C_ROT,12,0,
	P_ROT,C_ROT,13,0,
	P_ROT,C_ROT,14,0,
	P_ROT,C_ROT,15,0,
	P_ROT,C_ROT,16,0,
	P_ROT,C_ROT,17,0,
	P_ROT,C_ROT,18,0,
	P_END
};

const unsigned char ed_seq_rot_right_a[]={
	P_ROT,C_ROT,11,0,
	P_ROT,C_ROT,10,0,
	P_ROT,C_ROT,9,0,
	P_ROT,C_ROT,8,0,
	P_ROT,C_ROT,7,0,
	P_ROT,C_ROT,6,0,
	P_ROT,C_ROT,5,0,
	P_ROT,C_ROT,4,0,
	P_ROT,C_ROT,3,0,
	P_ROT,C_ROT,2,0,
	P_ROT,C_ROT,1,0,
	P_ROT,C_ROT,0,0,
	P_END
};

const unsigned char ed_seq_rot_right_b[]={
	P_ROT,C_ROT,11,1,
	P_ROT,C_ROT,10,1,
	P_ROT,C_ROT,9,1,
	P_ROT,C_ROT,8,1,
	P_ROT,C_ROT,7,1,
	P_ROT,C_ROT,6,1,
	P_ROT,C_ROT,5,1,
	P_ROT,C_ROT,4,1,
	P_ROT,C_ROT,3,1,
	P_ROT,C_ROT,2,1,
	P_ROT,C_ROT,1,1,
	P_ROT,C_ROT,0,1,
	P_END
};

const unsigned char ed_seq_rot_right_from_wall_b[]={
	P_ROT,C_ROT,24,0,
	P_ROT,C_ROT,23,0,
	P_ROT,C_ROT,22,0,
	P_ROT,C_ROT,21,0,
	P_ROT,C_ROT,20,0,
	P_ROT,C_ROT,19,0,
	P_ROT,C_ROT,5,0,
	P_ROT,C_ROT,4,0,
	P_ROT,C_ROT,3,0,
	P_ROT,C_ROT,2,0,
	P_ROT,C_ROT,1,0,
	P_ROT,C_ROT,0,0,
	P_END
};

#define ANIM_PAUSE(n)	((const char*)(n))

const char* const ed_anim[]={
	ed_seq_start,
	ANIM_PAUSE(64),
	ed_seq_fwd_a,
	ANIM_PAUSE(16),
	ed_seq_rot_left_to_wall_a,
	ANIM_PAUSE(8),
	ed_seq_rot_right_from_wall_b,
	ANIM_PAUSE(8),
	ed_seq_fwd_a,
	ANIM_PAUSE(16),
	ed_seq_rot_right_b,
	ANIM_PAUSE(16),
	ed_seq_fwd_b,
	ANIM_PAUSE(16),
	ed_seq_rot_left_b,
	ANIM_PAUSE(16),
	ed_seq_fwd_a,
	ed_seq_rot_left_door_a,
	ANIM_PAUSE(16),
	ed_seq_fwd_door_b,
	0
};


const unsigned char door_sprite[6*9]={
	0x01,0x02,0x02,0x02,0x02,0x03,
	0x04,0x05,0x06,0x07,0x05,0x08,
	0x04,0x05,0x09,0x0a,0x05,0x08,
	0x0b,0x0c,0x0d,0x0e,0x05,0x08,
	0x0f,0x10,0x05,0x05,0x05,0x08,
	0x04,0x05,0x05,0x05,0x05,0x08,
	0x04,0x05,0x05,0x05,0x05,0x08,
	0x04,0x05,0x05,0x05,0x05,0x08,
	0x11,0x12,0x12,0x12,0x12,0x13
};



const unsigned char mario_0_data[]={

	-24,-36,0x00,3,
	-16,-36,0x81,3,
	- 8,-36,0x82,3,
	  0,-36,0x83,3,
	  8,-36,0x84,3,
	 16,-36,0x00,3,
	-24,-28,0x00,3,
	-16,-28,0x85,3,
	- 8,-28,0x86,3,
	  0,-28,0x86,3,
	  8,-28,0x87,3,
	 16,-28,0x00,3,
	-24,-20,0x00,3,
	-16,-20,0x88,3,
	- 8,-20,0x89,3,
	  0,-20,0x8a,3,
	  8,-20,0x8b,3,
	 16,-20,0x00,3,
	-24,-12,0x00,3,
	-16,-12,0x8c,3,
	- 8,-12,0x8d,1,
	  0,-12,0x8e,1,
	  8,-12,0x8f,3,
	 16,-12,0x00,3,
	-24,- 4,0x90,2,
	-16,- 4,0x91,2,
	- 8,- 4,0x92,2,
	  0,- 4,0x93,2,
	  8,- 4,0x94,2,
	 16,- 4,0x95,2,
	-24,  4,0x96,2,
	-16,  4,0x97,2,
	- 8,  4,0x98,2,
	  0,  4,0x98,2,
	  8,  4,0x99,2,
	 16,  4,0x9a,2,
	-24, 12,0x9b,2,
	-16, 12,0x9c,2,
	- 8, 12,0x9d,2,
	  0, 12,0x9e,2,
	  8, 12,0x9f,2,
	 16, 12,0xa0,2,
	-24, 20,0x00,2,
	-16, 20,0xa1,2,
	- 8, 20,0xa2,2,
	  0, 20,0xa3,2,
	  8, 20,0xa4,2,
	 16, 20,0x00,2,
	-24, 28,0x00,3,
	-16, 28,0xa5,3,
	- 8, 28,0xa6,3,
	  0, 28,0xa7,3,
	  8, 28,0xa8,3,
	 16, 28,0x00,3,
	128

};

const unsigned char mario_1_data[]={

	-24,-36,0x00,3,
	-16,-36,0xa9,3,
	- 8,-36,0xaa,3,
	  0,-36,0xab,3,
	  8,-36,0x95,3,
	 16,-36,0x00,3,
	-24,-28,0x00,3,
	-16,-28,0xac,3,
	- 8,-28,0x86,3,
	  0,-28,0x86,3,
	  8,-28,0xad,3,
	 16,-28,0x00,3,
	-24,-20,0x00,3,
	-16,-20,0xae,3,
	- 8,-20,0xaf,3,
	  0,-20,0xb0,3,
	  8,-20,0xb1,3,
	 16,-20,0x00,3,
	-24,-12,0x00,3,
	-16,-12,0xb2,3,
	- 8,-12,0xb3,1,
	  0,-12,0xb4,1,
	  8,-12,0x8f,3,
	 16,-12,0x00,3,
	-24,- 4,0xb5,2,
	-16,- 4,0xb6,2,
	- 8,- 4,0x98,2,
	  0,- 4,0xb7,2,
	  8,- 4,0xb8,2,
	 16,- 4,0xb9,2,
	-24,  4,0xba,2,
	-16,  4,0xbb,2,
	- 8,  4,0x98,2,
	  0,  4,0x98,2,
	  8,  4,0xbc,2,
	 16,  4,0xbd,2,
	-24, 12,0xbe,2,
	-16, 12,0xbf,2,
	- 8, 12,0x98,2,
	  0, 12,0xc0,2,
	  8, 12,0xc1,2,
	 16, 12,0xc2,2,
	-24, 20,0x00,2,
	-16, 20,0xbf,2,
	- 8, 20,0x98,2,
	  0, 20,0xc3,3,
	  8, 20,0xc4,3,
	 16, 20,0x00,3,
	-24, 28,0x00,2,
	-16, 28,0xc5,3,
	- 8, 28,0xc6,3,
	  0, 28,0x00,2,
	  8, 28,0x00,3,
	 16, 28,0x00,3,
	128

};

const unsigned char mario_2_data[]={

	-24,-36,0x00,3|OAM_FLIP_H,
	-16,-36,0x95,3|OAM_FLIP_H,
	- 8,-36,0xab,3|OAM_FLIP_H,
	  0,-36,0xaa,3|OAM_FLIP_H,
	  8,-36,0xa9,3|OAM_FLIP_H,
	 16,-36,0x00,3|OAM_FLIP_H,
	-24,-28,0x00,3|OAM_FLIP_H,
	-16,-28,0xad,3|OAM_FLIP_H,
	- 8,-28,0x86,3|OAM_FLIP_H,
	  0,-28,0x86,3|OAM_FLIP_H,
	  8,-28,0xac,3|OAM_FLIP_H,
	 16,-28,0x00,3|OAM_FLIP_H,
	-24,-20,0x00,3|OAM_FLIP_H,
	-16,-20,0xb1,3|OAM_FLIP_H,
	- 8,-20,0xb0,3|OAM_FLIP_H,
	  0,-20,0xaf,3|OAM_FLIP_H,
	  8,-20,0xae,3|OAM_FLIP_H,
	 16,-20,0x00,3|OAM_FLIP_H,
	-24,-12,0x00,3|OAM_FLIP_H,
	-16,-12,0x8f,3|OAM_FLIP_H,
	- 8,-12,0xb4,1|OAM_FLIP_H,
	  0,-12,0xb3,1|OAM_FLIP_H,
	  8,-12,0xb2,3|OAM_FLIP_H,
	 16,-12,0x00,3|OAM_FLIP_H,
	-24,- 4,0xb9,2|OAM_FLIP_H,
	-16,- 4,0xb8,2|OAM_FLIP_H,
	- 8,- 4,0xb7,2|OAM_FLIP_H,
	  0,- 4,0x98,2|OAM_FLIP_H,
	  8,- 4,0xb6,2|OAM_FLIP_H,
	 16,- 4,0xb5,2|OAM_FLIP_H,
	-24,  4,0xbd,2|OAM_FLIP_H,
	-16,  4,0xbc,2|OAM_FLIP_H,
	- 8,  4,0x98,2|OAM_FLIP_H,
	  0,  4,0x98,2|OAM_FLIP_H,
	  8,  4,0xbb,2|OAM_FLIP_H,
	 16,  4,0xba,2|OAM_FLIP_H,
	-24, 12,0xc2,2|OAM_FLIP_H,
	-16, 12,0xc1,2|OAM_FLIP_H,
	- 8, 12,0xc0,2|OAM_FLIP_H,
	  0, 12,0x98,2|OAM_FLIP_H,
	  8, 12,0xbf,2|OAM_FLIP_H,
	 16, 12,0xbe,2|OAM_FLIP_H,
	-24, 20,0x00,3|OAM_FLIP_H,
	-16, 20,0xc4,3|OAM_FLIP_H,
	- 8, 20,0xc3,3|OAM_FLIP_H,
	  0, 20,0x98,2|OAM_FLIP_H,
	  8, 20,0xbf,2|OAM_FLIP_H,
	 16, 20,0x00,2|OAM_FLIP_H,
	-24, 28,0x00,3|OAM_FLIP_H,
	-16, 28,0x00,3|OAM_FLIP_H,
	- 8, 28,0x00,2|OAM_FLIP_H,
	  0, 28,0xc6,3|OAM_FLIP_H,
	  8, 28,0xc5,3|OAM_FLIP_H,
	 16, 28,0x00,2|OAM_FLIP_H,
	128

};

const unsigned char* const mario_list[]={

	mario_0_data,
	mario_1_data,
	mario_0_data,
	mario_2_data

};








void __fastcall__ dungeon_copy_frame(unsigned char prg,unsigned int off);



void ed_display_door(unsigned char frame)
{
	signed int sxx,dxx;
	
	dxx=-8*(signed int)frame;
	
	_sy=80-1;
	
	for(_i=0;_i<9;++_i)
	{
		_ptr=_i*6+5;
		sxx=(104+5*8)<<6;
		
		for(_j=0;_j<6;++_j)
		{
			oam_spr(sxx>>6,_sy,door_sprite[_ptr--],0,oam_off);
			
			oam_off+=4;
			sxx+=dxx;
		}
		
		_sy+=8;
	}
}



void ed_display_mario(unsigned char sx,unsigned char sy,unsigned char frame,signed int scale)
{
	const unsigned char* data;
	unsigned char sxa[6],sya[9];
	signed int ssx,ssy;
	
	ssx=-24;

	for(_i=0;_i<6;++_i)
	{
		sxa[_i]=sx+ssx*scale/64;
		ssx+=8;
	}

	ssy=-36;

	for(_i=0;_i<9;++_i)
	{
		sya[_i]=sy+ssy*scale/64;
		ssy+=8;
	}
		
	data=mario_list[frame];
	_ptr=0;
	
	for(_i=0;_i<9;++_i)
	{
		for(_j=0;_j<6;++_j)
		{
			_tile=data[_ptr+2];
			_attr=data[_ptr+3];
			
			oam_spr(sxa[_j],sya[_i],_tile,_attr,oam_off);
			oam_off+=4;
			_ptr+=4;
		}
	}
}



void e_dungeon(void)
{
	unsigned char chr,prg,frm,inv,frame,bright,done;
	unsigned char seq_ptr,anim_ptr,anim_delay,door_frame,mario_size,mario_floor;
	const unsigned char* seq;
	unsigned int seqi;
	
	oam_clear_fast();
	oam_size(0);
	
	chr=CHR_DUNGEON_SPRITE;
	
	mmc3_chr_bank(chr+0,2);
	mmc3_chr_bank(chr+1,3);
	mmc3_chr_bank(chr+2,4);
	mmc3_chr_bank(chr+3,5);

	mmc3_set_mirroring(M_HORIZONTAL);
	
	set_irq_handler(IRQ_DUNGEON);
	set_nmi_handler(NMI_NORMAL);
	
	memfill(update_list,0,sizeof(update_list));	//these lists used as a frame buffer here
	memfill(split_list ,0,sizeof(split_list));	//252 bytes in each list
	
	pal_bg (dungeon_palette_bg);
	pal_spr(dungeon_palette_spr);
	pal_bright(0);
	
	vram_adr(NAMETABLE_A);
	vram_unrle(dungeon_frame);
	
	anim_ptr=0;
	anim_delay=0;
	seq_ptr=255;
	frame=0;
	door_frame=0;
	bright=0;
	done=FALSE;
	
	scroll(0,8);
	
	mmc3_irq_enable(192);
	
	ppu_on_all();
	
	while(1)
	{
		if(!(frame&1))
		{
			if(seq_ptr==255)
			{
				if(!ed_anim[anim_ptr]) break;

				seq=ed_anim[anim_ptr++];
				seqi=(unsigned int)seq;
				
				if(seqi<256)
				{
					anim_delay=seqi;
					seq_ptr=255;
				}
				else
				{
					seq_ptr=0;
				}
			}
			
			if(anim_delay) --anim_delay;
			
			if(seq&&!anim_delay)
			{
				prg=seq[seq_ptr+0];
				chr=seq[seq_ptr+1];
				frm=seq[seq_ptr+2];
				inv=seq[seq_ptr+3];
				
				dungeon_copy_frame(prg,frm*504);
				
				mmc3_chr_bank(chr+0,0);
				mmc3_chr_bank(chr+2,1);
		
				if(!inv)
				{
					pal_col(0x02,dungeon_palette_bg[0x02]);
					pal_col(0x03,dungeon_palette_bg[0x03]);
					pal_col(0x06,dungeon_palette_bg[0x06]);
					pal_col(0x07,dungeon_palette_bg[0x07]);
				}
				else
				{
					pal_col(0x02,dungeon_palette_bg[0x03]);
					pal_col(0x03,dungeon_palette_bg[0x02]);
					pal_col(0x06,dungeon_palette_bg[0x07]);
					pal_col(0x07,dungeon_palette_bg[0x06]);
				}
				
				seq_ptr+=4;

				if(seq[seq_ptr]==P_END) seq_ptr=255;
			}
		}
		
		pal_bright(bright);
		
		oam_update();
		
		ppu_wait_nmi();
		
		if(!(frame&7))
		{
			if(bright<4) ++bright;
		}
		
		++frame;
	}

	frame=0;
	bright=4;
	mario_size=64;
	mario_floor=224;
	
	while(1)
	{
		oam_off=0;
		
		ed_display_mario(128,mario_floor,(frame>>1)&3,mario_size);
		
		oam_hide_rest(oam_off);
		
		pal_spr_bright(bright);
		
		oam_update();
		
		ppu_wait_nmi();

		if(mario_floor<160) if(mario_size>32) --mario_size;
		if(mario_floor>120)
		{
			mario_floor-=2;
		}
		else
		{
			if(!(frame&1))
			{
				if(bright) --bright; else break;
			}
		}
		
		++frame;
	}
	
	while(1)
	{
		oam_clear_fast();
		
		oam_off=0;
		
		ed_display_door(door_frame);
		
		bright=1+door_frame/16;
		
		if(bright>4) bright=4;
		
		pal_spr_bright(bright);
		
		oam_update();
		
		ppu_wait_nmi();
		
		if(door_frame<64) door_frame+=2; else break;
	}
	
	delay(60);
	
	bright=4;
	
	while(bright)
	{
		--bright;
		pal_bright(bright);
		delay(8);
	}
	
	ppu_off();
	
	mmc3_irq_enable(0);
}