program skull_charset_image;
var  
   i: byte; 
   t2:byte=64;
/*
	ExportCompressed takes the follow paramters:
	X start, Y start, width, height, compression level
	make sure that the compression level creates a charset that is *lower* than 256, 
	or you'll be missing some chars!

*/

// Compression 30 seems to fit nicely here, with 247 chars exported
@exportcompressed "resources/images/skull.flf" "resources/images/skull.bin" 0 0 40 25  30

   image_screen : incbin("resources/images/skull_screen.bin", $3000);
   image_charset : incbin("resources/images/skull_charset.bin",$2000);

	const screenLoc : address = $4000;
	zp,p1,p2 : ^byte;
	xscroll,yscroll,time : byte;
	siny : 	array[256] of byte = buildtable( "(Math.sin(i/256*3.14159*2)*0x7f + 0x7f)/1.5+30");
	// fast integer i*80 table for screen lookup
	ytab : array[50] of integer = buildtable("i*80");


/*

	Sets up the backbuffer screen by creating a 80x50 buffer with 
	4x offset copies of the 40x25 screen data
	
*/

procedure SetupScreen();
begin
	zp:=#screenLoc;;
	p1:=#image_screen + 12*40;
	p2:=#image_screen;
	for i:=0 to screen_height*2 do
	begin
		//fill(zp,1,20); // first 		
		memcpy(p2,0,zp,screen_width); // first image
		zp:=zp+screen_width;
	
		
		memcpy(p1,0,zp,screen_width); // cneter
		zp:=zp+screen_width;
		
		p2:=p2+screen_width;
		p1:=p1+screen_width;		

		if (i=24 or i=24+25) then p2:=#image_screen;				
		if (i=12 or i=12+25) then p1:=#image_screen;				
	end;

end;

/*
	Copies the data to the screen on each frame
*/

procedure CopyAll();
begin
	for i:=0 to 25 do
	begin
		memcpyunroll(zp,0,p1,40);
		zp:=zp+80;
		p1:=p1+40;
	end;
end;


// Called before each new vertical blank irq. Sets up the pointers for copying
procedure Prepare();
begin
	xscroll:=sine[time];
	yscroll:=siny[t2];
	hideborderx(1);
	hidebordery(1);

	zp:=#screenLoc + xscroll/8;
	zp:=zp +ytab[yscroll/8];
	p1 := $0400;
end;

// Updates x and y time counters
procedure UpdateTime();
begin
	inc(time);
	if (time&1=1) then inc(t2);
end;



// Main raster
interrupt Raster();
begin
	startirq(0);
	// Set scroll registers
	scrolly(7-yscroll&7);
	scrollx(7-xscroll&7);
	// Copy data
	CopyAll();
	// Update time
	UpdateTime();
	// prepare pointers for next round	
	Prepare();
	closeirq();
end;




begin
	SetupScreen();
	setcharsetlocation($2000);
	setmulticolormode();
	
	screen_bg_col:=black;
	screen_fg_col:=0;
	screen_fg_col[2]:=dark_grey;
	screen_fg_col[1]:=grey;
	clearscreen(white|8,^$D800);
	disableciainterrupts();
	setmemoryconfig(1,0,0);
	Prepare();
	
	StartRasterchain(Raster(), 250,0);


	loop();
end.
