early-access version 3344
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| yuzu emulator early access | ||||
| ============= | ||||
|  | ||||
| This is the source code for early-access 3343. | ||||
| This is the source code for early-access 3344. | ||||
|  | ||||
| ## Legal Notice | ||||
|  | ||||
|   | ||||
| @@ -130,6 +130,8 @@ struct ButtonStatus { | ||||
|     bool inverted{}; | ||||
|     // Press once to activate, press again to release | ||||
|     bool toggle{}; | ||||
|     // Spams the button when active | ||||
|     bool turbo{}; | ||||
|     // Internal lock for the toggle status | ||||
|     bool locked{}; | ||||
| }; | ||||
|   | ||||
| @@ -687,6 +687,7 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback | ||||
|     } | ||||
|  | ||||
|     current_status.toggle = new_status.toggle; | ||||
|     current_status.turbo = new_status.turbo; | ||||
|     current_status.uuid = uuid; | ||||
|  | ||||
|     // Update button status with current | ||||
| @@ -1548,7 +1549,7 @@ NpadButtonState EmulatedController::GetNpadButtons() const { | ||||
|     if (is_configuring) { | ||||
|         return {}; | ||||
|     } | ||||
|     return controller.npad_button_state; | ||||
|     return {controller.npad_button_state.raw & GetTurboButtonMask()}; | ||||
| } | ||||
|  | ||||
| DebugPadButton EmulatedController::GetDebugPadButtons() const { | ||||
| @@ -1656,4 +1657,74 @@ void EmulatedController::DeleteCallback(int key) { | ||||
|     } | ||||
|     callback_list.erase(iterator); | ||||
| } | ||||
|  | ||||
| void EmulatedController::TurboButtonUpdate() { | ||||
|     turbo_button_state = !turbo_button_state; | ||||
| } | ||||
|  | ||||
| NpadButton EmulatedController::GetTurboButtonMask() const { | ||||
|     // Apply no mask when disabled | ||||
|     if (!turbo_button_state) { | ||||
|         return {NpadButton::All}; | ||||
|     } | ||||
|  | ||||
|     NpadButtonState button_mask{}; | ||||
|     for (std::size_t index = 0; index < controller.button_values.size(); ++index) { | ||||
|         if (!controller.button_values[index].turbo) { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         switch (index) { | ||||
|         case Settings::NativeButton::A: | ||||
|             button_mask.a.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::B: | ||||
|             button_mask.b.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::X: | ||||
|             button_mask.x.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::Y: | ||||
|             button_mask.y.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::L: | ||||
|             button_mask.l.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::R: | ||||
|             button_mask.r.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::ZL: | ||||
|             button_mask.zl.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::ZR: | ||||
|             button_mask.zr.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::DLeft: | ||||
|             button_mask.left.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::DUp: | ||||
|             button_mask.up.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::DRight: | ||||
|             button_mask.right.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::DDown: | ||||
|             button_mask.down.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::SL: | ||||
|             button_mask.left_sl.Assign(1); | ||||
|             button_mask.right_sl.Assign(1); | ||||
|             break; | ||||
|         case Settings::NativeButton::SR: | ||||
|             button_mask.left_sr.Assign(1); | ||||
|             button_mask.right_sr.Assign(1); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return static_cast<NpadButton>(~button_mask.raw); | ||||
| } | ||||
|  | ||||
| } // namespace Core::HID | ||||
|   | ||||
| @@ -411,6 +411,9 @@ public: | ||||
|      */ | ||||
|     void DeleteCallback(int key); | ||||
|  | ||||
|     /// Swaps the state of the turbo buttons | ||||
|     void TurboButtonUpdate(); | ||||
|  | ||||
| private: | ||||
|     /// creates input devices from params | ||||
|     void LoadDevices(); | ||||
| @@ -511,6 +514,8 @@ private: | ||||
|      */ | ||||
|     void TriggerOnChange(ControllerTriggerType type, bool is_service_update); | ||||
|  | ||||
|     NpadButton GetTurboButtonMask() const; | ||||
|  | ||||
|     const NpadIdType npad_id_type; | ||||
|     NpadStyleIndex npad_type{NpadStyleIndex::None}; | ||||
|     NpadStyleIndex original_npad_type{NpadStyleIndex::None}; | ||||
| @@ -520,6 +525,7 @@ private: | ||||
|     bool system_buttons_enabled{true}; | ||||
|     f32 motion_sensitivity{0.01f}; | ||||
|     bool force_update_motion{false}; | ||||
|     bool turbo_button_state{false}; | ||||
|  | ||||
|     // Temporary values to avoid doing changes while the controller is in configuring mode | ||||
|     NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; | ||||
|   | ||||
| @@ -428,6 +428,9 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // This function is unique to yuzu for the turbo buttons to work properly | ||||
|     controller.device->TurboButtonUpdate(); | ||||
|  | ||||
|     auto& pad_entry = controller.npad_pad_state; | ||||
|     auto& trigger_entry = controller.npad_trigger_state; | ||||
|     const auto button_state = controller.device->GetNpadButtons(); | ||||
|   | ||||
| @@ -16,10 +16,10 @@ public: | ||||
|  | ||||
| class InputFromButton final : public Common::Input::InputDevice { | ||||
| public: | ||||
|     explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, | ||||
|                              InputEngine* input_engine_) | ||||
|         : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), | ||||
|           input_engine(input_engine_) { | ||||
|     explicit InputFromButton(PadIdentifier identifier_, int button_, bool turbo_, bool toggle_, | ||||
|                              bool inverted_, InputEngine* input_engine_) | ||||
|         : identifier(identifier_), button(button_), turbo(turbo_), toggle(toggle_), | ||||
|           inverted(inverted_), input_engine(input_engine_) { | ||||
|         UpdateCallback engine_callback{[this]() { OnChange(); }}; | ||||
|         const InputIdentifier input_identifier{ | ||||
|             .identifier = identifier, | ||||
| @@ -40,6 +40,7 @@ public: | ||||
|             .value = input_engine->GetButton(identifier, button), | ||||
|             .inverted = inverted, | ||||
|             .toggle = toggle, | ||||
|             .turbo = turbo, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @@ -68,6 +69,7 @@ public: | ||||
| private: | ||||
|     const PadIdentifier identifier; | ||||
|     const int button; | ||||
|     const bool turbo; | ||||
|     const bool toggle; | ||||
|     const bool inverted; | ||||
|     int callback_key; | ||||
| @@ -77,10 +79,10 @@ private: | ||||
|  | ||||
| class InputFromHatButton final : public Common::Input::InputDevice { | ||||
| public: | ||||
|     explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_, | ||||
|                                 bool inverted_, InputEngine* input_engine_) | ||||
|         : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_), | ||||
|           inverted(inverted_), input_engine(input_engine_) { | ||||
|     explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool turbo_, | ||||
|                                 bool toggle_, bool inverted_, InputEngine* input_engine_) | ||||
|         : identifier(identifier_), button(button_), direction(direction_), turbo(turbo_), | ||||
|           toggle(toggle_), inverted(inverted_), input_engine(input_engine_) { | ||||
|         UpdateCallback engine_callback{[this]() { OnChange(); }}; | ||||
|         const InputIdentifier input_identifier{ | ||||
|             .identifier = identifier, | ||||
| @@ -101,6 +103,7 @@ public: | ||||
|             .value = input_engine->GetHatButton(identifier, button, direction), | ||||
|             .inverted = inverted, | ||||
|             .toggle = toggle, | ||||
|             .turbo = turbo, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @@ -130,6 +133,7 @@ private: | ||||
|     const PadIdentifier identifier; | ||||
|     const int button; | ||||
|     const u8 direction; | ||||
|     const bool turbo; | ||||
|     const bool toggle; | ||||
|     const bool inverted; | ||||
|     int callback_key; | ||||
| @@ -853,14 +857,15 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice( | ||||
|     const auto keyboard_key = params.Get("code", 0); | ||||
|     const auto toggle = params.Get("toggle", false) != 0; | ||||
|     const auto inverted = params.Get("inverted", false) != 0; | ||||
|     const auto turbo = params.Get("turbo", false) != 0; | ||||
|     input_engine->PreSetController(identifier); | ||||
|     input_engine->PreSetButton(identifier, button_id); | ||||
|     input_engine->PreSetButton(identifier, keyboard_key); | ||||
|     if (keyboard_key != 0) { | ||||
|         return std::make_unique<InputFromButton>(identifier, keyboard_key, toggle, inverted, | ||||
|         return std::make_unique<InputFromButton>(identifier, keyboard_key, turbo, toggle, inverted, | ||||
|                                                  input_engine.get()); | ||||
|     } | ||||
|     return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted, | ||||
|     return std::make_unique<InputFromButton>(identifier, button_id, turbo, toggle, inverted, | ||||
|                                              input_engine.get()); | ||||
| } | ||||
|  | ||||
| @@ -876,11 +881,12 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice( | ||||
|     const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); | ||||
|     const auto toggle = params.Get("toggle", false) != 0; | ||||
|     const auto inverted = params.Get("inverted", false) != 0; | ||||
|     const auto turbo = params.Get("turbo", false) != 0; | ||||
|  | ||||
|     input_engine->PreSetController(identifier); | ||||
|     input_engine->PreSetHatButton(identifier, button_id); | ||||
|     return std::make_unique<InputFromHatButton>(identifier, button_id, direction, toggle, inverted, | ||||
|                                                 input_engine.get()); | ||||
|     return std::make_unique<InputFromHatButton>(identifier, button_id, direction, turbo, toggle, | ||||
|                                                 inverted, input_engine.get()); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( | ||||
|   | ||||
| @@ -355,21 +355,21 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { | ||||
| u32 GetTextureHandle(Environment& env, const ConstBufferAddr& cbuf) { | ||||
|     const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; | ||||
|     const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; | ||||
|     const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left}; | ||||
|     const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset) | ||||
|                       << cbuf.secondary_shift_left}; | ||||
|     return env.ReadTextureType(lhs_raw | rhs_raw); | ||||
|     return lhs_raw | rhs_raw; | ||||
| } | ||||
|  | ||||
| TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { | ||||
|     return env.ReadTextureType(GetTextureHandle(env, cbuf)); | ||||
| } | ||||
|  | ||||
| TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) { | ||||
|     const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; | ||||
|     const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; | ||||
|     const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)}; | ||||
|     const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)}; | ||||
|     return env.ReadTexturePixelFormat(lhs_raw | rhs_raw); | ||||
|     return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); | ||||
| } | ||||
|  | ||||
| class Descriptors { | ||||
| @@ -386,8 +386,10 @@ public: | ||||
|         return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { | ||||
|             return desc.cbuf_index == existing.cbuf_index && | ||||
|                    desc.cbuf_offset == existing.cbuf_offset && | ||||
|                    desc.shift_left == existing.shift_left && | ||||
|                    desc.secondary_cbuf_index == existing.secondary_cbuf_index && | ||||
|                    desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && | ||||
|                    desc.secondary_shift_left == existing.secondary_shift_left && | ||||
|                    desc.count == existing.count && desc.size_shift == existing.size_shift && | ||||
|                    desc.has_secondary == existing.has_secondary; | ||||
|         }); | ||||
| @@ -405,15 +407,20 @@ public: | ||||
|     } | ||||
|  | ||||
|     u32 Add(const TextureDescriptor& desc) { | ||||
|         return Add(texture_descriptors, desc, [&desc](const auto& existing) { | ||||
|         const u32 index{Add(texture_descriptors, desc, [&desc](const auto& existing) { | ||||
|             return desc.type == existing.type && desc.is_depth == existing.is_depth && | ||||
|                    desc.has_secondary == existing.has_secondary && | ||||
|                    desc.cbuf_index == existing.cbuf_index && | ||||
|                    desc.cbuf_offset == existing.cbuf_offset && | ||||
|                    desc.shift_left == existing.shift_left && | ||||
|                    desc.secondary_cbuf_index == existing.secondary_cbuf_index && | ||||
|                    desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && | ||||
|                    desc.secondary_shift_left == existing.secondary_shift_left && | ||||
|                    desc.count == existing.count && desc.size_shift == existing.size_shift; | ||||
|         }); | ||||
|         })}; | ||||
|         // TODO: Read this from TIC | ||||
|         texture_descriptors[index].is_multisample |= desc.is_multisample; | ||||
|         return index; | ||||
|     } | ||||
|  | ||||
|     u32 Add(const ImageDescriptor& desc) { | ||||
|   | ||||
| @@ -182,12 +182,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | ||||
|     const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); | ||||
|     const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); | ||||
|     const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : ""); | ||||
|     const QString turbo = QString::fromStdString(param.Get("turbo", false) ? "$" : ""); | ||||
|     const auto common_button_name = input_subsystem->GetButtonName(param); | ||||
|  | ||||
|     // Retrieve the names from Qt | ||||
|     if (param.Get("engine", "") == "keyboard") { | ||||
|         const QString button_str = GetKeyName(param.Get("code", 0)); | ||||
|         return QObject::tr("%1%2%3").arg(toggle, inverted, button_str); | ||||
|         return QObject::tr("%1%2%3%4").arg(turbo, toggle, inverted, button_str); | ||||
|     } | ||||
|  | ||||
|     if (common_button_name == Common::Input::ButtonNames::Invalid) { | ||||
| @@ -201,7 +202,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | ||||
|     if (common_button_name == Common::Input::ButtonNames::Value) { | ||||
|         if (param.Has("hat")) { | ||||
|             const QString hat = GetDirectionName(param.Get("direction", "")); | ||||
|             return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); | ||||
|             return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, hat); | ||||
|         } | ||||
|         if (param.Has("axis")) { | ||||
|             const QString axis = QString::fromStdString(param.Get("axis", "")); | ||||
| @@ -219,13 +220,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | ||||
|         } | ||||
|         if (param.Has("button")) { | ||||
|             const QString button = QString::fromStdString(param.Get("button", "")); | ||||
|             return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); | ||||
|             return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     QString button_name = GetButtonName(common_button_name); | ||||
|     if (param.Has("hat")) { | ||||
|         return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); | ||||
|         return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name); | ||||
|     } | ||||
|     if (param.Has("axis")) { | ||||
|         return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); | ||||
| @@ -234,7 +235,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | ||||
|         return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); | ||||
|     } | ||||
|     if (param.Has("button")) { | ||||
|         return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); | ||||
|         return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button_name); | ||||
|     } | ||||
|  | ||||
|     return QObject::tr("[unknown]"); | ||||
| @@ -395,6 +396,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|                             button_map[button_id]->setText(ButtonToText(param)); | ||||
|                             emulated_controller->SetButtonParam(button_id, param); | ||||
|                         }); | ||||
|                         context_menu.addAction(tr("Turbo button"), [&] { | ||||
|                             const bool turbo_value = !param.Get("turbo", false); | ||||
|                             param.Set("turbo", turbo_value); | ||||
|                             button_map[button_id]->setText(ButtonToText(param)); | ||||
|                             emulated_controller->SetButtonParam(button_id, param); | ||||
|                         }); | ||||
|                     } | ||||
|                     if (param.Has("axis")) { | ||||
|                         context_menu.addAction(tr("Invert axis"), [&] { | ||||
|   | ||||
| @@ -58,13 +58,16 @@ std::vector<std::string> InputProfiles::GetInputProfileNames() { | ||||
|     std::vector<std::string> profile_names; | ||||
|     profile_names.reserve(map_profiles.size()); | ||||
|  | ||||
|     for (const auto& [profile_name, config] : map_profiles) { | ||||
|     auto it = map_profiles.cbegin(); | ||||
|     while (it != map_profiles.cend()) { | ||||
|         const auto& [profile_name, config] = *it; | ||||
|         if (!ProfileExistsInFilesystem(profile_name)) { | ||||
|             DeleteProfile(profile_name); | ||||
|             it = map_profiles.erase(it); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         profile_names.push_back(profile_name); | ||||
|         ++it; | ||||
|     } | ||||
|  | ||||
|     std::stable_sort(profile_names.begin(), profile_names.end()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user