#include <stdio.h>

#define versao "v2.1 beta 1"
#define data "2002/mar/09"



//////////////////////////////////////////////////////////////////////
// Algums valores globais

FILE *f,*dest;
#define tam1 10
#define tam2 44
 //                           not ax     not dx    mov cx,0037h     div cx    mov
 unsigned char antes1 [tam1]={0xF7,0xD0, 0xF7,0xD2, 0xB9,0x37,0x00, 0xF7,0xF1, 0xA3};
 //                           not ax     not dx    mov ax,FFFFh    nop  nop   mov
 unsigned char depois1[tam1]={0xF7,0xD0, 0xF7,0xD2, 0xB8,0xFF,0xFF, 0x90,0x90, 0xA3};

 //                           mov bx,sp    mov cx,ss:[bx+4]    jcxz @@2     mov es,seg 0000   xor di,di  mov bl,es:[di]  mov ax,DelayCnt xor dx,dx  call DelayLoop   loop @@1     retf 0002       sub ax,1        sbb dx,0       jc @@2   cmp bl,es:[di]    je @@1   retn
 unsigned char antes2 [tam2]={0x8B,0xDC, 0x36,0x8B,0x4F,0x04, 0xE3,0x13, 0x8E,0x06,0x00,0x00, 0x33,0xFF, 0x26,0x8A,0x1D, 0xA1,0x00,0x00, 0x33,0xD2, 0xE8,0x05,0x00, 0xE2,0xF6, 0xCA,0x02,0x00, 0x2D,0x01,0x00, 0x83,0xDA,0x00, 0x72,0x05, 0x26,0x3A,0x1D, 0x74,0xF3, 0xC3};
 //                           mov bx,sp    mov cx,ss:[bx+4]    jcxz @@2    mov ax,1000 ;  mul cx  ; mov cx,dx;mov dx,ax  mov ah,86;  int 15  ;   retf 0002   ;                                                                                                       retn
 unsigned char depois2[tam2]={0x8B,0xDC, 0x36,0x8B,0x4F,0x04, 0xE3,0x0D, 0xB8,0xE8,0x03,0xF7, 0xE1,0x89, 0xD1,0x89,0xC2, 0xB4,0x86,0xCD, 0x15,0xCA, 0x02,0x00,0x90, 0x90,0x90, 0x90,0x90,0x90, 0x90,0x90,0x90, 0x90,0x90,0x90, 0x90,0x90, 0x90,0x90,0x90, 0x90,0x90, 0xC3};
 unsigned char acao2  [tam2]={   1,   1,    1,   1,   1,   1,    1,   1,    1,   1,   0,   0,    1,   1,    1,   1,   1,    1,   0,   0,    1,   1,    1,   1,   1,    1,   1,    1,   1,   1,    1,   1,   1,    1,   1,   1,    1,   1,    1,   1,   1,    1,   1,    1};
//Acao -> 1=Byte identico; 0=Byte variavel

 unsigned char erro=0;
 int tipo_de_erro;

 unsigned char idioma=0; //Suporte a mais de um idioma: 0=Portugues



//////////////////////////////////////////////////////////////////////
// Inicio das funcoes

void cabecalho(){
 printf("PPP - Pascal Program Patch " versao " (" data ")\n");
 printf("      Criado por Denilson F. de S  (CrazyTerabyte)\n");
 printf("\n");
}



void ajuda(){
 printf("Este programa serve para resolver o famoso \"Runtime error 200\" ao se executar\n");
 printf("programas criados com Turbo Pascal (c) defeituoso em computadores mais r pidos\n");
 printf("que 200MHz. O defeito estava na Unit CRT do Pascal e j  foi corrigido atrav‚s\n");
 printf("de um patch, por‚m muitos programas nÆo foram recompilados e continuam com o\n");
 printf("bug. Nesses casos, nos quais nÆo se tem acesso ao c¢digo fonte para se efetuar\n");
 printf("a recompila‡Æo, este programa ‚ £til. Ele altera a parte defeituosa, removendo\n");
 printf("o bug.\n\n");

 printf("O PPP v2.0 altera o c¢digo de inicializa‡Æo da CRT que causava a divisÆo por\n");
 printf("zero (erro 200) e tamb‚m altera o c¢digo da procedure Delay, de modo que o\n");
 printf("programa, ap¢s a aplica‡Æo do patch, torne-se inteiramente utiliz vel.\n\n");

 printf("A versÆo 2.0 conserta todos os bugs da versÆo anterior (1.0). Al‚m do j \n");
 printf("descrito no par grafo anterior, esta versÆo pergunta antes de sobrescrever\n");
 printf("o arquivo de destino, caso j  exista.\n\n");

/* printf("A altera‡Æo que este programa faz elimina o Runtime error 200, tornando o\n");
 printf("programa mais ou menos utiliz vel. Caso o programa original utilize a fun‡Æo\n");
 printf("Delay, provavelmente nÆo funcionar  corretamente.\n\n");

 printf("O PPP nÆo faz milagres (ainda :P). Provavelmente os programas por ele\n");
 printf("consertados ainda fiquem r pidos demais nos computadores novos e muito lentos\n");
 printf("em computadores velhos (mantenha a versÆo original do seu programa, ‚ melhor).\n");
 printf("De qualquer modo, assim ainda ‚ melhor que o Runtime error 200. Estou estudando\n");
 printf("uma forma de consertar totalmente os bugs da Delay. Enquanto nÆo sai o PPP 2.0,\n");
 printf("a versÆo 1.0 ‚ uma mÆo na roda!\n\n");*/

 printf("Criado por:  Denilson F. de S  (CrazyTerabyte)\n");
 printf("             denilson@vialink.com.br\n");
 printf("             http:/""/go.to/denilson - http:/""/pagina.de/denilson\n");

 exit(2);
}



void aplicar(long int pos1, long int pos2){
 unsigned char i;   //Loop FOR
 int b;   //Contem o byte lido do arquivo


 rewind(f);



 while(ftell(f)<pos1) fputc(fgetc(f),dest);  //Localiza o patch 1

 for (i=0;i<tam1;i++){    //Patch 1 (div cx)
   fgetc(f);
   fputc(depois1[i],dest);
 }



 while(ftell(f)<pos2) fputc(fgetc(f),dest);  //Localiza o patch 2

 for (i=0;i<tam2;i++){    //Patch 2 (Delay)
   fgetc(f);
   fputc(depois2[i],dest);
 }

 //Restante do arquivo
 while((b=fgetc(f))!=EOF) fputc(b,dest);
}



long int procurar1(){
 unsigned char i;   //Loop FOR
 int b;   //Contem o byte lido do arquivo
 long int posicao;  //Posicao no arquivo - ftell() fseek()

 while( (b=fgetc(f))!=EOF ){
   if(b==antes1[0]){       //Se o byte e' igual, comeca a busca
     posicao=ftell(f)-1;

     for(i=1;i<tam1 && (b=fgetc(f))!=EOF;i++)
       if(b!=antes1[i]) break;  //Nao, nao e' o lugar ainda

     if(i==tam1) return posicao;    //Opa, encontramos!
   }
 }
 erro=3;
 return 0;
}



long int procurar2(){
 unsigned char i;   //Loop FOR
 int b;   //Contem o byte lido do arquivo
 long int posicao;  //Posicao no arquivo - ftell() fseek()

 while( (b=fgetc(f))!=EOF ){
   if(b==antes2[0]){       //Se o byte e' igual, comeca a busca
     posicao=ftell(f)-1;

     for(i=1;i<tam2 && (b=fgetc(f))!=EOF;i++)
       if(acao2[i] && b!=antes2[i]) break;  //Nao, nao e' o lugar ainda

     if(i==tam2) return posicao;    //Opa, encontramos!
   }
 }
 erro=1;
 return 0;
}



//////////////////////////////////////////////////////////////////////
// MAIN

int main(int argc, char *argv[]){
 unsigned char i;
 long int pos1;

 cabecalho();

 for(i=1;i<argc;i++) if(argv[i][0]=='?' || argv[i][1]=='?') ajuda();

 if(argc==3){   //Parametros corretos

   f=fopen(argv[1],"rb");
   if(f==NULL){             //Erro no arquivo de origem
     erro=10;
     tipo_de_erro=ferror(f);
   }else{

     dest=fopen(argv[2],"rb");
     if(dest!=NULL){            //Arquivo de destino j  existe
       fclose(dest);
       printf("O arquivo \"%s\" j  existe. Deseja sobrescrevˆ-lo? [s/n]",argv[2]);
       do{
         i=getchar();
         if(i<97) i+=32;
       }while(i!='s' && i!='n');

       if(i=='n'){     //No caso de nÆo sobrescrever o arquivo
         fclose(f);
         erro=11;
       }
     }
   }

   if(erro==0){

     if(pos1=procurar1()){  //Caso encontre o bug, come‡a a realizar o trabalho

       dest=fopen(argv[2],"wb");  //Verifica o arquivo de destino somente se o de origem precisar de patch
       if(dest==NULL){            //O arquivo de destino possui erros
         erro=12;
         tipo_de_erro=ferror(dest);
         fclose(f);
       }

       if(erro==0){
         aplicar(pos1,procurar2());   //Agora verifica se precisa do segundo patch e aproveita para aplic -los
       }
     }
   }
   if(erro<10){
     fclose(f);
     fclose(dest);
   }
 } else {
   printf("Utilize \"ppp programa.exe destino.exe\"\n");
   printf("Para mais informa‡äes, digite \"ppp ?\"");
   return 2;
 }

 switch(erro){
   case 0: printf("O arquivo \"%s\" foi alterado com sucesso e gravado em \"%s\".",argv[1],argv[2]); break;
   case 1: printf("O arquivo \"%s\" foi alterado com sucesso e gravado em \"%s\".",argv[1],argv[2]); break;
// case 2: Ajuda
   case 3: printf("O arquivo \"%s\" nÆo precisa de patch.",argv[1]); break;
   case 10: printf("Erro %i no arquivo \"%s\".",tipo_de_erro,argv[1]); break;
// case 11: Nao sobrescreveu o arquivo
   case 12: printf("Erro %i no arquivo \"%s\".",tipo_de_erro,argv[2]); break;
 }
 return erro;
}

