From b663cd22c87f13f40e1753bf22bef12d08bf6f3e Mon Sep 17 00:00:00 2001
From: mageven <62494521+mageven@users.noreply.github.com>
Date: Wed, 27 May 2020 14:10:23 +0530
Subject: [PATCH] Fix GetDesiredLanguage (#1275)

* Fix GetDesiredLanguage

* Correct tzcnt slip-up

* Address gdkchan's comments
---
 .../ApplicationProxy/IApplicationFunctions.cs | 33 ++++++++++++++++++-
 Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs |  5 ++-
 Ryujinx.HLE/HOS/SystemState/TitleLanguage.cs  |  2 +-
 3 files changed, 37 insertions(+), 3 deletions(-)

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 51e8d3deb2..fb85d856be 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
@@ -12,7 +12,9 @@ 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;
+using Ryujinx.HLE.HOS.SystemState;
 using System;
+using System.Numerics;
 
 using static LibHac.Fs.ApplicationSaveDataManagement;
 using AccountUid = Ryujinx.HLE.HOS.Services.Account.Acc.UserId;
@@ -79,7 +81,36 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
         // GetDesiredLanguage() -> nn::settings::LanguageCode
         public ResultCode GetDesiredLanguage(ServiceCtx context)
         {
-            context.ResponseData.Write(context.Device.System.State.DesiredLanguageCode);
+            // This seems to be calling ns:am GetApplicationDesiredLanguage followed by ConvertApplicationLanguageToLanguageCode
+            // Calls are from a IReadOnlyApplicationControlDataInterface object
+            // ConvertApplicationLanguageToLanguageCode compares language code strings and returns the index
+            // TODO: When above calls are implemented, switch to using ns:am
+
+            long desiredLanguageCode = context.Device.System.State.DesiredLanguageCode;
+            
+            int supportedLanguages = (int)context.Device.Application.ControlData.Value.SupportedLanguages;
+            int firstSupported = BitOperations.TrailingZeroCount(supportedLanguages);
+
+            if (firstSupported > (int)SystemState.TitleLanguage.Chinese)
+            {
+                Logger.PrintWarning(LogClass.ServiceAm, "Application has zero supported languages");
+
+                context.ResponseData.Write(desiredLanguageCode);
+
+                return ResultCode.Success;
+            }
+
+            // If desired language is not supported by application, use first supported language from TitleLanguage. 
+            // TODO: In the future, a GUI could enable user-specified search priority
+            if (((1 << (int)context.Device.System.State.DesiredTitleLanguage) & supportedLanguages) == 0)
+            {
+                SystemLanguage newLanguage = Enum.Parse<SystemLanguage>(Enum.GetName(typeof(SystemState.TitleLanguage), firstSupported));
+                desiredLanguageCode = SystemStateMgr.GetLanguageCode((int)newLanguage);
+
+                Logger.PrintInfo(LogClass.ServiceAm, $"Application doesn't support configured language. Using {newLanguage}");
+            }
+
+            context.ResponseData.Write(desiredLanguageCode);
 
             return ResultCode.Success;
         }
diff --git a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
index 53b2095591..1abfc8c3c5 100644
--- a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
+++ b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
@@ -37,6 +37,8 @@ namespace Ryujinx.HLE.HOS.SystemState
 
         internal long DesiredKeyboardLayout { get; private set; }
 
+        internal SystemLanguage DesiredSystemLanguage { get; private set; }
+
         internal long DesiredLanguageCode { get; private set; }
 
         internal uint DesiredRegionCode { get; private set; }
@@ -68,7 +70,8 @@ namespace Ryujinx.HLE.HOS.SystemState
 
         public void SetLanguage(SystemLanguage language)
         {
-            DesiredLanguageCode = GetLanguageCode((int)language);
+            DesiredSystemLanguage = language;
+            DesiredLanguageCode = GetLanguageCode((int)DesiredSystemLanguage);
 
             switch (language)
             {
diff --git a/Ryujinx.HLE/HOS/SystemState/TitleLanguage.cs b/Ryujinx.HLE/HOS/SystemState/TitleLanguage.cs
index f481ac2932..931463a742 100644
--- a/Ryujinx.HLE/HOS/SystemState/TitleLanguage.cs
+++ b/Ryujinx.HLE/HOS/SystemState/TitleLanguage.cs
@@ -16,6 +16,6 @@
         Russian,
         Korean,
         Taiwanese,
-        Chinese        
+        Chinese
     }
 }