Răsfoiți Sursa

bcat:u: Implement EnumerateDeliveryCacheDirectory (#768)

* bcat:u: Implement EnumerateDeliveryCacheDirectory

Basic implementation `EnumerateDeliveryCacheDirectory` call to `IDeliveryCacheStorageService` according to RE.  (close #622)
I've added some comments in the whole service for when we'll implement a real bcat implementation.
For now, all games who use it isn't playable because of GPU.

* Use Array instead of List

* Add ApplicationLaunchPropertyHelper

* Fix helper

* Fix helper 2

* Fix ApplicationLaunchProperty Default

* Fix ApplicationLaunchProperty 2

* Fix folder
Ac_K 6 ani în urmă
părinte
comite
0e93a51030

+ 3 - 15
Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs

@@ -1,6 +1,6 @@
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS.Services.Arp;
+using Ryujinx.HLE.HOS.Services.Glue;
 using Ryujinx.HLE.HOS.SystemState;
 using Ryujinx.HLE.Utilities;
 using System;
@@ -173,26 +173,14 @@ namespace Ryujinx.HLE.HOS.Services.Acc
             /*
             if (nn::arp::detail::IReader::GetApplicationLaunchProperty() == 0xCC9D) // InvalidProcessId
             {
-                _applicationLaunchProperty = new ApplicationLaunchProperty
-                {
-                    TitleId             = 0x00;
-                    Version             = 0x00;
-                    BaseGameStorageId   = 0x03;
-                    UpdateGameStorageId = 0x00;
-                }
+                _applicationLaunchProperty = ApplicationLaunchProperty.Default;
 
                 return ResultCode.InvalidArgument;
             }
             else
             */
             {
-                _applicationLaunchProperty = new ApplicationLaunchProperty
-                {
-                    TitleId             = BitConverter.ToInt64(StringUtils.HexToBytes(context.Device.System.TitleID), 0),
-                    Version             = 0x00,
-                    BaseGameStorageId   = (byte)StorageId.NandSystem,
-                    UpdateGameStorageId = (byte)StorageId.None
-                };
+                _applicationLaunchProperty = ApplicationLaunchProperty.GetByPid(context);
             }
 
             Logger.PrintStub(LogClass.ServiceAcc, new { unknown });

+ 1 - 1
Ryujinx.HLE/HOS/Services/Acc/IManagerForApplication.cs

@@ -1,5 +1,5 @@
 using Ryujinx.Common.Logging;
-using Ryujinx.HLE.HOS.Services.Arp;
+using Ryujinx.HLE.HOS.Services.Glue;
 using Ryujinx.HLE.Utilities;
 
 namespace Ryujinx.HLE.HOS.Services.Acc

+ 0 - 11
Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs

@@ -1,11 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Arp
-{
-    class ApplicationLaunchProperty
-    {
-        public long  TitleId;
-        public int   Version;
-        public byte  BaseGameStorageId;
-        public byte  UpdateGameStorageId;
-        public short Padding;
-    }
-}

+ 3 - 1
Ryujinx.HLE/HOS/Services/Bcat/IBcatService.cs

@@ -1,7 +1,9 @@
+using Ryujinx.HLE.HOS.Services.Glue;
+
 namespace Ryujinx.HLE.HOS.Services.Bcat
 {
     class IBcatService : IpcService
     {
-        public IBcatService() { }
+        public IBcatService(ApplicationLaunchProperty applicationLaunchProperty) { }
     }
 }

+ 41 - 1
Ryujinx.HLE/HOS/Services/Bcat/IDeliveryCacheStorageService.cs

@@ -1,7 +1,47 @@
+using Ryujinx.HLE.HOS.Services.Glue;
+using System;
+using System.Text;
+
 namespace Ryujinx.HLE.HOS.Services.Bcat
 {
     class IDeliveryCacheStorageService : IpcService
     {
-        public IDeliveryCacheStorageService() { }
+        private const int DeliveryCacheDirectoriesLimit    = 100;
+        private const int DeliveryCacheDirectoryNameLength = 32;
+
+        private string[] _deliveryCacheDirectories = new string[0];
+
+        public IDeliveryCacheStorageService(ServiceCtx context, ApplicationLaunchProperty applicationLaunchProperty)
+        {
+            // TODO: Read directories.meta file from the save data (loaded in IServiceCreator) in _deliveryCacheDirectories.
+        }
+
+        [Command(10)]
+        // EnumerateDeliveryCacheDirectory() -> (u32, buffer<nn::bcat::DirectoryName, 6>)
+        public ResultCode EnumerateDeliveryCacheDirectory(ServiceCtx context)
+        {
+            long outputPosition = context.Request.ReceiveBuff[0].Position;
+            long outputSize     = context.Request.ReceiveBuff[0].Size;
+
+            for (int index = 0; index < _deliveryCacheDirectories.Length; index++)
+            {
+                if (index == DeliveryCacheDirectoriesLimit - 1)
+                {
+                    break;
+                }
+
+                byte[] directoryNameBuffer = Encoding.ASCII.GetBytes(_deliveryCacheDirectories[index]);
+
+                Array.Resize(ref directoryNameBuffer, DeliveryCacheDirectoryNameLength);
+
+                directoryNameBuffer[DeliveryCacheDirectoryNameLength - 1] = 0x00;
+                
+                context.Memory.WriteBytes(outputPosition + index * DeliveryCacheDirectoryNameLength, directoryNameBuffer);
+            }
+
+            context.ResponseData.Write(_deliveryCacheDirectories.Length);
+
+            return ResultCode.Success;
+        }
     }
 }

+ 20 - 4
Ryujinx.HLE/HOS/Services/Bcat/IServiceCreator.cs

@@ -1,3 +1,5 @@
+using Ryujinx.HLE.HOS.Services.Glue;
+
 namespace Ryujinx.HLE.HOS.Services.Bcat
 {
     [Service("bcat:a")]
@@ -12,9 +14,16 @@ namespace Ryujinx.HLE.HOS.Services.Bcat
         // CreateBcatService(u64, pid) -> object<nn::bcat::detail::ipc::IBcatService>
         public ResultCode CreateBcatService(ServiceCtx context)
         {
-            long id = context.RequestData.ReadInt64();
+            // TODO: Call arp:r GetApplicationLaunchProperty with the pid to get the TitleId.
+            //       Add an instance of nn::bcat::detail::service::core::PassphraseManager.
+            //       Add an instance of nn::bcat::detail::service::ServiceMemoryManager.
+            //       Add an instance of nn::bcat::detail::service::core::TaskManager who load "bcat-sys:/" system save data and open "dc/task.bin". 
+            //       If the file don't exist, create a new one (size of 0x800) and write 2 empty struct with a size of 0x400.
+
+            MakeObject(context, new IBcatService(ApplicationLaunchProperty.GetByPid(context)));
 
-            MakeObject(context, new IBcatService());
+            // NOTE: If the IBcatService is null this error is returned, Doesn't occur in our case. 
+            //       return ResultCode.NullObject;
 
             return ResultCode.Success;
         }
@@ -23,9 +32,16 @@ namespace Ryujinx.HLE.HOS.Services.Bcat
         // CreateDeliveryCacheStorageService(u64, pid) -> object<nn::bcat::detail::ipc::IDeliveryCacheStorageService>
         public ResultCode CreateDeliveryCacheStorageService(ServiceCtx context)
         {
-            long id = context.RequestData.ReadInt64();
+            // TODO: Call arp:r GetApplicationLaunchProperty with the pid to get the TitleId.
+            //       Add an instance of nn::bcat::detail::service::core::ApplicationStorageManager who load "bcat-dc-X:/" system save data,
+            //       return ResultCode.NullSaveData if failed.
+            //       Where X depend of the ApplicationLaunchProperty stored in an array (range 0-3).
+            //       Add an instance of nn::bcat::detail::service::ServiceMemoryManager.
+
+            MakeObject(context, new IDeliveryCacheStorageService(context, ApplicationLaunchProperty.GetByPid(context)));
 
-            MakeObject(context, new IDeliveryCacheStorageService());
+            // NOTE: If the IDeliveryCacheStorageService is null this error is returned, Doesn't occur in our case. 
+            //       return ResultCode.NullObject;
 
             return ResultCode.Success;
         }

+ 14 - 0
Ryujinx.HLE/HOS/Services/Bcat/ResultCode.cs

@@ -0,0 +1,14 @@
+namespace Ryujinx.HLE.HOS.Services.Bcat
+{
+    enum ResultCode
+    {
+        ModuleId       = 122,
+        ErrorCodeShift = 9,
+
+        Success = 0,
+
+        NullArgument = (2  << ErrorCodeShift) | ModuleId,
+        NullSaveData = (31 << ErrorCodeShift) | ModuleId,
+        NullObject   = (91 << ErrorCodeShift) | ModuleId
+    }
+}

+ 43 - 0
Ryujinx.HLE/HOS/Services/Glue/ApplicationLaunchProperty.cs

@@ -0,0 +1,43 @@
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.Utilities;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Glue
+{
+    class ApplicationLaunchProperty
+    {
+        public long  TitleId;
+        public int   Version;
+        public byte  BaseGameStorageId;
+        public byte  UpdateGameStorageId;
+        public short Padding;
+
+        public static ApplicationLaunchProperty Default
+        {
+            get
+            {
+                return new ApplicationLaunchProperty
+                {
+                    TitleId             = 0x00,
+                    Version             = 0x00,
+                    BaseGameStorageId   = (byte)StorageId.NandSystem,
+                    UpdateGameStorageId = (byte)StorageId.None
+                };
+            }
+        }
+
+        public static ApplicationLaunchProperty GetByPid(ServiceCtx context)
+        {
+            // TODO: Handle ApplicationLaunchProperty as array when pid will be supported and return the right item.
+            //       For now we can hardcode values, and fix it after GetApplicationLaunchProperty is implemented.
+
+            return new ApplicationLaunchProperty
+            {
+                TitleId             = BitConverter.ToInt64(StringUtils.HexToBytes(context.Device.System.TitleID), 0),
+                Version             = 0x00,
+                BaseGameStorageId   = (byte)StorageId.NandSystem,
+                UpdateGameStorageId = (byte)StorageId.None
+            };
+        }
+    }
+}