Program example14_wave_colors;
@use "demounit"
var
	zp,p1, dataPointer, lumi : pointer;
	time,j,i,k,adv,started : byte = 0;
	
	ti : integer;
	yscroll : byte = 0; // 8
	curCol : byte=1; // 1
	curStart : byte = 0;
	cc,a,b,x,y,isInit : byte = 0;
	cur:byte=0;
	
	shifts : array[4] of byte = (0,8,16,24); // The timing shifts of the waves, cycles every 4
	
	tableData : array[64] of integer;
	tableDiv20 : array[256] of byte = BuildTable("i/20");

	charset2 : incbin("data/wavecolors_charset.bin",$2000);
	data1 : incbin("data/wavecolors_screen.bin",$8000);
	
//   	lumi: array[32] of byte = (0,0,0,0,0,0,$c,6,4,6,3,5,3,7,13);
//   	Black2White: array[16] of byte = (0,0,0,0,0,0,$9,2,8,10,7,1,1,1,1,1);
   	Black2White: array[16] of byte = (0,0,0,0,0,0,6,11,4,14,3,13,1,7,10,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2);

@ifndef IS_DEMO
// music : incsid("../demo_system/music/moskou.sid",2);
@endif


/*
	This effect uses the extended color mode for the C64, i.e. you have 2 colors per colour cell but are
	limited to 64 chars in total.
		
	The compressed image data for this effect is rendered with corresponding .fjo Fjong raytracer file.
	
*/

// This method prints 4 rows of colors and is updated on every 8th cycle

procedure PrintColors();
begin
	// Setup initial position
	zp:=#screen_col_loc+280-curStart-curStart;
	k:=4+curCol;
	for i:=0 to 4 do
	begin
		j:=lumi[k];
		fillfast(zp,j,39);
		zp:=zp+320; // move 8 lines down	
		dec(k);
	end;
end;

	// Set the additional colors for extended color mode
procedure SetExtraCols();
begin
	for i:=0 to 4 do
		poke(^$D021,i, lumi[5-i+curCol]);
end;

/*
 Print initial colors
*/
procedure PrintInitColor();
begin
	zp:=$D800;
	j:=1;
	for i:=0 to 4 do
	begin
		fill(zp,lumi[4-j+curCol],160); 
		zp:=zp+160;
		fill(zp,lumi[4-j+curCol],160); 
		zp:=zp+160;
		inc(j);
	end;
end;
/*
	Advance : increase the scroll counter by 1. When 
	htting 8, reset the scroll and increase the current line by 1 (20).
	Print 4 new lines of colour. 
*/
procedure Advance();
begin
	yscroll:=(yscroll+2)&7;
	if (yscroll=0) then
	begin
		if (curStart=0) then
		begin
			curStart:=140;
			curCol:=curCol+1;
			adv:=1;
				
		end
		else
			curStart:=curStart-20;
			
		PrintColors();
	end;	
end;



/*
	Initialize data
*/

procedure Init(dp,ll : pointer);
begin
	dataPointer := dp;
	lumi:=ll;
	PrintInitColor();
	dec(curCol);
	SetExtraCols();
	
	setcharsetlocation($2000);
	setbank(VIC_BANK0);
	settextmode();
	setregularcolormode();

	// Calculate tables: data pointer. Each frame consists of 320 bytes, so this is 
	//effectively a table of mul 320
	ti:=int2ptr(dataPointer);
	for i:=0 to 64 do
	begin
		tableData[i]:=ti;
		ti:=ti+320;
	end;
	// Table of div 20
//	for i:=0 to 0 do
	//	tableDiv20[i]:=i/20;
end;



procedure Paint(p_col,start,stop:byte);
var 
	p_i, p_j: byte;
begin
	
	p_col := p_col << 6;

	p1:=zp + start*2;
	start:=tableDiv20[start];	
	stop:=tableDiv20[stop];	

 	for i:=start to stop do
	begin
		// Basically a memcpy of the data, but ora with the colour cell value defined in p_col
		asm("
			ldy #39
lpp:
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			lda (p1),y
			ora p_col
			sta (screenmemory),y
			dey
			bpl lpp
		
		");
		// Increase pointers
		p1:=p1+40;
		screenmemory:=screenmemory+40;
	end;

end;

/*
	The main raster!
*/
interrupt Raster();
begin
	startirq(0);
	hidebordery(1);
	i:=peek(^$D011,0);
	poke(^$D011,0,i | %01000000);
	scrolly(yscroll);


	if (started=1) then
		Advance()
	else
		started := 1;
/*	if (time&1=0) then
		Advance();
	*/
	k:=0;
	a:=0;
	b:=2;
	if (time&1=1) then
	begin
		//screenmemory:=$0400 + 364;
		k:=2;
		a:=2;
		b:=4;
	end
	else
		screenmemory:=$0400;
		
	for j:=a to b do begin
		cc:=shifts[(3-j+curCol)&3];		
		cc:=cc&63;
		if (cc=63) then cc:=0; // bug?
		
		zp:=tableData[cc];
		if (j>0 and j<3) then // Center blocks
			Paint(k,0,160);
		
		if	(j=0 and curStart<>160) then // First block
			Paint(k,curStart,160);
			
		if	(j=3) then // Final block
			if (curStart<>0) then		
				Paint(k,0,curStart+20);
		// Advance colour block
		k:=(k+1)&3;
	end;

	// Increase shift positions
	if (time&1=1) then
	begin		
		shifts[1]:=shifts[1]+1;
		shifts[2]:=shifts[2]-1;
		shifts[0]:=shifts[0]+1;
		shifts[3]:=shifts[3]-1;
	end;
	// Add some extra juicy variation to some of the shifts
	if (time&1=7) then
	begin
		shifts[2]:=shifts[2]-1;
		shifts[0]:=shifts[0]+1;
	
	end;
		
	inc(time);
	// Must be called at the end: Update colours (if advancement has been triggered)
	if (adv=1) then 
	begin
		waitforraster(0);
		SetExtraCols();
		adv:=0;
	end;
	@ifndef IS_DEMO
//	call(sidfile_1_play);
	@endif
	@ifdef IS_DEMO
		call(^@callPos);
	@endif

	closeirq();
end;


 
// mainblock
begin
	definescreen();
	@ifndef IS_DEMO
	disableciainterrupts();
	setmemoryconfig(1,0,0);
	@endif
	// Setup 
	Init(#data1,#Black2White);
	// Colors
	@ifndef IS_DEMO
	
	disableciainterrupts();
	preventirq();
	setmemoryconfig(1,0,0);
	i := peek(^$01,0);
	poke(^@keepPos,0,i);
//	initsid(SIDFILE_1_INIT);	
	
	@endif
	screen_bg_col:=black;
	screen_fg_col:=black;
	setcharsetlocation($2000);
	// Initialze blank screen
	clearscreen(1,screen_char_loc);
	// Start raster!
	StartRasterchain(Raster(),16,0);
	DemoUnit::curBorderY := 1;
	poke(^@curBorderY,0,1);
//	DemoUnit::Endd();

	while (true) do
	begin
		@ifdef IS_DEMO
		//call(^@outerCall);
		asm(" 
			jsr @outerCall
			beq pp_cnt
			");
			waitforraster(0);
			scrolly(3);
			asm("			

			jmp $810
pp_cnt:
		
		");
	//	inc(^$D020);
		@endif
	//	waitforverticalblank();
	end;

//	Loop();	

end.

