program part7_RenderLevel;
var  
/*
	In this tutorial, we combine part 3 (sprites) with level rendering

*/


// levels are loaded to/from $5000
@define levelPosition $5000
// User $2000 for charset (vic 0)
@define charsetPosition $2000
// Turn off kernal
@define useKernal 0

   	charset1: incbin("charsets/charset1.bin", @charsetPosition);
	// Sprite locations as in part 3 (at $3200)
	mySprites:incbin("sprites/sprites.bin", $3200);
	levels: incbin("levels/level1.flf", @levelPosition);

	colors, levelpointer, colormemory : pointer;
	i,j:byte = 0;
	curLevel_x, curLevel_y : byte=0;

	// Player position x and y. x must be integer since the sprite x coordinate can vary between 0 and 320
	player_x: integer;
	player_y: byte;

// Max / min movement position for player sprite x,y	
	@define miny 66
	@define maxy 210
	@define minx 16
	@define maxx 320 

	// Let's always use sprite "0" as our player sprite
	@define playerSprite 0

@define colorpointer colormemory

// RasLib contains all level rendering routines
@include "../../RasLib/levels.ras"

// Sets up sprite
procedure InitMainSprite();
begin
	// Set sprite position at bank 0 to $C8=$3200/64
	setspriteloc(@playerSprite,$C8,0);
	player_x:=80;
	player_y:=120;
	// Set sprite x,y pos
	spritepos(player_x,player_y,@playerSprite);

	// Turn on only player sprite
	SPRITE_BITMASK:=%00000001;

 	// All sprites are multicolor
	SPRITE_MULTICOLOR:=$FF;
	SPRITE_MULTICOLOR_REG1:=LIGHT_GREEN;
	SPRITE_MULTICOLOR_REG2:=GREY;

	SPRITE_COLOR[@playerSprite]:=RED;
end;

// This method initializes charset data, and is similar to the one in part 6
procedure Initialize();
begin
	clearscreen(LIGHT_BLUE, ^$D800);
	clearscreen($20, ^$0400);
	SCREEN_BG_COL:=BLACK;
	SCREEN_FG_COL:=BLACK;
	// Pointer to character color definitions
	colors:=$2800;

	MULTICOLOR_CHAR_COL[1]:=GREY;
	MULTICOLOR_CHAR_COL[2]:=BROWN;

	setmulticolormode();

	setcharsetlocation(@charsetPosition);

	levelpointer:=@levelPosition;
	ReadHeader();
end;

/*	
	Traverselevels checkes whether the player has moved close to a border.
    If true, then the neighbouring screen is loaded and the player sprite is placed
	on the opposite part of the screen. 

*/
procedure TraverseLevels();
var 
   redraw:byte=0;
begin
	redraw:=0; // don't redraw

	if (player_x<@minx) then begin
		if (curLevel_x<>0) then begin
			// decrease level counter
			dec(curLevel_x);
			// move player x to the other side of the screen
			player_x:=@maxx-1;
			redraw:=1;
		end
		else
			player_x:=@minx+1;
	end;
	if (player_x>@maxx) then begin
		if (curLevel_x+1<>m_rl_width) then begin
			inc(curLevel_x);
			player_x:=@minx+1;
			redraw:=1;
		end
		else 
			player_x:=@maxx-1;

	end;

	if (player_y<@miny) then begin
		if (curLevel_y<>0) then begin
			dec(curLevel_y);
			player_y:=@maxy-1;
			redraw:=1;
		end
		else
			player_y:=@miny+1;
	end;
	if (player_y>@maxy) then begin
		if (curLevel_y+1<>m_rl_height) then begin
			inc(curLevel_y);
			player_y:=@miny;
			redraw:=1;
		end
		else
			player_y:=@maxy-1;
	end;



	if redraw=1 then begin
		levelpointer:=@levelPosition;
		RenderCharsetColorLevel(curLevel_x,curLevel_y,$04);
	end;


end;

/*
	 Moves the player
*/
procedure MovePlayerSprite();
begin
	joystick(2);
	player_x:=player_x+joystickright-joystickleft;
	player_y:=player_y+joystickdown-joystickup;
	spritepos(player_x,player_y,@playerSprite);
end;


// Main raster function: Contains all high-level procedure calls to sprite & entity handling
interrupt RasterRenderLevels();
begin
	StartIRQ(@useKernal);
	setbank(VIC_BANK0);
	MovePlayerSprite();	
	TraverseLevels();


	CloseIRQ();
end;



// Main block
begin
	Initialize();
	InitMainSprite();

	levelpointer:=@levelPosition;
	RenderCharsetColorLevel(curLevel_x,curLevel_y,$04);
	// Turn off all interrupts
	DisableCIAInterrupts();
	// Turn off kernal
	SetMemoryConfig(1,@useKernal,0);
	// Set up raster IRQ
	RasterIRQ(RasterRenderLevels(),$00,@useKernal);
	EnableRasterIRQ();
	enableirq();
	Loop(); 
end.
