diff --git a/PrismBinary/Formats/ELF/ELFFile32.cs b/PrismBinary/Formats/ELF/ELFFile32.cs index eb9e88ed..a7a944a0 100644 --- a/PrismBinary/Formats/ELF/ELFFile32.cs +++ b/PrismBinary/Formats/ELF/ELFFile32.cs @@ -16,26 +16,10 @@ public ELFFile32(byte[] Binary) fixed (byte* P = Binary) { // Load main file header. - Header = new((ELFHeader32*)P); - SectionHeaders = new(); - StringTable = new(); + ELFHeader32 Header = new((ELFHeader32*)P); // Assign entry point. - Main = (delegate* unmanaged)Header.EntryPoint; - - // Load the first section header. - ELFSectionHeader32 SHHeader = new((ELFSectionHeader32*)(P + Header.SHOffset)); - - // Load all section headers. - for (int I = 0; I < Header.SHCount; I++) - { - ELFSectionHeader32 X = new(&SHHeader + I); - if (X.Type == ELFSectionType.StringTable) - { - StringTable.Add(X.Offset); - } - SectionHeaders.Add(X); - } + Main = (delegate* unmanaged)(Header.EntryPoint); // Load the first program header. ELFProgramHeader32* PHeader = (ELFProgramHeader32*)(P + Header.PHOffset); @@ -48,7 +32,7 @@ public ELFFile32(byte[] Binary) case ELFProgramType.Null: break; case ELFProgramType.Load: - Buffer.MemoryCopy((byte*)PHeader->VAddress, P + PHeader->Offset, PHeader->FileSize, PHeader->FileSize); + Buffer.MemoryCopy(PHeader + PHeader->Offset, (byte*)PHeader->VAddress, PHeader->FileSize, PHeader->FileSize); break; default: throw new ArgumentException("Unsupported program type!"); @@ -65,13 +49,5 @@ public ELFFile32(byte[] Binary) public delegate* unmanaged Main; #endregion - - #region Fields - - public List SectionHeaders; - public List StringTable; - public ELFHeader32 Header; - - #endregion - } + } } \ No newline at end of file diff --git a/PrismBinary/Formats/ELF/ELFFile64.cs b/PrismBinary/Formats/ELF/ELFFile64.cs index 47ec1d2b..3e5d59e4 100644 --- a/PrismBinary/Formats/ELF/ELFFile64.cs +++ b/PrismBinary/Formats/ELF/ELFFile64.cs @@ -16,26 +16,10 @@ public ELFFile64(byte[] Binary) fixed (byte* P = Binary) { // Load main file header. - Header = new((ELFHeader64*)P); - SectionHeaders = new(); - StringTable = new(); + ELFHeader64 Header = new((ELFHeader64*)P); // Assign entry point. - Main = (delegate* unmanaged)Header.EntryPoint; - - // Load the first section header. - ELFSectionHeader64 SHHeader = new((ELFSectionHeader64*)(P + Header.SHOffset)); - - // Load all section headers. - for (int I = 0; I < Header.SHCount; I++) - { - ELFSectionHeader64 X = new(&SHHeader + I); - if (X.Type == ELFSectionType.StringTable) - { - StringTable.Add(X.Offset); - } - SectionHeaders.Add(X); - } + Main = (delegate* unmanaged)(Header.EntryPoint + 512); // Load the first program header. ELFProgramHeader64* PHeader = (ELFProgramHeader64*)(P + Header.PHOffset); @@ -65,13 +49,5 @@ public ELFFile64(byte[] Binary) public delegate* unmanaged Main; #endregion - - #region Fields - - public List SectionHeaders; - public List StringTable; - public ELFHeader64 Header; - - #endregion } } \ No newline at end of file diff --git a/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader32.cs b/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader32.cs index 160f1a0e..9db5cb78 100644 --- a/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader32.cs +++ b/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader32.cs @@ -7,6 +7,7 @@ public unsafe struct ELFHeader32 { public ELFHeader32(ELFHeader32* Original) { + MagicNumber = Original->MagicNumber; ClassType = Original->ClassType; EndianType = Original->EndianType; Version = Original->Version; @@ -32,11 +33,7 @@ public ELFHeader32(ELFHeader32* Original) public bool IsValid() { - return - Magic[0] == 0x7f && - Magic[1] == 0x45 && - Magic[2] == 0x4c && - Magic[3] == 0x46; + return MagicNumber == BitConverter.ToUInt32(new byte[] { 0x7F, 0x45, 0x4C, 0x46 }); } #endregion @@ -45,7 +42,7 @@ public bool IsValid() #region Identifier [14 bytes] - public fixed char Magic[4]; + public uint MagicNumber; public ELFClassType ClassType; public ELFEndianType EndianType; private readonly byte Version; diff --git a/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader64.cs b/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader64.cs index c88db30a..1f911173 100644 --- a/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader64.cs +++ b/PrismBinary/Formats/ELF/Structure/ELFHeader/ELFHeader64.cs @@ -7,6 +7,7 @@ public unsafe struct ELFHeader64 { public ELFHeader64(ELFHeader64* Original) { + MagicNumber = Original->MagicNumber; ClassType = Original->ClassType; EndianType = Original->EndianType; Version = Original->Version; @@ -32,11 +33,7 @@ public ELFHeader64(ELFHeader64* Original) public bool IsValid() { - return - Magic[0] == 0x7f && - Magic[1] == 0x45 && - Magic[2] == 0x4c && - Magic[3] == 0x46; + return MagicNumber == 0x7F454C46; } #endregion @@ -45,7 +42,7 @@ public bool IsValid() #region Identifier [14 bytes] - public fixed char Magic[4]; + public uint MagicNumber; public ELFClassType ClassType; public ELFEndianType EndianType; private readonly byte Version; diff --git a/PrismBinary/Formats/ELF/Structure/ELFSectionFlagsType.cs b/PrismBinary/Formats/ELF/Structure/ELFSectionFlagsType.cs index 46542121..beb4a80e 100644 --- a/PrismBinary/Formats/ELF/Structure/ELFSectionFlagsType.cs +++ b/PrismBinary/Formats/ELF/Structure/ELFSectionFlagsType.cs @@ -1,10 +1,11 @@ namespace PrismBinary.Formats.ELF.Structure { + [Flags] public enum ELFSectionFlagsType : uint { None, Write, Allocate, - ExexInstruction, + Executable, } } \ No newline at end of file diff --git a/PrismGraphics/Animators/FadeControler.cs b/PrismGraphics/Animators/FadeControler.cs new file mode 100644 index 00000000..276d3d22 --- /dev/null +++ b/PrismGraphics/Animators/FadeControler.cs @@ -0,0 +1,175 @@ +namespace PrismGraphics.Animators +{ + /// + /// The class used to create color fading animations. + /// WIP : Not working properly! + /// + public class FadeControler + { + /// + /// Creates a new instance of the class. + /// + /// The color to start fading from. + /// The color to fade to. + /// The duration to fade the colors. + /// The mode to fade the colors. + public FadeControler(Color BeginColor, Color TargetColor, TimeSpan Duration, FadeMode Mode = FadeMode.Linear) + { + // Assign public API fields. + this.BeginColor = BeginColor; + this.TargetColor = TargetColor; + this.Duration = Duration; + this.Mode = Mode; + IsEnabled = false; + + // Assign private API fields. + StepA = (TargetColor.A - BeginColor.A) / (Duration.Milliseconds * 1000000); + StepR = (TargetColor.R - BeginColor.R) / (Duration.Milliseconds * 1000000); + StepG = (TargetColor.G - BeginColor.G) / (Duration.Milliseconds * 1000000); + StepB = (TargetColor.B - BeginColor.B) / (Duration.Milliseconds * 1000000); + A = BeginColor.A; + R = BeginColor.R; + G = BeginColor.G; + B = BeginColor.B; + + // Adjust step deltas based on fade mode. + switch (Mode) + { + case FadeMode.FastInSlowOut: + Duration /= 2; + StepA *= 2; + StepR *= 2; + StepG *= 2; + StepB *= 2; + break; + case FadeMode.FastOutSlowIn: + Duration *= 2; + StepA /= 2; + StepR /= 2; + StepG /= 2; + StepB /= 2; + break; + } + + // Create an interupt timer. + Cosmos.HAL.Global.PIT.RegisterTimer(new(Next, (ulong)((TargetColor - BeginColor).Brightness / (Duration.TotalMilliseconds * 1000000)), true)); + } + + #region Properties + + /// + /// The current color of the fade, will always be present. + /// + public Color ResultColor + { + get + { + return ((byte)A, (byte)R, (byte)G, (byte)B); + } + } + + #endregion + + #region Methods + + /// + /// Restarts the interpolation, starts it if it was stopped. + /// + public void Restart() + { + // Reset the result color value. + A = BeginColor.A; + R = BeginColor.R; + G = BeginColor.G; + B = BeginColor.B; + + // Enable the animator. + IsEnabled = true; + } + + /// + /// Resets the interpolation, does not change playing state. + /// + public void Reset() + { + // Reset the result color value. + A = BeginColor.A; + R = BeginColor.R; + G = BeginColor.G; + B = BeginColor.B; + } + + /// + /// Starts the interpolation, doesn't reset the interpolation. + /// + public void Start() + { + IsEnabled = true; + } + + /// + /// Pauses the interpolation, doesn't reset the interpolation. + /// + public void Pause() + { + IsEnabled = false; + } + + /// + /// Stops the interpolation, resets the interpolation and pauses it. + /// + public void Stop() + { + // Reset the result color value. + A = BeginColor.A; + R = BeginColor.R; + G = BeginColor.G; + B = BeginColor.B; + + // Disable the animator. + IsEnabled = false; + } + + /// + /// Updates the color to the next of the interpolation. + /// + private void Next() + { + // Return if no operation needs to be done. + if (!IsEnabled) + { + return; + } + if (ResultColor == TargetColor) + { + IsEnabled = false; + return; + } + + A += (byte)StepA; + R += (byte)StepR; + G += (byte)StepG; + B += (byte)StepB; + } + + #endregion + + #region Fields + + // Public API fields. + public Color BeginColor; + public Color TargetColor; + public TimeSpan Duration; + public FadeMode Mode; + public bool IsEnabled; + + // Private API fields. + private readonly double StepA; + private readonly double StepR; + private readonly double StepG; + private readonly double StepB; + private double A, R, G, B; + + #endregion + } +} \ No newline at end of file diff --git a/PrismGraphics/Animators/FadeMode.cs b/PrismGraphics/Animators/FadeMode.cs new file mode 100644 index 00000000..511475d7 --- /dev/null +++ b/PrismGraphics/Animators/FadeMode.cs @@ -0,0 +1,15 @@ +namespace PrismGraphics.Animators +{ + /// + /// This is an enum to keep a list of all the possible fade types. + /// + public enum FadeMode + { + /// + /// This mode fades a color in fast but slows down the closer it gets to the target color. + /// + FastInSlowOut, + FastOutSlowIn, + Linear, + } +} \ No newline at end of file diff --git a/PrismGraphics/Color.cs b/PrismGraphics/Color.cs index 2bc1309b..f56b3337 100644 --- a/PrismGraphics/Color.cs +++ b/PrismGraphics/Color.cs @@ -7,6 +7,135 @@ namespace PrismGraphics /// public struct Color { + #region Properties + + /// + /// The brightness (or average value) of the color. + /// + public byte Brightness + { + get + { + return (byte)((A + R + G + B) / 4); + } + } + + /// + /// Saturation of the color. + /// + public int Saturation + { + get + { + // Calculate the saturation of the color + int Max = Math.Max(_R, Math.Max(_G, _B)); + int Min = Math.Min(_R, Math.Min(_G, _B)); + return (Max - Min) / 255; + } + set + { + // Set the saturation of the color + int Max = Math.Max(_R, Math.Max(_G, _B)); + int Min = Math.Min(_R, Math.Min(_G, _B)); + int Diff = Max - Min; + if (Diff == 0) + { + _R = _G = _B = (byte)value; + } + else + { + _R = (byte)((Max - _R) * value / Diff + _R); + _G = (byte)((Max - _G) * value / Diff + _G); + _B = (byte)((Max - _B) * value / Diff + _B); + } + } + } + + /// + /// Packed ARGB value of the color. + /// + public uint ARGB + { + get + { + return _ARGB; + } + set + { + _ARGB = value; + _A = (byte)(_ARGB >> 24); + _R = (byte)(_ARGB >> 16); + _G = (byte)(_ARGB >> 8); + _B = (byte)(_ARGB); + } + } + + /// + /// Alpha channel of the color. + /// + public byte A + { + get + { + return _A; + } + set + { + _A = value; + _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); + } + } + + /// + /// Red channel of the color. + /// + public byte R + { + get + { + return _R; + } + set + { + _R = value; + _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); + } + } + + /// + /// Green channel of the color. + /// + public byte G + { + get + { + return _G; + } + set + { + _G = value; + _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); + } + } + + /// + /// Blue channel of the color. + /// + public byte B + { + get + { + return _B; + } + set + { + _B = value; + _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); + } + } + + #endregion + #region Operators public static implicit operator Color((byte, byte, byte, byte) Color) @@ -204,154 +333,154 @@ public static Color FromName(string ColorName) Color C = ColorName switch { - "AliceBlue" => "#F0F8FF", - "AntiqueWhite" => "#FAEBD7", - "Aqua" => "#00FFFF", - "Aquamarine" => "#7FFFD4", - "Azure" => "#F0FFFF", - "Beige" => "#F5F5DC", - "Bisque" => "#FFE4C4", - "Black" => "#000000", - "BlanchedAlmond" => "#FFEBCD", - "Blue" => "#0000FF", - "BlueViolet" => "#8A2BE2", - "Brown" => "#A52A2A", - "BurlyWood" => "#DEB887", - "CadetBlue" => "#5F9EA0", - "Chartreuse" => "#7FFF00", - "Chocolate" => "#D2691E", - "Coral" => "#FF7F50", - "CornflowerBlue" => "#6495ED", - "Cornsilk" => "#FFF8DC", - "Crimson" => "#DC143C", - "Cyan" => "#00FFFF", - "DarkBlue" => "#00008B", - "DarkCyan" => "#008B8B", - "DarkGoldenRod" => "#B8860B", - "DarkGray" => "#A9A9A9", - "DarkGrey" => "#A9A9A9", - "DarkGreen" => "#006400", - "DarkKhaki" => "#BDB76B", - "DarkMagenta" => "#8B008B", - "DarkOliveGreen" => "#556B2F", - "DarkOrange" => "#FF8C00", - "DarkOrchid" => "#9932CC", - "DarkRed" => "#8B0000", - "DarkSalmon" => "#E9967A", - "DarkSeaGreen" => "#8FBC8F", - "DarkSlateBlue" => "#483D8B", - "DarkSlateGray" => "#2F4F4F", - "DarkSlateGrey" => "#2F4F4F", - "DarkTurquoise" => "#00CED1", - "DarkViolet" => "#9400D3", - "DeepPink" => "#FF1493", - "DeepSkyBlue" => "#00BFFF", - "DimGray" => "#696969", - "DimGrey" => "#696969", - "DodgerBlue" => "#1E90FF", - "FireBrick" => "#B22222", - "FloralWhite" => "#FFFAF0", - "ForestGreen" => "#228B22", - "Fuchsia" => "#FF00FF", - "Gainsboro" => "#DCDCDC", - "GhostWhite" => "#F8F8FF", - "Gold" => "#FFD700", - "GoldenRod" => "#DAA520", - "Gray" => "#808080", - "Grey" => "#808080", - "Green" => "#008000", - "GreenYellow" => "#ADFF2F", - "HoneyDew" => "#F0FFF0", - "HotPink" => "#FF69B4", - "IndianRed" => "#CD5C5C", - "Indigo" => "#4B0082", - "Ivory" => "#FFFFF0", - "Khaki" => "#F0E68C", - "Lavender" => "#E6E6FA", - "LavenderBlush" => "#FFF0F5", - "LawnGreen" => "#7CFC00", - "LemonChiffon" => "#FFFACD", - "LightBlue" => "#ADD8E6", - "LightCoral" => "#F08080", - "LightCyan" => "#E0FFFF", - "LightGoldenRodYellow" => "#FAFAD2", - "LightGray" => "#D3D3D3", - "LightGrey" => "#D3D3D3", - "LightGreen" => "#90EE90", - "LightPink" => "#FFB6C1", - "LightSalmon" => "#FFA07A", - "LightSeaGreen" => "#20B2AA", - "LightSkyBlue" => "#87CEFA", - "LightSlateGray" => "#778899", - "LightSlateGrey" => "#778899", - "LightSteelBlue" => "#B0C4DE", - "LightYellow" => "#FFFFE0", - "Lime" => "#00FF00", - "LimeGreen" => "#32CD32", - "Linen" => "#FAF0E6", - "Magenta" => "#FF00FF", - "Maroon" => "#800000", - "MediumAquaMarine" => "#66CDAA", - "MediumBlue" => "#0000CD", - "MediumOrchid" => "#BA55D3", - "MediumPurple" => "#9370DB", - "MediumSeaGreen" => "#3CB371", - "MediumSlateBlue" => "#7B68EE", - "MediumSpringGreen" => "#00FA9A", - "MediumTurquoise" => "#48D1CC", - "MediumVioletRed" => "#C71585", - "MidnightBlue" => "#191970", - "MintCream" => "#F5FFFA", - "MistyRose" => "#FFE4E1", - "Moccasin" => "#FFE4B5", - "NavajoWhite" => "#FFDEAD", - "Navy" => "#000080", - "OldLace" => "#FDF5E6", - "Olive" => "#808000", - "OliveDrab" => "#6B8E23", - "Orange" => "#FFA500", - "OrangeRed" => "#FF4500", - "Orchid" => "#DA70D6", - "PaleGoldenRod" => "#EEE8AA", - "PaleGreen" => "#98FB98", - "PaleTurquoise" => "#AFEEEE", - "PaleVioletRed" => "#DB7093", - "PapayaWhip" => "#FFEFD5", - "PeachPuff" => "#FFDAB9", - "Peru" => "#CD853F", - "Pink" => "#FFC0CB", - "Plum" => "#DDA0DD", - "PowderBlue" => "#B0E0E6", - "Purple" => "#800080", - "RebeccaPurple" => "#663399", - "Red" => "#FF0000", - "RosyBrown" => "#BC8F8F", - "RoyalBlue" => "#4169E1", - "SaddleBrown" => "#8B4513", - "Salmon" => "#FA8072", - "SandyBrown" => "#F4A460", - "SeaGreen" => "#2E8B57", - "SeaShell" => "#FFF5EE", - "Sienna" => "#A0522D", - "Silver" => "#C0C0C0", - "SkyBlue" => "#87CEEB", - "SlateBlue" => "#6A5ACD", - "SlateGray" => "#708090", - "SlateGrey" => "#708090", - "Snow" => "#FFFAFA", - "SpringGreen" => "#00FF7F", - "SteelBlue" => "#4682B4", - "Tan" => "#D2B48C", - "Teal" => "#008080", - "Thistle" => "#D8BFD8", - "Tomato" => "#FF6347", - "Turquoise" => "#40E0D0", - "Violet" => "#EE82EE", - "Wheat" => "#F5DEB3", - "White" => "#FFFFFF", - "WhiteSmoke" => "#F5F5F5", - "Yellow" => "#FFFF00", - "YellowGreen" => "#9ACD32", + "AliceBlue" => 0xFFF0F8FF, + "AntiqueWhite" => 0xFFFAEBD7, + "Aqua" => 0xFF00FFFF, + "Aquamarine" => 0xFF7FFFD4, + "Azure" => 0xFFF0FFFF, + "Beige" => 0xFFF5F5DC, + "Bisque" => 0xFFFFE4C4, + "Black" => 0xFF000000, + "BlanchedAlmond" => 0xFFFFEBCD, + "Blue" => 0xFF0000FF, + "BlueViolet" => 0xFF8A2BE2, + "Brown" => 0xFFA52A2A, + "BurlyWood" => 0xFFDEB887, + "CadetBlue" => 0xFF5F9EA0, + "Chartreuse" => 0xFF7FFF00, + "Chocolate" => 0xFFD2691E, + "Coral" => 0xFFFF7F50, + "CornflowerBlue" => 0xFF6495ED, + "Cornsilk" => 0xFFFFF8DC, + "Crimson" => 0xFFDC143C, + "Cyan" => 0xFF00FFFF, + "DarkBlue" => 0xFF00008B, + "DarkCyan" => 0xFF008B8B, + "DarkGoldenRod" => 0xFFB8860B, + "DarkGray" => 0xFFA9A9A9, + "DarkGrey" => 0xFFA9A9A9, + "DarkGreen" => 0xFF006400, + "DarkKhaki" => 0xFFBDB76B, + "DarkMagenta" => 0xFF8B008B, + "DarkOliveGreen" => 0xFF556B2F, + "DarkOrange" => 0xFFFF8C00, + "DarkOrchid" => 0xFF9932CC, + "DarkRed" => 0xFF8B0000, + "DarkSalmon" => 0xFFE9967A, + "DarkSeaGreen" => 0xFF8FBC8F, + "DarkSlateBlue" => 0xFF483D8B, + "DarkSlateGray" => 0xFF2F4F4F, + "DarkSlateGrey" => 0xFF2F4F4F, + "DarkTurquoise" => 0xFF00CED1, + "DarkViolet" => 0xFF9400D3, + "DeepPink" => 0xFFFF1493, + "DeepSkyBlue" => 0xFF00BFFF, + "DimGray" => 0xFF696969, + "DimGrey" => 0xFF696969, + "DodgerBlue" => 0xFF1E90FF, + "FireBrick" => 0xFFB22222, + "FloralWhite" => 0xFFFFFAF0, + "ForestGreen" => 0xFF228B22, + "Fuchsia" => 0xFFFF00FF, + "Gainsboro" => 0xFFDCDCDC, + "GhostWhite" => 0xFFF8F8FF, + "Gold" => 0xFFFFD700, + "GoldenRod" => 0xFFDAA520, + "Gray" => 0xFF808080, + "Grey" => 0xFF808080, + "Green" => 0xFF008000, + "GreenYellow" => 0xFFADFF2F, + "HoneyDew" => 0xFFF0FFF0, + "HotPink" => 0xFFFF69B4, + "IndianRed" => 0xFFCD5C5C, + "Indigo" => 0xFF4B0082, + "Ivory" => 0xFFFFFFF0, + "Khaki" => 0xFFF0E68C, + "Lavender" => 0xFFE6E6FA, + "LavenderBlush" => 0xFFFFF0F5, + "LawnGreen" => 0xFF7CFC00, + "LemonChiffon" => 0xFFFFFACD, + "LightBlue" => 0xFFADD8E6, + "LightCoral" => 0xFFF08080, + "LightCyan" => 0xFFE0FFFF, + "LightGoldenRodYellow" => 0xFFFAFAD2, + "LightGray" => 0xFFD3D3D3, + "LightGrey" => 0xFFD3D3D3, + "LightGreen" => 0xFF90EE90, + "LightPink" => 0xFFFFB6C1, + "LightSalmon" => 0xFFFFA07A, + "LightSeaGreen" => 0xFF20B2AA, + "LightSkyBlue" => 0xFF87CEFA, + "LightSlateGray" => 0xFF778899, + "LightSlateGrey" => 0xFF778899, + "LightSteelBlue" => 0xFFB0C4DE, + "LightYellow" => 0xFFFFFFE0, + "Lime" => 0xFF00FF00, + "LimeGreen" => 0xFF32CD32, + "Linen" => 0xFFFAF0E6, + "Magenta" => 0xFFFF00FF, + "Maroon" => 0xFF800000, + "MediumAquaMarine" => 0xFF66CDAA, + "MediumBlue" => 0xFF0000CD, + "MediumOrchid" => 0xFFBA55D3, + "MediumPurple" => 0xFF9370DB, + "MediumSeaGreen" => 0xFF3CB371, + "MediumSlateBlue" => 0xFF7B68EE, + "MediumSpringGreen" => 0xFF00FA9A, + "MediumTurquoise" => 0xFF48D1CC, + "MediumVioletRed" => 0xFFC71585, + "MidnightBlue" => 0xFF191970, + "MintCream" => 0xFFF5FFFA, + "MistyRose" => 0xFFFFE4E1, + "Moccasin" => 0xFFFFE4B5, + "NavajoWhite" => 0xFFFFDEAD, + "Navy" => 0xFF000080, + "OldLace" => 0xFFFDF5E6, + "Olive" => 0xFF808000, + "OliveDrab" => 0xFF6B8E23, + "Orange" => 0xFFFFA500, + "OrangeRed" => 0xFFFF4500, + "Orchid" => 0xFFDA70D6, + "PaleGoldenRod" => 0xFFEEE8AA, + "PaleGreen" => 0xFF98FB98, + "PaleTurquoise" => 0xFFAFEEEE, + "PaleVioletRed" => 0xFFDB7093, + "PapayaWhip" => 0xFFFFEFD5, + "PeachPuff" => 0xFFFFDAB9, + "Peru" => 0xFFCD853F, + "Pink" => 0xFFFFC0CB, + "Plum" => 0xFFDDA0DD, + "PowderBlue" => 0xFFB0E0E6, + "Purple" => 0xFF800080, + "RebeccaPurple" => 0xFF663399, + "Red" => 0xFFFF0000, + "RosyBrown" => 0xFFBC8F8F, + "RoyalBlue" => 0xFF4169E1, + "SaddleBrown" => 0xFF8B4513, + "Salmon" => 0xFFFA8072, + "SandyBrown" => 0xFFF4A460, + "SeaGreen" => 0xFF2E8B57, + "SeaShell" => 0xFFFFF5EE, + "Sienna" => 0xFFA0522D, + "Silver" => 0xFFC0C0C0, + "SkyBlue" => 0xFF87CEEB, + "SlateBlue" => 0xFF6A5ACD, + "SlateGray" => 0xFF708090, + "SlateGrey" => 0xFF708090, + "Snow" => 0xFFFFFAFA, + "SpringGreen" => 0xFF00FF7F, + "SteelBlue" => 0xFF4682B4, + "Tan" => 0xFFD2B48C, + "Teal" => 0xFF008080, + "Thistle" => 0xFFD8BFD8, + "Tomato" => 0xFFFF6347, + "Turquoise" => 0xFF40E0D0, + "Violet" => 0xFFEE82EE, + "Wheat" => 0xFFF5DEB3, + "White" => 0xFFFFFFFF, + "WhiteSmoke" => 0xFFF5F5F5, + "Yellow" => 0xFFFFFF00, + "YellowGreen" => 0xFF9ACD32, _ => throw new($"Color '{ColorName}' does not exist."), }; @@ -504,120 +633,6 @@ public static Color FromConsleColor(ConsoleColor Color) /// private readonly static Dictionary Cache = new(); - /// - /// Saturation of the color. - /// - public int Saturation - { - get - { - // Calculate the saturation of the color - int Max = Math.Max(_R, Math.Max(_G, _B)); - int Min = Math.Min(_R, Math.Min(_G, _B)); - return (Max - Min) / 255; - } - set - { - // Set the saturation of the color - int Max = Math.Max(_R, Math.Max(_G, _B)); - int Min = Math.Min(_R, Math.Min(_G, _B)); - int Diff = Max - Min; - if (Diff == 0) - { - _R = _G = _B = (byte)value; - } - else - { - _R = (byte)((Max - _R) * value / Diff + _R); - _G = (byte)((Max - _G) * value / Diff + _G); - _B = (byte)((Max - _B) * value / Diff + _B); - } - } - } - - /// - /// Packed ARGB value of the color. - /// - public uint ARGB - { - get - { - return _ARGB; - } - set - { - _ARGB = value; - _A = (byte)(_ARGB >> 24); - _R = (byte)(_ARGB >> 16); - _G = (byte)(_ARGB >> 8); - _B = (byte)(_ARGB); - } - } - - /// - /// Alpha channel of the color. - /// - public byte A - { - get - { - return _A; - } - set - { - _A = value; - _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); - } - } - - /// - /// Red channel of the color. - /// - public byte R - { - get - { - return _R; - } - set - { - _R = value; - _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); - } - } - - /// - /// Green channel of the color. - /// - public byte G - { - get - { - return _G; - } - set - { - _G = value; - _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); - } - } - - /// - /// Blue channel of the color. - /// - public byte B - { - get - { - return _B; - } - set - { - _B = value; - _ARGB = (uint)(_A << 24 | _R << 16 | _G << 8 | _B); - } - } - private uint _ARGB; private byte _A; private byte _R; @@ -626,6 +641,11 @@ public byte B #endregion + public override int GetHashCode() + { + return A * R / G * B; + } + public override string ToString() { return $"{typeof(Color).FullName} [A: {A}, R: {R}, G: {G}, B: {B}]"; diff --git a/PrismGraphics/Extentions/VBEConsole.cs b/PrismGraphics/Extentions/VBEConsole.cs index 7f7b4733..d7592ec9 100644 --- a/PrismGraphics/Extentions/VBEConsole.cs +++ b/PrismGraphics/Extentions/VBEConsole.cs @@ -1,4 +1,5 @@ using static Cosmos.HAL.Global; +using PrismGraphics.Fonts; using IL2CPU.API.Attribs; using PrismTools.IO; using Cosmos.Core; @@ -204,11 +205,11 @@ private static void WriteCore(char C) if (X >= Canvas.Width - SpacingX) { X = SpacingX; - Y += (int)Font.Fallback.Size; + Y += Font.Fallback.Size; } else { - X += (int)Font.Fallback.MeasureString(C.ToString()); + X += Font.Fallback.MeasureString(C.ToString()); } if (Y == Canvas.Height) { diff --git a/PrismGraphics/Font.cs b/PrismGraphics/Fonts/Font.cs similarity index 92% rename from PrismGraphics/Font.cs rename to PrismGraphics/Fonts/Font.cs index 59faf30b..ecc8287a 100644 --- a/PrismGraphics/Font.cs +++ b/PrismGraphics/Fonts/Font.cs @@ -1,61 +1,84 @@ -namespace PrismGraphics +namespace PrismGraphics.Fonts { /// - /// Nifanfa's bitfont class, ported to Prism OS. + /// A (mostly) custom made font class that uses glyph caching. + /// Font logic designed by nifanfa. /// - public unsafe class Font + public class Font { /// /// Creates a new instance of the class. /// /// Binary of the font file. /// Height of the font. - public Font(byte[] Binary, uint Size) + public Font(byte[] Binary, ushort Size) { - fixed (byte* PTR = Binary) - { - this.Binary = PTR; - } - Size16 = Size / 16; - Size8 = Size / 8; - Size4 = Size / 4; - Size2 = Size / 2; + // Assign font data. + this.Binary = Binary; + + // Assign size values. + Size8 = (ushort)(Size / 8); this.Size = Size; + + // Create cache instance. + Glyphs = new(); } #region Methods /// - /// Draws an invisive character, used for measuring the font. + /// Measures a string's total width. /// - /// X position of the char. - /// Y position of the char. - /// Char to draw. - /// Option to center in X and Y. - /// Width of the char. - private uint DrawChar(int X, int Y, char Char, bool Center) + /// String to measure. + /// Width of the input string. + public ushort MeasureString(string String) { - uint Index = (uint)DefaultCharset.IndexOf(Char); - if (Char == ' ') + ushort Width = 0; + + for (int I = 0; I < String.Length; I++) { - return Size2; + Width += (ushort)(GetGlyph(String[I]).Width + 2); } - if (Char == '\t') + + return Width; + } + + /// + /// Generates or loads a cached font glyph. + /// + /// The char to load a glyph for. + /// Existing or generated glyph. + public Glyph GetGlyph(char C) + { + // Return cached value if it exists. + if (Glyphs.ContainsKey(C)) { - return Size2 * 4; + return Glyphs[C]; } - if (Index < 0) + + // Create new empty glyph. + Glyph Temp = new(0, Size); + + // Get the index of the char in the font. + uint Index = (uint)DefaultCharset.IndexOf(C); + + if (C == ' ') { - return Size2; + Temp.Width = (ushort)(Size / 2); + return Temp; } - if (Center) + if (C == '\t') + { + Temp.Width = (ushort)(Size * 2); + return Temp; + } + if (Index < 0) { - X -= (int)Size16; - Y -= (int)Size8; + Temp.Width = (ushort)(Size / 2); + return Temp; } - uint MaxX = 0; - uint SizePerFont = Size * Size8 * Index; + ushort SizePerFont = (ushort)(Size * Size8 * Index); for (int h = 0; h < Size; h++) { @@ -65,31 +88,21 @@ private uint DrawChar(int X, int Y, char Char, bool Center) { if ((Binary[SizePerFont + (h * Size8) + aw] & (0x80 >> ww)) != 0) { - int N = (aw * 8) + ww; - if (N > MaxX) + int Max = (aw * 8) + ww; + + Temp.Points.Add((Max, h)); + + // Give the glyph the max with that the real glyph takes up. + if (Max > Temp.Width) { - MaxX = (uint)N; + Temp.Width = (ushort)Max; } } } } } - return MaxX; - } - /// - /// Measures a string's total width. - /// - /// String to measure. - /// Width of the input string. - public uint MeasureString(string String) - { - uint Width = 0; - for (int I = 0; I < String.Length; I++) - { - Width += DrawChar(0, 0, String[I], false) + 2; - } - return Width; + return Temp; } #endregion @@ -100,6 +113,7 @@ public uint MeasureString(string String) /// The standard charset of all fonts. /// public static string DefaultCharset = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + /// /// The default font used before other fonts can be loaded. /// @@ -296,29 +310,24 @@ public uint MeasureString(string String) }, 16); /// - /// The pointer to the raw memory for the font file. + /// The glyph cache, it stores previously used glyphs to increase performance by skipping rendering. /// - public byte* Binary; + public Dictionary Glyphs; + /// - /// Size divided by 16. + /// The pointer to the raw memory for the font file. /// - public uint Size16; + public byte[] Binary; + /// /// Size divided by 8. /// - public uint Size8; - /// - /// Size divided by 4. - /// - public uint Size4; - /// - /// Size divided by 2. - /// - public uint Size2; + public ushort Size8; + /// /// Size (Height) of the font. /// - public uint Size; + public ushort Size; #endregion } diff --git a/PrismGraphics/Fonts/Glyph.cs b/PrismGraphics/Fonts/Glyph.cs new file mode 100644 index 00000000..d2bbb9dc --- /dev/null +++ b/PrismGraphics/Fonts/Glyph.cs @@ -0,0 +1,38 @@ +namespace PrismGraphics.Fonts +{ + /// + /// The glyph class, used for caching font glyphs. + /// See: https://github.com/Project-Prism/Prism-OS/tree/main/PrismGraphics/Font/README.md#Glyphs + /// + public class Glyph + { + /// + /// Creates a new instance of the class. + /// + /// The width of the glyph. + /// The height of the glyph. + public Glyph(ushort Width, ushort Height) + { + this.Height = Height; + this.Width = Width; + Points = new(); + } + + #region Properties + + /// + /// A basic check to see if there are any pixels that need to be drawn. + /// + public bool IsEmpty => Points.Count == 0; + + #endregion + + #region Fields + + public List<(int X, int Y)> Points; + public ushort Height; + public ushort Width; + + #endregion + } +} \ No newline at end of file diff --git a/PrismGraphics/Fonts/README.md b/PrismGraphics/Fonts/README.md new file mode 100644 index 00000000..315bfc2a --- /dev/null +++ b/PrismGraphics/Fonts/README.md @@ -0,0 +1,11 @@ +
+ +# Glyphs + +Font glyphs are cached in the '[Glyph](https://github.com/Project-Prism/Prism-OS/tree/main/PrismGraphics/Font/Glyph.cs)' class, this allows fonts to be rendered very fast. + +## How it works + +When a glyph is cached, every pixel with an offset X and Y value is stored into the class, which allows it to directly render only the required pixels. A color can be applied even after caching because each pixel is not color dependant. + +
\ No newline at end of file diff --git a/PrismGraphics/Gradient.cs b/PrismGraphics/Gradient.cs index 4a48acfe..9067dfe2 100644 --- a/PrismGraphics/Gradient.cs +++ b/PrismGraphics/Gradient.cs @@ -12,11 +12,11 @@ public unsafe class Gradient : Graphics /// Width of the gradient. /// Height of the gradient. /// Colors to use. - public Gradient(uint Width, uint Height, Color[] Colors) : base(Width, Height) + public Gradient(ushort Width, ushort Height, Color[] Colors) : base(Width, Height) { - for (int Y = 0; Y < Height; Y++) + for (ushort Y = 0; Y < Height; Y++) { - for (int X = 0; X < Width; X++) + for (ushort X = 0; X < Width; X++) { this[X, Y] = InterpolateColors(Colors, 1 / Height * Y); } diff --git a/PrismGraphics/Graphics.cs b/PrismGraphics/Graphics.cs index f97e169f..5b238556 100644 --- a/PrismGraphics/Graphics.cs +++ b/PrismGraphics/Graphics.cs @@ -1,8 +1,8 @@ -// using System.Runtime.InteropServices; +// using System.Runtime.InteropServices; - Waiting for PR +using PrismGraphics.Fonts; using Cosmos.Core.Memory; using Cosmos.Core; -// Note: waiting for a PR to be merged. namespace PrismGraphics { /// @@ -15,7 +15,7 @@ public unsafe class Graphics : IDisposable /// /// Width of the canvas. /// Height of the canvas. - public Graphics(uint Width, uint Height) + public Graphics(ushort Width, ushort Height) { _Width = Width; _Height = Height; @@ -27,133 +27,142 @@ public Graphics(uint Width, uint Height) } } - #region Fields - - public uint* Internal { get; set; } - public uint Height + /// + /// Indexer to set or get a color value at the X and Y position. + /// + /// X position of the pixel. + /// Y position of the pixel. + /// The pixel color at X and Y. + public Color this[int X, int Y] { get { - return _Height; + return Internal[Y * Width + X]; } set { - if (_Height == value) + // Blend 2 colors together if the new color has alpha. + if (value.A < 255) { - return; + value = Color.AlphaBlend(this[X, Y], value); } - _Height = value; - - if (_Width != 0) - { - if (Internal == (uint*)0) - { - // Internal = (uint*)NativeMemory.Alloc(Size * 4); - Internal = (uint*)Heap.Alloc(Size * 4); - } - else - { - // Internal = (uint*)NativeMemory.Realloc(Internal, Size * 4); - Internal = (uint*)Heap.Realloc((byte*)Internal, Size * 4); - } - } + Internal[Y * Width + X] = value.ARGB; } } - public uint Width + + /// + /// Indexer to set or get a color value at the specified index. + /// + /// Index position of the pixel. + /// The pixel color at the linear index. + public Color this[uint Index] { get { - return _Width; + return Internal[Index]; } set { - if (_Width == value) + // Blend 2 colors together if the new color has alpha. + if (value.A < 255) { - return; + value = Color.AlphaBlend(this[Index], value); } - _Width = value; - - if (_Height != 0) - { - if (Internal == (uint*)0) - { - // Internal = (uint*)NativeMemory.Alloc(Size * 4); - Internal = (uint*)Heap.Alloc(Size * 4); - } - else - { - // Internal = (uint*)NativeMemory.Realloc(Internal, Size * 4); - Internal = (uint*)Heap.Realloc((byte*)Internal, Size * 4); - } - } - } - } - public uint Size - { - get - { - return _Width * _Height; + Internal[Index] = value.ARGB; } } - private uint _Height; - private uint _Width; - - #endregion - - #region Pixel + #region Properties /// - /// Indexer to set or get a color value at the X and Y position. + /// The total height of the canvas in pixels. /// - /// X position of the pixel. - /// Y position of the pixel. - /// The pixel color at X and Y. - public Color this[long X, long Y] + public ushort Height { get { - return Internal[Y * Width + X]; + return _Height; } set { - // Blend 2 colors together if the new color has alpha. - if (value.A < 255) + if (_Height == value) { - value = Color.AlphaBlend(this[X, Y], value); + return; + } + if (_Width == 0) + { + _Height = value; + return; } - Internal[Y * Width + X] = value.ARGB; + _Height = value; + + if (Internal == (uint*)0) + { + // Internal = (uint*)NativeMemory.Alloc(Size * 4); + Internal = (uint*)Heap.Alloc(Size * 4); + } + else + { + // Internal = (uint*)NativeMemory.Realloc(Internal, Size * 4); + Internal = (uint*)Heap.Realloc((byte*)Internal, Size * 4); + } } } /// - /// Indexer to set or get a color value at the specified index. + /// The total width of the canvas in pixels. /// - /// Index position of the pixel. - /// The pixel color at the linear index. - public Color this[long Index] + public ushort Width { get { - return Internal[Index]; + return _Width; } set { - // Blend 2 colors together if the new color has alpha. - if (value.A < 255) + if (_Width == value) { - value = Color.AlphaBlend(this[Index], value); + return; + } + if (_Height == 0) + { + _Width = value; + return; } - Internal[Index] = value.ARGB; + _Width = value; + + if (Internal == (uint*)0) + { + // Internal = (uint*)NativeMemory.Alloc(Size * 4); + Internal = (uint*)Heap.Alloc(Size * 4); + } + else + { + // Internal = (uint*)NativeMemory.Realloc(Internal, Size * 4); + Internal = (uint*)Heap.Realloc((byte*)Internal, Size * 4); + } + } + } + + /// + /// The total area of the canvas in pixels. + /// + public uint Size + { + get + { + return (uint)(_Width * _Height); } } #endregion + #region Methods + #region Rectangle /// @@ -165,7 +174,7 @@ public Color this[long Index] /// Height of the rectangle /// Border radius of the rectangle. /// Color to draw with. - public void DrawFilledRectangle(long X, long Y, long Width, long Height, long Radius, Color Color) + public void DrawFilledRectangle(int X, int Y, ushort Width, ushort Height, ushort Radius, Color Color) { // Just clear the screen if the color fills the screen. if (X == 0 && Y == 0 && Width == this.Width && Height == this.Height && Radius == 0 && Color.A == 255) @@ -179,35 +188,38 @@ public void DrawFilledRectangle(long X, long Y, long Width, long Height, long Ra { if (X < 0) { - Width -= (uint)Math.Abs(X); + Width -= (ushort)Math.Abs(X); X = 0; } if (Y < 0) { - Height -= (uint)Math.Abs(Y); + Height -= (ushort)Math.Abs(Y); Y = 0; } if (X + Width >= this.Width) { - Width -= (uint)X; + Width -= (ushort)X; } if (Y + Height >= this.Height) { - Height -= (uint)Y; + Height -= (ushort)Y; } + for (int IY = 0; IY < Height; IY++) { - MemoryOperations.Fill(Internal + ((Y + IY) * this.Width + X), Color.ARGB, (int)Width); + MemoryOperations.Fill(Internal + ((Y + IY) * this.Width + X), Color.ARGB, Width); } + + // Make sure to return. return; } // Fastest alpha supporting rectangle. if (Radius == 0) { - for (long IX = X; IX < X + Width; IX++) + for (int IX = X; IX < X + Width; IX++) { - for (long IY = Y; IY < Y + Height; IY++) + for (int IY = Y; IY < Y + Height; IY++) { this[IX, IY] = Color; } @@ -223,8 +235,8 @@ public void DrawFilledRectangle(long X, long Y, long Width, long Height, long Ra DrawFilledCircle(X + Radius, Y + Height - Radius - 1, Radius, Color); DrawFilledCircle(X + Width - Radius - 1, Y + Height - Radius - 1, Radius, Color); - DrawFilledRectangle(X + Radius, Y, Width - Radius * 2, Height, 0, Color); - DrawFilledRectangle(X, Y + Radius, Width, Height - Radius * 2, 0, Color); + DrawFilledRectangle(X + Radius, Y, (ushort)(Width - Radius * 2), Height, 0, Color); + DrawFilledRectangle(X, Y + Radius, Width, (ushort)(Height - Radius * 2), 0, Color); } } @@ -237,9 +249,9 @@ public void DrawFilledRectangle(long X, long Y, long Width, long Height, long Ra /// Height of the rectangle /// Border radius of the rectangle. /// Color to draw with. - public void DrawRectangle(long X, long Y, long Width, long Height, long Radius, Color Color) - { // This is essentialy just incomprehensible garbage that should never be touched, don't ever worry about it as i have worked out the corrdinates already and have verified it to be 100% correct. - + public void DrawRectangle(int X, int Y, ushort Width, ushort Height, ushort Radius, Color Color) + { + // Draw circles to add curvature if needed. if (Radius > 0) { DrawArc(Radius + X, Radius + Y, Radius, Color, 180, 270); // Top left @@ -247,6 +259,7 @@ public void DrawRectangle(long X, long Y, long Width, long Height, long Radius, DrawArc(Radius + X, Y + Height - Radius, Radius, Color, 90, 180); // Bottom left DrawArc(X + Width - Radius, Radius + Y, Radius, Color, 270, 360); } + DrawLine(X + Radius, Y, X + Width - Radius, Y, Color); // Top Line DrawLine(X + Radius, Y + Height, X + Width - Radius, Height + Y, Color); // Bottom Line DrawLine(X, Y + Radius, X, Y + Height - Radius, Color); // Left Line @@ -263,7 +276,7 @@ public void DrawRectangle(long X, long Y, long Width, long Height, long Radius, /// Scale of all blocks. /// Color of block type 1. /// Color of block type 2. - public void DrawRectangleGrid(long X, long Y, long BlockCountX, long BlockCountY, long BlockSize, Color BlockType1, Color BlockType2) + public void DrawRectangleGrid(int X, int Y, ushort BlockCountX, ushort BlockCountY, ushort BlockSize, Color BlockType1, Color BlockType2) { for (int IX = 0; IX < BlockCountX; IX++) { @@ -295,62 +308,61 @@ public void DrawRectangleGrid(long X, long Y, long BlockCountX, long BlockCountY /// X position 3. /// Y position 3. /// Color to draw with. - public void DrawFilledTriangle(long X1, long Y1, long X2, long Y2, long X3, long Y3, Color Color, bool UseAntiAliasing = false) + public void DrawFilledTriangle(int X1, int Y1, int X2, int Y2, int X3, int Y3, Color Color, bool UseAntiAliasing = false) { - // 28.4 fixed-point coordinates - Y1 = (long)Math.Round(16.0f * Y1); - Y2 = (long)Math.Round(16.0f * Y2); - Y3 = (long)Math.Round(16.0f * Y3); + Y1 = (int)Math.Round(16.0f * Y1); + Y2 = (int)Math.Round(16.0f * Y2); + Y3 = (int)Math.Round(16.0f * Y3); - X1 = (long)Math.Round(16.0f * X1); - X2 = (long)Math.Round(16.0f * X2); - X3 = (long)Math.Round(16.0f * X3); + X1 = (int)Math.Round(16.0f * X1); + X2 = (int)Math.Round(16.0f * X2); + X3 = (int)Math.Round(16.0f * X3); // Deltas - long DX12 = X1 - X2; - long DX23 = X2 - X3; - long DX31 = X3 - X1; + int DX12 = X1 - X2; + int DX23 = X2 - X3; + int DX31 = X3 - X1; - long DY12 = Y1 - Y2; - long DY23 = Y2 - Y3; - long DY31 = Y3 - Y1; + int DY12 = Y1 - Y2; + int DY23 = Y2 - Y3; + int DY31 = Y3 - Y1; // Fixed-point deltas - long FDX12 = DX12 << 4; - long FDX23 = DX23 << 4; - long FDX31 = DX31 << 4; + int FDX12 = DX12 << 4; + int FDX23 = DX23 << 4; + int FDX31 = DX31 << 4; - long FDY12 = DY12 << 4; - long FDY23 = DY23 << 4; - long FDY31 = DY31 << 4; + int FDY12 = DY12 << 4; + int FDY23 = DY23 << 4; + int FDY31 = DY31 << 4; // Bounding rectangle - long MinX = (Math.Min(Math.Min(X1, X2), X3) + 0xF) >> 4; - long MaxX = (Math.Max(Math.Max(X1, X2), X3) + 0xF) >> 4; - long MinY = (Math.Min(Math.Min(Y1, Y2), Y3) + 0xF) >> 4; - long MaxY = (Math.Max(Math.Max(Y1, Y2), Y3) + 0xF) >> 4; + int MinX = (Math.Min(Math.Min(X1, X2), X3) + 0xF) >> 4; + int MaxX = (Math.Max(Math.Max(X1, X2), X3) + 0xF) >> 4; + int MinY = (Math.Min(Math.Min(Y1, Y2), Y3) + 0xF) >> 4; + int MaxY = (Math.Max(Math.Max(Y1, Y2), Y3) + 0xF) >> 4; // Half-edge constants - long C1 = DY12 * X1 - DX12 * Y1; - long C2 = DY23 * X2 - DX23 * Y2; - long C3 = DY31 * X3 - DX31 * Y3; + int C1 = DY12 * X1 - DX12 * Y1; + int C2 = DY23 * X2 - DX23 * Y2; + int C3 = DY31 * X3 - DX31 * Y3; // Correct for fill convention if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++; if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++; if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++; - long CY1 = C1 + DX12 * (MinY << 4) - DY12 * (MinX << 4); - long CY2 = C2 + DX23 * (MinY << 4) - DY23 * (MinX << 4); - long CY3 = C3 + DX31 * (MinY << 4) - DY31 * (MinX << 4); + int CY1 = C1 + DX12 * (MinY << 4) - DY12 * (MinX << 4); + int CY2 = C2 + DX23 * (MinY << 4) - DY23 * (MinX << 4); + int CY3 = C3 + DX31 * (MinY << 4) - DY31 * (MinX << 4); - for (long Y = MinY; Y < MaxY; Y++) + for (int Y = MinY; Y < MaxY; Y++) { - long CX1 = CY1; - long CX2 = CY2; - long CX3 = CY3; + int CX1 = CY1; + int CX2 = CY2; + int CX3 = CY3; - for (long X = MinX; X < MaxX; X++) + for (int X = MinX; X < MaxX; X++) { if (CX1 > 0 && CX2 > 0 && CX3 > 0) { @@ -383,7 +395,7 @@ public void DrawFilledTriangle(long X1, long Y1, long X2, long Y2, long X3, long /// X position 3. /// Y position 3. /// Color to draw with. - public void DrawTriangle(long X1, long Y1, long X2, long Y2, long X3, long Y3, Color Color, bool UseAntiAliasing = false) + public void DrawTriangle(int X1, int Y1, int X2, int Y2, int X3, int Y3, Color Color, bool UseAntiAliasing = false) { DrawLine(X1, Y1, X2, Y2, Color, UseAntiAliasing); DrawLine(X1, Y1, X3, Y3, Color, UseAntiAliasing); @@ -401,34 +413,39 @@ public void DrawTriangle(long X1, long Y1, long X2, long Y2, long X3, long Y3, C /// Center Y of the circle. /// Radius of the circle. /// Color to draw with. - public void DrawFilledCircle(long X, long Y, long Radius, Color Color) + public void DrawFilledCircle(int X, int Y, ushort Radius, Color Color) { + // Quit if there is nothing to draw. if (Radius == 0) { return; } - + + // Check if the circle can be drawn fast. if (Color.A == 255) - { // This method fills the length of the circle from the correct X and Length values for every Y pixel in the circle, it uses memcpy to make it fast. - long R2 = Radius * Radius; - for (long IY = -Radius; IY <= Radius; IY++) + { + ushort R2 = (ushort)(Radius * Radius); + + for (int IY = -Radius; IY <= Radius; IY++) { - uint IX = (uint)(Math.Sqrt(R2 - IY * IY) + 0.5); + int IX = (int)(Math.Sqrt(R2 - IY * IY) + 0.5); uint* Offset = Internal + (Width * (Y + IY)) + X - IX; - MemoryOperations.Fill(Offset, Color.ARGB, (int)IX * 2); + MemoryOperations.Fill(Offset, Color.ARGB, IX * 2); } + + // Be sure to return. + return; } - else + + // Draw using slow algorithm. + for (int IX = -Radius; IX < Radius; IX++) { - for (long IX = -Radius; IX < Radius; IX++) - { - long Height = (long)Math.Sqrt((Radius * Radius) - (IX * IX)); + int Height = (int)Math.Sqrt((Radius * Radius) - (IX * IX)); - for (long IY = -Height; IY < Height; IY++) - { - this[IX + X, IY + Y] = Color; - } + for (int IY = -Height; IY < Height; IY++) + { + this[IX + X, IY + Y] = Color; } } } @@ -440,9 +457,9 @@ public void DrawFilledCircle(long X, long Y, long Radius, Color Color) /// Center Y of the circle. /// Radius of the circle. /// Color to draw with. - public void DrawCircle(long X, long Y, long Radius, Color Color) + public void DrawCircle(int X, int Y, ushort Radius, Color Color) { - long IX = 0, IY = Radius, DP = 3 - 2 * Radius; + int IX = 0, IY = Radius, DP = 3 - 2 * Radius; while (IY >= IX) { @@ -456,6 +473,7 @@ public void DrawCircle(long X, long Y, long Radius, Color Color) this[X - IY, Y - IX] = Color; IX++; + if (DP > 0) { IY--; @@ -483,20 +501,20 @@ public void DrawCircle(long X, long Y, long Radius, Color Color) /// Y position 2. /// Color to draw with. /// Used inside the method only. - public void DrawQuadraticBezierLine(long X1, long Y1, long X2, long Y2, long X3, long Y3, Color Color, int N = 6) + public void DrawQuadraticBezierLine(int X1, int Y1, int X2, int Y2, int X3, int Y3, Color Color, byte N = 6) { // X2 and Y2 is where the curve should bend to. if (N > 0) { - long X12 = (X1 + X2) / 2; - long Y12 = (Y1 + Y2) / 2; - long X23 = (X2 + X3) / 2; - long Y23 = (Y2 + Y3) / 2; - long X123 = (X12 + X23) / 2; - long Y123 = (Y12 + Y23) / 2; + int X12 = (X1 + X2) / 2; + int Y12 = (Y1 + Y2) / 2; + int X23 = (X2 + X3) / 2; + int Y23 = (Y2 + Y3) / 2; + int X123 = (X12 + X23) / 2; + int Y123 = (Y12 + Y23) / 2; - DrawQuadraticBezierLine(X1, Y1, X12, Y12, X123, Y123, Color, N - 1); - DrawQuadraticBezierLine(X123, Y123, X23, Y23, X3, Y3, Color, N - 1); + DrawQuadraticBezierLine(X1, Y1, X12, Y12, X123, Y123, Color, (byte)(N - 1)); + DrawQuadraticBezierLine(X123, Y123, X23, Y23, X3, Y3, Color, (byte)(N - 1)); } else { @@ -517,7 +535,7 @@ public void DrawQuadraticBezierLine(long X1, long Y1, long X2, long Y2, long X3, /// X position 2. /// Y position 2. /// Color to draw with. - public void DrawCubicBezierLine(long X1, long Y1, long X2, long Y2, long X3, long Y3, long X4, long Y4, Color Color) + public void DrawCubicBezierLine(int X1, int Y1, int X2, int Y2, int X3, int Y3, int X4, int Y4, Color Color) { for (double U = 0.0; U <= 1.0; U += 0.0001) { @@ -528,8 +546,8 @@ public void DrawCubicBezierLine(long X1, long Y1, long X2, long Y2, long X3, lon double XU = Power3V1 * X1 + 3 * U * Power2V1 * X2 + 3 * Power2V2 * (1 - U) * X3 + Power3V2 * X4; double YU = Power3V1 * Y1 + 3 * U * Power2V1 * Y2 + 3 * Power2V2 * (1 - U) * Y3 + Power3V2 * Y4; - - this[(long)XU, (long)YU] = Color; + + this[(int)XU, (int)YU] = Color; } } @@ -542,11 +560,11 @@ public void DrawCubicBezierLine(long X1, long Y1, long X2, long Y2, long X3, lon /// Y position 2. /// Color to draw with. /// Enable or disable the use of anti-aliasing. - public void DrawLine(long X1, long Y1, long X2, long Y2, Color Color, bool UseAntiAlias = false) + public void DrawLine(int X1, int Y1, int X2, int Y2, Color Color, bool UseAntiAlias = false) { - long DX = Math.Abs(X2 - X1), SX = X1 < X2 ? 1 : -1; - long DY = Math.Abs(Y2 - Y1), SY = Y1 < Y2 ? 1 : -1; - long err = (DX > DY ? DX : -DY) / 2; + int DX = Math.Abs(X2 - X1), SX = X1 < X2 ? 1 : -1; + int DY = Math.Abs(Y2 - Y1), SY = Y1 < Y2 ? 1 : -1; + int err = (DX > DY ? DX : -DY) / 2; while (X1 != X2 || Y1 != Y2) { @@ -565,7 +583,9 @@ public void DrawLine(long X1, long Y1, long X2, long Y2, Color Color, bool UseAn this[X1, Y1 - 1] = Color.FromARGB((byte)(Color.A / 2), Color.R, Color.G, Color.B); } } - long E2 = err; + + int E2 = err; + if (E2 > -DX) { err -= DY; X1 += SX; } if (E2 < DY) { err += DX; Y1 += SY; } } @@ -579,10 +599,11 @@ public void DrawLine(long X1, long Y1, long X2, long Y2, Color Color, bool UseAn /// Angle in degrees. /// Radius or Length. /// Color to draw with. - public void DrawAngledLine(long X, long Y, int Angle, long Radius, Color Color) + public void DrawAngledLine(int X, int Y, short Angle, ushort Radius, Color Color) { - long IX = (long)(Radius * Math.Cos(Math.PI * Angle / 180)); - long IY = (long)(Radius * Math.Sin(Math.PI * Angle / 180)); + int IX = (int)(Radius * Math.Cos(Math.PI * Angle / 180)); + int IY = (int)(Radius * Math.Sin(Math.PI * Angle / 180)); + DrawLine(X, Y, X + IX, Y + IY, Color); } @@ -599,14 +620,15 @@ public void DrawAngledLine(long X, long Y, int Angle, long Radius, Color Color) /// Color to draw with. /// Angle at which to start. /// Angle at which to end. - public void DrawFilledArc(long X, long Y, long Radius, Color Color, int StartAngle = 0, int EndAngle = 360) + public void DrawFilledArc(int X, int Y, ushort Radius, Color Color, int StartAngle = 0, int EndAngle = 360) { + // Quit if nothing needs to be drawn. if (Radius == 0) { return; } - for (uint I = 0; I < Radius; I++) + for (ushort I = 0; I < Radius; I++) { DrawArc(X, Y, I, Color, StartAngle, EndAngle); } @@ -622,14 +644,20 @@ public void DrawFilledArc(long X, long Y, long Radius, Color Color, int StartAng /// Color to draw with. /// Angle at which to start. /// Angle at which to end. - public void DrawArc(long X, long Y, long Width, long Height, Color Color, int StartAngle = 0, int EndAngle = 360) + public void DrawArc(int X, int Y, ushort Width, ushort Height, Color Color, int StartAngle = 0, int EndAngle = 360) { + // Quit if nothing needs to be drawn. + if (Width == 0 || Height == 0) + { + return; + } + for (double Angle = StartAngle; Angle < EndAngle; Angle += 0.5) { double Angle1 = Math.PI * Angle / 180; - long IX = (long)(Width * Math.Cos(Angle1)); - long IY = (long)(Height * Math.Sin(Angle1)); + int IX = (int)(Width * Math.Cos(Angle1)); + int IY = (int)(Height * Math.Sin(Angle1)); this[X + IX, Y + IY] = Color; } @@ -644,14 +672,20 @@ public void DrawArc(long X, long Y, long Width, long Height, Color Color, int St /// Color to draw with. /// Angle at which to start. /// Angle at which to end. - public void DrawArc(long X, long Y, long Radius, Color Color, int StartAngle = 0, int EndAngle = 360) + public void DrawArc(int X, int Y, ushort Radius, Color Color, int StartAngle = 0, int EndAngle = 360) { + // Quit if nothing needs to be drawn. + if (Radius == 0) + { + return; + } + for (double Angle = StartAngle; Angle < EndAngle; Angle += 0.5) { double Angle1 = Math.PI * Angle / 180; - long IX = (long)(Radius * Math.Cos(Angle1)); - long IY = (long)(Radius * Math.Sin(Angle1)); + int IX = (int)(Radius * Math.Cos(Angle1)); + int IY = (int)(Radius * Math.Sin(Angle1)); this[X + IX, Y + IY] = Color; } @@ -669,7 +703,7 @@ public void DrawArc(long X, long Y, long Radius, Color Color, int StartAngle = 0 /// Image to draw. /// Option to not use alpha, it will be faster if it's disabled. /// Thrown when input is null. - public void DrawImage(long X, long Y, Graphics Image, bool Alpha = true) + public void DrawImage(int X, int Y, Graphics Image, bool Alpha = true) { // Basic null check. if (Image == null) @@ -677,6 +711,16 @@ public void DrawImage(long X, long Y, Graphics Image, bool Alpha = true) throw new NullReferenceException("Cannot draw a null image file."); } + // Quit if nothing needs to be drawn. + if (X + Image.Width < 0 || Y + Image.Height < 0) + { + return; + } + if (X >= Width || Y >= Height) + { + return; + } + // Fastest copy-only draw method, fills the whole buffer. if (!Alpha && X == 0 && Y == 0 && Image.Width == Width && Image.Height == Height) { @@ -741,7 +785,7 @@ public void DrawImage(long X, long Y, Graphics Image, bool Alpha = true) /// Font to use. /// Color to draw with. /// Option to cented the text at X and Y. - public void DrawString(long X, long Y, string Text, Font Font, Color Color, bool Center = false) + public void DrawString(int X, int Y, string Text, Font Font, Color Color, bool Center = false) { // Basic null check. if (Text == null || Text.Length == 0) @@ -749,15 +793,22 @@ public void DrawString(long X, long Y, string Text, Font Font, Color Color, bool return; } + // Quit if nothing needs to be drawn. + if (X >= Width || Y >= Height) + { + return; + } + string[] Lines = Text.Split('\n'); // Loop Through Each Line Of Text for (int Line = 0; Line < Lines.Length; Line++) { // Advanced Calculations To Determine Position - long IX = X - (Center ? (Font.MeasureString(Text) / 2) : 0); - long IY = Y + (Font.Size * Line) - (Center ? Font.Size * Lines.Length / 2 : 0); + int IX = X - (Center ? (Font.MeasureString(Text) / 2) : 0); + int IY = Y + (Font.Size * Line) - (Center ? Font.Size * Lines.Length / 2 : 0); + // Skip if nothig needs to be drawn. if (IY > Height) { return; @@ -766,10 +817,12 @@ public void DrawString(long X, long Y, string Text, Font Font, Color Color, bool // Loop Though Each Char In The Line for (int Char = 0; Char < Lines[Line].Length; Char++) { + // Skip if nothig needs to be drawn. if (IX > Width) { continue; } + IX += DrawChar(IX, IY, Lines[Line][Char], Font, Color, Center) + 2; } } @@ -785,54 +838,32 @@ public void DrawString(long X, long Y, string Text, Font Font, Color Color, bool /// Color to draw with. /// Option to center the char at X and Y. /// Width of the drawn character. - public uint DrawChar(long X, long Y, char Char, Font Font, Color Color, bool Center) + public int DrawChar(int X, int Y, char Char, Font Font, Color Color, bool Center) { - // Get the index of the char in the font. - uint Index = (uint)Font.DefaultCharset.IndexOf(Char); + // Get the glyph for this char. + Glyph Temp = Font.GetGlyph(Char); - if (Char == ' ') - { - return Font.Size2; - } - if (Char == '\t') - { - return Font.Size2 * 4; - } - if (Index < 0) - { - return Font.Size2; - } + // Center the position if needed. if (Center) { - X -= Font.Size16; - Y -= Font.Size8; + Y -= Temp.Height / 2; + X -= Temp.Width / 2; } - uint MaxX = 0; - uint SizePerFont = Font.Size * Font.Size8 * Index; - - for (int h = 0; h < Font.Size; h++) + // Return if nothing needs to be done. + if (Temp.IsEmpty) { - for (int aw = 0; aw < Font.Size8; aw++) - { - for (int ww = 0; ww < 8; ww++) - { - if ((Font.Binary[SizePerFont + (h * Font.Size8) + aw] & (0x80 >> ww)) != 0) - { - int Max = (aw * 8) + ww; - - this[X + Max, Y + h] = Color; + return Temp.Width; + } - if (Max > MaxX) - { - MaxX = (uint)Max; - } - } - } - } + // Draw all pixels. + for (int I = 0; I < Temp.Points.Count; I++) + { + this[X + Temp.Points[I].X, Y + Temp.Points[I].Y] = Color; } - return MaxX; + // Return total width of the glyph. + return Temp.Width; } #endregion @@ -852,8 +883,8 @@ public Graphics Rotate(double Angle) { for (int Y = 0; Y < Height; Y++) { - long X2 = (long)(Math.Cos(Angle) * X - Math.Sin(Angle) * Y); - long Y2 = (long)(Math.Sin(Angle) * X + Math.Cos(Angle) * Y); + int X2 = (int)(Math.Cos(Angle) * X - Math.Sin(Angle) * Y); + int Y2 = (int)(Math.Sin(Angle) * X + Math.Cos(Angle) * Y); Result[X2, Y2] = this[X, Y]; } @@ -870,7 +901,7 @@ public Graphics Rotate(double Angle) /// /// Scaled image. /// Thrown if scale method does not exist. - public Graphics Scale(uint Width, uint Height) + public Graphics Scale(ushort Width, ushort Height) { // Out of bounds check. if (Width <= 0 || Height <= 0 || Width == this.Width || Height == this.Height) @@ -878,7 +909,7 @@ public Graphics Scale(uint Width, uint Height) return this; } - // Create temporary buffer. + // Create a temporary buffer. Graphics FB = new(Width, Height); // Find the scale ratios. @@ -888,10 +919,12 @@ public Graphics Scale(uint Width, uint Height) for (uint Y = 0; Y < Height; Y++) { double PY = Math.Floor(Y * YRatio); + for (uint X = 0; X < Width; X++) { double PX = Math.Floor(X * XRatio); - FB[Y * Width + X] = Internal[(long)((PY * this.Width) + PX)]; + + FB[Y * Width + X] = Internal[(uint)((PY * this.Width) + PX)]; } } @@ -940,5 +973,16 @@ public void Dispose() } #endregion + + #endregion + + #region Fields + + public uint* Internal { get; set; } + + private ushort _Height; + private ushort _Width; + + #endregion } } \ No newline at end of file diff --git a/PrismGraphics/Image.cs b/PrismGraphics/Image.cs index d2f56122..bb86dda0 100644 --- a/PrismGraphics/Image.cs +++ b/PrismGraphics/Image.cs @@ -11,7 +11,7 @@ public unsafe class Image : Graphics /// /// Width of the image. /// Height of the image. - public Image(uint Width, uint Height) : base(Width, Height) { } + public Image(ushort Width, ushort Height) : base(Width, Height) { } #region Structure @@ -42,7 +42,7 @@ private struct TGAHeader public static Image FromBitmap(byte[] Binary) { Cosmos.System.Graphics.Bitmap BMP = new(Binary); - Image Result = new(BMP.Width, BMP.Height); + Image Result = new((ushort)BMP.Width, (ushort)BMP.Height); fixed (int* PTR = BMP.rawData) { @@ -84,8 +84,8 @@ public static Image FromPNG(byte[] Binary) switch (Encoding.ASCII.GetString(Reader.ReadBytes(4))) { case "IHDR": - Result.Width = Reader.ReadUInt32(); - Result.Height = Reader.ReadUInt32(); + Result.Width = (ushort)Reader.ReadUInt32(); + Result.Height = (ushort)Reader.ReadUInt32(); Reader.BaseStream.Position += 5; break; case "PLTE": @@ -182,8 +182,8 @@ public static Image FromTGA(byte[] Binary) Header = (TGAHeader*)P; } - Result.Height = (uint)Header->Height; - Result.Width = (uint)Header->Width; + Result.Height = (ushort)Header->Height; + Result.Width = (ushort)Header->Width; switch (Header->ColorDepth) { @@ -244,7 +244,7 @@ public static Image FromPPM(byte[] Binary) Reader.ReadChar(); // Skip Newline - Image Result = new(uint.Parse(widths), uint.Parse(heights)); + Image Result = new((ushort)uint.Parse(widths), (ushort)uint.Parse(heights)); for (int Y = 0; Y < Result.Height; Y++) { diff --git a/PrismGraphics/README.md b/PrismGraphics/README.md new file mode 100644 index 00000000..f9be02fe --- /dev/null +++ b/PrismGraphics/README.md @@ -0,0 +1,25 @@ +# Introduction - PrismGraphics + +PrismgGraphics is the 2D graphics rasterization platform that allows for drawing of text, images, shapes, gradients, and whatever else on a 2D canvas. + +This readme is still in progress, not finished! + +> There is no hardware acceleration and is constantly WIP, expect bugs! + +
+ +## PrismGraphics/Animators + +This folder consains animation tools to aid in making special GFX. + +### FadeControler + +This animation controler fades from one color to another over a period of time based on the mode it is set in. The available modes are as follows: + +
+ +- ``FastInSlowOut`` - The color will transition fast at the beginning but slow down as it continues. +- ``FastOutSlowIn`` - The color will transition slow at the beginning but speed up as it continues. +- ``Linear`` - The color will transition at the same speed for the entire duration of the transition. + +
\ No newline at end of file diff --git a/PrismGraphics3D/Engine.cs b/PrismGraphics3D/Engine.cs index 9165ca69..e675d62e 100644 --- a/PrismGraphics3D/Engine.cs +++ b/PrismGraphics3D/Engine.cs @@ -7,7 +7,7 @@ namespace PrismGraphics3D public class Engine : Graphics { // To-Do: Implement Camera Rotation - public Engine(uint Width, uint Height, double FOV) : base(Width, Height) + public Engine(ushort Width, ushort Height, double FOV) : base(Width, Height) { this.Height = Height; this.Width = Width; diff --git a/PrismOS/Program.cs b/PrismOS/Program.cs index 15882f82..8103fbe5 100644 --- a/PrismOS/Program.cs +++ b/PrismOS/Program.cs @@ -20,9 +20,11 @@ public unsafe class Program : Kernel { protected override void BeforeRun() { + // Initialize debugger. Debugger = new("Kernel"); - System.Console.Clear(); + // Clear console & display ascii art. + System.Console.Clear(); System.Console.WriteLine(@" ____ _ ____ _____"); System.Console.WriteLine(@" / __ \_____(_)________ ___ / __ \/ ___/"); System.Console.WriteLine(@" / /_/ / ___/ / ___/ __ `__ \ / / / /\__ \ "); @@ -30,6 +32,7 @@ protected override void BeforeRun() System.Console.WriteLine(@"/_/ /_/ /_/____/_/ /_/ /_/ \____//____/ "); System.Console.WriteLine("CopyLeft PrismProject 2022. Licensed with GPL2.\n"); + // Initialize system services. NetworkManager.Init(); SystemCalls.Init(); VBEConsole.Init(); @@ -38,6 +41,12 @@ protected override void BeforeRun() { VFSManager.RegisterVFS(new CosmosVFS(), false, false); Debugger.Log("Initialized filesystem!", Debugger.Severity.Ok); + + // Write the testing ELF to the filesystem (Temporary). + if (!File.Exists("0:\\Test.elf")) + { + File.WriteAllBytes("0:\\Test.elf", Assets.ELF); + } } catch { diff --git a/PrismRuntime/PrismRuntime.csproj b/PrismRuntime/PrismRuntime.csproj index 3bf9ed82..feaed567 100644 --- a/PrismRuntime/PrismRuntime.csproj +++ b/PrismRuntime/PrismRuntime.csproj @@ -14,6 +14,7 @@ + diff --git a/PrismRuntime/SShell/Scripts/Unix.cs b/PrismRuntime/SShell/Scripts/Unix.cs index 537c3feb..416f0f3d 100644 --- a/PrismRuntime/SShell/Scripts/Unix.cs +++ b/PrismRuntime/SShell/Scripts/Unix.cs @@ -1,11 +1,12 @@ -using PrismRuntime.SShell.Structure; +using PrismBinary.Formats.ELF.Structure.ELFHeader; +using PrismRuntime.SShell.Structure; using Console = System.Console; using Cosmos.System; using Cosmos.Core; namespace PrismRuntime.SShell.Scripts { - public static class Unix + public static unsafe class Unix { public class PowerOff : Script { @@ -16,6 +17,74 @@ public override void Invoke(string[] Args) Power.Shutdown(); } } + public class HexDump : Script + { + public HexDump() : base("hexdump", "Print all bytes of a file as 'readable' hex.") + { + AdvancedDescription = "hexdump [NumberOfBytes] [path/to/file]"; + } + + public override void Invoke(string[] Args) + { + // Check if improper arguments were specifed. + if (Args.Length < 2 || Args[0].Length == 0 || Args[1].Length == 0) + { + Console.WriteLine("Please specify proper options. Run 'man hexdump' for more info."); + return; + } + + // Check if the file exists + if (int.TryParse(Args[0], out int N) && N > 0 && File.Exists(Args[1])) + { + // Load the file into memory. + byte[] Hex = File.ReadAllBytes(Args[1]); + + // Print the number of hex bytes specified from the file. + Console.WriteLine("0x" + BitConverter.ToString(Hex, 0, N).Replace("-", " 0x")); + } + } + } + public class ReadELF : Script + { + public ReadELF() : base("readelf", "Read about ELF files on the filesystem.") + { + AdvancedDescription = + "readelf [options] [path/to/elf]\n" + + "\tOnly '-h' is implemented at the moment."; + } + + public override void Invoke(string[] Args) + { + // Check if improper arguments were specifed. + if (Args.Length < 2 || Args[0].Length == 0 || Args[1].Length == 0) + { + Console.WriteLine("Please specify proper options. Run 'man readelf' for more info."); + return; + } + + // Check if the file exists + if (Args[0] == "-h" && File.Exists(Args[1])) + { + fixed (byte* P = File.ReadAllBytes(Args[1])) + { + // Read the ELF header. + ELFHeader32 Header = new((ELFHeader32*)P); + + // Print out it's details. + Console.WriteLine($"Is Valid: {Header.IsValid()}"); + Console.WriteLine($"Type: {Header.Type}"); + Console.WriteLine($"Machine Type: {Header.MachineType}"); + Console.WriteLine($"Machine Version: {Header.MachineVersion}"); + Console.WriteLine($"Entry Point: 0x{Header.EntryPoint}"); + } + } + else + { + Console.WriteLine($"Impropper arguments were specified."); + return; + } + } + } public class Reboot : Script { public Reboot() : base("reboot", "Reboots the system.") { } diff --git a/PrismRuntime/SShell/Shell.cs b/PrismRuntime/SShell/Shell.cs index fffa73cc..458f60e0 100644 --- a/PrismRuntime/SShell/Shell.cs +++ b/PrismRuntime/SShell/Shell.cs @@ -1,11 +1,13 @@ -using PrismRuntime.SShell.Structure; +using PrismBinary.Formats.ELF.Structure.ELFHeader; +using PrismRuntime.SShell.Structure; using PrismRuntime.SShell.Scripts; +using PrismBinary.Formats.ELF; using PrismRuntime.SSharp; using PrismTools; namespace PrismRuntime.SShell { - public static class Shell + public static unsafe class Shell { #region Methods @@ -46,16 +48,31 @@ public static void Invoke(string[] VS) } } - if (File.Exists($"0:\\{VS[0]}")|| File.Exists(VS[0])) + if (File.Exists($"0:\\{VS[0]}") || File.Exists(VS[0])) { - Executable EXE = new(File.ReadAllBytes(VS[0])); + // Read the program's running data. + byte[] ROM = File.ReadAllBytes(VS[0]); - while (EXE.IsEnabled) + // Check if the file isn't an ELF. Run as a SSharp program if it isn't. + if (ROM.Length < sizeof(ELFHeader32)) { - EXE.Next(); - } + Executable EXE = new(File.ReadAllBytes(VS[0])); - return; + while (EXE.IsEnabled) + { + EXE.Next(); + } + + return; + } + // Run an elf file when it's detected. + else + { + // Create a new header, then run it. + ELFFile32 ELF = new(ROM); + ELF.Main(); + return; + } } Debugger.Warn("Command not found!"); @@ -70,6 +87,8 @@ public static void Main() // Initialize all commands. _ = new Unix.PowerOff(); + _ = new Unix.HexDump(); + _ = new Unix.ReadELF(); _ = new Unix.Reboot(); _ = new Unix.Clear(); _ = new Unix.MKDir(); diff --git a/README.md b/README.md index 392c20a1..979754f1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,14 @@ This Project is Made Possible by Cosmos and the Community Around it, We Give a H
+# Donations +Donations aren't needed at the moment but they would show me support and give me motivation to continue the project. You can donate to our monero wallet: +> 44WnT2itBkUWzNEHE2xcAEJcSR8jpBmuaPujVNFZvh1PHjPkH9pi2QnJXEd1vU8J4vUZAKpVJTtuAA1CzA7XqFGoMzmuomy + +
+ +
+

    Prism OS's Feature List:

  • A Basic 3D Rasteriser