program MegaScroller;
//
var
	// Various
	c,val,time,i, scroll,scrollsplit,val2,k : byte = 0;
	
	charset: IncBin("charsets/charset_8x8.bin","$2800");
	charset1_2: IncBin("charsets/charset_8x8.bin","$6800");
	charset2: IncBin("charsets/charset_16x16.bin","$A000");
	
	// Scroll shift
	shiftx: byte;
	// Scroller y amplitude
	text: string=( "THIS ",
	"IS A SCROLLER   "); // ends with a zero
	
	// Banking vars
	
	g_currentBank:byte = 0;
	g_dataLoc : byte=$1a;
	
	textp: pointer;
	zeropage1:pointer;
	
	// Turn ON of off KERNAL (0/1)
	@define useKernal "1"
	
	
	@define clearVal "$20"
	
	// Define some text pointers
	@define textpointer textp
	
	
	/*
	
	This tutorial basically takes a 2x2 charset and converts bit information in the character map
	to a 16x16 char image.
	
	As with tutorial 8-9, we render off-screen on an alternate bank, and perform half-page
	copying on various stages of the scroll. When the scrolling resets, we flip banks and start
	over again.
	*/
	
	
	/*
	Copies half upper/lower screen to 1 char left
	
	*/
procedure CopyHScreen(ul_:byte);
begin
	if g_currentBank=0 offpage then begin
		if ul_=0 then
			copyhalfscreen(^$0400 + ^520, ^$4400 -^1 + ^520,12, 1,0)
		else
			copyhalfscreen(^$0400, ^$4400 -^1, 13, 1,0);
		
	end;
	if g_currentBank=1 offpage then begin
		if ul_=0 then
			copyhalfscreen(^$4400+^520, ^$0400 - ^1 + ^520, 12, 1,0)
		else
			copyhalfscreen(^$4400, ^$0400 - ^1,13, 1,0);
	end;
	
end;

/*
Switches between bank 0 and 1
*/
procedure SwitchBank();
begin
	if g_currentBank=0 then
		SetBank(VIC_BANK1)
	else
		SetBank(VIC_BANK0);
	
	poke(VIC_DATA_LOC, 0, g_dataLoc);
	
	g_currentBank:=(g_currentBank+1)&1;
end;


/*
Performs the rendering of the 16x16 text, split into 1x8 + 1x8 vertical lines for each stage (shiftx)
	*/

procedure WriteText();
begin
	moveto(0,4,val);
	screenmemory[39]:=$20;
	moveto(0,5,val);
	if (scroll>127) then begin // if scroll<0, trigger a new line to draw
		val:=@textpointer[0]; // Look up current char
		if (val<>$20) then begin
		if (val>64) then val:=val-65; // Look up in charmap
			zeropage1:=charset2;
		if val>16 then val:=val+24;   // Align chars (for this particular font)
			
		// point to the correct char in memory, each char is 2x2 x 8 bytes, so 16 bytes in total
		
		if (val<>0) then
			for i:=0 to val do inczp(zeropage1, 16);
		
		
		
		// val2 here is the actual character to draw, 74 is semi-filled char
		val2:=168-shiftx+scrollsplit;
		// Scrollsplit decides whether we use the first (0) char in a letter or the second (8)
		inczp(zeropage1, scrollsplit);
		// Draw upper 8 chars
		for i:=0 to 8 do begin
			// Default is blank
			c:=$20;
			if (getbit(zeropage1[i], shiftx)=1) then c:=val2;
//			c:=val2;
			screenmemory[39]:=c;
			inczp(screenmemory,40);
			
		end;
		// The next char is located 1 row below, so 40*8 = 320 = 160x2 bytes ahead
		inczp(zeropage1, 160);
		inczp(zeropage1, 160);
		// Repeat drawing
		for i:=0 to 8 do begin
			c:=$20;
			if (getbit(zeropage1[i], shiftx)=1) then c:=val2;
			screenmemory[39]:=c;
			inczp(screenmemory,40);
			
		end;
		end
		else begin
				c:=$20;
			for i:=0 to 16 do begin
				screenmemory[39]:=c;
				inczp(screenmemory,40);
			
			end;

		end;
		
		dec(shiftx);
		if (shiftx>127) then begin // if shift is less than zero
			shiftx:=7; // Reset value
			// Do we increase text pointer or just shift +8 bytes to draw next part of 2x2 char?
			if (scrollsplit=0) then scrollsplit:=8
				else begin
				// Reset and increase text pointer!
				scrollsplit:=0;
				inczp(@textpointer,1);
				if @textpointer[0]=0 then @textpointer:=text;
			end;
			
		end;
		// Reset scroll
		scroll:=7;
	end;
	
	
end;

interrupt Raster1();
begin
	StartIRQ(@useKernal);
	SetMemoryConfig(0,1,1,1,0);	

	@ifdef displayRasterTime
	SCREEN_BG_COL:=GREEN;
	@endif
	
	inc(time);
	
	scroll:=scroll - 2; // Scroll speed
	scrollx(scroll);
	
	
	val:=$04;
	if g_currentBank=0 then val:=$44;
	
	WriteText();
	
	if scroll=1 then CopyHScreen(0);
	if scroll=3 then CopyHScreen(1);
	
	
	if (scroll=7) then SwitchBank();
	
	hideborderx(1);
	
	SCREEN_BG_COL:=BLACK;
	
	
	@ifdef displayRasterTime
	SCREEN_BG_COL:=BLACK;
	@endif

//	SCREEN_BG_COL:=RED;

	CloseIRQ();
end;

/* Empty NMI */
interrupt NMI();
begin
end;

begin
	//	HideborderY(0);
	// Set color background
	SCREEN_BG_COL:=BLACK;
	SCREEN_FG_COL:=BLACK;
	// Set charmap location at $3000
	VIC_DATA_LOC := $1A;
	// Clear screen and color memory
	ClearScreen(64, SCREEN_CHAR_LOC);
	ClearScreen(@clearVal, ^$4400);
	ClearScreen(@clearVal, ^$0400);
	ClearScreen(LIGHT_BLUE, SCREEN_COL_LOC);
	
	@textpointer:=text;
	
//	setmulticolormode();
	MULTICOLOR_CHAR_COL[1]:=LIGHT_BLUE;
	MULTICOLOR_CHAR_COL[2]:=CYAN;
	shiftx:=7;
	scrollsplit := 0;
	// Hook the raster
	hideborderx(0);
	StartRasterChain(Raster1(),1,@useKernal);
	Loop();
end.

