Program SpriteScroller;
@use "tables/luminosities"
var
	zp,tp, p1,ep,time: pointer;
	i,j,k,col : byte;
	temp2: array[256] of byte;


/*
	In this tutorial we first use the 2x2 font to generate
	sprite data for A-Z. We therefore start off by copying the 2x2 (16x16 pixel) blocks to the 24x21 pixel sprite blocks.

	There are max 8 sprites displayed on the screen at any time, and the sprites are "recycled" when leaving the screen. 
*/





	const maxTextSprites : byte = 8;

	// Variables for holding sprite values
	// x and y
	textSprite_x:array[maxTextSprites] of byte;
	textSprite_y:array[maxTextSprites] of byte;
	// Current color
	textSprite_col:array[maxTextSprites] of byte;
	textSprite_status:array[maxTextSprites] of byte;
	textSprite_t:array[maxTextSprites] of byte;
	textSprite_cnt:byte=0;
	ms_x: integer;
	
	scrollerText : string=(" THIS IS A NICE SPRITE SCROLLER TEXT  ",0);

	colorsGreen : array [16] of byte = (  11,11,5,12,13,13,15,7,  7,15,13,13,12,5,11,11  );

	
	const useKernal:byte = 0;

// Position of included charset
@define charsetLoc $1400

@export "resources/charsets/charset_16x16.flf" "resources/charsets/charset_16x16.bin" 256

	charset : incbin("resources/charsets/charset_16x16.bin", @charsetLoc);

// Position of generated chars (right after)
@define generatedSpritesLoc $2800
// Sprite loc on vic bank

@define spriteScrollerWaviness 16

@define spriteScrollerYPos 170

@define spriteTextColor colorsGreen


// Generates sprite data from 16x16 font 

procedure GenerateSprites();
begin
	// Place at p1
	// Org at zp
	tp:=zp;
	// Let tp point to the "next" line in character data (8 bytes *40 chars = 320 )
	tp:=tp+320; 
	// Loop through all 26 characters A-Z
	for k:=0 to 26 do begin 
		fill(p1, 0, 64); // Clear sprite data  

		j:=0;
		// There are 8x4 = 32 bytes of data that we use (the rest of the sprite is unused)
		for i:=0 to 8 do begin
			p1[j]:=zp[i]; 
			p1[j+1]:=zp[i+8];
			p1[j+24]:=tp[i];
			p1[j+25]:=tp[i+8];
			j:=j+3;
		end;
		// Advance sprite pointer
		p1:=p1+64;
		// Advance pointers to font data
		zp:=zp+16;
		tp:=tp+16;
		// at character 15, set new font positions
		if (k=15) then begin
			zp:=zp+384;
			tp:=tp+384;//64+160+160 down
		end;
		
	end;
end;

// Maintains the sprites : moving them, setting y pos, color,turns off
procedure Maintain16x16Sprites();
begin
	col:=0;
	for i:=0 to maxTextSprites do 
	begin
		if (textSprite_status[i]=1) then 
		begin
			textSprite_x[i]:=textSprite_x[i] -1;
			k:=textSprite_t[i];
			textSprite_y[i]:=@spriteScrollerYPos + temp2[k];
			ms_x:=textSprite_x[i]*2;
			spritepos(ms_x, textSprite_y[i], i);
			textSprite_t[i]:=textSprite_t[i]+3;
		//	if (time&1=1) then 
				inc(textSprite_col[i]);
//			waitnoraster(1);
			k:=textSprite_col[i]&15;
			sprite_color[i]:= @spriteTextColor[k];

//			poke(SPRITE_COLOR,i, fadeGreen[k]);
			if (textSprite_x[i]>250) then begin
				togglebit(sprite_bitmask,i,0);
				textSprite_status[i]:=0;
			end;
		end;
	end;
	

end;

// Renews a new sprite (from text), called whenever a sprite leaves the screen and a
// new one is chosen

procedure Renew16x16Sprites();
begin
	inc(textSprite_cnt);
	if (textSprite_cnt<24) then return();
	textSprite_cnt:=0;

	k:=ep[0];
	if (k=key_space) then  // skip on $20
	begin
		ep:=ep+1;
		if (ep[0]=0) then ep:=#scrollerText;
		return();
	end;
	if (k>64) then begin
		k:=k-64-1;
		j:=255;
		// Find a slot for the sprite
		for i:=0 to maxTextSprites do 
			if textSprite_status[i]=0 then j:=i;
		
		if (j<>255) then begin
			textSprite_x[j]:=176;
			textSprite_status[j]:=1;
			togglebit(sprite_bitmask, j, 1);
			textSprite_col[j]:=0;
			setspriteloc(j, @generatedSpritesLoc/64 +k, 0);
			textSprite_t[j]:=time;
			ep:=ep+1;
		end;

	end;
end;



// Initializes sprites and generates sprite data
procedure Init16x16Sprites();
begin
	zp:=@charsetLoc;
	p1:=@generatedSpritesLoc;
	GenerateSprites();

	sprite_bitmask:=$00;
	sprite_stretch_X:=$FF;
	sprite_stretch_Y:=$FF;

	fill(#textSprite_status,0,maxTextSprites);
	// Set up sine function
	for i:=0 to 0 do
		temp2[i]:=sine[i]/@spriteScrollerWaviness;

end;

// Main raster
interrupt RasterMain();
begin
	StartIRQ(useKernal);
	inc(time);

	Renew16x16Sprites();
	Maintain16x16Sprites();
	closeIrq();	
end;

// Main routine
begin
	PreventIRQ();
	disableciainterrupts();	
	setmemoryconfig(1,useKernal,0);
	clearscreen(key_space,screen_char_loc);
	screen_bg_col:=black;
	screen_fg_col:=black;
	Init16x16Sprites();
	ep:=#scrollerText;
	StartRasterChain(RasterMain(),0,@useKernal);
	Loop();
end.