Beispiel #1
0
        private void chooseTileset_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.Title           = "Select file";
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.CheckPathExists = true;

            openFileDialog1.Filter = "1PP tileset binary (*.tsb)|*.tsb";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                activeTsb           = new tsbfile();
                activeTsb.form1     = form1;
                activeTsb.filepath  = openFileDialog1.FileName;
                activeTsb.filebytes = File.ReadAllBytes(activeTsb.filepath);
                activeTsb.Load();
            }
        }
Beispiel #2
0
        private void importFromPNG_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.Title           = "Select image file";
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.CheckPathExists = true;

            openFileDialog1.Filter = "PNG image (*.png)|*.png";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                activeTsb            = new tsbfile();
                activeMpb            = new mpbfile();
                activeMpb.editorForm = this;

                Bitmap image = (Bitmap)Image.FromFile(openFileDialog1.FileName);

                //check dimensions
                if (image.Width % 8 != 0)
                {
                    MessageBox.Show("Image width must be a multiple of 8.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
                if (image.Height % 8 != 0)
                {
                    MessageBox.Show("Image height must be a multiple of 8.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                //check palette
                List <Color> palette = new List <Color>();

                for (int y = 0; y < image.Height; y++)
                {
                    for (int x = 0; x < image.Width; x++)
                    {
                        Color newColour = image.GetPixel(x, y);

                        if (!palette.Contains(newColour))
                        {
                            palette.Add(newColour);
                        }

                        if (palette.Count > 256)
                        {
                            MessageBox.Show("The image must not have more than 256 colours.", "Too many colours", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            return;
                        }
                    }
                }

                if (palette.Count < 256 && !palette.Contains(Color.FromArgb(0xFF, 0xFF, 0x00, 0xFF)) && !palette.Contains(Color.FromArgb(0x00, 0xFF, 0x00, 0xFF)))  //if there's space for it, sneakily add the magenta alpha anyway
                {
                    palette.Add(Color.FromArgb(0xFF, 0xFF, 0x00, 0xFF));
                }

                TSBAlphaColour = Color.FromArgb(0xFF, 0xFF, 0x00, 0xFF);

                MessageBox.Show("Alpha colour is enforced as RGB 0xFF00FF (a bright magenta). If you don't have this colour in your image, an unexpected colour may turn transparent in-game!", "Notice", MessageBoxButtons.OK, MessageBoxIcon.Information);

                //swap the alpha colour to the start

                for (int c = 0; c < palette.Count; c++)
                {
                    if ((palette[c].R & 0xF8) == (TSBAlphaColour.R & 0xF8) && (palette[c].G & 0xF8) == (TSBAlphaColour.G & 0xF8) && (palette[c].B & 0xF8) == (TSBAlphaColour.B & 0xF8))
                    {
                        //swap the first slot colour here, and put the alpha colour in the first slot instead
                        palette[c] = palette[0];
                        palette[0] = TSBAlphaColour;
                        break;
                    }
                }

                //truncate colours

                TSBAlphaColour = Color.FromArgb(0xFF, TSBAlphaColour.R & 0xF8, TSBAlphaColour.G & 0xF8, TSBAlphaColour.B & 0xF8);

                for (int c = 0; c < palette.Count; c++)
                {
                    palette[c] = Color.FromArgb(0xFF, palette[c].R & 0xF8, palette[c].G & 0xF8, palette[c].B & 0xF8);
                }

                //turn image into tiles

                activeTsb.palette = palette.ToArray();

                byte[] NBFCimage = (form1.ImageToNBFC(image, 8, activeTsb.palette));

                NBFCimage.Reverse();

                List <Tile> tiles = new List <Tile>();

                int width_in_tiles  = image.Width / 8;
                int height_in_tiles = image.Height / 8;

                int pos = 0;


                List <Tile> uniqueTiles = new List <Tile>();

                for (int y = 0; y < height_in_tiles; y++)
                {
                    for (int x = 0; x < width_in_tiles; x++)
                    {
                        //make a new tile from the current pos in the image
                        Tile newTile = new Tile();

                        for (int i = 7; i >= 0; i--)
                        {
                            Array.Copy(NBFCimage, pos + (image.Width * i), newTile.tileImage, 8 * i, 8);
                        }

                        //now that we have the tile, compare it to the other tiles

                        for (int t = 0; t < tiles.Count; t++)
                        {
                            if (tiles[t].hasSimilarTile)    //only use tiles that aren't already references to other tiles
                            {
                                continue;
                            }

                            int tileSimilarlity = AreTilesSimilar(newTile, tiles[t]);

                            if (tileSimilarlity > 0) //if they are similar (i.e. identical but one of them is a mirror of the other)
                            {
                                newTile.hasSimilarTile = true;
                                newTile.SimilarTile    = tiles[t];

                                if (tileSimilarlity == 1)   //then they are just the same tile
                                {
                                }
                                else if (tileSimilarlity == 2)   //then they are the same but one of them is X flipped
                                {
                                    newTile.flipX = true;
                                }
                                else if (tileSimilarlity == 3)   //then they are the same but one of them is Y flipped
                                {
                                    newTile.flipY = true;
                                }
                                else if (tileSimilarlity == 4)   //then they are the same but one of them is flipped on both X and Y
                                {
                                    newTile.flipX = true;
                                    newTile.flipY = true;
                                }
                                break;
                            }
                        }

                        if (!newTile.hasSimilarTile)
                        {
                            uniqueTiles.Add(newTile);
                        }

                        tiles.Add(newTile);
                        pos += 8;
                    }

                    if (pos % image.Width == 0)
                    {
                        pos += image.Width * 7;
                    }
                }

                //now we should have a list of tiles, some of which are mirrors of each other if applicable


                activeTsb.filebytes = new byte[0x200 + (uniqueTiles.Count * 64)];

                //now write palette to tsb

                for (int c = 0; c < palette.Count; c++)
                {
                    ushort ABGR1555Colour = form1.ColorToABGR1555(palette[c]);

                    activeTsb.filebytes[(c * 2)]     = (byte)ABGR1555Colour;
                    activeTsb.filebytes[(c * 2) + 1] = (byte)(ABGR1555Colour >> 8);
                }

                //now write tiles to tsb, but only the ones that are their own tile and not just referencing another one



                int tileWritingPos = 0x200;

                for (int t = 0; t < uniqueTiles.Count; t++)
                {
                    if (!uniqueTiles[t].hasSimilarTile)   //only process it if it's a master tile
                    {
                        foreach (Byte b in uniqueTiles[t].tileImage)
                        {
                            activeTsb.filebytes[tileWritingPos] = b;
                            tileWritingPos++;
                        }
                    }
                }

                //MPB

                activeMpb.filebytes = new byte[tiles.Count * 2];


                for (int t = 0; t < tiles.Count; t++)
                {
                    ushort tileDescriptor = 0;

                    if (tiles[t].hasSimilarTile)
                    {
                        //then write a reference to the similar tile instead

                        tileDescriptor = (ushort)uniqueTiles.IndexOf(tiles[t].SimilarTile);

                        if (tileDescriptor > 8191)
                        {    //if it's 8192 or above, start counting from zero again and set the third bit. Yeah it seems like this is what should happen anyway, but the third bit seemed to be doing weird things before, and this method works.
                            tileDescriptor -= 8192;
                            tileDescriptor |= 0x2000;
                        }

                        if (tiles[t].flipX)
                        {
                            tileDescriptor |= 0x4000;
                        }

                        if (tiles[t].flipY)
                        {
                            tileDescriptor |= 0x8000;
                        }
                    }
                    else    //otherwise, just write this tile normally
                    {
                        tileDescriptor = (ushort)uniqueTiles.IndexOf(tiles[t]);
                    }

                    activeMpb.filebytes[(t * 2)]     = (byte)tileDescriptor;
                    activeMpb.filebytes[(t * 2) + 1] = (byte)(tileDescriptor >> 8);
                }

                LoadBoth();
            }
        }