diff options
Diffstat (limited to 'win32/fcp.c')
-rw-r--r-- | win32/fcp.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/win32/fcp.c b/win32/fcp.c new file mode 100644 index 000000000000..e578606c5d69 --- /dev/null +++ b/win32/fcp.c @@ -0,0 +1,167 @@ +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef _WIN32 +#include <io.h> +#else +#include <unistd.h> +#endif + +#ifdef FCPW +#include <windows.h> +#define FCP "fcpw" +#else +#define FCP "fcp" +#endif + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +static void fatal(const char *format, ...) +{ + va_list ap; +#ifdef FCPW + char buffer[640]; + + va_start(ap, format); + vsnprintf(buffer, sizeof buffer, format, ap); + MessageBox(NULL, buffer, FCP, MB_ICONSTOP | MB_OK); +#else + fprintf(stderr, "%s: ", FCP); + va_start(ap, format); + vfprintf(stderr, format, ap); + fputc('\n', stderr); +#endif + va_end(ap); + exit(1); +} + +static void error(const char *s) +{ +#ifdef FCPW + char buffer[640]; + + snprintf(buffer, sizeof buffer, "%s: %s", s, strerror(errno)); + MessageBox(NULL, buffer, FCP, MB_ICONSTOP | MB_OK); +#else + fprintf(stderr, "%s: ", FCP); + perror(s); +#endif + exit(1); +} + +#define SIZE ((1 << 24) + 1) + +#ifdef FCPW +#define main wrap +#endif + +static const char *usage = + "usage: " FCP " [OFFSET] FILE PATCH\n" + "\n" + FCP " 0.10.2, Copyright (C) 2017 Dimitar Toshkov Zhekov\n" + "\n" + "This program is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU General Public License as\n" + "published by the Free Software Foundation; either version 2 of\n" + "the License, or (at your option) any later version.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n"; + +int main(int argc, char **argv) +{ + unsigned char *buffer; + const char *name, *patch; + int f, n; + FILE *p; + char s[0x80]; + long ignore; + long minoff = -1, maxoff; + + if (argc == 4) + { + argv++; + if (sscanf(*argv, "%lx%n", &ignore, &n) != 1 || n != (int) strlen(*argv)) fatal("%s: invalid offset", *argv); + if (ignore < 0 || ignore >= SIZE) fatal("%s: offset out of range", ignore); + } + else if (argc != 3) + { + #ifdef FCPW + MessageBox(NULL, usage, FCP, MB_OK); + #else + fputs(usage, stderr); + #endif + return 1; + } + if ((buffer = malloc(SIZE)) == NULL) error(FCP); + name = argv[1]; + patch = argv[2]; + + if ((f = open(name, O_RDWR | O_BINARY)) == -1) error(name); + if ((n = read(f, buffer, SIZE)) == -1) error(name); + if (n == SIZE) fatal("%s: larger than %d bytes", name, SIZE - 1); + if ((p = fopen(patch, "r")) == NULL) error(patch); + + while (fgets(s, sizeof s, p) != NULL) + { + char *lf; + long offset; + unsigned orig, chng; + + if ((lf = strchr(s, '\n')) != NULL) *lf = '\0'; + if (sscanf(s, "%lx: %x %x%n", &offset, &orig, &chng, &n) == 3 && n == (int) strlen(s)) + { + if (offset < 0 || offset >= SIZE) fatal("%s: offset out of range", s); + if (orig > 0xFF || chng > 0xFF) fatal("%s: byte(s) out of range", s); + if (offset >= ignore) + { + if (buffer[offset] != orig) fatal("offset %lx not equal to %x", offset, orig); + if (orig != chng) + { + if (minoff == -1) minoff = offset; + buffer[maxoff = offset] = chng; + } + } + } + #ifdef FCPW + #else + else + fprintf(stderr, "%s: `%s'\n", patch, s); + #endif + } + + if (minoff >= 0) + { + if (lseek(f, minoff, SEEK_SET) == -1) error(name); + if (write(f, buffer + minoff, maxoff - minoff + 1) == -1) error(name); + } + + if (close(f) == -1) error(name); + if (fclose(p) == -1) error(patch); + + return 0; +} + +#ifdef FCPW +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + int i; + + (void) hInstance; + (void) hPrevInstance; + (void) lpCmdLine; + (void) nCmdShow; + + for (i = 1; i < __argc; i++) + if (strlen(__argv[i]) > 255) fatal("argument %d too long", i); + + return wrap(__argc, __argv); +} +#endif |