Пример #1
0
        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));
        }
Пример #2
0
        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;
            }
        }
Пример #3
0
        private static void ProgramExit()
        {
            Ptc.Dispose();
            PtcProfiler.Dispose();

            Logger.Shutdown();
        }
Пример #4
0
        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));
        }
Пример #5
0
        public static void Exit()
        {
            DiscordIntegrationModule.Exit();

            Ptc.Dispose();
            PtcProfiler.Dispose();

            Logger.Shutdown();
        }
Пример #6
0
        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();
            }
        }
Пример #7
0
        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();
            }
        }
Пример #8
0
        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();
            }
        }
Пример #9
0
        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);
            }
        }
Пример #10
0
        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();
        }
Пример #11
0
        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;
            });
        }
Пример #12
0
        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;
            });
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        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;
            });
        }
Пример #18
0
        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);
        }