//---------------------------------------------------------------------------
 #define STRICT

#include <vcl.h>
#include <stdio.h>
#include <Clipbrd.hpp>
#include <math.h>
#pragma hdrstop

#include "UnitMain.h"
#include "UnitCHREditor.h"
#include "UnitSwapColors.h"
#include "UnitNametableOffset.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;


#define REG_SECTION "Software\\Shiru\\NES Screen Tool\\"

const char regWorkingDirectory[]="WorkDir";
const char colBlack=0x0f;
int        g_nrExportedSprite = 0;
int		   g_EditorMode       = 0;

#define EDITOR_BG_MODE  1
#define EDITOR_SPR_MODE 2


#define SAVE_NAMETABLE_NAM		1
#define SAVE_NAMETABLE_BIN		2
#define SAVE_NAMETABLE_RLE		3
#define SAVE_NAMETABLE_H		4




AnsiString reg_load_str(const char *name,AnsiString def)
{
	HKEY key;
	DWORD type,size;
	char *str;
	AnsiString ret;

	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,REG_SECTION,0,KEY_READ,&key)!=ERROR_SUCCESS) return def;

	type=REG_SZ;
	size=1024;
	str=(char*)malloc(size);
	if(RegQueryValueEx(key,name,NULL,&type,(unsigned char*)str,&size)!=ERROR_SUCCESS) ret=def; else ret=str;
	free(str);
	RegCloseKey(key);

	return ret;
}



void reg_save_str(const char *name,AnsiString str)
{
	HKEY key;
	DWORD disp;

	if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,REG_SECTION,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&key,&disp)!=ERROR_SUCCESS) return;

	RegSetValueEx(key,name,0,REG_SZ,str.c_str(),strlen(str.c_str())+1);
	RegCloseKey(key);
}



int basePalette[64]={//from a picture found in internet
	0x7f7f7f,0xff0000,0xbf0000,0xbf2b47,
	0x870097,0x2300ab,0x0013ab,0x00178b,
	0x003053,0x007800,0x006b00,0x005b00,
	0x584300,0x000000,0x000000,0x000000,
	0xbfbfbf,0xf87800,0xf85800,0xff476b,
	0xcd00db,0x5b00e7,0x0038f8,0x135fe7,
	0x007faf,0x00b800,0x00ab00,0x47ab00,
	0x8b8b00,0x000000,0x000000,0x000000,
	0xf8f8f8,0xffbf3f,0xff886b,0xf87898,
	0xf878f8,0x9858f8,0x5878f8,0x47a3ff,
	0x00b8f8,0x18f8b8,0x57db5b,0x98f858,
	0xdbeb00,0x787878,0x000000,0x000000,
	0xffffff,0xffe7a7,0xf8b8b8,0xf8b8d8,
	0xf8b8f8,0xc3a7fb,0xb0d0f0,0xabe3ff,
	0x7bdbfb,0x78f8d8,0xb8f8b8,0xd8f8b8,
	0xffff00,0xf8d8f8,0x000000,0x000000
};

float emphasis[8][3]={//from nintech.txt
	{100.0,100.0,100.0},
	{ 74.3, 91.5,123.9},
	{ 88.2,108.6, 79.4},
	{ 65.3, 98.0,101.9},
	{127.7,102.6, 90.5},
	{ 97.9, 90.8,102.3},
	{100.1, 98.7, 74.1},
	{ 75.0, 75.0, 75.0}
};


int palette[64];
int ppuMask;

unsigned char bgPal[4][4]={{0,15,16,48},{0,1,33,49},{0,6,22,38},{0,9,25,41}};

int bgPalCur;
int palActive;
int tileActive;
int bankActive;
int nameXC;
int nameYC;
int tileXC;
int tileYC;
int palHover;
int palColHover;
int colHover;

unsigned char chr[8192];
unsigned char chrCopy[4096];
unsigned char nameTable[960];
unsigned char attrTable[960];

//unsigned char attrTable[64];

TRect nameSelection;
int nameCopyWidth;
int nameCopyHeight;

unsigned char nameCopy[960];
unsigned char attrCopy[960];

unsigned char undoChr[8192];
unsigned char undoNameTable[960];
unsigned char undoAttrTable[960];

TRect chrSelection;
int chrCopyWidth;
int chrCopyHeight;
bool chrCopyRect;
bool chrSelected[256];
bool chrSelectRect;



int get_file_size(FILE *file)
{
	int size;

	fseek(file,0,SEEK_END);
	size=ftell(file);
	fseek(file,0,SEEK_SET);

	return size;
}



int read_dword(unsigned char *data)
{
	return data[0]+(data[1]<<8)+(data[2]<<16)+(data[3]<<24);
}



int attr_get(int x,int y)
{
	int pal;
	pal=attrTable[y * 32 + x];
	return pal;
}



void attr_set(int x,int y,int pal)
{
	attrTable[y * 32 + x ]= pal;
}



void save_data(const char *name,unsigned char *src,int size,int type)
{
	char arrname[256],temp[256];
	FILE *file;
	int i,min,tag,pp,len,sym;
	unsigned char *dst;
	int stat[256];
	bool rle;

	rle=(type==SAVE_NAMETABLE_RLE||type==SAVE_NAMETABLE_H)?true:false;

	if(rle)
	{
		dst=(unsigned char*)malloc(size*2);

		for(i=0;i<256;i++) stat[i]=0;
		for(i=0;i<size;i++) stat[src[i]]++;

		min=256;
		tag=255;

		for(i=0;i<256;i++)
		{
			if(stat[i]<min)
			{
				min=stat[i];
				tag=i;
			}
		}

		//tag=255;
		pp=0;
		dst[pp++]=tag;
		len=0;
		sym=-1;

		for(i=0;i<size;i++)
		{
			if(src[i]!=sym||len==255||i==size-1)
			{
				if(src[i]==sym&&i==size-1) len++;
				if(len) dst[pp++]=sym;
				if(len>1)
				{
					if(len==2)
					{
						dst[pp++]=sym;
					}
					else
					{
						dst[pp++]=tag;
						dst[pp++]=len-1;
					}
				}
				sym=src[i];
				len=1;
			}
			else
			{
				len++;
			}
		}

		dst[pp++]=tag;
		dst[pp++]=0;
		size=pp;
	}
	else
	{
		dst=src;
	}

	if(type!=SAVE_NAMETABLE_H)//binary
	{
		file=fopen(name,"wb");

		if(file)
		{
			fwrite(dst,size,1,file);
			fclose(file);
		}
	}
	else//text
	{
		file=fopen(name,"wt");

		if(file)
		{
			i=strlen(name);

			while(i)
			{
				if(name[i]=='\\'||name[i]=='/')
				{
					i++;
					break;
				}
				i--;
			}

			strcpy(arrname,&name[i]);

			for(i=strlen(arrname)-1;i>=0;i--)
			{
				if(arrname[i]=='.')
				{
					arrname[i]=0;
					break;
				}
			}

			if(arrname[0]!='_'&&!(arrname[0]>='a'&&arrname[0]<='z')&&!(arrname[0]>='A'&&arrname[0]<='Z'))
			{
				strcpy(temp,arrname);
				strcpy(arrname,"n");
				strcat(arrname,temp);
			}

			fprintf(file,"const unsigned char %s[%i]={\n",arrname,size);

			for(i=0;i<size;i++)
			{
				fprintf(file,"0x%2.2x",dst[i]);
				if(i<size-1) fprintf(file,",");
				if((i&15)==15||i==(size-1)) fprintf(file,"\n");
			}

			fprintf(file,"};\n");
			fclose(file);
		}
	}

	if(rle) free(dst);
}



void mem_exchange(unsigned char *src,unsigned char *dst,int len)
{
	int temp;

	while(len)
	{
		temp=*src;
		*src++=*dst;
		*dst++=temp;
		len--;
	}
}



void pal_validate(void)
{
	int i,j;

	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			switch(bgPal[i][j])
			{
			case 0x0d:
			case 0x1d:
			case 0x0e:
			case 0x1e:
			case 0x2e:
			case 0x3e:
			case 0x1f:
			case 0x2f:
			case 0x3f:
				bgPal[i][j]=colBlack;
				break;
			}
		}
	}
}



void palette_calc(void)
{
	int i;
	float r,g,b;

	if(!(ppuMask&0x01))
	{
		for(i=0;i<64;i++)
		{
			r=((float)((basePalette[i]>>16)&0xff))/255.0;
			g=((float)((basePalette[i]>>8)&0xff))/255.0;
			b=((float)(basePalette[i]&0xff))/255.0;
			r=r*emphasis[ppuMask>>5][0]/100.0;
			g=g*emphasis[ppuMask>>5][1]/100.0;
			b=b*emphasis[ppuMask>>5][2]/100.0;
			if(r>1.0) r=1.0;
			if(g>1.0) g=1.0;
			if(b>1.0) b=1.0;
			palette[i]=(((int)(255.0*r))<<16)|(((int)(255.0*g))<<8)|((int)(255.0*b));
		}
	}
	else
	{
		for(i=0;i<64;i++)
		{
			palette[i]=basePalette[i&0xf0];
		}
	}
}



AnsiString RemoveExt(AnsiString name)
{
	return ChangeFileExt(name,"");
}



AnsiString GetExt(AnsiString name)
{
	name=ExtractFileName(name);

	return name.SubString(name.LastDelimiter(".")+1,name.Length()-name.LastDelimiter(".")).LowerCase();
}



void __fastcall TFormMain::DrawCol(int x,int y,int c,bool sel)
{
	TRect r;

	r.left=x;
	r.top=y;
	r.right=x+20;
	r.Bottom=y+20;
	PaintBoxPal->Canvas->Brush->Color=TColor(palette[c]);
	PaintBoxPal->Canvas->FillRect(r);
	if(sel)
	{
		PaintBoxPal->Canvas->Pen->Color=TColor(0xffffff);
		PaintBoxPal->Canvas->Rectangle(r);
		PaintBoxPal->Canvas->Pen->Color=TColor(0);
		r.left+=1;
		r.top+=1;
		r.right-=1;
		r.bottom-=1;
		PaintBoxPal->Canvas->Rectangle(r);
	}
}



void __fastcall TFormMain::DrawBGPal(int x,int y,int pal)
{
	DrawCol(x   ,y,bgPal[pal][0],pal==palActive&&bgPalCur==0?true:false);
	DrawCol(x+20,y,bgPal[pal][1],pal==palActive&&bgPalCur==1?true:false);
	DrawCol(x+40,y,bgPal[pal][2],pal==palActive&&bgPalCur==2?true:false);
	DrawCol(x+60,y,bgPal[pal][3],pal==palActive&&bgPalCur==3?true:false);
}



void __fastcall TFormMain::DrawPalettes(void)
{
	int i,j,x,y,pp,col;
	TRect r;

	if(!Visible) return;

	DrawBGPal(16,0,0);
	DrawBGPal(128,0,1);
	DrawBGPal(16,32,2);
	DrawBGPal(128,32,3);

	y=64;
	pp=0;
	col=bgPal[palActive][bgPalCur];

	for(i=0;i<4;i++)
	{
		x=0;
		for(j=0;j<14;j++)
		{
			PaintBoxPal->Canvas->Brush->Color=TColor(palette[pp]);
			r.left=x;
			r.top=y;
			r.right=x+16;
			r.bottom=y+16;
			PaintBoxPal->Canvas->FillRect(r);
			if(pp==col)
			{
				PaintBoxPal->Canvas->Pen->Color=TColor(0xffffff);
				PaintBoxPal->Canvas->Rectangle(r);
				r.left+=1;
				r.top+=1;
				r.right-=1;
				r.bottom-=1;
				PaintBoxPal->Canvas->Pen->Color=TColor(0);
				PaintBoxPal->Canvas->Rectangle(r);
			}
			pp++;
			x+=16;
		}
		pp+=2;
		y+=16;
	}
}



void __fastcall TFormMain::DrawTile(TPicture *pic,int x,int y,int tile,int pal,int tx,int ty,bool sel)
{
	int j,k,pp,col,r,g,b;
	unsigned char *d1,*d2;
	int hgrid,vgrid,hcol,vcol;

	pp=tile*16+bankActive;

	if(chrSelectRect) sel=false;

	for(j=0;j<8;j++)
	{
		d1=(unsigned char*)pic->Bitmap->ScanLine[y+j*2]+x*3;
		d2=(unsigned char*)pic->Bitmap->ScanLine[y+j*2+1]+x*3;
		for(k=0;k<8;k++)
		{
			col=(((chr[pp+j]<<k)&128)>>7)|(((chr[pp+j+8]<<k)&128)>>6);
			col=palette[bgPal[pal][col]];
			r=(col>>16)&0xff;
			g=(col>>8)&0xff;
			b=col&0xff;
			if(sel)
			{
				r-=64;
				if(r<0) r=0;
				g+=64;
				if(g>255) g=255;
				b-=64;
				if(b<0) b=0;
			}
			*d1++=r;
			*d1++=g;
			*d1++=b;
			*d1++=r;
			*d1++=g;
			*d1++=b;
			*d2++=r;
			*d2++=g;
			*d2++=b;
			*d2++=r;
			*d2++=g;
			*d2++=b;
		}
	}

	hgrid=0;
	vgrid=0;
	hcol=64;
	vcol=64;

	if(tx<0&&ty<0)
	{
		if(SpeedButtonGridTile->Down||SpeedButtonGridAtr->Down||SpeedButtonGridBlock->Down)
		{
			hgrid=2;
			vgrid=2;
		}
	}
	else
	{
		if(SpeedButtonGridTile->Down)
		{
			hgrid=2;
			vgrid=2;
		}
		if(SpeedButtonGridAtr->Down)
		{
			if(!(ty&1))
			{
				hcol=96;
				hgrid=1;
			}
			if(!(tx&1))
			{
				vcol=96;
				vgrid=1;
			}
		}
		if(SpeedButtonGridBlock->Down)
		{
			if(!(ty&3))
			{
				hcol=128;
				hgrid=1;
			}
			if(!(tx&3))
			{
				vcol=128;
				vgrid=1;
			}
		}
	}

	if(hgrid)
	{
		d1=(unsigned char*)pic->Bitmap->ScanLine[y]+x*3;
		for(j=0;j<16;j+=hgrid)
		{
			*d1+++=hcol;
			*d1+++=hcol;
			*d1+++=hcol;
			if(hgrid>1) d1+=(hgrid-1)*3;
		}
	}

	if(vgrid)
	{
		for(j=1;j<16;j+=vgrid)
		{
			d1=(unsigned char*)pic->Bitmap->ScanLine[y+j]+x*3;
			*d1+++=vcol;
			*d1+++=vcol;
			*d1+++=vcol;
		}
		*d1=*d1;//to prevent warning
	}
}



void __fastcall TFormMain::DrawTileChecker(TPicture *pic,int x,int y,int tile,int pal,int tx,int ty,bool sel)
{
	const unsigned char checker[16]={
		0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
		0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff
	};
	int j,k,col,r,g,b;
	unsigned char *d1,*d2;
	int hgrid,vgrid,hcol,vcol;

	if(chrSelectRect) sel=false;

	for(j=0;j<8;j++)
	{
		d1=(unsigned char*)pic->Bitmap->ScanLine[y+j*2]+x*3;
		d2=(unsigned char*)pic->Bitmap->ScanLine[y+j*2+1]+x*3;
		for(k=0;k<8;k++)
		{
			col=(((checker[j]<<k)&128)>>7)|(((checker[j+8]<<k)&128)>>6);
			col=palette[bgPal[pal][col]];
			r=(col>>16)&0xff;
			g=(col>>8)&0xff;
			b=col&0xff;
			if(sel)
			{
				r-=64;
				if(r<0) r=0;
				g+=64;
				if(g>255) g=255;
				b-=64;
				if(b<0) b=0;
			}
			*d1++=r;
			*d1++=g;
			*d1++=b;
			*d1++=r;
			*d1++=g;
			*d1++=b;
			*d2++=r;
			*d2++=g;
			*d2++=b;
			*d2++=r;
			*d2++=g;
			*d2++=b;
		}
	}

	hgrid=0;
	vgrid=0;
	hcol=64;
	vcol=64;

	if(tx<0&&ty<0)
	{
		if(SpeedButtonGridTile->Down||SpeedButtonGridAtr->Down||SpeedButtonGridBlock->Down)
		{
			hgrid=2;
			vgrid=2;
		}
	}
	else
	{
		if(SpeedButtonGridTile->Down)
		{
			hgrid=2;
			vgrid=2;
		}
		if(SpeedButtonGridAtr->Down)
		{
			if(!(ty&1))
			{
				hcol=96;
				hgrid=1;
			}
			if(!(tx&1))
			{
				vcol=96;
				vgrid=1;
			}
		}
		if(SpeedButtonGridBlock->Down)
		{
			if(!(ty&3))
			{
				hcol=128;
				hgrid=1;
			}
			if(!(tx&3))
			{
				vcol=128;
				vgrid=1;
			}
		}
	}

	if(hgrid)
	{
		d1=(unsigned char*)pic->Bitmap->ScanLine[y]+x*3;
		for(j=0;j<16;j+=hgrid)
		{
			*d1+++=hcol;
			*d1+++=hcol;
			*d1+++=hcol;
			if(hgrid>1) d1+=(hgrid-1)*3;
		}
	}

	if(vgrid)
	{
		for(j=1;j<16;j+=vgrid)
		{
			d1=(unsigned char*)pic->Bitmap->ScanLine[y+j]+x*3;
			*d1+++=vcol;
			*d1+++=vcol;
			*d1+++=vcol;
		}
		*d1=*d1;//to prevent warning
	}
}



void __fastcall TFormMain::DrawSmallTile(TPicture *pic,int x,int y,int tile,int pal,int tx,int ty)
{
	int j,k,pp,col,r,g,b;
	unsigned char *d1;
	int hgrid,vgrid,hcol,vcol;

	pp=tile*16+bankActive;

	for(j=0;j<8;j++)
	{
		d1=(unsigned char*)pic->Bitmap->ScanLine[y+j]+x*3;
		for(k=0;k<8;k++)
		{
			col=(((chr[pp+j]<<k)&128)>>7)|(((chr[pp+j+8]<<k)&128)>>6);
			col=palette[bgPal[pal][col]];
			r=(col>>16)&0xff;
			g=(col>>8)&0xff;
			b=col&0xff;
			*d1++=r;
			*d1++=g;
			*d1++=b;
		}
	}
}



void __fastcall TFormMain::DrawSelection(TImage *image,TRect rect)
{
	TRect r;

	if(rect.left>=0&&rect.top>=0)
	{
		r.left=rect.left*16;
		r.top=rect.top*16;
		r.right=rect.right*16;
		r.bottom=rect.bottom*16;

		image->Canvas->Brush->Style=bsClear;
		image->Canvas->Pen->Color=TColor(0xffffff);
		image->Canvas->Rectangle(r);
		r.left+=1;
		r.top+=1;
		r.right-=1;
		r.bottom-=1;
		image->Canvas->Pen->Color=TColor(0x000000);
		image->Canvas->Rectangle(r);
		r.left-=2;
		r.top-=2;
		r.right+=2;
		r.bottom+=2;
		image->Canvas->Pen->Color=TColor(0x000000);
		image->Canvas->Rectangle(r);
	}
}



void __fastcall TFormMain::UpdateTiles(bool updchr)
{
	int i,x,y;

	if(!Visible) return;

	x=0;
	y=0;

	for(i=0;i<256;i++)
	{
		DrawTile(ImageTiles->Picture,x,y,i,palActive,-1,-1,chrSelected[i]);
		x+=16;
		if(x>=256)
		{
			x=0;
			y+=16;
		}
	}

	if(chrSelectRect) DrawSelection(ImageTiles,chrSelection);

	ImageTiles->Repaint();
	if(updchr) FormCHREditor->PaintBoxChr->Repaint();
}



void __fastcall TFormMain::UpdateNameTable(int tx,int ty)
{
	int i,j,x,y;

	if(!Visible) return;

	if(tx<0||ty<0)
	{
		y=0;

		for(i=0;i<30;i++)
		{
			x=0;
			for(j=0;j<32;j++)
			{
				if(SpeedButtonChecker->Down)
				{
					DrawTileChecker(ImageName->Picture,x,y,nameTable[i*32+j],attr_get(j,i),j,i,false);
				}
				else
				{
					DrawTile(ImageName->Picture,x,y,nameTable[i*32+j],attr_get(j,i),j,i,false);
				}

				x+=16;
			}
			y+=16;
		}
	}
	else
	{
		tx&=~1;
		ty&=~1;
		y=ty*16;

		for(i=0;i<2;i++)
		{
			x=tx*16;
			for(j=0;j<2;j++)
			{
				if(SpeedButtonChecker->Down)
				{
					DrawTileChecker(ImageName->Picture,x,y,nameTable[(ty+i)*32+tx+j],attr_get(tx+j,ty+i),tx+j,ty+i,false);
				}
				else
				{
					DrawTile(ImageName->Picture,x,y,nameTable[(ty+i)*32+tx+j],attr_get(tx+j,ty+i),tx+j,ty+i,false);
				}

				x+=16;
			}
			y+=16;
		}
	}

	DrawSelection(ImageName,nameSelection);

	ImageName->Repaint();
}



void __fastcall TFormMain::CopyCHR(bool copy,bool cut)
{
	int i,j,k,pp,ps,x,y,w,h;

	if(chrSelectRect)
	{
		GetSelection(chrSelection,x,y,w,h);
		if(w&&h&&cut) SetUndo();

		pp=0;

		for(i=0;i<h;i++)
		{
			for(j=0;j<w;j++)
			{
				for(k=0;k<16;k++)
				{
					ps=bankActive+(x+j)*16+(y+i)*256+k;
					if(copy) chrCopy[pp++]=chr[ps];
					if(cut) chr[ps]=0;
				}
			}
		}

		if(copy)
		{
			chrCopyWidth=w;
			chrCopyHeight=h;
			chrCopyRect=true;
		}
	}
	else
	{
		if(cut) SetUndo();

		pp=0;
		w=0;
		h=-1;

		for(i=0;i<256;i++)
		{
			if(chrSelected[i])
			{
				for(j=0;j<16;j++)
				{
					ps=bankActive+i*16+j;
					if(copy) chrCopy[pp++]=chr[ps];
					if(cut) chr[ps]=0;
				}
				w++;
			}
		}

		if(copy)
		{
			chrCopyWidth=w;
			chrCopyHeight=h;
			chrCopyRect=false;
		}
	}

	if(cut)
	{
		UpdateTiles(true);
		UpdateNameTable(-1,-1);
	}
}



void __fastcall TFormMain::PasteCHR(void)
{
	int i,j,k,pp,pd,x,y,w,h;

	if(chrCopyRect)
	{
		if(chrCopyWidth<1||chrCopyHeight<1) return;

		GetSelection(chrSelection,x,y,w,h);
		SetUndo();

		pp=0;

		for(i=0;i<chrCopyHeight;i++)
		{
			for(j=0;j<chrCopyWidth;j++)
			{
				if(x+j<16&&y+i<16)
				{
					for(k=0;k<16;k++)
					{
						pd=bankActive+(x+j)*16+(y+i)*256+k;
						chr[pd]=chrCopy[pp+k];
					}
				}
				pp+=16;
			}
		}
	}
	else
	{
		if(chrCopyWidth<1) return;

		pp=0;
		pd=tileActive*16;

		for(i=0;i<chrCopyWidth;i++)
		{
			pd=bankActive+(pd&0x0fff);
			for(j=0;j<16;j++)
			{
				chr[pd++]=chrCopy[pp++];
			}
		}
	}

	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::NameTableScrollLeft(bool all)
{
	unsigned char temp[32];
	int i,j,k;

	for(k=0;k<(all?2:1);k++)
	{
		for(i=0;i<30;i++) temp[i]=nameTable[i*32];

		for(i=0;i<31;i++)
		{
			for(j=0;j<30;j++)
			{
				nameTable[j*32+i]=nameTable[j*32+i+1];
			}
		}

		for(i=0;i<30;i++) nameTable[i*32+31]=temp[i];
	}

	if(all)
	{
		for(i=0;i<16;i++) temp[i]=attr_get(0,i*2);

		for(i=0;i<15;i++)
		{
			for(j=0;j<16;j++)
			{
				attr_set(i*2,j*2,attr_get(i*2+2,j*2));
			}
		}

		for(i=0;i<16;i++) attr_set(30,i*2,temp[i]);
	}

	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::NameTableScrollRight(bool all)
{
	unsigned char temp[32];
	int i,j,k;

	for(k=0;k<(all?2:1);k++)
	{
		for(i=0;i<30;i++) temp[i]=nameTable[i*32+31];

		for(i=31;i>0;i--)
		{
			for(j=0;j<30;j++)
			{
				nameTable[j*32+i]=nameTable[j*32+i-1];
			}
		}

		for(i=0;i<30;i++) nameTable[i*32]=temp[i];
	}

	if(all)
	{
		for(i=0;i<16;i++) temp[i]=attr_get(30,i*2);

		for(i=15;i>0;i--)
		{
			for(j=0;j<16;j++)
			{
				attr_set(i*2,j*2,attr_get(i*2-2,j*2));
			}
		}

		for(i=0;i<16;i++) attr_set(0,i*2,temp[i]);
	}

	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::NameTableScrollUp(bool all)
{
	unsigned char temp[32];
	int i,j,k;

	for(k=0;k<(all?2:1);k++)
	{
		for(i=0;i<32;i++) temp[i]=nameTable[i];

		for(i=0;i<29;i++)
		{
			for(j=0;j<32;j++)
			{
				nameTable[i*32+j]=nameTable[(i+1)*32+j];
			}
		}

		for(i=0;i<32;i++) nameTable[960-32+i]=temp[i];
	}

	if(all)
	{
		for(i=0;i<16;i++) temp[i]=attr_get(i*2,0);

		for(i=0;i<14;i++)
		{
			for(j=0;j<16;j++)
			{
				attr_set(j*2,i*2,attr_get(j*2,i*2+2));
			}
		}

		for(i=0;i<16;i++) attr_set(i*2,28,temp[i]);
	}

	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::NameTableScrollDown(bool all)
{
	unsigned char temp[32];
	int i,j,k;

	for(k=0;k<(all?2:1);k++)
	{
		for(i=0;i<32;i++) temp[i]=nameTable[960-32+i];

		for(i=29;i>0;i--)
		{
			for(j=0;j<32;j++)
			{
				nameTable[i*32+j]=nameTable[(i-1)*32+j];
			}
		}

		for(i=0;i<32;i++) nameTable[i]=temp[i];
	}

	if(all)
	{
		for(i=0;i<16;i++) temp[i]=attr_get(i*2,28);

		for(i=14;i>0;i--)
		{
			for(j=0;j<16;j++)
			{
				attr_set(j*2,i*2,attr_get(j*2,i*2-2));
			}
		}

		for(i=0;i<16;i++) attr_set(i*2,0,temp[i]);
	}

	UpdateNameTable(-1,-1);
}



bool __fastcall TFormMain::OpenCHR(AnsiString name)
{
	unsigned char buf[4096];
	FILE *file;
	int i,pp,size,type;

	file=fopen(name.c_str(),"rb");

	type=-1;

	if(file)
	{
		size=get_file_size(file);

		switch(size)
		{
		case 8192:
			fread(chr,8192,1,file);
			type=4;
			break;

		case 4096:
			fread(chr+bankActive,4096,1,file);
			type=3;
			break;

		default:
			if(size<4096&&!(size&15))
			{
				fread(buf,size,1,file);
				pp=tileActive*16;
				for(i=0;i<size;i++)
				{
					chr[bankActive+pp++]=buf[i];
					if(pp>=4096) pp=0;
				}
				if(size==2048) type=2;
				if(size==1024) type=1;
			}
			else
			{
				Application->MessageBox("Wrong file size","Error",MB_OK);
				fclose(file);
				return false;
			}
		}
	}

	fclose(file);

	if(type<0) return false;

	SaveDialogChr->FilterIndex=type;
	UpdateTiles(true);
	UpdateNameTable(-1,-1);

	return true;
}



void __fastcall TFormMain::InterleaveCHR(bool dir)
{
	unsigned char buf[4096];
	int table[256];
	int i,j,pp,pd,num;

	SetUndo();

	for(i=0;i<16;i++)
	{
		num=(i/2)*32+(i&1);
		for(j=0;j<16;j++)
		{
			if(dir) table[i*16+j]=num; else table[num]=i*16+j;
			num+=2;
		}
	}

	pp=0;

	for(i=0;i<256;i++)
	{
		pd=table[i]*16;
		for(j=0;j<16;j++)
		{
			buf[pd++]=chr[pp++];
		}
	}

	memcpy(chr,buf,4096);

	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}



bool __fastcall TFormMain::OpenNameTable(AnsiString name)
{
	FILE *file;
	int size;
	unsigned char src[2048],dst[1024];
	int i,tag,pp,pd;
	AnsiString ext;

	ext=GetExt(name);

	file=fopen(name.c_str(),"rb");

	if(file)
	{
		if(ext!="rle")
		{
			size=get_file_size(file);
			if(size== 1920)
			{
				fread(nameTable,960,1,file);
				fread(attrTable,960,1,file);
				fclose(file);
				UpdateNameTable(-1,-1);
				return true;
			}
			else
			{
				Application->MessageBox("nameTable should be 1920 bytes long","Error",MB_OK);
			}
		}
		else
		{
			size=get_file_size(file);

			if(size<2048)
			{
				fread(src,size,1,file);
				fclose(file);

				tag=src[0];
				pp=1;
				pd=0;

				while(pp<size)
				{
					if(src[pp]==tag)
					{
						pp++;
						if(src[pp]==0) break;
						for(i=0;i<src[pp];i++) dst[pd++]=dst[pd-1];
						pp++;
					}
					else
					{
						dst[pd++]=src[pp++];
					}
				}
			}

			if(pd==959||pd==1023) pd++;//for old files saved when RLE packer had bug
			if(pd==960||pd==1024) memcpy(nameTable,dst,960);
			if(pd==1024) memcpy(attrTable,dst+960,960);
			if(pd!=960&&pd!=1024) Application->MessageBox("Can't decode RLE","Error",MB_OK);

			UpdateNameTable(-1,-1);
			return true;
		}
	}

	return false;
}



bool __fastcall TFormMain::OpenPalette(AnsiString name)
{
	FILE *file;
	unsigned char pal[16];
	int i;

	file=fopen(name.c_str(),"rb");
	
	if(file)
	{
		if(get_file_size(file)==16)
		{
			fread(pal,16,1,file);
			fclose(file);
			for(i=0;i<4;i++)
			{
				bgPal[0][i]=pal[i];
				bgPal[1][i]=pal[i+4];
				bgPal[2][i]=pal[i+8];
				bgPal[3][i]=pal[i+12];
			}
			pal_validate();
			DrawPalettes();
			UpdateTiles(true);
			UpdateNameTable(-1,-1);
			return true;
		}
		else
		{
			Application->MessageBox("Palette file should be 16 bytes long","Error",MB_OK);
		}
	}

	return false;
}



void __fastcall TFormMain::GetSelection(TRect r,int &x,int &y,int &w,int &h)
{
	if(r.left<r.right)
	{
		x=r.left;
		w=r.right-x;
	}
	else
	{
		x=r.right;
		w=r.left-x;
	}
	if(r.top<r.bottom)
	{
		y=r.top;
		h=r.bottom-y;
	}
	else
	{
		y=r.bottom;
		h=r.top-y;
	}
}



void __fastcall TFormMain::CopyMap(bool cut)
{
	int i,j,x,y,w,h,pp;

	GetSelection(nameSelection,x,y,w,h);
	if(w&&h&&cut) SetUndo();

	pp=0;

	for(i=0;i<h;i++)
	{
		for(j=0;j<w;j++)
		{
			nameCopy[pp]=nameTable[y*32+x+j];
			attrCopy[pp]=attr_get(x+j,y);
			if(cut&&SpeedButtonTiles->Down) nameTable[y*32+x+j]=0;
			pp++;
		}
		y++;
	}

	nameCopyWidth=w;
	nameCopyHeight=h;

	if(cut) UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::CopyMapCodeASM(void)
{
	char str[65536],buf[1024];
	int i,j,x,y,w,h;

	if(nameSelection.left>=0&&nameSelection.top>=0)
	{
		GetSelection(nameSelection,x,y,w,h);

		strcpy(str,"");

		for(i=0;i<h;i++)
		{
			strcat(str,"\t.db ");
			for(j=0;j<w;j++)
			{
				sprintf(buf,"$%2.2x%c",nameTable[(y+i)*32+x+j],j<w-1?',':'\n');
				strcat(str,buf);
			}
		}

		Clipboard()->SetTextBuf(str);
	}
}



void __fastcall TFormMain::CopyMapCodeC(void)
{
	char str[65536],buf[1024];
	int i,j,x,y,w,h;

	if(nameSelection.left>=0&&nameSelection.top>=0)
	{
		GetSelection(nameSelection,x,y,w,h);

		sprintf(str,"const unsigned char nametable[%i*%i]={\n",w,h);

		for(i=0;i<h;i++)
		{
			strcat(str,"\t");
			for(j=0;j<w;j++)
			{
				sprintf(buf,"0x%2.2x%c",nameTable[(y+i)*32+x+j],j<w-1?',':'\n');
				strcat(str,buf);
			}
		}

		strcat(str,"};\n");

		Clipboard()->SetTextBuf(str);
	}
}



void __fastcall TFormMain::CopyMetaSpriteCodeC(bool hflip)
{
	char str[65536],buf[1024];
	int i,j,x,y,w,h;

	if(nameSelection.left>=0&&nameSelection.top>=0)
	{
		GetSelection(nameSelection,x,y,w,h);

		sprintf(str,"const unsigned char metasprite[]={\n");

		if(!hflip)
		{
			for(i=0;i<h;i++)
			{
				for(j=0;j<w;j++)
				{
					sprintf(buf,"%i,%i,0x%2.2x,%i,\n",j*8,i*8,nameTable[(y+i)*32+x+j],attr_get(x+j,y+i));
					strcat(str,buf);
				}
			}
		}
		else
		{
			for(i=0;i<h;i++)
			{
				for(j=0;j<w;j++)
				{
					sprintf(buf,"%i,%i,0x%2.2x,%i|OAM_FLIP_H,\n",j*8,i*8,nameTable[(y+i)*32+x+(w-1-j)],attr_get(x+(w-1-j),y+i));
					strcat(str,buf);
				}
			}
		}

		strcat(str,"128\n};\n");

		Clipboard()->SetTextBuf(str);
	}
}



void __fastcall TFormMain::PasteMap(void)
{
	int i,j,x,y,w,h,pp;

	if(nameCopyHeight<1||nameCopyWidth<1) return;

	GetSelection(nameSelection,x,y,w,h);
	if(w&&h) SetUndo();

	pp=0;

	for(i=0;i<nameCopyHeight;i++)
	{
		for(j=0;j<nameCopyWidth;j++)
		{
			if(x+j<32&&y<30)
			{
				if(SpeedButtonTiles->Down) nameTable[y*32+x+j]=nameCopy[pp];
				if(SpeedButtonPal->Down) attr_set(x+j,y,attrCopy[pp]);
			}
			pp++;
		}
		y++;
	}

	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::FillMap(void)
{
	int i,j,x,y,w,h;

	GetSelection(nameSelection,x,y,w,h);
	if(w&&h) SetUndo();

	for(i=0;i<h;i++)
	{
		for(j=0;j<w;j++)
		{
			if(SpeedButtonTiles->Down) nameTable[y*32+x+j]=tileActive;
		}
		y++;
	}

	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::OpenAll(AnsiString name)
{
	name=RemoveExt(name);

	if(OpenCHR(name+".chr"))
	{
		SaveDialogChr->FileName=name;
	}
	else
	{
		if(OpenCHR(name+".bin")) SaveDialogChr->FileName=name;
	}

	if(OpenNameTable(name+".snam"))
	{
		SaveDialogName->FileName=name;
	}
	else
	{
		if(OpenNameTable(name+".rle"))
		{
			SaveDialogName->FileName=name;
		}
	}

	if(OpenPalette(name+".pal"))
	{
		SaveDialogPal->FileName=name;
	}
}



void __fastcall TFormMain::UpdateStats(void)
{
	AnsiString str;
	int i,cnt,tile,off,col;

	if(tileXC>=0&&tileYC>=0)
	{
		tile=tileYC*16+tileXC;
		cnt=0;

		for(i=0;i<960;i++) if(nameTable[i]==tile) cnt++;

		LabelStats->Caption="Tile:$"+IntToHex(tile,2)+" ("+IntToStr(cnt)+" entries)";
	}

	if(nameXC>=0&&nameYC>=0)
	{
		off=nameYC*32+nameXC;
		str="X:"+IntToStr(nameXC)+" Y:"+IntToStr(nameYC)+" Off:$"+IntToHex(off,3)+" Tile:$"+IntToHex(nameTable[off],2);
		str+=" AtrX:"+IntToStr(nameXC/2)+" AtrY:"+IntToStr(nameYC/2)+" AtrOff:$"+IntToHex(nameYC/4*8+nameXC/4+960,3)+"."+IntToStr((nameXC&2)+(nameYC&2)*2)+" Atr:$"+IntToHex(attrTable[nameYC/4*8+nameXC/4],2)+" Pal:"+IntToStr(attr_get(nameXC,nameYC));
		if(nameSelection.left>=0) str+=" W:"+IntToStr(nameSelection.right-nameSelection.left)+" H:"+IntToStr(nameSelection.bottom-nameSelection.top);
		LabelStats->Caption=str;
	}

	if(palHover>=0) LabelStats->Caption="Pal:"+IntToStr(palHover)+" Entry:"+IntToStr(palColHover)+" Adr:"+IntToHex(0x3f00+palHover*4+palColHover,4)+" Color:$"+IntToHex(bgPal[palHover][palColHover],2);

	if(colHover>=0)
	{
		col=colHover;
		if(col==0x0d||col==0x1d) col=0x0f;
		LabelStats->Caption="Color:$"+IntToHex(col,2);
	}

	if(tileXC<0&&tileYC<0&&nameXC<0&&nameYC<0&&palHover<0&&palColHover<0&&colHover<0) LabelStats->Caption="---";
}



void __fastcall TFormMain::SetUndo(void)
{
	memcpy(undoChr,chr,8192);
	memcpy(undoNameTable,nameTable,960);
	memcpy(undoAttrTable,attrTable,960);
}



void __fastcall TFormMain::Undo(void)
{
	mem_exchange(undoChr,chr,8192);
	mem_exchange(undoNameTable,nameTable,960);
	mem_exchange(undoAttrTable,attrTable,960);

	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}



void __fastcall TFormMain::SetTile(int tile)
{
	int i;

	tileActive=tile;
	chrSelection.left=tile&15;
	chrSelection.top=tile/16;
	chrSelection.right=chrSelection.left+1;
	chrSelection.bottom=chrSelection.top+1;

	for(i=0;i<256;i++) chrSelected[i]=false;
	chrSelected[tile]=true;
	chrSelectRect=true;

	UpdateTiles(true);
}



//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormPaint(TObject *Sender)
{
	DrawPalettes();
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormCreate(TObject *Sender)
{
	FILE *file;
	int i,pp;
	unsigned char buf[192];
	AnsiString dir;

	bgPalCur=0;
	palActive=0;
	tileActive=0;
	//bankActive=4096;
	bankActive=0;

	for(i=0;i<960;i++)  nameTable[i]=0;
	for(i=0;i<960;i++)   attrTable[i]=0;
	for(i=0;i<8192;i++) chr[i]=0;
	for(i=0;i<4096;i++) chrCopy[i]=0;

	dir=ParamStr(0).SubString(0,ParamStr(0).LastDelimiter("\\/"));

	file=fopen((dir+"nes.pal").c_str(),"rb");
	if(file)
	{
		if(get_file_size(file)==192)
		{
			fread(buf,192,1,file);
			fclose(file);

			pp=0;
			for(i=0;i<64;i++)
			{
				basePalette[i]=(buf[pp+2]<<16)|(buf[pp+1]<<8)|buf[pp];
				pp+=3;
			}
		}
	}

	ppuMask=0;
	palette_calc();

	nameSelection.left=-1;
	nameSelection.top=-1;
	nameCopyWidth=-1;
	nameCopyHeight=-1;

	chrSelection.left=0;
	chrSelection.right=0;
	chrSelection.right=1;
	chrSelection.bottom=1;
	chrCopyWidth=-1;
	chrCopyHeight=-1;
	chrCopyRect=true;
	for(i=0;i<256;i++) chrSelected[i]=false;
	chrSelected[tileActive]=true;
	chrSelectRect=true;

	tileXC=-1;
	tileYC=-1;
	nameXC=-1;
	nameYC=-1;
	palHover=-1;
	palColHover=-1;
	colHover=-1;

	dir = reg_load_str(regWorkingDirectory,"");

	//Application->MessageBox(ParamStr(1).c_str(),"Warning",MB_OK);
	//Application->MessageBox(ParamStr(2).c_str(),"Warning",MB_OK);
	//Application->MessageBox(ParamStr(3).c_str(),"Warning",MB_OK);
	//Application->MessageBox(ParamStr(4).c_str(),"Warning",MB_OK);

	g_EditorMode = atol(ParamStr(1).c_str());


	switch (g_EditorMode)
	{
		case EDITOR_BG_MODE:
		break;

		case EDITOR_SPR_MODE:
		OpenAll(ParamStr(2));
		OpenAll(ParamStr(3));
		OpenAll(ParamStr(4));
		dir = ParamStr(5);
		SetCurrentDirectory(dir.c_str());
		break;


		default:
		break;
	}

   /*	if(ParamStr(1)!="")
	{
		OpenAll(ParamStr(1));
		dir=ParamStr(1);
	}

	if(ParamStr(2)!="")
	{
		OpenAll(ParamStr(2));
	}

	if(ParamStr(3)!="")
	{
		OpenAll(ParamStr(3));
	}  */

  /*	if(ParamStr(4)!="")
	{
	  dir=ParamStr(4);
	  SetCurrentDirectory(dir.c_str());
	}

	GroupBox1->SetTextBuf("Test");  */

	
	//SetCurrentDirectory(dir.c_str());

	SetUndo();

		// open a test chr file
	//if(OpenCHR("c:\\chr\\poong.chr")) SaveDialogChr->FileName=OpenDialogChr->FileName;

	//bankActive=4096;

   //	UpdateTiles(true);
   //	UpdateNameTable(-1,-1);

}
//---------------------------------------------------------------------------

void __fastcall TFormMain::PaintBoxPalMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
	int i,x,y,col;

	y=0;
	x=16;

	for(i=0;i<4;i++)
	{
		if(Y>=y&&Y<y+20)
		{
			if(X>=x   &&X<x+20)
			{
				bgPalCur=0;
				palActive=i;
			}
			if(X>=x+20&&X<x+40)
			{
				bgPalCur=1;
				palActive=i;
			}
			if(X>=x+40&&X<x+60)
			{
				bgPalCur=2;
				palActive=i;
			}
			if(X>=x+60&&X<x+80)
			{
				bgPalCur=3;
				palActive=i;
			}
		}
		x+=128-16;
		if(x>128)
		{
			x=16;
			y=32;
		}
	}

	if(X>=0&&X<14*16&&Y>=64&&Y<64+4*16)
	{
		bgPal[palActive][bgPalCur]=X/16+(Y-64)/16*16;
		col=bgPal[palActive][0];
		bgPal[0][0]=col;
		bgPal[1][0]=col;
		bgPal[2][0]=col;
		bgPal[3][0]=col;
	}

	pal_validate();
	DrawPalettes();
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::ImageTilesMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
	int i;

	if(X>=0&&X<256&&Y>=0&&Y<256)
	{
		if(Shift.Contains(ssCtrl)&&(Shift.Contains(ssLeft)||Shift.Contains(ssRight)))
		{
			chrSelected[Y/16*16+X/16]=Shift.Contains(ssLeft);
			chrSelectRect=false;
		}
		else
		{
			tileActive=Y/16*16+X/16;
			chrSelection.left=X/16;
			chrSelection.top=Y/16;

			chrSelection.right=chrSelection.left+1;
			chrSelection.bottom=chrSelection.top+1;

			for(i=0;i<256;i++) chrSelected[i]=false;
			chrSelected[tileActive]=true;

			chrSelectRect=true;
		}

		nameSelection.left=-1;
		nameSelection.top=-1;

		UpdateTiles(true);
		UpdateNameTable(-1,-1);
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonGridAllClick(TObject *Sender)
{
	if(((TSpeedButton*)Sender)->GroupIndex==10)
	{
		SpeedButtonGridTile->Down=SpeedButtonGridAll->Down;
		SpeedButtonGridAtr->Down=SpeedButtonGridAll->Down;
		SpeedButtonGridBlock->Down=SpeedButtonGridAll->Down;
	}
	if(!SpeedButtonGridTile->Down||!SpeedButtonGridAtr->Down||!SpeedButtonGridBlock->Down) SpeedButtonGridAll->Down=false;
	if(SpeedButtonGridTile->Down&&SpeedButtonGridAtr->Down&&SpeedButtonGridBlock->Down) SpeedButtonGridAll->Down=true;

	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MOpenCHRClick(TObject *Sender)
{
	if(OpenDialogChr->Execute())
	{
		if(OpenCHR(OpenDialogChr->FileName)) SaveDialogChr->FileName=OpenDialogChr->FileName;
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::PaintBoxNamePaint(TObject *Sender)
{
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ImageNameMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
	int i;

	if (Button == mbRight)
	{
	 // right button pressed, show contextmenue
	 TPoint LeftTop;
	 LeftTop.x = 0;
	 LeftTop.y = 0;
	 TPoint P = ImageName->ClientToScreen(LeftTop);
	 PopupMenu1->Popup(P.x + X, P.y + Y);
	 return;
	}

	if(X>=0&&X<512&&Y>=0&&Y<480)
	{
				//tileActive=Y/16*16+X/16;
		//tileActive=nameTable[Y/16*16+X/16];
		  //nameTable
		if((Shift.Contains(ssShift)||GetKeyState(VK_CAPITAL))&&Shift.Contains(ssLeft))
		{
			nameSelection.left=X/16;
			nameSelection.top=Y/16;
			nameSelection.right=nameSelection.left+1;
			nameSelection.bottom=nameSelection.top+1;
			UpdateNameTable(-1,-1);

			chrSelection.right=chrSelection.left+1;
			chrSelection.bottom=chrSelection.top+1;

			for(i=0;i<256;i++) chrSelected[i]=false;
			chrSelected[tileActive]=true;
			chrSelectRect=true;

			UpdateTiles(true);
		}
		else
		{
			if(Shift.Contains(ssLeft)) SetUndo();
			ImageNameMouseMove(Sender,Shift,X,Y);

			if(nameSelection.left>=0||nameSelection.top>=0)
			{
				nameSelection.left=-1;
				nameSelection.top=-1;
				UpdateNameTable(-1,-1);
			}
		}
	}

	UpdateStats();
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::ImageNameMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
	int i,tx,ty;

	if(X>=0&&X<512&&Y>=0&&Y<480)
	{
		tx=X/16;
		ty=Y/16;
		nameXC=tx;
		nameYC=ty;

		if(Shift.Contains(ssShift)||GetKeyState(VK_CAPITAL))
		{
			if(Shift.Contains(ssLeft))
			{
				nameSelection.right=tx+(tx>=nameSelection.left?1:0);
				nameSelection.bottom=ty+(ty>=nameSelection.top?1:0);
			}
			if(Shift.Contains(ssRight))
			{
				nameSelection.left=-1;
				nameSelection.top=-1;
			}

			UpdateNameTable(-1,-1);
		}
		else
		{
			if(Shift.Contains(ssLeft))
			{
				if(SpeedButtonTiles->Down) nameTable[ty*32+tx]=tileActive;
				if(SpeedButtonPal->Down) attr_set(tx,ty,palActive);
				UpdateNameTable(tx,ty);
			}

			if(Shift.Contains(ssRight))
			{
				tileActive=nameTable[ty*32+tx];
				chrSelection.left=tileActive&15;
				chrSelection.top=tileActive/16;
				chrSelection.right=chrSelection.left+1;
				chrSelection.bottom=chrSelection.top+1;

				for(i=0;i<256;i++) chrSelected[i]=false;
				chrSelected[tileActive]=true;

				palActive=attr_get(tx,ty);
				UpdateTiles(true);
				DrawPalettes();
			}
		}
	}
	else
	{
		nameXC=-1;
		nameYC=-1;
	}

	UpdateStats();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MOpenNameTableClick(TObject *Sender)
{
	if(OpenDialogName->Execute())
	{
		if(OpenNameTable(OpenDialogName->FileName)) SaveDialogName->FileName=OpenDialogName->FileName;
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MSaveNameTableOnlyClick(TObject *Sender)
{
	AnsiString name;

	SaveDialogName->FileName=RemoveExt(SaveDialogName->FileName);

	if(SaveDialogName->Execute())
	{
		name=RemoveExt(SaveDialogName->FileName);

		switch(SaveDialogName->FilterIndex)
		{
		case 2:  name+=".bin"; break;
		case 3:  name+=".rle"; break;
		case 4:  name+=".h"; break;
		default: name+=".nam";
		}

		if(FileExists(name))
		{
			if(Application->MessageBox(("File "+name+" already exists, overwrite?").c_str(),"Confirm",MB_YESNO)!=IDYES) return;
		}

		save_data(name.c_str(),nameTable,960,SaveDialogName->FilterIndex);
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MSaveNameTableAttributesClick(TObject *Sender)
{
	/*unsigned char buf[1920];
	AnsiString name;

	SaveDialogName->FileName=RemoveExt(SaveDialogName->FileName);

	if(SaveDialogName->Execute())
	{
		name=RemoveExt(SaveDialogName->FileName);

		switch(SaveDialogName->FilterIndex)
		{
		case 2: name+=".bin"; break;
		case 3: name+=".rle"; break;
		case 4: name+=".h"; break;
		default: name+=".nam";
		}

		memcpy(buf,nameTable,960);
		memcpy(buf+960,attrTable,960);

		if(FileExists(name))
		{
			if(Application->MessageBox(("File "+name+" already exists, overwrite?").c_str(),"Confirm",MB_YESNO)!=IDYES) return;
		}

		save_data(name.c_str(),nameTable,1920,SaveDialogName->FilterIndex);
	} */

	unsigned char buf[1024];
	AnsiString name;

	if(SaveDialogName->Execute())
	{
		name=SaveDialogName->FileName;
		name=name.Delete(name.LastDelimiter("."),name.Length());

		switch(SaveDialogName->FilterIndex)
		{
		case 2: name+=".bin"; break;
		case 3: name+=".rle"; break;
		case 4: name+=".h"; break;
		default: name+=".nam";
		}

		memcpy(buf,nameTable,960);
		memcpy(buf+960,attrTable,64);

		save_data(name.c_str(),nameTable,1024,SaveDialogName->FilterIndex);
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MOpenPalettesClick(TObject *Sender)
{
	if(OpenDialogPal->Execute())
	{
		if(OpenPalette(OpenDialogPal->FileName)) SaveDialogPal->FileName=OpenDialogPal->FileName;
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MSavePalettesClick(TObject *Sender)
{
	if(SaveDialogPal->Execute())
	{
	  savePal(SaveDialogPal->FileName.c_str());
	}
}

//---------------------------------------------------------------------------

void __fastcall TFormMain::savePal(char *pFileName)
{
	int i = 0;
	unsigned char pal[16];
	FILE *file = NULL;
	pal_validate();

	for(i=0;i<4;i++)
	{
	  pal[i]=bgPal[0][i];
	  pal[i+4]=bgPal[1][i];
	  pal[i+8]=bgPal[2][i];
	  pal[i+12]=bgPal[3][i];
	}

	file=fopen(pFileName , "wb");
	if(file)
	{
	  fwrite(pal,16,1,file);
	  fclose(file);
	}
}

//---------------------------------------------------------------------------

void __fastcall TFormMain::MPutCodeToClipboardClick(TObject *Sender)
{
	char str[1024],buf[1024];
	int i,j;

	pal_validate();

	sprintf(str,"\tlda #$3f\n\tsta $2006\n\tlda #$00\n\tsta $2006\n\tldx #$%2.2x\n\tstx $2007\n",bgPal[0][0]);

	for(i=0;i<4;i++)
	{
		if(i) strcat(str,"\tstx $2007\n");
		for(j=1;j<4;j++)
		{
			sprintf(buf,"\tlda #$%2.2x\n\tsta $2007\n",bgPal[i][j]);
			strcat(str,buf);
		}
	}

	Clipboard()->SetTextBuf(str);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::PaintBoxPalPaint(TObject *Sender)
{
	DrawPalettes();
}
//---------------------------------------------------------------------------



void __fastcall TFormMain::MCHREditorClick(TObject *Sender)
{
	FormCHREditor->Visible^=true;
}
//---------------------------------------------------------------------------
	/*
void __fastcall TFormMain::GetBlockColors(TObject *Sender)
{
	BYTE colorTable[256];

	memset(colorTable,0,sizeof(colorTable));
				memset(chrt,0,4096);
				memset(namet,0,960);
				ptr=0;
				cnt=0;

	for (int y = 0; y < 8;y++)
	{
	  BYTE *pBitmapScanline = (BYTE*) BmpMercedes->ScanLine[y];
	  for (int x = 0; x < 8; x++)
	  {
		colorTable[pBitmapScanline[x]]++;
	  }
	}
	// count colors for 8x8 tile
	int usedColors = 0;
	int transColorIndex = -1;

	for (int i = 0; i < 256; i++)
	{
		byte colorCount = colorTable[i];
		if (colorCount > 0)
		{
			if (palEntry[i].peRed   != 255 &&
				palEntry[i].peGreen != 0   &&
				palEntry[i].peBlue  != 255)
			{
			  usedColors++;
			}
			else
			{
			  // found transparent color
			  transColorIndex = i;
			  Application->MessageBox(IntToStr(i).c_str(),"Warning",MB_OK);

			}
		}
	}
}
	*/



  /*
	typedef struct {
   unsigned char r, g, b;
} RGB;

double ColourDistance(RGB e1, RGB e2)
{
  long rmean = ( (long)e1.r + (long)e2.r ) / 2;
  long r = (long)e1.r - (long)e2.r;
  long g = (long)e1.g - (long)e2.g;
  long b = (long)e1.b - (long)e2.b;
  return sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
}   */

int __fastcall TFormMain::FindBestPalMatch(PALETTEENTRY *pPalEntry)
 {
	BYTE    r2 = pPalEntry->peRed;
	BYTE    g2 = pPalEntry->peGreen;
	BYTE    b2 = pPalEntry->peBlue;

	int bestIndex = -1;
	double colorDist = 0;

	for (int i = 0; i < 64; i++)
	{
		TColor color = TColor(palette[i]);
		BYTE	b1=(color>>16)&0xff;
		BYTE	g1=(color>>8)&0xff;
		BYTE	r1=color&0xff;

		long rmean = ( ((long) r1 - (long) r2) ) / 2;

		long r = ((long) r1 - (long) r2) ;
		long g = ((long) g1 - (long) g2);
		long b = ((long) b1 - (long) b2);


		double dist = sqrt(sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8)));

		if ((dist) < colorDist || bestIndex == -1)
		{
		 colorDist = dist;
		 bestIndex = i;
		}
	 }
	 return bestIndex;
 }


 int __fastcall TFormMain::FindBestSubPalMatch(int subPalnr ,
												PALETTEENTRY *pPalEntry)
 {
	BYTE    r2 = pPalEntry->peRed;
	BYTE    g2 = pPalEntry->peGreen;
	BYTE    b2 = pPalEntry->peBlue;

	int bestIndex = -1;
	double colorDist = 0;

	for (int i = 1; i < 4; i++)
	{
		TColor color = TColor(bgPal[subPalnr][i]);
		BYTE	b1=(color>>16)&0xff;
		BYTE	g1=(color>>8)&0xff;
		BYTE	r1=color&0xff;


		long rmean = ( ((long) r1 - (long) r2) ) / 2;

		long r = ((long) r1 - (long) r2) ;
		long g = ((long) g1 - (long) g2);
		long b = ((long) b1 - (long) b2);

		double dist = sqrt(sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8)));

		if ((dist < colorDist) || bestIndex == -1)
		{
		 colorDist = dist;
		 bestIndex = i;
		}
	 }
	 return bestIndex;
 }


 /*void  __fastcall::GenerateChrTile(int xPos , int yPos , BYTE *pTile , TBitmap *pBitmap)
 {
   memset(pTile,0,16);
   int	pp=0;
	for (int y = 0; y < 8;y++)
	{
	  BYTE *pBitmapScanline = (BYTE*) pBitmap->ScanLine[y];
	  for (int x = 0; x < 8; x++)
	  {
		if (pBitmapScanline[x] !=  transColorIndex)
		{

			byte colorBits = 0;

			if (pBitmapScanline[x] == color1Index)
				colorBits = 1;
			if (pBitmapScanline[x] == color2Index)
				colorBits = 2;

			if (pBitmapScanline[x] == color3Index)
				colorBits = 3;

			//Application->MessageBox(IntToStr(colorBits).c_str(),"Warning",MB_OK);

			tile[pp]|=(colorBits & 1) ?1<<(7-x):0;
			tile[pp+8]|=(colorBits & 2) ?1<<(7-x):0;
		}
	  }
		pp++;
	}  */

int __fastcall TFormMain::GetNextMostUsedColor(BYTE *pColorTable , int transColorIndex)
{
	int colorMaxIndex = -1;
	int colorMax      = 0;
	for (int i = 0; i < 256; i++)
	{
		byte colorCount = pColorTable[i];
		if (colorCount > 0 && i != transColorIndex)
			if (colorCount > colorMax) {
				   colorMax =  colorCount;
				   colorMaxIndex = i;
			}
	}
	pColorTable[colorMaxIndex] = 0;
	return colorMaxIndex;
}

// --------------------------------------------------------------------------

void __fastcall TFormMain::CountTileColors(int xTilePos,
										  int yTilePos  ,
										  Graphics::TBitmap *pBitmap,
										  unsigned char *pCountArray)
{
  for (int y = 0; y < 8;y++)
  {
	BYTE *pBitmapScanline = (BYTE*) pBitmap->ScanLine[y + (yTilePos * 8)];
	 for (int x = 0; x < 8; x++)
		  pCountArray[pBitmapScanline[x  + (xTilePos*8)]]++;
  }
}

// --------------------------------------------------------------------------

/*int __fastcall TFormMain::GenerateTile(int xTilePos,
										int yTilePos  ,
										Graphics::TBitmap *pBitmap,
										unsigned char *pTile,
										unsigned char *pSprPal)
{
  // count colors for 8x8 tile
/*  int usedColors = 0;
  int transColorIndex = -1;

  PALETTEENTRY palEntry[256];
  HPALETTE hPal = pBitmap->Palette;

  GetPaletteEntries(hPal, 0 , 256,  palEntry);

  BYTE colorTable[256];
  BYTE colorTransTable[256];

  memset(colorTable,0,256);
  memset(colorTransTable,0,256);
  memset(pTile , 0 , 16);

  for (int y = 0; y < 8;y++)
  {
	BYTE *pBitmapScanline = (BYTE*) pBitmap->ScanLine[y + (yTilePos * 8)];
	 for (int x = 0; x < 8; x++)
		  colorTable[pBitmapScanline[x  + (xTilePos*8)]]++;
  }

  for (int i = 0; i < 256; i++)
  {
	if (colorTable[i] > 0)
	{
		if ((palEntry[i].peRed   == 255) &&
			(palEntry[i].peGreen == 0)   &&
			(palEntry[i].peBlue  == 255))
		{
		   // found transparent color
		   transColorIndex = i;
		}
		else
		{
		  usedColors++;
		}
	 }
  }

  int color1Index = -1;
  int color2Index = -1;
  int color3Index = -1;

  color1Index = GetNextMostUsedColor(colorTable , transColorIndex);
  color2Index = GetNextMostUsedColor(colorTable , transColorIndex);
  color3Index = GetNextMostUsedColor(colorTable , transColorIndex);

  if (color1Index != -1)
  {
	pSprPal[0] = FindBestPalMatch(&palEntry[color1Index]);
	colorTransTable[color1Index] = 1;
  }
  if (color2Index != -1)
  {
	pSprPal[1] = FindBestPalMatch(&palEntry[color2Index]);
	colorTransTable[color2Index] = 2;
  }
  if (color3Index != -1)
  {
	pSprPal[2] = FindBestPalMatch(&palEntry[color3Index]);
	colorTransTable[color3Index] = 3;
  }

  int pp = 0;
  for (int y = 0; y < 8;y++)
  {
	BYTE *pBitmapScanline = (BYTE*) pBitmap->ScanLine[y + (yTilePos * 8)];
	for (int x = 0; x < 8; x++)
	{
	  if (pBitmapScanline[x + (xTilePos*8)] !=  transColorIndex)
	  {
		byte colorBits = colorTransTable[pBitmapScanline[x  + (xTilePos*8)]];
		pTile[pp]|=(colorBits & 1) ?1<<(7-x):0;
		pTile[pp+8]|=(colorBits & 2) ?1<<(7-x):0;
	  }
	 }
	 pp++;
   } */

 /* int pp = 0;
  for (int y = 0; y < 8;y++)
  {
	BYTE *pBitmapScanline = (BYTE*) pBitmap->ScanLine[y + (yTilePos * 8)];
	for (int x = 0; x < 8; x++)
	{
	  if (pBitmapScanline[x + (xTilePos*8)] !=  transColorIndex)
	  {
		byte colorBits = colorTransTable[pBitmapScanline[x  + (xTilePos*8)]];
		pTile[pp]|=(colorBits & 1) ?1<<(7-x):0;
		pTile[pp+8]|=(colorBits & 2) ?1<<(7-x):0;
	  }
	 }
	 pp++;
   } */

//}


int __fastcall TFormMain::GenerateTile( int xTilePos,
										int yTilePos  ,
										Graphics::TBitmap *pBitmap,
										unsigned char *pTile,
										unsigned char *pColorTable ,
										int transColorIndex)
{
  int pp = 0;
  for (int y = 0; y < 8;y++)
  {
	BYTE *pBitmapScanline = (BYTE*) pBitmap->ScanLine[y + (yTilePos * 8)];
	for (int x = 0; x < 8; x++)
	{
	  if (pBitmapScanline[x + (xTilePos*8)] !=  transColorIndex)
	  {
		byte colorBits = pColorTable[pBitmapScanline[x  + (xTilePos*8)]];
		pTile[pp]|=(colorBits & 1) ?1<<(7-x):0;
		pTile[pp+8]|=(colorBits & 2) ?1<<(7-x):0;
	  }
	 }
	 pp++;
  }
}

void __fastcall TFormMain::MImportClick(TObject *Sender)
{


	int j,k,l,size,wdt,hgt,pp = 0,ps,off,ptr,cnt,bpp;
	unsigned char tile[16];
    unsigned char sprPal[3];

	unsigned char chrt[4096 * 2];
	unsigned char namet[960];
	bool add;
	AnsiString ext;


   //	Graphics::TBitmap *pBmp = new Graphics::TBitmap;
   //	pBmp->LoadFromFile("c:\\test2.bmp");


  /*	HPALETTE hpal = BmpMercedes->Palette;
	PALETTEENTRY palEntry[256];

	GetPaletteEntries(hpal, 0 , 256,  palEntry);

	BYTE colorTable[256];
	BYTE colorTransTable[256];


	memset(colorTable,0,256);
	memset(colorTransTable,0,256);

	*/

	if(OpenDialogImport->Execute())
	{
		ext=OpenDialogImport->FileName;
		ext=ext.SubString(ext.LastDelimiter(".")+1,ext.Length()-ext.LastDelimiter(".")).LowerCase();

		if(ext=="bmp")//import BMP file
		{


	BYTE colorTable[256];
	BYTE colorTransTable[256];
	
	memset(colorTable,0,256);
	memset(colorTransTable,0,256);
	
	Graphics::TBitmap *pBmp = new Graphics::TBitmap;

	//pBmp->LoadFromFile("c:\\high-hopes-1.bmp");

	pBmp->LoadFromFile(OpenDialogImport->FileName.c_str());

	if(pBmp->Width!=256 ||(pBmp->Height != 240))
	{
	  Application->MessageBox("BMP should be 256x240 pixels","Error",MB_OK);
	  delete pBmp;
	  return;
	}

	HPALETTE hpal = pBmp->Palette;
	PALETTEENTRY palEntry[256];

	GetPaletteEntries(hpal, 0 , 256,  palEntry);

	memset(chrt,0,4096*2);
	memset(namet,0,960);
	ptr = 0;
	cnt = 0;

	for (int yTilePos = 0; yTilePos < 30; yTilePos++)
	for (int xTilePos = 0; xTilePos < 32; xTilePos++)
	{
	  CountTileColors(xTilePos , yTilePos , pBmp , colorTable);
	}

	// count colors for the Picture
	int usedColors = 0;
	int transColorIndex = -1;

	for (int i = 0; i < 256; i++)
	{
	   if (colorTable[i] > 0)
		   usedColors++;
	}

	Application->MessageBox(("Used colors ("+IntToStr(usedColors)+")").c_str(),"Warning",MB_OK);

	int color1Index = -1;
	int color2Index = -1;
	int color3Index = -1;
	int color4Index = -1;


	color1Index = GetNextMostUsedColor(colorTable , -1);
	color2Index = GetNextMostUsedColor(colorTable , -1);
	color3Index = GetNextMostUsedColor(colorTable , -1);
	color4Index = GetNextMostUsedColor(colorTable , -1);


   if (color1Index != -1)
   {
	 bgPal[0][0] = FindBestPalMatch(&palEntry[color1Index]);
	 colorTransTable[color1Index] = 0;
   }
   if (color2Index != -1)
   {
	 bgPal[0][1]  = FindBestPalMatch(&palEntry[color2Index]);
	 colorTransTable[color2Index] = 1;
   }
   if (color3Index != -1)
   {
	 bgPal[0][2]  = FindBestPalMatch(&palEntry[color3Index]);
	 colorTransTable[color3Index] = 2;
   }
   if (color4Index != -1)
   {
	 bgPal[0][3] = FindBestPalMatch(&palEntry[color4Index]);
	 colorTransTable[color4Index] = 3;
   }

   // Fill base colors (3) if there more, then try to match the as best
	// as possible
	int nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);

	while (nextColor != -1)
	{
	   colorTransTable[nextColor] = FindBestSubPalMatch(0,  &palEntry[nextColor]);
	   nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);
	}

   bool bankA = true;

   for (int yTilePos = 0; yTilePos < 30; yTilePos++)
   for (int xTilePos = 0; xTilePos < 32; xTilePos++)
   {
	 memset(tile , 0 , 16);
	 GenerateTile(xTilePos , yTilePos , pBmp , tile , colorTransTable , -1);


	 bool add=true;

	 if (bankA == true)
	 {
	  for(k=0;k<cnt;k++)
	  {
		if(memcmp(tile,&chrt[k*16],16)==0)
		{
		  namet[yTilePos*32+xTilePos]=k;
		  add=false;
		  break;
		}
	  }
	 }
	 else
	 {
	  for(k=256;k< 256 + cnt;k++)
	  {
		if(memcmp(tile,&chrt[k*16],16)==0)
		{
		  namet[yTilePos*32+xTilePos]=k - 256;
		  add=false;
		  break;
		}
	  }
	 }

	 /*for(k=0;k<cnt;k++)
	 {
		if(memcmp(tile,&chrt[k*16],16)==0)
		{
		  namet[yTilePos*32+xTilePos]=k;
		  add=false;
		  break;
		}
	  }*/

	 if (add == true)
	 {

		memcpy(&chrt[ptr],tile,16);
		ptr+=16;

			namet[yTilePos*32+xTilePos]= cnt;


		cnt++;

		if (cnt == 256)
		{
		  bankA = false;
		  cnt = 0;
		}
	 }
	 /* if(add&&cnt<256)
	  {
		memcpy(&chrt[ptr],tile,16);
		ptr+=16;
		namet[yTilePos*32+xTilePos]=cnt;
		cnt++;
	  }*/



	// memcpy(&chrt[cnt],tile,16);
	// cnt+=16;
   }


   }
		}








	 /*
    	memset(colorTable,0,256);
	memset(colorTransTable,0,256);

	for (int yTilePos = 0+7; yTilePos < 7+7; yTilePos++)
	for (int xTilePos = 0; xTilePos < 32; xTilePos++)
	{
	  CountTileColors(xTilePos , yTilePos , pBmp , colorTable);
	}

	// count colors for the Picture
	 usedColors = 0;
	 transColorIndex = -1;

	for (int i = 0; i < 256; i++)
	{
	   if (colorTable[i] > 0)
		   usedColors++;
	}

	Application->MessageBox(("Used colors ("+IntToStr(usedColors)+")").c_str(),"Warning",MB_OK);

	 color1Index = -1;
	 color2Index = -1;
	 color3Index = -1;
	 color4Index = -1;


	color1Index = GetNextMostUsedColor(colorTable , -1);
	color2Index = GetNextMostUsedColor(colorTable , -1);
	color3Index = GetNextMostUsedColor(colorTable , -1);
	color4Index = GetNextMostUsedColor(colorTable , -1);


   if (color1Index != -1)
   {
	 bgPal[1][0] = FindBestPalMatch(&palEntry[color1Index]);
	 colorTransTable[color1Index] = 0;
   }
   if (color2Index != -1)
   {
	 bgPal[1][1]  = FindBestPalMatch(&palEntry[color2Index]);
	 colorTransTable[color2Index] = 1;
   }
   if (color3Index != -1)
   {
	 bgPal[1][2]  = FindBestPalMatch(&palEntry[color3Index]);
	 colorTransTable[color3Index] = 2;
   }
   if (color4Index != -1)
   {
	 bgPal[1][3] = FindBestPalMatch(&palEntry[color4Index]);
	 colorTransTable[color4Index] = 3;
   }

   // Fill base colors (3) if there more, then try to match the as best
	// as possible
	 nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);

	while (nextColor != -1)
	{
	   colorTransTable[nextColor] = FindBestSubPalMatch(1,  &palEntry[nextColor]);
	   nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);
	}

   for (int yTilePos = 0+7; yTilePos < 7+7; yTilePos++)
   for (int xTilePos = 0; xTilePos < 32; xTilePos++)
   {
	 memset(tile , 0 , 16);
	 GenerateTile(xTilePos , yTilePos , pBmp , tile , colorTransTable , -1);


	 bool add=true;
	 for(k=0;k<cnt;k++)
	 {
		if(memcmp(tile,&chrt[k*16],16)==0)
		{
		  namet[yTilePos*32+xTilePos]=k;
		  add=false;
		  break;
		}
	  }
	  if(add&&cnt<256)
	  {
		memcpy(&chrt[ptr],tile,16);
		ptr+=16;
		namet[yTilePos*32+xTilePos]=cnt;
		cnt++;
	  }
	// memcpy(&chrt[cnt],tile,16);
	// cnt+=16;
   }    */

  /* int __fastcall TFormMain::GenerateTile( int xTilePos,
										int yTilePos  ,
										Graphics::TBitmap *pBitmap,
										unsigned char *pTile,
										unsigned char *pColorTable ,
										int transColorIndex)
	*/
   /*
	memset(chrt,0,4096);
	memset(namet,0,960);
				ptr=0;
				cnt=0;

   Graphics::TBitmap *pBmp = new Graphics::TBitmap;
	pBmp->LoadFromFile("c:\\test2.bmp");
	GenerateTile(0 , 0 , pBmp , tile , sprPal);
	memcpy(&chrt[cnt],tile,16);
	cnt+=16;
	delete pBmp;


	pBmp = new Graphics::TBitmap;
	pBmp->LoadFromFile("c:\\test2.bmp");

	GenerateTile(0 , 1 , pBmp , tile , sprPal);
	memcpy(&chrt[cnt],tile,16);
	cnt+=16;
		delete pBmp;
	pBmp = new Graphics::TBitmap;
	pBmp->LoadFromFile("c:\\test2.bmp");

	GenerateTile(0 , 2 , pBmp , tile , sprPal);
	memcpy(&chrt[cnt],tile,16);
		cnt+=16;
	delete pBmp;



	pBmp = new Graphics::TBitmap;
	pBmp->LoadFromFile("c:\\test2.bmp");

	GenerateTile(1 , 0 , pBmp , tile , sprPal);
	memcpy(&chrt[cnt],tile,16);
	cnt+=16;
		delete pBmp;

	pBmp = new Graphics::TBitmap;
	pBmp->LoadFromFile("c:\\test2.bmp");


	GenerateTile(1 , 1 , pBmp , tile , sprPal);
	memcpy(&chrt[cnt],tile,16);
	cnt+=16;
		delete pBmp;
		pBmp = new Graphics::TBitmap;
	pBmp->LoadFromFile("c:\\test2.bmp");

	GenerateTile(1 , 2 , pBmp , tile , sprPal);
	memcpy(&chrt[cnt],tile,16);

	   delete pBmp;  */



   //bankActive
	memcpy(chr  , chrt , 4096*2);
	memcpy(nameTable,namet,960);
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
	DrawPalettes();
   //	delete pBmp;

   /*
	for (int y = 0; y < 8;y++)
	{
	  BYTE *pBitmapScanline = (BYTE*) BmpMercedes->ScanLine[y];
	  for (int x = 0; x < 8; x++)
	  {
		 colorTable[pBitmapScanline[x]]++;
	  }
	}
	// count colors for 8x8 tile
	int usedColors = 0;
	int transColorIndex = -1;

	for (int i = 0; i < 256; i++)
	{
	   if (colorTable[i] > 0)
	   {
			if ((palEntry[i].peRed   == 255) &&  (palEntry[i].peGreen == 0)   &&
				(palEntry[i].peBlue  == 255))
			{
				  // found transparent color
			  transColorIndex = i;
			}
			else
			{
			  usedColors++;

			}

		}
	}


	//	   return;
	int color1Index = -1;
	int color2Index = -1;
	int color3Index = -1;

	color1Index = GetNextMostUsedColor(colorTable , transColorIndex);
	color2Index = GetNextMostUsedColor(colorTable , transColorIndex);
	color3Index = GetNextMostUsedColor(colorTable , transColorIndex);

	if (color1Index != -1)
	{
		bgPal[0][1] = FindBestPalMatch(&palEntry[color1Index]);
		colorTransTable[color1Index] = 1;
	}
	if (color2Index != -1)
	{
		bgPal[0][2] = FindBestPalMatch(&palEntry[color2Index]);
		colorTransTable[color2Index] = 2;
	}
	if (color3Index != -1)
	{
		bgPal[0][3] = FindBestPalMatch(&palEntry[color3Index]);
		colorTransTable[color3Index] = 3;
	}


	// Fill base colors (3) if there more, then try to match the as best
	// as possible
	int nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);

	while (nextColor != -1)
	{
	   colorTransTable[nextColor] = FindBestSubPalMatch(0,  &palEntry[nextColor]);
	   nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);
	}

	memset(tile,0,16);
	pp=0;
	for (int y = 0; y < 8;y++)
	{
	  BYTE *pBitmapScanline = (BYTE*) BmpMercedes->ScanLine[y];
	  for (int x = 0; x < 8; x++)
	  {
		if (pBitmapScanline[x] !=  transColorIndex)
		{
			byte colorBits = colorTransTable[pBitmapScanline[x]];
			tile[pp]|=(colorBits & 1) ?1<<(7-x):0;
			tile[pp+8]|=(colorBits & 2) ?1<<(7-x):0;
		}
	  }
		pp++;
	}



	 memcpy(&chrt[0],tile,16);




	memset(colorTable,0,256);
	memset(colorTransTable,0,256);

     for (int y = 0; y < 8;y++)
	{
	  BYTE *pBitmapScanline = (BYTE*) BmpMercedes->ScanLine[y+8];
	  for (int x = 0; x < 8; x++)
	  {
 		 colorTable[pBitmapScanline[x]]++;
	  }
	}
	// count colors for 8x8 tile
	 usedColors = 0;
	 transColorIndex = -1;

	for (int i = 0; i < 256; i++)
	{
	   if (colorTable[i] > 0)
	   {
			if ((palEntry[i].peRed   == 255) &&  (palEntry[i].peGreen == 0)   &&
				(palEntry[i].peBlue  == 255))
			{
				  // found transparent color
			  transColorIndex = i;
			}
			else
			{
			  usedColors++;

			}

		}
	}


	//	   return;
	 color1Index = -1;
	 color2Index = -1;
	 color3Index = -1;

	color1Index = GetNextMostUsedColor(colorTable , transColorIndex);
	color2Index = GetNextMostUsedColor(colorTable , transColorIndex);
	color3Index = GetNextMostUsedColor(colorTable , transColorIndex);

	if (color1Index != -1)
	{
		bgPal[1][1] = FindBestPalMatch(&palEntry[color1Index]);
		colorTransTable[color1Index] = 1;
	}
	if (color2Index != -1)
	{
		bgPal[1][2] = FindBestPalMatch(&palEntry[color2Index]);
		colorTransTable[color2Index] = 2;
	}
	if (color3Index != -1)
	{
		bgPal[1][3] = FindBestPalMatch(&palEntry[color3Index]);
		colorTransTable[color3Index] = 3;
	}


	// Fill base colors (3) if there more, then try to match the as best
	// as possible
	 nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);

	while (nextColor != -1)
	{
	   colorTransTable[nextColor] = FindBestSubPalMatch(1,  &palEntry[nextColor]);
	   nextColor =  GetNextMostUsedColor(colorTable , transColorIndex);
	}

	memset(tile,0,16);
	pp=0;
	for (int y = 0; y < 8;y++)
	{
	  BYTE *pBitmapScanline = (BYTE*) BmpMercedes->ScanLine[y+8];
	  for (int x = 0; x < 8; x++)
	  {
		if (pBitmapScanline[x] !=  transColorIndex)
		{
			byte colorBits = colorTransTable[pBitmapScanline[x]];
			tile[pp]|=(colorBits & 1) ?1<<(7-x):0;
			tile[pp+8]|=(colorBits & 2) ?1<<(7-x):0;
		}
	  }
		pp++;
	}



	 memcpy(&chrt[16],tile,16);




	memcpy(chr+bankActive,chrt,4096);
	memcpy(nameTable,namet,960);
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
	delete BmpMercedes;
	return;

	 /*
	memcpy(&chrt[cnt],tile,16);

	cnt+=16;
	namet[32]=1;

	memcpy(&chrt[0],tile,16);

	namet[0]=0;

























		if(ext=="nes")//import ROM file
		{
			file=fopen(OpenDialogImport->FileName.c_str(),"rb");
			if(file)
			{
				fseek(file,0,SEEK_END);
				size=ftell(file);

				if(size==24592||size==40976)
				{
					fseek(file,size-8192,SEEK_SET);
					fread(chr,8192,1,file);
				}
				else
				{
					Application->MessageBoxA("Only 24K and 40K ROMs are supported","Error",MB_OK);
				}

				fclose(file);
			}
		}
			 */
	 //	UpdateTiles(true);
	 //	UpdateNameTable(-1,-1);
	//} */
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MSaveCHRClick(TObject *Sender)
{
	int size = 0;

	if(SaveDialogChr->Execute())
	{
		switch(SaveDialogChr->FilterIndex)
		{
		case 1: size=1024; break;
		case 2: size=2048; break;
		case 3: size=4096; break;
		default: size=8192;
		}

	   saveChrBank(SaveDialogChr->FileName.c_str() , size);
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::saveChrBank(char *pFileName, int size)
{
 FILE *file = NULL;
 unsigned char buf[8192];
 int i,pp;


 file=fopen(pFileName,"wb");

		if(file)
		{
			if(size==4096||size==8192)
			{
				if(size==4096)
				{
					memcpy(buf,chr+bankActive,4096);
				}
				else
				{
					memcpy(buf,chr,8192);
				}
			}
			else
			{
				pp=tileActive*16+bankActive;
				for(i=0;i<size;i++)
				{
					buf[i]=chr[pp++];
					if(pp>=4096) pp=0;
				}
			}
			fwrite(buf,size,1,file);
			fclose(file);
		}
}

//---------------------------------------------------------------------------


void __fastcall TFormMain::FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
	if(Shift.Contains(ssShift))
	{
		if(Key=='C')
		{
			CopyMap(false);
			CopyMapCodeC();
			return;
		}
	}

	if(Shift.Contains(ssCtrl))
	{
		if(Key=='Z') Undo();

		if(nameSelection.left<0&&nameSelection.top<0)
		{
			if(Key=='X') CopyCHR(true,true);
			if(Key=='C') CopyCHR(true,false);
			if(Key=='V') PasteCHR();
		}
		else
		{
			if(Key=='X') CopyMap(true);
			if(Key=='C') CopyMap(false);
			if(Key=='V') PasteMap();
			if(Key=='F') FillMap();
		}
	}
	else
	{
		if(nameSelection.left<0&&nameSelection.top<0)
		{
			if(Key==VK_DELETE) CopyCHR(false,true);
			if(Key=='H') FormCHREditor->MirrorHorizontal();
			if(Key=='V') FormCHREditor->MirrorVertical();
		}
	}

	if(Key==VK_LEFT)  NameTableScrollLeft(Shift.Contains(ssCtrl));
	if(Key==VK_RIGHT) NameTableScrollRight(Shift.Contains(ssCtrl));
	if(Key==VK_UP)    NameTableScrollUp(Shift.Contains(ssCtrl));
	if(Key==VK_DOWN)  NameTableScrollDown(Shift.Contains(ssCtrl));

	if(Key=='A')
	{
		SpeedButtonChecker->Down^=true;
		SpeedButtonCheckerClick(Sender);
	}
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::PutDataToClipboardASMClick(TObject *Sender)
{
	char str[1024],buf[1024];
	int i,j;

	strcpy(str,".db ");

	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			sprintf(buf,"$%2.2x%c",bgPal[i][j],i*4+j<15?',':'\n');
			strcat(str,buf);
		}
	}

	Clipboard()->SetTextBuf(str);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ImageTilesDblClick(TObject *Sender)
{
	FormCHREditor->Show();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MOpenClick(TObject *Sender)
{
	if(OpenDialogAll->Execute()) OpenAll(OpenDialogAll->FileName);
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::FormDestroy(TObject *Sender)
{
	char path[MAX_PATH];
	int len;

	GetCurrentDirectory(len,path);
	reg_save_str(regWorkingDirectory,path);

	int iRespone = Application->MessageBox("Do you want to save the changes?" , "Confirm" , MB_YESNO);


	if (iRespone!= IDYES)
		return;






	switch (g_EditorMode)
	{
		case EDITOR_BG_MODE:
		saveChrBank(ParamStr(1).c_str(), 4096);
		Application->MessageBox("Overwrite?","1",MB_YESNO);

		break;

		case EDITOR_SPR_MODE:
	   //	OpenAll(ParamStr(2));
	   //	OpenAll(ParamStr(3));
	   //	OpenAll(ParamStr(4));
	   //	dir = ParamStr(5);
	   //	SetCurrentDirectory(dir.c_str());
		if (ParamStr(2)!="")
			saveChrBank(ParamStr(2).c_str(), 4096);

		if (ParamStr(3)!="")
			save_data(ParamStr(3).c_str(),nameTable,1920,0);

		if (ParamStr(4) !="")
			savePal(ParamStr(4).c_str());

		break;


		default:
		break;
	}


	//saveChrBank("bgBank.chr", 4096);

  /*	// Save spritesheet and chr file and pal file
	if(ParamStr(1)!="")
	   saveChrBank(ParamStr(1).c_str(), 8192);

	if (ParamStr(2)!="")
		save_data(ParamStr(2).c_str(),nameTable,1920,0);

	if (ParamStr(3) !="")
		savePal(ParamStr(3).c_str());  */

}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ImageNameMouseLeave(TObject *Sender)
{
	nameXC=-1;
	nameYC=-1;
	UpdateStats();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ImageTilesMouseLeave(TObject *Sender)
{
	tileXC=-1;
	tileYC=-1;
	UpdateStats();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ImageTilesMouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
	int i,j,tx,ty;
	int xs,ys,wdt,hgt;

	if(X>=0&&X<256&&Y>=0&&Y<256)
	{
		tx=X/16;
		ty=Y/16;
		tileXC=tx;
		tileYC=ty;

		if(Shift.Contains(ssShift)&&!Shift.Contains(ssCtrl))
		{
			if(Shift.Contains(ssLeft))
			{
				chrSelection.right=tx+(tx>=chrSelection.left?1:0);
				chrSelection.bottom=ty+(ty>=chrSelection.top?1:0);
				if(abs(chrSelection.left-chrSelection.right)>1||abs(chrSelection.top-chrSelection.bottom)>1)
				{
					nameSelection.left=-1;
					nameSelection.right=-1;
					UpdateNameTable(-1,-1);
				}

				for(i=0;i<256;i++) chrSelected[i]=false;

				xs=chrSelection.left<chrSelection.right?chrSelection.left:chrSelection.right;
				ys=chrSelection.top<chrSelection.bottom?chrSelection.top:chrSelection.bottom;
				wdt=abs(chrSelection.right-chrSelection.left);
				hgt=abs(chrSelection.bottom-chrSelection.top);

				for(i=0;i<hgt;i++)
				{
					for(j=0;j<wdt;j++)
					{
						chrSelected[(i+ys)*16+j+xs]=true;
					}
				}

				chrSelectRect=true;
			}
		}

		if(Shift.Contains(ssCtrl)&&(Shift.Contains(ssLeft)||Shift.Contains(ssRight)))
		{
			chrSelected[ty*16+tx]=Shift.Contains(ssLeft);
			chrSelectRect=false;
		}
	}
	else
	{
		tileXC=-1;
		tileYC=-1;
	}

	UpdateTiles(false);
	UpdateStats();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MPutSelectedBlockToClipboardASMClick(TObject *Sender)
{
	CopyMapCodeASM();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MClearCHRClick(TObject *Sender)
{
	int i;

	if(Application->MessageBox("Do you really want to clear 8K CHR?","Confirm",MB_YESNO)==ID_YES)
	{
		SetUndo();
		for(i=0;i<8192;i++) chr[i]=0;
		UpdateTiles(true);
		UpdateNameTable(-1,-1);
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonChrBank1Click(TObject *Sender)
{
	bankActive=SpeedButtonChrBank1->Down?0:4096;
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MOptimizeCHRClick(TObject *Sender)
{
	int i,j,k,pp,x,y,w,h;
	bool clear[256],skip[256];

	SetUndo();

	GetSelection(chrSelection,x,y,w,h);

	for(i=0;i<256;i++)
	{
		clear[i]=false;
		skip[i]=false;
	}

	if(chrSelectRect)
	{
		if(w>1||h>1)
		{
			for(i=0;i<16;i++)
			{
				for(j=0;j<16;j++)
				{
					skip[i*16+j]=(i>=y&&i<y+h&&j>=x&&j<x+w)?true:false;
				}
			}
		}
	}
	else
	{
		for(i=0;i<256;i++) skip[i]=chrSelected[i];
	}

	for(i=0;i<256;i++)
	{
		if(!clear[i]&&!skip[i])
		{
			for(j=i+1;j<256;j++)
			{
				if(!memcmp(&chr[bankActive+i*16],&chr[bankActive+j*16],16)&&!skip[j])
				{
					clear[j]=true;
					for(k=0;k<960;k++) if(nameTable[k]==j) nameTable[k]=i;
				}
			}
		}
	}

	pp=bankActive;

	for(i=0;i<256;i++)
	{
		if(!clear[i]&&!skip[i])
		{
			while(skip[pp/16]) pp+=16;
			for(j=0;j<960;j++) if(nameTable[j]==i) nameTable[j]=pp/16;
			for(j=0;j<16;j++) chr[pp++]=chr[bankActive+i*16+j];
		}
	}

	for(;pp<4096;pp++) if(!skip[pp/16]) chr[bankActive+pp]=0;

	UpdateTiles(true);
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::PaintBoxPalMouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
	int i,x,y,col;

	y=0;
	x=16;

	palHover=-1;
	palColHover=-1;
	colHover=-1;

	for(i=0;i<4;i++)
	{
		if(Y>=y&&Y<y+20)
		{
			if(X>=x   &&X<x+20)
			{
				palHover=i;
				palColHover=0;
				colHover=-1;
			}
			if(X>=x+20&&X<x+40)
			{
				palHover=i;
				palColHover=1;
				colHover=-1;
			}
			if(X>=x+40&&X<x+60)
			{
				palHover=i;
				palColHover=2;
				colHover=-1;
			}
			if(X>=x+60&&X<x+80)
			{
				palHover=i;
				palColHover=3;
				colHover=-1;
			}
		}
		x+=128-16;
		if(x>128)
		{
			x=16;
			y=32;
		}
	}

	if(X>=0&&X<14*16&&Y>=64&&Y<64+4*16)
	{
		colHover=X/16+(Y-64)/16*16;
		palHover=-1;
		palColHover=-1;
	}

	UpdateStats();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::PaintBoxPalMouseLeave(TObject *Sender)
{
	palHover=-1;
	palColHover=-1;
	colHover=-1;
	UpdateStats();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MSaveChrSelectionClick(TObject *Sender)
{
	FILE *file;
	int i,size;

	if(SaveDialogChrSelection->Execute())
	{
		size=0;

		for(i=0;i<256;i++) if(chrSelected[i]) size+=16;

		file=fopen(SaveDialogChrSelection->FileName.c_str(),"rb");

		if(file)
		{
			fseek(file,0,SEEK_END);
			i=ftell(file);
			fclose(file);

			if(Application->MessageBox((size==i?"Overwrite?":"Previous file has different size! Overwrite?"),"Confirm",MB_YESNO)!=IDYES) return;
		}

		file=fopen(SaveDialogChrSelection->FileName.c_str(),"wb");

		if(file)
		{
			for(i=0;i<256;i++)
			{
				if(chrSelected[i]) fwrite(chr+i*16,16,1,file);
			}

			fclose(file);
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MInterleaveCHRClick(TObject *Sender)
{
	InterleaveCHR(true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MDeinterleaveCHRClick(TObject *Sender)
{
	InterleaveCHR(false);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MSwapColorsCHRClick(TObject *Sender)
{
	bool swap[256*2];
	int i,j,k,pp,col,bit;
	unsigned char paltemp[4];

	FormSwapColors->ShowModal();

	if(FormSwapColors->Swap)
	{
		SetUndo();

		for(i=0;i<256*2;i++) swap[i]=false;

		if(FormSwapColors->Selection)
		{
			for(i=0;i<256;i++) swap[(bankActive/4096*256)+i]=chrSelected[i];
		}
		else
		{
			if(FormSwapColors->WholeCHR)
			{
				for(i=0;i<256*2;i++) swap[i]=true;
			}
			else
			{
				for(i=0;i<256;i++) swap[(bankActive/4096*256)+i]=true;
			}
		}

		for(i=0;i<256*2;i++)
		{
			if(swap[i])
			{
				pp=i*16;

				for(j=0;j<8;j++)
				{
					for(k=0;k<8;k++)
					{
						bit=1<<k;
						col=((chr[pp]&bit)?1:0)|((chr[pp+8]&bit)?2:0);
						col=FormSwapColors->Map[col];
						chr[pp]=(chr[pp]&~bit)|((col&1)<<k);
						chr[pp+8]=(chr[pp+8]&~bit)|((col>>1)<<k);
					}
					pp++;
				}
			}
		}

		if(FormSwapColors->RemapPalette)
		{
			for(i=0;i<4;i++)
			{
				for(j=0;j<4;j++) paltemp[FormSwapColors->Map[j]]=bgPal[i][j];
				for(j=0;j<4;j++) bgPal[i][j]=paltemp[j];
			}
			bgPal[1][0]=bgPal[0][0];
			bgPal[2][0]=bgPal[0][0];
			bgPal[3][0]=bgPal[0][0];
		}

		UpdateTiles(true);
		UpdateNameTable(-1,-1);
		DrawPalettes();
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MAddOffsetClick(TObject *Sender)
{
	int i;

	FormNameOffset->ShowModal();

	if(FormNameOffset->MakeOffset)
	{
		SetUndo();

		for(i=0;i<960;i++)
		{
			if(nameTable[i]>=FormNameOffset->From&&nameTable[i]<=FormNameOffset->To) nameTable[i]+=FormNameOffset->Offset;
		}

		UpdateNameTable(-1,-1);
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonMaskBClick(TObject *Sender)
{
	ppuMask^=0x80;
	SpeedButtonMaskB->Caption="B"+IntToStr((ppuMask&0x80?1:0));
	palette_calc();
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
	DrawPalettes();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonMaskGClick(TObject *Sender)
{
	ppuMask^=0x40;
	SpeedButtonMaskG->Caption="G"+IntToStr((ppuMask&0x40?1:0));
	palette_calc();
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
	DrawPalettes();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonMaskRClick(TObject *Sender)
{
	ppuMask^=0x20;
	SpeedButtonMaskR->Caption="R"+IntToStr((ppuMask&0x20?1:0));
	palette_calc();
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
	DrawPalettes();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonMaskMClick(TObject *Sender)
{
	ppuMask^=0x01;
	SpeedButtonMaskM->Caption="M"+IntToStr((ppuMask&0x01?1:0));
	palette_calc();
	UpdateTiles(true);
	UpdateNameTable(-1,-1);
	DrawPalettes();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MExportScreenShotClick(TObject *Sender)
{
	TPicture *picture;
	Graphics::TBitmap *bmp;
	int i,j,x,y;

	if(SaveDialogImage->Execute())
	{
		picture=new TPicture();
		bmp=new Graphics::TBitmap();
		bmp->SetSize(256,240);
		bmp->PixelFormat=ImageName->Picture->Bitmap->PixelFormat;
		picture->Bitmap=bmp;

		y=0;

		for(i=0;i<30;i++)
		{
			x=0;
			for(j=0;j<32;j++)
			{
				DrawSmallTile(picture,x,y,nameTable[i*32+j],attr_get(j,i),j,i);
				x+=8;
			}
			y+=8;
		}

		picture->SaveToFile(SaveDialogImage->FileName);

		delete bmp;
		delete picture;
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MExportTilesetImageClick(TObject *Sender)
{
	TPicture *picture;
	Graphics::TBitmap *bmp;
	int i,x,y;
      
	if(SaveDialogImage->Execute())
	{
		picture=new TPicture();
		bmp=new Graphics::TBitmap();
		bmp->SetSize(128,128);
		bmp->PixelFormat=ImageTiles->Picture->Bitmap->PixelFormat;
		picture->Bitmap=bmp;

		x=0;
		y=0;

		for(i=0;i<256;i++)
		{
			DrawSmallTile(picture,x,y,i,palActive,-1,-1);
			x+=8;
			if(x>=128)
			{
				x=0;
				y+=8;
			}
		}

		picture->SaveToFile(SaveDialogImage->FileName);

		delete bmp;
		delete picture;
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::PutDataToClipboardCClick(TObject *Sender)
{
	char str[1024],buf[1024];
	int i,j;

	strcpy(str,"const unsigned char palette[16]={ ");

	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			sprintf(buf,"0x%2.2x%c",bgPal[i][j],i*4+j<15?',':' ');
			strcat(str,buf);
		}
	}

	strcat(str,"};\n");

	Clipboard()->SetTextBuf(str);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MPutSelectedBlockToClipboardCClick(TObject *Sender)
{
	CopyMapCodeC();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::SpeedButtonCheckerClick(TObject *Sender)
{
	UpdateNameTable(-1,-1);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MPutMetaSpriteToClipboardCClick(TObject *Sender)
{
	CopyMetaSpriteCodeC(false);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::MPutMetaSpriteToClipboardHFlipCClick(TObject *Sender)
{
	CopyMetaSpriteCodeC(true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::E1Click(TObject *Sender)
{
   CopyMapCodeC();
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

void __fastcall TFormMain::ExportSpriteFile(char *pFileName)
{
  char str[65536],buf[1024];
  int i,j,x,y,w,h;
  int bmpXpos = 0;
  int bmpYpos = 0;

  TPicture *picture;
  Graphics::TBitmap *bmp;

  if(nameSelection.left>=0&&nameSelection.top>=0)
  {
	GetSelection(nameSelection,x,y,w,h);

	sprintf(str,"const unsigned char nametable[%i*%i]={\t",w,h);

	for(i=0;i<h;i++)
	{
		strcat(str,"\t");
		for(j=0;j<w;j++)
		{
			sprintf(buf,"0x%2.2x ",nameTable[(y+i)*32+x+j]);
			strcat(str,buf);

			sprintf(buf,"0x%2.2x%c",attr_get(x+j,y+i),j<w-1?',':' ');
			strcat(str,buf);

				//sprintf(buf,"%i,%i,0x%2.2x,%i,\n",j*8,i*8,nameTable[(y+i)*32+x+j],attr_get(x+j,y+i));

			//strcat(str,buf);
		}
	 }

   strcat(str,"};\n");


   FILE *pFile = fopen(pFileName,"wt+");

   if (pFile != NULL)
   {
	 fwrite(str,strlen(str),1,pFile);
	 fclose(pFile);
					
	 // Export sprite preview bitmap
	 	picture=new TPicture();
		bmp=new Graphics::TBitmap();
		bmp->SetSize(w*8,h*8);
		bmp->PixelFormat=ImageName->Picture->Bitmap->PixelFormat;
	
		picture->Bitmap=bmp;

		bmpYpos=0;

		for(i=0;i<h;i++)
	{
		bmpXpos= 0;
		for(j=0;j<w;j++)
		{
			//sprintf(buf,"0x%2.2x%c",nameTable[(y+i)*32+x+j],j<w-1?',':'\n');
				DrawSmallTile(picture,bmpXpos,bmpYpos,nameTable[(y+i)*32+x+j],attr_get(x+j,y+i),j,i);
				bmpXpos+=8;
		}
				bmpYpos+=8;
	 }

		char newFileName[1024*16];
		memset(newFileName,0,0);
		memcpy(newFileName,pFileName , strlen(pFileName) - 4);
		newFileName[strlen(pFileName) - 4] = '\0';
		strcat(newFileName,".bmp");


		picture->SaveToFile(newFileName);

		delete bmp;
		delete picture;

   }

  }

}


void __fastcall TFormMain::MouseUpEvent(TObject *Sender, TMouseButton Button,
	  TShiftState Shift, int X, int Y)
{
  //Button.


}
//---------------------------------------------------------------------------


void __fastcall TFormMain::est1Click(TObject *Sender)
{
 	// Export sprite and create a preview image for scratchalan
	 g_nrExportedSprite++;
	 char filename [ FILENAME_MAX ];
	 sprintf(filename, "%d.spr",  g_nrExportedSprite);
	 ExportSpriteFile(filename);
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::ImageNameDblClick(TObject *Sender)
{
//  int nameXPos = X/16;
  //			nameSelection.top=Y/16;

 //FormCHREditor->Show();
}
//---------------------------------------------------------------------------







