text: /*---------------------------------------------------------------------------------
  
  	Copyright (C) 2018-2020
  		Alekmaul 
  
  	This software is provided 'as-is', without any express or implied
  	warranty.  In no event will the authors be held liable for any
  	damages arising from the use of this software.
  
  	Permission is granted to anyone to use this software for any
  	purpose, including commercial applications, and to alter it and
  	redistribute it freely, subject to the following restrictions:
  
  	1.	The origin of this software must not be misrepresented; you
  		must not claim that you wrote the original software. If you use
  		this software in a product, an acknowledgment in the product
  		documentation would be appreciated but is not required.
  	2.	Altered source versions must be plainly marked as such, and
  		must not be misrepresented as being the original software.
  	3.	This notice may not be removed or altered from any source
  		distribution.
  
  	Image converter for colecovision.
  	BMP BI_RLE8 compression support by Andrey Beletsky
  	palette rounded option from Artemio Urbina
      Dan1 & Dan2 & Dan3 compression support from Amy Purple aka newcoleco
  	
  ***************************************************************************/
  
  //INCLUDES
  #include <stdlib.h>
  #include <stdio.h>
  #include <memory.h>
  #include <malloc.h>
  #include <string.h>
  
  #include "gfx2col.h"
  
  #include "lodepic.h"
  #include "lodepng.h"
  
  #include "comptool.h"
  #include "comprle.h"
  #include "compdan1.h"
  #include "compdan2.h"
  #include "compdan3.h"
  
  enum FILE_TYPE {
      BMP_FILE = 1,
      PCX_FILE,
      TGA_FILE,
      PNG_FILE
  };
  
  int output_palette=-1;		  // 64 colors output (F18A only) palettes
  int palette_rnd=0;      	  // 1 = round palette up & down (F18A only)
  int quietmode=0;              // 0 = not quiet, 1 = i can't say anything :P
  int compress=0;               // 0 = not compressed, 1 = rle compression, 2 = ple compression, 3 = dan1 compression, 
                                //    4 = dan2 compression, 5 = dan3 compression
  int sprmode=0;                // 0 = background 1 = sprite
  int bmpmode=0;				  // 0 = normal tile mode, 1=bitmap mode
  int gramode=0;				  // 0 = TMS9918a graphic mode 2, 1 = graphic mode 1
  int ecmmode=0;				  // 0 = noactive, 1=ecm0,2=ecm1, etc ... (F18A only, will generate a palette)
  int offset_tile=0;			  // n = offset in tile number
  int transmode=0;			  // 0 = not transparent, 1 = transprent tiles activated
  int highpriority=0;     	  // 1 = high priority for map
  
  //---------------------------------------------------------------------------
  void PutWord(int data, FILE *fp)
  {
  	putc(LOW_BYTE(data),fp);
  	putc(HI_BYTE(data),fp);
  } //end of PutWord
  
  //---------------------------------------------------------------------------
  unsigned char *ArrangeBlocks( unsigned char *img, int width, int height,
  							 int size, int *xsize, int *ysize, int new_width)
  {
  	/*
  	** img = image buffer
  	** width = width (in pixels) of image buffer
  	** height = height (in pixels) of image buffer
  	**
  	** size = size (in pixels) of image blocks in the image
  	** *xsize = number of image block horizontally in image block grid
  	** *ysize = number of image block vertically in image block grid
  	**
  	** new_width = how wide (in pixels) you want the new buffer to be
  	**             must be a multiple of size
  	**
  	**
  	** returns:
  	**      pointer to new buffer, and updates xsize and ysize
  	**
  	*/
  	unsigned char *buffer;
  	int rows, num;
  	int i,j, line;
  	int x,y;
  
  	//get number of full image block rows in the new buffer
  	rows = (*xsize)*(*ysize)/(new_width/size);   // rows = num_blocks / new_xsize
  
  	//if it doesn't divide evenly, add another full row
  	if ( ((*xsize)*(*ysize))%(new_width/size) != 0 )
  		rows++;
  
  	if (quietmode == 0)
  		printf("\nrows=%d",rows);
  
  	//get memory for the new buffer
  	buffer = (unsigned char *) malloc( rows*size*new_width*sizeof(char) );
  	if(buffer == NULL) {
  		return 0;
  	}
  
  	// Initially clear the buffer, so if there are empty image blocks or incomplete blocks, the empty parts will be blank
  	memset(buffer,0,(size_t) rows*size*new_width*sizeof(char) );
  
  	//position in new buffer (x,y) where x and y are in pixel co-ordinates
  	x=0;
  	y=0;
  
  	//go through each image block(i,j) where i and j are in block co-ordinates
  	for(j=0; j < *ysize; j++)
      {
      	for(i=0; i < *xsize; i++)
  	    {
  		    //move each line of the block into the new buffer
      		//don't worry about reading past the end of the image here
  	    	//there is an extra 64 lines to read in.
  		    for(line=0;line<size;line++)
      		{
  	    		//find out how much to copy
  		    	//this is needed because the screen mode files may not be
      			//a multiple of 8 pixels wide
  	    		//or no-border files may have the wrong width
  		    	num = width - (i*(size));
  			    if(num>size)
  				    num=size;
  
      			memcpy( &buffer[ (y+line)*new_width + x ], &img[ (j*(size) + line )*width + i*(size) ], num);
  	    	}
  
  		    // move to the next location in the new buffer
      		x+=size;
  	    	if(x >= new_width)
  		    {
  			    x=0;
      			y+=size;
  	    	}
  	    }
      }
  
      *xsize = new_width/size;
      *ysize = rows;
  
  	return buffer;
  } //end of ArrangeBlocks()
  
  //---------------------------------------------------------------------------
  unsigned int MakeCol(unsigned char *buffer, unsigned int *tilemap, unsigned char *num_col, unsigned int *colmap,int *num_tiles,int mapw, int maph)
  {
  	int colval,nbcol;
  	int i,j, t,x,y;
  	int colidx, tilidx;
  	unsigned char minv,maxv,actminv,actmaxv;
  	unsigned char valtil[8];
  	unsigned char newcol;
  	unsigned char *tilreorg;
  	unsigned int *mapreorg;
  	unsigned int idxcoltil[256];
  
  	// init color values
  	newcol=0;
  	for (t=0;t<32;t++)
  		colmap[t]=0x100; 					// outside scope value 
  	for (t=0;t<256;t++)
  		idxcoltil[t]= 32;					// outside score value 
  		
  	//loop through tiles
  	for (t=0;t<*num_tiles;t++) 
  	{ 
  		actminv=1; actmaxv=0xF;
  		for(y=0;y<8;y++) {
  			minv=0xFF; maxv=0x00;
  
  			// get the 8 values
  			for (x=0;x<8;x++) {
  				valtil[x]=buffer[t*64 + y*8 + x];
  				// get min and max value
  				if (valtil[x]<minv)
  					minv=valtil[x];
  				if (valtil[x]>maxv)
  					maxv=valtil[x];
  			}
  			// put 1 if max color
  			if (maxv <= 0x01) maxv=0xF;
  			if (minv == 0xff) minv=1;
  			// if 1st time,assign it
  			if (y==0)
  			{
  				if ( (minv!=1) && (maxv!=minv) ) actminv=minv;
  				if (maxv!=0xF) actmaxv=maxv;
  			}
  			else
  			{
  				if ( (actminv!=minv) &&  (actmaxv!=maxv) ) 
  				{
  					printf("\nERROR: Too much color (4) for 8x8 tile #%d\n",t);
  					return 0;
  				}
  				if ( (actminv!=minv) && (actminv!=1)  && (maxv!=minv) )
  				{
  					printf("\nERROR: Too much color (min) for 8x8 tile #%d\n",t);
  					return 0;
  				}
  				else
  					if (maxv!=minv) actminv=minv;
  				if ( (actmaxv!=maxv) && (actmaxv!=0xF) && (maxv!=0xF) )
  				{
  					printf("\nERROR: Too much color (max) for 8x8 tile #%d\n",t);
  					return 0;
  				}
  				else
  					if (maxv!=0xF) actmaxv=maxv;
  			}
  			colval=(actmaxv<<4) | (actminv);		// FG color | BG color 
  		}
  		// try to assign for a color for the 8x8 square
  		colidx=-1;
  		for (i=0;i<32;i++)
  		{
  			if (colmap[i]==0x100) {
  				colmap[i]=colval;
  				colidx=i;
  				newcol++;
  				break;
  			}
  			else if (colmap[i]==colval)
  			{
  				colidx=i;
  				break;
  			}
  		}
  		// if not assigned, huston, we have a problem ;)
  		if (colidx==-1) 
  		{
  			printf("\nERROR: Too much colors assigned (more than 32) encountered for 8x8 tile #%d\n",t);
  			return 0;
  		}
  		idxcoltil[t]=colval;
  	}
  	
  	// try to alloc for new tiles arrangement
  	tilreorg=(unsigned char *) malloc((size_t)256*64);
  	if(tilreorg==NULL) {
  		return 0;
  	}
  	mapreorg=(unsigned int *) malloc((size_t)mapw*maph*sizeof(int));
  	if(mapreorg==NULL) {
  		return 0;
  	}
  	memset(tilreorg,0,256*64);
  	memset(mapreorg,0,mapw*maph*sizeof(int));
  
  	// Rearrange tiles & map to fit with colors (1 colors for 8 tiles)
  	printf("\nRearrange tiles & map to fit with colors (1 colors for 8 tiles)...");fflush(stdout);
  	tilidx=0;
  	for (i=0;i<32;i++)
  	{
  		// check all tiles
  		nbcol=0;
  		for (t=0;t<*num_tiles;t++) 
  		{
  			// if we find the color, just put the tile
  			if (idxcoltil[t]==colmap[i])
  			{
  				// if we have now more than 8 tiles, need to go next color entry
  				if (nbcol==8)
  				{
  					nbcol=0;
  					newcol++;
  					for (j=31;j>i;j--)
  					{
  						colmap[j]=colmap[j-1];
  					}
  					i++;
  					colmap[i]=colmap[i-1];
  				}
  
  				// Put the tile
  				memcpy(&tilreorg[tilidx],&buffer[t*64],64);
  				// Adapt the map
  				for (j=0;j<mapw*maph;j++)
  				{
  					if (*(tilemap+j)==t)
  					{
  						*(mapreorg+j)=(tilidx/64);
  					}
  				}
  				tilidx+=64;
  				nbcol++;
  			}
  		}
  		
  		// one color is finished, if we are not near a 8 tiles border, need to adapt
  		if (nbcol & 7)
  		{
  			tilidx+=(8-nbcol)*64;
  		}
  	}
  	// now put back to buffer & map
  	printf("\nNew number of tiles is %d...",tilidx/64);fflush(stdout);
  
  	for (i=0;i<tilidx;i++)
  		*(buffer+i)=*(tilreorg+i);
  	for (i=0;i<mapw*maph;i++)
  		*(tilemap+i)=*(mapreorg+i);
  	
  	free(mapreorg);
  	free(tilreorg);
  
  	// keep track of number of colors & number of tiles
  	*num_col=newcol;
  	*num_tiles=tilidx/64;
  	
  	return 1;
  }
  
  //---------------------------------------------------------------------------
  unsigned int *MakeMap(unsigned char *img, unsigned int *colf18a, int *num_tiles, int xsize, int ysize, int tile_x, int tile_y, unsigned char optimize)
  {
  	unsigned int *map;
  	int newtiles;
  	int current,palette,oldpal;	//the current tile we're looking at
  	int i,t;
  	int x,y;
  
  	//allocate map
  	map=(unsigned int *) malloc((size_t)tile_x*tile_y*sizeof(int));
  	if(map==NULL) {
  		return 0;
  	}
  
  	//clear map
  	memset(map,0,tile_x*tile_y*sizeof(int));
  
  	current=0;
  	t=0;
  	newtiles=0;
  	oldpal=-1;
  
  	for(y=0;y<ysize;y++)
      {
      	for(x=0;x<xsize;x++)
  	    {
  
  			//get the palette number
  			if (ecmmode==4) // ecm 3
  				palette = (img[current*64] >> 3) & 0x07;
  			else if (ecmmode==3) // ecm 2
  				palette = (img[current*64] >> 2) & 0x0F;
  			else				// ecm 1 and others
  				palette = (img[current*64] >> 1) & 0x1F;
  			/* test purpose if (ecmmode>1) 
  			{
  				if (oldpal!=palette) {
  					printf("\npalette=%04x",palette);fflush(stdout);
  					oldpal=palette;
  				}
  			}*/
  
      		//check for matches with previous tiles if tile_reduction on
              if (optimize)
              {
      			for(i=0;i<newtiles;i++)
  	    			if( memcmp(&img[i*64],&img[current*64],64) == 0 )
  		    			break;
              }
              else
                  i=newtiles;
  
  			// if ecm mode, put in color table for the tile attributre
  			if (ecmmode>1) 
  			{
  				// How colors are managed:
  				// ps  = palette select from VR24
  				// cs  = color value from color table (256 bytes for ECM1..3)
  				// px0 = pixel from byte from pattern table 0 (original mode and EMC1)
  				// px1 = pixel from byte from pattern table 1 (ECM2)
  				// px2 = pixel from byte from pattern table 2 (ECM3)
  			
  				// Bit  Name       Expl.
  				// 0-3  PS3-0      Palette selection (b3=PS0, b0=PS3)
  				// 4    TRANS      When 1, colors with 0, 00 or 000 will be transparent instead of a palette index
  				// 5    FLIPY      Tile flip over Y
  				// 6    FLIPX      Tile flip over X
  				// 7    PRI        Tile priority over sprite
    				if (ecmmode==2) colf18a[newtiles]=(palette); 					// ECM1    : ps0 cs0 cs1 cs2 cs3 px0 
  				else if (ecmmode==3) colf18a[newtiles]=(palette); 				// ECM2    : cs0 cs1 cs2 cs3 px1 px0
  				else if (ecmmode==4) colf18a[newtiles]=(palette<<1)& 0xFE; 		// ECM3    : cs0 cs1 cs2 px2 px1 px0
  				colf18a[newtiles]|=(transmode<<4) | (highpriority<<7);
  			}
  			
  			//is it a new tile?
  			if(i==newtiles)
  			{
  				// yes -> add it
  				memcpy(&img[newtiles*64],&img[current*64],64);
  				t=newtiles;
  				newtiles++;
  			}
  			else
  			{	// no -> find what tile number it is
  				t=i;
  			}
  
      		//put tile number in map
  	    	map[y*tile_x+x] = t+offset_tile;
  		}
  
  		//goto the next tile
  		current++;
  	}
  
  	//also return the number of new tiles
  	*num_tiles = newtiles;
  
  	return map;
  
  }//end of MakeMap
  
  //---------------------------------------------------------------------------
  void ConvertPalette(RGB_color *palette, unsigned int *new_palette)
  {
  	int i,data;
  	int rounded;
  	int temp;
  
  	//Convert the colors and put them in the new array
  	//
  	//alternate rounding down and rounding up
  	//this is an attempt to preserve the brightness of a color
  	//which the human eye notices easier than a change in color
  	rounded=0;
  	for(i=0;i<64;i++) 
  	{
  		if(palette_rnd) 
  		{
  			data=0;
  
  			//get red portion and round it
  			temp = (palette[i].red & 0x01);		//see if this needs rounding
  			if(palette[i].red == 31) 			//if value == 63, then we can't round up
  			{
  				temp = 0;
  				rounded = 1;
  			}
  			data = (palette[i].red >> 1) + (temp & rounded);				//round up if necessary
  			rounded = (temp ^ rounded);			//reset rounded down flag after rounding up
  
  			//get green portion and round it
  			temp = (palette[i].green & 0x01);	//see if this needs rounding
  			if(palette[i].green == 31) 			//if value == 63, then we can't round up
  			{
  				temp = 0;
  				rounded = 1;
  			}
  			data = (data<<4) + (palette[i].green >> 1) + (temp & rounded);	 //round up if necessary
  			rounded = (temp ^ rounded);			//reset rounded down flag after rounding up
  
  			//get blue portion and round it off
  			temp = (palette[i].blue & 0x01);	//see if this needs rounding
  			if(palette[i].blue == 31) 			//if value == 63, then we can't round up
  			{
  				temp = 0;
  				rounded = 1;
  			}
  			data = (data<<4) + (palette[i].blue >> 1) + (temp & rounded);				//round up if necessary
  			rounded = (temp ^ rounded);			//reset rounded down flag after rounding up
  
  			//store converted color
  			new_palette[i] = data;
  		}
  		else
  		{
  			data=0;
  
  			data = (palette[i].red >> 1);
  			data = (data<<4) + (palette[i].green >> 1);
  			data = (data<<4) + (palette[i].blue >> 1);
  
  			//store converted color
  			new_palette[i] = data;
  		}
  	}//loop through all colors
  
  } //end of ConvertPalette
  
  //---------------------------------------------------------------------------
  void addcomment(FILE *fp, unsigned int ratio,unsigned int size,unsigned int compress) {
  	if (compress==1)
  		fprintf(fp, "// rle compression %d bytes (%d%%)\n", size,ratio);
  	else if (compress==2)
  		fprintf(fp, "// ple compression %d bytes (%d%%)\n", size,ratio);
  	else if (compress==3)
  		fprintf(fp, "// dan1 compression %d bytes (%d%%)\n", size,ratio);
  	else if (compress==4)
  		fprintf(fp, "// dan2 compression %d bytes (%d%%)\n", size,ratio);
  	else if (compress==5)
  		fprintf(fp, "// dan3 compression %d bytes (%d%%)\n", size,ratio);
  }
  
  int Convert2Pic(char *filebase, unsigned char *buffer, unsigned int *tilemap, unsigned int *palet, unsigned int *tilecol, int num_tiles, int mapw, int maph, int savemap, int savepal)
  {
  	char filenamec[256],filenameh[256],filenamef[256];
  	unsigned int val16b;
  	unsigned char bufsw1[8];
  	unsigned char value, minv,maxv;
  	unsigned char valtil[8];
  	unsigned char *tiMem,*tiMemEncode,*coMem,*coMemEncode, *maMem, *maMemEncode;
  	int x,y,t,b;
      int lenencode,lenencode1,lenencode2;
  	int lenencodet1,lenencodet2,lenencodet3;
  	FILE *fpc,*fph;
  	unsigned char bitplanes,mask;
  	
  	int len = strlen(filebase)-1;
  	int i;
  	for (i = len; i >= 0; i--) {
  		if (filebase[i] == '/') {
  			break;
  		}
  	}
  	if (i==-1)
  	{
  		sprintf(filenamef,"%sgfx",filebase);
  	}
  	else
  	{
  		sprintf(filenamef,"%sgfx",&filebase[i+1]);
  	}
  
  	sprintf(filenamec,"%sgfx.inc",&filebase[i+1]);
  	sprintf(filenameh,"%sgfx.h",&filebase[i+1]);
  
  	sprintf(filenamec,"%sgfx.inc",filebase);
  	sprintf(filenameh,"%sgfx.h",filebase);
  
  	if (quietmode == 0) {
  		printf("\nSaving gfx source file: [%s]",filenamec);
  		printf("\nSaving gfx header file: [%s]",filenameh);
  	}
  	fpc = fopen(filenamec,"wb");
  	fph = fopen(filenameh,"wb");
  
  	if(fpc==NULL)
  	{
  		printf("\nERROR: Can't open file [%s] for writing\n",filenamec);
  		return 0;
  	}
  	if(fph==NULL)
  	{
  		printf("\nERROR: Can't open file [%s] for writing\n",filenameh);
  		return 0;
  	}
  	if (bmpmode) num_tiles=768;
  	
      //tiMem = (unsigned char *) malloc(num_tiles*8);
      //tiMemEncode = (unsigned char *) malloc(num_tiles*8);
      tiMem = (unsigned char *) malloc(256*8*3); 			// max number for bitmap mode or f18a emc3 mode
      tiMemEncode = (unsigned char *) malloc(256*8*3);	// max number for bitmap mode or f18a emc3 mode
  	coMem = (unsigned char *) malloc(num_tiles*8);
      coMemEncode = (unsigned char *) malloc(num_tiles*8);
      maMem = (unsigned char *) malloc(mapw*maph);
      maMemEncode = (unsigned char *) malloc(mapw*maph);
  
  	if ( (tiMem==NULL) || (coMem==NULL) || (maMem==NULL) || 
  		 (tiMemEncode==NULL) || (coMemEncode==NULL) || (maMemEncode==NULL)  )
  	{
  		printf("\nERROR: Could not allocate enough memory\n");
  		return 0;
  	}
  	
  	if (quietmode == 0) {
  		printf("\nDecode for %d tiles...\n",num_tiles);
  	}
  
  	// different check for ecm1-3
  	if (ecmmode>1)
  	{
  		// grab number of planes
  		bitplanes=(ecmmode-1);
  		
  		for(t=0;t<num_tiles;t++) //loop through tiles
  		{
  			for(b=0;b<bitplanes;b++) //loop through bitplane pairs
  			{
  				//get bit-mask
  				mask = 1 << b;
  				for(y=0;y<8;y++)
  				{
  					value = 0;
  
  					//get row of bit-plane and save row
  					for(x=0;x<8;x++)
  					{
  						value = value << 1;
  						if(buffer[t*64 + y*8 + x] & mask)
  							value = value+1;
  					}
  					*(tiMem+y+t*8+(b*256*8))=value;
  				}
  			}
  			*(coMem+t)=*(tilecol+t);    // tile priority
  		}
  	}
  	else
  	{
  		for(t=0;t<num_tiles;t++) { //loop through tiles
  			for(y=0;y<8;y++) {
  				value=0; minv=0xFF; maxv=0x00;
  
  				// get the 8 values
  				for (x=0;x<8;x++) {
  					valtil[x]=buffer[t*64 + y*8 + x];
  					// get min and max value
  					if (valtil[x]<minv)
  						minv=valtil[x];
  					if (valtil[x]>maxv)
  						maxv=valtil[x];
  				}
  				// put 1 if max color
  				if (maxv <= 0x01) maxv=0xF;
  				if (minv == 0xff) minv=1;
  				for (x=0;x<8;x++) {
  					if (valtil[x]==maxv)
  						value=value | (1<<(7-x));
  				}
  				*(tiMem+y+t*8)=value;
  				if (gramode!=1)
  					*(coMem+y+t*8)=(maxv<<4) | (minv);    // FG color | BG color 
  			}
  		}
  		if (gramode==1)
  		{
  			for (t=0;t<32;t++)
  			 *(coMem+t)=*(tilecol+t);
  		}
  	}
  
  	// sprites are 16x16 but we need to swap tile 2<>3  
  	if (sprmode)
  	{
  		// different check for ecm1-3
  		if (ecmmode>1)
  		{
  			// grab number of planes
  			bitplanes=(ecmmode-1);
  		
  			for(t=0;t<num_tiles;t+=4)  //loop through tiles
  			{
  				for(b=0;b<bitplanes;b++) //loop through bitplane pairs
  				{
  					memcpy(bufsw1,(tiMem+(t+1)*8+(b*256*8)),8);
  					memcpy((tiMem+(t+1)*8+(b*256*8)),(tiMem+(t+2)*8+(b*256*8)),8);
  					memcpy((tiMem+(t+2)*8+(b*256*8)),bufsw1,8);
  				}
  			}
  		}
  		else 
  		{
  			for(t=0;t<num_tiles;t+=4) { //loop through tiles
  				memcpy(bufsw1,(tiMem+(t+1)*8),8);
  				memcpy((tiMem+(t+1)*8),(tiMem+(t+2)*8),8);
  				memcpy((tiMem+(t+2)*8),bufsw1,8);
  			}
  		}
  	}
  
      // Get map if possible (so not in sprite mode)
  	if (tilemap!=NULL)
  	{
  		for (t=0;t<mapw*maph;t++) {
  			// if bitmap mode, adapt it
  			if (bmpmode)
  			{
  				if (tilemap[t]>=256*2)
  					*(maMem+t)=tilemap[t]-256*2;
  				else if (tilemap[t]>=256)
  					*(maMem+t)=tilemap[t]-256;
  				else
  					*(maMem+t)=tilemap[t];
  			}
  			else
  				*(maMem+t)=tilemap[t];
  		}
      }
  
  	// write files regarding compression type
  	lenencode=num_tiles*8;lenencode1=num_tiles*8;lenencode2=mapw*maph;
  	lenencodet1=lenencodet2=lenencodet3=num_tiles*8;
  	if (ecmmode>1)
  	{
  		lenencode1=num_tiles;
  	}
  	if (compress==0) { // no compression
  		memcpy(tiMemEncode,tiMem,lenencode);
  		if (gramode==1)
  		{
  			memcpy(coMemEncode,coMem,32);
  			lenencode1=32;
  		}
  		else
  			memcpy(coMemEncode,coMem,lenencode1);
  		memcpy(maMemEncode,maMem,lenencode2);
  	}
  	else if (compress==1) { // rle compression
  		if (ecmmode>1)
  		{
  			lenencodet1=rleCompress( tiMem,tiMemEncode,lenencode);
  			lenencodet2=rleCompress( tiMem+256*8,tiMemEncode+256*8,lenencode);
  			lenencodet3=rleCompress( tiMem+256*8*2,tiMemEncode+256*8*2,lenencode);
  		}
  		else
  			lenencode=rleCompress( tiMem,tiMemEncode,lenencode);
  		if (gramode==1)
  		{
  			memcpy(coMemEncode,coMem,32);
  			lenencode1=32;
  		}
  		else
  			lenencode1=rleCompress(coMem,coMemEncode,lenencode1);
          if (savemap)
              lenencode2=rleCompress(maMem,maMemEncode,lenencode2);
          else
              memcpy(maMemEncode,maMem,lenencode2);
  	}
  	else if (compress==2) { // ple compression
  		if (ecmmode>1)
  		{
  			lenencodet1=pleCompress( tiMem,tiMemEncode,lenencode);
  			lenencodet2=pleCompress( tiMem+256*8,tiMemEncode+256*8,lenencode);
  			lenencodet3=pleCompress( tiMem+256*8*2,tiMemEncode+256*8*2,lenencode);
  		}
  		else
  			lenencode=pleCompress( tiMem,tiMemEncode,lenencode);
  		if (gramode==1)
  		{
  			memcpy(coMemEncode,coMem,32);
  			lenencode1=32;
  		}
  		else
  			lenencode1=pleCompress(coMem,coMemEncode,lenencode1);
          if (savemap)
              lenencode2=pleCompress(maMem,maMemEncode,lenencode2);
          else
              memcpy(maMemEncode,maMem,lenencode2);
  	}
  	else if (compress==3) { // dan1 compression
  		if (ecmmode>1)
  		{
  			lenencodet1=dan1Compress( tiMem,tiMemEncode,lenencode);
  			lenencodet2=dan1Compress( tiMem+256*8,tiMemEncode+256*8,lenencode);
  			lenencodet3=dan1Compress( tiMem+256*8*2,tiMemEncode+256*8*2,lenencode);
  		}
  		else
          {
  			lenencode=dan1Compress( tiMem,tiMemEncode,lenencode);
          }
  		if (gramode==1)
  		{
  			memcpy(coMemEncode,coMem,32);
  			lenencode1=32;
  		}
  		else
          {
  			lenencode1=dan1Compress(coMem,coMemEncode,lenencode1);
          }
          if (savemap)
          {
              lenencode2=dan1Compress(maMem,maMemEncode,lenencode2);
          }
          else
          {
              memcpy(maMemEncode,maMem,lenencode2);
          }
      }		
  	else if (compress==4) { // dan2 compression
  		if (ecmmode>1)
  		{
  			lenencodet1=dan2Compress( tiMem,tiMemEncode,lenencode);
  			lenencodet2=dan2Compress( tiMem+256*8,tiMemEncode+256*8,lenencode);
  			lenencodet3=dan2Compress( tiMem+256*8*2,tiMemEncode+256*8*2,lenencode);
  		}
  		else
          {
  			lenencode=dan2Compress( tiMem,tiMemEncode,lenencode);
          }
  		if (gramode==1)
  		{
  			memcpy(coMemEncode,coMem,32);
  			lenencode1=32;
  		}
  		else
          {
  			lenencode1=dan2Compress(coMem,coMemEncode,lenencode1);
          }
          if (savemap)
          {
              lenencode2=dan2Compress(maMem,maMemEncode,lenencode2);
          }
          else
          {
              memcpy(maMemEncode,maMem,lenencode2);
          }
      }	
  	else if (compress==5) { // dan3 compression
  		if (ecmmode>1)
  		{
  			lenencodet1=dan3Compress( tiMem,tiMemEncode,lenencode);
  			lenencodet2=dan3Compress( tiMem+256*8,tiMemEncode+256*8,lenencode);
  			lenencodet3=dan3Compress( tiMem+256*8*2,tiMemEncode+256*8*2,lenencode);
  		}
  		else
          {
  			lenencode=dan3Compress( tiMem,tiMemEncode,lenencode);
          }
  		if (gramode==1)
  		{
  			memcpy(coMemEncode,coMem,32);
  			lenencode1=32;
  		}
  		else
          {
  			lenencode1=dan3Compress(coMem,coMemEncode,lenencode1);
          }
          if (savemap)
          {
              lenencode2=dan3Compress(maMem,maMemEncode,lenencode2);
          }
          else
          {
              memcpy(maMemEncode,maMem,lenencode2);
          }
      }	
  	
  	// write to files
  	fprintf(fpc,"// Generated by gfx2col\n\n");
  	
  	if (ecmmode>1)
  	{
  		addcomment(fpc, (((num_tiles*8)-lenencodet1)*100)/(num_tiles*8),lenencodet1,compress);
  		fprintf(fpc, "const unsigned char TILP1%s[%d]={\n", filenamef,lenencodet1);
  		// write characters & colors
  		for (t = 0; t < lenencodet1; t++) {
  			if(t) {
  				if((t & 31) == 0)
  					fprintf(fpc, ",\n");
  				else
  					fprintf(fpc, ", ");
  			}
  			fprintf(fpc, "0x%02X", *(tiMemEncode+t));
  		}
  		fprintf(fpc, "\n};\n\n");
  		if (ecmmode>2)
  		{
  			addcomment(fpc, (((num_tiles*8)-lenencodet2)*100)/(num_tiles*8),lenencodet2,compress);
  			fprintf(fpc, "const unsigned char TILP2%s[%d]={\n", filenamef,lenencodet2);
  			// write characters & colors
  			for (t = 0; t < lenencodet2; t++) {
  				if(t) {
  					if((t & 31) == 0)
  						fprintf(fpc, ",\n");
  					else
  						fprintf(fpc, ", ");
  				}
  				fprintf(fpc, "0x%02X", *(tiMemEncode+t+256*8));
  			}
  			fprintf(fpc, "\n};\n\n");
  		}
  		if (ecmmode>3)
  		{
  			addcomment(fpc, ((num_tiles*8-lenencodet3)*100)/(num_tiles*8),lenencodet3,compress);
  			fprintf(fpc, "const unsigned char TILP3%s[%d]={\n", filenamef,lenencodet3);
  			// write characters & colors
  			for (t = 0; t < lenencodet3; t++) {
  				if(t) {
  					if((t & 31) == 0)
  						fprintf(fpc, ",\n");
  					else
  						fprintf(fpc, ", ");
  				}
  				fprintf(fpc, "0x%02X", *(tiMemEncode+t+256*8*2));
  			}
  			fprintf(fpc, "\n};\n\n");
  		}
  	}
  	else
  	{
  		addcomment(fpc, ((num_tiles*8-lenencode)*100)/(num_tiles*8),lenencode,compress);
  		fprintf(fpc, "const unsigned char TIL%s[%d]={\n", filenamef,lenencode);
  		// write characters & colors
  		for (t = 0; t < lenencode; t++) {
  			if(t) {
  				if((t & 31) == 0)
  					fprintf(fpc, ",\n");
  				else
  					fprintf(fpc, ", ");
  			}
  			fprintf(fpc, "0x%02X", *(tiMemEncode+t));
  		}
  		fprintf(fpc, "\n};\n\n");
  	}
  	
  	// do that only if it is not a sprite
  	if (sprmode==0) 
  	{
  		if (gramode!=1)
  		{
  			if (ecmmode>1)
  			{
  				addcomment(fpc, ((num_tiles-lenencode1)*100)/(num_tiles),lenencode1,compress);
  			}
  			else
  				addcomment(fpc, ((num_tiles*8-lenencode1)*100)/(num_tiles*8),lenencode1,compress);
  		}
  		fprintf(fpc, "const unsigned char COL%s[%d]={\n", filenamef,lenencode1);
  		for (t = 0; t < lenencode1; t++) {
  			if(t) {
  				if((t & 31) == 0)
  					fprintf(fpc, ",\n");
  				else
  					fprintf(fpc, ", ");
  			}
  			fprintf(fpc, "0x%02X", *(coMemEncode+t));
  		}
  		fprintf(fpc, "\n};\n\n");
  			
  		// write map if needed
  		if (savemap) {
  			addcomment(fpc, ((mapw*maph-lenencode2)*100)/(mapw*maph),lenencode2,compress);
  			fprintf(fpc, "const unsigned char MAP%s[%d]={\n", filenamef,lenencode2);
  			for (t = 0; t < lenencode2; t++) {
  				if(t) {
  					if((t & 31) == 0)
  						fprintf(fpc, ",\n");
  					else
  						fprintf(fpc, ", ");
  				}
  				fprintf(fpc, "0x%02X", *(maMemEncode+t));
  			}
  			fprintf(fpc, "\n};\n\n");
  		}
  	}
  
  	// do that only if we need palette
  	if (savepal) 
  	{
  		if (output_palette==64) 
  		{
  			fprintf(fpc, "const unsigned char PAL%s[%d]={\n", filenamef,(ecmmode==1) ? 16*2 : 64*2);
  			if (ecmmode==1)
  			{
  				y=15;
  				for (t = 0; t <  16; t++) 
  				{
  					if (t) 
  					{
  						if((t & 15) == 0)
  							fprintf(fpc, ",\n");
  						else
  							fprintf(fpc, ", ");
  					}
  
  					val16b=*(palet+t);
  					fprintf(fpc, "0x%02X", (val16b & 0xF00)>>8);
  					fprintf(fpc, ",0x%02X", (val16b & 0xFF));
  				}
  			}
  			else
  			{
  				y = (1<<(ecmmode-1))-1;
  				for (t = 0; t < 64; t++) 
  				{
  					if (t) 
  					{
  						if((t & y) == 0)
  							fprintf(fpc, ", // PAL %d\n",(t/(y+1))-1);
  						else
  							fprintf(fpc, ", ");
  					}
  
  					val16b=*(palet+t);
  					fprintf(fpc, "0x%02X", (val16b & 0xF00)>>8);
  					fprintf(fpc, ",0x%02X", (val16b & 0xFF));
  				}
  			}
  			fprintf(fpc, "  // PAL %d\n};\n\n",(t/(y+1))-1);
  		}
  	}
  
  	// write hearder file
  	fprintf(fph, "#ifndef %s_INC_\n", filenamef);
  	fprintf(fph, "#define %s_INC_\n\n", filenamef);
  	if (ecmmode>1)
  	{
  		fprintf(fph, "#define SZTILP1%s %d\n", filenamef,lenencodet1);
  		fprintf(fph, "#define SZTILP2%s %d\n", filenamef,lenencodet2);
  		fprintf(fph, "#define SZTILP3%s %d\n", filenamef,lenencodet3);
  
  	}
  	else
  		fprintf(fph, "#define SZTIL%s %d\n", filenamef,lenencode);
  	// do that only if it is not a sprite
  	if (sprmode==0) 
  	{
  
  		fprintf(fph, "#define SZCOL%s %d\n", filenamef,lenencode1);
  		if (savemap)
  			fprintf(fph, "#define SZMAP%s %d\n", filenamef,lenencode2);
  		fprintf(fph,"\n");
  	}
  	if (ecmmode>1)
  	{
  		fprintf(fph, "extern const unsigned char TILP1%s[];\n", filenamef);
  		fprintf(fph, "extern const unsigned char TILP2%s[];\n", filenamef);
  		fprintf(fph, "extern const unsigned char TILP3%s[];\n", filenamef);
  	}
  	else
  		fprintf(fph, "extern const unsigned char TIL%s[];\n", filenamef);
  	// do that only if it is not a sprite
  	if (sprmode==0) 
  	{
  		fprintf(fph, "extern const unsigned char COL%s[];\n", filenamef);
  		if (savemap)
  			fprintf(fph, "extern const unsigned char MAP%s[];\n", filenamef);
  	}
  	if (savepal)
  	{
  		if (output_palette==64) 
  		{
  			fprintf(fph, "extern const unsigned char PAL%s[];\n", filenamef);
  		}
  	}
  
  	fprintf(fph, "\n\n");
  	fprintf(fph, "#endif\n");
  		
  	fclose(fpc);fclose(fph);
  
      // free memory
      if (maMemEncode) free(maMemEncode);
      if (maMem) free(maMem);
      if (coMemEncode) free(coMemEncode);
      if (coMem) free(coMem);
      if (tiMemEncode) free(tiMemEncode);
      if (tiMem) free(tiMem);
  
  	return -1;
  } //end of Convert2Pic
  
  
  //---------------------------------------------------------------------------
  void PrintOptions(char *str) {
  	printf("\n\nUsage : gfx2col [options] bmp/pcx/tga filename ...");
  	printf("\n  where filename is a 256 color PNG, BMP, PCX or TGA file");
  	printf("\n   and palette is only the 1st 16 colors in bitmap or");
  	printf("\n   the 1st 64 colors in bitmap for F18A mode.");
  	
  	if(str[0]!=0)
  		printf("\nThe [%s] parameter is not recognized.",str);
  
  	printf("\n\nOptions are:");
  	printf("\n\n--- General options ---");
  	printf("\n-c[no|rle|ple|dan1|dan2|dan3]    Compression method [no]");
  	printf("\n\n--- Graphic options ---");
  	printf("\n-s                               Generate sprite graphics");
  	printf("\n-b                               Bitmap mode (no more 256 tiles limit)");
  	printf("\n-g[m1|m2]                        TMS9918 Graphic mode (mode 2 or mode 1) [m2]");
  	printf("\n-e[0|1|2|3]                      Enhanced Color Mode (F18A only) [0]");
  	printf("\n-t                               Enable transparent tiles (color 0)");
  	printf("\n\n--- Map options ---");
  	printf("\n-m!                              Exclude map from output");
  	printf("\n-m                               Convert the whole picture");
  	printf("\n-mR!                             No tile reduction (not advised)");
  	printf("\n-mn#              	           Generate the whole picture with an offset for tile number");
  	printf("\n                   	            where # is the offset in decimal (0 to 2047)");
  	printf("\n\n--- Palette options ---");
  	printf("\n-p!                              Exclude palette from output");
  	printf("\n-po                              Export palette (16 colors (ecm0) or 64 colors(ecm1-3)");
  	printf("\n-pR                              Palette rounding");
  	printf("\n\n--- File options ---");
  	printf("\n-f[bmp|pcx|tga|png]              Convert a bmp or pcx or tga or png file [bmp]");
  	printf("\n\n--- Misc options ---");
  	printf("\n-q                               Quiet mode");
  	printf("\n");
  	
  	printf("\nExample:");
  	printf("\ngfx2col -crle -fpng -m myimage.png");
  	printf("\n  will convert a myimage png file to a inc file with 8x8 tiles, rle compressed");
  	printf("\n  and a map.");
  } //end of PrintOptions()
  
  //---------------------------------------------------------------------------
  // M A I N 
  int main(int argc, char **arg) {
  	unsigned int palette[64];
  	unsigned int colorspal[256];//,coltilopt[256];
  	unsigned char colornumbers;
  	
  	int height, width;
  	int xsize, ysize,xsize1, ysize1;
  	pcx_picture image;
  
  	unsigned char *buffer, *buff=NULL;
  	unsigned int *tilemap,*timap=NULL;
  
  	char filebase[256]="";
  	char filename[256];
  
  	int i, x,y; 
  
      int file_type=BMP_FILE;
      int tile_reduction=1;         // 0 = no tile reduction (warning !)
      int savemap=1;                // 1 = save the map
      int savepal=1;                // 1 = save the palette
      
  	// Show something to begin :)
  	if (quietmode == 0) {
  		printf("\n==============================");
  		printf("\n---gfx2col v"GFX2COLVERSION" "GFX2COLDATE"---");
  		printf("\n------------------------------");
  		printf("\n(c) 2018-2020 Alekmaul");
  		printf("\n==============================\n");
  	}
  
  	//parse the arguments
  	for(i=1;i<argc;i++)	
  	{
  		if(arg[i][0]=='-') 
  		{
  			if(arg[i][1]=='q') //quiet mode
  			{
  				quietmode=1;
  			}
  			else if(arg[i][1]=='t') // transparent tile mode 
  			{
  				transmode=1;
  			}
  			else if(arg[i][1]=='s') // sprite mode
  			{
  				sprmode=1;
  				tile_reduction=0;
                  savemap=0;          // Fix 200318 , no need for sprite
  			}
  			else if(arg[i][1]=='b') // bitmap mode
  			{
  				bmpmode=1;
  			}			
  			else if(arg[i][1]=='m') //map options
  			{
  				if( strcmp(&arg[i][1],"m") == 0)
  				{
  				}
  				else if( strcmp(&arg[i][1],"m!") == 0)
  				{
  					savemap=0;
  				}
  				else if( strcmp(&arg[i][1],"mp") == 0)
  				{
  					highpriority=1;
  				}
  				else if(arg[i][2]=='n') //offset for tiles
  				{
  					offset_tile = atoi(&arg[i][3]);
  				}
  				else if( strcmp(&arg[i][1],"mR!") == 0)
  				{
  					tile_reduction=0;
  				}
  				else
  				{
  					PrintOptions(arg[i]);
  					return 1;
  				}
  			}
  			else if(arg[i][1]=='g')		// graphic mode
  			{
  				if( strcmp(&arg[i][1],"gm1") == 0)
  				{
  					gramode = 1; 
  				}
                  else //invalid option
                  {
                      PrintOptions(arg[i]);
                      return 1;
                  }
  			}
  			else if(arg[i][1]=='p') 	//palette options
  			{
  				if( strcmp(&arg[i][1],"p!") == 0)
  				{
  					savepal=0;
  				}
  				else if(arg[i][2]=='o') 		//palette output (64 colors)
  				{
  					output_palette=64;
  				}
  				else if(arg[i][2]=='R') // color rounded
  				{
  					palette_rnd=1;
  				}
                  else //invalid option
                  {
                      PrintOptions(arg[i]);
                      return 1;
                  }
  			}
  			else if(arg[i][1]=='e') 	//ecm mode
  			{
  				if(arg[i][2]=='o') 		//palette output (64 colors)
  				{
  					output_palette=64;
  				}
  				else if(arg[i][2]=='R') // color rounded
  				{
  					palette_rnd=1;
  				}
  				else if ( (arg[i][2]>='0') && (arg[i][2]<='3') )
  				{
  					ecmmode=1+arg[i][2]-48;
  					output_palette=64;
  				}
  				else
  				{
  					PrintOptions(arg[i]);
  					return 1;
  				}
  			}
  			else if(arg[i][1]=='c')		//compression method
  			{
  				if( strcmp(&arg[i][1],"crle") == 0)
  				{
  					compress = 1; 
  				}
  				else if( strcmp(&arg[i][1],"cple") == 0)
  				{
  					compress = 2;
  				}
  				else if( strcmp(&arg[i][1],"cdan1") == 0)
  				{
  					compress = 3; // DAN1 compression
  				}
  				else if( strcmp(&arg[i][1],"cdan2") == 0)
  				{
  					compress = 4; // DAN2 compression
  				}
  				else if( strcmp(&arg[i][1],"cdan3") == 0)
  				{
  					compress = 5; // DAN3 compression
  				}
                  else //invalid option
                  {
                      PrintOptions(arg[i]);
                      return 1;
                  }
  			}
  			else if(arg[i][1]=='f') //file type specification
  			{
  				if( strcmp(&arg[i][1],"fpcx") == 0)
  				{
  					file_type = 2; // PCX,
  				}
  				else if( strcmp(&arg[i][1],"ftga") == 0)
  				{
  					file_type = 3; // TGA
  				}
  				else if( strcmp(&arg[i][1],"fpng") == 0)
  				{
  					file_type = 4; // PNG, evething else is bmp
  				}
                  else //invalid option
                  {
                      PrintOptions(arg[i]);
                      return 1;
                  }
  			}
  			else //invalid option
  			{
  				PrintOptions(arg[i]);
  				return 1;
  			}
  		}
  		else
  		{
  			//its not an option flag, so it must be the filebase
  			if(filebase[0]!=0) // if already defined... there's a problem
  			{
  				PrintOptions(arg[i]);
  				return 1;
  			}
  			else
  				strcpy(filebase,arg[i]);
  		}
  	}
  
  	if( filebase[0] == 0 ) {
  		printf("\nERROR: You must specify a base filename.");
  		PrintOptions("");
  		return 1;
  	}
  
  	//Load picture
  	if (filebase[strlen(filebase)-4] == '.') {
  		filebase[strlen(filebase)-4] = '\0';
  	}
  	switch (file_type) {
  		case 2 : // PCX
  			sprintf(filename,"%s.pcx",filebase);
  			if (quietmode == 0)
  				printf("\nOpening graphics file: [%s]",filename);
  			if(!PCX_Load(filename,(pcx_picture_ptr) &image))
  				return 1;
  			break;
  		case 3 : // TGA
  			sprintf(filename,"%s.tga",filebase);
  			if (quietmode == 0)
  				printf("\nOpening graphics file: [%s]",filename);
  			if(!TGA_Load(filename,(pcx_picture_ptr) &image))
  				return 1;
  			break;
  		case 4 : // PNG
  			sprintf(filename,"%s.png",filebase);
  			if (quietmode == 0)
  				printf("\nOpening graphics file: [%s]",filename);
  			if(!PNG_Load(filename,(pcx_picture_ptr) &image))
  				return 1;
  			break;
  		default : // BMP for everithing else
  			sprintf(filename,"%s.bmp",filebase);
  			if (quietmode == 0)
  				printf("\nOpening graphics file: [%s]",filename);
  			if(!BMP_Load(filename,(pcx_picture_ptr) &image))
  				return 1;
  			break;
  	}
  
  	//convert the palette
  	if (output_palette==64)
  		ConvertPalette(image.palette, palette);
  	
  	height = image.header.height;
  	width = image.header.width;
  	xsize = width>>3; ysize = height>>3;
  	
  	//Print what the user has selected
  	if (quietmode == 0) {
  		printf("\n****** O P T I O N S ***************");
  		if (sprmode)
  			printf("\nSprite mode=ON");
  		else {
  			printf("\nSprite mode=OFF");
  			if (transmode)
  				printf("\nF18A Tile transparent mode=ON");
  			else 
  				printf("\nF18A Tile transparent mode=OFF");
  			if (highpriority)
  				printf("\nF18A Tile highpriority mode=ON");
  			else
  				printf("\nF18A Tile highpriority mode=OFF");
  			if (ecmmode==0) 
  			{
  				if (bmpmode)
  					printf("\nTMS9918 Bitmap mode2=ON");
  				else {
  					printf("\nTMS9918 Bitmap mode2=OFF");
  					if (gramode == 0)
  						printf("\nTMS9918 Graphic mode 2");
  					else if (gramode == 1)
  						printf("\nTMS9918 Graphic mode 1");
  				}
  			}
  			if (tile_reduction)
  				printf("\nOptimize tilemap=ON");
  			else
  				printf("\nOptimize tilemap=OFF");
  		}
  		if (ecmmode!=0) 
  		{
  			printf("\nF18A Enhanced Color Mode=%d",ecmmode-1);
  		}
  			
  		if (file_type == 2)
  			printf("\nPCX file: %dx%d pixels",width,height);
  		else if (file_type == 3)
  			printf("\nTGA file: %dx%d pixels",width,height);
  		else if (file_type == 4)
  			printf("\nPNG file: %dx%d pixels",width,height);
  		else
  			printf("\nBMP file: %dx%d pixels",width,height);
  
  		if (compress == 0)
  			printf("\nNo compression");
  		else if (compress == 1)
  			printf("\nRLE compression");
  		else if (compress == 2)
  			printf("\nPLE compression");
  		else if (compress == 3)
  			printf("\nDAN1 compression");
  		else if (compress == 4)
  			printf("\nDAN2 compression");
  		else if (compress == 5)
  			printf("\nDAN3 compression");
  
  		if (output_palette)
  			printf("\nPalette output=ON");
  		else 
  			printf("\nPalette output=OFF");
  
  		printf("\n************************************");
  	}
  	fflush(stdout);
  
  	if ( (bmpmode==1) && (width != 256) && (height != 192) )
  	{
  		printf("\nERROR : Image must have 256x192 pixel size in bitmap mode (%d,%d here).\n",width, height);
  		return 1;
  	}
  		
  	if (bmpmode) 
  	{
  		// prepare global map & tiles
  		tilemap=(unsigned int *) malloc(32*24*sizeof(int));
  		buffer = (unsigned char *) malloc( 768*8*8*sizeof(char) );
  		ysize=0;
  
  		// 3 parts for tiles in bitmap mode
          for (i=0;i<3;i++) {
  			ysize1=8;xsize1=32;
  
  			// Get tiles
              if (buff) free(buff);
              buff=ArrangeBlocks(image.buffer+i*256*64,256,64,8,&xsize1,&ysize1,8);
  			if(buff==NULL)
  			{
  				printf("\nERROR:Not enough memory to do image operations...\n");
  				return 1;
  			
  			}
  			
  			// Optimize map with current tile set
              if (timap) free (timap);
              timap=MakeMap(buff, colorspal, &ysize1, xsize1, ysize1, xsize1, ysize1, tile_reduction );
  			if(timap==NULL) 
  			{
  				free(buff);
  				printf("\nERROR:Not enough memory to do tile map optimizations..\n");
  				return 1;
  			}
  
  			// load tiles
  			ysize+=ysize1;
  			if ( (ysize1>0)) {
  				memcpy(buffer+i*256*8*8,buff,256*8*8);
  							
  				// change map at the end
                  for (y=0;y<8;y++)
  					for (x=0;x<32;x++)
  						tilemap[x+y*32+i*256]=timap[x+y*32]+i*256;
  			} // if ( (ysize>0))
  		} // for (i=0;i<3;i++) {
  		free(image.buffer);
  		free(buff);
  		free(timap);
  	}
  	else {
  		// now re-arrange into a list of 8x8 blocks for easy conversion
  		buffer=ArrangeBlocks( image.buffer, width, height, 8, &xsize, &ysize, 8);
  		free(image.buffer);
  		if(buffer==NULL)
  		{
  			printf("\nERROR:Not enough memory to do image operations...\n");
  			return 1;
  		}
  			
  		//make the tile map now
  		tilemap=MakeMap(buffer, colorspal, &ysize, xsize, ysize, xsize, ysize, tile_reduction );
  		if(tilemap==NULL) 
  		{
  			free(buffer);
  			printf("\nERROR:Not enough memory to do tile map optimizations..\n");
  			return 1;
  		}
  
  		// make color map now for mode 1 and if not F18A enhanced mode 1-3 (will erase colorspal, but don't care)
  		if ( (ecmmode<=1) && (gramode==1) )
  		{
  			if ( MakeCol(buffer, tilemap,&colornumbers, colorspal,  &ysize,width/8, height/8) == 0)
  			{
  				return 1;
  			}
  			if (quietmode == 0) 
  				printf("\nScreen uses %d colors.",colornumbers);
  				
  		}
  	}
  
  	if (ysize>0) 
  	{
  		if (quietmode == 0) 
  		{
  			if (tile_reduction)
  				printf("\nReduced screen to %d tiles.",ysize);
  			else
  				printf("\nComputed screen with %d tiles.",ysize);
  		}
  		
  		if ( (ysize>255) && (bmpmode==0) && (sprmode==0) )  // fix 200318 no control if in sprite mode
  		{
  			printf("\nERROR : Image must have less than 256 tiles (%d here).\n",ysize);
  			return 1;
  		}
  		
  		//convert pictures and save to file
  		if(!Convert2Pic(filebase, buffer, tilemap, palette, colorspal, ysize, width/8, height/8,savemap,savepal)) 
  		{
  			//free up image & tilemap memory
  			free(tilemap);
  			free(buffer);
  			return 1;
  		}
  	}
  
  	//free up image & tilemap memory
  	free(tilemap);
  	free(buffer);
  
  	if (quietmode == 0)
  		printf("\nDone !\n\n");
  
  	return 0;
  }
  