program PlasmaExample;
@use "system"
@use "memory"
@use "screen"
@use "compression/compression"




// Good old plasma example!

var  
	// some plasma variables
	val,val2,c2x, c2y,ax, ay,time, time2 : byte;
	x,y,shift : byte;
	dst : ^byte;
	// mini sine table
	const width : byte = 40;
	const height : byte = 50;	
	// The tables must be aligned at $xx00
    siny : array[height] of byte;
	sinx : array[width] of byte; 
	// Org sine table
	sin : array[256] of byte = buildsinetable(200);
 	// smooth data generated in resources/fjong/generate_data.fjo
	data : incbin("data/smooth_data.bin");

// Plasma procedure

procedure Calculate();
begin
	c2x:=ax;
	c2y:=ay;
	
	// Set up y-sine table
	for x:=0 to height unroll do begin 
		siny[x]:=  sin[c2x] + sin[c2y]-time2;
		c2x:=c2x+2;
		c2y:=c2y+5;
	end;

	ax:=ax+2;
	ay:=ay-3;

	// Set up x-sine table
	for x:=0 to width unroll do begin 
		sinx[x] := sin[c2x] + sin[c2y];
		c2x:=c2x+9;
		c2y:=c2y+13;

	end;
	// alternate every 2nd line
	dst:=#Screen::gfx + shift*40;
end;




@define FAST 1


procedure Plasma();
begin
	for y:=0 to height  offpage do 
	begin
		val:=siny[y];
@if FAST=0
		// Unrolled code. toggle by setting FAST to 0 or 1
		for x:=0 to width do 
		begin
			dst[x]:=data[ byte(sinx[x] +val) ];;
		end;
@else
		
		asm("
		ldx #sinx
		ldu dst
		ldy #data+128  
			");
		// write 10 * 4 = 40 byte unrolled

		for val:=0 to 40 unroll do
		asm("
		lda ,x+ 
		adda val
		lda a,y
		sta ,u+
		");
@endif		
		dst+=40*4;
	end;

end;

begin
	System::Init();
	// 320x225 4-colour 
	Screen::SetBitmapMode(Screen::BPL_40, 1);
	Screen::SetColor(0,0); // black
	Screen::SetColor(1,$b); // from flf image
	Screen::SetColor(2,$1c); 
	Screen::SetColor(3,$33); 
	// Clearscreen
	Memory::Fill16(#Screen::gfx,0,40*225);
	while (true) do
	begin
		Calculate();
		time2+=5;
		time+=1;
		shift:=time&3;
		Plasma()
		
	end;

end.
