diff --git a/SpriteCompiler/Problem/CodeSequence.cs b/SpriteCompiler/Problem/CodeSequence.cs index 395e632..873ecb2 100644 --- a/SpriteCompiler/Problem/CodeSequence.cs +++ b/SpriteCompiler/Problem/CodeSequence.cs @@ -53,7 +53,7 @@ namespace SpriteCompiler.Problem public override string ToString() { - return (offset == 0) ? "TSC" : ("ADC #" + offset.ToString() + " / TSC"); + return (offset == 0) ? "TCS" : ("ADC #" + offset.ToString() + " / TCS"); } public override string Emit() diff --git a/SpriteCompiler/Program.cs b/SpriteCompiler/Program.cs index f63d6d8..020cfc7 100644 --- a/SpriteCompiler/Program.cs +++ b/SpriteCompiler/Program.cs @@ -7,6 +7,24 @@ using System.Drawing; using System.Linq; + public static class ExtensionMethods + { + public static void Dump(this int[,] array) + { + var rows = array.GetLength(1); + var cols = array.GetLength(0); + + for (int r = 0; r < rows; r++) + { + for (int c = 0; c < cols; c++) + { + Console.Write(array[c, r].ToString("X1")); + } + Console.Write(Environment.NewLine); + } + } + + } public class ApplicationArguments { public List Data { get; set; } @@ -27,84 +45,119 @@ static void Main(string[] args) { - IEnumerable data = null; + var data = new List(); + var mask = new List(); + var filename = (string)null; + Color? maskColor = null; + var sprite = new List(); - try - { - data = args.Select((s, i) => new SpriteByte(Convert.ToByte(s, 16), (ushort)i)); - } - catch (FormatException e) - { - // If there is only one or two arguments, them marybe the user passed in a file - if (args.Length <= 2) - { - var palette = new Dictionary(); - int nextIndex = 1; + var p = new FluentCommandLineParser(); - // Convert the image / mask to a paletted image - var bitmap = new Bitmap(args[0]); - int[,] buffer = new int[bitmap.Width, bitmap.Height]; + p.Setup>('d', "data") + .Callback(_ => data = _.Select(s => Convert.ToByte(s, 16)).ToList()); - for (int r = 0; r < bitmap.Height; r++) - { - for (int w = 0; w < bitmap.Width; w++) - { - var rgb = bitmap.GetPixel(w, r); + p.Setup>('m', "mask") + .Callback(_ => data = _.Select(s => Convert.ToByte(s, 16)).ToList()); - if (!palette.ContainsKey(rgb)) - { - if (palette.Count >= 15) - { - throw new Exception("Image cannot have more than 15 unique colors"); - } - palette[rgb] = nextIndex++; - } + p.Setup('i', "image") + .Callback(_ => filename = _); - buffer[w, r] = palette[rgb]; - } - } - - // Pair up pixles to build bytes - var sprite = new List(); - - for (int r = 0; r < bitmap.Height; r++) - { - for (int w = 0; w < bitmap.Width; w += 2) - { - sprite.Add(new SpriteByte((byte)((buffer[w, r] << 4) + buffer[w + 1, r]), (ushort)(r * 160 + (w / 2)))); - } - } - - data = sprite; - } - } - /* - return; - - var p = new FluentCommandLineParser(); - - // specify which property the value will be assigned too. - p.Setup>(arg => arg.Data) - .As('d', "data") // define the short and long option name - .Required() // using the standard fluent Api to declare this Option as required. - .Callback(d => d.Select(s => Convert.ToByte(s, 16)).ToArray()); - - p.Setup>(arg => arg.Mask) - .As('m', "mask"); + p.Setup("bg-color") + .Callback(_ => maskColor = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32(_, 16)))); - var result = p.Parse(args); + p.Parse(args); - if (!result.HasErrors) + Console.WriteLine("Manual data has " + data.Count + " bytes"); + Console.WriteLine("Manual mask has " + mask.Count + " bytes"); + Console.WriteLine("Input filename is " + filename); + Console.WriteLine("Image mask color is " + (maskColor.HasValue ? maskColor.ToString() : "(none)")); + + if (!String.IsNullOrEmpty(filename)) { - */ + var palette = new Dictionary(); + int nextIndex = 1; - var problem = SpriteGeneratorSearchProblem.CreateSearchProblem(); - var search = SpriteGeneratorSearchProblem.Create(); + // Convert the image / mask to a paletted image + var bitmap = new Bitmap(filename); + int[,] data_buffer = new int[bitmap.Width, bitmap.Height]; + int[,] mask_buffer = new int[bitmap.Width, bitmap.Height]; - var solution = search.Search(problem, new SpriteGeneratorState(data)); + Console.WriteLine(String.Format(" Image is {0} x {1}", bitmap.Width, bitmap.Height)); - WriteOutSolution(solution); - //} + if (maskColor.HasValue) + { + palette[maskColor.Value] = 0; + } + + for (int r = 0; r < bitmap.Height; r++) + { + for (int w = 0; w < bitmap.Width; w++) + { + var rgb = bitmap.GetPixel(w, r); + + if (!palette.ContainsKey(rgb)) + { + if (palette.Count >= 15) + { + throw new Exception("Image cannot have more than 15 unique colors"); + } + palette[rgb] = nextIndex++; + } + + data_buffer[w, r] = palette[rgb]; + + if (maskColor.HasValue) + { + if (rgb.Equals(maskColor.Value)) + { + data_buffer[w, r] = 0x0; + mask_buffer[w, r] = 0xF; + } + else + { + data_buffer[w, r] = palette[rgb]; + mask_buffer[w, r] = 0x0; + } + } + else + { + data_buffer[w, r] = palette[rgb]; + } + } + } + + data_buffer.Dump(); + Console.WriteLine(); + mask_buffer.Dump(); + + // Pair up pixels to build bytes + for (int r = 0; r < bitmap.Height; r++) + { + for (int w = 0; w < bitmap.Width; w += 2) + { + var mask_byte = (byte)((mask_buffer[w, r] << 4) + mask_buffer[w + 1, r]); + var data_byte = (byte)((data_buffer[w, r] << 4) + data_buffer[w + 1, r]); + var offset = (ushort)(r * 160 + (w / 2)); + + // Skip fully transparent bytes + if (mask_byte == 0xFF) + { + continue; + } + + Console.WriteLine(String.Format("Adding ({0:X2}, {1:X2}, {2})", data_byte, mask_byte, offset)); + + sprite.Add(new SpriteByte(data_byte, mask_byte, offset)); + } + } + } + + var problem = SpriteGeneratorSearchProblem.CreateSearchProblem(); + var search = SpriteGeneratorSearchProblem.Create(); + + var solution = search.Search(problem, new SpriteGeneratorState(sprite)); + + WriteOutSolution(solution); } } } diff --git a/SpriteCompiler/Samples/Mario_000.png b/SpriteCompiler/Samples/Mario_000.png new file mode 100644 index 0000000..21b7aad Binary files /dev/null and b/SpriteCompiler/Samples/Mario_000.png differ diff --git a/SpriteCompiler/Samples/SpriteX1_000.png b/SpriteCompiler/Samples/SpriteX1_000.png new file mode 100644 index 0000000..9d8ed9a Binary files /dev/null and b/SpriteCompiler/Samples/SpriteX1_000.png differ diff --git a/SpriteCompiler/SpriteCompiler.csproj b/SpriteCompiler/SpriteCompiler.csproj index dc24373..4a37303 100644 --- a/SpriteCompiler/SpriteCompiler.csproj +++ b/SpriteCompiler/SpriteCompiler.csproj @@ -94,6 +94,8 @@ + +