From 8ca4d8c230647644b1ad13650f9c2666e8e339f3 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Thu, 27 Jan 2022 03:52:17 +0100 Subject: [PATCH] early-access version 2437 --- README.md | 2 +- src/common/settings.h | 1 + src/core/hid/emulated_controller.cpp | 1 + src/core/hid/motion_input.cpp | 4 +- src/input_common/input_poller.cpp | 13 ++- src/video_core/engines/maxwell_3d.cpp | 2 +- src/video_core/macro/macro.cpp | 13 +-- src/video_core/macro/macro.h | 2 +- src/video_core/macro/macro_hle.cpp | 36 +++--- src/video_core/macro/macro_hle.h | 21 +--- src/video_core/macro/macro_interpreter.cpp | 92 ++++++++++++++-- src/video_core/macro/macro_interpreter.h | 78 +------------ src/video_core/macro/macro_jit_x64.cpp | 104 +++++++++++++++--- src/video_core/macro/macro_jit_x64.h | 71 ------------ src/yuzu/configuration/config.cpp | 3 + .../configure_input_advanced.cpp | 2 + .../configuration/configure_input_advanced.ui | 19 +++- .../configuration/configure_input_player.cpp | 12 ++ src/yuzu/hotkeys.cpp | 3 + src/yuzu/util/controller_navigation.cpp | 3 + 20 files changed, 258 insertions(+), 224 deletions(-) diff --git a/README.md b/README.md index f462bef9d..12ede2a17 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2436. +This is the source code for early-access 2437. ## Legal Notice diff --git a/src/common/settings.h b/src/common/settings.h index 85b5f7dad..ab453addc 100755 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -554,6 +554,7 @@ struct Values { Setting use_docked_mode{true, "use_docked_mode"}; BasicSetting enable_raw_input{false, "enable_raw_input"}; + BasicSetting controller_navigation{true, "controller_navigation"}; Setting vibration_enabled{true, "vibration_enabled"}; Setting enable_accurate_vibrations{false, "enable_accurate_vibrations"}; diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index d12037b11..a7cdf45e6 100755 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -749,6 +749,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback raw_status.gyro.y.value, raw_status.gyro.z.value, }); + emulated.SetGyroThreshold(raw_status.gyro.x.properties.threshold); emulated.UpdateRotation(raw_status.delta_timestamp); emulated.UpdateOrientation(raw_status.delta_timestamp); force_update_motion = raw_status.force_update; diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp index 6e126be19..05042fd99 100755 --- a/src/core/hid/motion_input.cpp +++ b/src/core/hid/motion_input.cpp @@ -10,7 +10,7 @@ namespace Core::HID { MotionInput::MotionInput() { // Initialize PID constants with default values SetPID(0.3f, 0.005f, 0.0f); - SetGyroThreshold(0.00005f); + SetGyroThreshold(0.007f); } void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { @@ -31,7 +31,7 @@ void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f); } - if (gyro.Length2() < gyro_threshold) { + if (gyro.Length() < gyro_threshold) { gyro = {}; } else { only_accelerometer = false; diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 7b370335f..2f3c0735a 100755 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -504,9 +504,10 @@ private: class InputFromMotion final : public Common::Input::InputDevice { public: - explicit InputFromMotion(PadIdentifier identifier_, int motion_sensor_, + explicit InputFromMotion(PadIdentifier identifier_, int motion_sensor_, float gyro_threshold_, InputEngine* input_engine_) - : identifier(identifier_), motion_sensor(motion_sensor_), input_engine(input_engine_) { + : identifier(identifier_), motion_sensor(motion_sensor_), gyro_threshold(gyro_threshold_), + input_engine(input_engine_) { UpdateCallback engine_callback{[this]() { OnChange(); }}; const InputIdentifier input_identifier{ .identifier = identifier, @@ -525,8 +526,9 @@ public: const auto basic_motion = input_engine->GetMotion(identifier, motion_sensor); Common::Input::MotionStatus status{}; const Common::Input::AnalogProperties properties = { - .deadzone = 0.001f, + .deadzone = 0.0f, .range = 1.0f, + .threshold = gyro_threshold, .offset = 0.0f, }; status.accel.x = {.raw_value = basic_motion.accel_x, .properties = properties}; @@ -551,6 +553,7 @@ public: private: const PadIdentifier identifier; const int motion_sensor; + const float gyro_threshold; int callback_key; InputEngine* input_engine; }; @@ -873,9 +876,11 @@ std::unique_ptr InputFactory::CreateMotionDevice( if (params.Has("motion")) { const auto motion_sensor = params.Get("motion", 0); + const auto gyro_threshold = params.Get("threshold", 0.007f); input_engine->PreSetController(identifier); input_engine->PreSetMotion(identifier, motion_sensor); - return std::make_unique(identifier, motion_sensor, input_engine.get()); + return std::make_unique(identifier, motion_sensor, gyro_threshold, + input_engine.get()); } const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f); diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index b18b8a02a..c38ebd670 100755 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -240,7 +240,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) ((method - MacroRegistersStart) >> 1) % static_cast(macro_positions.size()); // Execute the current macro. - macro_engine->Execute(*this, macro_positions[entry], parameters); + macro_engine->Execute(macro_positions[entry], parameters); if (mme_draw.current_mode != MMEDrawMode::Undefined) { FlushMMEInlineDraw(); } diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index d7fabe605..0aeda4ce8 100755 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp @@ -2,12 +2,13 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include + #include + #include "common/assert.h" -#include "common/logging/log.h" #include "common/settings.h" -#include "video_core/engines/maxwell_3d.h" #include "video_core/macro/macro.h" #include "video_core/macro/macro_hle.h" #include "video_core/macro/macro_interpreter.h" @@ -24,8 +25,7 @@ void MacroEngine::AddCode(u32 method, u32 data) { uploaded_macro_code[method].push_back(data); } -void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, - const std::vector& parameters) { +void MacroEngine::Execute(u32 method, const std::vector& parameters) { auto compiled_macro = macro_cache.find(method); if (compiled_macro != macro_cache.end()) { const auto& cache_info = compiled_macro->second; @@ -66,10 +66,9 @@ void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, cache_info.lle_program = Compile(code); } - auto hle_program = hle_macros->GetHLEProgram(cache_info.hash); - if (hle_program.has_value()) { + if (auto hle_program = hle_macros->GetHLEProgram(cache_info.hash)) { cache_info.has_hle_program = true; - cache_info.hle_program = std::move(hle_program.value()); + cache_info.hle_program = std::move(hle_program); cache_info.hle_program->Execute(parameters, method); } else { cache_info.lle_program->Execute(parameters, method); diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h index 31ee3440a..7aaa49286 100755 --- a/src/video_core/macro/macro.h +++ b/src/video_core/macro/macro.h @@ -119,7 +119,7 @@ public: void AddCode(u32 method, u32 data); // Compiles the macro if its not in the cache, and executes the compiled macro - void Execute(Engines::Maxwell3D& maxwell3d, u32 method, const std::vector& parameters); + void Execute(u32 method, const std::vector& parameters); protected: virtual std::unique_ptr Compile(const std::vector& code) = 0; diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 121f380f8..615d14f2a 100755 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp @@ -7,12 +7,15 @@ #include "common/scope_exit.h" #include "video_core/dirty_flags.h" #include "video_core/engines/maxwell_3d.h" +#include "video_core/macro/macro.h" #include "video_core/macro/macro_hle.h" #include "video_core/rasterizer_interface.h" namespace Tegra { - namespace { + +using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector& parameters); + // HLE'd functions void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector& parameters) { const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); @@ -137,8 +140,6 @@ void HLE_3f5e74b9c9a50164(Engines::Maxwell3D& maxwell3d, const std::vector& } } -} // Anonymous namespace - constexpr std::array, 4> hle_funcs{{ {0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, @@ -146,25 +147,32 @@ constexpr std::array, 4> hle_funcs{{ {0x3f5e74b9c9a50164, &HLE_3f5e74b9c9a50164}, }}; +class HLEMacroImpl final : public CachedMacro { +public: + explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d_, HLEFunction func_) + : maxwell3d{maxwell3d_}, func{func_} {} + + void Execute(const std::vector& parameters, u32 method) override { + func(maxwell3d, parameters); + } + +private: + Engines::Maxwell3D& maxwell3d; + HLEFunction func; +}; + +} // Anonymous namespace + HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} HLEMacro::~HLEMacro() = default; -std::optional> HLEMacro::GetHLEProgram(u64 hash) const { +std::unique_ptr HLEMacro::GetHLEProgram(u64 hash) const { const auto it = std::find_if(hle_funcs.cbegin(), hle_funcs.cend(), [hash](const auto& pair) { return pair.first == hash; }); if (it == hle_funcs.end()) { - return std::nullopt; + return nullptr; } return std::make_unique(maxwell3d, it->second); } -HLEMacroImpl::~HLEMacroImpl() = default; - -HLEMacroImpl::HLEMacroImpl(Engines::Maxwell3D& maxwell3d_, HLEFunction func_) - : maxwell3d{maxwell3d_}, func{func_} {} - -void HLEMacroImpl::Execute(const std::vector& parameters, u32 method) { - func(maxwell3d, parameters); -} - } // namespace Tegra diff --git a/src/video_core/macro/macro_hle.h b/src/video_core/macro/macro_hle.h index cb3bd1600..b86ba84a1 100755 --- a/src/video_core/macro/macro_hle.h +++ b/src/video_core/macro/macro_hle.h @@ -5,10 +5,7 @@ #pragma once #include -#include -#include #include "common/common_types.h" -#include "video_core/macro/macro.h" namespace Tegra { @@ -16,29 +13,17 @@ namespace Engines { class Maxwell3D; } -using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector& parameters); - class HLEMacro { public: explicit HLEMacro(Engines::Maxwell3D& maxwell3d_); ~HLEMacro(); - std::optional> GetHLEProgram(u64 hash) const; + // Allocates and returns a cached macro if the hash matches a known function. + // Returns nullptr otherwise. + [[nodiscard]] std::unique_ptr GetHLEProgram(u64 hash) const; private: Engines::Maxwell3D& maxwell3d; }; -class HLEMacroImpl : public CachedMacro { -public: - explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d, HLEFunction func); - ~HLEMacroImpl(); - - void Execute(const std::vector& parameters, u32 method) override; - -private: - Engines::Maxwell3D& maxwell3d; - HLEFunction func; -}; - } // namespace Tegra diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp index 8da26fd59..fba755448 100755 --- a/src/video_core/macro/macro_interpreter.cpp +++ b/src/video_core/macro/macro_interpreter.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include + #include "common/assert.h" #include "common/logging/log.h" #include "common/microprofile.h" @@ -11,16 +14,81 @@ MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192)); namespace Tegra { -MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d_) - : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} +namespace { +class MacroInterpreterImpl final : public CachedMacro { +public: + explicit MacroInterpreterImpl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) + : maxwell3d{maxwell3d_}, code{code_} {} -std::unique_ptr MacroInterpreter::Compile(const std::vector& code) { - return std::make_unique(maxwell3d, code); -} + void Execute(const std::vector& params, u32 method) override; -MacroInterpreterImpl::MacroInterpreterImpl(Engines::Maxwell3D& maxwell3d_, - const std::vector& code_) - : maxwell3d{maxwell3d_}, code{code_} {} +private: + /// Resets the execution engine state, zeroing registers, etc. + void Reset(); + + /** + * Executes a single macro instruction located at the current program counter. Returns whether + * the interpreter should keep running. + * + * @param is_delay_slot Whether the current step is being executed due to a delay slot in a + * previous instruction. + */ + bool Step(bool is_delay_slot); + + /// Calculates the result of an ALU operation. src_a OP src_b; + u32 GetALUResult(Macro::ALUOperation operation, u32 src_a, u32 src_b); + + /// Performs the result operation on the input result and stores it in the specified register + /// (if necessary). + void ProcessResult(Macro::ResultOperation operation, u32 reg, u32 result); + + /// Evaluates the branch condition and returns whether the branch should be taken or not. + bool EvaluateBranchCondition(Macro::BranchCondition cond, u32 value) const; + + /// Reads an opcode at the current program counter location. + Macro::Opcode GetOpcode() const; + + /// Returns the specified register's value. Register 0 is hardcoded to always return 0. + u32 GetRegister(u32 register_id) const; + + /// Sets the register to the input value. + void SetRegister(u32 register_id, u32 value); + + /// Sets the method address to use for the next Send instruction. + void SetMethodAddress(u32 address); + + /// Calls a GPU Engine method with the input parameter. + void Send(u32 value); + + /// Reads a GPU register located at the method address. + u32 Read(u32 method) const; + + /// Returns the next parameter in the parameter queue. + u32 FetchParameter(); + + Engines::Maxwell3D& maxwell3d; + + /// Current program counter + u32 pc{}; + /// Program counter to execute at after the delay slot is executed. + std::optional delayed_pc; + + /// General purpose macro registers. + std::array registers = {}; + + /// Method address to use for the next Send instruction. + Macro::MethodAddress method_address = {}; + + /// Input parameters of the current macro. + std::unique_ptr parameters; + std::size_t num_parameters = 0; + std::size_t parameters_capacity = 0; + /// Index of the next parameter that will be fetched by the 'parm' instruction. + u32 next_parameter_index = 0; + + bool carry_flag = false; + const std::vector& code; +}; void MacroInterpreterImpl::Execute(const std::vector& params, u32 method) { MICROPROFILE_SCOPE(MacroInterp); @@ -283,5 +351,13 @@ u32 MacroInterpreterImpl::FetchParameter() { ASSERT(next_parameter_index < num_parameters); return parameters[next_parameter_index++]; } +} // Anonymous namespace + +MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d_) + : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} + +std::unique_ptr MacroInterpreter::Compile(const std::vector& code) { + return std::make_unique(maxwell3d, code); +} } // namespace Tegra diff --git a/src/video_core/macro/macro_interpreter.h b/src/video_core/macro/macro_interpreter.h index d50c619ce..8a9648e46 100755 --- a/src/video_core/macro/macro_interpreter.h +++ b/src/video_core/macro/macro_interpreter.h @@ -3,10 +3,9 @@ // Refer to the license.txt file included. #pragma once -#include -#include + #include -#include "common/bit_field.h" + #include "common/common_types.h" #include "video_core/macro/macro.h" @@ -26,77 +25,4 @@ private: Engines::Maxwell3D& maxwell3d; }; -class MacroInterpreterImpl : public CachedMacro { -public: - explicit MacroInterpreterImpl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_); - void Execute(const std::vector& params, u32 method) override; - -private: - /// Resets the execution engine state, zeroing registers, etc. - void Reset(); - - /** - * Executes a single macro instruction located at the current program counter. Returns whether - * the interpreter should keep running. - * - * @param is_delay_slot Whether the current step is being executed due to a delay slot in a - * previous instruction. - */ - bool Step(bool is_delay_slot); - - /// Calculates the result of an ALU operation. src_a OP src_b; - u32 GetALUResult(Macro::ALUOperation operation, u32 src_a, u32 src_b); - - /// Performs the result operation on the input result and stores it in the specified register - /// (if necessary). - void ProcessResult(Macro::ResultOperation operation, u32 reg, u32 result); - - /// Evaluates the branch condition and returns whether the branch should be taken or not. - bool EvaluateBranchCondition(Macro::BranchCondition cond, u32 value) const; - - /// Reads an opcode at the current program counter location. - Macro::Opcode GetOpcode() const; - - /// Returns the specified register's value. Register 0 is hardcoded to always return 0. - u32 GetRegister(u32 register_id) const; - - /// Sets the register to the input value. - void SetRegister(u32 register_id, u32 value); - - /// Sets the method address to use for the next Send instruction. - void SetMethodAddress(u32 address); - - /// Calls a GPU Engine method with the input parameter. - void Send(u32 value); - - /// Reads a GPU register located at the method address. - u32 Read(u32 method) const; - - /// Returns the next parameter in the parameter queue. - u32 FetchParameter(); - - Engines::Maxwell3D& maxwell3d; - - /// Current program counter - u32 pc; - /// Program counter to execute at after the delay slot is executed. - std::optional delayed_pc; - - /// General purpose macro registers. - std::array registers = {}; - - /// Method address to use for the next Send instruction. - Macro::MethodAddress method_address = {}; - - /// Input parameters of the current macro. - std::unique_ptr parameters; - std::size_t num_parameters = 0; - std::size_t parameters_capacity = 0; - /// Index of the next parameter that will be fetched by the 'parm' instruction. - u32 next_parameter_index = 0; - - bool carry_flag = false; - const std::vector& code; -}; - } // namespace Tegra diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp index c6b2b2109..924c9fe5c 100755 --- a/src/video_core/macro/macro_jit_x64.cpp +++ b/src/video_core/macro/macro_jit_x64.cpp @@ -2,9 +2,17 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include + +#include + #include "common/assert.h" +#include "common/bit_field.h" #include "common/logging/log.h" #include "common/microprofile.h" +#include "common/x64/xbyak_abi.h" #include "common/x64/xbyak_util.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/macro/macro_interpreter.h" @@ -14,13 +22,14 @@ MICROPROFILE_DEFINE(MacroJitCompile, "GPU", "Compile macro JIT", MP_RGB(173, 255 MICROPROFILE_DEFINE(MacroJitExecute, "GPU", "Execute macro JIT", MP_RGB(255, 255, 0)); namespace Tegra { +namespace { constexpr Xbyak::Reg64 STATE = Xbyak::util::rbx; constexpr Xbyak::Reg32 RESULT = Xbyak::util::ebp; constexpr Xbyak::Reg64 PARAMETERS = Xbyak::util::r12; constexpr Xbyak::Reg32 METHOD_ADDRESS = Xbyak::util::r14d; constexpr Xbyak::Reg64 BRANCH_HOLDER = Xbyak::util::r15; -static const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ +const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ STATE, RESULT, PARAMETERS, @@ -28,19 +37,75 @@ static const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ BRANCH_HOLDER, }); -MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d_) - : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} +// Arbitrarily chosen based on current booting games. +constexpr size_t MAX_CODE_SIZE = 0x10000; -std::unique_ptr MacroJITx64::Compile(const std::vector& code) { - return std::make_unique(maxwell3d, code); +std::bitset<32> PersistentCallerSavedRegs() { + return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED; } -MacroJITx64Impl::MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) - : CodeGenerator{MAX_CODE_SIZE}, code{code_}, maxwell3d{maxwell3d_} { - Compile(); -} +class MacroJITx64Impl final : public Xbyak::CodeGenerator, public CachedMacro { +public: + explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) + : CodeGenerator{MAX_CODE_SIZE}, code{code_}, maxwell3d{maxwell3d_} { + Compile(); + } -MacroJITx64Impl::~MacroJITx64Impl() = default; + void Execute(const std::vector& parameters, u32 method) override; + + void Compile_ALU(Macro::Opcode opcode); + void Compile_AddImmediate(Macro::Opcode opcode); + void Compile_ExtractInsert(Macro::Opcode opcode); + void Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode); + void Compile_ExtractShiftLeftRegister(Macro::Opcode opcode); + void Compile_Read(Macro::Opcode opcode); + void Compile_Branch(Macro::Opcode opcode); + +private: + void Optimizer_ScanFlags(); + + void Compile(); + bool Compile_NextInstruction(); + + Xbyak::Reg32 Compile_FetchParameter(); + Xbyak::Reg32 Compile_GetRegister(u32 index, Xbyak::Reg32 dst); + + void Compile_ProcessResult(Macro::ResultOperation operation, u32 reg); + void Compile_Send(Xbyak::Reg32 value); + + Macro::Opcode GetOpCode() const; + + struct JITState { + Engines::Maxwell3D* maxwell3d{}; + std::array registers{}; + u32 carry_flag{}; + }; + static_assert(offsetof(JITState, maxwell3d) == 0, "Maxwell3D is not at 0x0"); + using ProgramType = void (*)(JITState*, const u32*); + + struct OptimizerState { + bool can_skip_carry{}; + bool has_delayed_pc{}; + bool zero_reg_skip{}; + bool skip_dummy_addimmediate{}; + bool optimize_for_method_move{}; + bool enable_asserts{}; + }; + OptimizerState optimizer{}; + + std::optional next_opcode{}; + ProgramType program{nullptr}; + + std::array labels; + std::array delay_skip; + Xbyak::Label end_of_code{}; + + bool is_delay_slot{}; + u32 pc{}; + + const std::vector& code; + Engines::Maxwell3D& maxwell3d; +}; void MacroJITx64Impl::Execute(const std::vector& parameters, u32 method) { MICROPROFILE_SCOPE(MacroJitExecute); @@ -307,11 +372,11 @@ void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { Compile_ProcessResult(opcode.result_operation, opcode.dst); } -static void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { +void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { maxwell3d->CallMethodFromMME(method_address.address, value); } -void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { +void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); mov(Common::X64::ABI_PARAM1, qword[STATE]); mov(Common::X64::ABI_PARAM2, METHOD_ADDRESS); @@ -338,7 +403,7 @@ void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { L(dont_process); } -void Tegra::MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { ASSERT_MSG(!is_delay_slot, "Executing a branch in a delay slot is not valid"); const s32 jump_address = static_cast(pc) + static_cast(opcode.GetBranchTarget() / sizeof(s32)); @@ -392,7 +457,7 @@ void Tegra::MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { L(end); } -void Tegra::MacroJITx64Impl::Optimizer_ScanFlags() { +void MacroJITx64Impl::Optimizer_ScanFlags() { optimizer.can_skip_carry = true; optimizer.has_delayed_pc = false; for (auto raw_op : code) { @@ -534,7 +599,7 @@ bool MacroJITx64Impl::Compile_NextInstruction() { return true; } -Xbyak::Reg32 Tegra::MacroJITx64Impl::Compile_FetchParameter() { +Xbyak::Reg32 MacroJITx64Impl::Compile_FetchParameter() { mov(eax, dword[PARAMETERS]); add(PARAMETERS, sizeof(u32)); return eax; @@ -611,9 +676,12 @@ Macro::Opcode MacroJITx64Impl::GetOpCode() const { ASSERT(pc < code.size()); return {code[pc]}; } +} // Anonymous namespace -std::bitset<32> MacroJITx64Impl::PersistentCallerSavedRegs() const { - return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED; +MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d_) + : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} + +std::unique_ptr MacroJITx64::Compile(const std::vector& code) { + return std::make_unique(maxwell3d, code); } - } // namespace Tegra diff --git a/src/video_core/macro/macro_jit_x64.h b/src/video_core/macro/macro_jit_x64.h index d03d480b4..773b037ae 100755 --- a/src/video_core/macro/macro_jit_x64.h +++ b/src/video_core/macro/macro_jit_x64.h @@ -4,12 +4,7 @@ #pragma once -#include -#include -#include -#include "common/bit_field.h" #include "common/common_types.h" -#include "common/x64/xbyak_abi.h" #include "video_core/macro/macro.h" namespace Tegra { @@ -18,9 +13,6 @@ namespace Engines { class Maxwell3D; } -/// MAX_CODE_SIZE is arbitrarily chosen based on current booting games -constexpr size_t MAX_CODE_SIZE = 0x10000; - class MacroJITx64 final : public MacroEngine { public: explicit MacroJITx64(Engines::Maxwell3D& maxwell3d_); @@ -32,67 +24,4 @@ private: Engines::Maxwell3D& maxwell3d; }; -class MacroJITx64Impl : public Xbyak::CodeGenerator, public CachedMacro { -public: - explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_); - ~MacroJITx64Impl(); - - void Execute(const std::vector& parameters, u32 method) override; - - void Compile_ALU(Macro::Opcode opcode); - void Compile_AddImmediate(Macro::Opcode opcode); - void Compile_ExtractInsert(Macro::Opcode opcode); - void Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode); - void Compile_ExtractShiftLeftRegister(Macro::Opcode opcode); - void Compile_Read(Macro::Opcode opcode); - void Compile_Branch(Macro::Opcode opcode); - -private: - void Optimizer_ScanFlags(); - - void Compile(); - bool Compile_NextInstruction(); - - Xbyak::Reg32 Compile_FetchParameter(); - Xbyak::Reg32 Compile_GetRegister(u32 index, Xbyak::Reg32 dst); - - void Compile_ProcessResult(Macro::ResultOperation operation, u32 reg); - void Compile_Send(Xbyak::Reg32 value); - - Macro::Opcode GetOpCode() const; - std::bitset<32> PersistentCallerSavedRegs() const; - - struct JITState { - Engines::Maxwell3D* maxwell3d{}; - std::array registers{}; - u32 carry_flag{}; - }; - static_assert(offsetof(JITState, maxwell3d) == 0, "Maxwell3D is not at 0x0"); - using ProgramType = void (*)(JITState*, const u32*); - - struct OptimizerState { - bool can_skip_carry{}; - bool has_delayed_pc{}; - bool zero_reg_skip{}; - bool skip_dummy_addimmediate{}; - bool optimize_for_method_move{}; - bool enable_asserts{}; - }; - OptimizerState optimizer{}; - - std::optional next_opcode{}; - ProgramType program{nullptr}; - - std::array labels; - std::array delay_skip; - Xbyak::Label end_of_code{}; - - bool is_delay_slot{}; - u32 pc{}; - std::optional delayed_pc; - - const std::vector& code; - Engines::Maxwell3D& maxwell3d; -}; - } // namespace Tegra diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 5143633ad..d6e1c4cd2 100755 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -416,6 +416,8 @@ void Config::ReadControlValues() { ReadGlobalSetting(Settings::values.enable_accurate_vibrations); ReadGlobalSetting(Settings::values.motion_enabled); + ReadBasicSetting(Settings::values.controller_navigation); + qt_config->endGroup(); } @@ -1035,6 +1037,7 @@ void Config::SaveControlValues() { WriteBasicSetting(Settings::values.keyboard_enabled); WriteBasicSetting(Settings::values.emulate_analog_keyboard); WriteBasicSetting(Settings::values.mouse_panning_sensitivity); + WriteBasicSetting(Settings::values.controller_navigation); WriteBasicSetting(Settings::values.tas_enable); WriteBasicSetting(Settings::values.tas_loop); diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 78f7ae799..8fd1f4a38 100755 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -135,6 +135,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() { Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); Settings::values.enable_raw_input = ui->enable_raw_input->isChecked(); Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked(); + Settings::values.controller_navigation = ui->controller_navigation->isChecked(); Settings::values.enable_ring_controller = ui->enable_ring_controller->isChecked(); } @@ -167,6 +168,7 @@ void ConfigureInputAdvanced::LoadConfiguration() { ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue()); ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue()); + ui->controller_navigation->setChecked(Settings::values.controller_navigation.GetValue()); ui->enable_ring_controller->setChecked(Settings::values.enable_ring_controller.GetValue()); UpdateUIEnabled(); diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index cf3888eaa..14403cb10 100755 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2669,6 +2669,19 @@ + + + + 0 + 23 + + + + Controller navigation + + + + @@ -2681,7 +2694,7 @@ - + Mouse sensitivity @@ -2703,14 +2716,14 @@ - + Motion / Touch - + Configure diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index b2af83eed..d06b5ae12 100755 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -403,10 +403,22 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i connect(button, &QPushButton::customContextMenuRequested, [=, this](const QPoint& menu_location) { QMenu context_menu; + Common::ParamPackage param = emulated_controller->GetMotionParam(motion_id); context_menu.addAction(tr("Clear"), [&] { emulated_controller->SetMotionParam(motion_id, {}); motion_map[motion_id]->setText(tr("[not set]")); }); + if (param.Has("motion")) { + context_menu.addAction(tr("Set gyro threshold"), [&] { + const int gyro_threshold = + static_cast(param.Get("threshold", 0.007f) * 1000.0f); + const int new_threshold = QInputDialog::getInt( + this, tr("Set threshold"), tr("Choose a value between 0% and 100%"), + gyro_threshold, 0, 100); + param.Set("threshold", new_threshold / 1000.0f); + emulated_controller->SetMotionParam(motion_id, param); + }); + } context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location)); }); } diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index d96497c4e..6ed9611c7 100755 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.cpp @@ -190,6 +190,9 @@ void ControllerShortcut::ControllerUpdateEvent(Core::HID::ControllerTriggerType if (type != Core::HID::ControllerTriggerType::Button) { return; } + if (!Settings::values.controller_navigation) { + return; + } if (button_sequence.npad.raw == Core::HID::NpadButton::None && button_sequence.capture.raw == 0 && button_sequence.home.raw == 0) { return; diff --git a/src/yuzu/util/controller_navigation.cpp b/src/yuzu/util/controller_navigation.cpp index 86fb28b9f..c2b13123d 100755 --- a/src/yuzu/util/controller_navigation.cpp +++ b/src/yuzu/util/controller_navigation.cpp @@ -40,6 +40,9 @@ void ControllerNavigation::TriggerButton(Settings::NativeButton::Values native_b void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) { std::lock_guard lock{mutex}; + if (!Settings::values.controller_navigation) { + return; + } if (type == Core::HID::ControllerTriggerType::Button) { ControllerUpdateButton(); return;