From 1694303e4ceefe5f9c681eee479b8be52873ac7e Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen <emmausssss@gmail.com> Date: Sun, 25 Jun 2023 12:20:05 +0000 Subject: [PATCH] add nativaot libryujinx project --- Directory.Packages.props | 6 +- Ryujinx.sln | 24 + .../LibRyujinx.NativeSample.csproj | 14 + .../LibRyujinxInterop.cs | 81 +++ src/LibRyujinx.NativeSample/NativeWindow.cs | 115 +++ src/LibRyujinx.NativeSample/Program.cs | 33 + src/LibRyujinx/LibRyujinx.Device.cs | 151 ++++ src/LibRyujinx/LibRyujinx.Graphics.cs | 224 ++++++ src/LibRyujinx/LibRyujinx.Input.cs | 12 + src/LibRyujinx/LibRyujinx.Shared.csproj | 41 ++ src/LibRyujinx/LibRyujinx.cs | 151 ++++ src/LibRyujinx/OpenTKBindingsContext.cs | 20 + src/LibRyujinx/rd.xml | 661 ++++++++++++++++++ 13 files changed, 1530 insertions(+), 3 deletions(-) create mode 100644 src/LibRyujinx.NativeSample/LibRyujinx.NativeSample.csproj create mode 100644 src/LibRyujinx.NativeSample/LibRyujinxInterop.cs create mode 100644 src/LibRyujinx.NativeSample/NativeWindow.cs create mode 100644 src/LibRyujinx.NativeSample/Program.cs create mode 100644 src/LibRyujinx/LibRyujinx.Device.cs create mode 100644 src/LibRyujinx/LibRyujinx.Graphics.cs create mode 100644 src/LibRyujinx/LibRyujinx.Input.cs create mode 100644 src/LibRyujinx/LibRyujinx.Shared.csproj create mode 100644 src/LibRyujinx/LibRyujinx.cs create mode 100644 src/LibRyujinx/OpenTKBindingsContext.cs create mode 100644 src/LibRyujinx/rd.xml diff --git a/Directory.Packages.props b/Directory.Packages.props index c163cb0bf..ca628f872 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,9 +40,9 @@ <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" /> - <PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" /> - <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" /> - <PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" /> + <PackageVersion Include="Silk.NET.Vulkan" Version="2.17.1" /> + <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.17.1" /> + <PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.17.1" /> <PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" /> <PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" /> <PackageVersion Include="SPB" Version="0.0.4-build28" /> diff --git a/Ryujinx.sln b/Ryujinx.sln index bb196cabc..eb4a3bfa9 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -87,6 +87,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibRyujinx.Shared", "src\LibRyujinx\LibRyujinx.Shared.csproj", "{5BBF478C-A520-41E7-9B88-890AD26766B8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{C75176EB-C44E-449A-8077-A48AD94534EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibRyujinx.NativeSample", "src\LibRyujinx.NativeSample\LibRyujinx.NativeSample.csproj", "{63D2C96B-5194-4592-BC91-30BEB11C06BD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibRyujinx.Build", "src\LibRyujinx.Build\LibRyujinx.Build.csproj", "{028BA6E8-BDB5-4F85-BCA0-EDC559C85F4F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -249,6 +257,22 @@ Global {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU + {5BBF478C-A520-41E7-9B88-890AD26766B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BBF478C-A520-41E7-9B88-890AD26766B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BBF478C-A520-41E7-9B88-890AD26766B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BBF478C-A520-41E7-9B88-890AD26766B8}.Release|Any CPU.Build.0 = Release|Any CPU + {C75176EB-C44E-449A-8077-A48AD94534EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C75176EB-C44E-449A-8077-A48AD94534EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C75176EB-C44E-449A-8077-A48AD94534EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C75176EB-C44E-449A-8077-A48AD94534EE}.Release|Any CPU.Build.0 = Release|Any CPU + {63D2C96B-5194-4592-BC91-30BEB11C06BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63D2C96B-5194-4592-BC91-30BEB11C06BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63D2C96B-5194-4592-BC91-30BEB11C06BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63D2C96B-5194-4592-BC91-30BEB11C06BD}.Release|Any CPU.Build.0 = Release|Any CPU + {028BA6E8-BDB5-4F85-BCA0-EDC559C85F4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {028BA6E8-BDB5-4F85-BCA0-EDC559C85F4F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {028BA6E8-BDB5-4F85-BCA0-EDC559C85F4F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {028BA6E8-BDB5-4F85-BCA0-EDC559C85F4F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/LibRyujinx.NativeSample/LibRyujinx.NativeSample.csproj b/src/LibRyujinx.NativeSample/LibRyujinx.NativeSample.csproj new file mode 100644 index 000000000..0c44a3456 --- /dev/null +++ b/src/LibRyujinx.NativeSample/LibRyujinx.NativeSample.csproj @@ -0,0 +1,14 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net7.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="OpenTK" /> + </ItemGroup> +</Project> diff --git a/src/LibRyujinx.NativeSample/LibRyujinxInterop.cs b/src/LibRyujinx.NativeSample/LibRyujinxInterop.cs new file mode 100644 index 000000000..a52264edf --- /dev/null +++ b/src/LibRyujinx.NativeSample/LibRyujinxInterop.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LibRyujinx.Sample +{ + internal static class LibRyujinxInterop + { + private const string dll = "LibRyujinx.Shared.dll"; + + [DllImport(dll, EntryPoint = "initialize")] + public extern static bool Initialize(IntPtr path); + + + [DllImport(dll, EntryPoint = "graphics_initialize")] + public extern static bool InitializeGraphics(GraphicsConfiguration graphicsConfiguration); + + [DllImport(dll, EntryPoint = "device_initialize")] + internal extern static bool InitializeDevice(); + + [DllImport(dll, EntryPoint = "graphics_initialize_renderer")] + internal extern static bool InitializeGraphicsRenderer(GraphicsBackend backend, NativeGraphicsInterop nativeGraphicsInterop); + + [DllImport(dll, EntryPoint = "device_load")] + internal extern static bool LoadApplication(IntPtr pathPtr); + + [DllImport(dll, EntryPoint = "graphics_renderer_run_loop")] + internal extern static void RunLoop(); + + [DllImport(dll, EntryPoint = "graphics_renderer_set_size")] + internal extern static void SetRendererSize(int width, int height); + + [DllImport(dll, EntryPoint = "graphics_renderer_set_swap_buffer_callback")] + internal extern static void SetSwapBuffersCallback(IntPtr swapBuffers); + + [DllImport(dll, EntryPoint = "graphics_renderer_set_vsync")] + internal extern static void SetVsyncState(bool enabled); + } + + [StructLayout(LayoutKind.Sequential)] + public struct GraphicsConfiguration + { + public float ResScale = 1f; + public float MaxAnisotropy = -1; + public bool FastGpuTime = true; + public bool Fast2DCopy = true; + public bool EnableMacroJit = false; + public bool EnableMacroHLE = true; + public bool EnableShaderCache = true; + public bool EnableSpirvCompilationOnVulkan = true; + public bool EnableTextureRecompression = false; + public BackendThreading BackendThreading = BackendThreading.Auto; + + public GraphicsConfiguration() + { + } + } + public enum GraphicsBackend + { + Vulkan, + OpenGl + } + public enum BackendThreading + { + Auto, + Off, + On + } + + public struct NativeGraphicsInterop + { + public IntPtr GlGetProcAddress; + public IntPtr VkNativeContextLoader; + public IntPtr VkCreateSurface; + public IntPtr VkRequiredExtensions; + public int VkRequiredExtensionsCount; + } +} diff --git a/src/LibRyujinx.NativeSample/NativeWindow.cs b/src/LibRyujinx.NativeSample/NativeWindow.cs new file mode 100644 index 000000000..63ac5a0ad --- /dev/null +++ b/src/LibRyujinx.NativeSample/NativeWindow.cs @@ -0,0 +1,115 @@ +using LibRyujinx.Sample; +using OpenTK.Graphics.OpenGL; +using OpenTK.Windowing.Desktop; +using OpenTK.Windowing.GraphicsLibraryFramework; +using System.Runtime.InteropServices; + +namespace LibRyujinx.NativeSample +{ + internal class NativeWindow : OpenTK.Windowing.Desktop.NativeWindow + { + private nint del; + public delegate void SwapBuffersCallback(); + public delegate IntPtr GetProcAddress(string name); + public delegate IntPtr CreateSurface(IntPtr instance); + + private bool _isVulkan; + + public NativeWindow(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings) + { + _isVulkan = true; + } + + internal unsafe void Start(string gamePath) + { + if (!_isVulkan) + { + MakeCurrent(); + } + + var getProcAddress = Marshal.GetFunctionPointerForDelegate<GetProcAddress>(x => GLFW.GetProcAddress(x)); + var createSurface = Marshal.GetFunctionPointerForDelegate<CreateSurface>( x => + { + VkHandle surface; + GLFW.CreateWindowSurface(new VkHandle(x) ,this.WindowPtr, null, out surface); + + return surface.Handle; + }); + var vkExtensions = GLFW.GetRequiredInstanceExtensions(); + + + var pointers = new IntPtr[vkExtensions.Length]; + for (int i = 0; i < vkExtensions.Length; i++) + { + pointers[i] = Marshal.StringToHGlobalAnsi(vkExtensions[i]); + } + + fixed (IntPtr* ptr = pointers) + { + var nativeGraphicsInterop = new NativeGraphicsInterop() + { + GlGetProcAddress = getProcAddress, + VkRequiredExtensions = (nint)ptr, + VkRequiredExtensionsCount = pointers.Length, + VkCreateSurface = createSurface + }; + var success = LibRyujinxInterop.InitializeGraphicsRenderer(_isVulkan ? GraphicsBackend.Vulkan : GraphicsBackend.OpenGl, nativeGraphicsInterop); + success = LibRyujinxInterop.InitializeDevice(); + + var path = Marshal.StringToHGlobalAnsi(gamePath); + var loaded = LibRyujinxInterop.LoadApplication(path); + LibRyujinxInterop.SetRendererSize(Size.X, Size.Y); + Marshal.FreeHGlobal(path); + } + + if (!_isVulkan) + { + Context.MakeNoneCurrent(); + } + + var thread = new Thread(new ThreadStart(RunLoop)); + thread.Start(); + thread.Join(); + + foreach(var ptr in pointers) + { + Marshal.FreeHGlobal(ptr); + } + } + + public void RunLoop() + { + del = Marshal.GetFunctionPointerForDelegate<SwapBuffersCallback>(SwapBuffers); + LibRyujinxInterop.SetSwapBuffersCallback(del); + + if (!_isVulkan) + { + MakeCurrent(); + + Context.SwapInterval = 0; + } + + Task.Run(async () => + { + await Task.Delay(1000); + + LibRyujinxInterop.SetVsyncState(false); + }); + + LibRyujinxInterop.RunLoop(); + + if (!_isVulkan) + { + Context.MakeNoneCurrent(); + } + } + + private void SwapBuffers() + { + if (!_isVulkan) + { + this.Context.SwapBuffers(); + } + } + } +} diff --git a/src/LibRyujinx.NativeSample/Program.cs b/src/LibRyujinx.NativeSample/Program.cs new file mode 100644 index 000000000..c27d77883 --- /dev/null +++ b/src/LibRyujinx.NativeSample/Program.cs @@ -0,0 +1,33 @@ +using LibRyujinx.Sample; +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using OpenTK.Windowing.Desktop; + +namespace LibRyujinx.NativeSample +{ + internal class Program + { + static void Main(string[] args) + { + if (args.Length > 0) + { + var success = LibRyujinxInterop.Initialize(IntPtr.Zero); + success = LibRyujinxInterop.InitializeGraphics(new GraphicsConfiguration()); + var nativeWindowSettings = new NativeWindowSettings() + { + Size = new Vector2i(800, 600), + Title = "Ryujinx", + API = ContextAPI.NoAPI, + IsEventDriven = true, + // This is needed to run on macos + Flags = ContextFlags.ForwardCompatible, + }; + + using var window = new NativeWindow(nativeWindowSettings); + + window.IsVisible = true; + window.Start(args[0]); + } + } + } +} \ No newline at end of file diff --git a/src/LibRyujinx/LibRyujinx.Device.cs b/src/LibRyujinx/LibRyujinx.Device.cs new file mode 100644 index 000000000..6ddf9381e --- /dev/null +++ b/src/LibRyujinx/LibRyujinx.Device.cs @@ -0,0 +1,151 @@ +using ARMeilleure.Translation; +using Ryujinx.Common.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LibRyujinx +{ + public static partial class LibRyujinx + { + [UnmanagedCallersOnly(EntryPoint = "device_initialize")] + public static bool InitializeDeviceNative() + { + return InitializeDevice(); + } + + public static bool InitializeDevice() + { + if (SwitchDevice == null) + { + return false; + } + + return SwitchDevice.InitializeContext(); + } + + [UnmanagedCallersOnly(EntryPoint = "device_load")] + public static bool LoadApplicationNative(IntPtr pathPtr) + { + if(SwitchDevice?.EmulationContext == null) + { + return false; + } + + var path = Marshal.PtrToStringAnsi(pathPtr); + + return LoadApplication(path); + } + + public static bool LoadApplication(string path) + { + var emulationContext = SwitchDevice.EmulationContext; + + if (Directory.Exists(path)) + { + string[] romFsFiles = Directory.GetFiles(path, "*.istorage"); + + if (romFsFiles.Length == 0) + { + romFsFiles = Directory.GetFiles(path, "*.romfs"); + } + + if (romFsFiles.Length > 0) + { + Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS."); + + if (!emulationContext.LoadCart(path, romFsFiles[0])) + { + SwitchDevice.DisposeContext(); + + return false; + } + } + else + { + Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS."); + + if (!emulationContext.LoadCart(path)) + { + SwitchDevice.DisposeContext(); + + return false; + } + } + } + else if (File.Exists(path)) + { + switch (Path.GetExtension(path).ToLowerInvariant()) + { + case ".xci": + Logger.Info?.Print(LogClass.Application, "Loading as XCI."); + + if (!emulationContext.LoadXci(path)) + { + SwitchDevice.DisposeContext(); + + return false; + } + break; + case ".nca": + Logger.Info?.Print(LogClass.Application, "Loading as NCA."); + + if (!emulationContext.LoadNca(path)) + { + SwitchDevice.DisposeContext(); + + return false; + } + break; + case ".nsp": + case ".pfs0": + Logger.Info?.Print(LogClass.Application, "Loading as NSP."); + + if (!emulationContext.LoadNsp(path)) + { + SwitchDevice.DisposeContext(); + + return false; + } + break; + default: + Logger.Info?.Print(LogClass.Application, "Loading as Homebrew."); + try + { + if (!emulationContext.LoadProgram(path)) + { + SwitchDevice.DisposeContext(); + + return false; + } + } + catch (ArgumentOutOfRangeException) + { + Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx."); + + SwitchDevice.DisposeContext(); + + return false; + } + break; + } + } + else + { + Logger.Warning?.Print(LogClass.Application, $"Couldn't load '{path}'. Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); + + SwitchDevice.DisposeContext(); + + return false; + } + + Translator.IsReadyForTranslation.Reset(); + + return true; + } + } +} diff --git a/src/LibRyujinx/LibRyujinx.Graphics.cs b/src/LibRyujinx/LibRyujinx.Graphics.cs new file mode 100644 index 000000000..ad16bca69 --- /dev/null +++ b/src/LibRyujinx/LibRyujinx.Graphics.cs @@ -0,0 +1,224 @@ +using ARMeilleure.Translation; +using LibRyujinx.Shared; +using OpenTK.Graphics.OpenGL; +using Ryujinx.Common.Configuration; +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu; +using Ryujinx.Graphics.OpenGL; +using Ryujinx.Graphics.Vulkan; +using Silk.NET.Vulkan; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; + +namespace LibRyujinx +{ + public static partial class LibRyujinx + { + private static bool _isActive; + private static bool _isStopped; + private static CancellationTokenSource _gpuCancellationTokenSource; + private static SwapBuffersCallback _swapBuffersCallback; + private static NativeGraphicsInterop _nativeGraphicsInterop; + + public delegate void SwapBuffersCallback(); + public delegate IntPtr GetProcAddress(string name); + public delegate IntPtr CreateSurface(IntPtr instance); + + + public static IRenderer? Renderer { get; set; } + public static GraphicsConfiguration GraphicsConfiguration { get; private set; } + + [UnmanagedCallersOnly(EntryPoint = "graphics_initialize")] + public static bool InitializeGraphicsNative(GraphicsConfiguration graphicsConfiguration) + { + if(OperatingSystem.IsAndroid()) + { + Silk.NET.Core.Loader.SearchPathContainer.Platform = Silk.NET.Core.Loader.UnderlyingPlatform.Android; + } + return InitializeGraphics(graphicsConfiguration); + } + public static bool InitializeGraphics(GraphicsConfiguration graphicsConfiguration) + { + GraphicsConfig.ResScale = graphicsConfiguration.ResScale; + GraphicsConfig.MaxAnisotropy = graphicsConfiguration.MaxAnisotropy; + GraphicsConfig.FastGpuTime = graphicsConfiguration.FastGpuTime; + GraphicsConfig.Fast2DCopy = graphicsConfiguration.Fast2DCopy; + GraphicsConfig.EnableMacroJit = graphicsConfiguration.EnableMacroJit; + GraphicsConfig.EnableMacroHLE = graphicsConfiguration.EnableMacroHLE; + GraphicsConfig.EnableShaderCache = graphicsConfiguration.EnableShaderCache; + GraphicsConfig.EnableSpirvCompilationOnVulkan = graphicsConfiguration.EnableSpirvCompilationOnVulkan; + GraphicsConfig.EnableTextureRecompression = graphicsConfiguration.EnableTextureRecompression; + + GraphicsConfiguration = graphicsConfiguration; + + return true; + } + + [UnmanagedCallersOnly(EntryPoint = "graphics_initialize_renderer")] + public unsafe static bool InitializeGraphicsRendererNative(GraphicsBackend graphicsBackend, NativeGraphicsInterop nativeGraphicsInterop) + { + _nativeGraphicsInterop = nativeGraphicsInterop; + if (Renderer != null) + { + return false; + } + + List<string> extensions = new List<string>(); + var size = Marshal.SizeOf<IntPtr>(); + var extPtr = (IntPtr*)nativeGraphicsInterop.VkRequiredExtensions; + for (int i = 0; i < nativeGraphicsInterop.VkRequiredExtensionsCount; i++) + { + var ptr = extPtr[i]; + extensions.Add(Marshal.PtrToStringAnsi(ptr) ?? string.Empty); + } + + CreateSurface createSurfaceFunc = nativeGraphicsInterop.VkCreateSurface == IntPtr.Zero ? default : Marshal.GetDelegateForFunctionPointer<CreateSurface>(nativeGraphicsInterop.VkCreateSurface); + + return InitializeGraphicsRenderer(graphicsBackend, createSurfaceFunc, extensions.ToArray()); + } + + public static bool InitializeGraphicsRenderer(GraphicsBackend graphicsBackend, CreateSurface createSurfaceFunc, string[] requiredExtensions) + { + if (Renderer != null) + { + return false; + } + + if (graphicsBackend == GraphicsBackend.OpenGl) + { + Renderer = new OpenGLRenderer(); + } + else if (graphicsBackend == GraphicsBackend.Vulkan) + { + Renderer = new VulkanRenderer(Vk.GetApi(), (instance, vk) => new SurfaceKHR((ulong?)createSurfaceFunc(instance.Handle)), + () => requiredExtensions, + null); + } + else + { + return false; + } + + return true; + } + + + [UnmanagedCallersOnly(EntryPoint = "graphics_renderer_set_size")] + public static void SetRendererSizeNative(int width, int height) + { + Renderer?.Window?.SetSize(width, height); + } + + public static void SetRendererSize(int width, int height) + { + Renderer?.Window?.SetSize(width, height); + } + + [UnmanagedCallersOnly(EntryPoint = "graphics_renderer_run_loop")] + public static void RunLoopNative() + { + if (Renderer is OpenGLRenderer) + { + var proc = Marshal.GetDelegateForFunctionPointer<GetProcAddress>(_nativeGraphicsInterop.GlGetProcAddress); + GL.LoadBindings(new OpenTKBindingsContext(x => proc!.Invoke(x))); + } + RunLoop(); + } + + [UnmanagedCallersOnly(EntryPoint = "graphics_renderer_set_vsync")] + public static void SetVsyncStateNative(bool enabled) + { + SetVsyncState(enabled); + } + + public static void SetVsyncState(bool enabled) + { + var device = SwitchDevice!.EmulationContext!; + device.EnableDeviceVsync = enabled; + device.Gpu.Renderer.Window.ChangeVSyncMode(enabled); + } + + public static void RunLoop() + { + if (Renderer == null) + { + return; + } + var device = SwitchDevice!.EmulationContext!; + + device.Gpu.Renderer.Initialize(GraphicsDebugLevel.None); + _gpuCancellationTokenSource = new CancellationTokenSource(); + + device.Gpu.Renderer.RunLoop(() => + { + device.Gpu.SetGpuThread(); + device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token); + Translator.IsReadyForTranslation.Set(); + + _isActive = true; + + while (_isActive) + { + if (_isStopped) + { + return; + } + + if (device.WaitFifo()) + { + device.Statistics.RecordFifoStart(); + device.ProcessFrame(); + device.Statistics.RecordFifoEnd(); + } + + while (device.ConsumeFrameAvailable()) + { + device.PresentFrame(() => _swapBuffersCallback?.Invoke()); + } + } + }); + } + + [UnmanagedCallersOnly(EntryPoint = "graphics_renderer_set_swap_buffer_callback")] + public static void SetSwapBuffersCallbackNative(IntPtr swapBuffersCallback) + { + _swapBuffersCallback = Marshal.GetDelegateForFunctionPointer<SwapBuffersCallback>(swapBuffersCallback); + } + + public static void SetSwapBuffersCallback(SwapBuffersCallback swapBuffersCallback) + { + _swapBuffersCallback = swapBuffersCallback; + } + } + + + [StructLayout(LayoutKind.Sequential)] + public struct GraphicsConfiguration + { + public float ResScale = 1f; + public float MaxAnisotropy = -1; + public bool FastGpuTime = true; + public bool Fast2DCopy = true; + public bool EnableMacroJit = false; + public bool EnableMacroHLE = true; + public bool EnableShaderCache; + public bool EnableSpirvCompilationOnVulkan = true; + public bool EnableTextureRecompression = false; + public BackendThreading BackendThreading = BackendThreading.Auto; + + public GraphicsConfiguration() + { + } + } + + public struct NativeGraphicsInterop + { + public IntPtr GlGetProcAddress; + public IntPtr VkNativeContextLoader; + public IntPtr VkCreateSurface; + public IntPtr VkRequiredExtensions; + public int VkRequiredExtensionsCount; + } +} diff --git a/src/LibRyujinx/LibRyujinx.Input.cs b/src/LibRyujinx/LibRyujinx.Input.cs new file mode 100644 index 000000000..c301f3502 --- /dev/null +++ b/src/LibRyujinx/LibRyujinx.Input.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LibRyujinx +{ + public static partial class LibRyujinx + { + } +} diff --git a/src/LibRyujinx/LibRyujinx.Shared.csproj b/src/LibRyujinx/LibRyujinx.Shared.csproj new file mode 100644 index 000000000..8bcb26228 --- /dev/null +++ b/src/LibRyujinx/LibRyujinx.Shared.csproj @@ -0,0 +1,41 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net7.0</TargetFramework> + <Nullable>enable</Nullable> + </PropertyGroup> + <PropertyGroup> + <PublishAot>true</PublishAot> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <EnableTrimAnalyzer>true</EnableTrimAnalyzer> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" /> + <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" /> + <ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" /> + <ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" /> + <ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" /> + <ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" /> + <ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" /> + <ProjectReference Include="..\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj" /> + </ItemGroup> + <ItemGroup> + <RdXmlFile Include="rd.xml" /> + </ItemGroup> + + <ItemGroup> + <Compile Update="LibRyujinx.cs"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Compile> + <Compile Update="LibRyujinx.Device.cs"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Compile> + <Compile Update="LibRyujinx.Graphics.cs"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Compile> + <Compile Update="LibRyujinx.Input.cs"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Compile> + </ItemGroup> +</Project> diff --git a/src/LibRyujinx/LibRyujinx.cs b/src/LibRyujinx/LibRyujinx.cs new file mode 100644 index 000000000..6d9a14c05 --- /dev/null +++ b/src/LibRyujinx/LibRyujinx.cs @@ -0,0 +1,151 @@ +// State class for the library +using Ryujinx.HLE.FileSystem; +using Ryujinx.HLE.HOS.Services.Account.Acc; +using Ryujinx.HLE.HOS; +using Ryujinx.Input.HLE; +using Ryujinx.HLE; +using System; +using System.Runtime.InteropServices; +using Ryujinx.Common.Configuration; +using LibHac.Tools.FsSystem; +using Ryujinx.Graphics.GAL.Multithreading; +using Ryujinx.Audio.Backends.Dummy; +using Ryujinx.HLE.HOS.SystemState; +using Ryujinx.Ui.Common.Configuration; +using Ryujinx.Common.Logging; + +namespace LibRyujinx +{ + public static partial class LibRyujinx + { + public static SwitchDevice? SwitchDevice { get; set; } + + [UnmanagedCallersOnly(EntryPoint = "initialize")] + public static bool Initialize(IntPtr basePathPtr) + { + var path = Marshal.PtrToStringAnsi(basePathPtr); + + return Initialize(path); + } + + public static bool Initialize(string? basePath) + { + if (SwitchDevice != null) + { + return false; + } + + try + { + AppDataManager.Initialize(basePath); + + ConfigurationState.Initialize(); + LoggerModule.Initialize(); + + SwitchDevice = new SwitchDevice(); + + Logger.SetEnable(LogLevel.Debug, false); + Logger.SetEnable(LogLevel.Stub, true); + Logger.SetEnable(LogLevel.Info, true); + Logger.SetEnable(LogLevel.Warning, true); + Logger.SetEnable(LogLevel.Error, true); + Logger.SetEnable(LogLevel.Trace, false); + Logger.SetEnable(LogLevel.Guest, true); + Logger.SetEnable(LogLevel.AccessLog, false); + } + catch (Exception ex) + { + return false; + } + + return true; + } + } + + public class SwitchDevice : IDisposable + { + public VirtualFileSystem VirtualFileSystem { get; set; } + public ContentManager ContentManager { get; set; } + public AccountManager AccountManager { get; set; } + public LibHacHorizonManager LibHacHorizonManager { get; set; } + public UserChannelPersistence UserChannelPersistence { get; set; } + public InputManager? InputManager { get; set; } + public Switch? EmulationContext { get; set; } + + public void Dispose() + { + VirtualFileSystem?.Dispose(); + InputManager?.Dispose(); + EmulationContext?.Dispose(); + } + + public SwitchDevice() + { + VirtualFileSystem = VirtualFileSystem.CreateInstance(); + LibHacHorizonManager = new LibHacHorizonManager(); + + LibHacHorizonManager.InitializeFsServer(VirtualFileSystem); + LibHacHorizonManager.InitializeArpServer(); + LibHacHorizonManager.InitializeBcatServer(); + LibHacHorizonManager.InitializeSystemClients(); + + ContentManager = new ContentManager(VirtualFileSystem); + AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient); + UserChannelPersistence = new UserChannelPersistence(); + } + + public bool InitializeContext() + { + if(LibRyujinx.Renderer == null) + { + return false; + } + + var renderer = LibRyujinx.Renderer; + BackendThreading threadingMode = LibRyujinx.GraphicsConfiguration.BackendThreading; + + bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading); + + if (threadedGAL) + { + renderer = new ThreadedRenderer(renderer); + } + + HLEConfiguration configuration = new HLEConfiguration(VirtualFileSystem, + LibHacHorizonManager, + ContentManager, + AccountManager, + UserChannelPersistence, + renderer, + new DummyHardwareDeviceDriver(), //Audio + MemoryConfiguration.MemoryConfiguration4GiB, + null, + SystemLanguage.AmericanEnglish, + RegionCode.USA, + true, + true, + true, + false, + IntegrityCheckLevel.None, + 0, + 0, + "UTC", + MemoryManagerMode.HostMappedUnsafe, + false, + AspectRatio.Fixed16x9, + 0, + true, + ""); + + EmulationContext = new Switch(configuration); + + return true; + } + + internal void DisposeContext() + { + EmulationContext?.Dispose(); + EmulationContext = null; + } + } +} \ No newline at end of file diff --git a/src/LibRyujinx/OpenTKBindingsContext.cs b/src/LibRyujinx/OpenTKBindingsContext.cs new file mode 100644 index 000000000..203caee8b --- /dev/null +++ b/src/LibRyujinx/OpenTKBindingsContext.cs @@ -0,0 +1,20 @@ +using OpenTK; +using System; + +namespace LibRyujinx.Shared +{ + public class OpenTKBindingsContext : IBindingsContext + { + private readonly Func<string, IntPtr> _getProcAddress; + + public OpenTKBindingsContext(Func<string, IntPtr> getProcAddress) + { + _getProcAddress = getProcAddress; + } + + public IntPtr GetProcAddress(string procName) + { + return _getProcAddress(procName); + } + } +} \ No newline at end of file diff --git a/src/LibRyujinx/rd.xml b/src/LibRyujinx/rd.xml new file mode 100644 index 000000000..c533ac82a --- /dev/null +++ b/src/LibRyujinx/rd.xml @@ -0,0 +1,661 @@ +<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"> + <Application> + <Assembly Name="ARMeilleure"> + <Type Name="ARMeilleure.Instructions.NativeInterface"> + <Method Name="Break"/> + </Type> + </Assembly> + <Assembly Name="Silk.NET.Vulkan.Extensions.EXT"> + <Type Name="Silk.NET.Vulkan.Extensions.EXT.ExtDebugUtils" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.EXT.ExtExternalMemoryHost" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.EXT.ExtConditionalRendering" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.EXT.ExtExtendedDynamicState" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.EXT.ExtTransformFeedback" + Dynamic="Required All"/> + </Assembly> + <Assembly Name="Silk.NET.Vulkan.Extensions.KHR"> + <Type Name="Silk.NET.Vulkan.Extensions.KHR.KhrSurface" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.KHR.KhrPushDescriptor" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.KHR.KhrDrawIndirectCount" + Dynamic="Required All"/> + <Type Name="Silk.NET.Vulkan.Extensions.KHR.KhrSwapchain" + Dynamic="Required All"/> + </Assembly> + <Assembly Name="Ryujinx.HLE"> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.NvHostGpuDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.IFileSystemProxyForLoader" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pm.IInformationInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ngct.IService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.Tcap.IFactorySettingsServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Grc.IRemoteVideoTransfer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.AccountService.IProfileEditor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostDbgGpu.NvHostDbgGpuDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy.ILibraryAppletSelfAccessor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.AccountService.IProfile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.AccountService.IManagerForSystemService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ssl.SslService.SslManagedSocketConnection" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.INetworkInstallManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.HardwareOpusDecoderManager.Decoder" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Apm.SessionServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Ethc.IEthInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.Nfp.IAmManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.Types.NvQueryEventNotImplementedException" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap.NvMapDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.Idle.IPolicyManagerSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IAccountServiceForSystemService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Apm.ManagerServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Bluetooth.IBluetoothUser" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.Irs.IIrSensorSystemServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.EphemeralNetworkSystemClockContextWriter" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.ProfilesJsonSerializerContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Apm.IManagerPrivileged" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.MouseDevice" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Bpc.IRtcManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Bgct.IStateControlService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.BluetoothManager.IBtmSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.IStaticServiceForPsc" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fatal.IService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ins.IReceiverManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.SurfaceFlinger.ConsumerBase" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.StaticService.ISteadyClock" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.IStorage" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Psc.IPmService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.HidServer.IAppletResource" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nifm.StaticService.IGeneralService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.IServiceGetterInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.IMultiCommitManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IAudioController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IHardwareOpusDecoderManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.Nfp.AmiiboJsonSerializerContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IPdManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.HardwareOpusDecoderManager.MultiSampleDecoder" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.StandardLocalSystemClockCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Arp.IWriter" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.NfcManager.INfc" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Fgm.IDebugger" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.IHidServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Eupld.IRequest" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.TickBasedSteadyClockCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.SurfaceFlinger.BufferItem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.IShopServiceManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.IDaemonSuspendSessionService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Erpt.IContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer.IShopServiceAccessor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IFileSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService.ISystemDisplayService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Caps.IScreenshotService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IGlobalStateController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Settings.IFirmwareDebugSettingsServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioRendererManagerForApplet" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IUnknown2" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Arp.IReader" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.StandardNetworkSystemClockCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.HardwareOpusDecoderManager.IHardwareOpusDecoder" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Olsc.IOlscServiceForApplication" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.IApplicationManagerInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.IProgramRegistry" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ldn.Lp2p.IServiceCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.IHidDebugServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.IAmManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sdb.Pdm.INotifyService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.IPowerStateRequestHandler" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.IDeviceOperator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IPdCradleManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Lbl.LblControllerServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioOutManagerForApplet" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.ISystemAppletProxy" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRendererManagerServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Caps.IAlbumAccessorService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sdb.Pl.ISharedFontManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Cec.ICecManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.Nfp.IUserManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.ServiceAttribute" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.News.IServiceCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.Irs.IIrSensorServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pctl.IParentalControlServiceFactory" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Bgct.ITaskService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.Omm.IOperationModeManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.KeyboardDevice" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fatal.IPrivateService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.BluetoothManager.IBtmDebug" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRenderer.AudioDeviceServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy.IProcessWindingController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IDirectory" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer.ShopServiceAccessor.IShopServiceAsync" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.TouchDevice" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.NetworkSystemClockContextWriter" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nifm.StaticService.IRequest" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Settings.ISystemSettingsServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.ISelfController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.ICommonStateGetter" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService.IEnsureNetworkClockAvailabilityService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IWindowController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.DebugPadDevice" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioOut.AudioOut" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.ISocketManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager.ILocationResolver" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Mii.IStaticService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.IHidbusServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Clkrst.IClkrstManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.IDevelopInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Mii.StaticService.DatabaseServiceImpl" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.IHidSystemServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IAccountServiceForAdministrator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ectx.IWriterForSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.NpadDevices" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Vi.IManagerRootService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.INvDrvServices" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.AccountService.IManagerForApplication" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.HidServer.IActiveApplicationDeviceList" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IDebugFunctions" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.Tcap.IAvmService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Srepo.ISrepoService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.BluetoothManager.IBtmUser" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcie.IManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioIn.AudioIn" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.IStorageAccessor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator.ILibraryAppletAccessor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IAccountServiceForApplication" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioRendererManagerForDebugger" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Caps.IScreenShotApplicationService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IBaasAccessTokenAccessor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioSnoopManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.IUserManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.IShopServiceAccessSystemInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.IApplicationProxy" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.BluetoothManager.IBtm" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Fgm.ISession" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.Host1xContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Arp.LibHacIReader" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Arp.LibHacArpServiceObject" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.IAlarmService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ngct.IServiceWithManagementApi" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Npns.INpnsSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Ts.IMeasurementServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostProfGpu.NvHostProfGpuDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.INotificationService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AppletFifo`1" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Bpc.IBoardPowerControlManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ins.ISenderManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.ILocalGetFrame" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.IUnknown1" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ldn.IUserServiceCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Spl.IRandomInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IPmService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sdb.Pdm.IQueryService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Pcm.IManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioInManagerForApplet" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.SurfaceFlinger.HOSBinderDriverServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.ILocalManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ncm.IContentManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Vi.ISystemRootService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Fan.IManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.IApplicationFunctions" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioInManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.Nfp.INfp" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Mm.IRequest" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.IVulnerabilityManagerInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.IInfraManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Caps.IAlbumApplicationService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.Tcap.IManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.IFriendService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.SurfaceFlinger.BufferQueueProducer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.EphemeralNetworkSystemClockCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Bsd.ServerInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.IShopServiceAccessServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.Aoc.IPurchaseEventManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ro.IRoInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Mig.IService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.Ntc.IStaticService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.StaticService.ITimeZoneServiceForPsc" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.Types.NvIoctlNotImplementedException" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioOutManagerForDebugger" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ldn.ISystemServiceCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.ServerBase" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Nsd.IManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.LocalSystemClockContextWriter" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcie.ILogManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Dauth.IService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.INvGemControl" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Spl.IGeneralInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Clkrst.IArbitrationManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl.EventFileDescriptorPollManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Ethc.IEthInterfaceGroup" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Settings.ISettingsServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.INvDrvDebugFSServices" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.ISystemUpdateInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ovln.IReceiverService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.ISystemManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.IPcvService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRenderer.AudioRendererServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.IApplicationProxyService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IFinalOutputRecorderManagerForApplet" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Loader.IShellInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ssl.SslService.ISslConnection" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.SurfaceFlinger.BufferItemConsumer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.ISocketGetFrame" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl.NvHostCtrlDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory.IParentalControlService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.IAllSystemAppletProxiesService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.IReadOnlyApplicationControlDataInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Erpt.ISession" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Friend.IServiceCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Psm.IPsmServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nim.IShopServiceAccessServerInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Caps.IScreenShotControlService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.StandardSteadyClockCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IAudioInManagerForDebugger" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Hid.ISystemServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.Mifare.IUserManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Clkrst.ClkrstManager.IClkrstSession" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.StaticService.ISystemClock" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pm.IDebugMonitorInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ldn.IMonitorServiceCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Grc.IGrcService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IDisplayController" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Bsd.IClient" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IApplicationCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.Aoc.IAddOnContentManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.ITimeServiceManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Bluetooth.IBluetoothDriver" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ns.Aoc.IContentsServiceManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.ILibraryAppletCreator" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IFinalOutputRecorderManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Psc.IPmControl" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.NvHostChannelDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IStorage" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sm.IUserInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.NvHostCtrlGpuDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.CommandTipcAttribute" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Eupld.IControl" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioIn.AudioInServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Psc.IPmUnknown" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Vi.RootService.IApplicationDisplayService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Loader.IDebugMonitorInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioOutManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nfc.Nfp.ISystemManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IAsyncNetworkServiceLicenseKindContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ectx.IWriterForApplication" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ncm.Lr.ILocationResolverManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.StaticService.ITimeZoneServiceForGlue" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Wlan.ILocalGetActionFrame" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Notification.INotificationServicesForSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.Spsm.IPowerStateInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.DummyService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IHomeMenuFunctions" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.NvHostAsGpuDeviceFile" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Apm.SystemManagerServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioOutManagerServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.IFinalOutputRecorderManagerForDebugger" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sm.IManagerInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.SurfaceFlinger.SurfaceFlinger" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.IResolver" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRenderer.AudioKernelEvent" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Psm.IPsmSession" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IAsyncContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.IAppletCommonFunctions" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl.ManagedSocket" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pm.IBootModeInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ovln.ISenderService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Npns.INpnsUser" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Olsc.IOlscServiceForSystemService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRenderer.AudioRenderer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IDsService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService.IManagerDisplayService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ptm.Tc.IManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IUnknown1" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ectx.IReaderForSystem" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Loader.IProcessManagerInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Notification.INotificationServicesForApplication" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pm.IShellInterface" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.ILibraryAppletProxy" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioInManagerServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ssl.ISslService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Mii.IImageDatabaseService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.StandardUserSystemClockCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Vi.IApplicationRootService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Usb.IClientRootSession" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioOut.AudioOutServer" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser.IBtmUserCore" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.ISaveDataInfoReader" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ssl.SslService.ISslContext" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nv.INvGemCoreDump" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl.EventFileDescriptor" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Mnpp.IServiceForApplication" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Fs.IFileSystemProxy" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Caps.IAlbumControlService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.IUserLocalCommunicationService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Nifm.IStaticService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl.ManagedSocketPollManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Audio.AudioRenderer.AudioDevice" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Time.IStaticServiceForGlue" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.CommandCmifAttribute" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Rtc.IRtcManager" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Es.IETicketService" + Dynamic="Required All" /> + <Type Name="Ryujinx.HLE.HOS.Services.Pcv.Rgltr.IRegulatorManager" + Dynamic="Required All" /> + </Assembly> + </Application> +</Directives> \ No newline at end of file