예제 #1
0
        public void TestSingleWordSprite()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0xAA, 0x55 };

            var initialState     = SpriteGeneratorState.Init(data);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // The fastest way to draw a single word at the current location should be
            //
            // TCS
            // LDA #$55AA
            // STA 0,s     = 10 cycles
            //
            // Alternate
            //
            // ADC #1
            // TCS
            // PEA #$55AA  = 10 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(3, solution.Count());
            Assert.AreEqual(10, (int)solution.Last().PathCost);
        }
예제 #2
0
        public void TestOverlappingWrite()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0x11, 0x22, 0x22 };

            var initialState     = SpriteGeneratorState.Init(data);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // Solution should be 18 cycles
            //
            // TCS
            // LDA #$2211
            // STA 0,s
            // LDA #$2222
            // STA 1,s    = 18 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(18, (int)solution.Last().PathCost);
        }
예제 #3
0
        public void TestLines_1_To_2()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();
            var sprite  = new List <SpriteByte>
            {
                new SpriteByte(0x11, 0x00, 3),
                new SpriteByte(0x11, 0x00, 4),
                new SpriteByte(0x10, 0x0F, 5),

                new SpriteByte(0x11, 0x00, 162),
                new SpriteByte(0x11, 0x00, 163),
                new SpriteByte(0x11, 0x00, 164),
                new SpriteByte(0x20, 0x0F, 165),
            };

            // Act : solve the problem
            var initialState     = SpriteGeneratorState.Init(sprite);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert : The initial state IS the goal state (47 cycles is the currrent best solution)
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
        }
예제 #4
0
        public void TestSingleByteSprite()
        {
            Trace.WriteLine("Testing a sprite with just one byte");

            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0xAA };

            var initialState     = SpriteGeneratorState.Init(data);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // The fastest way to draw a single byte at the current location should be
            //
            // TCS
            // SHORT A
            // LDA #$AA
            // PHA
            // LONG A     = 13 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(5, solution.Count());
            Assert.AreEqual(13, (int)solution.Last().PathCost);
        }
예제 #5
0
        public void TestSingleByteWithMask()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0x00, 0x11 };
            var mask = new byte[] { 0xFF, 0x00 };

            var initialState     = SpriteGeneratorState.Init(data, mask);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // Solution should be same as regular single-byte sprite, except
            // the store happens at offset 1, instead of 0.

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(5, solution.Count());
            Assert.AreEqual(14, (int)solution.Last().PathCost);
        }
예제 #6
0
        public void TestConsecutiveWordSpriteWithMask()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0x01, 0x11, 0x22, 0x11, 0x33 };
            var mask = new byte[] { 0xF0, 0x00, 0x00, 0x00, 0x00 };

            var initialState     = SpriteGeneratorState.Init(data, mask);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // The fastest way to render this data should be
            //
            // ADC #4
            // TCS
            // PEA $3311
            // PEA $2211
            // LDA 0,s
            // AND #$00F0
            // ORA #$1101
            // STA 0,s   = 31 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(31, (int)solution.Last().PathCost);
        }
예제 #7
0
        public void TestConsecutiveWordSprite()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0xAA, 0x55, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };

            var initialState     = SpriteGeneratorState.Init(data);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // The fastest way to draw a consecutive words should be
            //
            // ADC #7
            // TCS
            // PEA $6655
            // PEA $4433
            // PEA $2211
            // PEA $55AA   = 25 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(6, solution.Count());
            Assert.AreEqual(25, (int)solution.Last().PathCost);
        }
예제 #8
0
        public void TestSinglePixelMask()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new byte[] { 0x01, 0x11 };
            var mask = new byte[] { 0xF0, 0x00 };

            var initialState     = SpriteGeneratorState.Init(data, mask);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert
            //
            // Solution should be a single 16-bit RMW
            //
            // TCS
            // LDA 0,s
            // AND #$00F0
            // ORA #$1101
            // STA 0,s     = 18 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(18, (int)solution.Last().PathCost);
        }
예제 #9
0
            public void Initialize(SpriteGeneratorSearchProblem problem, SpriteGeneratorState initialState)
            {
                // Create a new fringe
                // fringe = new Adapters.QueueAdapter<SpriteGeneratorSearchNode, IntegerCost>();
                fringe = new LIFO <SpriteGeneratorSearchNode>();

                // Add the initial state to the fringe
                fringe.Enqueue(Expander.CreateNode(initialState));
            }
예제 #10
0
        public void TestThreeLineSprite()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var data = new[]
            {
                new SpriteByte(0x11, 0),
                new SpriteByte(0x11, 160),
                new SpriteByte(0x11, 320)
            };

            var initialState     = SpriteGeneratorState.Init(data);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Current best solution
            //
            //	TCS		; 2 cycles
            //	SEP	#$10	; 3 cycles
            //	LDA	#$11	; 2 cycles
            //	PHA	        ; 3 cycles
            //	STA	A1,s	; 4 cycles
            //	REP	#$10	; 3 cycles
            //	TSC		    ; 2 cycles
            //	ADC	#321	; 3 cycles
            //	TCS		    ; 2 cycles
            //	SEP	#$10	; 3 cycles
            //	LDA	#$11	; 2 cycles
            //	PHA         ; 3 cycles
            //	REP	#$10	; 3 cycles
            //; Total Cost = 35 cycles
            //
            // Once other register caching becomes available, this should be able to be improved to
            //
            //	TCS		    ; 2 cycles
            //	SEP	#$20	; 3 cycles
            //	LDX	#$11	; 2 cycles
            //	PHX	        ; 3 cycles
            //  ADC #160    ; 3 cycles
            //  TCS         ; 2 cycles
            //  PHX         ; 3 cycles
            //  ADC #161    ; 3 cycles
            //  TCS         ; 2 cycles
            //  PHX         ; 3 cycles
            //  REP #$20    ; 3 cycles
            //; Total Cost = 29 cycles

            // Write out the solution
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(35, (int)solution.Last().PathCost);
        }
예제 #11
0
        public void TestFirstLine()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();
            var sprite  = new List <SpriteByte>
            {
                new SpriteByte(0x11, 0x00, 3),
                new SpriteByte(0x11, 0x00, 4),
                new SpriteByte(0x10, 0x0F, 5)
            };

            // Act : solve the problem
            var solution = search.Search(problem, SpriteGeneratorState.Init(sprite));

            // Assert : The initial state IS the goal state
            WriteOutSolution(solution);
        }
예제 #12
0
        public void TestEmptySprite()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create();

            // Act : solve the problem
            var initialState     = SpriteGeneratorState.Init(Enumerable.Empty <SpriteByte>());
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert : The initial state IS the goal state
            WriteOutSolution(solution, initialHeuristic);

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
            Assert.AreEqual(1, solution.Count());
        }
예제 #13
0
            public SpriteGeneratorSearchNode SearchStep(SpriteGeneratorSearchProblem problem)
            {
                // If the fringe is empty, return null to indicate that no solution was found
                if (fringe.Empty)
                {
                    return(null);
                }

                // Select the next node
                var node = fringe.Remove();

                // If the node is a solution, then we're done! Otherwise expand the node and add to the queue
                if (!problem.IsGoal(node.State))
                {
                    AddNodes(fringe, node, problem);
                }

                // Return the node that we selected to the caller
                return(node);
            }
예제 #14
0
        public void TestLines_1_To_4()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create(200); // max budget of 200 cycles
            var sprite  = new List <SpriteByte>
            {
                new SpriteByte(0x11, 0x00, 3),
                new SpriteByte(0x11, 0x00, 4),
                new SpriteByte(0x10, 0x0F, 5),

                new SpriteByte(0x11, 0x00, 162),
                new SpriteByte(0x11, 0x00, 163),
                new SpriteByte(0x11, 0x00, 164),
                new SpriteByte(0x20, 0x0F, 165),

                new SpriteByte(0x01, 0xF0, 321),
                new SpriteByte(0x11, 0x00, 322),
                new SpriteByte(0x11, 0x00, 323),
                new SpriteByte(0x12, 0x00, 324),
                new SpriteByte(0x20, 0x0F, 325),

                new SpriteByte(0x01, 0xF0, 481),
                new SpriteByte(0x11, 0x00, 482),
                new SpriteByte(0x11, 0x00, 483),
                new SpriteByte(0x11, 0x00, 484),
                new SpriteByte(0x11, 0x00, 485),
                new SpriteByte(0x11, 0x00, 486)
            };

            // Act : solve the problem
            var initialState     = SpriteGeneratorState.Init(sprite);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert : The initial state IS the goal state
            WriteOutSolution(solution);
        }
예제 #15
0
        public void TestLines_1_To_3()
        {
            // Arrange
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = SpriteGeneratorSearchProblem.Create(100); // max budget of 100 cycles
            var sprite  = new List <SpriteByte>
            {
                new SpriteByte(0x11, 0x00, 3),
                new SpriteByte(0x11, 0x00, 4),
                new SpriteByte(0x10, 0x0F, 5),

                new SpriteByte(0x11, 0x00, 162),
                new SpriteByte(0x11, 0x00, 163),
                new SpriteByte(0x11, 0x00, 164),
                new SpriteByte(0x20, 0x0F, 165),

                new SpriteByte(0x01, 0xF0, 321),
                new SpriteByte(0x11, 0x00, 322),
                new SpriteByte(0x11, 0x00, 323),
                new SpriteByte(0x12, 0x00, 324),
                new SpriteByte(0x20, 0x0F, 325)
            };

            // Act : solve the problem
            var initialState     = SpriteGeneratorState.Init(sprite);
            var initialHeuristic = problem.Heuristic(initialState);

            var solution = search.Search(problem, initialState);

            // Assert : The initial state IS the goal state
            WriteOutSolution(solution);

            //    TCS		; 2 cycles
            //    LDA	04,s	; 5 cycles
            //    AND	#$0F00	; 3 cycles
            //    ORA	#$1011	; 3 cycles
            //    STA	04,s	; 5 cycles
            //    LDA	#$1111	; 3 cycles
            //    STA	03,s	; 5 cycles
            //    STA	A2,s	; 5 cycles
            //    LDA	A4,s	; 5 cycles
            //    AND	#$0F00	; 3 cycles
            //    ORA	#$2011	; 3 cycles
            //    STA	A4,s	; 5 cycles
            //    TSC		; 2 cycles
            //    ADC	#321	; 3 cycles
            //    TCS		; 2 cycles
            //    LDA	00,s	; 5 cycles
            //    AND	#$00F0	; 3 cycles
            //    ORA	#$1101	; 3 cycles
            //    STA	00,s	; 5 cycles
            //    LDA	03,s	; 5 cycles
            //    AND	#$0F00	; 3 cycles
            //    ORA	#$2012	; 3 cycles
            //    STA	03,s	; 5 cycles
            //    LDA	#$1211	; 3 cycles
            //    STA	02,s	; 5 cycles
            //; Total Cost = 94 cycles

            initialHeuristic.Should().BeLessOrEqualTo(solution.Last().PathCost);
        }
예제 #16
0
        private void button1_Click(object sender, EventArgs e)
        {
            var bgcolor = source.GetPixel(0, 0);
            var record  = BrutalDeluxeClassifier.Decompose(source, bgcolor);

            var classified = new Bitmap(source.Width, source.Height);

            for (int y = 0; y < source.Height; y++)
            {
                for (int x = 0; x < (source.Width / 2); x++)
                {
                    // A mask value of 255 (0xFF) is a tansparent pair of pixels, use the background color
                    var color = BrutalDeluxeClassifier.ToRGB(record.Classes[x, y]);
                    classified.SetPixel(2 * x, y, color);
                    classified.SetPixel(2 * x + 1, y, color);
                }
            }

            pictureBox3.Image    = Expand(classified, pictureBox3.ClientSize.Width, pictureBox3.ClientSize.Height);;
            pictureBox3.SizeMode = PictureBoxSizeMode.Zoom;


            var rb_record = BrutalDeluxeClassifier.DecomposeIntoRedBlueImageMap(source, bgcolor);

            var rb_classified = new Bitmap(source.Width, source.Height);

            for (int y = 0; y < source.Height; y++)
            {
                for (int x = 0; x < (source.Width / 2); x++)
                {
                    // A mask value of 255 (0xFF) is a tansparent pair of pixels, use the background color
                    var color = BrutalDeluxeClassifier.ToRGB(rb_record.Classes[x, y]);
                    rb_classified.SetPixel(2 * x, y, color);
                    rb_classified.SetPixel(2 * x + 1, y, color);
                }
            }

            pictureBox2.Image    = Expand(rb_classified, pictureBox2.ClientSize.Width, pictureBox2.ClientSize.Height);;
            pictureBox2.SizeMode = PictureBoxSizeMode.Zoom;

            var histogram = BrutalDeluxeClassifier.GenerateStatistics(rb_record);

            textBox1.Clear();

            textBox1.AppendText("Most Common Values\n");
            textBox1.AppendText("------------------\n");
            foreach (var stat in histogram.OrderByDescending(x => x.Value).Take(10))
            {
                textBox1.AppendText(String.Format("0x{0:X} : {1}\n", stat.Key, stat.Value));
            }

            // Initialize the search
            var maxCycles = 5 + source.Height * (3 + (source.Width / 4 * 31) - 1 + 41) - 1;

            problem      = SpriteGeneratorSearchProblem.CreateSearchProblem();
            initialState = SpriteGeneratorState.Init(rb_record.SpriteData);

            var expander = new SpriteGeneratorNodeExpander();

            strategy = new InspectableTreeSearch(expander);

            strategy.Initialize(problem, initialState);
        }
예제 #17
0
        static void Main(string[] args)
        {
            var   data      = new List <byte>();
            var   mask      = new List <byte>();
            var   filename  = (string)null;
            Color?maskColor = null;
            int?  maxCycles = null;
            var   sprite    = new List <SpriteByte>();
            bool  verbose   = false;

            var p = new FluentCommandLineParser();

            p.Setup <List <string> >('d', "data")
            .Callback(_ => data = _.Select(s => Convert.ToByte(s, 16)).ToList());

            p.Setup <List <string> >('m', "mask")
            .Callback(_ => mask = _.Select(s => Convert.ToByte(s, 16)).ToList());

            p.Setup <string>('i', "image")
            .Callback(_ => filename = _);

            p.Setup <string>('l', "limit")
            .Callback(_ => maxCycles = int.Parse(_));

            p.Setup <string>('v', "verbose")
            .Callback(_ => verbose = true);

            p.Setup <string>("bg-color")
            .Callback(_ => maskColor = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32(_, 16))));

            p.Parse(args);

            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)"));

            // Set the global state
            var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
            var search  = maxCycles.HasValue ?
                          SpriteGeneratorSearchProblem.Create(maxCycles.Value) :
                          SpriteGeneratorSearchProblem.Create();

            SpriteGeneratorState initialState = null;

            // Handle the difference command line cases
            if (!String.IsNullOrEmpty(filename))
            {
                var bitmap = new Bitmap(filename);
                var record = BrutalDeluxeClassifier.Decompose(bitmap, maskColor);

                record.Data.Dump();
                Console.WriteLine();
                record.Mask.Dump();
                Console.WriteLine();
                record.Classes.Dump();

                //initialState = SpriteGeneratorState.Init(sprite);
            }
            else if (data.Count == mask.Count)
            {
                initialState = SpriteGeneratorState.Init(data, mask);
            }
            else
            {
                initialState = SpriteGeneratorState.Init(data);
            }

            //var solution = search.Search(problem, initialState);
            //WriteOutSolution(solution);
        }