XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
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 (;;) { }
    }
}