


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>


#define F_CPU 16000000UL 		        // рабочая частота процессора (16 MHz)
#define INCDIRECTION		XDIR	    // ориентация дисплея XDIR (вертикально), YDIR (горизонтально)
#include "proc.h"						// базовые процедуры
#include "adjectives.h"					// основные определения
#include "keyboard.h"					// клавиатура
#include "lcd.h"						// дисплей + рисование примитивов (линии, круги, прямоугольники)
#include "draw_spr.h"					// рисование спрайтов
#include "chr.h"						// печать текста
#include "sdcard.h"						// рабрта с SD картой
#include "window.h"						// окна



unsigned char fgColor = 0x00;
unsigned char bgColor = 0xff;



char text2[] = "Счёт:";
char text3[] = "Линий:";


unsigned char presskey;
unsigned char colors[7] = {0xe0, 0x1c, 0x03, 0xfc, 0xe3, 0x1f, 0x00};
unsigned char figures[7] = {0x66, 0xf0, 0xc6, 0x6c, 0xe4, 0xe2, 0xe8};
unsigned char stack[23][10];


unsigned char volatile n1,n10,n2;


// звук
ISR(TIMER0_OVF_vect)
{
  n1--;
  if (n1 == 0)
  {
    if (n10 != 0)
	  PORTD ^= (1<<PD6);
	n1 = n10;
  n2--;
  if (n2 == 0)
  {
	n10 = 0;
  }
  }
}






void put_block(unsigned char x, unsigned char y, unsigned char color)
{
  ls020_set_window(6+x*8,3+y*8,6+x*8+6,3+y*8+6);
  for (unsigned char i=0; i<49; i++)
    ls020_wrdata8(color);
}

void draw_stack() //стакан выводится начиная со второй линии
{
  for(unsigned char x=2; x<23; x++)
	for(unsigned char y=0; y<10; y++)
      put_block(x-2,y,stack[x][y]);
}

void draw_score(unsigned char score, unsigned char lines)
{

  	

  char text[] = "0000000  ";


  for(unsigned char i=6; i>0; i--)
  {
    text[i] = 0x30 + score % 10;
    score/=10;
  }
  rectangle8(17,87,18,132,0x0A);
  put_string8(17,87,text,0xFF,0x0A);


  for(unsigned char i=6; i>0; i--)
  {
    text[i] = 0x30 + lines % 10;
    lines/=10;
  }
  rectangle8(35,87,36,132,0x0A);
  put_string8(35,87,text,0xFF,0x0A);
}

void draw_bg()
{
  put_string8(8,87,text2,0xFF,0x0A);
  put_string8(26,87,text3,0xFF,0x0A);
  draw_score(0,0);
  rectangle8(1,1,174,1,0x00);
  rectangle8(1,83,174,83,0x00);
  rectangle8(174,1,174,83,0x00);
}

void put_figure(unsigned char x, unsigned char y, unsigned char figure, unsigned char orient, unsigned char color)
{
  unsigned char b=figures[figure];
  switch(orient)
  {
    case 0:
      for(char dx=0; dx<2; dx++)
        for(char dy=0; dy<4; dy++)
	    {
          if(b%2 != 0)
	        stack[x+1-dx][y+2-dy] = color;
          b/=2;
        }
	  break;
    case 1:
      for(char dy=0; dy<2; dy++)
        for(char dx=0; dx<4; dx++)
	    {
          if(b%2 != 0)
	        stack[x-2+dx][y-1+dy] = color;
          b/=2;
        }
	  break;
    case 2:
      for(char dx=0; dx<2; dx++)
        for(char dy=0; dy<4; dy++)
	    {
          if(b%2 != 0)
	        stack[x-1+dx][y-2+dy] = color;
          b/=2;
        }
	  break;
    case 3:
      for(char dy=0; dy<2; dy++)
        for(char dx=0; dx<4; dx++)
	    {
          if(b%2 != 0)
	        stack[x-2+dx][y+1-dy] = color;
          b/=2;
        }
	  break;
  }
}

int check_figure(unsigned char x, unsigned char y, unsigned char figure, unsigned char orient)
{
  unsigned char b = figures[figure];
  switch(orient)
  {
    case 0:
      for(char dx=0; dx<2; dx++)
        for(char dy=0; dy<4; dy++)
        {
	      if(b%2 != 0)
            if((stack[x+1-dx][y+2-dy] != bgColor)||(x+1-dx<0)||(x+1-dx>22)||(y+2-dy<0)||(y+2-dy>9))
              return 0;
	      b/=2;
	    }
      break;
    case 1:
      for(char dy=0; dy<2; dy++)
        for(char dx=0; dx<4; dx++)
        {
	      if(b%2 != 0)
            if((stack[x-2+dx][y-1+dy] != bgColor)||(x-2+dx<0)||(x-2+dx>22)||(y-1+dy<0)||(y-1+dy>9))
              return 0;
	      b/=2;
	    }
      break;
    case 2:
      for(char dx=0; dx<2; dx++)
        for(char dy=0; dy<4; dy++)
        {
	      if(b%2 != 0)
            if((stack[x-1+dx][y-2+dy] != bgColor)||(x-1+dx<0)||(x-1+dx>22)||(y-2+dy<0)||(y-2+dy>9))
              return 0;
	      b/=2;
	    }
      break;
    case 3:
      for(char dy=0; dy<2; dy++)
        for(char dx=0; dx<4; dx++)
        {
	      if(b%2 != 0)
            if((stack[x-2+dx][y+1-dy] != bgColor)||(x-2+dx<0)||(x-2+dx>22)||(y+1-dy<0)||(y+1-dy>9))
              return 0;
	      b/=2;
	    }
      break;
  }
  return 1;
}

unsigned char x,y,f,r,x_old,y_old,r_old,tick,level,score,lines,play;

void clear_stack()
{
  for(x=0; x<23; x++)
    for(y=0; y<10; y++)
      stack[x][y] = bgColor;
}

void clear_effect()
{
  for(x=0; x<23; x++)
  {
    for(y=0; y<10; y++)
	  stack[x][y] = fgColor;
    draw_stack();
    _delay_ms(5);
  }
  for(x=0; x<23; x++)
  {
    for(y=0; y<10; y++)
	  stack[x][y] = bgColor;
    draw_stack();
    _delay_ms(5);
  }
}

void clear_line(unsigned char line)
{
  for(; line>0; line--)
    for(y=0; y<10; y++)
	  stack[line][y] = stack[line-1][y];
}

int check_line(unsigned char line)
{
  for(y=0; y<10; y++)
    if(stack[line][y] == bgColor)
	  return 0;
  return 1;
}

void check_keyboard()
{

  if (PINC==255) presskey=0;


  if((PINC & VK_KEY6) == 0x00) //down
   {
boot_load();
    }



  if((PINC & VK_KEY2) == 0x00) //down
  {
    x++;
    if(!check_figure(x,y,f,r))
      x=x_old;
    else
      tick=0;
  }
  if(((PINC & VK_KEY4) == 0x00)& (presskey==0)) //right
  {
    presskey=1;
    y++;
    if(!check_figure(x,y,f,r))
	  y=y_old;
  }
  if(((PINC & VK_KEY1) == 0x00)& (presskey==0)) //left
  {
    presskey=1;
    y--;
    if(!check_figure(x,y,f,r))
      y=y_old;
  }
  if(((PINC & VK_KEY3) == 0x00) & (presskey==0)) //rotate
  {
    presskey=1;
	r++;
    r%=4;
    if(!check_figure(x,y,f,r))
	  r=r_old;
  }
}


void menu_cycle()
{
unsigned char fn[13] = "m.abm";
load_spr(fn,0,0);
while (1) {
	if((PINC & VK_KEY6) == 0x00) {boot_load();}
	if(PINC  != 255) {return;}
}
}

void game_cycle()
{
unsigned char fn[13] = "m1.abm";
load_spr(fn,0,0);

  draw_bg();
  clear_stack();
  draw_stack();

  score=0; lines=0; level=0;
  play=1;
  while(play)
  {
    tick=0;
	x_old=x=1; y_old=y=4; r_old=r=0;
	f = rand() % 7;
    if(!check_figure(x,y,f,r))
	{
      play=0;
	  break;
    }
    while(1)
	{
	  if(!check_figure(x,y,f,r))
        break;
	  x_old=x; y_old=y; r_old=r;
	  check_keyboard();
      put_figure(x,y,f,r,colors[f]);
      draw_stack();
	  draw_score(score,lines);
      _delay_ms(5);
      put_figure(x,y,f,r,bgColor);
	  tick++;
	  if(tick >= (10 - level))
	  {
		x++;
		tick=0;
      }
    }
    n10 = 55; n2 = 10;
    put_figure(x_old,y_old,f,r_old,colors[f]);
	y=0;
	for(x=2; x<23; x++)
      if (check_line(x))
	  {
        lines++;
		y++;
	    clear_line(x);
		x--;
        n10 = 5; n2 = 100;
      }
    score+=y*2;
  }
  clear_effect();
}




int main(void)
{
  keyboard_init(); 
  lcd_init(clWhite);
  sdcard_init();



  while(1)
  {
    menu_cycle();
    game_cycle();
  }
}




