procedure wait_vbl();
var
	@use "crt"
begin

	
end;


procedure cls();
var

begin
	ClearScreen($20, screen_char_loc);
	moveto(0,0,hi(screen_char_loc));
end;

function _ti(): integer;
var 
	ti_temp: integer;
begin
	ti_temp:=0;
    ti_temp := ti_temp + (peek(#$8D,0)*256*256);
	ti_temp := ti_temp + (peek(#$8E,0)*256);
 	ti_temp := ti_temp +  peek(#$8F,0);
	_ti:=ti_temp;

end;

procedure uppercase();
begin
	poke(#$E84C,0,12);
end;

procedure cursor_home();
begin

	_A:=19;
    call(#$FFD2);

end;

procedure cursor_clear();
begin

	_A:=147;
    call(#$FFD2);

end;

procedure cursor_return();
begin

	_A:=13;
    call(#$FFD2);

end;

procedure cursor_down();
begin

	_A:=17;
    call(#$FFD2);

end;

procedure cursor_graphic();
begin

	_A:=142;
    call(#$FFD2);

end;

procedure basic_print(_ptr:pointer;);
var
	next_ch: byte;
begin

	next_ch:=0;
	while(_ptr[next_ch]<>0) do
	begin 
		_A:=_ptr[next_ch];
    		call(#$FFD2);
    		inc(next_ch);
	end;
	
	cursor_return();
	cursor_down();

end;

// Tests for Rom 4 explicitly
function is_rom_4(): byte;
begin
	// Register check
	if(peek(#$91,0) & $F0 = $E0) then begin 
		returnvalue(true); 
	end;
	// Alternate test
	if(peek(^50003,0) = 160) then
	begin
		returnvalue(true); 
	end; //4.0 ROMS
	
	// Pretty sure not v4 at this point
	returnvalue(false); 
end;


// Hacky way to check for 80 column screen
function is_80_columns(): byte;
var  
	char: byte; 
	test_string:string=(147,17,43);
	screen_pointer: pointer;
begin
	
	screen_pointer:=$8000;

	for char:=0 to 3 do
	begin
		_A:=test_string[char];
	    call(#$FFD2);
	end;
	
    if(screen_pointer[80]=43) then
    begin
    		returnvalue(true);
    end
    else
    begin
    		returnvalue(false);
	end;
	
end;

procedure sleep_delay();
var 
	_old_ti, _new_ti: integer;
	
begin

    _new_ti :=_ti();
    _old_ti :=_new_ti;
    
	while(_new_ti=_old_ti) do
	begin
 	    _new_ti :=_ti();
	end;

end;

procedure frame_delay();
var
	sleepx:byte;
begin
	fori sleepx:=1 to 2 do
	begin
		sleep_delay();
	end;

end;


function getkey() : byte;
var
	_ks,_itk:byte;
	_this_k: integer;

begin
	Key::SetupScreenCodes();
	Key::Read();
	_ks:=0;
	while(_ks = 0 ) do
	begin
		Key::Read();
		_ks:=Key::keyState;
		_this_k := Key::GetHeld();
	end;	

	fori _itk:=0 to 2 do begin sleep_delay(); end;
	getkey:=_this_k;

end;


function getat(sx: byte; sy: byte;) : byte;
var 
	szp : pointer;

begin
	szp:= $8000 + sy*40 + sx;
	getat:=szp[0]; 
end;

procedure textat(x: byte; y: byte; this_str: pointer; str_len: byte );
var 
	zp : pointer;

begin
	zp:= $8000 + y*40 + x;
	MemCpyFast( this_str, 0, zp, str_len ); 
end;


procedure numberat(num_x: byte; num_y: byte; num: integer; num_len: byte );
var 


begin
	moveto(num_x,num_y,hi(#$8000));
	printdecimal(num, 4);
	
end;

// =========================================
// SOUND!

procedure PlayNote(note : byte, note_len : byte);
var
 note_duration: byte;
begin
	if(PLAY_SOUND=1) then
	begin
		SOUND_FREQ := note;
		for note_duration:=0 to note_len do wait(200);
	end;
end;

procedure burp();
begin
	SOUND_OCTAVE := 15;
	SOUND := SOUND_ON;
	PlayNote(238,255);
	SOUND := SOUND_OFF;
end;

procedure ping();
begin
	SOUND_OCTAVE := 85;
	SOUND := SOUND_ON;
	PlayNote(238,200);
	PlayNote(251,200);
	PlayNote(210,255);
	PlayNote(210,255);
	SOUND := SOUND_OFF;
end;

// =========================================

procedure ScrollY();
var
	c_row,p_row:pointer;
	scroll,scrolls: byte;
begin
    for scrolls:=1 to 25 do 
    begin    
	p_row:=#$8000;
	c_row:=p_row+40;
	    fori scroll:=1 to 25 do 
	    begin
	        MemCpyFast( c_row, 0, p_row, 40 ); 	       
	    		p_row:=p_row+40;
    	    		c_row:=p_row+40; 
	    end;
	    fillfast(c_row,$20,40);
    		Crt::WaitVblStart();	
	end;

end;


procedure help_screen();
var
	hks:byte;
	help_screen_pointer:pointer;
	  
begin
	
	// Set up pointer to array:
	help_screen_pointer:=#help_screen_array;
	hks:=0;
	cls();

	// Draw the frog
	CopyFullScreen(help_screen_pointer, #$8000);
	
 
	Key::SetupScreenCodes();
	Key::Read();
	hks:=Key::keyState;
	while(hks=0) do
	begin
		Key::Read();
		hks:=Key::keyState;
		sleep_delay();
	end;
	
	ScrollY();

end;

procedure title_screen();
var
	ctr,slide:byte;
	              //12345678901234567890
    	inst0:cstring=(98,98,98,98,98,98,32);
	inst1:cstring=(220,139,133,153,147,186,98,98,98,32);
	inst2:cstring=(220,160,160,160,160,151,160,221,160,32);
	inst3:cstring=(220,160,160,160,129,147,132,221,160,32);
	inst4:cstring=(220,160,160,160,192,192,192,253,160,32);	
	inst5:cstring=(220,160,160,160,160,184,160,221,160,32);
	inst6:cstring=(220,160,160,160,180,181,182,221,160,32);
	inst7:cstring=(32,32,32,124,226,226,226,226,32,32);	
begin
	
	// Set up pointer to array:
	title_screen_frog_pointer:=#title_screen_frog;
	ks:=0;
	cls();

	// Draw the frog
	CopyFullScreen(title_screen_frog_pointer, #screenmemory);
	
    MemCpyFast(#logo, 0, ^32768, 13 );  
    MemCpyFast(#logo, 13, ^32808, 13 );  
    MemCpyFast(#logo, 26, ^32848, 13 );  
    MemCpyFast(#logo, 39, ^32888, 13 );  

	textat(0,13,#inst0,7);
	textat(0,14,#inst1,10);
	textat(0,15,#inst2,10);
	textat(0,16,#inst3,10);
	textat(0,17,#inst4,10);
	textat(0,18,#inst5,10);
	textat(0,19,#inst6,10);
	textat(0,20,#inst7,10);
	
	textat(2,21,#blk,28);
	textat(2,22, #by,28);	
	textat(2,23,#url,28);	


	Key::SetupScreenCodes();
	Key::Read();
	ks:=Key::keyState;

	while(ks=0) do
	begin
		Key::Read();
		ks:=Key::keyState;


			Key::Read();
			ks:=Key::keyState;
			textat(4,24,#space2,25);	
			frame_delay();


			Key::Read();
			ks:=Key::keyState;
			textat(4,24,#space,25);
			frame_delay();


			Key::Read();
			ks:=Key::keyState;
			textat(4,24,#blk,25);
			frame_delay();

			Key::Read();
			ks:=Key::keyState;
			textat(4,24,#help,25);	
			frame_delay();

			

			Key::Read();
			ks:=Key::keyState;
			textat(4,24,#help2,25);	
			frame_delay();


			Key::Read();
			ks:=Key::keyState;
			textat(4,24,#blk,25);
			frame_delay();

	end;
	
	ScrollY();
	help_screen();

end;


procedure score_screen();
begin
	cls();

	if(WON_GAME=1) do
	begin	
		petscii_pointer:=#success;
	end
	else
	begin	
		petscii_pointer:=#rip;
	end;
	CopyFullScreen(petscii_pointer, #$8000);

    MemCpyFast(#logo, 0, ^32768, 13 );  
    MemCpyFast(#logo, 13, ^32808, 13 );  
    MemCpyFast(#logo, 26, ^32848, 13 );  
    MemCpyFast(#logo, 39, ^32888, 13 );  

	moveto(13,0,hi(#$8000));
	printstring(#over,0,13);
		
	moveto(13,1,hi(#$8000));
	printstring(#score,0,13);
	
	moveto(25,1,hi(#$8000));
	printdecimal(player_score,3);		

	Key::Read();
	ks:=Key::keyState;

	while (ks=0) do
	begin
		Key::Read();
		ks:=Key::keyState;
		textat(14,24,#space,23);
		frame_delay();
		Key::Read();
		ks:=Key::keyState;
		textat(14,24,#space,23);
		frame_delay();
		Key::Read();
		ks:=Key::keyState;
		textat(14,24,"                       ",23);		
		frame_delay();
		Key::Read();
		ks:=Key::keyState;
		textat(14,24,"                       ",23);		
		frame_delay();
	end;
	ScrollY();
end;

procedure sprite_xy(spr_x: byte; spr_y: byte; source_str: pointer; spr_len: byte );
var 
	spr_p : pointer;

begin
	spr_p:= #level_strips + spr_y*80 + spr_x;
	MemCpyFast( source_str, 0, spr_p, spr_len ); 
	spr_p:= #level_strips + spr_y*80 + spr_x+39;
	MemCpyFast( source_str, 0, spr_p, spr_len ); 
end;

procedure init_vars();
var
	this_row,target_strip:pointer;
	iteration:byte;
	homeplate:byte=211;

begin
	cls();
	FROGS_SAVED:=0;	
	GAME_SPEED:=8;
	Key::SetupScreenCodes();
	
	// Init the playfield
	screenmemory := $8000;
	petscii_pointer:=#level2;
	CopyFullScreen(petscii_pointer, #screenmemory);
	this_row:=petscii_pointer;
	target_strip:=#level_strips;

	// Obstacle Blanks
	fori iteration:= 1 to 25 do
	begin
		// Copy the source twice
		MemCpyFast(this_row, 0, #target_strip, 40);
		target_strip:=target_strip+40;
		MemCpyFast(this_row, 0, #target_strip, 40);
		target_strip:=target_strip+40;
		
		// Next row
		this_row:=this_row+40;
	end;
							

	// Init the "sprites"
	MemCpy(#arr_crockr, 0, #str_crockr, 9 ); 
	MemCpy(#arr_crockl, 0, #str_crockl, 9 ); 
	MemCpy(#arr_logl, 0, #str_logl, 5 ); 
	MemCpy(#arr_logr, 0, #str_logr, 5 ); 
	MemCpy(#arr_turtles, 0, #str_turtles, 5 ); 
	MemCpy(#arr_river_r, 0, #str_river_r, 5 ); 
	MemCpy(#arr_river_l, 0, #str_river_l, 5 ); 	
	
	MemCpy(#arr_truckt_r, 0, #str_truckt_r, 8 ); 
	MemCpy(#arr_truckb_r, 0, #str_truckb_r, 8 ); 
	MemCpy(#arr_carl, 0, #str_cart, 4 ); 
	MemCpy(#arr_carr, 0, #str_carb, 4 ); 

	// "Sprite" start positions
	sprite_xy(10,obstacles_y[0],#str_crockr,9);
	sprite_xy(24,obstacles_y[0],#str_logr,5);
		
	sprite_xy(30,obstacles_y[1],#str_crockl,9);
	sprite_xy(5,obstacles_y[1],#str_logl,5);
		
	sprite_xy(04,obstacles_y[2],#str_logr,5);
	sprite_xy(14,obstacles_y[2],#str_logr,5);
	
	sprite_xy(24,obstacles_y[3],#str_logl,5);
	sprite_xy(34,obstacles_y[3],#str_logl,5);
	
	sprite_xy(10,obstacles_y[4],#str_turtles,5);	
	sprite_xy(20,obstacles_y[4],#str_turtles,5);	
	sprite_xy(30,obstacles_y[4],#str_turtles,5);	

	sprite_xy(8,obstacles_y[5],#str_cart,4);
	sprite_xy(8,obstacles_y[6],#str_carb,4);

	sprite_xy(34,obstacles_y[5],#str_cart,4);
	sprite_xy(34,obstacles_y[6],#str_carb,4);
	
	sprite_xy(19,obstacles_y[7],#str_cart,4);
	sprite_xy(19,obstacles_y[8],#str_carb,4);
	sprite_xy(29,obstacles_y[7],#str_cart,4);
	sprite_xy(29,obstacles_y[8],#str_carb,4);

	
	sprite_xy(10,obstacles_y[9],#str_truckt_r,8);
	sprite_xy(10,obstacles_y[10],#str_truckb_r,8);

	sprite_xy(19,obstacles_y[11],#str_truckt_r,8);
	sprite_xy(19,obstacles_y[12],#str_truckb_r,8);
	sprite_xy(32,obstacles_y[11],#str_truckt_r,8);
	sprite_xy(32,obstacles_y[12],#str_truckb_r,8);

	frog_x:= 20;
	frog_y:= 24;
	
	KEYPRESS := 0;
	ALIVE:=1;
	WON_GAME:=0;
	
	player_lives:=3;
	player_score:=0;
	
	// Home plates
	textat(3,1,#homeplate,1);
	textat(10,1,#homeplate,1);
	textat(18,1,#homeplate,1);
	textat(24,1,#homeplate,1);
	textat(31,1,#homeplate,1);
	textat(37,1,#homeplate,1);
end;

procedure move_obstacles();

begin
	// TRSE way of incrementing 
	// counter with loop back to 0
	incRange(obstacles_x_rl, 0, 39);
	obstacles_x_lr:=39-obstacles_x_rl;
end;

procedure move_traffic();

begin
	// TRSE way of incrementing 
	// counter with loop back to 0
	incRange(traffic_x_rl, 0, 39);
	traffic_x_lr:=39-traffic_x_rl;
end;


procedure frog_ride();
var
	char_under: byte;
	
begin
	char_under := getat(frog_x,frog_y);

	// Ride turtles and logs etc
	case char_under of
	
			81: 
	        	  begin
	        	  		if(frog_x>0) then
					begin
						dec(frog_x);
					end;
	           end;

			168: // (
	        	  begin
	        	  		if(frog_x<38) then
					begin
						inc(frog_x);
					end;
	           end;

			169:	 // ) 
	        	  begin
	        	  		if(frog_x>0) then
					begin
						dec(frog_x);
					end;
	           end;

			220: // Crock body 
	        	  begin
	        	  		if(frog_x<38 and frog_y>4) then
					begin
						inc(frog_x);
					end;
	
	        	  		if(frog_x>0 and frog_y=4) then
					begin
						dec(frog_x);
					end;
	           end;	
	end;
end;
	
procedure show_obstacles();
var
	strip_num,this_strip:byte;
	this_source_offset:pointer;
	game_move:byte;
begin

	// Sets traffic speed
	if(mod(GAME_TICKS,GAME_SPEED/2)=0) then
	begin
		move_traffic();
	end;	
	
	// Update obstacles positions
	if(mod(GAME_TICKS,GAME_SPEED)=0) then
	begin
		// Update obstacles positions
		move_obstacles();
		game_move:=1;
	end
	else
	begin
		game_move:=0;
	end;

	// "Scroll" each line of obstacle according to direction
	for strip_num := 0 to 5 do
	begin
		this_strip:=obstacles_y[strip_num];
		screenmemory:=$8000+(this_strip*40);

		this_source_offset:=#level_strips+(this_strip*80);
		
		if(strip_direction[strip_num]=1) then
		begin
			this_source_offset:=this_source_offset+obstacles_x_rl;
		end
		else
		begin
			this_source_offset:=this_source_offset+obstacles_x_lr;
		end;
		
		MemCpyFast(this_source_offset, 0, screenmemory, 40); 


	end;
	
	for strip_num := 5 to 13 do
	begin
		this_strip:=obstacles_y[strip_num];
		screenmemory:=$8000+(this_strip*40);
		this_source_offset:=#level_strips+(this_strip*80);
		
		if(strip_direction[strip_num]=1) then
		begin
			this_source_offset:=this_source_offset+traffic_x_rl;
		end
		else
		begin
			this_source_offset:=this_source_offset+traffic_x_lr;
		end;
		
		MemCpyFast(this_source_offset, 0, screenmemory, 40); 


	end;
	
	if(game_move=1) then
	begin
				
		// Is the frog riding an object?
		frog_ride();	
	end;

	// RESET SCREEN MEMORY
	screenmemory := $8000;

end;

procedure kill_frog();
begin
	textat(frog_old_x,frog_old_y, #previous_tile,1);
	textat(frog_x,frog_y, #next_tile,1);
	previous_tile:=32;
	next_tile:=32;
	frog_x:= 20;
	frog_y:= 24;
    frog_old_x:=frog_x;        
    frog_old_y:=frog_y;
    burp();	
	dec(player_lives);
end;

procedure check_collisions();
var

begin
		// CHECK COLLISSIONS
		next_tile := getat(frog_x,frog_y);


		// There is no function to search a string
		// or check an array, or return array size,
		// so we need to check each character individually
		case next_tile of

		// Can't occupy where already landed
			frogcharA:
			  begin
	        	  	if(frog_y<24) then
	        	  	begin
		             frog_x:=frog_old_x;
		             frog_y:=frog_old_y;
		        end;
	           end;
			frogcharB:
			  begin
	        	  	if(frog_y<24) then
	        	  	begin
		             frog_x:=frog_old_x;
		             frog_y:=frog_old_y;
		        end;
	           end;	           
		// Scenery
	        $66: 
	        	  begin
	        	  	if(frog_y<24) then
	        	  	begin
		             frog_x:=frog_old_x;
		             frog_y:=frog_old_y;
		        end;
	           end;

	        $68: 
	        	  begin
	             frog_x:=frog_old_x;
	             frog_y:=frog_old_y;
	           end;
	           
	        $5c: 
	        	  begin
	             frog_x:=frog_old_x;
	             frog_y:=frog_old_y;
	           end;


		// Water kills the frog for some reason?

	        32: 
	        	  begin
	        	  		if(frog_y<9 and frog_y >3 ) then
					begin
						kill_frog();
					end;
	           end;


		// Traffic!
	        $F0: 
	        	  begin
				kill_frog();
	           end;

	        215: 
	        	  begin
				kill_frog();
	           end;

            $ED: 
	        	  begin
				kill_frog();

	           end;
	        $EE: 
	        	  begin
				kill_frog();

	           end;

	        $FD: 
	        	  begin
				kill_frog();

	           end;
	           
	        96: 
	        	  begin
				kill_frog();

	           end;
	        
	        243: 
	        	  begin
				kill_frog();

	           end;
	        
	        235: 
	        	  begin
				kill_frog();

	           end;	
	                   
	        240: 
	        	  begin
				kill_frog();

	           end;

		// Crock!
			198: 
	        	  begin
				kill_frog();
					
	           end;

			162: 
	        	  begin
				kill_frog();
	           end;

		// HOME
			// Occupied
			214: 
	        	  begin
	             frog_x:=frog_old_x;
	             frog_y:=frog_old_y;
	           end;
			// Success
			211: 
	        	  begin
	        	  	if(frog_x<>frog_old_x or frog_y<>frog_old_y ) then
				begin
					player_score:=player_score+100;
					inc(FROGS_SAVED);
					ping();
										
					if(FROGS_SAVED=6) do
					begin
						// Yay you won!
						WON_GAME:=1;
					end
					else
					begin
						frog_x:= 20;
						frog_y:= 24;
						frog_old_x:=frog_x;
						frog_old_y:=frog_y;
					end;
				end;
	           end;


	    else
	    begin


	    end;
end;


