view combine.c @ 98:c856945880be

Remove debugging
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 17 Dec 2006 11:57:21 +0000
parents
children 1345fc500e7e
line wrap: on
line source

/*
 * combine - Combine several maps into one bigger
 *
 * Programmed by Matti 'ccr' Hämäläinen (Ggr Pupunen)
 * (C) Copyright 2006 Tecnic Software productions (TNSP)
 */
#include "maputils.h"
#include <string.h>
#include <strings.h>
#include "th_args.h"
#include "th_string.h"


#define	MAX_FILES	(256)


typedef struct {
	char *fileName;
	int x, y;
	mapblock_t *b;
} mapfile_t;


/* Variables
 */
int	nsrcFiles = 0;
mapfile_t srcFiles[MAX_FILES];
char	*destFile = NULL;
int	optFillChar = -1;
BOOL	optInputIsDiff = FALSE;


/* Arguments
 */
optarg_t optList[] = {
	{ 0, '?', "help",	"Show this help", OPT_NONE },
	{ 1, 'o', "output",	"Specify output file", OPT_ARGREQ },
	{ 2, 'v', "verbose",	"Be more verbose", OPT_NONE },
	{ 3, 'q', "quiet",	"Be quiet", OPT_NONE },
	{ 5, 'd', "diff",	"Map files are in 'diff' format", OPT_NONE },
	{ 4, 'f', "fill",	"Fill character", OPT_ARGREQ },
};

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


void argShowHelp()
{
	th_args_help(stdout, optList, optListN, th_prog_name,
		"[options] <mapfile1:x-offset:y-offset> [<mapfile2:x:y> ...]");
}


BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
{
	switch (optN) {
	case 0:
		argShowHelp();
		exit(0);
		break;

	case 1:
		destFile = optArg;
		THMSG(1, "Output file '%s'\n", destFile);
		break;

	case 2:
		th_verbosityLevel++;
		break;
	
	case 3:
		th_verbosityLevel = -1;
		break;
	
	case 4:
		if (optArg[1] != 0) {
			THERR("Fill character is not a string, dumbass!\n");
			return FALSE;
		}

		optFillChar = optArg[0];
		THMSG(1, "Using fill character '%c'\n", optFillChar);
		break;
	
	case 5:
		THMSG(1, "Assuming all input files are diffs.\n");
		optInputIsDiff = TRUE;
		break;
		
	default:
		THERR("Unknown option '%s'.\n", currArg);
		return FALSE;
		break;
	}
	
	return TRUE;
}


BOOL argHandleFile(char *currArg)
{
	if (nsrcFiles < MAX_FILES) {
		char *q, *c, *tmpArg = th_strdup(currArg);
		
		if (!tmpArg) {
			THERR("Could not allocate temp buffer!\n");
			return FALSE;
		}
		
		/* Get filename component */
		for (q = c = tmpArg; *c && (*c != ':'); c++);
		if (*c != ':') {
			th_free(tmpArg);
			THERR("Expected ':' after filename in '%s'.\n",
				currArg);
			return FALSE;
		}
		
		*(c++) = 0;
		srcFiles[nsrcFiles].fileName = th_strdup(q);
		
		/* Get X offset*/
		if (!th_isdigit(*c)) {
			th_free(tmpArg);
			THERR("Expected decimal X offset value in '%s'.\n",
				currArg);
			return FALSE;
		}
		
		for (q = c; *c && (*c != ':') && th_isdigit(*c); c++);
		if (*c != ':') {
			th_free(tmpArg);
			THERR("Expected ':' after X offset value in '%s'.\n",
				currArg);
			return FALSE;
		}
		
		*(c++) = 0;
		srcFiles[nsrcFiles].x = atoi(q);
		
		/* Get Y offset*/
		if (!th_isdigit(*c)) {
			th_free(tmpArg);
			THERR("Expected decimal Y offset value in '%s'.\n",
				currArg);
			return FALSE;
		}

		for (q = c; *c && th_isdigit(*c); c++);
		if (*c != 0) {
			th_free(tmpArg);
			THERR("Invalid Y offset value in '%s'.\n",
				currArg);
			return FALSE;
		}

		srcFiles[nsrcFiles].y = atoi(q);
		
		th_free(tmpArg);
		
		nsrcFiles++;
	} else {
		THERR("Too many input files specified (%d max)!\n", MAX_FILES);
		return FALSE;
	}
	
	return TRUE;
}


void printBlockRaw(FILE *f, mapblock_t *map)
{
	char *c;
	int x, y;

	c = map->d;
	
	for (y = 0; y < map->h; y++) {
		for (x = 0; x < map->w; x++) {
			fputc(*c, f);
			c++;
		}
		
		fputc(0xff, f);
	}
}


void findWorldSize(mapblock_t *tmp,
	int *worldX0, int *worldY0,
	int *worldX1, int *worldY1)
{
	if (tmp->x < *worldX0) *worldX0 = tmp->x;
	if ((tmp->x + tmp->w) > *worldX1) *worldX1 = (tmp->x + tmp->w);

	if (tmp->y < *worldY0) *worldY0 = tmp->y;
	if ((tmp->y + tmp->h) > *worldY1) *worldY1 = (tmp->y + tmp->h);
}


int main(int argc, char *argv[])
{
	int i, worldX0, worldY0, worldX1, worldY1;
	mapblock_t *worldMap = NULL;

	th_init("combine", "Combine several maps into one", "0.1", NULL, NULL);
	th_verbosityLevel = 1;
	
	/* Parse arguments */
	if (!th_args_process(argc, argv, optList, optListN,
		argHandleOpt, argHandleFile, TRUE))
		exit(1);
	
	if (nsrcFiles < 1) {
		THERR("Nothing to do. (try --help)\n");
		exit(0);
	}
	

	/* Read map files
	 */
	for (i = 0; i < nsrcFiles; i++) {
		if ((srcFiles[i].b = parseFile(srcFiles[i].fileName, optInputIsDiff)) == NULL) {
			THERR("Error reading input file '%s'!\n",
				srcFiles[i]);
			exit(1);
		}
		
		srcFiles[i].b->x = srcFiles[i].x;
		srcFiles[i].b->y = srcFiles[i].y;
	}
	
	THMSG(1, "Total of %d maps read.\n", nsrcFiles);
	
	if (nsrcFiles <= 0) {
		THERR("No maps, nothing to do.\n");
		exit(11);
	}


	/* Get world dimensions */
	worldX0 = worldY0 = worldX1 = worldY1 = 0;
	for (i = 0; i < nsrcFiles; i++)
		findWorldSize(srcFiles[i].b, &worldX0, &worldY0, &worldX1, &worldY1);
	
	
	/* Allocate world map */
	if ((worldMap = allocBlock((worldX1 - worldX0 + 1), (worldY1 - worldY0 + 1))) == NULL) {
		THERR("Error allocating world map!\n");
		exit(4);
	}
	
	THMSG(2, "Initialized world map of (%d x %d)\n",
		worldMap->w, worldMap->h);
	

	/* Clear with some character
	 */
	if (optFillChar > 0) {
		th_memset(worldMap->d, optFillChar,
			(worldMap->w * worldMap->h * sizeof(char)));
	}
	

	/* Blit maps
	 */
	for (i = 0; i < nsrcFiles; i++) {
	}


	/* Output generated map
	 */
	if (worldMap) {
		FILE *tmpFile;
		
		THMSG(1, "Outputting generated map of (%d x %d) ...\n",
			worldMap->w, worldMap->h);

		if (destFile == NULL)
			tmpFile = stdout;
		else if ((tmpFile = fopen(destFile, "wb")) == NULL) {
			THERR("Error opening output file '%s'!\n",
				destFile);
			exit(1);
		}
		
		if (optInputIsDiff)
			printBlockRaw(tmpFile, worldMap);
		else
			printBlock(tmpFile, worldMap);
	
		fclose(tmpFile);
	} else {
		THERR("No map generated?\n");
	}
	
	exit(0);	
	return 0;
}