diff --git a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate index 7571c55ce..a744fe34d 100644 Binary files a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate and b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/src/MeloNX/MeloNX/Core/Headers/Ryujinx-Header.h b/src/MeloNX/MeloNX/Core/Headers/Ryujinx-Header.h index 6fecdba2e..fb12df14a 100644 --- a/src/MeloNX/MeloNX/Core/Headers/Ryujinx-Header.h +++ b/src/MeloNX/MeloNX/Core/Headers/Ryujinx-Header.h @@ -31,6 +31,8 @@ void install_firmware(const char* inputPtr); char* installed_firmware_version(); +void stop_emulation(); + int main_ryujinx_sdl(int argc, char **argv); void initialize(); diff --git a/src/MeloNX/MeloNX/Views/ContentView.swift b/src/MeloNX/MeloNX/Views/ContentView.swift index 85c4e6cbb..a27d74173 100644 --- a/src/MeloNX/MeloNX/Views/ContentView.swift +++ b/src/MeloNX/MeloNX/Views/ContentView.swift @@ -33,6 +33,10 @@ struct ContentView: View { @State var onscreencontroller: Controller = Controller(id: "", name: "") @AppStorage("JIT") var isJITEnabled: Bool = false + @AppStorage("quit") var quit: Bool = false + + @State var quits: Bool = false + // MARK: - Initialization init() { let defaultConfig = loadSettings() ?? Ryujinx.Configuration(gamepath: "") @@ -52,10 +56,25 @@ struct ContentView: View { // MARK: - Body var body: some View { - if let game { + if let game, quits == false { emulationView + .onAppear() { + Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in + print(quit) + + quits = quit + + if quits { + quit = false + timer.invalidate() + } + } + } } else { mainMenuView + .onAppear() { + quits = false + } } } diff --git a/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift b/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift index 03159c90d..c760f8154 100644 --- a/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift +++ b/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift @@ -11,10 +11,24 @@ import SwiftUIJoystick import CoreMotion struct ControllerView: View { + @AppStorage("quit") var quit: Bool = false var body: some View { GeometryReader { geometry in if geometry.size.height > geometry.size.width && UIDevice.current.userInterfaceIdiom != .pad { VStack { + /* + HStack { + Spacer() + + Button("Stop emulation") { + DispatchQueue.main.async { + stop_emulation() + quit = true + } + } + } + */ + Spacer() VStack { HStack { @@ -48,6 +62,19 @@ struct ControllerView: View { } else { // could be landscape VStack { + /* + HStack { + Spacer() + + Button("Stop emulation") { + DispatchQueue.main.async { + stop_emulation() + quit = true + } + } + } + */ + Spacer() VStack { HStack { diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 67b3d2f92..22b1b2b23 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -93,6 +93,7 @@ using Silk.NET.Vulkan; using System; using System.IO; using System.Runtime.InteropServices; +using SDL2; public class GamepadInfo { @@ -288,6 +289,21 @@ namespace Ryujinx.Headless.SDL2 return String.Empty; } + [UnmanagedCallersOnly(EntryPoint = "stop_emulation")] + public static void StopEmulation() + { + + if (_window != null) + { + + _window.Exit(); + _emulationContext.Dispose(); + _emulationContext = null; + } + } + + + [UnmanagedCallersOnly(EntryPoint = "get_game_controllers")] public static unsafe IntPtr GetGamepadList() diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs index 9f5b50506..21a0e01d7 100644 --- a/src/Ryujinx.Headless.SDL2/WindowBase.cs +++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs @@ -45,14 +45,14 @@ namespace Ryujinx.Headless.SDL2 _mainThreadActions.Enqueue(action); } - public NpadManager NpadManager { get; } - public TouchScreenManager TouchScreenManager { get; } - public Switch Device { get; private set; } - public IRenderer Renderer { get; private set; } + public NpadManager NpadManager; + public TouchScreenManager TouchScreenManager; + public Switch Device; + public IRenderer Renderer; public event EventHandler StatusUpdatedEvent; - protected IntPtr WindowHandle { get; set; } + public IntPtr WindowHandle; public IHostUiTheme HostUiTheme { get; } public int Width { get; private set; } @@ -66,18 +66,18 @@ namespace Ryujinx.Headless.SDL2 public ScalingFilter ScalingFilter { get; set; } public int ScalingFilterLevel { get; set; } - protected SDL2MouseDriver MouseDriver; + public SDL2MouseDriver MouseDriver; private readonly InputManager _inputManager; private readonly IKeyboard _keyboardInterface; private readonly GraphicsDebugLevel _glLogLevel; private readonly Stopwatch _chrono; private readonly long _ticksPerFrame; private readonly CancellationTokenSource _gpuCancellationTokenSource; - private readonly ManualResetEvent _exitEvent; - private readonly ManualResetEvent _gpuDoneEvent; + public ManualResetEvent _exitEvent; + public ManualResetEvent _gpuDoneEvent; private long _ticks; - private bool _isActive; + public bool _isActive; private bool _isStopped; private uint _windowId;