mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-10-02 16:50:20 -07:00
add libryujinx to solution
This commit is contained in:
parent
a2c0035013
commit
92117c299f
12
Ryujinx.sln
12
Ryujinx.sln
@ -89,6 +89,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Gene
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibRyujinx", "src\LibRyujinx\LibRyujinx.csproj", "{D4E40005-CC75-41B2-878E-5A4300197A2C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibRyujinx.NativeSample", "src\LibRyujinx.NativeSample\LibRyujinx.NativeSample.csproj", "{DCB49372-5B6F-4AF4-9A62-D4C2CBB9217B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -255,6 +259,14 @@ Global
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4E40005-CC75-41B2-878E-5A4300197A2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D4E40005-CC75-41B2-878E-5A4300197A2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D4E40005-CC75-41B2-878E-5A4300197A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4E40005-CC75-41B2-878E-5A4300197A2C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DCB49372-5B6F-4AF4-9A62-D4C2CBB9217B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DCB49372-5B6F-4AF4-9A62-D4C2CBB9217B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DCB49372-5B6F-4AF4-9A62-D4C2CBB9217B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DCB49372-5B6F-4AF4-9A62-D4C2CBB9217B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
16
src/LibRyujinx.NativeSample/LibRyujinx.NativeSample.csproj
Normal file
16
src/LibRyujinx.NativeSample/LibRyujinx.NativeSample.csproj
Normal file
@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK" />
|
||||
<PackageReference Include="Ryujinx.SDL2-CS" />
|
||||
</ItemGroup>
|
||||
</Project>
|
228
src/LibRyujinx.NativeSample/LibRyujinxInterop.cs
Normal file
228
src/LibRyujinx.NativeSample/LibRyujinxInterop.cs
Normal file
@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LibRyujinx.Sample
|
||||
{
|
||||
internal static class LibRyujinxInterop
|
||||
{
|
||||
private const string dll = "LibRyujinx.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(bool isHostMapped,
|
||||
bool useHypervisor,
|
||||
SystemLanguage systemLanguage,
|
||||
RegionCode regionCode,
|
||||
bool enableVsync,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableInternetAccess,
|
||||
IntPtr timeZone,
|
||||
bool ignoreMissingServices);
|
||||
|
||||
[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);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_initialize")]
|
||||
internal extern static void InitializeInput(int width, int height);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_set_client_size")]
|
||||
internal extern static void SetClientSize(int width, int height);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_set_touch_point")]
|
||||
internal extern static void SetTouchPoint(int x, int y);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_release_touch_point")]
|
||||
internal extern static void ReleaseTouchPoint();
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_update")]
|
||||
internal extern static void UpdateInput();
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_set_button_pressed")]
|
||||
public extern static void SetButtonPressed(GamepadButtonInputId button, IntPtr idPtr);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_set_button_released")]
|
||||
public extern static void SetButtonReleased(GamepadButtonInputId button, IntPtr idPtr);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_set_stick_axis")]
|
||||
public extern static void SetStickAxis(StickInputId stick, Vector2 axes, IntPtr idPtr);
|
||||
|
||||
[DllImport(dll, EntryPoint = "input_connect_gamepad")]
|
||||
public extern static IntPtr ConnectGamepad(int index);
|
||||
}
|
||||
|
||||
public enum GraphicsBackend
|
||||
{
|
||||
Vulkan,
|
||||
OpenGl
|
||||
}
|
||||
|
||||
public enum BackendThreading
|
||||
{
|
||||
Auto,
|
||||
Off,
|
||||
On
|
||||
}
|
||||
|
||||
[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 EnableTextureRecompression = false;
|
||||
public BackendThreading BackendThreading = BackendThreading.Auto;
|
||||
public AspectRatio AspectRatio = AspectRatio.Fixed16x9;
|
||||
|
||||
public GraphicsConfiguration()
|
||||
{
|
||||
}
|
||||
}
|
||||
public enum SystemLanguage
|
||||
{
|
||||
Japanese,
|
||||
AmericanEnglish,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Spanish,
|
||||
Chinese,
|
||||
Korean,
|
||||
Dutch,
|
||||
Portuguese,
|
||||
Russian,
|
||||
Taiwanese,
|
||||
BritishEnglish,
|
||||
CanadianFrench,
|
||||
LatinAmericanSpanish,
|
||||
SimplifiedChinese,
|
||||
TraditionalChinese,
|
||||
BrazilianPortuguese,
|
||||
}
|
||||
public enum RegionCode
|
||||
{
|
||||
Japan,
|
||||
USA,
|
||||
Europe,
|
||||
Australia,
|
||||
China,
|
||||
Korea,
|
||||
Taiwan,
|
||||
|
||||
Min = Japan,
|
||||
Max = Taiwan,
|
||||
}
|
||||
|
||||
public struct NativeGraphicsInterop
|
||||
{
|
||||
public IntPtr GlGetProcAddress;
|
||||
public IntPtr VkNativeContextLoader;
|
||||
public IntPtr VkCreateSurface;
|
||||
public IntPtr VkRequiredExtensions;
|
||||
public int VkRequiredExtensionsCount;
|
||||
}
|
||||
|
||||
public enum AspectRatio
|
||||
{
|
||||
Fixed4x3,
|
||||
Fixed16x9,
|
||||
Fixed16x10,
|
||||
Fixed21x9,
|
||||
Fixed32x9,
|
||||
Stretched
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represent a button from a gamepad.
|
||||
/// </summary>
|
||||
public enum GamepadButtonInputId : byte
|
||||
{
|
||||
Unbound,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
LeftStick,
|
||||
RightStick,
|
||||
LeftShoulder,
|
||||
RightShoulder,
|
||||
|
||||
// Likely axis
|
||||
LeftTrigger,
|
||||
// Likely axis
|
||||
RightTrigger,
|
||||
|
||||
DpadUp,
|
||||
DpadDown,
|
||||
DpadLeft,
|
||||
DpadRight,
|
||||
|
||||
// Special buttons
|
||||
|
||||
Minus,
|
||||
Plus,
|
||||
|
||||
Back = Minus,
|
||||
Start = Plus,
|
||||
|
||||
Guide,
|
||||
Misc1,
|
||||
|
||||
// Xbox Elite paddle
|
||||
Paddle1,
|
||||
Paddle2,
|
||||
Paddle3,
|
||||
Paddle4,
|
||||
|
||||
// PS5 touchpad button
|
||||
Touchpad,
|
||||
|
||||
// Virtual buttons for single joycon
|
||||
SingleLeftTrigger0,
|
||||
SingleRightTrigger0,
|
||||
|
||||
SingleLeftTrigger1,
|
||||
SingleRightTrigger1,
|
||||
|
||||
Count
|
||||
}
|
||||
|
||||
public enum StickInputId : byte
|
||||
{
|
||||
Unbound,
|
||||
Left,
|
||||
Right,
|
||||
|
||||
Count
|
||||
}
|
||||
}
|
260
src/LibRyujinx.NativeSample/NativeWindow.cs
Normal file
260
src/LibRyujinx.NativeSample/NativeWindow.cs
Normal file
@ -0,0 +1,260 @@
|
||||
using LibRyujinx.Sample;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using OpenTK.Mathematics;
|
||||
using OpenTK.Windowing.Common;
|
||||
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 _run;
|
||||
private bool _isVulkan;
|
||||
private Vector2 _lastPosition;
|
||||
private bool _mousePressed;
|
||||
private nint _gamepadIdPtr;
|
||||
private string? _gamepadId;
|
||||
|
||||
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);
|
||||
var timeZone = Marshal.StringToHGlobalAnsi("UTC");
|
||||
success = LibRyujinxInterop.InitializeDevice(true,
|
||||
false,
|
||||
SystemLanguage.AmericanEnglish,
|
||||
RegionCode.USA,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
timeZone,
|
||||
false);
|
||||
LibRyujinxInterop.InitializeInput(ClientSize.X, ClientSize.Y);
|
||||
Marshal.FreeHGlobal(timeZone);
|
||||
|
||||
var path = Marshal.StringToHGlobalAnsi(gamePath);
|
||||
var loaded = LibRyujinxInterop.LoadApplication(path);
|
||||
LibRyujinxInterop.SetRendererSize(Size.X, Size.Y);
|
||||
Marshal.FreeHGlobal(path);
|
||||
}
|
||||
|
||||
_gamepadIdPtr = LibRyujinxInterop.ConnectGamepad(0);
|
||||
_gamepadId = Marshal.PtrToStringAnsi(_gamepadIdPtr);
|
||||
|
||||
if (!_isVulkan)
|
||||
{
|
||||
Context.MakeNoneCurrent();
|
||||
}
|
||||
|
||||
_run = true;
|
||||
var thread = new Thread(new ThreadStart(RunLoop));
|
||||
thread.Start();
|
||||
|
||||
UpdateLoop();
|
||||
|
||||
thread.Join();
|
||||
|
||||
foreach(var ptr in pointers)
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(_gamepadIdPtr);
|
||||
}
|
||||
|
||||
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(true);
|
||||
});*/
|
||||
|
||||
LibRyujinxInterop.RunLoop();
|
||||
|
||||
_run = false;
|
||||
|
||||
if (!_isVulkan)
|
||||
{
|
||||
Context.MakeNoneCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
private void SwapBuffers()
|
||||
{
|
||||
if (!_isVulkan)
|
||||
{
|
||||
this.Context.SwapBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseMoveEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
_lastPosition = e.Position;
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
if(e.Button == MouseButton.Left)
|
||||
{
|
||||
_mousePressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnResize(ResizeEventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
|
||||
if (_run)
|
||||
{
|
||||
LibRyujinxInterop.SetRendererSize(e.Width, e.Height);
|
||||
LibRyujinxInterop.SetClientSize(e.Width, e.Height);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseButtonEventArgs e)
|
||||
{
|
||||
base.OnMouseUp(e);
|
||||
if (e.Button == MouseButton.Left)
|
||||
{
|
||||
_mousePressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyboardKeyEventArgs e)
|
||||
{
|
||||
base.OnKeyUp(e);
|
||||
|
||||
if (_gamepadIdPtr != IntPtr.Zero)
|
||||
{
|
||||
var key = GetKeyMapping(e.Key);
|
||||
|
||||
LibRyujinxInterop.SetButtonReleased(key, _gamepadIdPtr);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyboardKeyEventArgs e)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
|
||||
if (_gamepadIdPtr != IntPtr.Zero)
|
||||
{
|
||||
var key = GetKeyMapping(e.Key);
|
||||
|
||||
LibRyujinxInterop.SetButtonPressed(key, _gamepadIdPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateLoop()
|
||||
{
|
||||
while(_run)
|
||||
{
|
||||
ProcessWindowEvents(true);
|
||||
NewInputFrame();
|
||||
ProcessWindowEvents(IsEventDriven);
|
||||
if (_mousePressed)
|
||||
{
|
||||
LibRyujinxInterop.SetTouchPoint((int)_lastPosition.X, (int)_lastPosition.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
LibRyujinxInterop.ReleaseTouchPoint();
|
||||
}
|
||||
|
||||
LibRyujinxInterop.UpdateInput();
|
||||
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
public GamepadButtonInputId GetKeyMapping(Keys key)
|
||||
{
|
||||
if(_keyMapping.TryGetValue(key, out var mapping))
|
||||
{
|
||||
return mapping;
|
||||
}
|
||||
|
||||
return GamepadButtonInputId.Unbound;
|
||||
}
|
||||
|
||||
private Dictionary<Keys, GamepadButtonInputId> _keyMapping = new Dictionary<Keys, GamepadButtonInputId>()
|
||||
{
|
||||
{Keys.A, GamepadButtonInputId.A },
|
||||
{Keys.S, GamepadButtonInputId.B },
|
||||
{Keys.Z, GamepadButtonInputId.X },
|
||||
{Keys.X, GamepadButtonInputId.Y },
|
||||
{Keys.Equal, GamepadButtonInputId.Plus },
|
||||
{Keys.Minus, GamepadButtonInputId.Minus },
|
||||
{Keys.Q, GamepadButtonInputId.LeftShoulder },
|
||||
{Keys.D1, GamepadButtonInputId.LeftTrigger },
|
||||
{Keys.W, GamepadButtonInputId.RightShoulder },
|
||||
{Keys.D2, GamepadButtonInputId.RightTrigger },
|
||||
{Keys.E, GamepadButtonInputId.LeftStick },
|
||||
{Keys.R, GamepadButtonInputId.RightStick },
|
||||
{Keys.Up, GamepadButtonInputId.DpadUp },
|
||||
{Keys.Down, GamepadButtonInputId.DpadDown },
|
||||
{Keys.Left, GamepadButtonInputId.DpadLeft },
|
||||
{Keys.Right, GamepadButtonInputId.DpadRight },
|
||||
{Keys.U, GamepadButtonInputId.SingleLeftTrigger0 },
|
||||
{Keys.D7, GamepadButtonInputId.SingleLeftTrigger1 },
|
||||
{Keys.O, GamepadButtonInputId.SingleRightTrigger0 },
|
||||
{Keys.D9, GamepadButtonInputId.SingleRightTrigger1 }
|
||||
};
|
||||
}
|
||||
}
|
33
src/LibRyujinx.NativeSample/Program.cs
Normal file
33
src/LibRyujinx.NativeSample/Program.cs
Normal file
@ -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()
|
||||
{
|
||||
ClientSize = new Vector2i(800, 600),
|
||||
Title = "Ryujinx Native",
|
||||
API = ContextAPI.NoAPI,
|
||||
IsEventDriven = false,
|
||||
// This is needed to run on macos
|
||||
Flags = ContextFlags.ForwardCompatible,
|
||||
};
|
||||
|
||||
using var window = new NativeWindow(nativeWindowSettings);
|
||||
|
||||
window.IsVisible = true;
|
||||
window.Start(args[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
src/LibRyujinx/Android/AndroidLogTarget.cs
Normal file
49
src/LibRyujinx/Android/AndroidLogTarget.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Logging.Formatters;
|
||||
using Ryujinx.Common.Logging.Targets;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public class AndroidLogTarget : ILogTarget
|
||||
{
|
||||
private readonly string _name;
|
||||
private readonly DefaultLogFormatter _formatter;
|
||||
|
||||
string ILogTarget.Name { get => _name; }
|
||||
|
||||
public AndroidLogTarget(string name)
|
||||
{
|
||||
_name = name;
|
||||
_formatter = new DefaultLogFormatter();
|
||||
}
|
||||
|
||||
public void Log(object sender, LogEventArgs args)
|
||||
{
|
||||
Logcat.AndroidLogPrint(GetLogLevel(args.Level), _name, _formatter.Format(args));
|
||||
}
|
||||
|
||||
private static Logcat.LogLevel GetLogLevel(LogLevel logLevel)
|
||||
{
|
||||
return logLevel switch
|
||||
{
|
||||
LogLevel.Debug => Logcat.LogLevel.Debug,
|
||||
LogLevel.Stub => Logcat.LogLevel.Info,
|
||||
LogLevel.Info => Logcat.LogLevel.Info,
|
||||
LogLevel.Warning => Logcat.LogLevel.Warn,
|
||||
LogLevel.Error => Logcat.LogLevel.Error,
|
||||
LogLevel.Guest => Logcat.LogLevel.Info,
|
||||
LogLevel.AccessLog => Logcat.LogLevel.Info,
|
||||
LogLevel.Notice => Logcat.LogLevel.Info,
|
||||
LogLevel.Trace => Logcat.LogLevel.Verbose,
|
||||
_ => throw new NotImplementedException(),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
114
src/LibRyujinx/Android/AndroidUiHandler.cs
Normal file
114
src/LibRyujinx/Android/AndroidUiHandler.cs
Normal file
@ -0,0 +1,114 @@
|
||||
using LibHac.Tools.Fs;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||
using Ryujinx.HLE.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LibRyujinx.Android
|
||||
{
|
||||
internal class AndroidUIHandler : IHostUIHandler, IDisposable
|
||||
{
|
||||
private bool _isDisposed;
|
||||
private bool _isOkPressed;
|
||||
private string? _input;
|
||||
private ManualResetEvent _resetEvent = new ManualResetEvent(false);
|
||||
|
||||
public IHostUITheme HostUITheme => throw new NotImplementedException();
|
||||
|
||||
public IDynamicTextInputHandler CreateDynamicTextInputHandler()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText)
|
||||
{
|
||||
Interop.UpdateUiHandler(title ?? "",
|
||||
message ?? "",
|
||||
"",
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
KeyboardMode.Default,
|
||||
"",
|
||||
"");
|
||||
|
||||
return _isOkPressed;
|
||||
}
|
||||
|
||||
public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
|
||||
{
|
||||
_input = null;
|
||||
_resetEvent.Reset();
|
||||
Interop.UpdateUiHandler("Software Keyboard",
|
||||
args.HeaderText ?? "",
|
||||
args.GuideText ?? "",
|
||||
2,
|
||||
args.StringLengthMin,
|
||||
args.StringLengthMax,
|
||||
args.KeyboardMode,
|
||||
args.SubtitleText ?? "",
|
||||
args.InitialText ?? "");
|
||||
|
||||
_resetEvent.WaitOne();
|
||||
|
||||
userText = _input ?? "";
|
||||
|
||||
return _isOkPressed;
|
||||
}
|
||||
|
||||
public bool DisplayMessageDialog(string title, string message)
|
||||
{
|
||||
Interop.UpdateUiHandler(title ?? "",
|
||||
message ?? "",
|
||||
"",
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
KeyboardMode.Default,
|
||||
"",
|
||||
"");
|
||||
|
||||
return _isOkPressed;
|
||||
}
|
||||
|
||||
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
||||
{
|
||||
string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
|
||||
|
||||
string message = $"Application requests **{playerCount}** player(s) with:\n\n"
|
||||
+ $"**TYPES:** {args.SupportedStyles}\n\n"
|
||||
+ $"**PLAYERS:** {string.Join(", ", args.SupportedPlayers)}\n\n"
|
||||
+ (args.IsDocked ? "Docked mode set. `Handheld` is also invalid.\n\n" : "")
|
||||
+ "_Please reconfigure Input now and then press OK._";
|
||||
|
||||
return DisplayMessageDialog("Controller Applet", message);
|
||||
}
|
||||
|
||||
public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
|
||||
{
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal void SetResponse(bool isOkPressed, string input)
|
||||
{
|
||||
if (_isDisposed)
|
||||
return;
|
||||
_isOkPressed = isOkPressed;
|
||||
_input = input;
|
||||
_resetEvent.Set();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
232
src/LibRyujinx/Android/Interop.cs
Normal file
232
src/LibRyujinx/Android/Interop.cs
Normal file
@ -0,0 +1,232 @@
|
||||
using LibRyujinx.Jni;
|
||||
using LibRyujinx.Jni.Identifiers;
|
||||
using LibRyujinx.Jni.Pointers;
|
||||
using LibRyujinx.Jni.Primitives;
|
||||
using LibRyujinx.Jni.References;
|
||||
using LibRyujinx.Jni.Values;
|
||||
using Rxmxnx.PInvoke;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace LibRyujinx.Android
|
||||
{
|
||||
internal unsafe static class Interop
|
||||
{
|
||||
internal const string BaseClassName = "org/ryujinx/android/RyujinxNative";
|
||||
|
||||
private static JGlobalRef? _classId;
|
||||
private static ConcurrentDictionary<(string method, string descriptor), JMethodId> _methodCache = new ConcurrentDictionary<(string method, string descriptor), JMethodId>();
|
||||
private static (string name, string descriptor)[] _methods = new[]
|
||||
{
|
||||
("test", "()V"),
|
||||
("updateUiHandler", "(JJJIIIIJJ)V"),
|
||||
("frameEnded", "()V"),
|
||||
("updateProgress", "(JF)V"),
|
||||
("getSurfacePtr", "()J"),
|
||||
("getWindowHandle", "()J")
|
||||
};
|
||||
|
||||
internal static void Initialize(JEnvRef jniEnv)
|
||||
{
|
||||
var vm = JniHelper.GetVirtualMachine(jniEnv);
|
||||
if (_classId == null)
|
||||
{
|
||||
var className = new ReadOnlySpan<Byte>(Encoding.UTF8.GetBytes(BaseClassName));
|
||||
using (IReadOnlyFixedMemory<Byte>.IDisposable cName = className.GetUnsafeValPtr()
|
||||
.GetUnsafeFixedContext(className.Length))
|
||||
{
|
||||
_classId = JniHelper.GetGlobalClass(jniEnv, cName);
|
||||
if (_classId == null)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"Class Id {BaseClassName} not found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var x in _methods)
|
||||
{
|
||||
CacheMethod(jniEnv, x.name, x.descriptor);
|
||||
}
|
||||
|
||||
JniEnv._jvm = vm;
|
||||
}
|
||||
|
||||
private static void CacheMethod(JEnvRef jEnv, string name, string descriptor)
|
||||
{
|
||||
if (!_methodCache.TryGetValue((name, descriptor), out var method))
|
||||
{
|
||||
var methodName = new ReadOnlySpan<Byte>(Encoding.UTF8.GetBytes(name));
|
||||
var descriptorId = new ReadOnlySpan<Byte>(Encoding.UTF8.GetBytes(descriptor));
|
||||
using (IReadOnlyFixedMemory<Byte>.IDisposable mName = methodName.GetUnsafeValPtr()
|
||||
.GetUnsafeFixedContext(methodName.Length))
|
||||
using (IReadOnlyFixedMemory<Byte>.IDisposable dName = descriptorId.GetUnsafeValPtr()
|
||||
.GetUnsafeFixedContext(descriptorId.Length))
|
||||
{
|
||||
var methodId = JniHelper.GetStaticMethodId(jEnv, (JClassLocalRef)(_classId.Value.Value), mName, dName);
|
||||
if (methodId == null)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Java Method Id {name} not found");
|
||||
return;
|
||||
}
|
||||
|
||||
method = methodId.Value;
|
||||
_methodCache[(name, descriptor)] = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void CallVoidMethod(string name, string descriptor, params JValue[] values)
|
||||
{
|
||||
using var env = JniEnv.Create();
|
||||
if (_methodCache.TryGetValue((name, descriptor), out var method))
|
||||
{
|
||||
if (descriptor.EndsWith("V"))
|
||||
{
|
||||
JniHelper.CallStaticVoidMethod(env.Env, (JClassLocalRef)(_classId.Value.Value), method, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JLong CallLongMethod(string name, string descriptor, params JValue[] values)
|
||||
{
|
||||
using var env = JniEnv.Create();
|
||||
if (_methodCache.TryGetValue((name, descriptor), out var method))
|
||||
{
|
||||
if (descriptor.EndsWith("J"))
|
||||
return JniHelper.CallStaticLongMethod(env.Env, (JClassLocalRef)(_classId.Value.Value), method, values) ?? (JLong)(-1);
|
||||
}
|
||||
|
||||
return (JLong)(-1);
|
||||
}
|
||||
|
||||
public static void Test()
|
||||
{
|
||||
CallVoidMethod("test", "()V");
|
||||
}
|
||||
|
||||
public static void FrameEnded(double time)
|
||||
{
|
||||
CallVoidMethod("frameEnded", "()V");
|
||||
}
|
||||
|
||||
public static void UpdateProgress(string info, float progress)
|
||||
{
|
||||
using var infoPtr = new TempNativeString(info);
|
||||
CallVoidMethod("updateProgress", "(JF)V", new JValue[]
|
||||
{
|
||||
JValue.Create(infoPtr.AsBytes()),
|
||||
JValue.Create(progress.AsBytes())
|
||||
});
|
||||
}
|
||||
|
||||
public static JLong GetSurfacePtr()
|
||||
{
|
||||
return CallLongMethod("getSurfacePtr", "()J");
|
||||
}
|
||||
|
||||
public static JLong GetWindowsHandle()
|
||||
{
|
||||
return CallLongMethod("getWindowHandle", "()J");
|
||||
}
|
||||
|
||||
public static void UpdateUiHandler(string newTitle,
|
||||
string newMessage,
|
||||
string newWatermark,
|
||||
int newType,
|
||||
int min,
|
||||
int max,
|
||||
KeyboardMode nMode,
|
||||
string newSubtitle,
|
||||
string newInitialText)
|
||||
{
|
||||
using var titlePointer = new TempNativeString(newTitle);
|
||||
using var messagePointer = new TempNativeString(newMessage);
|
||||
using var watermarkPointer = new TempNativeString(newWatermark);
|
||||
using var subtitlePointer = new TempNativeString(newSubtitle);
|
||||
using var newInitialPointer = new TempNativeString(newInitialText);
|
||||
CallVoidMethod("updateUiHandler", "(JJJIIIIJJ)V", new JValue[]
|
||||
{
|
||||
JValue.Create(titlePointer.AsBytes()),
|
||||
JValue.Create(messagePointer.AsBytes()),
|
||||
JValue.Create(watermarkPointer.AsBytes()),
|
||||
JValue.Create(newType.AsBytes()),
|
||||
JValue.Create(min.AsBytes()),
|
||||
JValue.Create(max.AsBytes()),
|
||||
JValue.Create(nMode.AsBytes()),
|
||||
JValue.Create(subtitlePointer.AsBytes()),
|
||||
JValue.Create(newInitialPointer.AsBytes())
|
||||
});
|
||||
}
|
||||
|
||||
private class TempNativeString : IDisposable
|
||||
{
|
||||
private JLong _jPointer;
|
||||
|
||||
public TempNativeString(string value)
|
||||
{
|
||||
Pointer = Marshal.StringToHGlobalAuto(value);
|
||||
JPointer = (JLong)Pointer;
|
||||
}
|
||||
|
||||
public nint Pointer { get; private set; }
|
||||
public JLong JPointer { get => _jPointer; private set => _jPointer = value; }
|
||||
|
||||
public Span<byte> AsBytes()
|
||||
{
|
||||
return _jPointer.AsBytes();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Pointer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(Pointer);
|
||||
}
|
||||
Pointer = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private class JniEnv : IDisposable
|
||||
{
|
||||
internal static JavaVMRef? _jvm;
|
||||
private readonly JEnvRef _env;
|
||||
private readonly bool _newAttach;
|
||||
|
||||
public JEnvRef Env => _env;
|
||||
|
||||
private JniEnv(JEnvRef env, bool newAttach)
|
||||
{
|
||||
_env = env;
|
||||
_newAttach = newAttach;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if(_newAttach)
|
||||
{
|
||||
JniHelper.Detach(_jvm!.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static JniEnv? Create()
|
||||
{
|
||||
bool newAttach = false;
|
||||
ReadOnlySpan<Byte> threadName = "JvmCall"u8;
|
||||
var env = _jvm == null ? default : JniHelper.Attach(_jvm.Value, threadName.GetUnsafeValPtr().GetUnsafeFixedContext(threadName.Length),
|
||||
out newAttach);
|
||||
|
||||
return env != null ? new JniEnv(env.Value, newAttach) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
357
src/LibRyujinx/Android/Jni/Delegates.cs
Normal file
357
src/LibRyujinx/Android/Jni/Delegates.cs
Normal file
@ -0,0 +1,357 @@
|
||||
using LibRyujinx.Jni.Identifiers;
|
||||
using LibRyujinx.Jni.Pointers;
|
||||
using LibRyujinx.Jni.Primitives;
|
||||
using LibRyujinx.Jni.References;
|
||||
using LibRyujinx.Jni.Values;
|
||||
using System;
|
||||
|
||||
using Rxmxnx.PInvoke;
|
||||
|
||||
namespace LibRyujinx.Jni;
|
||||
|
||||
internal delegate Int32 GetVersionDelegate(JEnvRef env);
|
||||
|
||||
internal delegate JResult RegisterNativesDelegate(JEnvRef env, JClassLocalRef jClass,
|
||||
ReadOnlyValPtr<JNativeMethod> methods0, Int32 nMethods);
|
||||
|
||||
internal delegate JResult UnregisterNativesDelegate(JEnvRef env, JClassLocalRef jClass);
|
||||
internal delegate JResult MonitorEnterDelegate(JEnvRef env, JObjectLocalRef jClass);
|
||||
internal delegate JResult MonitorExitDelegate(JEnvRef env, JObjectLocalRef jClass);
|
||||
internal delegate JResult GetVirtualMachineDelegate(JEnvRef env, out JavaVMRef jvm);
|
||||
internal delegate JResult DestroyVirtualMachineDelegate(JavaVMRef vm);
|
||||
internal delegate JResult AttachCurrentThreadDelegate(JavaVMRef vm, out JEnvRef env, in JavaVMAttachArgs args);
|
||||
internal delegate JResult DetachCurrentThreadDelegate(JavaVMRef vm);
|
||||
internal delegate JResult GetEnvDelegate(JavaVMRef vm, out JEnvRef env, Int32 version);
|
||||
internal delegate JResult AttachCurrentThreadAsDaemonDelegate(JavaVMRef vm, out JEnvRef env, in JavaVMAttachArgs args);
|
||||
|
||||
internal delegate JResult GetCreatedVirtualMachinesDelegate(ValPtr<JavaVMRef> buffer0, Int32 bufferLength,
|
||||
out Int32 totalVms);
|
||||
|
||||
internal delegate JStringLocalRef NewStringDelegate(JEnvRef env, ReadOnlyValPtr<Char> chars0, Int32 length);
|
||||
internal delegate Int32 GetStringLengthDelegate(JEnvRef env, JStringLocalRef jString);
|
||||
|
||||
internal delegate ReadOnlyValPtr<Char>
|
||||
GetStringCharsDelegate(JEnvRef env, JStringLocalRef jString, out JBoolean isCopy);
|
||||
|
||||
internal delegate void ReleaseStringCharsDelegate(JEnvRef env, JStringLocalRef jString, ReadOnlyValPtr<Char> chars0);
|
||||
internal delegate JStringLocalRef NewStringUtfDelegate(JEnvRef env, ReadOnlyValPtr<Byte> utf8Chars0);
|
||||
internal delegate Int32 GetStringUtfLengthDelegate(JEnvRef env, JStringLocalRef jString);
|
||||
|
||||
internal delegate ReadOnlyValPtr<Byte> GetStringUtfCharsDelegate(JEnvRef env, JStringLocalRef jString,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate void ReleaseStringUtfCharsDelegate(JEnvRef env, JStringLocalRef jString,
|
||||
ReadOnlyValPtr<Byte> utf8Chars0);
|
||||
|
||||
internal delegate void GetStringRegionDelegate(JEnvRef env, JStringLocalRef jString, Int32 startIndex, Int32 length,
|
||||
ValPtr<Char> buffer0);
|
||||
|
||||
internal delegate void GetStringUtfRegionDelegate(JEnvRef env, JStringLocalRef jString, Int32 startIndex, Int32 length,
|
||||
ValPtr<Byte> buffer0);
|
||||
|
||||
internal delegate ReadOnlyValPtr<Char> GetStringCriticalDelegate(JEnvRef env, JStringLocalRef jString,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate void ReleaseStringCriticalDelegate(JEnvRef env, JStringLocalRef jString, ReadOnlyValPtr<Char> chars0);
|
||||
|
||||
internal delegate JObjectLocalRef CallStaticObjectMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JBoolean CallStaticBooleanMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JByte CallStaticByteMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JChar CallStaticCharMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JShort CallStaticShortMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JInt CallStaticIntMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JLong CallStaticLongMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JFloat CallStaticFloatMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JDouble CallStaticDoubleMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate void CallStaticVoidMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JObjectLocalRef GetStaticObjectFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JBoolean GetStaticBooleanFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JByte GetStaticByteFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JChar GetStaticCharFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JShort GetStaticShortFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JInt GetStaticIntFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JLong GetStaticLongFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JFloat GetStaticFloatFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
internal delegate JDouble GetStaticDoubleFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
|
||||
|
||||
internal delegate void SetStaticObjectFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField,
|
||||
JObjectLocalRef value);
|
||||
|
||||
internal delegate void SetStaticBooleanFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField,
|
||||
JBoolean value);
|
||||
|
||||
internal delegate void SetStaticByteFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JByte value);
|
||||
internal delegate void SetStaticCharFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JChar value);
|
||||
internal delegate void SetStaticShortFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JShort value);
|
||||
internal delegate void SetStaticIntFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JInt value);
|
||||
internal delegate void SetStaticLongFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JLong value);
|
||||
internal delegate void SetStaticFloatFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JFloat value);
|
||||
internal delegate void SetStaticDoubleFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JDouble value);
|
||||
internal delegate JMethodId FromReflectedMethodDelegate(JEnvRef env, JObjectLocalRef method);
|
||||
internal delegate JFieldId FromReflectedFieldDelegate(JEnvRef env, JObjectLocalRef field);
|
||||
internal delegate JResult PushLocalFrameDelegate(JEnvRef env, Int32 capacity);
|
||||
internal delegate JObjectLocalRef PopLocalFrameDelegate(JEnvRef env, JObjectLocalRef result);
|
||||
internal delegate JGlobalRef NewGlobalRefDelegate(JEnvRef env, JObjectLocalRef localRef);
|
||||
internal delegate void DeleteGlobalRefDelegate(JEnvRef env, JGlobalRef globalRef);
|
||||
internal delegate void DeleteLocalRefDelegate(JEnvRef env, JObjectLocalRef localRef);
|
||||
internal delegate JBoolean IsSameObjectDelegate(JEnvRef env, JObjectLocalRef obj1, JObjectLocalRef obj2);
|
||||
internal delegate JObjectLocalRef NewLocalRefDelegate(JEnvRef env, JObjectLocalRef objRef);
|
||||
internal delegate JResult EnsureLocalCapacityDelegate(JEnvRef env, Int32 capacity);
|
||||
internal delegate JWeakRef NewWeakGlobalRefDelegate(JEnvRef env, JObjectLocalRef obj);
|
||||
internal delegate void DeleteWeakGlobalRefDelegate(JEnvRef env, JWeakRef jWeak);
|
||||
internal delegate JReferenceType GetObjectRefTypeDelegate(JEnvRef env, JObjectLocalRef obj);
|
||||
|
||||
internal delegate JObjectLocalRef CallNonVirtualObjectMethodADelegate(JEnvRef env, JObjectLocalRef obj,
|
||||
JClassLocalRef jClass, JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JBoolean CallNonVirtualBooleanMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JByte CallNonVirtualByteMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JChar CallNonVirtualCharMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JShort CallNonVirtualShortMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JInt CallNonVirtualIntMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JLong CallNonVirtualLongMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JFloat CallNonVirtualFloatMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JDouble CallNonVirtualDoubleMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate void CallNonVirtualVoidMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
|
||||
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JObjectLocalRef CallObjectMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JBoolean CallBooleanMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JByte CallByteMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JChar CallCharMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JShort CallShortMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JInt CallIntMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JLong CallLongMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JFloat CallFloatMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JDouble CallDoubleMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate void CallVoidMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> args0);
|
||||
|
||||
internal delegate JObjectLocalRef GetObjectFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JBoolean GetBooleanFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JByte GetByteFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JChar GetCharFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JShort GetShortFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JInt GetIntFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JLong GetLongFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JFloat GetFloatFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate JDouble GetDoubleFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
|
||||
internal delegate void SetObjectFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JObjectLocalRef value);
|
||||
internal delegate void SetBooleanFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JBoolean value);
|
||||
internal delegate void SetByteFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JByte value);
|
||||
internal delegate void SetCharFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JChar value);
|
||||
internal delegate void SetShortFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JShort value);
|
||||
internal delegate void SetIntFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JInt value);
|
||||
internal delegate void SetLongFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JLong value);
|
||||
internal delegate void SetFloatFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JFloat value);
|
||||
internal delegate void SetDoubleFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JDouble value);
|
||||
internal delegate JResult ThrowDelegate(JEnvRef env, JThrowableLocalRef obj);
|
||||
internal delegate JResult ThrowNewDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> messageChars0);
|
||||
internal delegate JThrowableLocalRef ExceptionOccurredDelegate(JEnvRef env);
|
||||
internal delegate void ExceptionDescribeDelegate(JEnvRef env);
|
||||
internal delegate void ExceptionClearDelegate(JEnvRef env);
|
||||
internal delegate void FatalErrorDelegate(JEnvRef env, ReadOnlyValPtr<Byte> messageChars0);
|
||||
internal delegate JBoolean ExceptionCheckDelegate(JEnvRef env);
|
||||
internal delegate JObjectLocalRef NewDirectByteBufferDelegate(JEnvRef env, IntPtr address, Int64 capacity);
|
||||
internal delegate IntPtr GetDirectBufferAddressDelegate(JEnvRef env, JObjectLocalRef buffObj);
|
||||
internal delegate Int64 GetDirectBufferCapacityDelegate(JEnvRef env, JObjectLocalRef buffObj);
|
||||
|
||||
internal delegate JClassLocalRef DefineClassDelegate(JEnvRef env, ReadOnlyValPtr<Byte> nameChars0,
|
||||
JObjectLocalRef loader, IntPtr binaryData, Int32 len);
|
||||
|
||||
internal delegate JClassLocalRef FindClassDelegate(JEnvRef env, ReadOnlyValPtr<Byte> nameChars0);
|
||||
|
||||
internal delegate JObjectLocalRef ToReflectedMethodDelegate(JEnvRef env, JClassLocalRef jClass, JMethodId methodId,
|
||||
JBoolean isStatic);
|
||||
|
||||
internal delegate JClassLocalRef GetSuperclassDelegate(JEnvRef env, JClassLocalRef sub);
|
||||
internal delegate JBoolean IsAssignableFromDelegate(JEnvRef env, JClassLocalRef sub, JClassLocalRef sup);
|
||||
internal delegate JClassLocalRef GetObjectClassDelegate(JEnvRef env, JObjectLocalRef obj);
|
||||
internal delegate JBoolean IsInstanceOfDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass);
|
||||
|
||||
internal delegate JObjectLocalRef ToReflectedFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId fieldId,
|
||||
JBoolean isStatic);
|
||||
|
||||
internal delegate JMethodId GetMethodIdDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> nameChars0,
|
||||
ReadOnlyValPtr<Byte> signatureChars0);
|
||||
|
||||
internal delegate JFieldId GetFieldIdDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> nameChars0,
|
||||
ReadOnlyValPtr<Byte> signatureChars0);
|
||||
|
||||
internal delegate JMethodId GetStaticMethodIdDelegate(JEnvRef env, JClassLocalRef jClass,
|
||||
ReadOnlyValPtr<Byte> nameChars0, ReadOnlyValPtr<Byte> signatureChars0);
|
||||
|
||||
internal delegate JFieldId GetStaticFieldIdDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> nameChars0,
|
||||
ReadOnlyValPtr<Byte> signatureChars0);
|
||||
|
||||
internal delegate Int32 GetArrayLengthDelegate(JEnvRef env, JArrayLocalRef array);
|
||||
|
||||
internal delegate JArrayLocalRef NewObjectArrayDelegate(JEnvRef env, Int32 length, JClassLocalRef jClass,
|
||||
JObjectLocalRef init);
|
||||
|
||||
internal delegate JObjectLocalRef GetObjectArrayElementDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 index);
|
||||
|
||||
internal delegate void SetObjectArrayElementDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 index,
|
||||
JObjectLocalRef obj);
|
||||
|
||||
internal delegate JArrayLocalRef NewBooleanArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewByteArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewCharArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewShortArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewIntArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewLongArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewFloatArrayDelegate(JEnvRef env, Int32 length);
|
||||
internal delegate JArrayLocalRef NewDoubleArrayDelegate(JEnvRef env, Int32 length);
|
||||
|
||||
internal delegate ValPtr<JBoolean> GetBooleanArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate ValPtr<JByte> GetByteArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
|
||||
internal delegate ValPtr<JChar> GetCharArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
|
||||
|
||||
internal delegate ValPtr<JShort> GetShortArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate ValPtr<JInt> GetIntArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
|
||||
internal delegate ValPtr<JLong> GetLongArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
|
||||
|
||||
internal delegate ValPtr<JFloat> GetFloatArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate ValPtr<JDouble> GetDoubleArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate void ReleaseBooleanArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JBoolean> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseByteArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JByte> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseCharArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JChar> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseShortArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JShort> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseIntArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JInt> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseLongArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JLong> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseFloatArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JFloat> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void ReleaseDoubleArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ReadOnlyValPtr<JDouble> elements0, JReleaseMode mode);
|
||||
|
||||
internal delegate void GetBooleanArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
|
||||
Int32 length, ValPtr<JBoolean> buffer0);
|
||||
|
||||
internal delegate void GetByteArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ValPtr<JByte> buffer0);
|
||||
|
||||
internal delegate void GetCharArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ValPtr<JChar> buffer0);
|
||||
|
||||
internal delegate void GetShortArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ValPtr<JShort> buffer0);
|
||||
|
||||
internal delegate void GetIntArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ValPtr<JInt> buffer0);
|
||||
|
||||
internal delegate void GetLongArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ValPtr<JLong> buffer0);
|
||||
|
||||
internal delegate void GetFloatArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ValPtr<JFloat> buffer0);
|
||||
|
||||
internal delegate void GetDoubleArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
|
||||
Int32 length, ValPtr<JDouble> buffer0);
|
||||
|
||||
internal delegate void SetBooleanArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
|
||||
Int32 length, ReadOnlyValPtr<JBoolean> buffer0);
|
||||
|
||||
internal delegate void SetByteArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ReadOnlyValPtr<JByte> buffer0);
|
||||
|
||||
internal delegate void SetCharArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ReadOnlyValPtr<JChar> buffer0);
|
||||
|
||||
internal delegate void SetShortArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ReadOnlyValPtr<JShort> buffer0);
|
||||
|
||||
internal delegate void SetIntArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ReadOnlyValPtr<JInt> buffer0);
|
||||
|
||||
internal delegate void SetLongArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ReadOnlyValPtr<JLong> buffer0);
|
||||
|
||||
internal delegate void SetFloatArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
|
||||
ReadOnlyValPtr<JFloat> buffer0);
|
||||
|
||||
internal delegate void SetDoubleArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
|
||||
Int32 length, ReadOnlyValPtr<JDouble> buffer0);
|
||||
|
||||
internal delegate ValPtr<Byte> GetPrimitiveArrayCriticalDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
out JBoolean isCopy);
|
||||
|
||||
internal delegate void ReleasePrimitiveArrayCriticalDelegate(JEnvRef env, JArrayLocalRef arrayRef,
|
||||
ValPtr<Byte> elements, JReleaseMode mode);
|
||||
|
||||
internal delegate JObjectLocalRef NewObjectADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
|
||||
ReadOnlyValPtr<JValue> arg0);
|
28
src/LibRyujinx/Android/Jni/Identifiers/JFieldId.cs
Normal file
28
src/LibRyujinx/Android/Jni/Identifiers/JFieldId.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.Identifiers
|
||||
{
|
||||
public readonly struct JFieldId : IEquatable<JFieldId>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JFieldId other)
|
||||
=> this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj)
|
||||
=> obj is JFieldId other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JFieldId a, JFieldId b) => a.Equals(b);
|
||||
public static Boolean operator !=(JFieldId a, JFieldId b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
||||
}
|
28
src/LibRyujinx/Android/Jni/Identifiers/JMethodId.cs
Normal file
28
src/LibRyujinx/Android/Jni/Identifiers/JMethodId.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.Identifiers
|
||||
{
|
||||
public readonly struct JMethodId : IEquatable<JMethodId>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JMethodId other)
|
||||
=> this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj)
|
||||
=> obj is JMethodId other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JMethodId a, JMethodId b) => a.Equals(b);
|
||||
public static Boolean operator !=(JMethodId a, JMethodId b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
||||
}
|
12
src/LibRyujinx/Android/Jni/JReferenceType.cs
Normal file
12
src/LibRyujinx/Android/Jni/JReferenceType.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni
|
||||
{
|
||||
public enum JReferenceType : Int32
|
||||
{
|
||||
InvalidRefType = 0,
|
||||
LocalRefType = 1,
|
||||
GlobalRefType = 2,
|
||||
WeakGlobalRefType = 3
|
||||
}
|
||||
}
|
11
src/LibRyujinx/Android/Jni/JReleaseMode.cs
Normal file
11
src/LibRyujinx/Android/Jni/JReleaseMode.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni
|
||||
{
|
||||
public enum JReleaseMode : Int32
|
||||
{
|
||||
Free = 0,
|
||||
Commit = 1,
|
||||
Abort = 2,
|
||||
}
|
||||
}
|
15
src/LibRyujinx/Android/Jni/JResult.cs
Normal file
15
src/LibRyujinx/Android/Jni/JResult.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni
|
||||
{
|
||||
public enum JResult : Int32
|
||||
{
|
||||
Ok = 0,
|
||||
Error = -1,
|
||||
DetachedThreadError = -2,
|
||||
VersionError = -3,
|
||||
MemoryError = -4,
|
||||
ExitingVMError = -5,
|
||||
InvalidArgumentsError = -6,
|
||||
}
|
||||
}
|
251
src/LibRyujinx/Android/Jni/JniHelper.cs
Normal file
251
src/LibRyujinx/Android/Jni/JniHelper.cs
Normal file
@ -0,0 +1,251 @@
|
||||
using LibRyujinx.Jni.Identifiers;
|
||||
using LibRyujinx.Jni.Pointers;
|
||||
using LibRyujinx.Jni.Primitives;
|
||||
using LibRyujinx.Jni.References;
|
||||
using LibRyujinx.Jni.Values;
|
||||
using System;
|
||||
|
||||
using Rxmxnx.PInvoke;
|
||||
|
||||
namespace LibRyujinx.Jni
|
||||
{
|
||||
internal static class JniHelper
|
||||
{
|
||||
public const Int32 JniVersion = 0x00010006; //JNI_VERSION_1_6;
|
||||
|
||||
public static JEnvRef? Attach(JavaVMRef javaVm, IReadOnlyFixedMemory<Byte> threadName, out Boolean newAttach)
|
||||
{
|
||||
ref JavaVMValue value = ref javaVm.VirtualMachine;
|
||||
ref JInvokeInterface jInvoke = ref value.Functions;
|
||||
|
||||
IntPtr getEnvPtr = jInvoke.GetEnvPointer;
|
||||
GetEnvDelegate getEnv = getEnvPtr.GetUnsafeDelegate<GetEnvDelegate>()!;
|
||||
|
||||
if (getEnv(javaVm, out JEnvRef jEnv, JniHelper.JniVersion) == JResult.Ok)
|
||||
{
|
||||
newAttach = false;
|
||||
return jEnv;
|
||||
}
|
||||
|
||||
JavaVMAttachArgs args = new() { Version = JniHelper.JniVersion, Name = threadName.ValuePointer, };
|
||||
IntPtr attachCurrentThreadPtr = jInvoke.AttachCurrentThreadPointer;
|
||||
AttachCurrentThreadDelegate attachCurrentThread =
|
||||
attachCurrentThreadPtr.GetUnsafeDelegate<AttachCurrentThreadDelegate>()!;
|
||||
|
||||
newAttach = true;
|
||||
return attachCurrentThread(javaVm, out jEnv, in args) == JResult.Ok ? jEnv : null;
|
||||
}
|
||||
public static JEnvRef? AttachDaemon(JavaVMRef javaVm, IReadOnlyFixedMemory<Byte> daemonName)
|
||||
{
|
||||
ref JavaVMValue value = ref javaVm.VirtualMachine;
|
||||
ref JInvokeInterface jInvoke = ref value.Functions;
|
||||
|
||||
JavaVMAttachArgs args = new() { Version = JniHelper.JniVersion, Name = daemonName.ValuePointer, };
|
||||
IntPtr attachCurrentThreadAsDaemonPtr = jInvoke.AttachCurrentThreadAsDaemonPointer;
|
||||
AttachCurrentThreadAsDaemonDelegate attachCurrentThreadAsDaemon =
|
||||
attachCurrentThreadAsDaemonPtr.GetUnsafeDelegate<AttachCurrentThreadAsDaemonDelegate>()!;
|
||||
|
||||
return attachCurrentThreadAsDaemon(javaVm, out JEnvRef jEnv, in args) == JResult.Ok ? jEnv : null;
|
||||
}
|
||||
public static void Detach(JavaVMRef javaVm)
|
||||
{
|
||||
ref JavaVMValue value = ref javaVm.VirtualMachine;
|
||||
ref JInvokeInterface jInvoke = ref value.Functions;
|
||||
|
||||
IntPtr detachCurrentThreadPtr = jInvoke.DetachCurrentThreadPointer;
|
||||
DetachCurrentThreadDelegate detachCurrentThread =
|
||||
detachCurrentThreadPtr.GetUnsafeDelegate<DetachCurrentThreadDelegate>()!;
|
||||
|
||||
detachCurrentThread(javaVm);
|
||||
}
|
||||
public static JGlobalRef? GetGlobalClass(JEnvRef jEnv, IReadOnlyFixedMemory<Byte> className)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr findClassPtr = jInterface.FindClassPointer;
|
||||
FindClassDelegate findClass = findClassPtr.GetUnsafeDelegate<FindClassDelegate>()!;
|
||||
JClassLocalRef jClass = findClass(jEnv, className.ValuePointer);
|
||||
|
||||
if (JniHelper.ExceptionCheck(jEnv))
|
||||
return default;
|
||||
|
||||
IntPtr newGlobalRefPtr = jInterface.NewGlobalRefPointer;
|
||||
NewGlobalRefDelegate newGlobalRef = newGlobalRefPtr.GetUnsafeDelegate<NewGlobalRefDelegate>()!;
|
||||
|
||||
JGlobalRef jGlobal = newGlobalRef(jEnv, (JObjectLocalRef)jClass);
|
||||
JniHelper.RemoveLocal(jEnv, (JObjectLocalRef)jClass);
|
||||
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? jGlobal : null;
|
||||
}
|
||||
public static void RemoveLocal(JEnvRef jEnv, JObjectLocalRef jObject)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr deleteLocalRefPtr = jInterface.DeleteLocalRefPointer;
|
||||
DeleteLocalRefDelegate deleteLocalRef = deleteLocalRefPtr.GetUnsafeDelegate<DeleteLocalRefDelegate>()!;
|
||||
|
||||
deleteLocalRef(jEnv, jObject);
|
||||
}
|
||||
public static void RemoveGlobal(JEnvRef jEnv, JGlobalRef jObject)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr deleteGlobalRefPtr = jInterface.DeleteGlobalRefPointer;
|
||||
DeleteGlobalRefDelegate deleteGlobalRef = deleteGlobalRefPtr.GetUnsafeDelegate<DeleteGlobalRefDelegate>()!;
|
||||
|
||||
deleteGlobalRef(jEnv, jObject);
|
||||
}
|
||||
public static void RemoveWeakGlobal(JEnvRef jEnv, JWeakRef jObject)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr deleteWeakGlobalRefPtr = jInterface.DeleteWeakGlobalRefPointer;
|
||||
DeleteWeakGlobalRefDelegate deleteWeakGlobalRef =
|
||||
deleteWeakGlobalRefPtr.GetUnsafeDelegate<DeleteWeakGlobalRefDelegate>()!;
|
||||
|
||||
deleteWeakGlobalRef(jEnv, jObject);
|
||||
}
|
||||
public static JStringLocalRef? CreateString(JEnvRef jEnv, String textValue)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr newStringPtr = jInterface.NewStringPointer;
|
||||
NewStringDelegate newString = newStringPtr.GetUnsafeDelegate<NewStringDelegate>()!;
|
||||
using IReadOnlyFixedMemory<Char>.IDisposable ctx = textValue.AsMemory().GetFixedContext();
|
||||
JStringLocalRef jString = newString(jEnv, ctx.ValuePointer, ctx.Values.Length);
|
||||
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? jString : null;
|
||||
}
|
||||
public static JWeakRef? CreateWeakGlobal(JEnvRef jEnv, JObjectLocalRef jObject)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr newWeakGlobalRefPtr = jInterface.NewWeakGlobalRefPointer;
|
||||
NewWeakGlobalRefDelegate newWeakGlobalRef = newWeakGlobalRefPtr.GetUnsafeDelegate<NewWeakGlobalRefDelegate>()!;
|
||||
JWeakRef jWeak = newWeakGlobalRef(jEnv, jObject);
|
||||
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? jWeak : null;
|
||||
}
|
||||
private static Boolean ExceptionCheck(JEnvRef jEnv)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr exceptionCheckPtr = jInterface.ExceptionCheckPointer;
|
||||
ExceptionCheckDelegate exceptionCheck = exceptionCheckPtr.GetUnsafeDelegate<ExceptionCheckDelegate>()!;
|
||||
|
||||
if (!exceptionCheck(jEnv))
|
||||
return false;
|
||||
IntPtr exceptionDescribePtr = jInterface.ExceptionDescribePointer;
|
||||
IntPtr exceptionClearPtr = jInterface.ExceptionClearPointer;
|
||||
|
||||
ExceptionDescribeDelegate exceptionDescribe =
|
||||
exceptionDescribePtr.GetUnsafeDelegate<ExceptionDescribeDelegate>()!;
|
||||
ExceptionClearDelegate exceptionClear = exceptionClearPtr.GetUnsafeDelegate<ExceptionClearDelegate>()!;
|
||||
|
||||
exceptionDescribe(jEnv);
|
||||
exceptionClear(jEnv);
|
||||
return true;
|
||||
}
|
||||
public static JavaVMRef? GetVirtualMachine(JEnvRef jEnv)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr getJavaVmPtr = jInterface.GetJavaVMPointer;
|
||||
GetVirtualMachineDelegate getJavaVm = getJavaVmPtr.GetUnsafeDelegate<GetVirtualMachineDelegate>()!;
|
||||
return getJavaVm(jEnv, out JavaVMRef javaVm) == JResult.Ok ? javaVm : null;
|
||||
}
|
||||
public static Boolean? IsValidGlobalWeak(JEnvRef jEnv, JWeakRef jWeak)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr isSameObjectPtr = jInterface.IsSameObjectPointer;
|
||||
IsSameObjectDelegate isSameObject = isSameObjectPtr.GetUnsafeDelegate<IsSameObjectDelegate>()!;
|
||||
JBoolean result = isSameObject(jEnv, (JObjectLocalRef)jWeak, default);
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? !result : null;
|
||||
}
|
||||
public static JMethodId? GetMethodId(JEnvRef jEnv, JClassLocalRef jClass, IReadOnlyFixedMemory<Byte> methodName,
|
||||
IReadOnlyFixedMemory<Byte> descriptor)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr getMethodIdPtr = jInterface.GetMethodIdPointer;
|
||||
GetMethodIdDelegate getMethodId = getMethodIdPtr.GetUnsafeDelegate<GetMethodIdDelegate>()!;
|
||||
JMethodId methodId = getMethodId(jEnv, jClass, methodName.ValuePointer, descriptor.ValuePointer);
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? methodId : null;
|
||||
}
|
||||
public static JMethodId? GetStaticMethodId(JEnvRef jEnv, JClassLocalRef jClass,
|
||||
IReadOnlyFixedMemory<Byte> methodName, IReadOnlyFixedMemory<Byte> descriptor)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr getStaticMethodIdPtr = jInterface.GetStaticMethodIdPointer;
|
||||
GetStaticMethodIdDelegate getStaticMethodId =
|
||||
getStaticMethodIdPtr.GetUnsafeDelegate<GetStaticMethodIdDelegate>()!;
|
||||
JMethodId jMethodId = getStaticMethodId(jEnv, jClass, methodName.ValuePointer, descriptor.ValuePointer);
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? jMethodId : null;
|
||||
}
|
||||
public static void CallStaticVoidMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
|
||||
params JValue[] args)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr callStaticVoidMethodPtr = jInterface.CallStaticVoidMethodAPointer;
|
||||
CallStaticVoidMethodADelegate callStaticVoidMethod =
|
||||
callStaticVoidMethodPtr.GetUnsafeDelegate<CallStaticVoidMethodADelegate>()!;
|
||||
|
||||
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
|
||||
callStaticVoidMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
|
||||
}
|
||||
public static JObjectLocalRef? CallStaticObjectMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
|
||||
params JValue[] args)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr callStaticObjectMethodPtr = jInterface.CallStaticObjectMethodAPointer;
|
||||
CallStaticObjectMethodADelegate callStaticObjectMethod =
|
||||
callStaticObjectMethodPtr.GetUnsafeDelegate<CallStaticObjectMethodADelegate>()!;
|
||||
|
||||
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
|
||||
JObjectLocalRef jObject = callStaticObjectMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? jObject : null;
|
||||
}
|
||||
public static JLong? CallStaticLongMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
|
||||
params JValue[] args)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr callStaticLongMethodPtr = jInterface.CallStaticLongMethodAPointer;
|
||||
CallStaticLongMethodADelegate callStaticLongMethod =
|
||||
callStaticLongMethodPtr.GetUnsafeDelegate<CallStaticLongMethodADelegate>()!;
|
||||
|
||||
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
|
||||
JLong jLong = callStaticLongMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
|
||||
return !JniHelper.ExceptionCheck(jEnv) ? jLong : null;
|
||||
}
|
||||
public static void CallVoidMethod(JEnvRef jEnv, JObjectLocalRef jObject, JMethodId jMethodId, params JValue[] args)
|
||||
{
|
||||
ref readonly JEnvValue value = ref jEnv.Environment;
|
||||
ref JNativeInterface jInterface = ref value.Functions;
|
||||
|
||||
IntPtr callVoidMethodPtr = jInterface.CallVoidMethodAPointer;
|
||||
CallVoidMethodADelegate callVoidMethod = callVoidMethodPtr.GetUnsafeDelegate<CallVoidMethodADelegate>()!;
|
||||
|
||||
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
|
||||
callVoidMethod(jEnv, jObject, jMethodId, fArgs.ValuePointer);
|
||||
}
|
||||
}
|
||||
}
|
37
src/LibRyujinx/Android/Jni/Pointers/JEnvRef.cs
Normal file
37
src/LibRyujinx/Android/Jni/Pointers/JEnvRef.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using LibRyujinx.Jni.Values;
|
||||
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Pointers
|
||||
{
|
||||
public readonly struct JEnvRef : IEquatable<JEnvRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
public JEnvRef(IntPtr val)
|
||||
{
|
||||
_value = val;
|
||||
}
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JEnvRef a, JEnvRef b) => a._value.Equals(b._value);
|
||||
public static Boolean operator !=(JEnvRef a, JEnvRef b) => !a._value.Equals(b._value);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
internal readonly ref JEnvValue Environment => ref this._value.GetUnsafeReference<JEnvValue>();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JEnvRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override Boolean Equals(Object obj) => obj is JEnvRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
31
src/LibRyujinx/Android/Jni/Pointers/JavaVMRef.cs
Normal file
31
src/LibRyujinx/Android/Jni/Pointers/JavaVMRef.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using LibRyujinx.Jni.Values;
|
||||
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Pointers;
|
||||
|
||||
public readonly struct JavaVMRef : IEquatable<JavaVMRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JavaVMRef a, JavaVMRef b) => a._value.Equals(b._value);
|
||||
public static Boolean operator !=(JavaVMRef a, JavaVMRef b) => !a._value.Equals(b._value);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
internal readonly ref JavaVMValue VirtualMachine => ref this._value.GetUnsafeReference<JavaVMValue>();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JavaVMRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override Boolean Equals(Object obj) => obj is JavaVMRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
67
src/LibRyujinx/Android/Jni/Primitives/JBoolean.cs
Normal file
67
src/LibRyujinx/Android/Jni/Primitives/JBoolean.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives;
|
||||
|
||||
public readonly struct JBoolean : IComparable<Boolean>, IEquatable<Boolean>
|
||||
{
|
||||
internal static readonly Type Type = typeof(JBoolean);
|
||||
private const Byte trueByte = 1;
|
||||
private const Byte falseByte = 0;
|
||||
|
||||
public static readonly CString Signature = (CString)"Z";
|
||||
|
||||
private readonly Byte _value;
|
||||
private Boolean Value => this._value == JBoolean.trueByte;
|
||||
|
||||
private JBoolean(Boolean value) => this._value = value ? JBoolean.trueByte : JBoolean.falseByte;
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JBoolean(Boolean value) => new(value);
|
||||
public static implicit operator Boolean(JBoolean jValue) => jValue._value == 1;
|
||||
public static JBoolean operator !(JBoolean a) => new(!a.Value);
|
||||
public static JBoolean operator |(JBoolean a, JBoolean b) => new(a.Value || b.Value);
|
||||
public static JBoolean operator |(Boolean a, JBoolean b) => new(a || b.Value);
|
||||
public static JBoolean operator |(JBoolean a, Boolean b) => new(a.Value || b);
|
||||
public static JBoolean operator &(JBoolean a, JBoolean b) => new(a.Value && b.Value);
|
||||
public static JBoolean operator &(Boolean a, JBoolean b) => new(a && b.Value);
|
||||
public static JBoolean operator &(JBoolean a, Boolean b) => new(a.Value && b);
|
||||
public static Boolean operator ==(JBoolean a, JBoolean b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Boolean a, JBoolean b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JBoolean a, Boolean b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JBoolean a, JBoolean b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Boolean a, JBoolean b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JBoolean a, Boolean b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Boolean a, JBoolean b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JBoolean a, Boolean b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Boolean a, JBoolean b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JBoolean a, Boolean b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Boolean a, JBoolean b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JBoolean a, Boolean b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Boolean a, JBoolean b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JBoolean a, Boolean b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Boolean other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JBoolean other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj)
|
||||
=> obj is JBoolean jvalue ? this.CompareTo(jvalue) :
|
||||
obj is Boolean value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Boolean other) => this._value.Equals(other);
|
||||
public Boolean Equals(JBoolean other) => this._value.Equals(other._value);
|
||||
public String ToString(IFormatProvider formatProvider) => this._value.ToString(formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj)
|
||||
=> obj is JBoolean jvalue ? this.Equals(jvalue) :
|
||||
obj is Boolean value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
74
src/LibRyujinx/Android/Jni/Primitives/JByte.cs
Normal file
74
src/LibRyujinx/Android/Jni/Primitives/JByte.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JByte : IComparable<SByte>, IEquatable<SByte>, IFormattable
|
||||
{
|
||||
internal static readonly Type Type = typeof(JByte);
|
||||
|
||||
public static readonly CString Signature = (CString)"B";
|
||||
|
||||
private readonly SByte _value;
|
||||
|
||||
private JByte(SByte value) => this._value = value;
|
||||
private JByte(Int32 value) => this._value = Convert.ToSByte(value);
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JByte(SByte value) => new(value);
|
||||
public static implicit operator SByte(JByte jValue) => jValue._value;
|
||||
public static JByte operator +(JByte a) => a;
|
||||
public static JByte operator ++(JByte a) => new(a._value + 1);
|
||||
public static JByte operator -(JByte a) => new(-a._value);
|
||||
public static JByte operator --(JByte a) => new(a._value - 1);
|
||||
public static JByte operator +(JByte a, JByte b) => new(a._value + b._value);
|
||||
public static JByte operator +(SByte a, JByte b) => new(a + b._value);
|
||||
public static JByte operator +(JByte a, SByte b) => new(a._value + b);
|
||||
public static JByte operator -(JByte a, JByte b) => new(a._value - b._value);
|
||||
public static JByte operator -(SByte a, JByte b) => new(a - b._value);
|
||||
public static JByte operator -(JByte a, SByte b) => new(a._value - b);
|
||||
public static JByte operator *(JByte a, JByte b) => new(a._value * b._value);
|
||||
public static JByte operator *(SByte a, JByte b) => new(a * b._value);
|
||||
public static JByte operator *(JByte a, SByte b) => new(a._value * b);
|
||||
public static JByte operator /(JByte a, JByte b) => new(a._value / b._value);
|
||||
public static JByte operator /(SByte a, JByte b) => new(a / b._value);
|
||||
public static JByte operator /(JByte a, SByte b) => new(a._value / b);
|
||||
public static JByte operator %(JByte a, JByte b) => new(a._value % b._value);
|
||||
public static JByte operator %(SByte a, JByte b) => new(a % b._value);
|
||||
public static JByte operator %(JByte a, SByte b) => new(a._value % b);
|
||||
public static Boolean operator ==(JByte a, JByte b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(SByte a, JByte b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JByte a, SByte b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JByte a, JByte b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(SByte a, JByte b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JByte a, SByte b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JByte a, JByte b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(SByte a, JByte b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JByte a, SByte b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JByte a, JByte b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(SByte a, JByte b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JByte a, SByte b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JByte a, JByte b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(SByte a, JByte b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JByte a, SByte b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JByte a, JByte b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(SByte a, JByte b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JByte a, SByte b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(SByte other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JByte other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JByte jValue ? this.CompareTo(jValue) : obj is SByte value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(SByte other) => this._value.Equals(other);
|
||||
public Boolean Equals(JByte other) => this._value.Equals(other._value);
|
||||
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JByte jvalue ? this.Equals(jvalue) : obj is SByte value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
56
src/LibRyujinx/Android/Jni/Primitives/JChar.cs
Normal file
56
src/LibRyujinx/Android/Jni/Primitives/JChar.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JChar : IComparable<Char>, IEquatable<Char>
|
||||
{
|
||||
internal static readonly Type Type = typeof(JChar);
|
||||
|
||||
public static readonly CString Signature = (CString)"C";
|
||||
|
||||
private readonly Char _value;
|
||||
|
||||
private JChar(Char value) => this._value = value;
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JChar(Char value) => new(value);
|
||||
public static explicit operator JChar(Int16 value) => new((Char)value);
|
||||
public static implicit operator Char(JChar jValue) => jValue._value;
|
||||
public static explicit operator Int16(JChar jValue) => (Int16)jValue._value;
|
||||
public static Boolean operator ==(JChar a, JChar b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Char a, JChar b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JChar a, Char b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JChar a, JChar b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Char a, JChar b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JChar a, Char b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JChar a, JChar b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Char a, JChar b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JChar a, Char b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JChar a, JChar b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Char a, JChar b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JChar a, Char b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JChar a, JChar b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Char a, JChar b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JChar a, Char b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JChar a, JChar b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Char a, JChar b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JChar a, Char b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Char other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JChar other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JChar jvalue ? this.CompareTo(jvalue) : obj is Char value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Char other) => this._value.Equals(other);
|
||||
public Boolean Equals(JChar other) => this._value.Equals(other._value);
|
||||
public String ToString(IFormatProvider formatProvider) => this._value.ToString(formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JChar jvalue ? this.Equals(jvalue) : obj is Char value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
70
src/LibRyujinx/Android/Jni/Primitives/JDouble.cs
Normal file
70
src/LibRyujinx/Android/Jni/Primitives/JDouble.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JDouble : IComparable<Double>, IEquatable<Double>, IFormattable
|
||||
{
|
||||
internal static readonly Type Type = typeof(JDouble);
|
||||
|
||||
public static readonly CString Signature = (CString)"D";
|
||||
|
||||
private readonly Double _value;
|
||||
|
||||
private JDouble(Double value) => this._value = value;
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JDouble(Double value) => new(value);
|
||||
public static implicit operator Double(JDouble jValue) => jValue._value;
|
||||
public static JDouble operator +(JDouble a) => a;
|
||||
public static JDouble operator ++(JDouble a) => new(a._value + 1);
|
||||
public static JDouble operator -(JDouble a) => new(-a._value);
|
||||
public static JDouble operator --(JDouble a) => new(a._value - 1);
|
||||
public static JDouble operator +(JDouble a, JDouble b) => new(a._value + b._value);
|
||||
public static JDouble operator +(Double a, JDouble b) => new(a + b._value);
|
||||
public static JDouble operator +(JDouble a, Double b) => new(a._value + b);
|
||||
public static JDouble operator -(JDouble a, JDouble b) => new(a._value - b._value);
|
||||
public static JDouble operator -(Double a, JDouble b) => new(a - b._value);
|
||||
public static JDouble operator -(JDouble a, Double b) => new(a._value - b);
|
||||
public static JDouble operator *(JDouble a, JDouble b) => new(a._value * b._value);
|
||||
public static JDouble operator *(Double a, JDouble b) => new(a * b._value);
|
||||
public static JDouble operator *(JDouble a, Double b) => new(a._value * b);
|
||||
public static JDouble operator /(JDouble a, JDouble b) => new(a._value / b._value);
|
||||
public static JDouble operator /(Double a, JDouble b) => new(a / b._value);
|
||||
public static JDouble operator /(JDouble a, Double b) => new(a._value / b);
|
||||
public static Boolean operator ==(JDouble a, JDouble b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Double a, JDouble b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JDouble a, Double b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JDouble a, JDouble b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Double a, JDouble b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JDouble a, Double b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JDouble a, JDouble b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Double a, JDouble b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JDouble a, Double b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JDouble a, JDouble b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Double a, JDouble b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JDouble a, Double b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JDouble a, JDouble b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Double a, JDouble b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JDouble a, Double b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JDouble a, JDouble b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Double a, JDouble b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JDouble a, Double b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Double other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JDouble other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JDouble jvalue ? this.CompareTo(jvalue) : obj is Double value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Double other) => this._value.Equals(other);
|
||||
public Boolean Equals(JDouble other) => this._value.Equals(other._value);
|
||||
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JDouble jvalue ? this.Equals(jvalue) : obj is Double value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
70
src/LibRyujinx/Android/Jni/Primitives/JFloat.cs
Normal file
70
src/LibRyujinx/Android/Jni/Primitives/JFloat.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JFloat : IComparable<Single>, IEquatable<Single>, IFormattable
|
||||
{
|
||||
internal static readonly Type Type = typeof(JFloat);
|
||||
|
||||
public static readonly CString Signature = (CString)"F";
|
||||
|
||||
private readonly Single _value;
|
||||
|
||||
private JFloat(Single value) => this._value = value;
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JFloat(Single value) => new(value);
|
||||
public static implicit operator Single(JFloat jValue) => jValue._value;
|
||||
public static JFloat operator +(JFloat a) => a;
|
||||
public static JFloat operator ++(JFloat a) => new(a._value + 1);
|
||||
public static JFloat operator -(JFloat a) => new(-a._value);
|
||||
public static JFloat operator --(JFloat a) => new(a._value - 1);
|
||||
public static JFloat operator +(JFloat a, JFloat b) => new(a._value + b._value);
|
||||
public static JFloat operator +(Single a, JFloat b) => new(a + b._value);
|
||||
public static JFloat operator +(JFloat a, Single b) => new(a._value + b);
|
||||
public static JFloat operator -(JFloat a, JFloat b) => new(a._value - b._value);
|
||||
public static JFloat operator -(Single a, JFloat b) => new(a - b._value);
|
||||
public static JFloat operator -(JFloat a, Single b) => new(a._value - b);
|
||||
public static JFloat operator *(JFloat a, JFloat b) => new(a._value * b._value);
|
||||
public static JFloat operator *(Single a, JFloat b) => new(a * b._value);
|
||||
public static JFloat operator *(JFloat a, Single b) => new(a._value * b);
|
||||
public static JFloat operator /(JFloat a, JFloat b) => new(a._value / b._value);
|
||||
public static JFloat operator /(Single a, JFloat b) => new(a / b._value);
|
||||
public static JFloat operator /(JFloat a, Single b) => new(a._value / b);
|
||||
public static Boolean operator ==(JFloat a, JFloat b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Single a, JFloat b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JFloat a, Single b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JFloat a, JFloat b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Single a, JFloat b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JFloat a, Single b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JFloat a, JFloat b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Single a, JFloat b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JFloat a, Single b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JFloat a, JFloat b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Single a, JFloat b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JFloat a, Single b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JFloat a, JFloat b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Single a, JFloat b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JFloat a, Single b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JFloat a, JFloat b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Single a, JFloat b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JFloat a, Single b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Single other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JFloat other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JFloat jvalue ? this.CompareTo(jvalue) : obj is Single value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Single other) => this._value.Equals(other);
|
||||
public Boolean Equals(JFloat other) => this._value.Equals(other._value);
|
||||
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JFloat jvalue ? this.Equals(jvalue) : obj is Single value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
73
src/LibRyujinx/Android/Jni/Primitives/JInt.cs
Normal file
73
src/LibRyujinx/Android/Jni/Primitives/JInt.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JInt : IComparable<Int32>, IEquatable<Int32>, IFormattable
|
||||
{
|
||||
internal static readonly Type Type = typeof(JInt);
|
||||
|
||||
public static readonly CString Signature = (CString)"I";
|
||||
|
||||
private readonly Int32 _value;
|
||||
|
||||
private JInt(Int32 value) => this._value = value;
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JInt(Int32 value) => new(value);
|
||||
public static implicit operator Int32(JInt jValue) => jValue._value;
|
||||
public static JInt operator +(JInt a) => a;
|
||||
public static JInt operator ++(JInt a) => new(a._value + 1);
|
||||
public static JInt operator -(JInt a) => new(-a._value);
|
||||
public static JInt operator --(JInt a) => new(a._value - 1);
|
||||
public static JInt operator +(JInt a, JInt b) => new(a._value + b._value);
|
||||
public static JInt operator +(Int32 a, JInt b) => new(a + b._value);
|
||||
public static JInt operator +(JInt a, Int32 b) => new(a._value + b);
|
||||
public static JInt operator -(JInt a, JInt b) => new(a._value - b._value);
|
||||
public static JInt operator -(Int32 a, JInt b) => new(a - b._value);
|
||||
public static JInt operator -(JInt a, Int32 b) => new(a._value - b);
|
||||
public static JInt operator *(JInt a, JInt b) => new(a._value * b._value);
|
||||
public static JInt operator *(Int32 a, JInt b) => new(a * b._value);
|
||||
public static JInt operator *(JInt a, Int32 b) => new(a._value * b);
|
||||
public static JInt operator /(JInt a, JInt b) => new(a._value / b._value);
|
||||
public static JInt operator /(Int32 a, JInt b) => new(a / b._value);
|
||||
public static JInt operator /(JInt a, Int32 b) => new(a._value / b);
|
||||
public static JInt operator %(JInt a, JInt b) => new(a._value % b._value);
|
||||
public static JInt operator %(Int32 a, JInt b) => new(a % b._value);
|
||||
public static JInt operator %(JInt a, Int32 b) => new(a._value % b);
|
||||
public static Boolean operator ==(JInt a, JInt b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Int32 a, JInt b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JInt a, Int32 b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JInt a, JInt b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Int32 a, JInt b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JInt a, Int32 b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JInt a, JInt b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Int32 a, JInt b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JInt a, Int32 b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JInt a, JInt b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Int32 a, JInt b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JInt a, Int32 b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JInt a, JInt b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Int32 a, JInt b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JInt a, Int32 b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JInt a, JInt b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Int32 a, JInt b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JInt a, Int32 b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Int32 other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JInt other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JInt jValue ? this.CompareTo(jValue) : obj is Int32 value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Int32 other) => this._value.Equals(other);
|
||||
public Boolean Equals(JInt other) => this._value.Equals(other._value);
|
||||
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JInt jvalue ? this.Equals(jvalue) : obj is Int32 value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
73
src/LibRyujinx/Android/Jni/Primitives/JLong.cs
Normal file
73
src/LibRyujinx/Android/Jni/Primitives/JLong.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JLong : IComparable<Int64>, IEquatable<Int64>, IFormattable
|
||||
{
|
||||
internal static readonly Type Type = typeof(JLong);
|
||||
|
||||
public static readonly CString Signature = (CString)"J";
|
||||
|
||||
private readonly Int64 _value;
|
||||
|
||||
private JLong(Int64 value) => this._value = value;
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JLong(Int64 value) => new(value);
|
||||
public static implicit operator Int64(JLong jValue) => jValue._value;
|
||||
public static JLong operator +(JLong a) => a;
|
||||
public static JLong operator ++(JLong a) => new(a._value + 1);
|
||||
public static JLong operator -(JLong a) => new(-a._value);
|
||||
public static JLong operator --(JLong a) => new(a._value - 1);
|
||||
public static JLong operator +(JLong a, JLong b) => new(a._value + b._value);
|
||||
public static JLong operator +(Int64 a, JLong b) => new(a + b._value);
|
||||
public static JLong operator +(JLong a, Int64 b) => new(a._value + b);
|
||||
public static JLong operator -(JLong a, JLong b) => new(a._value - b._value);
|
||||
public static JLong operator -(Int64 a, JLong b) => new(a - b._value);
|
||||
public static JLong operator -(JLong a, Int64 b) => new(a._value - b);
|
||||
public static JLong operator *(JLong a, JLong b) => new(a._value * b._value);
|
||||
public static JLong operator *(Int64 a, JLong b) => new(a * b._value);
|
||||
public static JLong operator *(JLong a, Int64 b) => new(a._value * b);
|
||||
public static JLong operator /(JLong a, JLong b) => new(a._value / b._value);
|
||||
public static JLong operator /(Int64 a, JLong b) => new(a / b._value);
|
||||
public static JLong operator /(JLong a, Int64 b) => new(a._value / b);
|
||||
public static JLong operator %(JLong a, JLong b) => new(a._value % b._value);
|
||||
public static JLong operator %(Int64 a, JLong b) => new(a % b._value);
|
||||
public static JLong operator %(JLong a, Int64 b) => new(a._value % b);
|
||||
public static Boolean operator ==(JLong a, JLong b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Int64 a, JLong b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JLong a, Int64 b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JLong a, JLong b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Int64 a, JLong b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JLong a, Int64 b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JLong a, JLong b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Int64 a, JLong b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JLong a, Int64 b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JLong a, JLong b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Int64 a, JLong b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JLong a, Int64 b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JLong a, JLong b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Int64 a, JLong b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JLong a, Int64 b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JLong a, JLong b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Int64 a, JLong b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JLong a, Int64 b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Int64 other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JLong other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JLong jvalue ? this.CompareTo(jvalue) : obj is Int64 value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Int64 other) => this._value.Equals(other);
|
||||
public Boolean Equals(JLong other) => this._value.Equals(other._value);
|
||||
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JLong jvalue ? this.Equals(jvalue) : obj is Int64 value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
74
src/LibRyujinx/Android/Jni/Primitives/JShort.cs
Normal file
74
src/LibRyujinx/Android/Jni/Primitives/JShort.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Primitives
|
||||
{
|
||||
public readonly struct JShort : IComparable<Int16>, IEquatable<Int16>, IFormattable
|
||||
{
|
||||
internal static readonly Type Type = typeof(JShort);
|
||||
|
||||
public static readonly CString Signature = (CString)"S";
|
||||
|
||||
private readonly Int16 _value;
|
||||
|
||||
private JShort(Int16 value) => this._value = value;
|
||||
private JShort(Int32 value) => this._value = Convert.ToInt16(value);
|
||||
|
||||
#region Operators
|
||||
public static implicit operator JShort(Int16 value) => new(value);
|
||||
public static implicit operator Int16(JShort jValue) => jValue._value;
|
||||
public static JShort operator +(JShort a) => a;
|
||||
public static JShort operator ++(JShort a) => new(a._value + 1);
|
||||
public static JShort operator -(JShort a) => new(-a._value);
|
||||
public static JShort operator --(JShort a) => new(a._value - 1);
|
||||
public static JShort operator +(JShort a, JShort b) => new(a._value + b._value);
|
||||
public static JShort operator +(Int16 a, JShort b) => new(a + b._value);
|
||||
public static JShort operator +(JShort a, Int16 b) => new(a._value + b);
|
||||
public static JShort operator -(JShort a, JShort b) => new(a._value - b._value);
|
||||
public static JShort operator -(Int16 a, JShort b) => new(a - b._value);
|
||||
public static JShort operator -(JShort a, Int16 b) => new(a._value - b);
|
||||
public static JShort operator *(JShort a, JShort b) => new(a._value * b._value);
|
||||
public static JShort operator *(Int16 a, JShort b) => new(a * b._value);
|
||||
public static JShort operator *(JShort a, Int16 b) => new(a._value * b);
|
||||
public static JShort operator /(JShort a, JShort b) => new(a._value / b._value);
|
||||
public static JShort operator /(Int16 a, JShort b) => new(a / b._value);
|
||||
public static JShort operator /(JShort a, Int16 b) => new(a._value / b);
|
||||
public static JShort operator %(JShort a, JShort b) => new(a._value % b._value);
|
||||
public static JShort operator %(Int16 a, JShort b) => new(a % b._value);
|
||||
public static JShort operator %(JShort a, Int16 b) => new(a._value % b);
|
||||
public static Boolean operator ==(JShort a, JShort b) => a._value.Equals(b._value);
|
||||
public static Boolean operator ==(Int16 a, JShort b) => a.Equals(b._value);
|
||||
public static Boolean operator ==(JShort a, Int16 b) => a._value.Equals(b);
|
||||
public static Boolean operator !=(JShort a, JShort b) => !a._value.Equals(b._value);
|
||||
public static Boolean operator !=(Int16 a, JShort b) => !a.Equals(b._value);
|
||||
public static Boolean operator !=(JShort a, Int16 b) => !a._value.Equals(b);
|
||||
public static Boolean operator >(JShort a, JShort b) => a._value.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(Int16 a, JShort b) => a.CompareTo(b._value) > 0;
|
||||
public static Boolean operator >(JShort a, Int16 b) => a._value.CompareTo(b) > 0;
|
||||
public static Boolean operator <(JShort a, JShort b) => a._value.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(Int16 a, JShort b) => a.CompareTo(b._value) < 0;
|
||||
public static Boolean operator <(JShort a, Int16 b) => a._value.CompareTo(b) < 0;
|
||||
public static Boolean operator >=(JShort a, JShort b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(Int16 a, JShort b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
|
||||
public static Boolean operator >=(JShort a, Int16 b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
|
||||
public static Boolean operator <=(JShort a, JShort b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(Int16 a, JShort b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
|
||||
public static Boolean operator <=(JShort a, Int16 b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Int32 CompareTo(Int16 other) => this._value.CompareTo(other);
|
||||
public Int32 CompareTo(JShort other) => this._value.CompareTo(other._value);
|
||||
public Int32 CompareTo(Object obj) => obj is JShort jvalue ? this.CompareTo(jvalue) : obj is Int16 value ? this.CompareTo(value) : this._value.CompareTo(obj);
|
||||
public Boolean Equals(Int16 other) => this._value.Equals(other);
|
||||
public Boolean Equals(JShort other) => this._value.Equals(other._value);
|
||||
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override String ToString() => this._value.ToString();
|
||||
public override Boolean Equals(Object obj) => obj is JShort jvalue ? this.Equals(jvalue) : obj is Int16 value ? this.Equals(value) : this._value.Equals(obj);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
26
src/LibRyujinx/Android/Jni/References/JArrayLocalRef.cs
Normal file
26
src/LibRyujinx/Android/Jni/References/JArrayLocalRef.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References;
|
||||
|
||||
public readonly struct JArrayLocalRef : IEquatable<JArrayLocalRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly JObjectLocalRef _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JArrayLocalRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JArrayLocalRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static explicit operator JObjectLocalRef(JArrayLocalRef a) => a._value;
|
||||
public static Boolean operator ==(JArrayLocalRef a, JArrayLocalRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JArrayLocalRef a, JArrayLocalRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
29
src/LibRyujinx/Android/Jni/References/JClassLocalRef.cs
Normal file
29
src/LibRyujinx/Android/Jni/References/JClassLocalRef.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References;
|
||||
|
||||
public readonly struct JClassLocalRef : IEquatable<JClassLocalRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly JObjectLocalRef _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private JClassLocalRef(JObjectLocalRef value) => this._value = value;
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JClassLocalRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JClassLocalRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static explicit operator JObjectLocalRef(JClassLocalRef a) => a._value;
|
||||
public static explicit operator JClassLocalRef(JObjectLocalRef a) => new(a);
|
||||
public static Boolean operator ==(JClassLocalRef a, JClassLocalRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JClassLocalRef a, JClassLocalRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
28
src/LibRyujinx/Android/Jni/References/JGlobalRef.cs
Normal file
28
src/LibRyujinx/Android/Jni/References/JGlobalRef.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References;
|
||||
|
||||
public readonly struct JGlobalRef : IEquatable<JGlobalRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly JObjectLocalRef _value;
|
||||
|
||||
public JObjectLocalRef Value => _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JGlobalRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JGlobalRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static explicit operator JObjectLocalRef(JGlobalRef a) => a._value;
|
||||
public static Boolean operator ==(JGlobalRef a, JGlobalRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JGlobalRef a, JGlobalRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
28
src/LibRyujinx/Android/Jni/References/JObjectLocalRef.cs
Normal file
28
src/LibRyujinx/Android/Jni/References/JObjectLocalRef.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References
|
||||
{
|
||||
public readonly struct JObjectLocalRef : IEquatable<JObjectLocalRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JObjectLocalRef other)
|
||||
=> this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj)
|
||||
=> obj is JObjectLocalRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JObjectLocalRef a, JObjectLocalRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JObjectLocalRef a, JObjectLocalRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
||||
}
|
27
src/LibRyujinx/Android/Jni/References/JStringLocalRef.cs
Normal file
27
src/LibRyujinx/Android/Jni/References/JStringLocalRef.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References;
|
||||
|
||||
public readonly struct JStringLocalRef : IEquatable<JStringLocalRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly JObjectLocalRef _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JStringLocalRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj)
|
||||
=> obj is JStringLocalRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static explicit operator JObjectLocalRef(JStringLocalRef a) => a._value;
|
||||
public static Boolean operator ==(JStringLocalRef a, JStringLocalRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JStringLocalRef a, JStringLocalRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
27
src/LibRyujinx/Android/Jni/References/JThrowableLocalRef.cs
Normal file
27
src/LibRyujinx/Android/Jni/References/JThrowableLocalRef.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References;
|
||||
|
||||
public readonly struct JThrowableLocalRef : IEquatable<JThrowableLocalRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly JObjectLocalRef _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JThrowableLocalRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj)
|
||||
=> obj is JThrowableLocalRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static explicit operator JObjectLocalRef(JThrowableLocalRef a) => a._value;
|
||||
public static Boolean operator ==(JThrowableLocalRef a, JThrowableLocalRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JThrowableLocalRef a, JThrowableLocalRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
26
src/LibRyujinx/Android/Jni/References/JWeakRef.cs
Normal file
26
src/LibRyujinx/Android/Jni/References/JWeakRef.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.References;
|
||||
|
||||
public readonly struct JWeakRef : IEquatable<JWeakRef>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly JObjectLocalRef _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JWeakRef other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JWeakRef other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
public static explicit operator JObjectLocalRef(JWeakRef a) => a._value;
|
||||
public static Boolean operator ==(JWeakRef a, JWeakRef b) => a.Equals(b);
|
||||
public static Boolean operator !=(JWeakRef a, JWeakRef b) => !a.Equals(b);
|
||||
#endregion
|
||||
}
|
30
src/LibRyujinx/Android/Jni/Values/JEnvValue.cs
Normal file
30
src/LibRyujinx/Android/Jni/Values/JEnvValue.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Values
|
||||
{
|
||||
internal readonly struct JEnvValue : IEquatable<JEnvValue>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JEnvValue a, JEnvValue b) => a._value.Equals(b._value);
|
||||
public static Boolean operator !=(JEnvValue a, JEnvValue b) => !a._value.Equals(b._value);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
internal readonly ref JNativeInterface Functions => ref this._value.GetUnsafeReference<JNativeInterface>();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JEnvValue other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override Boolean Equals(Object obj) => obj is JEnvValue other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
||||
}
|
20
src/LibRyujinx/Android/Jni/Values/JInvokeInterface.cs
Normal file
20
src/LibRyujinx/Android/Jni/Values/JInvokeInterface.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LibRyujinx.Jni.Values
|
||||
{
|
||||
[SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "This struct is created only by binary operations.")]
|
||||
public readonly struct JInvokeInterface
|
||||
{
|
||||
#pragma warning disable 0169
|
||||
private readonly IntPtr _reserved0;
|
||||
private readonly IntPtr _reserved1;
|
||||
private readonly IntPtr _reserved2;
|
||||
#pragma warning restore 0169
|
||||
internal IntPtr DestroyJavaVMPointer { get; init; }
|
||||
internal IntPtr AttachCurrentThreadPointer { get; init; }
|
||||
internal IntPtr DetachCurrentThreadPointer { get; init; }
|
||||
internal IntPtr GetEnvPointer { get; init; }
|
||||
internal IntPtr AttachCurrentThreadAsDaemonPointer { get; init; }
|
||||
}
|
||||
}
|
247
src/LibRyujinx/Android/Jni/Values/JNativeInterface.cs
Normal file
247
src/LibRyujinx/Android/Jni/Values/JNativeInterface.cs
Normal file
@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibRyujinx.Jni.Values;
|
||||
|
||||
[SuppressMessage("CodeQuality", "IDE0051:Remove unused private members",
|
||||
Justification = "This struct is created only by binary operations.")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public readonly struct JNativeInterface
|
||||
{
|
||||
#pragma warning disable 0169
|
||||
private readonly IntPtr _reserved0;
|
||||
private readonly IntPtr _reserved1;
|
||||
private readonly IntPtr _reserved2;
|
||||
private readonly IntPtr _reserved3;
|
||||
#pragma warning restore 0169
|
||||
internal readonly IntPtr GetVersionPointer { get; init; }
|
||||
internal readonly IntPtr DefineClassPointer { get; init; }
|
||||
internal readonly IntPtr FindClassPointer { get; init; }
|
||||
internal readonly IntPtr FromReflectedMethodPointer { get; init; }
|
||||
internal readonly IntPtr FromReflectedFieldPointer { get; init; }
|
||||
internal readonly IntPtr ToReflectedMethodPointer { get; init; }
|
||||
internal readonly IntPtr GetSuperclassPointer { get; init; }
|
||||
internal readonly IntPtr IsAssignableFromPointer { get; init; }
|
||||
internal readonly IntPtr ToReflectedFieldPointer { get; init; }
|
||||
internal readonly IntPtr ThrowPointer { get; init; }
|
||||
internal readonly IntPtr ThrowNewPointer { get; init; }
|
||||
internal readonly IntPtr ExceptionOccurredPointer { get; init; }
|
||||
internal readonly IntPtr ExceptionDescribePointer { get; init; }
|
||||
internal readonly IntPtr ExceptionClearPointer { get; init; }
|
||||
internal readonly IntPtr FatalErrorPointer { get; init; }
|
||||
internal readonly IntPtr PushLocalFramePointer { get; init; }
|
||||
internal readonly IntPtr PopLocalFramePointer { get; init; }
|
||||
internal readonly IntPtr NewGlobalRefPointer { get; init; }
|
||||
internal readonly IntPtr DeleteGlobalRefPointer { get; init; }
|
||||
internal readonly IntPtr DeleteLocalRefPointer { get; init; }
|
||||
internal readonly IntPtr IsSameObjectPointer { get; init; }
|
||||
internal readonly IntPtr NewLocalRefPointer { get; init; }
|
||||
internal readonly IntPtr EnsureLocalCapacityPointer { get; init; }
|
||||
internal readonly IntPtr AllocObjectPointer { get; init; }
|
||||
internal readonly IntPtr NewObjectPointer { get; init; }
|
||||
internal readonly IntPtr NewObjectVPointer { get; init; }
|
||||
internal readonly IntPtr NewObjectAPointer { get; init; }
|
||||
internal readonly IntPtr GetObjectClassPointer { get; init; }
|
||||
internal readonly IntPtr IsInstanceOfPointer { get; init; }
|
||||
internal readonly IntPtr GetMethodIdPointer { get; init; }
|
||||
private readonly IntPtr CallObjectMethodPointer { get; init; }
|
||||
private readonly IntPtr CallObjectMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallObjectMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallBooleanMethodPointer { get; init; }
|
||||
private readonly IntPtr CallBooleanMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallBooleanMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallByteMethodPointer { get; init; }
|
||||
private readonly IntPtr CallByteMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallByteMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallCharMethodPointer { get; init; }
|
||||
private readonly IntPtr CallCharMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallCharMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallShortMethodPointer { get; init; }
|
||||
private readonly IntPtr CallShortMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallShortMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallIntMethodPointer { get; init; }
|
||||
private readonly IntPtr CallIntMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallIntMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallLongMethodPointer { get; init; }
|
||||
private readonly IntPtr CallLongMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallLongMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallFloatMethodPointer { get; init; }
|
||||
private readonly IntPtr CallFloatMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallFloatMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallDoubleMethodPointer { get; init; }
|
||||
private readonly IntPtr CallDoubleMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallDoubleMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallVoidMethodPointer { get; init; }
|
||||
private readonly IntPtr CallVoidMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallVoidMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualObjectMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualObjectMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualObjectMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualBooleanMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualBooleanMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualBooleanMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualByteMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualByteMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualByteMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualCharMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualCharMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualCharMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualShortMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualShortMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualShortMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualIntMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualIntMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualIntMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualLongMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualLongMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualLongMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualFloatMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualFloatMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualFloatMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualDoubleMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualDoubleMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualDoubleMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualVoidMethodPointer { get; init; }
|
||||
private readonly IntPtr CallNonVirtualVoidMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallNonVirtualVoidMethodAPointer { get; init; }
|
||||
internal readonly IntPtr GetFieldIdPointer { get; init; }
|
||||
internal readonly IntPtr GetObjectFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetBooleanFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetByteFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetCharFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetShortFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetIntFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetLongFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetFloatFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetDoubleFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetObjectFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetBooleanFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetByteFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetCharFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetShortFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetIntFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetLongFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetFloatFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetDoubleFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticMethodIdPointer { get; init; }
|
||||
private readonly IntPtr CallStaticObjectMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticObjectMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticObjectMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticBooleanMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticBooleanMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticBooleanMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticByteMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticByteMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticByteMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticCharMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticCharMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticCharMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticShortMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticShortMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticShortMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticIntMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticIntMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticIntMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticLongMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticLongMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticLongMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticFloatMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticFloatMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticFloatMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticDoubleMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticDoubleMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticDoubleMethodAPointer { get; init; }
|
||||
private readonly IntPtr CallStaticVoidMethodPointer { get; init; }
|
||||
private readonly IntPtr CallStaticVoidMethodVPointer { get; init; }
|
||||
internal readonly IntPtr CallStaticVoidMethodAPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticFieldIdPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticObjectFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticBooleanFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticByteFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticCharFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticShortFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticIntFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticLongFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticFloatFieldPointer { get; init; }
|
||||
internal readonly IntPtr GetStaticDoubleFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticObjectFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticBooleanFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticByteFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticCharFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticShortFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticIntFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticLongFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticFloatFieldPointer { get; init; }
|
||||
internal readonly IntPtr SetStaticDoubleFieldPointer { get; init; }
|
||||
internal readonly IntPtr NewStringPointer { get; init; }
|
||||
internal readonly IntPtr GetStringLengthPointer { get; init; }
|
||||
internal readonly IntPtr GetStringCharsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseStringCharsPointer { get; init; }
|
||||
internal readonly IntPtr NewStringUtfPointer { get; init; }
|
||||
internal readonly IntPtr GetStringUtfLengthPointer { get; init; }
|
||||
internal readonly IntPtr GetStringUtfCharsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseStringUtfCharsPointer { get; init; }
|
||||
internal readonly IntPtr GetArrayLengthPointer { get; init; }
|
||||
internal readonly IntPtr NewObjectArrayPointer { get; init; }
|
||||
internal readonly IntPtr GetObjectArrayElementPointer { get; init; }
|
||||
internal readonly IntPtr SetObjectArrayElementPointer { get; init; }
|
||||
internal readonly IntPtr NewBooleanArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewByteArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewCharArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewShortArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewIntArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewLongArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewFloatArrayPointer { get; init; }
|
||||
internal readonly IntPtr NewDoubleArrayPointer { get; init; }
|
||||
internal readonly IntPtr GetBooleanArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetByteArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetCharArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetShortArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetIntArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetLongArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetFloatArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetDoubleArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseBooleanArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseByteArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseCharArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseShortArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseIntArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseLongArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseFloatArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseDoubleArrayElementsPointer { get; init; }
|
||||
internal readonly IntPtr GetBooleanArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetByteArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetCharArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetShortArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetIntArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetLongArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetFloatArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetDoubleArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetBooleanArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetByteArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetCharArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetShortArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetIntArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetLongArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetFloatArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr SetDoubleArrayRegionPointer { get; init; }
|
||||
internal readonly IntPtr RegisterNativesPointer { get; init; }
|
||||
internal readonly IntPtr UnregisterNativesPointer { get; init; }
|
||||
internal readonly IntPtr MonitorEnterPointer { get; init; }
|
||||
internal readonly IntPtr MonitorExitPointer { get; init; }
|
||||
internal readonly IntPtr GetJavaVMPointer { get; init; }
|
||||
internal readonly IntPtr GetStringRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetStringUtfRegionPointer { get; init; }
|
||||
internal readonly IntPtr GetPrimitiveArrayCriticalPointer { get; init; }
|
||||
internal readonly IntPtr ReleasePrimitiveArrayCriticalPointer { get; init; }
|
||||
internal readonly IntPtr GetStringCriticalPointer { get; init; }
|
||||
internal readonly IntPtr ReleaseStringCriticalPointer { get; init; }
|
||||
internal readonly IntPtr NewWeakGlobalRefPointer { get; init; }
|
||||
internal readonly IntPtr DeleteWeakGlobalRefPointer { get; init; }
|
||||
internal readonly IntPtr ExceptionCheckPointer { get; init; }
|
||||
internal readonly IntPtr NewDirectByteBufferPointer { get; init; }
|
||||
internal readonly IntPtr GetDirectBufferAddressPointer { get; init; }
|
||||
internal readonly IntPtr GetDirectBufferCapacityPointer { get; init; }
|
||||
internal readonly IntPtr GetObjectRefTypePointer { get; init; }
|
||||
}
|
11
src/LibRyujinx/Android/Jni/Values/JNativeMethod.cs
Normal file
11
src/LibRyujinx/Android/Jni/Values/JNativeMethod.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Values;
|
||||
|
||||
public readonly struct JNativeMethod
|
||||
{
|
||||
internal ReadOnlyValPtr<Byte> Name { get; init; }
|
||||
internal ReadOnlyValPtr<Byte> Signature { get; init; }
|
||||
internal IntPtr Pointer { get; init; }
|
||||
}
|
46
src/LibRyujinx/Android/Jni/Values/JValue.cs
Normal file
46
src/LibRyujinx/Android/Jni/Values/JValue.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using LibRyujinx.Jni.References;
|
||||
|
||||
using Rxmxnx.PInvoke;
|
||||
|
||||
namespace LibRyujinx.Jni.Values;
|
||||
|
||||
internal readonly struct JValue
|
||||
{
|
||||
private delegate Boolean IsDefaultDelegate(in JValue value);
|
||||
|
||||
private static readonly Int32 size = NativeUtilities.SizeOf<JValue>();
|
||||
|
||||
private static readonly IsDefaultDelegate isDefault = JValue.GetIsDefault();
|
||||
|
||||
#pragma warning disable 0649
|
||||
#pragma warning disable 0169
|
||||
private readonly Byte _value1;
|
||||
private readonly Byte _value2;
|
||||
private readonly Int16 _value3;
|
||||
private readonly Int32 _value4;
|
||||
#pragma warning restore 0169
|
||||
#pragma warning restore 0649
|
||||
|
||||
public Boolean IsDefault => JValue.isDefault(this);
|
||||
|
||||
public static JValue Create(in ReadOnlySpan<Byte> source)
|
||||
{
|
||||
Byte[] result = new Byte[JValue.size];
|
||||
for (Int32 i = 0; i < source.Length; i++)
|
||||
result[i] = source[i];
|
||||
return result.ToValue<JValue>();
|
||||
}
|
||||
|
||||
private static IsDefaultDelegate GetIsDefault() => Environment.Is64BitProcess ? JValue.DefaultLong : JValue.Default;
|
||||
|
||||
private static Boolean Default(in JValue jValue)
|
||||
=> jValue._value1 + jValue._value2 + jValue._value3 == default && jValue._value4 == default;
|
||||
|
||||
private static Boolean DefaultLong(in JValue jValue)
|
||||
=> Unsafe.AsRef(in jValue).Transform<JValue, Int64>() == default;
|
||||
|
||||
public static explicit operator JValue(JObjectLocalRef a) => JValue.Create(NativeUtilities.AsBytes(in a));
|
||||
}
|
13
src/LibRyujinx/Android/Jni/Values/JavaVMAttachArgs.cs
Normal file
13
src/LibRyujinx/Android/Jni/Values/JavaVMAttachArgs.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using LibRyujinx.Jni.References;
|
||||
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Values;
|
||||
|
||||
public readonly struct JavaVMAttachArgs
|
||||
{
|
||||
internal Int32 Version { get; init; }
|
||||
internal ReadOnlyValPtr<Byte> Name { get; init; }
|
||||
internal JObjectLocalRef Group { get; init; }
|
||||
}
|
12
src/LibRyujinx/Android/Jni/Values/JavaVMInitArgs.cs
Normal file
12
src/LibRyujinx/Android/Jni/Values/JavaVMInitArgs.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Values
|
||||
{
|
||||
public readonly struct JavaVMInitArgs
|
||||
{
|
||||
internal Int32 Version { get; init; }
|
||||
internal Int32 OptionsLenght { get; init; }
|
||||
internal IntPtr Options { get; init; }
|
||||
internal Boolean IgnoreUnrecognized { get; init; }
|
||||
}
|
||||
}
|
10
src/LibRyujinx/Android/Jni/Values/JavaVMOption.cs
Normal file
10
src/LibRyujinx/Android/Jni/Values/JavaVMOption.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Values;
|
||||
|
||||
public readonly struct JavaVMOption
|
||||
{
|
||||
internal ReadOnlyValPtr<Byte> Name { get; init; }
|
||||
internal IntPtr ExtraInfo { get; init; }
|
||||
}
|
29
src/LibRyujinx/Android/Jni/Values/JavaVMValue.cs
Normal file
29
src/LibRyujinx/Android/Jni/Values/JavaVMValue.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using Rxmxnx.PInvoke;
|
||||
using System;
|
||||
|
||||
namespace LibRyujinx.Jni.Values;
|
||||
|
||||
internal readonly struct JavaVMValue : IEquatable<JavaVMValue>
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
private readonly IntPtr _value;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#region Operators
|
||||
public static Boolean operator ==(JavaVMValue a, JavaVMValue b) => a._value.Equals(b._value);
|
||||
public static Boolean operator !=(JavaVMValue a, JavaVMValue b) => !a._value.Equals(b._value);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
internal readonly ref JInvokeInterface Functions => ref this._value.GetUnsafeReference<JInvokeInterface>();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public Boolean Equals(JavaVMValue other) => this._value.Equals(other._value);
|
||||
#endregion
|
||||
|
||||
#region Overrided Methods
|
||||
public override Boolean Equals(Object obj) => obj is JavaVMValue other && this.Equals(other);
|
||||
public override Int32 GetHashCode() => this._value.GetHashCode();
|
||||
#endregion
|
||||
}
|
566
src/LibRyujinx/Android/JniExportedMethods.cs
Normal file
566
src/LibRyujinx/Android/JniExportedMethods.cs
Normal file
@ -0,0 +1,566 @@
|
||||
using LibRyujinx.Android;
|
||||
using LibRyujinx.Jni.Pointers;
|
||||
using Ryujinx.Audio.Backends.OpenAL;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Logging.Targets;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.Input;
|
||||
using Silk.NET.Core.Loader;
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public static partial class LibRyujinx
|
||||
{
|
||||
private static long _surfacePtr;
|
||||
private static long _window = 0;
|
||||
|
||||
public static VulkanLoader? VulkanLoader { get; private set; }
|
||||
|
||||
[DllImport("libryujinxjni")]
|
||||
internal extern static void setRenderingThread();
|
||||
|
||||
[DllImport("libryujinxjni")]
|
||||
internal extern static void debug_break(int code);
|
||||
|
||||
[DllImport("libryujinxjni")]
|
||||
internal extern static void setCurrentTransform(long native_window, int transform);
|
||||
|
||||
public delegate IntPtr JniCreateSurface(IntPtr native_surface, IntPtr instance);
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "javaInitialize")]
|
||||
public unsafe static bool JniInitialize(IntPtr jpathId, IntPtr jniEnv)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
PlatformInfo.IsBionic = true;
|
||||
|
||||
Logger.AddTarget(
|
||||
new AsyncLogTargetWrapper(
|
||||
new AndroidLogTarget("RyujinxLog"),
|
||||
1000,
|
||||
AsyncLogTargetOverflowAction.Block
|
||||
));
|
||||
|
||||
var path = Marshal.PtrToStringAnsi(jpathId);
|
||||
|
||||
var init = Initialize(path);
|
||||
|
||||
Interop.Initialize(new JEnvRef(jniEnv));
|
||||
|
||||
Interop.Test();
|
||||
|
||||
return init;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceReloadFilesystem")]
|
||||
public static void JnaReloadFileSystem()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SwitchDevice?.ReloadFileSystem();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceInitialize")]
|
||||
public static bool JnaDeviceInitialize(bool isHostMapped,
|
||||
bool useNce,
|
||||
int systemLanguage,
|
||||
int regionCode,
|
||||
bool enableVsync,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableInternetAccess,
|
||||
IntPtr timeZonePtr,
|
||||
bool ignoreMissingServices)
|
||||
{
|
||||
debug_break(4);
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
AudioDriver = new OpenALHardwareDeviceDriver();
|
||||
|
||||
var timezone = Marshal.PtrToStringAnsi(timeZonePtr);
|
||||
return InitializeDevice(isHostMapped,
|
||||
useNce,
|
||||
(SystemLanguage)systemLanguage,
|
||||
(RegionCode)regionCode,
|
||||
enableVsync,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableInternetAccess,
|
||||
timezone,
|
||||
ignoreMissingServices);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameFifo")]
|
||||
public static double JnaGetGameFifo()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var stats = SwitchDevice?.EmulationContext?.Statistics.GetFifoPercent() ?? 0;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameFrameTime")]
|
||||
public static double JnaGetGameFrameTime()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var stats = SwitchDevice?.EmulationContext?.Statistics.GetGameFrameTime() ?? 0;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameFrameRate")]
|
||||
public static double JnaGetGameFrameRate()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var stats = SwitchDevice?.EmulationContext?.Statistics.GetGameFrameRate() ?? 0;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceLaunchMiiEditor")]
|
||||
public static bool JNALaunchMiiEditApplet()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
if (SwitchDevice?.EmulationContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return LaunchMiiEditApplet();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetDlcContentList")]
|
||||
public static IntPtr JniGetDlcContentListNative(IntPtr pathPtr, long titleId)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var list = GetDlcContentList(Marshal.PtrToStringAnsi(pathPtr) ?? "", (ulong)titleId);
|
||||
|
||||
return CreateStringArray(list);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetDlcTitleId")]
|
||||
public static long JniGetDlcTitleIdNative(IntPtr pathPtr, IntPtr ncaPath)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
return Marshal.StringToHGlobalAnsi(GetDlcTitleId(Marshal.PtrToStringAnsi(pathPtr) ?? "", Marshal.PtrToStringAnsi(ncaPath) ?? ""));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceSignalEmulationClose")]
|
||||
public static void JniSignalEmulationCloseNative()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SignalEmulationClose();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceCloseEmulation")]
|
||||
public static void JniCloseEmulationNative()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
CloseEmulation();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceLoadDescriptor")]
|
||||
public static bool JnaLoadApplicationNative(int descriptor, int type, int updateDescriptor)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
if (SwitchDevice?.EmulationContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stream = OpenFile(descriptor);
|
||||
var update = updateDescriptor == -1 ? null : OpenFile(updateDescriptor);
|
||||
|
||||
return LoadApplication(stream, (FileType)type, update);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceVerifyFirmware")]
|
||||
public static IntPtr JniVerifyFirmware(int descriptor, bool isXci)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
|
||||
var stream = OpenFile(descriptor);
|
||||
|
||||
IntPtr stringHandle = 0;
|
||||
string? version = "0.0";
|
||||
|
||||
try
|
||||
{
|
||||
version = VerifyFirmware(stream, isXci)?.VersionString;
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Service, $"Unable to verify firmware. Exception: {_}");
|
||||
}
|
||||
|
||||
if (version != null)
|
||||
{
|
||||
stringHandle = Marshal.StringToHGlobalAnsi(version);
|
||||
}
|
||||
|
||||
return stringHandle;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceInstallFirmware")]
|
||||
public static void JniInstallFirmware(int descriptor, bool isXci)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
|
||||
var stream = OpenFile(descriptor);
|
||||
|
||||
InstallFirmware(stream, isXci);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetInstalledFirmwareVersion")]
|
||||
public static IntPtr JniGetInstalledFirmwareVersion()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
|
||||
var version = GetInstalledFirmwareVersion() ?? "0.0";
|
||||
return Marshal.StringToHGlobalAnsi(version);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphicsInitialize")]
|
||||
public static bool JnaGraphicsInitialize(float resScale,
|
||||
float maxAnisotropy,
|
||||
bool fastGpuTime,
|
||||
bool fast2DCopy,
|
||||
bool enableMacroJit,
|
||||
bool enableMacroHLE,
|
||||
bool enableShaderCache,
|
||||
bool enableTextureRecompression,
|
||||
int backendThreading)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SearchPathContainer.Platform = UnderlyingPlatform.Android;
|
||||
return InitializeGraphics(new GraphicsConfiguration()
|
||||
{
|
||||
ResScale = resScale,
|
||||
MaxAnisotropy = maxAnisotropy,
|
||||
FastGpuTime = fastGpuTime,
|
||||
Fast2DCopy = fast2DCopy,
|
||||
EnableMacroJit = enableMacroJit,
|
||||
EnableMacroHLE = enableMacroHLE,
|
||||
EnableShaderCache = enableShaderCache,
|
||||
EnableTextureRecompression = enableTextureRecompression,
|
||||
BackendThreading = (BackendThreading)backendThreading
|
||||
});
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphicsInitializeRenderer")]
|
||||
public unsafe static bool JnaGraphicsInitializeRenderer(char** extensionsArray,
|
||||
int extensionsLength,
|
||||
long driverHandle)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
if (Renderer != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<string?> extensions = new();
|
||||
|
||||
for (int i = 0; i < extensionsLength; i++)
|
||||
{
|
||||
extensions.Add(Marshal.PtrToStringAnsi((IntPtr)extensionsArray[i]));
|
||||
}
|
||||
|
||||
if (driverHandle != 0)
|
||||
{
|
||||
VulkanLoader = new VulkanLoader((IntPtr)driverHandle);
|
||||
}
|
||||
|
||||
CreateSurface createSurfaceFunc = instance =>
|
||||
{
|
||||
_surfacePtr = Interop.GetSurfacePtr();
|
||||
_window = Interop.GetWindowsHandle();
|
||||
|
||||
var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
|
||||
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))
|
||||
{
|
||||
var createInfo = new AndroidSurfaceCreateInfoKHR
|
||||
{
|
||||
SType = StructureType.AndroidSurfaceCreateInfoKhr,
|
||||
Window = (nint*)_surfacePtr,
|
||||
};
|
||||
|
||||
var result = surfaceExtension.CreateAndroidSurface(new Instance(instance), createInfo, null, out var surface);
|
||||
|
||||
return (nint)surface.Handle;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
};
|
||||
|
||||
return InitializeGraphicsRenderer(GraphicsBackend.Vulkan, createSurfaceFunc, extensions.ToArray());
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphicsRendererSetSize")]
|
||||
public static void JnaSetRendererSizeNative(int width, int height)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
Renderer?.Window?.SetSize(width, height);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphicsRendererRunLoop")]
|
||||
public static void JniRunLoopNative()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetSwapBuffersCallback(() =>
|
||||
{
|
||||
var time = SwitchDevice.EmulationContext.Statistics.GetGameFrameTime();
|
||||
Interop.FrameEnded(time);
|
||||
});
|
||||
RunLoop();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "loggingSetEnabled")]
|
||||
public static void JniSetLoggingEnabledNative(int logLevel, bool enabled)
|
||||
{
|
||||
Logger.SetEnable((LogLevel)logLevel, enabled);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "loggingEnabledGraphicsLog")]
|
||||
public static void JniSetLoggingEnabledGraphicsLog(bool enabled)
|
||||
{
|
||||
_enableGraphicsLogging = enabled;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameInfo")]
|
||||
public unsafe static void JniGetGameInfo(int fileDescriptor, IntPtr extension, IntPtr infoPtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
using var stream = OpenFile(fileDescriptor);
|
||||
var ext = Marshal.PtrToStringAnsi(extension);
|
||||
var info = GetGameInfo(stream, ext.ToLower()) ?? GetDefaultInfo(stream);
|
||||
var i = (GameInfoNative*)infoPtr;
|
||||
var n = new GameInfoNative(info);
|
||||
i->TitleId = n.TitleId;
|
||||
i->TitleName = n.TitleName;
|
||||
i->Version = n.Version;
|
||||
i->FileSize = n.FileSize;
|
||||
i->Icon = n.Icon;
|
||||
i->Version = n.Version;
|
||||
i->Developer = n.Developer;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphicsRendererSetVsync")]
|
||||
public static void JnaSetVsyncStateNative(bool enabled)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetVsyncState(enabled);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputInitialize")]
|
||||
public static void JnaInitializeInput(int width, int height)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
InitializeInput(width, height);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetClientSize")]
|
||||
public static void JnaSetClientSize(int width, int height)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetClientSize(width, height);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetTouchPoint")]
|
||||
public static void JnaSetTouchPoint(int x, int y)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetTouchPoint(x, y);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputReleaseTouchPoint")]
|
||||
public static void JnaReleaseTouchPoint()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
ReleaseTouchPoint();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputUpdate")]
|
||||
public static void JniUpdateInput()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
UpdateInput();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetButtonPressed")]
|
||||
public static void JnaSetButtonPressed(int button, int id)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetButtonPressed((GamepadButtonInputId)button, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetButtonReleased")]
|
||||
public static void JnaSetButtonReleased(int button, int id)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetButtonReleased((GamepadButtonInputId)button, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetAccelerometerData")]
|
||||
public static void JniSetAccelerometerData(float x, float y, float z, int id)
|
||||
{
|
||||
var accel = new Vector3(x, y, z);
|
||||
SetAccelerometerData(accel, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetGyroData")]
|
||||
public static void JniSetGyroData(float x, float y, float z, int id)
|
||||
{
|
||||
var gryo = new Vector3(x, y, z);
|
||||
SetGryoData(gryo, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputSetStickAxis")]
|
||||
public static void JnaSetStickAxis(int stick, float x, float y, int id)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
SetStickAxis((StickInputId)stick, new Vector2(float.IsNaN(x) ? 0 : x, float.IsNaN(y) ? 0 : y), id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "inputConnectGamepad")]
|
||||
public static int JnaConnectGamepad(int index)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
return ConnectGamepad(index);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userGetOpenedUser")]
|
||||
public static IntPtr JniGetOpenedUser()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = GetOpenedUser();
|
||||
var ptr = Marshal.StringToHGlobalAnsi(userId);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userGetUserPicture")]
|
||||
public static IntPtr JniGetUserPicture(IntPtr userIdPtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
return Marshal.StringToHGlobalAnsi(GetUserPicture(userId));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userSetUserPicture")]
|
||||
public static void JniGetUserPicture(IntPtr userIdPtr, IntPtr picturePtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
var picture = Marshal.PtrToStringAnsi(picturePtr) ?? "";
|
||||
|
||||
SetUserPicture(userId, picture);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userGetUserName")]
|
||||
public static IntPtr JniGetUserName(IntPtr userIdPtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
return Marshal.StringToHGlobalAnsi(GetUserName(userId));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userSetUserName")]
|
||||
public static void JniSetUserName(IntPtr userIdPtr, IntPtr userNamePtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
var userName = Marshal.PtrToStringAnsi(userNamePtr) ?? "";
|
||||
|
||||
SetUserName(userId, userName);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userGetAllUsers")]
|
||||
public static IntPtr JniGetAllUsers()
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var users = GetAllUsers();
|
||||
|
||||
return CreateStringArray(users.ToList());
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userAddUser")]
|
||||
public static void JniAddUser(IntPtr userNamePtr, IntPtr picturePtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userName = Marshal.PtrToStringAnsi(userNamePtr) ?? "";
|
||||
var picture = Marshal.PtrToStringAnsi(picturePtr) ?? "";
|
||||
|
||||
AddUser(userName, picture);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userDeleteUser")]
|
||||
public static void JniDeleteUser(IntPtr userIdPtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
DeleteUser(userId);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "uiHandlerSetup")]
|
||||
public static void JniSetupUiHandler()
|
||||
{
|
||||
SetupUiHandler();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "uiHandlerSetResponse")]
|
||||
public static void JniSetUiHandlerResponse(bool isOkPressed, IntPtr input)
|
||||
{
|
||||
SetUiHandlerResponse(isOkPressed, Marshal.PtrToStringAnsi(input) ?? "");
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userOpenUser")]
|
||||
public static void JniOpenUser(IntPtr userIdPtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
OpenUser(userId);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "userCloseUser")]
|
||||
public static void JniCloseUser(IntPtr userIdPtr)
|
||||
{
|
||||
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
CloseUser(userId);
|
||||
}
|
||||
}
|
||||
|
||||
internal static partial class Logcat
|
||||
{
|
||||
[LibraryImport("liblog", StringMarshalling = StringMarshalling.Utf8)]
|
||||
private static partial void __android_log_print(LogLevel level, string? tag, string format, string args, IntPtr ptr);
|
||||
|
||||
internal static void AndroidLogPrint(LogLevel level, string? tag, string message) =>
|
||||
__android_log_print(level, tag, "%s", message, IntPtr.Zero);
|
||||
|
||||
internal enum LogLevel
|
||||
{
|
||||
Unknown = 0x00,
|
||||
Default = 0x01,
|
||||
Verbose = 0x02,
|
||||
Debug = 0x03,
|
||||
Info = 0x04,
|
||||
Warn = 0x05,
|
||||
Error = 0x06,
|
||||
Fatal = 0x07,
|
||||
Silent = 0x08,
|
||||
}
|
||||
}
|
||||
}
|
235
src/LibRyujinx/LibRyujinx.Device.cs
Normal file
235
src/LibRyujinx/LibRyujinx.Device.cs
Normal file
@ -0,0 +1,235 @@
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public static partial class LibRyujinx
|
||||
{
|
||||
public static bool InitializeDevice(bool isHostMapped,
|
||||
bool useHypervisor,
|
||||
SystemLanguage systemLanguage,
|
||||
RegionCode regionCode,
|
||||
bool enableVsync,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableInternetAccess,
|
||||
string? timeZone,
|
||||
bool ignoreMissingServices)
|
||||
{
|
||||
if (SwitchDevice == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SwitchDevice.InitializeContext(isHostMapped,
|
||||
useHypervisor,
|
||||
systemLanguage,
|
||||
regionCode,
|
||||
enableVsync,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableInternetAccess,
|
||||
timeZone,
|
||||
ignoreMissingServices);
|
||||
}
|
||||
|
||||
public static void InstallFirmware(Stream stream, bool isXci)
|
||||
{
|
||||
SwitchDevice?.ContentManager.InstallFirmware(stream, isXci);
|
||||
}
|
||||
|
||||
public static string GetInstalledFirmwareVersion()
|
||||
{
|
||||
var version = SwitchDevice?.ContentManager.GetCurrentFirmwareVersion();
|
||||
|
||||
if (version != null)
|
||||
{
|
||||
return version.VersionString;
|
||||
}
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
public static SystemVersion? VerifyFirmware(Stream stream, bool isXci)
|
||||
{
|
||||
return SwitchDevice?.ContentManager?.VerifyFirmwarePackage(stream, isXci) ?? null;
|
||||
}
|
||||
|
||||
public static bool LoadApplication(Stream stream, FileType type, Stream? updateStream = null)
|
||||
{
|
||||
var emulationContext = SwitchDevice.EmulationContext;
|
||||
return type switch
|
||||
{
|
||||
FileType.None => false,
|
||||
FileType.Nsp => emulationContext?.LoadNsp(stream, 0, updateStream) ?? false,
|
||||
FileType.Xci => emulationContext?.LoadXci(stream, 0, updateStream) ?? false,
|
||||
FileType.Nro => emulationContext?.LoadProgram(stream, true, "") ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
public static bool LaunchMiiEditApplet()
|
||||
{
|
||||
string contentPath = SwitchDevice.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
|
||||
|
||||
return LoadApplication(contentPath);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void SignalEmulationClose()
|
||||
{
|
||||
_isStopped = true;
|
||||
_isActive = false;
|
||||
}
|
||||
|
||||
public static void CloseEmulation()
|
||||
{
|
||||
if (SwitchDevice == null)
|
||||
return;
|
||||
|
||||
_npadManager?.Dispose();
|
||||
_npadManager = null;
|
||||
|
||||
_touchScreenManager?.Dispose();
|
||||
_touchScreenManager = null;
|
||||
|
||||
SwitchDevice!.InputManager?.Dispose();
|
||||
SwitchDevice!.InputManager = null;
|
||||
_inputManager = null;
|
||||
|
||||
if (Renderer != null)
|
||||
{
|
||||
_gpuDoneEvent.WaitOne();
|
||||
_gpuDoneEvent.Dispose();
|
||||
_gpuDoneEvent = null;
|
||||
SwitchDevice?.DisposeContext();
|
||||
Renderer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static FileStream OpenFile(int descriptor)
|
||||
{
|
||||
var safeHandle = new SafeFileHandle(descriptor, false);
|
||||
|
||||
return new FileStream(safeHandle, FileAccess.ReadWrite);
|
||||
}
|
||||
|
||||
public enum FileType
|
||||
{
|
||||
None,
|
||||
Nsp,
|
||||
Xci,
|
||||
Nro
|
||||
}
|
||||
}
|
||||
}
|
248
src/LibRyujinx/LibRyujinx.Graphics.cs
Normal file
248
src/LibRyujinx/LibRyujinx.Graphics.cs
Normal file
@ -0,0 +1,248 @@
|
||||
using LibRyujinx.Android;
|
||||
using LibRyujinx.Shared;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.GAL.Multithreading;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.Graphics.Gpu.Shader;
|
||||
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;
|
||||
private static ManualResetEvent _gpuDoneEvent;
|
||||
private static bool _enableGraphicsLogging;
|
||||
|
||||
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; }
|
||||
|
||||
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.EnableTextureRecompression = graphicsConfiguration.EnableTextureRecompression;
|
||||
|
||||
GraphicsConfiguration = graphicsConfiguration;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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(createSurfaceFunc == null ? null : (ulong?)createSurfaceFunc(instance.Handle)),
|
||||
() => requiredExtensions,
|
||||
null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void SetRendererSize(int width, int height)
|
||||
{
|
||||
Renderer?.Window?.SetSize(width, height);
|
||||
}
|
||||
|
||||
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!;
|
||||
_gpuDoneEvent = new ManualResetEvent(true);
|
||||
|
||||
device.Gpu.Renderer.Initialize(_enableGraphicsLogging ? GraphicsDebugLevel.All : GraphicsDebugLevel.None);
|
||||
|
||||
_gpuCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
device.Gpu.ShaderCacheStateChanged += LoadProgressStateChangedHandler;
|
||||
device.Processes.ActiveApplication.DiskCacheLoadState.StateChanged += LoadProgressStateChangedHandler;
|
||||
|
||||
try
|
||||
{
|
||||
device.Gpu.Renderer.RunLoop(() =>
|
||||
{
|
||||
_gpuDoneEvent.Reset();
|
||||
device.Gpu.SetGpuThread();
|
||||
device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
||||
|
||||
_isActive = true;
|
||||
|
||||
if (Ryujinx.Common.PlatformInfo.IsBionic)
|
||||
{
|
||||
setRenderingThread();
|
||||
}
|
||||
|
||||
while (_isActive)
|
||||
{
|
||||
if (_isStopped)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (device.WaitFifo())
|
||||
{
|
||||
device.Statistics.RecordFifoStart();
|
||||
device.ProcessFrame();
|
||||
device.Statistics.RecordFifoEnd();
|
||||
}
|
||||
|
||||
while (device.ConsumeFrameAvailable())
|
||||
{
|
||||
device.PresentFrame(() =>
|
||||
{
|
||||
if (device.Gpu.Renderer is ThreadedRenderer threaded && threaded.BaseRenderer is VulkanRenderer vulkanRenderer)
|
||||
{
|
||||
setCurrentTransform(_window, (int)vulkanRenderer.CurrentTransform);
|
||||
}
|
||||
_swapBuffersCallback?.Invoke();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (device.Gpu.Renderer is ThreadedRenderer threaded)
|
||||
{
|
||||
threaded.FlushThreadedCommands();
|
||||
}
|
||||
|
||||
_gpuDoneEvent.Set();
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
device.Gpu.ShaderCacheStateChanged -= LoadProgressStateChangedHandler;
|
||||
device.Processes.ActiveApplication.DiskCacheLoadState.StateChanged -= LoadProgressStateChangedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadProgressStateChangedHandler<T>(T state, int current, int total) where T : Enum
|
||||
{
|
||||
void SetInfo(string status, float value)
|
||||
{
|
||||
if(Ryujinx.Common.PlatformInfo.IsBionic)
|
||||
{
|
||||
Interop.UpdateProgress(status, value);
|
||||
}
|
||||
}
|
||||
var status = $"{current} / {total}";
|
||||
var progress = current / (float)total;
|
||||
if (float.IsNaN(progress))
|
||||
progress = 0;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case LoadState ptcState:
|
||||
if (float.IsNaN((progress)))
|
||||
progress = 0;
|
||||
|
||||
switch (ptcState)
|
||||
{
|
||||
case LoadState.Unloaded:
|
||||
case LoadState.Loading:
|
||||
SetInfo($"Loading PTC {status}", progress);
|
||||
break;
|
||||
case LoadState.Loaded:
|
||||
SetInfo($"PTC Loaded", -1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ShaderCacheState shaderCacheState:
|
||||
switch (shaderCacheState)
|
||||
{
|
||||
case ShaderCacheState.Start:
|
||||
case ShaderCacheState.Loading:
|
||||
SetInfo($"Compiling Shaders {status}", progress);
|
||||
break;
|
||||
case ShaderCacheState.Packaging:
|
||||
SetInfo($"Packaging Shaders {status}", progress);
|
||||
break;
|
||||
case ShaderCacheState.Loaded:
|
||||
SetInfo($"Shaders Loaded", -1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
|
||||
}
|
||||
}
|
||||
|
||||
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 = true;
|
||||
public bool EnableTextureRecompression = false;
|
||||
public BackendThreading BackendThreading = BackendThreading.Auto;
|
||||
public AspectRatio AspectRatio = AspectRatio.Fixed16x9;
|
||||
|
||||
public GraphicsConfiguration()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public struct NativeGraphicsInterop
|
||||
{
|
||||
public IntPtr GlGetProcAddress;
|
||||
public IntPtr VkNativeContextLoader;
|
||||
public IntPtr VkCreateSurface;
|
||||
public IntPtr VkRequiredExtensions;
|
||||
public int VkRequiredExtensionsCount;
|
||||
}
|
||||
}
|
525
src/LibRyujinx/LibRyujinx.Input.cs
Normal file
525
src/LibRyujinx/LibRyujinx.Input.cs
Normal file
@ -0,0 +1,525 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.HLE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
using StickInputId = Ryujinx.Input.StickInputId;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public static partial class LibRyujinx
|
||||
{
|
||||
private static VirtualGamepadDriver? _gamepadDriver;
|
||||
private static VirtualTouchScreen? _virtualTouchScreen;
|
||||
private static VirtualTouchScreenDriver? _touchScreenDriver;
|
||||
private static TouchScreenManager? _touchScreenManager;
|
||||
private static InputManager? _inputManager;
|
||||
private static NpadManager? _npadManager;
|
||||
private static InputConfig[] _configs;
|
||||
|
||||
public static void InitializeInput(int width, int height)
|
||||
{
|
||||
if(SwitchDevice!.InputManager != null)
|
||||
{
|
||||
throw new InvalidOperationException("Input is already initialized");
|
||||
}
|
||||
|
||||
_gamepadDriver = new VirtualGamepadDriver(4);
|
||||
_configs = new InputConfig[4];
|
||||
_virtualTouchScreen = new VirtualTouchScreen();
|
||||
_touchScreenDriver = new VirtualTouchScreenDriver(_virtualTouchScreen);
|
||||
_inputManager = new InputManager(null, _gamepadDriver);
|
||||
_inputManager.SetMouseDriver(_touchScreenDriver);
|
||||
_npadManager = _inputManager.CreateNpadManager();
|
||||
|
||||
SwitchDevice!.InputManager = _inputManager;
|
||||
|
||||
_touchScreenManager = _inputManager.CreateTouchScreenManager();
|
||||
_touchScreenManager.Initialize(SwitchDevice!.EmulationContext);
|
||||
|
||||
_npadManager.Initialize(SwitchDevice.EmulationContext, new List<InputConfig>(), false, false);
|
||||
|
||||
_virtualTouchScreen.ClientSize = new Size(width, height);
|
||||
}
|
||||
|
||||
public static void SetClientSize(int width, int height)
|
||||
{
|
||||
_virtualTouchScreen!.ClientSize = new Size(width, height);
|
||||
}
|
||||
|
||||
public static void SetTouchPoint(int x, int y)
|
||||
{
|
||||
_virtualTouchScreen?.SetPosition(x, y);
|
||||
}
|
||||
|
||||
public static void ReleaseTouchPoint()
|
||||
{
|
||||
_virtualTouchScreen?.ReleaseTouch();
|
||||
}
|
||||
|
||||
public static void SetButtonPressed(GamepadButtonInputId button, int id)
|
||||
{
|
||||
_gamepadDriver?.SetButtonPressed(button, id);
|
||||
}
|
||||
|
||||
public static void SetButtonReleased(GamepadButtonInputId button, int id)
|
||||
{
|
||||
_gamepadDriver?.SetButtonReleased(button, id);
|
||||
}
|
||||
|
||||
public static void SetAccelerometerData(Vector3 accel, int id)
|
||||
{
|
||||
_gamepadDriver?.SetAccelerometerData(accel, id);
|
||||
}
|
||||
|
||||
public static void SetGryoData(Vector3 gyro, int id)
|
||||
{
|
||||
_gamepadDriver?.SetGryoData(gyro, id);
|
||||
}
|
||||
|
||||
public static void SetStickAxis(StickInputId stick, Vector2 axes, int deviceId)
|
||||
{
|
||||
_gamepadDriver?.SetStickAxis(stick, axes, deviceId);
|
||||
}
|
||||
|
||||
public static int ConnectGamepad(int index)
|
||||
{
|
||||
var gamepad = _gamepadDriver?.GetGamepad(index);
|
||||
if (gamepad != null)
|
||||
{
|
||||
var config = CreateDefaultInputConfig();
|
||||
|
||||
config.Id = gamepad.Id;
|
||||
config.PlayerIndex = (PlayerIndex)index;
|
||||
|
||||
_configs[index] = config;
|
||||
}
|
||||
|
||||
_npadManager?.ReloadConfiguration(_configs.Where(x => x != null).ToList(), false, false);
|
||||
|
||||
return int.TryParse(gamepad?.Id, out var idInt) ? idInt : -1;
|
||||
}
|
||||
|
||||
private static InputConfig CreateDefaultInputConfig()
|
||||
{
|
||||
return new StandardControllerInputConfig
|
||||
{
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.GamepadSDL2,
|
||||
Id = null,
|
||||
ControllerType = ControllerType.ProController,
|
||||
DeadzoneLeft = 0.1f,
|
||||
DeadzoneRight = 0.1f,
|
||||
RangeLeft = 1.0f,
|
||||
RangeRight = 1.0f,
|
||||
TriggerThreshold = 0.5f,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
DpadUp = ConfigGamepadInputId.DpadUp,
|
||||
DpadDown = ConfigGamepadInputId.DpadDown,
|
||||
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
||||
DpadRight = ConfigGamepadInputId.DpadRight,
|
||||
ButtonMinus = ConfigGamepadInputId.Minus,
|
||||
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
||||
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||
},
|
||||
|
||||
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||
{
|
||||
Joystick = ConfigStickInputId.Left,
|
||||
StickButton = ConfigGamepadInputId.LeftStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
ButtonA = ConfigGamepadInputId.A,
|
||||
ButtonB = ConfigGamepadInputId.B,
|
||||
ButtonX = ConfigGamepadInputId.X,
|
||||
ButtonY = ConfigGamepadInputId.Y,
|
||||
ButtonPlus = ConfigGamepadInputId.Plus,
|
||||
ButtonR = ConfigGamepadInputId.RightShoulder,
|
||||
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||
},
|
||||
|
||||
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||
{
|
||||
Joystick = ConfigStickInputId.Right,
|
||||
StickButton = ConfigGamepadInputId.RightStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
Motion = new StandardMotionConfigController
|
||||
{
|
||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||
EnableMotion = true,
|
||||
Sensitivity = 100,
|
||||
GyroDeadzone = 1,
|
||||
},
|
||||
Rumble = new RumbleConfigController
|
||||
{
|
||||
StrongRumble = 1f,
|
||||
WeakRumble = 1f,
|
||||
EnableRumble = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void UpdateInput()
|
||||
{
|
||||
_npadManager?.Update(GraphicsConfiguration.AspectRatio.ToFloat());
|
||||
|
||||
if(!_touchScreenManager!.Update(true, _virtualTouchScreen!.IsButtonPressed(MouseButton.Button1), GraphicsConfiguration.AspectRatio.ToFloat()))
|
||||
{
|
||||
SwitchDevice!.EmulationContext?.Hid.Touchscreen.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class VirtualTouchScreen : IMouse
|
||||
{
|
||||
public Size ClientSize { get; set; }
|
||||
|
||||
public bool[] Buttons { get; }
|
||||
|
||||
public VirtualTouchScreen()
|
||||
{
|
||||
Buttons = new bool[2];
|
||||
}
|
||||
|
||||
public Vector2 CurrentPosition { get; private set; }
|
||||
public Vector2 Scroll { get; private set; }
|
||||
public string Id => "0";
|
||||
public string Name => "AvaloniaMouse";
|
||||
|
||||
public bool IsConnected => true;
|
||||
public GamepadFeaturesFlag Features => throw new NotImplementedException();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetMappedStateSnapshot()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetPosition(int x, int y)
|
||||
{
|
||||
CurrentPosition = new Vector2(x, y);
|
||||
|
||||
Buttons[0] = true;
|
||||
}
|
||||
|
||||
public void ReleaseTouch()
|
||||
{
|
||||
Buttons[0] = false;
|
||||
}
|
||||
|
||||
public Vector3 GetMotionData(MotionInputId inputId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Vector2 GetPosition()
|
||||
{
|
||||
return CurrentPosition;
|
||||
}
|
||||
|
||||
public Vector2 GetScroll()
|
||||
{
|
||||
return Scroll;
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetStateSnapshot()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public (float, float) GetStick(Ryujinx.Input.StickInputId inputId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsButtonPressed(MouseButton button)
|
||||
{
|
||||
return Buttons[0];
|
||||
}
|
||||
|
||||
public bool IsPressed(GamepadButtonInputId inputId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfiguration(InputConfig configuration)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetTriggerThreshold(float triggerThreshold)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class VirtualTouchScreenDriver : IGamepadDriver
|
||||
{
|
||||
private readonly VirtualTouchScreen _virtualTouchScreen;
|
||||
|
||||
public VirtualTouchScreenDriver(VirtualTouchScreen virtualTouchScreen)
|
||||
{
|
||||
_virtualTouchScreen = virtualTouchScreen;
|
||||
}
|
||||
|
||||
public string DriverName => "VirtualTouchDriver";
|
||||
|
||||
public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
|
||||
|
||||
|
||||
public event Action<string> OnGamepadConnected
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public event Action<string> OnGamepadDisconnected
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IGamepad GetGamepad(string id)
|
||||
{
|
||||
return _virtualTouchScreen;
|
||||
}
|
||||
}
|
||||
|
||||
public class VirtualGamepadDriver : IGamepadDriver
|
||||
{
|
||||
private readonly int _controllerCount;
|
||||
|
||||
public ReadOnlySpan<string> GamepadsIds => _gamePads.Keys.Select(x => x.ToString()).ToArray();
|
||||
|
||||
public string DriverName => "Virtual";
|
||||
|
||||
public event Action<string> OnGamepadConnected;
|
||||
public event Action<string> OnGamepadDisconnected;
|
||||
|
||||
private Dictionary<int, VirtualGamepad> _gamePads;
|
||||
|
||||
public VirtualGamepadDriver(int controllerCount)
|
||||
{
|
||||
_gamePads = new Dictionary<int, VirtualGamepad>();
|
||||
for (int joystickIndex = 0; joystickIndex < controllerCount; joystickIndex++)
|
||||
{
|
||||
HandleJoyStickConnected(joystickIndex);
|
||||
}
|
||||
|
||||
_controllerCount = controllerCount;
|
||||
}
|
||||
|
||||
private void HandleJoyStickConnected(int joystickDeviceId)
|
||||
{
|
||||
_gamePads[joystickDeviceId] = new VirtualGamepad(this, joystickDeviceId);
|
||||
OnGamepadConnected?.Invoke(joystickDeviceId.ToString());
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Simulate a full disconnect when disposing
|
||||
var ids = GamepadsIds;
|
||||
foreach (string id in ids)
|
||||
{
|
||||
OnGamepadDisconnected?.Invoke(id);
|
||||
}
|
||||
|
||||
_gamePads.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
public IGamepad GetGamepad(string id)
|
||||
{
|
||||
return _gamePads[int.Parse(id)];
|
||||
}
|
||||
|
||||
public IGamepad GetGamepad(int index)
|
||||
{
|
||||
return _gamePads[index];
|
||||
}
|
||||
|
||||
public void SetStickAxis(StickInputId stick, Vector2 axes, int deviceId)
|
||||
{
|
||||
if(_gamePads.TryGetValue(deviceId, out var gamePad))
|
||||
{
|
||||
gamePad.StickInputs[(int)stick] = axes;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetButtonPressed(GamepadButtonInputId button, int deviceId)
|
||||
{
|
||||
if (_gamePads.TryGetValue(deviceId, out var gamePad))
|
||||
{
|
||||
gamePad.ButtonInputs[(int)button] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetButtonReleased(GamepadButtonInputId button, int deviceId)
|
||||
{
|
||||
if (_gamePads.TryGetValue(deviceId, out var gamePad))
|
||||
{
|
||||
gamePad.ButtonInputs[(int)button] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAccelerometerData(Vector3 accel, int deviceId)
|
||||
{
|
||||
if (_gamePads.TryGetValue(deviceId, out var gamePad))
|
||||
{
|
||||
gamePad.Accelerometer = accel;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetGryoData(Vector3 gyro, int deviceId)
|
||||
{
|
||||
if (_gamePads.TryGetValue(deviceId, out var gamePad))
|
||||
{
|
||||
gamePad.Gyro = gyro;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class VirtualGamepad : IGamepad
|
||||
{
|
||||
private readonly VirtualGamepadDriver _driver;
|
||||
|
||||
private bool[] _buttonInputs;
|
||||
|
||||
private Vector2[] _stickInputs;
|
||||
|
||||
public VirtualGamepad(VirtualGamepadDriver driver, int id)
|
||||
{
|
||||
_buttonInputs = new bool[(int)GamepadButtonInputId.Count];
|
||||
_stickInputs = new Vector2[(int)StickInputId.Count];
|
||||
_driver = driver;
|
||||
Id = id.ToString();
|
||||
IdInt = id;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public GamepadFeaturesFlag Features { get; } = GamepadFeaturesFlag.Motion;
|
||||
public string Id { get; }
|
||||
|
||||
internal readonly int IdInt;
|
||||
|
||||
public string Name => Id;
|
||||
public bool IsConnected { get; }
|
||||
public Vector2[] StickInputs { get => _stickInputs; set => _stickInputs = value; }
|
||||
public bool[] ButtonInputs { get => _buttonInputs; set => _buttonInputs = value; }
|
||||
public Vector3 Accelerometer { get; internal set; }
|
||||
public Vector3 Gyro { get; internal set; }
|
||||
|
||||
public bool IsPressed(GamepadButtonInputId inputId)
|
||||
{
|
||||
return _buttonInputs[(int)inputId];
|
||||
}
|
||||
|
||||
public (float, float) GetStick(StickInputId inputId)
|
||||
{
|
||||
var v = _stickInputs[(int)inputId];
|
||||
|
||||
return (v.X, v.Y);
|
||||
}
|
||||
|
||||
public Vector3 GetMotionData(MotionInputId inputId)
|
||||
{
|
||||
if (inputId == MotionInputId.Accelerometer)
|
||||
return Accelerometer;
|
||||
else if (inputId == MotionInputId.Gyroscope)
|
||||
return RadToDegree(Gyro);
|
||||
return new Vector3();
|
||||
}
|
||||
|
||||
private static Vector3 RadToDegree(Vector3 rad)
|
||||
{
|
||||
return rad * (180 / MathF.PI);
|
||||
}
|
||||
|
||||
public void SetTriggerThreshold(float triggerThreshold)
|
||||
{
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfiguration(InputConfig configuration)
|
||||
{
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||
{
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetMappedStateSnapshot()
|
||||
{
|
||||
GamepadStateSnapshot result = default;
|
||||
|
||||
foreach (var button in Enum.GetValues<GamepadButtonInputId>())
|
||||
{
|
||||
// Do not touch state of button already pressed
|
||||
if (button != GamepadButtonInputId.Count && !result.IsPressed(button))
|
||||
{
|
||||
result.SetPressed(button, IsPressed(button));
|
||||
}
|
||||
}
|
||||
|
||||
(float leftStickX, float leftStickY) = GetStick(StickInputId.Left);
|
||||
(float rightStickX, float rightStickY) = GetStick(StickInputId.Right);
|
||||
|
||||
result.SetStick(StickInputId.Left, leftStickX, leftStickY);
|
||||
result.SetStick(StickInputId.Right, rightStickX, rightStickY);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetStateSnapshot()
|
||||
{
|
||||
return new GamepadStateSnapshot();
|
||||
}
|
||||
}
|
||||
}
|
455
src/LibRyujinx/LibRyujinx.Native.cs
Normal file
455
src/LibRyujinx/LibRyujinx.Native.cs
Normal file
@ -0,0 +1,455 @@
|
||||
using LibRyujinx.Shared;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public static partial class LibRyujinx
|
||||
{
|
||||
private unsafe static IntPtr CreateStringArray(List<string> strings)
|
||||
{
|
||||
uint size = (uint)(Marshal.SizeOf<IntPtr>() * (strings.Count + 1));
|
||||
var array = (char**)Marshal.AllocHGlobal((int)size);
|
||||
Unsafe.InitBlockUnaligned(array, 0, size);
|
||||
|
||||
for (int i = 0; i < strings.Count; i++)
|
||||
{
|
||||
array[i] = (char*)Marshal.StringToHGlobalAnsi(strings[i]);
|
||||
}
|
||||
|
||||
return (nint)array;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_initialize")]
|
||||
public static bool InitializeDeviceNative(bool isHostMapped,
|
||||
bool useHypervisor,
|
||||
SystemLanguage systemLanguage,
|
||||
RegionCode regionCode,
|
||||
bool enableVsync,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableInternetAccess,
|
||||
IntPtr timeZone,
|
||||
bool ignoreMissingServices)
|
||||
{
|
||||
return InitializeDevice(isHostMapped,
|
||||
useHypervisor,
|
||||
systemLanguage,
|
||||
regionCode,
|
||||
enableVsync,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableInternetAccess,
|
||||
Marshal.PtrToStringAnsi(timeZone),
|
||||
ignoreMissingServices);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_reload_file_system")]
|
||||
public static void ReloadFileSystemNative()
|
||||
{
|
||||
SwitchDevice?.ReloadFileSystem();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_load")]
|
||||
public static bool LoadApplicationNative(IntPtr pathPtr)
|
||||
{
|
||||
if (SwitchDevice?.EmulationContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var path = Marshal.PtrToStringAnsi(pathPtr);
|
||||
|
||||
return LoadApplication(path);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_install_firmware")]
|
||||
public static void InstallFirmwareNative(int descriptor, bool isXci)
|
||||
{
|
||||
var stream = OpenFile(descriptor);
|
||||
|
||||
InstallFirmware(stream, isXci);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_installed_firmware_version")]
|
||||
public static IntPtr GetInstalledFirmwareVersionNative()
|
||||
{
|
||||
var result = GetInstalledFirmwareVersion();
|
||||
return Marshal.StringToHGlobalAnsi(result);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "initialize")]
|
||||
public static bool InitializeNative(IntPtr basePathPtr)
|
||||
{
|
||||
var path = Marshal.PtrToStringAnsi(basePathPtr);
|
||||
|
||||
var res = Initialize(path);
|
||||
|
||||
InitializeAudio();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphics_initialize")]
|
||||
public static bool InitializeGraphicsNative(GraphicsConfiguration graphicsConfiguration)
|
||||
{
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
// Yes, macOS not iOS
|
||||
Silk.NET.Core.Loader.SearchPathContainer.Platform = Silk.NET.Core.Loader.UnderlyingPlatform.MacOS;
|
||||
}
|
||||
return InitializeGraphics(graphicsConfiguration);
|
||||
}
|
||||
|
||||
[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());
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphics_renderer_set_size")]
|
||||
public static void SetRendererSizeNative(int width, int height)
|
||||
{
|
||||
SetRendererSize(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);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "graphics_renderer_set_swap_buffer_callback")]
|
||||
public static void SetSwapBuffersCallbackNative(IntPtr swapBuffersCallback)
|
||||
{
|
||||
_swapBuffersCallback = Marshal.GetDelegateForFunctionPointer<SwapBuffersCallback>(swapBuffersCallback);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "get_game_info")]
|
||||
public static GameInfoNative GetGameInfoNative(int descriptor, IntPtr extensionPtr)
|
||||
{
|
||||
var extension = Marshal.PtrToStringAnsi(extensionPtr);
|
||||
var stream = OpenFile(descriptor);
|
||||
|
||||
var gameInfo = GetGameInfo(stream, extension ?? "");
|
||||
|
||||
return gameInfo == null ? default : new GameInfoNative(gameInfo.FileSize, gameInfo.TitleName, gameInfo.TitleId, gameInfo.Developer, gameInfo.Version, gameInfo.Icon);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_initialize")]
|
||||
public static void InitializeInputNative(int width, int height)
|
||||
{
|
||||
InitializeInput(width, height);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_client_size")]
|
||||
public static void SetClientSizeNative(int width, int height)
|
||||
{
|
||||
SetClientSize(width, height);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_touch_point")]
|
||||
public static void SetTouchPointNative(int x, int y)
|
||||
{
|
||||
SetTouchPoint(x, y);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_release_touch_point")]
|
||||
public static void ReleaseTouchPointNative()
|
||||
{
|
||||
ReleaseTouchPoint();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_update")]
|
||||
public static void UpdateInputNative()
|
||||
{
|
||||
UpdateInput();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_button_pressed")]
|
||||
public static void SetButtonPressedNative(GamepadButtonInputId button, int id)
|
||||
{
|
||||
SetButtonPressed(button, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_button_released")]
|
||||
public static void SetButtonReleasedNative(GamepadButtonInputId button, int id)
|
||||
{
|
||||
SetButtonReleased(button, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_accelerometer_data")]
|
||||
public static void SetAccelerometerDataNative(Vector3 accel, int id)
|
||||
{
|
||||
SetAccelerometerData(accel, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_gyro_data")]
|
||||
public static void SetGryoDataNative(Vector3 gyro, int id)
|
||||
{
|
||||
SetGryoData(gyro, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_set_stick_axis")]
|
||||
public static void SetStickAxisNative(StickInputId stick, Vector2 axes, int id)
|
||||
{
|
||||
SetStickAxis(stick, axes, id);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "input_connect_gamepad")]
|
||||
public static IntPtr ConnectGamepadNative(int index)
|
||||
{
|
||||
return ConnectGamepad(index);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_game_fifo")]
|
||||
public static double GetGameInfoNative()
|
||||
{
|
||||
var stats = SwitchDevice?.EmulationContext?.Statistics.GetFifoPercent() ?? 0;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_game_frame_time")]
|
||||
public static double GetGameFrameTimeNative()
|
||||
{
|
||||
var stats = SwitchDevice?.EmulationContext?.Statistics.GetGameFrameTime() ?? 0;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_game_frame_rate")]
|
||||
public static double GetGameFrameRateNative()
|
||||
{
|
||||
var stats = SwitchDevice?.EmulationContext?.Statistics.GetGameFrameRate() ?? 0;
|
||||
|
||||
return stats;
|
||||
}
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_launch_mii_editor")]
|
||||
public static bool LaunchMiiEditAppletNative()
|
||||
{
|
||||
if (SwitchDevice?.EmulationContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return LaunchMiiEditApplet();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_dlc_content_list")]
|
||||
public static IntPtr GetDlcContentListNative(IntPtr pathPtr, long titleId)
|
||||
{
|
||||
var list = GetDlcContentList(Marshal.PtrToStringAnsi(pathPtr) ?? "", (ulong)titleId);
|
||||
|
||||
return CreateStringArray(list);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_dlc_title_id")]
|
||||
public static long GetDlcTitleIdNative(IntPtr pathPtr, IntPtr ncaPath)
|
||||
{
|
||||
return Marshal.StringToHGlobalAnsi(GetDlcTitleId(Marshal.PtrToStringAnsi(pathPtr) ?? "", Marshal.PtrToStringAnsi(ncaPath) ?? ""));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_signal_emulation_close")]
|
||||
public static void SignalEmulationCloseNative()
|
||||
{
|
||||
SignalEmulationClose();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_close_emulation")]
|
||||
public static void CloseEmulationNative()
|
||||
{
|
||||
CloseEmulation();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_load_descriptor")]
|
||||
public static bool LoadApplicationNative(int descriptor, int type, int updateDescriptor)
|
||||
{
|
||||
if (SwitchDevice?.EmulationContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stream = OpenFile(descriptor);
|
||||
var update = updateDescriptor == -1 ? null : OpenFile(updateDescriptor);
|
||||
|
||||
return LoadApplication(stream, (FileType)type, update);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_verify_firmware")]
|
||||
public static IntPtr VerifyFirmwareNative(int descriptor, bool isXci)
|
||||
{
|
||||
var stream = OpenFile(descriptor);
|
||||
|
||||
IntPtr stringHandle = 0;
|
||||
string? version = "0.0";
|
||||
|
||||
try
|
||||
{
|
||||
version = VerifyFirmware(stream, isXci)?.VersionString;
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Service, $"Unable to verify firmware. Exception: {_}");
|
||||
}
|
||||
|
||||
if (version != null)
|
||||
{
|
||||
stringHandle = Marshal.StringToHGlobalAnsi(version);
|
||||
}
|
||||
|
||||
return stringHandle;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "logging_set_enabled")]
|
||||
public static void SetLoggingEnabledNative(int logLevel, bool enabled)
|
||||
{
|
||||
Logger.SetEnable((LogLevel)logLevel, enabled);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "logging_enabled_graphics_log")]
|
||||
public static void SetLoggingEnabledGraphicsLogNative(bool enabled)
|
||||
{
|
||||
_enableGraphicsLogging = enabled;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "device_get_game_info")]
|
||||
public unsafe static void GetGameInfoNative(int fileDescriptor, IntPtr extension, IntPtr infoPtr)
|
||||
{
|
||||
using var stream = OpenFile(fileDescriptor);
|
||||
var ext = Marshal.PtrToStringAnsi(extension);
|
||||
var info = GetGameInfo(stream, ext.ToLower()) ?? GetDefaultInfo(stream);
|
||||
var i = (GameInfoNative*)infoPtr;
|
||||
var n = new GameInfoNative(info);
|
||||
i->TitleId = n.TitleId;
|
||||
i->TitleName = n.TitleName;
|
||||
i->Version = n.Version;
|
||||
i->FileSize = n.FileSize;
|
||||
i->Icon = n.Icon;
|
||||
i->Version = n.Version;
|
||||
i->Developer = n.Developer;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_get_opened_user")]
|
||||
public static IntPtr GetOpenedUserNative()
|
||||
{
|
||||
var userId = GetOpenedUser();
|
||||
var ptr = Marshal.StringToHGlobalAnsi(userId);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_get_user_picture")]
|
||||
public static IntPtr GetUserPictureNative(IntPtr userIdPtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
return Marshal.StringToHGlobalAnsi(GetUserPicture(userId));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_set_user_picture")]
|
||||
public static void SetUserPictureNative(IntPtr userIdPtr, IntPtr picturePtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
var picture = Marshal.PtrToStringAnsi(picturePtr) ?? "";
|
||||
|
||||
SetUserPicture(userId, picture);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_get_user_name")]
|
||||
public static IntPtr GetUserNameNative(IntPtr userIdPtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
return Marshal.StringToHGlobalAnsi(GetUserName(userId));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_set_user_name")]
|
||||
public static void SetUserNameNative(IntPtr userIdPtr, IntPtr userNamePtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
var userName = Marshal.PtrToStringAnsi(userNamePtr) ?? "";
|
||||
|
||||
SetUserName(userId, userName);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_get_all_users")]
|
||||
public static IntPtr GetAllUsersNative()
|
||||
{
|
||||
var users = GetAllUsers();
|
||||
|
||||
return CreateStringArray(users.ToList());
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_add_user")]
|
||||
public static void AddUserNative(IntPtr userNamePtr, IntPtr picturePtr)
|
||||
{
|
||||
var userName = Marshal.PtrToStringAnsi(userNamePtr) ?? "";
|
||||
var picture = Marshal.PtrToStringAnsi(picturePtr) ?? "";
|
||||
|
||||
AddUser(userName, picture);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_delete_user")]
|
||||
public static void DeleteUserNative(IntPtr userIdPtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
DeleteUser(userId);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_open_user")]
|
||||
public static void OpenUserNative(IntPtr userIdPtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
OpenUser(userId);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "user_close_user")]
|
||||
public static void CloseUserNative(IntPtr userIdPtr)
|
||||
{
|
||||
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
|
||||
|
||||
CloseUser(userId);
|
||||
}
|
||||
}
|
||||
}
|
82
src/LibRyujinx/LibRyujinx.User.cs
Normal file
82
src/LibRyujinx/LibRyujinx.User.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public static partial class LibRyujinx
|
||||
{
|
||||
public static string GetOpenedUser()
|
||||
{
|
||||
var lastProfile = SwitchDevice?.AccountManager.LastOpenedUser;
|
||||
|
||||
return lastProfile?.UserId.ToString() ?? "";
|
||||
}
|
||||
|
||||
public static string GetUserPicture(string userId)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
|
||||
var user = SwitchDevice?.AccountManager.GetAllUsers().FirstOrDefault(x => x.UserId == uid);
|
||||
|
||||
if (user == null)
|
||||
return "";
|
||||
|
||||
var pic = user.Image;
|
||||
|
||||
return pic != null ? Convert.ToBase64String(pic) : "";
|
||||
}
|
||||
|
||||
public static void SetUserPicture(string userId, string picture)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
|
||||
SwitchDevice?.AccountManager.SetUserImage(uid, Convert.FromBase64String(picture));
|
||||
}
|
||||
|
||||
public static string GetUserName(string userId)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
|
||||
var user = SwitchDevice?.AccountManager.GetAllUsers().FirstOrDefault(x => x.UserId == uid);
|
||||
|
||||
return user?.Name ?? "";
|
||||
}
|
||||
|
||||
public static void SetUserName(string userId, string name)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
|
||||
SwitchDevice?.AccountManager.SetUserName(uid, name);
|
||||
}
|
||||
|
||||
public static string[] GetAllUsers()
|
||||
{
|
||||
return SwitchDevice?.AccountManager.GetAllUsers().Select(x => x.UserId.ToString()).ToArray() ??
|
||||
Array.Empty<string>();
|
||||
}
|
||||
|
||||
public static void AddUser(string userName, string picture)
|
||||
{
|
||||
SwitchDevice?.AccountManager.AddUser(userName, Convert.FromBase64String(picture));
|
||||
}
|
||||
|
||||
public static void DeleteUser(string userId)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
SwitchDevice?.AccountManager.DeleteUser(uid);
|
||||
}
|
||||
|
||||
public static void OpenUser(string userId)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
SwitchDevice?.AccountManager.OpenUser(uid);
|
||||
}
|
||||
|
||||
public static void CloseUser(string userId)
|
||||
{
|
||||
var uid = new UserId(userId);
|
||||
SwitchDevice?.AccountManager.CloseUser(uid);
|
||||
}
|
||||
}
|
||||
}
|
852
src/LibRyujinx/LibRyujinx.cs
Normal file
852
src/LibRyujinx/LibRyujinx.cs
Normal file
@ -0,0 +1,852 @@
|
||||
// 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;
|
||||
using Ryujinx.Audio.Integration;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
using System.IO;
|
||||
using LibHac.Common.Keys;
|
||||
using LibHac.Common;
|
||||
using LibHac.Ns;
|
||||
using LibHac.Tools.Fs;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Fs;
|
||||
using Path = System.IO.Path;
|
||||
using LibHac;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using Ryujinx.HLE.Loaders.Npdm;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.Globalization;
|
||||
using Ryujinx.UI.Common.Configuration.System;
|
||||
using Ryujinx.Common.Logging.Targets;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Ryujinx.HLE.UI;
|
||||
using LibRyujinx.Android;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public static partial class LibRyujinx
|
||||
{
|
||||
internal static IHardwareDeviceDriver AudioDriver { get; set; } = new DummyHardwareDeviceDriver();
|
||||
|
||||
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
public static SwitchDevice? SwitchDevice { get; set; }
|
||||
|
||||
public static bool Initialize(string? basePath)
|
||||
{
|
||||
if (SwitchDevice != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AppDataManager.Initialize(basePath);
|
||||
|
||||
ConfigurationState.Initialize();
|
||||
LoggerModule.Initialize();
|
||||
|
||||
string logDir = Path.Combine(AppDataManager.BaseDirPath, "Logs");
|
||||
FileStream logFile = FileLogTarget.PrepareLogFile(logDir);
|
||||
Logger.AddTarget(new AsyncLogTargetWrapper(
|
||||
new FileLogTarget("file", logFile),
|
||||
1000,
|
||||
AsyncLogTargetOverflowAction.Block
|
||||
));
|
||||
|
||||
Logger.Notice.Print(LogClass.Application, "Initializing...");
|
||||
Logger.Notice.Print(LogClass.Application, $"Using base path: {AppDataManager.BaseDirPath}");
|
||||
|
||||
SwitchDevice = new SwitchDevice();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
OpenALLibraryNameContainer.OverridePath = "libopenal.so";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void InitializeAudio()
|
||||
{
|
||||
AudioDriver = new SDL2HardwareDeviceDriver();
|
||||
}
|
||||
|
||||
public static GameStats GetGameStats()
|
||||
{
|
||||
if (SwitchDevice?.EmulationContext == null)
|
||||
return new GameStats();
|
||||
|
||||
var context = SwitchDevice.EmulationContext;
|
||||
|
||||
return new GameStats
|
||||
{
|
||||
Fifo = context.Statistics.GetFifoPercent(),
|
||||
GameFps = context.Statistics.GetGameFrameRate(),
|
||||
GameTime = context.Statistics.GetGameFrameTime()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static GameInfo? GetGameInfo(string? file)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(file))
|
||||
{
|
||||
return new GameInfo();
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"Getting game info for file: {file}");
|
||||
|
||||
using var stream = File.Open(file, FileMode.Open);
|
||||
|
||||
return GetGameInfo(stream, new FileInfo(file).Extension.Remove('.'));
|
||||
}
|
||||
|
||||
public static GameInfo? GetGameInfo(Stream gameStream, string extension)
|
||||
{
|
||||
if (SwitchDevice == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "SwitchDevice is not initialized.");
|
||||
return null;
|
||||
}
|
||||
GameInfo gameInfo = GetDefaultInfo(gameStream);
|
||||
|
||||
const Language TitleLanguage = Language.AmericanEnglish;
|
||||
|
||||
BlitStruct<ApplicationControlProperty> controlHolder = new(1);
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (extension == "nsp" || extension == "pfs0" || extension == "xci")
|
||||
{
|
||||
IFileSystem pfs;
|
||||
|
||||
bool isExeFs = false;
|
||||
|
||||
if (extension == "xci")
|
||||
{
|
||||
Xci xci = new(SwitchDevice.VirtualFileSystem.KeySet, gameStream.AsStorage());
|
||||
|
||||
pfs = xci.OpenPartition(XciPartitionType.Secure);
|
||||
}
|
||||
else
|
||||
{
|
||||
var pfsTemp = new PartitionFileSystem();
|
||||
pfsTemp.Initialize(gameStream.AsStorage()).ThrowIfFailure();
|
||||
pfs = pfsTemp;
|
||||
|
||||
// If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
|
||||
bool hasMainNca = false;
|
||||
|
||||
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
|
||||
{
|
||||
if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca")
|
||||
{
|
||||
using UniqueRef<IFile> ncaFile = new();
|
||||
|
||||
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = new(SwitchDevice.VirtualFileSystem.KeySet, ncaFile.Get.AsStorage());
|
||||
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
|
||||
|
||||
// Some main NCAs don't have a data partition, so check if the partition exists before opening it
|
||||
if (nca.Header.ContentType == NcaContentType.Program && !(nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
|
||||
{
|
||||
hasMainNca = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
|
||||
{
|
||||
isExeFs = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasMainNca && !isExeFs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (isExeFs)
|
||||
{
|
||||
using UniqueRef<IFile> npdmFile = new();
|
||||
|
||||
Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read);
|
||||
|
||||
if (ResultFs.PathNotFound.Includes(result))
|
||||
{
|
||||
Npdm npdm = new(npdmFile.Get.AsStream());
|
||||
|
||||
gameInfo.TitleName = npdm.TitleName;
|
||||
gameInfo.TitleId = npdm.Aci0.TitleId.ToString("x16");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetControlFsAndTitleId(pfs, out IFileSystem? controlFs, out string? id);
|
||||
|
||||
gameInfo.TitleId = id;
|
||||
|
||||
if (controlFs == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"No control FS was returned. Unable to process game any further: {gameInfo.TitleName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if there is an update available.
|
||||
if (IsUpdateApplied(gameInfo.TitleId, out IFileSystem? updatedControlFs))
|
||||
{
|
||||
// Replace the original ControlFs by the updated one.
|
||||
controlFs = updatedControlFs;
|
||||
}
|
||||
|
||||
ReadControlData(controlFs, controlHolder.ByteSpan);
|
||||
|
||||
GetGameInformation(ref controlHolder.Value, out gameInfo.TitleName, out _, out gameInfo.Developer, out gameInfo.Version);
|
||||
|
||||
// Read the icon from the ControlFS and store it as a byte array
|
||||
try
|
||||
{
|
||||
using UniqueRef<IFile> icon = new();
|
||||
|
||||
controlFs?.OpenFile(ref icon.Ref, $"/icon_{TitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
|
||||
icon.Get.AsStream().CopyTo(stream);
|
||||
gameInfo.Icon = stream.ToArray();
|
||||
}
|
||||
catch (HorizonResultException)
|
||||
{
|
||||
foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
|
||||
{
|
||||
if (entry.Name == "control.nacp")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var icon = new UniqueRef<IFile>();
|
||||
|
||||
controlFs?.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
|
||||
icon.Get.AsStream().CopyTo(stream);
|
||||
gameInfo.Icon = stream.ToArray();
|
||||
|
||||
if (gameInfo.Icon != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (extension == "nro")
|
||||
{
|
||||
BinaryReader reader = new(gameStream);
|
||||
|
||||
byte[] Read(long position, int size)
|
||||
{
|
||||
gameStream.Seek(position, SeekOrigin.Begin);
|
||||
|
||||
return reader.ReadBytes(size);
|
||||
}
|
||||
|
||||
gameStream.Seek(24, SeekOrigin.Begin);
|
||||
|
||||
int assetOffset = reader.ReadInt32();
|
||||
|
||||
if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
|
||||
{
|
||||
byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
|
||||
|
||||
long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
|
||||
long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
|
||||
|
||||
ulong nacpOffset = reader.ReadUInt64();
|
||||
ulong nacpSize = reader.ReadUInt64();
|
||||
|
||||
// Reads and stores game icon as byte array
|
||||
if (iconSize > 0)
|
||||
{
|
||||
gameInfo.Icon = Read(assetOffset + iconOffset, (int)iconSize);
|
||||
}
|
||||
|
||||
// Read the NACP data
|
||||
Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);
|
||||
|
||||
GetGameInformation(ref controlHolder.Value, out gameInfo.TitleName, out _, out gameInfo.Developer, out gameInfo.Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MissingKeyException exception)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
|
||||
}
|
||||
catch (InvalidDataException exception)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. {exception}");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"The gameStream encountered was not of a valid type. Error: {exception}");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, exception.Message);
|
||||
}
|
||||
|
||||
void ReadControlData(IFileSystem? controlFs, Span<byte> outProperty)
|
||||
{
|
||||
using UniqueRef<IFile> controlFile = new();
|
||||
|
||||
controlFs?.OpenFile(ref controlFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
controlFile.Get.Read(out _, 0, outProperty, ReadOption.None).ThrowIfFailure();
|
||||
}
|
||||
|
||||
void GetGameInformation(ref ApplicationControlProperty controlData, out string? titleName, out string titleId, out string? publisher, out string? version)
|
||||
{
|
||||
_ = Enum.TryParse(TitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);
|
||||
|
||||
if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage)
|
||||
{
|
||||
titleName = controlData.Title[(int)desiredTitleLanguage].NameString.ToString();
|
||||
publisher = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
titleName = null;
|
||||
publisher = null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(titleName))
|
||||
{
|
||||
foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
|
||||
{
|
||||
if (!controlTitle.NameString.IsEmpty())
|
||||
{
|
||||
titleName = controlTitle.NameString.ToString();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(publisher))
|
||||
{
|
||||
foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
|
||||
{
|
||||
if (!controlTitle.PublisherString.IsEmpty())
|
||||
{
|
||||
publisher = controlTitle.PublisherString.ToString();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (controlData.PresenceGroupId != 0)
|
||||
{
|
||||
titleId = controlData.PresenceGroupId.ToString("x16");
|
||||
}
|
||||
else if (controlData.SaveDataOwnerId != 0)
|
||||
{
|
||||
titleId = controlData.SaveDataOwnerId.ToString();
|
||||
}
|
||||
else if (controlData.AddOnContentBaseId != 0)
|
||||
{
|
||||
titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
|
||||
}
|
||||
else
|
||||
{
|
||||
titleId = "0000000000000000";
|
||||
}
|
||||
|
||||
version = controlData.DisplayVersionString.ToString();
|
||||
}
|
||||
|
||||
void GetControlFsAndTitleId(IFileSystem pfs, out IFileSystem? controlFs, out string? titleId)
|
||||
{
|
||||
if (SwitchDevice == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "SwitchDevice is not initialized.");
|
||||
|
||||
controlFs = null;
|
||||
titleId = null;
|
||||
return;
|
||||
}
|
||||
(_, _, Nca? controlNca) = GetGameData(SwitchDevice.VirtualFileSystem, pfs, 0);
|
||||
|
||||
if (controlNca == null)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "Control NCA is null. Unable to load control FS.");
|
||||
}
|
||||
|
||||
// Return the ControlFS
|
||||
controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
|
||||
titleId = controlNca?.Header.TitleId.ToString("x16");
|
||||
}
|
||||
|
||||
(Nca? mainNca, Nca? patchNca, Nca? controlNca) GetGameData(VirtualFileSystem fileSystem, IFileSystem pfs, int programIndex)
|
||||
{
|
||||
Nca? mainNca = null;
|
||||
Nca? patchNca = null;
|
||||
Nca? controlNca = null;
|
||||
|
||||
fileSystem.ImportTickets(pfs);
|
||||
|
||||
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
|
||||
{
|
||||
using var ncaFile = new UniqueRef<IFile>();
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"Loading file from PFS: {fileEntry.FullPath}");
|
||||
|
||||
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
|
||||
|
||||
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
|
||||
|
||||
if (ncaProgramIndex != programIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nca.Header.ContentType == NcaContentType.Program)
|
||||
{
|
||||
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
|
||||
|
||||
if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
|
||||
{
|
||||
patchNca = nca;
|
||||
}
|
||||
else
|
||||
{
|
||||
mainNca = nca;
|
||||
}
|
||||
}
|
||||
else if (nca.Header.ContentType == NcaContentType.Control)
|
||||
{
|
||||
controlNca = nca;
|
||||
}
|
||||
}
|
||||
|
||||
return (mainNca, patchNca, controlNca);
|
||||
}
|
||||
|
||||
bool IsUpdateApplied(string? titleId, out IFileSystem? updatedControlFs)
|
||||
{
|
||||
updatedControlFs = null;
|
||||
|
||||
string? updatePath = "(unknown)";
|
||||
|
||||
if (SwitchDevice?.VirtualFileSystem == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "SwitchDevice was not initialized.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
(Nca? patchNca, Nca? controlNca) = GetGameUpdateData(SwitchDevice.VirtualFileSystem, titleId, 0, out updatePath);
|
||||
|
||||
if (patchNca != null && controlNca != null)
|
||||
{
|
||||
updatedControlFs = controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {updatePath}");
|
||||
}
|
||||
catch (MissingKeyException exception)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
(Nca? patch, Nca? control) GetGameUpdateData(VirtualFileSystem fileSystem, string? titleId, int programIndex, out string? updatePath)
|
||||
{
|
||||
updatePath = null;
|
||||
|
||||
if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdBase))
|
||||
{
|
||||
// Clear the program index part.
|
||||
titleIdBase &= ~0xFUL;
|
||||
|
||||
// Load update information if exists.
|
||||
string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json");
|
||||
|
||||
if (File.Exists(titleUpdateMetadataPath))
|
||||
{
|
||||
updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
|
||||
|
||||
if (File.Exists(updatePath))
|
||||
{
|
||||
FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
|
||||
PartitionFileSystem nsp = new();
|
||||
nsp.Initialize(file.AsStorage()).ThrowIfFailure();
|
||||
|
||||
return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
(Nca? patchNca, Nca? controlNca) GetGameUpdateDataFromPartition(VirtualFileSystem fileSystem, PartitionFileSystem pfs, string titleId, int programIndex)
|
||||
{
|
||||
Nca? patchNca = null;
|
||||
Nca? controlNca = null;
|
||||
|
||||
fileSystem.ImportTickets(pfs);
|
||||
|
||||
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
|
||||
{
|
||||
using var ncaFile = new UniqueRef<IFile>();
|
||||
|
||||
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage());
|
||||
|
||||
int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);
|
||||
|
||||
if (ncaProgramIndex != programIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (nca.Header.ContentType == NcaContentType.Program)
|
||||
{
|
||||
patchNca = nca;
|
||||
}
|
||||
else if (nca.Header.ContentType == NcaContentType.Control)
|
||||
{
|
||||
controlNca = nca;
|
||||
}
|
||||
}
|
||||
|
||||
return (patchNca, controlNca);
|
||||
}
|
||||
|
||||
return gameInfo;
|
||||
}
|
||||
|
||||
private static GameInfo GetDefaultInfo(Stream gameStream)
|
||||
{
|
||||
return new GameInfo
|
||||
{
|
||||
FileSize = gameStream.Length * 0.000000000931,
|
||||
TitleName = "Unknown",
|
||||
TitleId = "0000000000000000",
|
||||
Developer = "Unknown",
|
||||
Version = "0",
|
||||
Icon = null
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetDlcTitleId(string path, string ncaPath)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
using FileStream containerFile = File.OpenRead(path);
|
||||
|
||||
PartitionFileSystem partitionFileSystem = new();
|
||||
partitionFileSystem.Initialize(containerFile.AsStorage()).ThrowIfFailure();
|
||||
|
||||
SwitchDevice.VirtualFileSystem.ImportTickets(partitionFileSystem);
|
||||
|
||||
using UniqueRef<IFile> ncaFile = new();
|
||||
|
||||
partitionFileSystem.OpenFile(ref ncaFile.Ref, ncaPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), ncaPath);
|
||||
if (nca != null)
|
||||
{
|
||||
return nca.Header.TitleId.ToString("X16");
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
private static Nca TryOpenNca(IStorage ncaStorage, string containerPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Nca(SwitchDevice.VirtualFileSystem.KeySet, ncaStorage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<string> GetDlcContentList(string path, ulong titleId)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return new List<string>();
|
||||
|
||||
using FileStream containerFile = File.OpenRead(path);
|
||||
|
||||
PartitionFileSystem partitionFileSystem = new();
|
||||
partitionFileSystem.Initialize(containerFile.AsStorage()).ThrowIfFailure();
|
||||
|
||||
SwitchDevice.VirtualFileSystem.ImportTickets(partitionFileSystem);
|
||||
List<string> paths = new List<string>();
|
||||
|
||||
foreach (DirectoryEntryEx fileEntry in partitionFileSystem.EnumerateEntries("/", "*.nca"))
|
||||
{
|
||||
using var ncaFile = new UniqueRef<IFile>();
|
||||
|
||||
partitionFileSystem.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), path);
|
||||
if (nca == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nca.Header.ContentType == NcaContentType.PublicData)
|
||||
{
|
||||
if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000) != titleId)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
paths.Add(fileEntry.FullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
public static void SetupUiHandler()
|
||||
{
|
||||
if (SwitchDevice is { } switchDevice)
|
||||
{
|
||||
switchDevice.HostUiHandler = new AndroidUIHandler();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetUiHandlerResponse(bool isOkPressed, string input)
|
||||
{
|
||||
if (SwitchDevice?.HostUiHandler is AndroidUIHandler uiHandler)
|
||||
{
|
||||
uiHandler.SetResponse(isOkPressed, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SwitchDevice : IDisposable
|
||||
{
|
||||
private readonly SystemVersion _firmwareVersion;
|
||||
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 IHostUIHandler? HostUiHandler { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
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();
|
||||
|
||||
_firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
|
||||
|
||||
if (_firmwareVersion != null)
|
||||
{
|
||||
Logger.Notice.Print(LogClass.Application, $"System Firmware Version: {_firmwareVersion.VersionString}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Notice.Print(LogClass.Application, $"System Firmware not installed");
|
||||
}
|
||||
}
|
||||
|
||||
public bool InitializeContext(bool isHostMapped,
|
||||
bool useHypervisor,
|
||||
SystemLanguage systemLanguage,
|
||||
RegionCode regionCode,
|
||||
bool enableVsync,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableInternetAccess,
|
||||
string? timeZone,
|
||||
bool ignoreMissingServices)
|
||||
{
|
||||
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,
|
||||
LibRyujinx.AudioDriver, //Audio
|
||||
MemoryConfiguration.MemoryConfiguration4GiB,
|
||||
HostUiHandler,
|
||||
systemLanguage,
|
||||
regionCode,
|
||||
enableVsync,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableInternetAccess,
|
||||
IntegrityCheckLevel.None,
|
||||
0,
|
||||
0,
|
||||
timeZone,
|
||||
isHostMapped ? MemoryManagerMode.HostMappedUnsafe : MemoryManagerMode.SoftwarePageTable,
|
||||
ignoreMissingServices,
|
||||
LibRyujinx.GraphicsConfiguration.AspectRatio,
|
||||
100,
|
||||
useHypervisor,
|
||||
"",
|
||||
Ryujinx.Common.Configuration.Multiplayer.MultiplayerMode.Disabled);
|
||||
|
||||
EmulationContext = new Switch(configuration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void ReloadFileSystem()
|
||||
{
|
||||
VirtualFileSystem.ReloadKeySet();
|
||||
ContentManager = new ContentManager(VirtualFileSystem);
|
||||
AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient);
|
||||
}
|
||||
|
||||
internal void DisposeContext()
|
||||
{
|
||||
EmulationContext?.Dispose();
|
||||
EmulationContext?.DisposeGpu();
|
||||
EmulationContext = null;
|
||||
LibRyujinx.Renderer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class GameInfo
|
||||
{
|
||||
public double FileSize;
|
||||
public string? TitleName;
|
||||
public string? TitleId;
|
||||
public string? Developer;
|
||||
public string? Version;
|
||||
public byte[]? Icon;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct GameInfoNative
|
||||
{
|
||||
public double FileSize;
|
||||
public char* TitleName;
|
||||
public char* TitleId;
|
||||
public char* Developer;
|
||||
public char* Version;
|
||||
public char* Icon;
|
||||
|
||||
public GameInfoNative()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GameInfoNative(double fileSize, string? titleName, string? titleId, string? developer, string? version, byte[]? icon)
|
||||
{
|
||||
FileSize = fileSize;
|
||||
TitleId = (char*)Marshal.StringToHGlobalAnsi(titleId);
|
||||
Version = (char*)Marshal.StringToHGlobalAnsi(version);
|
||||
Developer = (char*)Marshal.StringToHGlobalAnsi(developer);
|
||||
TitleName = (char*)Marshal.StringToHGlobalAnsi(titleName);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
Icon = (char*)Marshal.StringToHGlobalAnsi(Convert.ToBase64String(icon));
|
||||
}
|
||||
else
|
||||
{
|
||||
Icon = (char*)0;
|
||||
}
|
||||
}
|
||||
|
||||
public GameInfoNative(GameInfo info) : this(info.FileSize, info.TitleName, info.TitleId, info.Developer, info.Version, info.Icon){}
|
||||
}
|
||||
|
||||
public class GameStats
|
||||
{
|
||||
public double Fifo;
|
||||
public double GameFps;
|
||||
public double GameTime;
|
||||
}
|
||||
}
|
76
src/LibRyujinx/LibRyujinx.csproj
Normal file
76
src/LibRyujinx/LibRyujinx.csproj
Normal file
@ -0,0 +1,76 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RuntimeIdentifiers>linux-bionic-arm64;ios-arm64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
<LinkerFlavor Condition="'$(RuntimeIdentifier)'=='linux-bionic-arm64'">lld</LinkerFlavor>
|
||||
<DefineConstants>$(DefineConstants);FORCE_EXTERNAL_BASE_DIR</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
|
||||
<!-- Not sure why, but on iOS this results in an error. Result is still a .dylib. -->
|
||||
<NativeLib Condition="'$(RuntimeIdentifier)'=='linux-bionic-arm64'">Shared</NativeLib>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
||||
<IlcInstructionSet>armv8.2-a</IlcInstructionSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<Optimize>true</Optimize>
|
||||
<OptimizationPreference>Speed</OptimizationPreference>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- iOS Linking Fixes -->
|
||||
<Target Condition="'$(RuntimeIdentifier)'=='ios-arm64'" Name="PrepareBeforeIlcCompile" BeforeTargets="IlcCompile">
|
||||
<Exec Command="xcrun xcode-select -p" ConsoleToMSBuild="true">
|
||||
<Output TaskParameter="ConsoleOutput" PropertyName="XcodeSelect" />
|
||||
</Exec>
|
||||
<PropertyGroup>
|
||||
<XcodePath>$(XcodeSelect)</XcodePath>
|
||||
<XcodePath>$([MSBuild]::EnsureTrailingSlash('$(XCodePath)'))</XcodePath>
|
||||
</PropertyGroup>
|
||||
<Message Importance="normal" Text="Found Xcode at $(XcodeSelect)" />
|
||||
<ItemGroup>
|
||||
<LinkerArg Include="-Wl,-ld_classic" />
|
||||
<LinkerArg Include="-isysroot %22$(XcodePath)Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk%22" Condition=" $(RuntimeIdentifier.Contains('simulator')) " />
|
||||
<LinkerArg Include="-isysroot %22$(XcodePath)Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk%22" Condition=" !$(RuntimeIdentifier.Contains('simulator')) " />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Condition="'$(RuntimeIdentifier)'=='ios-arm64'" Name="FixDylib" AfterTargets="Publish">
|
||||
<Exec Command="install_name_tool -id @rpath/$(TargetName).dylib $(NativeBinary)" ConsoleToMSBuild="true" />
|
||||
</Target>
|
||||
<Target Condition="'$(RuntimeIdentifier)'=='ios-arm64'" Name="FixSymbols" AfterTargets="Publish">
|
||||
<RemoveDir Directories="$(PublishDir)$(TargetName).framework.dSYM" />
|
||||
<!-- create-xcframework (called from the export plugin wants the symbol files in a directory
|
||||
with a slightly different name from the one created by dotnet publish, so we copy them over
|
||||
to the correctly-named directory -->
|
||||
<ItemGroup>
|
||||
<SymbolFiles Include="$(NativeBinary).dsym\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(SymbolFiles)" DestinationFolder="$(PublishDir)$(TargetName).framework.dSYM" />
|
||||
</Target>
|
||||
<!-- End iOS Linking Fixes -->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
|
||||
<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>
|
||||
<PackageReference Include="Rxmxnx.PInvoke.Extensions" />
|
||||
<PackageReference Include="Silk.NET.Vulkan" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
|
||||
<LinkerArg Condition="'$(RuntimeIdentifier)'=='linux-bionic-arm64'" Include="-llog" />
|
||||
</ItemGroup>
|
||||
</Project>
|
20
src/LibRyujinx/OpenTKBindingsContext.cs
Normal file
20
src/LibRyujinx/OpenTKBindingsContext.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
98
src/LibRyujinx/VulkanLoader.cs
Normal file
98
src/LibRyujinx/VulkanLoader.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Silk.NET.Core.Contexts;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LibRyujinx
|
||||
{
|
||||
public class VulkanLoader : IDisposable
|
||||
{
|
||||
private delegate IntPtr GetInstanceProcAddress(IntPtr instance, IntPtr name);
|
||||
private delegate IntPtr GetDeviceProcAddress(IntPtr device, IntPtr name);
|
||||
|
||||
private IntPtr _loadedLibrary = IntPtr.Zero;
|
||||
private GetInstanceProcAddress _getInstanceProcAddr;
|
||||
private GetDeviceProcAddress _getDeviceProcAddr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_loadedLibrary != IntPtr.Zero)
|
||||
{
|
||||
NativeLibrary.Free(_loadedLibrary);
|
||||
_loadedLibrary = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public VulkanLoader(IntPtr driver)
|
||||
{
|
||||
_loadedLibrary = driver;
|
||||
|
||||
if (_loadedLibrary != IntPtr.Zero)
|
||||
{
|
||||
var instanceGetProc = NativeLibrary.GetExport(_loadedLibrary, "vkGetInstanceProcAddr");
|
||||
var deviceProc = NativeLibrary.GetExport(_loadedLibrary, "vkGetDeviceProcAddr");
|
||||
|
||||
_getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer<GetInstanceProcAddress>(instanceGetProc);
|
||||
_getDeviceProcAddr = Marshal.GetDelegateForFunctionPointer<GetDeviceProcAddress>(deviceProc);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe Vk GetApi()
|
||||
{
|
||||
|
||||
if (_loadedLibrary == IntPtr.Zero)
|
||||
{
|
||||
return Vk.GetApi();
|
||||
}
|
||||
var ctx = new MultiNativeContext(new INativeContext[1]);
|
||||
var ret = new Vk(ctx);
|
||||
ctx.Contexts[0] = new LamdaNativeContext
|
||||
(
|
||||
x =>
|
||||
{
|
||||
var xPtr = Marshal.StringToHGlobalAnsi(x);
|
||||
byte* xp = (byte*)xPtr;
|
||||
try
|
||||
{
|
||||
nint ptr = default;
|
||||
ptr = _getInstanceProcAddr(ret.CurrentInstance.GetValueOrDefault().Handle, xPtr);
|
||||
|
||||
if (ptr == default)
|
||||
{
|
||||
ptr = _getInstanceProcAddr(IntPtr.Zero, xPtr);
|
||||
|
||||
if (ptr == default)
|
||||
{
|
||||
var currentDevice = ret.CurrentDevice.GetValueOrDefault().Handle;
|
||||
if (currentDevice != IntPtr.Zero)
|
||||
{
|
||||
ptr = _getDeviceProcAddr(currentDevice, xPtr);
|
||||
}
|
||||
|
||||
if (ptr == default)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Gpu, $"Failed to get function pointer: {x}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(xPtr);
|
||||
}
|
||||
}
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
536
src/LibRyujinx/rd.xml
Normal file
536
src/LibRyujinx/rd.xml
Normal file
@ -0,0 +1,536 @@
|
||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||
<Application>
|
||||
<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.KhrAndroidSurface"
|
||||
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.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.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.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.Nfc.Nfp.AmiiboJsonSerializerContext"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Time.Clock.StandardLocalSystemClockCore"
|
||||
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.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.Time.Clock.StandardNetworkSystemClockCore"
|
||||
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.Am.AppletAE.AllSystemAppletProxiesService.ISystemAppletProxy"
|
||||
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.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.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.BluetoothManager.IBtmUser"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Pcie.IManager"
|
||||
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.Caps.IScreenShotApplicationService"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Account.Acc.IBaasAccessTokenAccessor"
|
||||
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.Nv.NvDrvServices.NvHostProfGpu.NvHostProfGpuDeviceFile"
|
||||
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.Ldn.IUserServiceCreator"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Spl.IRandomInterface"
|
||||
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.SurfaceFlinger.HOSBinderDriverServer"
|
||||
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.Nfc.Nfp.INfp"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Ns.IVulnerabilityManagerInterface"
|
||||
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.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.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.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.Nfc.ISystemManager"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Pcv.IPcvService"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Am.IApplicationProxyService"
|
||||
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.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.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.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.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.Vi.RootService.IApplicationDisplayService"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Loader.IDebugMonitorInterface"
|
||||
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.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.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.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.Npns.INpnsUser"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Olsc.IOlscServiceForSystemService"
|
||||
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.Ectx.IReaderForSystem"
|
||||
Dynamic="Required All" />
|
||||
<Type Name="Ryujinx.HLE.HOS.Services.Loader.IProcessManagerInterface"
|
||||
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.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.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.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>
|
Loading…
x
Reference in New Issue
Block a user