From 839d1926350e404a46466ffbd45755486017be07 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Sun, 2 Jul 2023 16:48:53 +0000 Subject: [PATCH] add bionic nativeaot support (cherry picked from commit 0aed709520c49d51c5c894b72ee3837680cc1d50) --- Directory.Packages.props | 1 + src/LibRyujinx/AndroidLogTarget.cs | 51 +++ src/LibRyujinx/Audio/Oboe/OboeAudioBuffer.cs | 18 + .../Audio/Oboe/OboeHardwareDeviceDriver.cs | 108 +++++ .../Audio/Oboe/OboeHardwareDeviceSession.cs | 169 ++++++++ src/LibRyujinx/Audio/Oboe/OboeInterop.cs | 41 ++ src/LibRyujinx/Jni/Delegates.cs | 286 +++++++++++++ src/LibRyujinx/Jni/Identifiers/JFieldId.cs | 28 ++ src/LibRyujinx/Jni/Identifiers/JMethodId.cs | 28 ++ src/LibRyujinx/Jni/JReferenceType.cs | 12 + src/LibRyujinx/Jni/JReleaseMode.cs | 10 + src/LibRyujinx/Jni/JResult.cs | 14 + src/LibRyujinx/Jni/Pointers/CCharSequence.cs | 36 ++ src/LibRyujinx/Jni/Pointers/JBooleanRef.cs | 25 ++ src/LibRyujinx/Jni/Pointers/JCharSequence.cs | 33 ++ src/LibRyujinx/Jni/Pointers/JEnvRef.cs | 32 ++ .../Jni/Pointers/JNativeMethodSequence.cs | 33 ++ src/LibRyujinx/Jni/Pointers/JValueSequence.cs | 33 ++ src/LibRyujinx/Jni/Pointers/JavaVMRef.cs | 25 ++ src/LibRyujinx/Jni/Primitives/JBoolean.cs | 67 +++ src/LibRyujinx/Jni/Primitives/JByte.cs | 74 ++++ src/LibRyujinx/Jni/Primitives/JChar.cs | 56 +++ src/LibRyujinx/Jni/Primitives/JDouble.cs | 70 +++ src/LibRyujinx/Jni/Primitives/JFloat.cs | 70 +++ src/LibRyujinx/Jni/Primitives/JInt.cs | 73 ++++ src/LibRyujinx/Jni/Primitives/JLong.cs | 73 ++++ src/LibRyujinx/Jni/Primitives/JShort.cs | 74 ++++ .../Jni/References/JArrayLocalRef.cs | 28 ++ .../Jni/References/JClassLocalRef.cs | 28 ++ src/LibRyujinx/Jni/References/JGlobalRef.cs | 28 ++ .../Jni/References/JObjectLocalRef.cs | 28 ++ .../Jni/References/JStringLocalRef.cs | 28 ++ .../Jni/References/JThrowableLocalRef.cs | 28 ++ src/LibRyujinx/Jni/References/JWeakRef.cs | 28 ++ src/LibRyujinx/Jni/Values/JEnvValue.cs | 30 ++ src/LibRyujinx/Jni/Values/JInvokeInterface.cs | 20 + src/LibRyujinx/Jni/Values/JNativeInterface.cs | 245 +++++++++++ src/LibRyujinx/Jni/Values/JNativeMethod.cs | 12 + src/LibRyujinx/Jni/Values/JValue.cs | 44 ++ src/LibRyujinx/Jni/Values/JavaVMAttachArgs.cs | 13 + src/LibRyujinx/Jni/Values/JavaVMInitArgs.cs | 12 + src/LibRyujinx/Jni/Values/JavaVMOption.cs | 11 + src/LibRyujinx/JniExportedMethods.cs | 404 ++++++++++++++++++ src/LibRyujinx/rd.xml | 4 +- .../Logging/Formatters/DefaultLogFormatter.cs | 2 +- 45 files changed, 2531 insertions(+), 2 deletions(-) create mode 100644 src/LibRyujinx/AndroidLogTarget.cs create mode 100644 src/LibRyujinx/Audio/Oboe/OboeAudioBuffer.cs create mode 100644 src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceDriver.cs create mode 100644 src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceSession.cs create mode 100644 src/LibRyujinx/Audio/Oboe/OboeInterop.cs create mode 100644 src/LibRyujinx/Jni/Delegates.cs create mode 100644 src/LibRyujinx/Jni/Identifiers/JFieldId.cs create mode 100644 src/LibRyujinx/Jni/Identifiers/JMethodId.cs create mode 100644 src/LibRyujinx/Jni/JReferenceType.cs create mode 100644 src/LibRyujinx/Jni/JReleaseMode.cs create mode 100644 src/LibRyujinx/Jni/JResult.cs create mode 100644 src/LibRyujinx/Jni/Pointers/CCharSequence.cs create mode 100644 src/LibRyujinx/Jni/Pointers/JBooleanRef.cs create mode 100644 src/LibRyujinx/Jni/Pointers/JCharSequence.cs create mode 100644 src/LibRyujinx/Jni/Pointers/JEnvRef.cs create mode 100644 src/LibRyujinx/Jni/Pointers/JNativeMethodSequence.cs create mode 100644 src/LibRyujinx/Jni/Pointers/JValueSequence.cs create mode 100644 src/LibRyujinx/Jni/Pointers/JavaVMRef.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JBoolean.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JByte.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JChar.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JDouble.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JFloat.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JInt.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JLong.cs create mode 100644 src/LibRyujinx/Jni/Primitives/JShort.cs create mode 100644 src/LibRyujinx/Jni/References/JArrayLocalRef.cs create mode 100644 src/LibRyujinx/Jni/References/JClassLocalRef.cs create mode 100644 src/LibRyujinx/Jni/References/JGlobalRef.cs create mode 100644 src/LibRyujinx/Jni/References/JObjectLocalRef.cs create mode 100644 src/LibRyujinx/Jni/References/JStringLocalRef.cs create mode 100644 src/LibRyujinx/Jni/References/JThrowableLocalRef.cs create mode 100644 src/LibRyujinx/Jni/References/JWeakRef.cs create mode 100644 src/LibRyujinx/Jni/Values/JEnvValue.cs create mode 100644 src/LibRyujinx/Jni/Values/JInvokeInterface.cs create mode 100644 src/LibRyujinx/Jni/Values/JNativeInterface.cs create mode 100644 src/LibRyujinx/Jni/Values/JNativeMethod.cs create mode 100644 src/LibRyujinx/Jni/Values/JValue.cs create mode 100644 src/LibRyujinx/Jni/Values/JavaVMAttachArgs.cs create mode 100644 src/LibRyujinx/Jni/Values/JavaVMInitArgs.cs create mode 100644 src/LibRyujinx/Jni/Values/JavaVMOption.cs create mode 100644 src/LibRyujinx/JniExportedMethods.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 7eb217ce6..2c63988fc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -49,5 +49,6 @@ + diff --git a/src/LibRyujinx/AndroidLogTarget.cs b/src/LibRyujinx/AndroidLogTarget.cs new file mode 100644 index 000000000..937b02bf2 --- /dev/null +++ b/src/LibRyujinx/AndroidLogTarget.cs @@ -0,0 +1,51 @@ +using Ryujinx.Common; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Logging.Formatters; +using Ryujinx.Common.Logging.Targets; +using System; +using System.IO; +using System.Linq; + +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 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() + { + } + } +} diff --git a/src/LibRyujinx/Audio/Oboe/OboeAudioBuffer.cs b/src/LibRyujinx/Audio/Oboe/OboeAudioBuffer.cs new file mode 100644 index 000000000..aad74115f --- /dev/null +++ b/src/LibRyujinx/Audio/Oboe/OboeAudioBuffer.cs @@ -0,0 +1,18 @@ +namespace LibRyujinx.Shared.Audio.Oboe +{ + internal class OboeAudioBuffer + { + public readonly ulong DriverIdentifier; + public readonly ulong SampleCount; + public readonly byte[] Data; + public ulong SamplePlayed; + + public OboeAudioBuffer(ulong driverIdentifier, byte[] data, ulong sampleCount) + { + DriverIdentifier = driverIdentifier; + Data = data; + SampleCount = sampleCount; + SamplePlayed = 0; + } + } +} diff --git a/src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceDriver.cs b/src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceDriver.cs new file mode 100644 index 000000000..c56d0fe38 --- /dev/null +++ b/src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceDriver.cs @@ -0,0 +1,108 @@ +using Ryujinx.Audio; +using Ryujinx.Audio.Common; +using Ryujinx.Audio.Integration; +using Ryujinx.Memory; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static Ryujinx.Audio.Integration.IHardwareDeviceDriver; + +namespace LibRyujinx.Shared.Audio.Oboe +{ + internal class OboeHardwareDeviceDriver : IHardwareDeviceDriver + { + private readonly ManualResetEvent _updateRequiredEvent; + private readonly ManualResetEvent _pauseEvent; + private readonly ConcurrentDictionary _sessions; + + public OboeHardwareDeviceDriver() + { + _updateRequiredEvent = new ManualResetEvent(false); + _pauseEvent = new ManualResetEvent(true); + _sessions = new ConcurrentDictionary(); + } + + public static bool IsSupported => true; + + public ManualResetEvent GetUpdateRequiredEvent() + { + return _updateRequiredEvent; + } + + public ManualResetEvent GetPauseEvent() + { + return _pauseEvent; + } + + public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume) + { + if (channelCount == 0) + { + channelCount = 2; + } + + if (sampleRate == 0) + { + sampleRate = Constants.TargetSampleRate; + } + + if (direction != Direction.Output) + { + throw new NotImplementedException("Input direction is currently not implemented on Oboe backend!"); + } + + OboeHardwareDeviceSession session = new OboeHardwareDeviceSession(this, memoryManager, sampleFormat, sampleRate, channelCount, volume); + + _sessions.TryAdd(session, 0); + + return session; + } + + internal bool Unregister(OboeHardwareDeviceSession session) + { + return _sessions.TryRemove(session, out _); + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + foreach (OboeHardwareDeviceSession session in _sessions.Keys) + { + session.Dispose(); + } + + _pauseEvent.Dispose(); + } + } + + public bool SupportsSampleRate(uint sampleRate) + { + return true; + } + + public bool SupportsSampleFormat(SampleFormat sampleFormat) + { + return sampleFormat != SampleFormat.Adpcm; + } + + public bool SupportsChannelCount(uint channelCount) + { + return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6; + } + + public bool SupportsDirection(Direction direction) + { + return direction == Direction.Output; + } + } +} \ No newline at end of file diff --git a/src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceSession.cs b/src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceSession.cs new file mode 100644 index 000000000..b23426d30 --- /dev/null +++ b/src/LibRyujinx/Audio/Oboe/OboeHardwareDeviceSession.cs @@ -0,0 +1,169 @@ +using Ryujinx.Audio.Backends.Common; +using Ryujinx.Audio.Common; +using Ryujinx.Memory; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace LibRyujinx.Shared.Audio.Oboe +{ + internal class OboeHardwareDeviceSession : HardwareDeviceSessionOutputBase + { + private OboeHardwareDeviceDriver _driver; + private bool _isWorkerActive; + private Queue _queuedBuffers; + private bool _isActive; + private ulong _playedSampleCount; + private Thread _workerThread; + private ManualResetEvent _updateRequiredEvent; + private IntPtr _session; + private object _queueLock = new object(); + private object _trackLock = new object(); + + public OboeHardwareDeviceSession(OboeHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount) + { + _driver = driver; + _isActive = false; + _playedSampleCount = 0; + _isWorkerActive = true; + _queuedBuffers = new Queue(); + _updateRequiredEvent = driver.GetUpdateRequiredEvent(); + + _session = OboeInterop.CreateSession((int)requestedSampleFormat, requestedSampleRate, requestedChannelCount); + + _workerThread = new Thread(Update); + _workerThread.Name = $"HardwareDeviceSession.Android.Track"; + _workerThread.Start(); + + SetVolume(requestedVolume); + } + + public override void UnregisterBuffer(AudioBuffer buffer) { } + + public unsafe void Update(object ignored) + { + while (_isWorkerActive) + { + bool needUpdate = false; + + bool hasBuffer; + + OboeAudioBuffer buffer; + + lock (_queueLock) + { + hasBuffer = _queuedBuffers.TryPeek(out buffer); + } + + while (hasBuffer) + { + StartIfNotPlaying(); + + fixed(byte* ptr = buffer.Data) + OboeInterop.WriteToSession(_session, (ulong)ptr, buffer.SampleCount); + + lock (_queueLock) + { + _playedSampleCount += buffer.SampleCount; + + _queuedBuffers.TryDequeue(out _); + } + + needUpdate = true; + + lock (_queueLock) + { + hasBuffer = _queuedBuffers.TryPeek(out buffer); + } + } + + if (needUpdate) + { + _updateRequiredEvent.Set(); + } + + // No work + Thread.Sleep(5); + } + + } + + public override void Dispose() + { + OboeInterop.CloseSession(_session); + } + public override void PrepareToClose() + { + _isWorkerActive = false; + _workerThread.Join(); + } + + private void StartIfNotPlaying() + { + lock (_trackLock) + { + if (OboeInterop.IsPlaying(_session) == 0) + { + Start(); + } + } + } + + public override void QueueBuffer(AudioBuffer buffer) + { + lock (_queueLock) + { + OboeAudioBuffer driverBuffer = new OboeAudioBuffer(buffer.DataPointer, buffer.Data, GetSampleCount(buffer)); + + _queuedBuffers.Enqueue(driverBuffer); + + if (_isActive) + { + StartIfNotPlaying(); + } + } + } + + public override float GetVolume() + { + return OboeInterop.GetSessionVolume(_session); + } + + public override ulong GetPlayedSampleCount() + { + lock (_queueLock) + { + return _playedSampleCount; + } + } + + public override void SetVolume(float volume) + { + volume = 1; + OboeInterop.SetSessionVolume(_session, volume); + } + + public override void Start() + { + OboeInterop.StartSession(_session); + } + + public override void Stop() + { + OboeInterop.StopSession(_session); + } + + public override bool WasBufferFullyConsumed(AudioBuffer buffer) + { + lock (_queueLock) + { + if (!_queuedBuffers.TryPeek(out OboeAudioBuffer driverBuffer)) + { + return true; + } + + return driverBuffer.DriverIdentifier != buffer.DataPointer; + } + } + } +} diff --git a/src/LibRyujinx/Audio/Oboe/OboeInterop.cs b/src/LibRyujinx/Audio/Oboe/OboeInterop.cs new file mode 100644 index 000000000..79d9ca43e --- /dev/null +++ b/src/LibRyujinx/Audio/Oboe/OboeInterop.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LibRyujinx.Shared.Audio.Oboe +{ + internal static partial class OboeInterop + { + private const string InteropLib = "libryujinxjni"; + + [LibraryImport(InteropLib, EntryPoint = "create_session")] + public static partial IntPtr CreateSession(int sample_format, + uint sample_rate, + uint channel_count); + + + [LibraryImport(InteropLib, EntryPoint = "start_session")] + public static partial void StartSession(IntPtr session); + + [LibraryImport(InteropLib, EntryPoint = "stop_session")] + public static partial void StopSession(IntPtr session); + + [LibraryImport(InteropLib, EntryPoint = "close_session")] + public static partial void CloseSession(IntPtr session); + + [LibraryImport(InteropLib, EntryPoint = "set_session_volume")] + public static partial void SetSessionVolume(IntPtr session, float volume); + + [LibraryImport(InteropLib, EntryPoint = "get_session_volume")] + public static partial float GetSessionVolume(IntPtr session); + + [LibraryImport(InteropLib, EntryPoint = "is_playing")] + public static partial int IsPlaying(IntPtr session); + + [LibraryImport(InteropLib, EntryPoint = "write_to_session")] + public static partial void WriteToSession(IntPtr session, ulong data, ulong samples); + } +} diff --git a/src/LibRyujinx/Jni/Delegates.cs b/src/LibRyujinx/Jni/Delegates.cs new file mode 100644 index 000000000..683109ade --- /dev/null +++ b/src/LibRyujinx/Jni/Delegates.cs @@ -0,0 +1,286 @@ +using LibRyujinx.Jni.Identifiers; +using LibRyujinx.Jni.Internal.Pointers; +using LibRyujinx.Jni.Pointers; +using LibRyujinx.Jni.Primitives; +using LibRyujinx.Jni.References; +using LibRyujinx.Jni.Values; +using System; + +namespace LibRyujinx.Jni +{ + internal delegate Int32 GetVersionDelegate(JEnvRef env); + + internal delegate JClassLocalRef DefineClassDelegate(JEnvRef env, CCharSequence name, JObjectLocalRef loader, IntPtr binaryData, Int32 len); + internal delegate JClassLocalRef FindClassDelegate(JEnvRef env, CCharSequence name); + + internal delegate JMethodId FromReflectedMethodDelegate(JEnvRef env, JObjectLocalRef method); + internal delegate JFieldId FromReflectedFieldIdDelegate(JEnvRef env, JObjectLocalRef field); + + internal delegate JObjectLocalRef ToReflectedMethodDelegate(JEnvRef env, JClassLocalRef jClass, JMethodId methodId, Boolean isStatic); + + internal delegate JClassLocalRef GetSuperclassDelegate(JEnvRef env, JClassLocalRef sub); + internal delegate Boolean IsAssignableFromDelegate(JEnvRef env, JClassLocalRef sub, JClassLocalRef sup); + + internal delegate JObjectLocalRef ToReflectedFieldIdDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId fieldId, Boolean isStatic); + + internal delegate JResult ThrowDelegate(JEnvRef env, JThrowableLocalRef obj); + internal delegate JResult ThrowNewDelegate(JEnvRef env, JClassLocalRef jClass, CCharSequence msg); + internal delegate JThrowableLocalRef ExceptionOccurredDelegate(JEnvRef env); + internal delegate void ExceptionDescribeDelegate(JEnvRef env); + internal delegate void ExceptionClearDelegate(JEnvRef env); + internal delegate void FatalErrorDelegate(JEnvRef env, CCharSequence msg); + + internal delegate JResult PushLocalFrameDelegate(JEnvRef env, Int32 capacity); + internal delegate JObjectLocalRef PopLocalFrameDelegate(JEnvRef env, JObjectLocalRef result); + + internal delegate JGlobalRef NewGlobalRefDelegate(JEnvRef env, JObjectLocalRef lref); + internal delegate void DeleteGlobalRefDelegate(JEnvRef env, JGlobalRef gref); + internal delegate void DeleteLocalRefDelegate(JEnvRef env, JObjectLocalRef lref); + internal delegate Boolean 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 JObjectLocalRef AllocObjectDelegate(JEnvRef env, JClassLocalRef jClass); + internal delegate JObjectLocalRef NewObjectDelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod, IntPtr args); + internal delegate JObjectLocalRef NewObjectVDelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod, ArgIterator args); + internal delegate JObjectLocalRef NewObjectADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod, JValueSequence args); + + internal delegate JClassLocalRef GetObjectClassDelegate(JEnvRef env, JObjectLocalRef obj); + internal delegate Boolean IsInstanceOfDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass); + + internal delegate JMethodId GetMethodIdDelegate(JEnvRef env, JClassLocalRef jClass, CCharSequence name, CCharSequence signature); + + internal delegate JObjectLocalRef CallObjectMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JObjectLocalRef CallObjectMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JObjectLocalRef CallObjectMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JBoolean CallBooleanMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JBoolean CallBooleanMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JBoolean CallBooleanMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JByte CallByteMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JByte CallByteMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JByte CallByteMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JChar CallCharMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JChar CallCharMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JChar CallCharMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JShort CallShortMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JShort CallShortMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JShort CallShortMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JInt CallIntMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JInt CallIntMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JInt CallIntMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JLong CallLongMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JLong CallLongMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JLong CallLongMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JFloat CallFloatMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JFloat CallFloatMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JFloat CallFloatMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate JDouble CallDoubleMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate JDouble CallDoubleMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate JDouble CallDoubleMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + internal delegate void CallVoidMethodDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, IntPtr args); + internal delegate void CallVoidMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, ArgIterator args); + internal delegate void CallVoidMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod, JValueSequence args); + + internal delegate JObjectLocalRef CallNonVirtualObjectMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JObjectLocalRef CallNonVirtualObjectMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JObjectLocalRef CallNonVirtualObjectMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JBoolean CallNonVirtualBooleanMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JBoolean CallNonVirtualBooleanMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JBoolean CallNonVirtualBooleanMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JByte CallNonVirtualByteMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JByte CallNonVirtualByteMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JByte CallNonVirtualByteMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JChar CallNonVirtualCharMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JChar CallNonVirtualCharMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JChar CallNonVirtualCharMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JShort CallNonVirtualShortMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JShort CallNonVirtualShortMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JShort CallNonVirtualShortMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JInt CallNonVirtualIntMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JInt CallNonVirtualIntMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JInt CallNonVirtualIntMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JLong CallNonVirtualLongMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JLong CallNonVirtualLongMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JLong CallNonVirtualLongMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JFloat CallNonVirtualFloatMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JFloat CallNonVirtualFloatMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JFloat CallNonVirtualFloatMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JDouble CallNonVirtualDoubleMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JDouble CallNonVirtualDoubleMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JDouble CallNonVirtualDoubleMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate void CallNonVirtualVoidMethodDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate void CallNonVirtualVoidMethodVDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate void CallNonVirtualVoidMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + + internal delegate JFieldId GetFieldIdDelegate(JEnvRef env, JClassLocalRef jclass, CCharSequence name, CCharSequence signature); + + 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 JMethodId GetStaticMethodIdDelegate(JEnvRef env, JClassLocalRef jClass, CCharSequence name, CCharSequence signature); + + internal delegate JObjectLocalRef CallStaticObjectMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JObjectLocalRef CallStaticObjectMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JObjectLocalRef CallStaticObjectMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JBoolean CallStaticBooleanMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JBoolean CallStaticBooleanMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JBoolean CallStaticBooleanMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JByte CallStaticByteMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JByte CallStaticByteMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JByte CallStaticByteMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JChar CallStaticCharMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JChar CallStaticCharMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JChar CallStaticCharMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JShort CallStaticShortMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JShort CallStaticShortMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JShort CallStaticShortMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JInt CallStaticIntMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JInt CallStaticIntMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JInt CallStaticIntMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JLong CallStaticLongMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JLong CallStaticLongMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JLong CallStaticLongMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JFloat CallStaticFloatMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JFloat CallStaticFloatMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JFloat CallStaticFloatMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate JDouble CallStaticDoubleMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate JDouble CallStaticDoubleMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate JDouble CallStaticDoubleMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + internal delegate void CallStaticVoidMethodDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, IntPtr args); + internal delegate void CallStaticVoidMethodVDelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, ArgIterator args); + internal delegate void CallStaticVoidMethodADelegate(JEnvRef env, JClassLocalRef jclass, JMethodId jMethod, JValueSequence args); + + internal delegate JFieldId GetStaticFieldIdDelegate(JEnvRef env, JClassLocalRef jclass, CCharSequence name, CCharSequence signature); + + 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 JStringLocalRef NewStringDelegate(JEnvRef env, JCharSequence unicode, Int32 length); + + internal delegate Int32 GetStringLengthDelegate(JEnvRef env, JStringLocalRef jString); + internal delegate JCharSequence GetStringCharsDelegate(JEnvRef env, JStringLocalRef jString, JBooleanRef isCopy); + internal delegate void ReleaseStringCharsDelegate(JEnvRef env, JStringLocalRef jString, JCharSequence chars); + + internal delegate JStringLocalRef NewStringUtfDelegate(JEnvRef env, CCharSequence unicode); + internal delegate Int32 GetStringUtfLengthDelegate(JEnvRef env, JStringLocalRef jString); + internal delegate CCharSequence GetStringUtfCharsDelegate(JEnvRef env, JStringLocalRef jString, JBooleanRef isCopy); + internal delegate void ReleaseStringUtfCharsDelegate(JEnvRef env, JStringLocalRef jString, CCharSequence chars); + + 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 jArray, Int32 index); + internal delegate void SetObjectArrayElementDelegate(JEnvRef env, JArrayLocalRef jArray, 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 IntPtr GetBooleanArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetByteArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetCharArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetShortArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetIntArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetLongArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetFloatArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate IntPtr GetDoubleArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + + internal delegate void ReleaseBooleanArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseByteArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseCharArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseShortArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseIntArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseLongArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseFloatArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + internal delegate void ReleaseDoubleArrayElementsDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + + internal delegate void GetBooleanArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetByteArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetCharArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetShortArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetIntArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetLongArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetFloatArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void GetDoubleArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetBooleanArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetByteArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetCharArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetShortArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetIntArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetLongArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetFloatArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + internal delegate void SetDoubleArrayRegionDelegate(JEnvRef env, JArrayLocalRef jArray, Int32 startIndex, Int32 length, IntPtr buffer); + + internal delegate JResult RegisterNativesDelegate(JEnvRef env, JClassLocalRef jClass, JNativeMethodSequence methods); + 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 GetJavaVMDelegate(JEnvRef env, ref JavaVMRef jvm); + + internal delegate void GetStringRegionDelegate(JEnvRef env, JStringLocalRef jString, Int32 startIndex, Int32 length, JCharSequence buffer); + internal delegate void GetStringUtfRegionDelegate(JEnvRef env, JStringLocalRef jString, Int32 startIndex, Int32 length, CCharSequence buffer); + + internal delegate IntPtr GetPrimitiveArrayCriticalDelegate(JEnvRef env, JArrayLocalRef jArray, JBooleanRef isCopy); + internal delegate void ReleasePrimitiveArrayCriticalDelegate(JEnvRef env, JArrayLocalRef jArray, IntPtr elements, JReleaseMode mode); + + internal delegate JCharSequence GetStringCriticalDelegate(JEnvRef env, JStringLocalRef jString, JBooleanRef isCopy); + internal delegate void ReleaseStringCriticalDelegate(JEnvRef env, JStringLocalRef jString, JCharSequence chars); + + internal delegate JWeakRef NewWeakGlobalRefDelegate(JEnvRef env, JObjectLocalRef obj); + internal delegate void DeleteWeakGlobalRefDelegate(JEnvRef env, JWeakRef jWeak); + + internal delegate Boolean 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 JReferenceType GetObjectRefTypeDelegate(JEnvRef env, JObjectLocalRef obj); + + internal delegate JResult DestroyJavaVMDelegate(JavaVMRef vm); + internal delegate JResult AttachCurrentThreadDelegate(JavaVMRef vm, ref JEnvRef env, in JavaVMAttachArgs args); + internal delegate JResult DetachCurrentThreadDelegate(JavaVMRef vm); + + internal delegate JResult GetEnvDelegate(JavaVMRef vm, ref JEnvRef env, JInt version); + + internal delegate JResult AttachCurrentThreadAsDaemonDelegate(JavaVMRef vm, ref JEnvRef env, in JavaVMAttachArgs args); +} \ No newline at end of file diff --git a/src/LibRyujinx/Jni/Identifiers/JFieldId.cs b/src/LibRyujinx/Jni/Identifiers/JFieldId.cs new file mode 100644 index 000000000..aa35f9074 --- /dev/null +++ b/src/LibRyujinx/Jni/Identifiers/JFieldId.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.Identifiers +{ + public readonly struct JFieldId : IEquatable + { +#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 + } +} diff --git a/src/LibRyujinx/Jni/Identifiers/JMethodId.cs b/src/LibRyujinx/Jni/Identifiers/JMethodId.cs new file mode 100644 index 000000000..b8fee13c3 --- /dev/null +++ b/src/LibRyujinx/Jni/Identifiers/JMethodId.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.Identifiers +{ + public readonly struct JMethodId : IEquatable + { +#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 + } +} diff --git a/src/LibRyujinx/Jni/JReferenceType.cs b/src/LibRyujinx/Jni/JReferenceType.cs new file mode 100644 index 000000000..47c9f2aef --- /dev/null +++ b/src/LibRyujinx/Jni/JReferenceType.cs @@ -0,0 +1,12 @@ +using System; + +namespace LibRyujinx.Jni +{ + public enum JReferenceType : Int32 + { + InvalidRefType = 0, + LocalRefType = 1, + GlobalRefType = 2, + WeakGlobalRefType = 3 + } +} diff --git a/src/LibRyujinx/Jni/JReleaseMode.cs b/src/LibRyujinx/Jni/JReleaseMode.cs new file mode 100644 index 000000000..4a86b5a0b --- /dev/null +++ b/src/LibRyujinx/Jni/JReleaseMode.cs @@ -0,0 +1,10 @@ +using System; +namespace LibRyujinx.Jni +{ + public enum JReleaseMode : Int32 + { + Free = 0, + Commit = 1, + Abort = 2, + } +} diff --git a/src/LibRyujinx/Jni/JResult.cs b/src/LibRyujinx/Jni/JResult.cs new file mode 100644 index 000000000..d3cdddff9 --- /dev/null +++ b/src/LibRyujinx/Jni/JResult.cs @@ -0,0 +1,14 @@ +using System; +namespace LibRyujinx.Jni +{ + public enum JResult : Int32 + { + Ok = 0, + Error = -1, + DetachedThreadError = -2, + VersionError = -3, + MemoryError = -4, + ExitingVMError = -5, + InvalidArgumentsError = -6, + } +} diff --git a/src/LibRyujinx/Jni/Pointers/CCharSequence.cs b/src/LibRyujinx/Jni/Pointers/CCharSequence.cs new file mode 100644 index 000000000..d52bcf6f4 --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/CCharSequence.cs @@ -0,0 +1,36 @@ +using System.Runtime.InteropServices; +using System; + +using Rxmxnx.PInvoke; + +namespace LibRyujinx.Jni.Pointers +{ + public readonly struct CCharSequence : IEquatable + { + private readonly IntPtr _value; + + private CCharSequence(IntPtr value) => this._value = value; + + #region Operators + public static implicit operator CCharSequence(IntPtr value) => new(value); + public static implicit operator CCharSequence(Span span) => new(span.GetUnsafeIntPtr()); + public static implicit operator CCharSequence(ReadOnlySpan readonlySpan) => new(readonlySpan.GetUnsafeIntPtr()); + + public static CCharSequence operator ++(CCharSequence a) => new(a._value + sizeof(Byte)); + public static CCharSequence operator --(CCharSequence a) => new(a._value - sizeof(Byte)); + public static Boolean operator ==(CCharSequence a, CCharSequence b) => a._value.Equals(b._value); + public static Boolean operator !=(CCharSequence a, CCharSequence b) => !a._value.Equals(b._value); + #endregion + + #region Public Methods + public Boolean Equals(CCharSequence other) => this._value.Equals(other._value); + public String AsString(Int32 length = 0) + => length == 0 ? Marshal.PtrToStringUTF8(_value) : Marshal.PtrToStringUTF8(_value, length); + #endregion + + #region Overrided Methods + public override Boolean Equals(Object obj) => obj is CCharSequence other && this.Equals(other); + public override Int32 GetHashCode() => this._value.GetHashCode(); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/Pointers/JBooleanRef.cs b/src/LibRyujinx/Jni/Pointers/JBooleanRef.cs new file mode 100644 index 000000000..6ec641f3d --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/JBooleanRef.cs @@ -0,0 +1,25 @@ +using System.Runtime.CompilerServices; +using System; + +using LibRyujinx.Jni.Primitives; + +using Rxmxnx.PInvoke; + +namespace LibRyujinx.Jni.Pointers +{ + public readonly struct JBooleanRef + { + private const Int32 JBooleanResultFalse = 0; + private const Int32 JBooleanResultTrue = 1; + +#pragma warning disable IDE0052 + private readonly IntPtr _value; +#pragma warning restore IDE0052 + + public JBooleanRef(JBoolean? jBoolean) + => this._value = jBoolean.HasValue ? GetJBooleanRef(jBoolean.Value) : IntPtr.Zero; + + private static IntPtr GetJBooleanRef(Boolean value) + => value ? Unsafe.AsRef(JBooleanResultTrue).GetUnsafeIntPtr() : Unsafe.AsRef(JBooleanResultFalse).GetUnsafeIntPtr(); + } +} diff --git a/src/LibRyujinx/Jni/Pointers/JCharSequence.cs b/src/LibRyujinx/Jni/Pointers/JCharSequence.cs new file mode 100644 index 000000000..461944fc5 --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/JCharSequence.cs @@ -0,0 +1,33 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Pointers +{ + public readonly struct JCharSequence : IEquatable + { + private readonly IntPtr _value; + + private JCharSequence(IntPtr value) => this._value = value; + + #region Operators + public static implicit operator JCharSequence(IntPtr value) => new(value); + public static implicit operator JCharSequence(Span span) => new(span.GetUnsafeIntPtr()); + public static implicit operator JCharSequence(ReadOnlySpan readonlySpan) => new(readonlySpan.GetUnsafeIntPtr()); + + public static JCharSequence operator ++(JCharSequence a) => new(a._value + sizeof(Char)); + public static JCharSequence operator --(JCharSequence a) => new(a._value - sizeof(Char)); + public static Boolean operator ==(JCharSequence a, JCharSequence b) => a._value.Equals(b._value); + public static Boolean operator !=(JCharSequence a, JCharSequence b) => !a._value.Equals(b._value); + #endregion + + #region Public Methods + public Boolean Equals(JCharSequence other) => this._value.Equals(other._value); + public String AsString(Int32 length = 0) => this._value.GetUnsafeString(length); + #endregion + + #region Overrided Methods + public override Boolean Equals(Object obj) => obj is JCharSequence other && this.Equals(other); + public override Int32 GetHashCode() => this._value.GetHashCode(); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/Pointers/JEnvRef.cs b/src/LibRyujinx/Jni/Pointers/JEnvRef.cs new file mode 100644 index 000000000..f58c25d5e --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/JEnvRef.cs @@ -0,0 +1,32 @@ +using LibRyujinx.Jni.Values; + +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Pointers +{ + public readonly struct JEnvRef : IEquatable + { +#pragma warning disable 0649 + private readonly IntPtr _value; +#pragma warning restore 0649 + + #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(); + #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 + } +} diff --git a/src/LibRyujinx/Jni/Pointers/JNativeMethodSequence.cs b/src/LibRyujinx/Jni/Pointers/JNativeMethodSequence.cs new file mode 100644 index 000000000..d5508714d --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/JNativeMethodSequence.cs @@ -0,0 +1,33 @@ +using LibRyujinx.Jni.Values; + +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Pointers +{ + public readonly struct JNativeMethodSequence : IEquatable + { + private readonly IntPtr _value; + + private JNativeMethodSequence(IntPtr value) => this._value = value; + + #region Operators + public static implicit operator JNativeMethodSequence(IntPtr value) => new(value); + public static implicit operator JNativeMethodSequence(ReadOnlySpan readonlySpan) => new(readonlySpan.GetUnsafeIntPtr()); + + public static JNativeMethodSequence operator ++(JNativeMethodSequence a) => new(a._value + JValue.Size); + public static JNativeMethodSequence operator --(JNativeMethodSequence a) => new(a._value - JValue.Size); + public static Boolean operator ==(JNativeMethodSequence a, JNativeMethodSequence b) => a._value.Equals(b._value); + public static Boolean operator !=(JNativeMethodSequence a, JNativeMethodSequence b) => !a._value.Equals(b._value); + #endregion + + #region Public Methods + public Boolean Equals(JNativeMethodSequence other) => this._value.Equals(other._value); + #endregion + + #region Overrided Methods + public override Boolean Equals(Object obj) => obj is JNativeMethodSequence other && this.Equals(other); + public override Int32 GetHashCode() => this._value.GetHashCode(); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/Pointers/JValueSequence.cs b/src/LibRyujinx/Jni/Pointers/JValueSequence.cs new file mode 100644 index 000000000..caa65ac9b --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/JValueSequence.cs @@ -0,0 +1,33 @@ +using LibRyujinx.Jni.Values; + +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Internal.Pointers +{ + internal readonly struct JValueSequence : IEquatable + { + private readonly IntPtr _value; + + private JValueSequence(IntPtr value) => this._value = value; + internal JValueSequence(ReadOnlySpan readonlySpan) : this(readonlySpan.GetUnsafeIntPtr()) { } + + #region Operators + public static implicit operator JValueSequence(IntPtr value) => new(value); + + public static JValueSequence operator ++(JValueSequence a) => new(a._value + JValue.Size); + public static JValueSequence operator --(JValueSequence a) => new(a._value - JValue.Size); + public static Boolean operator ==(JValueSequence a, JValueSequence b) => a._value.Equals(b._value); + public static Boolean operator !=(JValueSequence a, JValueSequence b) => !a._value.Equals(b._value); + #endregion + + #region Public Methods + public Boolean Equals(JValueSequence other) => this._value.Equals(other._value); + #endregion + + #region Overrided Methods + public override Boolean Equals(Object obj) => obj is JValueSequence other && this.Equals(other); + public override Int32 GetHashCode() => this._value.GetHashCode(); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/Pointers/JavaVMRef.cs b/src/LibRyujinx/Jni/Pointers/JavaVMRef.cs new file mode 100644 index 000000000..27ba389f1 --- /dev/null +++ b/src/LibRyujinx/Jni/Pointers/JavaVMRef.cs @@ -0,0 +1,25 @@ +using System; + +namespace LibRyujinx.Jni.Pointers +{ + public readonly struct JavaVMRef : IEquatable + { +#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 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JBoolean.cs b/src/LibRyujinx/Jni/Primitives/JBoolean.cs new file mode 100644 index 000000000..88b4b7dba --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JBoolean.cs @@ -0,0 +1,67 @@ +using LibRyujinx.Jni.Pointers; + +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JBoolean : IComparable, IEquatable + { + internal static readonly Type Type = typeof(JBoolean); + private static readonly Byte trueByte = 1; + private static readonly Byte falseByte = 2; + + public static readonly CString Signature = (CString)"Z"; + + private readonly Byte _value; + private Boolean Value => this._value == trueByte; + + private JBoolean(Boolean value) => this._value = value ? trueByte : falseByte; + + #region Operators + public static implicit operator JBoolean(Boolean value) => new(value); + public static implicit operator Boolean(JBoolean jValue) => jValue._value == 1; + public static implicit operator JBooleanRef(JBoolean? jValue) => new(jValue); + 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JByte.cs b/src/LibRyujinx/Jni/Primitives/JByte.cs new file mode 100644 index 000000000..a5ed5b0a4 --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JByte.cs @@ -0,0 +1,74 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JByte : IComparable, IEquatable, 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JChar.cs b/src/LibRyujinx/Jni/Primitives/JChar.cs new file mode 100644 index 000000000..b2ba3782d --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JChar.cs @@ -0,0 +1,56 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JChar : IComparable, IEquatable + { + 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JDouble.cs b/src/LibRyujinx/Jni/Primitives/JDouble.cs new file mode 100644 index 000000000..94f05eb9a --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JDouble.cs @@ -0,0 +1,70 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JDouble : IComparable, IEquatable, 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JFloat.cs b/src/LibRyujinx/Jni/Primitives/JFloat.cs new file mode 100644 index 000000000..52f833241 --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JFloat.cs @@ -0,0 +1,70 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JFloat : IComparable, IEquatable, 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JInt.cs b/src/LibRyujinx/Jni/Primitives/JInt.cs new file mode 100644 index 000000000..adf86a8d7 --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JInt.cs @@ -0,0 +1,73 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JInt : IComparable, IEquatable, 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JLong.cs b/src/LibRyujinx/Jni/Primitives/JLong.cs new file mode 100644 index 000000000..a5bd6613a --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JLong.cs @@ -0,0 +1,73 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JLong : IComparable, IEquatable, 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 + } +} diff --git a/src/LibRyujinx/Jni/Primitives/JShort.cs b/src/LibRyujinx/Jni/Primitives/JShort.cs new file mode 100644 index 000000000..78650c2fe --- /dev/null +++ b/src/LibRyujinx/Jni/Primitives/JShort.cs @@ -0,0 +1,74 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Primitives +{ + public readonly struct JShort : IComparable, IEquatable, 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 + } +} diff --git a/src/LibRyujinx/Jni/References/JArrayLocalRef.cs b/src/LibRyujinx/Jni/References/JArrayLocalRef.cs new file mode 100644 index 000000000..6501b4360 --- /dev/null +++ b/src/LibRyujinx/Jni/References/JArrayLocalRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JArrayLocalRef : IEquatable + { +#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 Boolean operator ==(JArrayLocalRef a, JArrayLocalRef b) => a.Equals(b); + public static Boolean operator !=(JArrayLocalRef a, JArrayLocalRef b) => !a.Equals(b); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/References/JClassLocalRef.cs b/src/LibRyujinx/Jni/References/JClassLocalRef.cs new file mode 100644 index 000000000..5880f5ddb --- /dev/null +++ b/src/LibRyujinx/Jni/References/JClassLocalRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JClassLocalRef : IEquatable + { +#pragma warning disable 0649 + public readonly JObjectLocalRef _value; +#pragma warning restore 0649 + + #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 Boolean operator ==(JClassLocalRef a, JClassLocalRef b) => a.Equals(b); + public static Boolean operator !=(JClassLocalRef a, JClassLocalRef b) => !a.Equals(b); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/References/JGlobalRef.cs b/src/LibRyujinx/Jni/References/JGlobalRef.cs new file mode 100644 index 000000000..1befe7b94 --- /dev/null +++ b/src/LibRyujinx/Jni/References/JGlobalRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JGlobalRef : IEquatable + { +#pragma warning disable 0649 + private readonly IntPtr _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 Boolean operator ==(JGlobalRef a, JGlobalRef b) => a.Equals(b); + public static Boolean operator !=(JGlobalRef a, JGlobalRef b) => !a.Equals(b); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/References/JObjectLocalRef.cs b/src/LibRyujinx/Jni/References/JObjectLocalRef.cs new file mode 100644 index 000000000..ff1953137 --- /dev/null +++ b/src/LibRyujinx/Jni/References/JObjectLocalRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JObjectLocalRef : IEquatable + { +#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 + } +} diff --git a/src/LibRyujinx/Jni/References/JStringLocalRef.cs b/src/LibRyujinx/Jni/References/JStringLocalRef.cs new file mode 100644 index 000000000..002fd9942 --- /dev/null +++ b/src/LibRyujinx/Jni/References/JStringLocalRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JStringLocalRef : IEquatable + { +#pragma warning disable 0649 + public 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 Boolean operator ==(JStringLocalRef a, JStringLocalRef b) => a.Equals(b); + public static Boolean operator !=(JStringLocalRef a, JStringLocalRef b) => !a.Equals(b); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/References/JThrowableLocalRef.cs b/src/LibRyujinx/Jni/References/JThrowableLocalRef.cs new file mode 100644 index 000000000..a7e5e3b40 --- /dev/null +++ b/src/LibRyujinx/Jni/References/JThrowableLocalRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JThrowableLocalRef : IEquatable + { +#pragma warning disable 0649 + private readonly IntPtr _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 Boolean operator ==(JThrowableLocalRef a, JThrowableLocalRef b) => a.Equals(b); + public static Boolean operator !=(JThrowableLocalRef a, JThrowableLocalRef b) => !a.Equals(b); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/References/JWeakRef.cs b/src/LibRyujinx/Jni/References/JWeakRef.cs new file mode 100644 index 000000000..9572c6035 --- /dev/null +++ b/src/LibRyujinx/Jni/References/JWeakRef.cs @@ -0,0 +1,28 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.References +{ + public readonly struct JWeakRef : IEquatable + { +#pragma warning disable 0649 + private readonly IntPtr _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 Boolean operator ==(JWeakRef a, JWeakRef b) => a.Equals(b); + public static Boolean operator !=(JWeakRef a, JWeakRef b) => !a.Equals(b); + #endregion + } +} diff --git a/src/LibRyujinx/Jni/Values/JEnvValue.cs b/src/LibRyujinx/Jni/Values/JEnvValue.cs new file mode 100644 index 000000000..dc4d8a17b --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JEnvValue.cs @@ -0,0 +1,30 @@ +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Values +{ + internal readonly struct JEnvValue : IEquatable + { +#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(); + #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 + } +} diff --git a/src/LibRyujinx/Jni/Values/JInvokeInterface.cs b/src/LibRyujinx/Jni/Values/JInvokeInterface.cs new file mode 100644 index 000000000..14473c574 --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JInvokeInterface.cs @@ -0,0 +1,20 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +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; } + } +} diff --git a/src/LibRyujinx/Jni/Values/JNativeInterface.cs b/src/LibRyujinx/Jni/Values/JNativeInterface.cs new file mode 100644 index 000000000..b3aa132ec --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JNativeInterface.cs @@ -0,0 +1,245 @@ +using System.Diagnostics.CodeAnalysis; +using System; + +namespace LibRyujinx.Jni.Values +{ + [SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "This struct is created only by binary operations.")] + 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; } + internal readonly IntPtr CallObjectMethodPointer { get; init; } + internal readonly IntPtr CallObjectMethodVPointer { get; init; } + internal readonly IntPtr CallObjectMethodAPointer { get; init; } + internal readonly IntPtr CallBooleanMethodPointer { get; init; } + internal readonly IntPtr CallBooleanMethodVPointer { get; init; } + internal readonly IntPtr CallBooleanMethodAPointer { get; init; } + internal readonly IntPtr CallByteMethodPointer { get; init; } + internal readonly IntPtr CallByteMethodVPointer { get; init; } + internal readonly IntPtr CallByteMethodAPointer { get; init; } + internal readonly IntPtr CallCharMethodPointer { get; init; } + internal readonly IntPtr CallCharMethodVPointer { get; init; } + internal readonly IntPtr CallCharMethodAPointer { get; init; } + internal readonly IntPtr CallShortMethodPointer { get; init; } + internal readonly IntPtr CallShortMethodVPointer { get; init; } + internal readonly IntPtr CallShortMethodAPointer { get; init; } + internal readonly IntPtr CallIntMethodPointer { get; init; } + internal readonly IntPtr CallIntMethodVPointer { get; init; } + internal readonly IntPtr CallIntMethodAPointer { get; init; } + internal readonly IntPtr CallLongMethodPointer { get; init; } + internal readonly IntPtr CallLongMethodVPointer { get; init; } + internal readonly IntPtr CallLongMethodAPointer { get; init; } + internal readonly IntPtr CallFloatMethodPointer { get; init; } + internal readonly IntPtr CallFloatMethodVPointer { get; init; } + internal readonly IntPtr CallFloatMethodAPointer { get; init; } + internal readonly IntPtr CallDoubleMethodPointer { get; init; } + internal readonly IntPtr CallDoubleMethodVPointer { get; init; } + internal readonly IntPtr CallDoubleMethodAPointer { get; init; } + internal readonly IntPtr CallVoidMethodPointer { get; init; } + internal readonly IntPtr CallVoidMethodVPointer { get; init; } + internal readonly IntPtr CallVoidMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualObjectMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualObjectMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualObjectMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualBooleanMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualBooleanMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualBooleanMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualByteMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualByteMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualByteMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualCharMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualCharMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualCharMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualShortMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualShortMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualShortMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualIntMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualIntMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualIntMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualLongMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualLongMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualLongMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualFloatMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualFloatMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualFloatMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualDoubleMethodPointer { get; init; } + internal readonly IntPtr CallNonVirtualDoubleMethodVPointer { get; init; } + internal readonly IntPtr CallNonVirtualDoubleMethodAPointer { get; init; } + internal readonly IntPtr CallNonVirtualVoidMethodPointer { get; init; } + internal 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; } + internal readonly IntPtr CallStaticObjectMethodPointer { get; init; } + internal readonly IntPtr CallStaticObjectMethodVPointer { get; init; } + internal readonly IntPtr CallStaticObjectMethodAPointer { get; init; } + internal readonly IntPtr CallStaticBooleanMethodPointer { get; init; } + internal readonly IntPtr CallStaticBooleanMethodVPointer { get; init; } + internal readonly IntPtr CallStaticBooleanMethodAPointer { get; init; } + internal readonly IntPtr CallStaticByteMethodPointer { get; init; } + internal readonly IntPtr CallStaticByteMethodVPointer { get; init; } + internal readonly IntPtr CallStaticByteMethodAPointer { get; init; } + internal readonly IntPtr CallStaticCharMethodPointer { get; init; } + internal readonly IntPtr CallStaticCharMethodVPointer { get; init; } + internal readonly IntPtr CallStaticCharMethodAPointer { get; init; } + internal readonly IntPtr CallStaticShortMethodPointer { get; init; } + internal readonly IntPtr CallStaticShortMethodVPointer { get; init; } + internal readonly IntPtr CallStaticShortMethodAPointer { get; init; } + internal readonly IntPtr CallStaticIntMethodPointer { get; init; } + internal readonly IntPtr CallStaticIntMethodVPointer { get; init; } + internal readonly IntPtr CallStaticIntMethodAPointer { get; init; } + internal readonly IntPtr CallStaticLongMethodPointer { get; init; } + internal readonly IntPtr CallStaticLongMethodVPointer { get; init; } + internal readonly IntPtr CallStaticLongMethodAPointer { get; init; } + internal readonly IntPtr CallStaticFloatMethodPointer { get; init; } + internal readonly IntPtr CallStaticFloatMethodVPointer { get; init; } + internal readonly IntPtr CallStaticFloatMethodAPointer { get; init; } + internal readonly IntPtr CallStaticDoubleMethodPointer { get; init; } + internal readonly IntPtr CallStaticDoubleMethodVPointer { get; init; } + internal readonly IntPtr CallStaticDoubleMethodAPointer { get; init; } + internal readonly IntPtr CallStaticVoidMethodPointer { get; init; } + internal 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; } + } +} diff --git a/src/LibRyujinx/Jni/Values/JNativeMethod.cs b/src/LibRyujinx/Jni/Values/JNativeMethod.cs new file mode 100644 index 000000000..10315071e --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JNativeMethod.cs @@ -0,0 +1,12 @@ +using LibRyujinx.Jni.Pointers; +using System; + +namespace LibRyujinx.Jni.Values +{ + public readonly struct JNativeMethod + { + internal CCharSequence Name { get; init; } + internal CCharSequence Signature { get; init; } + internal IntPtr Pointer { get; init; } + } +} diff --git a/src/LibRyujinx/Jni/Values/JValue.cs b/src/LibRyujinx/Jni/Values/JValue.cs new file mode 100644 index 000000000..c482b85ad --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JValue.cs @@ -0,0 +1,44 @@ +using System.Runtime.CompilerServices; + +using Rxmxnx.PInvoke; +using System; + +namespace LibRyujinx.Jni.Values +{ + internal readonly struct JValue + { + private delegate Boolean IsDefaultDelegate(in JValue value); + + public static readonly Int32 Size = NativeUtilities.SizeOf(); + + private static readonly IsDefaultDelegate isDefault = 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 => isDefault(this); + + public static JValue Create(ReadOnlySpan source) + { + Byte[] result = new Byte[Size]; + for (Int32 i = 0; i < source.Length; i++) + result[i] = source[i]; + return result.ToValue(); + } + + private static IsDefaultDelegate GetIsDefault() => Environment.Is64BitProcess ? DefaultLong : 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(jValue).Transform() == default; + } +} diff --git a/src/LibRyujinx/Jni/Values/JavaVMAttachArgs.cs b/src/LibRyujinx/Jni/Values/JavaVMAttachArgs.cs new file mode 100644 index 000000000..d8b827c4d --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JavaVMAttachArgs.cs @@ -0,0 +1,13 @@ +using LibRyujinx.Jni.Pointers; +using LibRyujinx.Jni.References; +using System; + +namespace LibRyujinx.Jni.Values +{ + public readonly struct JavaVMAttachArgs + { + internal Int32 Version { get; init; } + internal CCharSequence Name { get; init; } + internal JObjectLocalRef Group { get; init; } + } +} diff --git a/src/LibRyujinx/Jni/Values/JavaVMInitArgs.cs b/src/LibRyujinx/Jni/Values/JavaVMInitArgs.cs new file mode 100644 index 000000000..d9fa6d161 --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JavaVMInitArgs.cs @@ -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; } + } +} diff --git a/src/LibRyujinx/Jni/Values/JavaVMOption.cs b/src/LibRyujinx/Jni/Values/JavaVMOption.cs new file mode 100644 index 000000000..153fc64c3 --- /dev/null +++ b/src/LibRyujinx/Jni/Values/JavaVMOption.cs @@ -0,0 +1,11 @@ +using LibRyujinx.Jni.Pointers; +using System; + +namespace LibRyujinx.Jni.Values +{ + public readonly struct JavaVMOption + { + internal CCharSequence Name { get; init; } + internal IntPtr ExtraInfo { get; init; } + } +} diff --git a/src/LibRyujinx/JniExportedMethods.cs b/src/LibRyujinx/JniExportedMethods.cs new file mode 100644 index 000000000..c27e488f1 --- /dev/null +++ b/src/LibRyujinx/JniExportedMethods.cs @@ -0,0 +1,404 @@ +using System; +using System.Runtime.InteropServices; +using Ryujinx.Common.Configuration; +using System.Collections.Generic; +using LibRyujinx.Jni.Pointers; +using LibRyujinx.Jni.References; +using LibRyujinx.Jni.Values; +using LibRyujinx.Jni.Primitives; +using LibRyujinx.Jni; +using Rxmxnx.PInvoke; +using System.Text; +using LibRyujinx.Jni.Internal.Pointers; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Logging.Targets; +using Silk.NET.Vulkan; +using Silk.NET.Vulkan.Extensions.KHR; +using LibRyujinx.Shared.Audio.Oboe; +using System.Threading; +using System.IO; +using Microsoft.Win32.SafeHandles; +using Newtonsoft.Json.Linq; +using System.Security.Cryptography; + +namespace LibRyujinx +{ + public static partial class LibRyujinx + { + private static ManualResetEvent _surfaceEvent; + private static long _surfacePtr; + + [DllImport("libryujinxjni")] + private extern static IntPtr getStringPointer(JEnvRef jEnv, JStringLocalRef s); + + public delegate IntPtr JniCreateSurface(IntPtr native_surface, IntPtr instance); + + [UnmanagedCallersOnly(EntryPoint = "JNI_OnLoad")] + internal static int LoadLibrary(JavaVMRef vm, IntPtr unknown) + { + return 0x00010006; //JNI_VERSION_1_6 + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_initialize")] + public static JBoolean JniInitialize(JEnvRef jEnv, JObjectLocalRef jObj, JStringLocalRef jpath) + { + var path = GetString(jEnv, jpath); + + Ryujinx.Common.SystemInfo.SystemInfo.IsBionic = true; + + var init = Initialize(path); + + AudioDriver = new OboeHardwareDeviceDriver(); + + _surfaceEvent = new ManualResetEvent(false); + + Logger.AddTarget( + new AsyncLogTargetWrapper( + new AndroidLogTarget("Ryujinx"), + 1000, + AsyncLogTargetOverflowAction.Block + )); + + return init; + } + + private static string GetString(JEnvRef jEnv, JStringLocalRef jString) + { + var stringPtr = getStringPointer(jEnv, jString); + + var s = Marshal.PtrToStringAnsi(stringPtr); + Marshal.FreeHGlobal(stringPtr); + return s; + } + + private static JStringLocalRef CreateString(string str, JEnvRef jEnv) + { + return str.AsSpan().WithSafeFixed(jEnv, CreateString); + } + + + private static JStringLocalRef CreateString(in IReadOnlyFixedContext ctx, JEnvRef jEnv) + { + JEnvValue value = jEnv.Environment; + ref JNativeInterface jInterface = ref value.Functions; + + IntPtr newStringPtr = jInterface.NewStringPointer; + NewStringDelegate newString = newStringPtr.GetUnsafeDelegate(); + + return newString(jEnv, ctx.Pointer, ctx.Values.Length); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_deviceInitialize")] + public static JBoolean JniInitializeDeviceNative(JEnvRef jEnv, JObjectLocalRef jObj, JBoolean isHostMapped) + { + return InitializeDevice(isHostMapped); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_deviceLoad")] + public static JBoolean JniLoadApplicationNative(JEnvRef jEnv, JObjectLocalRef jObj, JStringLocalRef pathPtr) + { + if (SwitchDevice?.EmulationContext == null) + { + return false; + } + + var path = GetString(jEnv, pathPtr); + + return LoadApplication(path); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_deviceLoadDescriptor")] + public static JBoolean JniLoadApplicationNative(JEnvRef jEnv, JObjectLocalRef jObj, JInt descriptor, JBoolean isXci) + { + if (SwitchDevice?.EmulationContext == null) + { + return false; + } + + var stream = OpenFile(descriptor); + + return LoadApplication(stream, isXci); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsInitialize")] + public static JBoolean JniInitializeGraphicsNative(JEnvRef jEnv, JObjectLocalRef jObj, JObjectLocalRef graphicObject) + { + JEnvValue value = jEnv.Environment; + ref JNativeInterface jInterface = ref value.Functions; + IntPtr getObjectClassPtr = jInterface.GetObjectClassPointer; + IntPtr getFieldIdPtr = jInterface.GetFieldIdPointer; + IntPtr getIntFieldPtr = jInterface.GetIntFieldPointer; + IntPtr getLongFieldPtr = jInterface.GetLongFieldPointer; + IntPtr getFloatFieldPtr = jInterface.GetFloatFieldPointer; + IntPtr getBooleanFieldPtr = jInterface.GetBooleanFieldPointer; + + var getObjectClass = getObjectClassPtr.GetUnsafeDelegate(); + var getFieldId = getFieldIdPtr.GetUnsafeDelegate(); + var getLongField = getLongFieldPtr.GetUnsafeDelegate(); + var getIntField = getIntFieldPtr.GetUnsafeDelegate(); + var getBooleanField = getBooleanFieldPtr.GetUnsafeDelegate(); + var getFloatField = getFloatFieldPtr.GetUnsafeDelegate(); + + var jobject = getObjectClass(jEnv, graphicObject); + + GraphicsConfiguration graphicsConfiguration = new GraphicsConfiguration() + { + EnableShaderCache = getBooleanField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("EnableShaderCache"), GetCCharSequence("Z"))), + EnableMacroHLE = getBooleanField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("EnableMacroHLE"), GetCCharSequence("Z"))), + EnableMacroJit = getBooleanField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("EnableMacroJit"), GetCCharSequence("Z"))), + EnableTextureRecompression = getBooleanField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("EnableTextureRecompression"), GetCCharSequence("Z"))), + Fast2DCopy = getBooleanField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("Fast2DCopy"), GetCCharSequence("Z"))), + FastGpuTime = getBooleanField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("FastGpuTime"), GetCCharSequence("Z"))), + ResScale = getFloatField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("ResScale"), GetCCharSequence("F"))), + MaxAnisotropy = getFloatField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("MaxAnisotropy"), GetCCharSequence("F"))), + BackendThreading = (BackendThreading)(int)getIntField(jEnv, graphicObject, getFieldId(jEnv, jobject, GetCCharSequence("BackendThreading"), GetCCharSequence("I"))) + }; + Silk.NET.Core.Loader.SearchPathContainer.Platform = Silk.NET.Core.Loader.UnderlyingPlatform.Android; + return InitializeGraphics(graphicsConfiguration); + } + + private static CCharSequence GetCCharSequence(string s) + { + return (CCharSequence)Encoding.UTF8.GetBytes(s).AsSpan(); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsSetSurface")] + public unsafe static void JniSetSurface(JEnvRef jEnv, JObjectLocalRef jObj, JLong surfacePtr) + { + _surfacePtr = surfacePtr; + + _surfaceEvent.Set(); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsInitializeRenderer")] + public unsafe static JBoolean JniInitializeGraphicsRendererNative(JEnvRef jEnv, JObjectLocalRef jObj, JArrayLocalRef extensionsArray, JLong surfacePtr) + { + if (Renderer != null) + { + return false; + } + + JEnvValue value = jEnv.Environment; + ref JNativeInterface jInterface = ref value.Functions; + IntPtr getObjectClassPtr = jInterface.GetObjectClassPointer; + IntPtr getFieldIdPtr = jInterface.GetFieldIdPointer; + IntPtr getLongFieldPtr = jInterface.GetLongFieldPointer; + IntPtr getArrayLengthPtr = jInterface.GetArrayLengthPointer; + IntPtr getObjectArrayElementPtr = jInterface.GetObjectArrayElementPointer; + IntPtr getObjectFieldPtr = jInterface.GetObjectFieldPointer; + + var getObjectClass = getObjectClassPtr.GetUnsafeDelegate(); + var getFieldId = getFieldIdPtr.GetUnsafeDelegate(); + var getArrayLength = getArrayLengthPtr.GetUnsafeDelegate(); + var getObjectArrayElement = getObjectArrayElementPtr.GetUnsafeDelegate(); + var getLongField = getLongFieldPtr.GetUnsafeDelegate(); + var getObjectField = getObjectFieldPtr.GetUnsafeDelegate(); + + List extensions = new List(); + + var count = getArrayLength(jEnv, extensionsArray); + + for(int i = 0; i < count; i++) + { + var obj = getObjectArrayElement(jEnv, extensionsArray, i); + var ext = obj.Transform(); + + extensions.Add(GetString(jEnv, ext)); + } + + _surfaceEvent.Set(); + + _surfacePtr = (long)surfacePtr; + + CreateSurface createSurfaceFunc = (IntPtr instance) => + { + _surfaceEvent.WaitOne(); + _surfaceEvent.Reset(); + + var api = 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 = "Java_org_ryujinx_android_RyujinxNative_graphicsRendererSetSize")] + public static void JniSetRendererSizeNative(JEnvRef jEnv, JObjectLocalRef jObj, JInt width, JInt height) + { + Renderer?.Window?.SetSize(width, height); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsRendererRunLoop")] + public static void JniRunLoopNative(JEnvRef jEnv, JObjectLocalRef jObj) + { + RunLoop(); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_deviceGetGameInfo")] + public static JObjectLocalRef JniGetGameInfo(JEnvRef jEnv, JObjectLocalRef jObj, JInt fileDescriptor, JBoolean isXci) + { + using var stream = OpenFile(fileDescriptor); + + var info = GetGameInfo(stream, isXci) ?? new GameInfo(); + + var javaClassName = GetCCharSequence("org/ryujinx/android/viewmodels/GameInfo"); + + JEnvValue value = jEnv.Environment; + ref JNativeInterface jInterface = ref value.Functions; + IntPtr findClassPtr = jInterface.FindClassPointer; + IntPtr newGlobalRefPtr = jInterface.NewGlobalRefPointer; + IntPtr getFieldIdPtr = jInterface.GetFieldIdPointer; + IntPtr getMethodPtr = jInterface.GetMethodIdPointer; + IntPtr newObjectPtr = jInterface.NewObjectPointer; + IntPtr setObjectFieldPtr = jInterface.SetObjectFieldPointer; + IntPtr setDoubleFieldPtr = jInterface.SetDoubleFieldPointer; + + + var findClass = findClassPtr.GetUnsafeDelegate(); + var newGlobalRef = newGlobalRefPtr.GetUnsafeDelegate (); + var getFieldId = getFieldIdPtr.GetUnsafeDelegate(); + var getMethod = getMethodPtr.GetUnsafeDelegate(); + var newObject = newObjectPtr.GetUnsafeDelegate(); + var setObjectField = setObjectFieldPtr.GetUnsafeDelegate(); + var setDoubleField = setDoubleFieldPtr.GetUnsafeDelegate(); + + var javaClass = findClass(jEnv, javaClassName); + var newGlobal = newGlobalRef(jEnv, javaClass._value); + var constructor = getMethod(jEnv, javaClass, GetCCharSequence(""), GetCCharSequence("()V")); + var newObj = newObject(jEnv, javaClass, constructor, 0); + + using var sha = SHA256.Create(); + + var iconCacheByte = sha.ComputeHash(info.Icon ?? new byte[0]); + var iconCache = BitConverter.ToString(iconCacheByte).Replace("-", ""); + + var cacheDirectory = Path.Combine(AppDataManager.BaseDirPath, "iconCache"); + Directory.CreateDirectory(cacheDirectory); + + var cachePath = Path.Combine(cacheDirectory, iconCache); + if (!File.Exists(cachePath)) + { + File.WriteAllBytes(cachePath, info.Icon ?? new byte[0]); + } + + setObjectField(jEnv, newObj, getFieldId(jEnv, javaClass, GetCCharSequence("TitleName"), GetCCharSequence("Ljava/lang/String;")), CreateString(info.TitleName, jEnv)._value); + setObjectField(jEnv, newObj, getFieldId(jEnv, javaClass, GetCCharSequence("TitleId"), GetCCharSequence("Ljava/lang/String;")), CreateString(info.TitleId, jEnv)._value); + setObjectField(jEnv, newObj, getFieldId(jEnv, javaClass, GetCCharSequence("Developer"), GetCCharSequence("Ljava/lang/String;")), CreateString(info.Developer, jEnv)._value); + setObjectField(jEnv, newObj, getFieldId(jEnv, javaClass, GetCCharSequence("Version"), GetCCharSequence("Ljava/lang/String;")), CreateString(info.Version, jEnv)._value); + setObjectField(jEnv, newObj, getFieldId(jEnv, javaClass, GetCCharSequence("IconCache"), GetCCharSequence("Ljava/lang/String;")), CreateString(iconCache, jEnv)._value); + setDoubleField(jEnv, newObj, getFieldId(jEnv, javaClass, GetCCharSequence("FileSize"), GetCCharSequence("D")), info.FileSize); + + return newObj; + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsRendererSetVsync")] + public static void JniSetVsyncStateNative(JEnvRef jEnv, JObjectLocalRef jObj, JBoolean enabled) + { + SetVsyncState(enabled); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsRendererSetSwapBufferCallback")] + public static void JniSetSwapBuffersCallbackNative(JEnvRef jEnv, JObjectLocalRef jObj, IntPtr swapBuffersCallback) + { + _swapBuffersCallback = Marshal.GetDelegateForFunctionPointer(swapBuffersCallback); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputInitialize")] + public static void JniInitializeInput(JEnvRef jEnv, JObjectLocalRef jObj, JInt width, JInt height) + { + InitializeInput(width, height); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputSetClientSize")] + public static void JniSetClientSize(JEnvRef jEnv, JObjectLocalRef jObj, JInt width, JInt height) + { + SetClientSize(width, height); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputSetTouchPoint")] + public static void JniSetTouchPoint(JEnvRef jEnv, JObjectLocalRef jObj, JInt x, JInt y) + { + SetTouchPoint(x, y); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputReleaseTouchPoint")] + public static void JniReleaseTouchPoint(JEnvRef jEnv, JObjectLocalRef jObj) + { + ReleaseTouchPoint(); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputUpdate")] + public static void JniUpdateInput(JEnvRef jEnv, JObjectLocalRef jObj) + { + UpdateInput(); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputSetButtonPressed")] + public static void JniSetButtonPressed(JEnvRef jEnv, JObjectLocalRef jObj, JInt button, JStringLocalRef id) + { + SetButtonPressed((Ryujinx.Input.GamepadButtonInputId)(int)button, GetString(jEnv, id)); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputSetButtonReleased")] + public static void JniSetButtonReleased(JEnvRef jEnv, JObjectLocalRef jObj, JInt button, JStringLocalRef id) + { + SetButtonReleased((Ryujinx.Input.GamepadButtonInputId)(int)button, GetString(jEnv, id)); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputSetStickAxis")] + public static void JniSetStickAxis(JEnvRef jEnv, JObjectLocalRef jObj, JInt stick, JFloat x, JFloat y, JStringLocalRef id) + { + SetStickAxis((Ryujinx.Input.StickInputId)(int)stick, new System.Numerics.Vector2(x, y), GetString(jEnv, id)); + } + + [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_inputConnectGamepad")] + public static JStringLocalRef JniConnectGamepad(JEnvRef jEnv, JObjectLocalRef jObj, JInt index) + { + var id = ConnectGamepad(index); + + return (id ?? "").AsSpan().WithSafeFixed(jEnv, CreateString); + } + + private static Stream OpenFile(int descriptor) + { + var safeHandle = new SafeFileHandle(descriptor, false); + + return new FileStream(safeHandle, FileAccess.Read); + } + } + + 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 + } + } +} diff --git a/src/LibRyujinx/rd.xml b/src/LibRyujinx/rd.xml index b1cecb007..2faf502ad 100644 --- a/src/LibRyujinx/rd.xml +++ b/src/LibRyujinx/rd.xml @@ -15,6 +15,8 @@ + - + \ No newline at end of file diff --git a/src/Ryujinx.Common/Logging/Formatters/DefaultLogFormatter.cs b/src/Ryujinx.Common/Logging/Formatters/DefaultLogFormatter.cs index b1cffcb56..2ff49526a 100644 --- a/src/Ryujinx.Common/Logging/Formatters/DefaultLogFormatter.cs +++ b/src/Ryujinx.Common/Logging/Formatters/DefaultLogFormatter.cs @@ -3,7 +3,7 @@ using System.Text; namespace Ryujinx.Common.Logging.Formatters { - internal class DefaultLogFormatter : ILogFormatter + public class DefaultLogFormatter : ILogFormatter { private static readonly ObjectPool _stringBuilderPool = SharedPools.Default();