#include <cpu_prog_model.h>
#include <stdio.h>

#define _READ  0
#define _WRITE 1

#define FALSE  0
#define TRUE   1

void  home(),
      bascalc(),
      wait();

short real_time(),
      touch_char(),
      dos_io(),
      rwts();

short display_page(),
      refresh();

char  take_char();

fortran void recycl(),
             sleep$();

void mem_check( address, value, code, type)
unsigned short int   address;
short              * value;
PM                 * code;
short                type;
{
   char          tecken;
   short         bit_8,
                 area,
                 loop,
                 dummy;

   static short  char_number_flag;

   switch (type)
   {
      case Func_JSR:   case Func_JMP:
         switch (address >> 12)
         {
            case 0x0:
               switch ( (address >> 8) & 0xF)
               {
                  case 0x3:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0xD:
                           switch (address & 0xF)
                           {
case 99:/*                              case 0x9:   /* 03D9 */
                                 printf("RWTS\n");
                                 exit(-1);
                                 break;
                           }
                           break;
                     }
                     break;

               }
               break;

            /* Ordiary RAM */
            case 0x1:   case 0x2:
               break;

            case 0x3:
               switch ( (address >> 8) & 0xF)
               {
                  case 0xA:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x0:
                           switch (address & 0xF)
                           {
                              case 0x0:   /* 3A00 */
                                 if ( (code->Me [0x3A00] != 0xA2) ||
                                      (code->Me [0x3A01] != 0x11) ||
                                      (code->Me [0x3A02] != 0xCA) ||
                                      (code->Me [0x3A03] != 0xD0) ||
                                      (code->Me [0x3A04] != 0xFD)   )
                                 break;

                                 do
                                 {
                                    code->Xr         = 0x00;
                                    code->Me [0x46] += 0x01;
                                    if (code->Me [0x46] == 0x100)
                                    {
                                       code->Me [0x46]  = 0x00;
                                       code->Me [0x47] += 0x01;
                                       code->Me [0x47] &= 0xFF;
                                    }
                                    code->Ac        -= 0x01;
                                 }  while (code->Ac != 0x00);
                                 code->PC = 0x3A10;
                                 break;
                           }
                           break;
                     }
                     break;

               }
               break;

            /* Ordiary RAM */
            case 0x4:   case 0x5:   case 0x6:   case 0x7:   case 0x8:
            case 0x9:   case 0xA:
               break;

            case 0xB:
               switch ( (address >> 8) & 0xF)
               {
                  case 0xA:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x0:
                           switch (address & 0xF)
                           {
                              case 0x0:   /* BA00 */
                                 if ( (code->Me [0x3A00] != 0xA2) ||
                                      (code->Me [0x3A01] != 0x11) ||
                                      (code->Me [0x3A02] != 0xCA) ||
                                      (code->Me [0x3A03] != 0xD0) ||
                                      (code->Me [0x3A04] != 0xFD)   )
                                 break;

                                 do
                                 {
                                    code->Xr         = 0x00;
                                    code->Me [0x46] += 0x01;
                                    if (code->Me [0x46] == 0x100)
                                    {
                                       code->Me [0x46]  = 0x00;
                                       code->Me [0x47] += 0x01;
                                       code->Me [0x47] &= 0xFF;
                                    }
                                    code->Ac        -= 0x01;
                                 }  while (code->Ac != 0x00);
                                 code->PC = 0x3A10;
                                 break;
                           }
                           break;
                     }
                     break;

                  case 0x7:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0xB:
                           switch (address & 0xF)
                           {
                              case 0x5:   /* B7B5 */
                                 if (code->Tr)
                                    printf("Attempt to use RWTS from $B7B5.\n");
                                 rwts( code);
                                 break;
                           }
                           break;
                     }
                     break;
               }
               break;

            case 0xC:
               switch ( (address >> 8) & 0xF)
               {
                  case 0x0:
                     printf( "Access violation.\n");
                     exit (-1);

                  case 0x1:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x0:
                           printf("Back to primos\n");
                           code->Qu = TRUE;
                           code->Ex = TRUE;
                           break;
                     }
                     break;

                  case 0x3:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x0:
                           switch (address & 0xF)
                           {
                              case 0x0:   /* C300 */
                                 if (code->Me [0xC300] == 0)
                                 {
                                    printf("80-Screen isn't included yet.\n");
                                    code->PC = 0xFE93;   /* Setvid (PR#0) */
                                 }
                                 break;

                              case 0x1:   /* C301 */
                                 refresh( code);
                                 RTS( code);
                                 break;
                           }
                           break;
                     }
                     break;

                  case 0x5:    /* C500 */
                     if (code->Me [0xC500] == 0)
                     {
                        printf("Time isn't included yet.\n");
                        code->PC = 0xFE93;   /* Setvid (PR#0) */
                     }
                     break;

                  case 0x6:
                     /* Disk drive */
                     break;

                  default:
                     printf("Can't find $C%03x\n", address & 0xFFF);
                     exit(-1);
               }
               break;

            case 0xD:   case 0xE:
               /* Basic */
               break;

            case 0xF:
               switch ( (address >> 8) & 0xF)
               {
                  case 0xB:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0xC:
                           switch (address & 0xF)
                           {
                              case 0x1:   /* FBC1 */
                                 bascalc( code->Ac, code);
                                 code->Tl --;
                                 code->PC = 0xFBD8;
                           }
                           break;

                        case 0xF:
                           switch (address & 0xF)
                           {
case 999:/*                              case 0xD:   /* FBFD   vidout */
                                 tecken = code->Ac;
                                 switch (tecken >> 5)
                                 {
                                    case 0x4:  /* Ctrls */
                                       switch (tecken & 0x1F)
                                       {
                                          case 0x7:
                                             printf("\207");
                                             code->Tl --;
                                             code->PC = 0xFC2B;
                                             break;
                                       }
                                       break;

                                    case 0x5:   case 0x6:   /* Normal */
                                       printf( "%c", tecken | 0x80);

                                       bascalc( code->Me [0x25], code);

                                       if (code->Me [0x24] < code->Me [0x21])
                                       {
                                          printf( "%c", tecken | 0x80);
                                          (code->Me [0x24])++;
                                          code->Tl --;
                                          code->PC = 0xFDFF;
                                       }
                                       break;

                                    default:
                                       /* Let is pas without no ation */
/*printf( "[^%c]", tecken | 0x40);*/
                                 }
                                 break;

                              default:
/*
                                 printf("Can't find $FBF%x\n", address & 0xF);
*/
                           }
                           break;

                        default:
/*
                           printf("Can't find $FB%x\n", address & 0xFF);
*/
                  }
                  break;

                  case 0xC:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x5:
                           switch (address & 0xF)
                           {
                              case 0x8:   /* FC58 = HOME */
                                 home( code);
                                 code->PC = 0xFC22;  /* VTAB */
                                 break;

                           }
                           break;

                        case 0xA:
                           switch (address & 0xF)
                           {
                              case 0x8:   /* FCA8 */
                                 wait( code);
                                 code->Tl --;
                                 code->PC = 0xFCB3;
                                 break;

                              default:
/*
                                 printf("Can't find $FCA%x\n", address & 0xF);
*/
                           }
                           break;

                        default:
/*
                           printf("Can't find $FC%02x\n", address & 0xFF);
*/
                      }
                     break;

                  case 0xF:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x3:
                           switch (address & 0xF)
                           {
                              case 0xA:   /* FF3A = BELL */
                                 printf("\207");
                                 code->Tl --;
                                 code->PC = 0xFDFF;  /* RTS */
                                 break;

                              default:
/*
                                 printf("Can't find $FF3%x\n", address & 0xF);
*/
                           }
                           break;

                        default:
/*
                           printf("Can't find $FF%02x\n", address & 0xFF);
*/
                     }
                     break;

                  default:
/*
                     printf("Can't find $F%03x\n", address & 0xFFF);
*/
               }
               break;

            default:
               printf("Can't find $%04x\n", address);
         }
         break;

      case Func_LOAD:
         switch ( (address >> 12) & 0xF)
         {
            case 0x0:
               switch ( (address >> 8) & 0xF)
               {
                  /* Take no action, this is the screen */
                  case 0x4:   case 0x5:   case 0x6:   case 0x7:
                     break;
               }
               break;

            case 0xC:
               switch ( (address >> 8) & 0xF)
               {
                  case 0x0:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x0:   /* 0xC000 */
                           if (code->Qu)
                              return;

                           if (touch_char( value) )
                           {
                              char_number_flag = 0;

                              if (*value == '\233')
                              {
                                 short tecken;

                                 skip_if_char();     /* Skip the first ESC */
                                 tecken = take_char();   /* And check next */

                                 if (tecken == '\233')
                                 {
                                    code->Qu = TRUE;
                                    code->Mo = Mode_SLOW;
                                    *value  &= 0x7F;  /* value is'n present */
                                    return;
                                 }
                                 char_take_back( *value);
                                 char_take_back( tecken);

                              }
                           }

                           else
                           {
                              if (char_number_flag < 10)
                                 char_number_flag ++;
                              else
sleep$(100l);
/*                                 recycl();*/
                           }
                           break;

                        case 0x1:
                           skip_if_char();
                           break;

                        case 0x3:
/*                           printf("Speaker not allowed now! (LOAD)\n");
/*                           exit (-1);*/
                           break;

                        case 0x5:
                           switch (address & 0xF)
                           {
                              defalut:
                                 printf("Referns to undefined function.\n");
                                 exit(-1);
                                 break;

                           }
                           break;

                        case 0xB:
                           switch (address & 0xF)
                           {
                              case 0x1:    case 0x2:
                                 *value = code->Me [address];
                                 break;

                              case 0x3:
                                 *value = code->Sl;

                           }
                           break;

                        case 0xD:
                           switch (address & 0xF)
                           {
                              case 0x0:
                                 *value = real_time( HOUR);
                                 break;

                              case 0x1:
                                 *value = real_time( MINUTE);
                                 break;

                              case 0x2:
                                 *value = real_time( SECOND);
                                 break;
                           }
                           break;

                        case 0x8:
                           if (code->Tr)
                           {
                              printf("\n");
                              printf("Can't Read on address $%04x.\n", address);
                           }
/*
                           code->Mo = Mode_SLOW;
                           code->Qu = TRUE;
*/
                           break;

                        case 0xE:
                           dos_io( address & 0xF, value, code, _READ);
                           break;

                        default:
                           printf("Can't Read on address $%04x.\n", address);
                           code->Mo = Mode_SLOW;
                           code->Qu = TRUE;
                           break;
                     }  /* End of Switch (C0xx) */
                     break;

                  default:
/*
                     printf("Can't Read on address $%04x.\n", address);
                     exit(-1);
*/
                     break;
               }  /* End of switch (Cxxx) */
               break;

            default:
               /* Take no care of the rest */
               break;
         }
         break;

      case Func_STORE:
         switch ( (address >> 12) & 0xF)
         {
            case 0x0:
               switch ( (address >> 8) & 0xF)
               {
                  case 0x0:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x3:
                           switch (address & 0xF)
                           {
                              case 0x7:   /* (0037) CSWH */
                                 if ( ((code->Sl & 0x10) != 0x10) &&
                                      ((code->Sl & 0x0F) == 0x03) &&
                                      (*value != 0xC3)              )
                                 {
break;
                                    refresh( code);
                                    code->Sl &= 0xF0;
                                    code->Sl |= 0x10;
                                 }
                                 break;
                           }
                           break;
                     }
                     break;

                  case 0x4:   case 0x5:   case 0x6:   case 0x7:
                     /* Test if there is a realy Srceen */
                     if ( ((area = display_page( address)) != 0) &&
                          ((code->Sl & 0x0F) != 0x03)               )
                        to_video( address, area, *value);

               }
               break;

            case 0xC:
               switch ( (address >> 8) & 0xF)
               {
                  case 0x0:
                     switch ( (address >> 4) & 0xF)
                     {
                        case 0x0:
/*
                           printf("Can't Write to 0xC000 $%04x.\n", code->PC);
                           abort();
*/
                           break;

                        case 0x1:
                           skip_if_char();
                           break;

                        case 0x3:   /* C030 */
                           printf("Bell (Not now)\n");
/*                           exit (-1);*/
                           break;

                        case 0x5:
                           switch (address & 0xF)
                           {
                              case 0:
                                 printf("Switch to Graph.\n");
                                 exit(-1);
                                 break;

                              case 1:
                                 printf("Switch to TEXT.\n");
                                 break;

                              case 2:
                                 printf("Switch to Hole_Screen.\n");
                                 break;

                              case 3:
                                 printf("Switch to Mixt_screen.\n");
                                 break;

                              case 4:
                                 printf("Switch to Screen_1.\n");
                                 break;

                              case 5:
                                 printf("Switch to screen_2.\n");
                                 break;

                              case 6:
                                 printf("Switch to LOW_Res.\n");
                                 break;

                              case 7:
                                 printf("Switch to HI_Res.\n");
                                 break;

                           }
                           break;

                        case 0x8:
                           switch (address & 0xF)
                           {
                              case 0x0:
                                 if (code->Tr)
                                    printf("RAM card ON.\n");
/*
                                 exit (-1);
*/
                                 break;

                              case 0x1:
                                 if (code->Tr)
                                    printf("RAM card OFF.\n");
/*
                                 exit (-1);
*/
                                 break;

                           }
                           break;

                        case 0xB:
                           switch (address & 0xF)
                           {
                              case 0x0:   /* C0B0 */
                                 switch( *value)
                                 {
                                    case 0x8D:
                                       printf("\n");
                                       break;

                                    default:
                                       printf("%c", *value | 0x80);
                                       break;
                                 }
                                 break;

                              case 0x1:    case 0x2:
                                 code->Me [address] = *value;
                                 break;

                              case 0x3:
                                 code->Sl = *value;
                                 break;

                           }
                           break;

                        case 0xE:
                           dos_io( address & 0xF, value, code, _WRITE);
                           break;

                        default:
                           printf("Illegal Slot: It's activated.\n");
                           abort();
                           break;
                     }
                     break;

                  case 0x1:   case 0x2:   case 0x3:   case 0x4:   case 0x5:
                  case 0x6:   case 0x7:   case 0x8:   case 0x9:   case 0xA:
                  case 0xB:   case 0xC:   case 0xD:   case 0xE:   case 0xF:
                     /* Dos rom */
                     break;

                  default:
                     printf("Que!   $%04x.\n", address);
                     abort();
                     break;
               }

            default:
               /* Take no care of the rest */
               break;
         }
         break;

      default:
         printf("Wrong type (%d) of address check.\n", type);
         exit(-1);
   }

}


