program DualSidMusicPlayer;
var  

@define spriteLoc $1000
@define data2 $A000
@define colPos $3000

/*

	Music & gfx by Mibri
	Code by Leuat

*/



@export "images/main.flf" "images/main.bin" 0
	data : incbin("images/main_data.bin", $6000);
	image_colors : incbin("images/main_color.bin",@colPos);

	sprites:incbin("data/scroller.bin",$5000);

	music: incsid("music/radiofree.sid",2);
	
	perlin : incbin("data/perlin40.dat");
	
	startWobble : byte = false;
	tp,zp,sp,zp2,p1: pointer;
	ip : integer;
	t,i,j,k,time,time2 , fade,time3,ypos : byte = 0;
	curSpriteCol : byte=0;

	const targetSpriteCol : byte = 13;
	// Flashing colors
	lumi:  array[33] of byte = ($00,$06,$09,$0b,$02,$04,$08,$0c,$0e,$0a,$05,$0f,$03,$07,$0d,$01,$0d,$07,$03,$0f,$05,$0a,$0e,$0c,$08,$04,$02,$0b,$09,$06,00,0,0);
	cols: array[256] of byte;


// Initialize colors
procedure InitCols();
begin
	for i:=0 to 0 do begin
		j:=i/2;
		// Remove *16 to get background colors
		cols[i]:=lumi[j]*16;

	end;

end;

// Moves "PAL" sprites
procedure UpdateSprites();
begin
	ip:=108;
	i:=time3&15;
	setspriteloc(0, (@spriteLoc)/64 + i,1);
	i:=(time3+3)&15;
	setspriteloc(1, @spriteLoc/64 + i+$10,1);
	i:=(time3+7)&15;
	setspriteloc(2, @spriteLoc/64 + i+$20,1);
	i:=(time3+3)&15;
	setspriteloc(3, @spriteLoc/64 + i+$30,1);
	i:=(time3+1)&15;
	setspriteloc(4, @spriteLoc/64 + i+$10,1);
	k:=time2*4;
	for i:=0 to 5 do begin
		j:=sine[k]/8 + ypos;
		spritepos(ip,j,i);
		ip:=ip+32;
		k:=k-32;
	end;
	i:=lumi[curSpriteCol];
	fill(SPRITE_COLOR,i,8);
	if (time2&1=0) then
	if (fade>20) then 
	begin
		if (curSpriteCol<targetSpriteCol) then
			inc(curSpriteCol);
	end;
	
	ypos := 128+sine[time]/4;
end;

procedure fillBox(fx, fy, w, h,v : byte);
begin
	zp2:=$4400 + fx +fy*40;
	for i:=0 to h do
	begin
		fill(zp2,v,w);
		zp2:=zp2+40;
		
	end;
	
end;


interrupt RasterTwo();


procedure SetupMibriData(tpos:byte);
begin
	p1:=$B000;
	zp:=$0400;
	zp:=zp+tpos;
	
//	zp:=zp+40;
	
end;
/*
	Copies NO unrolled lines of data for the logo wobble
*/
procedure CopyMibriData(no:byte);
begin
	for i:=0 to no do
	begin
		memcpyunroll(p1,0,zp, 22);
		p1:=p1+22;
		zp:=zp+40;
	end;		
end;

/*
	Raster where scrolling stops, go back to bitmap mode,
	shift bank to 1
*/
interrupt RasterTwoFive();
begin
	startirq(0);
	scrollx(0);
	vic_data_loc:=$18;
	setbank(vic_bank1);
	setbitmapmode();
	RasterIRQ(RasterTwo(),156,0);

	closeirq();
end;



// Main raster routine, called every frame
interrupt RasterMain();
begin
	startirq(0);
	//if (curBank=0) then setbank(VIC_BANK0) else setbank(VIC_BANK1);

	call(sidfile_1_play);	
	if (startWobble=1) then
	begin
		setbank(VIC_BANK0);
		setcharsetlocation($2000);
		setregularcolormode();
		settextmode();

		t:=sine[time2]/2;
		SetupMibriData(t/8 +1);
		i:=sine[time2*2]/8;
		i:=lumi[i]*16;
		fillBox(0,8,15,9,i);		

	end;
	
	RasterIRQ(RasterTwoFive(),114,0); // org 118
	inc(time2);
	if (time2&1=0) then inc(time3);
	closeirq();
end;

/*
	Lower part of the raster: Play the sid a 2nd time. 
	Also updates sprites and colours
*/
interrupt RasterTwo();
begin
	StartIRQ(0);
//	setbank(VIC_BANK1);
	scrollx(0);
	call(sidfile_1_play);	

	// Copy 8 lines of image data for the wobble
	if (startWobble=1) then
		CopyMibriData(8);	
		
	UpdateSprites();

	if (startWobble=1) then
	begin
		i:=sine[time2*2+64]/8;
		i:=lumi[i]*16;
		fillBox(25,8,15,9,i);		
	end;
		i:=(t)&7;	
		scrollx(i);

	RasterIRQ(RasterMain(),0,0);

	closeirq();
end;





// Update colors, performed in main loop. "Fades" from black to the color defined in the image.
procedure UpdateColorsIn();
var
	jj,ii,curCol : byte = 0;
begin
	// moveto
	screenmemory:=$4400;
	tp:=$D800;
	zp:=@colPos+2;
	sp:=#perlin;
	for jj:=0 to 12 do begin
		for ii:=0 to 83 do begin
			asm("

			ldy ii
			lda (sp),y
			sbc curCol
			sta $50
			cmp #64
			bcs cont2
			tax
			lda cols,x
			sta (screenmemory),y
			jmp jadda
cont2:		lda $50
			cmp #240
			bcc jadda
			lda (zp),y
			sta (screenmemory),y
			lda (zp2),y
			sta (tp),y

jadda:
			
");
					
		end;
		zp:=zp+83;
		zp2:=zp2+83;
		screenmemory:=screenmemory+83;
		sp:=sp+83;
		tp:=tp+83;
	end;
	
//	if (time&3=0) then if curCol<16 then inc(curCol);
end;


procedure InitSprites();
begin
	SPRITE_BITMASK:=%00011111;
	sprite_color[0]:=blue;
	sprite_color[1]:=purple;
	sprite_color[2]:=cyan;
	sprite_color[3]:=light_red;
	sprite_color[4]:=green;
	SPRITE_MULTICOLOR:=0;
	
end;



// Generate the charset used in the upper part for the "mibri"
procedure GenerateCharset();
begin
	p1 := @data2;
	p1:=p1 + 9*8;
	zp:=$2000;
	zp:=zp+tpos*8;
	
	for i:=0 to 8 do
	begin
		memcpy(p1,0,zp,22*8);
		p1:=p1+320;
		zp:=zp+22*8;
	end;	
	

end;

// Generates the "Mibri" screen from characters
procedure GenerateScreen();
begin
	clearscreen(0,^$B000);
	p1:=$B000;	
	k:=0;
	for i:=0 to 8 do
	begin
		for j:=0 to 22 do
		begin
			p1[j]:=k;
			inc(k);
		end;
		p1:=p1+22;
	end;
	
end;


procedure UpdateMainScreen();
begin
	// Curcol starts at 0, then increases to 250
	while( true) do begin
		inc(time);
		if (time&7=1) then inc(fade);
		if (startWobble=false) then
			UpdateColorsIn();
		if (fade>12) then 
		begin
			if (curCol<250) then curCol:=curCol+4
			else begin
			 	if (startWobble=false) then
			 	begin
			 		clearscreen(white*16,^$4400);
			 		clearscreen(white,^$D800);
			 		clearscreen(0,^$0400);
			 		time2:=128;
				end;
				startWobble:=true;
			end;
		end;
			
		waitforraster(0);
	end;
end;



begin
	DefineScreen();
	screen_bg_col:=black;
	screen_fg_col:=black;
	
	disableciainterrupts();
	setmemoryconfig(1,0,0);
	initsid(sidfile_1_init);
	blockmemcpy(^$6000,^@data2,16);
	// Convert the upper part of the screen to a charset
	GenerateCharset();
	// Draw the screen
	GenerateScreen();
	// Set up sprites
	InitSprites();
	
	StartRasterChain(RasterMain(),0,0);
	
	InitCols();
	clearscreen($00,^$D800);
	clearscreen($00,^$4400);
	clearscreen($00,^$0400);
	setbitmapmode();
	UpdateMainScreen();

end.
