program Tutorial_19;
var  
   a,b,i,j,val,idx,y,x,dx,dy,col,k,c2,l,m,t: byte; 
   p1, zp,l1,t1,tp,val2: pointer;

	ms_scroll, ms_shift, scroll:byte=0;


	posx: array[64] of byte=
	(3,4,4,3,2,2,2,3,4,5,5,5,5,4,3,2,1, 1, 1, 1, 1, 2,3,4,5,6, 6,6,6,6,6, 5,4,3,2,1,0,  0,0,0,0,0,0,     
	1,2,3,4,5,6); 
	posy: array[64] of byte=
	(3,3,4,4,4,3,2,2,2,2,3,4,5,5,5,5,5, 4, 3, 2 ,1, 1,1,1,1,1, 2,3,4,5,6, 6,6,6,6,6,6,  5,4,3,2,1,0,  
	0,0,0,0,0,0) ;

	c,time,c2x, c2y,ax, ay : byte;
	// Use custom charset
	// nice colors
	fade : array [256] of byte;// = (11,6,12,12,4,14,15,1,15,14,4,12,12,6,11,14,4,15,1,15,14,4,12,12,6,11); 
	add:byte=0;

	// mini sine table
	sine2: array[256] of byte;

	effect: byte = 0;

	cnt,colorTick:byte=0;

	text: string= " TUTORIAL 19 SCROLLER TEXT      ";

	circles: incbin("images/circles.bin", "$3000");
	lines: incbin("images/lines.bin", "$3800");
	charset: IncBin("charsets/tutorial19_charset.bin","$4000");

	pText, rtext:pointer;	


	@define scrollerLineY 14
	@define screen_hi $44

	@define useKernal 0

	@define starty "4"


/*
	Generates a charset of 100 chars with increasing number of pixels.
	Unfolds like a snake with x/y coords given from
	posx, posy

*/

procedure GenerateCharset();
begin

	clearscreen($00,^$2000);
	clearscreen($00,^$2300);


	zp:=$2008;
	for i:=0 to 100 do begin

		cnt:=i+1;
		if cnt>49 then begin	
			cnt:=100-i;
//			cnt:=49;
		end;
		for j:=0 to cnt do begin
			y:=posy[j];
			x:=posx[j];
			togglebit(zp[y],x,1);
		end;

		inczp(zp,8);
	end;



end;
/* 

Main tunnell effect. Playing around with some random stuff. After
having found some nice parameters, convert to assembler. Original code 
in comments. 

Draws at $0400, but checkes whether value at $4400 is not zero

*/

procedure Tunnel();
begin
	
	a:=6;
	b:=8;
	// Pointer locations
	p1:=^$3000+^@starty*^40+^2;
	l1:=^$3800+^@starty*^40+^2;
	zp:=^$D800+^@starty*^40+^2;
	rtext:=^$4400+^@starty*^40+^2;
	screenmemory:=^$0400+^@starty*^40+^2;

	// Some random values
	c:=time*2;
	c2:=sine[time];
	// Point to text
	t1:=text;

	t:=time*5;
	m:=time*2;

	for y:=@starty to 22 do begin
/*		for x:=0 to 240 do begin
			asm(";startt");
			c:=rtext[x];
			if (c=0) then begin
				c2:=sine2[l1[x]+m];
				screenmemory[x]:=(p1[x]+t+c2)&127;
				zp[x]:=fade[c2];

			end
			else
			begin
				screenmemory[x]:=add;
				zp[x]:=YELLOW;
			end;
			asm(";endd");*/
	// Only call effect on certain y values (every 4th line updated each frame)
	k:=(effect+y/4-1)&1;
	if (k=0) then
asm("
	ldy #34

outer:
	lda (rtext),y
	
;	sta c
;	cmp #0
	bne elseblock20820
ConditionalTrueBlock29938

	lda (l1),y
	
	adc m
	 ; end add / sub var with constant
	
	tax
	lda sine2,x

	tax

	sta c2

	adc (p1),y
	
	adc t

	and #127
	
	sta (screenmemory),y

	lda fade,x
	
	sta (zp),y

	jmp elsedoneblock29672
elseblock20820

	lda add
	sta (screenmemory),y

	lda #7
	sta (zp),y

elsedoneblock29672
	; 
	; ****** Inline assembler section

	dey
	bne outer
");
			
//		end;
		// Increase x by 40 (next row)
		inczp(screenmemory, 40);
		inczp(p1, 40);
		inczp(zp, 40);
		inczp(l1, 40);
		inczp(rtext,40);
	end;


end;

/*
	Draws "text" off screen (at $4400) that will be used as a lookup
*/

procedure DrawText();
begin
	// if scroll<0
	//if (ms_scroll>127) then 
		val:=pText[0];
		moveto(0,@scrollerLineY, @screen_hi);
		if val>64 then val:=val-64;

		// Unpacked font position
		zp:=charset;
		if (val<>0) then
			for i:=0 to val do inczp(zp, 8);

//		if (val<>$20) then
		for i:=0 to 8 do begin
			c:=$0;
			if (getbit(zp[i], 7-ms_shift)=1) then c:=30;
			screenmemory[38]:=c;
			inczp(screenmemory,40);		
		end;

		inc(ms_shift);
		if (ms_shift=8) then begin
			ms_shift:=0;
			inczp(pText,1);
			if (pText[0]=0) then pText:=text;

		end;
		//ms_scroll:=7;
	
end;

procedure SetColor(sc_a, sc_b, sc_c:byte);
begin
	for i:=0 to 0 do begin
		
		fade[i]:=sc_a;
		if j=0 then fade[i]:=sc_b;
		if j=1 then fade[i]:=sc_c;

		dec(k);
		if (k=0) then begin
			k:=4;
			inc(j);
			if j=3 then j:=0;

		end;
		// optimized sine tab
	end;


end;




interrupt Raster1();
begin
	StartIRQ(@useKernal);
		time:=time+1;

	if (effect=2) then begin
		inc(scroll);
		if (scroll=2) then begin
		DrawText();
		// Copy memory: scroll
		memcpy(^$4400+^@scrollerLineY*^40,0,^$4400+^@scrollerLineY*^40-^1,160);
		memcpy(^$4400+^@scrollerLineY*^40+^160,0,^$4400+^@scrollerLineY*^40-^1+^160,160);
		scroll:=0;
		end
		else
		begin
			if colorTick=4 then SetColor(DARK_GREY,DARK_GREY, DARK_GREY);
			if colorTick=6 then SetColor(DARK_GREY, DARK_GREY, BLUE);
			if colorTick=8 then SetColor(DARK_GREY, BLUE, LIGHT_GREY);
			if colorTick=10 then SetColor(BLUE, PURPLE, LIGHT_BLUE);

			if colorTick=22 then SetColor(DARK_GREY, BLUE, LIGHT_GREY);
			if colorTick=24 then SetColor(DARK_GREY, DARK_GREY, BLUE);
			if colorTick=26 then SetColor(DARK_GREY,DARK_GREY, DARK_GREY);

		    if colorTick=28 then colorTick := 0;

			if (colorTick<>255) then
				inc(colorTick);
		end;
		
	end;
	if effect<2 then
		Tunnel();
//	SCREEN_BG_COL:=GREEN;
	SCREEN_BG_COL:=BLACK;
		add:=49;//sine[8*time+128]/8+24;

	inc(effect);
	if (effect=3) then effect:=0;


	closeirq();
end;

interrupt NMI();
begin


end;



procedure TweakTabs();
begin
	zp:=circles;
	for y:=0 to 25 do begin
		for x:=0 to 40 do
			zp[x]:=zp[x]*12;
		inczp(zp,40);	
	end;

	j:=0;
	k:=4;
	// Create color tab

	for i:=0 to 0 do 
		sine2[i]:=sine[i]/2;


end;


procedure Initialize();
begin
	SetCharsetLocation($2000);
	SCREEN_BG_COL:=BLACK;
	SCREEN_FG_COL:=BLACK;
	clearscreen($00,^$0400);
	clearscreen($00,^$4400);
	clearscreen(LIGHT_BLUE, ^$D800);
	GenerateCharset();
	cnt:=0;
	idx:=0;
	TweakTabs();
	SetColor(BLACK, BLACK, BLACK);
	hideborderx(1);
	pText:=text;

end;


begin
	Initialize();

	SetMemoryConfig(1,@useKernal,0);

	StartRasterChain(Raster1(),0,@useKernal);
	Loop();

end.
