view patchmap.c @ 945:81184d58133c aprilli2011

Sync.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 May 2010 11:18:20 +0000
parents 304a50a9d51f
children 667ce752bfe3
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 Tecnic Software productions (TNSP)
 */
#include "maputils.h"
#include "th_util.h"
#include "th_args.h"
#include "th_string.h"
#include <string.h>

char    *mapFilename = NULL,
        *patchFilename = NULL,
        *destFilename = NULL;
BOOL    optCheck = FALSE;


/* Arguments
 */
optarg_t 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 },
};

const int optListN = (sizeof(optList) / sizeof(optarg_t));


void argShowHelp(void)
{
    th_args_help(stderr, optList, optListN, th_prog_name,
    "[options] <mapfile> <patchfile>");
}


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_t *map, *patch;
    FILE *outFile;
    int x, y;
    unsigned char *s, *d;
    
    /* 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, TRUE))
        exit(1);
    
    if (mapFilename == NULL || patchFilename == NULL) {
        THERR("Nothing to do. (try --help)\n");
        exit(0);
    }
    
    /* Read map and patch file */
    if ((map = parseFile(mapFilename, FALSE)) == NULL)
        exit(2);

    if ((patch = parseFile(patchFilename, TRUE)) == NULL)
        exit(3);
    
    /* Check map and diff sizes */
    if (optCheck && (map->w != patch->w || map->h != patch->h)) {
        THERR("Map and patch dimensions do not match (%d x %d [map] <-> %d x %d [patch])\n",
            map->w, map->h, patch->w, patch->h);
        exit(4);
    }
    
    /* Generate */
    d = map->d; s = patch->d;
    for (y = 0; y < map->h; y++)
    for (x = 0; x < map->w; x++) {
        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);
    }
    
    printBlock(outFile, map);

    fclose(outFile);
    
    exit(0);
    return 0;
}