using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;


namespace WTD_Editor
{
    unsafe public class PAGfx_Convertor
    {
        // special attributes
        protected Map map;
        public MemoryStream minimap_bytes;
        public MemoryStream map_bytes;
        public MemoryStream tiles_bytes;
        public MemoryStream minimap_pal_bytes;
        public MemoryStream map_pal_bytes;

        // constructeur
        public PAGfx_Convertor(Map map)
        {
            this.map = map;
            minimap_bytes = new MemoryStream();
            map_bytes = new MemoryStream();
            tiles_bytes = new MemoryStream();
            minimap_pal_bytes = new MemoryStream();
            map_pal_bytes = new MemoryStream();
            TilesInfo = new UInt32[4, 256, 2000];
            NTilesInfo = new UInt32[4, 256];
            Palette = new PaletteStruct[2];

            InitTranspColor();
            putMinimapSprite();
            putMapBg();
        }


        // Ini parser structures...
        public struct IniSpriteStruct
        {
            public string Name;
            public string Path; // Path to open file
            public int ColorMode; // 0 pour 16 couleurs, 1 pour 256, 2 pour 16bit...
            public string PaletteName;
        };
        public struct IniBgStruct
        {
            public string Name;
            public string Path; // Path to open file...
            public int BgMode; // 8bit, 16bit, TileBg, RotBg, LargeMap
            public string PaletteName;
        };
        public struct TranspStruct
        {
            public int Number; // Number (0-4)
            public UInt16 Color; // Color
            public string Name; // Colorname...
        }
        public struct IniStruct
        {
            public string[] Lines; // Different lines
            public int NLines; // Number of lines
            public string[] Strings; // Strings in a line...
        }

        public int NSprites = 0; // Nombre de sprites
        public int NBackgrounds = 0; // Nombre de sprites

        public IniSpriteStruct[] IniSprites;
        public IniBgStruct[] IniBgs;
        public TranspStruct TranspColor;
        public string[] SpriteModes;
        public string[] BgModes;
        UInt16[] TranspColors;

        void InitTranspColor()
        {
            // Init the color modes...
            TranspColors = new UInt16[1];
            TranspColors[0] = PA_RGB(31, 0, 31);

            TranspColor.Number = 0;
            TranspColor.Color = TranspColors[TranspColor.Number];
            TranspColor.Name = "Magenta";
        }

        int GetTranspColor()
        {
            return 0;   // magenta
        }

        public bool putMinimapSprite()
        {
            // Puts the sprite infos into the sprite structure
/*            bool FileOk = true;
            IniSprites[NSprites].Path = ExtractPath();
            string PathBackup = IniSprites[NSprites].Path;

            FileOk = File.Exists(IniSprites[NSprites].Path);
            if (!FileOk && !Path.IsPathRooted(IniSprites[NSprites].Path))
            {
                IniSprites[NSprites].Path = System.AppDomain.CurrentDomain.BaseDirectory + IniSprites[NSprites].Path;
                FileOk = File.Exists(IniSprites[NSprites].Path);
            }

            if (FileOk)
*/            {
                  IniSprites = new IniSpriteStruct[1];
                  IniSprites[NSprites].Name = "minimap";//ExtractName(IniSprites[NSprites].Path);

                // Try to get the color mode, sets to 256Colors by default
                IniSprites[NSprites].ColorMode = 1;
                //Console.Write(Ini.Strings.Length);
/*                if (Ini.Strings.Length > 1)
                    for (int i = 0; i < 5; i++)
                        if (Ini.Strings[1].ToLower() == SpriteModes[i].ToLower())
                            IniSprites[NSprites].ColorMode = i;

                // Try to get the palette name, gives the sprite name if no palette found
                if (IniSprites[NSprites].ColorMode != 2) // If not 16bit...
*/                {
                    IniSprites[NSprites].PaletteName = IniSprites[NSprites].Name;
/*                    if (Ini.Strings.Length > 2)
                        IniSprites[NSprites].PaletteName = Ini.Strings[2];
*/                }

                NSprites++;
            }
            return true;
        }

        bool putMapBg()
        {
            // Puts the sprite infos into the sprite structure
/*            bool FileOk = true;
            IniBgs[NBackgrounds].Path = ExtractPath();

            FileOk = File.Exists(IniBgs[NBackgrounds].Path);
            if (!FileOk && !Path.IsPathRooted(IniBgs[NBackgrounds].Path))
            {
                IniBgs[NBackgrounds].Path = System.AppDomain.CurrentDomain.BaseDirectory + IniBgs[NBackgrounds].Path;
                FileOk = File.Exists(IniBgs[NBackgrounds].Path);
            }

            if (FileOk)
*/            {
                IniBgs = new IniBgStruct[1];
                IniBgs[NBackgrounds].Name = "map";//ExtractName(IniBgs[NBackgrounds].Path);

                // Try to get the color mode, sets to Tiled by default
                IniBgs[NBackgrounds].BgMode = 4; // Large Bg
/*                if (Ini.Strings.Length > 1)
                    for (int i = 0; i < 9; i++)
                        if (Ini.Strings[1].ToLower() == BgModes[i].ToLower())
                            IniBgs[NBackgrounds].BgMode = i;

                if (IniBgs[NBackgrounds].BgMode != 1)
                {
                    // Try to get the palette name, gives the sprite name if no palette found
*/                    IniBgs[NBackgrounds].PaletteName = IniBgs[NBackgrounds].Name;
/*                    if (Ini.Strings.Length > 2)
                        IniBgs[NBackgrounds].PaletteName = Ini.Strings[2];
                }
*/
                NBackgrounds++;
            }
            return true;
        }

        
        #region Variables

        UInt16 PA_RGB(int r, int g, int b)
        {
            return (UInt16)((1 << 15) + r + (g << 5) + (b << 10));
        }
        UInt16 PA_RGB8(int r, int g, int b)
        {
            return (UInt16)((1 << 15) + (r >> 3) + ((g >> 3) << 5) + ((b >> 3) << 10));
        }  // Avec le 1<<15, pour les palettes et fonds
        UInt16 PA_RGB8b(int r, int g, int b)
        {
            return (UInt16)((r >> 3) + ((g >> 3) << 5) + ((b >> 3) << 10));
        } // Sans le 1<<15, pour les sprites

        // Data infos...
        struct PaletteStruct
        {
            public string Name;
            public UInt16[] Colors; // Toutes les couleurs
            public int[] OkColors; // Toutes les couleurs déjà utilisée seront à leur valeur normale, les autres à -1...
            public int NColors;  // Nombre de couleurs
        } ;
        struct SpriteStruct
        {
            public string Name;
            public UInt32[] Pixels; // Pour les pixels...
            public int ColorMode; // 0 pour 16 couleurs, 1 pour 256, 2 pour 16bit...
            public int NPalette; // Palette used
        } ;
        struct BgStruct
        {
            public string Name;
            public UInt32[] Tiles; // Tiles...
            public UInt32[] Map; // Map...
            public int BgMode; // 8bit, 16bit, TileBg, RotBg, LargeMap, InfiniteMap
            public int NPalette; // Palette used
            public int NTiles; // Number of tiles
        } ;

        PaletteStruct[] Palette;
        SpriteStruct Sprite;
        BgStruct Background;

        UInt16 NPalettes = 0; // Nombre de palettes

        Bitmap readBitmap;

        int swidth, sheight, width, height, x, y; // Variables temppour infos du fichier
        UInt16[] buffer; // tableau temp

        BinaryWriter cwriter = null;
        BinaryWriter hwriter = null;
        BinaryWriter binWriter;
        BinaryWriter infoWriter; // Will be used for Bg info

        UInt32[, ,] TilesInfo;
        UInt32[,] NTilesInfo;


        byte oldmode;

        int HFlip, VFlip; // For map tiles...

        #endregion

        #region Sprites

        public void CreateMinimapSprite()
        {
            int Spr = 0;
            readBitmap = new Bitmap(map.minimap); // new Bitmap(PAGfx_Convertor.IniSprites[Spr].Path);
            Sprite = new SpriteStruct();
            Sprite.ColorMode = IniSprites[Spr].ColorMode;
            Sprite.Name = IniSprites[Spr].Name;

//            PAGfxWrite("  " + Sprite.Name + " : " + PAGfx_Convertor.SpriteModes[Sprite.ColorMode] + ", ");

            width = readBitmap.Width; height = readBitmap.Height;
            x = 0; y = 0;

            swidth = 64; sheight = 64;
            // On ajuste si sprite trop petit...
            if (!((swidth == 8) || (swidth == 16) || (swidth == 32) || (swidth == 64)))
            {
                if (swidth < 8) swidth = 8;
                else if (swidth < 16) swidth = 16;
                else if (swidth < 32) swidth = 32;
                else if (swidth < 64) swidth = 64;
            }
            //            PAGfxWrite(swidth + "x" + sheight + ", ");

/*            if (Sprite.ColorMode != 2) // Uses palettes...
            {
                if (Sprite.ColorMode < 4)   // Optimized palettes
                {
*/                    Sprite.NPalette = GetPal(IniSprites[Spr].PaletteName);
/*                    PAGfxWrite("Pal : " + Palette[Sprite.NPalette].Name + "_Pal, ");
                }
                else  // Full palettes
                {
                    Sprite.NPalette = GetFullPal(PAGfx_Convertor.IniSprites[Spr].PaletteName, Spr);
                    PAGfxWrite("Pal : " + Palette[Sprite.NPalette].Name + "_Pal, ");
                }
            }
*/
            Create256CSpriteMinimap();

/*            if (Sprite.ColorMode == 0) Create16CSprite(); // 16 colors
            if (Sprite.ColorMode == 1) Create256CSprite(); // 256 colors
            if (Sprite.ColorMode == 2) Create16BSprite(); // 16bit
            if (Sprite.ColorMode == 3) CreateSpritePal(); // Only the palette
            if (Sprite.ColorMode == 4) Create256CSprite(); // 256 colors full palette
            if (Sprite.ColorMode == 5) CreateSpritePal(); // Only the full palette
*/            
        }

        void CreateSprite(int Spr)
        {
            readBitmap = new Bitmap(IniSprites[Spr].Path);
            Sprite.ColorMode = IniSprites[Spr].ColorMode;
            Sprite.Name = IniSprites[Spr].Name;

            PAGfxWrite("  " + Sprite.Name + " : " + SpriteModes[Sprite.ColorMode] + ", ");
            
            width = readBitmap.Width; height = readBitmap.Height;
            x = 0; y = 0;

            swidth = width; sheight = height;
            // On ajuste si sprite trop petit...
            if (!((swidth == 8) || (swidth == 16) || (swidth == 32) || (swidth == 64)))
            {
                if (swidth < 8) swidth = 8;
                else if (swidth < 16) swidth = 16;
                else if (swidth < 32) swidth = 32;
                else if (swidth < 64) swidth = 64;
            }

            PAGfxWrite(swidth+"x"+sheight+", ");

            if (Sprite.ColorMode != 2) // Uses palettes...
            {
                if (Sprite.ColorMode < 4)   // Optimized palettes
                {
                    Sprite.NPalette = GetPal(IniSprites[Spr].PaletteName);
                    PAGfxWrite("Pal : " + Palette[Sprite.NPalette].Name + "_Pal, ");
                }
            }

//            if (Sprite.ColorMode == 0) Create16CSprite(); // 16 colors
            if (Sprite.ColorMode == 1) Create256CSprite(); // 256 colors
//            if (Sprite.ColorMode == 2) Create16BSprite(); // 16bit
            if (Sprite.ColorMode == 3) CreateSpritePal(); // Only the palette
            if (Sprite.ColorMode == 4) Create256CSprite(); // 256 colors full palette
            if (Sprite.ColorMode == 5) CreateSpritePal(); // Only the full palette
            
        }

        void CreateSpritePal()
        {
            buffer = new UInt16[swidth * sheight]; // Tableau pour remplir le sprite
            int palette = Sprite.NPalette; // Palette

            Init8bitBuffer(palette);
//            PAGfxWriteLine(" ");
        }

        void Create256CSpriteMinimap()
        {
            buffer = new UInt16[swidth * sheight]; // Tableau pour remplir le sprite
            Sprite.Pixels = new UInt32[swidth * sheight ]; // Sprite final !
            int palette = Sprite.NPalette; // Palette

            int pixel = 0;

            Init8bitBuffer(palette);

            for (y = 0; y < sheight; y += 8)// Blocs de 8x8
            {
                for (x = 0; x < swidth; x += 8)// Idem
                {
                    int tempy, pos;
                    for (tempy = 0; tempy < 8; tempy++) // On fait le bloc de 0...
                    {
                        pos = x + ((y + tempy) * swidth);
                        Sprite.Pixels[pixel] = buffer[pos];
                        Sprite.Pixels[pixel + 1] = buffer[pos + 1];
                        Sprite.Pixels[pixel + 2] = buffer[pos + 2];
                        Sprite.Pixels[pixel + 3] = buffer[pos + 3];
                        Sprite.Pixels[pixel + 4] = buffer[pos + 4];
                        Sprite.Pixels[pixel + 5] = buffer[pos + 5];
                        Sprite.Pixels[pixel + 6] = buffer[pos + 6];
                        Sprite.Pixels[pixel + 7] = buffer[pos + 7];
                        pixel += 8;
                    }
                }
            }


            // Et enfin, on écrit le fichier !!
/*            FileStream spritefile, binfile; // Permet de faire le fichier
            BinaryWriter spritewriter;
            string tempstring, binstring;

            tempstring = Sprite.Name + ".c";
            binstring = "bin/" + Sprite.Name + "_Sprite.bin";

            spritefile = new FileStream(tempstring, FileMode.Create); // Créé le fichier
            spritewriter = new BinaryWriter(spritefile);  // Permet d'écrire dedans
            binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
*/            binWriter = new BinaryWriter(minimap_bytes);  // Permet d'écrire dedans




 /*           spritewriter.Write(Encoding.UTF8.GetBytes("//Sprite created using PAGfx\r\n//This sprite uses " + Palette[palette].Name + "_Pal\r\n\r\n"));

*/            int maxj = swidth * sheight;
/*            string namestring = "#include " + '"' + tempstring + '"' + "\r\n";
            tempstring = "const unsigned char " + Sprite.Name + "_Sprite[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";

            cwriter.Write(Encoding.UTF8.GetBytes(namestring));
            tempstring = "const unsigned char " + Sprite.Name + "_Sprite[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned char " + Sprite.Name + "_Sprite[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
*/

            WriteData8bit(null, binWriter, null, Sprite.Pixels, maxj);
/*
            PAGfxWriteLine("-> " + Sprite.Name + "_Sprite");

            spritefile.Close(); // Libère la mémoire
            spritewriter.Close();
            binfile.Close();
            binWriter.Close();
*/
        }

        void Create256CSprite()
        {
            buffer = new UInt16[swidth * sheight]; // Tableau pour remplir le sprite
            Sprite.Pixels = new UInt32[swidth * sheight]; // Sprite final !
            int palette = Sprite.NPalette; // Palette

            int pixel = 0;

            Init8bitBuffer(palette);

            for (y = 0; y < sheight; y += 8)// Blocs de 8x8
            {
                for (x = 0; x < swidth; x += 8)// Idem
                {
                    int tempy, pos;
                    for (tempy = 0; tempy < 8; tempy++) // On fait le bloc de 0...
                    {
                        pos = x + ((y + tempy) * swidth);
                        Sprite.Pixels[pixel] = buffer[pos];
                        Sprite.Pixels[pixel + 1] = buffer[pos + 1];
                        Sprite.Pixels[pixel + 2] = buffer[pos + 2];
                        Sprite.Pixels[pixel + 3] = buffer[pos + 3];
                        Sprite.Pixels[pixel + 4] = buffer[pos + 4];
                        Sprite.Pixels[pixel + 5] = buffer[pos + 5];
                        Sprite.Pixels[pixel + 6] = buffer[pos + 6];
                        Sprite.Pixels[pixel + 7] = buffer[pos + 7];
                        pixel += 8;
                    }
                }
            }


            // Et enfin, on écrit le fichier !!
            FileStream spritefile, binfile; // Permet de faire le fichier
            BinaryWriter spritewriter;
            string tempstring, binstring;

            tempstring = Sprite.Name + ".c";
            binstring = "bin/" + Sprite.Name + "_Sprite.bin";

            spritefile = new FileStream(tempstring, FileMode.Create); // Créé le fichier
            spritewriter = new BinaryWriter(spritefile);  // Permet d'écrire dedans
            binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
            binWriter = new BinaryWriter(binfile);  // Permet d'écrire dedans

            


            spritewriter.Write(Encoding.UTF8.GetBytes("//Sprite created using PAGfx\r\n//This sprite uses " + Palette[palette].Name + "_Pal\r\n\r\n"));

            int maxj = swidth * sheight;
            string namestring = "#include " + '"' + tempstring + '"' + "\r\n";
            tempstring = "const unsigned char " + Sprite.Name + "_Sprite[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";

            cwriter.Write(Encoding.UTF8.GetBytes(namestring));
            tempstring = "const unsigned char " + Sprite.Name + "_Sprite[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned char " + Sprite.Name + "_Sprite[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));


            WriteData8bit(spritewriter, binWriter, tempstring, Sprite.Pixels, maxj);

            PAGfxWriteLine("-> " + Sprite.Name + "_Sprite");

            spritefile.Close(); // Libère la mémoire
            spritewriter.Close();
            binfile.Close();
            binWriter.Close();
        }

        #endregion

        #region Backgrounds


        public void CreateMapBg()
        {
            int Bg = 0;

            readBitmap = new Bitmap(map.gfxmap);//PAGfx_Convertor.IniBgs[Bg].Path);

            Background = new BgStruct();

            Background.BgMode = IniBgs[Bg].BgMode;
            Background.Name = IniBgs[Bg].Name;

            width = readBitmap.Width; height = readBitmap.Height;
            x = 0; y = 0;

            swidth = width; sheight = height;

            if (Background.BgMode == 6) Background.BgMode = 2; // Go to Tiled Bg mode...

            if (Background.BgMode == 2)
            { // If tiled Bg too small...        
                if (swidth <= 256) swidth = 256; // Minimum 256...
                else if ((sheight > 256) && (swidth < 512)) swidth = 512; // Minimum 192...
                if (sheight <= 192) sheight = 192; // Minimum 192...
                if ((swidth > 256) && (sheight <= 256)) sheight = 256; // Minimum 256 if map if larger
            }

            Background.NPalette = GetPal(IniBgs[Bg].PaletteName);
            oldmode = (byte)Background.BgMode;
            
            CreateMapTiledBg();
        }

        void CreateBg(int Bg)
        {
            //if (Background.BgMode != 1) // If palettes are used
            
            

            readBitmap = new Bitmap(IniBgs[Bg].Path);
            
            Background.BgMode = IniBgs[Bg].BgMode;
            Background.Name = IniBgs[Bg].Name;


            PAGfxWrite("  " + Background.Name + " : " + BgModes[Background.BgMode] + ", ");

            width = readBitmap.Width; height = readBitmap.Height;
            x = 0; y = 0;

            swidth = width; sheight = height;

            if (Background.BgMode == 6) Background.BgMode = 2; // Go to Tiled Bg mode...

            if (Background.BgMode == 2)
            { // If tiled Bg too small...        
                if (swidth <= 256) swidth = 256; // Minimum 256...
                else if ((sheight > 256) && (swidth < 512)) swidth = 512; // Minimum 192...
                if (sheight <= 192) sheight = 192; // Minimum 192...
                if ((swidth > 256) && (sheight <= 256)) sheight = 256; // Minimum 256 if map if larger
            }

            if (Background.BgMode == 3)// RotBg
            {
                if ((swidth <= 128) && (sheight <= 128))
                {
                    swidth = 128; sheight = 128;
                }
                else if ((swidth <= 256) && (sheight <= 256))
                {
                    swidth = 256; sheight = 256;
                }
                else if ((swidth <= 512) && (sheight <= 512))
                {
                    swidth = 512; sheight = 512;
                }
                else
                {
                    swidth = 1024; sheight = 1024;
                }

            }


            PAGfxWrite(swidth + "x" + sheight + ", ");

            if (Background.BgMode != 1) // Uses palettes...
            {
                Background.NPalette = GetPal(IniBgs[Bg].PaletteName);
                PAGfxWrite("Pal : " + Palette[Background.NPalette].Name + "_Pal, ");
            }

            oldmode = (byte)Background.BgMode;

//            if (Background.BgMode == 0) Create8bBg();
//            else if (Background.BgMode == 1) Create16bBg();
             if (Background.BgMode == 2) CreateTiledBg();
            else if (Background.BgMode == 3) CreateTiledBg();
            else if (Background.BgMode == 4) CreateTiledBg();
            else if (Background.BgMode == 5) CreateTiledBg();

        }

        Int32 CompareNorm(int CurrentPos, int firstcol)
        {   
            int tile = 0;
            Int32 TileNumber = -1;
            Int32 OkTile = -1; // wrong number by default
            Int32 temppixel;
            bool ok = false;
            int BigY;
            for (tile = 0; (tile < NTilesInfo[0, firstcol]) && !ok; tile++)
            //for (TileNumber = 0; (TileNumber < Background.NTiles) && !ok; TileNumber++)
            {
                ok = true; // true by default, proove it wrong
                TileNumber = (Int32)TilesInfo[0, firstcol, tile];

                // Writes the tile...
                temppixel = TileNumber * 8 * 8; // Taille des blocs...
                int tempx2 = 0, tempy2 = 0;
                int i, j;
                for (i = 0; (i < 8) && ok; i++) // On fait le bloc de 0...
                {
                    tempx2 = 0;
                    BigY = (tempy2 * swidth);
                    for (j = 0; (j < 8) && ok; j++)
                    {
                        ok = (Background.Tiles[temppixel] == buffer[CurrentPos + tempx2 + BigY]);
                        /*
                        if (Background.Tiles[temppixel] != buffer[CurrentPos + tempx2 + (tempy2 * swidth)])
                        {
                            OkTile = -1; // not good !
                        }*/
                        temppixel++;
                        tempx2++;
                        //CurrentPos++;
                    }
                    tempy2 ++;
                }
//                if (OkTile != -1) ok = true; 
            }
            if (ok == false) OkTile = -1;
            else OkTile = TileNumber;
            return OkTile; // tells if same thing or not
      }

        Int32 CompareHFlip(int CurrentPos, int firstcol)
        {
            int tile = 0;
            Int32 TileNumber = -1;
            Int32 OkTile = -1; // wrong number by default
            Int32 temppixel;
            bool ok = false;
            int BigY;
            for (tile = 0; (tile < NTilesInfo[1, firstcol]) && !ok; tile++)
            //for (TileNumber = 0; (TileNumber < Background.NTiles) && !ok; TileNumber++)
            {
                ok = true; // true by default, proove it wrong
                TileNumber = (Int32)TilesInfo[1, firstcol, tile];

                // Writes the tile...
                temppixel = TileNumber * 8 * 8; // Taille des blocs...
                int tempx2 = 7, tempy2 = 0;
                int i, j;
                for (i = 0; (i < 8) && ok; i++) // On fait le bloc de 0...
                {
                    tempx2 = 7;
                    BigY = (tempy2 * swidth);
                    for (j = 0; (j < 8) && ok; j++)
                    {
                        ok = (Background.Tiles[temppixel] == buffer[CurrentPos + tempx2 + BigY]);
                        temppixel++;
                        tempx2--;
                    }
                    tempy2++;
                }
            }
            if (ok == false) OkTile = -1;
            else OkTile = TileNumber;
            return OkTile; // tells if same thing or not
        }

        Int32 CompareVFlip(int CurrentPos, int firstcol)
        {
            int tile = 0;
            Int32 TileNumber = -1;
            Int32 OkTile = -1; // wrong number by default
            Int32 temppixel;
            bool ok = false;
            int tempx2 = 0, tempy2 = 7;
            int i, j;
            int BigY;
            for (tile = 0; (tile < NTilesInfo[2, firstcol]) && !ok; tile++)
            //for (TileNumber = 0; (TileNumber < Background.NTiles) && !ok; TileNumber++)
            {
                ok = true; // true by default, proove it wrong
                TileNumber = (Int32)TilesInfo[2, firstcol, tile];

                // Writes the tile...
                temppixel = TileNumber * 8 * 8; // Taille des blocs...
                tempx2 = 0;
                tempy2 = 7;

                for (i = 0; (i < 8) && ok; i++) // On fait le bloc de 0...
                {
                    tempx2 = 0;
                    BigY = (tempy2 * swidth);
                    for (j = 0; (j < 8) && ok; j++)
                    {
                        ok = (Background.Tiles[temppixel] == buffer[CurrentPos + tempx2 + BigY]);
                        temppixel++;
                        tempx2++;
                    }
                    tempy2--;
                }
//                if (OkTile != -1) ok = true; 
            }
            if (ok == false) OkTile = -1;
            else OkTile = TileNumber;
            return OkTile; // tells if same thing or not
        }

        Int32 CompareHVFlip(int CurrentPos, int firstcol)
        {
            int tile = 0;
            Int32 TileNumber = -1;
            Int32 OkTile = -1; // wrong number by default
            Int32 temppixel;
            bool ok = false;
            int BigY;
            for (tile = 0; (tile < NTilesInfo[3, firstcol]) && !ok; tile++)
            {
                ok = true; // true by default, proove it wrong
                TileNumber = (Int32)TilesInfo[3, firstcol, tile];
                //OkTile = (Int32)TileNumber; // still running

                // Writes the tile...
                temppixel = TileNumber * 8 * 8; // Taille des blocs...
                int tempx2 = 7, tempy2 = 7;
                int i, j;
                for (i = 0; (i < 8) && ok; i++) // On fait le bloc de 0...
                {
                    tempx2 = 7;
                    BigY = (tempy2 * swidth);
                    for (j = 0; (j < 8) && ok; j++)
                    {
                        ok = (Background.Tiles[temppixel] == buffer[CurrentPos + tempx2 + BigY]);
                        temppixel++;
                        tempx2--;
                    }
                    tempy2--;
                }
            }
            if (ok == false) OkTile = -1;
            else OkTile = TileNumber;
            return OkTile; // tells if same thing or not
        }

        void CreateMapTiledBg()
        {
            buffer = new UInt16[swidth * sheight]; // Tableau pour remplir le sprite
            Background.Tiles = new UInt32[swidth * sheight]; // Final background!
            
            //      TilesInfo[,,] // first col of tiles
            int i, j;
            for (i = 0; i < 4; i++)
                for (j = 0; j < 256; j++)
                    NTilesInfo[i, j] = 0; // NO tiles by default

            int palette = Background.NPalette; // Palette

            int tempheight = sheight >> 3; int tempwidth = swidth >> 3;
            Background.Map = new UInt32[tempwidth * tempheight]; // Final background!

            int pixel = 0;
            Background.NTiles = 0; // A la base, pas de tiles...
            
            Init8bitBuffer(palette);

            // Map layout
            int position = 0;

            int Pos;

            for (y = 0; y < sheight; y += 8)// Blocs de 8x8
            {
                for (x = 0; x < swidth; x += 8)// Idem
                {
                    int tempy;

                    int tile = -1;
                    Pos = x + (y * swidth);

                    HFlip = 0; VFlip = 0; // No flip first
                    tile = CompareNorm(Pos, buffer[Pos]);
                    if ((tile == -1) && (Background.BgMode != 3)) // Flip inactivated for rotbg...
                    {
                        HFlip = 1; // Now we'll test for HFlip
                        tile = CompareHFlip(Pos, buffer[Pos]);
                        if (tile == -1)
                        {
                            HFlip = 0; VFlip = 1;
                            tile = CompareVFlip(Pos, buffer[Pos]);
                            if (tile == -1)
                            {
                                HFlip = 1; VFlip = 1;
                                tile = CompareHVFlip(Pos, buffer[Pos]);
                            }
                        }

                    }
                    if (tile == -1) // new tile...
                    {
                        tile = Background.NTiles;

                        // No flip tile
                        TilesInfo[0, buffer[Pos], NTilesInfo[0, buffer[Pos]]] = (UInt32)tile; // New tile in the array
                        NTilesInfo[0, buffer[Pos]]++; // One more tile in that category...
                        // Hflip tile
                        TilesInfo[1, buffer[Pos + 7], NTilesInfo[1, buffer[Pos + 7]]] = (UInt32)tile;
                        NTilesInfo[1, buffer[Pos + 7]]++;
                        Pos = x + ((y + 7) * swidth);
                        // Vflip tile
                        TilesInfo[2, buffer[Pos], NTilesInfo[2, buffer[Pos]]] = (UInt32)tile;
                        NTilesInfo[2, buffer[Pos]]++;
                        // HVflip tile
                        TilesInfo[3, buffer[Pos + 7], NTilesInfo[3, buffer[Pos + 7]]] = (UInt32)tile;
                        NTilesInfo[3, buffer[Pos + 7]]++;


                        // Writes the tile...
                        for (tempy = 0; tempy < 8; tempy++) // On fait le bloc de 0...
                        {
                            Pos = x + ((y + tempy) * swidth);
                            Background.Tiles[pixel] = buffer[Pos];
                            Background.Tiles[pixel + 1] = buffer[Pos + 1];
                            Background.Tiles[pixel + 2] = buffer[Pos + 2];
                            Background.Tiles[pixel + 3] = buffer[Pos + 3];
                            Background.Tiles[pixel + 4] = buffer[Pos + 4];
                            Background.Tiles[pixel + 5] = buffer[Pos + 5];
                            Background.Tiles[pixel + 6] = buffer[Pos + 6];
                            Background.Tiles[pixel + 7] = buffer[Pos + 7];
                            pixel += 8;
                        }



                        Background.NTiles++;
                        HFlip = 0; VFlip = 0; // par défaut, pas de flip

                    }

                    // Check for infinite or normal mode...
                    //   if (Background.BgMode == 5) Background.Map[position] = (UInt32)(tile + (HFlip << 29) + (VFlip << 30));   // Last 2 bits for flips...
                    Background.Map[position] = (UInt32)(tile + (HFlip << 29) + (VFlip << 30));   // Last 2 bits for flips...
                    //   else Background.Map[position] = (UInt16)(tile + (HFlip << 10) + (VFlip<< 11)); 
                    position++;

                }
            }

            // Check if TiledBg->LargeMap->InfiniteMap ?
            // Switch to LargeMap if too big...
            if ((Background.BgMode == 2) && ((swidth > 512) || (sheight > 512))) Background.BgMode = 4;
            // Switch to Infinite if needed
            if ((Background.BgMode == 4) && (Background.NTiles >= 1008)) Background.BgMode = 5;

            if (oldmode != Background.BgMode)
            {
                string[] BgModes = new string[7];
                BgModes[0] = "8bit";
                BgModes[1] = "16bit";
                BgModes[2] = "TileBg";
                BgModes[3] = "RotBg";
                BgModes[4] = "LargeMap";
                BgModes[5] = "InfiniteMap";
                BgModes[6] = "EasyBg";
//                PAGfxWrite("Converted to " + BgModes[Background.BgMode] + ", ");
            }
            

            // Et enfin, on écrit le fichier !!
/*            FileStream tilefile, binfile, infofile; // Permet de faire le fichier
            BinaryWriter tilewriter;
            string tempstring, binstring, infostring;

            tempstring = Background.Name + ".c";
            binstring = "bin/" + Background.Name + "_Map.bin";
            infostring = "bin/" + Background.Name + "_Info.bin";

            tilefile = new FileStream(tempstring, FileMode.Create); // Créé le fichier
            tilewriter = new BinaryWriter(tilefile);  // Permet d'écrire dedans
            binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
*/            binWriter = new BinaryWriter(map_bytes);  // Permet d'écrire dedans
            
/*            tilewriter.Write(Encoding.UTF8.GetBytes("//Background converted using Mollusk's PAGfx Converter\r\n//This Background uses " + Palette[palette].Name + "_Pal\r\n\r\n"));
            //        tilewriter.Write(Encoding.UTF8.GetBytes("const int "+ Background.Name + "_Width = " + swidth + ";\r\n"));
            //        tilewriter.Write(Encoding.UTF8.GetBytes("const int "+ Background.Name + "_Height = " + sheight + ";\r\n\r\n"));
            tilewriter.Write(Encoding.UTF8.GetBytes("const int " + Background.Name + "_Info[3] = {" + Background.BgMode + ", " + swidth + ", " + sheight + "}; // BgMode, Width, Height\r\n\r\n"));


            infofile = new FileStream(infostring, FileMode.Create); // Créé le fichier
            infoWriter = new BinaryWriter(infofile);  // Permet d'écrire dedans
            infoWriter.Write((UInt32)(Background.BgMode));  // First : BgMode
            infoWriter.Write((UInt32)(swidth));  // Second : Width
            infoWriter.Write((UInt32)(sheight));  // Third : Height
*/
            // Write the map.....
            int maxj = tempwidth * tempheight;

/*            string namestring = "#include " + '"' + tempstring + '"' + "\r\n";

            cwriter.Write(Encoding.UTF8.GetBytes(namestring));

            //      hwriter.Write(Encoding.UTF8.GetBytes("extern const int " + Background.Name + "_Width, "+ Background.Name + "_Height;\r\n"));
            hwriter.Write(Encoding.UTF8.GetBytes("extern const int " + Background.Name + "_Info[3]; // BgMode, Width, Height\r\n"));

            if (Background.BgMode == 3)// Rotbg, en char au lieu de short
            {
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned char " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
                tempstring = "const unsigned char " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            }
            else if (Background.BgMode == 5)
            {
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned int " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
                tempstring = "const unsigned int " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            }
            else
            { // Tiled/Largemap, convert to u16 format
                uint flip;
                for (position = 0; position < maxj; position++)
                {
                    flip = Background.Map[position] >> 29;
                    Background.Map[position] = (Background.Map[position] & 1023) + (flip << 10);
                }
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned short " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
                tempstring = "const unsigned short " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            }
*/
            WriteData16bit(null, binWriter, null, Background.Map, maxj);
/*
            if (Background.BgMode == 3)
            { // RotBg
                WriteData8bit(tilewriter, binWriter, tempstring, Background.Map, maxj);
            }
            else if (Background.BgMode == 4) // LargeMap
            {
                WriteData16bit(tilewriter, binWriter, tempstring, Background.Map, maxj);
            }
            else if (Background.BgMode == 5) // InfiniteMap
            {
                WriteData32bit(tilewriter, binWriter, tempstring, Background.Map, maxj);
            }
            else if (Background.BgMode == 2) // Si TiledBg, optimiser pour DMACopy...
            {
                tilewriter.Write(Encoding.UTF8.GetBytes(tempstring));
                j = 0;
                int xlimit = 256; if (swidth > 256) xlimit = 512;
                int ylimit = 256; if (sheight > 256) ylimit = 512;
                int xtemp, ytemp;

                int limitx = xlimit >> 3; int limity = ylimit >> 3;

                Console.WriteLine(limitx + ", " + limity);
                for (ytemp = 0; ytemp < limity; ytemp += 32)
                {
                    for (xtemp = 0; xtemp < limitx; xtemp += 32)
                    {
                        for (y = ytemp; (y < 32 + ytemp) && (y < tempheight); y++)
                        {
                            //Console.WriteLine(y + "/" + tempheight);
                            for (x = xtemp; (x < 32 + xtemp) && (x < tempwidth); x++)
                            {
                                j = x + (y * limitx);
                                if (j < maxj - 1)
                                {
                                    //Console.Write(j+", ");
                                    tilewriter.Write(Encoding.UTF8.GetBytes(Background.Map[j] + ", "));
                                    binWriter.Write((short)(Background.Map[j] & 65535));
                                    if (((j + 1) & 15) == 0) tilewriter.Write(Encoding.UTF8.GetBytes("\r\n"));
                                }
                            }
                        }
                    }
                }
                tilewriter.Write(Encoding.UTF8.GetBytes(Background.Map[maxj - 1] + "\r\n};\r\n\r\n"));
                binWriter.Write((short)(Background.Map[maxj - 1] & 65535));
            }

            // Close Map files, on to Tile files...
            binfile.Close(); // Libère la mémoire
            binWriter.Close();

            // On to the tiles...
            binstring = "bin/" + Background.Name + "_Tiles.bin";
            binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
*/            binWriter = new BinaryWriter(tiles_bytes);  // Permet d'écrire dedans

            // Write the tiles.....
            maxj = Background.NTiles * 8 * 8;
/*            hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned char " + Background.Name + "_Tiles[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n\r\n"));

            tempstring = "const unsigned char " + Background.Name + "_Tiles[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
*/
            WriteData8bit(null, binWriter, null, Background.Tiles, maxj);
/*
            PAGfxWriteLine(Background.NTiles + " tiles -> " + Background.Name + "_Tiles and " + Background.Name + "_Map");

            tilefile.Close(); // Libère la mémoire
            tilewriter.Close();
            binfile.Close(); // Libère la mémoire
            binWriter.Close();*/
        }

        void CreateTiledBg()
        {
            buffer = new UInt16[swidth * sheight]; // Tableau pour remplir le sprite
            Background.Tiles = new UInt32[swidth * sheight]; // Final background!

              //      TilesInfo[,,] // first col of tiles
            int i, j;
            for (i = 0; i < 4; i++)
                for (j = 0; j < 256; j++)
                    NTilesInfo[i, j] = 0; // NO tiles by default

            int palette = Background.NPalette; // Palette

            int tempheight = sheight >> 3; int tempwidth = swidth >> 3; 
            Background.Map = new UInt32[tempwidth * tempheight]; // Final background!

            int pixel = 0;
            Background.NTiles = 0; // A la base, pas de tiles...

            Init8bitBuffer(palette);

            // Map layout
            int position = 0;

            int Pos;

#if (!VERSION_LINUX)
            int pourcentage = 0;
            bool dopourcentage = false;
            if (swidth * sheight > 512 * 512)
            {
                dopourcentage = true;
                Console.WriteLine(" ");
                Console.Write("Optimising tiles : 0%...");
            }
#endif

            for (y = 0; y < sheight; y += 8)// Blocs de 8x8
            {
                for (x = 0; x < swidth; x += 8)// Idem
                {
                    int tempy;

                    int tile = -1;
                    Pos = x + (y * swidth);
                    
                    HFlip = 0; VFlip = 0; // No flip first
                    tile = CompareNorm(Pos, buffer[Pos]);
                    if ((tile == -1) && (Background.BgMode != 3)) // Flip inactivated for rotbg...
                    {
                        HFlip = 1; // Now we'll test for HFlip
                        tile = CompareHFlip(Pos, buffer[Pos]);
                        if (tile == -1)
                        {
                            HFlip = 0; VFlip = 1;
                            tile = CompareVFlip(Pos, buffer[Pos]);
                            if (tile == -1)
                            {
                                HFlip = 1; VFlip = 1;
                                tile = CompareHVFlip(Pos, buffer[Pos]);
                            }
                        }

                    }
                    if (tile == -1) // new tile...
                    {
                        tile = Background.NTiles;

                        // No flip tile
                        TilesInfo[0, buffer[Pos], NTilesInfo[0, buffer[Pos]]] = (UInt32)tile; // New tile in the array
                        NTilesInfo[0, buffer[Pos]]++; // One more tile in that category...
                        // Hflip tile
                        TilesInfo[1, buffer[Pos+7], NTilesInfo[1, buffer[Pos+7]]] = (UInt32)tile; 
                        NTilesInfo[1, buffer[Pos+7]]++;
                        Pos = x + ((y + 7) * swidth);
                        // Vflip tile
                        TilesInfo[2, buffer[Pos], NTilesInfo[2, buffer[Pos]]] = (UInt32)tile;
                        NTilesInfo[2, buffer[Pos]]++;
                        // HVflip tile
                        TilesInfo[3, buffer[Pos + 7], NTilesInfo[3, buffer[Pos + 7]]] = (UInt32)tile;
                        NTilesInfo[3, buffer[Pos + 7]]++; 


                        // Writes the tile...
                        for (tempy = 0; tempy < 8; tempy++) // On fait le bloc de 0...
                        {
                            Pos = x + ((y+tempy) * swidth);
                            Background.Tiles[pixel] = buffer[Pos];
                            Background.Tiles[pixel + 1] = buffer[Pos + 1];
                            Background.Tiles[pixel + 2] = buffer[Pos + 2];
                            Background.Tiles[pixel + 3] = buffer[Pos + 3];
                            Background.Tiles[pixel + 4] = buffer[Pos + 4];
                            Background.Tiles[pixel + 5] = buffer[Pos + 5];
                            Background.Tiles[pixel + 6] = buffer[Pos + 6];
                            Background.Tiles[pixel + 7] = buffer[Pos + 7];
                            pixel += 8;
                        }



                        Background.NTiles++;
                        HFlip = 0; VFlip = 0; // par défaut, pas de flip

                    }

                    // Check for infinite or normal mode...
                 //   if (Background.BgMode == 5) Background.Map[position] = (UInt32)(tile + (HFlip << 29) + (VFlip << 30));   // Last 2 bits for flips...
                    Background.Map[position] = (UInt32)(tile + (HFlip << 29) + (VFlip << 30));   // Last 2 bits for flips...
                 //   else Background.Map[position] = (UInt16)(tile + (HFlip << 10) + (VFlip<< 11)); 
                    position++;

                }
#if (!VERSION_LINUX)
                // Manage pourcentage...
                if (dopourcentage)
                {
                    Console.CursorLeft -= pourcentage.ToString().Length + 4;
                    pourcentage = y * 100 / height;
                    Console.Write(pourcentage + "%...");
                }
#endif
            }
#if (!VERSION_LINUX)
            if (dopourcentage)
            {
                Console.CursorLeft -= 6;
                Console.WriteLine("100% !   ");
            }
#endif


            // Check if TiledBg->LargeMap->InfiniteMap ?
                // Switch to LargeMap if too big...
            if ((Background.BgMode == 2) && ((swidth > 512) || (sheight > 512))) Background.BgMode = 4; 
                // Switch to Infinite if needed
            if ((Background.BgMode == 4) && (Background.NTiles >= 1008)) Background.BgMode = 5;

            if (oldmode != Background.BgMode)
            {
                string[] BgModes = new string[7];
                BgModes[0] = "8bit";
                BgModes[1] = "16bit";
                BgModes[2] = "TileBg";
                BgModes[3] = "RotBg";
                BgModes[4] = "LargeMap";
                BgModes[5] = "InfiniteMap";
                BgModes[6] = "EasyBg";
                PAGfxWrite("Converted to " + BgModes[Background.BgMode] + ", ");
            }


            // Et enfin, on écrit le fichier !!
            FileStream tilefile, binfile, infofile; // Permet de faire le fichier
            BinaryWriter tilewriter;
            string tempstring, binstring, infostring;

            tempstring = Background.Name + ".c";
            binstring = "bin/" + Background.Name + "_Map.bin";
            infostring = "bin/" + Background.Name + "_Info.bin";

            tilefile = new FileStream(tempstring, FileMode.Create); // Créé le fichier
            tilewriter = new BinaryWriter(tilefile);  // Permet d'écrire dedans
            binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
            binWriter = new BinaryWriter(binfile);  // Permet d'écrire dedans

            tilewriter.Write(Encoding.UTF8.GetBytes("//Background converted using Mollusk's PAGfx Converter\r\n//This Background uses " + Palette[palette].Name + "_Pal\r\n\r\n"));
    //        tilewriter.Write(Encoding.UTF8.GetBytes("const int "+ Background.Name + "_Width = " + swidth + ";\r\n"));
    //        tilewriter.Write(Encoding.UTF8.GetBytes("const int "+ Background.Name + "_Height = " + sheight + ";\r\n\r\n"));
            tilewriter.Write(Encoding.UTF8.GetBytes("const int " + Background.Name + "_Info[3] = {" + Background.BgMode+ ", " + swidth + ", " + sheight + "}; // BgMode, Width, Height\r\n\r\n"));


            infofile = new FileStream(infostring, FileMode.Create); // Créé le fichier
            infoWriter = new BinaryWriter(infofile);  // Permet d'écrire dedans
            infoWriter.Write((UInt32)(Background.BgMode));  // First : BgMode
            infoWriter.Write((UInt32)(swidth));  // Second : Width
            infoWriter.Write((UInt32)(sheight));  // Third : Height

            // Write the map.....
            int maxj = tempwidth * tempheight;

            string namestring = "#include " + '"' + tempstring + '"' + "\r\n";

            cwriter.Write(Encoding.UTF8.GetBytes(namestring));

      //      hwriter.Write(Encoding.UTF8.GetBytes("extern const int " + Background.Name + "_Width, "+ Background.Name + "_Height;\r\n"));
            hwriter.Write(Encoding.UTF8.GetBytes("extern const int " + Background.Name + "_Info[3]; // BgMode, Width, Height\r\n"));

            if (Background.BgMode == 3)// Rotbg, en char au lieu de short
            {
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned char " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
                tempstring = "const unsigned char " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            }
            else if (Background.BgMode == 5)
            {
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned int " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
                tempstring = "const unsigned int " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            }
            else { // Tiled/Largemap, convert to u16 format
                uint flip;
                for (position = 0; position < maxj; position++)
                {
                    flip = Background.Map[position] >> 29;
                    Background.Map[position] = (Background.Map[position] & 1023) + (flip << 10);
                }
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned short " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n"));
                tempstring = "const unsigned short " + Background.Name + "_Map[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";
            }


            if (Background.BgMode == 3){ // RotBg
                WriteData8bit(tilewriter, binWriter, tempstring, Background.Map, maxj);
            }
            else if (Background.BgMode == 4) // LargeMap
            {
                WriteData16bit(tilewriter, binWriter, tempstring, Background.Map, maxj);
            }
            else if (Background.BgMode == 5) // InfiniteMap
            {
//                WriteData32bit(tilewriter, binWriter, tempstring, Background.Map, maxj);
            }
            else if (Background.BgMode == 2) // Si TiledBg, optimiser pour DMACopy...
            {
                tilewriter.Write(Encoding.UTF8.GetBytes(tempstring));
                j = 0;
                int xlimit = 256; if (swidth > 256) xlimit = 512;
                int ylimit = 256; if (sheight > 256) ylimit = 512;
                int xtemp, ytemp;

                int limitx = xlimit >> 3; int limity = ylimit >> 3;

                Console.WriteLine(limitx + ", " + limity);
                for (ytemp = 0; ytemp < limity; ytemp += 32)
                {
                    for (xtemp = 0; xtemp < limitx; xtemp += 32)
                    {
                        for (y = ytemp; (y < 32 + ytemp) && (y < tempheight); y++)
                        {
                            //Console.WriteLine(y + "/" + tempheight);
                            for (x = xtemp; (x < 32 + xtemp) && (x < tempwidth); x++)
                            {
                                j = x + (y * limitx);
                                if (j < maxj - 1)
                                {
                                    //Console.Write(j+", ");
                                    tilewriter.Write(Encoding.UTF8.GetBytes(Background.Map[j] + ", "));
                                    binWriter.Write((short)(Background.Map[j] & 65535));
                                    if (((j + 1) & 15) == 0) tilewriter.Write(Encoding.UTF8.GetBytes("\r\n"));
                                }
                            }
                        }
                    }
                }
                tilewriter.Write(Encoding.UTF8.GetBytes(Background.Map[maxj - 1] + "\r\n};\r\n\r\n"));
                binWriter.Write((short)(Background.Map[maxj - 1] & 65535));
            }

            // Close Map files, on to Tile files...
            binfile.Close(); // Libère la mémoire
            binWriter.Close();

            // On to the tiles...
            binstring = "bin/" + Background.Name + "_Tiles.bin";
            binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
            binWriter = new BinaryWriter(binfile);  // Permet d'écrire dedans

            // Write the tiles.....
            maxj = Background.NTiles*8*8;
            hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned char " + Background.Name + "_Tiles[" + maxj + "] __attribute__ ((aligned (4))) ;  // Pal : " + Palette[palette].Name + "_Pal\r\n\r\n"));

            tempstring = "const unsigned char " + Background.Name + "_Tiles[" + maxj + "] __attribute__ ((aligned (4))) = {\r\n";

            WriteData8bit(tilewriter, binWriter, tempstring, Background.Tiles, maxj);

            PAGfxWriteLine(Background.NTiles + " tiles -> " + Background.Name + "_Tiles and " + Background.Name + "_Map");

            tilefile.Close(); // Libère la mémoire
            tilewriter.Close();
            binfile.Close(); // Libère la mémoire
            binWriter.Close();
        }

        bool CompareFlipT(int CurrentPos, int TileNumber)
        {
            // Writes the tile...
            Int32 temppixel = TileNumber * 8 * 8; // Taille des blocs...
            int tempx2 = 0, tempy2 = 0;
            bool ok = true; // Par défaut, c'est la meme...

            int addx = 1; if (HFlip == 1) { addx = -1; tempx2 = 7; }
            int addy = 1; if (VFlip == 1) { addy = -1; tempy2 = 7; }
            int i, j;

            for (i = 0; (i < 8) && ok; i++) // On fait le bloc de 0...
            {
               if (HFlip == 1) tempx2 = 7;
                else tempx2 = 0;
                for (j = 0; (j < 8) && ok; j++)
                {
                    if (Background.Tiles[temppixel] != buffer[CurrentPos + tempx2 + (tempy2 * swidth)])
                    {
                        ok = false; // pas bon !!
                    }
                    temppixel++;
                    tempx2 += addx;
                    //CurrentPos++;
                }
                tempy2 += addy;
            }
            return ok; // tells if same thing or not
        }

        bool CompareTile(int CurrentPos, int TileNumber)
        {
            bool ok = false; // Par défaut, c'est la meme...
            //bool flip = false;

            HFlip = 0; VFlip = 0; // No flip yet          {
            ok = CompareFlipT(CurrentPos, TileNumber);

            if (Background.BgMode != 3)  // En rotscale, pas de tiles...
            {
                if (ok) return ok;  // Found a match, quit searching ! 

                HFlip = 1;
                ok = CompareFlipT(CurrentPos, TileNumber);
                if (ok) return ok;  // Found a match, quit searching ! 

                VFlip = 1;
                ok = CompareFlipT(CurrentPos, TileNumber);
                if (ok) return ok;  // Found a match, quit searching ! 

                HFlip = 0;
                ok = CompareFlipT(CurrentPos, TileNumber);


            }
            return ok;  // Found a match, quit searching ! 
        }

        #endregion

        // Gets the palette, sprite, and Bg infos
        int GetPal(string PalName)
        {
            int PalNumber = 0;
            bool PalExists = false; // You have to create it by default...
            for (int i = 0; (i < NPalettes) && !PalExists; i++)
            {
                if (PalName == Palette[i].Name)
                {
                    PalExists = true; // The palette exists...
                    PalNumber = i; // Palette number !
                }
            }
            if (!PalExists) // You have to create the palette...
            {
                PalNumber = NPalettes; // New palette number
                Palette[NPalettes].Name = PalName;
                Palette[NPalettes].NColors = 1; // Only one color, the transp color...
                Palette[NPalettes].Colors = new UInt16[256]; // 256 colors...
                Palette[NPalettes].OkColors = new int[32 * 32 * 32 * 2]; // All colors
                for (int j = 0; j < 32 * 32 * 32 * 2; j++) Palette[PalNumber].OkColors[j] = -1;
                Palette[NPalettes].OkColors[TranspColor.Color] = 0; // First color...
                Palette[NPalettes].Colors[0] = TranspColor.Color;   // First color...
                NPalettes++; // one more palette !
                //PAGfxWriteLine("New palette : " + PalName);
            }
            return PalNumber;
        }

        void WriteData8bit(BinaryWriter Writer, BinaryWriter binWriter, string tempstring, UInt32[] Data, int maxj)
        {
//            Writer.Write(Encoding.UTF8.GetBytes(tempstring));
          //  byte reduce;
           // uint reduce2;
            for (UInt32 j = 0; j < maxj - 1; j++) // On ajoute les données
            {
//                Writer.Write(Encoding.UTF8.GetBytes(Data[j] + ", "));
         //       reduce = (byte)(Data[j]);
               // reduce2 = reduce;
                binWriter.Write((byte)(Data[j]));
                //Console.WriteLine("after bin");   
              //  string test = Encoding.UTF8.GetBytes(Data[j]);
            /*    if (j == 1908)
                {
                    Console.WriteLine("1908 : " + Data[j] + " vs " + test);
                    Console.ReadKey();
            }*/
//                if (((j + 1) & 15) == 0) Writer.Write(Encoding.UTF8.GetBytes("\r\n"));
            }
//            Writer.Write(Encoding.UTF8.GetBytes(Data[maxj - 1] + "\r\n};\r\n\r\n"));
          //  reduce = (byte)(Data[maxj - 1]);
         //   reduce2 = reduce;
            binWriter.Write((byte)(Data[maxj - 1]));
        }

        void WriteData16bit(BinaryWriter Writer, BinaryWriter binWriter, string tempstring, UInt32[] Data, int maxj)
        {
//            Writer.Write(Encoding.UTF8.GetBytes(tempstring));
            for (UInt32 j = 0; j < maxj - 1; j++) // On ajoute les données
            {
//                Writer.Write(Encoding.UTF8.GetBytes(Data[j] + ", "));
                binWriter.Write((short)(Data[j] & 65535));
//                if (((j + 1) & 15) == 0) Writer.Write(Encoding.UTF8.GetBytes("\r\n"));
            }
//            Writer.Write(Encoding.UTF8.GetBytes(Data[maxj - 1] + "\r\n};\r\n\r\n"));
            binWriter.Write((short)(Data[maxj - 1] & 65535));
        }

        // For paletted sprites/bg
        void Init8bitBuffer(int palette) // S'occupe de faire tous les buffers 8bit
        {
            UInt16 TempColor;
            // On vide la mémoire du sprite...
            for (y = height; y < sheight; y++)
                for (x = 0; x < width; x++ )
                    buffer[x + (y * swidth)] = 0;
            for (y = 0; y < sheight; y++) 
                for (x = width; x < swidth; x++)  
                    buffer[x + (y*swidth)] = 0;
            /*
            int pourcentage = 0;
            bool dopourcentage = false;
            if (width * height > 512 * 512)
            {
                dopourcentage = true;
                Console.WriteLine(" ");
                Console.Write("Creating palette : 0%...");
            }*/


            Rectangle rect = new Rectangle(0, 0, readBitmap.Width, readBitmap.Height);
            System.Drawing.Imaging.BitmapData bmpData = readBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format16bppRgb555); // directly in 555 pixel format !

            UInt16* ptr = (UInt16*) bmpData.Scan0.ToPointer();
            
          //  int[] RGB = new int[readBitmap.Width * readBitmap.Height];
          //  System.Runtime.InteropServices.Marshal.Copy(ptr, RGB, 0, readBitmap.Width * readBitmap.Height);



            UInt32 pixel = 0;

            // On va tout d'abord copier le sprite dans un tableau, puis on fera les tiles
            for (y = 0; y < height; y++)
            {
                for (x = 0; x < width; x++)
                { // Pour chaque pixel, on extrait les valeurs RGB...
                    /*Color c = readBitmap.GetPixel(x, y);
                    
                    TempColor = (UInt16)PA_RGB8(c.R, c.G, c.B);*/
                    TempColor = *(UInt16*)(ptr + pixel);
                    int col1 = TempColor >> 10;
                    int col2 = TempColor >> 5;
                    TempColor = (ushort)((col1 & 31) + ((col2 & 31) << 5) + ((TempColor & 31) << 10) | (1 << 15));
                  //  TempColor |= (1 << 15);
                  //  Console.WriteLine(TempColor);

                    if (Palette[palette].OkColors[TempColor] != -1)
                    { // La couleur est déjà là...
                        buffer[x + (y * swidth)] = (byte)Palette[palette].OkColors[TempColor];
                        // Couleur
                    }
                    else // La couleur n'existe pas encore dans la palette !
                    {
                        buffer[x + (y * swidth)] = (byte)AddColorToPalette(palette, TempColor);
                    }

                    pixel++;
                }

               /* if (dopourcentage)
                {
                    Console.CursorLeft -= pourcentage.ToString().Length + 4;
                    pourcentage = y * 100 / height;
                    Console.Write(pourcentage+"%...");     
                }*/
            }/*
            if (dopourcentage)
            {
                Console.CursorLeft -= 6;
                Console.Write("100% !       ");
            }*/
        }

        UInt16 AddColorToPalette(int palette, UInt16 color)
        {
            try
            {
                Palette[palette].OkColors[color] = Palette[palette].NColors;
                Palette[palette].Colors[Palette[palette].NColors] = color;
                Palette[palette].NColors++; // Une couleur de plus
                return ((byte)Palette[palette].OkColors[color]); 
            }
            catch
            {
//                PAGfxWriteLine("\r\n Error : Palette " + Palette[palette].Name + " has more than 256 colors. Please use some different palettes or reduce your file's color depth");
//                PAGfxWriteLine("Press any key to exit...");
//                Console.ReadKey();
                //Application.Exit();
                MessageBox.Show("Error: too many colors in the palette");
            }

            //Palette[palette].Colors[Palette[palette].NColors] = color;

            return 0;
        }

        public void WriteMinimapPalette()
        {
            //            FileStream palfile, binfile; // Permet de faire le fichier
            //BinaryWriter palwriter; 
            //            string tempstring, binstring;
            //            byte[] tempbyte;

            uint i = 0;
//            for (uint i = 0; i < NPalettes; i++)
            { // pour chaque palette désirée
                /*                tempstring = Palette[i].Name + ".pal.c";
                                binstring = "bin/" + Palette[i].Name + "_Pal.bin";
                                string namestring = "#include " + '"' + tempstring + '"' + "\r\n";
                                cwriter.Write(Encoding.UTF8.GetBytes(namestring));
                                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned short " + Palette[i].Name + "_Pal[" + Palette[i].NColors + "] __attribute__ ((aligned (4))) ;\r\n"));

                                palfile = new FileStream(tempstring, FileMode.Create); // Créé le fichier
                                palwriter = new BinaryWriter(palfile);  // Permet d'écrire dedans
                                binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
                */
                binWriter = new BinaryWriter(minimap_pal_bytes);  // Permet d'écrire dedans

                /*                palwriter.Write(Encoding.UTF8.GetBytes("//Palette created using Mollusk's PAGfxConverter\r\n\r\n"));

                                tempstring = "const unsigned short " + Palette[i].Name + "_Pal[" + Palette[i].NColors + "] __attribute__ ((aligned (4))) = {\r\n";
                                PAGfxWrite("  " + Palette[i].Name + "_Pal, " + Palette[i].NColors + " colors\r\n");
                */
                for (int j = 0; j < Palette[i].NColors; j++) // On ajoute les couleurs...
                {
                    //                    tempstring = tempstring + Palette[i].Colors[j];
                    binWriter.Write((short)(Palette[i].Colors[j] & 65535));
                    //                    if (j < Palette[i].NColors - 1) tempstring = tempstring + ", ";
                }
                //                palwriter.Write(Encoding.UTF8.GetBytes(tempstring));

                if ((Palette[i].NColors % 2) != 0) binWriter.Write((short)0);

                // palwriter.Write(" ");
                //                tempbyte = Encoding.UTF8.GetBytes("};\r\n");
                /*                palwriter.Write(tempbyte);
                                palwriter.Close();
                                palfile.Close();
                                binfile.Close();
                                binWriter.Close();*/
            }
        }

        public void WriteMapPalette(){
//            FileStream palfile, binfile; // Permet de faire le fichier
            //BinaryWriter palwriter; 
//            string tempstring, binstring;
//            byte[] tempbyte;

            uint i = 1;
//            for (uint i = 0; i < NPalettes; i++)
            { // pour chaque palette désirée
/*                tempstring = Palette[i].Name + ".pal.c";
                binstring = "bin/" + Palette[i].Name + "_Pal.bin";
                string namestring = "#include " + '"' + tempstring + '"' + "\r\n";
                cwriter.Write(Encoding.UTF8.GetBytes(namestring));
                hwriter.Write(Encoding.UTF8.GetBytes("extern const unsigned short " + Palette[i].Name + "_Pal[" + Palette[i].NColors + "] __attribute__ ((aligned (4))) ;\r\n"));

                palfile = new FileStream(tempstring, FileMode.Create); // Créé le fichier
                palwriter = new BinaryWriter(palfile);  // Permet d'écrire dedans
                binfile = new FileStream(binstring, FileMode.Create); // Créé le fichier
*/                binWriter = new BinaryWriter(map_pal_bytes);  // Permet d'écrire dedans

/*                palwriter.Write(Encoding.UTF8.GetBytes("//Palette created using Mollusk's PAGfxConverter\r\n\r\n"));

                tempstring = "const unsigned short " + Palette[i].Name + "_Pal[" + Palette[i].NColors + "] __attribute__ ((aligned (4))) = {\r\n";
                PAGfxWrite("  " + Palette[i].Name + "_Pal, " + Palette[i].NColors + " colors\r\n");
*/
                for (int j = 0; j < Palette[i].NColors; j++) // On ajoute les couleurs...
                {
//                    tempstring = tempstring + Palette[i].Colors[j];
                    binWriter.Write((short)(Palette[i].Colors[j] & 65535));
//                    if (j < Palette[i].NColors - 1) tempstring = tempstring + ", ";
                }
//                palwriter.Write(Encoding.UTF8.GetBytes(tempstring));

                if ((Palette[i].NColors % 2) != 0) binWriter.Write((short)0);

                // palwriter.Write(" ");
//                tempbyte = Encoding.UTF8.GetBytes("};\r\n");
/*                palwriter.Write(tempbyte);
                palwriter.Close();
                palfile.Close();
                binfile.Close();
                binWriter.Close();*/
            }
        }

        void PAGfxWrite(string temp) // Writes the Log and on screen
        {
            Console.Write(temp);
        }

        void PAGfxWriteLine(string temp) // Writes the Log and on screen
        {
            Console.WriteLine(temp);
        }


    






    }
}
