#include <io.h>
#include <system.h>
#include <stdio.h>
#include <alt_types.h>
#include <sys/alt_irq.h>

#define IOWR_VGA_DATA(base, offset, data) \
 IOWR_16DIRECT(base, (offset) * 2, data)  

#define IORD_VGA_DATA(base, offset) \
 IORD_16DIRECT(base, (offset) * 2)  
  
unsigned char code;

int main()
{ 
  int count, i;
  int frog_x = 0;
  int frog_y = 0;
  int frog_alive=0;
  int pause = 0;
  int stopflag = 1;
  int frog_action = 0;
  int frog_direction=1;
  const int max=70000;
  int frog_last_y = 416;
  int score = 0;
  int frog_life = 5;
  int dummy_life = 5;
  int offset;
  int clear = 1 ;
  // audio
  int VolRd = 0, VolWr = 0;
  int a, audioi;

while(1) { 
   frog_alive = IORD_VGA_DATA(VGA_RASTER_BASE, 24);
   // audio collision
   if (frog_alive == 1) {
     IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0001);
     IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0001);
        audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            if (audioi == 4) {
                break;
            } 
        } 
   } 
   
   else if (frog_alive == 2) {
     IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0001);
     IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0000);
        audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            if (audioi == 4) {
                break;
            } 
        } 
   } 
   
 if (IORD_8DIRECT(PS2_BASE, 0) == 1){
   code = IORD_8DIRECT(PS2_BASE, 4);
   //detect keyboard input
   if (code == 0x1d || code == 0x1b || code == 0x1c || code == 0x23 || code == 0x29 || code == 0x55 || code == 0x4e){
    if (stopflag == 1)
        stopflag = 0;
    else
        stopflag = 1;
   }
   
   //pause function
   pause = IORD_VGA_DATA(VGA_RASTER_BASE, 25);
   if (code == 0x29 && stopflag == 0){
    pause = (pause + 1)%2;
    IOWR_VGA_DATA(VGA_RASTER_BASE, 25, pause);
   } 
   
   // audio volume
   if (code == 0x4e && stopflag == 0){
     VolRd = IORD_16DIRECT(AUDIO_BASE, 2*2);
     IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0002);
     if (VolRd < 3) VolWr = VolRd + 1;
     IOWR_16DIRECT(AUDIO_BASE, 2*2, VolWr);
   } 
   else if (code == 0x55 && stopflag == 0){
     VolRd = IORD_16DIRECT(AUDIO_BASE, 2*2);
     IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0002);
     if (VolRd > 0) VolWr = VolRd - 1;
     IOWR_16DIRECT(AUDIO_BASE, 2*2, VolWr);
   }
   

   
   //send frog x and y to C
   if (frog_alive == 0 && pause == 0 ) {
   frog_x = IORD_VGA_DATA(VGA_RASTER_BASE, 20);
   frog_y = IORD_VGA_DATA(VGA_RASTER_BASE, 21);

   if (code == 0x1d && stopflag == 0)   //up key
      { 
        frog_direction=1;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 22, frog_direction);
        // AUDIO
        IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0000);
        
       //see whether we should add score or not              
        if (frog_y == frog_last_y){
           score = score + 10;
           frog_last_y = frog_y - 32;
           IOWR_VGA_DATA(VGA_RASTER_BASE, 26, score);               
        } 
                                             
        frog_y -= 16; // move only one step
        frog_action = 1;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
        // audio
        IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0001);
        audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            if (audioi == 4) {
                break;
            } 
        }
        for (count=0;count<max;count++){
        }
        if (frog_y  > 0) frog_y -= 16; //move the next step
        
        //check whether arrive at destination
        if (frog_y == 32 ){     
            IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);      
            IOWR_VGA_DATA(VGA_RASTER_BASE, 28, frog_x);
            printf("HIHIHIHIHIHI\n");
            frog_last_y = 416;
        }
        else{
        frog_action = 0;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
        }
        // audio
        IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0000);
      } 
   else if (code == 0x1b && stopflag == 0)  //down
      {
        frog_direction=3; 
        IOWR_VGA_DATA(VGA_RASTER_BASE, 22, frog_direction); 
        // audio

        IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0000);   

        if (frog_y < 416) frog_y += 16; 
        frog_action = 1;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
        // audio
        IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0001);
        audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            if (audioi == 4) {
                break;
            } 
        }
        for (count=0;count<max;count++){
        }
        if (frog_y < 416) frog_y += 16;
        frog_action = 0;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
        // audio
        IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0000);
      }
      
      
      
   else if (code == 0x1c && stopflag == 0)  //left
      { 
       frog_direction=2;
       IOWR_VGA_DATA(VGA_RASTER_BASE, 22, frog_direction); 
       // audio
       IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0000);            
       if (frog_x >= 16) frog_x -= 16;
       else if (frog_x >= 0) frog_x = 0;
       frog_action = 1;
       IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
       IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
       IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
       // audio
       IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0001);
       audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            printf("a = %x\n", a);
            if (audioi == 4) {
                break;
            } 
        }
       for (count=0;count<max;count++){
       }
       if (frog_x >= 16) frog_x -= 16;
       else if (frog_x >= 0) frog_x = 0;
       frog_action = 0;
       IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
       IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
       IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
       // audio
       IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0000);
      }
      
      
   else if (code == 0x23 && stopflag == 0)  //right
      { 
        frog_direction=4;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 22, frog_direction);
        // AUDIO
        IOWR_16DIRECT(AUDIO_BASE, 1*2, 0x0000);
        if (frog_x <= 464) frog_x += 16;
        else if (frog_x <= 480) frog_x = 480;
        frog_action = 1;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
        // audio
        IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0001);
        audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            if (audioi == 4) {
                break;
            } 
        }
        for (count=0;count<max;count++){
        }
        if (frog_x <= 464) frog_x += 16;
        else if (frog_x <= 480) frog_x = 480;
        frog_action = 0;
        
        IOWR_VGA_DATA(VGA_RASTER_BASE, 21, frog_y);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 20, frog_x);
        IOWR_VGA_DATA(VGA_RASTER_BASE, 23, frog_action);
        // audio
        IOWR_16DIRECT(AUDIO_BASE, 3*2, 0x0000);

      }
   }
   audioi = 0; 
        while (1) {
            audioi++;    
            a = IORD_16DIRECT(AUDIO_BASE, audioi*2);
            if (audioi == 4) {
                break;
            } 
        }
 }
   else //keep track with the current status of the frog
   {
    IOWR_VGA_DATA(VGA_RASTER_BASE, 26, score); //keep writing score
    dummy_life = frog_life;
    frog_life = IORD_VGA_DATA(VGA_RASTER_BASE, 27); //keep reading frog life
    if (dummy_life > frog_life){
        frog_last_y = 416;
    }
    if (frog_life == 0 && frog_alive  == 1){
        frog_life = 5;
        score = 0;
        IOWR_VGA_DATA(VGA_RASTER_BASE, 29, clear);
    }
   }
}
    
  return 0;
}

//addresses for communication between software and hardware
//20  write read forg_x
//21  write read frog_y
//22  write frog_direction
//23  write frog_action
//24  read frog_alive 
//25  write read pause
//26  write score
//27  read frog_life
//28  write frog_x
//29  write clear


