internal static TranslatedFunction Translate(IMemoryManager memory, JumpTable jumpTable, ulong address, ExecutionMode mode, bool highCq) { ArmEmitterContext context = new ArmEmitterContext(memory, jumpTable, address, highCq, Aarch32Mode.User); Logger.StartPass(PassName.Decoding); Block[] blocks = Decoder.Decode(memory, address, mode, highCq, singleBlock: false); Logger.EndPass(PassName.Decoding); PreparePool(highCq ? 1 : 0); Logger.StartPass(PassName.Translation); EmitSynchronization(context); if (blocks[0].Address != address) { context.Branch(context.GetLabel(address)); } ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange); ulong funcSize = funcRange.End - funcRange.Start; Logger.EndPass(PassName.Translation); Logger.StartPass(PassName.RegisterUsage); RegisterUsage.RunPass(cfg, mode); Logger.EndPass(PassName.RegisterUsage); OperandType[] argTypes = new OperandType[] { OperandType.I64 }; CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; GuestFunction func; if (Ptc.State == PtcState.Disabled) { func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options); ResetPool(highCq ? 1 : 0); } else { using PtcInfo ptcInfo = new PtcInfo(); func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo); ResetPool(highCq ? 1 : 0); Hash128 hash = Ptc.ComputeHash(memory, address, funcSize); Ptc.WriteInfoCodeRelocUnwindInfo(address, funcSize, hash, highCq, ptcInfo); } return(new TranslatedFunction(func, funcSize, highCq)); }
private static void ExecutionEntrypoint() { if (OperatingSystem.IsWindows()) { _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1); } DisplaySleep.Prevent(); _window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse); _window.Execute(); Ptc.Close(); PtcProfiler.Stop(); _emulationContext.Dispose(); _window.Dispose(); if (OperatingSystem.IsWindows()) { _windowsMultimediaTimerResolution?.Dispose(); _windowsMultimediaTimerResolution = null; } }
private static void ProgramExit() { Ptc.Dispose(); PtcProfiler.Dispose(); Logger.Shutdown(); }
internal static TranslatedFunction Translate(IMemoryManager memory, JumpTable jumpTable, ulong address, ExecutionMode mode, bool highCq) { ArmEmitterContext context = new ArmEmitterContext(memory, jumpTable, (long)address, highCq, Aarch32Mode.User); PrepareOperandPool(highCq); PrepareOperationPool(highCq); Logger.StartPass(PassName.Decoding); Block[] blocks = Decoder.DecodeFunction(memory, address, mode, highCq); Logger.EndPass(PassName.Decoding); Logger.StartPass(PassName.Translation); EmitSynchronization(context); if (blocks[0].Address != address) { context.Branch(context.GetLabel(address)); } ControlFlowGraph cfg = EmitAndGetCFG(context, blocks); Logger.EndPass(PassName.Translation); Logger.StartPass(PassName.RegisterUsage); RegisterUsage.RunPass(cfg, mode, isCompleteFunction: false); Logger.EndPass(PassName.RegisterUsage); OperandType[] argTypes = new OperandType[] { OperandType.I64 }; CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; GuestFunction func; if (Ptc.State == PtcState.Disabled) { func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options); } else { using (PtcInfo ptcInfo = new PtcInfo()) { func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo); Ptc.WriteInfoCodeReloc((long)address, highCq, ptcInfo); } } ResetOperandPool(highCq); ResetOperationPool(highCq); return(new TranslatedFunction(func, highCq)); }
public static void Exit() { DiscordIntegrationModule.Exit(); Ptc.Dispose(); PtcProfiler.Dispose(); Logger.Shutdown(); }
public void Execute(State.ExecutionContext context, ulong address) { if (Interlocked.Increment(ref _threadCount) == 1) { IsReadyForTranslation.WaitOne(); if (Ptc.State == PtcState.Enabled) { Ptc.MakeAndSaveTranslations(_funcs, _memory, _jumpTable); } PtcProfiler.Start(); Ptc.Disable(); // Simple heuristic, should be user configurable in future. (1 for 4 core/ht or less, 2 for 6 core+ht etc). // All threads are normal priority except from the last, which just fills as much of the last core as the os lets it with a low priority. // If we only have one rejit thread, it should be normal priority as highCq code is performance critical. // TODO: Use physical cores rather than logical. This only really makes sense for processors with hyperthreading. Requires OS specific code. int unboundedThreadCount = Math.Max(1, (Environment.ProcessorCount - 6) / 3); int threadCount = Math.Min(4, unboundedThreadCount); for (int i = 0; i < threadCount; i++) { bool last = i != 0 && i == unboundedThreadCount - 1; Thread backgroundTranslatorThread = new Thread(TranslateStackedSubs) { Name = "CPU.BackgroundTranslatorThread." + i, Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal }; backgroundTranslatorThread.Start(); } } Statistics.InitializeTimer(); NativeInterface.RegisterThread(context, _memory, this); do { address = ExecuteSingle(context, address); }while (context.Running && (address & ~1UL) != 0); NativeInterface.UnregisterThread(); if (Interlocked.Decrement(ref _threadCount) == 0) { _backgroundTranslatorEvent.Set(); } }
private static void Glib_UnhandledException(GLib.UnhandledExceptionArgs e) { Exception exception = e.ExceptionObject as Exception; Logger.PrintError(LogClass.Application, $"Unhandled exception caught: {exception}"); Ptc.Close(); PtcProfiler.Stop(); if (e.IsTerminating) { Logger.Shutdown(); Ptc.Dispose(); PtcProfiler.Dispose(); } }
private static void ProcessUnhandledException(Exception ex, bool isTerminating) { Ptc.Close(); PtcProfiler.Stop(); string message = $"Unhandled exception caught: {ex}"; Logger.Error?.PrintMsg(LogClass.Application, message); if (Logger.Error == null) { Logger.Notice.PrintMsg(LogClass.Application, message); } if (isTerminating) { Exit(); } }
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory) { _memory = memory; _funcs = new ConcurrentDictionary <ulong, TranslatedFunction>(); _backgroundStack = new ConcurrentStack <RejitRequest>(); _backgroundTranslatorEvent = new AutoResetEvent(false); _jumpTable = new JumpTable(allocator); JitCache.Initialize(allocator); DirectCallStubs.InitializeStubs(); if (Ptc.State == PtcState.Enabled) { Ptc.LoadTranslations(_funcs, memory.PageTablePointer, _jumpTable); } }
private void End(HLE.Switch device) { #if USE_DEBUGGING _debugger.Dispose(); #endif if (_ending) { return; } _ending = true; if (device != null) { UpdateGameMetadata(device.Application.TitleIdText); if (_glWidget != null) { // We tell the widget that we are exiting _glWidget.Exit(); // Wait for the other thread to dispose the HLE context before exiting. _deviceExitStatus.WaitOne(); } } Dispose(); Profile.FinishProfiling(); DiscordIntegrationModule.Exit(); Ptc.Dispose(); PtcProfiler.Dispose(); Logger.Shutdown(); Application.Quit(); }
private void CreateGameWindow(HLE.Switch device) { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1); } _glWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel); Application.Invoke(delegate { _viewBox.Remove(_gameTableWindow); _glWidget.Expand = true; _viewBox.Child = _glWidget; _glWidget.ShowAll(); EditFooterForGameRender(); if (this.Window.State.HasFlag(Gdk.WindowState.Fullscreen)) { ToggleExtraWidgets(false); } }); _glWidget.WaitEvent.WaitOne(); _glWidget.Start(); Ptc.Close(); PtcProfiler.Stop(); device.Dispose(); _deviceExitStatus.Set(); // NOTE: Everything that is here will not be executed when you close the UI. Application.Invoke(delegate { if (this.Window.State.HasFlag(Gdk.WindowState.Fullscreen)) { ToggleExtraWidgets(true); } _viewBox.Remove(_glWidget); _glWidget.Exit(); if (_glWidget.Window != this.Window && _glWidget.Window != null) { _glWidget.Window.Dispose(); } _glWidget.Dispose(); _windowsMultimediaTimerResolution?.Dispose(); _windowsMultimediaTimerResolution = null; _viewBox.Add(_gameTableWindow); _gameTableWindow.Expand = true; this.Window.Title = $"Ryujinx {Program.Version}"; _emulationContext = null; _gameLoaded = false; _glWidget = null; DiscordIntegrationModule.SwitchToMainMenu(); RecreateFooterForMenu(); UpdateColumns(); UpdateGameTable(); Task.Run(RefreshFirmwareLabel); _stopEmulation.Sensitive = false; _firmwareInstallFile.Sensitive = true; _firmwareInstallDirectory.Sensitive = true; }); }
private void CreateGameWindow() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1); } DisplaySleep.Prevent(); GlRendererWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel); Application.Invoke(delegate { _viewBox.Remove(_gameTableWindow); GlRendererWidget.Expand = true; _viewBox.Child = GlRendererWidget; GlRendererWidget.ShowAll(); EditFooterForGameRenderer(); if (Window.State.HasFlag(Gdk.WindowState.Fullscreen)) { ToggleExtraWidgets(false); } else if (ConfigurationState.Instance.Ui.StartFullscreen.Value) { FullScreen_Toggled(null, null); } }); GlRendererWidget.WaitEvent.WaitOne(); GlRendererWidget.Start(); Ptc.Close(); PtcProfiler.Stop(); _emulationContext.Dispose(); _deviceExitStatus.Set(); // NOTE: Everything that is here will not be executed when you close the UI. Application.Invoke(delegate { if (Window.State.HasFlag(Gdk.WindowState.Fullscreen)) { ToggleExtraWidgets(true); } GlRendererWidget.Exit(); if (GlRendererWidget.Window != Window && GlRendererWidget.Window != null) { GlRendererWidget.Window.Dispose(); } GlRendererWidget.Dispose(); _windowsMultimediaTimerResolution?.Dispose(); _windowsMultimediaTimerResolution = null; DisplaySleep.Restore(); _viewBox.Remove(GlRendererWidget); _viewBox.Add(_gameTableWindow); _gameTableWindow.Expand = true; Window.Title = $"Ryujinx {Program.Version}"; _emulationContext = null; _gameLoaded = false; GlRendererWidget = null; DiscordIntegrationModule.SwitchToMainMenu(); RecreateFooterForMenu(); UpdateColumns(); UpdateGameTable(); Task.Run(RefreshFirmwareLabel); Task.Run(HandleRelaunch); _stopEmulation.Sensitive = false; _simulateWakeUpMessage.Sensitive = false; _firmwareInstallFile.Sensitive = true; _firmwareInstallDirectory.Sensitive = true; }); }
public static bool TryFastTranslateDyn( Translator translator, ulong address, ulong funcSize, bool highCq, ref TtcInfo ttcInfoRef, out TranslatedFunction translatedFuncDyn) { ttcInfoRef = null; translatedFuncDyn = null; if (!Translator.OverlapsWith(address, funcSize, Translator.StaticCodeStart, Translator.StaticCodeSize) && (highCq || funcSize > MinFuncSizeDyn)) { Hash128 preHash = translator.ComputeHash(address, funcSize); Hash128 hash = highCq ? ~preHash : preHash; if (!translator.TtcInfos.TryGetValue(hash, out TtcInfo ttcInfoOut)) { TtcInfo ttcInfoNew = new TtcInfo(); ttcInfoNew.IsBusy = true; ttcInfoNew.LastGuestAddress = address; ttcInfoNew.GuestSize = funcSize; if (translator.TtcInfos.TryAdd(hash, ttcInfoNew)) { ttcInfoRef = ttcInfoNew; } else { ttcInfoNew.Dispose(); } } else { lock (ttcInfoOut) { if (!ttcInfoOut.IsBusy) { ttcInfoOut.IsBusy = true; ttcInfoOut.LastGuestAddress = address; if (ttcInfoOut.RelocEntriesCount != 0) { RelocEntry[] relocEntries = Ptc.GetRelocEntries(ttcInfoOut.RelocStream, ttcInfoOut.RelocEntriesCount, reloadStream: true); JitCache.ModifyMapped(ttcInfoOut.TranslatedFunc.FuncPtr, ttcInfoOut.HostSize, (code) => PatchCodeDyn(translator, code, relocEntries, address)); } if (ttcInfoOut.TranslatedFunc.CallCounter != null && Volatile.Read(ref ttcInfoOut.TranslatedFunc.CallCounter.Value) > Translator.MinsCallForRejit) { Volatile.Write(ref ttcInfoOut.TranslatedFunc.CallCounter.Value, Translator.MinsCallForRejit); } translatedFuncDyn = ttcInfoOut.TranslatedFunc; Logger.Debug?.Print(LogClass.Ttc, $"Fast translated dynamic function 0x{preHash} " + $"(HighCq: {highCq}{(!highCq ? $" [CallCounter: {ttcInfoOut.TranslatedFunc.CallCounter.Value}]" : string.Empty)}, HostSize: {ttcInfoOut.HostSize}) " + $"| DynFuncs: {translator.TtcInfos.Count}."); return(true); } } } } return(false); }
private bool UpdateFrame() { if (!_isActive) { return(true); } if (_isStopped) { return(false); } if (_isFocused) { Gtk.Application.Invoke(delegate { KeyboardState keyboard = OpenTK.Input.Keyboard.GetState(); HandleScreenState(keyboard); if (keyboard.IsKeyDown(OpenTK.Input.Key.Delete)) { if (!ParentWindow.State.HasFlag(Gdk.WindowState.Fullscreen)) { Ptc.Continue(); } } }); } List <GamepadInput> gamepadInputs = new List <GamepadInput>(NpadDevices.MaxControllers); List <SixAxisInput> motionInputs = new List <SixAxisInput>(NpadDevices.MaxControllers); MotionDevice motionDevice = new MotionDevice(_dsuClient); foreach (InputConfig inputConfig in ConfigurationState.Instance.Hid.InputConfig.Value) { ControllerKeys currentButton = 0; JoystickPosition leftJoystick = new JoystickPosition(); JoystickPosition rightJoystick = new JoystickPosition(); KeyboardInput? hidKeyboard = null; int leftJoystickDx = 0; int leftJoystickDy = 0; int rightJoystickDx = 0; int rightJoystickDy = 0; if (inputConfig.EnableMotion) { motionDevice.RegisterController(inputConfig.PlayerIndex); } if (inputConfig is KeyboardConfig keyboardConfig) { if (_isFocused) { // Keyboard Input KeyboardController keyboardController = new KeyboardController(keyboardConfig); currentButton = keyboardController.GetButtons(); (leftJoystickDx, leftJoystickDy) = keyboardController.GetLeftStick(); (rightJoystickDx, rightJoystickDy) = keyboardController.GetRightStick(); leftJoystick = new JoystickPosition { Dx = leftJoystickDx, Dy = leftJoystickDy }; rightJoystick = new JoystickPosition { Dx = rightJoystickDx, Dy = rightJoystickDy }; if (ConfigurationState.Instance.Hid.EnableKeyboard) { hidKeyboard = keyboardController.GetKeysDown(); } if (!hidKeyboard.HasValue) { hidKeyboard = new KeyboardInput { Modifier = 0, Keys = new int[0x8] }; } if (ConfigurationState.Instance.Hid.EnableKeyboard) { _device.Hid.Keyboard.Update(hidKeyboard.Value); } } } else if (inputConfig is Common.Configuration.Hid.ControllerConfig controllerConfig) { // Controller Input JoystickController joystickController = new JoystickController(controllerConfig); currentButton |= joystickController.GetButtons(); (leftJoystickDx, leftJoystickDy) = joystickController.GetLeftStick(); (rightJoystickDx, rightJoystickDy) = joystickController.GetRightStick(); leftJoystick = new JoystickPosition { Dx = controllerConfig.LeftJoycon.InvertStickX ? -leftJoystickDx : leftJoystickDx, Dy = controllerConfig.LeftJoycon.InvertStickY ? -leftJoystickDy : leftJoystickDy }; rightJoystick = new JoystickPosition { Dx = controllerConfig.RightJoycon.InvertStickX ? -rightJoystickDx : rightJoystickDx, Dy = controllerConfig.RightJoycon.InvertStickY ? -rightJoystickDy : rightJoystickDy }; } currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick); motionDevice.Poll(inputConfig, inputConfig.Slot); SixAxisInput sixAxisInput = new SixAxisInput() { PlayerId = (HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex, Accelerometer = motionDevice.Accelerometer, Gyroscope = motionDevice.Gyroscope, Rotation = motionDevice.Rotation, Orientation = motionDevice.Orientation }; motionInputs.Add(sixAxisInput); gamepadInputs.Add(new GamepadInput { PlayerId = (HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex, Buttons = currentButton, LStick = leftJoystick, RStick = rightJoystick }); if (inputConfig.ControllerType == Common.Configuration.Hid.ControllerType.JoyconPair) { if (!inputConfig.MirrorInput) { motionDevice.Poll(inputConfig, inputConfig.AltSlot); sixAxisInput = new SixAxisInput() { PlayerId = (HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex, Accelerometer = motionDevice.Accelerometer, Gyroscope = motionDevice.Gyroscope, Rotation = motionDevice.Rotation, Orientation = motionDevice.Orientation }; } motionInputs.Add(sixAxisInput); } } _device.Hid.Npads.Update(gamepadInputs); _device.Hid.Npads.UpdateSixAxis(motionInputs); _device.TamperMachine.UpdateInput(gamepadInputs); if (_isFocused) { // Hotkeys HotkeyButtons currentHotkeyButtons = KeyboardController.GetHotkeyButtons(OpenTK.Input.Keyboard.GetState()); if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) && !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync)) { _device.EnableDeviceVsync = !_device.EnableDeviceVsync; Logger.Info?.Print(LogClass.Application, $"Vsync toggled to: {_device.EnableDeviceVsync}"); } _prevHotkeyButtons = currentHotkeyButtons; } //Touchscreen bool hasTouch = false; // Get screen touch position from left mouse click // OpenTK always captures mouse events, even if out of focus, so check if window is focused. if (_isFocused && _mousePressed) { float aspectWidth = SwitchPanelHeight * ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat(); int screenWidth = AllocatedWidth; int screenHeight = AllocatedHeight; if (AllocatedWidth > AllocatedHeight * aspectWidth / SwitchPanelHeight) { screenWidth = (int)(AllocatedHeight * aspectWidth) / SwitchPanelHeight; } else { screenHeight = (AllocatedWidth * SwitchPanelHeight) / (int)aspectWidth; } int startX = (AllocatedWidth - screenWidth) >> 1; int startY = (AllocatedHeight - screenHeight) >> 1; int endX = startX + screenWidth; int endY = startY + screenHeight; if (_mouseX >= startX && _mouseY >= startY && _mouseX < endX && _mouseY < endY) { int screenMouseX = (int)_mouseX - startX; int screenMouseY = (int)_mouseY - startY; int mX = (screenMouseX * (int)aspectWidth) / screenWidth; int mY = (screenMouseY * SwitchPanelHeight) / screenHeight; TouchPoint currentPoint = new TouchPoint { X = (uint)mX, Y = (uint)mY, // Placeholder values till more data is acquired DiameterX = 10, DiameterY = 10, Angle = 90 }; hasTouch = true; _device.Hid.Touchscreen.Update(currentPoint); } } if (!hasTouch) { _device.Hid.Touchscreen.Update(); } _device.Hid.DebugPad.Update(); return(true); }
private bool UpdateFrame() { if (!IsActive) { return(true); } if (IsStopped) { return(false); } if (IsFocused) { Gtk.Application.Invoke(delegate { KeyboardState keyboard = OpenTK.Input.Keyboard.GetState(); HandleScreenState(keyboard); if (keyboard.IsKeyDown(OpenTK.Input.Key.Delete)) { if (!ParentWindow.State.HasFlag(Gdk.WindowState.Fullscreen)) { Ptc.Continue(); } } }); } List <GamepadInput> gamepadInputs = new List <GamepadInput>(); foreach (InputConfig inputConfig in ConfigurationState.Instance.Hid.InputConfig.Value.ToArray()) { ControllerKeys currentButton = 0; JoystickPosition leftJoystick = new JoystickPosition(); JoystickPosition rightJoystick = new JoystickPosition(); KeyboardInput? hidKeyboard = null; int leftJoystickDx = 0; int leftJoystickDy = 0; int rightJoystickDx = 0; int rightJoystickDy = 0; if (inputConfig is KeyboardConfig keyboardConfig) { if (IsFocused) { // Keyboard Input KeyboardController keyboardController = new KeyboardController(keyboardConfig); currentButton = keyboardController.GetButtons(); (leftJoystickDx, leftJoystickDy) = keyboardController.GetLeftStick(); (rightJoystickDx, rightJoystickDy) = keyboardController.GetRightStick(); leftJoystick = new JoystickPosition { Dx = leftJoystickDx, Dy = leftJoystickDy }; rightJoystick = new JoystickPosition { Dx = rightJoystickDx, Dy = rightJoystickDy }; if (ConfigurationState.Instance.Hid.EnableKeyboard) { hidKeyboard = keyboardController.GetKeysDown(); } if (!hidKeyboard.HasValue) { hidKeyboard = new KeyboardInput { Modifier = 0, Keys = new int[0x8] }; } if (ConfigurationState.Instance.Hid.EnableKeyboard) { _device.Hid.Keyboard.Update(hidKeyboard.Value); } } } else if (inputConfig is Common.Configuration.Hid.ControllerConfig controllerConfig) { // Controller Input JoystickController joystickController = new JoystickController(controllerConfig); currentButton |= joystickController.GetButtons(); (leftJoystickDx, leftJoystickDy) = joystickController.GetLeftStick(); (rightJoystickDx, rightJoystickDy) = joystickController.GetRightStick(); leftJoystick = new JoystickPosition { Dx = controllerConfig.LeftJoycon.InvertStickX ? -leftJoystickDx : leftJoystickDx, Dy = controllerConfig.LeftJoycon.InvertStickY ? -leftJoystickDy : leftJoystickDy }; rightJoystick = new JoystickPosition { Dx = controllerConfig.RightJoycon.InvertStickX ? -rightJoystickDx : rightJoystickDx, Dy = controllerConfig.RightJoycon.InvertStickY ? -rightJoystickDy : rightJoystickDy }; } currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick); gamepadInputs.Add(new GamepadInput { PlayerId = (HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex, Buttons = currentButton, LStick = leftJoystick, RStick = rightJoystick }); } _device.Hid.Npads.SetGamepadsInput(gamepadInputs.ToArray()); // Hotkeys HotkeyButtons currentHotkeyButtons = KeyboardController.GetHotkeyButtons(OpenTK.Input.Keyboard.GetState()); if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) && !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync)) { _device.EnableDeviceVsync = !_device.EnableDeviceVsync; } _prevHotkeyButtons = currentHotkeyButtons; //Touchscreen bool hasTouch = false; // Get screen touch position from left mouse click // OpenTK always captures mouse events, even if out of focus, so check if window is focused. if (IsFocused && _mousePressed) { int screenWidth = AllocatedWidth; int screenHeight = AllocatedHeight; if (AllocatedWidth > (AllocatedHeight * SwitchPanelWidth) / SwitchPanelHeight) { screenWidth = (AllocatedHeight * SwitchPanelWidth) / SwitchPanelHeight; } else { screenHeight = (AllocatedWidth * SwitchPanelHeight) / SwitchPanelWidth; } int startX = (AllocatedWidth - screenWidth) >> 1; int startY = (AllocatedHeight - screenHeight) >> 1; int endX = startX + screenWidth; int endY = startY + screenHeight; if (_mouseX >= startX && _mouseY >= startY && _mouseX < endX && _mouseY < endY) { int screenMouseX = (int)_mouseX - startX; int screenMouseY = (int)_mouseY - startY; int mX = (screenMouseX * SwitchPanelWidth) / screenWidth; int mY = (screenMouseY * SwitchPanelHeight) / screenHeight; TouchPoint currentPoint = new TouchPoint { X = (uint)mX, Y = (uint)mY, // Placeholder values till more data is acquired DiameterX = 10, DiameterY = 10, Angle = 90 }; hasTouch = true; _device.Hid.Touchscreen.Update(currentPoint); } } if (!hasTouch) { _device.Hid.Touchscreen.Update(); } _device.Hid.DebugPad.Update(); return(true); }
private bool UpdateFrame() { if (!_isActive) { return(true); } if (_isStopped) { return(false); } if (_isFocused) { Gtk.Application.Invoke(delegate { KeyboardStateSnapshot keyboard = _keyboardInterface.GetKeyboardStateSnapshot(); HandleScreenState(keyboard); if (keyboard.IsPressed(Key.Delete)) { if (!ParentWindow.State.HasFlag(WindowState.Fullscreen)) { Ptc.Continue(); } } }); } NpadManager.Update(_device.Hid, _device.TamperMachine); if (_isFocused) { KeyboardHotkeyState currentHotkeyState = GetHotkeyState(); if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync) && !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync)) { _device.EnableDeviceVsync = !_device.EnableDeviceVsync; } _prevHotkeyState = currentHotkeyState; } //Touchscreen bool hasTouch = false; // Get screen touch position from left mouse click // OpenTK always captures mouse events, even if out of focus, so check if window is focused. if (_isFocused && _mousePressed) { float aspectWidth = SwitchPanelHeight * ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat(); int screenWidth = AllocatedWidth; int screenHeight = AllocatedHeight; if (AllocatedWidth > AllocatedHeight * aspectWidth / SwitchPanelHeight) { screenWidth = (int)(AllocatedHeight * aspectWidth) / SwitchPanelHeight; } else { screenHeight = (AllocatedWidth * SwitchPanelHeight) / (int)aspectWidth; } int startX = (AllocatedWidth - screenWidth) >> 1; int startY = (AllocatedHeight - screenHeight) >> 1; int endX = startX + screenWidth; int endY = startY + screenHeight; if (_mouseX >= startX && _mouseY >= startY && _mouseX < endX && _mouseY < endY) { int screenMouseX = (int)_mouseX - startX; int screenMouseY = (int)_mouseY - startY; int mX = (screenMouseX * (int)aspectWidth) / screenWidth; int mY = (screenMouseY * SwitchPanelHeight) / screenHeight; TouchPoint currentPoint = new TouchPoint { X = (uint)mX, Y = (uint)mY, // Placeholder values till more data is acquired DiameterX = 10, DiameterY = 10, Angle = 90 }; hasTouch = true; _device.Hid.Touchscreen.Update(currentPoint); } } if (!hasTouch) { _device.Hid.Touchscreen.Update(); } _device.Hid.DebugPad.Update(); return(true); }
private void CreateGameWindow(HLE.Switch device) { device.Hid.Npads.AddControllers(ConfigurationState.Instance.Hid.InputConfig.Value.Select(inputConfig => new HLE.HOS.Services.Hid.ControllerConfig { Player = (PlayerIndex)inputConfig.PlayerIndex, Type = (ControllerType)inputConfig.ControllerType } ).ToArray()); _glWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel); Application.Invoke(delegate { _viewBox.Remove(_gameTableWindow); _glWidget.Expand = true; _viewBox.Child = _glWidget; _glWidget.ShowAll(); EditFooterForGameRender(); if (this.Window.State.HasFlag(Gdk.WindowState.Fullscreen)) { ToggleExtraWidgets(false); } }); _glWidget.WaitEvent.WaitOne(); _glWidget.Start(); Ptc.Close(); PtcProfiler.Stop(); device.Dispose(); _deviceExitStatus.Set(); // NOTE: Everything that is here will not be executed when you close the UI. Application.Invoke(delegate { if (this.Window.State.HasFlag(Gdk.WindowState.Fullscreen)) { ToggleExtraWidgets(true); } _viewBox.Remove(_glWidget); _glWidget.Exit(); if (_glWidget.Window != this.Window && _glWidget.Window != null) { _glWidget.Window.Dispose(); } _glWidget.Dispose(); _viewBox.Add(_gameTableWindow); _gameTableWindow.Expand = true; this.Window.Title = $"Ryujinx {Program.Version}"; _emulationContext = null; _gameLoaded = false; _glWidget = null; DiscordIntegrationModule.SwitchToMainMenu(); RecreateFooterForMenu(); UpdateColumns(); UpdateGameTable(); Task.Run(RefreshFirmwareLabel); _stopEmulation.Sensitive = false; _firmwareInstallFile.Sensitive = true; _firmwareInstallDirectory.Sensitive = true; }); }
private bool UpdateFrame() { if (!_isActive) { return(true); } if (_isStopped) { return(false); } if ((Toplevel as MainWindow).IsFocused) { Application.Invoke(delegate { KeyboardStateSnapshot keyboard = _keyboardInterface.GetKeyboardStateSnapshot(); HandleScreenState(keyboard); if (keyboard.IsPressed(Key.Delete)) { if (!ParentWindow.State.HasFlag(WindowState.Fullscreen)) { Ptc.Continue(); } } }); } NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat()); if ((Toplevel as MainWindow).IsFocused) { KeyboardHotkeyState currentHotkeyState = GetHotkeyState(); if (currentHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync) && !_prevHotkeyState.HasFlag(KeyboardHotkeyState.ToggleVSync)) { Device.EnableDeviceVsync = !Device.EnableDeviceVsync; } if ((currentHotkeyState.HasFlag(KeyboardHotkeyState.Screenshot) && !_prevHotkeyState.HasFlag(KeyboardHotkeyState.Screenshot)) || ScreenshotRequested) { ScreenshotRequested = false; Renderer.Screenshot(); } _prevHotkeyState = currentHotkeyState; } // Touchscreen bool hasTouch = false; // Get screen touch position if ((Toplevel as MainWindow).IsFocused && !ConfigurationState.Instance.Hid.EnableMouse) { hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as GTK3MouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat()); } if (!hasTouch) { TouchScreenManager.Update(false); } Device.Hid.DebugPad.Update(); return(true); }