program MusicUnitDemo;
@use "Music"
@use "crtc"

// Good old plasma example with 3 channel music!

var  
	// some plasma variables
	val,val2,c2x, c2y,ax, ay,time, time2 : byte;
	x,y,shift : byte;
	dst : ^byte;
	// mini sine table
	const width : byte = 512/8;
	const height : byte = 64/2;	
	// The tables must be aligned at $xx00
    siny : array[width] of byte at $7F00; 
	sinx : array[height] of byte at $7E00; 
	// Org sine table
	sin : array[256] of byte = buildsinetable(127);
 	// smooth data generated in resources/fjong/generate_data.fjo
	data : incbin("data/smooth_data.bin", $7D00);

//	Read the following
//
//	This Music Player release contains the original implementation manual and the description of the music format in a PDF document:
//		http://tvc.hu/cas/2024/Szalontai_B%c3%a9la(Fast&Force)/FF_Music_Player_Source.zip
//	This package contains a SID converter for TVC including GUI for Windows
//		http://tvc.hu/cas/2024/Util/SidDumpTvcGUI_v1.1.zip
//		SIDDumpTVC (c) by Béla Szalontai, 2023-2024
//		SIDDumpTVCGUI (c) by Károly Kiss, 2023-2024
//	Here you can find 58000+ SID music
//		https://deepsid.chordian.net/
//		https://www.hvsc.c64.org/downloads
//	Recommended SID crator/editor/tracker for Windows: GoatTracker 2.76
//		https://sourceforge.net/projects/goattracker2/files/GoatTracker%202/2.76/
//	Other SID trackers
//		https://chordian.net/c64editors.htm
//
//  Steps for creating MUSIC:
//	1. download a .sid music or create a new one with one of the trackers
//	2. convert .sid file into .bin using SIDDumpTVCGUIv1.1.exe
//	3. include the .bin converted music to your TRSE app...

	music_1_data : incbin("data/music_test1_sid.bin");	// music with disabled loop
	music_2_data : incbin("data/music_test2_sid.bin");	// music with enabled loop
	bg_color: byte = 1;

// Plasma procedure
procedure Calculate();
begin
	c2x:=ax;
	c2y:=ay;
	
	// Set up y-sine table
	for x:=0 to height do begin 
		siny[x]:=  sin[c2x] + sin[c2y]-time2;
		c2x:=c2x+2;
		c2y:=c2y+5;
	end;

	ax:=ax+2;
	ay:=ay-3;

	// Set up x-sine table
	for x:=0 to width do begin 
		sinx[x] := sin[c2x] + sin[c2y];
		c2x:=c2x+3;
		c2y:=c2y+7;

	end;
	// alternate every 2nd line
	dst:=$8000+shift<<7 + 128*32;
end;

procedure Plasma();
begin
	for y:=0 to height  offpage do 
	begin
		val:=siny[y];
		//unrolled
		asm("
			ld de,[dst]
			ld a,[val]
			ld b,a
			repeat 64
			
			ld hl,sinx +[i]
			
			ld a,b  ; a = val
			add a,[hl] ; a+ sinx[x]
			; lookup table data [ ...]
			ld hl,data
			ld l,a ; +data[a]
			
			ldi ; ld [de],[hl], inc de
			
			repend
		
		");
		dst+=64*4;
	end;
end;

begin
	// test non blocking music player @5008Hz interrupt frequency
	// music is not looped
	Music::Init(Music::INTERRUPT_FREQ_5008);
	Music::Play(#music_1_data, Music::BPM_SID_5008, Music::GRAPHICS_MODE_4);
	
	Crtc::SetMode(Crtc::mode_4_color);
	Crtc::EnableVRAM();
	Crtc::SetPalette(0,Crtc::black);
	Crtc::SetPalette(1,Crtc::dark_blue);
	Crtc::SetPalette(2,Crtc::dark_magenta);
	Crtc::SetPalette(3,Crtc::green);
	
	// Clear full screen
	Fill($8000,0,64*240);
	while (Music::IsMusicFinished() = 0) do
	begin
		Calculate();
		time2+=5;
		time+=1;
		shift:=time&1;
		Plasma()
	end;
	Music::Stop();
	
	Crtc::SetMode(Crtc::mode_16_color);

	// test non blocking music player @8491Hz interrupt frequency		
	// music is looped
	Music::Init(Music::INTERRUPT_FREQ_8491);
	Music::Play(#music_2_data, Music::BPM_SID_8491, Music::GRAPHICS_MODE_16);
	
	while(True) do 
	begin
		Fill($8F00,bg_color,64*132);
		Inc(bg_color);
	end;
end.
