//rom controller generating program by dan williams
// converted from QBASIC jan 2006

#include <conio.h>
#include <math.h>
#include <string.h>



void printmenu() ;
void newFile() ;
void inputBox () ;
void boxPrompt(char *prompt, char * hint) ;
void loadProg() ;
void noFile () ;
void saveProg();
void editit() ;
void printBin(int input, int mask);
void info() ;
int places(float i);

#define celing  1024
#define listlen 19
#define gotoyx(A,B)  gotoxy(B,A)
#define colour(A,B)  textcolor(A); textbackground(B)


 unsigned long outt[celing];
 unsigned long gotoo[celing];
 char filename[25];
 int q, s;
 int inputs;
 int outputs;
 int saved;
 long int level;



int main(void) {

 
  int  inmask;
  int  a;
  char reply[20];

  saved       = 1;
  filename[0] = '\0';             //current file name
  s           = 1;
  inmask      = 8;
  

  initconio(); 

  do {
    printmenu(s);
    reply[0] = '\0';
    cscanf("%s", &reply);
    a = atoi(reply);
    if ( reply[0] == '\0' ) { a = s; }
    
   //if ( a = 7 ) { GOTO castout
   
    if (0) {
    } else if ( a == 1 ) { 
       newFile();   
    } else if ( a == 2 ) { 
       loadProg(); 
    } else if ( a == 3  & filename[0] != '\0' ) { 
       saveProg(); 
    } else if ( a == 8  ) { 
       info(); 
    } else if ( a == 4  & filename[0] != '\0' ) { 
       editit(); 
       s = 3; 
    }
    
 } while(a != 7);

 doneconio(); 

 return 0;
}


//*************************** new file *********************
void newFile() {

 
 int n;

 //get filename
 boxPrompt("New Filename ", "FILENAME.EXT");
 cscanf ( "%s", &filename );
  
 //get number of inputs
 boxPrompt("Number of inputs ", "");
 cscanf ("%d", &inputs);
 
 boxPrompt("Number of outputs ", "0 TO 8");
 cscanf ("%d", &outputs);
 colour( 7, 0 );

 level = pow(2, inputs);
 for ( n = 0 ; n < celing; n++) {
  outt[n] = 0;
  gotoo[n] = n / level;
 }
 s = 4; 
 
}


//*************************** load program *********************
void loadProg() {

  int n;
  FILE *fin;

  boxPrompt("Filename ", "FILENAME.EXT");
  cscanf ("%s", &filename);
  
 if ( filename[0] != '\0') {
 
   if ((fin = fopen(filename, "rt")) == NULL) {  //open text file 'param 1' w/ err chk       
      noFile();      
      s = 1;
      return;
    }

   fscanf( fin, "%d", &inputs);
   fscanf( fin, "%d", &outputs);
   
   for ( n = 0; n < celing ; n++) {
    fscanf (fin, " %d , %d", &outt[n], &gotoo[n]);
   }
   fclose (fin);
  
   colour( 7, 0 );  
   level = pow(2 , inputs);
   s = 4;  
 } else {
   s = 1;
 }
 
}


// ************************ file not found *********************
void noFile () {

 boxPrompt("FILE ERROR. HIT ANY KEY", "");
 getche();
 s = 1;
 filename[0] = '\0';

}

//************************ save progam **************************

void saveProg() {

  int n;
  FILE *fout;

 if ((fout = fopen(filename, "wt")) == NULL) {  //open text file 'param 1' w/ err chk       
      noFile();      
      s = 1;
      return;
    }
 fprintf ( fout, "%d\n", inputs );
 fprintf ( fout, "%d\n", outputs);
 for ( n = 0 ; n < celing ; n++ ) {
  fprintf ( fout , " %d , %d\n", outt[n], gotoo[n] );
 }
 fclose(fout);
 s = 4;
 saved = 1;
}

//*********************** print program info ************************

void info() {
  clrscr();
  colour( 3, 0);
  cprintf ("\n");
  cprintf ( " This program was written by Dan Williams. The reason for its creation\n");
  cprintf ( " was due to a request, during an open house at BCIT, for a simple, cheap\n");
  cprintf ( " controler. These controlers are something that I stumbled on at some\n");
  cprintf ( " point in my life, never got into them much because of the complexity\n");
  cprintf ( " of the programming. This program automatically generates the numbers\n");
  cprintf ( " to make a controler of this type work, as an added bonus I made it look\n");
  cprintf ( " like a high level language (well basic really). The basic idea is that \n");
  cprintf ( " a memory chip (usually rom, could be done with ram) has part of its output\n");
  cprintf ( " lines fed back into the address lines (through a timed latch) The extra \n");
  cprintf ( " output lines are used as the system output, & the extra address lines\n");
  cprintf ( " can be used as scanfs. This has the unfor (tunate heavy limitation\n");
  cprintf ( " of the number of outputs versus program length (inversly proportunate)\n");
  cprintf ( " this could be assisted by using multiple memory chips with the address \n");
  cprintf ( " lines paralleled (would give 8 extra outputs)\n");
  cprintf ( " This program probably has a quadrillion bugs in it but if you don//t tell\n");
  cprintf ( " then i won't either.... ooops!!, oh well...\n");
  cprintf ("\n");
  cprintf ( " have fun!!!\n");
  cprintf ( "       Dan Williams        OH YEH, & ITS FREEWARE!!!  (nearly forgot)\n");
  cprintf ( " dan_williams@sunshine.net\n");
  cprintf ("\n");
  cprintf ("\n");
  cprintf ( "any key to continue \n");
  getche();
  colour( 7, 0);
}


//**************************   edit program  *****************************

void editit() {

  int listart ;
  int crsx    ;
  int crsy    ;
  char mode;
  int     a   ;
  int inmask  ;
  int simmins ;
  int simlin  ;
  int simcrs, lenny, dsp  ;
  int x, y, z, k;

  listart = 0;
  crsx    = 2;
  crsy    = 0;
  mode   = 'e';
  inmask  = inputs;
  simmins = 0;
  simlin  = 0;
  simcrs  = 0;

  clrscr();
  colour( 3, 0);
  cprintf("\n");
  cprintf ( "-------------------------------------------------------------------------------");

  gotoyx ( 23, 1 );
  cprintf ( "-------------------------------------------------------------------------------");
  colour( 7, 0);

do {
  gotoyx ( 1, 1 );
  if ( mode == 'e' ) {
    cprintf ( "Max 'if' level is %d                                     ", level );
  } else {
    cprintf ( "input is ");
    printBin(simmins, 8);
    cprintf ( " output is ");
    printBin(outt[simcrs], outputs);
    cprintf ( "                           ");
  }

  gotoyx ( 3, 1 );

  lenny = 1;
  dsp = listart;

//for ( dsp = listart TO (listart + listlen)


    if ( mode == 's' ) {
      y = wherey();
      x = wherex();
      gotoyx ( 1, 29 );   //update display

      printBin(outt[simcrs], outputs);

      cprintf ( "                           ");
      gotoyx ( y, x );
    }
    // universe = dsp - (dsp / level) - (dsp / level) * (level - 1);
   //if ( universe < 2 ^ inmask ) {
  do {   
   lenny++;

   if ( mode == 's' ) {   // line highlight for ( simulate
     simcrs = (simlin * level) + simmins;
     if ( simcrs < listart ) {
       listart = simcrs;
       //GOTO loup
       continue;
     }
     if ( simcrs > (listart + listlen) ) {
       listart = simcrs + listlen / 2;
  //     GOTO loup
       continue;
     }
     if ( simcrs == dsp ) {
       colour( 14, 1 );
     } else {
       colour( 7, 0 );
     }
   } else {
     colour( 7, 0 );
   }


   if ( (dsp % level) == 0 ) {      //**************** do a div 0 check!!!
     cprintf ("%d                                                         ",  dsp / level);
   } else {
    // for ( z = 1 ; z < places(dsp / level) + 1; z++ ) {
    //   cprintf ( " ");
    // }
    cprintf("                                                            ");
   }
   gotoyx ( wherey(), 6 );
   cprintf ( "if input = ");
   gotoyx ( wherey(), 17);
   cprintf ( "         ");
   gotoyx ( wherey(), 17);

   printBin(dsp - (dsp / level) - (dsp / level) * (level - 1), inputs);

   gotoyx ( wherey(), 26);
   cprintf ( "then output");
   gotoyx ( wherey(), 38);
   cprintf ( "    ");
   gotoyx ( wherey(), 38 );
   if ( crsx == 2 & crsy == dsp & mode == 'e' ) { colour( 14, 1 ) ; }

   printBin(outt[dsp], outputs);

   if ( mode == 'e' ) { colour( 7, 0) ; }
   gotoyx ( wherey(), 45 );
   cprintf ( "; goto ");
   if ( crsx == 3 & crsy == dsp & mode == 'e' ) { colour( 14, 1) ; }
   cprintf ("%d", gotoo[dsp]);
   if ( mode == 'e' ) { colour( 7, 0 ) ; }
   cprintf ( "            \n");
  // } else {
  //  if ( crsy = dsp ) { crsy = crsy + 1
  // }
  //NEXT dsp

  dsp++;
  colour( 7, 0 );
  
  } while (lenny < listlen + 2)  ;



gotoyx ( 24, 1 );
 if ( mode == 'e' ) {
   cprintf ( "Enter = edit value, q = menu, s = simulate mode                      ");
   //cprintf ( "Enter = edit value, esc = menu, m = set scanf mask, s = simulate mode";
 } else {
   cprintf ( "Enter = change input, q = menu, [spacebar] = next line, e = edit mode");
 }


//subloup:

   do {
     a = getche();
   }while ( a == '\0' );
   

if ( mode == 'e' ) {
   if ( a == 's' | a == 'S' ) {
     mode = 's';
    listart = simlin;
   }

   if ( a == 0x105 ) {   // cursor right
     if ( crsx < 3 ) {
        crsx++;
     } else {
        if ( crsy < celing - 1 ) {
         crsx = 2;
         crsy++;
         if ( crsy > listart + listlen ) {
          if ( listart < celing - 1 - listlen ) {
           listart++;
          } else {
           continue;
          }
         }
       }
     }
   }

   if ( a == 0x104 ) {   // cursor left
     if ( crsx > 2 ) {
        crsx--;
     } else {
        if ( crsy > 0 ) {
         crsx = 3;
         crsy--;
         if ( crsy < listart ) {
          if ( listart > 0 ) {
           listart--;
          } else {
           continue;
          }
         }
        }
     }
   }


   if ( a == 0x103 ) {   //cursor up?
     if ( crsy > 0 ) {
       crsy--;
       if ( crsy < listart ) {
        if ( listart > 0 ) {
         listart--;
        } else {
         continue;
        }
       }
     } else {
       continue;
     }
   }

   if ( a == 0x102 ) {    //cursor down?
     if ( crsy < celing - 1 ) {                      // if not at end of list
       crsy++;
       if ( listart + listlen < crsy ) {        // if off bottm of screen
          if ( listart < celing - 1 - listlen ) {    // if not at end of list
            listart++;              // scroll down
          } else {
            continue;                       // } else { new scanf
          }
       }
     } else {
       continue;                          // if off end of list, new scanf
     }
   }

   if ( a == 'm' | a == 'M' ) {    // get scanf mask
     gotoyx ( 24, 1 );
     cprintf ( "                                                                     ");
     gotoyx ( 24, 1 );
     cprintf("How many inputs would you like to show");
     scanf ("%d", &inmask);
   }

   if ( a == 'q' | a == 'Q' ) { return; }     //enough already?

   if ( a == '+' ) {
     if ( crsx == 2 ) { outt[crsy]++; }
     if ( crsx == 3 ) { gotoo[crsy]++; }
   }

   if ( a == '-' ) {
    if ( crsx == 2 ) { outt[crsy]--; }
    if ( crsx == 3 ) { gotoo[crsy]--; }
   }

   if ( a == 13 ) {            //edit vlaue?
    saved = 0;
    gotoyx ( 24, 1 );
    cprintf ( "                                                                     ");
    gotoyx ( 24, 1 );
    cprintf ( "Current value: ");
    if ( crsx == 2 ) {
      cprintf ( "%d", outt[crsy]);
    }
    if ( crsx == 3 ) {
      cprintf ("%d", gotoo[crsy]);
    }
    cprintf(" New value ");
    cscanf ("%d", &k);
    if ( crsx == 2 ) {
      outt[crsy] = k;
    }
    if ( crsx == 3 ) {
      gotoo[crsy] = k;
    }
   }

 } else {  
// ((((((((((((((((((((( simulate mode ))))))))))))))))))))

   if ( a == 'e' | a == 'E' ) {
     mode = 'e';
     //listart = crsy
     crsy = simlin;
   }

   if ( a == ' ' ) {
     z = gotoo[simcrs];
     if ( z < (256 / level) & (z >= 0) ) {
       simlin = z;
     } else {
      // the error thing

      boxPrompt("Illegal goto value, hit a key", "");

      getche();

      gotoyx ( 10, 9 );
      cprintf ( "                                             ");
      gotoyx ( 11, 9 );
      cprintf ( "                                             ");
      gotoyx ( 12, 9 );
      cprintf ( "                                             ");

     }
   }

   if ( a == 'q' | a == 'Q' ) { return; }     //enough already?

   if ( a == 13 ) {            //edit vlaue?
    gotoyx ( 24, 1);
    cprintf ( "                                                                       ");
    gotoyx ( 24, 1 );
    cprintf ( "Current value: ");
    cprintf ( "%d ", simmins);;
    cprintf ( "New value " );
    cscanf  ("%d", &z);
    if ( (z < level) & (z >= 0) ) {
      simmins = z;
    } else {
    
      gotoyx ( 10, 9 );

      boxPrompt("Illegal input value, hit a key", "");

      getche();

      gotoyx ( 10, 9 );
      cprintf ( "                                             ");
      gotoyx ( 11, 9 );
      cprintf ( "                                             ");
      gotoyx ( 12, 9 );
      cprintf ( "                                             ");

    }
   }
  

    }
  } while (1);
}

//************************ print the main menu ***********************

void printmenu(int s) {
 clrscr();
 gotoyx ( 23, 1 );
 colour( 2, 0 );
 cprintf ( "-------------------------------------------------------------------------------\n");
 colour( 7, 0 );
 cprintf ( "Press Enter to select blue or red hilighted\n");
 colour( 8, 0 );
 cprintf ( "Written by Dan Williams 4/10/98\n");
 colour( 7, 0 );
 gotoyx ( 1, 1 );
 cprintf ("\n");
 colour( 15, 1 );
 cprintf ( "               THE GREAT MEMORY CONTROLLER DEVELOPER THINGY                   \n");
 colour( 7, 0 );
 cprintf ("\n");
 if ( filename[0] == '\0' ) {
    cprintf ( "No program loaded\n");
  } else {
    cprintf ( "The file selected is ' %s '\n", filename);
  }
 cprintf("\n");
 if ( filename[0] == '\0' & s == 1 ) { colour( 4, 0 ); }
   cprintf ( "         1  Start a new program  \n");
 colour( 7, 0 );
 if ( filename[0] == '\0' & s == 2 ) { colour( 1, 0); }
   cprintf ( "         2  Load a program \n");
   colour( 7, 0 );
 if ( filename[0] != '\0' & s == 3 ) { colour( 2, 0 );}      //emphasis if not done
 cprintf ( "         3  Save program \n");
 colour( 7, 0 );
 if ( filename[0] != '\0' & s == 4 ) { colour( 2, 0 ); }
 cprintf ( "         4  View / Edit / Test \n");
 colour( 7, 0 );
 if ( filename[0] != '\0' & s == 5 ) { colour( 2, 0 ); }
 cprintf ( "         5  Print program\n");
 colour( 7, 0 );
 if ( filename[0] != '\0' & s == 6 ) { colour( 2, 0 ); }
 cprintf ( "         6  View mem listing\n");
 colour( 7, 0 );
 if ( s == 7 ) { colour( 2, 0 ); }
 cprintf ( "         7  Exit\n");
 colour( 7, 0 );
 if ( s == 8 ) { colour( 2, 0 ); }
 cprintf ( "         8  info\n");
 colour( 7, 0 );
 cprintf("\n");
 cprintf ( "Your selection please.. \n");
}
//
// //*********************** make shure user has saved *************
//
//castout:
// if ( saved = 1 ) {
//  END
// } else {
//  CLS
//  gotoyx ( 12, 8
//  colour( 4
//  scanf " Would you like to save the changes that you made (Y/N)"; yn$
//  if ( yn$ = "y" OR yn$ = "Y" ) {
//    OPEN filename for ( OUTPUT AS #1
//    cprintf ( #1, scanfs
//    cprintf ( #1, outputs
//    for ( n = 0 TO 255
//     cprintf ( #1, outt(n); ","; gotoo(n)
//    NEXT n
//    CLOSE #1
//  } else {
//   colour( 7
//   END
//  }
// }
//

void printBin(int input, int mask) {
  int z, temp, t;
  
  z = pow(2, mask-1);
  for ( temp = mask; temp != 0; temp--) { //start at start marker
    t = input & z;   //test place
    if ( t != 0 ) {
      cprintf ( "1" );
    } else {
      cprintf ( "0");
    }
   z /= 2;  // next place
  }
}



void inputBox () {
 gotoyx ( 10, 9 );
 colour( 15, 1 );
 cprintf ( "+-----------------------------------+");
 gotoyx ( 11, 9 );
 cprintf ( "|                                   |");
 gotoyx ( 12, 9 );
 cprintf ( "+-----------------------------------+");
}

void boxPrompt(char *prompt, char * hint) {
 inputBox();

 colour(8, 0);
 gotoyx(11, 11+strlen(prompt)); 
 cprintf("%s", hint);
 
 colour( 7, 0 );
 gotoyx ( 11, 11);
 cprintf("%s", prompt);
 
}

int places(float i) {

  if (i < 10)          return 1;
  if (i < 100)         return 2;
  if (i < 1000)        return 3;  
  if (i < 10000)       return 4;
  if (i < 100000)      return 5;
  if (i < 1000000)     return 6;
  if (i < 10000000)    return 7;
  if (i < 100000000)   return 8;
  if (i < 1000000000)  return 9;
  
}



