Kill command - stop emulation
This commit is contained in:
parent
38c15faacf
commit
055ac70eaa
6 changed files with 29 additions and 24 deletions
|
@ -1076,9 +1076,11 @@ namespace Ryujinx.UI
|
||||||
RendererWidget.WaitEvent.WaitOne();
|
RendererWidget.WaitEvent.WaitOne();
|
||||||
|
|
||||||
RendererWidget.Start();
|
RendererWidget.Start();
|
||||||
|
_pauseEmulation.Sensitive = false;
|
||||||
|
_resumeEmulation.Sensitive = false;
|
||||||
|
UpdateMenuItem.Sensitive = true;
|
||||||
|
|
||||||
_emulationContext.Dispose();
|
_emulationContext.Dispose();
|
||||||
_deviceExitStatus.Set();
|
|
||||||
|
|
||||||
// NOTE: Everything that is here will not be executed when you close the UI.
|
// NOTE: Everything that is here will not be executed when you close the UI.
|
||||||
Application.Invoke(delegate
|
Application.Invoke(delegate
|
||||||
|
@ -1173,7 +1175,7 @@ namespace Ryujinx.UI
|
||||||
RendererWidget.Exit();
|
RendererWidget.Exit();
|
||||||
|
|
||||||
// Wait for the other thread to dispose the HLE context before exiting.
|
// Wait for the other thread to dispose the HLE context before exiting.
|
||||||
_deviceExitStatus.WaitOne();
|
_emulationContext.ExitStatus.WaitOne();
|
||||||
RendererWidget.Dispose();
|
RendererWidget.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1511,9 +1513,6 @@ namespace Ryujinx.UI
|
||||||
UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
|
UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pauseEmulation.Sensitive = false;
|
|
||||||
_resumeEmulation.Sensitive = false;
|
|
||||||
UpdateMenuItem.Sensitive = true;
|
|
||||||
RendererWidget?.Exit();
|
RendererWidget?.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ namespace Ryujinx.UI
|
||||||
|
|
||||||
public static event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
public static event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
||||||
|
|
||||||
private bool _isActive;
|
|
||||||
private bool _isStopped;
|
private bool _isStopped;
|
||||||
|
|
||||||
private bool _toggleFullscreen;
|
private bool _toggleFullscreen;
|
||||||
|
@ -459,7 +458,7 @@ namespace Ryujinx.UI
|
||||||
|
|
||||||
(Toplevel as MainWindow)?.ActivatePauseMenu();
|
(Toplevel as MainWindow)?.ActivatePauseMenu();
|
||||||
|
|
||||||
while (_isActive)
|
while (Device.IsActive)
|
||||||
{
|
{
|
||||||
if (_isStopped)
|
if (_isStopped)
|
||||||
{
|
{
|
||||||
|
@ -519,7 +518,7 @@ namespace Ryujinx.UI
|
||||||
{
|
{
|
||||||
_chrono.Restart();
|
_chrono.Restart();
|
||||||
|
|
||||||
_isActive = true;
|
Device.IsActive = true;
|
||||||
|
|
||||||
Gtk.Window parent = Toplevel as Gtk.Window;
|
Gtk.Window parent = Toplevel as Gtk.Window;
|
||||||
|
|
||||||
|
@ -573,9 +572,9 @@ namespace Ryujinx.UI
|
||||||
|
|
||||||
_isStopped = true;
|
_isStopped = true;
|
||||||
|
|
||||||
if (_isActive)
|
if (Device.IsActive)
|
||||||
{
|
{
|
||||||
_isActive = false;
|
Device.IsActive = false;
|
||||||
|
|
||||||
_exitEvent.WaitOne();
|
_exitEvent.WaitOne();
|
||||||
_exitEvent.Dispose();
|
_exitEvent.Dispose();
|
||||||
|
@ -584,7 +583,7 @@ namespace Ryujinx.UI
|
||||||
|
|
||||||
private void NvidiaStutterWorkaround()
|
private void NvidiaStutterWorkaround()
|
||||||
{
|
{
|
||||||
while (_isActive)
|
while (Device.IsActive)
|
||||||
{
|
{
|
||||||
// When NVIDIA Threaded Optimization is on, the driver will snapshot all threads in the system whenever the application creates any new ones.
|
// When NVIDIA Threaded Optimization is on, the driver will snapshot all threads in the system whenever the application creates any new ones.
|
||||||
// The ThreadPool has something called a "GateThread" which terminates itself after some inactivity.
|
// The ThreadPool has something called a "GateThread" which terminates itself after some inactivity.
|
||||||
|
@ -603,7 +602,7 @@ namespace Ryujinx.UI
|
||||||
|
|
||||||
public void MainLoop()
|
public void MainLoop()
|
||||||
{
|
{
|
||||||
while (_isActive)
|
while (Device.IsActive)
|
||||||
{
|
{
|
||||||
UpdateFrame();
|
UpdateFrame();
|
||||||
|
|
||||||
|
@ -616,7 +615,7 @@ namespace Ryujinx.UI
|
||||||
|
|
||||||
private bool UpdateFrame()
|
private bool UpdateFrame()
|
||||||
{
|
{
|
||||||
if (!_isActive)
|
if (!Device.IsActive)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,6 +218,8 @@ namespace Ryujinx.HLE.Debugger
|
||||||
}
|
}
|
||||||
case 'k':
|
case 'k':
|
||||||
Logger.Notice.Print(LogClass.GdbStub, "Kill request received");
|
Logger.Notice.Print(LogClass.GdbStub, "Kill request received");
|
||||||
|
Device.IsActive = false;
|
||||||
|
Device.ExitStatus.WaitOne();
|
||||||
Reply("");
|
Reply("");
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
|
|
|
@ -311,7 +311,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
if (Owner != null && Owner.PinnedThreads[KernelStatic.GetCurrentThread().CurrentCore] == this)
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
|
if (Owner != null && currentThread != null && Owner.PinnedThreads[currentThread.CurrentCore] == this)
|
||||||
{
|
{
|
||||||
Owner.UnpinThread(this);
|
Owner.UnpinThread(this);
|
||||||
}
|
}
|
||||||
|
@ -366,7 +368,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
ThreadSchedState state = PrepareForTermination();
|
ThreadSchedState state = PrepareForTermination();
|
||||||
|
|
||||||
if (state != ThreadSchedState.TerminationPending)
|
if (KernelStatic.GetCurrentThread() == this && state != ThreadSchedState.TerminationPending)
|
||||||
{
|
{
|
||||||
KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _);
|
KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Ryujinx.HLE.Loaders.Processes;
|
||||||
using Ryujinx.HLE.UI;
|
using Ryujinx.HLE.UI;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE
|
namespace Ryujinx.HLE
|
||||||
{
|
{
|
||||||
|
@ -27,11 +28,14 @@ namespace Ryujinx.HLE
|
||||||
public TamperMachine TamperMachine { get; }
|
public TamperMachine TamperMachine { get; }
|
||||||
public IHostUIHandler UIHandler { get; }
|
public IHostUIHandler UIHandler { get; }
|
||||||
public Debugger.Debugger Debugger { get; }
|
public Debugger.Debugger Debugger { get; }
|
||||||
|
public ManualResetEvent ExitStatus { get; }
|
||||||
|
|
||||||
public bool EnableDeviceVsync { get; set; } = true;
|
public bool EnableDeviceVsync { get; set; } = true;
|
||||||
|
|
||||||
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
|
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
|
||||||
|
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
|
||||||
public Switch(HLEConfiguration configuration)
|
public Switch(HLEConfiguration configuration)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
||||||
|
@ -56,6 +60,7 @@ namespace Ryujinx.HLE
|
||||||
Hid = new Hid(this, System.HidStorage);
|
Hid = new Hid(this, System.HidStorage);
|
||||||
Processes = new ProcessLoader(this);
|
Processes = new ProcessLoader(this);
|
||||||
TamperMachine = new TamperMachine();
|
TamperMachine = new TamperMachine();
|
||||||
|
ExitStatus = new ManualResetEvent(false);
|
||||||
|
|
||||||
System.InitializeServices();
|
System.InitializeServices();
|
||||||
System.State.SetLanguage(Configuration.SystemLanguage);
|
System.State.SetLanguage(Configuration.SystemLanguage);
|
||||||
|
@ -157,6 +162,7 @@ namespace Ryujinx.HLE
|
||||||
FileSystem.Dispose();
|
FileSystem.Dispose();
|
||||||
Memory.Dispose();
|
Memory.Dispose();
|
||||||
Debugger.Dispose();
|
Debugger.Dispose();
|
||||||
|
ExitStatus.Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,6 @@ namespace Ryujinx.Ava
|
||||||
CursorStates.CursorIsVisible : CursorStates.CursorIsHidden;
|
CursorStates.CursorIsVisible : CursorStates.CursorIsHidden;
|
||||||
|
|
||||||
private bool _isStopped;
|
private bool _isStopped;
|
||||||
private bool _isActive;
|
|
||||||
private bool _renderingStarted;
|
private bool _renderingStarted;
|
||||||
|
|
||||||
private readonly ManualResetEvent _gpuDoneEvent;
|
private readonly ManualResetEvent _gpuDoneEvent;
|
||||||
|
@ -427,8 +426,6 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
RendererHost.BoundsChanged += Window_BoundsChanged;
|
RendererHost.BoundsChanged += Window_BoundsChanged;
|
||||||
|
|
||||||
_isActive = true;
|
|
||||||
|
|
||||||
_renderingThread.Start();
|
_renderingThread.Start();
|
||||||
|
|
||||||
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
||||||
|
@ -497,7 +494,7 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
_isActive = false;
|
Device.IsActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Exit()
|
private void Exit()
|
||||||
|
@ -510,14 +507,14 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
|
|
||||||
_isStopped = true;
|
_isStopped = true;
|
||||||
_isActive = false;
|
Device.IsActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeContext()
|
public void DisposeContext()
|
||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
|
|
||||||
_isActive = false;
|
Device.IsActive = false;
|
||||||
|
|
||||||
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
|
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
|
||||||
// We only need to wait for all commands submitted during the main gpu loop to be processed.
|
// We only need to wait for all commands submitted during the main gpu loop to be processed.
|
||||||
|
@ -950,7 +947,7 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
private void MainLoop()
|
private void MainLoop()
|
||||||
{
|
{
|
||||||
while (_isActive)
|
while (Device.IsActive)
|
||||||
{
|
{
|
||||||
UpdateFrame();
|
UpdateFrame();
|
||||||
|
|
||||||
|
@ -1001,7 +998,7 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
|
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||||
|
|
||||||
while (_isActive)
|
while (Device.IsActive)
|
||||||
{
|
{
|
||||||
_ticks += _chrono.ElapsedTicks;
|
_ticks += _chrono.ElapsedTicks;
|
||||||
|
|
||||||
|
@ -1100,7 +1097,7 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
private bool UpdateFrame()
|
private bool UpdateFrame()
|
||||||
{
|
{
|
||||||
if (!_isActive)
|
if (!Device.IsActive)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue