From c464e1ec522d41565923fbc542148ebeca61749e Mon Sep 17 00:00:00 2001
From: Thog <me@thog.eu>
Date: Wed, 12 Feb 2020 00:07:13 +0100
Subject: [PATCH] Stub the application copyright framebuffer api (#921)

* Stub the application copyright framebuffer api

As we currently don't support multi layers on vi/nvnflinger, this PR
implement a stub of this API.

* Address Cyuubi's comments

* Add IPC checks and comments for future reversing

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
---
 .../SystemAppletProxy/ICommonStateGetter.cs   |   2 +-
 .../ApplicationProxy/IApplicationFunctions.cs | 109 ++++++++++++++++++
 Ryujinx.HLE/HOS/Services/Am/ResultCode.cs     |  11 +-
 3 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
index 085d9fe600..10c732b75b 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
@@ -128,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
 
             if (cpuBoostMode > 1)
             {
-                return ResultCode.CpuBoostModeInvalid;
+                return ResultCode.InvalidParameters;
             }
 
             _cpuBoostMode = (CpuBoostMode)cpuBoostMode;
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
index 3ae24c555a..990b18ee95 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
@@ -8,6 +8,7 @@ using Ryujinx.Common;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage;
 using Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService;
@@ -168,6 +169,114 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
             return ResultCode.Success;
         }
 
+        [Command(100)] // 5.0.0+
+        // InitializeApplicationCopyrightFrameBuffer(s32 width, s32 height, handle<copy, transfer_memory> transfer_memory, u64 transfer_memory_size)
+        public ResultCode InitializeApplicationCopyrightFrameBuffer(ServiceCtx context)
+        {
+            int   width                 = context.RequestData.ReadInt32();
+            int   height                = context.RequestData.ReadInt32();
+            ulong transferMemorySize    = context.RequestData.ReadUInt64();
+            int   transferMemoryHandle  = context.Request.HandleDesc.ToCopy[0];
+            ulong transferMemoryAddress = context.Process.HandleTable.GetObject<KTransferMemory>(transferMemoryHandle).Address;
+
+            ResultCode resultCode = ResultCode.InvalidParameters;
+
+            if (((transferMemorySize & 0x3FFFF) == 0) && width <= 1280 && height <= 720)
+            {
+                resultCode = InitializeApplicationCopyrightFrameBufferImpl(transferMemoryAddress, transferMemorySize, width, height);
+            }
+
+            /*
+            if (transferMemoryHandle)
+            {
+                svcCloseHandle(transferMemoryHandle);
+            }
+            */
+
+            return resultCode;
+        }
+
+        private ResultCode InitializeApplicationCopyrightFrameBufferImpl(ulong transferMemoryAddress, ulong transferMemorySize, int width, int height)
+        {
+            ResultCode resultCode = ResultCode.ObjectInvalid;
+
+            if ((transferMemorySize & 0x3FFFF) != 0)
+            {
+                return ResultCode.InvalidParameters;
+            }
+
+            // if (_copyrightBuffer == null)
+            {
+                // TODO: Initialize buffer and object.
+
+                Logger.PrintStub(LogClass.ServiceAm, new { transferMemoryAddress, transferMemorySize, width, height });
+
+                resultCode = ResultCode.Success;
+            }
+
+            return resultCode;
+        }
+
+        [Command(101)] // 5.0.0+
+        // SetApplicationCopyrightImage(buffer<bytes, 0x45> frame_buffer, s32 x, s32 y, s32 width, s32 height, s32 window_origin_mode)
+        public ResultCode SetApplicationCopyrightImage(ServiceCtx context)
+        {
+            long frameBufferPos   = context.Request.SendBuff[0].Position;
+            long frameBufferSize  = context.Request.SendBuff[0].Size;
+            int  x                = context.RequestData.ReadInt32();
+            int  y                = context.RequestData.ReadInt32();
+            int  width            = context.RequestData.ReadInt32();
+            int  height           = context.RequestData.ReadInt32();
+            uint windowOriginMode = context.RequestData.ReadUInt32();
+
+            ResultCode resultCode = ResultCode.InvalidParameters;
+
+            if (((y | x) >= 0) && width >= 1 && height >= 1)
+            {
+                ResultCode result = SetApplicationCopyrightImageImpl(x, y, width, height, frameBufferPos, frameBufferSize, windowOriginMode);
+
+                if (resultCode != ResultCode.Success)
+                {
+                    resultCode = result;
+                }
+                else
+                {
+                    resultCode = ResultCode.Success;
+                }
+            }
+
+            Logger.PrintStub(LogClass.ServiceAm, new { frameBufferPos, frameBufferSize, x, y, width, height, windowOriginMode });
+
+            return resultCode;
+        }
+
+        private ResultCode SetApplicationCopyrightImageImpl(int x, int y, int width, int height, long frameBufferPos, long frameBufferSize, uint windowOriginMode)
+        {
+            /*
+            if (_copyrightBuffer == null)
+            {
+                return ResultCode.NullCopyrightObject;
+            }
+            */
+
+            Logger.PrintStub(LogClass.ServiceAm, new { x, y, width, height, frameBufferPos, frameBufferSize, windowOriginMode });
+
+            return ResultCode.Success;
+        }
+
+        [Command(102)] // 5.0.0+
+        // SetApplicationCopyrightVisibility(bool visible)
+        public ResultCode SetApplicationCopyrightVisibility(ServiceCtx context)
+        {
+            bool visible = context.RequestData.ReadBoolean();
+
+            Logger.PrintStub(LogClass.ServiceAm, new { visible });
+
+            // NOTE: It sets an internal field and return ResultCode.Success in all case.
+
+            return ResultCode.Success;
+        }
+
         [Command(110)] // 5.0.0+
         // QueryApplicationPlayStatistics(buffer<bytes, 5> title_id_list) -> (buffer<bytes, 6> entries, s32 entries_count)
         public ResultCode QueryApplicationPlayStatistics(ServiceCtx context)
diff --git a/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs
index d8979f4af9..2ff83d7f48 100644
--- a/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs
@@ -7,10 +7,11 @@ namespace Ryujinx.HLE.HOS.Services.Am
 
         Success = 0,
 
-        NotAvailable        = (2   << ErrorCodeShift) | ModuleId,
-        NoMessages          = (3   << ErrorCodeShift) | ModuleId,
-        ObjectInvalid       = (500 << ErrorCodeShift) | ModuleId,
-        OutOfBounds         = (503 << ErrorCodeShift) | ModuleId,
-        CpuBoostModeInvalid = (506 << ErrorCodeShift) | ModuleId
+        NotAvailable      = (2   << ErrorCodeShift) | ModuleId,
+        NoMessages        = (3   << ErrorCodeShift) | ModuleId,
+        ObjectInvalid     = (500 << ErrorCodeShift) | ModuleId,
+        OutOfBounds       = (503 << ErrorCodeShift) | ModuleId,
+        InvalidParameters = (506 << ErrorCodeShift) | ModuleId,
+        NullObject        = (518 << ErrorCodeShift) | ModuleId
     }
 }
\ No newline at end of file