
#include <stdio.h>
#include <system.h>
#include <io.h>

int main()
{
  int row_old_pacman = 20;
  int col_old_pacman = 20;
  int row_new_pacman = 20;
  int col_new_pacman = 20;
  int row_old_ghost = 13;
  int col_old_ghost = 14;
  int row_new_ghost = 13;
  int col_new_ghost = 14;
  int recover_sprite = 0;
  unsigned char code;
  int score = 0;
  int score_bit_0;
  int score_bit_1;
  int score_bit_2;
  int count = 0;
  
  // pacman        : 0001 (0x1)
  // brick         : 1111 (0xf)
  // background    : 0000 (0x0)
  // dot_small     : 0010 (0x2)
  // dot_large     : 0011 (0x3)
  // ghost         : 0100 (0x4)
  //                             0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39
  //                             |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  int control_array[30][40] = {0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   // 0
                               0xf,0x3,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x3,0xf,   // 1
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   // 2
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   // 3
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   // 4
                               0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,   // 5
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   // 6
                               0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,   // 7
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   // 8
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   // 9
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //10
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0x0,0x0,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //11
                               0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,   //12
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //13
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //14
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //15
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //16
                               0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,   //17
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   //18
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   //19
                               0xf,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0xf,   //20
                               0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,   //21
                               0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,   //22
                               0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,0xf,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0xf,   //23
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   //24
                               0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,0xf,0x2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x2,0xf,   //25
                               0xf,0x3,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x3,0xf,   //26
                               0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,   //27
                               0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,   //28
                               0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; //29
                  
  printf("Ready to read the PS2 keyboard!\n");
  
  for (;;)
  {
      while (!IORD_8DIRECT(PS2_BASE,0)) 
      {
        IOWR_16DIRECT(VGA_BASE, 0, row_new_pacman); 
        IOWR_16DIRECT(VGA_BASE, 2, col_new_pacman);
        IOWR_16DIRECT(VGA_BASE, 4, score_bit_0); 
        IOWR_16DIRECT(VGA_BASE, 6, score_bit_1); 
        IOWR_16DIRECT(VGA_BASE, 8, score_bit_2); 
        IOWR_16DIRECT(VGA_BASE, 10, row_new_ghost); 
        IOWR_16DIRECT(VGA_BASE, 12, col_new_ghost);
        IOWR_16DIRECT(VGA_BASE, 14, recover_sprite);
        
        if (count == 0)
        {
            if (row_new_pacman > row_new_ghost)
                if (control_array[row_new_ghost+1][col_new_ghost] != 0xf)  // check if wall is hit
                    row_new_ghost++;
            if (row_new_pacman < row_new_ghost)
                if (control_array[row_new_ghost-1][col_new_ghost] != 0xf)  // check if wall is hit
                    row_new_ghost--;
            if (col_new_pacman > col_new_ghost)
                if (control_array[row_new_ghost][col_new_ghost+1] != 0xf)  // check if wall is hit
                    col_new_ghost++;
            if (col_new_pacman < col_new_ghost)
                if (control_array[row_new_ghost][col_new_ghost-1] != 0xf)  // check if wall is hit
                    col_new_ghost--;
        }
        count++;
        if (count == 30000)
            count = 0;
        
      }
      code = IORD_8DIRECT(PS2_BASE,4);
     
      // LEFT  ARROW: 224 107 224 240 107
      // RIGHT ARROW: 224 116 224 240 116
      // UP    ARROW: 224 117 224 240 117
      // DOWN  ARROW: 224 114 224 240 114
      
      if (code == 224)
      {
        while (!IORD_8DIRECT(PS2_BASE,0))
        {
          IOWR_16DIRECT(VGA_BASE, 0, row_new_pacman); 
          IOWR_16DIRECT(VGA_BASE, 2, col_new_pacman);
          IOWR_16DIRECT(VGA_BASE, 4, score_bit_0); 
          IOWR_16DIRECT(VGA_BASE, 6, score_bit_1); 
          IOWR_16DIRECT(VGA_BASE, 8, score_bit_2); 
          IOWR_16DIRECT(VGA_BASE, 10, row_new_ghost); 
          IOWR_16DIRECT(VGA_BASE, 12, col_new_ghost);
          IOWR_16DIRECT(VGA_BASE, 14, recover_sprite);
        }
        code = IORD_8DIRECT(PS2_BASE,4);
        switch (code)
        {
            case 107:
                if (control_array[row_new_pacman][col_new_pacman-1] != 0xf)  // check if wall is hit
                {
                    col_new_pacman--;
                }
                break;
                
            case 116:
                if (control_array[row_new_pacman][col_new_pacman+1] != 0xf)  // check if wall is hit
                {
                    col_new_pacman++;
                }
                break;
                
            case 117:
                if (control_array[row_new_pacman-1][col_new_pacman] != 0xf)  // check if wall is hit
                {
                    row_new_pacman--;
                }
                break;
                
            case 114:
                if (control_array[row_new_pacman+1][col_new_pacman] != 0xf)  // check if wall is hit
                {
                    row_new_pacman++;
                }
                break;
                
            default : 
                break;
        }
      }
      IOWR_16DIRECT(VGA_BASE, 0, row_new_pacman); 
      IOWR_16DIRECT(VGA_BASE, 2, col_new_pacman);
      
      if (control_array[row_new_pacman][col_new_pacman] == 0x2)  // eat a small dot
      {
        score = score + 1;
      }
      if (control_array[row_new_pacman][col_new_pacman] == 0x3)  // eat a large dot
      {
        score = score + 5;
      }
      
      score_bit_0 = score%10;
      score_bit_1 = (score/10)%10;
      score_bit_2 = score/100;
      
      IOWR_16DIRECT(VGA_BASE, 4, score_bit_0); 
      IOWR_16DIRECT(VGA_BASE, 6, score_bit_1); 
      IOWR_16DIRECT(VGA_BASE, 8, score_bit_2); 
      IOWR_16DIRECT(VGA_BASE, 10, row_new_ghost); 
      IOWR_16DIRECT(VGA_BASE, 12, col_new_ghost);
      printf("******* score = %d; %d,%d,%d\n", score, score_bit_2, score_bit_1, score_bit_0);
      
      control_array[row_old_pacman][col_old_pacman] = 0x0;
      control_array[row_new_pacman][col_new_pacman] = 0x1;
 
      row_old_pacman = row_new_pacman;
      col_old_pacman = col_new_pacman;
      
      if (row_old_ghost != row_new_ghost || col_old_ghost != col_new_ghost)
      {
          IOWR_16DIRECT(VGA_BASE, 14, recover_sprite);
          control_array[row_old_ghost][col_old_ghost] = recover_sprite;
          recover_sprite = control_array[row_new_ghost][col_new_ghost];
          control_array[row_new_ghost][col_new_ghost] = 0x4;
          row_old_ghost = row_new_ghost;
          col_old_ghost = col_new_ghost;
      }
  }
  
  return 0;
}
