Mercurial > hg > batmud > maputils
view patchmap.c @ 1822:892d5277f1ff
Remove note about the search pattern parser being not very tolerant, it's somewhat better now.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 30 Oct 2017 12:55:21 +0200 |
parents | 72adabd8e746 |
children | 79dd960610cb |
line wrap: on
line source
/* * patchmap - Patch a map with given diff file * Programmed by Matti 'ccr' Hämäläinen (Ggr Pupunen) * (C) Copyright 2008-2015 Tecnic Software productions (TNSP) */ #include "libmaputils.h" #include "th_util.h" #include "th_args.h" #include "th_string.h" char *mapFilename = NULL, *patchFilename = NULL, *destFilename = NULL; BOOL optCheck = FALSE; /* Arguments */ static const th_optarg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'q', "quiet", "Be quiet", OPT_NONE }, { 3, 'c', "check", "Check non-patched blocks", OPT_NONE }, { 4, 'o', "output", "Output filename", OPT_ARGREQ }, }; static const int optListN = sizeof(optList) / sizeof(optList[0]); void argShowHelp(void) { th_print_banner(stdout, th_prog_name, "[options] <mapfile> <patchfile>"); th_args_help(stdout, optList, optListN, 0); } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { switch (optN) { case 0: argShowHelp(); exit(0); break; case 1: th_verbosityLevel++; break; case 2: th_verbosityLevel = -1; break; case 3: optCheck = TRUE; THMSG(2, "Checking non-patched blocks for match.\n"); break; case 4: destFilename = optArg; THMSG(2, "Output file set to '%s'.\n", destFilename); break; default: THERR("Unknown option '%s'.\n", currArg); return FALSE; } return TRUE; } BOOL argHandleFile(char *currArg) { if (!mapFilename) mapFilename = currArg; else if (!patchFilename) patchFilename = currArg; else { THERR("Too many input map files specified!\n"); return FALSE; } return TRUE; } int main(int argc, char *argv[]) { MapBlock *map, *patch; FILE *outFile; // Initialize th_init("patchmap", "Patch a mapfile with a diff", "0.1", NULL, NULL); th_verbosityLevel = 1; // Parse arguments if (!th_args_process(argc, argv, optList, optListN, argHandleOpt, argHandleFile, OPTH_BAILOUT)) exit(1); if (mapFilename == NULL || patchFilename == NULL) { THERR("Nothing to do. (try --help)\n"); exit(0); } // Read map and patch file if ((map = mapBlockParseFile(mapFilename, FALSE)) == NULL) exit(2); if ((patch = mapBlockParseFile(patchFilename, TRUE)) == NULL) exit(3); // Check map and diff sizes if (optCheck && (map->width != patch->width || map->height != patch->height)) { THERR("Map and patch dimensions do not match (%d x %d [map] <-> %d x %d [patch])\n", map->width, map->height, patch->width, patch->height); exit(4); } // Generate for (int y = 0; y < map->height; y++) { unsigned char *d = map->data + (map->scansize * y), *s = patch->data + (patch->scansize * y); for (int x = 0; x < map->width; x++) { const int i = (*s & 63); unsigned char c; if (*s == 0xfd) c = ' '; else if (i < nmapPieces) c = mapPieces[i].symbol; else { THERR("[%d,%d] invalid symbol index %d (%d) in patch\n", x+1, y+1, *s, i); exit(5); } if (*s < 64) { if (optCheck && *s != *d) { THERR("[%d,%d] mismatch %d != %d\n", x+1, y+1, *s, *d); } } else *d = c; s++; d++; } } // Open output file if (destFilename == NULL) outFile = stdout; else if ((outFile = fopen(destFilename, "wb")) == NULL) { THERR("Error opening output file '%s'!\n", destFilename); exit(1); } mapBlockPrint(outFile, map); fclose(outFile); return 0; }