using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
using XFESystem.Platform;
using XFESystem.NativeKernel;
namespace XFESystem.NativeRuntime.Application;
/// <summary>Exact 56-byte value-only ABI provided by XFESystem.NativeKernel.RuntimeBridge.</summary>
[StructLayout(LayoutKind.Sequential, Size = 56)]
internal struct NativeFramebufferInfo
{
public ulong Address, MappedBytes;
public uint Width, Height, PitchBytes, BitsPerPixel;
public uint RedMaskSize, RedMaskShift, GreenMaskSize, GreenMaskShift, BlueMaskSize, BlueMaskShift;
internal readonly FramebufferSurface ToSurface() => new(checked((nuint)Address), checked((nuint)MappedBytes),
checked((int)Width), checked((int)Height), checked((int)PitchBytes), checked((int)BitsPerPixel),
Mask(RedMaskSize, RedMaskShift), Mask(GreenMaskSize, GreenMaskShift), Mask(BlueMaskSize, BlueMaskShift));
private static uint Mask(uint size, uint shift)
{
if (size is 0 or > 32 || shift >= 32 || size + shift > 32) throw new InvalidDataException("Native framebuffer channel mask is invalid.");
return (uint)((size == 32 ? uint.MaxValue : (1UL << (int)size) - 1) << (int)shift);
}
}
internal static unsafe class NativePlatform
{
private static readonly object outputGate = new();
// Direct PInvoke during ELF compilation; no dynamic loader, strings or object marshalling crosses this ABI.
private const string Library = "xfe_pal";
[DllImport(Library, EntryPoint = "xfe_runtime_framebuffer_info", CallingConvention = CallingConvention.Cdecl)]
private static extern int FramebufferInfo(NativeFramebufferInfo* information);
[DllImport(Library, EntryPoint = "xfe_runtime_write", CallingConvention = CallingConvention.Cdecl)]
private static extern void WriteNative(byte* bytes, ulong length);
[DllImport(Library, EntryPoint = "xfe_runtime_mono_ns", CallingConvention = CallingConvention.Cdecl)]
private static extern ulong MonotonicNanoseconds();
[DllImport(Library, EntryPoint = "xfe_runtime_clock_ready", CallingConvention = CallingConvention.Cdecl)]
private static extern int ClockReady();
[DllImport(Library, EntryPoint = "xfe_runtime_halt", CallingConvention = CallingConvention.Cdecl)]
private static extern void HaltNative(byte* zeroTerminatedReason);
[DllImport(Library, EntryPoint = "xfe_runtime_input_ready", CallingConvention = CallingConvention.Cdecl)]
private static extern uint InputReady();
[DllImport(Library, EntryPoint = "xfe_runtime_input_read", CallingConvention = CallingConvention.Cdecl)]
private static extern int InputRead(NativeInputReport* report);
internal static uint InputCapabilities() => InputReady() & 7;
internal static bool ReadInput(out NativeInputReport report)
{
if (sizeof(NativeInputReport) != 32) throw new InvalidOperationException("Native input ABI size mismatch.");
NativeInputReport value = default; int result = InputRead(&value);
if (result is not (0 or 1)) throw new InvalidOperationException("Native input read failed its ABI contract.");
report = value; return result == 1;
}
internal static FramebufferSurface ReadFramebuffer()
{
if (sizeof(NativeFramebufferInfo) != 56) throw new InvalidOperationException("Native framebuffer ABI size mismatch.");
NativeFramebufferInfo information = default;
if (FramebufferInfo(&information) != 1) throw new InvalidOperationException("The independent kernel did not supply a mapped framebuffer.");
return information.ToSurface();
}
internal static void RequireClock()
{
if (ClockReady() != 1) throw new InvalidOperationException("The independent kernel's monotonic clock is unavailable.");
}
internal static long Nanoseconds() => (long)Math.Min(MonotonicNanoseconds(), (ulong)long.MaxValue);
internal static long Milliseconds() => (long)(MonotonicNanoseconds() / 1_000_000);
internal static void Write(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
// Background document/editor diagnostics must stay complete records
// when the independently scheduled managed threads are preempted.
lock (outputGate)
fixed (byte* pointer = bytes) WriteNative(pointer, (ulong)bytes.Length);
}
[DoesNotReturn]
internal static void Halt(string reason)
{
byte[] encoded = Encoding.UTF8.GetBytes(reason);
byte[] bounded = new byte[Math.Min(encoded.Length, 255) + 1];
encoded.AsSpan(0, bounded.Length - 1).CopyTo(bounded);
fixed (byte* pointer = bounded) HaltNative(pointer);
// A broken native contract must never let Main continue or return into an uninitialised scheduler.
for (;;) { }
}
}
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
using XFESystem.Platform;
using XFESystem.NativeKernel;
namespace XFESystem.NativeRuntime.Application;
/// <summary>Exact 56-byte value-only ABI provided by XFESystem.NativeKernel.RuntimeBridge.</summary>
[StructLayout(LayoutKind.Sequential, Size = 56)]
internal struct NativeFramebufferInfo
{
public ulong Address, MappedBytes;
public uint Width, Height, PitchBytes, BitsPerPixel;
public uint RedMaskSize, RedMaskShift, GreenMaskSize, GreenMaskShift, BlueMaskSize, BlueMaskShift;
internal readonly FramebufferSurface ToSurface() => new(checked((nuint)Address), checked((nuint)MappedBytes),
checked((int)Width), checked((int)Height), checked((int)PitchBytes), checked((int)BitsPerPixel),
Mask(RedMaskSize, RedMaskShift), Mask(GreenMaskSize, GreenMaskShift), Mask(BlueMaskSize, BlueMaskShift));
private static uint Mask(uint size, uint shift)
{
if (size is 0 or > 32 || shift >= 32 || size + shift > 32) throw new InvalidDataException("Native framebuffer channel mask is invalid.");
return (uint)((size == 32 ? uint.MaxValue : (1UL << (int)size) - 1) << (int)shift);
}
}
internal static unsafe class NativePlatform
{
private static readonly object outputGate = new();
// Direct PInvoke during ELF compilation; no dynamic loader, strings or object marshalling crosses this ABI.
private const string Library = "xfe_pal";
[DllImport(Library, EntryPoint = "xfe_runtime_framebuffer_info", CallingConvention = CallingConvention.Cdecl)]
private static extern int FramebufferInfo(NativeFramebufferInfo* information);
[DllImport(Library, EntryPoint = "xfe_runtime_write", CallingConvention = CallingConvention.Cdecl)]
private static extern void WriteNative(byte* bytes, ulong length);
[DllImport(Library, EntryPoint = "xfe_runtime_mono_ns", CallingConvention = CallingConvention.Cdecl)]
private static extern ulong MonotonicNanoseconds();
[DllImport(Library, EntryPoint = "xfe_runtime_clock_ready", CallingConvention = CallingConvention.Cdecl)]
private static extern int ClockReady();
[DllImport(Library, EntryPoint = "xfe_runtime_halt", CallingConvention = CallingConvention.Cdecl)]
private static extern void HaltNative(byte* zeroTerminatedReason);
[DllImport(Library, EntryPoint = "xfe_runtime_input_ready", CallingConvention = CallingConvention.Cdecl)]
private static extern uint InputReady();
[DllImport(Library, EntryPoint = "xfe_runtime_input_read", CallingConvention = CallingConvention.Cdecl)]
private static extern int InputRead(NativeInputReport* report);
internal static uint InputCapabilities() => InputReady() & 7;
internal static bool ReadInput(out NativeInputReport report)
{
if (sizeof(NativeInputReport) != 32) throw new InvalidOperationException("Native input ABI size mismatch.");
NativeInputReport value = default; int result = InputRead(&value);
if (result is not (0 or 1)) throw new InvalidOperationException("Native input read failed its ABI contract.");
report = value; return result == 1;
}
internal static FramebufferSurface ReadFramebuffer()
{
if (sizeof(NativeFramebufferInfo) != 56) throw new InvalidOperationException("Native framebuffer ABI size mismatch.");
NativeFramebufferInfo information = default;
if (FramebufferInfo(&information) != 1) throw new InvalidOperationException("The independent kernel did not supply a mapped framebuffer.");
return information.ToSurface();
}
internal static void RequireClock()
{
if (ClockReady() != 1) throw new InvalidOperationException("The independent kernel's monotonic clock is unavailable.");
}
internal static long Nanoseconds() => (long)Math.Min(MonotonicNanoseconds(), (ulong)long.MaxValue);
internal static long Milliseconds() => (long)(MonotonicNanoseconds() / 1_000_000);
internal static void Write(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
// Background document/editor diagnostics must stay complete records
// when the independently scheduled managed threads are preempted.
lock (outputGate)
fixed (byte* pointer = bytes) WriteNative(pointer, (ulong)bytes.Length);
}
[DoesNotReturn]
internal static void Halt(string reason)
{
byte[] encoded = Encoding.UTF8.GetBytes(reason);
byte[] bounded = new byte[Math.Min(encoded.Length, 255) + 1];
encoded.AsSpan(0, bounded.Length - 1).CopyTo(bounded);
fixed (byte* pointer = bounded) HaltNative(pointer);
// A broken native contract must never let Main continue or return into an uninitialised scheduler.
for (;;) { }
}
}