From d8515b603bff4712fe0e84113d7f7823a84c85eb Mon Sep 17 00:00:00 2001
From: Ac_K <Acoustik666@gmail.com>
Date: Mon, 27 Jul 2020 00:25:04 +0200
Subject: [PATCH] audin: Implement IAudioInManager ListAudioIns (#1419)

* audin: Implement IAudioInManager ListAudioIns

This implement some calls of IAudioInManager:
- ListAudioIns
- ListAudioInsAuto
- ListAudioInsAutoFiltered

Accordingly to RE.

Close #1056

* Fix count

* Comment condition

* Fix comment
---
 .../HOS/Services/Audio/IAudioInManager.cs     | 80 ++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs b/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs
index d8e1f468e2..9b3b951cbf 100644
--- a/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs
@@ -1,8 +1,86 @@
-namespace Ryujinx.HLE.HOS.Services.Audio
+using Ryujinx.Cpu;
+using System;
+using System.Text;
+
+namespace Ryujinx.HLE.HOS.Services.Audio
 {
     [Service("audin:u")]
     class IAudioInManager : IpcService
     {
+        private const string DefaultAudioInsName = "BuiltInHeadset";
+
         public IAudioInManager(ServiceCtx context) { }
+
+        [Command(0)]
+        // ListAudioIns() -> (u32 count, buffer<bytes, 6> names)
+        public ResultCode ListAudioIns(ServiceCtx context)
+        {
+            long bufferPosition = context.Request.ReceiveBuff[0].Position;
+            long bufferSize     = context.Request.ReceiveBuff[0].Size;
+
+            // NOTE: The service check if AudioInManager thread is started, if not it starts it.
+
+            uint count = ListAudioInsImpl(context.Memory, bufferPosition, bufferSize, false);
+
+            context.ResponseData.Write(count);
+
+            return ResultCode.Success;
+        }
+
+        [Command(3)] // 3.0.0+
+        // ListAudioInsAuto() -> (u32 count, buffer<bytes, 0x22> names)
+        public ResultCode ListAudioInsAuto(ServiceCtx context)
+        {
+            (long bufferPosition, long bufferSize) = context.Request.GetBufferType0x22();
+
+            // NOTE: The service check if AudioInManager thread is started, if not it starts it.
+
+            uint count = ListAudioInsImpl(context.Memory, bufferPosition, bufferSize, false);
+
+            context.ResponseData.Write(count);
+
+            return ResultCode.Success;
+        }
+
+        [Command(4)] // 3.0.0+
+        // ListAudioInsAutoFiltered() -> (u32 count, buffer<bytes, 0x22> names)
+        public ResultCode ListAudioInsAutoFiltered(ServiceCtx context)
+        {
+            (long bufferPosition, long bufferSize) = context.Request.GetBufferType0x22();
+
+            // NOTE: The service check if AudioInManager thread is started, if not it starts it.
+
+            uint count = ListAudioInsImpl(context.Memory, bufferPosition, bufferSize, true);
+
+            context.ResponseData.Write(count);
+
+            return ResultCode.Success;
+        }
+
+        private uint ListAudioInsImpl(MemoryManager memory, long bufferPosition, long bufferSize, bool filtered = false)
+        {
+            uint count = 0;
+
+            MemoryHelper.FillWithZeros(memory, bufferPosition, (int)bufferSize);
+
+            if (bufferSize > 0)
+            {
+                // NOTE: The service also check that the input target is enabled when in filtering mode, as audctl and most of the audin logic isn't supported, we don't support it.
+                if (!filtered)
+                {
+                    byte[] deviceNameBuffer = Encoding.ASCII.GetBytes(DefaultAudioInsName + "\0");
+
+                    memory.Write((ulong)bufferPosition, deviceNameBuffer);
+
+                    count++;
+                }
+
+                // NOTE: The service adds other input devices names available in the buffer,
+                //       every name is aligned to 0x100 bytes.
+                //       Since we don't support it for now, it's fine to do nothing here.
+            }
+
+            return count;
+        }
     }
 }
\ No newline at end of file