program ClearThatScreen;
@use "screen/screen"
var  
   	i,j,k,l,m,c2x: byte; 

	zp,p1,l1: pointer;
	// Fade colors
	colorsc1 : array [] of byte = (  0, 11,6,12,12,4,14,15,7,1,7,6,   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6  );
	// border fade colors
	colorsc2 : array [] of byte = (  0, 11,6,12,12,4,14,14,14,   14,14,14,14,14,14,14,14,14  );
	// 16x16=256 byte perlin noise data	
	orgperlin:incbin("resources/data/perlin16.dat");	

// Random place to store 1000 bytes
	const dataLoc : address = $5000;	
// Turn off to un-optimize
@define IS_OPTIMIZED 1

procedure CalculateCircles();
begin
	zp:=#dataLoc;
	// Since perlin noise repeats every 16 bytes, we add a higher frequency noise with a shifted phase	
	for j:=0 to Screen::height do begin
		for i:=0 to Screen::width do begin
			m:=j&15;
			// lookup : val := x+y*16 with x,y confined to 0..15
			l:=i&15+m*16;	
			
			// Original phase
			k:=orgperlin[l]/8;
			m:=(j/2); 
			l:=(i/2)+m*16; // half phase
			// This is where we add the half phase to make it look random
			k:=k+orgperlin[l+133]/8;
//			k:=k+sine[i+j]/8;
			zp[i]:=k/2+8; 
		end;
		zp:=zp+Screen::width;
	end;
end;

/*
	Performs the actual perlin noise effect. 
	Both optimized and unoptimized version are included.
*/
procedure PerformPerlin();
begin
	zp:=#Screen::screen0;
	p1:=#Screen::color;
	l1:=#dataLoc;
		


	for j:=0 to Screen::height do begin
		for i:=0 to Screen::width do begin
		
@if IS_OPTIMIZED=0
			k:=l1[i];
			if (k) then begin
				dec(k);
				l1[i]:=k;
				p1[i]:=colorsc1[k];
			end;		
@endif
@if IS_OPTIMIZED=1
			asm("
				ldy i
				lda (l1),y
				beq pp_cont
				sec
				sbc #1
				sta (l1),y
				tax
				lda colorsc1,x
				sta (p1),y
pp_cont:
");			
@endif
		end;
		p1:=p1+Screen::width;
		l1:=l1+Screen::width;
//		inczp(zp,40);
	end;

end;


begin
	Screen::Clear(#Screen::color, blue);
	Screen::Clear(#Screen::screen0, $A0);
	CalculateCircles();
	c2x:=16;
	while(true) do begin
		Screen::WaitForVerticalBlank();
		if (c2x<127) then begin
			Screen::bg_col:=colorsc2[c2x];
			c2x-=1;
		end;
		PerformPerlin();
	end;

end.
