toc/
toc/account/a/
toc/area/backup/
toc/area/imc/
toc/caste/
toc/caste/backup/
toc/clans/
toc/classes/
toc/crash/
toc/gods/
toc/guilds/
toc/lname/s/
toc/maps/backup/
toc/player/a/
toc/src/
toc/system/backup/
toc/tableprog/
/*
Fear 2.0 map to bitmap converter
Code by Rameti
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int c_line;
char *c_file;


#define SMBUFSIZE 4096
int sm_fd;
unsigned char sm_buffer[ SMBUFSIZE ];
unsigned char *sm_cur;
unsigned char *sm_lim;

#define MAX_X 1500
#define MAX_Y 1000
int map[MAX_Y * MAX_X];


#define sm_eof 256


int smxfatal(int status)
{
	exit(status);
}



int sm_getc(void)
{
	int res;
	if(sm_cur < sm_lim)
		return *(unsigned char *)sm_cur++;
	
reload:
	res = read(sm_fd, sm_buffer, SMBUFSIZE);
	if(res == 0)
		return sm_eof;
	if(res == -1)
	{
		if(errno == EINTR)
			goto reload;
		fprintf(stderr,"%s:%i Read error %s\n", c_file, c_line, strerror(errno));
		smxfatal(1);
	}
	sm_cur = sm_buffer;
	sm_lim = sm_cur + res;
	return *(unsigned char *)sm_cur++;
}


#define smxgetc() ( (sm_cur < sm_lim) ? *sm_cur++ : sm_getc() )
#define smxungetc(ch) (*(--sm_cur) = (ch))

#define MAXIDSTR 256
char sm_idstr[MAXIDSTR];
char *sm_idcur;
long sm_value;

#define MAXSTRLEN 4096
char sm_str[MAXSTRLEN];
char *sm_curstr;


enum
{
	smx_error=-1,
	smx_eof=0,
	smx_idtag,
	smx_string,
	smx_semicolon,
	smx_period,
	smx_set,
	smx_cmpeq,
	smx_value,
	smx_setmul,
	smx_setdiv,
	smx_setpower,
	smx_mul,
	smx_div,
	smx_power,
	smx_ptrderef,
};

char *dbsmx[] =
{
	"eof",
	"idtag",
	"string",
	"semicolon",
	"period",
	"set",
	"cmpeq",
	"value",
	"setmul",
	"setdiv",
	"setpower",
	"mul",
	"div",
	"power",
	"ptrderef"
};



#define smxtodigit(c)    ((c) - '0')
#define smxisdigit(c) ((unsigned)smxtodigit(c) <= 9)

#define smxlctodigit(c)    ((c) - 'a')
#define smxuctodigit(c)    ((c) - 'A')

#define smxlcisdigit(c) ((unsigned)smxlctodigit(c) <= 25)
#define smxucisdigit(c) ((unsigned)smxuctodigit(c) <= 25)

#define smxtoxdigit(c) (smxisdigit(c) ? smxtodigit(c) : smxlcisdigit(c) ? smxlctodigit(c)+10 : smxucisdigit(c) ? smxuctodigit(c)+10 : -1)

enum
{
	asc_nul,
	asc_soh,
	asc_stx,
	asc_etx,
	asc_eot,
	asc_enq,
	asc_ack,
	asc_bel,
	asc_bs,
	asc_ht,
	asc_nl,
	asc_vt,
	asc_np,
	asc_cr,
	asc_so,
	asc_si,
	asc_dle,
	asc_dc1,
	asc_dc2,
	asc_dc3,
	asc_dc4,
	asc_nak,
	asc_syn,
	asc_etb,
	asc_can,
	asc_em,
	asc_sub,
	asc_esc,
	asc_fs,
	asc_gs,
	asc_rs,
	asc_us,
	asc_sp
};

/*
	000 nul  001 soh  002 stx  003 etx  004 eot  005 enq  006 ack  007 bel
     010 bs   011 ht   012 nl   013 vt   014 np   015 cr   016 so   017 si
     020 dle  021 dc1  022 dc2  023 dc3  024 dc4  025 nak  026 syn  027 etb
     030 can  031 em   032 sub  033 esc  034 fs   035 gs   036 rs   037 us
     040 sp   041  !   042  "   043  #   044  $   045  %   046  &   047  '
     050  (   051  )   052  *   053  +   054  ,   055  -   056  .   057  /
     060  0   061  1   062  2   063  3   064  4   065  5   066  6   067  7
     070  8   071  9   072  :   073  ;   074  <   075  =   076  >   077  ?
     100  @   101  A   102  B   103  C   104  D   105  E   106  F   107  G
     110  H   111  I   112  J   113  K   114  L   115  M   116  N   117  O
     120  P   121  Q   122  R   123  S   124  T   125  U   126  V   127  W
     130  X   131  Y   132  Z   133  [   134  \   135  ]   136  ^   137  _
     140     141  a   142  b   143  c   144  d   145  e   146  f   147  g
     150  h   151  i   152  j   153  k   154  l   155  m   156  n   157  o
     160  p   161  q   162  r   163  s   164  t   165  u   166  v   167  w
     170  x   171  y   172  z   173  {   174  |   175  }   176  ~   177 del
*/                              

int smxlexescape(void)
{
	int tnum;
	int num;
	int ch;

	num = 0;
	ch = smxgetc();
	/* accellerate some escapes */
	switch(ch)
	{
		case '\\':
			return '\\';
		case 'n':
			return asc_nl;
		case 'r':
			return asc_cr;
		case 'f':
			return asc_np;
		case 'b':
			return asc_bs;
		case 'a':
			return asc_bel;
		case 'v':
			return asc_vt;
		case 'e':
			return asc_esc;
	}
		

	if(ch == 'x')
	{
		ch = smxgetc();
		if(ch == sm_eof)
			return sm_eof;

		num = smxtoxdigit(ch);
		if(num == -1 || num > 15)
		{
			smxungetc(ch);
			return 'x';
		}

		for(;;)
		{
			ch = smxgetc();
			if(ch == sm_eof)
				return sm_eof;
		
			tnum = smxtoxdigit(ch);
			if(tnum == -1 || tnum > 15)
			{
				smxungetc(ch);
				return (unsigned char)num;
			}
			num *= 16;
			num += tnum;
		}
	}
	
	if(ch >= '0' && ch <= '7')
	{
		num = ch - '0';
		for(;;)
		{
			ch = smxgetc();
			if(ch == sm_eof)
				return sm_eof;
		
			tnum = smxtodigit(ch);
			if(tnum == -1 || tnum > 7)
			{
				smxungetc(ch);
				return (unsigned char)num;
			}
			num *= 8;
			num += tnum;
		}
	}
	
	

	return ch;
}

int smxlex(void)
{
	int ch;

smxnext:
	ch = smxgetc();
	if(ch == sm_eof)
		return 0;
		
	/* ignore whitespace */
	if(ch == '\n')
	{
		c_line++;
		goto smxnext;
	}
	if(ch == ' ' || ch == '\r' || ch == '\t')
		goto smxnext;
		
	/* check identifier */
	if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || ch == '#')
	{
		sm_idcur = sm_idstr;
		do
		{
			if(sm_idcur >= (sm_idstr + MAXIDSTR))
				goto idstroverflow;
			*sm_idcur++ = ch;
			ch = smxgetc();
		} while((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= '0' && ch <= '9'));
		if(ch != sm_eof)
			smxungetc(ch);
		if(sm_idcur >= (sm_idstr + MAXIDSTR))
			goto idstroverflow;
		*sm_idcur = '\0';
		return smx_idtag;
idstroverflow:
		fprintf(stderr, "%s:%i\n Identifier too long, max %d\n", c_file, c_line, MAXIDSTR);
		return smx_error;				
	}
	if(ch == ';')
		return smx_semicolon;
	if(ch == '.')
		return smx_period;
	
	
	if((ch >= '0' && ch <= '9'))
	{
		sm_value = ch - '0';
		for(;;)
		{
			ch = smxgetc();
			if(ch >= '0' && ch <= '9')
			{
				sm_value *= 10;
				sm_value += ch - '0';
				continue;
			}
			if(ch != sm_eof)
				smxungetc(ch);
			return smx_value;
		}
	}
//handle * *= ** **=

	if(ch == '*')
	{
		ch = smxgetc();
		if(ch == '*')
		{
			ch = smxgetc();
			if(ch == '=')
				return smx_setpower;
			if(ch != sm_eof)
				smxungetc(ch);
			return smx_power;
		}
		if(ch == '=')
			return smx_setmul;

		if(ch == '(' || ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')))
		{
			smxungetc(ch);
			return smx_ptrderef;
		}
		if(ch != sm_eof)
			smxungetc(ch);
		return smx_mul;
	}
//handle / /* // /=

	if(ch == '/')
	{
		ch = smxgetc();
		if(ch == sm_eof)
			return 0;
		if(ch == '*')
		{
			for(;;)
			{
				ch = smxgetc();
				if(ch == '\n')
					c_line++;
				if(ch == sm_eof)
					goto err_eofincommentblk;
				if(ch == '*')
				{
					ch = smxgetc();
					if(ch == sm_eof)
						goto err_eofincommentblk;
					if(ch == '/')
						break;
					if(ch == '\n')
						c_line++;
				}
			}
			goto smxnext;
		}
		if(ch == '/')
		{
			for(;;)
			{
				ch = smxgetc();
				if(ch == '\n')
				{
					c_line++;
					goto smxnext;
				}
				if(ch == sm_eof)
					return smx_eof;
			}
		}
		if(ch == '=')
			return smx_setdiv;
		if(ch != sm_eof)
			smxungetc(ch);
		return smx_div;
	}
//handle = ==
	if(ch == '=')
	{
		ch = smxgetc();
		if(ch == '=')
			return smx_cmpeq;
		smxungetc(ch);
		return smx_set;
	
	}
//handle quoted strings
	if(ch == '"')
	{
		sm_curstr = sm_str;
		for(;;)
		{
			ch = smxgetc();
			if(ch == sm_eof)
				goto quotestreoferror;
			if(ch == '\n')
				c_line++;
			if(ch == '"')
				break;
			if(ch == '\\')
			{
				ch = smxlexescape();
				if(ch == sm_eof)
					goto quotestreoferror;
			}
			if(sm_curstr >= (sm_str + MAXSTRLEN))
				goto quotestroverflow;
			*sm_curstr++ = ch;
		}
		if(sm_curstr >= (sm_str + MAXSTRLEN))
			goto quotestroverflow;
		*sm_curstr = '\0';
		
		return smx_string;
quotestreoferror:
		fprintf(stderr, "%s:%i End of file inside string\n", c_file, c_line);
		return smx_error;		
quotestroverflow:
		fprintf(stderr, "%s:%i String lenth exceeds maximum lenth of %i\n", MAXSTRLEN);
		return smx_error;
	}

//handle anything unable to be resolved
	fprintf(stderr, "%s:%i Syntax error\n", c_file, c_line);
	return -1;
err_eofincommentblk:
	fprintf(stderr, "%s:%i End of file while in comment block\n", c_file, c_line);
	return -1;


}


typedef signed char bm8;
typedef unsigned char bmu8;

typedef signed short bm16;
typedef unsigned short bmu16;

typedef signed long bm32;
typedef unsigned long bmu32;

#define wrcachelen 4096
char wrcache[wrcachelen];
char *wrdest = wrcache;
#define wrcacheeod (wrcache + wrcachelen)

int wrrawnocache(int fd, void *buf, int length)
{
	int res;
	char *src;
	char *eos;
	src = (char *)buf;
	eos = src + length;
	for(;;)
	{
		if(src >= eos)
			break;
		res = write(fd, buf, eos - src);
		if(res == -1)
		{
			perror("write file");
			return 1;
		}
		src += res;
	}
	return 0;
}

int wrflush(int fd)
{
	int res;
	res = 0;
	if(wrdest > wrcache)
	{
		res = wrrawnocache(fd, wrcache, wrdest - wrcache);
		wrdest = wrcache;
	}
	return res;
}

int wrraw(int fd, void *buf, int length)
{
	int res;
	char *src;
	char *eos;
	src = (char *)buf;
	eos = src + length;
	for(;;)
	{
		if(src >= eos)
			break;
		
		if(wrdest > wrcacheeod)
		{
			res = wrflush(fd);
			if(res) return res;
		}
		*wrdest++ = *src++;
	}
	return 0;
}


int wrbm8(int fd, bm8 value)
{
	return wrraw(fd, &value, sizeof(value));
}

int wrbmu8(int fd, bmu8 value)
{
	return wrraw(fd, &value, sizeof(value));
}

int wrbm16(int fd, bm16 value)
{
	return wrraw(fd, &value, sizeof(value));
}

int wrbmu16(int fd, bmu16 value)
{
	return wrraw(fd, &value, sizeof(value));
}


int wrbm32(int fd, bm32 value)
{
	return wrraw(fd, &value, sizeof(value));
}

int wrbmu32(int fd, bmu32 value)
{
	return wrraw(fd, &value, sizeof(value));
}


unsigned char cpal[] =
{
	0x00,0x00,0x00,0x00,
	0x80,0x00,0x00,0x00,
	0x00,0x80,0x00,0x00,
	0x80,0x80,0x00,0x00,
	0x00,0x00,0x80,0x00,
	0x80,0x00,0x80,0x00,
	0x00,0x80,0x80,0x00,
	0xc0,0xc0,0xc0,0x00,
	0x80,0x80,0x80,0x00,
	0xff,0x00,0x00,0x00,
	0x00,0xff,0x00,0x00,
	0xff,0xff,0x00,0x00,
	0x00,0x00,0xff,0x00,
	0xff,0x00,0xff,0x00,
	0x00,0xff,0xff,0x00,
	0xff,0xff,0xff,0x00,
};

//#define MAKETAB
#undef MAKETAB



#ifdef MAKETAB
unsigned char scolor[256] =
{

};
#else
unsigned char scolor[] = 
{
	15,15,10,2,10,3,14,6,12,14,11,0,4,3,7,15,
	11,9,11,7,2,7,7,4,12,7,3,4,7,10,12,2,
	11,15,15,4,9,10,7,3,7,15,15,2,2,3,7,14,
	0,7,9,1,7,7,11,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
	10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10
};
#endif

enum
{
	bp_red        = 1<<0,
	bp_green      = 1<<1,
	bp_blue       = 1<<2,
	bp_bold       = 1<<3,
	bp_bred       = 1<<4,
	bp_bgreen     = 1<<5,
	bp_bblue      = 1<<6,
	bp_blink      = 1<<7,
	at_colors     = 1<<8,
	bm_rgb        = bp_red | bp_green | bp_blue,	
	bm_brgb       = bp_bred | bp_bgreen | bp_bblue,

	at_default    = -1,
	at_black      = 0,
	at_red        = bp_red,
	at_green      = bp_green,
	at_brown      = bp_green | bp_red,
	at_blue       = bp_blue,
	at_magenta    = bp_blue | bp_red,
	at_cyan       = bp_blue | bp_green,
	at_white      = bp_blue | bp_green | bp_red,
	at_grey       = bp_bold,
	at_lt_red     = bp_bold | at_red,
	at_lt_green   = bp_bold | at_green,
	at_yellow     = bp_bold | at_brown,
	at_lt_blue    = bp_bold | at_blue,
	at_lt_magenta = bp_bold | at_magenta,
	at_lt_cyan    = bp_bold | at_cyan,
	at_hi_white   = bp_bold | at_white,
	at_st_green   = bp_bold | at_green | at_cyan
};


int clparse(char *fmt)
{
	char *cp;
	char ch;
	int col;
	col = 0;

	col = at_white;
	for(;;)
	{
		for(cp = fmt; (ch = *fmt) && ch != '&'; fmt++);
		if(ch == '\0')
			break;
		fmt++; /* skip the '&' */
		ch = *fmt++;
		if(ch == '\0')
			break;
		switch(ch)
		{
			case 'x':
				col = at_black;
				break;
			case 'g':
				col = at_green;
				break;
			case 'b':
				col = at_blue;
				break;
			case 'c':
				col = at_cyan;
				break;
			case 'z':
				col = at_white;
				break;
			case 'G':
				col = at_lt_green;
				break;
			case 'B':
				col = at_lt_blue;
				break;
			case 'C':
				col = at_lt_cyan;
				break;
		        case 'E':
		                col = at_st_green;
		                break;
			case 'r':
				col = at_red;
				break;
			case 'O':
				col = at_brown;
				break;
			case 'p':
				col = at_magenta;
				break;
			case 'w':
				col = at_white;
				break;
			case 'R':
				col = at_lt_red;
				break;
			case 'Y':
				col = at_yellow;
				break;
			case 'P':
				col = at_lt_magenta;
				break;
			case 'W':
				col = at_hi_white;
				break;
		}
	}
	return col;
}


#define MAX_MAPSECTOR 55

typedef enum
{
  SECT_INSIDE, SECT_CITY, SECT_FIELD, SECT_FOREST, SECT_HILLS, SECT_MOUNTAIN,
  SECT_WATER_SWIM, SECT_WATER_NOSWIM, SECT_UNDERWATER, SECT_AIR, SECT_DESERT,
  SECT_DUNNO, SECT_OCEANFLOOR, SECT_UNDERGROUND, SECT_ROAD, SECT_ENTER,
  SECT_MINEGOLD, SECT_MINEIRON, SECT_HCORN, SECT_HGRAIN, SECT_STREE, SECT_NTREE,
  SECT_SGOLD, SECT_NGOLD, SECT_SIRON, SECT_NIRON, SECT_SCORN, SECT_NCORN,
  SECT_SGRAIN, SECT_NGRAIN, SECT_RIVER, SECT_JUNGLE, SECT_SHORE, SECT_TUNDRA,
  SECT_ICE, SECT_OCEAN, SECT_LAVA, SECT_TREE, SECT_NOSTONE, SECT_QUICKSAND,
  SECT_WALL, SECT_GLACIER, SECT_EXIT, SECT_SWAMP, SECT_PATH, SECT_PLAINS,
  SECT_PAVE, SECT_BRIDGE, SECT_VOID, SECT_STABLE, SECT_FIRE, SECT_BURNT, 
  SECT_STONE, SECT_SSTONE, SECT_NSTONE, SECT_MAX
} sector_types;



char *ns(int sector)
{
	switch(sector)
	{
		case SECT_INSIDE:   	return "&G&W%";
		case SECT_CITY:		return "&G&W#";
		case SECT_FIELD:		return "&G\"";
		case SECT_FOREST:		return "&E@";
		case SECT_HILLS:		return "&G^^";
		case SECT_MOUNTAIN:		return "&O^^";
		case SECT_WATER_SWIM:	return "&C~";  
		case SECT_WATER_NOSWIM:	return "&c~";
		case SECT_UNDERWATER: 	return "&B~";
		case SECT_AIR:			return "&C%";
		case SECT_DESERT:		return "&Y=";
		case SECT_DUNNO:		return "&x?";
		case SECT_OCEANFLOOR:	return "&b~";
		case SECT_UNDERGROUND:	return "&O#";
		case SECT_ROAD:		return "&c&w+";
		case SECT_ENTER:		return "&G&W#";
		case SECT_MINEGOLD:		return "&Y^^";
		case SECT_MINEIRON:		return "&R^^";
		case SECT_HCORN:		return "&Y\"";
		case SECT_HGRAIN:		return "&z\"";
		case SECT_STREE:		return "&g@";
		case SECT_NTREE:		return "&c&w@";
		case SECT_SGOLD:		return "&c&w^^";
		case SECT_NGOLD:		return "&b^^";
		case SECT_SIRON:		return "&B^^";
		case SECT_NIRON:		return "&z^^";
		case SECT_SCORN:		return "&O\"";
		case SECT_NCORN:		return "&b\"";
		case SECT_SGRAIN:		return "&z\"";
		case SECT_NGRAIN:		return "&G\"";
		case SECT_RIVER:		return "&B-";
		case SECT_JUNGLE:		return "&g*";
		case SECT_SHORE:		return "&Y.";
		case SECT_TUNDRA:		return "&G&W+";
		case SECT_ICE:			return "&G&WI";
		case SECT_OCEAN:		return "&b~";
		case SECT_LAVA:		return "&R:";
		case SECT_TREE:		return "&G*";
		case SECT_NOSTONE:		return "&c&w^^";
		case SECT_QUICKSAND:	return "&O%";
		case SECT_WALL:		return "&c&wI";
		case SECT_GLACIER:		return "&G&W=";
		case SECT_EXIT:		return "&G&W#";
		case SECT_SWAMP:		return "&g%";
		case SECT_PATH:		return "&g+";
		case SECT_PLAINS:		return "&O~";
		case SECT_PAVE:		return "&z#";
		case SECT_BRIDGE:		return "&C=";
		case SECT_VOID:		return "&x ";
		case SECT_STABLE:		return "&c&w#";
		case SECT_FIRE:		return "&R#";
		case SECT_BURNT:		return "&r+";
		case SECT_STONE:		return "&c&w*";
		case SECT_SSTONE:		return "&z*";
		case SECT_NSTONE:		return "&Y*";
		default:			return "&G?";
	}
}

int wrbmp(int fd)
{
	int p;
	unsigned char fg;
	unsigned char fred;
	unsigned char fgreen;
	unsigned char fblue;
	unsigned char *lc;
	int x;
	int y;
#define BMFHSIZE 14
#define BMIHSIZE 40
	/* BMFH */
	int res;
	res = wrbmu16(fd, ('B' | 'M' <<8)); /* bfType */
	if(res)return res;
	res = wrbmu32(fd, (MAX_Y * MAX_X) + BMFHSIZE + BMIHSIZE + (256 * 4)); /* bfSize */
	if(res) return res;
	res = wrbmu16(fd, 0); /* bfReserved1 */
	if(res) return res;	
	res = wrbmu16(fd, 0); /* bfReserved2 */
	if(res) return res;
	res = wrbmu32(fd, BMFHSIZE + BMIHSIZE + (256 * 4 )); /* bfOffBits */
	if(res) return res;
	/* BMIH */
	res = wrbmu32(fd, BMIHSIZE); /* biSize */
	if(res) return res;
	res = wrbm32(fd, MAX_X); /* biWidth */
	if(res) return res;
	res = wrbm32(fd, MAX_Y); /* biHeight */
	if(res) return res;
	res = wrbm16(fd, 1); /* biPlanes */
	if(res) return res;
	res = wrbm16(fd, 8); /* biBitCount */
	if(res) return res;
	res = wrbmu32(fd, 0); /* biCompression */
	if(res) return res;
	res = wrbmu32(fd, 0); /* biSizeImage */
	if(res) return res;
	res = wrbm32(fd, 3780); /* biXPelsPerMeter */
	if(res) return res;
	res = wrbm32(fd, 3780); /* biYpelsPerMeter */
	if(res) return res;
	res = wrbmu32(fd, 0); /* biClrUsed */
	if(res) return res;
	res = wrbmu32(fd, 0); /* biClrImportant */
	if(res) return res;
	for(p = 0; p < 256; p++)
	{
		fg = p & 0xf;
		lc = cpal + (4 * fg);
		fred = *lc++;
		fgreen = *lc++;
		fblue = *lc++;
#define RGB(r,g,b) ((bmu32)(((bmu8)(r)|((bmu16)(g)<<8))| (((bmu32)(bmu8)(b))<<16)))
    
#if RGB
		res = wrbmu32(fd, RGB(fred,fgreen,fblue));
		if(res) return res;
#else
		res = wrbmu8(fd, fblue); /* blue */
		if(res) return res;
		res = wrbmu8(fd, fgreen); /* green */
		if(res) return res;
		res = wrbmu8(fd, fred); /* red */
		if(res) return res;
		res = wrbmu8(fd, 0); /* reserved */
		if(res) return res;
#endif
	}
	
	for(y = MAX_Y - 1; y >= 0; y--)
	{
		for(x = 0; x < MAX_X; x++)
		{
			res = wrbmu8(fd, scolor[map[y * MAX_X + x]]);
			if(res) return res;
		}
	}
	res = wrflush(fd);
	if(res) return res;
	return 0;	
}






int main(int argc, char **argv)
{
	int bmfd;
	int res;
	int clsrc;
	int x;
	int y;
	int cnt;
	int inmap;
	
	int mapstate;
	int startx;
	int starty;
	int endx;
	int endy;
	int sector;
	char *src;
	
#ifdef MAKETAB
	int p;
	int col;
	printf("unsigned char scolor[] = \n{\n	");
	col = 0;
//	for(p = 0; p < MAX_MAPSECTOR; p++)
	for(p = 0; p < 256; p++, col++)
	{
		src = ns(p);
//		printf("%i %i %s\n", p, clparse(src), src);
		scolor[p] = clparse(src);
		if(col > 15)
		{
			printf("\n	");
			col = 0;
		}
		printf("%i,", clparse(src));
	}
	printf("\n};\n");
#endif
	
	if(argc < 3)
	{
		fprintf(stderr, "syntax: map2bmp <file.map> <file.bmp>\n");
		return 1;
	}
	
	c_file = argv[1];
	c_line = 1;
	sm_fd = open(c_file, O_RDONLY);
	if(sm_fd == -1)
	{
		perror("open source file");
		return 1;
	}
	
	inmap = 0;
	x = y = 0;
	for(;;)
	{
		res = smxlex();
		if(res == smx_error)
		{
			fprintf(stderr, "error\n");
			goto failed;
		}
		if(res == smx_eof)
			break;

		if(res == smx_idtag)
		{
			int preproc;
			
			src = sm_idstr;
			if(*src == '#')
			{
				preproc = 1;
				src++;
			}
			else
				preproc = 0;
			
			if(!strcasecmp("map", src))
			{
//				printf("map\n");
				memset(map, 0, sizeof(map));
				cnt = 0;
				y = x = 0;
				inmap = 1;
				mapstate = 0;
				continue;
			}
			if(!strncasecmp("end", src))
			{
//				printf("end\n");
				break;
			}
			fprintf(stderr, "Undefined map directive %s\n", src);
			continue;
		}

		if(inmap)
		{
			if(res == smx_value)
			{
				switch(mapstate)
				{
					case 0:
						mapstate++;
						startx = sm_value;
						continue;
					case 1:
						mapstate++;
						starty = sm_value;
						continue;
					case 2:
						mapstate++;
						endx = sm_value;
						continue;
					case 3:
						mapstate++;
						endy = sm_value;
						continue;
					case 4:
						mapstate = 0;
						sector = sm_value;
						break;
				}
				/* got a full set */
				startx--;
				endx--;
				starty--;
				endy--;
#if 0
				if(startx < 0 || endx < 0 || starty < 0 || endy < 0 || sector < 0
				|| startx > MAX_X || endx > MAX_X || starty > MAX_Y || endy > MAX_Y
				|| startx > endx || starty > endy
				|| sector > SECT_MAX)
				{
					fprintf(stderr, "bad meta data in map %i %i %i %i %i\n", startx, starty, endx, endy, sector);
					goto failed;
				}
#endif
				for(x = startx; x <= endx; x++)
				{
					y = (x == startx) ? starty : 1;
					for(;;y++)
					{
						if(x == endx && y > endy || y == MAX_Y)
							break;
						map[ y * MAX_X + x] = sector;
					
					}
				
				}
#if 0
				for(y = starty; y < endy; y++)
				{
					for(x = startx; x < endx; x++)
					{
						printf("adding %i %i %i\n", x, y, sector);
						map[y * MAX_X + x] = sector;
					}
				}
#endif
			}
			else
			{
				fprintf(stderr, "non-value in map section\n");
				goto failed;
			}
			continue;
		}
		fprintf(stderr, "Syntax error: %i\n", res);
		break;
	}
	
	if(mapstate > 0)
	{
		fprintf(stderr, "incomplete meta data in map section\n");
	}

	close(sm_fd);
	
	bmfd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0666);
	if(bmfd == -1)
	{
		perror("open dest file");
		return 1;
	}	

	wrbmp(bmfd);
	
	return 0;	

failed:
	fprintf(stderr, "failed to process\n");
	close(sm_fd);
	
	return 1;
}