diff --git a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs index af241acb2..aa04fda5d 100644 --- a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs +++ b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs @@ -15,26 +15,26 @@ namespace Cosmos.TestRunner.Full // Stable kernel types: the ones that are stable and will run in AppVeyor public static IEnumerable GetStableKernelTypes() { - //yield return typeof(BoxingTests.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.TypeSystem.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.Bcl.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.Bcl.System.Kernel); - ////yield return typeof(Cosmos.Compiler.Tests.Encryption.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.Exceptions.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.MethodTests.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel); - //yield return typeof(Cosmos.Kernel.Tests.Fat.Kernel); - //yield return typeof(Cosmos.Kernel.Tests.IO.Kernel); - //yield return typeof(SimpleStructsAndArraysTest.Kernel); - //yield return typeof(Cosmos.Kernel.Tests.DiskManager.Kernel); + yield return typeof(BoxingTests.Kernel); + yield return typeof(Cosmos.Compiler.Tests.TypeSystem.Kernel); + yield return typeof(Cosmos.Compiler.Tests.Bcl.Kernel); + yield return typeof(Cosmos.Compiler.Tests.Bcl.System.Kernel); + //yield return typeof(Cosmos.Compiler.Tests.Encryption.Kernel); + yield return typeof(Cosmos.Compiler.Tests.Exceptions.Kernel); + yield return typeof(Cosmos.Compiler.Tests.MethodTests.Kernel); + yield return typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel); + yield return typeof(Cosmos.Kernel.Tests.Fat.Kernel); + yield return typeof(Cosmos.Kernel.Tests.IO.Kernel); + yield return typeof(SimpleStructsAndArraysTest.Kernel); + yield return typeof(Cosmos.Kernel.Tests.DiskManager.Kernel); //yield return typeof(KernelGen3.Boot); yield return typeof(GraphicTest.Kernel); /* Please see the notes on the kernel itself before enabling it */ - //yield return typeof(ConsoleTest.Kernel); + yield return typeof(ConsoleTest.Kernel); /* This is a bit slow and works only because ring check is disabled to decide if leave it enabled */ - //yield return typeof(MemoryOperationsTest.Kernel); + yield return typeof(MemoryOperationsTest.Kernel); } } } diff --git a/Tests/Kernels/GraphicTest/Kernel.cs b/Tests/Kernels/GraphicTest/Kernel.cs index a69a0ba69..525b7942d 100644 --- a/Tests/Kernels/GraphicTest/Kernel.cs +++ b/Tests/Kernels/GraphicTest/Kernel.cs @@ -80,7 +80,7 @@ namespace GraphicTest /* A LimeGreen rectangle */ pen.Color = Color.LimeGreen; - aCanvas.DrawRectangle(pen, 450, 450, 80, 60); + aCanvas.DrawRectangle(pen, 450, 300, 80, 60); /* A filled rectange */ pen.Color = Color.Chocolate; @@ -123,22 +123,24 @@ namespace GraphicTest TestBitmaps(); + /* First test with the DefaultMode */ + //canvas = FullScreenCanvas.GetFullScreenCanvas(); + //DoTest(canvas); + + //DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(800, 600, ColorDepth.ColorDepth32))); + //DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(1024, 768, ColorDepth.ColorDepth32))); + //DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(1366, 768, ColorDepth.ColorDepth32))); + //DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(1280, 720, ColorDepth.ColorDepth32))); + VGACanvas vGACanvas = new VGACanvas(new Mode(320, 200, ColorDepth.ColorDepth8)); - DoTest(vGACanvas); + //DoTest(vGACanvas); + //vGACanvas = new VGACanvas(new Mode(720, 480, ColorDepth.ColorDepth4)); + //DoTest(vGACanvas); vGACanvas = new VGACanvas(new Mode(720, 480, ColorDepth.ColorDepth4)); - DoTest(vGACanvas); + DoTest((Canvas)vGACanvas); vGACanvas = new VGACanvas(new Mode(320, 200, ColorDepth.ColorDepth8)); DoTest(vGACanvas); - /* First test with the DefaultMode */ - canvas = FullScreenCanvas.GetFullScreenCanvas(); - DoTest(canvas); - - DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(800, 600, ColorDepth.ColorDepth32))); - DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(1024, 768, ColorDepth.ColorDepth32))); - DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(1366, 768, ColorDepth.ColorDepth32))); - DoTest(FullScreenCanvas.GetFullScreenCanvas(new Mode(1280, 720, ColorDepth.ColorDepth32))); - TestController.Completed(); } catch (Exception e) @@ -152,13 +154,12 @@ namespace GraphicTest private void DoTest(VGACanvas vGACanvas) { mDebugger.Send($"Testing VGA Canvas with mode {vGACanvas.Mode}"); - vGACanvas.Clear(); vGACanvas.Clear(Color.Blue); for (int x = 0; x < 20; x++) { for (int y = 0; y < 20; y++) { - vGACanvas.DrawPoint((uint)(x % (int)vGACanvas.Mode.ColorDepth), 5 + x, 5 + y); + vGACanvas.DrawPoint((uint)(x % (2 << ((int)vGACanvas.Mode.ColorDepth - 1))), 5 + x, 5 + y); } } @@ -166,7 +167,7 @@ namespace GraphicTest { for (int y = 0; y < 20; y++) { - vGACanvas.DrawPoint((uint)((x + 1) % (int)vGACanvas.Mode.ColorDepth), 5 + x, 5 + y); + vGACanvas.DrawPoint((uint)(x % (2 << ((int)vGACanvas.Mode.ColorDepth - 1))), 25 + x, 5 + y); } } diff --git a/source/Cosmos.HAL2/Drivers/Video/VGADriver.cs b/source/Cosmos.HAL2/Drivers/Video/VGADriver.cs index 54a116b59..48779490c 100644 --- a/source/Cosmos.HAL2/Drivers/Video/VGADriver.cs +++ b/source/Cosmos.HAL2/Drivers/Video/VGADriver.cs @@ -1,5 +1,6 @@ #define COSMOSDEBUG using System; +using System.Collections.Generic; using System.Drawing; using Cosmos.Core; @@ -178,8 +179,63 @@ namespace Cosmos.HAL public VGADriver() { + } + /// + /// The closest color in the palette will be found to be drawn + /// This is quite slow, so whenever possible use the index of the color + /// + /// + /// + /// + public void SetPixel(uint aX, uint aY, Color aColor) + { + //Find the closest index + var index = GetClosestColorInPalette(aColor); + + //Draw + SetPixel(aX, aY, index); + } + + private static Dictionary colorToPalette = new Dictionary(); + public uint GetClosestColorInPalette(Color aColor) + { + if (colorToPalette.ContainsKey(aColor.ToArgb())) + { + return colorToPalette[aColor.ToArgb()]; + } + + uint index = 0; + double diff = 1000000; + for (uint i = 0; i < 2 << ((int)_ColorDepth - 1); i++) //iterate over the total palette + { + var paletteColor = _Palette[i]; + var colorDiff = (aColor.R - paletteColor.R) * (aColor.R - paletteColor.R) * 0.3 + //Taken from https://stackoverflow.com/questions/1847092/given-an-rgb-value-what-would-be-the-best-way-to-find-the-closest-match-in-the-d + (aColor.G - paletteColor.G) * (aColor.G - paletteColor.G) * 0.59 + (aColor.B - paletteColor.B) * (aColor.B - paletteColor.B) * 0.11; + mDebugger.Send($"Standard Color: {aColor.R} {aColor.G} {aColor.B} Comparing to: {paletteColor.R} {paletteColor.G} {paletteColor.B} Diff: {colorDiff}"); + if (colorDiff < diff) + { + index = i; + diff = colorDiff; + if (diff == 0) + { + break; + } + } + } + colorToPalette.Add(aColor.ToArgb(), index); + mDebugger.Send("Chosen index: " + index); + + return index; + } + + /// + /// + /// + /// + /// + /// The index of the color in the palette public void SetPixel(uint aX, uint aY, uint aColor) { //Global.mDebugger.Send($"Setting pixel: ({x}, {y}) to {color}"); @@ -425,6 +481,73 @@ namespace Cosmos.HAL default: throw new Exception("Unknown screen size"); } + + //Initialize the palette + _Palette[0] = Color.Black; + switch (aDepth) + { + case ColorDepth.BitDepth2: + _Palette[1] = Color.Cyan; + _Palette[2] = Color.Magenta; + _Palette[3] = Color.Gray; + break; + case ColorDepth.BitDepth4: + _Palette[1] = Color.Blue; + _Palette[2] = Color.Green; + _Palette[3] = Color.Cyan; + _Palette[4] = Color.Red; + _Palette[5] = Color.DarkMagenta; + _Palette[6] = Color.Brown; + _Palette[7] = Color.LightGray; + _Palette[8] = Color.DarkGray; + _Palette[9] = Color.LightBlue; + _Palette[10] = Color.LightGreen; + _Palette[11] = Color.LightCyan; + _Palette[12] = Color.Pink; + _Palette[13] = Color.Magenta; + _Palette[14] = Color.Yellow; + _Palette[15] = Color.White; + break; + case ColorDepth.BitDepth8: + int[] colors = new int[256] // Credits to https://commons.wikimedia.org/w/index.php?title=User:Psychonaut/ipalette.sh&oldid=8607095 + { + 0x000000,0x0000AA,0x00AA00,0x00AAAA,0xAA0000,0xAA00AA,0xAA5500,0xAAAAAA,0x555555,0x5555FF, + 0x55FF55,0x55FFFF,0xFF5555,0xFF55FF,0xFFFF55,0xFFFFFF,0x000000,0x101010,0x202020,0x353535, + 0x454545,0x555555,0x656565,0x757575,0x8A8A8A,0x9A9A9A,0xAAAAAA,0xBABABA,0xCACACA,0xDFDFDF, + 0xEFEFEF,0xFFFFFF,0x0000FF,0x4100FF,0x8200FF,0xBE00FF,0xFF00FF,0xFF00BE,0xFF0082,0xFF0041, + 0xFF0000,0xFF4100,0xFF8200,0xFFBE00,0xFFFF00,0xBEFF00,0x82FF00,0x41FF00,0x00FF00,0x00FF41, + 0x00FF82,0x00FFBE,0x00FFFF,0x00BEFF,0x0082FF,0x0041FF,0x8282FF,0x9E82FF,0xBE82FF,0xDF82FF, + 0xFF82FF,0xFF82DF,0xFF82BE,0xFF829E,0xFF8282,0xFF9E82,0xFFBE82,0xFFDF82,0xFFFF82,0xDFFF82, + 0xBEFF82,0x9EFF82,0x82FF82,0x82FF9E,0x82FFBE,0x82FFDF,0x82FFFF,0x82DFFF,0x82BEFF,0x829EFF, + 0xBABAFF,0xCABAFF,0xDFBAFF,0xEFBAFF,0xFFBAFF,0xFFBAEF,0xFFBADF,0xFFBACA,0xFFBABA,0xFFCABA, + 0xFFDFBA,0xFFEFBA,0xFFFFBA,0xEFFFBA,0xDFFFBA,0xCAFFBA,0xBAFFBA,0xBAFFCA,0xBAFFDF,0xBAFFEF, + 0xBAFFFF,0xBAEFFF,0xBADFFF,0xBACAFF,0x000071,0x1C0071,0x390071,0x550071,0x710071,0x710055, + 0x710039,0x71001C,0x710000,0x711C00,0x713900,0x715500,0x717100,0x557100,0x397100,0x1C7100, + 0x007100,0x00711C,0x007139,0x007155,0x007171,0x005571,0x003971,0x001C71,0x393971,0x453971, + 0x553971,0x613971,0x713971,0x713961,0x713955,0x713945,0x713939,0x714539,0x715539,0x716139, + 0x717139,0x617139,0x557139,0x457139,0x397139,0x397145,0x397155,0x397161,0x397171,0x396171, + 0x395571,0x394571,0x515171,0x595171,0x615171,0x695171,0x715171,0x715169,0x715161,0x715159, + 0x715151,0x715951,0x716151,0x716951,0x717151,0x697151,0x617151,0x597151,0x517151,0x517159, + 0x517161,0x517169,0x517171,0x516971,0x516171,0x515971,0x000041,0x100041,0x200041,0x310041, + 0x410041,0x410031,0x410020,0x410010,0x410000,0x411000,0x412000,0x413100,0x414100,0x314100, + 0x204100,0x104100,0x004100,0x004110,0x004120,0x004131,0x004141,0x003141,0x002041,0x001041, + 0x202041,0x282041,0x312041,0x392041,0x412041,0x412039,0x412031,0x412028,0x412020,0x412820, + 0x413120,0x413920,0x414120,0x394120,0x314120,0x284120,0x204120,0x204128,0x204131,0x204139, + 0x204141,0x203941,0x203141,0x202841,0x2D2D41,0x312D41,0x352D41,0x3D2D41,0x412D41,0x412D3D, + 0x412D35,0x412D31,0x412D2D,0x41312D,0x41352D,0x413D2D,0x41412D,0x3D412D,0x35412D,0x31412D, + 0x2D412D,0x2D4131,0x2D4135,0x2D413D,0x2D4141,0x2D3D41,0x2D3541,0x2D3141,0x000000,0x000000, + 0x000000,0x000000,0x000000,0x000000,0x000000,0x000000 + }; + for (int i = 0; i < 256; i++) + { + _Palette[i] = Color.FromArgb(colors[i]); + } + break; + case ColorDepth.BitDepth16: + break; + default: + break; + } } public void SetPixel320x200x8(uint aX, uint aY, uint aC) @@ -549,38 +672,83 @@ namespace Cosmos.HAL public int PixelHeight { private set; get; } public int Colors { private set; get; } - public void TestMode320x200x8() + public void DrawFilledRectangle(int aX, int aY, int aW, int aH, uint aColor) { - SetGraphicsMode(ScreenSize.Size320x200, ColorDepth.BitDepth8); - - for (byte i = 0; i < 64; i++) + mDebugger.Send("Clearing the screen"); + if (_Mode == Mode.Text) { - SetPaletteEntry(i, i, 0, 0); - SetPaletteEntry(i + 64, 63, i, 0); - SetPaletteEntry(i + 128, 63, 63, i); - SetPaletteEntry(i + 192, (byte)(63 - i), (byte)(63 - i), (byte)(63 - i)); + throw new Exception("Cannot set pixel in text mode"); } - - var xSegment = GetFramebufferSegment(); - - for (uint y = 0; y < PixelHeight; y++) + switch (_ScreenSize) { - for (uint x = 0; x < PixelWidth; x++) - { - xSegment[(y * 320) + x] = (byte)(x + y); - } - } - } - - public void Clear(int aColor) - { - //TODO: Copy more memory at once - for (int y = 0; y < PixelHeight; y++) - { - for (int x = 0; x < PixelWidth; x++) - { - SetPixel((uint)x, (uint)y, (uint)aColor); - } + case ScreenSize.Size640x480: + switch (_ColorDepth) + { + case ColorDepth.BitDepth2: + throw new NotImplementedException(); + case ColorDepth.BitDepth4: + for (uint x = (uint)aX; x < aX + aW; x++) + { + for (uint y = (uint)aY; y < aY + aH; y++) + { + SetPixel640x480x4(x, y, aColor); + } + } + break; + case ColorDepth.BitDepth8: + throw new NotImplementedException(); + case ColorDepth.BitDepth16: + throw new NotImplementedException(); + default: + throw new NotImplementedException(); + } + break; + case ScreenSize.Size720x480: + switch (_ColorDepth) + { + case ColorDepth.BitDepth2: + throw new NotImplementedException(); + case ColorDepth.BitDepth4: + for (uint x = (uint)aX; x < aX + aW; x++) + { + for (uint y = (uint)aY; y < aY + aH; y++) + { + SetPixel720x480x4(x, y, aColor); + } + } + break; + case ColorDepth.BitDepth8: + throw new NotImplementedException(); + case ColorDepth.BitDepth16: + throw new NotImplementedException(); + default: + throw new NotImplementedException(); + } + break; + case ScreenSize.Size320x200: + switch (_ColorDepth) + { + case ColorDepth.BitDepth2: + throw new NotImplementedException(); + case ColorDepth.BitDepth4: + throw new NotImplementedException(); + case ColorDepth.BitDepth8: + for (uint x = (uint)aX; x < aX + aW; x++) + { + for (uint y = (uint)aY; y < aY + aH; y++) + { + SetPixel320x200x8(x, y, aColor); + } + } + break; + case ColorDepth.BitDepth16: + throw new NotImplementedException(); + default: + throw new NotImplementedException(); + } + break; + default: + throw new NotImplementedException(); } } @@ -599,6 +767,7 @@ namespace Cosmos.HAL public void SetPaletteEntry(int aIndex, byte aR, byte aG, byte aB) { + _Palette[aIndex] = Color.FromArgb(aR, aG, aB); _MIO.DACIndex_Write.Byte = (byte)aIndex; _MIO.DAC_Data.Byte = (byte)(aR >> 2); _MIO.DAC_Data.Byte = (byte)(aG >> 2); diff --git a/source/Cosmos.System2/Graphics/VGACanvas.cs b/source/Cosmos.System2/Graphics/VGACanvas.cs index 10e421f91..f16470fef 100644 --- a/source/Cosmos.System2/Graphics/VGACanvas.cs +++ b/source/Cosmos.System2/Graphics/VGACanvas.cs @@ -31,7 +31,8 @@ namespace Cosmos.System.Graphics public override void Clear(Color aColor) { - base.Clear(aColor); + var paletteIndex = _VGADriver.GetClosestColorInPalette(aColor); + _VGADriver.DrawFilledRectangle(0,0, _VGADriver.PixelWidth, _VGADriver.PixelHeight, paletteIndex); } public override void Disable() @@ -92,12 +93,12 @@ namespace Cosmos.System.Graphics public override void DrawFilledRectangle(Pen aPen, Point aPoint, int aWidth, int aHeight) { - base.DrawFilledRectangle(aPen, aPoint, aWidth, aHeight); + DrawFilledRectangle(aPen, aPoint.X, aPoint.Y, aWidth, aHeight); } public override void DrawFilledRectangle(Pen aPen, int aXStart, int aYStart, int aWidth, int aHeight) { - base.DrawFilledRectangle(aPen, aXStart, aYStart, aWidth, aHeight); + _VGADriver.DrawFilledRectangle(aXStart, aYStart, aWidth, aHeight, _VGADriver.GetClosestColorInPalette(aPen.Color)); } public override void DrawLine(Pen aPen, int aX1, int aY1, int aX2, int aY2) @@ -107,7 +108,7 @@ namespace Cosmos.System.Graphics public override void DrawPoint(Pen aPen, int aX, int aY) { - DrawPoint((uint)aPen.Color.ToArgb(), aX, aY); + _VGADriver.SetPixel((uint)aX, (uint)aY, aPen.Color); } public void DrawPoint(uint aColor, int aX, int aY) @@ -162,7 +163,13 @@ namespace Cosmos.System.Graphics new Mode(320, 200, ColorDepth.ColorDepth8) }; - public override List AvailableModes => _AvailableModes; + public override List AvailableModes + { + get + { + return _AvailableModes; + } + } public override Color GetPointColor(int aX, int aY) { diff --git a/source/Cosmos.System2/Graphics/VGATextMode.cs b/source/Cosmos.System2/Graphics/VGATextMode.cs index 76b083e33..d50b7a6d7 100644 --- a/source/Cosmos.System2/Graphics/VGATextMode.cs +++ b/source/Cosmos.System2/Graphics/VGATextMode.cs @@ -30,12 +30,7 @@ namespace Cosmos.System.Graphics public static void Clear(int aColor) { - _Screen.Clear(aColor); - } - - public static void TestMode320x200x8() - { - _Screen.TestMode320x200x8(); + _Screen.DrawFilledRectangle(0,0, _Screen.PixelWidth, _Screen.PixelHeight, (uint)aColor); } public static void SetPaletteEntry(int aIndex, byte aR, byte aG, byte aB)