Răsfoiți Sursa

am: Implement CreateHandleStorage and fixes (#1929)

Ac_K 5 ani în urmă
părinte
comite
1364f36161

+ 38 - 7
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs

@@ -26,8 +26,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         {
             long size = context.RequestData.ReadInt64();
 
+            if (size <= 0)
+            {
+                return ResultCode.ObjectInvalid;
+            }
+
             MakeObject(context, new IStorage(new byte[size]));
 
+            // NOTE: Returns ResultCode.MemoryAllocationFailed if IStorage is null, it doesn't occur in our case.
+
             return ResultCode.Success;
         }
 
@@ -35,20 +42,44 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         // CreateTransferMemoryStorage(b8, u64, handle<copy>) -> object<nn::am::service::IStorage>
         public ResultCode CreateTransferMemoryStorage(ServiceCtx context)
         {
-            bool unknown = context.RequestData.ReadBoolean();
-            long size    = context.RequestData.ReadInt64();
-            int  handle  = context.Request.HandleDesc.ToCopy[0];
+            bool isReadOnly = context.RequestData.ReadBoolean();
+            long size       = context.RequestData.ReadInt64();
+            int  handle     = context.Request.HandleDesc.ToCopy[0];
 
             KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle);
 
-            if (transferMem == null)
+            if (size <= 0)
             {
-                Logger.Warning?.Print(LogClass.ServiceAm, $"Invalid TransferMemory Handle: {handle:X}");
+                return ResultCode.ObjectInvalid;
+            }
+
+            byte[] data = new byte[transferMem.Size];
+
+            transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
+
+            context.Device.System.KernelContext.Syscall.CloseHandle(handle);
 
-                return ResultCode.Success; // TODO: Find correct error code
+            MakeObject(context, new IStorage(data, isReadOnly));
+
+            return ResultCode.Success;
+        }
+
+        [Command(12)] // 2.0.0+
+        // CreateHandleStorage(u64, handle<copy>) -> object<nn::am::service::IStorage>
+        public ResultCode CreateHandleStorage(ServiceCtx context)
+        {
+            long size   = context.RequestData.ReadInt64();
+            int  handle = context.Request.HandleDesc.ToCopy[0];
+
+            KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle);
+
+            if (size <= 0)
+            {
+                return ResultCode.ObjectInvalid;
             }
 
-            var data = new byte[transferMem.Size];
+            byte[] data = new byte[transferMem.Size];
+
             transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
 
             context.Device.System.KernelContext.Syscall.CloseHandle(handle);

+ 5 - 3
Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs

@@ -2,11 +2,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
 {
     class IStorage : IpcService
     {
-        public byte[] Data { get; private set; }
+        public bool   IsReadOnly { get; private set; }
+        public byte[] Data       { get; private set; }
 
-        public IStorage(byte[] data)
+        public IStorage(byte[] data, bool isReadOnly = false)
         {
-            Data = data;
+            IsReadOnly = isReadOnly;
+            Data       = data;
         }
 
         [Command(0)]

+ 5 - 0
Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs

@@ -24,6 +24,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
         // Write(u64, buffer<bytes, 0x21>)
         public ResultCode Write(ServiceCtx context)
         {
+            if (_storage.IsReadOnly)
+            {
+                return ResultCode.ObjectInvalid;
+            }
+
             long writePosition = context.RequestData.ReadInt64();
 
             if (writePosition > _storage.Data.Length)