#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
  const int MAXLEN = 17;                  //Maximum Length of string to search.
                                          //Arbitrary, but needn't be too long here.
  int Chan, Compare, Signal, Oldnum, Num; //Data variables.      
  int Counter = 0;                        //Pseudo-Pointer into file.
  int Length = 0;                         //Length of search string.
  int Found = 0;                          //Number of sequential matched characters.
  int Diff = 0;                           //Relational difference between 2 characters.
  int Shift = 0;                          //Number of occurrences of a string match.
  int Same = 1;                           //Flag for uniformity in shifting amounts.
  char Response = 'Y';                    //No further explanation.
  char Code[MAXLEN];                      //Storage array for string.
  FILE *FI,*FO;
  
  if(argc>2)
  {
    fprintf(stderr,"Usage: %s [file]\n",argv[0]);                       //Instructions for Dummies(TM).
    return(1);
  }

  if(!(FI=argc<2? stdin:fopen(argv[1],"rb")))
  { fprintf(stderr,"%s: Can't open input file\n",argv[0]);return(1); }

  cout << "\n\tROMSearcher v1.0, ©1998-99 Chris Covell (ccovell@direct.ca)"
       << "\n\t  Searches for text hidden in game ROMs and other files.\n";

  while((Length<3)||(Length>=MAXLEN))
  {
    cout << "\nEnter search string of length 3-" << MAXLEN-1 << ": ";
  
    cin >> Code;
  
    while(Code[Length]!='\0')                   //Search for terminator.
    {
      Length++;
    }
    if(Length>=MAXLEN) Code[MAXLEN-1]='\0';     //Make sure there is one!
  }  
  cout << endl;
  
  while((Response=='Y')||(Response=='y'))
  {
    Compare=fgetc(FI);
    while(((Chan=fgetc(FI))>=0)&&(Found<Length-1))      //Halt either at EOF or matched string.
    {
      Counter++;
      Diff = Code[Found] - Code[Found+1];               //Compare difference between 2 chars.
      if(Compare-Chan==Diff)
      {
          Found++;
      }
      else
      {
          Found=0;
      }
    
      Signal=Compare;
      Compare=Chan;
    }
    if(Found==Length-1)                                 //If found a perfect match...
    {
      Num = (Signal - Code[Found-1]);
      cout << "Match found at offset " << Counter-Found << ", shifted by " << Num << "\tLetter 'A' in CHR Bank should be at position " << 65 + Num << endl;
      Found=0;                                          //Turn off found flag again.
      Counter+=2;                                       
      Response = 'Y';
      if(!Shift) Oldnum = Num;                          //If this is 1st match...
      Shift++;                                          //Increase # of matches.
      if(Same)                                          //If shift indexes are same up to now...
      {
          Same = (Num==Oldnum);                         //Test if they are still the same.
          Oldnum = Num;
      }
    }
    else
    {
      Response = 'N';
      cout << "\nNo Further Matches Found.\n\n";
    }
  }
  fclose(FI);
  
  if((Shift)&&(!(Same&&!Num)))                                          //Some complex logic here...
  {
    cout << "Would you like to Shift the bytes in the file? (Y/N) ";
    cin >> Response;
    
    if((Response=='Y')||(Response=='y'))
    {

      if(!(FI=argc<2? stdin:fopen(argv[1],"rb")))
      { fprintf(stderr,"%s: Can't open input file\n",argv[0]);return(1); }
      if(!(FO=argc<2? stdout:fopen("Shifted.BIN","wb")))
      { fprintf(stderr,"%s: Can't open output file\n",argv[0]);return(1); }

      if((Shift==1)||(Same)) Num*=-1;                           //If all the shifting indexes were the same...
      else                                                      //...then no need to prompt user...  if not...
      {
        cout << "Where should the letter 'A' be in the CHR bank? ";
        cin >> Num;

        Num=65-Num;
      }
      if(Num)
      {
        while((Chan=fgetc(FI))>=0)
        {
            Chan=Chan+Num;                                      //Shift bytes in file.
            fputc(Chan,FO);
        }
      
        fclose(FO);
        fclose(FI);
  
        cout << "Bytes shifted by " << Num << " into file 'Shifted.BIN'.\n  You can make all your modifications now.\n\n";
        
        
//Ignore this junk...    
/*code chahsr DCOCDS Dfk"!!"!sc=sp CfKDKps sjsj Hfds c char[] ajJ sejes= c"jcDHs ;shsjsJJdskkl
FFJSJk jssjk= K!!ss:PPW"W Dksk-s a;J[]FJks CchETT ""KFks LSSL dlsl*/ //fjfdss D=SSJEjFKKEK
/*Fss HFSJj chceoo HFfc FJFJFJ*/ char Disl[] = "!Jg!zpv!dbo!sfbe!uijt-!zpv!bsf!ezjoh\"!";//Deeug
//chahsr DCOCDS Dfk"!!"!sc=sp CfKDKps sjsj Hfds c cha[]r ajJ sejes= c"jcDHs ;shsjsJJdskkl     
    
        cout << "Would you now like to shift it back? (Y/N) ";
        cin >> Response;
    
        if((Response=='Y')||(Response=='y'))
        {

          if(!(FI=argc<2? stdin:fopen("Shifted.BIN","rb")))
          { fprintf(stderr,"%s: Can't open input file\n",argv[0]);return(1); }
          if(!(FO=argc<2? stdout:fopen("Output.ROM","wb")))
          { fprintf(stderr,"%s: Can't open output file\n",argv[0]);return(1); }
    
          while((Chan=fgetc(FI))>=0)
          {
              Chan=Chan-Num;
              fputc(Chan,FO);
          }
          cout << "Bytes shifted back to original position into file 'Output.ROM'.\n";
          Disl[0] = '!';
        }
      }
      else cout << "\n\tIt doesn't get shifted anywhere!\n";    //I'm not gonna move a bunch of bytes around...
      fclose(FO);                                               //if they end up back in the same place.
      fclose(FI);                                               //There's a program called "Copy" for that...

    }
  }
  return(0);
}
