const unsigned char roll_palette[16]={ 0x0f,0x01,0x11,0x21,0x0f,0x15,0x10,0x30,0x0f,0x00,0x10,0x30,0x0f,0x06,0x17,0x28 };

#define ERO_HEIGHT		40		//multiple of five
#define ERO_DONE_DELAY 	60*2

const unsigned char credits_large_font[64]={
	0x00,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x4f,0x49,0x4a,0x48,0x00,
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x47,0x00,0x00,0x46,0x00,0x00,
	0x4d,0x0b,0x0c,0x0d,0x0e,0x0f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,
	0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x40,0x41,0x42,0x43,0x44,0x00,0x00,0x00,0x00,0x00
};


//0 small, 1 small with underscore, 2 large, 3 large another color

const char roll_text[]={
"\n"
"0     YOU HAVE JUST WATCHED\n"
"0   AN OLDSCHOOL ONE MAN FAST\n"
"0  PROD MADE OF CODE LEFTOVERS\n"
"0      AND REHASHED IDEAS:\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"3       H E O H  D E M O\n"
"\n"
"1        PARTY__EDITION\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"1             CAST\n"
"2         DONDY  DENDY\n"
"2        VADERS  INVADERS\n"
"2    CIRCLEGRAM  PAC-MAN\n"
"2         DIRDY  KIRBY\n"
"2         SHASH  RASH\n"
"2       JANITOR  MARIO\n"
"2     GUO XIANG  VID\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"1           FEATURES\n"
"2         SPOOF ON AON\n"
"2           TV NOISE\n"
"2         ZOOMING BARS\n"
"2        ROTATING CHARS\n"
"2         PIXEL VADERS\n"
"2        ANIMATED 3DLOGO\n"
"2         FLIPPING CART\n"
"2          HUGE CIRCLE\n"
"2        FALLING PICTURE\n"
"2         TOWER OF FAME\n"
"2         PSEUDO3D MAZE\n"
"2        WARPY TEXT ROLL\n"
"2         PSEUDOSCALING\n"
"2         SOFTWARE DPCM\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"1         POWERED__WITH\n"
"2         CC65 AND CA65\n"
"2          FAMITRACKER\n"
"2         GRAPHICS GALE\n"
"2             FCEUX\n"
"2           NESTOPIA\n"
"2             PUNES\n"
"2             MESEN\n"
"2            NOTEPAD++\n"
"2       OPENOFFICE WRITER\n"
"2        NES SCREEN TOOL\n"
"2       NES SPACE CHECKER\n"
"2        VC++2008 EXPRESS\n"
"2         SDL2 LIBRARY\n"
"2              HXD\n"
"2              GIMP\n"
"2             RJDMC\n"
"2             REAPER\n"
"2            WAVOSAUR\n"
"2            BLENDER\n"
"2           IFRANVIEW\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"0     ALL ICONIC VIDEO GAME\n"
"0    REFERENCES IN THIS PROD\n"
"0    SERVE COMIC EFFECT ONLY\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"1          PRODUCED_BY\n"
"2             SHIRU\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"2    THANK YOU FOR WATCHING!\n"
"\n"
"\n"
"0       CC0 MOSCOW MMXIX\n"
"0      FOR CAFE2019 PARTY\r"
};


unsigned int sine_table[]={
	0,12,25,37,49,62,74,86,97,109,120,131,142,152,162,171,181,189,197,205,212,219,225,
	231,236,241,244,248,251,253,254,255,256,255,254,253,251,248,244,241,236,231,225,
	219,212,205,197,189,181,171,162,152,142,131,120,109,97,86,74,62,49,37,25,12
};


const char* roll_set_row(const char *text,unsigned char row)
{
	unsigned char i,c,c1,c2,off,color;
	unsigned int adr;

	c=*text;
	
	if(c>=32)
	{
		color=(*text++-'0')&3;
	}
	else
	{
		color=0;
	}
	
	if(row<30) adr=NTADR_A(0,row); else adr=NTADR_C(0,row-30);
	
	update_list[0]=MSB(adr)|NT_UPD_HORZ;
	update_list[1]=LSB(adr);
	update_list[2]=32;
	
	adr+=32;
	
	update_list[35]=MSB(adr)|NT_UPD_HORZ;
	update_list[36]=LSB(adr);
	update_list[37]=32;

	for(i=0;i<32;++i)
	{
		c=*text;
		
		if(c>=32)
		{
			c-=32;
			
			if(color>=2)
			{
				c1=credits_large_font[c];
				c2=c1+16;
			}
			else
			{
				c1=0x60+c;
				
				if(color&&c) c2=0x80; else c2=0;
			}
			
			++text;
		}
		else
		{
			c1=0;
			c2=0;
		}
		
		update_list[ 3+i]=c1;
		update_list[38+i]=c2;
	}
	
	if(row<30)
	{
		adr=NAMETABLE_A+960+((row>>2)<<3);
	}
	else
	{
		adr=NAMETABLE_C+960+(((row-30)>>2)<<3);
	}

	update_list[70]=MSB(adr)|NT_UPD_HORZ;
	update_list[71]=LSB(adr);
	update_list[72]=8;
	
	color=color|(color<<2)|(color<<4)|(color<<6);
	
	while(row>=30) row-=30;

	off=73;
	
	if(!(row&2))
	{
		color&=0x0f;
		
		for(i=0;i<8;++i)
		{
			update_list[off]=(update_list[off]&0xf0)|color;
			
			++off;
		}
	}
	else
	{
		color&=0xf0;
		
		for(i=0;i<8;++i)
		{
			update_list[off]=(update_list[off]&0x0f)|color;
			
			++off;
		}
	}
	
	update_list[off]=NT_UPD_EOF;
	
	if(*text=='\n') ++text;
	
	return text;
}



void e_roll(void)
{
	unsigned char i,off,row_dst,roll,fade,frame,bright;
	unsigned int py,ny,offx,offd,scroll_y,scroll_dy,wait;
	const char *text;
	
	mmc3_chr_bank(CHR_FONT+0,0);
	mmc3_chr_bank(CHR_FONT+2,1);

	mmc3_set_mirroring(M_HORIZONTAL);
	
	set_irq_handler(IRQ_ROLL_FADE);
	set_nmi_handler(NMI_NORMAL);
	
	vram_adr(NAMETABLE_A);
	vram_fill(0,1024);
	vram_adr(NAMETABLE_C);
	vram_fill(0,1024);
	
	pal_bg(roll_palette);
	
	memfill(update_list,NT_UPD_EOF,sizeof(update_list));
	memfill(split_list,0,sizeof(split_list));
	
	text=roll_set_row(roll_text,0);

	frame=0;
	bright=4;
	roll=TRUE;
	fade=FALSE;
	wait=ERO_DONE_DELAY;
	scroll_y=0;
	scroll_dy=64;
	
	offx=0;
	offd=0;
	
	for(i=0;i<ERO_HEIGHT;++i)
	{
		offd+=1;
		offx+=offd;
		
		off=(sine_table[i]*(offx>>2))>>9;
		
		if(i&1) off=-4-off; else off=-4+off;

		split_list[ERO_HEIGHT-1-i]=off;
		split_list[ERO_HEIGHT+i]=off;
	}
	
	mmc3_irq_enable(240-ERO_HEIGHT+1);
	
	pal_bright(0);
	ppu_on_bg();

	while(1)
	{		
		py=scroll_y>>(6+4);
		
		scroll_y+=scroll_dy;
	
		if(scroll_y>=(480<<6)) scroll_y=0;
		
		ny=scroll_y>>(6+4);
		
		if(ny!=py)
		{
			row_dst=((ny<<1)+30);
			
			while(row_dst>=60) row_dst-=60;
			
			text=roll_set_row(text,row_dst);

			if(*text=='\r') roll=FALSE;
		}
		
		if(!roll) if(!(frame&1)) if(scroll_dy) --scroll_dy;
		
		scroll(-4,scroll_y>>6);

		pal_bright(bright);
		
		set_vram_update();
		
		ppu_wait_nmi();

		if(!scroll_dy&&!fade)
		{
			if(wait) --wait; else fade=TRUE;
		}
		
		if(fade)
		{
			if(!(frame&7))
			{
				if(bright) --bright; else break;
			}
		}
		
		++frame;
	}

	ppu_off();
}
