diff --git a/src/Ryujinx.Gtk3/UI/MainWindow.cs b/src/Ryujinx.Gtk3/UI/MainWindow.cs index b10dfe3f9..311ce42c2 100644 --- a/src/Ryujinx.Gtk3/UI/MainWindow.cs +++ b/src/Ryujinx.Gtk3/UI/MainWindow.cs @@ -21,6 +21,7 @@ using Ryujinx.Graphics.GAL.Multithreading; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; +using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.Input.GTK3; using Ryujinx.Input.HLE; @@ -677,7 +678,8 @@ namespace Ryujinx.UI ConfigurationState.Instance.System.AudioVolume, ConfigurationState.Instance.System.UseHypervisor, ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value, - ConfigurationState.Instance.Multiplayer.Mode); + ConfigurationState.Instance.Multiplayer.Mode, + () => StopEmulation()); _emulationContext = new HLE.Switch(configuration); } @@ -1484,7 +1486,7 @@ namespace Ryujinx.UI SaveConfig(); } - private void StopEmulation_Pressed(object sender, EventArgs args) + private void StopEmulation() { if (_emulationContext != null) { @@ -1497,6 +1499,16 @@ namespace Ryujinx.UI RendererWidget?.Exit(); } + private void StopEmulation_Pressed(object sender, EventArgs args) + { + _emulationContext.System.RequestExit(); + Task.Run(async () => + { + await Task.Delay(5000); + StopEmulation(); + }); + } + private void PauseEmulation_Pressed(object sender, EventArgs args) { _pauseEmulation.Sensitive = false; diff --git a/src/Ryujinx.HLE/HLEConfiguration.cs b/src/Ryujinx.HLE/HLEConfiguration.cs index 955fee4b5..0fb4381d4 100644 --- a/src/Ryujinx.HLE/HLEConfiguration.cs +++ b/src/Ryujinx.HLE/HLEConfiguration.cs @@ -169,6 +169,11 @@ namespace Ryujinx.HLE /// public Action RefreshInputConfig { internal get; set; } + /// + /// An action to stop emulation. + /// + public Action Stop { internal get; set; } + public HLEConfiguration(VirtualFileSystem virtualFileSystem, LibHacHorizonManager libHacHorizonManager, ContentManager contentManager, @@ -194,7 +199,8 @@ namespace Ryujinx.HLE float audioVolume, bool useHypervisor, string multiplayerLanInterfaceId, - MultiplayerMode multiplayerMode) + MultiplayerMode multiplayerMode, + Action stop) { VirtualFileSystem = virtualFileSystem; LibHacHorizonManager = libHacHorizonManager; @@ -222,6 +228,7 @@ namespace Ryujinx.HLE UseHypervisor = useHypervisor; MultiplayerLanInterfaceId = multiplayerLanInterfaceId; MultiplayerMode = multiplayerMode; + Stop = stop; } } } diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs index 64b08e309..32c17958e 100644 --- a/src/Ryujinx.HLE/HOS/Horizon.cs +++ b/src/Ryujinx.HLE/HOS/Horizon.cs @@ -329,6 +329,12 @@ namespace Ryujinx.HLE.HOS AppletState.SetFocus(true); } + public void RequestExit() + { + AppletState.Messages.Enqueue(AppletMessage.Exit); + AppletState.MessageEvent.ReadableEvent.Signal(); + } + public void SimulateWakeUpMessage() { AppletState.Messages.Enqueue(AppletMessage.Resume); diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs index 85898f138..322938f3b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -51,7 +51,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys // Exit() public ResultCode Exit(ServiceCtx context) { - Logger.Stub?.PrintStub(LogClass.ServiceAm); + Logger.Warning?.Print(LogClass.ServiceAm, "Self Applet Exit"); + + context.Device.Configuration.Stop(); return ResultCode.Success; } diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 4ee271203..f24ba1bc2 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -580,7 +580,8 @@ namespace Ryujinx.Headless.SDL2 options.AudioVolume, options.UseHypervisor ?? true, options.MultiplayerLanInterfaceId, - Common.Configuration.Multiplayer.MultiplayerMode.Disabled); + Common.Configuration.Multiplayer.MultiplayerMode.Disabled, + () => _window.Exit()); return new Switch(configuration); } diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs index 8768913f5..b17348db8 100644 --- a/src/Ryujinx.Headless.SDL2/WindowBase.cs +++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs @@ -221,7 +221,12 @@ namespace Ryujinx.Headless.SDL2 break; case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE: - Exit(); + Device.System.RequestExit(); + /* + SDL2Driver.Instance.AddTimer(5000, () => { + Exit(); + }); + */ break; } } diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs index ed6d94190..f994f9b36 100644 --- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs +++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs @@ -25,7 +25,7 @@ namespace Ryujinx.SDL2.Common public static Action MainThreadDispatcher { get; set; } - private const uint SdlInitFlags = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_VIDEO; + private const uint SdlInitFlags = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER; private bool _isRunning; private uint _refereceCount; diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index f4bfd1169..01e6a294b 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -872,7 +872,8 @@ namespace Ryujinx.Ava ConfigurationState.Instance.System.AudioVolume, ConfigurationState.Instance.System.UseHypervisor, ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value, - ConfigurationState.Instance.Multiplayer.Mode); + ConfigurationState.Instance.Multiplayer.Mode, + () => Stop()); Device = new Switch(configuration); } @@ -1092,7 +1093,12 @@ namespace Ryujinx.Ava if (shouldExit) { - Stop(); + Device.System.RequestExit(); + Task.Run(async () => + { + await Task.Delay(5000); + Stop(); + }); } }