namespace XFESystem.NativeKernel;
public static unsafe class Framebuffer
{
public static byte* Address;
public static uint Width, Height, Pitch;
static byte _redShift, _greenShift, _blueShift;
public static bool Ready;
public static bool Initialize(LimineFramebuffer* source)
{
Ready = false;
if (source == null || source->Address == null || source->BitsPerPixel != 32 || source->MemoryModel != 1 ||
source->Width == 0 || source->Height == 0 || source->Width > 16384 || source->Height > 16384 ||
source->Pitch < source->Width * 4 || source->Pitch > 1024 * 1024 || (source->Pitch & 3) != 0 ||
source->RedSize != 8 || source->GreenSize != 8 || source->BlueSize != 8 ||
source->RedShift > 24 || source->GreenShift > 24 || source->BlueShift > 24) return false;
uint red = 255u << source->RedShift, green = 255u << source->GreenShift, blue = 255u << source->BlueShift;
if ((red & green) != 0 || (red & blue) != 0 || (green & blue) != 0 ||
(ulong)source->Address > ~0UL - source->Pitch * source->Height) return false;
Address = source->Address;
Width = (uint)source->Width;
Height = (uint)source->Height;
Pitch = (uint)source->Pitch;
_redShift = source->RedShift; _greenShift = source->GreenShift; _blueShift = source->BlueShift;
Ready = true;
return true;
}
public static uint Pack(uint rgb) => (((rgb >> 16) & 255) << _redShift) |
(((rgb >> 8) & 255) << _greenShift) | ((rgb & 255) << _blueShift);
public static void Pixel(int x, int y, uint rgb)
{
if (Ready && x >= 0 && y >= 0 && (uint)x < Width && (uint)y < Height)
*(uint*)(Address + (ulong)(uint)y * Pitch + (ulong)(uint)x * 4) = Pack(rgb);
}
public static void Rectangle(int x, int y, int width, int height, uint rgb)
{
if (!Ready || width <= 0 || height <= 0) return;
long right = (long)x + width, bottom = (long)y + height;
if (right <= 0 || bottom <= 0 || x >= (long)Width || y >= (long)Height) return;
int left = x < 0 ? 0 : x, top = y < 0 ? 0 : y;
int r = right > Width ? (int)Width : (int)right, b = bottom > Height ? (int)Height : (int)bottom;
uint color = Pack(rgb);
for (int py = top; py < b; py++)
{
uint* row = (uint*)(Address + (ulong)(uint)py * Pitch);
for (int px = left; px < r; px++) row[px] = color;
}
}
public static void Fill(uint rgb) => Rectangle(0, 0, (int)Width, (int)Height, rgb);
public static void BootStage(uint stage, bool failure = false)
{
if (!Ready) return;
Rectangle(0, 0, (int)Width, 10, 0x131d2a);
Rectangle(0, 0, (int)(Width * (stage > 100 ? 100 : stage) / 100), 10, failure ? 0xdc3657u : 0x38c7a4u);
Native.MemoryBarrier();
}
public static bool SelfTest()
{
if (!Ready) return false;
uint* first = (uint*)Address;
uint saved = *first;
Pixel(0, 0, 0x2ea8df);
Native.MemoryBarrier();
bool result = *first == Pack(0x2ea8df);
*first = saved;
Native.MemoryBarrier();
return result;
}
}
namespace XFESystem.NativeKernel;
public static unsafe class Framebuffer
{
public static byte* Address;
public static uint Width, Height, Pitch;
static byte _redShift, _greenShift, _blueShift;
public static bool Ready;
public static bool Initialize(LimineFramebuffer* source)
{
Ready = false;
if (source == null || source->Address == null || source->BitsPerPixel != 32 || source->MemoryModel != 1 ||
source->Width == 0 || source->Height == 0 || source->Width > 16384 || source->Height > 16384 ||
source->Pitch < source->Width * 4 || source->Pitch > 1024 * 1024 || (source->Pitch & 3) != 0 ||
source->RedSize != 8 || source->GreenSize != 8 || source->BlueSize != 8 ||
source->RedShift > 24 || source->GreenShift > 24 || source->BlueShift > 24) return false;
uint red = 255u << source->RedShift, green = 255u << source->GreenShift, blue = 255u << source->BlueShift;
if ((red & green) != 0 || (red & blue) != 0 || (green & blue) != 0 ||
(ulong)source->Address > ~0UL - source->Pitch * source->Height) return false;
Address = source->Address;
Width = (uint)source->Width;
Height = (uint)source->Height;
Pitch = (uint)source->Pitch;
_redShift = source->RedShift; _greenShift = source->GreenShift; _blueShift = source->BlueShift;
Ready = true;
return true;
}
public static uint Pack(uint rgb) => (((rgb >> 16) & 255) << _redShift) |
(((rgb >> 8) & 255) << _greenShift) | ((rgb & 255) << _blueShift);
public static void Pixel(int x, int y, uint rgb)
{
if (Ready && x >= 0 && y >= 0 && (uint)x < Width && (uint)y < Height)
*(uint*)(Address + (ulong)(uint)y * Pitch + (ulong)(uint)x * 4) = Pack(rgb);
}
public static void Rectangle(int x, int y, int width, int height, uint rgb)
{
if (!Ready || width <= 0 || height <= 0) return;
long right = (long)x + width, bottom = (long)y + height;
if (right <= 0 || bottom <= 0 || x >= (long)Width || y >= (long)Height) return;
int left = x < 0 ? 0 : x, top = y < 0 ? 0 : y;
int r = right > Width ? (int)Width : (int)right, b = bottom > Height ? (int)Height : (int)bottom;
uint color = Pack(rgb);
for (int py = top; py < b; py++)
{
uint* row = (uint*)(Address + (ulong)(uint)py * Pitch);
for (int px = left; px < r; px++) row[px] = color;
}
}
public static void Fill(uint rgb) => Rectangle(0, 0, (int)Width, (int)Height, rgb);
public static void BootStage(uint stage, bool failure = false)
{
if (!Ready) return;
Rectangle(0, 0, (int)Width, 10, 0x131d2a);
Rectangle(0, 0, (int)(Width * (stage > 100 ? 100 : stage) / 100), 10, failure ? 0xdc3657u : 0x38c7a4u);
Native.MemoryBarrier();
}
public static bool SelfTest()
{
if (!Ready) return false;
uint* first = (uint*)Address;
uint saved = *first;
Pixel(0, 0, 0x2ea8df);
Native.MemoryBarrier();
bool result = *first == Pack(0x2ea8df);
*first = saved;
Native.MemoryBarrier();
return result;
}
}