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

#define FALSE 0
#define TRUE  1


struct term term_buffer;

fortran void mkon$p();

void    reset(),
        cpu(),
        reg_dump(),
      * malloc(),
        obj_reader(),
        auto_list();

short   hex_reader();

char  * lsdir(),
      * dis_ass();

strtoupper( string)
char *string;
{
   while (*string)    *string++ = toupper( *string);
}

without_sufix( path_name)
char *path_name;
{
   char *temp_pointer;

   temp_pointer = path_name + strlen( path_name);
   while( (temp_pointer > path_name) && (*temp_pointer != '.') )
      temp_pointer--;

   *temp_pointer = NULL;
}

show_dis( code)
PM *code;
{
   short loop;
   char  key;

   printf("...");
   do
   {
      printf("\010\010\010");
      for (loop = 0;loop < 20;loop ++)
      {
         short new_line_flag,
               length;

         if (code->St == code->PC)
         {
            printf( "                     ORG   $%04x\n\n", code->PC );
            loop += 2;
         }

         new_line_flag = FALSE;
         if (code->Me [code->PC] == 0x60)
         new_line_flag = TRUE;

         printf( "%s\n", dis_ass( code, &length) );
         code->PC += length;
         if (new_line_flag)
         {
            printf("\n");
            loop++;
         }
      }

      printf("...");
   }  while ( (key = toupper( getchar() )), key != 'N' &&
                                            key != 'Q'    );
   printf("\n");
}

short * code_Qu,
      * code_Mo,
        Reset_Flg;

fortran Ctrl_P( dummy)
int *dummy;
{
   *code_Qu  = TRUE;
   Reset_Flg = TRUE;
   *code_Mo  = Mode_FAST;
   char_take_back( 0x8D);
}

main( argc, argv)
int   argc;
char *argv [];
{
   PM   code;

   int file_unit;

   char   file_name   [256],
          list_buffer [256],
        * temp_pointer;

   short  old_term,
          arg_counter,
          list_buff_pos,
          number_of_files,
          loop;

   gterm( &term_buffer);
   old_term = term_buffer.tt_flags;
   term_buffer.tt_flags = BREAK | RAW;
   sterm( &term_buffer);

   code_Qu   = &(code.Qu);
   code_Mo   = &(code.Mo);
   Reset_Flg = FALSE;

   code.Me = (unsigned short int *) malloc( sizeof (short int) * 65536);
   if (code.Me == NIL)
   {
      printf("Couldn't allocate the memory for you.\n");
      exit (-1);
   }

   file_unit = open( APPLE_PROGS, 0);
   if (file_unit == -1)
   {
      printf("Can't find the library.\n");
      exit (-1);
   }

   while (temp_pointer = lsdir( file_unit) )
   {
      char buffer [256];

      strcpy( file_name, temp_pointer);
      sprintf( buffer, "%s>%s", APPLE_PROGS, file_name);
      if (ftype( buffer) > 1)
         continue;

      /* Make shoure that is only with .OBJ as a sufix */
      without_sufix( file_name);
      strcat( file_name, ".OBJ");
      obj_reader( &code, file_name);

   }
   close( file_unit);

   reset( &code);
   code.Mo = Mode_FAST;
   code.Ex = FALSE;
   code.Tr = FALSE;
   code.Tl = 0;
   code.Sl = 0x00;

   /* Check if trace is requested */
   mem_check( 0xC000, &(code.Ac), &code, Func_LOAD);

   if (argc >= 2)
   {
      arg_counter     = 1;
      list_buff_pos   = 0;
      number_of_files = 0;

      while (argc > arg_counter)
      {
         strtoupper( argv [arg_counter]);

         switch (*argv [arg_counter])
         {
            case '-':
               switch (argv [arg_counter][1])
               {
                  case 'D':
                     if ( (argc > (arg_counter + 1) ) &&
                          (*argv [arg_counter + 1] == '$') )
                     {
                        sscanf( argv [arg_counter + 1] + 1, "%x", &code.St);
                        arg_counter += 2;
                     }
                     else
                        arg_counter ++;

                     show_dis( &code);
                     break;

                  case 'T':
                     code.Tr = TRUE;
                     arg_counter++;
                     break;

                  default:
                     printf("Can't undersatnd %s.\n", argv [2]);
                     exit (-1);
               }
               break;

            default:
               strcpy( file_name, argv [arg_counter]);
               strcat( file_name, ".HEX");
               if (hex_reader( &code, file_name) )
               {
                  short temp_pos;

                  list_buffer [list_buff_pos++] = code.St & 0xFF;
                  list_buffer [list_buff_pos++] = code.St >> 8;
                  temp_pos = 0;
                  while (file_name [temp_pos])
                     list_buffer [list_buff_pos++] = file_name [temp_pos++];
                  list_buffer [list_buff_pos++] = NULL;
                  number_of_files ++;
                  arg_counter++;
                  break;
               }

               printf("Can't open the file %s\n", argv [arg_counter]);
               exit( -1);

         }  /* End of switch (*argv [arg_counter]) */
      }  /* End of while (argc > arg_counter) */

      list_buffer [list_buff_pos + 2] = NULL;

      if (number_of_files)
      {
         auto_list( &code, list_buffer, number_of_files);
         temp_pointer = "\nCALL 49424 : RUN\n";
         loop = 0;
         while (temp_pointer [loop])
            char_take_back( temp_pointer [loop++]);
      }

   }  /* End if( argc <= 2) */

/*   mkon$p( "QUIT$", 5, Ctrl_P);   /* Quit$ = 5 letters */

   while (!code.Er && !code.Ex)
   {
      printf("\nEntering mode (");

      switch (code.Mo)
      {
         case Mode_FAST:
            printf("Fast)\n");
            code.Qu = FALSE;
            fast_cpu( &code);
            break;

         case Mode_SLOW:
            printf("Slow)\n");
            do
            {
               slow_cpu( &code);
            }  while( !code.Qu);
            break;
      }

      if (Reset_Flg)
      {
         home( &code);
         printf("<RESET>    Press Esc two times and Q to Quit.\n");
         reset( &code);
         Reset_Flg = FALSE;
         code.Qu   = FALSE;
      }

      if (code.Er)
      {
         short steps;

         printf("Error:\n");
         printf("%s\n", dis_ass( &code, &steps) );
         reg_dump( &code);
         printf("Quit or Continue  :");
         if (toupper( getchar()) == 'C')
         {
            code.Tr = FALSE;
            code.Qu = FALSE;
            reset( &code);
         }
         else
            printf("\n");
      }

   }

   term_buffer.tt_flags = old_term;
   sterm( &term_buffer);
}

