program Tutorial7;
@use "system/z80cpm"
@use "system/screen"
@use "system/tiles"
@use "system/system"
@use "system/graphics"

@addemulatorparam "-nothrottle"

var
	@deletefile "images/tiles.bin"	
	@exportsubregion "images/tiles.flf" "images/tiles.bin"  0 112 16 16 // invad 1A
	@exportsubregion "images/tiles.flf" "images/tiles.bin" 32 112 16 16 // invad 1B
	@exportsubregion "images/tiles.flf" "images/tiles.bin"  0 128 16 16 // invad 1A
	@exportsubregion "images/tiles.flf" "images/tiles.bin" 32 128 16 16 // invad 1B
	@exportsubregion "images/tiles.flf" "images/tiles.bin"  0 144 16 16 // ship 1A
	@exportsubregion "images/tiles.flf" "images/tiles.bin" 16 144 16 16 // ship 1B
	sprites: incbin("images/tiles.bin");	// include sprites

	font: incbin("zxchars.bin");
	scrolltxt: string = ("Space invaders demo        o/p - left/right    q - quit ");

	i,j,x,y: integer;

	shipx, shipdx, shipauto : integer;
	backgr: array[64] of byte = BuildTable("0");	// empty tile

    invx,invdx: integer;
    skip,phase: integer;
    ch: integer;


// draws two rows of invaders
procedure drawinv(x, y: global integer, inva, invb: integer);
begin
	// address is passed as last parameter
    Tiles::PutTile(x-4, y, #backgr);
    for i := 0 to 16 step 2 do begin
	    // index is passed as last parameter
        Tiles::PutTile(x, y, inva);
        x += 4;
	    // index is passed as last parameter
        Tiles::PutTile(x, y, invb);
        x += 4;
    end;
	// address is passed as last parameter
    Tiles::PutTile(x, y, #backgr);
end;

// draws player ship
procedure drawship(x, y: global integer);
begin
    Tiles::PutTile(x-4, y, #backgr);
    Tiles::PutTile(x, y, 4);
    Tiles::PutTile(x+4, y, 5);
    Tiles::PutTile(x+8, y, #backgr);
end;

// automatic ship movement, called from interrupt
procedure moveship();
begin
    if shipauto = 0 then begin
        shipx += shipdx;
        if shipx>110 then shipdx := 0-shipdx;
        if shipx<6 then shipdx := 0-shipdx;
    end
    else shipauto -= 1;
    Screen::DoScroll();
end;


begin
	Z80CPM::Startup();
	System::CursorOff();
	System::SetScreenPos(0);
	Screen::SetFont(#font);
	Tiles::SetIndexTiles(#sprites);
	Screen::ClearBox(0, 0, 128, 64, 0);

    invx := 10;
    invdx := 1;
    shipx := 5;
    shipdx := 1;
    skip := 0;
    phase := 0;
    shipauto := 0;

	Screen::SetScroll(64-24,0,24,#scrolltxt);
    System::SetTimerFunction(#moveship);

    while (true) do 
	begin
        if phase < 8 then begin
            drawinv(invx, 5, 2, 3);
            drawinv(invx, 9, 3, 2);
            drawinv(invx, 13, 0, 1);
            drawinv(invx, 17, 1, 0);
        end else begin
            drawinv(invx, 5, 3, 2);
            drawinv(invx, 9, 2, 3);
            drawinv(invx, 13, 1, 0);
            drawinv(invx, 17, 0, 1);
        end;
        
        phase += 1;
        if phase>15 then phase := 0;

        if skip = 0 then begin
            invx += invdx;
            if invx>50 then invdx := 0-invdx;
            if invx<11 then invdx := 0-invdx;
        end;
        skip +=1;
        if skip>3 then skip := 0;

		// check if key was pressed
        if Z80CPM::KeyPressed() then begin
            ch := Z80CPM::GetChar();
            if ASCII::lower_o = ch then begin
                if shipx>=6 then shipx -= 1;
                shipauto := 10;
            end else if ASCII::lower_p = ch then begin
                if shipx<=110 then shipx += 1;
                shipauto := 10;
            end
            else if ASCII::lower_q = ch then break;
        end;

        drawship(shipx, 25);
    end;

    System::SetTimerFunction(0);
	Screen::ClearBox(0, 0, 128, 64, 0);
	System::CursorOn();
	Z80CPM::Exit();
end.
