program fading_text;
@use "screen/screen"
@use "system/memory"
var  
   	time1, waitTime,x,y,i,j,k,val : byte = 0; 

// @max defines how many texts can be written on the screen at the same time
	const maxx : byte = 6;
	const useKernal : byte = 1;

	// Colors to fade between, one per frame
	colors:  array[] of byte = (0, $06,$06,$09,$0b,$02,$04,$08,$0c,$0e,$0a,$05,$0f,$03,$07,$0d,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$0d,$07,$03,$0f,$05,$0a,$0e,$0c,$08,$04,$02,$0b,$09,$06,$06,$06,$06);
	p:^byte;

	// Current texts, supports @max 
//	text_x, text_y, text_time, text_len:array[max] of byte = (0,0,0,0,0,0);
	textType = record
		x,y,time,len : byte;
	end;

	text : array[maxx] of textType;

	// Pointer to text and color ram
	textPtr, colorPtr:pointer;


	// the text itself: format
	// x,y, "string", 0, pause time
	// terminates with 255, restarts


	demotext: string = (5,10, "TURBO RASCAL", 0,8,
						8,12, "PRESENTS",0,8,
						3,12, "ALPHA", 0,1,
						10,12, "BETA", 0,1,
						18,12, "GAMMA", 0,1,
						10,14, "DELTA", 0,4,

						3,5, "VARIABLE",0,8,
						3,7, "FADING",0,4,
						10,15, "TEXT",0,6,
						20,4, "WITH",0,6,
						8,12, "PAUSES",0,12,
						255);


/*
	Finds an available slot out of @max, checks for time =0

*/

procedure FindAvailableSlot(); // returns j
begin
	j:=0;
	for i:=0 to maxx do begin
		if text[i].time=0 then
		begin 
			j:=i; 
			return(); 
		end;
	end;
end;
	
/*
	Advances the text counter, searches through data and assigns a new slot (out of total @max)
*/
procedure Advance();
begin
	// Finds one out of @max available slots (with time zero)
	FindAvailableSlot(); // Sets j
	// keep x/y position
	x:=textPtr[0];
	y:=textPtr[1];
	text[j].x:=x;
	text[j].y:=y;

	// Set time to size of color list
	text[j].time:=40; // set time
	// Advance to text
	textPtr:=textPtr+2;
	// Move screenmemory pointer to $d800 color ram
	colorPtr := #Screen::color + Screen::tab40[y]+x;
	// Also, move to screen position
	p := #Screen::screen0 + Screen::tab40[y]+x;
	i:=0;
	// Write chars as long as char isn't zero 
	while (textPtr[0]<>0) do begin
		colorPtr[i]:=0; // Should be black!
		val:=textPtr[0];
		if (val>64) then val-=64; // Petscii/c64 codes conversion
		p[i]:=val;
		i+=1;
		textPtr:=textPtr+1;
	end;
	text[j].len:=i; // Set length
	waitTime:=textPtr[1];
	// Pointing to the next
	textPtr:=textPtr+2;
	// If value is 255, then reset text pointer
	if (textPtr[0]=255) then textPtr:=#demotext;
end;

/*
	Called per frame (or second, or whatever)
	Loops through all slots with time>0 and updates color ram. 
	Color should be terminated same as background color, here black

*/
procedure UpdateTextColors();
begin
	for i:=0 to maxx do begin
		if (text[i].time<>0) then begin // is active: update color 
			text[i].time-=1; 
			p := #Screen::color + Screen::tab40[text[i].y]+text[i].x;
			Memory::Fill(p, colors[text[i].time], text[i].len);
		end;
	end; 

end;


/*
	Main update loop, called from the raster
*/
procedure Update();
begin
	time1+=1;
	// Update colors
	UpdateTextColors();
	// Every 7th frame, advance timer
	if (time1&7=0) then 
	begin	
		waitTime-=1;	
		// if wait time is over, advance text pointer and create a new slot
		if (waitTime>127) then 
			Advance();
	end;

end;

// Main raster, enables Update to be called once per raster cycle
interrupt RasterMain();
begin
	StartIRQ(useKernal);
	Update();

	CloseIRQ();
end;

// Main block
begin
	Screen::background:=black;
	Screen::border:=black;
	textPtr:=#demotext;
	Screen::Clear(#Screen::screen0,key_space);
	Screen::Clear(#Screen::color,black);
	
	StartRasterChain(RasterMain(),0,useKernal);
	Loop();
end.
