program Fullscreen_Scroller;
var 

/*
	This tutorial is based on chardata cycling, as presented in tutorial 12. 
	
	Whatever is going on here:
		- decrease the 8-pixel wide hardware scroll register
		- if the scroll value is zero: 
			- reset to 7
			- spend lots of cycles copying*all* screen data 1 column to the right 
			- draw a new row of random (perlin noise) data at the leftmost column on the screen
		- whenever the scrollr register is *not* zero, perform the character set shift to create a plasma effect
		
*/
	const useKernal:byte = 1;
// Use character 64 as base+16 in the charmap (check out resources/charset/charset.flf)
	const charVal:byte= 64;
// Place 40x25 noise data at a random position
	const noisePos : address = $8000;
	const charsetLoc : address =  $2000;

// include data
   	noiseData: incbin("resources/data/perlin40.dat",noisePos); 
	charset: incbin("resources/charsets/charset.bin",charsetLoc);   
// scroll register
	scroll : byte=0;
// pointers used for copying data
	src,dst:pointer;
	
	i, curColumn : byte = 0;
	
/*
	PrintData prints a single column of perlin data on the 39th column on the screen
	The "curColumn" variable is used to determine where in the data we currently are
*/
procedure PrintData();
begin
// point dst to 39th column of screen
	dst:=#screen_char_loc+screen_width-1;
// src to the current column of the noise data
	src:=#noiseData;
	src+= curColumn;
	// print 25 rows
	for i:=0 to screen_height do begin
		// divide by some value
		dst[0]:=src[0]/8 + charVal-5;
		// Goto next row
		dst+=screen_width;
		src+=screen_width;
	end;
	curColumn+=1;
	if (curColumn=screen_width) then curColumn:=0;
end;


procedure CopyScreen();
begin
	src:=#screen_char_loc+1;
	dst:=#screen_char_loc;
	for i:=0 to screen_height do begin
		memcpyunroll(src,0,dst,screen_width-1);	
		src+=screen_width;
		dst+=screen_width;
	end;
end;

procedure UpdateScroll();
begin
	if (scroll) then 
		dec(scroll)
	else 
	begin
		scroll:=7;
		CopyScreen();
		PrintData();
	end;
end;

procedure ShiftCharsetData();
begin
	// We copy 16 characters * 8 bytes each 128 byte from the original point in memory @charsetLoc  + 8*@charVal
	// 8 bytes to the rigth, cycling the characters
	memcpy(charsetLoc+charVal*^8, 0, charsetLoc+charVal*8+128,8);
	memcpy(charsetLoc+charVal*^8+^8, 0, charsetLoc+charVal*8,128);

end;


interrupt RasterMain();
begin
	StartIRQ(useKernal);
	if (scroll&1=1) then	
		ShiftCharsetData();	

	UpdateScroll();
	scrollx(scroll);
	
	CloseIRQ();
end;	
	

begin
	// Hide column 0 and 39!
	hideborderx(1);
	setcharsetlocation(charsetLoc);
	StartRasterChain(RasterMain(),100,useKernal);
	Loop();
end.
