Beispiel #1
0
        static void Main(string[] args)
        {
            byte[]               art;
            ColorPalette         palette;
            List <MappingsFrame> map;
            List <DPLCFrame>     dplc;
            SpriteInfo           spriteInfo;

            LevelData.littleendian = false;
            LongOpt[] opts = new[] {
                new LongOpt("help", Argument.No, null, 'h'),
                new LongOpt("padding", Argument.Required, null, 'p'),
                new LongOpt("columns", Argument.Required, null, 'c'),
                new LongOpt("width", Argument.Required, null, 'w'),
                new LongOpt("background", Argument.Required, null, 'b'),
                new LongOpt("grid", Argument.No, null, 'g')
            };
            Getopt getopt     = new Getopt("SpriteSheetGen", args, Getopt.digest(opts), opts);
            int    padding    = 2;
            int    columns    = 8;
            int    width      = 0;
            bool   fixedwidth = false;
            int    gridsize   = -1;
            Color  background = Color.Transparent;
            int    opt        = getopt.getopt();

            while (opt != -1)
            {
                switch (opt)
                {
                case 'h':
                    Console.Write(Properties.Resources.HelpText);
                    return;

                case 'p':
                    padding = int.Parse(getopt.Optarg);
                    break;

                case 'c':
                    columns = int.Parse(getopt.Optarg);
                    break;

                case 'w':
                    width      = int.Parse(getopt.Optarg);
                    columns    = -1;
                    fixedwidth = true;
                    break;

                case 'g':
                    gridsize = 0;
                    break;

                case 'b':
                    if (getopt.Optarg.StartsWith("#"))
                    {
                        background = Color.FromArgb((int)(0xFF000000 | uint.Parse(getopt.Optarg.Substring(1), System.Globalization.NumberStyles.HexNumber)));
                    }
                    else
                    {
                        background = Color.FromName(getopt.Optarg.Replace(" ", ""));
                    }
                    break;
                }
                opt = getopt.getopt();
            }
            string filename;

            Console.Write("File: ");
            if (getopt.Optind == args.Length)
            {
                filename = Console.ReadLine();
            }
            else
            {
                filename = args[getopt.Optind];
                Console.WriteLine(filename);
            }
            filename = Path.GetFullPath(filename);
            Environment.CurrentDirectory = Path.GetDirectoryName(filename);
            spriteInfo = IniSerializer.Deserialize <SpriteInfo>(filename);
            if (spriteInfo.MappingsGame == EngineVersion.Invalid)
            {
                spriteInfo.MappingsGame = spriteInfo.Game;
            }
            if (spriteInfo.DPLCGame == EngineVersion.Invalid)
            {
                spriteInfo.DPLCGame = spriteInfo.Game;
            }
            MultiFileIndexer <byte> tiles = new MultiFileIndexer <byte>();

            foreach (SonicRetro.SonLVL.API.FileInfo file in spriteInfo.Art)
            {
                tiles.AddFile(new List <byte>(Compression.Decompress(file.Filename, spriteInfo.ArtCompression)), file.Offset);
            }
            art = tiles.ToArray();
            tiles.Clear();
            byte[] tmp = null;
            using (Bitmap palbmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
                palette = palbmp.Palette;
            for (int i = 0; i < 256; i++)
            {
                palette.Entries[i] = Color.Black;
            }
            foreach (PaletteInfo palent in spriteInfo.Palette)
            {
                tmp = File.ReadAllBytes(palent.Filename);
                SonLVLColor[] palfile;
                palfile = new SonLVLColor[tmp.Length / 2];
                for (int pi = 0; pi < tmp.Length; pi += 2)
                {
                    palfile[pi / 2] = new SonLVLColor(SonicRetro.SonLVL.API.ByteConverter.ToUInt16(tmp, pi));
                }
                for (int pa = 0; pa < palent.Length; pa++)
                {
                    palette.Entries[pa + palent.Destination] = palfile[pa + palent.Source].RGBColor;
                }
            }
            palette.Entries[0] = background;
            Dictionary <string, int> labels = new Dictionary <string, int>();

            tmp = null;
            switch (spriteInfo.MappingsFormat)
            {
            case MappingsFormat.Binary:
                tmp = File.ReadAllBytes(spriteInfo.MappingsFile);
                break;

            case MappingsFormat.ASM:
            case MappingsFormat.Macro:
                tmp = LevelData.ASMToBin(spriteInfo.MappingsFile, spriteInfo.MappingsGame, out labels);
                break;
            }
            map = MappingsFrame.Load(tmp, spriteInfo.MappingsGame, labels);
            if (!string.IsNullOrEmpty(spriteInfo.DPLCFile))
            {
                labels = new Dictionary <string, int>();
                tmp    = null;
                switch (spriteInfo.DPLCFormat)
                {
                case MappingsFormat.Binary:
                    tmp = File.ReadAllBytes(spriteInfo.DPLCFile);
                    break;

                case MappingsFormat.ASM:
                case MappingsFormat.Macro:
                    tmp = LevelData.ASMToBin(spriteInfo.DPLCFile, spriteInfo.DPLCGame, out labels);
                    break;
                }
                dplc = DPLCFrame.Load(tmp, spriteInfo.DPLCGame, labels);
            }
            else
            {
                dplc = null;
            }
            List <BitmapBits> spritesLow    = new List <BitmapBits>(map.Count);
            List <BitmapBits> spritesHigh   = new List <BitmapBits>(map.Count);
            List <BitmapBits> spritesMerged = new List <BitmapBits>(map.Count);
            List <Point>      offsets       = new List <Point>(map.Count);
            List <Point>      centers       = new List <Point>(map.Count);

            for (int i = 0; i < map.Count; i++)
            {
                if (map[i].TileCount == 0)
                {
                    //File.AppendAllText("log.txt", "Frame " + i + " empty.\r\n");
                    continue;
                }
                Sprite spr;
                if (dplc != null)
                {
                    spr = LevelData.MapFrameToBmp(art, map[i], dplc[i], spriteInfo.StartPalette);
                }
                else
                {
                    spr = LevelData.MapFrameToBmp(art, map[i], spriteInfo.StartPalette);
                }
                BitmapBits sprLow    = spr.GetBitmapLow();
                BitmapBits sprHigh   = spr.GetBitmapHigh();
                BitmapBits sprMerged = spr.GetBitmap();
                int        cx        = -spr.X;
                int        cy        = -spr.Y;
                for (int _x = 0; _x < sprMerged.Width; _x++)
                {
                    for (int _y = 0; _y < sprMerged.Height; _y++)
                    {
                        if (sprMerged[_x, _y] != 0)
                        {
                            sprMerged = sprMerged.GetSection(_x, 0, sprMerged.Width - _x, sprMerged.Height);
                            sprLow    = sprLow.GetSection(_x, 0, sprLow.Width - _x, sprLow.Height);
                            sprHigh   = sprHigh.GetSection(_x, 0, sprHigh.Width - _x, sprHigh.Height);
                            cx       -= _x;
                            goto checkright;
                        }
                    }
                }
checkright:
                for (int _x = sprMerged.Width - 1; _x >= 0; _x--)
                {
                    for (int _y = 0; _y < sprMerged.Height; _y++)
                    {
                        if (sprMerged[_x, _y] != 0)
                        {
                            sprMerged = sprMerged.GetSection(0, 0, _x + 1, sprMerged.Height);
                            sprLow    = sprLow.GetSection(0, 0, _x + 1, sprLow.Height);
                            sprHigh   = sprHigh.GetSection(0, 0, _x + 1, sprHigh.Height);
                            goto checktop;
                        }
                    }
                }
checktop:
                for (int _y = 0; _y < sprMerged.Height; _y++)
                {
                    for (int _x = 0; _x < sprMerged.Width; _x++)
                    {
                        if (sprMerged[_x, _y] != 0)
                        {
                            sprMerged = sprMerged.GetSection(0, _y, sprMerged.Width, sprMerged.Height - _y);
                            sprLow    = sprLow.GetSection(0, _y, sprLow.Width, sprLow.Height - _y);
                            sprHigh   = sprHigh.GetSection(0, _y, sprHigh.Width, sprHigh.Height - _y);
                            cy       -= _y;
                            goto checkbottom;
                        }
                    }
                }
checkbottom:
                for (int _y = sprMerged.Height - 1; _y >= 0; _y--)
                {
                    for (int _x = 0; _x < sprMerged.Width; _x++)
                    {
                        if (sprMerged[_x, _y] != 0)
                        {
                            sprMerged = sprMerged.GetSection(0, 0, sprMerged.Width, _y + 1);
                            sprLow    = sprLow.GetSection(0, 0, sprLow.Width, _y + 1);
                            sprHigh   = sprHigh.GetSection(0, 0, sprHigh.Width, _y + 1);
                            goto checkdone;
                        }
                    }
                }
checkdone:
                spritesMerged.Add(sprMerged);
                spritesLow.Add(sprLow);
                spritesHigh.Add(sprHigh);
                centers.Add(new Point(cx, cy));
            }
            if (gridsize == 0)
            {
                for (int i = 0; i < spritesMerged.Count; i++)
                {
                    gridsize = Math.Max(gridsize, Math.Max(spritesMerged[i].Width, spritesMerged[i].Height));
                }
                if (!fixedwidth)
                {
                    width = (padding * 2 + gridsize) * columns;
                }
            }
            int x         = padding;
            int y         = padding;
            int height    = 0;
            int rowcnt    = 0;
            int rowheight = 0;

            for (int i = 0; i < spritesMerged.Count; i++)
            {
                BitmapBits spr = spritesMerged[i];
                Point      off;
                if (gridsize == -1)
                {
                    if (fixedwidth && x + spr.Width + padding > width)
                    {
                        x         = padding;
                        y        += rowheight;
                        rowheight = 0;
                    }
                    off        = new System.Drawing.Point(x, y);
                    centers[i] = new Point(centers[i].X + off.X, centers[i].Y + off.Y);
                    if (!fixedwidth)
                    {
                        width = Math.Max(width, x + spr.Width + padding);
                    }
                    height = Math.Max(height, y + spr.Height + padding);
                    if (spr.Height + 2 * padding > rowheight)
                    {
                        rowheight = spr.Height + 2 * padding;
                    }
                    if (!fixedwidth && ++rowcnt == columns)
                    {
                        x         = padding;
                        y        += rowheight;
                        rowcnt    = 0;
                        rowheight = 0;
                    }
                    else
                    {
                        x += spr.Width + 2 * padding;
                    }
                }
                else
                {
                    if (fixedwidth && x + gridsize + padding > width)
                    {
                        x  = padding;
                        y += gridsize + 2 * padding;
                    }
                    off        = new Point(x + (gridsize - spr.Width) / 2, y + (gridsize - spr.Height) / 2);
                    centers[i] = new Point(centers[i].X + off.X, centers[i].Y + off.Y);
                    height     = Math.Max(height, y + gridsize + padding);
                    if (!fixedwidth && ++rowcnt == columns)
                    {
                        x      = padding;
                        y     += gridsize + 2 * padding;
                        rowcnt = 0;
                    }
                    else
                    {
                        x += gridsize + 2 * padding;
                    }
                }
                offsets.Add(off);
            }
            BitmapBits bmpMerged = new BitmapBits(width, height);

            for (int i = 0; i < spritesMerged.Count; i++)
            {
                bmpMerged.DrawBitmap(spritesMerged[i], offsets[i]);
            }
            BitmapBits bmpLow = new BitmapBits(width, height);

            for (int i = 0; i < spritesLow.Count; i++)
            {
                bmpLow.DrawBitmap(spritesLow[i], offsets[i]);
            }
            BitmapBits bmpHigh = new BitmapBits(width, height);

            for (int i = 0; i < spritesHigh.Count; i++)
            {
                bmpHigh.DrawBitmap(spritesHigh[i], offsets[i]);
            }
            BitmapBits bmpCenter = new BitmapBits(width, height);

            for (int i = 0; i < centers.Count; i++)
            {
                bmpCenter[centers[i].X, centers[i].Y] = 1;
            }
            Console.Write("Save as: ");
            if (getopt.Optind + 1 >= args.Length)
            {
                filename = Console.ReadLine();
            }
            else
            {
                filename = args[getopt.Optind + 1];
                Console.WriteLine(filename);
            }
            filename = Path.GetFullPath(filename);
            bmpMerged.ToBitmap(palette).Save(filename);
            if (!bmpLow.Bits.FastArrayEqual(0) && !bmpHigh.Bits.FastArrayEqual(0))
            {
                bmpLow.ToBitmap(palette).Save(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "_low" + Path.GetExtension(filename)));
                bmpHigh.ToBitmap(palette).Save(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "_high" + Path.GetExtension(filename)));
            }
            bmpCenter.ToBitmap1bpp(Color.Black, Color.White).Save(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "_center" + Path.GetExtension(filename)));
        }
Beispiel #2
0
        private static void SpriteToMap(Rectangle sprite, Point center, BitmapBits plane, List <byte[]> tiles, MappingsFrame mapframe, DPLCFrame dplcframe, byte startpal, bool pri, bool twoplayer)
        {
            BitmapBits bmp = plane.GetSection(sprite);

            if (bmp.Width % 8 != 0 || bmp.Height % 8 != 0)
            {
                int w = bmp.Width;
                if (w % 8 != 0)
                {
                    w = (w & ~7) + 8;
                }
                int h = bmp.Height;
                if (h % 8 != 0)
                {
                    h = (h & ~7) + 8;
                }
                BitmapBits tmp = new BitmapBits(w, h);
                tmp.DrawBitmapBounded(bmp, 0, 0);
                bmp = tmp;
            }
            int tw = bmp.Width / 8;
            int th = bmp.Height / 8;

            byte[,] tilepals = new byte[tw, th];
            for (int ty = 0; ty < th; ty++)
            {
                for (int tx = 0; tx < tw; tx++)
                {
                    tilepals[tx, ty] = 0xFF;
                    int[] palcnt = new int[4];
                    for (int y = 0; y < 8; y++)
                    {
                        for (int x = 0; x < 8; x++)
                        {
                            if (bmp[tx * 8 + x, ty * 8 + y] % 16 != 0)
                            {
                                palcnt[bmp[tx * 8 + x, ty * 8 + y] / 16]++;
                            }
                        }
                    }
                    if (!palcnt.FastArrayEqual(0))
                    {
                        tilepals[tx, ty] = 0;
                        for (int i = 1; i < 4; i++)
                        {
                            if (palcnt[i] > palcnt[tilepals[tx, ty]])
                            {
                                tilepals[tx, ty] = (byte)i;
                            }
                        }
                    }
                }
            }
            int numtiles = 0;

            for (int ty = 0; ty < th; ty++)
            {
                for (int tx = 0; tx < tw; tx++)
                {
                    if (tilepals[tx, ty] != 0xFF)
                    {
                        int w = Math.Min(4, (tw) - tx);
                        for (int x = 1; x < w; x++)
                        {
                            if (tilepals[tx + x, ty] != tilepals[tx, ty])
                            {
                                w = x;
                            }
                        }
                        int h = Math.Min(4, (th) - ty);
                        for (int y = 1; y < h; y++)
                        {
                            for (int x = 0; x < w; x++)
                            {
                                if (tilepals[tx + x, ty + y] != tilepals[tx, ty])
                                {
                                    h = y;
                                }
                            }
                        }
                        if (twoplayer && h % 2 == 1)
                        {
                            h++;
                        }
                        if (dplcframe != null)
                        {
                            mapframe.Tiles.Add(new MappingsTile((short)((tx * 8) - center.X), (short)((ty * 8) - center.Y), (byte)w, (byte)h, (ushort)numtiles, false, false, startpal, pri));
                            dplcframe.Tiles.Add(new DPLCEntry((byte)(w * h), (ushort)tiles.Count));
                        }
                        else
                        {
                            mapframe.Tiles.Add(new MappingsTile((short)((tx * 8) - center.X), (short)((ty * 8) - center.Y), (byte)w, (byte)h, (ushort)tiles.Count, false, false, startpal, pri));
                        }
                        for (int x = 0; x < w; x++)
                        {
                            for (int y = 0; y < h; y++)
                            {
                                if (ty + y < th)
                                {
                                    tiles.Add(bmp.ToTile((tx + x) * 8, (ty + y) * 8));
                                    tilepals[tx + x, ty + y] = 0xFF;
                                }
                                else
                                {
                                    tiles.Add(new byte[32]);
                                }
                            }
                        }
                        numtiles += w * h;
                        tx       += w - 1;
                    }
                }
            }
        }
Beispiel #3
0
        public static void Init()
        {
            using (Bitmap tmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
                Palette = tmp.Palette;
            SonLVLColor[] pal = SonLVLColor.Load(Properties.Resources.Palette, EngineVersion.S1);
            for (int i = 0; i < pal.Length; i++)
            {
                Palette.Entries[i] = pal[i].RGBColor;
            }
            Palette.Entries[0] = Color.Transparent;
            BitmapBits bmp = new BitmapBits(Properties.Resources.GFX);

            BitmapBits[] sprites = new BitmapBits[bmp.Width / 24];
            for (int i = 0; i < sprites.Length; i++)
            {
                sprites[i] = bmp.GetSection(i * 24, 0, 24, 24);
            }
            bmp = new BitmapBits(Properties.Resources.Font);
            BitmapBits[] font = new BitmapBits[11];
            for (int i = 0; i < 10; i++)
            {
                font[i] = bmp.GetSection(i * 8, 0, 8, 8);
            }
            font[10]      = bmp.GetSection(10 * 8, 0, 16, 8);
            ObjectBmps[0] = new BitmapBits(24, 24);
            byte ind = 1;

            // walls
            for (int p = 0; p < 4; p++)
            {
                BitmapBits tmp = new BitmapBits(sprites[0]);
                ObjectBmps[ind++] = tmp;
                for (int i = 1; i < 9; i++)
                {
                    BitmapBits t2 = new BitmapBits(tmp);
                    t2.DrawBitmapComposited(font[i], 16, 16);
                    ObjectBmps[ind++] = t2;
                }
                sprites[0].IncrementIndexes(16);
            }
            // misc
            for (int i = 1; i < 7; i++)
            {
                ObjectBmps[ind++] = sprites[i];
            }
            // "R"
            sprites[7].IncrementIndexes(16);
            ObjectBmps[ind++] = sprites[7];
            // red/white
            ObjectBmps[ind++] = sprites[8];
            // diamonds
            for (int p = 0; p < 4; p++)
            {
                BitmapBits tmp = new BitmapBits(sprites[9]);
                ObjectBmps[ind++] = tmp;
                sprites[9].IncrementIndexes(16);
            }
            // unused blocks
            ind += 3;
            // "ZONE" blocks
            for (int i = 10; i < 16; i++)
            {
                ObjectBmps[ind++] = sprites[i];
            }
            // ring
            sprites[16].IncrementIndexes(16);
            ObjectBmps[ind++] = sprites[16];
            // blue/yellow/pink/green emerald
            for (int p = 0; p < 4; p++)
            {
                BitmapBits tmp = new BitmapBits(sprites[19]);
                ObjectBmps[ind++] = tmp;
                sprites[19].IncrementIndexes(16);
            }
            // red emerald
            ObjectBmps[ind++] = sprites[17];
            // gray emerald
            ObjectBmps[ind++] = sprites[18];
            // pass-through barrier
            ObjectBmps[ind++] = sprites[20];
            ObjectBmps[0x4A]  = new BitmapBits(sprites[20]);
            ObjectBmps[0x4A].DrawBitmapComposited(font[10], 4, 8);
            ObjectBmpsNoNum = new Dictionary <byte, BitmapBits>(ObjectBmps);
            for (int p = 0; p < 4; p++)
            {
                BitmapBits tmp = ObjectBmps[(byte)(p * 9 + 1)];
                for (int i = 1; i < 9; i++)
                {
                    ObjectBmpsNoNum[(byte)(p * 9 + 1 + i)] = tmp;
                }
            }
            StartPosBmp = new BitmapBits(Properties.Resources.StartPos);
        }