home *** CD-ROM | disk | FTP | other *** search
/ 1,001 Nights of Doom / 1001NightsOfDoom1995wickedSensations.iso / graphics / chookexe.zip / BINPATCH.C next >
C/C++ Source or Header  |  1994-07-19  |  5KB  |  206 lines

  1. /*  binpatch.c  Simple non-interactive binary patch utility
  2.  *  DWF  7/19/94  First version and hopefully the last.  Just say NO to
  3.  *  creeping features!
  4.  *
  5.  *  Usage:  binpatch infile outfile < patch
  6.  *
  7.  *  This program is written so that it should work under Messy-DOS, i.e.,
  8.  *  it uses temporary files instead of reading the entire binary into memory.
  9.  *  I have successfully compiled it with an old version of Turbo C, but I had
  10.  *  to add an #ifdef to the includes.
  11.  *
  12.  *  Here is an example patch file.  Comments, with # in the first column,
  13.  *  are ignored; the other lines alternate between search-string and
  14.  *  replace-string in hexadecimal.
  15.  *
  16.  *    #  Patches for shareware doom.exe 1.5 beta posted to alt.games.doom by
  17.  *    #  ep104@cus.cam.ac.uk (Elias 'CaveMan' Papavassilopoulos)
  18.  *    #
  19.  *    #  Fix crash & burn on idkfa + shotgun
  20.  *    B9 09 00 00 00 C7 40 B0 02 00 00 00
  21.  *    B9 08 00 00 00 C7 40 B0 02 00 00 00
  22.  *    #
  23.  *    #  Enable cheat codes in Nightmare mode
  24.  *    0F 85 29 03 00 00 83 3D 70 82 02 00 04
  25.  *    0F 85 29 03 00 00 83 3D 70 82 02 00 45
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #ifndef __TURBOC__
  31. #include <unistd.h>
  32. #endif
  33.  
  34. /* Names for temporary files */
  35. #define temp1 "temp1"
  36. #define temp2 "temp2"
  37.  
  38. /* Maximum length of text lines on input */
  39. /*#define maxlen 80*/
  40. #define maxlen 256
  41.  
  42. void
  43. usage ()
  44. {
  45.   puts ("Usage:  binpatch infile outfile < patch");
  46.   exit (0);
  47. }
  48.  
  49. void
  50. bail ()
  51. {
  52.   unlink (temp1);
  53.   unlink (temp2);
  54.   exit (-1);
  55. }
  56.  
  57. void
  58. dont_clobber (char *fname)
  59. {
  60.   FILE *inf;
  61.   if ((inf = fopen (fname, "r"))) {
  62.     printf ("Will not overwrite existing file %s -- rename or delete it\n",
  63.       fname);
  64.     exit (-1);
  65.   }
  66. }
  67.  
  68. int
  69. get_line (unsigned char line[maxlen], int *len)
  70. {
  71.   char txtlin[maxlen];
  72.   int t, tt;
  73.   *len = 0;
  74.   do t = (int) fgets (txtlin, maxlen, stdin); while ((txtlin[0] == '#') && t);
  75.   if (!t)
  76.     return 0;
  77.   if (strlen (txtlin) >= maxlen-1) {
  78.     printf ("Line in patch file >= %d characters:  too long\n", maxlen-1);
  79.     bail ();
  80.   }
  81.   t = 0;
  82.   while (sscanf (txtlin+t, "%x", &tt) == 1) {
  83.     line[(*len)++] = (unsigned char)tt;
  84.     while (isalnum (txtlin[t])) t++;
  85.     while (isspace (txtlin[t])) t++;
  86.   }
  87.   return *len;
  88. }
  89.  
  90. void
  91. search_and_destroy (FILE *inf, FILE *otf, unsigned char srch[maxlen],
  92. int srchlen, unsigned char repl[maxlen], int *matches)
  93. {
  94.   int matchnum=0, fchar, t;
  95.   while ((fchar = fgetc (inf)) != EOF) {
  96.     if (fchar == (int)srch[matchnum]) {
  97.       matchnum++;
  98.       if (matchnum == srchlen) {
  99.         for (t=0;t<matchnum;t++)
  100.           fputc ((int)repl[t], otf);
  101.         matchnum = 0;
  102.         (*matches)++;
  103.       }
  104.     } else {
  105.       for (t=0;t<matchnum;t++)
  106.         fputc ((int)srch[t], otf);
  107.       matchnum = 0;
  108.       fputc (fchar, otf);
  109.     }
  110.   }
  111.   for (t=0;t<matchnum;t++)
  112.     fputc ((int)srch[t], otf);
  113. }
  114.  
  115. int
  116. main (int argc, char **argv)
  117. {
  118.   FILE *inf=NULL, *otf=NULL;
  119.   int matches, whichtemp=0, srchlen, repllen, pnum=0;
  120.   unsigned char srch[maxlen], repl[maxlen];
  121.   if (argc != 3)
  122.     usage ();
  123.  
  124.   dont_clobber (temp1);
  125.   dont_clobber (temp2);
  126.   dont_clobber (argv[2]);
  127.  
  128.   /* Open initial input file */
  129.   if (!(inf = fopen (argv[1], "rb"))) {
  130.     perror ("fopen");
  131.     usage ();
  132.   }
  133.  
  134.   while (get_line (srch, &srchlen)) {
  135.     pnum++;
  136.     if (!(get_line (repl, &repllen))) {
  137.       printf ("Unexpected EOF in patch file\n");
  138.       bail ();
  139.     }
  140.     if (srchlen != repllen) {
  141.       printf ("Search-string length != replace-string length in patch file\n");
  142.       bail ();
  143.     }
  144.  
  145.     /* Open files */
  146.     if (whichtemp) {
  147.       if (!(otf = fopen (temp1, "wb"))) {
  148.         perror ("fopen");
  149.         bail ();
  150.       }
  151.       if (!inf)
  152.         if (!(inf = fopen (temp2, "rb"))) {
  153.           perror ("fopen");
  154.           bail ();
  155.         }
  156.     } else {
  157.       if (!(otf = fopen (temp2, "wb"))) {
  158.         perror ("fopen");
  159.         bail ();
  160.       }
  161.       if (!inf)
  162.         if (!(inf = fopen (temp1, "rb"))) {
  163.           perror ("fopen");
  164.           bail ();
  165.         }
  166.     }
  167.     whichtemp = 1 - whichtemp;
  168.  
  169.     matches = 0;
  170.     search_and_destroy (inf, otf, srch, srchlen, repl, &matches);
  171.     printf ("Chunk #%d:  ", pnum);
  172.     switch (matches) {
  173.     case 0:
  174.       puts ("Error -- no strings matched.");
  175.       break;
  176.     case 1:
  177.       puts ("Replaced 1 string.");
  178.       break;
  179.     default:
  180.       printf ("Replaced %d strings.\n", matches);
  181.     }
  182.  
  183.     fclose (inf);
  184.     fclose (otf);
  185.     inf = otf = NULL;
  186.   }
  187.  
  188.   unlink (argv[2]);
  189.   if (whichtemp) {
  190.     unlink (temp1);
  191.     if (rename (temp2, argv[2])) {
  192.       perror ("rename");
  193.       bail ();
  194.     }
  195.   } else {
  196.     unlink (temp2);
  197.     if (rename (temp1, argv[2])) {
  198.       perror ("rename");
  199.       bail ();
  200.     }
  201.   }
  202.  
  203.   exit (0);
  204. }
  205.  
  206.