diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/init/init_slab_setup.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_device_address_space.cpp | 150 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_device_address_space.h | 60 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_types.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 2 | ||||
| -rw-r--r-- | src/input_common/helpers/stick_from_buttons.cpp | 45 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/value.h | 11 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.cpp | 16 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.h | 2 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.ui | 7 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 3 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 13 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 48 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.h | 10 | 
16 files changed, 310 insertions, 79 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 3eee1cfbe..112c61b80 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -195,6 +195,8 @@ add_library(core STATIC      hle/kernel/k_condition_variable.cpp      hle/kernel/k_condition_variable.h      hle/kernel/k_debug.h +    hle/kernel/k_device_address_space.cpp +    hle/kernel/k_device_address_space.h      hle/kernel/k_dynamic_page_manager.h      hle/kernel/k_dynamic_resource_manager.h      hle/kernel/k_dynamic_slab_heap.h diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index 7b363eb1e..571acf4b2 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -11,6 +11,7 @@  #include "core/hle/kernel/init/init_slab_setup.h"  #include "core/hle/kernel/k_code_memory.h"  #include "core/hle/kernel/k_debug.h" +#include "core/hle/kernel/k_device_address_space.h"  #include "core/hle/kernel/k_event.h"  #include "core/hle/kernel/k_event_info.h"  #include "core/hle/kernel/k_memory_layout.h" @@ -43,6 +44,7 @@ namespace Kernel::Init {      HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__)                     \      HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__)                         \      HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__)                                 \ +    HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ##__VA_ARGS__)                 \      HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__)                                       \      HANDLER(KThreadLocalPage,                                                                      \              (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8),             \ diff --git a/src/core/hle/kernel/k_device_address_space.cpp b/src/core/hle/kernel/k_device_address_space.cpp new file mode 100644 index 000000000..27659ea3b --- /dev/null +++ b/src/core/hle/kernel/k_device_address_space.cpp @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "core/core.h" +#include "core/hle/kernel/k_device_address_space.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/svc_results.h" + +namespace Kernel { + +KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel_) +    : KAutoObjectWithSlabHeapAndContainer(kernel_), m_lock(kernel_), m_is_initialized(false) {} +KDeviceAddressSpace::~KDeviceAddressSpace() = default; + +void KDeviceAddressSpace::Initialize() { +    // This just forwards to the device page table manager. +    // KDevicePageTable::Initialize(); +} + +// Member functions. +Result KDeviceAddressSpace::Initialize(u64 address, u64 size) { +    // Initialize the device page table. +    // R_TRY(m_table.Initialize(address, size)); + +    // Set member variables. +    m_space_address = address; +    m_space_size = size; +    m_is_initialized = true; + +    R_SUCCEED(); +} + +void KDeviceAddressSpace::Finalize() { +    // Finalize the table. +    // m_table.Finalize(); +} + +Result KDeviceAddressSpace::Attach(Svc::DeviceName device_name) { +    // Lock the address space. +    KScopedLightLock lk(m_lock); + +    // Attach. +    // R_RETURN(m_table.Attach(device_name, m_space_address, m_space_size)); +    R_SUCCEED(); +} + +Result KDeviceAddressSpace::Detach(Svc::DeviceName device_name) { +    // Lock the address space. +    KScopedLightLock lk(m_lock); + +    // Detach. +    // R_RETURN(m_table.Detach(device_name)); +    R_SUCCEED(); +} + +Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, size_t size, +                                u64 device_address, u32 option, bool is_aligned) { +    // Check that the address falls within the space. +    R_UNLESS((m_space_address <= device_address && +              device_address + size - 1 <= m_space_address + m_space_size - 1), +             ResultInvalidCurrentMemory); + +    // Decode the option. +    const Svc::MapDeviceAddressSpaceOption option_pack{option}; +    const auto device_perm = option_pack.permission.Value(); +    const auto flags = option_pack.flags.Value(); +    const auto reserved = option_pack.reserved.Value(); + +    // Validate the option. +    // TODO: It is likely that this check for flags == none is only on NX board. +    R_UNLESS(flags == Svc::MapDeviceAddressSpaceFlag::None, ResultInvalidEnumValue); +    R_UNLESS(reserved == 0, ResultInvalidEnumValue); + +    // Lock the address space. +    KScopedLightLock lk(m_lock); + +    // Lock the page table to prevent concurrent device mapping operations. +    // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock(); + +    // Lock the pages. +    bool is_io{}; +    R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size, +                                                   ConvertToKMemoryPermission(device_perm), +                                                   is_aligned, true)); + +    // Ensure that if we fail, we don't keep unmapped pages locked. +    ON_RESULT_FAILURE { +        ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess); +    }; + +    // Check that the io status is allowable. +    if (is_io) { +        R_UNLESS(static_cast<u32>(flags & Svc::MapDeviceAddressSpaceFlag::NotIoRegister) == 0, +                 ResultInvalidCombination); +    } + +    // Map the pages. +    { +        // Perform the mapping. +        // R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, +        //                   is_aligned, is_io)); + +        // Ensure that we unmap the pages if we fail to update the protections. +        // NOTE: Nintendo does not check the result of this unmap call. +        // ON_RESULT_FAILURE { m_table.Unmap(device_address, size); }; + +        // Update the protections in accordance with how much we mapped. +        // R_TRY(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size)); +    } + +    // We succeeded. +    R_SUCCEED(); +} + +Result KDeviceAddressSpace::Unmap(KPageTable* page_table, VAddr process_address, size_t size, +                                  u64 device_address) { +    // Check that the address falls within the space. +    R_UNLESS((m_space_address <= device_address && +              device_address + size - 1 <= m_space_address + m_space_size - 1), +             ResultInvalidCurrentMemory); + +    // Lock the address space. +    KScopedLightLock lk(m_lock); + +    // Lock the page table to prevent concurrent device mapping operations. +    // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock(); + +    // Lock the pages. +    R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true)); + +    // Unmap the pages. +    { +        // If we fail to unmap, we want to do a partial unlock. +        // ON_RESULT_FAILURE { +        //     ASSERT(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size) == +        //            ResultSuccess); +        // }; + +        // Perform the unmap. +        // R_TRY(m_table.Unmap(page_table, process_address, size, device_address)); +    } + +    // Unlock the pages. +    ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess); + +    R_SUCCEED(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h new file mode 100644 index 000000000..4709df995 --- /dev/null +++ b/src/core/hle/kernel/k_device_address_space.h @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <string> + +#include "common/common_types.h" +#include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/slab_helpers.h" +#include "core/hle/result.h" + +namespace Kernel { + +class KDeviceAddressSpace final +    : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> { +    KERNEL_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject); + +public: +    explicit KDeviceAddressSpace(KernelCore& kernel); +    ~KDeviceAddressSpace(); + +    Result Initialize(u64 address, u64 size); +    void Finalize(); + +    bool IsInitialized() const { +        return m_is_initialized; +    } +    static void PostDestroy(uintptr_t arg) {} + +    Result Attach(Svc::DeviceName device_name); +    Result Detach(Svc::DeviceName device_name); + +    Result MapByForce(KPageTable* page_table, VAddr process_address, size_t size, +                      u64 device_address, u32 option) { +        R_RETURN(this->Map(page_table, process_address, size, device_address, option, false)); +    } + +    Result MapAligned(KPageTable* page_table, VAddr process_address, size_t size, +                      u64 device_address, u32 option) { +        R_RETURN(this->Map(page_table, process_address, size, device_address, option, true)); +    } + +    Result Unmap(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address); + +    static void Initialize(); + +private: +    Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address, +               u32 option, bool is_aligned); + +private: +    KLightLock m_lock; +    // KDevicePageTable m_table; +    u64 m_space_address{}; +    u64 m_space_size{}; +    bool m_is_initialized{}; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 8d22f8d2c..5f52e1e95 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -35,6 +35,7 @@ class GlobalSchedulerContext;  class KAutoObjectWithListContainer;  class KClientSession;  class KDebug; +class KDeviceAddressSpace;  class KDynamicPageManager;  class KEvent;  class KEventInfo; @@ -359,6 +360,8 @@ public:              return slab_heap_container->transfer_memory;          } else if constexpr (std::is_same_v<T, KCodeMemory>) {              return slab_heap_container->code_memory; +        } else if constexpr (std::is_same_v<T, KDeviceAddressSpace>) { +            return slab_heap_container->device_address_space;          } else if constexpr (std::is_same_v<T, KPageBuffer>) {              return slab_heap_container->page_buffer;          } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { @@ -431,6 +434,7 @@ private:          KSlabHeap<KThread> thread;          KSlabHeap<KTransferMemory> transfer_memory;          KSlabHeap<KCodeMemory> code_memory; +        KSlabHeap<KDeviceAddressSpace> device_address_space;          KSlabHeap<KPageBuffer> page_buffer;          KSlabHeap<KThreadLocalPage> thread_local_page;          KSlabHeap<KSessionRequest> session_request; diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 9c2f9998a..e90c35601 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -5,6 +5,7 @@  #include <bitset> +#include "common/bit_field.h"  #include "common/common_funcs.h"  #include "common/common_types.h" @@ -498,6 +499,19 @@ enum class MemoryMapping : u32 {      Memory = 2,  }; +enum class MapDeviceAddressSpaceFlag : u32 { +    None = (0U << 0), +    NotIoRegister = (1U << 0), +}; +DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag); + +union MapDeviceAddressSpaceOption { +    u32 raw; +    BitField<0, 16, MemoryPermission> permission; +    BitField<16, 1, MapDeviceAddressSpaceFlag> flags; +    BitField<17, 15, u32> reserved; +}; +  enum class KernelDebugType : u32 {      Thread = 0,      ThreadCallStack = 1, diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index cab44bf9c..447d624e1 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -1083,7 +1083,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {  }  void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { -    const auto raw = ctx.ReadBuffer(); +    const auto raw = ctx.ReadBufferCopy();      auto log = Common::StringFromFixedZeroTerminatedBuffer(          reinterpret_cast<const char*>(raw.data()), raw.size()); diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 096c23b07..a6be6dac1 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -15,6 +15,9 @@ public:      // do not play nicely with the theoretical maximum range.      // Using a value one lower from the maximum emulates real stick behavior.      static constexpr float MAX_RANGE = 32766.0f / 32767.0f; +    static constexpr float TAU = Common::PI * 2.0f; +    // Use wider angle to ease the transition. +    static constexpr float APERTURE = TAU * 0.15f;      using Button = std::unique_ptr<Common::Input::InputDevice>; @@ -61,30 +64,23 @@ public:      }      bool IsAngleGreater(float old_angle, float new_angle) const { -        constexpr float TAU = Common::PI * 2.0f; -        // Use wider angle to ease the transition. -        constexpr float aperture = TAU * 0.15f; -        const float top_limit = new_angle + aperture; +        const float top_limit = new_angle + APERTURE;          return (old_angle > new_angle && old_angle <= top_limit) ||                 (old_angle + TAU > new_angle && old_angle + TAU <= top_limit);      }      bool IsAngleSmaller(float old_angle, float new_angle) const { -        constexpr float TAU = Common::PI * 2.0f; -        // Use wider angle to ease the transition. -        constexpr float aperture = TAU * 0.15f; -        const float bottom_limit = new_angle - aperture; +        const float bottom_limit = new_angle - APERTURE;          return (old_angle >= bottom_limit && old_angle < new_angle) ||                 (old_angle - TAU >= bottom_limit && old_angle - TAU < new_angle);      }      float GetAngle(std::chrono::time_point<std::chrono::steady_clock> now) const { -        constexpr float TAU = Common::PI * 2.0f;          float new_angle = angle;          auto time_difference = static_cast<float>( -            std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); -        time_difference /= 1000.0f * 1000.0f; +            std::chrono::duration_cast<std::chrono::milliseconds>(now - last_update).count()); +        time_difference /= 1000.0f;          if (time_difference > 0.5f) {              time_difference = 0.5f;          } @@ -201,8 +197,6 @@ public:      }      void UpdateStatus() { -        const float coef = modifier_status.value ? modifier_scale : MAX_RANGE; -          bool r = right_status;          bool l = left_status;          bool u = up_status; @@ -220,7 +214,7 @@ public:          // Move if a key is pressed          if (r || l || u || d) { -            amplitude = coef; +            amplitude = modifier_status.value ? modifier_scale : MAX_RANGE;          } else {              amplitude = 0;          } @@ -274,30 +268,17 @@ public:          Common::Input::StickStatus status{};          status.x.properties = properties;          status.y.properties = properties; +          if (Settings::values.emulate_analog_keyboard) {              const auto now = std::chrono::steady_clock::now(); -            float angle_ = GetAngle(now); +            const float angle_ = GetAngle(now);              status.x.raw_value = std::cos(angle_) * amplitude;              status.y.raw_value = std::sin(angle_) * amplitude;              return status;          } -        constexpr float SQRT_HALF = 0.707106781f; -        int x = 0, y = 0; -        if (right_status) { -            ++x; -        } -        if (left_status) { -            --x; -        } -        if (up_status) { -            ++y; -        } -        if (down_status) { -            --y; -        } -        const float coef = modifier_status.value ? modifier_scale : MAX_RANGE; -        status.x.raw_value = static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF); -        status.y.raw_value = static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF); + +        status.x.raw_value = std::cos(goal_angle) * amplitude; +        status.y.raw_value = std::sin(goal_angle) * amplitude;          return status;      } diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 22e89dd1b..c27546b0e 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -43,7 +43,6 @@ public:      explicit Value(u8 value) noexcept;      explicit Value(u16 value) noexcept;      explicit Value(u32 value) noexcept; -    explicit Value(s32 value) noexcept;      explicit Value(f32 value) noexcept;      explicit Value(u64 value) noexcept;      explicit Value(f64 value) noexcept; @@ -66,7 +65,6 @@ public:      [[nodiscard]] u8 U8() const;      [[nodiscard]] u16 U16() const;      [[nodiscard]] u32 U32() const; -    [[nodiscard]] s32 S32() const;      [[nodiscard]] f32 F32() const;      [[nodiscard]] u64 U64() const;      [[nodiscard]] f64 F64() const; @@ -86,7 +84,6 @@ private:          u8 imm_u8;          u16 imm_u16;          u32 imm_u32; -        s32 imm_s32;          f32 imm_f32;          u64 imm_u64;          f64 imm_f64; @@ -378,14 +375,6 @@ inline u32 Value::U32() const {      return imm_u32;  } -inline s32 Value::S32() const { -    if (IsIdentity()) { -        return inst->Arg(0).S32(); -    } -    DEBUG_ASSERT(type == Type::S32); -    return imm_s32; -} -  inline f32 Value::F32() const {      if (IsIdentity()) {          return inst->Arg(0).F32(); diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 08c275696..6c93e3511 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp @@ -77,6 +77,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,      // UI Buttons      connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby);      connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned); +    connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty);      connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull);      connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);      connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); @@ -329,6 +330,16 @@ bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s          return true;      } +    // filter by empty rooms +    if (filter_empty) { +        QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); +        int player_count = +            sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size(); +        if (player_count == 0) { +            return false; +        } +    } +      // filter by filled rooms      if (filter_full) {          QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); @@ -399,6 +410,11 @@ void LobbyFilterProxyModel::SetFilterOwned(bool filter) {      invalidate();  } +void LobbyFilterProxyModel::SetFilterEmpty(bool filter) { +    filter_empty = filter; +    invalidate(); +} +  void LobbyFilterProxyModel::SetFilterFull(bool filter) {      filter_full = filter;      invalidate(); diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h index 300dad13e..2674ae7c3 100644 --- a/src/yuzu/multiplayer/lobby.h +++ b/src/yuzu/multiplayer/lobby.h @@ -130,12 +130,14 @@ public:  public slots:      void SetFilterOwned(bool); +    void SetFilterEmpty(bool);      void SetFilterFull(bool);      void SetFilterSearch(const QString&);  private:      QStandardItemModel* game_list;      bool filter_owned = false; +    bool filter_empty = false;      bool filter_full = false;      QString filter_search;  }; diff --git a/src/yuzu/multiplayer/lobby.ui b/src/yuzu/multiplayer/lobby.ui index 4c9901c9a..0ef0ef762 100644 --- a/src/yuzu/multiplayer/lobby.ui +++ b/src/yuzu/multiplayer/lobby.ui @@ -78,6 +78,13 @@            </widget>           </item>           <item> +          <widget class="QCheckBox" name="hide_empty"> +           <property name="text"> +            <string>Hide Empty Rooms</string> +           </property> +          </widget> +         </item> +         <item>            <widget class="QCheckBox" name="hide_full">             <property name="text">              <string>Hide Full Rooms</string> diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 527017282..9c34cdc6e 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -176,6 +176,9 @@ void Config::ReadValues() {              Settings::values.debug_pad_analogs[i] = default_param;      } +    ReadSetting("ControlsGeneral", Settings::values.enable_raw_input); +    ReadSetting("ControlsGeneral", Settings::values.enable_joycon_driver); +    ReadSetting("ControlsGeneral", Settings::values.emulate_analog_keyboard);      ReadSetting("ControlsGeneral", Settings::values.vibration_enabled);      ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations);      ReadSetting("ControlsGeneral", Settings::values.motion_enabled); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 67d230462..3f3651dbe 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -14,6 +14,7 @@ const char* sdl2_config_file =  # Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values  # Indicates if this player should be connected at boot +# 0 (default): Disabled, 1: Enabled  connected=  # for button input, the following devices are available: @@ -94,6 +95,18 @@ motionright=  # 0 (default): Disabled, 1: Enabled  debug_pad_enabled = +# Enable sdl raw input. Allows to configure up to 8 xinput controllers. +# 0 (default): Disabled, 1: Enabled +enable_raw_input = + +# Enable yuzu joycon driver instead of SDL drive. +# 0: Disabled, 1 (default): Enabled +enable_joycon_driver = + +# Emulates an analog input from buttons. Allowing to dial any angle. +# 0 (default): Disabled, 1: Enabled +emulate_analog_keyboard = +  # Whether to enable or disable vibration  # 0: Disabled, 1 (default): Enabled  vibration_enabled= diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 31f28a507..5450b8c38 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -18,11 +18,11 @@  EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_)      : input_subsystem{input_subsystem_}, system{system_} { -    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { +    input_subsystem->Initialize(); +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) {          LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");          exit(1);      } -    input_subsystem->Initialize();      SDL_SetMainReady();  } @@ -32,10 +32,6 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {      SDL_Quit();  } -void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { -    input_subsystem->GetMouse()->MouseMove(x, y, 0, 0, 0, 0); -} -  InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const {      switch (button) {      case SDL_BUTTON_LEFT: @@ -53,44 +49,36 @@ InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) cons      }  } +std::pair<float, float> EmuWindow_SDL2::MouseToTouchPos(s32 touch_x, s32 touch_y) const { +    int w, h; +    SDL_GetWindowSize(render_window, &w, &h); +    const float fx = static_cast<float>(touch_x) / w; +    const float fy = static_cast<float>(touch_y) / h; + +    return {std::clamp<float>(fx, 0.0f, 1.0f), std::clamp<float>(fy, 0.0f, 1.0f)}; +} +  void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {      const auto mouse_button = SDLButtonToMouseButton(button);      if (state == SDL_PRESSED) { -        input_subsystem->GetMouse()->PressButton(x, y, 0, 0, mouse_button); +        const auto [touch_x, touch_y] = MouseToTouchPos(x, y); +        input_subsystem->GetMouse()->PressButton(x, y, touch_x, touch_y, mouse_button);      } else {          input_subsystem->GetMouse()->ReleaseButton(mouse_button);      }  } -std::pair<unsigned, unsigned> EmuWindow_SDL2::TouchToPixelPos(float touch_x, float touch_y) const { -    int w, h; -    SDL_GetWindowSize(render_window, &w, &h); - -    touch_x *= w; -    touch_y *= h; - -    return {static_cast<unsigned>(std::max(std::round(touch_x), 0.0f)), -            static_cast<unsigned>(std::max(std::round(touch_y), 0.0f))}; +void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { +    const auto [touch_x, touch_y] = MouseToTouchPos(x, y); +    input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, 0, 0);  }  void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) { -    int width, height; -    SDL_GetWindowSize(render_window, &width, &height); -    const auto [px, py] = TouchToPixelPos(x, y); -    const float fx = px * 1.0f / width; -    const float fy = py * 1.0f / height; - -    input_subsystem->GetTouchScreen()->TouchPressed(fx, fy, id); +    input_subsystem->GetTouchScreen()->TouchPressed(x, y, id);  }  void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) { -    int width, height; -    SDL_GetWindowSize(render_window, &width, &height); -    const auto [px, py] = TouchToPixelPos(x, y); -    const float fx = px * 1.0f / width; -    const float fy = py * 1.0f / height; - -    input_subsystem->GetTouchScreen()->TouchMoved(fx, fy, id); +    input_subsystem->GetTouchScreen()->TouchMoved(x, y, id);  }  void EmuWindow_SDL2::OnFingerUp() { diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 25c23e2a5..d9b453dee 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h @@ -38,17 +38,17 @@ protected:      /// Called by WaitEvent when a key is pressed or released.      void OnKeyEvent(int key, u8 state); -    /// Called by WaitEvent when the mouse moves. -    void OnMouseMotion(s32 x, s32 y); -      /// Converts a SDL mouse button into MouseInput mouse button      InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const; +    /// Translates pixel position to float position +    std::pair<float, float> MouseToTouchPos(s32 touch_x, s32 touch_y) const; +      /// Called by WaitEvent when a mouse button is pressed or released      void OnMouseButton(u32 button, u8 state, s32 x, s32 y); -    /// Translates pixel position (0..1) to pixel positions -    std::pair<unsigned, unsigned> TouchToPixelPos(float touch_x, float touch_y) const; +    /// Called by WaitEvent when the mouse moves. +    void OnMouseMotion(s32 x, s32 y);      /// Called by WaitEvent when a finger starts touching the touchscreen      void OnFingerDown(float x, float y, std::size_t id); | 
