Ver Fonte

am/gui: Implement Wake-up message (#1750)

* am/gui: Implement Wake-up message.

This implement the ability to send a Wake-up (Resume) message to the guest.
Sometime games needs to Sleep and Wake-up the switch to unlock some ingame features.

* Address gdkchan feedback
Ac_K há 5 anos atrás
pai
commit
808380690c

+ 10 - 2
Ryujinx.HLE/HOS/Horizon.cs

@@ -278,8 +278,10 @@ namespace Ryujinx.HLE.HOS
                 State.DockedMode = e.NewValue;
                 PerformanceState.PerformanceMode = State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
 
-                AppletState.EnqueueMessage(MessageInfo.OperationModeChanged);
-                AppletState.EnqueueMessage(MessageInfo.PerformanceModeChanged);
+                AppletState.Messages.Enqueue(MessageInfo.OperationModeChanged);
+                AppletState.Messages.Enqueue(MessageInfo.PerformanceModeChanged);
+                AppletState.MessageEvent.ReadableEvent.Signal();
+
                 SignalDisplayResolutionChange();
 
                 // Reconfigure controllers
@@ -287,6 +289,12 @@ namespace Ryujinx.HLE.HOS
             }
         }
 
+        public void SimulateWakeUpMessage()
+        {
+            AppletState.Messages.Enqueue(MessageInfo.Resume);
+            AppletState.MessageEvent.ReadableEvent.Signal();
+        }
+
         public void SignalDisplayResolutionChange()
         {
             DisplayResolutionChangeEvent.ReadableEvent.Signal();

+ 15 - 1
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs

@@ -46,11 +46,25 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         // ReceiveMessage() -> nn::am::AppletMessage
         public ResultCode ReceiveMessage(ServiceCtx context)
         {
-            if (!context.Device.System.AppletState.TryDequeueMessage(out MessageInfo message))
+            if (!context.Device.System.AppletState.Messages.TryDequeue(out MessageInfo message))
             {
                 return ResultCode.NoMessages;
             }
 
+            KEvent messageEvent = context.Device.System.AppletState.MessageEvent;
+
+            // NOTE: Service checks if current states are different than the stored ones.
+            //       Since we don't support any states for now, it's fine to check if there is still messages available.
+
+            if (context.Device.System.AppletState.Messages.IsEmpty)
+            {
+                messageEvent.ReadableEvent.Clear();
+            }
+            else
+            {
+                messageEvent.ReadableEvent.Signal();
+            }
+
             context.ResponseData.Write((int)message);
 
             return ResultCode.Success;

+ 1 - 0
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/MessageInfo.cs

@@ -3,6 +3,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
     enum MessageInfo
     {
         FocusStateChanged      = 0xf,
+        Resume                 = 0x10,
         OperationModeChanged   = 0x1e,
         PerformanceModeChanged = 0x1f
     }

+ 4 - 23
Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs

@@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.SystemState
 {
     class AppletStateMgr
     {
-        private ConcurrentQueue<MessageInfo> _messages;
+        public ConcurrentQueue<MessageInfo> Messages { get; }
 
         public FocusState FocusState { get; private set; }
 
@@ -16,8 +16,7 @@ namespace Ryujinx.HLE.HOS.SystemState
 
         public AppletStateMgr(Horizon system)
         {
-            _messages = new ConcurrentQueue<MessageInfo>();
-
+            Messages     = new ConcurrentQueue<MessageInfo>();
             MessageEvent = new KEvent(system.KernelContext);
 
             AppletResourceUserIds = new IdDictionary();
@@ -25,28 +24,10 @@ namespace Ryujinx.HLE.HOS.SystemState
 
         public void SetFocus(bool isFocused)
         {
-            FocusState = isFocused
-                ? FocusState.InFocus
-                : FocusState.OutOfFocus;
-
-            EnqueueMessage(MessageInfo.FocusStateChanged);
-        }
-
-        public void EnqueueMessage(MessageInfo message)
-        {
-            _messages.Enqueue(message);
+            FocusState = isFocused ? FocusState.InFocus : FocusState.OutOfFocus;
 
+            Messages.Enqueue(MessageInfo.FocusStateChanged);
             MessageEvent.ReadableEvent.Signal();
         }
-
-        public bool TryDequeueMessage(out MessageInfo message)
-        {
-            if (_messages.Count < 2)
-            {
-                MessageEvent.ReadableEvent.Clear();
-            }
-
-            return _messages.TryDequeue(out message);
-        }
     }
 }

+ 5 - 0
Ryujinx/Ui/MainWindow.cs

@@ -1205,6 +1205,11 @@ namespace Ryujinx.Ui
             settingsWin.Show();
         }
 
+        private void Simulate_WakeUp_Message_Pressed(object sender, EventArgs args)
+        {
+            _emulationContext.System.SimulateWakeUpMessage();
+        }
+
         private void Update_Pressed(object sender, EventArgs args)
         {
             if (Updater.CanUpdate(true))

+ 10 - 0
Ryujinx/Ui/MainWindow.glade

@@ -137,6 +137,16 @@
                         <signal name="activate" handler="StopEmulation_Pressed" swapped="no"/>
                       </object>
                     </child>
+                    <child>
+                      <object class="GtkMenuItem" id="SimulateWakeUpMessage">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="tooltip_text" translatable="yes">Simulate a Wake-up Message</property>
+                        <property name="label" translatable="yes">Simulate Wake-up Message</property>
+                        <property name="use_underline">True</property>
+                        <signal name="activate" handler="Simulate_WakeUp_Message_Pressed" swapped="no"/>
+                      </object>
+                    </child>
                     <child>
                       <object class="GtkSeparatorMenuItem">
                         <property name="visible">True</property>