diff --git a/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs b/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs
index 86afc2b4d..374f4746b 100644
--- a/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs
+++ b/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs
@@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
LinuxFeatureInfoHwCap2 = (LinuxFeatureFlagsHwCap2)getauxval(AT_HWCAP2);
}
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
for (int i = 0; i < _sysctlNames.Length; i++)
{
@@ -130,6 +130,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
private static bool CheckSysctlName(string name)
{
ulong size = sizeof(int);
diff --git a/src/ARMeilleure/CodeGen/CompiledFunction.cs b/src/ARMeilleure/CodeGen/CompiledFunction.cs
index 3844cbfc9..485c85d16 100644
--- a/src/ARMeilleure/CodeGen/CompiledFunction.cs
+++ b/src/ARMeilleure/CodeGen/CompiledFunction.cs
@@ -58,9 +58,9 @@ namespace ARMeilleure.CodeGen
/// Type of delegate
/// Pointer to the function code in memory
/// A delegate of type pointing to the mapped function
- public T MapWithPointer(out IntPtr codePointer)
+ public T MapWithPointer(out IntPtr codePointer, bool deferProtect = false)
{
- codePointer = JitCache.Map(this);
+ codePointer = JitCache.Map(this, deferProtect);
return Marshal.GetDelegateForFunctionPointer(codePointer);
}
diff --git a/src/ARMeilleure/Native/JitSupportDarwin.cs b/src/ARMeilleure/Native/JitSupportDarwin.cs
index ed347b9cf..bf94514ed 100644
--- a/src/ARMeilleure/Native/JitSupportDarwin.cs
+++ b/src/ARMeilleure/Native/JitSupportDarwin.cs
@@ -5,9 +5,41 @@ using System.Runtime.Versioning;
namespace ARMeilleure.Native
{
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
internal static partial class JitSupportDarwin
{
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);
}
+
+ [SupportedOSPlatform("ios")]
+ internal static partial class JitSupportDarwinAot
+ {
+ [LibraryImport("pthread", EntryPoint = "pthread_jit_write_protect_np")]
+ private static partial void pthread_jit_write_protect_np(int enabled);
+
+ [LibraryImport("libc", EntryPoint = "sys_icache_invalidate")]
+ private static partial void sys_icache_invalidate(IntPtr start, IntPtr length);
+
+ public static unsafe void Copy(IntPtr dst, IntPtr src, ulong n) {
+ // When NativeAOT is in use, we can toggle per-thread write protection without worrying about breaking .NET code.
+
+ //pthread_jit_write_protect_np(0);
+
+ var srcSpan = new Span(src.ToPointer(), (int)n);
+ var dstSpan = new Span(dst.ToPointer(), (int)n);
+ srcSpan.CopyTo(dstSpan);
+
+ //pthread_jit_write_protect_np(1);
+
+ // Ensure that the instruction cache for this range is invalidated.
+ sys_icache_invalidate(dst, (IntPtr)n);
+ }
+
+ public static unsafe void Invalidate(IntPtr dst, ulong n)
+ {
+ // Ensure that the instruction cache for this range is invalidated.
+ sys_icache_invalidate(dst, (IntPtr)n);
+ }
+ }
}
diff --git a/src/ARMeilleure/Signal/NativeSignalHandler.cs b/src/ARMeilleure/Signal/NativeSignalHandler.cs
index 31ec16cb1..d0d1aab7c 100644
--- a/src/ARMeilleure/Signal/NativeSignalHandler.cs
+++ b/src/ARMeilleure/Signal/NativeSignalHandler.cs
@@ -112,7 +112,7 @@ namespace ARMeilleure.Signal
ref SignalHandlerConfig config = ref GetConfigRef();
- if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
@@ -252,13 +252,13 @@ namespace ARMeilleure.Signal
private static Operand GenerateUnixFaultAddress(EmitterContext context, Operand sigInfoPtr)
{
- ulong structAddressOffset = OperatingSystem.IsMacOS() ? 24ul : 16ul; // si_addr
+ ulong structAddressOffset = (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS()) ? 24ul : 16ul; // si_addr
return context.Load(OperandType.I64, context.Add(sigInfoPtr, Const(structAddressOffset)));
}
private static Operand GenerateUnixWriteFlag(EmitterContext context, Operand ucontextPtr)
{
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
const ulong McontextOffset = 48; // uc_mcontext
Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(McontextOffset)));
diff --git a/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs b/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs
index 70e9f2204..433aab636 100644
--- a/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs
+++ b/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs
@@ -62,7 +62,7 @@ namespace ARMeilleure.Signal
throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}");
}
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
result = sigaction(SIGBUS, ref sig, out _);
@@ -77,7 +77,7 @@ namespace ARMeilleure.Signal
public static bool RestoreExceptionHandler(SigAction oldAction)
{
- return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
+ return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
}
}
}
diff --git a/src/ARMeilleure/Translation/Cache/CacheMemoryAllocator.cs b/src/ARMeilleure/Translation/Cache/CacheMemoryAllocator.cs
index f36bf7a3d..a1bd3933a 100644
--- a/src/ARMeilleure/Translation/Cache/CacheMemoryAllocator.cs
+++ b/src/ARMeilleure/Translation/Cache/CacheMemoryAllocator.cs
@@ -30,21 +30,26 @@ namespace ARMeilleure.Translation.Cache
_blocks.Add(new MemoryBlock(0, capacity));
}
- public int Allocate(int size)
+ public int Allocate(ref int size, int alignment)
{
+ int alignM1 = alignment - 1;
for (int i = 0; i < _blocks.Count; i++)
{
MemoryBlock block = _blocks[i];
+ int misAlignment = ((block.Offset + alignM1) & (~alignM1)) - block.Offset;
+ int alignedSize = size + misAlignment;
- if (block.Size > size)
+ if (block.Size > alignedSize)
{
- _blocks[i] = new MemoryBlock(block.Offset + size, block.Size - size);
- return block.Offset;
+ size = alignedSize;
+ _blocks[i] = new MemoryBlock(block.Offset + alignedSize, block.Size - alignedSize);
+ return block.Offset + misAlignment;
}
- else if (block.Size == size)
+ else if (block.Size == alignedSize)
{
+ size = alignedSize;
_blocks.RemoveAt(i);
- return block.Offset;
+ return block.Offset + misAlignment;
}
}
diff --git a/src/ARMeilleure/Translation/Cache/JitCache.cs b/src/ARMeilleure/Translation/Cache/JitCache.cs
index e2b5e2d10..db4be66e5 100644
--- a/src/ARMeilleure/Translation/Cache/JitCache.cs
+++ b/src/ARMeilleure/Translation/Cache/JitCache.cs
@@ -4,6 +4,7 @@ using ARMeilleure.Memory;
using ARMeilleure.Native;
using Ryujinx.Memory;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
@@ -18,6 +19,7 @@ namespace ARMeilleure.Translation.Cache
private const int CodeAlignment = 4; // Bytes.
private const int CacheSize = 2047 * 1024 * 1024;
+ private const int CacheSizeIOS = 512 * 1024 * 1024;
private static ReservedRegion _jitRegion;
private static JitCacheInvalidation _jitCacheInvalidator;
@@ -47,9 +49,9 @@ namespace ARMeilleure.Translation.Cache
return;
}
- _jitRegion = new ReservedRegion(allocator, CacheSize);
+ _jitRegion = new ReservedRegion(allocator, (ulong)(OperatingSystem.IsIOS() ? CacheSizeIOS : CacheSize));
- if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
+ if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS() && !OperatingSystem.IsIOS())
{
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
}
@@ -65,7 +67,17 @@ namespace ARMeilleure.Translation.Cache
}
}
- public static IntPtr Map(CompiledFunction func)
+ static ConcurrentQueue<(int funcOffset, int length)> _deferredRxProtect = new();
+
+ public static void RunDeferredRxProtects()
+ {
+ while (_deferredRxProtect.TryDequeue(out var result))
+ {
+ ReprotectAsExecutable(result.funcOffset, result.length);
+ }
+ }
+
+ public static IntPtr Map(CompiledFunction func, bool deferProtect)
{
byte[] code = func.Code;
@@ -73,11 +85,25 @@ namespace ARMeilleure.Translation.Cache
{
Debug.Assert(_initialized);
- int funcOffset = Allocate(code.Length);
+ int funcOffset = Allocate(code.Length, deferProtect);
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
- if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+ if (OperatingSystem.IsIOS())
+ {
+ Marshal.Copy(code, 0, funcPtr, code.Length);
+ if (deferProtect)
+ {
+ _deferredRxProtect.Enqueue((funcOffset, code.Length));
+ }
+ else
+ {
+ ReprotectAsExecutable(funcOffset, code.Length);
+
+ JitSupportDarwinAot.Invalidate(funcPtr, (ulong)code.Length);
+ }
+ }
+ else if (OperatingSystem.IsMacOS()&& RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
unsafe
{
@@ -111,6 +137,11 @@ namespace ARMeilleure.Translation.Cache
public static void Unmap(IntPtr pointer)
{
+ if (OperatingSystem.IsIOS())
+ {
+ return;
+ }
+
lock (_lock)
{
Debug.Assert(_initialized);
@@ -145,11 +176,20 @@ namespace ARMeilleure.Translation.Cache
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
- private static int Allocate(int codeSize)
+ private static int Allocate(int codeSize, bool deferProtect = false)
{
- codeSize = AlignCodeSize(codeSize);
+ codeSize = AlignCodeSize(codeSize, deferProtect);
- int allocOffset = _cacheAllocator.Allocate(codeSize);
+ int alignment = CodeAlignment;
+
+ if (OperatingSystem.IsIOS() && !deferProtect)
+ {
+ alignment = 0x4000;
+ }
+
+ int allocOffset = _cacheAllocator.Allocate(ref codeSize, alignment);
+
+ Console.WriteLine($"{allocOffset:x8}: {codeSize:x8} {alignment:x8}");
if (allocOffset < 0)
{
@@ -161,9 +201,16 @@ namespace ARMeilleure.Translation.Cache
return allocOffset;
}
- private static int AlignCodeSize(int codeSize)
+ private static int AlignCodeSize(int codeSize, bool deferProtect = false)
{
- return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
+ int alignment = CodeAlignment;
+
+ if (OperatingSystem.IsIOS() && !deferProtect)
+ {
+ alignment = 0x4000;
+ }
+
+ return checked(codeSize + (alignment - 1)) & ~(alignment - 1);
}
private static void Add(int offset, int size, UnwindInfo unwindInfo)
diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs
index 6f6dfcadf..5ed27927a 100644
--- a/src/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/src/ARMeilleure/Translation/PTC/Ptc.cs
@@ -3,6 +3,7 @@ using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Common;
using ARMeilleure.Memory;
+using ARMeilleure.Translation.Cache;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
@@ -744,7 +745,7 @@ namespace ARMeilleure.Translation.PTC
bool highCq)
{
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
- var gFunc = cFunc.MapWithPointer(out IntPtr gFuncPointer);
+ var gFunc = cFunc.MapWithPointer(out IntPtr gFuncPointer, true);
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
}
@@ -826,7 +827,7 @@ namespace ARMeilleure.Translation.PTC
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
- TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq);
+ TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq, deferProtect: true);
bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func);
@@ -1004,6 +1005,7 @@ namespace ARMeilleure.Translation.PTC
osPlatform |= (OperatingSystem.IsLinux() ? 1u : 0u) << 1;
osPlatform |= (OperatingSystem.IsMacOS() ? 1u : 0u) << 2;
osPlatform |= (OperatingSystem.IsWindows() ? 1u : 0u) << 3;
+ osPlatform |= (OperatingSystem.IsIOS() ? 1u : 0u) << 4;
#pragma warning restore IDE0055
return osPlatform;
diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs
index dc18038ba..88656b68f 100644
--- a/src/ARMeilleure/Translation/Translator.cs
+++ b/src/ARMeilleure/Translation/Translator.cs
@@ -112,6 +112,8 @@ namespace ARMeilleure.Translation
Debug.Assert(Functions.Count == 0);
_ptc.LoadTranslations(this);
_ptc.MakeAndSaveTranslations(this);
+
+ JitCache.RunDeferredRxProtects();
}
_ptc.Profiler.Start();
@@ -250,7 +252,7 @@ namespace ARMeilleure.Translation
}
}
- internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
+ internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool deferProtect = false)
{
var context = new ArmEmitterContext(
Memory,
@@ -308,7 +310,7 @@ namespace ARMeilleure.Translation
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
}
- GuestFunction func = compiledFunc.MapWithPointer(out IntPtr funcPointer);
+ GuestFunction func = compiledFunc.MapWithPointer(out IntPtr funcPointer, deferProtect);
Allocators.ResetAll();
diff --git a/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs
index b83e63dbc..58137bb38 100644
--- a/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs
+++ b/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs
@@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Backends.SDL2
// TODO: Add this to SDL2-CS
// NOTE: We use a DllImport here because of marshaling issue for spec.
#pragma warning disable SYSLIB1054
- [DllImport("SDL2")]
+ [DllImport("SDL2.framework/SDL2")]
private static extern int SDL_GetDefaultAudioInfo(IntPtr name, out SDL_AudioSpec spec, int isCapture);
#pragma warning restore SYSLIB1054
diff --git a/src/Ryujinx.Common/Configuration/AppDataManager.cs b/src/Ryujinx.Common/Configuration/AppDataManager.cs
index 2b4a594d3..010b39dbf 100644
--- a/src/Ryujinx.Common/Configuration/AppDataManager.cs
+++ b/src/Ryujinx.Common/Configuration/AppDataManager.cs
@@ -50,6 +50,10 @@ namespace Ryujinx.Common.Configuration
{
appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support");
}
+ else if (OperatingSystem.IsIOS())
+ {
+ appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ }
else
{
appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
diff --git a/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
index 42ba00cd5..effc8f507 100644
--- a/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
+++ b/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
@@ -30,15 +30,26 @@ namespace Ryujinx.Common.Logging.Targets
public void Log(object sender, LogEventArgs args)
{
- Console.ForegroundColor = GetLogColor(args.Level);
- Console.WriteLine(_formatter.Format(args));
- Console.ResetColor();
+ if (OperatingSystem.IsIOS())
+ {
+ Console.WriteLine(_formatter.Format(args));
+ }
+ else
+ {
+ Console.ForegroundColor = GetLogColor(args.Level);
+ Console.WriteLine(_formatter.Format(args));
+ Console.ResetColor();
+ }
}
public void Dispose()
{
GC.SuppressFinalize(this);
- Console.ResetColor();
+
+ if (!OperatingSystem.IsIOS())
+ {
+ Console.ResetColor();
+ }
}
}
}
diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs
index ab65a98f3..bf68cbbc8 100644
--- a/src/Ryujinx.Common/ReleaseInformation.cs
+++ b/src/Ryujinx.Common/ReleaseInformation.cs
@@ -30,6 +30,11 @@ namespace Ryujinx.Common
public static string GetVersion()
{
+ if (OperatingSystem.IsIOS())
+ {
+ return "ios";
+ }
+
if (IsValid())
{
return BuildVersion;
@@ -46,7 +51,7 @@ namespace Ryujinx.Common
#else
public static string GetBaseApplicationDirectory()
{
- if (IsFlatHubBuild() || OperatingSystem.IsMacOS())
+ if (IsFlatHubBuild() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
return AppDataManager.BaseDirPath;
}
diff --git a/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs b/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs
index a04c404d8..1cf7a1928 100644
--- a/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs
+++ b/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs
@@ -19,7 +19,7 @@ namespace Ryujinx.Common.SystemInterop
public StdErrAdapter()
{
- if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) // TODO: iOS?
{
RegisterPosix();
}
@@ -27,6 +27,7 @@ namespace Ryujinx.Common.SystemInterop
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
private void RegisterPosix()
{
const int StdErrFileno = 2;
@@ -44,6 +45,7 @@ namespace Ryujinx.Common.SystemInterop
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
private async Task EventWorkerAsync(CancellationToken cancellationToken)
{
using TextReader reader = new StreamReader(_pipeReader, leaveOpen: true);
@@ -92,6 +94,7 @@ namespace Ryujinx.Common.SystemInterop
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
private static Stream CreateFileDescriptorStream(int fd)
{
return new FileStream(
diff --git a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
index fbb7399ca..9707d4fac 100644
--- a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
+++ b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
@@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu
///
/// Enables or disables the Just-in-Time compiler for GPU Macro code.
///
- public static bool EnableMacroJit = true;
+ public static bool EnableMacroJit = false;
///
/// Enables or disables high-level emulation of common GPU Macro code.
diff --git a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
index 5167ff9fe..c0a49b5f7 100644
--- a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
+++ b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
@@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{
return $"lib{libraryName}.so.{version}";
}
- else if (OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS()) // TODO: ffmpeg on ios
{
return $"lib{libraryName}.{version}.dylib";
}
diff --git a/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs b/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs
index 457240aa0..fadfc66dd 100644
--- a/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs
+++ b/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs
@@ -6,6 +6,7 @@ using System.Runtime.Versioning;
namespace Ryujinx.Graphics.Vulkan.MoltenVK
{
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
public static partial class MVKInitialization
{
[LibraryImport("libMoltenVK.dylib")]
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 893ecf1a9..d379b9c18 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -101,7 +101,7 @@ namespace Ryujinx.Graphics.Vulkan
Textures = new HashSet();
Samplers = new HashSet();
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MVKInitialization.Initialize();
diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/Types/IpAddressSetting.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/Types/IpAddressSetting.cs
index 4fa674de9..359c9b75e 100644
--- a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/Types/IpAddressSetting.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/Types/IpAddressSetting.cs
@@ -15,7 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
public IpAddressSetting(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastIPAddressInformation)
{
- IsDhcpEnabled = OperatingSystem.IsMacOS() || interfaceProperties.DhcpServerAddresses.Count != 0;
+ IsDhcpEnabled = OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || interfaceProperties.DhcpServerAddresses.Count != 0;
Address = new IpV4Address(unicastIPAddressInformation.Address);
IPv4Mask = new IpV4Address(unicastIPAddressInformation.IPv4Mask);
GatewayAddress = (interfaceProperties.GatewayAddresses.Count == 0) ? new IpV4Address() : new IpV4Address(interfaceProperties.GatewayAddresses[0].Address);
diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs
index e2ef75f80..b6d8be135 100644
--- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs
@@ -283,7 +283,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
public static LinuxError ConvertError(WsaError errorCode)
{
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
if (_errorMapMacOs.TryGetValue((int)errorCode, out LinuxError errno))
{
diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs
index 7e3c79f54..bd077bc7e 100644
--- a/src/Ryujinx.Headless.SDL2/Program.cs
+++ b/src/Ryujinx.Headless.SDL2/Program.cs
@@ -33,6 +33,7 @@ using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.IO;
+using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading;
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
@@ -60,16 +61,46 @@ namespace Ryujinx.Headless.SDL2
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+ [UnmanagedCallersOnly(EntryPoint = "main_ryujinx_sdl")]
+ public static unsafe int MainExternal(int argCount, IntPtr* pArgs)
+ {
+ string[] args = new string[argCount];
+
+ try
+ {
+ for (int i = 0; i < argCount; i++)
+ {
+ args[i] = Marshal.PtrToStringAnsi(pArgs[i]);
+
+ Console.WriteLine(args[i]);
+ }
+
+ Main(args);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ return -1;
+ }
+
+ return 0;
+ }
+
static void Main(string[] args)
{
- Version = ReleaseInformation.GetVersion();
-
// Make process DPI aware for proper window sizing on high-res screens.
ForceDpiAware.Windows();
- Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
+ Silk.NET.Core.Loader.SearchPathContainer.Platform = Silk.NET.Core.Loader.UnderlyingPlatform.MacOS;
- if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
+ Version = ReleaseInformation.GetVersion();
+
+ if (!OperatingSystem.IsIOS())
+ {
+ Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
+ }
+
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsLinux())
{
AutoResetEvent invoked = new(false);
@@ -344,12 +375,12 @@ namespace Ryujinx.Headless.SDL2
GraphicsConfig.EnableShaderCache = true;
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
if (option.GraphicsBackend == GraphicsBackend.OpenGl)
{
option.GraphicsBackend = GraphicsBackend.Vulkan;
- Logger.Warning?.Print(LogClass.Application, "OpenGL is not supported on macOS, switching to Vulkan!");
+ Logger.Warning?.Print(LogClass.Application, "OpenGL is not supported on Apple platforms, switching to Vulkan!");
}
}
diff --git a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
index 7b13df736..bb43ced2e 100644
--- a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
+++ b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
@@ -2,21 +2,88 @@
net8.0
- win-x64;osx-x64;linux-x64
- Exe
+ ios-arm64
true
1.0.0-dirty
$(DefineConstants);$(ExtraDefineConstants)
-
true
+
+ true
+ true
+ true
+ false
+
+
+
+ true
+ true
+ true
+ /Applications/Xcode.app/Contents/Developer
+ $([MSBuild]::EnsureTrailingSlash('$(XCodePath)'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(XcodeSelect)
+ $([MSBuild]::EnsureTrailingSlash('$(XCodePath)'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -65,7 +132,7 @@
- true
+ false
true
partial
diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs
index adab07641..9603a86be 100644
--- a/src/Ryujinx.Headless.SDL2/WindowBase.cs
+++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs
@@ -36,7 +36,7 @@ namespace Ryujinx.Headless.SDL2
private static readonly ConcurrentQueue _mainThreadActions = new();
- [LibraryImport("SDL2")]
+ [LibraryImport("SDL2.framework/SDL2")]
// TODO: Remove this as soon as SDL2-CS was updated to expose this method publicly
private static partial IntPtr SDL_LoadBMP_RW(IntPtr src, int freesrc);
diff --git a/src/Ryujinx.Memory/MachJitWorkaround.cs b/src/Ryujinx.Memory/MachJitWorkaround.cs
new file mode 100644
index 000000000..cfb1e419c
--- /dev/null
+++ b/src/Ryujinx.Memory/MachJitWorkaround.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.Memory
+{
+ [SupportedOSPlatform("ios")]
+ static unsafe partial class MachJitWorkaround
+ {
+ [LibraryImport("libc")]
+ public static partial int mach_task_self();
+
+ [LibraryImport("libc")]
+ public static partial int mach_make_memory_entry_64(IntPtr target_task, IntPtr* size, IntPtr offset, int permission, IntPtr* object_handle, IntPtr parent_entry);
+
+ [LibraryImport("libc")]
+ public static partial int mach_memory_entry_ownership(IntPtr mem_entry, IntPtr owner, int ledger_tag, int ledger_flags);
+
+ [LibraryImport("libc")]
+ public static partial int vm_map(IntPtr target_task, IntPtr* address, IntPtr size, IntPtr mask, int flags, IntPtr obj, IntPtr offset, int copy, int cur_protection, int max_protection, int inheritance);
+
+ [LibraryImport("libc")]
+ public static partial int vm_allocate(IntPtr target_task, IntPtr* address, IntPtr size, int flags);
+
+ [LibraryImport("libc")]
+ public static partial int vm_deallocate(IntPtr target_task, IntPtr address, IntPtr size);
+
+ [LibraryImport("libc")]
+ public static partial int vm_remap(IntPtr target_task, IntPtr* target_address, IntPtr size, IntPtr mask, int flags, IntPtr src_task, IntPtr src_address, int copy, int* cur_protection, int* max_protection, int inheritance);
+
+ const int MAP_MEM_LEDGER_TAGGED = 0x002000;
+ const int MAP_MEM_NAMED_CREATE = 0x020000;
+
+ const int VM_PROT_READ = 0x01;
+ const int VM_PROT_WRITE = 0x02;
+ const int VM_PROT_EXECUTE = 0x04;
+
+ const int VM_LEDGER_TAG_DEFAULT = 0x00000001;
+ const int VM_LEDGER_FLAG_NO_FOOTPRINT = 0x00000001;
+
+ const int VM_INHERIT_COPY = 1;
+ const int VM_INHERIT_DEFAULT = VM_INHERIT_COPY;
+
+ const int VM_FLAGS_FIXED = 0x0000;
+ const int VM_FLAGS_ANYWHERE = 0x0001;
+ const int VM_FLAGS_OVERWRITE = 0x4000;
+
+ const IntPtr TASK_NULL = 0;
+
+ public static void ReallocateBlock(IntPtr address, int size)
+ {
+ IntPtr selfTask = mach_task_self();
+ IntPtr memorySize = (IntPtr)size;
+ IntPtr memoryObjectPort = IntPtr.Zero;
+
+ int err = mach_make_memory_entry_64(selfTask, &memorySize, 0, MAP_MEM_NAMED_CREATE | MAP_MEM_LEDGER_TAGGED | VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, &memoryObjectPort, 0);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException($"Make memory entry failed: {err}");
+ }
+
+ try
+ {
+ if (memorySize != (IntPtr)size)
+ {
+ throw new InvalidOperationException($"Created with size {memorySize} instead of {size}.");
+ }
+
+ err = mach_memory_entry_ownership(memoryObjectPort, TASK_NULL, VM_LEDGER_TAG_DEFAULT, VM_LEDGER_FLAG_NO_FOOTPRINT);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException($"Failed to set ownership: {err}");
+ }
+
+ IntPtr mapAddress = address;
+
+ err = vm_map(
+ selfTask,
+ &mapAddress,
+ memorySize,
+ /*mask=*/ 0,
+ /*flags=*/ VM_FLAGS_OVERWRITE,
+ memoryObjectPort,
+ /*offset=*/ 0,
+ /*copy=*/ 0,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE,
+ VM_INHERIT_COPY);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException($"Failed to map: {err}");
+ }
+
+ if (address != mapAddress)
+ {
+ throw new InvalidOperationException($"Remap changed address");
+ }
+ }
+ finally
+ {
+ //mach_port_deallocate(selfTask, memoryObjectPort);
+ }
+
+ Console.WriteLine($"Reallocated an area... {address:x16}");
+ }
+
+ public static void ReallocateAreaWithOwnership(IntPtr address, int size)
+ {
+ int mapChunkSize = 128 * 1024 * 1024;
+ IntPtr endAddress = address + size;
+ IntPtr blockAddress = address;
+ while (blockAddress < endAddress)
+ {
+ int blockSize = Math.Min(mapChunkSize, (int)(endAddress - blockAddress));
+
+ ReallocateBlock(blockAddress, blockSize);
+
+ blockAddress += blockSize;
+ }
+ }
+
+ public static IntPtr AllocateSharedMemory(ulong size, bool reserve)
+ {
+ IntPtr address = 0;
+
+ int err = vm_allocate(mach_task_self(), &address, (IntPtr)size, VM_FLAGS_ANYWHERE);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException($"Failed to allocate shared memory: {err}");
+ }
+
+ return address;
+ }
+
+ public static void DestroySharedMemory(IntPtr handle, ulong size)
+ {
+ vm_deallocate(mach_task_self(), handle, (IntPtr)size);
+ }
+
+ public static IntPtr MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size)
+ {
+ IntPtr taskSelf = mach_task_self();
+ IntPtr srcAddress = (IntPtr)((ulong)sharedMemory + srcOffset);
+ IntPtr dstAddress = location;
+
+ int cur_protection = 0;
+ int max_protection = 0;
+
+ int err = vm_remap(taskSelf, &dstAddress, (IntPtr)size, 0, VM_FLAGS_OVERWRITE, taskSelf, srcAddress, 0, &cur_protection, &max_protection, VM_INHERIT_DEFAULT);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException($"Failed to allocate remap memory: {err}");
+ }
+
+ return dstAddress;
+ }
+
+ public static void UnmapView(IntPtr location, ulong size)
+ {
+ vm_deallocate(mach_task_self(), location, (IntPtr)size);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ryujinx.Memory/MemoryBlock.cs b/src/Ryujinx.Memory/MemoryBlock.cs
index 7fe7862a9..477be893a 100644
--- a/src/Ryujinx.Memory/MemoryBlock.cs
+++ b/src/Ryujinx.Memory/MemoryBlock.cs
@@ -426,7 +426,7 @@ namespace Ryujinx.Memory
return OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
}
- return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
+ return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS();
}
return true;
diff --git a/src/Ryujinx.Memory/MemoryManagement.cs b/src/Ryujinx.Memory/MemoryManagement.cs
index 860d3f368..a23fafb57 100644
--- a/src/Ryujinx.Memory/MemoryManagement.cs
+++ b/src/Ryujinx.Memory/MemoryManagement.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.Memory
{
return MemoryManagementWindows.Allocate((IntPtr)size);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
return MemoryManagementUnix.Allocate(size, forJit);
}
@@ -26,7 +26,7 @@ namespace Ryujinx.Memory
{
return MemoryManagementWindows.Reserve((IntPtr)size, viewCompatible);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
return MemoryManagementUnix.Reserve(size, forJit);
}
@@ -42,7 +42,7 @@ namespace Ryujinx.Memory
{
MemoryManagementWindows.Commit(address, (IntPtr)size);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MemoryManagementUnix.Commit(address, size, forJit);
}
@@ -58,7 +58,7 @@ namespace Ryujinx.Memory
{
MemoryManagementWindows.Decommit(address, (IntPtr)size);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MemoryManagementUnix.Decommit(address, size);
}
@@ -74,7 +74,7 @@ namespace Ryujinx.Memory
{
MemoryManagementWindows.MapView(sharedMemory, srcOffset, address, (IntPtr)size, owner);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MemoryManagementUnix.MapView(sharedMemory, srcOffset, address, size);
}
@@ -90,7 +90,7 @@ namespace Ryujinx.Memory
{
MemoryManagementWindows.UnmapView(sharedMemory, address, (IntPtr)size, owner);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MemoryManagementUnix.UnmapView(address, size);
}
@@ -108,7 +108,7 @@ namespace Ryujinx.Memory
{
result = MemoryManagementWindows.Reprotect(address, (IntPtr)size, permission, forView);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
result = MemoryManagementUnix.Reprotect(address, size, permission);
}
@@ -129,7 +129,7 @@ namespace Ryujinx.Memory
{
return MemoryManagementWindows.Free(address, (IntPtr)size);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
return MemoryManagementUnix.Free(address);
}
@@ -145,7 +145,7 @@ namespace Ryujinx.Memory
{
return MemoryManagementWindows.CreateSharedMemory((IntPtr)size, reserve);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
return MemoryManagementUnix.CreateSharedMemory(size, reserve);
}
@@ -161,7 +161,7 @@ namespace Ryujinx.Memory
{
MemoryManagementWindows.DestroySharedMemory(handle);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MemoryManagementUnix.DestroySharedMemory(handle);
}
@@ -177,7 +177,7 @@ namespace Ryujinx.Memory
{
return MemoryManagementWindows.MapSharedMemory(handle);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
return MemoryManagementUnix.MapSharedMemory(handle, size);
}
@@ -193,7 +193,7 @@ namespace Ryujinx.Memory
{
MemoryManagementWindows.UnmapSharedMemory(address);
}
- else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
MemoryManagementUnix.UnmapSharedMemory(address, size);
}
diff --git a/src/Ryujinx.Memory/MemoryManagementUnix.cs b/src/Ryujinx.Memory/MemoryManagementUnix.cs
index e132dbbb8..78966777e 100644
--- a/src/Ryujinx.Memory/MemoryManagementUnix.cs
+++ b/src/Ryujinx.Memory/MemoryManagementUnix.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using static Ryujinx.Memory.MemoryManagerUnixHelper;
@@ -8,6 +9,7 @@ namespace Ryujinx.Memory
{
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
static class MemoryManagementUnix
{
private static readonly ConcurrentDictionary _allocations = new();
@@ -40,7 +42,7 @@ namespace Ryujinx.Memory
flags |= MmapFlags.MAP_NORESERVE;
}
- if (OperatingSystem.IsMacOSVersionAtLeast(10, 14) && forJit)
+ if (OperatingSystem.IsMacOS() && OperatingSystem.IsMacOSVersionAtLeast(10, 14) && forJit)
{
flags |= MmapFlags.MAP_JIT_DARWIN;
@@ -57,6 +59,11 @@ namespace Ryujinx.Memory
throw new SystemException(Marshal.GetLastPInvokeErrorMessage());
}
+ if (OperatingSystem.IsIOS() && forJit)
+ {
+ MachJitWorkaround.ReallocateAreaWithOwnership(ptr, (int)size);
+ }
+
if (!_allocations.TryAdd(ptr, size))
{
// This should be impossible, kernel shouldn't return an already mapped address.
@@ -70,7 +77,7 @@ namespace Ryujinx.Memory
{
MmapProts prot = MmapProts.PROT_READ | MmapProts.PROT_WRITE;
- if (OperatingSystem.IsMacOSVersionAtLeast(10, 14) && forJit)
+ if ((OperatingSystem.IsIOS() || OperatingSystem.IsMacOSVersionAtLeast(10, 14)) && forJit)
{
prot |= MmapProts.PROT_EXEC;
}
@@ -134,11 +141,21 @@ namespace Ryujinx.Memory
return munmap(address, size) == 0;
}
+ private static Dictionary _sharedMemorySizes = new Dictionary();
+
public unsafe static IntPtr CreateSharedMemory(ulong size, bool reserve)
{
int fd;
- if (OperatingSystem.IsMacOS())
+ if (OperatingSystem.IsIOS())
+ {
+ IntPtr baseAddress = MachJitWorkaround.AllocateSharedMemory(size, reserve);
+
+ _sharedMemorySizes.Add(baseAddress, size);
+
+ return baseAddress;
+ }
+ else if (OperatingSystem.IsMacOS())
{
byte[] memName = "Ryujinx-XXXXXX"u8.ToArray();
@@ -185,27 +202,64 @@ namespace Ryujinx.Memory
public static void DestroySharedMemory(IntPtr handle)
{
- close(handle.ToInt32());
+ if (OperatingSystem.IsIOS())
+ {
+ if (_sharedMemorySizes.TryGetValue(handle, out ulong size))
+ {
+ MachJitWorkaround.DestroySharedMemory(handle, size);
+ }
+ }
+ else
+ {
+ close(handle.ToInt32());
+ }
}
public static IntPtr MapSharedMemory(IntPtr handle, ulong size)
{
- return Mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, handle.ToInt32(), 0);
+ if (OperatingSystem.IsIOS())
+ {
+ // The base of the shared memory is already mapped - it's the handle.
+ // Views are remapped from it.
+
+ return handle;
+ }
+ else
+ {
+ return Mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, handle.ToInt32(), 0);
+ }
}
public static void UnmapSharedMemory(IntPtr address, ulong size)
{
- munmap(address, size);
+ if (!OperatingSystem.IsIOS())
+ {
+ munmap(address, size);
+ }
}
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size)
{
- Mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, sharedMemory.ToInt32(), (long)srcOffset);
+ if (OperatingSystem.IsIOS())
+ {
+ MachJitWorkaround.MapView(sharedMemory, srcOffset, location, size);
+ }
+ else
+ {
+ Mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, sharedMemory.ToInt32(), (long)srcOffset);
+ }
}
public static void UnmapView(IntPtr location, ulong size)
{
- Mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED | MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_NORESERVE, -1, 0);
+ if (OperatingSystem.IsIOS())
+ {
+ MachJitWorkaround.UnmapView(location, size);
+ }
+ else
+ {
+ Mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED | MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_NORESERVE, -1, 0);
+ }
}
}
}
diff --git a/src/Ryujinx.Memory/MemoryManagerUnixHelper.cs b/src/Ryujinx.Memory/MemoryManagerUnixHelper.cs
index 43888c85b..6ed4d2387 100644
--- a/src/Ryujinx.Memory/MemoryManagerUnixHelper.cs
+++ b/src/Ryujinx.Memory/MemoryManagerUnixHelper.cs
@@ -6,6 +6,7 @@ namespace Ryujinx.Memory
{
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
public static partial class MemoryManagerUnixHelper
{
[Flags]
@@ -114,7 +115,7 @@ namespace Ryujinx.Memory
{
result |= MAP_ANONYMOUS_LINUX_GENERIC;
}
- else if (OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
result |= MAP_ANONYMOUS_DARWIN;
}
@@ -130,7 +131,7 @@ namespace Ryujinx.Memory
{
result |= MAP_NORESERVE_LINUX_GENERIC;
}
- else if (OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
result |= MAP_NORESERVE_DARWIN;
}
@@ -146,7 +147,7 @@ namespace Ryujinx.Memory
{
result |= MAP_UNLOCKED_LINUX_GENERIC;
}
- else if (OperatingSystem.IsMacOS())
+ else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
// FIXME: Doesn't exist on Darwin
}
@@ -156,7 +157,7 @@ namespace Ryujinx.Memory
}
}
- if (flags.HasFlag(MmapFlags.MAP_JIT_DARWIN) && OperatingSystem.IsMacOSVersionAtLeast(10, 14))
+ if (flags.HasFlag(MmapFlags.MAP_JIT_DARWIN) && (OperatingSystem.IsIOS() || OperatingSystem.IsMacOSVersionAtLeast(10, 14)))
{
result |= (int)MmapFlags.MAP_JIT_DARWIN;
}
diff --git a/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs b/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
index b017d384c..52575a7e3 100644
--- a/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
+++ b/src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
@@ -1536,7 +1536,7 @@ namespace Ryujinx.Ui.Common.Configuration
{
// Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan.
// Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
- if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
+ if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
{
return GraphicsBackend.Vulkan;
}
diff --git a/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs b/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
index af8723e2f..16a67ecb2 100644
--- a/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
+++ b/src/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
@@ -5,6 +5,7 @@ using System.Runtime.Versioning;
namespace Ryujinx.Ui.Common.Helper
{
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
public static partial class ObjectiveC
{
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
diff --git a/src/Ryujinx/Ui/Helper/MetalHelper.cs b/src/Ryujinx/Ui/Helper/MetalHelper.cs
index a7af2aed2..f46a5e36e 100644
--- a/src/Ryujinx/Ui/Helper/MetalHelper.cs
+++ b/src/Ryujinx/Ui/Helper/MetalHelper.cs
@@ -8,6 +8,7 @@ namespace Ryujinx.Ui.Helper
public delegate void UpdateBoundsCallbackDelegate(Window window);
[SupportedOSPlatform("macos")]
+ [SupportedOSPlatform("ios")]
static partial class MetalHelper
{
private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";