home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Instant Doom Levels
/
Instant.Doom.Levels.-.Level.Master.II.iso
/
WADS
/
DOOM1
/
PATCHES
/
ZIPPED
/
CHOOKEXE.ZIP
/
BINPATCH.C
next >
Wrap
C/C++ Source or Header
|
1994-07-19
|
5KB
|
206 lines
/* binpatch.c Simple non-interactive binary patch utility
* DWF 7/19/94 First version and hopefully the last. Just say NO to
* creeping features!
*
* Usage: binpatch infile outfile < patch
*
* This program is written so that it should work under Messy-DOS, i.e.,
* it uses temporary files instead of reading the entire binary into memory.
* I have successfully compiled it with an old version of Turbo C, but I had
* to add an #ifdef to the includes.
*
* Here is an example patch file. Comments, with # in the first column,
* are ignored; the other lines alternate between search-string and
* replace-string in hexadecimal.
*
* # Patches for shareware doom.exe 1.5 beta posted to alt.games.doom by
* # ep104@cus.cam.ac.uk (Elias 'CaveMan' Papavassilopoulos)
* #
* # Fix crash & burn on idkfa + shotgun
* B9 09 00 00 00 C7 40 B0 02 00 00 00
* B9 08 00 00 00 C7 40 B0 02 00 00 00
* #
* # Enable cheat codes in Nightmare mode
* 0F 85 29 03 00 00 83 3D 70 82 02 00 04
* 0F 85 29 03 00 00 83 3D 70 82 02 00 45
*/
#include <stdio.h>
#include <ctype.h>
#ifndef __TURBOC__
#include <unistd.h>
#endif
/* Names for temporary files */
#define temp1 "temp1"
#define temp2 "temp2"
/* Maximum length of text lines on input */
/*#define maxlen 80*/
#define maxlen 256
void
usage ()
{
puts ("Usage: binpatch infile outfile < patch");
exit (0);
}
void
bail ()
{
unlink (temp1);
unlink (temp2);
exit (-1);
}
void
dont_clobber (char *fname)
{
FILE *inf;
if ((inf = fopen (fname, "r"))) {
printf ("Will not overwrite existing file %s -- rename or delete it\n",
fname);
exit (-1);
}
}
int
get_line (unsigned char line[maxlen], int *len)
{
char txtlin[maxlen];
int t, tt;
*len = 0;
do t = (int) fgets (txtlin, maxlen, stdin); while ((txtlin[0] == '#') && t);
if (!t)
return 0;
if (strlen (txtlin) >= maxlen-1) {
printf ("Line in patch file >= %d characters: too long\n", maxlen-1);
bail ();
}
t = 0;
while (sscanf (txtlin+t, "%x", &tt) == 1) {
line[(*len)++] = (unsigned char)tt;
while (isalnum (txtlin[t])) t++;
while (isspace (txtlin[t])) t++;
}
return *len;
}
void
search_and_destroy (FILE *inf, FILE *otf, unsigned char srch[maxlen],
int srchlen, unsigned char repl[maxlen], int *matches)
{
int matchnum=0, fchar, t;
while ((fchar = fgetc (inf)) != EOF) {
if (fchar == (int)srch[matchnum]) {
matchnum++;
if (matchnum == srchlen) {
for (t=0;t<matchnum;t++)
fputc ((int)repl[t], otf);
matchnum = 0;
(*matches)++;
}
} else {
for (t=0;t<matchnum;t++)
fputc ((int)srch[t], otf);
matchnum = 0;
fputc (fchar, otf);
}
}
for (t=0;t<matchnum;t++)
fputc ((int)srch[t], otf);
}
int
main (int argc, char **argv)
{
FILE *inf=NULL, *otf=NULL;
int matches, whichtemp=0, srchlen, repllen, pnum=0;
unsigned char srch[maxlen], repl[maxlen];
if (argc != 3)
usage ();
dont_clobber (temp1);
dont_clobber (temp2);
dont_clobber (argv[2]);
/* Open initial input file */
if (!(inf = fopen (argv[1], "rb"))) {
perror ("fopen");
usage ();
}
while (get_line (srch, &srchlen)) {
pnum++;
if (!(get_line (repl, &repllen))) {
printf ("Unexpected EOF in patch file\n");
bail ();
}
if (srchlen != repllen) {
printf ("Search-string length != replace-string length in patch file\n");
bail ();
}
/* Open files */
if (whichtemp) {
if (!(otf = fopen (temp1, "wb"))) {
perror ("fopen");
bail ();
}
if (!inf)
if (!(inf = fopen (temp2, "rb"))) {
perror ("fopen");
bail ();
}
} else {
if (!(otf = fopen (temp2, "wb"))) {
perror ("fopen");
bail ();
}
if (!inf)
if (!(inf = fopen (temp1, "rb"))) {
perror ("fopen");
bail ();
}
}
whichtemp = 1 - whichtemp;
matches = 0;
search_and_destroy (inf, otf, srch, srchlen, repl, &matches);
printf ("Chunk #%d: ", pnum);
switch (matches) {
case 0:
puts ("Error -- no strings matched.");
break;
case 1:
puts ("Replaced 1 string.");
break;
default:
printf ("Replaced %d strings.\n", matches);
}
fclose (inf);
fclose (otf);
inf = otf = NULL;
}
unlink (argv[2]);
if (whichtemp) {
unlink (temp1);
if (rename (temp2, argv[2])) {
perror ("rename");
bail ();
}
} else {
unlink (temp2);
if (rename (temp1, argv[2])) {
perror ("rename");
bail ();
}
}
exit (0);
}