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

XFESystem

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

公开
关注 0 Fork 0 Star 0
UTF-8
using XFESystem.Browser;
using XFESystem.Console;
using XFESystem.ConsoleDemo;
using XFESystem.Core;
using XFESystem.Desktop;
using XFESystem.ManagedRuntime;
using XFESystem.Platform;
using XFESystem.NativeRuntime.Application.Web;

namespace XFESystem.NativeRuntime.Application;

/// <summary>Ordinary Microsoft NativeAOT Main, called after the independently installed PAL/bootstrapper.</summary>
internal static class Program
{
    private const string ManagedDemoPath = "X:\\Programs\\ManagedHello\\ManagedHello.dll";
    private static int Main()
    {
        NativePlatform.Write("XFE_INDEPENDENT_APPLICATION_ENTER\nXFE_SYSTEM_EDITION|Desktop\n");
        try
        {
            global::System.Console.SetOut(new NativeDiagnosticWriter());
            global::System.Console.SetError(new NativeDiagnosticWriter());
            NativePlatform.RequireClock();
            RuntimeSelfCheck.Run();
            var surface = NativePlatform.ReadFramebuffer();
            int scalePercent = surface.Width >= 3000 || surface.Height >= 1800 ? 200 : 100;
            var canvas = new CpuFramebufferCanvas(new BootFramebufferPresenter(new MemoryFramebufferPresenter(surface)), scalePercent: scalePercent, timestamp: NativePlatform.Nanoseconds);
            var workspace = CreateWorkspace();
            workspace.CreateDirectory(SystemPaths.Combine(SystemPaths.System, "Diagnostics"));
            var gpuReport = NativeGpuDiagnostics.ReadReport(out bool hasRtx5090);
            var gpuReportPath = SystemPaths.Combine(SystemPaths.System, "Diagnostics\\Gpu.txt");
            var usbReportPath = SystemPaths.Combine(SystemPaths.System, "Diagnostics\\Usb.txt");
            workspace.WriteText(usbReportPath, NativeUsbDiagnostics.ReadReport());
            workspace.WriteText(gpuReportPath, gpuReport);
            var browser = new BrowserService(new NativeWebTransport(), limits: new BrowserLimits
            {
                MaximumExternalResourceCharacters = 2_500_000,
                // First-use cryptographic setup also counts toward the bounded
                // request, including under QEMU TCG. It runs on the navigation worker.
                NetworkTimeout = TimeSpan.FromSeconds(60)
            }) { Trace = NativePlatform.Write };
            // RuntimeSelfCheck has exercised real GC/EH/TLS and managed threads.
            // Each page keeps one thread owner; navigation cannot block editor work.
            using var editorWorker = new DesktopBackgroundWorkScheduler(error => NativePlatform.Halt("Editor worker failed: " + error.Message));
            using var navigationWorker = new DesktopBackgroundWorkScheduler(error => NativePlatform.Halt("Navigation worker failed: " + error.Message));
            using var programWorker = new DesktopBackgroundWorkScheduler(error => NativePlatform.Halt("Program worker failed: " + error.Message));
            var uiCompletions = new Queue<Action>();
            object completionGate = new();
            void PostCompletion(Action completed) { lock (completionGate) uiCompletions.Enqueue(completed); }
            void DrainCompletions()
            {
                for (int count = 0; count < 64; count++)
                {
                    Action? completed;
                    lock (completionGate) completed = uiCompletions.Count > 0 ? uiCompletions.Dequeue() : null;
                    if (completed is null) return;
                    completed();
                }
            }
            var editorPreparation = new BrowserEditorPreparationService(browser, editorWorker, canvas,
                NativePlatform.Write, () => Environment.CurrentManagedThreadId, NativePlatform.Milliseconds, navigationWorker);
            var terminal = new TerminalBuffer(100, 30);
            var writer = new TerminalTextWriter(terminal);
            DesktopSession? desktop = null;
            void RunConsoleDemo()
            {
                terminal.Reset(); ConsoleDemoScenario.Run(writer); ConsoleDemoScenario.RunXfeConsoleApi(writer);
                terminal.Complete();
                var snapshot = writer.Snapshot();
                string text = string.Concat(snapshot.Cells.Select(cell => cell.Text));
                if (!text.Contains(ConsoleDemoScenario.SuccessMarker, StringComparison.Ordinal) ||
                    !text.Contains("XFEConsole API: Real NuGet 2.6.0", StringComparison.Ordinal))
                    throw new InvalidOperationException("The real console demo did not produce its terminal markers.");
                desktop!.SetTerminalSnapshot(snapshot);
                NativePlatform.Write("XFE_INDEPENDENT_CONSOLE_DEMO_OK ANSI XFEConsole2.6.0 terminal_cells\n");
            }
            void RunManagedApplication(string path)
            {
                var programTerminal = new TerminalBuffer(100, 30);
                var programOutput = new TerminalTextWriter(programTerminal);
                if (!programWorker.TryQueue(() =>
                {
                    ExecuteManagedApplication(path, programOutput);
                    programTerminal.Complete();
                    var snapshot = programOutput.Snapshot();
                    PostCompletion(() =>
                    {
                        desktop!.SetTerminalSnapshot(snapshot);
                        pendingConsoleWindowId = desktop.ActiveWindow?.Id ?? 0; pendingConsolePath = path;
                    });
                })) desktop!.WriteTerminalOutput("Program queue is busy.\n");
            }
            void ExecuteManagedApplication(string path, TerminalTextWriter output)
            {
                try
                {
                    var result = new ManagedApplicationRunner().Execute(workspace.ReadBytes(path), new TerminalManagedConsole(output));
                    output.WriteLine("Managed ConsoleIL exit: " + result.ExitCode);
                    var sampleText = string.Concat(output.Snapshot().Cells.Select(cell => cell.Text));
                    if (result.ExitCode == 0 && sampleText.Contains("XFE_MANAGED_APP_OK", StringComparison.Ordinal) &&
                        sampleText.Contains("XFE_MANAGED_XFECONSOLE_OK", StringComparison.Ordinal))
                        NativePlatform.Write("XFE_INDEPENDENT_CONSOLE_IL_OK actual_embedded_net10_PE bounded_interpreter\n");
                }
                catch (Exception error) when (error is not OutOfMemoryException and not StackOverflowException)
                { output.WriteLine("Managed program failed: " + error.Message); }
            }
            desktop = new DesktopSession(canvas, workspace, browser, RunConsoleDemo, RunManagedApplication,
                NativePlatform.Milliseconds, editorPreparation: editorPreparation,
                threadIdentity: () => Environment.CurrentManagedThreadId)
            {
                Trace = NativePlatform.Write,
                TerminalProgramRequested = request =>
                {
                    if (!programWorker.TryQueue(() =>
                    {
                        ExecuteManagedApplication(request.Path, request.Output);
                        PostCompletion(() =>
                        {
                            desktop!.RefreshTerminalOutput(request.WindowId);
                            pendingConsoleWindowId = request.WindowId; pendingConsolePath = request.Path;
                        });
                    }))
                    {
                        request.Output.WriteLine("Program queue is busy.");
                        PostCompletion(() => desktop!.RefreshTerminalOutput(request.WindowId));
                    }
                }
            };
            var input = new Ps2InputSource(new NativePs2ReportBackend(), canvas.NativeWidth, canvas.NativeHeight, canvas.ScalePercent,
                () => new(desktop.HasBrowserContentFocus, desktop.ActiveWindow?.Application));
            desktop.Open(DesktopApplication.Files);
            // Entity tests must be readable even before native USB HID works.
            // This is a plain RAM text file; no web/Monaco initialization is needed.
            if (hasRtx5090) desktop.OpenFile(gpuReportPath);
            desktop.Pointer(input.PointerX, input.PointerY, false, timestampMs: NativePlatform.Milliseconds());
            desktop.Render();
            if (!desktop.LastFrameCompleted || canvas.FramesPresented == 0)
                throw new InvalidOperationException("The desktop did not finish an actual raw framebuffer presentation.");
            NativePlatform.Write("XFE_INDEPENDENT_DESKTOP_FIRST_FRAME|Width|" + canvas.NativeWidth + "|Height|" + canvas.NativeHeight +
                "|ScalePercent|" + canvas.ScalePercent + "|Presented|" + canvas.FramesPresented + "\n");
            NativePlatform.Write("XFE_INDEPENDENT_INPUT|Connected|" + (input.IsAvailable ? 1 : 0) + "|Keyboard|" + (input.Capabilities & 1) +
                "|Mouse|" + ((input.Capabilities >> 1) & 1) + "|Wheel|" + ((input.Capabilities >> 2) & 1) + "|Backend|PS2+xHCI|UsbHid|" + NativeUsbDiagnostics.KeyboardMouse + "\n");
            NativePlatform.Write("XFE_INDEPENDENT_CAPABILITIES|RAMOnly|"+(workspace.IsPersistent?0:1)+"|NativeNetwork|1|NetworkBackend|E1000_StaticQemuNat|Gpu|0|Cuda|0|BackgroundEditor|1|EditorThread|" +
                editorWorker.WorkerThreadId + "|NavigationThread|" + navigationWorker.WorkerThreadId + "|UiThread|" + Environment.CurrentManagedThreadId + "\n");
            ReportWindowState(desktop);
            long nextUsb = NativePlatform.Milliseconds() + 2000;
            Pump(desktop, input, () => {
                DrainCompletions(); long now = NativePlatform.Milliseconds();
                if (now >= nextUsb) { nextUsb = now + 2000; workspace.WriteText(usbReportPath, NativeUsbDiagnostics.ReadReport()); }
            });
            return 0;
        }
        catch (Exception error)
        {
            NativePlatform.Write("XFE_INDEPENDENT_APPLICATION_FAILED|" + error.Message + "\n");
            NativePlatform.Halt("Managed desktop failed: " + error.Message);
            return 1;
        }
    }

    private static IWorkspaceBinaryStorage CreateWorkspace()
    {
        var workspace = NativeWorkspace.Open();
        string welcome=SystemPaths.Combine(SystemPaths.Desktop,"Welcome.md");
        if(!workspace.Exists(welcome))workspace.WriteText(welcome,workspace.IsPersistent?"# XFESystem\n\nFiles and settings are saved to the boot USB workspace.\n":"# XFESystem\n\nRAM fallback: no usable boot USB storage. Files disappear after shutdown.\n");
        string helloJs=SystemPaths.Combine(SystemPaths.Documents,"Hello.js");
        if(!workspace.Exists(helloJs))workspace.WriteText(helloJs,"const greeting = 'XFESystem';\nconsole.log(`Hello from ${greeting}!`);\n");
        string helloCs=SystemPaths.Combine(SystemPaths.Documents,"Hello.cs");
        if(!workspace.Exists(helloCs))workspace.WriteText(helloCs,"using System;\n\nConsole.ForegroundColor = ConsoleColor.Cyan;\nConsole.WriteLine(\"Hello XFESystem!\");\nConsole.ResetColor();\n");
        string readme=SystemPaths.Combine(SystemPaths.Documents,"Readme.md");
        if(!workspace.Exists(readme))workspace.WriteText(readme, """
            # XFESystem 独立内核

            启动 U 盘可用时,文件和设置保存到物理 U 盘;没有可用启动 U 盘时明确回退到 RAM 会话。

            - 原有 Desktop、Browser、Documents 和 Terminal 接口继续使用。
            - PS/2 与 xHCI HID 输入已接入,实体兼容仍需验收。
            - X:\UsbFiles 对应 U 盘 UserFiles 文件夹,可以运行符合 ConsoleIL 范围的 .dll。
            - QEMU e1000 网络已接入;GPU/CUDA 尚未实现。
            """);
        string parity=SystemPaths.Combine(SystemPaths.Documents,"WebsiteParity.md");
        if(!workspace.Exists(parity))workspace.WriteText(parity,
            XFESystem.Documents.WebsiteAssets.ReadText("Fixtures/WebsiteParity.md"));
        workspace.CreateDirectory("X:\\Programs\\ManagedHello");
        using var sample = typeof(Program).Assembly.GetManifestResourceStream("ApplicationSamples/ManagedHello.dll")
            ?? throw new InvalidOperationException("The actual ConsoleIL sample assembly is missing.");
        if (sample.Length > ManagedRuntimeCapabilities.MaxImageBytes) throw new InvalidDataException("Managed sample exceeds the ConsoleIL image budget.");
        byte[] image = new byte[checked((int)sample.Length)]; sample.ReadExactly(image);
        if(!workspace.Exists(ManagedDemoPath))workspace.WriteBytes(ManagedDemoPath, image);
        string samplePath=SystemPaths.Combine(SystemPaths.Documents,"ManagedHello.dll");
        if(!workspace.Exists(samplePath))workspace.WriteBytes(samplePath,image);
        return workspace;
    }

    // Input remains an explicit optional adapter. No fabricated reports or host window input enter this loop.
    private static void Pump(DesktopSession desktop, INativeInputSource? input, Action drainCompletions)
    {
        long previous = NativePlatform.Milliseconds(), nextTick = previous;
        for (;;)
        {
            long now = NativePlatform.Milliseconds();
            if (now < previous) throw new InvalidOperationException("The native monotonic clock moved backward.");
            previous = now;
            drainCompletions();
            if (input is { IsAvailable: true })
                for (int reports = 0; reports < 256 && input.TryRead(out var report); reports++) NativeInput.Dispatch(desktop, report, now);
            if (now >= nextTick)
            {
                desktop.AdvanceFeedback(now);
                if (desktop.NeedsRender)
                {
                    desktop.Render();
                    if (desktop.LastFrameCompleted)
                    {
                        if (pendingConsolePath is { } presentedPath && desktop.ActiveWindow is { Application: DesktopApplication.Terminal } terminalWindow &&
                            terminalWindow.Id == pendingConsoleWindowId)
                        {
                            NativePlatform.Write("XFE_INDEPENDENT_CONSOLE_PRESENTED|Path|" + presentedPath + "|Window|" + terminalWindow.Id + "\n");
                            pendingConsolePath = null;
                        }
                        ReportWindowState(desktop);
                        ReportTerminalState(desktop);
                        if (desktop.ActiveWindow is { } active && (active.BrowserSession is not null || active.PreviewSession is not null)) ReportBrowserState(active, now);
                    }
                }
                nextTick = now + 16;
            }
            Thread.Sleep(1);
        }
    }

    private static string lastWindowState = "";
    private static string? pendingConsolePath;
    private static int pendingConsoleWindowId;
    private static TerminalSnapshot? lastTerminalSnapshot;
    private static int lastTerminalWindowId;
    private static void ReportTerminalState(DesktopSession desktop)
    {
        if (desktop.ActiveWindow is not { Application: DesktopApplication.Terminal, Terminal: { } snapshot, Shell: { } shell } window ||
            window.Id == lastTerminalWindowId && ReferenceEquals(snapshot, lastTerminalSnapshot)) return;
        lastTerminalWindowId = window.Id; lastTerminalSnapshot = snapshot;
        var text = new System.Text.StringBuilder();
        for (int row = Math.Max(0, snapshot.CursorRow - 31); row <= Math.Min(snapshot.CursorRow, snapshot.Rows - 1); row++)
        {
            for (int col = 0; col < snapshot.Columns; col++)
            {
                var cell = snapshot.GetCell(col, row);
                if (!cell.IsContinuation) text.Append(cell.Text);
            }
            text.Append('\n');
        }
        string json = "{\"WindowId\":" + window.Id + ",\"Text\":" + NativeWebTransport.Quote(text.ToString()) +
            ",\"Input\":" + NativeWebTransport.Quote(shell.Input) + ",\"Prompt\":" + NativeWebTransport.Quote(shell.Prompt) +
            ",\"Busy\":" + (window.TerminalProgramRunning ? "true" : "false") + ",\"Version\":" + NativeWebTransport.Quote(shell.Version) +
            ",\"LastCommand\":" + NativeWebTransport.Quote(shell.History.LastOrDefault()) + "}";
        NativePlatform.Write("XFE_TERMINAL_SNAPSHOT_BEGIN\n" + json + "\nXFE_TERMINAL_SNAPSHOT_END\n");
    }
    private static void ReportWindowState(DesktopSession desktop)
    {
        string report = "XFE_DESKTOP_FLAGS|" + (desktop.IsStartMenuOpen ? 1 : 0) + "|" + (desktop.IsWindowSwitching ? 1 : 0) +
            "|Active|" + (desktop.ActiveWindow?.Id ?? 0) + "\n" +
            "XFE_DESKTOP_APPEARANCE|" + desktop.Theme.Mode + "|" + desktop.Theme.Accent.ToString("X6") +
            "|Persistent|" + (desktop.IsAppearancePersistent ? 1 : 0) + "\n";
        foreach (var window in desktop.Windows)
        {
            var b = window.Bounds;
            report += "XFE_WINDOW_STATE|" + window.Id + "|" + window.Application + "|" + b.X + "|" + b.Y + "|" + b.Width + "|" + b.Height +
                "|" + (window.IsMinimized ? 1 : 0) + "|" + (window.IsMaximized ? 1 : 0) + "|" + (window.IsSnapped ? 1 : 0) + "\n";
            if (window.IsMarkdown)
                report += "XFE_WINDOW_DOCUMENT|" + window.Id + "|" + window.Location + "|" + window.MarkdownView + "|" + (window.IsDirty ? 1 : 0) +
                    "|" + (window.IsEditorPreparing ? 1 : 0) + "|" + (window.IsPreviewPreparing ? 1 : 0) + "|" +
                    window.Status.Replace('|', '/').Replace('\n', ' ').Replace('\r', ' ') + "\n";
        }
        if (report == lastWindowState) return;
        lastWindowState = report;
        NativePlatform.Write("XFE_DESKTOP_ACTIVE|" + (desktop.ActiveWindow?.Application.ToString() ?? "Desktop") + "\n" + report + "XFE_DESKTOP_STATE_END\n");
    }

    private static string lastBrowserState = "", lastBrowserInput = "", lastMonacoProof = "";
    private static long lastBrowserReport;
    private static void ReportBrowserState(DesktopWindow window, long now)
    {
        var visible = window.IsMarkdown && window.MarkdownView != MarkdownViewMode.Edit ? window.PreviewSession : window.BrowserSession;
        var editor = window.BrowserSession;
        var diagnostics = (editor as IBackgroundEditorSession)?.Diagnostics;
        string inputTrace = diagnostics?.LastInputTrace ?? (visible as IBackgroundEditorSession)?.Diagnostics.LastInputTrace ??
            (visible as BrowserService)?.LastInputTrace ?? "";
        if (inputTrace != lastBrowserInput)
        {
            lastBrowserInput = inputTrace;
            NativePlatform.Write("XFE_BROWSER_INPUT|" + lastBrowserInput + "\n");
        }
        if (now - lastBrowserReport < 200) return;
        lastBrowserReport = now;
        string content = window.IsMarkdown && window.MarkdownView != MarkdownViewMode.Edit
            ? visible?.CurrentPage.Text ?? window.Content : editor?.ReadEditorText() ?? window.Content;
        string body = content.Length <= 4096 ? content : content[..4096];
        string state = window.Id + "|" + window.Location + "\n" + body;
        if (state != lastBrowserState)
        {
            lastBrowserState = state;
            NativePlatform.Write("XFE_BROWSER_STATE_BEGIN\n" + state + "\nXFE_BROWSER_STATE_END\n");
        }
        var modelPage = editor ?? visible;
        if (modelPage is not null && Uri.TryCreate(modelPage.CurrentPage.Address, UriKind.Absolute, out var uri) && BrowserService.IsMonacoAddress(uri))
        {
            string proof = diagnostics?.MonacoProof ?? (modelPage as IBackgroundEditorSession)?.Diagnostics.MonacoProof ??
                (modelPage as BrowserService)?.ReadMonacoProof() ?? "{}";
            if (proof != "{}" && proof != lastMonacoProof)
            {
                lastMonacoProof = proof;
                NativePlatform.Write("XFE_MONACO_CSHARP_PROOF_BEGIN\n" + proof + "\nXFE_MONACO_CSHARP_PROOF_END\n");
            }
            NativePlatform.Write("XFE_MONACO_VALUE_BEGIN\n" + (modelPage.ReadEditorText() ?? "Editor unavailable") + "\nXFE_MONACO_VALUE_END\n");
            if (modelPage is IBackgroundEditorSession background)
                NativePlatform.Write("XFE_MONACO_PRESENTATION|Window|" + window.Id + "|RasterPaints|" + background.RasterPaintCount +
                    "|CachedPaints|" + background.CachedPaintCount + "|WorkerThread|" + background.Diagnostics.WorkerThreadId + "\n");
        }
    }
}