#define INTUI_V36_NAMES_ONLY

#include "iffp/ilbmapp.h"

enum format_t {ASM_FORMAT,C_FORMAT};

#define NL fprintf(f,"\n");

#define BEGIN_COMMENT\
	fprintf(f,format==ASM_FORMAT?"\t;":"/*\n * ")
#define END_COMMENT\
	fprintf(f,format==ASM_FORMAT?"\n":"\n */\n")
#define NL_COMMENT\
	fprintf(f,format==ASM_FORMAT?"\n\t; ":"\n * ")
#define COMMENT(x)\
	fprintf(f,format==ASM_FORMAT?"; %s\n":"/* %s */\n",x)
#define IDENTIFIER(x)\
	fprintf(f,format==ASM_FORMAT?".%s:\n":"unsigned char %s[] = {\n",x)

typedef struct gbtile_struct
{
	UBYTE bmap[8][2];
} gbtile;

void __chkabort(void) {}          /* Disable SAS CTRL-C checking. */

void bye(UBYTE *s, int e);
void cleanup(void);

struct Library *IFFParseBase = NULL;
struct Library *GfxBase = NULL;

/* ILBM frame */
struct ILBMInfo ilbm = {0};


/* ILBM Property chunks to be grabbed - BMHD and CMAP needed for this app
 */
LONG	ilbmprops[] = {
		ID_ILBM, ID_BMHD,
		ID_ILBM, ID_CMAP,
		TAG_DONE
		};

/* ILBM Collection chunks (more than one in file) to be gathered */
LONG	*ilbmcollects = NULL;	/* none needed for this app */

/* ILBM Chunk to stop on */
LONG	ilbmstops[] = {
		ID_ILBM, ID_BODY,
		TAG_DONE
		};

void gbDump(struct BitMap *bitmap,SHORT *cols,enum format_t format,int first,BOOL stdtiles,char* filename, BOOL verbose);

/** main() ******************************************************************/

void main(int argc, char **argv)
{
	LONG error=NULL;
	UBYTE *ilbmname, fname[80], buf[24];

	if ((argc < 2)||(argv[argc-1][0]=='?'))
		bye("Usage from CLI: 'ILBMtoRaw filename'\n",RETURN_OK);
    
	if(!(GfxBase = OpenLibrary("graphics.library",0)))
		bye("Can't open graphics.library",RETURN_FAIL);

	if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
		bye("Can't open iffparse.library",RETURN_FAIL);

/*
 * Here we set up default ILBMInfo fields for our
 * application's frames.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like BMHD)
 */
	ilbm.ParseInfo.propchks      = ilbmprops;
	ilbm.ParseInfo.collectchks   = ilbmcollects;
	ilbm.ParseInfo.stopchks      = ilbmstops;
	if(!(ilbm.ParseInfo.iff = AllocIFF()))
		bye(IFFerr(IFFERR_NOMEM),RETURN_FAIL);	/* Alloc an IFFHandle */

	ilbmname = argv[1];

	/* Load as a brush since we don't need to display it */
	if (error = loadbrush(&ilbm,ilbmname))
	{
		printf("Can't load ilbm \"%s\", ifferr=%s\n",ilbmname,IFFerr(error));
		bye("",RETURN_WARN);
	}
	else /* Successfully loaded ILBM */
	{
		strcpy(fname,argv[1]);

		if(ilbm.camg & HAM)
			strcat(fname, ".ham");
		if(ilbm.camg & EXTRA_HALFBRITE)
			strcat(fname, ".ehb");

		if(ilbm.camg & HIRES)
			strcat(fname, ".hi");
		else
			strcat(fname, ".lo");

		if(ilbm.camg & LACE)	strcat(fname, ".lace");

		strcat(fname,".");
		sprintf(buf,"%d",ilbm.Bmhd.w);
		strcat(fname,buf);
		strcat(fname,"x");
		sprintf(buf,"%d",ilbm.Bmhd.h);
		strcat(fname,buf);
		strcat(fname,"x");
		sprintf(buf,"%d",ilbm.brbitmap->Depth);
		strcat(fname, buf);
		printf(" Creating file \"%s\" \n", fname);

		if ((ilbm.camg&(HAM|EXTRA_HALFBRITE))||(ilbm.Bmhd.w%8))
		{
			printf("\n4 col even div 8\n\n");
		}
		else
		{
			gbDump(ilbm.brbitmap,ilbm.colortable,C_FORMAT,0,TRUE,"olle",TRUE);
		}
		unloadbrush(&ilbm);

	  if(error)
			bye(IFFerr(error),RETURN_WARN);
	  else
			bye("",RETURN_OK);
	}
}

/*
void printtile(gbtile* tile)
{
	int i,j;
	for (i=0;i<8;i++)
	{
		for (j=7;j>=0;j--)
		{
			switch ((((tile->bmap[i][0])>>j)&0x01)|(((tile->bmap[i][1])>>j)&0x01)<<1)
			{
				case 0:
					printf("0");
					break;
				case 1:
					printf("1");
					break;
				case 2:
					printf("2");
					break;
				case 3:
					printf("3");
					break;
				default:
					break;
			}
		}
		printf("\n");
	}
	printf("\n");
}
*/

void gbDump(struct BitMap *bitmap,SHORT *cols,enum format_t format,int first,BOOL stdtiles,char* filename,BOOL verbose)
{
  FILE *f;

	int i,j;
	int x,y,c;
  int last;
  int std;

	gbtile tiles[0x100];
  gbtile t;

	char buffer[128];
  char dataname[64];
  UBYTE *buf,*b;

/*
	gbtile testtile;
	testtile.bmap[0][0]=0x00;testtile.bmap[0][1]=0x00;
	testtile.bmap[1][0]=0xff;testtile.bmap[1][1]=0x00;
	testtile.bmap[2][0]=0x00;testtile.bmap[2][1]=0xff;
	testtile.bmap[3][0]=0xff;testtile.bmap[3][1]=0xff;
	testtile.bmap[4][0]=0x01;testtile.bmap[4][1]=0x00;
	testtile.bmap[5][0]=0x00;testtile.bmap[5][1]=0x80;
	testtile.bmap[6][0]=0x30;testtile.bmap[6][1]=0xf0;
	testtile.bmap[7][0]=0x0f;testtile.bmap[7][1]=0x03;
	printtile(&testtile);
*/

	if (verbose)
	{
		printf("Dumping GB image to \"%s\"",filename);
		printf(" (size: %d - %d depth: %d)\n",bitmap->BytesPerRow*8,bitmap->Rows,bitmap->Depth);
	}

/*
	if(!(f=fopen(filename,"w")))
	{
		return;
	}
*/
	f=stdout;

	if (stdtiles)
		std=4;
	else
		std=0;

	strcpy(dataname,"image");

	last=first;

	if (verbose)
	{
		printf("First tile is 0x%02x\n",first);
		if (stdtiles)
			printf("Using standard tiles in 0xFC to 0xFF\n");
		printf("Dump format is %s\n",format==ASM_FORMAT?"ASSEMBLY":"C");
	}

	if(stdtiles)
	{
		// Create the 4 basic tiles
		for (i=0;i<8;i++)
		{
			tiles[0xFF].bmap[i][0]=tiles[0xFF].bmap[i][1]=
				tiles[0xFE].bmap[i][0]=tiles[0xFD].bmap[i][1]=0x00;
			tiles[0xFD].bmap[i][0]=tiles[0xFE].bmap[i][1]=
				tiles[0xFC].bmap[i][0]=tiles[0xFC].bmap[i][1]=0xFF;
		}
	}

	// Create tiles list
	buf=(UBYTE*)malloc((bitmap->BytesPerRow)*(bitmap->Rows/8)*sizeof(UBYTE));
	b=buf;

	// Loop over tile rows
	for(y=0;y<bitmap->Rows/8;y++)

		// Loop over tile columns
		for(x=0;x<bitmap->BytesPerRow;x++)
		{

			// Copy current position to temporary tile
			for(i=0;i<8;i++)
			{
				t.bmap[i][0]=(UBYTE)*((bitmap->Planes[0])+8*y*bitmap->BytesPerRow+i*bitmap->BytesPerRow+x);
				t.bmap[i][1]=(UBYTE)*((bitmap->Planes[1])+8*y*bitmap->BytesPerRow+i*bitmap->BytesPerRow+x);
			}

			// Check if current tile is a standard one
			for(c=0x100-std;c<0x100;c++)
			{
				if(memcmp(tiles[c].bmap,t.bmap,sizeof(t.bmap))==0)
					break;
			}

			// Current tile is not a standard one
			if(c>=0x100)
			{
				c=first;
				while(c<last)
				{
					if(memcmp(tiles[c].bmap,t.bmap,sizeof(t.bmap))==0)
					{
						break;
					}
					c++;
				}

				// Remember this new tile
				if(c==last)
				{
					if(last>=0x100-std)
					{
						fprintf(stderr, "Image has too much tiles.\n");
//						unlink(filename);
						return;
					}
					for(i=0;i<8;i++)
					{
						memcpy(tiles[last].bmap,t.bmap,sizeof(t.bmap));
					}
					last++;
				}
			}
			*b=c;
			b++;
		}
	if (verbose)
	{
		printf("Found %d unique tiles\n",last-first);
	}

/*
	for (i=first;i<last;i++)
	{
		printf("Tile: %d\n",i);
		printtile(&tiles[i]);
	}
*/

	// Write image info to file
	BEGIN_COMMENT;
	fprintf(f,"Image size: 0x%02X x 0x%02X",bitmap->BytesPerRow*8,bitmap->Rows);
	NL_COMMENT;
	fprintf(f, "Number of tiles (total - unique): 0x%02X - 0x%02X",
		(bitmap->BytesPerRow)*(bitmap->Rows/8),last-first);
	END_COMMENT;
	NL;

	// Write image data to file
	if (stdtiles)
	{
		IDENTIFIER("stdtiles_data");
		fprintf(f,"\t");
		COMMENT("Basic tiles (0xFC to 0xFF)");
		for (i=0x100-std;i<0x100;i++)
		{
			fprintf(f,"\t");
			if (format==ASM_FORMAT)
				fprintf(f,".byte\t");
			for (j=0;j<8;j++)
			{
				fprintf(f,"0x%02X,",tiles[i].bmap[j][0]);
				fprintf(f,"0x%02X",tiles[i].bmap[j][1]);
				if (j<7||(format==C_FORMAT&&i<0x100-1))
					fprintf(f,",");
			}
			fprintf(f,"\n");
		}
		if(format==C_FORMAT)
			fprintf(f,"};\n");
		NL;
	}

	sprintf(buffer,"%s_data",dataname);
	IDENTIFIER(buffer);
	i=first;
	while(i<last)
	{
		if(i==first||i%8==0)
		{
			fprintf(f,"\n\t");
			sprintf(buffer,"Tile 0x%02X",i);
			COMMENT(buffer);
		}
		fprintf(f,"\t");
		if (format==ASM_FORMAT)
			fprintf(f,".byte\t");
		for(j=0;j<8;j++)
		{
			fprintf(f,"0x%02X,",tiles[i].bmap[j][0]);
			fprintf(f,"0x%02X",tiles[i].bmap[j][1]);
			if (j<7||(format==C_FORMAT&&i<last-1))
				fprintf(f,",");
		}
		fprintf(f,"\n");
		i++;
	}
	if (format==C_FORMAT)
		fprintf(f,"};\n");
	NL;

	// Write image table to file
	sprintf(buffer,"%s_tiles",dataname);
	IDENTIFIER(buffer);
	b=buf;
	for (y=0;y<bitmap->Rows;y+=8)
	{
		fprintf(f,"\t");
		if (format == ASM_FORMAT)
			fprintf(f, ".byte\t");
		for (x=0;x<bitmap->BytesPerRow*8;x+=8)
		{
			fprintf(f,"0x%02X",*b);
			if(x<bitmap->BytesPerRow*8-8||(format==C_FORMAT&&y<bitmap->Rows-8))
				fprintf(f,",");
			b++;
		}
		fprintf(f,"\n");
	}
	if(format==C_FORMAT)
		fprintf(f,"};\n");
/*
	fclose(f);
*/
	free(buf);
}

void bye(UBYTE *s, int e)
    {
    if(s&&(*s))	printf("%s\n",s);
    cleanup();
    exit(e);
    }

void cleanup()
    {
    if(ilbm.ParseInfo.iff)		FreeIFF(ilbm.ParseInfo.iff);

    if(IFFParseBase)	CloseLibrary(IFFParseBase);
    if(GfxBase)		CloseLibrary(GfxBase);
    }





