From db9f8f999f2c9a50e25685424271735ed3538539 Mon Sep 17 00:00:00 2001
From: Thog <me@thog.eu>
Date: Thu, 6 Feb 2020 05:09:59 +0100
Subject: [PATCH] Implement IDeliveryCacheProgressService in bcat (#908)

* Implement IDeliveryCacheProgressService in bcat

This stub IDeliveryCacheProgressService IPC interface as we don't plan
to support cache delivery.

* Address jd's comments

* Address jd's comment correctly

* Address gdk's comments
---
 Ryujinx.Common/Logging/LogClass.cs            |  1 +
 .../Bcat/ServiceCreator/IBcatService.cs       |  9 +++
 .../IDeliveryCacheProgressService.cs          | 64 +++++++++++++++++++
 .../Types/DeliveryCacheProgressImpl.cs        | 18 ++++++
 4 files changed, 92 insertions(+)
 create mode 100644 Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs

diff --git a/Ryujinx.Common/Logging/LogClass.cs b/Ryujinx.Common/Logging/LogClass.cs
index 43efd8d58b..2aa601464b 100644
--- a/Ryujinx.Common/Logging/LogClass.cs
+++ b/Ryujinx.Common/Logging/LogClass.cs
@@ -19,6 +19,7 @@ namespace Ryujinx.Common.Logging
         ServiceAm,
         ServiceApm,
         ServiceAudio,
+        ServiceBcat,
         ServiceBsd,
         ServiceBtm,
         ServiceCaps,
diff --git a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs
index 1b32756a25..ff743f1535 100644
--- a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs
+++ b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs
@@ -5,5 +5,14 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
     class IBcatService : IpcService
     {
         public IBcatService(ApplicationLaunchProperty applicationLaunchProperty) { }
+
+        [Command(10100)]
+        // RequestSyncDeliveryCache() -> object<nn::bcat::detail::ipc::IDeliveryCacheProgressService>
+        public ResultCode RequestSyncDeliveryCache(ServiceCtx context)
+        {
+            MakeObject(context, new IDeliveryCacheProgressService(context));
+
+            return ResultCode.Success;
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs
new file mode 100644
index 0000000000..cb80904879
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs
@@ -0,0 +1,64 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator.Types;
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
+{
+    class IDeliveryCacheProgressService : IpcService
+    {
+        private KEvent _event;
+
+        public IDeliveryCacheProgressService(ServiceCtx context)
+        {
+            _event = new KEvent(context.Device.System);
+        }
+
+        [Command(0)]
+        // GetEvent() -> handle<copy>
+        public ResultCode GetEvent(ServiceCtx context)
+        {
+            if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out int handle) != KernelResult.Success)
+            {
+                throw new InvalidOperationException("Out of handles!");
+            }
+
+            context.Response.HandleDesc = IpcHandleDesc.MakeMove(handle);
+
+            Logger.PrintStub(LogClass.ServiceBcat);
+
+            return ResultCode.Success;
+        }
+
+        [Command(1)]
+        // GetImpl() -> buffer<nn::bcat::detail::DeliveryCacheProgressImpl, 0x1a>
+        public ResultCode GetImpl(ServiceCtx context)
+        {
+            DeliveryCacheProgressImpl deliveryCacheProgress = new DeliveryCacheProgressImpl
+            {
+                State  = DeliveryCacheProgressImpl.Status.Done,
+                Result = 0
+            };
+
+            WriteDeliveryCacheProgressImpl(context, context.Request.RecvListBuff[0], deliveryCacheProgress);
+
+            Logger.PrintStub(LogClass.ServiceBcat);
+
+            return ResultCode.Success;
+        }
+
+        private void WriteDeliveryCacheProgressImpl(ServiceCtx context, IpcRecvListBuffDesc ipcDesc, DeliveryCacheProgressImpl deliveryCacheProgress)
+        {
+            using (MemoryStream memory = new MemoryStream((int)ipcDesc.Size))
+            using (BinaryWriter bufferWriter = new BinaryWriter(memory))
+            {
+                bufferWriter.WriteStruct(deliveryCacheProgress);
+                context.Memory.WriteBytes(ipcDesc.Position, memory.ToArray());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs
new file mode 100644
index 0000000000..fb9a67be6e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs
@@ -0,0 +1,18 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator.Types
+{
+    [StructLayout(LayoutKind.Sequential, Size = 0x200)]
+    public struct DeliveryCacheProgressImpl
+    {
+        public enum Status
+        {
+            // TODO: determine other values
+            Done = 9
+        }
+
+        public Status State;
+        public uint   Result;
+        // TODO: reverse the rest of the structure
+    }
+}