diff options
Diffstat (limited to 'src')
82 files changed, 1192 insertions, 821 deletions
diff --git a/src/android/gradle.properties b/src/android/gradle.properties index e2f278f33..4fca1b576 100644 --- a/src/android/gradle.properties +++ b/src/android/gradle.properties | |||
| @@ -15,3 +15,6 @@ android.useAndroidX=true | |||
| 15 | kotlin.code.style=official | 15 | kotlin.code.style=official |
| 16 | kotlin.parallel.tasks.in.project=true | 16 | kotlin.parallel.tasks.in.project=true |
| 17 | android.defaults.buildfeatures.buildconfig=true | 17 | android.defaults.buildfeatures.buildconfig=true |
| 18 | |||
| 19 | # Android Gradle plugin 8.0.2 | ||
| 20 | android.suppressUnsupportedCompileSdk=34 | ||
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 404dcd0e9..6081352a2 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "audio_core/sink/sink_stream.h" | 12 | #include "audio_core/sink/sink_stream.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/fixed_point.h" | 14 | #include "common/fixed_point.h" |
| 15 | #include "common/scope_exit.h" | ||
| 15 | #include "common/settings.h" | 16 | #include "common/settings.h" |
| 16 | #include "core/core.h" | 17 | #include "core/core.h" |
| 17 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| @@ -19,9 +20,12 @@ | |||
| 19 | namespace AudioCore::Sink { | 20 | namespace AudioCore::Sink { |
| 20 | 21 | ||
| 21 | void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { | 22 | void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { |
| 22 | if (type == StreamType::In) { | 23 | SCOPE_EXIT({ |
| 23 | queue.enqueue(buffer); | 24 | queue.enqueue(buffer); |
| 24 | queued_buffers++; | 25 | ++queued_buffers; |
| 26 | }); | ||
| 27 | |||
| 28 | if (type == StreamType::In) { | ||
| 25 | return; | 29 | return; |
| 26 | } | 30 | } |
| 27 | 31 | ||
| @@ -66,16 +70,17 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { | |||
| 66 | static_cast<s16>(std::clamp(right_sample, min, max)); | 70 | static_cast<s16>(std::clamp(right_sample, min, max)); |
| 67 | } | 71 | } |
| 68 | 72 | ||
| 69 | samples = samples.subspan(0, samples.size() / system_channels * device_channels); | 73 | samples_buffer.Push(samples.subspan(0, samples.size() / system_channels * device_channels)); |
| 74 | return; | ||
| 75 | } | ||
| 70 | 76 | ||
| 71 | } else if (system_channels == 2 && device_channels == 6) { | 77 | if (system_channels == 2 && device_channels == 6) { |
| 72 | // We need moar samples! Not all games will provide 6 channel audio. | 78 | // We need moar samples! Not all games will provide 6 channel audio. |
| 73 | // TODO: Implement some upmixing here. Currently just passthrough, with other | 79 | // TODO: Implement some upmixing here. Currently just passthrough, with other |
| 74 | // channels left as silence. | 80 | // channels left as silence. |
| 75 | auto new_size = samples.size() / system_channels * device_channels; | 81 | std::vector<s16> new_samples(samples.size() / system_channels * device_channels); |
| 76 | tmp_samples.resize_destructive(new_size); | ||
| 77 | 82 | ||
| 78 | for (u32 read_index = 0, write_index = 0; read_index < new_size; | 83 | for (u32 read_index = 0, write_index = 0; read_index < samples.size(); |
| 79 | read_index += system_channels, write_index += device_channels) { | 84 | read_index += system_channels, write_index += device_channels) { |
| 80 | const auto left_sample{static_cast<s16>(std::clamp( | 85 | const auto left_sample{static_cast<s16>(std::clamp( |
| 81 | static_cast<s32>( | 86 | static_cast<s32>( |
| @@ -83,7 +88,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { | |||
| 83 | volume), | 88 | volume), |
| 84 | min, max))}; | 89 | min, max))}; |
| 85 | 90 | ||
| 86 | tmp_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample; | 91 | new_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample; |
| 87 | 92 | ||
| 88 | const auto right_sample{static_cast<s16>(std::clamp( | 93 | const auto right_sample{static_cast<s16>(std::clamp( |
| 89 | static_cast<s32>( | 94 | static_cast<s32>( |
| @@ -91,20 +96,21 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { | |||
| 91 | volume), | 96 | volume), |
| 92 | min, max))}; | 97 | min, max))}; |
| 93 | 98 | ||
| 94 | tmp_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample; | 99 | new_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample; |
| 95 | } | 100 | } |
| 96 | samples = std::span<s16>(tmp_samples); | ||
| 97 | 101 | ||
| 98 | } else if (volume != 1.0f) { | 102 | samples_buffer.Push(new_samples); |
| 99 | for (u32 i = 0; i < samples.size(); i++) { | 103 | return; |
| 104 | } | ||
| 105 | |||
| 106 | if (volume != 1.0f) { | ||
| 107 | for (u32 i = 0; i < samples.size(); ++i) { | ||
| 100 | samples[i] = static_cast<s16>( | 108 | samples[i] = static_cast<s16>( |
| 101 | std::clamp(static_cast<s32>(static_cast<f32>(samples[i]) * volume), min, max)); | 109 | std::clamp(static_cast<s32>(static_cast<f32>(samples[i]) * volume), min, max)); |
| 102 | } | 110 | } |
| 103 | } | 111 | } |
| 104 | 112 | ||
| 105 | samples_buffer.Push(samples); | 113 | samples_buffer.Push(samples); |
| 106 | queue.enqueue(buffer); | ||
| 107 | queued_buffers++; | ||
| 108 | } | 114 | } |
| 109 | 115 | ||
| 110 | std::vector<s16> SinkStream::ReleaseBuffer(u64 num_samples) { | 116 | std::vector<s16> SinkStream::ReleaseBuffer(u64 num_samples) { |
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h index 98d72ace1..6a4996ca3 100644 --- a/src/audio_core/sink/sink_stream.h +++ b/src/audio_core/sink/sink_stream.h | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include "common/polyfill_thread.h" | 16 | #include "common/polyfill_thread.h" |
| 17 | #include "common/reader_writer_queue.h" | 17 | #include "common/reader_writer_queue.h" |
| 18 | #include "common/ring_buffer.h" | 18 | #include "common/ring_buffer.h" |
| 19 | #include "common/scratch_buffer.h" | ||
| 20 | #include "common/thread.h" | 19 | #include "common/thread.h" |
| 21 | 20 | ||
| 22 | namespace Core { | 21 | namespace Core { |
| @@ -256,8 +255,6 @@ private: | |||
| 256 | /// Signalled when ring buffer entries are consumed | 255 | /// Signalled when ring buffer entries are consumed |
| 257 | std::condition_variable_any release_cv; | 256 | std::condition_variable_any release_cv; |
| 258 | std::mutex release_mutex; | 257 | std::mutex release_mutex; |
| 259 | /// Temporary buffer for appending samples when upmixing | ||
| 260 | Common::ScratchBuffer<s16> tmp_samples{}; | ||
| 261 | }; | 258 | }; |
| 262 | 259 | ||
| 263 | using SinkStreamPtr = std::unique_ptr<SinkStream>; | 260 | using SinkStreamPtr = std::unique_ptr<SinkStream>; |
diff --git a/src/common/input.h b/src/common/input.h index ea30770ae..2c4ccea22 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -75,8 +75,10 @@ enum class DriverResult { | |||
| 75 | ErrorWritingData, | 75 | ErrorWritingData, |
| 76 | NoDeviceDetected, | 76 | NoDeviceDetected, |
| 77 | InvalidHandle, | 77 | InvalidHandle, |
| 78 | InvalidParameters, | ||
| 78 | NotSupported, | 79 | NotSupported, |
| 79 | Disabled, | 80 | Disabled, |
| 81 | Delayed, | ||
| 80 | Unknown, | 82 | Unknown, |
| 81 | }; | 83 | }; |
| 82 | 84 | ||
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index 416680d44..5c961b202 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h | |||
| @@ -54,7 +54,7 @@ public: | |||
| 54 | return push_count; | 54 | return push_count; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | std::size_t Push(const std::span<T> input) { | 57 | std::size_t Push(std::span<const T> input) { |
| 58 | return Push(input.data(), input.size()); | 58 | return Push(input.data(), input.size()); |
| 59 | } | 59 | } |
| 60 | 60 | ||
diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h index 6fe907953..d5961b020 100644 --- a/src/common/scratch_buffer.h +++ b/src/common/scratch_buffer.h | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | 5 | ||
| 6 | #include <iterator> | 6 | #include <iterator> |
| 7 | 7 | ||
| 8 | #include "common/concepts.h" | ||
| 9 | #include "common/make_unique_for_overwrite.h" | 8 | #include "common/make_unique_for_overwrite.h" |
| 10 | 9 | ||
| 11 | namespace Common { | 10 | namespace Common { |
| @@ -19,15 +18,22 @@ namespace Common { | |||
| 19 | template <typename T> | 18 | template <typename T> |
| 20 | class ScratchBuffer { | 19 | class ScratchBuffer { |
| 21 | public: | 20 | public: |
| 22 | using iterator = T*; | ||
| 23 | using const_iterator = const T*; | ||
| 24 | using value_type = T; | ||
| 25 | using element_type = T; | 21 | using element_type = T; |
| 26 | using iterator_category = std::contiguous_iterator_tag; | 22 | using value_type = T; |
| 23 | using size_type = size_t; | ||
| 24 | using difference_type = std::ptrdiff_t; | ||
| 25 | using pointer = T*; | ||
| 26 | using const_pointer = const T*; | ||
| 27 | using reference = T&; | ||
| 28 | using const_reference = const T&; | ||
| 29 | using iterator = pointer; | ||
| 30 | using const_iterator = const_pointer; | ||
| 31 | using iterator_category = std::random_access_iterator_tag; | ||
| 32 | using iterator_concept = std::contiguous_iterator_tag; | ||
| 27 | 33 | ||
| 28 | ScratchBuffer() = default; | 34 | ScratchBuffer() = default; |
| 29 | 35 | ||
| 30 | explicit ScratchBuffer(size_t initial_capacity) | 36 | explicit ScratchBuffer(size_type initial_capacity) |
| 31 | : last_requested_size{initial_capacity}, buffer_capacity{initial_capacity}, | 37 | : last_requested_size{initial_capacity}, buffer_capacity{initial_capacity}, |
| 32 | buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {} | 38 | buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {} |
| 33 | 39 | ||
| @@ -39,7 +45,7 @@ public: | |||
| 39 | 45 | ||
| 40 | /// This will only grow the buffer's capacity if size is greater than the current capacity. | 46 | /// This will only grow the buffer's capacity if size is greater than the current capacity. |
| 41 | /// The previously held data will remain intact. | 47 | /// The previously held data will remain intact. |
| 42 | void resize(size_t size) { | 48 | void resize(size_type size) { |
| 43 | if (size > buffer_capacity) { | 49 | if (size > buffer_capacity) { |
| 44 | auto new_buffer = Common::make_unique_for_overwrite<T[]>(size); | 50 | auto new_buffer = Common::make_unique_for_overwrite<T[]>(size); |
| 45 | std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get()); | 51 | std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get()); |
| @@ -51,7 +57,7 @@ public: | |||
| 51 | 57 | ||
| 52 | /// This will only grow the buffer's capacity if size is greater than the current capacity. | 58 | /// This will only grow the buffer's capacity if size is greater than the current capacity. |
| 53 | /// The previously held data will be destroyed if a reallocation occurs. | 59 | /// The previously held data will be destroyed if a reallocation occurs. |
| 54 | void resize_destructive(size_t size) { | 60 | void resize_destructive(size_type size) { |
| 55 | if (size > buffer_capacity) { | 61 | if (size > buffer_capacity) { |
| 56 | buffer_capacity = size; | 62 | buffer_capacity = size; |
| 57 | buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity); | 63 | buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity); |
| @@ -59,43 +65,43 @@ public: | |||
| 59 | last_requested_size = size; | 65 | last_requested_size = size; |
| 60 | } | 66 | } |
| 61 | 67 | ||
| 62 | [[nodiscard]] T* data() noexcept { | 68 | [[nodiscard]] pointer data() noexcept { |
| 63 | return buffer.get(); | 69 | return buffer.get(); |
| 64 | } | 70 | } |
| 65 | 71 | ||
| 66 | [[nodiscard]] const T* data() const noexcept { | 72 | [[nodiscard]] const_pointer data() const noexcept { |
| 67 | return buffer.get(); | 73 | return buffer.get(); |
| 68 | } | 74 | } |
| 69 | 75 | ||
| 70 | [[nodiscard]] T* begin() noexcept { | 76 | [[nodiscard]] iterator begin() noexcept { |
| 71 | return data(); | 77 | return data(); |
| 72 | } | 78 | } |
| 73 | 79 | ||
| 74 | [[nodiscard]] const T* begin() const noexcept { | 80 | [[nodiscard]] const_iterator begin() const noexcept { |
| 75 | return data(); | 81 | return data(); |
| 76 | } | 82 | } |
| 77 | 83 | ||
| 78 | [[nodiscard]] T* end() noexcept { | 84 | [[nodiscard]] iterator end() noexcept { |
| 79 | return data() + last_requested_size; | 85 | return data() + last_requested_size; |
| 80 | } | 86 | } |
| 81 | 87 | ||
| 82 | [[nodiscard]] const T* end() const noexcept { | 88 | [[nodiscard]] const_iterator end() const noexcept { |
| 83 | return data() + last_requested_size; | 89 | return data() + last_requested_size; |
| 84 | } | 90 | } |
| 85 | 91 | ||
| 86 | [[nodiscard]] T& operator[](size_t i) { | 92 | [[nodiscard]] reference operator[](size_type i) { |
| 87 | return buffer[i]; | 93 | return buffer[i]; |
| 88 | } | 94 | } |
| 89 | 95 | ||
| 90 | [[nodiscard]] const T& operator[](size_t i) const { | 96 | [[nodiscard]] const_reference operator[](size_type i) const { |
| 91 | return buffer[i]; | 97 | return buffer[i]; |
| 92 | } | 98 | } |
| 93 | 99 | ||
| 94 | [[nodiscard]] size_t size() const noexcept { | 100 | [[nodiscard]] size_type size() const noexcept { |
| 95 | return last_requested_size; | 101 | return last_requested_size; |
| 96 | } | 102 | } |
| 97 | 103 | ||
| 98 | [[nodiscard]] size_t capacity() const noexcept { | 104 | [[nodiscard]] size_type capacity() const noexcept { |
| 99 | return buffer_capacity; | 105 | return buffer_capacity; |
| 100 | } | 106 | } |
| 101 | 107 | ||
| @@ -106,8 +112,8 @@ public: | |||
| 106 | } | 112 | } |
| 107 | 113 | ||
| 108 | private: | 114 | private: |
| 109 | size_t last_requested_size{}; | 115 | size_type last_requested_size{}; |
| 110 | size_t buffer_capacity{}; | 116 | size_type buffer_capacity{}; |
| 111 | std::unique_ptr<T[]> buffer{}; | 117 | std::unique_ptr<T[]> buffer{}; |
| 112 | }; | 118 | }; |
| 113 | 119 | ||
diff --git a/src/common/settings.h b/src/common/settings.h index ae5ed93d8..59e96e74f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -527,12 +527,10 @@ struct Values { | |||
| 527 | Setting<bool> mouse_panning{false, "mouse_panning"}; | 527 | Setting<bool> mouse_panning{false, "mouse_panning"}; |
| 528 | Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"}; | 528 | Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"}; |
| 529 | Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"}; | 529 | Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"}; |
| 530 | Setting<u8, true> mouse_panning_deadzone_x_counterweight{ | 530 | Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100, |
| 531 | 0, 0, 100, "mouse_panning_deadzone_x_counterweight"}; | 531 | "mouse_panning_deadzone_counterweight"}; |
| 532 | Setting<u8, true> mouse_panning_deadzone_y_counterweight{ | 532 | Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"}; |
| 533 | 0, 0, 100, "mouse_panning_deadzone_y_counterweight"}; | 533 | Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"}; |
| 534 | Setting<u8, true> mouse_panning_decay_strength{22, 0, 100, "mouse_panning_decay_strength"}; | ||
| 535 | Setting<u8, true> mouse_panning_min_decay{5, 0, 100, "mouse_panning_min_decay"}; | ||
| 536 | 534 | ||
| 537 | Setting<bool> mouse_enabled{false, "mouse_enabled"}; | 535 | Setting<bool> mouse_enabled{false, "mouse_enabled"}; |
| 538 | Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; | 536 | Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; |
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp index 91352912d..929ed67e4 100644 --- a/src/common/telemetry.cpp +++ b/src/common/telemetry.cpp | |||
| @@ -93,6 +93,7 @@ void AppendCPUInfo(FieldCollection& fc) { | |||
| 93 | add_field("CPU_Extension_x64_GFNI", caps.gfni); | 93 | add_field("CPU_Extension_x64_GFNI", caps.gfni); |
| 94 | add_field("CPU_Extension_x64_INVARIANT_TSC", caps.invariant_tsc); | 94 | add_field("CPU_Extension_x64_INVARIANT_TSC", caps.invariant_tsc); |
| 95 | add_field("CPU_Extension_x64_LZCNT", caps.lzcnt); | 95 | add_field("CPU_Extension_x64_LZCNT", caps.lzcnt); |
| 96 | add_field("CPU_Extension_x64_MONITORX", caps.monitorx); | ||
| 96 | add_field("CPU_Extension_x64_MOVBE", caps.movbe); | 97 | add_field("CPU_Extension_x64_MOVBE", caps.movbe); |
| 97 | add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq); | 98 | add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq); |
| 98 | add_field("CPU_Extension_x64_POPCNT", caps.popcnt); | 99 | add_field("CPU_Extension_x64_POPCNT", caps.popcnt); |
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp index c998b1197..780120a5b 100644 --- a/src/common/x64/cpu_detect.cpp +++ b/src/common/x64/cpu_detect.cpp | |||
| @@ -168,6 +168,7 @@ static CPUCaps Detect() { | |||
| 168 | __cpuid(cpu_id, 0x80000001); | 168 | __cpuid(cpu_id, 0x80000001); |
| 169 | caps.lzcnt = Common::Bit<5>(cpu_id[2]); | 169 | caps.lzcnt = Common::Bit<5>(cpu_id[2]); |
| 170 | caps.fma4 = Common::Bit<16>(cpu_id[2]); | 170 | caps.fma4 = Common::Bit<16>(cpu_id[2]); |
| 171 | caps.monitorx = Common::Bit<29>(cpu_id[2]); | ||
| 171 | } | 172 | } |
| 172 | 173 | ||
| 173 | if (max_ex_fn >= 0x80000007) { | 174 | if (max_ex_fn >= 0x80000007) { |
diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h index 8253944d6..756459417 100644 --- a/src/common/x64/cpu_detect.h +++ b/src/common/x64/cpu_detect.h | |||
| @@ -63,6 +63,7 @@ struct CPUCaps { | |||
| 63 | bool gfni : 1; | 63 | bool gfni : 1; |
| 64 | bool invariant_tsc : 1; | 64 | bool invariant_tsc : 1; |
| 65 | bool lzcnt : 1; | 65 | bool lzcnt : 1; |
| 66 | bool monitorx : 1; | ||
| 66 | bool movbe : 1; | 67 | bool movbe : 1; |
| 67 | bool pclmulqdq : 1; | 68 | bool pclmulqdq : 1; |
| 68 | bool popcnt : 1; | 69 | bool popcnt : 1; |
diff --git a/src/common/x64/cpu_wait.cpp b/src/common/x64/cpu_wait.cpp index c53dd4945..41d385f59 100644 --- a/src/common/x64/cpu_wait.cpp +++ b/src/common/x64/cpu_wait.cpp | |||
| @@ -13,36 +13,60 @@ | |||
| 13 | 13 | ||
| 14 | namespace Common::X64 { | 14 | namespace Common::X64 { |
| 15 | 15 | ||
| 16 | namespace { | ||
| 17 | |||
| 18 | // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources. | ||
| 19 | // For reference: | ||
| 20 | // At 1 GHz, 100K cycles is 100us | ||
| 21 | // At 2 GHz, 100K cycles is 50us | ||
| 22 | // At 4 GHz, 100K cycles is 25us | ||
| 23 | constexpr auto PauseCycles = 100'000U; | ||
| 24 | |||
| 25 | } // Anonymous namespace | ||
| 26 | |||
| 16 | #ifdef _MSC_VER | 27 | #ifdef _MSC_VER |
| 17 | __forceinline static void TPAUSE() { | 28 | __forceinline static void TPAUSE() { |
| 18 | // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources. | 29 | static constexpr auto RequestC02State = 0U; |
| 19 | // For reference: | 30 | _tpause(RequestC02State, FencedRDTSC() + PauseCycles); |
| 20 | // At 1 GHz, 100K cycles is 100us | 31 | } |
| 21 | // At 2 GHz, 100K cycles is 50us | 32 | |
| 22 | // At 4 GHz, 100K cycles is 25us | 33 | __forceinline static void MWAITX() { |
| 23 | static constexpr auto PauseCycles = 100'000; | 34 | static constexpr auto EnableWaitTimeFlag = 1U << 1; |
| 24 | _tpause(0, FencedRDTSC() + PauseCycles); | 35 | static constexpr auto RequestC1State = 0U; |
| 36 | |||
| 37 | // monitor_var should be aligned to a cache line. | ||
| 38 | alignas(64) u64 monitor_var{}; | ||
| 39 | _mm_monitorx(&monitor_var, 0, 0); | ||
| 40 | _mm_mwaitx(EnableWaitTimeFlag, RequestC1State, PauseCycles); | ||
| 25 | } | 41 | } |
| 26 | #else | 42 | #else |
| 27 | static void TPAUSE() { | 43 | static void TPAUSE() { |
| 28 | // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources. | 44 | static constexpr auto RequestC02State = 0U; |
| 29 | // For reference: | ||
| 30 | // At 1 GHz, 100K cycles is 100us | ||
| 31 | // At 2 GHz, 100K cycles is 50us | ||
| 32 | // At 4 GHz, 100K cycles is 25us | ||
| 33 | static constexpr auto PauseCycles = 100'000; | ||
| 34 | const auto tsc = FencedRDTSC() + PauseCycles; | 45 | const auto tsc = FencedRDTSC() + PauseCycles; |
| 35 | const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF); | 46 | const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF); |
| 36 | const auto edx = static_cast<u32>(tsc >> 32); | 47 | const auto edx = static_cast<u32>(tsc >> 32); |
| 37 | asm volatile("tpause %0" : : "r"(0), "d"(edx), "a"(eax)); | 48 | asm volatile("tpause %0" : : "r"(RequestC02State), "d"(edx), "a"(eax)); |
| 49 | } | ||
| 50 | |||
| 51 | static void MWAITX() { | ||
| 52 | static constexpr auto EnableWaitTimeFlag = 1U << 1; | ||
| 53 | static constexpr auto RequestC1State = 0U; | ||
| 54 | |||
| 55 | // monitor_var should be aligned to a cache line. | ||
| 56 | alignas(64) u64 monitor_var{}; | ||
| 57 | asm volatile("monitorx" : : "a"(&monitor_var), "c"(0), "d"(0)); | ||
| 58 | asm volatile("mwaitx" : : "a"(RequestC1State), "b"(PauseCycles), "c"(EnableWaitTimeFlag)); | ||
| 38 | } | 59 | } |
| 39 | #endif | 60 | #endif |
| 40 | 61 | ||
| 41 | void MicroSleep() { | 62 | void MicroSleep() { |
| 42 | static const bool has_waitpkg = GetCPUCaps().waitpkg; | 63 | static const bool has_waitpkg = GetCPUCaps().waitpkg; |
| 64 | static const bool has_monitorx = GetCPUCaps().monitorx; | ||
| 43 | 65 | ||
| 44 | if (has_waitpkg) { | 66 | if (has_waitpkg) { |
| 45 | TPAUSE(); | 67 | TPAUSE(); |
| 68 | } else if (has_monitorx) { | ||
| 69 | MWAITX(); | ||
| 46 | } else { | 70 | } else { |
| 47 | std::this_thread::yield(); | 71 | std::this_thread::yield(); |
| 48 | } | 72 | } |
diff --git a/src/core/core.cpp b/src/core/core.cpp index b74fd0a58..9e3eb3795 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "core/file_sys/savedata_factory.h" | 27 | #include "core/file_sys/savedata_factory.h" |
| 28 | #include "core/file_sys/vfs_concat.h" | 28 | #include "core/file_sys/vfs_concat.h" |
| 29 | #include "core/file_sys/vfs_real.h" | 29 | #include "core/file_sys/vfs_real.h" |
| 30 | #include "core/gpu_dirty_memory_manager.h" | ||
| 30 | #include "core/hid/hid_core.h" | 31 | #include "core/hid/hid_core.h" |
| 31 | #include "core/hle/kernel/k_memory_manager.h" | 32 | #include "core/hle/kernel/k_memory_manager.h" |
| 32 | #include "core/hle/kernel/k_process.h" | 33 | #include "core/hle/kernel/k_process.h" |
| @@ -130,7 +131,10 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 130 | struct System::Impl { | 131 | struct System::Impl { |
| 131 | explicit Impl(System& system) | 132 | explicit Impl(System& system) |
| 132 | : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{}, | 133 | : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{}, |
| 133 | cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} | 134 | cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system}, |
| 135 | gpu_dirty_memory_write_manager{} { | ||
| 136 | memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager); | ||
| 137 | } | ||
| 134 | 138 | ||
| 135 | void Initialize(System& system) { | 139 | void Initialize(System& system) { |
| 136 | device_memory = std::make_unique<Core::DeviceMemory>(); | 140 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| @@ -234,6 +238,8 @@ struct System::Impl { | |||
| 234 | // Setting changes may require a full system reinitialization (e.g., disabling multicore). | 238 | // Setting changes may require a full system reinitialization (e.g., disabling multicore). |
| 235 | ReinitializeIfNecessary(system); | 239 | ReinitializeIfNecessary(system); |
| 236 | 240 | ||
| 241 | memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager); | ||
| 242 | |||
| 237 | kernel.Initialize(); | 243 | kernel.Initialize(); |
| 238 | cpu_manager.Initialize(); | 244 | cpu_manager.Initialize(); |
| 239 | 245 | ||
| @@ -540,6 +546,9 @@ struct System::Impl { | |||
| 540 | 546 | ||
| 541 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | 547 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; |
| 542 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; | 548 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; |
| 549 | |||
| 550 | std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> | ||
| 551 | gpu_dirty_memory_write_manager{}; | ||
| 543 | }; | 552 | }; |
| 544 | 553 | ||
| 545 | System::System() : impl{std::make_unique<Impl>(*this)} {} | 554 | System::System() : impl{std::make_unique<Impl>(*this)} {} |
| @@ -629,10 +638,31 @@ void System::PrepareReschedule(const u32 core_index) { | |||
| 629 | impl->kernel.PrepareReschedule(core_index); | 638 | impl->kernel.PrepareReschedule(core_index); |
| 630 | } | 639 | } |
| 631 | 640 | ||
| 641 | Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() { | ||
| 642 | const std::size_t core = impl->kernel.GetCurrentHostThreadID(); | ||
| 643 | return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES | ||
| 644 | ? core | ||
| 645 | : Core::Hardware::NUM_CPU_CORES - 1]; | ||
| 646 | } | ||
| 647 | |||
| 648 | /// Provides a constant reference to the current gou dirty memory manager. | ||
| 649 | const Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() const { | ||
| 650 | const std::size_t core = impl->kernel.GetCurrentHostThreadID(); | ||
| 651 | return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES | ||
| 652 | ? core | ||
| 653 | : Core::Hardware::NUM_CPU_CORES - 1]; | ||
| 654 | } | ||
| 655 | |||
| 632 | size_t System::GetCurrentHostThreadID() const { | 656 | size_t System::GetCurrentHostThreadID() const { |
| 633 | return impl->kernel.GetCurrentHostThreadID(); | 657 | return impl->kernel.GetCurrentHostThreadID(); |
| 634 | } | 658 | } |
| 635 | 659 | ||
| 660 | void System::GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback) { | ||
| 661 | for (auto& manager : impl->gpu_dirty_memory_write_manager) { | ||
| 662 | manager.Gather(callback); | ||
| 663 | } | ||
| 664 | } | ||
| 665 | |||
| 636 | PerfStatsResults System::GetAndResetPerfStats() { | 666 | PerfStatsResults System::GetAndResetPerfStats() { |
| 637 | return impl->GetAndResetPerfStats(); | 667 | return impl->GetAndResetPerfStats(); |
| 638 | } | 668 | } |
diff --git a/src/core/core.h b/src/core/core.h index 93afc9303..14b2f7785 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -108,9 +108,10 @@ class CpuManager; | |||
| 108 | class Debugger; | 108 | class Debugger; |
| 109 | class DeviceMemory; | 109 | class DeviceMemory; |
| 110 | class ExclusiveMonitor; | 110 | class ExclusiveMonitor; |
| 111 | class SpeedLimiter; | 111 | class GPUDirtyMemoryManager; |
| 112 | class PerfStats; | 112 | class PerfStats; |
| 113 | class Reporter; | 113 | class Reporter; |
| 114 | class SpeedLimiter; | ||
| 114 | class TelemetrySession; | 115 | class TelemetrySession; |
| 115 | 116 | ||
| 116 | struct PerfStatsResults; | 117 | struct PerfStatsResults; |
| @@ -225,6 +226,14 @@ public: | |||
| 225 | /// Prepare the core emulation for a reschedule | 226 | /// Prepare the core emulation for a reschedule |
| 226 | void PrepareReschedule(u32 core_index); | 227 | void PrepareReschedule(u32 core_index); |
| 227 | 228 | ||
| 229 | /// Provides a reference to the gou dirty memory manager. | ||
| 230 | [[nodiscard]] Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager(); | ||
| 231 | |||
| 232 | /// Provides a constant reference to the current gou dirty memory manager. | ||
| 233 | [[nodiscard]] const Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager() const; | ||
| 234 | |||
| 235 | void GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback); | ||
| 236 | |||
| 228 | [[nodiscard]] size_t GetCurrentHostThreadID() const; | 237 | [[nodiscard]] size_t GetCurrentHostThreadID() const; |
| 229 | 238 | ||
| 230 | /// Gets and resets core performance statistics | 239 | /// Gets and resets core performance statistics |
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp index 1ff83c08c..e39c7b62b 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.cpp +++ b/src/core/file_sys/fsmitm_romfsbuild.cpp | |||
| @@ -105,19 +105,11 @@ static u64 romfs_get_hash_table_count(u64 num_entries) { | |||
| 105 | return count; | 105 | return count; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir, | 108 | void RomFSBuildContext::VisitDirectory(VirtualDir romfs_dir, VirtualDir ext_dir, |
| 109 | std::shared_ptr<RomFSBuildDirectoryContext> parent) { | 109 | std::shared_ptr<RomFSBuildDirectoryContext> parent) { |
| 110 | std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> child_dirs; | 110 | std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> child_dirs; |
| 111 | 111 | ||
| 112 | VirtualDir dir; | 112 | const auto entries = romfs_dir->GetEntries(); |
| 113 | |||
| 114 | if (parent->path_len == 0) { | ||
| 115 | dir = root_romfs; | ||
| 116 | } else { | ||
| 117 | dir = root_romfs->GetDirectoryRelative(parent->path); | ||
| 118 | } | ||
| 119 | |||
| 120 | const auto entries = dir->GetEntries(); | ||
| 121 | 113 | ||
| 122 | for (const auto& kv : entries) { | 114 | for (const auto& kv : entries) { |
| 123 | if (kv.second == VfsEntryType::Directory) { | 115 | if (kv.second == VfsEntryType::Directory) { |
| @@ -127,7 +119,7 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir | |||
| 127 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); | 119 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); |
| 128 | child->path = parent->path + "/" + kv.first; | 120 | child->path = parent->path + "/" + kv.first; |
| 129 | 121 | ||
| 130 | if (ext_dir != nullptr && ext_dir->GetFileRelative(child->path + ".stub") != nullptr) { | 122 | if (ext_dir != nullptr && ext_dir->GetFile(kv.first + ".stub") != nullptr) { |
| 131 | continue; | 123 | continue; |
| 132 | } | 124 | } |
| 133 | 125 | ||
| @@ -144,17 +136,17 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir | |||
| 144 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); | 136 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); |
| 145 | child->path = parent->path + "/" + kv.first; | 137 | child->path = parent->path + "/" + kv.first; |
| 146 | 138 | ||
| 147 | if (ext_dir != nullptr && ext_dir->GetFileRelative(child->path + ".stub") != nullptr) { | 139 | if (ext_dir != nullptr && ext_dir->GetFile(kv.first + ".stub") != nullptr) { |
| 148 | continue; | 140 | continue; |
| 149 | } | 141 | } |
| 150 | 142 | ||
| 151 | // Sanity check on path_len | 143 | // Sanity check on path_len |
| 152 | ASSERT(child->path_len < FS_MAX_PATH); | 144 | ASSERT(child->path_len < FS_MAX_PATH); |
| 153 | 145 | ||
| 154 | child->source = root_romfs->GetFileRelative(child->path); | 146 | child->source = romfs_dir->GetFile(kv.first); |
| 155 | 147 | ||
| 156 | if (ext_dir != nullptr) { | 148 | if (ext_dir != nullptr) { |
| 157 | if (const auto ips = ext_dir->GetFileRelative(child->path + ".ips")) { | 149 | if (const auto ips = ext_dir->GetFile(kv.first + ".ips")) { |
| 158 | if (auto patched = PatchIPS(child->source, ips)) { | 150 | if (auto patched = PatchIPS(child->source, ips)) { |
| 159 | child->source = std::move(patched); | 151 | child->source = std::move(patched); |
| 160 | } | 152 | } |
| @@ -168,23 +160,27 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir | |||
| 168 | } | 160 | } |
| 169 | 161 | ||
| 170 | for (auto& child : child_dirs) { | 162 | for (auto& child : child_dirs) { |
| 171 | this->VisitDirectory(root_romfs, ext_dir, child); | 163 | auto subdir_name = std::string_view(child->path).substr(child->cur_path_ofs); |
| 164 | auto child_romfs_dir = romfs_dir->GetSubdirectory(subdir_name); | ||
| 165 | auto child_ext_dir = ext_dir != nullptr ? ext_dir->GetSubdirectory(subdir_name) : nullptr; | ||
| 166 | this->VisitDirectory(child_romfs_dir, child_ext_dir, child); | ||
| 172 | } | 167 | } |
| 173 | } | 168 | } |
| 174 | 169 | ||
| 175 | bool RomFSBuildContext::AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, | 170 | bool RomFSBuildContext::AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, |
| 176 | std::shared_ptr<RomFSBuildDirectoryContext> dir_ctx) { | 171 | std::shared_ptr<RomFSBuildDirectoryContext> dir_ctx) { |
| 177 | // Check whether it's already in the known directories. | 172 | // Check whether it's already in the known directories. |
| 178 | const auto existing = directories.find(dir_ctx->path); | 173 | const auto [it, is_new] = directories.emplace(dir_ctx->path, nullptr); |
| 179 | if (existing != directories.end()) | 174 | if (!is_new) { |
| 180 | return false; | 175 | return false; |
| 176 | } | ||
| 181 | 177 | ||
| 182 | // Add a new directory. | 178 | // Add a new directory. |
| 183 | num_dirs++; | 179 | num_dirs++; |
| 184 | dir_table_size += | 180 | dir_table_size += |
| 185 | sizeof(RomFSDirectoryEntry) + Common::AlignUp(dir_ctx->path_len - dir_ctx->cur_path_ofs, 4); | 181 | sizeof(RomFSDirectoryEntry) + Common::AlignUp(dir_ctx->path_len - dir_ctx->cur_path_ofs, 4); |
| 186 | dir_ctx->parent = parent_dir_ctx; | 182 | dir_ctx->parent = parent_dir_ctx; |
| 187 | directories.emplace(dir_ctx->path, dir_ctx); | 183 | it->second = dir_ctx; |
| 188 | 184 | ||
| 189 | return true; | 185 | return true; |
| 190 | } | 186 | } |
| @@ -192,8 +188,8 @@ bool RomFSBuildContext::AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> | |||
| 192 | bool RomFSBuildContext::AddFile(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, | 188 | bool RomFSBuildContext::AddFile(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, |
| 193 | std::shared_ptr<RomFSBuildFileContext> file_ctx) { | 189 | std::shared_ptr<RomFSBuildFileContext> file_ctx) { |
| 194 | // Check whether it's already in the known files. | 190 | // Check whether it's already in the known files. |
| 195 | const auto existing = files.find(file_ctx->path); | 191 | const auto [it, is_new] = files.emplace(file_ctx->path, nullptr); |
| 196 | if (existing != files.end()) { | 192 | if (!is_new) { |
| 197 | return false; | 193 | return false; |
| 198 | } | 194 | } |
| 199 | 195 | ||
| @@ -202,7 +198,7 @@ bool RomFSBuildContext::AddFile(std::shared_ptr<RomFSBuildDirectoryContext> pare | |||
| 202 | file_table_size += | 198 | file_table_size += |
| 203 | sizeof(RomFSFileEntry) + Common::AlignUp(file_ctx->path_len - file_ctx->cur_path_ofs, 4); | 199 | sizeof(RomFSFileEntry) + Common::AlignUp(file_ctx->path_len - file_ctx->cur_path_ofs, 4); |
| 204 | file_ctx->parent = parent_dir_ctx; | 200 | file_ctx->parent = parent_dir_ctx; |
| 205 | files.emplace(file_ctx->path, file_ctx); | 201 | it->second = file_ctx; |
| 206 | 202 | ||
| 207 | return true; | 203 | return true; |
| 208 | } | 204 | } |
diff --git a/src/core/gpu_dirty_memory_manager.h b/src/core/gpu_dirty_memory_manager.h new file mode 100644 index 000000000..9687531e8 --- /dev/null +++ b/src/core/gpu_dirty_memory_manager.h | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <atomic> | ||
| 7 | #include <bit> | ||
| 8 | #include <functional> | ||
| 9 | #include <mutex> | ||
| 10 | #include <utility> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "core/memory.h" | ||
| 14 | |||
| 15 | namespace Core { | ||
| 16 | |||
| 17 | class GPUDirtyMemoryManager { | ||
| 18 | public: | ||
| 19 | GPUDirtyMemoryManager() : current{default_transform} { | ||
| 20 | back_buffer.reserve(256); | ||
| 21 | front_buffer.reserve(256); | ||
| 22 | } | ||
| 23 | |||
| 24 | ~GPUDirtyMemoryManager() = default; | ||
| 25 | |||
| 26 | void Collect(VAddr address, size_t size) { | ||
| 27 | TransformAddress t = BuildTransform(address, size); | ||
| 28 | TransformAddress tmp, original; | ||
| 29 | do { | ||
| 30 | tmp = current.load(std::memory_order_acquire); | ||
| 31 | original = tmp; | ||
| 32 | if (tmp.address != t.address) { | ||
| 33 | if (IsValid(tmp.address)) { | ||
| 34 | std::scoped_lock lk(guard); | ||
| 35 | back_buffer.emplace_back(tmp); | ||
| 36 | current.exchange(t, std::memory_order_relaxed); | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | tmp.address = t.address; | ||
| 40 | tmp.mask = 0; | ||
| 41 | } | ||
| 42 | if ((tmp.mask | t.mask) == tmp.mask) { | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | tmp.mask |= t.mask; | ||
| 46 | } while (!current.compare_exchange_weak(original, tmp, std::memory_order_release, | ||
| 47 | std::memory_order_relaxed)); | ||
| 48 | } | ||
| 49 | |||
| 50 | void Gather(std::function<void(VAddr, size_t)>& callback) { | ||
| 51 | { | ||
| 52 | std::scoped_lock lk(guard); | ||
| 53 | TransformAddress t = current.exchange(default_transform, std::memory_order_relaxed); | ||
| 54 | front_buffer.swap(back_buffer); | ||
| 55 | if (IsValid(t.address)) { | ||
| 56 | front_buffer.emplace_back(t); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | for (auto& transform : front_buffer) { | ||
| 60 | size_t offset = 0; | ||
| 61 | u64 mask = transform.mask; | ||
| 62 | while (mask != 0) { | ||
| 63 | const size_t empty_bits = std::countr_zero(mask); | ||
| 64 | offset += empty_bits << align_bits; | ||
| 65 | mask = mask >> empty_bits; | ||
| 66 | |||
| 67 | const size_t continuous_bits = std::countr_one(mask); | ||
| 68 | callback((static_cast<VAddr>(transform.address) << page_bits) + offset, | ||
| 69 | continuous_bits << align_bits); | ||
| 70 | mask = continuous_bits < align_size ? (mask >> continuous_bits) : 0; | ||
| 71 | offset += continuous_bits << align_bits; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | front_buffer.clear(); | ||
| 75 | } | ||
| 76 | |||
| 77 | private: | ||
| 78 | struct alignas(8) TransformAddress { | ||
| 79 | u32 address; | ||
| 80 | u32 mask; | ||
| 81 | }; | ||
| 82 | |||
| 83 | constexpr static size_t page_bits = Memory::YUZU_PAGEBITS - 1; | ||
| 84 | constexpr static size_t page_size = 1ULL << page_bits; | ||
| 85 | constexpr static size_t page_mask = page_size - 1; | ||
| 86 | |||
| 87 | constexpr static size_t align_bits = 6U; | ||
| 88 | constexpr static size_t align_size = 1U << align_bits; | ||
| 89 | constexpr static size_t align_mask = align_size - 1; | ||
| 90 | constexpr static TransformAddress default_transform = {.address = ~0U, .mask = 0U}; | ||
| 91 | |||
| 92 | bool IsValid(VAddr address) { | ||
| 93 | return address < (1ULL << 39); | ||
| 94 | } | ||
| 95 | |||
| 96 | template <typename T> | ||
| 97 | T CreateMask(size_t top_bit, size_t minor_bit) { | ||
| 98 | T mask = ~T(0); | ||
| 99 | mask <<= (sizeof(T) * 8 - top_bit); | ||
| 100 | mask >>= (sizeof(T) * 8 - top_bit); | ||
| 101 | mask >>= minor_bit; | ||
| 102 | mask <<= minor_bit; | ||
| 103 | return mask; | ||
| 104 | } | ||
| 105 | |||
| 106 | TransformAddress BuildTransform(VAddr address, size_t size) { | ||
| 107 | const size_t minor_address = address & page_mask; | ||
| 108 | const size_t minor_bit = minor_address >> align_bits; | ||
| 109 | const size_t top_bit = (minor_address + size + align_mask) >> align_bits; | ||
| 110 | TransformAddress result{}; | ||
| 111 | result.address = static_cast<u32>(address >> page_bits); | ||
| 112 | result.mask = CreateMask<u32>(top_bit, minor_bit); | ||
| 113 | return result; | ||
| 114 | } | ||
| 115 | |||
| 116 | std::atomic<TransformAddress> current{}; | ||
| 117 | std::mutex guard; | ||
| 118 | std::vector<TransformAddress> back_buffer; | ||
| 119 | std::vector<TransformAddress> front_buffer; | ||
| 120 | }; | ||
| 121 | |||
| 122 | } // namespace Core | ||
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index c8d574993..526a39130 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include "audio_core/renderer/audio_device.h" | 5 | #include "audio_core/renderer/audio_device.h" |
| 6 | #include "common/common_funcs.h" | 6 | #include "common/common_funcs.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/settings.h" | 8 | #include "common/scratch_buffer.h" |
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/hle/kernel/k_event.h" | 11 | #include "core/hle/kernel/k_event.h" |
| @@ -124,12 +124,15 @@ private: | |||
| 124 | 124 | ||
| 125 | void GetReleasedAudioInBuffer(HLERequestContext& ctx) { | 125 | void GetReleasedAudioInBuffer(HLERequestContext& ctx) { |
| 126 | const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); | 126 | const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); |
| 127 | tmp_buffer.resize_destructive(write_buffer_size); | 127 | released_buffer.resize_destructive(write_buffer_size); |
| 128 | tmp_buffer[0] = 0; | 128 | released_buffer[0] = 0; |
| 129 | 129 | ||
| 130 | const auto count = impl->GetReleasedBuffers(tmp_buffer); | 130 | const auto count = impl->GetReleasedBuffers(released_buffer); |
| 131 | 131 | ||
| 132 | ctx.WriteBuffer(tmp_buffer); | 132 | LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", |
| 133 | impl->GetSystem().GetSessionId(), count); | ||
| 134 | |||
| 135 | ctx.WriteBuffer(released_buffer); | ||
| 133 | 136 | ||
| 134 | IPC::ResponseBuilder rb{ctx, 3}; | 137 | IPC::ResponseBuilder rb{ctx, 3}; |
| 135 | rb.Push(ResultSuccess); | 138 | rb.Push(ResultSuccess); |
| @@ -155,7 +158,6 @@ private: | |||
| 155 | LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); | 158 | LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); |
| 156 | 159 | ||
| 157 | IPC::ResponseBuilder rb{ctx, 3}; | 160 | IPC::ResponseBuilder rb{ctx, 3}; |
| 158 | |||
| 159 | rb.Push(ResultSuccess); | 161 | rb.Push(ResultSuccess); |
| 160 | rb.Push(buffer_count); | 162 | rb.Push(buffer_count); |
| 161 | } | 163 | } |
| @@ -195,7 +197,7 @@ private: | |||
| 195 | KernelHelpers::ServiceContext service_context; | 197 | KernelHelpers::ServiceContext service_context; |
| 196 | Kernel::KEvent* event; | 198 | Kernel::KEvent* event; |
| 197 | std::shared_ptr<AudioCore::AudioIn::In> impl; | 199 | std::shared_ptr<AudioCore::AudioIn::In> impl; |
| 198 | Common::ScratchBuffer<u64> tmp_buffer; | 200 | Common::ScratchBuffer<u64> released_buffer; |
| 199 | }; | 201 | }; |
| 200 | 202 | ||
| 201 | AudInU::AudInU(Core::System& system_) | 203 | AudInU::AudInU(Core::System& system_) |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 032c8c11f..23f84a29f 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "audio_core/renderer/audio_device.h" | 9 | #include "audio_core/renderer/audio_device.h" |
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/scratch_buffer.h" | ||
| 12 | #include "common/string_util.h" | 13 | #include "common/string_util.h" |
| 13 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| @@ -102,8 +103,8 @@ private: | |||
| 102 | AudioOutBuffer buffer{}; | 103 | AudioOutBuffer buffer{}; |
| 103 | std::memcpy(&buffer, in_buffer.data(), sizeof(AudioOutBuffer)); | 104 | std::memcpy(&buffer, in_buffer.data(), sizeof(AudioOutBuffer)); |
| 104 | 105 | ||
| 105 | [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()}; | 106 | LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", |
| 106 | LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", sessionid, tag); | 107 | impl->GetSystem().GetSessionId(), tag); |
| 107 | 108 | ||
| 108 | auto result = impl->AppendBuffer(buffer, tag); | 109 | auto result = impl->AppendBuffer(buffer, tag); |
| 109 | 110 | ||
| @@ -123,12 +124,15 @@ private: | |||
| 123 | 124 | ||
| 124 | void GetReleasedAudioOutBuffers(HLERequestContext& ctx) { | 125 | void GetReleasedAudioOutBuffers(HLERequestContext& ctx) { |
| 125 | const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); | 126 | const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); |
| 126 | tmp_buffer.resize_destructive(write_buffer_size); | 127 | released_buffer.resize_destructive(write_buffer_size); |
| 127 | tmp_buffer[0] = 0; | 128 | released_buffer[0] = 0; |
| 128 | 129 | ||
| 129 | const auto count = impl->GetReleasedBuffers(tmp_buffer); | 130 | const auto count = impl->GetReleasedBuffers(released_buffer); |
| 130 | 131 | ||
| 131 | ctx.WriteBuffer(tmp_buffer); | 132 | ctx.WriteBuffer(released_buffer); |
| 133 | |||
| 134 | LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", | ||
| 135 | impl->GetSystem().GetSessionId(), count); | ||
| 132 | 136 | ||
| 133 | IPC::ResponseBuilder rb{ctx, 3}; | 137 | IPC::ResponseBuilder rb{ctx, 3}; |
| 134 | rb.Push(ResultSuccess); | 138 | rb.Push(ResultSuccess); |
| @@ -154,7 +158,6 @@ private: | |||
| 154 | LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); | 158 | LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); |
| 155 | 159 | ||
| 156 | IPC::ResponseBuilder rb{ctx, 3}; | 160 | IPC::ResponseBuilder rb{ctx, 3}; |
| 157 | |||
| 158 | rb.Push(ResultSuccess); | 161 | rb.Push(ResultSuccess); |
| 159 | rb.Push(buffer_count); | 162 | rb.Push(buffer_count); |
| 160 | } | 163 | } |
| @@ -165,7 +168,6 @@ private: | |||
| 165 | LOG_DEBUG(Service_Audio, "called. Played samples={}", samples_played); | 168 | LOG_DEBUG(Service_Audio, "called. Played samples={}", samples_played); |
| 166 | 169 | ||
| 167 | IPC::ResponseBuilder rb{ctx, 4}; | 170 | IPC::ResponseBuilder rb{ctx, 4}; |
| 168 | |||
| 169 | rb.Push(ResultSuccess); | 171 | rb.Push(ResultSuccess); |
| 170 | rb.Push(samples_played); | 172 | rb.Push(samples_played); |
| 171 | } | 173 | } |
| @@ -205,7 +207,7 @@ private: | |||
| 205 | KernelHelpers::ServiceContext service_context; | 207 | KernelHelpers::ServiceContext service_context; |
| 206 | Kernel::KEvent* event; | 208 | Kernel::KEvent* event; |
| 207 | std::shared_ptr<AudioCore::AudioOut::Out> impl; | 209 | std::shared_ptr<AudioCore::AudioOut::Out> impl; |
| 208 | Common::ScratchBuffer<u64> tmp_buffer; | 210 | Common::ScratchBuffer<u64> released_buffer; |
| 209 | }; | 211 | }; |
| 210 | 212 | ||
| 211 | AudOutU::AudOutU(Core::System& system_) | 213 | AudOutU::AudOutU(Core::System& system_) |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 12845c23a..003870176 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/common_funcs.h" | 15 | #include "common/common_funcs.h" |
| 16 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 17 | #include "common/polyfill_ranges.h" | 17 | #include "common/polyfill_ranges.h" |
| 18 | #include "common/scratch_buffer.h" | ||
| 18 | #include "common/string_util.h" | 19 | #include "common/string_util.h" |
| 19 | #include "core/core.h" | 20 | #include "core/core.h" |
| 20 | #include "core/hle/kernel/k_event.h" | 21 | #include "core/hle/kernel/k_event.h" |
| @@ -119,23 +120,23 @@ private: | |||
| 119 | auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0}; | 120 | auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0}; |
| 120 | if (is_buffer_b) { | 121 | if (is_buffer_b) { |
| 121 | const auto buffersB{ctx.BufferDescriptorB()}; | 122 | const auto buffersB{ctx.BufferDescriptorB()}; |
| 122 | tmp_output.resize_destructive(buffersB[0].Size()); | 123 | output_buffer.resize_destructive(buffersB[0].Size()); |
| 123 | tmp_performance.resize_destructive(buffersB[1].Size()); | 124 | performance_buffer.resize_destructive(buffersB[1].Size()); |
| 124 | } else { | 125 | } else { |
| 125 | const auto buffersC{ctx.BufferDescriptorC()}; | 126 | const auto buffersC{ctx.BufferDescriptorC()}; |
| 126 | tmp_output.resize_destructive(buffersC[0].Size()); | 127 | output_buffer.resize_destructive(buffersC[0].Size()); |
| 127 | tmp_performance.resize_destructive(buffersC[1].Size()); | 128 | performance_buffer.resize_destructive(buffersC[1].Size()); |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 130 | auto result = impl->RequestUpdate(input, tmp_performance, tmp_output); | 131 | auto result = impl->RequestUpdate(input, performance_buffer, output_buffer); |
| 131 | 132 | ||
| 132 | if (result.IsSuccess()) { | 133 | if (result.IsSuccess()) { |
| 133 | if (is_buffer_b) { | 134 | if (is_buffer_b) { |
| 134 | ctx.WriteBufferB(tmp_output.data(), tmp_output.size(), 0); | 135 | ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0); |
| 135 | ctx.WriteBufferB(tmp_performance.data(), tmp_performance.size(), 1); | 136 | ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1); |
| 136 | } else { | 137 | } else { |
| 137 | ctx.WriteBufferC(tmp_output.data(), tmp_output.size(), 0); | 138 | ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0); |
| 138 | ctx.WriteBufferC(tmp_performance.data(), tmp_performance.size(), 1); | 139 | ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1); |
| 139 | } | 140 | } |
| 140 | } else { | 141 | } else { |
| 141 | LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); | 142 | LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); |
| @@ -233,8 +234,8 @@ private: | |||
| 233 | Kernel::KEvent* rendered_event; | 234 | Kernel::KEvent* rendered_event; |
| 234 | Manager& manager; | 235 | Manager& manager; |
| 235 | std::unique_ptr<Renderer> impl; | 236 | std::unique_ptr<Renderer> impl; |
| 236 | Common::ScratchBuffer<u8> tmp_output; | 237 | Common::ScratchBuffer<u8> output_buffer; |
| 237 | Common::ScratchBuffer<u8> tmp_performance; | 238 | Common::ScratchBuffer<u8> performance_buffer; |
| 238 | }; | 239 | }; |
| 239 | 240 | ||
| 240 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { | 241 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index c835f6cb7..fa77007f3 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/scratch_buffer.h" | ||
| 14 | #include "core/hle/service/audio/hwopus.h" | 15 | #include "core/hle/service/audio/hwopus.h" |
| 15 | #include "core/hle/service/ipc_helpers.h" | 16 | #include "core/hle/service/ipc_helpers.h" |
| 16 | 17 | ||
| @@ -68,13 +69,13 @@ private: | |||
| 68 | ExtraBehavior extra_behavior) { | 69 | ExtraBehavior extra_behavior) { |
| 69 | u32 consumed = 0; | 70 | u32 consumed = 0; |
| 70 | u32 sample_count = 0; | 71 | u32 sample_count = 0; |
| 71 | tmp_samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>()); | 72 | samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>()); |
| 72 | 73 | ||
| 73 | if (extra_behavior == ExtraBehavior::ResetContext) { | 74 | if (extra_behavior == ExtraBehavior::ResetContext) { |
| 74 | ResetDecoderContext(); | 75 | ResetDecoderContext(); |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), tmp_samples, performance)) { | 78 | if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) { |
| 78 | LOG_ERROR(Audio, "Failed to decode opus data"); | 79 | LOG_ERROR(Audio, "Failed to decode opus data"); |
| 79 | IPC::ResponseBuilder rb{ctx, 2}; | 80 | IPC::ResponseBuilder rb{ctx, 2}; |
| 80 | // TODO(ogniK): Use correct error code | 81 | // TODO(ogniK): Use correct error code |
| @@ -90,7 +91,7 @@ private: | |||
| 90 | if (performance) { | 91 | if (performance) { |
| 91 | rb.Push<u64>(*performance); | 92 | rb.Push<u64>(*performance); |
| 92 | } | 93 | } |
| 93 | ctx.WriteBuffer(tmp_samples); | 94 | ctx.WriteBuffer(samples); |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input, | 97 | bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input, |
| @@ -154,7 +155,7 @@ private: | |||
| 154 | OpusDecoderPtr decoder; | 155 | OpusDecoderPtr decoder; |
| 155 | u32 sample_rate; | 156 | u32 sample_rate; |
| 156 | u32 channel_count; | 157 | u32 channel_count; |
| 157 | Common::ScratchBuffer<opus_int16> tmp_samples; | 158 | Common::ScratchBuffer<opus_int16> samples; |
| 158 | }; | 159 | }; |
| 159 | 160 | ||
| 160 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { | 161 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index 348207e25..c8a880e84 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | // SPDX-FileCopyrightText: 2021 Skyline Team and Contributors | 2 | // SPDX-FileCopyrightText: 2021 Skyline Team and Contributors |
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later | 3 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 4 | 4 | ||
| 5 | #include <cinttypes> | ||
| 6 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 6 | #include "core/core.h" |
| 8 | #include "core/hle/kernel/k_event.h" | 7 | #include "core/hle/kernel/k_event.h" |
| @@ -63,12 +62,12 @@ void NVDRV::Ioctl1(HLERequestContext& ctx) { | |||
| 63 | } | 62 | } |
| 64 | 63 | ||
| 65 | // Check device | 64 | // Check device |
| 66 | tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); | 65 | output_buffer.resize_destructive(ctx.GetWriteBufferSize(0)); |
| 67 | const auto input_buffer = ctx.ReadBuffer(0); | 66 | const auto input_buffer = ctx.ReadBuffer(0); |
| 68 | 67 | ||
| 69 | const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output); | 68 | const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer); |
| 70 | if (command.is_out != 0) { | 69 | if (command.is_out != 0) { |
| 71 | ctx.WriteBuffer(tmp_output); | 70 | ctx.WriteBuffer(output_buffer); |
| 72 | } | 71 | } |
| 73 | 72 | ||
| 74 | IPC::ResponseBuilder rb{ctx, 3}; | 73 | IPC::ResponseBuilder rb{ctx, 3}; |
| @@ -90,12 +89,12 @@ void NVDRV::Ioctl2(HLERequestContext& ctx) { | |||
| 90 | 89 | ||
| 91 | const auto input_buffer = ctx.ReadBuffer(0); | 90 | const auto input_buffer = ctx.ReadBuffer(0); |
| 92 | const auto input_inlined_buffer = ctx.ReadBuffer(1); | 91 | const auto input_inlined_buffer = ctx.ReadBuffer(1); |
| 93 | tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); | 92 | output_buffer.resize_destructive(ctx.GetWriteBufferSize(0)); |
| 94 | 93 | ||
| 95 | const auto nv_result = | 94 | const auto nv_result = |
| 96 | nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, tmp_output); | 95 | nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer); |
| 97 | if (command.is_out != 0) { | 96 | if (command.is_out != 0) { |
| 98 | ctx.WriteBuffer(tmp_output); | 97 | ctx.WriteBuffer(output_buffer); |
| 99 | } | 98 | } |
| 100 | 99 | ||
| 101 | IPC::ResponseBuilder rb{ctx, 3}; | 100 | IPC::ResponseBuilder rb{ctx, 3}; |
| @@ -116,12 +115,14 @@ void NVDRV::Ioctl3(HLERequestContext& ctx) { | |||
| 116 | } | 115 | } |
| 117 | 116 | ||
| 118 | const auto input_buffer = ctx.ReadBuffer(0); | 117 | const auto input_buffer = ctx.ReadBuffer(0); |
| 119 | tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); | 118 | output_buffer.resize_destructive(ctx.GetWriteBufferSize(0)); |
| 120 | tmp_output_inline.resize_destructive(ctx.GetWriteBufferSize(1)); | 119 | inline_output_buffer.resize_destructive(ctx.GetWriteBufferSize(1)); |
| 121 | const auto nv_result = nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output_inline); | 120 | |
| 121 | const auto nv_result = | ||
| 122 | nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, inline_output_buffer); | ||
| 122 | if (command.is_out != 0) { | 123 | if (command.is_out != 0) { |
| 123 | ctx.WriteBuffer(tmp_output, 0); | 124 | ctx.WriteBuffer(output_buffer, 0); |
| 124 | ctx.WriteBuffer(tmp_output_inline, 1); | 125 | ctx.WriteBuffer(inline_output_buffer, 1); |
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | IPC::ResponseBuilder rb{ctx, 3}; | 128 | IPC::ResponseBuilder rb{ctx, 3}; |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index 4b593ff90..6e98115dc 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | |||
| 7 | #include "common/scratch_buffer.h" | 8 | #include "common/scratch_buffer.h" |
| 8 | #include "core/hle/service/nvdrv/nvdrv.h" | 9 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 9 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| @@ -34,8 +35,8 @@ private: | |||
| 34 | 35 | ||
| 35 | u64 pid{}; | 36 | u64 pid{}; |
| 36 | bool is_initialized{}; | 37 | bool is_initialized{}; |
| 37 | Common::ScratchBuffer<u8> tmp_output; | 38 | Common::ScratchBuffer<u8> output_buffer; |
| 38 | Common::ScratchBuffer<u8> tmp_output_inline; | 39 | Common::ScratchBuffer<u8> inline_output_buffer; |
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 41 | } // namespace Service::Nvidia | 42 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvnflinger/parcel.h b/src/core/hle/service/nvnflinger/parcel.h index 23ba315a0..e2c9bbd50 100644 --- a/src/core/hle/service/nvnflinger/parcel.h +++ b/src/core/hle/service/nvnflinger/parcel.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <span> | 7 | #include <span> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | |||
| 9 | #include <boost/container/small_vector.hpp> | 10 | #include <boost/container/small_vector.hpp> |
| 10 | 11 | ||
| 11 | #include "common/alignment.h" | 12 | #include "common/alignment.h" |
| @@ -148,9 +149,9 @@ public: | |||
| 148 | this->WriteImpl(0U, m_object_buffer); | 149 | this->WriteImpl(0U, m_object_buffer); |
| 149 | } | 150 | } |
| 150 | 151 | ||
| 151 | std::vector<u8> Serialize() const { | 152 | std::span<u8> Serialize() { |
| 152 | std::vector<u8> output_buffer(sizeof(ParcelHeader) + m_data_buffer.size() + | 153 | m_output_buffer.resize(sizeof(ParcelHeader) + m_data_buffer.size() + |
| 153 | m_object_buffer.size()); | 154 | m_object_buffer.size()); |
| 154 | 155 | ||
| 155 | ParcelHeader header{}; | 156 | ParcelHeader header{}; |
| 156 | header.data_size = static_cast<u32>(m_data_buffer.size()); | 157 | header.data_size = static_cast<u32>(m_data_buffer.size()); |
| @@ -158,17 +159,17 @@ public: | |||
| 158 | header.objects_size = static_cast<u32>(m_object_buffer.size()); | 159 | header.objects_size = static_cast<u32>(m_object_buffer.size()); |
| 159 | header.objects_offset = header.data_offset + header.data_size; | 160 | header.objects_offset = header.data_offset + header.data_size; |
| 160 | 161 | ||
| 161 | std::memcpy(output_buffer.data(), &header, sizeof(header)); | 162 | std::memcpy(m_output_buffer.data(), &header, sizeof(ParcelHeader)); |
| 162 | std::ranges::copy(m_data_buffer, output_buffer.data() + header.data_offset); | 163 | std::ranges::copy(m_data_buffer, m_output_buffer.data() + header.data_offset); |
| 163 | std::ranges::copy(m_object_buffer, output_buffer.data() + header.objects_offset); | 164 | std::ranges::copy(m_object_buffer, m_output_buffer.data() + header.objects_offset); |
| 164 | 165 | ||
| 165 | return output_buffer; | 166 | return m_output_buffer; |
| 166 | } | 167 | } |
| 167 | 168 | ||
| 168 | private: | 169 | private: |
| 169 | template <typename T> | 170 | template <typename T, size_t BufferSize> |
| 170 | requires(std::is_trivially_copyable_v<T>) | 171 | requires(std::is_trivially_copyable_v<T>) |
| 171 | void WriteImpl(const T& val, boost::container::small_vector<u8, 0x200>& buffer) { | 172 | void WriteImpl(const T& val, boost::container::small_vector<u8, BufferSize>& buffer) { |
| 172 | const size_t aligned_size = Common::AlignUp(sizeof(T), 4); | 173 | const size_t aligned_size = Common::AlignUp(sizeof(T), 4); |
| 173 | const size_t old_size = buffer.size(); | 174 | const size_t old_size = buffer.size(); |
| 174 | buffer.resize(old_size + aligned_size); | 175 | buffer.resize(old_size + aligned_size); |
| @@ -177,8 +178,9 @@ private: | |||
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | private: | 180 | private: |
| 180 | boost::container::small_vector<u8, 0x200> m_data_buffer; | 181 | boost::container::small_vector<u8, 0x1B0> m_data_buffer; |
| 181 | boost::container::small_vector<u8, 0x200> m_object_buffer; | 182 | boost::container::small_vector<u8, 0x40> m_object_buffer; |
| 183 | boost::container::small_vector<u8, 0x200> m_output_buffer; | ||
| 182 | }; | 184 | }; |
| 183 | 185 | ||
| 184 | } // namespace Service::android | 186 | } // namespace Service::android |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 514ba0d66..257406f09 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <span> | ||
| 6 | 7 | ||
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 8 | #include "common/atomic_ops.h" | 9 | #include "common/atomic_ops.h" |
| @@ -13,6 +14,7 @@ | |||
| 13 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/device_memory.h" | 16 | #include "core/device_memory.h" |
| 17 | #include "core/gpu_dirty_memory_manager.h" | ||
| 16 | #include "core/hardware_properties.h" | 18 | #include "core/hardware_properties.h" |
| 17 | #include "core/hle/kernel/k_page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 18 | #include "core/hle/kernel/k_process.h" | 20 | #include "core/hle/kernel/k_process.h" |
| @@ -678,7 +680,7 @@ struct Memory::Impl { | |||
| 678 | LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, | 680 | LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, |
| 679 | GetInteger(vaddr), static_cast<u64>(data)); | 681 | GetInteger(vaddr), static_cast<u64>(data)); |
| 680 | }, | 682 | }, |
| 681 | [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(T)); }); | 683 | [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); }); |
| 682 | if (ptr) { | 684 | if (ptr) { |
| 683 | std::memcpy(ptr, &data, sizeof(T)); | 685 | std::memcpy(ptr, &data, sizeof(T)); |
| 684 | } | 686 | } |
| @@ -692,7 +694,7 @@ struct Memory::Impl { | |||
| 692 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}", | 694 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}", |
| 693 | sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data)); | 695 | sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data)); |
| 694 | }, | 696 | }, |
| 695 | [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(T)); }); | 697 | [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); }); |
| 696 | if (ptr) { | 698 | if (ptr) { |
| 697 | const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); | 699 | const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); |
| 698 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); | 700 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); |
| @@ -707,7 +709,7 @@ struct Memory::Impl { | |||
| 707 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}", | 709 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}", |
| 708 | GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0])); | 710 | GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0])); |
| 709 | }, | 711 | }, |
| 710 | [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(u128)); }); | 712 | [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); }); |
| 711 | if (ptr) { | 713 | if (ptr) { |
| 712 | const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); | 714 | const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); |
| 713 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); | 715 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); |
| @@ -717,7 +719,7 @@ struct Memory::Impl { | |||
| 717 | 719 | ||
| 718 | void HandleRasterizerDownload(VAddr address, size_t size) { | 720 | void HandleRasterizerDownload(VAddr address, size_t size) { |
| 719 | const size_t core = system.GetCurrentHostThreadID(); | 721 | const size_t core = system.GetCurrentHostThreadID(); |
| 720 | auto& current_area = rasterizer_areas[core]; | 722 | auto& current_area = rasterizer_read_areas[core]; |
| 721 | const VAddr end_address = address + size; | 723 | const VAddr end_address = address + size; |
| 722 | if (current_area.start_address <= address && end_address <= current_area.end_address) | 724 | if (current_area.start_address <= address && end_address <= current_area.end_address) |
| 723 | [[likely]] { | 725 | [[likely]] { |
| @@ -726,9 +728,31 @@ struct Memory::Impl { | |||
| 726 | current_area = system.GPU().OnCPURead(address, size); | 728 | current_area = system.GPU().OnCPURead(address, size); |
| 727 | } | 729 | } |
| 728 | 730 | ||
| 729 | Common::PageTable* current_page_table = nullptr; | 731 | void HandleRasterizerWrite(VAddr address, size_t size) { |
| 730 | std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> rasterizer_areas{}; | 732 | const size_t core = system.GetCurrentHostThreadID(); |
| 733 | auto& current_area = rasterizer_write_areas[core]; | ||
| 734 | VAddr subaddress = address >> YUZU_PAGEBITS; | ||
| 735 | bool do_collection = current_area.last_address == subaddress; | ||
| 736 | if (!do_collection) [[unlikely]] { | ||
| 737 | do_collection = system.GPU().OnCPUWrite(address, size); | ||
| 738 | if (!do_collection) { | ||
| 739 | return; | ||
| 740 | } | ||
| 741 | current_area.last_address = subaddress; | ||
| 742 | } | ||
| 743 | gpu_dirty_managers[core].Collect(address, size); | ||
| 744 | } | ||
| 745 | |||
| 746 | struct GPUDirtyState { | ||
| 747 | VAddr last_address; | ||
| 748 | }; | ||
| 749 | |||
| 731 | Core::System& system; | 750 | Core::System& system; |
| 751 | Common::PageTable* current_page_table = nullptr; | ||
| 752 | std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> | ||
| 753 | rasterizer_read_areas{}; | ||
| 754 | std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; | ||
| 755 | std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; | ||
| 732 | }; | 756 | }; |
| 733 | 757 | ||
| 734 | Memory::Memory(Core::System& system_) : system{system_} { | 758 | Memory::Memory(Core::System& system_) : system{system_} { |
| @@ -876,6 +900,10 @@ void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) | |||
| 876 | impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); | 900 | impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); |
| 877 | } | 901 | } |
| 878 | 902 | ||
| 903 | void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { | ||
| 904 | impl->gpu_dirty_managers = managers; | ||
| 905 | } | ||
| 906 | |||
| 879 | Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { | 907 | Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { |
| 880 | return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); | 908 | return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); |
| 881 | } | 909 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 72a0be813..ea01824f8 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <cstddef> | 6 | #include <cstddef> |
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <span> | ||
| 8 | #include <string> | 9 | #include <string> |
| 9 | #include "common/typed_address.h" | 10 | #include "common/typed_address.h" |
| 10 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| @@ -15,7 +16,8 @@ struct PageTable; | |||
| 15 | 16 | ||
| 16 | namespace Core { | 17 | namespace Core { |
| 17 | class System; | 18 | class System; |
| 18 | } | 19 | class GPUDirtyMemoryManager; |
| 20 | } // namespace Core | ||
| 19 | 21 | ||
| 20 | namespace Kernel { | 22 | namespace Kernel { |
| 21 | class PhysicalMemory; | 23 | class PhysicalMemory; |
| @@ -458,6 +460,8 @@ public: | |||
| 458 | */ | 460 | */ |
| 459 | void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); | 461 | void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); |
| 460 | 462 | ||
| 463 | void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers); | ||
| 464 | |||
| 461 | private: | 465 | private: |
| 462 | Core::System& system; | 466 | Core::System& system; |
| 463 | 467 | ||
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index 52494e0d9..0aca5a3a3 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp | |||
| @@ -102,12 +102,12 @@ bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const { | |||
| 102 | Joycon::SerialNumber serial_number{}; | 102 | Joycon::SerialNumber serial_number{}; |
| 103 | 103 | ||
| 104 | const auto result = Joycon::JoyconDriver::GetDeviceType(device_info, type); | 104 | const auto result = Joycon::JoyconDriver::GetDeviceType(device_info, type); |
| 105 | if (result != Joycon::DriverResult::Success) { | 105 | if (result != Common::Input::DriverResult::Success) { |
| 106 | return false; | 106 | return false; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | const auto result2 = Joycon::JoyconDriver::GetSerialNumber(device_info, serial_number); | 109 | const auto result2 = Joycon::JoyconDriver::GetSerialNumber(device_info, serial_number); |
| 110 | if (result2 != Joycon::DriverResult::Success) { | 110 | if (result2 != Common::Input::DriverResult::Success) { |
| 111 | return false; | 111 | return false; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| @@ -171,10 +171,10 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) { | |||
| 171 | LOG_WARNING(Input, "No free handles available"); | 171 | LOG_WARNING(Input, "No free handles available"); |
| 172 | return; | 172 | return; |
| 173 | } | 173 | } |
| 174 | if (result == Joycon::DriverResult::Success) { | 174 | if (result == Common::Input::DriverResult::Success) { |
| 175 | result = handle->RequestDeviceAccess(device_info); | 175 | result = handle->RequestDeviceAccess(device_info); |
| 176 | } | 176 | } |
| 177 | if (result == Joycon::DriverResult::Success) { | 177 | if (result == Common::Input::DriverResult::Success) { |
| 178 | LOG_WARNING(Input, "Initialize device"); | 178 | LOG_WARNING(Input, "Initialize device"); |
| 179 | 179 | ||
| 180 | const std::size_t port = handle->GetDevicePort(); | 180 | const std::size_t port = handle->GetDevicePort(); |
| @@ -273,8 +273,7 @@ Common::Input::DriverResult Joycons::SetLeds(const PadIdentifier& identifier, | |||
| 273 | led_config += led_status.led_3 ? 4 : 0; | 273 | led_config += led_status.led_3 ? 4 : 0; |
| 274 | led_config += led_status.led_4 ? 8 : 0; | 274 | led_config += led_status.led_4 ? 8 : 0; |
| 275 | 275 | ||
| 276 | return static_cast<Common::Input::DriverResult>( | 276 | return handle->SetLedConfig(static_cast<u8>(led_config)); |
| 277 | handle->SetLedConfig(static_cast<u8>(led_config))); | ||
| 278 | } | 277 | } |
| 279 | 278 | ||
| 280 | Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier, | 279 | Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier, |
| @@ -283,8 +282,8 @@ Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identi | |||
| 283 | if (handle == nullptr) { | 282 | if (handle == nullptr) { |
| 284 | return Common::Input::DriverResult::InvalidHandle; | 283 | return Common::Input::DriverResult::InvalidHandle; |
| 285 | } | 284 | } |
| 286 | return static_cast<Common::Input::DriverResult>(handle->SetIrsConfig( | 285 | return handle->SetIrsConfig(Joycon::IrsMode::ImageTransfer, |
| 287 | Joycon::IrsMode::ImageTransfer, static_cast<Joycon::IrsResolution>(camera_format))); | 286 | static_cast<Joycon::IrsResolution>(camera_format)); |
| 288 | }; | 287 | }; |
| 289 | 288 | ||
| 290 | Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const { | 289 | Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const { |
| @@ -351,7 +350,7 @@ Common::Input::NfcState Joycons::ReadMifareData(const PadIdentifier& identifier, | |||
| 351 | 350 | ||
| 352 | std::vector<Joycon::MifareReadData> read_data(read_request.size()); | 351 | std::vector<Joycon::MifareReadData> read_data(read_request.size()); |
| 353 | const auto result = handle->ReadMifareData(read_request, read_data); | 352 | const auto result = handle->ReadMifareData(read_request, read_data); |
| 354 | if (result == Joycon::DriverResult::Success) { | 353 | if (result == Common::Input::DriverResult::Success) { |
| 355 | for (std::size_t i = 0; i < read_request.size(); i++) { | 354 | for (std::size_t i = 0; i < read_request.size(); i++) { |
| 356 | data.data[i] = { | 355 | data.data[i] = { |
| 357 | .command = static_cast<u8>(command), | 356 | .command = static_cast<u8>(command), |
| @@ -402,15 +401,15 @@ Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identif | |||
| 402 | 401 | ||
| 403 | switch (polling_mode) { | 402 | switch (polling_mode) { |
| 404 | case Common::Input::PollingMode::Active: | 403 | case Common::Input::PollingMode::Active: |
| 405 | return static_cast<Common::Input::DriverResult>(handle->SetActiveMode()); | 404 | return handle->SetActiveMode(); |
| 406 | case Common::Input::PollingMode::Passive: | 405 | case Common::Input::PollingMode::Passive: |
| 407 | return static_cast<Common::Input::DriverResult>(handle->SetPassiveMode()); | 406 | return handle->SetPassiveMode(); |
| 408 | case Common::Input::PollingMode::IR: | 407 | case Common::Input::PollingMode::IR: |
| 409 | return static_cast<Common::Input::DriverResult>(handle->SetIrMode()); | 408 | return handle->SetIrMode(); |
| 410 | case Common::Input::PollingMode::NFC: | 409 | case Common::Input::PollingMode::NFC: |
| 411 | return static_cast<Common::Input::DriverResult>(handle->SetNfcMode()); | 410 | return handle->SetNfcMode(); |
| 412 | case Common::Input::PollingMode::Ring: | 411 | case Common::Input::PollingMode::Ring: |
| 413 | return static_cast<Common::Input::DriverResult>(handle->SetRingConMode()); | 412 | return handle->SetRingConMode(); |
| 414 | default: | 413 | default: |
| 415 | return Common::Input::DriverResult::NotSupported; | 414 | return Common::Input::DriverResult::NotSupported; |
| 416 | } | 415 | } |
| @@ -828,13 +827,13 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const { | |||
| 828 | } | 827 | } |
| 829 | } | 828 | } |
| 830 | 829 | ||
| 831 | Common::Input::NfcState Joycons::TranslateDriverResult(Joycon::DriverResult result) const { | 830 | Common::Input::NfcState Joycons::TranslateDriverResult(Common::Input::DriverResult result) const { |
| 832 | switch (result) { | 831 | switch (result) { |
| 833 | case Joycon::DriverResult::Success: | 832 | case Common::Input::DriverResult::Success: |
| 834 | return Common::Input::NfcState::Success; | 833 | return Common::Input::NfcState::Success; |
| 835 | case Joycon::DriverResult::Disabled: | 834 | case Common::Input::DriverResult::Disabled: |
| 836 | return Common::Input::NfcState::WrongDeviceState; | 835 | return Common::Input::NfcState::WrongDeviceState; |
| 837 | case Joycon::DriverResult::NotSupported: | 836 | case Common::Input::DriverResult::NotSupported: |
| 838 | return Common::Input::NfcState::NotSupported; | 837 | return Common::Input::NfcState::NotSupported; |
| 839 | default: | 838 | default: |
| 840 | return Common::Input::NfcState::Unknown; | 839 | return Common::Input::NfcState::Unknown; |
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index 4c323d7d6..112e970e1 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h | |||
| @@ -17,7 +17,6 @@ struct Color; | |||
| 17 | struct MotionData; | 17 | struct MotionData; |
| 18 | struct TagInfo; | 18 | struct TagInfo; |
| 19 | enum class ControllerType : u8; | 19 | enum class ControllerType : u8; |
| 20 | enum class DriverResult; | ||
| 21 | enum class IrsResolution; | 20 | enum class IrsResolution; |
| 22 | class JoyconDriver; | 21 | class JoyconDriver; |
| 23 | } // namespace InputCommon::Joycon | 22 | } // namespace InputCommon::Joycon |
| @@ -112,7 +111,7 @@ private: | |||
| 112 | /// Returns the name of the device in text format | 111 | /// Returns the name of the device in text format |
| 113 | std::string JoyconName(Joycon::ControllerType type) const; | 112 | std::string JoyconName(Joycon::ControllerType type) const; |
| 114 | 113 | ||
| 115 | Common::Input::NfcState TranslateDriverResult(Joycon::DriverResult result) const; | 114 | Common::Input::NfcState TranslateDriverResult(Common::Input::DriverResult result) const; |
| 116 | 115 | ||
| 117 | std::jthread scan_thread; | 116 | std::jthread scan_thread; |
| 118 | 117 | ||
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index f07cf8a0e..dac29c78f 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp | |||
| @@ -12,9 +12,13 @@ | |||
| 12 | 12 | ||
| 13 | namespace InputCommon { | 13 | namespace InputCommon { |
| 14 | constexpr int update_time = 10; | 14 | constexpr int update_time = 10; |
| 15 | constexpr float default_stick_sensitivity = 0.0044f; | 15 | constexpr float default_panning_sensitivity = 0.0010f; |
| 16 | constexpr float default_motion_sensitivity = 0.0003f; | 16 | constexpr float default_stick_sensitivity = 0.0006f; |
| 17 | constexpr float default_deadzone_counterweight = 0.01f; | ||
| 18 | constexpr float default_motion_panning_sensitivity = 2.5f; | ||
| 19 | constexpr float default_motion_sensitivity = 0.416f; | ||
| 17 | constexpr float maximum_rotation_speed = 2.0f; | 20 | constexpr float maximum_rotation_speed = 2.0f; |
| 21 | constexpr float maximum_stick_range = 1.5f; | ||
| 18 | constexpr int mouse_axis_x = 0; | 22 | constexpr int mouse_axis_x = 0; |
| 19 | constexpr int mouse_axis_y = 1; | 23 | constexpr int mouse_axis_y = 1; |
| 20 | constexpr int wheel_axis_x = 2; | 24 | constexpr int wheel_axis_x = 2; |
| @@ -81,7 +85,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) { | |||
| 81 | } | 85 | } |
| 82 | 86 | ||
| 83 | void Mouse::UpdateStickInput() { | 87 | void Mouse::UpdateStickInput() { |
| 84 | if (!Settings::values.mouse_panning) { | 88 | if (!IsMousePanningEnabled()) { |
| 85 | return; | 89 | return; |
| 86 | } | 90 | } |
| 87 | 91 | ||
| @@ -89,26 +93,13 @@ void Mouse::UpdateStickInput() { | |||
| 89 | 93 | ||
| 90 | // Prevent input from exceeding the max range (1.0f) too much, | 94 | // Prevent input from exceeding the max range (1.0f) too much, |
| 91 | // but allow some room to make it easier to sustain | 95 | // but allow some room to make it easier to sustain |
| 92 | if (length > 1.2f) { | 96 | if (length > maximum_stick_range) { |
| 93 | last_mouse_change /= length; | 97 | last_mouse_change /= length; |
| 94 | last_mouse_change *= 1.2f; | 98 | last_mouse_change *= maximum_stick_range; |
| 95 | } | 99 | } |
| 96 | 100 | ||
| 97 | auto mouse_change = last_mouse_change; | 101 | SetAxis(identifier, mouse_axis_x, last_mouse_change.x); |
| 98 | 102 | SetAxis(identifier, mouse_axis_y, -last_mouse_change.y); | |
| 99 | // Bind the mouse change to [0 <= deadzone_counterweight <= 1,1] | ||
| 100 | if (length < 1.0f) { | ||
| 101 | const float deadzone_h_counterweight = | ||
| 102 | Settings::values.mouse_panning_deadzone_x_counterweight.GetValue(); | ||
| 103 | const float deadzone_v_counterweight = | ||
| 104 | Settings::values.mouse_panning_deadzone_y_counterweight.GetValue(); | ||
| 105 | mouse_change /= length; | ||
| 106 | mouse_change.x *= length + (1 - length) * deadzone_h_counterweight * 0.01f; | ||
| 107 | mouse_change.y *= length + (1 - length) * deadzone_v_counterweight * 0.01f; | ||
| 108 | } | ||
| 109 | |||
| 110 | SetAxis(identifier, mouse_axis_x, mouse_change.x); | ||
| 111 | SetAxis(identifier, mouse_axis_y, -mouse_change.y); | ||
| 112 | 103 | ||
| 113 | // Decay input over time | 104 | // Decay input over time |
| 114 | const float clamped_length = std::min(1.0f, length); | 105 | const float clamped_length = std::min(1.0f, length); |
| @@ -120,14 +111,13 @@ void Mouse::UpdateStickInput() { | |||
| 120 | } | 111 | } |
| 121 | 112 | ||
| 122 | void Mouse::UpdateMotionInput() { | 113 | void Mouse::UpdateMotionInput() { |
| 123 | // This may need its own sensitivity instead of using the average | 114 | const float sensitivity = |
| 124 | const float sensitivity = (Settings::values.mouse_panning_x_sensitivity.GetValue() + | 115 | IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity; |
| 125 | Settings::values.mouse_panning_y_sensitivity.GetValue()) / | ||
| 126 | 2.0f * default_motion_sensitivity; | ||
| 127 | 116 | ||
| 128 | const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + | 117 | const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + |
| 129 | last_motion_change.y * last_motion_change.y); | 118 | last_motion_change.y * last_motion_change.y); |
| 130 | 119 | ||
| 120 | // Clamp rotation speed | ||
| 131 | if (rotation_velocity > maximum_rotation_speed / sensitivity) { | 121 | if (rotation_velocity > maximum_rotation_speed / sensitivity) { |
| 132 | const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity; | 122 | const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity; |
| 133 | last_motion_change.x = last_motion_change.x * multiplier; | 123 | last_motion_change.x = last_motion_change.x * multiplier; |
| @@ -144,7 +134,7 @@ void Mouse::UpdateMotionInput() { | |||
| 144 | .delta_timestamp = update_time * 1000, | 134 | .delta_timestamp = update_time * 1000, |
| 145 | }; | 135 | }; |
| 146 | 136 | ||
| 147 | if (Settings::values.mouse_panning) { | 137 | if (IsMousePanningEnabled()) { |
| 148 | last_motion_change.x = 0; | 138 | last_motion_change.x = 0; |
| 149 | last_motion_change.y = 0; | 139 | last_motion_change.y = 0; |
| 150 | } | 140 | } |
| @@ -154,33 +144,42 @@ void Mouse::UpdateMotionInput() { | |||
| 154 | } | 144 | } |
| 155 | 145 | ||
| 156 | void Mouse::Move(int x, int y, int center_x, int center_y) { | 146 | void Mouse::Move(int x, int y, int center_x, int center_y) { |
| 157 | if (Settings::values.mouse_panning) { | 147 | if (IsMousePanningEnabled()) { |
| 158 | const auto mouse_change = | 148 | const auto mouse_change = |
| 159 | (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); | 149 | (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); |
| 160 | const float x_sensitivity = | 150 | const float x_sensitivity = |
| 161 | Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity; | 151 | Settings::values.mouse_panning_x_sensitivity.GetValue() * default_panning_sensitivity; |
| 162 | const float y_sensitivity = | 152 | const float y_sensitivity = |
| 163 | Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity; | 153 | Settings::values.mouse_panning_y_sensitivity.GetValue() * default_panning_sensitivity; |
| 154 | const float deadzone_counterweight = | ||
| 155 | Settings::values.mouse_panning_deadzone_counterweight.GetValue() * | ||
| 156 | default_deadzone_counterweight; | ||
| 157 | |||
| 158 | last_motion_change += {-mouse_change.y * x_sensitivity, -mouse_change.x * y_sensitivity, 0}; | ||
| 159 | last_mouse_change.x += mouse_change.x * x_sensitivity; | ||
| 160 | last_mouse_change.y += mouse_change.y * y_sensitivity; | ||
| 164 | 161 | ||
| 165 | last_motion_change += {-mouse_change.y, -mouse_change.x, 0}; | 162 | // Bind the mouse change to [0 <= deadzone_counterweight <= 1.0] |
| 166 | last_mouse_change.x += mouse_change.x * x_sensitivity * 0.09f; | 163 | if (last_mouse_change.Length() < deadzone_counterweight) { |
| 167 | last_mouse_change.y += mouse_change.y * y_sensitivity * 0.09f; | 164 | last_mouse_change /= last_mouse_change.Length(); |
| 165 | last_mouse_change *= deadzone_counterweight; | ||
| 166 | } | ||
| 168 | 167 | ||
| 169 | return; | 168 | return; |
| 170 | } | 169 | } |
| 171 | 170 | ||
| 172 | if (button_pressed) { | 171 | if (button_pressed) { |
| 173 | const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; | 172 | const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; |
| 174 | const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue(); | 173 | const float x_sensitivity = |
| 175 | const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue(); | 174 | Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity; |
| 176 | SetAxis(identifier, mouse_axis_x, | 175 | const float y_sensitivity = |
| 177 | static_cast<float>(mouse_move.x) * x_sensitivity * 0.0012f); | 176 | Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity; |
| 178 | SetAxis(identifier, mouse_axis_y, | 177 | SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * x_sensitivity); |
| 179 | static_cast<float>(-mouse_move.y) * y_sensitivity * 0.0012f); | 178 | SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * y_sensitivity); |
| 180 | 179 | ||
| 181 | last_motion_change = { | 180 | last_motion_change = { |
| 182 | static_cast<float>(-mouse_move.y) / 50.0f, | 181 | static_cast<float>(-mouse_move.y) * x_sensitivity, |
| 183 | static_cast<float>(-mouse_move.x) / 50.0f, | 182 | static_cast<float>(-mouse_move.x) * y_sensitivity, |
| 184 | last_motion_change.z, | 183 | last_motion_change.z, |
| 185 | }; | 184 | }; |
| 186 | } | 185 | } |
| @@ -220,7 +219,7 @@ void Mouse::ReleaseButton(MouseButton button) { | |||
| 220 | SetButton(real_mouse_identifier, static_cast<int>(button), false); | 219 | SetButton(real_mouse_identifier, static_cast<int>(button), false); |
| 221 | SetButton(touch_identifier, static_cast<int>(button), false); | 220 | SetButton(touch_identifier, static_cast<int>(button), false); |
| 222 | 221 | ||
| 223 | if (!Settings::values.mouse_panning) { | 222 | if (!IsMousePanningEnabled()) { |
| 224 | SetAxis(identifier, mouse_axis_x, 0); | 223 | SetAxis(identifier, mouse_axis_x, 0); |
| 225 | SetAxis(identifier, mouse_axis_y, 0); | 224 | SetAxis(identifier, mouse_axis_y, 0); |
| 226 | } | 225 | } |
| @@ -234,7 +233,7 @@ void Mouse::ReleaseButton(MouseButton button) { | |||
| 234 | void Mouse::MouseWheelChange(int x, int y) { | 233 | void Mouse::MouseWheelChange(int x, int y) { |
| 235 | wheel_position.x += x; | 234 | wheel_position.x += x; |
| 236 | wheel_position.y += y; | 235 | wheel_position.y += y; |
| 237 | last_motion_change.z += static_cast<f32>(y) / 100.0f; | 236 | last_motion_change.z += static_cast<f32>(y); |
| 238 | SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); | 237 | SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); |
| 239 | SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); | 238 | SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); |
| 240 | } | 239 | } |
| @@ -244,6 +243,11 @@ void Mouse::ReleaseAllButtons() { | |||
| 244 | button_pressed = false; | 243 | button_pressed = false; |
| 245 | } | 244 | } |
| 246 | 245 | ||
| 246 | bool Mouse::IsMousePanningEnabled() { | ||
| 247 | // Disable mouse panning when a real mouse is connected | ||
| 248 | return Settings::values.mouse_panning && !Settings::values.mouse_enabled; | ||
| 249 | } | ||
| 250 | |||
| 247 | std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { | 251 | std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { |
| 248 | std::vector<Common::ParamPackage> devices; | 252 | std::vector<Common::ParamPackage> devices; |
| 249 | devices.emplace_back(Common::ParamPackage{ | 253 | devices.emplace_back(Common::ParamPackage{ |
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 0e8edcce1..2b93a40b9 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h | |||
| @@ -99,6 +99,8 @@ private: | |||
| 99 | void UpdateStickInput(); | 99 | void UpdateStickInput(); |
| 100 | void UpdateMotionInput(); | 100 | void UpdateMotionInput(); |
| 101 | 101 | ||
| 102 | bool IsMousePanningEnabled(); | ||
| 103 | |||
| 102 | Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; | 104 | Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; |
| 103 | 105 | ||
| 104 | Common::Vec2<int> mouse_origin; | 106 | Common::Vec2<int> mouse_origin; |
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index ec984a647..cf51f3481 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/input.h" | ||
| 4 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 5 | #include "common/scope_exit.h" | 6 | #include "common/scope_exit.h" |
| 6 | #include "common/swap.h" | 7 | #include "common/swap.h" |
| @@ -28,13 +29,13 @@ void JoyconDriver::Stop() { | |||
| 28 | input_thread = {}; | 29 | input_thread = {}; |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | DriverResult JoyconDriver::RequestDeviceAccess(SDL_hid_device_info* device_info) { | 32 | Common::Input::DriverResult JoyconDriver::RequestDeviceAccess(SDL_hid_device_info* device_info) { |
| 32 | std::scoped_lock lock{mutex}; | 33 | std::scoped_lock lock{mutex}; |
| 33 | 34 | ||
| 34 | handle_device_type = ControllerType::None; | 35 | handle_device_type = ControllerType::None; |
| 35 | GetDeviceType(device_info, handle_device_type); | 36 | GetDeviceType(device_info, handle_device_type); |
| 36 | if (handle_device_type == ControllerType::None) { | 37 | if (handle_device_type == ControllerType::None) { |
| 37 | return DriverResult::UnsupportedControllerType; | 38 | return Common::Input::DriverResult::UnsupportedControllerType; |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | hidapi_handle->handle = | 41 | hidapi_handle->handle = |
| @@ -43,15 +44,15 @@ DriverResult JoyconDriver::RequestDeviceAccess(SDL_hid_device_info* device_info) | |||
| 43 | if (!hidapi_handle->handle) { | 44 | if (!hidapi_handle->handle) { |
| 44 | LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.", | 45 | LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.", |
| 45 | device_info->vendor_id, device_info->product_id); | 46 | device_info->vendor_id, device_info->product_id); |
| 46 | return DriverResult::HandleInUse; | 47 | return Common::Input::DriverResult::HandleInUse; |
| 47 | } | 48 | } |
| 48 | SDL_hid_set_nonblocking(hidapi_handle->handle, 1); | 49 | SDL_hid_set_nonblocking(hidapi_handle->handle, 1); |
| 49 | return DriverResult::Success; | 50 | return Common::Input::DriverResult::Success; |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 52 | DriverResult JoyconDriver::InitializeDevice() { | 53 | Common::Input::DriverResult JoyconDriver::InitializeDevice() { |
| 53 | if (!hidapi_handle->handle) { | 54 | if (!hidapi_handle->handle) { |
| 54 | return DriverResult::InvalidHandle; | 55 | return Common::Input::DriverResult::InvalidHandle; |
| 55 | } | 56 | } |
| 56 | std::scoped_lock lock{mutex}; | 57 | std::scoped_lock lock{mutex}; |
| 57 | disable_input_thread = true; | 58 | disable_input_thread = true; |
| @@ -87,7 +88,7 @@ DriverResult JoyconDriver::InitializeDevice() { | |||
| 87 | rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle); | 88 | rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle); |
| 88 | 89 | ||
| 89 | // Get fixed joycon info | 90 | // Get fixed joycon info |
| 90 | if (generic_protocol->GetVersionNumber(version) != DriverResult::Success) { | 91 | if (generic_protocol->GetVersionNumber(version) != Common::Input::DriverResult::Success) { |
| 91 | // If this command fails the device doesn't accept configuration commands | 92 | // If this command fails the device doesn't accept configuration commands |
| 92 | input_only_device = true; | 93 | input_only_device = true; |
| 93 | } | 94 | } |
| @@ -129,7 +130,7 @@ DriverResult JoyconDriver::InitializeDevice() { | |||
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | disable_input_thread = false; | 132 | disable_input_thread = false; |
| 132 | return DriverResult::Success; | 133 | return Common::Input::DriverResult::Success; |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | void JoyconDriver::InputThread(std::stop_token stop_token) { | 136 | void JoyconDriver::InputThread(std::stop_token stop_token) { |
| @@ -229,7 +230,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 229 | if (!amiibo_detected) { | 230 | if (!amiibo_detected) { |
| 230 | Joycon::TagInfo tag_info; | 231 | Joycon::TagInfo tag_info; |
| 231 | const auto result = nfc_protocol->GetTagInfo(tag_info); | 232 | const auto result = nfc_protocol->GetTagInfo(tag_info); |
| 232 | if (result == DriverResult::Success) { | 233 | if (result == Common::Input::DriverResult::Success) { |
| 233 | joycon_poller->UpdateAmiibo(tag_info); | 234 | joycon_poller->UpdateAmiibo(tag_info); |
| 234 | amiibo_detected = true; | 235 | amiibo_detected = true; |
| 235 | } | 236 | } |
| @@ -255,7 +256,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 255 | } | 256 | } |
| 256 | } | 257 | } |
| 257 | 258 | ||
| 258 | DriverResult JoyconDriver::SetPollingMode() { | 259 | Common::Input::DriverResult JoyconDriver::SetPollingMode() { |
| 259 | SCOPE_EXIT({ disable_input_thread = false; }); | 260 | SCOPE_EXIT({ disable_input_thread = false; }); |
| 260 | disable_input_thread = true; | 261 | disable_input_thread = true; |
| 261 | 262 | ||
| @@ -270,7 +271,7 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | if (input_only_device) { | 273 | if (input_only_device) { |
| 273 | return DriverResult::NotSupported; | 274 | return Common::Input::DriverResult::NotSupported; |
| 274 | } | 275 | } |
| 275 | 276 | ||
| 276 | if (irs_protocol->IsEnabled()) { | 277 | if (irs_protocol->IsEnabled()) { |
| @@ -289,7 +290,7 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 289 | 290 | ||
| 290 | if (irs_enabled && supported_features.irs) { | 291 | if (irs_enabled && supported_features.irs) { |
| 291 | auto result = irs_protocol->EnableIrs(); | 292 | auto result = irs_protocol->EnableIrs(); |
| 292 | if (result == DriverResult::Success) { | 293 | if (result == Common::Input::DriverResult::Success) { |
| 293 | return result; | 294 | return result; |
| 294 | } | 295 | } |
| 295 | irs_protocol->DisableIrs(); | 296 | irs_protocol->DisableIrs(); |
| @@ -299,7 +300,7 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 299 | 300 | ||
| 300 | if (nfc_enabled && supported_features.nfc) { | 301 | if (nfc_enabled && supported_features.nfc) { |
| 301 | auto result = nfc_protocol->EnableNfc(); | 302 | auto result = nfc_protocol->EnableNfc(); |
| 302 | if (result == DriverResult::Success) { | 303 | if (result == Common::Input::DriverResult::Success) { |
| 303 | return result; | 304 | return result; |
| 304 | } | 305 | } |
| 305 | nfc_protocol->DisableNfc(); | 306 | nfc_protocol->DisableNfc(); |
| @@ -309,10 +310,10 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 309 | 310 | ||
| 310 | if (hidbus_enabled && supported_features.hidbus) { | 311 | if (hidbus_enabled && supported_features.hidbus) { |
| 311 | auto result = ring_protocol->EnableRingCon(); | 312 | auto result = ring_protocol->EnableRingCon(); |
| 312 | if (result == DriverResult::Success) { | 313 | if (result == Common::Input::DriverResult::Success) { |
| 313 | result = ring_protocol->StartRingconPolling(); | 314 | result = ring_protocol->StartRingconPolling(); |
| 314 | } | 315 | } |
| 315 | if (result == DriverResult::Success) { | 316 | if (result == Common::Input::DriverResult::Success) { |
| 316 | ring_connected = true; | 317 | ring_connected = true; |
| 317 | return result; | 318 | return result; |
| 318 | } | 319 | } |
| @@ -324,7 +325,7 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 324 | 325 | ||
| 325 | if (passive_enabled && supported_features.passive) { | 326 | if (passive_enabled && supported_features.passive) { |
| 326 | const auto result = generic_protocol->EnablePassiveMode(); | 327 | const auto result = generic_protocol->EnablePassiveMode(); |
| 327 | if (result == DriverResult::Success) { | 328 | if (result == Common::Input::DriverResult::Success) { |
| 328 | return result; | 329 | return result; |
| 329 | } | 330 | } |
| 330 | LOG_ERROR(Input, "Error enabling passive mode"); | 331 | LOG_ERROR(Input, "Error enabling passive mode"); |
| @@ -332,7 +333,7 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 332 | 333 | ||
| 333 | // Default Mode | 334 | // Default Mode |
| 334 | const auto result = generic_protocol->EnableActiveMode(); | 335 | const auto result = generic_protocol->EnableActiveMode(); |
| 335 | if (result != DriverResult::Success) { | 336 | if (result != Common::Input::DriverResult::Success) { |
| 336 | LOG_ERROR(Input, "Error enabling active mode"); | 337 | LOG_ERROR(Input, "Error enabling active mode"); |
| 337 | } | 338 | } |
| 338 | // Switch calls this function after enabling active mode | 339 | // Switch calls this function after enabling active mode |
| @@ -396,26 +397,26 @@ bool JoyconDriver::IsPayloadCorrect(int status, std::span<const u8> buffer) { | |||
| 396 | return true; | 397 | return true; |
| 397 | } | 398 | } |
| 398 | 399 | ||
| 399 | DriverResult JoyconDriver::SetVibration(const VibrationValue& vibration) { | 400 | Common::Input::DriverResult JoyconDriver::SetVibration(const VibrationValue& vibration) { |
| 400 | std::scoped_lock lock{mutex}; | 401 | std::scoped_lock lock{mutex}; |
| 401 | if (disable_input_thread) { | 402 | if (disable_input_thread) { |
| 402 | return DriverResult::HandleInUse; | 403 | return Common::Input::DriverResult::HandleInUse; |
| 403 | } | 404 | } |
| 404 | return rumble_protocol->SendVibration(vibration); | 405 | return rumble_protocol->SendVibration(vibration); |
| 405 | } | 406 | } |
| 406 | 407 | ||
| 407 | DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { | 408 | Common::Input::DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { |
| 408 | std::scoped_lock lock{mutex}; | 409 | std::scoped_lock lock{mutex}; |
| 409 | if (disable_input_thread) { | 410 | if (disable_input_thread) { |
| 410 | return DriverResult::HandleInUse; | 411 | return Common::Input::DriverResult::HandleInUse; |
| 411 | } | 412 | } |
| 412 | return generic_protocol->SetLedPattern(led_pattern); | 413 | return generic_protocol->SetLedPattern(led_pattern); |
| 413 | } | 414 | } |
| 414 | 415 | ||
| 415 | DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) { | 416 | Common::Input::DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) { |
| 416 | std::scoped_lock lock{mutex}; | 417 | std::scoped_lock lock{mutex}; |
| 417 | if (disable_input_thread) { | 418 | if (disable_input_thread) { |
| 418 | return DriverResult::HandleInUse; | 419 | return Common::Input::DriverResult::HandleInUse; |
| 419 | } | 420 | } |
| 420 | disable_input_thread = true; | 421 | disable_input_thread = true; |
| 421 | const auto result = irs_protocol->SetIrsConfig(mode_, format_); | 422 | const auto result = irs_protocol->SetIrsConfig(mode_, format_); |
| @@ -423,7 +424,7 @@ DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) { | |||
| 423 | return result; | 424 | return result; |
| 424 | } | 425 | } |
| 425 | 426 | ||
| 426 | DriverResult JoyconDriver::SetPassiveMode() { | 427 | Common::Input::DriverResult JoyconDriver::SetPassiveMode() { |
| 427 | std::scoped_lock lock{mutex}; | 428 | std::scoped_lock lock{mutex}; |
| 428 | motion_enabled = false; | 429 | motion_enabled = false; |
| 429 | hidbus_enabled = false; | 430 | hidbus_enabled = false; |
| @@ -433,7 +434,7 @@ DriverResult JoyconDriver::SetPassiveMode() { | |||
| 433 | return SetPollingMode(); | 434 | return SetPollingMode(); |
| 434 | } | 435 | } |
| 435 | 436 | ||
| 436 | DriverResult JoyconDriver::SetActiveMode() { | 437 | Common::Input::DriverResult JoyconDriver::SetActiveMode() { |
| 437 | if (is_ring_disabled_by_irs) { | 438 | if (is_ring_disabled_by_irs) { |
| 438 | is_ring_disabled_by_irs = false; | 439 | is_ring_disabled_by_irs = false; |
| 439 | SetActiveMode(); | 440 | SetActiveMode(); |
| @@ -449,11 +450,11 @@ DriverResult JoyconDriver::SetActiveMode() { | |||
| 449 | return SetPollingMode(); | 450 | return SetPollingMode(); |
| 450 | } | 451 | } |
| 451 | 452 | ||
| 452 | DriverResult JoyconDriver::SetIrMode() { | 453 | Common::Input::DriverResult JoyconDriver::SetIrMode() { |
| 453 | std::scoped_lock lock{mutex}; | 454 | std::scoped_lock lock{mutex}; |
| 454 | 455 | ||
| 455 | if (!supported_features.irs) { | 456 | if (!supported_features.irs) { |
| 456 | return DriverResult::NotSupported; | 457 | return Common::Input::DriverResult::NotSupported; |
| 457 | } | 458 | } |
| 458 | 459 | ||
| 459 | if (ring_connected) { | 460 | if (ring_connected) { |
| @@ -468,11 +469,11 @@ DriverResult JoyconDriver::SetIrMode() { | |||
| 468 | return SetPollingMode(); | 469 | return SetPollingMode(); |
| 469 | } | 470 | } |
| 470 | 471 | ||
| 471 | DriverResult JoyconDriver::SetNfcMode() { | 472 | Common::Input::DriverResult JoyconDriver::SetNfcMode() { |
| 472 | std::scoped_lock lock{mutex}; | 473 | std::scoped_lock lock{mutex}; |
| 473 | 474 | ||
| 474 | if (!supported_features.nfc) { | 475 | if (!supported_features.nfc) { |
| 475 | return DriverResult::NotSupported; | 476 | return Common::Input::DriverResult::NotSupported; |
| 476 | } | 477 | } |
| 477 | 478 | ||
| 478 | motion_enabled = true; | 479 | motion_enabled = true; |
| @@ -483,11 +484,11 @@ DriverResult JoyconDriver::SetNfcMode() { | |||
| 483 | return SetPollingMode(); | 484 | return SetPollingMode(); |
| 484 | } | 485 | } |
| 485 | 486 | ||
| 486 | DriverResult JoyconDriver::SetRingConMode() { | 487 | Common::Input::DriverResult JoyconDriver::SetRingConMode() { |
| 487 | std::scoped_lock lock{mutex}; | 488 | std::scoped_lock lock{mutex}; |
| 488 | 489 | ||
| 489 | if (!supported_features.hidbus) { | 490 | if (!supported_features.hidbus) { |
| 490 | return DriverResult::NotSupported; | 491 | return Common::Input::DriverResult::NotSupported; |
| 491 | } | 492 | } |
| 492 | 493 | ||
| 493 | motion_enabled = true; | 494 | motion_enabled = true; |
| @@ -499,20 +500,20 @@ DriverResult JoyconDriver::SetRingConMode() { | |||
| 499 | const auto result = SetPollingMode(); | 500 | const auto result = SetPollingMode(); |
| 500 | 501 | ||
| 501 | if (!ring_connected) { | 502 | if (!ring_connected) { |
| 502 | return DriverResult::NoDeviceDetected; | 503 | return Common::Input::DriverResult::NoDeviceDetected; |
| 503 | } | 504 | } |
| 504 | 505 | ||
| 505 | return result; | 506 | return result; |
| 506 | } | 507 | } |
| 507 | 508 | ||
| 508 | DriverResult JoyconDriver::StartNfcPolling() { | 509 | Common::Input::DriverResult JoyconDriver::StartNfcPolling() { |
| 509 | std::scoped_lock lock{mutex}; | 510 | std::scoped_lock lock{mutex}; |
| 510 | 511 | ||
| 511 | if (!supported_features.nfc) { | 512 | if (!supported_features.nfc) { |
| 512 | return DriverResult::NotSupported; | 513 | return Common::Input::DriverResult::NotSupported; |
| 513 | } | 514 | } |
| 514 | if (!nfc_protocol->IsEnabled()) { | 515 | if (!nfc_protocol->IsEnabled()) { |
| 515 | return DriverResult::Disabled; | 516 | return Common::Input::DriverResult::Disabled; |
| 516 | } | 517 | } |
| 517 | 518 | ||
| 518 | disable_input_thread = true; | 519 | disable_input_thread = true; |
| @@ -522,14 +523,14 @@ DriverResult JoyconDriver::StartNfcPolling() { | |||
| 522 | return result; | 523 | return result; |
| 523 | } | 524 | } |
| 524 | 525 | ||
| 525 | DriverResult JoyconDriver::StopNfcPolling() { | 526 | Common::Input::DriverResult JoyconDriver::StopNfcPolling() { |
| 526 | std::scoped_lock lock{mutex}; | 527 | std::scoped_lock lock{mutex}; |
| 527 | 528 | ||
| 528 | if (!supported_features.nfc) { | 529 | if (!supported_features.nfc) { |
| 529 | return DriverResult::NotSupported; | 530 | return Common::Input::DriverResult::NotSupported; |
| 530 | } | 531 | } |
| 531 | if (!nfc_protocol->IsEnabled()) { | 532 | if (!nfc_protocol->IsEnabled()) { |
| 532 | return DriverResult::Disabled; | 533 | return Common::Input::DriverResult::Disabled; |
| 533 | } | 534 | } |
| 534 | 535 | ||
| 535 | disable_input_thread = true; | 536 | disable_input_thread = true; |
| @@ -544,17 +545,17 @@ DriverResult JoyconDriver::StopNfcPolling() { | |||
| 544 | return result; | 545 | return result; |
| 545 | } | 546 | } |
| 546 | 547 | ||
| 547 | DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) { | 548 | Common::Input::DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) { |
| 548 | std::scoped_lock lock{mutex}; | 549 | std::scoped_lock lock{mutex}; |
| 549 | 550 | ||
| 550 | if (!supported_features.nfc) { | 551 | if (!supported_features.nfc) { |
| 551 | return DriverResult::NotSupported; | 552 | return Common::Input::DriverResult::NotSupported; |
| 552 | } | 553 | } |
| 553 | if (!nfc_protocol->IsEnabled()) { | 554 | if (!nfc_protocol->IsEnabled()) { |
| 554 | return DriverResult::Disabled; | 555 | return Common::Input::DriverResult::Disabled; |
| 555 | } | 556 | } |
| 556 | if (!amiibo_detected) { | 557 | if (!amiibo_detected) { |
| 557 | return DriverResult::ErrorWritingData; | 558 | return Common::Input::DriverResult::ErrorWritingData; |
| 558 | } | 559 | } |
| 559 | 560 | ||
| 560 | out_data.resize(0x21C); | 561 | out_data.resize(0x21C); |
| @@ -565,17 +566,17 @@ DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) { | |||
| 565 | return result; | 566 | return result; |
| 566 | } | 567 | } |
| 567 | 568 | ||
| 568 | DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { | 569 | Common::Input::DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { |
| 569 | std::scoped_lock lock{mutex}; | 570 | std::scoped_lock lock{mutex}; |
| 570 | 571 | ||
| 571 | if (!supported_features.nfc) { | 572 | if (!supported_features.nfc) { |
| 572 | return DriverResult::NotSupported; | 573 | return Common::Input::DriverResult::NotSupported; |
| 573 | } | 574 | } |
| 574 | if (!nfc_protocol->IsEnabled()) { | 575 | if (!nfc_protocol->IsEnabled()) { |
| 575 | return DriverResult::Disabled; | 576 | return Common::Input::DriverResult::Disabled; |
| 576 | } | 577 | } |
| 577 | if (!amiibo_detected) { | 578 | if (!amiibo_detected) { |
| 578 | return DriverResult::ErrorWritingData; | 579 | return Common::Input::DriverResult::ErrorWritingData; |
| 579 | } | 580 | } |
| 580 | 581 | ||
| 581 | disable_input_thread = true; | 582 | disable_input_thread = true; |
| @@ -585,18 +586,18 @@ DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { | |||
| 585 | return result; | 586 | return result; |
| 586 | } | 587 | } |
| 587 | 588 | ||
| 588 | DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data, | 589 | Common::Input::DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data, |
| 589 | std::span<MifareReadData> out_data) { | 590 | std::span<MifareReadData> out_data) { |
| 590 | std::scoped_lock lock{mutex}; | 591 | std::scoped_lock lock{mutex}; |
| 591 | 592 | ||
| 592 | if (!supported_features.nfc) { | 593 | if (!supported_features.nfc) { |
| 593 | return DriverResult::NotSupported; | 594 | return Common::Input::DriverResult::NotSupported; |
| 594 | } | 595 | } |
| 595 | if (!nfc_protocol->IsEnabled()) { | 596 | if (!nfc_protocol->IsEnabled()) { |
| 596 | return DriverResult::Disabled; | 597 | return Common::Input::DriverResult::Disabled; |
| 597 | } | 598 | } |
| 598 | if (!amiibo_detected) { | 599 | if (!amiibo_detected) { |
| 599 | return DriverResult::ErrorWritingData; | 600 | return Common::Input::DriverResult::ErrorWritingData; |
| 600 | } | 601 | } |
| 601 | 602 | ||
| 602 | disable_input_thread = true; | 603 | disable_input_thread = true; |
| @@ -606,17 +607,17 @@ DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data, | |||
| 606 | return result; | 607 | return result; |
| 607 | } | 608 | } |
| 608 | 609 | ||
| 609 | DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) { | 610 | Common::Input::DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) { |
| 610 | std::scoped_lock lock{mutex}; | 611 | std::scoped_lock lock{mutex}; |
| 611 | 612 | ||
| 612 | if (!supported_features.nfc) { | 613 | if (!supported_features.nfc) { |
| 613 | return DriverResult::NotSupported; | 614 | return Common::Input::DriverResult::NotSupported; |
| 614 | } | 615 | } |
| 615 | if (!nfc_protocol->IsEnabled()) { | 616 | if (!nfc_protocol->IsEnabled()) { |
| 616 | return DriverResult::Disabled; | 617 | return Common::Input::DriverResult::Disabled; |
| 617 | } | 618 | } |
| 618 | if (!amiibo_detected) { | 619 | if (!amiibo_detected) { |
| 619 | return DriverResult::ErrorWritingData; | 620 | return Common::Input::DriverResult::ErrorWritingData; |
| 620 | } | 621 | } |
| 621 | 622 | ||
| 622 | disable_input_thread = true; | 623 | disable_input_thread = true; |
| @@ -675,8 +676,8 @@ void JoyconDriver::SetCallbacks(const JoyconCallbacks& callbacks) { | |||
| 675 | joycon_poller->SetCallbacks(callbacks); | 676 | joycon_poller->SetCallbacks(callbacks); |
| 676 | } | 677 | } |
| 677 | 678 | ||
| 678 | DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, | 679 | Common::Input::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, |
| 679 | ControllerType& controller_type) { | 680 | ControllerType& controller_type) { |
| 680 | static constexpr std::array<std::pair<u32, ControllerType>, 6> supported_devices{ | 681 | static constexpr std::array<std::pair<u32, ControllerType>, 6> supported_devices{ |
| 681 | std::pair<u32, ControllerType>{0x2006, ControllerType::Left}, | 682 | std::pair<u32, ControllerType>{0x2006, ControllerType::Left}, |
| 682 | {0x2007, ControllerType::Right}, | 683 | {0x2007, ControllerType::Right}, |
| @@ -686,25 +687,25 @@ DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, | |||
| 686 | 687 | ||
| 687 | controller_type = ControllerType::None; | 688 | controller_type = ControllerType::None; |
| 688 | if (device_info->vendor_id != nintendo_vendor_id) { | 689 | if (device_info->vendor_id != nintendo_vendor_id) { |
| 689 | return DriverResult::UnsupportedControllerType; | 690 | return Common::Input::DriverResult::UnsupportedControllerType; |
| 690 | } | 691 | } |
| 691 | 692 | ||
| 692 | for (const auto& [product_id, type] : supported_devices) { | 693 | for (const auto& [product_id, type] : supported_devices) { |
| 693 | if (device_info->product_id == static_cast<u16>(product_id)) { | 694 | if (device_info->product_id == static_cast<u16>(product_id)) { |
| 694 | controller_type = type; | 695 | controller_type = type; |
| 695 | return Joycon::DriverResult::Success; | 696 | return Common::Input::DriverResult::Success; |
| 696 | } | 697 | } |
| 697 | } | 698 | } |
| 698 | return Joycon::DriverResult::UnsupportedControllerType; | 699 | return Common::Input::DriverResult::UnsupportedControllerType; |
| 699 | } | 700 | } |
| 700 | 701 | ||
| 701 | DriverResult JoyconDriver::GetSerialNumber(SDL_hid_device_info* device_info, | 702 | Common::Input::DriverResult JoyconDriver::GetSerialNumber(SDL_hid_device_info* device_info, |
| 702 | SerialNumber& serial_number) { | 703 | SerialNumber& serial_number) { |
| 703 | if (device_info->serial_number == nullptr) { | 704 | if (device_info->serial_number == nullptr) { |
| 704 | return DriverResult::Unknown; | 705 | return Common::Input::DriverResult::Unknown; |
| 705 | } | 706 | } |
| 706 | std::memcpy(&serial_number, device_info->serial_number, 15); | 707 | std::memcpy(&serial_number, device_info->serial_number, 15); |
| 707 | return Joycon::DriverResult::Success; | 708 | return Common::Input::DriverResult::Success; |
| 708 | } | 709 | } |
| 709 | 710 | ||
| 710 | } // namespace InputCommon::Joycon | 711 | } // namespace InputCommon::Joycon |
diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index 45b32d2f8..335e12cc3 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h | |||
| @@ -11,6 +11,10 @@ | |||
| 11 | 11 | ||
| 12 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 12 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 13 | 13 | ||
| 14 | namespace Common::Input { | ||
| 15 | enum class DriverResult; | ||
| 16 | } | ||
| 17 | |||
| 14 | namespace InputCommon::Joycon { | 18 | namespace InputCommon::Joycon { |
| 15 | class CalibrationProtocol; | 19 | class CalibrationProtocol; |
| 16 | class GenericProtocol; | 20 | class GenericProtocol; |
| @@ -26,8 +30,8 @@ public: | |||
| 26 | 30 | ||
| 27 | ~JoyconDriver(); | 31 | ~JoyconDriver(); |
| 28 | 32 | ||
| 29 | DriverResult RequestDeviceAccess(SDL_hid_device_info* device_info); | 33 | Common::Input::DriverResult RequestDeviceAccess(SDL_hid_device_info* device_info); |
| 30 | DriverResult InitializeDevice(); | 34 | Common::Input::DriverResult InitializeDevice(); |
| 31 | void Stop(); | 35 | void Stop(); |
| 32 | 36 | ||
| 33 | bool IsConnected() const; | 37 | bool IsConnected() const; |
| @@ -41,31 +45,31 @@ public: | |||
| 41 | SerialNumber GetSerialNumber() const; | 45 | SerialNumber GetSerialNumber() const; |
| 42 | SerialNumber GetHandleSerialNumber() const; | 46 | SerialNumber GetHandleSerialNumber() const; |
| 43 | 47 | ||
| 44 | DriverResult SetVibration(const VibrationValue& vibration); | 48 | Common::Input::DriverResult SetVibration(const VibrationValue& vibration); |
| 45 | DriverResult SetLedConfig(u8 led_pattern); | 49 | Common::Input::DriverResult SetLedConfig(u8 led_pattern); |
| 46 | DriverResult SetIrsConfig(IrsMode mode_, IrsResolution format_); | 50 | Common::Input::DriverResult SetIrsConfig(IrsMode mode_, IrsResolution format_); |
| 47 | DriverResult SetPassiveMode(); | 51 | Common::Input::DriverResult SetPassiveMode(); |
| 48 | DriverResult SetActiveMode(); | 52 | Common::Input::DriverResult SetActiveMode(); |
| 49 | DriverResult SetIrMode(); | 53 | Common::Input::DriverResult SetIrMode(); |
| 50 | DriverResult SetNfcMode(); | 54 | Common::Input::DriverResult SetNfcMode(); |
| 51 | DriverResult SetRingConMode(); | 55 | Common::Input::DriverResult SetRingConMode(); |
| 52 | DriverResult StartNfcPolling(); | 56 | Common::Input::DriverResult StartNfcPolling(); |
| 53 | DriverResult StopNfcPolling(); | 57 | Common::Input::DriverResult StopNfcPolling(); |
| 54 | DriverResult ReadAmiiboData(std::vector<u8>& out_data); | 58 | Common::Input::DriverResult ReadAmiiboData(std::vector<u8>& out_data); |
| 55 | DriverResult WriteNfcData(std::span<const u8> data); | 59 | Common::Input::DriverResult WriteNfcData(std::span<const u8> data); |
| 56 | DriverResult ReadMifareData(std::span<const MifareReadChunk> request, | 60 | Common::Input::DriverResult ReadMifareData(std::span<const MifareReadChunk> request, |
| 57 | std::span<MifareReadData> out_data); | 61 | std::span<MifareReadData> out_data); |
| 58 | DriverResult WriteMifareData(std::span<const MifareWriteChunk> request); | 62 | Common::Input::DriverResult WriteMifareData(std::span<const MifareWriteChunk> request); |
| 59 | 63 | ||
| 60 | void SetCallbacks(const JoyconCallbacks& callbacks); | 64 | void SetCallbacks(const JoyconCallbacks& callbacks); |
| 61 | 65 | ||
| 62 | // Returns device type from hidapi handle | 66 | // Returns device type from hidapi handle |
| 63 | static DriverResult GetDeviceType(SDL_hid_device_info* device_info, | 67 | static Common::Input::DriverResult GetDeviceType(SDL_hid_device_info* device_info, |
| 64 | ControllerType& controller_type); | 68 | ControllerType& controller_type); |
| 65 | 69 | ||
| 66 | // Returns serial number from hidapi handle | 70 | // Returns serial number from hidapi handle |
| 67 | static DriverResult GetSerialNumber(SDL_hid_device_info* device_info, | 71 | static Common::Input::DriverResult GetSerialNumber(SDL_hid_device_info* device_info, |
| 68 | SerialNumber& serial_number); | 72 | SerialNumber& serial_number); |
| 69 | 73 | ||
| 70 | private: | 74 | private: |
| 71 | struct SupportedFeatures { | 75 | struct SupportedFeatures { |
| @@ -84,7 +88,7 @@ private: | |||
| 84 | void OnNewData(std::span<u8> buffer); | 88 | void OnNewData(std::span<u8> buffer); |
| 85 | 89 | ||
| 86 | /// Updates device configuration to enable or disable features | 90 | /// Updates device configuration to enable or disable features |
| 87 | DriverResult SetPollingMode(); | 91 | Common::Input::DriverResult SetPollingMode(); |
| 88 | 92 | ||
| 89 | /// Returns true if input thread is valid and doesn't need to be stopped | 93 | /// Returns true if input thread is valid and doesn't need to be stopped |
| 90 | bool IsInputThreadValid() const; | 94 | bool IsInputThreadValid() const; |
diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp index d8f040f75..1300ecaf5 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.cpp +++ b/src/input_common/helpers/joycon_protocol/calibration.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <cstring> | 4 | #include <cstring> |
| 5 | 5 | ||
| 6 | #include "common/input.h" | ||
| 6 | #include "input_common/helpers/joycon_protocol/calibration.h" | 7 | #include "input_common/helpers/joycon_protocol/calibration.h" |
| 7 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 8 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 8 | 9 | ||
| @@ -11,28 +12,29 @@ namespace InputCommon::Joycon { | |||
| 11 | CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle) | 12 | CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle) |
| 12 | : JoyconCommonProtocol(std::move(handle)) {} | 13 | : JoyconCommonProtocol(std::move(handle)) {} |
| 13 | 14 | ||
| 14 | DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { | 15 | Common::Input::DriverResult CalibrationProtocol::GetLeftJoyStickCalibration( |
| 16 | JoyStickCalibration& calibration) { | ||
| 15 | ScopedSetBlocking sb(this); | 17 | ScopedSetBlocking sb(this); |
| 16 | DriverResult result{DriverResult::Success}; | 18 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 17 | JoystickLeftSpiCalibration spi_calibration{}; | 19 | JoystickLeftSpiCalibration spi_calibration{}; |
| 18 | bool has_user_calibration = false; | 20 | bool has_user_calibration = false; |
| 19 | calibration = {}; | 21 | calibration = {}; |
| 20 | 22 | ||
| 21 | if (result == DriverResult::Success) { | 23 | if (result == Common::Input::DriverResult::Success) { |
| 22 | result = HasUserCalibration(SpiAddress::USER_LEFT_MAGIC, has_user_calibration); | 24 | result = HasUserCalibration(SpiAddress::USER_LEFT_MAGIC, has_user_calibration); |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | // Read User defined calibration | 27 | // Read User defined calibration |
| 26 | if (result == DriverResult::Success && has_user_calibration) { | 28 | if (result == Common::Input::DriverResult::Success && has_user_calibration) { |
| 27 | result = ReadSPI(SpiAddress::USER_LEFT_DATA, spi_calibration); | 29 | result = ReadSPI(SpiAddress::USER_LEFT_DATA, spi_calibration); |
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | // Read Factory calibration | 32 | // Read Factory calibration |
| 31 | if (result == DriverResult::Success && !has_user_calibration) { | 33 | if (result == Common::Input::DriverResult::Success && !has_user_calibration) { |
| 32 | result = ReadSPI(SpiAddress::FACT_LEFT_DATA, spi_calibration); | 34 | result = ReadSPI(SpiAddress::FACT_LEFT_DATA, spi_calibration); |
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | if (result == DriverResult::Success) { | 37 | if (result == Common::Input::DriverResult::Success) { |
| 36 | calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); | 38 | calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); |
| 37 | calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); | 39 | calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); |
| 38 | calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); | 40 | calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); |
| @@ -47,28 +49,29 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration | |||
| 47 | return result; | 49 | return result; |
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) { | 52 | Common::Input::DriverResult CalibrationProtocol::GetRightJoyStickCalibration( |
| 53 | JoyStickCalibration& calibration) { | ||
| 51 | ScopedSetBlocking sb(this); | 54 | ScopedSetBlocking sb(this); |
| 52 | DriverResult result{DriverResult::Success}; | 55 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 53 | JoystickRightSpiCalibration spi_calibration{}; | 56 | JoystickRightSpiCalibration spi_calibration{}; |
| 54 | bool has_user_calibration = false; | 57 | bool has_user_calibration = false; |
| 55 | calibration = {}; | 58 | calibration = {}; |
| 56 | 59 | ||
| 57 | if (result == DriverResult::Success) { | 60 | if (result == Common::Input::DriverResult::Success) { |
| 58 | result = HasUserCalibration(SpiAddress::USER_RIGHT_MAGIC, has_user_calibration); | 61 | result = HasUserCalibration(SpiAddress::USER_RIGHT_MAGIC, has_user_calibration); |
| 59 | } | 62 | } |
| 60 | 63 | ||
| 61 | // Read User defined calibration | 64 | // Read User defined calibration |
| 62 | if (result == DriverResult::Success && has_user_calibration) { | 65 | if (result == Common::Input::DriverResult::Success && has_user_calibration) { |
| 63 | result = ReadSPI(SpiAddress::USER_RIGHT_DATA, spi_calibration); | 66 | result = ReadSPI(SpiAddress::USER_RIGHT_DATA, spi_calibration); |
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | // Read Factory calibration | 69 | // Read Factory calibration |
| 67 | if (result == DriverResult::Success && !has_user_calibration) { | 70 | if (result == Common::Input::DriverResult::Success && !has_user_calibration) { |
| 68 | result = ReadSPI(SpiAddress::FACT_RIGHT_DATA, spi_calibration); | 71 | result = ReadSPI(SpiAddress::FACT_RIGHT_DATA, spi_calibration); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | if (result == DriverResult::Success) { | 74 | if (result == Common::Input::DriverResult::Success) { |
| 72 | calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); | 75 | calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); |
| 73 | calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); | 76 | calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); |
| 74 | calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); | 77 | calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); |
| @@ -83,28 +86,28 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio | |||
| 83 | return result; | 86 | return result; |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { | 89 | Common::Input::DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { |
| 87 | ScopedSetBlocking sb(this); | 90 | ScopedSetBlocking sb(this); |
| 88 | DriverResult result{DriverResult::Success}; | 91 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 89 | ImuSpiCalibration spi_calibration{}; | 92 | ImuSpiCalibration spi_calibration{}; |
| 90 | bool has_user_calibration = false; | 93 | bool has_user_calibration = false; |
| 91 | calibration = {}; | 94 | calibration = {}; |
| 92 | 95 | ||
| 93 | if (result == DriverResult::Success) { | 96 | if (result == Common::Input::DriverResult::Success) { |
| 94 | result = HasUserCalibration(SpiAddress::USER_IMU_MAGIC, has_user_calibration); | 97 | result = HasUserCalibration(SpiAddress::USER_IMU_MAGIC, has_user_calibration); |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | // Read User defined calibration | 100 | // Read User defined calibration |
| 98 | if (result == DriverResult::Success && has_user_calibration) { | 101 | if (result == Common::Input::DriverResult::Success && has_user_calibration) { |
| 99 | result = ReadSPI(SpiAddress::USER_IMU_DATA, spi_calibration); | 102 | result = ReadSPI(SpiAddress::USER_IMU_DATA, spi_calibration); |
| 100 | } | 103 | } |
| 101 | 104 | ||
| 102 | // Read Factory calibration | 105 | // Read Factory calibration |
| 103 | if (result == DriverResult::Success && !has_user_calibration) { | 106 | if (result == Common::Input::DriverResult::Success && !has_user_calibration) { |
| 104 | result = ReadSPI(SpiAddress::FACT_IMU_DATA, spi_calibration); | 107 | result = ReadSPI(SpiAddress::FACT_IMU_DATA, spi_calibration); |
| 105 | } | 108 | } |
| 106 | 109 | ||
| 107 | if (result == DriverResult::Success) { | 110 | if (result == Common::Input::DriverResult::Success) { |
| 108 | calibration.accelerometer[0].offset = spi_calibration.accelerometer_offset[0]; | 111 | calibration.accelerometer[0].offset = spi_calibration.accelerometer_offset[0]; |
| 109 | calibration.accelerometer[1].offset = spi_calibration.accelerometer_offset[1]; | 112 | calibration.accelerometer[1].offset = spi_calibration.accelerometer_offset[1]; |
| 110 | calibration.accelerometer[2].offset = spi_calibration.accelerometer_offset[2]; | 113 | calibration.accelerometer[2].offset = spi_calibration.accelerometer_offset[2]; |
| @@ -127,8 +130,8 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati | |||
| 127 | return result; | 130 | return result; |
| 128 | } | 131 | } |
| 129 | 132 | ||
| 130 | DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration, | 133 | Common::Input::DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration, |
| 131 | s16 current_value) { | 134 | s16 current_value) { |
| 132 | constexpr s16 DefaultRingRange{800}; | 135 | constexpr s16 DefaultRingRange{800}; |
| 133 | 136 | ||
| 134 | // TODO: Get default calibration form ring itself | 137 | // TODO: Get default calibration form ring itself |
| @@ -144,15 +147,15 @@ DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibratio | |||
| 144 | .max_value = ring_data_max, | 147 | .max_value = ring_data_max, |
| 145 | .min_value = ring_data_min, | 148 | .min_value = ring_data_min, |
| 146 | }; | 149 | }; |
| 147 | return DriverResult::Success; | 150 | return Common::Input::DriverResult::Success; |
| 148 | } | 151 | } |
| 149 | 152 | ||
| 150 | DriverResult CalibrationProtocol::HasUserCalibration(SpiAddress address, | 153 | Common::Input::DriverResult CalibrationProtocol::HasUserCalibration(SpiAddress address, |
| 151 | bool& has_user_calibration) { | 154 | bool& has_user_calibration) { |
| 152 | MagicSpiCalibration spi_magic{}; | 155 | MagicSpiCalibration spi_magic{}; |
| 153 | const DriverResult result{ReadSPI(address, spi_magic)}; | 156 | const Common::Input::DriverResult result{ReadSPI(address, spi_magic)}; |
| 154 | has_user_calibration = false; | 157 | has_user_calibration = false; |
| 155 | if (result == DriverResult::Success) { | 158 | if (result == Common::Input::DriverResult::Success) { |
| 156 | has_user_calibration = spi_magic.first == CalibrationMagic::USR_MAGIC_0 && | 159 | has_user_calibration = spi_magic.first == CalibrationMagic::USR_MAGIC_0 && |
| 157 | spi_magic.second == CalibrationMagic::USR_MAGIC_1; | 160 | spi_magic.second == CalibrationMagic::USR_MAGIC_1; |
| 158 | } | 161 | } |
diff --git a/src/input_common/helpers/joycon_protocol/calibration.h b/src/input_common/helpers/joycon_protocol/calibration.h index c6fd0f729..82d94b366 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.h +++ b/src/input_common/helpers/joycon_protocol/calibration.h | |||
| @@ -12,8 +12,11 @@ | |||
| 12 | 12 | ||
| 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 14 | 14 | ||
| 15 | namespace InputCommon::Joycon { | 15 | namespace Common::Input { |
| 16 | enum class DriverResult; | 16 | enum class DriverResult; |
| 17 | } | ||
| 18 | |||
| 19 | namespace InputCommon::Joycon { | ||
| 17 | struct JoyStickCalibration; | 20 | struct JoyStickCalibration; |
| 18 | struct IMUCalibration; | 21 | struct IMUCalibration; |
| 19 | struct JoyconHandle; | 22 | struct JoyconHandle; |
| @@ -31,30 +34,30 @@ public: | |||
| 31 | * @param is_factory_calibration if true factory values will be returned | 34 | * @param is_factory_calibration if true factory values will be returned |
| 32 | * @returns JoyStickCalibration of the left joystick | 35 | * @returns JoyStickCalibration of the left joystick |
| 33 | */ | 36 | */ |
| 34 | DriverResult GetLeftJoyStickCalibration(JoyStickCalibration& calibration); | 37 | Common::Input::DriverResult GetLeftJoyStickCalibration(JoyStickCalibration& calibration); |
| 35 | 38 | ||
| 36 | /** | 39 | /** |
| 37 | * Sends a request to obtain the right stick calibration from memory | 40 | * Sends a request to obtain the right stick calibration from memory |
| 38 | * @param is_factory_calibration if true factory values will be returned | 41 | * @param is_factory_calibration if true factory values will be returned |
| 39 | * @returns JoyStickCalibration of the right joystick | 42 | * @returns JoyStickCalibration of the right joystick |
| 40 | */ | 43 | */ |
| 41 | DriverResult GetRightJoyStickCalibration(JoyStickCalibration& calibration); | 44 | Common::Input::DriverResult GetRightJoyStickCalibration(JoyStickCalibration& calibration); |
| 42 | 45 | ||
| 43 | /** | 46 | /** |
| 44 | * Sends a request to obtain the motion calibration from memory | 47 | * Sends a request to obtain the motion calibration from memory |
| 45 | * @returns ImuCalibration of the motion sensor | 48 | * @returns ImuCalibration of the motion sensor |
| 46 | */ | 49 | */ |
| 47 | DriverResult GetImuCalibration(MotionCalibration& calibration); | 50 | Common::Input::DriverResult GetImuCalibration(MotionCalibration& calibration); |
| 48 | 51 | ||
| 49 | /** | 52 | /** |
| 50 | * Calculates on run time the proper calibration of the ring controller | 53 | * Calculates on run time the proper calibration of the ring controller |
| 51 | * @returns RingCalibration of the ring sensor | 54 | * @returns RingCalibration of the ring sensor |
| 52 | */ | 55 | */ |
| 53 | DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value); | 56 | Common::Input::DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value); |
| 54 | 57 | ||
| 55 | private: | 58 | private: |
| 56 | /// Returns true if the specified address corresponds to the magic value of user calibration | 59 | /// Returns true if the specified address corresponds to the magic value of user calibration |
| 57 | DriverResult HasUserCalibration(SpiAddress address, bool& has_user_calibration); | 60 | Common::Input::DriverResult HasUserCalibration(SpiAddress address, bool& has_user_calibration); |
| 58 | 61 | ||
| 59 | /// Converts a raw calibration block to an u16 value containing the x axis value | 62 | /// Converts a raw calibration block to an u16 value containing the x axis value |
| 60 | u16 GetXAxisCalibrationValue(std::span<u8> block) const; | 63 | u16 GetXAxisCalibrationValue(std::span<u8> block) const; |
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index 88f4cec1c..a6eecf980 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/input.h" | ||
| 4 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 5 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 6 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 6 | 7 | ||
| @@ -21,10 +22,10 @@ void JoyconCommonProtocol::SetNonBlocking() { | |||
| 21 | SDL_hid_set_nonblocking(hidapi_handle->handle, 1); | 22 | SDL_hid_set_nonblocking(hidapi_handle->handle, 1); |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { | 25 | Common::Input::DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { |
| 25 | const auto result = ReadSPI(SpiAddress::DEVICE_TYPE, controller_type); | 26 | const auto result = ReadSPI(SpiAddress::DEVICE_TYPE, controller_type); |
| 26 | 27 | ||
| 27 | if (result == DriverResult::Success) { | 28 | if (result == Common::Input::DriverResult::Success) { |
| 28 | // Fallback to 3rd party pro controllers | 29 | // Fallback to 3rd party pro controllers |
| 29 | if (controller_type == ControllerType::None) { | 30 | if (controller_type == ControllerType::None) { |
| 30 | controller_type = ControllerType::Pro; | 31 | controller_type = ControllerType::Pro; |
| @@ -34,12 +35,13 @@ DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type | |||
| 34 | return result; | 35 | return result; |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) { | 38 | Common::Input::DriverResult JoyconCommonProtocol::CheckDeviceAccess( |
| 39 | SDL_hid_device_info* device_info) { | ||
| 38 | ControllerType controller_type{ControllerType::None}; | 40 | ControllerType controller_type{ControllerType::None}; |
| 39 | const auto result = GetDeviceType(controller_type); | 41 | const auto result = GetDeviceType(controller_type); |
| 40 | 42 | ||
| 41 | if (result != DriverResult::Success || controller_type == ControllerType::None) { | 43 | if (result != Common::Input::DriverResult::Success || controller_type == ControllerType::None) { |
| 42 | return DriverResult::UnsupportedControllerType; | 44 | return Common::Input::DriverResult::UnsupportedControllerType; |
| 43 | } | 45 | } |
| 44 | 46 | ||
| 45 | hidapi_handle->handle = | 47 | hidapi_handle->handle = |
| @@ -48,32 +50,32 @@ DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device | |||
| 48 | if (!hidapi_handle->handle) { | 50 | if (!hidapi_handle->handle) { |
| 49 | LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.", | 51 | LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.", |
| 50 | device_info->vendor_id, device_info->product_id); | 52 | device_info->vendor_id, device_info->product_id); |
| 51 | return DriverResult::HandleInUse; | 53 | return Common::Input::DriverResult::HandleInUse; |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | SetNonBlocking(); | 56 | SetNonBlocking(); |
| 55 | return DriverResult::Success; | 57 | return Common::Input::DriverResult::Success; |
| 56 | } | 58 | } |
| 57 | 59 | ||
| 58 | DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) { | 60 | Common::Input::DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) { |
| 59 | const std::array<u8, 1> buffer{static_cast<u8>(report_mode)}; | 61 | const std::array<u8, 1> buffer{static_cast<u8>(report_mode)}; |
| 60 | return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer); | 62 | return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer); |
| 61 | } | 63 | } |
| 62 | 64 | ||
| 63 | DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) { | 65 | Common::Input::DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) { |
| 64 | const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size()); | 66 | const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size()); |
| 65 | 67 | ||
| 66 | if (result == -1) { | 68 | if (result == -1) { |
| 67 | return DriverResult::ErrorWritingData; | 69 | return Common::Input::DriverResult::ErrorWritingData; |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | return DriverResult::Success; | 72 | return Common::Input::DriverResult::Success; |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 73 | DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, | 75 | Common::Input::DriverResult JoyconCommonProtocol::GetSubCommandResponse( |
| 74 | SubCommandResponse& output) { | 76 | SubCommand sc, SubCommandResponse& output) { |
| 75 | constexpr int timeout_mili = 66; | 77 | constexpr int timeout_mili = 66; |
| 76 | constexpr int MaxTries = 3; | 78 | constexpr int MaxTries = 10; |
| 77 | int tries = 0; | 79 | int tries = 0; |
| 78 | 80 | ||
| 79 | do { | 81 | do { |
| @@ -84,16 +86,17 @@ DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, | |||
| 84 | LOG_ERROR(Input, "No response from joycon"); | 86 | LOG_ERROR(Input, "No response from joycon"); |
| 85 | } | 87 | } |
| 86 | if (tries++ > MaxTries) { | 88 | if (tries++ > MaxTries) { |
| 87 | return DriverResult::Timeout; | 89 | return Common::Input::DriverResult::Timeout; |
| 88 | } | 90 | } |
| 89 | } while (output.input_report.report_mode != ReportMode::SUBCMD_REPLY && | 91 | } while (output.input_report.report_mode != ReportMode::SUBCMD_REPLY && |
| 90 | output.sub_command != sc); | 92 | output.sub_command != sc); |
| 91 | 93 | ||
| 92 | return DriverResult::Success; | 94 | return Common::Input::DriverResult::Success; |
| 93 | } | 95 | } |
| 94 | 96 | ||
| 95 | DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer, | 97 | Common::Input::DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, |
| 96 | SubCommandResponse& output) { | 98 | std::span<const u8> buffer, |
| 99 | SubCommandResponse& output) { | ||
| 97 | SubCommandPacket packet{ | 100 | SubCommandPacket packet{ |
| 98 | .output_report = OutputReport::RUMBLE_AND_SUBCMD, | 101 | .output_report = OutputReport::RUMBLE_AND_SUBCMD, |
| 99 | .packet_counter = GetCounter(), | 102 | .packet_counter = GetCounter(), |
| @@ -102,26 +105,28 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const | |||
| 102 | }; | 105 | }; |
| 103 | 106 | ||
| 104 | if (buffer.size() > packet.command_data.size()) { | 107 | if (buffer.size() > packet.command_data.size()) { |
| 105 | return DriverResult::InvalidParameters; | 108 | return Common::Input::DriverResult::InvalidParameters; |
| 106 | } | 109 | } |
| 107 | 110 | ||
| 108 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); | 111 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); |
| 109 | 112 | ||
| 110 | auto result = SendData(packet); | 113 | auto result = SendData(packet); |
| 111 | 114 | ||
| 112 | if (result != DriverResult::Success) { | 115 | if (result != Common::Input::DriverResult::Success) { |
| 113 | return result; | 116 | return result; |
| 114 | } | 117 | } |
| 115 | 118 | ||
| 116 | return GetSubCommandResponse(sc, output); | 119 | return GetSubCommandResponse(sc, output); |
| 117 | } | 120 | } |
| 118 | 121 | ||
| 119 | DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) { | 122 | Common::Input::DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, |
| 123 | std::span<const u8> buffer) { | ||
| 120 | SubCommandResponse output{}; | 124 | SubCommandResponse output{}; |
| 121 | return SendSubCommand(sc, buffer, output); | 125 | return SendSubCommand(sc, buffer, output); |
| 122 | } | 126 | } |
| 123 | 127 | ||
| 124 | DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) { | 128 | Common::Input::DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, |
| 129 | std::span<const u8> buffer) { | ||
| 125 | SubCommandPacket packet{ | 130 | SubCommandPacket packet{ |
| 126 | .output_report = OutputReport::MCU_DATA, | 131 | .output_report = OutputReport::MCU_DATA, |
| 127 | .packet_counter = GetCounter(), | 132 | .packet_counter = GetCounter(), |
| @@ -130,7 +135,7 @@ DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const | |||
| 130 | }; | 135 | }; |
| 131 | 136 | ||
| 132 | if (buffer.size() > packet.command_data.size()) { | 137 | if (buffer.size() > packet.command_data.size()) { |
| 133 | return DriverResult::InvalidParameters; | 138 | return Common::Input::DriverResult::InvalidParameters; |
| 134 | } | 139 | } |
| 135 | 140 | ||
| 136 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); | 141 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); |
| @@ -138,7 +143,7 @@ DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const | |||
| 138 | return SendData(packet); | 143 | return SendData(packet); |
| 139 | } | 144 | } |
| 140 | 145 | ||
| 141 | DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) { | 146 | Common::Input::DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) { |
| 142 | VibrationPacket packet{ | 147 | VibrationPacket packet{ |
| 143 | .output_report = OutputReport::RUMBLE_ONLY, | 148 | .output_report = OutputReport::RUMBLE_ONLY, |
| 144 | .packet_counter = GetCounter(), | 149 | .packet_counter = GetCounter(), |
| @@ -146,7 +151,7 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe | |||
| 146 | }; | 151 | }; |
| 147 | 152 | ||
| 148 | if (buffer.size() > packet.vibration_data.size()) { | 153 | if (buffer.size() > packet.vibration_data.size()) { |
| 149 | return DriverResult::InvalidParameters; | 154 | return Common::Input::DriverResult::InvalidParameters; |
| 150 | } | 155 | } |
| 151 | 156 | ||
| 152 | memcpy(packet.vibration_data.data(), buffer.data(), buffer.size()); | 157 | memcpy(packet.vibration_data.data(), buffer.data(), buffer.size()); |
| @@ -154,7 +159,8 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe | |||
| 154 | return SendData(packet); | 159 | return SendData(packet); |
| 155 | } | 160 | } |
| 156 | 161 | ||
| 157 | DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) { | 162 | Common::Input::DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, |
| 163 | std::span<u8> output) { | ||
| 158 | constexpr std::size_t HeaderSize = 5; | 164 | constexpr std::size_t HeaderSize = 5; |
| 159 | constexpr std::size_t MaxTries = 5; | 165 | constexpr std::size_t MaxTries = 5; |
| 160 | std::size_t tries = 0; | 166 | std::size_t tries = 0; |
| @@ -168,36 +174,36 @@ DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> out | |||
| 168 | memcpy(buffer.data(), &packet_data, sizeof(ReadSpiPacket)); | 174 | memcpy(buffer.data(), &packet_data, sizeof(ReadSpiPacket)); |
| 169 | do { | 175 | do { |
| 170 | const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, response); | 176 | const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, response); |
| 171 | if (result != DriverResult::Success) { | 177 | if (result != Common::Input::DriverResult::Success) { |
| 172 | return result; | 178 | return result; |
| 173 | } | 179 | } |
| 174 | 180 | ||
| 175 | if (tries++ > MaxTries) { | 181 | if (tries++ > MaxTries) { |
| 176 | return DriverResult::Timeout; | 182 | return Common::Input::DriverResult::Timeout; |
| 177 | } | 183 | } |
| 178 | } while (response.spi_address != addr); | 184 | } while (response.spi_address != addr); |
| 179 | 185 | ||
| 180 | if (response.command_data.size() < packet_data.size + HeaderSize) { | 186 | if (response.command_data.size() < packet_data.size + HeaderSize) { |
| 181 | return DriverResult::WrongReply; | 187 | return Common::Input::DriverResult::WrongReply; |
| 182 | } | 188 | } |
| 183 | 189 | ||
| 184 | // Remove header from output | 190 | // Remove header from output |
| 185 | memcpy(output.data(), response.command_data.data() + HeaderSize, packet_data.size); | 191 | memcpy(output.data(), response.command_data.data() + HeaderSize, packet_data.size); |
| 186 | return DriverResult::Success; | 192 | return Common::Input::DriverResult::Success; |
| 187 | } | 193 | } |
| 188 | 194 | ||
| 189 | DriverResult JoyconCommonProtocol::EnableMCU(bool enable) { | 195 | Common::Input::DriverResult JoyconCommonProtocol::EnableMCU(bool enable) { |
| 190 | const std::array<u8, 1> mcu_state{static_cast<u8>(enable ? 1 : 0)}; | 196 | const std::array<u8, 1> mcu_state{static_cast<u8>(enable ? 1 : 0)}; |
| 191 | const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state); | 197 | const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state); |
| 192 | 198 | ||
| 193 | if (result != DriverResult::Success) { | 199 | if (result != Common::Input::DriverResult::Success) { |
| 194 | LOG_ERROR(Input, "Failed with error {}", result); | 200 | LOG_ERROR(Input, "Failed with error {}", result); |
| 195 | } | 201 | } |
| 196 | 202 | ||
| 197 | return result; | 203 | return result; |
| 198 | } | 204 | } |
| 199 | 205 | ||
| 200 | DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { | 206 | Common::Input::DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { |
| 201 | LOG_DEBUG(Input, "ConfigureMCU"); | 207 | LOG_DEBUG(Input, "ConfigureMCU"); |
| 202 | std::array<u8, sizeof(MCUConfig)> config_buffer; | 208 | std::array<u8, sizeof(MCUConfig)> config_buffer; |
| 203 | memcpy(config_buffer.data(), &config, sizeof(MCUConfig)); | 209 | memcpy(config_buffer.data(), &config, sizeof(MCUConfig)); |
| @@ -205,15 +211,15 @@ DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { | |||
| 205 | 211 | ||
| 206 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer); | 212 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer); |
| 207 | 213 | ||
| 208 | if (result != DriverResult::Success) { | 214 | if (result != Common::Input::DriverResult::Success) { |
| 209 | LOG_ERROR(Input, "Failed with error {}", result); | 215 | LOG_ERROR(Input, "Failed with error {}", result); |
| 210 | } | 216 | } |
| 211 | 217 | ||
| 212 | return result; | 218 | return result; |
| 213 | } | 219 | } |
| 214 | 220 | ||
| 215 | DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode, | 221 | Common::Input::DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode, |
| 216 | MCUCommandResponse& output) { | 222 | MCUCommandResponse& output) { |
| 217 | constexpr int TimeoutMili = 200; | 223 | constexpr int TimeoutMili = 200; |
| 218 | constexpr int MaxTries = 9; | 224 | constexpr int MaxTries = 9; |
| 219 | int tries = 0; | 225 | int tries = 0; |
| @@ -226,17 +232,18 @@ DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode, | |||
| 226 | LOG_ERROR(Input, "No response from joycon attempt {}", tries); | 232 | LOG_ERROR(Input, "No response from joycon attempt {}", tries); |
| 227 | } | 233 | } |
| 228 | if (tries++ > MaxTries) { | 234 | if (tries++ > MaxTries) { |
| 229 | return DriverResult::Timeout; | 235 | return Common::Input::DriverResult::Timeout; |
| 230 | } | 236 | } |
| 231 | } while (output.input_report.report_mode != report_mode || | 237 | } while (output.input_report.report_mode != report_mode || |
| 232 | output.mcu_report == MCUReport::EmptyAwaitingCmd); | 238 | output.mcu_report == MCUReport::EmptyAwaitingCmd); |
| 233 | 239 | ||
| 234 | return DriverResult::Success; | 240 | return Common::Input::DriverResult::Success; |
| 235 | } | 241 | } |
| 236 | 242 | ||
| 237 | DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, MCUSubCommand sc, | 243 | Common::Input::DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, |
| 238 | std::span<const u8> buffer, | 244 | MCUSubCommand sc, |
| 239 | MCUCommandResponse& output) { | 245 | std::span<const u8> buffer, |
| 246 | MCUCommandResponse& output) { | ||
| 240 | SubCommandPacket packet{ | 247 | SubCommandPacket packet{ |
| 241 | .output_report = OutputReport::MCU_DATA, | 248 | .output_report = OutputReport::MCU_DATA, |
| 242 | .packet_counter = GetCounter(), | 249 | .packet_counter = GetCounter(), |
| @@ -245,23 +252,24 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, MCUSubCom | |||
| 245 | }; | 252 | }; |
| 246 | 253 | ||
| 247 | if (buffer.size() > packet.command_data.size()) { | 254 | if (buffer.size() > packet.command_data.size()) { |
| 248 | return DriverResult::InvalidParameters; | 255 | return Common::Input::DriverResult::InvalidParameters; |
| 249 | } | 256 | } |
| 250 | 257 | ||
| 251 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); | 258 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); |
| 252 | 259 | ||
| 253 | auto result = SendData(packet); | 260 | auto result = SendData(packet); |
| 254 | 261 | ||
| 255 | if (result != DriverResult::Success) { | 262 | if (result != Common::Input::DriverResult::Success) { |
| 256 | return result; | 263 | return result; |
| 257 | } | 264 | } |
| 258 | 265 | ||
| 259 | result = GetMCUDataResponse(report_mode, output); | 266 | result = GetMCUDataResponse(report_mode, output); |
| 260 | 267 | ||
| 261 | return DriverResult::Success; | 268 | return Common::Input::DriverResult::Success; |
| 262 | } | 269 | } |
| 263 | 270 | ||
| 264 | DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) { | 271 | Common::Input::DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, |
| 272 | MCUMode mode) { | ||
| 265 | MCUCommandResponse output{}; | 273 | MCUCommandResponse output{}; |
| 266 | constexpr std::size_t MaxTries{16}; | 274 | constexpr std::size_t MaxTries{16}; |
| 267 | std::size_t tries{}; | 275 | std::size_t tries{}; |
| @@ -269,17 +277,17 @@ DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMod | |||
| 269 | do { | 277 | do { |
| 270 | const auto result = SendMCUData(report_mode, MCUSubCommand::SetDeviceMode, {}, output); | 278 | const auto result = SendMCUData(report_mode, MCUSubCommand::SetDeviceMode, {}, output); |
| 271 | 279 | ||
| 272 | if (result != DriverResult::Success) { | 280 | if (result != Common::Input::DriverResult::Success) { |
| 273 | return result; | 281 | return result; |
| 274 | } | 282 | } |
| 275 | 283 | ||
| 276 | if (tries++ > MaxTries) { | 284 | if (tries++ > MaxTries) { |
| 277 | return DriverResult::WrongReply; | 285 | return Common::Input::DriverResult::WrongReply; |
| 278 | } | 286 | } |
| 279 | } while (output.mcu_report != MCUReport::StateReport || | 287 | } while (output.mcu_report != MCUReport::StateReport || |
| 280 | output.mcu_data[6] != static_cast<u8>(mode)); | 288 | output.mcu_data[6] != static_cast<u8>(mode)); |
| 281 | 289 | ||
| 282 | return DriverResult::Success; | 290 | return Common::Input::DriverResult::Success; |
| 283 | } | 291 | } |
| 284 | 292 | ||
| 285 | // crc-8-ccitt / polynomial 0x07 look up table | 293 | // crc-8-ccitt / polynomial 0x07 look up table |
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h index 411ec018a..dd667ca2b 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.h +++ b/src/input_common/helpers/joycon_protocol/common_protocol.h | |||
| @@ -38,30 +38,30 @@ public: | |||
| 38 | * Sends a request to obtain the joycon type from device | 38 | * Sends a request to obtain the joycon type from device |
| 39 | * @returns controller type of the joycon | 39 | * @returns controller type of the joycon |
| 40 | */ | 40 | */ |
| 41 | DriverResult GetDeviceType(ControllerType& controller_type); | 41 | Common::Input::DriverResult GetDeviceType(ControllerType& controller_type); |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Verifies and sets the joycon_handle if device is valid | 44 | * Verifies and sets the joycon_handle if device is valid |
| 45 | * @param device info from the driver | 45 | * @param device info from the driver |
| 46 | * @returns success if the device is valid | 46 | * @returns success if the device is valid |
| 47 | */ | 47 | */ |
| 48 | DriverResult CheckDeviceAccess(SDL_hid_device_info* device); | 48 | Common::Input::DriverResult CheckDeviceAccess(SDL_hid_device_info* device); |
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * Sends a request to set the polling mode of the joycon | 51 | * Sends a request to set the polling mode of the joycon |
| 52 | * @param report_mode polling mode to be set | 52 | * @param report_mode polling mode to be set |
| 53 | */ | 53 | */ |
| 54 | DriverResult SetReportMode(Joycon::ReportMode report_mode); | 54 | Common::Input::DriverResult SetReportMode(Joycon::ReportMode report_mode); |
| 55 | 55 | ||
| 56 | /** | 56 | /** |
| 57 | * Sends data to the joycon device | 57 | * Sends data to the joycon device |
| 58 | * @param buffer data to be send | 58 | * @param buffer data to be send |
| 59 | */ | 59 | */ |
| 60 | DriverResult SendRawData(std::span<const u8> buffer); | 60 | Common::Input::DriverResult SendRawData(std::span<const u8> buffer); |
| 61 | 61 | ||
| 62 | template <typename Output> | 62 | template <typename Output> |
| 63 | requires std::is_trivially_copyable_v<Output> | 63 | requires std::is_trivially_copyable_v<Output> |
| 64 | DriverResult SendData(const Output& output) { | 64 | Common::Input::DriverResult SendData(const Output& output) { |
| 65 | std::array<u8, sizeof(Output)> buffer; | 65 | std::array<u8, sizeof(Output)> buffer; |
| 66 | std::memcpy(buffer.data(), &output, sizeof(Output)); | 66 | std::memcpy(buffer.data(), &output, sizeof(Output)); |
| 67 | return SendRawData(buffer); | 67 | return SendRawData(buffer); |
| @@ -72,7 +72,8 @@ public: | |||
| 72 | * @param sub_command type of data to be returned | 72 | * @param sub_command type of data to be returned |
| 73 | * @returns a buffer containing the response | 73 | * @returns a buffer containing the response |
| 74 | */ | 74 | */ |
| 75 | DriverResult GetSubCommandResponse(SubCommand sub_command, SubCommandResponse& output); | 75 | Common::Input::DriverResult GetSubCommandResponse(SubCommand sub_command, |
| 76 | SubCommandResponse& output); | ||
| 76 | 77 | ||
| 77 | /** | 78 | /** |
| 78 | * Sends a sub command to the device and waits for it's reply | 79 | * Sends a sub command to the device and waits for it's reply |
| @@ -80,35 +81,35 @@ public: | |||
| 80 | * @param buffer data to be send | 81 | * @param buffer data to be send |
| 81 | * @returns output buffer containing the response | 82 | * @returns output buffer containing the response |
| 82 | */ | 83 | */ |
| 83 | DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, | 84 | Common::Input::DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, |
| 84 | SubCommandResponse& output); | 85 | SubCommandResponse& output); |
| 85 | 86 | ||
| 86 | /** | 87 | /** |
| 87 | * Sends a sub command to the device and waits for it's reply and ignores the output | 88 | * Sends a sub command to the device and waits for it's reply and ignores the output |
| 88 | * @param sc sub command to be send | 89 | * @param sc sub command to be send |
| 89 | * @param buffer data to be send | 90 | * @param buffer data to be send |
| 90 | */ | 91 | */ |
| 91 | DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer); | 92 | Common::Input::DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer); |
| 92 | 93 | ||
| 93 | /** | 94 | /** |
| 94 | * Sends a mcu command to the device | 95 | * Sends a mcu command to the device |
| 95 | * @param sc sub command to be send | 96 | * @param sc sub command to be send |
| 96 | * @param buffer data to be send | 97 | * @param buffer data to be send |
| 97 | */ | 98 | */ |
| 98 | DriverResult SendMCUCommand(SubCommand sc, std::span<const u8> buffer); | 99 | Common::Input::DriverResult SendMCUCommand(SubCommand sc, std::span<const u8> buffer); |
| 99 | 100 | ||
| 100 | /** | 101 | /** |
| 101 | * Sends vibration data to the joycon | 102 | * Sends vibration data to the joycon |
| 102 | * @param buffer data to be send | 103 | * @param buffer data to be send |
| 103 | */ | 104 | */ |
| 104 | DriverResult SendVibrationReport(std::span<const u8> buffer); | 105 | Common::Input::DriverResult SendVibrationReport(std::span<const u8> buffer); |
| 105 | 106 | ||
| 106 | /** | 107 | /** |
| 107 | * Reads the SPI memory stored on the joycon | 108 | * Reads the SPI memory stored on the joycon |
| 108 | * @param Initial address location | 109 | * @param Initial address location |
| 109 | * @returns output buffer containing the response | 110 | * @returns output buffer containing the response |
| 110 | */ | 111 | */ |
| 111 | DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); | 112 | Common::Input::DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); |
| 112 | 113 | ||
| 113 | /** | 114 | /** |
| 114 | * Reads the SPI memory stored on the joycon | 115 | * Reads the SPI memory stored on the joycon |
| @@ -117,37 +118,38 @@ public: | |||
| 117 | */ | 118 | */ |
| 118 | template <typename Output> | 119 | template <typename Output> |
| 119 | requires std::is_trivially_copyable_v<Output> | 120 | requires std::is_trivially_copyable_v<Output> |
| 120 | DriverResult ReadSPI(SpiAddress addr, Output& output) { | 121 | Common::Input::DriverResult ReadSPI(SpiAddress addr, Output& output) { |
| 121 | std::array<u8, sizeof(Output)> buffer; | 122 | std::array<u8, sizeof(Output)> buffer; |
| 122 | output = {}; | 123 | output = {}; |
| 123 | 124 | ||
| 124 | const auto result = ReadRawSPI(addr, buffer); | 125 | const auto result = ReadRawSPI(addr, buffer); |
| 125 | if (result != DriverResult::Success) { | 126 | if (result != Common::Input::DriverResult::Success) { |
| 126 | return result; | 127 | return result; |
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | std::memcpy(&output, buffer.data(), sizeof(Output)); | 130 | std::memcpy(&output, buffer.data(), sizeof(Output)); |
| 130 | return DriverResult::Success; | 131 | return Common::Input::DriverResult::Success; |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | /** | 134 | /** |
| 134 | * Enables MCU chip on the joycon | 135 | * Enables MCU chip on the joycon |
| 135 | * @param enable if true the chip will be enabled | 136 | * @param enable if true the chip will be enabled |
| 136 | */ | 137 | */ |
| 137 | DriverResult EnableMCU(bool enable); | 138 | Common::Input::DriverResult EnableMCU(bool enable); |
| 138 | 139 | ||
| 139 | /** | 140 | /** |
| 140 | * Configures the MCU to the corresponding mode | 141 | * Configures the MCU to the corresponding mode |
| 141 | * @param MCUConfig configuration | 142 | * @param MCUConfig configuration |
| 142 | */ | 143 | */ |
| 143 | DriverResult ConfigureMCU(const MCUConfig& config); | 144 | Common::Input::DriverResult ConfigureMCU(const MCUConfig& config); |
| 144 | 145 | ||
| 145 | /** | 146 | /** |
| 146 | * Waits until there's MCU data available. On timeout returns error | 147 | * Waits until there's MCU data available. On timeout returns error |
| 147 | * @param report mode of the expected reply | 148 | * @param report mode of the expected reply |
| 148 | * @returns a buffer containing the response | 149 | * @returns a buffer containing the response |
| 149 | */ | 150 | */ |
| 150 | DriverResult GetMCUDataResponse(ReportMode report_mode_, MCUCommandResponse& output); | 151 | Common::Input::DriverResult GetMCUDataResponse(ReportMode report_mode_, |
| 152 | MCUCommandResponse& output); | ||
| 151 | 153 | ||
| 152 | /** | 154 | /** |
| 153 | * Sends data to the MCU chip and waits for it's reply | 155 | * Sends data to the MCU chip and waits for it's reply |
| @@ -156,15 +158,15 @@ public: | |||
| 156 | * @param buffer data to be send | 158 | * @param buffer data to be send |
| 157 | * @returns output buffer containing the response | 159 | * @returns output buffer containing the response |
| 158 | */ | 160 | */ |
| 159 | DriverResult SendMCUData(ReportMode report_mode, MCUSubCommand sc, std::span<const u8> buffer, | 161 | Common::Input::DriverResult SendMCUData(ReportMode report_mode, MCUSubCommand sc, |
| 160 | MCUCommandResponse& output); | 162 | std::span<const u8> buffer, MCUCommandResponse& output); |
| 161 | 163 | ||
| 162 | /** | 164 | /** |
| 163 | * Wait's until the MCU chip is on the specified mode | 165 | * Wait's until the MCU chip is on the specified mode |
| 164 | * @param report mode of the expected reply | 166 | * @param report mode of the expected reply |
| 165 | * @param MCUMode configuration | 167 | * @param MCUMode configuration |
| 166 | */ | 168 | */ |
| 167 | DriverResult WaitSetMCUMode(ReportMode report_mode, MCUMode mode); | 169 | Common::Input::DriverResult WaitSetMCUMode(ReportMode report_mode, MCUMode mode); |
| 168 | 170 | ||
| 169 | /** | 171 | /** |
| 170 | * Calculates the checksum from the MCU data | 172 | * Calculates the checksum from the MCU data |
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp index 548a4b9e3..e9a056448 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp +++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/input.h" | ||
| 4 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 5 | #include "input_common/helpers/joycon_protocol/generic_functions.h" | 6 | #include "input_common/helpers/joycon_protocol/generic_functions.h" |
| 6 | 7 | ||
| @@ -9,73 +10,74 @@ namespace InputCommon::Joycon { | |||
| 9 | GenericProtocol::GenericProtocol(std::shared_ptr<JoyconHandle> handle) | 10 | GenericProtocol::GenericProtocol(std::shared_ptr<JoyconHandle> handle) |
| 10 | : JoyconCommonProtocol(std::move(handle)) {} | 11 | : JoyconCommonProtocol(std::move(handle)) {} |
| 11 | 12 | ||
| 12 | DriverResult GenericProtocol::EnablePassiveMode() { | 13 | Common::Input::DriverResult GenericProtocol::EnablePassiveMode() { |
| 13 | ScopedSetBlocking sb(this); | 14 | ScopedSetBlocking sb(this); |
| 14 | return SetReportMode(ReportMode::SIMPLE_HID_MODE); | 15 | return SetReportMode(ReportMode::SIMPLE_HID_MODE); |
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | DriverResult GenericProtocol::EnableActiveMode() { | 18 | Common::Input::DriverResult GenericProtocol::EnableActiveMode() { |
| 18 | ScopedSetBlocking sb(this); | 19 | ScopedSetBlocking sb(this); |
| 19 | return SetReportMode(ReportMode::STANDARD_FULL_60HZ); | 20 | return SetReportMode(ReportMode::STANDARD_FULL_60HZ); |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | DriverResult GenericProtocol::SetLowPowerMode(bool enable) { | 23 | Common::Input::DriverResult GenericProtocol::SetLowPowerMode(bool enable) { |
| 23 | ScopedSetBlocking sb(this); | 24 | ScopedSetBlocking sb(this); |
| 24 | const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)}; | 25 | const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)}; |
| 25 | return SendSubCommand(SubCommand::LOW_POWER_MODE, buffer); | 26 | return SendSubCommand(SubCommand::LOW_POWER_MODE, buffer); |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | DriverResult GenericProtocol::TriggersElapsed() { | 29 | Common::Input::DriverResult GenericProtocol::TriggersElapsed() { |
| 29 | ScopedSetBlocking sb(this); | 30 | ScopedSetBlocking sb(this); |
| 30 | return SendSubCommand(SubCommand::TRIGGERS_ELAPSED, {}); | 31 | return SendSubCommand(SubCommand::TRIGGERS_ELAPSED, {}); |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { | 34 | Common::Input::DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { |
| 34 | ScopedSetBlocking sb(this); | 35 | ScopedSetBlocking sb(this); |
| 35 | SubCommandResponse output{}; | 36 | SubCommandResponse output{}; |
| 36 | 37 | ||
| 37 | const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); | 38 | const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); |
| 38 | 39 | ||
| 39 | device_info = {}; | 40 | device_info = {}; |
| 40 | if (result == DriverResult::Success) { | 41 | if (result == Common::Input::DriverResult::Success) { |
| 41 | device_info = output.device_info; | 42 | device_info = output.device_info; |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | return result; | 45 | return result; |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type) { | 48 | Common::Input::DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type) { |
| 48 | return GetDeviceType(controller_type); | 49 | return GetDeviceType(controller_type); |
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | DriverResult GenericProtocol::EnableImu(bool enable) { | 52 | Common::Input::DriverResult GenericProtocol::EnableImu(bool enable) { |
| 52 | ScopedSetBlocking sb(this); | 53 | ScopedSetBlocking sb(this); |
| 53 | const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)}; | 54 | const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)}; |
| 54 | return SendSubCommand(SubCommand::ENABLE_IMU, buffer); | 55 | return SendSubCommand(SubCommand::ENABLE_IMU, buffer); |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, | 58 | Common::Input::DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, |
| 58 | AccelerometerSensitivity asen, | 59 | GyroPerformance gfrec, |
| 59 | AccelerometerPerformance afrec) { | 60 | AccelerometerSensitivity asen, |
| 61 | AccelerometerPerformance afrec) { | ||
| 60 | ScopedSetBlocking sb(this); | 62 | ScopedSetBlocking sb(this); |
| 61 | const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen), | 63 | const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen), |
| 62 | static_cast<u8>(gfrec), static_cast<u8>(afrec)}; | 64 | static_cast<u8>(gfrec), static_cast<u8>(afrec)}; |
| 63 | return SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer); | 65 | return SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer); |
| 64 | } | 66 | } |
| 65 | 67 | ||
| 66 | DriverResult GenericProtocol::GetBattery(u32& battery_level) { | 68 | Common::Input::DriverResult GenericProtocol::GetBattery(u32& battery_level) { |
| 67 | // This function is meant to request the high resolution battery status | 69 | // This function is meant to request the high resolution battery status |
| 68 | battery_level = 0; | 70 | battery_level = 0; |
| 69 | return DriverResult::NotSupported; | 71 | return Common::Input::DriverResult::NotSupported; |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | DriverResult GenericProtocol::GetColor(Color& color) { | 74 | Common::Input::DriverResult GenericProtocol::GetColor(Color& color) { |
| 73 | ScopedSetBlocking sb(this); | 75 | ScopedSetBlocking sb(this); |
| 74 | std::array<u8, 12> buffer{}; | 76 | std::array<u8, 12> buffer{}; |
| 75 | const auto result = ReadRawSPI(SpiAddress::COLOR_DATA, buffer); | 77 | const auto result = ReadRawSPI(SpiAddress::COLOR_DATA, buffer); |
| 76 | 78 | ||
| 77 | color = {}; | 79 | color = {}; |
| 78 | if (result == DriverResult::Success) { | 80 | if (result == Common::Input::DriverResult::Success) { |
| 79 | color.body = static_cast<u32>((buffer[0] << 16) | (buffer[1] << 8) | buffer[2]); | 81 | color.body = static_cast<u32>((buffer[0] << 16) | (buffer[1] << 8) | buffer[2]); |
| 80 | color.buttons = static_cast<u32>((buffer[3] << 16) | (buffer[4] << 8) | buffer[5]); | 82 | color.buttons = static_cast<u32>((buffer[3] << 16) | (buffer[4] << 8) | buffer[5]); |
| 81 | color.left_grip = static_cast<u32>((buffer[6] << 16) | (buffer[7] << 8) | buffer[8]); | 83 | color.left_grip = static_cast<u32>((buffer[6] << 16) | (buffer[7] << 8) | buffer[8]); |
| @@ -85,26 +87,26 @@ DriverResult GenericProtocol::GetColor(Color& color) { | |||
| 85 | return result; | 87 | return result; |
| 86 | } | 88 | } |
| 87 | 89 | ||
| 88 | DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { | 90 | Common::Input::DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { |
| 89 | ScopedSetBlocking sb(this); | 91 | ScopedSetBlocking sb(this); |
| 90 | std::array<u8, 16> buffer{}; | 92 | std::array<u8, 16> buffer{}; |
| 91 | const auto result = ReadRawSPI(SpiAddress::SERIAL_NUMBER, buffer); | 93 | const auto result = ReadRawSPI(SpiAddress::SERIAL_NUMBER, buffer); |
| 92 | 94 | ||
| 93 | serial_number = {}; | 95 | serial_number = {}; |
| 94 | if (result == DriverResult::Success) { | 96 | if (result == Common::Input::DriverResult::Success) { |
| 95 | memcpy(serial_number.data(), buffer.data() + 1, sizeof(SerialNumber)); | 97 | memcpy(serial_number.data(), buffer.data() + 1, sizeof(SerialNumber)); |
| 96 | } | 98 | } |
| 97 | 99 | ||
| 98 | return result; | 100 | return result; |
| 99 | } | 101 | } |
| 100 | 102 | ||
| 101 | DriverResult GenericProtocol::GetTemperature(u32& temperature) { | 103 | Common::Input::DriverResult GenericProtocol::GetTemperature(u32& temperature) { |
| 102 | // Not all devices have temperature sensor | 104 | // Not all devices have temperature sensor |
| 103 | temperature = 25; | 105 | temperature = 25; |
| 104 | return DriverResult::NotSupported; | 106 | return Common::Input::DriverResult::NotSupported; |
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) { | 109 | Common::Input::DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) { |
| 108 | DeviceInfo device_info{}; | 110 | DeviceInfo device_info{}; |
| 109 | 111 | ||
| 110 | const auto result = GetDeviceInfo(device_info); | 112 | const auto result = GetDeviceInfo(device_info); |
| @@ -113,23 +115,23 @@ DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) { | |||
| 113 | return result; | 115 | return result; |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | DriverResult GenericProtocol::SetHomeLight() { | 118 | Common::Input::DriverResult GenericProtocol::SetHomeLight() { |
| 117 | ScopedSetBlocking sb(this); | 119 | ScopedSetBlocking sb(this); |
| 118 | static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00}; | 120 | static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00}; |
| 119 | return SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer); | 121 | return SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer); |
| 120 | } | 122 | } |
| 121 | 123 | ||
| 122 | DriverResult GenericProtocol::SetLedBusy() { | 124 | Common::Input::DriverResult GenericProtocol::SetLedBusy() { |
| 123 | return DriverResult::NotSupported; | 125 | return Common::Input::DriverResult::NotSupported; |
| 124 | } | 126 | } |
| 125 | 127 | ||
| 126 | DriverResult GenericProtocol::SetLedPattern(u8 leds) { | 128 | Common::Input::DriverResult GenericProtocol::SetLedPattern(u8 leds) { |
| 127 | ScopedSetBlocking sb(this); | 129 | ScopedSetBlocking sb(this); |
| 128 | const std::array<u8, 1> buffer{leds}; | 130 | const std::array<u8, 1> buffer{leds}; |
| 129 | return SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer); | 131 | return SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer); |
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) { | 134 | Common::Input::DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) { |
| 133 | return SetLedPattern(static_cast<u8>(leds << 4)); | 135 | return SetLedPattern(static_cast<u8>(leds << 4)); |
| 134 | } | 136 | } |
| 135 | 137 | ||
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.h b/src/input_common/helpers/joycon_protocol/generic_functions.h index 424831e81..90fcd17f6 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.h +++ b/src/input_common/helpers/joycon_protocol/generic_functions.h | |||
| @@ -11,6 +11,10 @@ | |||
| 11 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 11 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 12 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 12 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 13 | 13 | ||
| 14 | namespace Common::Input { | ||
| 15 | enum class DriverResult; | ||
| 16 | } | ||
| 17 | |||
| 14 | namespace InputCommon::Joycon { | 18 | namespace InputCommon::Joycon { |
| 15 | 19 | ||
| 16 | /// Joycon driver functions that easily implemented | 20 | /// Joycon driver functions that easily implemented |
| @@ -20,34 +24,34 @@ public: | |||
| 20 | 24 | ||
| 21 | /// Enables passive mode. This mode only sends button data on change. Sticks will return digital | 25 | /// Enables passive mode. This mode only sends button data on change. Sticks will return digital |
| 22 | /// data instead of analog. Motion will be disabled | 26 | /// data instead of analog. Motion will be disabled |
| 23 | DriverResult EnablePassiveMode(); | 27 | Common::Input::DriverResult EnablePassiveMode(); |
| 24 | 28 | ||
| 25 | /// Enables active mode. This mode will return the current status every 5-15ms | 29 | /// Enables active mode. This mode will return the current status every 5-15ms |
| 26 | DriverResult EnableActiveMode(); | 30 | Common::Input::DriverResult EnableActiveMode(); |
| 27 | 31 | ||
| 28 | /// Enables or disables the low power mode | 32 | /// Enables or disables the low power mode |
| 29 | DriverResult SetLowPowerMode(bool enable); | 33 | Common::Input::DriverResult SetLowPowerMode(bool enable); |
| 30 | 34 | ||
| 31 | /// Unknown function used by the switch | 35 | /// Unknown function used by the switch |
| 32 | DriverResult TriggersElapsed(); | 36 | Common::Input::DriverResult TriggersElapsed(); |
| 33 | 37 | ||
| 34 | /** | 38 | /** |
| 35 | * Sends a request to obtain the joycon firmware and mac from handle | 39 | * Sends a request to obtain the joycon firmware and mac from handle |
| 36 | * @returns controller device info | 40 | * @returns controller device info |
| 37 | */ | 41 | */ |
| 38 | DriverResult GetDeviceInfo(DeviceInfo& controller_type); | 42 | Common::Input::DriverResult GetDeviceInfo(DeviceInfo& controller_type); |
| 39 | 43 | ||
| 40 | /** | 44 | /** |
| 41 | * Sends a request to obtain the joycon type from handle | 45 | * Sends a request to obtain the joycon type from handle |
| 42 | * @returns controller type of the joycon | 46 | * @returns controller type of the joycon |
| 43 | */ | 47 | */ |
| 44 | DriverResult GetControllerType(ControllerType& controller_type); | 48 | Common::Input::DriverResult GetControllerType(ControllerType& controller_type); |
| 45 | 49 | ||
| 46 | /** | 50 | /** |
| 47 | * Enables motion input | 51 | * Enables motion input |
| 48 | * @param enable if true motion data will be enabled | 52 | * @param enable if true motion data will be enabled |
| 49 | */ | 53 | */ |
| 50 | DriverResult EnableImu(bool enable); | 54 | Common::Input::DriverResult EnableImu(bool enable); |
| 51 | 55 | ||
| 52 | /** | 56 | /** |
| 53 | * Configures the motion sensor with the specified parameters | 57 | * Configures the motion sensor with the specified parameters |
| @@ -56,59 +60,60 @@ public: | |||
| 56 | * @param asen accelerometer sensitivity in G force | 60 | * @param asen accelerometer sensitivity in G force |
| 57 | * @param afrec accelerometer frequency in hertz | 61 | * @param afrec accelerometer frequency in hertz |
| 58 | */ | 62 | */ |
| 59 | DriverResult SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, | 63 | Common::Input::DriverResult SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, |
| 60 | AccelerometerSensitivity asen, AccelerometerPerformance afrec); | 64 | AccelerometerSensitivity asen, |
| 65 | AccelerometerPerformance afrec); | ||
| 61 | 66 | ||
| 62 | /** | 67 | /** |
| 63 | * Request battery level from the device | 68 | * Request battery level from the device |
| 64 | * @returns battery level | 69 | * @returns battery level |
| 65 | */ | 70 | */ |
| 66 | DriverResult GetBattery(u32& battery_level); | 71 | Common::Input::DriverResult GetBattery(u32& battery_level); |
| 67 | 72 | ||
| 68 | /** | 73 | /** |
| 69 | * Request joycon colors from the device | 74 | * Request joycon colors from the device |
| 70 | * @returns colors of the body and buttons | 75 | * @returns colors of the body and buttons |
| 71 | */ | 76 | */ |
| 72 | DriverResult GetColor(Color& color); | 77 | Common::Input::DriverResult GetColor(Color& color); |
| 73 | 78 | ||
| 74 | /** | 79 | /** |
| 75 | * Request joycon serial number from the device | 80 | * Request joycon serial number from the device |
| 76 | * @returns 16 byte serial number | 81 | * @returns 16 byte serial number |
| 77 | */ | 82 | */ |
| 78 | DriverResult GetSerialNumber(SerialNumber& serial_number); | 83 | Common::Input::DriverResult GetSerialNumber(SerialNumber& serial_number); |
| 79 | 84 | ||
| 80 | /** | 85 | /** |
| 81 | * Request joycon serial number from the device | 86 | * Request joycon serial number from the device |
| 82 | * @returns 16 byte serial number | 87 | * @returns 16 byte serial number |
| 83 | */ | 88 | */ |
| 84 | DriverResult GetTemperature(u32& temperature); | 89 | Common::Input::DriverResult GetTemperature(u32& temperature); |
| 85 | 90 | ||
| 86 | /** | 91 | /** |
| 87 | * Request joycon serial number from the device | 92 | * Request joycon serial number from the device |
| 88 | * @returns 16 byte serial number | 93 | * @returns 16 byte serial number |
| 89 | */ | 94 | */ |
| 90 | DriverResult GetVersionNumber(FirmwareVersion& version); | 95 | Common::Input::DriverResult GetVersionNumber(FirmwareVersion& version); |
| 91 | 96 | ||
| 92 | /** | 97 | /** |
| 93 | * Sets home led behaviour | 98 | * Sets home led behaviour |
| 94 | */ | 99 | */ |
| 95 | DriverResult SetHomeLight(); | 100 | Common::Input::DriverResult SetHomeLight(); |
| 96 | 101 | ||
| 97 | /** | 102 | /** |
| 98 | * Sets home led into a slow breathing state | 103 | * Sets home led into a slow breathing state |
| 99 | */ | 104 | */ |
| 100 | DriverResult SetLedBusy(); | 105 | Common::Input::DriverResult SetLedBusy(); |
| 101 | 106 | ||
| 102 | /** | 107 | /** |
| 103 | * Sets the 4 player leds on the joycon on a solid state | 108 | * Sets the 4 player leds on the joycon on a solid state |
| 104 | * @params bit flag containing the led state | 109 | * @params bit flag containing the led state |
| 105 | */ | 110 | */ |
| 106 | DriverResult SetLedPattern(u8 leds); | 111 | Common::Input::DriverResult SetLedPattern(u8 leds); |
| 107 | 112 | ||
| 108 | /** | 113 | /** |
| 109 | * Sets the 4 player leds on the joycon on a blinking state | 114 | * Sets the 4 player leds on the joycon on a blinking state |
| 110 | * @returns bit flag containing the led state | 115 | * @returns bit flag containing the led state |
| 111 | */ | 116 | */ |
| 112 | DriverResult SetLedBlinkPattern(u8 leds); | 117 | Common::Input::DriverResult SetLedBlinkPattern(u8 leds); |
| 113 | }; | 118 | }; |
| 114 | } // namespace InputCommon::Joycon | 119 | } // namespace InputCommon::Joycon |
diff --git a/src/input_common/helpers/joycon_protocol/irs.cpp b/src/input_common/helpers/joycon_protocol/irs.cpp index 731fd5981..68b0589e3 100644 --- a/src/input_common/helpers/joycon_protocol/irs.cpp +++ b/src/input_common/helpers/joycon_protocol/irs.cpp | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <thread> | 4 | #include "common/input.h" |
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "input_common/helpers/joycon_protocol/irs.h" | 6 | #include "input_common/helpers/joycon_protocol/irs.h" |
| 7 | 7 | ||
| @@ -10,21 +10,21 @@ namespace InputCommon::Joycon { | |||
| 10 | IrsProtocol::IrsProtocol(std::shared_ptr<JoyconHandle> handle) | 10 | IrsProtocol::IrsProtocol(std::shared_ptr<JoyconHandle> handle) |
| 11 | : JoyconCommonProtocol(std::move(handle)) {} | 11 | : JoyconCommonProtocol(std::move(handle)) {} |
| 12 | 12 | ||
| 13 | DriverResult IrsProtocol::EnableIrs() { | 13 | Common::Input::DriverResult IrsProtocol::EnableIrs() { |
| 14 | LOG_INFO(Input, "Enable IRS"); | 14 | LOG_INFO(Input, "Enable IRS"); |
| 15 | ScopedSetBlocking sb(this); | 15 | ScopedSetBlocking sb(this); |
| 16 | DriverResult result{DriverResult::Success}; | 16 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 17 | 17 | ||
| 18 | if (result == DriverResult::Success) { | 18 | if (result == Common::Input::DriverResult::Success) { |
| 19 | result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); | 19 | result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); |
| 20 | } | 20 | } |
| 21 | if (result == DriverResult::Success) { | 21 | if (result == Common::Input::DriverResult::Success) { |
| 22 | result = EnableMCU(true); | 22 | result = EnableMCU(true); |
| 23 | } | 23 | } |
| 24 | if (result == DriverResult::Success) { | 24 | if (result == Common::Input::DriverResult::Success) { |
| 25 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); | 25 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); |
| 26 | } | 26 | } |
| 27 | if (result == DriverResult::Success) { | 27 | if (result == Common::Input::DriverResult::Success) { |
| 28 | const MCUConfig config{ | 28 | const MCUConfig config{ |
| 29 | .command = MCUCommand::ConfigureMCU, | 29 | .command = MCUCommand::ConfigureMCU, |
| 30 | .sub_command = MCUSubCommand::SetMCUMode, | 30 | .sub_command = MCUSubCommand::SetMCUMode, |
| @@ -34,16 +34,16 @@ DriverResult IrsProtocol::EnableIrs() { | |||
| 34 | 34 | ||
| 35 | result = ConfigureMCU(config); | 35 | result = ConfigureMCU(config); |
| 36 | } | 36 | } |
| 37 | if (result == DriverResult::Success) { | 37 | if (result == Common::Input::DriverResult::Success) { |
| 38 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::IR); | 38 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::IR); |
| 39 | } | 39 | } |
| 40 | if (result == DriverResult::Success) { | 40 | if (result == Common::Input::DriverResult::Success) { |
| 41 | result = ConfigureIrs(); | 41 | result = ConfigureIrs(); |
| 42 | } | 42 | } |
| 43 | if (result == DriverResult::Success) { | 43 | if (result == Common::Input::DriverResult::Success) { |
| 44 | result = WriteRegistersStep1(); | 44 | result = WriteRegistersStep1(); |
| 45 | } | 45 | } |
| 46 | if (result == DriverResult::Success) { | 46 | if (result == Common::Input::DriverResult::Success) { |
| 47 | result = WriteRegistersStep2(); | 47 | result = WriteRegistersStep2(); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| @@ -52,12 +52,12 @@ DriverResult IrsProtocol::EnableIrs() { | |||
| 52 | return result; | 52 | return result; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | DriverResult IrsProtocol::DisableIrs() { | 55 | Common::Input::DriverResult IrsProtocol::DisableIrs() { |
| 56 | LOG_DEBUG(Input, "Disable IRS"); | 56 | LOG_DEBUG(Input, "Disable IRS"); |
| 57 | ScopedSetBlocking sb(this); | 57 | ScopedSetBlocking sb(this); |
| 58 | DriverResult result{DriverResult::Success}; | 58 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 59 | 59 | ||
| 60 | if (result == DriverResult::Success) { | 60 | if (result == Common::Input::DriverResult::Success) { |
| 61 | result = EnableMCU(false); | 61 | result = EnableMCU(false); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| @@ -66,7 +66,7 @@ DriverResult IrsProtocol::DisableIrs() { | |||
| 66 | return result; | 66 | return result; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | DriverResult IrsProtocol::SetIrsConfig(IrsMode mode, IrsResolution format) { | 69 | Common::Input::DriverResult IrsProtocol::SetIrsConfig(IrsMode mode, IrsResolution format) { |
| 70 | irs_mode = mode; | 70 | irs_mode = mode; |
| 71 | switch (format) { | 71 | switch (format) { |
| 72 | case IrsResolution::Size320x240: | 72 | case IrsResolution::Size320x240: |
| @@ -103,10 +103,10 @@ DriverResult IrsProtocol::SetIrsConfig(IrsMode mode, IrsResolution format) { | |||
| 103 | return EnableIrs(); | 103 | return EnableIrs(); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | return DriverResult::Success; | 106 | return Common::Input::DriverResult::Success; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | DriverResult IrsProtocol::RequestImage(std::span<u8> buffer) { | 109 | Common::Input::DriverResult IrsProtocol::RequestImage(std::span<u8> buffer) { |
| 110 | const u8 next_packet_fragment = | 110 | const u8 next_packet_fragment = |
| 111 | static_cast<u8>((packet_fragment + 1) % (static_cast<u8>(fragments) + 1)); | 111 | static_cast<u8>((packet_fragment + 1) % (static_cast<u8>(fragments) + 1)); |
| 112 | 112 | ||
| @@ -129,7 +129,7 @@ DriverResult IrsProtocol::RequestImage(std::span<u8> buffer) { | |||
| 129 | return RequestFrame(packet_fragment); | 129 | return RequestFrame(packet_fragment); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | DriverResult IrsProtocol::ConfigureIrs() { | 132 | Common::Input::DriverResult IrsProtocol::ConfigureIrs() { |
| 133 | LOG_DEBUG(Input, "Configure IRS"); | 133 | LOG_DEBUG(Input, "Configure IRS"); |
| 134 | constexpr std::size_t max_tries = 28; | 134 | constexpr std::size_t max_tries = 28; |
| 135 | SubCommandResponse output{}; | 135 | SubCommandResponse output{}; |
| @@ -152,20 +152,20 @@ DriverResult IrsProtocol::ConfigureIrs() { | |||
| 152 | do { | 152 | do { |
| 153 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); | 153 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); |
| 154 | 154 | ||
| 155 | if (result != DriverResult::Success) { | 155 | if (result != Common::Input::DriverResult::Success) { |
| 156 | return result; | 156 | return result; |
| 157 | } | 157 | } |
| 158 | if (tries++ >= max_tries) { | 158 | if (tries++ >= max_tries) { |
| 159 | return DriverResult::WrongReply; | 159 | return Common::Input::DriverResult::WrongReply; |
| 160 | } | 160 | } |
| 161 | } while (output.command_data[0] != 0x0b); | 161 | } while (output.command_data[0] != 0x0b); |
| 162 | 162 | ||
| 163 | return DriverResult::Success; | 163 | return Common::Input::DriverResult::Success; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | DriverResult IrsProtocol::WriteRegistersStep1() { | 166 | Common::Input::DriverResult IrsProtocol::WriteRegistersStep1() { |
| 167 | LOG_DEBUG(Input, "WriteRegistersStep1"); | 167 | LOG_DEBUG(Input, "WriteRegistersStep1"); |
| 168 | DriverResult result{DriverResult::Success}; | 168 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 169 | constexpr std::size_t max_tries = 28; | 169 | constexpr std::size_t max_tries = 28; |
| 170 | SubCommandResponse output{}; | 170 | SubCommandResponse output{}; |
| 171 | std::size_t tries = 0; | 171 | std::size_t tries = 0; |
| @@ -197,7 +197,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() { | |||
| 197 | mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); | 197 | mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); |
| 198 | mcu_request[37] = 0xFF; | 198 | mcu_request[37] = 0xFF; |
| 199 | 199 | ||
| 200 | if (result != DriverResult::Success) { | 200 | if (result != Common::Input::DriverResult::Success) { |
| 201 | return result; | 201 | return result; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| @@ -205,26 +205,26 @@ DriverResult IrsProtocol::WriteRegistersStep1() { | |||
| 205 | result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); | 205 | result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); |
| 206 | 206 | ||
| 207 | // First time we need to set the report mode | 207 | // First time we need to set the report mode |
| 208 | if (result == DriverResult::Success && tries == 0) { | 208 | if (result == Common::Input::DriverResult::Success && tries == 0) { |
| 209 | result = SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request); | 209 | result = SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request); |
| 210 | } | 210 | } |
| 211 | if (result == DriverResult::Success && tries == 0) { | 211 | if (result == Common::Input::DriverResult::Success && tries == 0) { |
| 212 | GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output); | 212 | GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | if (result != DriverResult::Success) { | 215 | if (result != Common::Input::DriverResult::Success) { |
| 216 | return result; | 216 | return result; |
| 217 | } | 217 | } |
| 218 | if (tries++ >= max_tries) { | 218 | if (tries++ >= max_tries) { |
| 219 | return DriverResult::WrongReply; | 219 | return Common::Input::DriverResult::WrongReply; |
| 220 | } | 220 | } |
| 221 | } while (!(output.command_data[0] == 0x13 && output.command_data[2] == 0x07) && | 221 | } while (!(output.command_data[0] == 0x13 && output.command_data[2] == 0x07) && |
| 222 | output.command_data[0] != 0x23); | 222 | output.command_data[0] != 0x23); |
| 223 | 223 | ||
| 224 | return DriverResult::Success; | 224 | return Common::Input::DriverResult::Success; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | DriverResult IrsProtocol::WriteRegistersStep2() { | 227 | Common::Input::DriverResult IrsProtocol::WriteRegistersStep2() { |
| 228 | LOG_DEBUG(Input, "WriteRegistersStep2"); | 228 | LOG_DEBUG(Input, "WriteRegistersStep2"); |
| 229 | constexpr std::size_t max_tries = 28; | 229 | constexpr std::size_t max_tries = 28; |
| 230 | SubCommandResponse output{}; | 230 | SubCommandResponse output{}; |
| @@ -255,18 +255,18 @@ DriverResult IrsProtocol::WriteRegistersStep2() { | |||
| 255 | do { | 255 | do { |
| 256 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); | 256 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); |
| 257 | 257 | ||
| 258 | if (result != DriverResult::Success) { | 258 | if (result != Common::Input::DriverResult::Success) { |
| 259 | return result; | 259 | return result; |
| 260 | } | 260 | } |
| 261 | if (tries++ >= max_tries) { | 261 | if (tries++ >= max_tries) { |
| 262 | return DriverResult::WrongReply; | 262 | return Common::Input::DriverResult::WrongReply; |
| 263 | } | 263 | } |
| 264 | } while (output.command_data[0] != 0x13 && output.command_data[0] != 0x23); | 264 | } while (output.command_data[0] != 0x13 && output.command_data[0] != 0x23); |
| 265 | 265 | ||
| 266 | return DriverResult::Success; | 266 | return Common::Input::DriverResult::Success; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | DriverResult IrsProtocol::RequestFrame(u8 frame) { | 269 | Common::Input::DriverResult IrsProtocol::RequestFrame(u8 frame) { |
| 270 | std::array<u8, 38> mcu_request{}; | 270 | std::array<u8, 38> mcu_request{}; |
| 271 | mcu_request[3] = frame; | 271 | mcu_request[3] = frame; |
| 272 | mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); | 272 | mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); |
| @@ -274,7 +274,7 @@ DriverResult IrsProtocol::RequestFrame(u8 frame) { | |||
| 274 | return SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request); | 274 | return SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | DriverResult IrsProtocol::ResendFrame(u8 frame) { | 277 | Common::Input::DriverResult IrsProtocol::ResendFrame(u8 frame) { |
| 278 | std::array<u8, 38> mcu_request{}; | 278 | std::array<u8, 38> mcu_request{}; |
| 279 | mcu_request[1] = 0x1; | 279 | mcu_request[1] = 0x1; |
| 280 | mcu_request[2] = frame; | 280 | mcu_request[2] = frame; |
diff --git a/src/input_common/helpers/joycon_protocol/irs.h b/src/input_common/helpers/joycon_protocol/irs.h index 76dfa02ea..714cbb6b2 100644 --- a/src/input_common/helpers/joycon_protocol/irs.h +++ b/src/input_common/helpers/joycon_protocol/irs.h | |||
| @@ -13,19 +13,23 @@ | |||
| 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 15 | 15 | ||
| 16 | namespace Common::Input { | ||
| 17 | enum class DriverResult; | ||
| 18 | } | ||
| 19 | |||
| 16 | namespace InputCommon::Joycon { | 20 | namespace InputCommon::Joycon { |
| 17 | 21 | ||
| 18 | class IrsProtocol final : private JoyconCommonProtocol { | 22 | class IrsProtocol final : private JoyconCommonProtocol { |
| 19 | public: | 23 | public: |
| 20 | explicit IrsProtocol(std::shared_ptr<JoyconHandle> handle); | 24 | explicit IrsProtocol(std::shared_ptr<JoyconHandle> handle); |
| 21 | 25 | ||
| 22 | DriverResult EnableIrs(); | 26 | Common::Input::DriverResult EnableIrs(); |
| 23 | 27 | ||
| 24 | DriverResult DisableIrs(); | 28 | Common::Input::DriverResult DisableIrs(); |
| 25 | 29 | ||
| 26 | DriverResult SetIrsConfig(IrsMode mode, IrsResolution format); | 30 | Common::Input::DriverResult SetIrsConfig(IrsMode mode, IrsResolution format); |
| 27 | 31 | ||
| 28 | DriverResult RequestImage(std::span<u8> buffer); | 32 | Common::Input::DriverResult RequestImage(std::span<u8> buffer); |
| 29 | 33 | ||
| 30 | std::vector<u8> GetImage() const; | 34 | std::vector<u8> GetImage() const; |
| 31 | 35 | ||
| @@ -34,13 +38,13 @@ public: | |||
| 34 | bool IsEnabled() const; | 38 | bool IsEnabled() const; |
| 35 | 39 | ||
| 36 | private: | 40 | private: |
| 37 | DriverResult ConfigureIrs(); | 41 | Common::Input::DriverResult ConfigureIrs(); |
| 38 | 42 | ||
| 39 | DriverResult WriteRegistersStep1(); | 43 | Common::Input::DriverResult WriteRegistersStep1(); |
| 40 | DriverResult WriteRegistersStep2(); | 44 | Common::Input::DriverResult WriteRegistersStep2(); |
| 41 | 45 | ||
| 42 | DriverResult RequestFrame(u8 frame); | 46 | Common::Input::DriverResult RequestFrame(u8 frame); |
| 43 | DriverResult ResendFrame(u8 frame); | 47 | Common::Input::DriverResult ResendFrame(u8 frame); |
| 44 | 48 | ||
| 45 | IrsMode irs_mode{IrsMode::ImageTransfer}; | 49 | IrsMode irs_mode{IrsMode::ImageTransfer}; |
| 46 | IrsResolution resolution{IrsResolution::Size40x30}; | 50 | IrsResolution resolution{IrsResolution::Size40x30}; |
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index e0e431156..77a43c67a 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h | |||
| @@ -402,23 +402,6 @@ enum class ExternalDeviceId : u16 { | |||
| 402 | Starlink = 0x2800, | 402 | Starlink = 0x2800, |
| 403 | }; | 403 | }; |
| 404 | 404 | ||
| 405 | enum class DriverResult { | ||
| 406 | Success, | ||
| 407 | WrongReply, | ||
| 408 | Timeout, | ||
| 409 | InvalidParameters, | ||
| 410 | UnsupportedControllerType, | ||
| 411 | HandleInUse, | ||
| 412 | ErrorReadingData, | ||
| 413 | ErrorWritingData, | ||
| 414 | NoDeviceDetected, | ||
| 415 | InvalidHandle, | ||
| 416 | NotSupported, | ||
| 417 | Disabled, | ||
| 418 | Delayed, | ||
| 419 | Unknown, | ||
| 420 | }; | ||
| 421 | |||
| 422 | struct MotionSensorCalibration { | 405 | struct MotionSensorCalibration { |
| 423 | s16 offset; | 406 | s16 offset; |
| 424 | s16 scale; | 407 | s16 scale; |
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index 261f46255..09953394b 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <thread> | 4 | #include "common/input.h" |
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "input_common/helpers/joycon_protocol/nfc.h" | 6 | #include "input_common/helpers/joycon_protocol/nfc.h" |
| 7 | 7 | ||
| @@ -10,21 +10,21 @@ namespace InputCommon::Joycon { | |||
| 10 | NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle) | 10 | NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle) |
| 11 | : JoyconCommonProtocol(std::move(handle)) {} | 11 | : JoyconCommonProtocol(std::move(handle)) {} |
| 12 | 12 | ||
| 13 | DriverResult NfcProtocol::EnableNfc() { | 13 | Common::Input::DriverResult NfcProtocol::EnableNfc() { |
| 14 | LOG_INFO(Input, "Enable NFC"); | 14 | LOG_INFO(Input, "Enable NFC"); |
| 15 | ScopedSetBlocking sb(this); | 15 | ScopedSetBlocking sb(this); |
| 16 | DriverResult result{DriverResult::Success}; | 16 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 17 | 17 | ||
| 18 | if (result == DriverResult::Success) { | 18 | if (result == Common::Input::DriverResult::Success) { |
| 19 | result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); | 19 | result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); |
| 20 | } | 20 | } |
| 21 | if (result == DriverResult::Success) { | 21 | if (result == Common::Input::DriverResult::Success) { |
| 22 | result = EnableMCU(true); | 22 | result = EnableMCU(true); |
| 23 | } | 23 | } |
| 24 | if (result == DriverResult::Success) { | 24 | if (result == Common::Input::DriverResult::Success) { |
| 25 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); | 25 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); |
| 26 | } | 26 | } |
| 27 | if (result == DriverResult::Success) { | 27 | if (result == Common::Input::DriverResult::Success) { |
| 28 | const MCUConfig config{ | 28 | const MCUConfig config{ |
| 29 | .command = MCUCommand::ConfigureMCU, | 29 | .command = MCUCommand::ConfigureMCU, |
| 30 | .sub_command = MCUSubCommand::SetMCUMode, | 30 | .sub_command = MCUSubCommand::SetMCUMode, |
| @@ -34,32 +34,32 @@ DriverResult NfcProtocol::EnableNfc() { | |||
| 34 | 34 | ||
| 35 | result = ConfigureMCU(config); | 35 | result = ConfigureMCU(config); |
| 36 | } | 36 | } |
| 37 | if (result == DriverResult::Success) { | 37 | if (result == Common::Input::DriverResult::Success) { |
| 38 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); | 38 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); |
| 39 | } | 39 | } |
| 40 | if (result == DriverResult::Success) { | 40 | if (result == Common::Input::DriverResult::Success) { |
| 41 | result = WaitUntilNfcIs(NFCStatus::Ready); | 41 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 42 | } | 42 | } |
| 43 | if (result == DriverResult::Success) { | 43 | if (result == Common::Input::DriverResult::Success) { |
| 44 | MCUCommandResponse output{}; | 44 | MCUCommandResponse output{}; |
| 45 | result = SendStopPollingRequest(output); | 45 | result = SendStopPollingRequest(output); |
| 46 | } | 46 | } |
| 47 | if (result == DriverResult::Success) { | 47 | if (result == Common::Input::DriverResult::Success) { |
| 48 | result = WaitUntilNfcIs(NFCStatus::Ready); | 48 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 49 | } | 49 | } |
| 50 | if (result == DriverResult::Success) { | 50 | if (result == Common::Input::DriverResult::Success) { |
| 51 | is_enabled = true; | 51 | is_enabled = true; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | return result; | 54 | return result; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | DriverResult NfcProtocol::DisableNfc() { | 57 | Common::Input::DriverResult NfcProtocol::DisableNfc() { |
| 58 | LOG_DEBUG(Input, "Disable NFC"); | 58 | LOG_DEBUG(Input, "Disable NFC"); |
| 59 | ScopedSetBlocking sb(this); | 59 | ScopedSetBlocking sb(this); |
| 60 | DriverResult result{DriverResult::Success}; | 60 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 61 | 61 | ||
| 62 | if (result == DriverResult::Success) { | 62 | if (result == Common::Input::DriverResult::Success) { |
| 63 | result = EnableMCU(false); | 63 | result = EnableMCU(false); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| @@ -69,60 +69,60 @@ DriverResult NfcProtocol::DisableNfc() { | |||
| 69 | return result; | 69 | return result; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | DriverResult NfcProtocol::StartNFCPollingMode() { | 72 | Common::Input::DriverResult NfcProtocol::StartNFCPollingMode() { |
| 73 | LOG_DEBUG(Input, "Start NFC polling Mode"); | 73 | LOG_DEBUG(Input, "Start NFC polling Mode"); |
| 74 | ScopedSetBlocking sb(this); | 74 | ScopedSetBlocking sb(this); |
| 75 | DriverResult result{DriverResult::Success}; | 75 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 76 | 76 | ||
| 77 | if (result == DriverResult::Success) { | 77 | if (result == Common::Input::DriverResult::Success) { |
| 78 | MCUCommandResponse output{}; | 78 | MCUCommandResponse output{}; |
| 79 | result = SendStartPollingRequest(output); | 79 | result = SendStartPollingRequest(output); |
| 80 | } | 80 | } |
| 81 | if (result == DriverResult::Success) { | 81 | if (result == Common::Input::DriverResult::Success) { |
| 82 | result = WaitUntilNfcIs(NFCStatus::Polling); | 82 | result = WaitUntilNfcIs(NFCStatus::Polling); |
| 83 | } | 83 | } |
| 84 | if (result == DriverResult::Success) { | 84 | if (result == Common::Input::DriverResult::Success) { |
| 85 | is_polling = true; | 85 | is_polling = true; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | return result; | 88 | return result; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | DriverResult NfcProtocol::StopNFCPollingMode() { | 91 | Common::Input::DriverResult NfcProtocol::StopNFCPollingMode() { |
| 92 | LOG_DEBUG(Input, "Stop NFC polling Mode"); | 92 | LOG_DEBUG(Input, "Stop NFC polling Mode"); |
| 93 | ScopedSetBlocking sb(this); | 93 | ScopedSetBlocking sb(this); |
| 94 | DriverResult result{DriverResult::Success}; | 94 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 95 | 95 | ||
| 96 | if (result == DriverResult::Success) { | 96 | if (result == Common::Input::DriverResult::Success) { |
| 97 | MCUCommandResponse output{}; | 97 | MCUCommandResponse output{}; |
| 98 | result = SendStopPollingRequest(output); | 98 | result = SendStopPollingRequest(output); |
| 99 | } | 99 | } |
| 100 | if (result == DriverResult::Success) { | 100 | if (result == Common::Input::DriverResult::Success) { |
| 101 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | 101 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 102 | } | 102 | } |
| 103 | if (result == DriverResult::Success) { | 103 | if (result == Common::Input::DriverResult::Success) { |
| 104 | is_polling = false; | 104 | is_polling = false; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | return result; | 107 | return result; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | DriverResult NfcProtocol::GetTagInfo(Joycon::TagInfo& tag_info) { | 110 | Common::Input::DriverResult NfcProtocol::GetTagInfo(Joycon::TagInfo& tag_info) { |
| 111 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { | 111 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { |
| 112 | return DriverResult::Delayed; | 112 | return Common::Input::DriverResult::Delayed; |
| 113 | } | 113 | } |
| 114 | update_counter = 0; | 114 | update_counter = 0; |
| 115 | 115 | ||
| 116 | LOG_DEBUG(Input, "Scan for amiibos"); | 116 | LOG_DEBUG(Input, "Scan for amiibos"); |
| 117 | ScopedSetBlocking sb(this); | 117 | ScopedSetBlocking sb(this); |
| 118 | DriverResult result{DriverResult::Success}; | 118 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 119 | TagFoundData tag_data{}; | 119 | TagFoundData tag_data{}; |
| 120 | 120 | ||
| 121 | if (result == DriverResult::Success) { | 121 | if (result == Common::Input::DriverResult::Success) { |
| 122 | result = IsTagInRange(tag_data); | 122 | result = IsTagInRange(tag_data); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | if (result == DriverResult::Success) { | 125 | if (result == Common::Input::DriverResult::Success) { |
| 126 | tag_info = { | 126 | tag_info = { |
| 127 | .uuid_length = tag_data.uuid_size, | 127 | .uuid_length = tag_data.uuid_size, |
| 128 | .protocol = 1, | 128 | .protocol = 1, |
| @@ -147,59 +147,59 @@ DriverResult NfcProtocol::GetTagInfo(Joycon::TagInfo& tag_info) { | |||
| 147 | return result; | 147 | return result; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | DriverResult NfcProtocol::ReadAmiibo(std::vector<u8>& data) { | 150 | Common::Input::DriverResult NfcProtocol::ReadAmiibo(std::vector<u8>& data) { |
| 151 | LOG_DEBUG(Input, "Scan for amiibos"); | 151 | LOG_DEBUG(Input, "Scan for amiibos"); |
| 152 | ScopedSetBlocking sb(this); | 152 | ScopedSetBlocking sb(this); |
| 153 | DriverResult result{DriverResult::Success}; | 153 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 154 | TagFoundData tag_data{}; | 154 | TagFoundData tag_data{}; |
| 155 | 155 | ||
| 156 | if (result == DriverResult::Success) { | 156 | if (result == Common::Input::DriverResult::Success) { |
| 157 | result = IsTagInRange(tag_data, 7); | 157 | result = IsTagInRange(tag_data, 7); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | if (result == DriverResult::Success) { | 160 | if (result == Common::Input::DriverResult::Success) { |
| 161 | result = GetAmiiboData(data); | 161 | result = GetAmiiboData(data); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | return result; | 164 | return result; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | DriverResult NfcProtocol::WriteAmiibo(std::span<const u8> data) { | 167 | Common::Input::DriverResult NfcProtocol::WriteAmiibo(std::span<const u8> data) { |
| 168 | LOG_DEBUG(Input, "Write amiibo"); | 168 | LOG_DEBUG(Input, "Write amiibo"); |
| 169 | ScopedSetBlocking sb(this); | 169 | ScopedSetBlocking sb(this); |
| 170 | DriverResult result{DriverResult::Success}; | 170 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 171 | TagUUID tag_uuid = GetTagUUID(data); | 171 | TagUUID tag_uuid = GetTagUUID(data); |
| 172 | TagFoundData tag_data{}; | 172 | TagFoundData tag_data{}; |
| 173 | 173 | ||
| 174 | if (result == DriverResult::Success) { | 174 | if (result == Common::Input::DriverResult::Success) { |
| 175 | result = IsTagInRange(tag_data, 7); | 175 | result = IsTagInRange(tag_data, 7); |
| 176 | } | 176 | } |
| 177 | if (result == DriverResult::Success) { | 177 | if (result == Common::Input::DriverResult::Success) { |
| 178 | if (tag_data.uuid != tag_uuid) { | 178 | if (tag_data.uuid != tag_uuid) { |
| 179 | result = DriverResult::InvalidParameters; | 179 | result = Common::Input::DriverResult::InvalidParameters; |
| 180 | } | 180 | } |
| 181 | } | 181 | } |
| 182 | if (result == DriverResult::Success) { | 182 | if (result == Common::Input::DriverResult::Success) { |
| 183 | MCUCommandResponse output{}; | 183 | MCUCommandResponse output{}; |
| 184 | result = SendStopPollingRequest(output); | 184 | result = SendStopPollingRequest(output); |
| 185 | } | 185 | } |
| 186 | if (result == DriverResult::Success) { | 186 | if (result == Common::Input::DriverResult::Success) { |
| 187 | result = WaitUntilNfcIs(NFCStatus::Ready); | 187 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 188 | } | 188 | } |
| 189 | if (result == DriverResult::Success) { | 189 | if (result == Common::Input::DriverResult::Success) { |
| 190 | MCUCommandResponse output{}; | 190 | MCUCommandResponse output{}; |
| 191 | result = SendStartPollingRequest(output, true); | 191 | result = SendStartPollingRequest(output, true); |
| 192 | } | 192 | } |
| 193 | if (result == DriverResult::Success) { | 193 | if (result == Common::Input::DriverResult::Success) { |
| 194 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | 194 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 195 | } | 195 | } |
| 196 | if (result == DriverResult::Success) { | 196 | if (result == Common::Input::DriverResult::Success) { |
| 197 | result = WriteAmiiboData(tag_uuid, data); | 197 | result = WriteAmiiboData(tag_uuid, data); |
| 198 | } | 198 | } |
| 199 | if (result == DriverResult::Success) { | 199 | if (result == Common::Input::DriverResult::Success) { |
| 200 | result = WaitUntilNfcIs(NFCStatus::WriteDone); | 200 | result = WaitUntilNfcIs(NFCStatus::WriteDone); |
| 201 | } | 201 | } |
| 202 | if (result == DriverResult::Success) { | 202 | if (result == Common::Input::DriverResult::Success) { |
| 203 | MCUCommandResponse output{}; | 203 | MCUCommandResponse output{}; |
| 204 | result = SendStopPollingRequest(output); | 204 | result = SendStopPollingRequest(output); |
| 205 | } | 205 | } |
| @@ -207,64 +207,65 @@ DriverResult NfcProtocol::WriteAmiibo(std::span<const u8> data) { | |||
| 207 | return result; | 207 | return result; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | DriverResult NfcProtocol::ReadMifare(std::span<const MifareReadChunk> read_request, | 210 | Common::Input::DriverResult NfcProtocol::ReadMifare(std::span<const MifareReadChunk> read_request, |
| 211 | std::span<MifareReadData> out_data) { | 211 | std::span<MifareReadData> out_data) { |
| 212 | LOG_DEBUG(Input, "Read mifare"); | 212 | LOG_DEBUG(Input, "Read mifare"); |
| 213 | ScopedSetBlocking sb(this); | 213 | ScopedSetBlocking sb(this); |
| 214 | DriverResult result{DriverResult::Success}; | 214 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 215 | TagFoundData tag_data{}; | 215 | TagFoundData tag_data{}; |
| 216 | MifareUUID tag_uuid{}; | 216 | MifareUUID tag_uuid{}; |
| 217 | 217 | ||
| 218 | if (result == DriverResult::Success) { | 218 | if (result == Common::Input::DriverResult::Success) { |
| 219 | result = IsTagInRange(tag_data, 7); | 219 | result = IsTagInRange(tag_data, 7); |
| 220 | } | 220 | } |
| 221 | if (result == DriverResult::Success) { | 221 | if (result == Common::Input::DriverResult::Success) { |
| 222 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); | 222 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); |
| 223 | result = GetMifareData(tag_uuid, read_request, out_data); | 223 | result = GetMifareData(tag_uuid, read_request, out_data); |
| 224 | } | 224 | } |
| 225 | if (result == DriverResult::Success) { | 225 | if (result == Common::Input::DriverResult::Success) { |
| 226 | MCUCommandResponse output{}; | 226 | MCUCommandResponse output{}; |
| 227 | result = SendStopPollingRequest(output); | 227 | result = SendStopPollingRequest(output); |
| 228 | } | 228 | } |
| 229 | if (result == DriverResult::Success) { | 229 | if (result == Common::Input::DriverResult::Success) { |
| 230 | result = WaitUntilNfcIs(NFCStatus::Ready); | 230 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 231 | } | 231 | } |
| 232 | if (result == DriverResult::Success) { | 232 | if (result == Common::Input::DriverResult::Success) { |
| 233 | MCUCommandResponse output{}; | 233 | MCUCommandResponse output{}; |
| 234 | result = SendStartPollingRequest(output, true); | 234 | result = SendStartPollingRequest(output, true); |
| 235 | } | 235 | } |
| 236 | if (result == DriverResult::Success) { | 236 | if (result == Common::Input::DriverResult::Success) { |
| 237 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | 237 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 238 | } | 238 | } |
| 239 | return result; | 239 | return result; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | DriverResult NfcProtocol::WriteMifare(std::span<const MifareWriteChunk> write_request) { | 242 | Common::Input::DriverResult NfcProtocol::WriteMifare( |
| 243 | std::span<const MifareWriteChunk> write_request) { | ||
| 243 | LOG_DEBUG(Input, "Write mifare"); | 244 | LOG_DEBUG(Input, "Write mifare"); |
| 244 | ScopedSetBlocking sb(this); | 245 | ScopedSetBlocking sb(this); |
| 245 | DriverResult result{DriverResult::Success}; | 246 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 246 | TagFoundData tag_data{}; | 247 | TagFoundData tag_data{}; |
| 247 | MifareUUID tag_uuid{}; | 248 | MifareUUID tag_uuid{}; |
| 248 | 249 | ||
| 249 | if (result == DriverResult::Success) { | 250 | if (result == Common::Input::DriverResult::Success) { |
| 250 | result = IsTagInRange(tag_data, 7); | 251 | result = IsTagInRange(tag_data, 7); |
| 251 | } | 252 | } |
| 252 | if (result == DriverResult::Success) { | 253 | if (result == Common::Input::DriverResult::Success) { |
| 253 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); | 254 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); |
| 254 | result = WriteMifareData(tag_uuid, write_request); | 255 | result = WriteMifareData(tag_uuid, write_request); |
| 255 | } | 256 | } |
| 256 | if (result == DriverResult::Success) { | 257 | if (result == Common::Input::DriverResult::Success) { |
| 257 | MCUCommandResponse output{}; | 258 | MCUCommandResponse output{}; |
| 258 | result = SendStopPollingRequest(output); | 259 | result = SendStopPollingRequest(output); |
| 259 | } | 260 | } |
| 260 | if (result == DriverResult::Success) { | 261 | if (result == Common::Input::DriverResult::Success) { |
| 261 | result = WaitUntilNfcIs(NFCStatus::Ready); | 262 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 262 | } | 263 | } |
| 263 | if (result == DriverResult::Success) { | 264 | if (result == Common::Input::DriverResult::Success) { |
| 264 | MCUCommandResponse output{}; | 265 | MCUCommandResponse output{}; |
| 265 | result = SendStartPollingRequest(output, true); | 266 | result = SendStartPollingRequest(output, true); |
| 266 | } | 267 | } |
| 267 | if (result == DriverResult::Success) { | 268 | if (result == Common::Input::DriverResult::Success) { |
| 268 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | 269 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 269 | } | 270 | } |
| 270 | return result; | 271 | return result; |
| @@ -277,17 +278,17 @@ bool NfcProtocol::HasAmiibo() { | |||
| 277 | update_counter = 0; | 278 | update_counter = 0; |
| 278 | 279 | ||
| 279 | ScopedSetBlocking sb(this); | 280 | ScopedSetBlocking sb(this); |
| 280 | DriverResult result{DriverResult::Success}; | 281 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 281 | TagFoundData tag_data{}; | 282 | TagFoundData tag_data{}; |
| 282 | 283 | ||
| 283 | if (result == DriverResult::Success) { | 284 | if (result == Common::Input::DriverResult::Success) { |
| 284 | result = IsTagInRange(tag_data, 7); | 285 | result = IsTagInRange(tag_data, 7); |
| 285 | } | 286 | } |
| 286 | 287 | ||
| 287 | return result == DriverResult::Success; | 288 | return result == Common::Input::DriverResult::Success; |
| 288 | } | 289 | } |
| 289 | 290 | ||
| 290 | DriverResult NfcProtocol::WaitUntilNfcIs(NFCStatus status) { | 291 | Common::Input::DriverResult NfcProtocol::WaitUntilNfcIs(NFCStatus status) { |
| 291 | constexpr std::size_t timeout_limit = 10; | 292 | constexpr std::size_t timeout_limit = 10; |
| 292 | MCUCommandResponse output{}; | 293 | MCUCommandResponse output{}; |
| 293 | std::size_t tries = 0; | 294 | std::size_t tries = 0; |
| @@ -295,30 +296,31 @@ DriverResult NfcProtocol::WaitUntilNfcIs(NFCStatus status) { | |||
| 295 | do { | 296 | do { |
| 296 | auto result = SendNextPackageRequest(output, {}); | 297 | auto result = SendNextPackageRequest(output, {}); |
| 297 | 298 | ||
| 298 | if (result != DriverResult::Success) { | 299 | if (result != Common::Input::DriverResult::Success) { |
| 299 | return result; | 300 | return result; |
| 300 | } | 301 | } |
| 301 | if (tries++ > timeout_limit) { | 302 | if (tries++ > timeout_limit) { |
| 302 | return DriverResult::Timeout; | 303 | return Common::Input::DriverResult::Timeout; |
| 303 | } | 304 | } |
| 304 | } while (output.mcu_report != MCUReport::NFCState || | 305 | } while (output.mcu_report != MCUReport::NFCState || |
| 305 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || | 306 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || |
| 306 | output.mcu_data[5] != 0x31 || output.mcu_data[6] != static_cast<u8>(status)); | 307 | output.mcu_data[5] != 0x31 || output.mcu_data[6] != static_cast<u8>(status)); |
| 307 | 308 | ||
| 308 | return DriverResult::Success; | 309 | return Common::Input::DriverResult::Success; |
| 309 | } | 310 | } |
| 310 | 311 | ||
| 311 | DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, std::size_t timeout_limit) { | 312 | Common::Input::DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, |
| 313 | std::size_t timeout_limit) { | ||
| 312 | MCUCommandResponse output{}; | 314 | MCUCommandResponse output{}; |
| 313 | std::size_t tries = 0; | 315 | std::size_t tries = 0; |
| 314 | 316 | ||
| 315 | do { | 317 | do { |
| 316 | const auto result = SendNextPackageRequest(output, {}); | 318 | const auto result = SendNextPackageRequest(output, {}); |
| 317 | if (result != DriverResult::Success) { | 319 | if (result != Common::Input::DriverResult::Success) { |
| 318 | return result; | 320 | return result; |
| 319 | } | 321 | } |
| 320 | if (tries++ > timeout_limit) { | 322 | if (tries++ > timeout_limit) { |
| 321 | return DriverResult::Timeout; | 323 | return Common::Input::DriverResult::Timeout; |
| 322 | } | 324 | } |
| 323 | } while (output.mcu_report != MCUReport::NFCState || | 325 | } while (output.mcu_report != MCUReport::NFCState || |
| 324 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || | 326 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || |
| @@ -328,10 +330,10 @@ DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, std::size_t timeout_l | |||
| 328 | data.uuid_size = std::min(output.mcu_data[14], static_cast<u8>(sizeof(TagUUID))); | 330 | data.uuid_size = std::min(output.mcu_data[14], static_cast<u8>(sizeof(TagUUID))); |
| 329 | memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); | 331 | memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); |
| 330 | 332 | ||
| 331 | return DriverResult::Success; | 333 | return Common::Input::DriverResult::Success; |
| 332 | } | 334 | } |
| 333 | 335 | ||
| 334 | DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | 336 | Common::Input::DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { |
| 335 | constexpr std::size_t timeout_limit = 60; | 337 | constexpr std::size_t timeout_limit = 60; |
| 336 | MCUCommandResponse output{}; | 338 | MCUCommandResponse output{}; |
| 337 | std::size_t tries = 0; | 339 | std::size_t tries = 0; |
| @@ -340,7 +342,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 340 | std::size_t ntag_buffer_pos = 0; | 342 | std::size_t ntag_buffer_pos = 0; |
| 341 | auto result = SendReadAmiiboRequest(output, NFCPages::Block135); | 343 | auto result = SendReadAmiiboRequest(output, NFCPages::Block135); |
| 342 | 344 | ||
| 343 | if (result != DriverResult::Success) { | 345 | if (result != Common::Input::DriverResult::Success) { |
| 344 | return result; | 346 | return result; |
| 345 | } | 347 | } |
| 346 | 348 | ||
| @@ -349,14 +351,14 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 349 | result = SendNextPackageRequest(output, package_index); | 351 | result = SendNextPackageRequest(output, package_index); |
| 350 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 352 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 351 | 353 | ||
| 352 | if (result != DriverResult::Success) { | 354 | if (result != Common::Input::DriverResult::Success) { |
| 353 | return result; | 355 | return result; |
| 354 | } | 356 | } |
| 355 | 357 | ||
| 356 | if ((output.mcu_report == MCUReport::NFCReadData || | 358 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 357 | output.mcu_report == MCUReport::NFCState) && | 359 | output.mcu_report == MCUReport::NFCState) && |
| 358 | nfc_status == NFCStatus::TagLost) { | 360 | nfc_status == NFCStatus::TagLost) { |
| 359 | return DriverResult::ErrorReadingData; | 361 | return Common::Input::DriverResult::ErrorReadingData; |
| 360 | } | 362 | } |
| 361 | 363 | ||
| 362 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { | 364 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { |
| @@ -375,14 +377,15 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 375 | 377 | ||
| 376 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { | 378 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { |
| 377 | LOG_INFO(Input, "Finished reading amiibo"); | 379 | LOG_INFO(Input, "Finished reading amiibo"); |
| 378 | return DriverResult::Success; | 380 | return Common::Input::DriverResult::Success; |
| 379 | } | 381 | } |
| 380 | } | 382 | } |
| 381 | 383 | ||
| 382 | return DriverResult::Timeout; | 384 | return Common::Input::DriverResult::Timeout; |
| 383 | } | 385 | } |
| 384 | 386 | ||
| 385 | DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<const u8> data) { | 387 | Common::Input::DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, |
| 388 | std::span<const u8> data) { | ||
| 386 | constexpr std::size_t timeout_limit = 60; | 389 | constexpr std::size_t timeout_limit = 60; |
| 387 | const auto nfc_data = MakeAmiiboWritePackage(tag_uuid, data); | 390 | const auto nfc_data = MakeAmiiboWritePackage(tag_uuid, data); |
| 388 | const std::vector<u8> nfc_buffer_data = SerializeWritePackage(nfc_data); | 391 | const std::vector<u8> nfc_buffer_data = SerializeWritePackage(nfc_data); |
| @@ -397,7 +400,7 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 397 | 400 | ||
| 398 | auto result = SendWriteAmiiboRequest(output, tag_uuid); | 401 | auto result = SendWriteAmiiboRequest(output, tag_uuid); |
| 399 | 402 | ||
| 400 | if (result != DriverResult::Success) { | 403 | if (result != Common::Input::DriverResult::Success) { |
| 401 | return result; | 404 | return result; |
| 402 | } | 405 | } |
| 403 | 406 | ||
| @@ -406,14 +409,14 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 406 | result = SendNextPackageRequest(output, package_index); | 409 | result = SendNextPackageRequest(output, package_index); |
| 407 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 410 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 408 | 411 | ||
| 409 | if (result != DriverResult::Success) { | 412 | if (result != Common::Input::DriverResult::Success) { |
| 410 | return result; | 413 | return result; |
| 411 | } | 414 | } |
| 412 | 415 | ||
| 413 | if ((output.mcu_report == MCUReport::NFCReadData || | 416 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 414 | output.mcu_report == MCUReport::NFCState) && | 417 | output.mcu_report == MCUReport::NFCState) && |
| 415 | nfc_status == NFCStatus::TagLost) { | 418 | nfc_status == NFCStatus::TagLost) { |
| 416 | return DriverResult::ErrorReadingData; | 419 | return Common::Input::DriverResult::ErrorReadingData; |
| 417 | } | 420 | } |
| 418 | 421 | ||
| 419 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { | 422 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { |
| @@ -442,7 +445,7 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 442 | if ((output.mcu_report == MCUReport::NFCReadData || | 445 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 443 | output.mcu_report == MCUReport::NFCState) && | 446 | output.mcu_report == MCUReport::NFCState) && |
| 444 | nfc_status == NFCStatus::TagLost) { | 447 | nfc_status == NFCStatus::TagLost) { |
| 445 | return DriverResult::ErrorReadingData; | 448 | return Common::Input::DriverResult::ErrorReadingData; |
| 446 | } | 449 | } |
| 447 | 450 | ||
| 448 | // Increase position when data is confirmed by the joycon | 451 | // Increase position when data is confirmed by the joycon |
| @@ -457,14 +460,14 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 457 | return result; | 460 | return result; |
| 458 | } | 461 | } |
| 459 | 462 | ||
| 460 | DriverResult NfcProtocol::GetMifareData(const MifareUUID& tag_uuid, | 463 | Common::Input::DriverResult NfcProtocol::GetMifareData( |
| 461 | std::span<const MifareReadChunk> read_request, | 464 | const MifareUUID& tag_uuid, std::span<const MifareReadChunk> read_request, |
| 462 | std::span<MifareReadData> out_data) { | 465 | std::span<MifareReadData> out_data) { |
| 463 | constexpr std::size_t timeout_limit = 60; | 466 | constexpr std::size_t timeout_limit = 60; |
| 464 | const auto nfc_data = MakeMifareReadPackage(tag_uuid, read_request); | 467 | const auto nfc_data = MakeMifareReadPackage(tag_uuid, read_request); |
| 465 | const std::vector<u8> nfc_buffer_data = SerializeMifareReadPackage(nfc_data); | 468 | const std::vector<u8> nfc_buffer_data = SerializeMifareReadPackage(nfc_data); |
| 466 | std::span<const u8> buffer(nfc_buffer_data); | 469 | std::span<const u8> buffer(nfc_buffer_data); |
| 467 | DriverResult result = DriverResult::Success; | 470 | Common::Input::DriverResult result = Common::Input::DriverResult::Success; |
| 468 | MCUCommandResponse output{}; | 471 | MCUCommandResponse output{}; |
| 469 | u8 block_id = 1; | 472 | u8 block_id = 1; |
| 470 | u8 package_index = 0; | 473 | u8 package_index = 0; |
| @@ -486,7 +489,7 @@ DriverResult NfcProtocol::GetMifareData(const MifareUUID& tag_uuid, | |||
| 486 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 489 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 487 | 490 | ||
| 488 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | 491 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { |
| 489 | return DriverResult::ErrorReadingData; | 492 | return Common::Input::DriverResult::ErrorReadingData; |
| 490 | } | 493 | } |
| 491 | 494 | ||
| 492 | // Increase position when data is confirmed by the joycon | 495 | // Increase position when data is confirmed by the joycon |
| @@ -498,7 +501,7 @@ DriverResult NfcProtocol::GetMifareData(const MifareUUID& tag_uuid, | |||
| 498 | } | 501 | } |
| 499 | } | 502 | } |
| 500 | 503 | ||
| 501 | if (result != DriverResult::Success) { | 504 | if (result != Common::Input::DriverResult::Success) { |
| 502 | return result; | 505 | return result; |
| 503 | } | 506 | } |
| 504 | 507 | ||
| @@ -507,12 +510,12 @@ DriverResult NfcProtocol::GetMifareData(const MifareUUID& tag_uuid, | |||
| 507 | result = SendNextPackageRequest(output, package_index); | 510 | result = SendNextPackageRequest(output, package_index); |
| 508 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 511 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 509 | 512 | ||
| 510 | if (result != DriverResult::Success) { | 513 | if (result != Common::Input::DriverResult::Success) { |
| 511 | return result; | 514 | return result; |
| 512 | } | 515 | } |
| 513 | 516 | ||
| 514 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | 517 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { |
| 515 | return DriverResult::ErrorReadingData; | 518 | return Common::Input::DriverResult::ErrorReadingData; |
| 516 | } | 519 | } |
| 517 | 520 | ||
| 518 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { | 521 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { |
| @@ -538,13 +541,13 @@ DriverResult NfcProtocol::GetMifareData(const MifareUUID& tag_uuid, | |||
| 538 | return result; | 541 | return result; |
| 539 | } | 542 | } |
| 540 | 543 | ||
| 541 | DriverResult NfcProtocol::WriteMifareData(const MifareUUID& tag_uuid, | 544 | Common::Input::DriverResult NfcProtocol::WriteMifareData( |
| 542 | std::span<const MifareWriteChunk> write_request) { | 545 | const MifareUUID& tag_uuid, std::span<const MifareWriteChunk> write_request) { |
| 543 | constexpr std::size_t timeout_limit = 60; | 546 | constexpr std::size_t timeout_limit = 60; |
| 544 | const auto nfc_data = MakeMifareWritePackage(tag_uuid, write_request); | 547 | const auto nfc_data = MakeMifareWritePackage(tag_uuid, write_request); |
| 545 | const std::vector<u8> nfc_buffer_data = SerializeMifareWritePackage(nfc_data); | 548 | const std::vector<u8> nfc_buffer_data = SerializeMifareWritePackage(nfc_data); |
| 546 | std::span<const u8> buffer(nfc_buffer_data); | 549 | std::span<const u8> buffer(nfc_buffer_data); |
| 547 | DriverResult result = DriverResult::Success; | 550 | Common::Input::DriverResult result = Common::Input::DriverResult::Success; |
| 548 | MCUCommandResponse output{}; | 551 | MCUCommandResponse output{}; |
| 549 | u8 block_id = 1; | 552 | u8 block_id = 1; |
| 550 | u8 package_index = 0; | 553 | u8 package_index = 0; |
| @@ -566,7 +569,7 @@ DriverResult NfcProtocol::WriteMifareData(const MifareUUID& tag_uuid, | |||
| 566 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 569 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 567 | 570 | ||
| 568 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | 571 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { |
| 569 | return DriverResult::ErrorReadingData; | 572 | return Common::Input::DriverResult::ErrorReadingData; |
| 570 | } | 573 | } |
| 571 | 574 | ||
| 572 | // Increase position when data is confirmed by the joycon | 575 | // Increase position when data is confirmed by the joycon |
| @@ -578,7 +581,7 @@ DriverResult NfcProtocol::WriteMifareData(const MifareUUID& tag_uuid, | |||
| 578 | } | 581 | } |
| 579 | } | 582 | } |
| 580 | 583 | ||
| 581 | if (result != DriverResult::Success) { | 584 | if (result != Common::Input::DriverResult::Success) { |
| 582 | return result; | 585 | return result; |
| 583 | } | 586 | } |
| 584 | 587 | ||
| @@ -587,12 +590,12 @@ DriverResult NfcProtocol::WriteMifareData(const MifareUUID& tag_uuid, | |||
| 587 | result = SendNextPackageRequest(output, package_index); | 590 | result = SendNextPackageRequest(output, package_index); |
| 588 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 591 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 589 | 592 | ||
| 590 | if (result != DriverResult::Success) { | 593 | if (result != Common::Input::DriverResult::Success) { |
| 591 | return result; | 594 | return result; |
| 592 | } | 595 | } |
| 593 | 596 | ||
| 594 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | 597 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { |
| 595 | return DriverResult::ErrorReadingData; | 598 | return Common::Input::DriverResult::ErrorReadingData; |
| 596 | } | 599 | } |
| 597 | 600 | ||
| 598 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { | 601 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { |
| @@ -609,8 +612,8 @@ DriverResult NfcProtocol::WriteMifareData(const MifareUUID& tag_uuid, | |||
| 609 | return result; | 612 | return result; |
| 610 | } | 613 | } |
| 611 | 614 | ||
| 612 | DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, | 615 | Common::Input::DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, |
| 613 | bool is_second_attempt) { | 616 | bool is_second_attempt) { |
| 614 | NFCRequestState request{ | 617 | NFCRequestState request{ |
| 615 | .command_argument = NFCCommand::StartPolling, | 618 | .command_argument = NFCCommand::StartPolling, |
| 616 | .block_id = {}, | 619 | .block_id = {}, |
| @@ -635,7 +638,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, | |||
| 635 | output); | 638 | output); |
| 636 | } | 639 | } |
| 637 | 640 | ||
| 638 | DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { | 641 | Common::Input::DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { |
| 639 | NFCRequestState request{ | 642 | NFCRequestState request{ |
| 640 | .command_argument = NFCCommand::StopPolling, | 643 | .command_argument = NFCCommand::StopPolling, |
| 641 | .block_id = {}, | 644 | .block_id = {}, |
| @@ -653,7 +656,8 @@ DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { | |||
| 653 | output); | 656 | output); |
| 654 | } | 657 | } |
| 655 | 658 | ||
| 656 | DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id) { | 659 | Common::Input::DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, |
| 660 | u8 packet_id) { | ||
| 657 | NFCRequestState request{ | 661 | NFCRequestState request{ |
| 658 | .command_argument = NFCCommand::StartWaitingRecieve, | 662 | .command_argument = NFCCommand::StartWaitingRecieve, |
| 659 | .block_id = {}, | 663 | .block_id = {}, |
| @@ -671,7 +675,8 @@ DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, u8 | |||
| 671 | output); | 675 | output); |
| 672 | } | 676 | } |
| 673 | 677 | ||
| 674 | DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages) { | 678 | Common::Input::DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, |
| 679 | NFCPages ntag_pages) { | ||
| 675 | NFCRequestState request{ | 680 | NFCRequestState request{ |
| 676 | .command_argument = NFCCommand::ReadNtag, | 681 | .command_argument = NFCCommand::ReadNtag, |
| 677 | .block_id = {}, | 682 | .block_id = {}, |
| @@ -696,8 +701,8 @@ DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCP | |||
| 696 | output); | 701 | output); |
| 697 | } | 702 | } |
| 698 | 703 | ||
| 699 | DriverResult NfcProtocol::SendWriteAmiiboRequest(MCUCommandResponse& output, | 704 | Common::Input::DriverResult NfcProtocol::SendWriteAmiiboRequest(MCUCommandResponse& output, |
| 700 | const TagUUID& tag_uuid) { | 705 | const TagUUID& tag_uuid) { |
| 701 | NFCRequestState request{ | 706 | NFCRequestState request{ |
| 702 | .command_argument = NFCCommand::ReadNtag, | 707 | .command_argument = NFCCommand::ReadNtag, |
| 703 | .block_id = {}, | 708 | .block_id = {}, |
| @@ -722,9 +727,10 @@ DriverResult NfcProtocol::SendWriteAmiiboRequest(MCUCommandResponse& output, | |||
| 722 | output); | 727 | output); |
| 723 | } | 728 | } |
| 724 | 729 | ||
| 725 | DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, u8 block_id, | 730 | Common::Input::DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, |
| 726 | bool is_last_packet, | 731 | u8 block_id, |
| 727 | std::span<const u8> data) { | 732 | bool is_last_packet, |
| 733 | std::span<const u8> data) { | ||
| 728 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); | 734 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); |
| 729 | NFCRequestState request{ | 735 | NFCRequestState request{ |
| 730 | .command_argument = NFCCommand::WriteNtag, | 736 | .command_argument = NFCCommand::WriteNtag, |
| @@ -745,8 +751,9 @@ DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, | |||
| 745 | output); | 751 | output); |
| 746 | } | 752 | } |
| 747 | 753 | ||
| 748 | DriverResult NfcProtocol::SendReadDataMifareRequest(MCUCommandResponse& output, u8 block_id, | 754 | Common::Input::DriverResult NfcProtocol::SendReadDataMifareRequest(MCUCommandResponse& output, |
| 749 | bool is_last_packet, std::span<const u8> data) { | 755 | u8 block_id, bool is_last_packet, |
| 756 | std::span<const u8> data) { | ||
| 750 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); | 757 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); |
| 751 | NFCRequestState request{ | 758 | NFCRequestState request{ |
| 752 | .command_argument = NFCCommand::Mifare, | 759 | .command_argument = NFCCommand::Mifare, |
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h index 0be95e40e..22db95170 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.h +++ b/src/input_common/helpers/joycon_protocol/nfc.h | |||
| @@ -13,30 +13,34 @@ | |||
| 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 15 | 15 | ||
| 16 | namespace Common::Input { | ||
| 17 | enum class DriverResult; | ||
| 18 | } | ||
| 19 | |||
| 16 | namespace InputCommon::Joycon { | 20 | namespace InputCommon::Joycon { |
| 17 | 21 | ||
| 18 | class NfcProtocol final : private JoyconCommonProtocol { | 22 | class NfcProtocol final : private JoyconCommonProtocol { |
| 19 | public: | 23 | public: |
| 20 | explicit NfcProtocol(std::shared_ptr<JoyconHandle> handle); | 24 | explicit NfcProtocol(std::shared_ptr<JoyconHandle> handle); |
| 21 | 25 | ||
| 22 | DriverResult EnableNfc(); | 26 | Common::Input::DriverResult EnableNfc(); |
| 23 | 27 | ||
| 24 | DriverResult DisableNfc(); | 28 | Common::Input::DriverResult DisableNfc(); |
| 25 | 29 | ||
| 26 | DriverResult StartNFCPollingMode(); | 30 | Common::Input::DriverResult StartNFCPollingMode(); |
| 27 | 31 | ||
| 28 | DriverResult StopNFCPollingMode(); | 32 | Common::Input::DriverResult StopNFCPollingMode(); |
| 29 | 33 | ||
| 30 | DriverResult GetTagInfo(Joycon::TagInfo& tag_info); | 34 | Common::Input::DriverResult GetTagInfo(Joycon::TagInfo& tag_info); |
| 31 | 35 | ||
| 32 | DriverResult ReadAmiibo(std::vector<u8>& data); | 36 | Common::Input::DriverResult ReadAmiibo(std::vector<u8>& data); |
| 33 | 37 | ||
| 34 | DriverResult WriteAmiibo(std::span<const u8> data); | 38 | Common::Input::DriverResult WriteAmiibo(std::span<const u8> data); |
| 35 | 39 | ||
| 36 | DriverResult ReadMifare(std::span<const MifareReadChunk> read_request, | 40 | Common::Input::DriverResult ReadMifare(std::span<const MifareReadChunk> read_request, |
| 37 | std::span<MifareReadData> out_data); | 41 | std::span<MifareReadData> out_data); |
| 38 | 42 | ||
| 39 | DriverResult WriteMifare(std::span<const MifareWriteChunk> write_request); | 43 | Common::Input::DriverResult WriteMifare(std::span<const MifareWriteChunk> write_request); |
| 40 | 44 | ||
| 41 | bool HasAmiibo(); | 45 | bool HasAmiibo(); |
| 42 | 46 | ||
| @@ -54,37 +58,41 @@ private: | |||
| 54 | TagUUID uuid; | 58 | TagUUID uuid; |
| 55 | }; | 59 | }; |
| 56 | 60 | ||
| 57 | DriverResult WaitUntilNfcIs(NFCStatus status); | 61 | Common::Input::DriverResult WaitUntilNfcIs(NFCStatus status); |
| 58 | 62 | ||
| 59 | DriverResult IsTagInRange(TagFoundData& data, std::size_t timeout_limit = 1); | 63 | Common::Input::DriverResult IsTagInRange(TagFoundData& data, std::size_t timeout_limit = 1); |
| 60 | 64 | ||
| 61 | DriverResult GetAmiiboData(std::vector<u8>& data); | 65 | Common::Input::DriverResult GetAmiiboData(std::vector<u8>& data); |
| 62 | 66 | ||
| 63 | DriverResult WriteAmiiboData(const TagUUID& tag_uuid, std::span<const u8> data); | 67 | Common::Input::DriverResult WriteAmiiboData(const TagUUID& tag_uuid, std::span<const u8> data); |
| 64 | 68 | ||
| 65 | DriverResult GetMifareData(const MifareUUID& tag_uuid, | 69 | Common::Input::DriverResult GetMifareData(const MifareUUID& tag_uuid, |
| 66 | std::span<const MifareReadChunk> read_request, | 70 | std::span<const MifareReadChunk> read_request, |
| 67 | std::span<MifareReadData> out_data); | 71 | std::span<MifareReadData> out_data); |
| 68 | 72 | ||
| 69 | DriverResult WriteMifareData(const MifareUUID& tag_uuid, | 73 | Common::Input::DriverResult WriteMifareData(const MifareUUID& tag_uuid, |
| 70 | std::span<const MifareWriteChunk> write_request); | 74 | std::span<const MifareWriteChunk> write_request); |
| 71 | 75 | ||
| 72 | DriverResult SendStartPollingRequest(MCUCommandResponse& output, | 76 | Common::Input::DriverResult SendStartPollingRequest(MCUCommandResponse& output, |
| 73 | bool is_second_attempt = false); | 77 | bool is_second_attempt = false); |
| 74 | 78 | ||
| 75 | DriverResult SendStopPollingRequest(MCUCommandResponse& output); | 79 | Common::Input::DriverResult SendStopPollingRequest(MCUCommandResponse& output); |
| 76 | 80 | ||
| 77 | DriverResult SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id); | 81 | Common::Input::DriverResult SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id); |
| 78 | 82 | ||
| 79 | DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages); | 83 | Common::Input::DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, |
| 84 | NFCPages ntag_pages); | ||
| 80 | 85 | ||
| 81 | DriverResult SendWriteAmiiboRequest(MCUCommandResponse& output, const TagUUID& tag_uuid); | 86 | Common::Input::DriverResult SendWriteAmiiboRequest(MCUCommandResponse& output, |
| 87 | const TagUUID& tag_uuid); | ||
| 82 | 88 | ||
| 83 | DriverResult SendWriteDataAmiiboRequest(MCUCommandResponse& output, u8 block_id, | 89 | Common::Input::DriverResult SendWriteDataAmiiboRequest(MCUCommandResponse& output, u8 block_id, |
| 84 | bool is_last_packet, std::span<const u8> data); | 90 | bool is_last_packet, |
| 91 | std::span<const u8> data); | ||
| 85 | 92 | ||
| 86 | DriverResult SendReadDataMifareRequest(MCUCommandResponse& output, u8 block_id, | 93 | Common::Input::DriverResult SendReadDataMifareRequest(MCUCommandResponse& output, u8 block_id, |
| 87 | bool is_last_packet, std::span<const u8> data); | 94 | bool is_last_packet, |
| 95 | std::span<const u8> data); | ||
| 88 | 96 | ||
| 89 | std::vector<u8> SerializeWritePackage(const NFCWritePackage& package) const; | 97 | std::vector<u8> SerializeWritePackage(const NFCWritePackage& package) const; |
| 90 | 98 | ||
diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp index 190cef812..96414fb67 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.cpp +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/input.h" | ||
| 4 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 5 | #include "input_common/helpers/joycon_protocol/ringcon.h" | 6 | #include "input_common/helpers/joycon_protocol/ringcon.h" |
| 6 | 7 | ||
| @@ -9,18 +10,18 @@ namespace InputCommon::Joycon { | |||
| 9 | RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle) | 10 | RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle) |
| 10 | : JoyconCommonProtocol(std::move(handle)) {} | 11 | : JoyconCommonProtocol(std::move(handle)) {} |
| 11 | 12 | ||
| 12 | DriverResult RingConProtocol::EnableRingCon() { | 13 | Common::Input::DriverResult RingConProtocol::EnableRingCon() { |
| 13 | LOG_DEBUG(Input, "Enable Ringcon"); | 14 | LOG_DEBUG(Input, "Enable Ringcon"); |
| 14 | ScopedSetBlocking sb(this); | 15 | ScopedSetBlocking sb(this); |
| 15 | DriverResult result{DriverResult::Success}; | 16 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 16 | 17 | ||
| 17 | if (result == DriverResult::Success) { | 18 | if (result == Common::Input::DriverResult::Success) { |
| 18 | result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); | 19 | result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); |
| 19 | } | 20 | } |
| 20 | if (result == DriverResult::Success) { | 21 | if (result == Common::Input::DriverResult::Success) { |
| 21 | result = EnableMCU(true); | 22 | result = EnableMCU(true); |
| 22 | } | 23 | } |
| 23 | if (result == DriverResult::Success) { | 24 | if (result == Common::Input::DriverResult::Success) { |
| 24 | const MCUConfig config{ | 25 | const MCUConfig config{ |
| 25 | .command = MCUCommand::ConfigureMCU, | 26 | .command = MCUCommand::ConfigureMCU, |
| 26 | .sub_command = MCUSubCommand::SetDeviceMode, | 27 | .sub_command = MCUSubCommand::SetDeviceMode, |
| @@ -33,12 +34,12 @@ DriverResult RingConProtocol::EnableRingCon() { | |||
| 33 | return result; | 34 | return result; |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | DriverResult RingConProtocol::DisableRingCon() { | 37 | Common::Input::DriverResult RingConProtocol::DisableRingCon() { |
| 37 | LOG_DEBUG(Input, "Disable RingCon"); | 38 | LOG_DEBUG(Input, "Disable RingCon"); |
| 38 | ScopedSetBlocking sb(this); | 39 | ScopedSetBlocking sb(this); |
| 39 | DriverResult result{DriverResult::Success}; | 40 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 40 | 41 | ||
| 41 | if (result == DriverResult::Success) { | 42 | if (result == Common::Input::DriverResult::Success) { |
| 42 | result = EnableMCU(false); | 43 | result = EnableMCU(false); |
| 43 | } | 44 | } |
| 44 | 45 | ||
| @@ -47,29 +48,29 @@ DriverResult RingConProtocol::DisableRingCon() { | |||
| 47 | return result; | 48 | return result; |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | DriverResult RingConProtocol::StartRingconPolling() { | 51 | Common::Input::DriverResult RingConProtocol::StartRingconPolling() { |
| 51 | LOG_DEBUG(Input, "Enable Ringcon"); | 52 | LOG_DEBUG(Input, "Enable Ringcon"); |
| 52 | ScopedSetBlocking sb(this); | 53 | ScopedSetBlocking sb(this); |
| 53 | DriverResult result{DriverResult::Success}; | 54 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 54 | bool is_connected = false; | 55 | bool is_connected = false; |
| 55 | 56 | ||
| 56 | if (result == DriverResult::Success) { | 57 | if (result == Common::Input::DriverResult::Success) { |
| 57 | result = IsRingConnected(is_connected); | 58 | result = IsRingConnected(is_connected); |
| 58 | } | 59 | } |
| 59 | if (result == DriverResult::Success && is_connected) { | 60 | if (result == Common::Input::DriverResult::Success && is_connected) { |
| 60 | LOG_INFO(Input, "Ringcon detected"); | 61 | LOG_INFO(Input, "Ringcon detected"); |
| 61 | result = ConfigureRing(); | 62 | result = ConfigureRing(); |
| 62 | } | 63 | } |
| 63 | if (result == DriverResult::Success) { | 64 | if (result == Common::Input::DriverResult::Success) { |
| 64 | is_enabled = true; | 65 | is_enabled = true; |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | return result; | 68 | return result; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { | 71 | Common::Input::DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { |
| 71 | LOG_DEBUG(Input, "IsRingConnected"); | 72 | LOG_DEBUG(Input, "IsRingConnected"); |
| 72 | constexpr std::size_t max_tries = 28; | 73 | constexpr std::size_t max_tries = 42; |
| 73 | SubCommandResponse output{}; | 74 | SubCommandResponse output{}; |
| 74 | std::size_t tries = 0; | 75 | std::size_t tries = 0; |
| 75 | is_connected = false; | 76 | is_connected = false; |
| @@ -77,20 +78,21 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { | |||
| 77 | do { | 78 | do { |
| 78 | const auto result = SendSubCommand(SubCommand::GET_EXTERNAL_DEVICE_INFO, {}, output); | 79 | const auto result = SendSubCommand(SubCommand::GET_EXTERNAL_DEVICE_INFO, {}, output); |
| 79 | 80 | ||
| 80 | if (result != DriverResult::Success) { | 81 | if (result != Common::Input::DriverResult::Success && |
| 82 | result != Common::Input::DriverResult::Timeout) { | ||
| 81 | return result; | 83 | return result; |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | if (tries++ >= max_tries) { | 86 | if (tries++ >= max_tries) { |
| 85 | return DriverResult::NoDeviceDetected; | 87 | return Common::Input::DriverResult::NoDeviceDetected; |
| 86 | } | 88 | } |
| 87 | } while (output.external_device_id != ExternalDeviceId::RingController); | 89 | } while (output.external_device_id != ExternalDeviceId::RingController); |
| 88 | 90 | ||
| 89 | is_connected = true; | 91 | is_connected = true; |
| 90 | return DriverResult::Success; | 92 | return Common::Input::DriverResult::Success; |
| 91 | } | 93 | } |
| 92 | 94 | ||
| 93 | DriverResult RingConProtocol::ConfigureRing() { | 95 | Common::Input::DriverResult RingConProtocol::ConfigureRing() { |
| 94 | LOG_DEBUG(Input, "ConfigureRing"); | 96 | LOG_DEBUG(Input, "ConfigureRing"); |
| 95 | 97 | ||
| 96 | static constexpr std::array<u8, 37> ring_config{ | 98 | static constexpr std::array<u8, 37> ring_config{ |
| @@ -98,9 +100,10 @@ DriverResult RingConProtocol::ConfigureRing() { | |||
| 98 | 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, | 100 | 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, |
| 99 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; | 101 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; |
| 100 | 102 | ||
| 101 | const DriverResult result = SendSubCommand(SubCommand::SET_EXTERNAL_FORMAT_CONFIG, ring_config); | 103 | const Common::Input::DriverResult result = |
| 104 | SendSubCommand(SubCommand::SET_EXTERNAL_FORMAT_CONFIG, ring_config); | ||
| 102 | 105 | ||
| 103 | if (result != DriverResult::Success) { | 106 | if (result != Common::Input::DriverResult::Success) { |
| 104 | return result; | 107 | return result; |
| 105 | } | 108 | } |
| 106 | 109 | ||
diff --git a/src/input_common/helpers/joycon_protocol/ringcon.h b/src/input_common/helpers/joycon_protocol/ringcon.h index 6e858f3fc..9f0888de3 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.h +++ b/src/input_common/helpers/joycon_protocol/ringcon.h | |||
| @@ -13,24 +13,28 @@ | |||
| 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 15 | 15 | ||
| 16 | namespace Common::Input { | ||
| 17 | enum class DriverResult; | ||
| 18 | } | ||
| 19 | |||
| 16 | namespace InputCommon::Joycon { | 20 | namespace InputCommon::Joycon { |
| 17 | 21 | ||
| 18 | class RingConProtocol final : private JoyconCommonProtocol { | 22 | class RingConProtocol final : private JoyconCommonProtocol { |
| 19 | public: | 23 | public: |
| 20 | explicit RingConProtocol(std::shared_ptr<JoyconHandle> handle); | 24 | explicit RingConProtocol(std::shared_ptr<JoyconHandle> handle); |
| 21 | 25 | ||
| 22 | DriverResult EnableRingCon(); | 26 | Common::Input::DriverResult EnableRingCon(); |
| 23 | 27 | ||
| 24 | DriverResult DisableRingCon(); | 28 | Common::Input::DriverResult DisableRingCon(); |
| 25 | 29 | ||
| 26 | DriverResult StartRingconPolling(); | 30 | Common::Input::DriverResult StartRingconPolling(); |
| 27 | 31 | ||
| 28 | bool IsEnabled() const; | 32 | bool IsEnabled() const; |
| 29 | 33 | ||
| 30 | private: | 34 | private: |
| 31 | DriverResult IsRingConnected(bool& is_connected); | 35 | Common::Input::DriverResult IsRingConnected(bool& is_connected); |
| 32 | 36 | ||
| 33 | DriverResult ConfigureRing(); | 37 | Common::Input::DriverResult ConfigureRing(); |
| 34 | 38 | ||
| 35 | bool is_enabled{}; | 39 | bool is_enabled{}; |
| 36 | }; | 40 | }; |
diff --git a/src/input_common/helpers/joycon_protocol/rumble.cpp b/src/input_common/helpers/joycon_protocol/rumble.cpp index 63b60c946..7647f505e 100644 --- a/src/input_common/helpers/joycon_protocol/rumble.cpp +++ b/src/input_common/helpers/joycon_protocol/rumble.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <cmath> | 5 | #include <cmath> |
| 6 | 6 | ||
| 7 | #include "common/input.h" | ||
| 7 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 8 | #include "input_common/helpers/joycon_protocol/rumble.h" | 9 | #include "input_common/helpers/joycon_protocol/rumble.h" |
| 9 | 10 | ||
| @@ -12,14 +13,14 @@ namespace InputCommon::Joycon { | |||
| 12 | RumbleProtocol::RumbleProtocol(std::shared_ptr<JoyconHandle> handle) | 13 | RumbleProtocol::RumbleProtocol(std::shared_ptr<JoyconHandle> handle) |
| 13 | : JoyconCommonProtocol(std::move(handle)) {} | 14 | : JoyconCommonProtocol(std::move(handle)) {} |
| 14 | 15 | ||
| 15 | DriverResult RumbleProtocol::EnableRumble(bool is_enabled) { | 16 | Common::Input::DriverResult RumbleProtocol::EnableRumble(bool is_enabled) { |
| 16 | LOG_DEBUG(Input, "Enable Rumble"); | 17 | LOG_DEBUG(Input, "Enable Rumble"); |
| 17 | ScopedSetBlocking sb(this); | 18 | ScopedSetBlocking sb(this); |
| 18 | const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)}; | 19 | const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)}; |
| 19 | return SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer); | 20 | return SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer); |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) { | 23 | Common::Input::DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) { |
| 23 | std::array<u8, sizeof(DefaultVibrationBuffer)> buffer{}; | 24 | std::array<u8, sizeof(DefaultVibrationBuffer)> buffer{}; |
| 24 | 25 | ||
| 25 | if (vibration.high_amplitude <= 0.0f && vibration.low_amplitude <= 0.0f) { | 26 | if (vibration.high_amplitude <= 0.0f && vibration.low_amplitude <= 0.0f) { |
diff --git a/src/input_common/helpers/joycon_protocol/rumble.h b/src/input_common/helpers/joycon_protocol/rumble.h index 6c12b7925..5e50e531a 100644 --- a/src/input_common/helpers/joycon_protocol/rumble.h +++ b/src/input_common/helpers/joycon_protocol/rumble.h | |||
| @@ -13,15 +13,19 @@ | |||
| 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" | 13 | #include "input_common/helpers/joycon_protocol/common_protocol.h" |
| 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" | 14 | #include "input_common/helpers/joycon_protocol/joycon_types.h" |
| 15 | 15 | ||
| 16 | namespace Common::Input { | ||
| 17 | enum class DriverResult; | ||
| 18 | } | ||
| 19 | |||
| 16 | namespace InputCommon::Joycon { | 20 | namespace InputCommon::Joycon { |
| 17 | 21 | ||
| 18 | class RumbleProtocol final : private JoyconCommonProtocol { | 22 | class RumbleProtocol final : private JoyconCommonProtocol { |
| 19 | public: | 23 | public: |
| 20 | explicit RumbleProtocol(std::shared_ptr<JoyconHandle> handle); | 24 | explicit RumbleProtocol(std::shared_ptr<JoyconHandle> handle); |
| 21 | 25 | ||
| 22 | DriverResult EnableRumble(bool is_enabled); | 26 | Common::Input::DriverResult EnableRumble(bool is_enabled); |
| 23 | 27 | ||
| 24 | DriverResult SendVibration(const VibrationValue& vibration); | 28 | Common::Input::DriverResult SendVibration(const VibrationValue& vibration); |
| 25 | 29 | ||
| 26 | private: | 30 | private: |
| 27 | u16 EncodeHighFrequency(f32 frequency) const; | 31 | u16 EncodeHighFrequency(f32 frequency) const; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 58a45ab67..b5ed3380f 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -115,7 +115,34 @@ void BufferCache<P>::WriteMemory(VAddr cpu_addr, u64 size) { | |||
| 115 | 115 | ||
| 116 | template <class P> | 116 | template <class P> |
| 117 | void BufferCache<P>::CachedWriteMemory(VAddr cpu_addr, u64 size) { | 117 | void BufferCache<P>::CachedWriteMemory(VAddr cpu_addr, u64 size) { |
| 118 | memory_tracker.CachedCpuWrite(cpu_addr, size); | 118 | const bool is_dirty = IsRegionRegistered(cpu_addr, size); |
| 119 | if (!is_dirty) { | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | VAddr aligned_start = Common::AlignDown(cpu_addr, YUZU_PAGESIZE); | ||
| 123 | VAddr aligned_end = Common::AlignUp(cpu_addr + size, YUZU_PAGESIZE); | ||
| 124 | if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { | ||
| 125 | WriteMemory(cpu_addr, size); | ||
| 126 | return; | ||
| 127 | } | ||
| 128 | |||
| 129 | tmp_buffer.resize_destructive(size); | ||
| 130 | cpu_memory.ReadBlockUnsafe(cpu_addr, tmp_buffer.data(), size); | ||
| 131 | |||
| 132 | InlineMemoryImplementation(cpu_addr, size, tmp_buffer); | ||
| 133 | } | ||
| 134 | |||
| 135 | template <class P> | ||
| 136 | bool BufferCache<P>::OnCPUWrite(VAddr cpu_addr, u64 size) { | ||
| 137 | const bool is_dirty = IsRegionRegistered(cpu_addr, size); | ||
| 138 | if (!is_dirty) { | ||
| 139 | return false; | ||
| 140 | } | ||
| 141 | if (memory_tracker.IsRegionGpuModified(cpu_addr, size)) { | ||
| 142 | return true; | ||
| 143 | } | ||
| 144 | WriteMemory(cpu_addr, size); | ||
| 145 | return false; | ||
| 119 | } | 146 | } |
| 120 | 147 | ||
| 121 | template <class P> | 148 | template <class P> |
| @@ -1553,6 +1580,14 @@ bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size, | |||
| 1553 | return false; | 1580 | return false; |
| 1554 | } | 1581 | } |
| 1555 | 1582 | ||
| 1583 | InlineMemoryImplementation(dest_address, copy_size, inlined_buffer); | ||
| 1584 | |||
| 1585 | return true; | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | template <class P> | ||
| 1589 | void BufferCache<P>::InlineMemoryImplementation(VAddr dest_address, size_t copy_size, | ||
| 1590 | std::span<const u8> inlined_buffer) { | ||
| 1556 | const IntervalType subtract_interval{dest_address, dest_address + copy_size}; | 1591 | const IntervalType subtract_interval{dest_address, dest_address + copy_size}; |
| 1557 | ClearDownload(subtract_interval); | 1592 | ClearDownload(subtract_interval); |
| 1558 | common_ranges.subtract(subtract_interval); | 1593 | common_ranges.subtract(subtract_interval); |
| @@ -1574,8 +1609,6 @@ bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size, | |||
| 1574 | } else { | 1609 | } else { |
| 1575 | buffer.ImmediateUpload(buffer.Offset(dest_address), inlined_buffer.first(copy_size)); | 1610 | buffer.ImmediateUpload(buffer.Offset(dest_address), inlined_buffer.first(copy_size)); |
| 1576 | } | 1611 | } |
| 1577 | |||
| 1578 | return true; | ||
| 1579 | } | 1612 | } |
| 1580 | 1613 | ||
| 1581 | template <class P> | 1614 | template <class P> |
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index fe6068cfe..460fc7551 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h | |||
| @@ -245,6 +245,8 @@ public: | |||
| 245 | 245 | ||
| 246 | void CachedWriteMemory(VAddr cpu_addr, u64 size); | 246 | void CachedWriteMemory(VAddr cpu_addr, u64 size); |
| 247 | 247 | ||
| 248 | bool OnCPUWrite(VAddr cpu_addr, u64 size); | ||
| 249 | |||
| 248 | void DownloadMemory(VAddr cpu_addr, u64 size); | 250 | void DownloadMemory(VAddr cpu_addr, u64 size); |
| 249 | 251 | ||
| 250 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); | 252 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); |
| @@ -543,6 +545,9 @@ private: | |||
| 543 | 545 | ||
| 544 | void ClearDownload(IntervalType subtract_interval); | 546 | void ClearDownload(IntervalType subtract_interval); |
| 545 | 547 | ||
| 548 | void InlineMemoryImplementation(VAddr dest_address, size_t copy_size, | ||
| 549 | std::span<const u8> inlined_buffer); | ||
| 550 | |||
| 546 | VideoCore::RasterizerInterface& rasterizer; | 551 | VideoCore::RasterizerInterface& rasterizer; |
| 547 | Core::Memory::Memory& cpu_memory; | 552 | Core::Memory::Memory& cpu_memory; |
| 548 | 553 | ||
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index a290d6ea7..f8598fd98 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -174,8 +174,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 174 | src_operand.address = regs.offset_in; | 174 | src_operand.address = regs.offset_in; |
| 175 | 175 | ||
| 176 | DMA::BufferOperand dst_operand; | 176 | DMA::BufferOperand dst_operand; |
| 177 | u32 abs_pitch_out = std::abs(static_cast<s32>(regs.pitch_out)); | 177 | dst_operand.pitch = static_cast<u32>(std::abs(regs.pitch_out)); |
| 178 | dst_operand.pitch = abs_pitch_out; | ||
| 179 | dst_operand.width = regs.line_length_in; | 178 | dst_operand.width = regs.line_length_in; |
| 180 | dst_operand.height = regs.line_count; | 179 | dst_operand.height = regs.line_count; |
| 181 | dst_operand.address = regs.offset_out; | 180 | dst_operand.address = regs.offset_out; |
| @@ -222,7 +221,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 222 | const size_t src_size = | 221 | const size_t src_size = |
| 223 | CalculateSize(true, bytes_per_pixel, width, height, depth, block_height, block_depth); | 222 | CalculateSize(true, bytes_per_pixel, width, height, depth, block_height, block_depth); |
| 224 | 223 | ||
| 225 | const size_t dst_size = static_cast<size_t>(abs_pitch_out) * regs.line_count; | 224 | const size_t dst_size = dst_operand.pitch * regs.line_count; |
| 226 | read_buffer.resize_destructive(src_size); | 225 | read_buffer.resize_destructive(src_size); |
| 227 | write_buffer.resize_destructive(dst_size); | 226 | write_buffer.resize_destructive(dst_size); |
| 228 | 227 | ||
| @@ -231,7 +230,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 231 | 230 | ||
| 232 | UnswizzleSubrect(write_buffer, read_buffer, bytes_per_pixel, width, height, depth, x_offset, | 231 | UnswizzleSubrect(write_buffer, read_buffer, bytes_per_pixel, width, height, depth, x_offset, |
| 233 | src_params.origin.y, x_elements, regs.line_count, block_height, block_depth, | 232 | src_params.origin.y, x_elements, regs.line_count, block_height, block_depth, |
| 234 | abs_pitch_out); | 233 | dst_operand.pitch); |
| 235 | 234 | ||
| 236 | memory_manager.WriteBlockCached(regs.offset_out, write_buffer.data(), dst_size); | 235 | memory_manager.WriteBlockCached(regs.offset_out, write_buffer.data(), dst_size); |
| 237 | } | 236 | } |
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 35d699bbf..ab20ff30f 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h | |||
| @@ -69,7 +69,6 @@ public: | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void SignalFence(std::function<void()>&& func) { | 71 | void SignalFence(std::function<void()>&& func) { |
| 72 | rasterizer.InvalidateGPUCache(); | ||
| 73 | bool delay_fence = Settings::IsGPULevelHigh(); | 72 | bool delay_fence = Settings::IsGPULevelHigh(); |
| 74 | if constexpr (!can_async_check) { | 73 | if constexpr (!can_async_check) { |
| 75 | TryReleasePendingFences<false>(); | 74 | TryReleasePendingFences<false>(); |
| @@ -96,6 +95,7 @@ public: | |||
| 96 | guard.unlock(); | 95 | guard.unlock(); |
| 97 | cv.notify_all(); | 96 | cv.notify_all(); |
| 98 | } | 97 | } |
| 98 | rasterizer.InvalidateGPUCache(); | ||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void SignalSyncPoint(u32 value) { | 101 | void SignalSyncPoint(u32 value) { |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index db385076d..c192e33b2 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -95,7 +95,9 @@ struct GPU::Impl { | |||
| 95 | 95 | ||
| 96 | /// Synchronizes CPU writes with Host GPU memory. | 96 | /// Synchronizes CPU writes with Host GPU memory. |
| 97 | void InvalidateGPUCache() { | 97 | void InvalidateGPUCache() { |
| 98 | rasterizer->InvalidateGPUCache(); | 98 | std::function<void(VAddr, size_t)> callback_writes( |
| 99 | [this](VAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); }); | ||
| 100 | system.GatherGPUDirtyMemory(callback_writes); | ||
| 99 | } | 101 | } |
| 100 | 102 | ||
| 101 | /// Signal the ending of command list. | 103 | /// Signal the ending of command list. |
| @@ -299,6 +301,10 @@ struct GPU::Impl { | |||
| 299 | gpu_thread.InvalidateRegion(addr, size); | 301 | gpu_thread.InvalidateRegion(addr, size); |
| 300 | } | 302 | } |
| 301 | 303 | ||
| 304 | bool OnCPUWrite(VAddr addr, u64 size) { | ||
| 305 | return rasterizer->OnCPUWrite(addr, size); | ||
| 306 | } | ||
| 307 | |||
| 302 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 308 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 303 | void FlushAndInvalidateRegion(VAddr addr, u64 size) { | 309 | void FlushAndInvalidateRegion(VAddr addr, u64 size) { |
| 304 | gpu_thread.FlushAndInvalidateRegion(addr, size); | 310 | gpu_thread.FlushAndInvalidateRegion(addr, size); |
| @@ -561,6 +567,10 @@ void GPU::InvalidateRegion(VAddr addr, u64 size) { | |||
| 561 | impl->InvalidateRegion(addr, size); | 567 | impl->InvalidateRegion(addr, size); |
| 562 | } | 568 | } |
| 563 | 569 | ||
| 570 | bool GPU::OnCPUWrite(VAddr addr, u64 size) { | ||
| 571 | return impl->OnCPUWrite(addr, size); | ||
| 572 | } | ||
| 573 | |||
| 564 | void GPU::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 574 | void GPU::FlushAndInvalidateRegion(VAddr addr, u64 size) { |
| 565 | impl->FlushAndInvalidateRegion(addr, size); | 575 | impl->FlushAndInvalidateRegion(addr, size); |
| 566 | } | 576 | } |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index e49c40cf2..ba2838b89 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -250,6 +250,10 @@ public: | |||
| 250 | /// Notify rasterizer that any caches of the specified region should be invalidated | 250 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 251 | void InvalidateRegion(VAddr addr, u64 size); | 251 | void InvalidateRegion(VAddr addr, u64 size); |
| 252 | 252 | ||
| 253 | /// Notify rasterizer that CPU is trying to write this area. It returns true if the area is | ||
| 254 | /// sensible, false otherwise | ||
| 255 | bool OnCPUWrite(VAddr addr, u64 size); | ||
| 256 | |||
| 253 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 257 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 254 | void FlushAndInvalidateRegion(VAddr addr, u64 size); | 258 | void FlushAndInvalidateRegion(VAddr addr, u64 size); |
| 255 | 259 | ||
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 889144f38..2f0f9f593 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -47,7 +47,7 @@ static void RunThread(std::stop_token stop_token, Core::System& system, | |||
| 47 | } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { | 47 | } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { |
| 48 | rasterizer->FlushRegion(flush->addr, flush->size); | 48 | rasterizer->FlushRegion(flush->addr, flush->size); |
| 49 | } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { | 49 | } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { |
| 50 | rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); | 50 | rasterizer->OnCacheInvalidation(invalidate->addr, invalidate->size); |
| 51 | } else { | 51 | } else { |
| 52 | ASSERT(false); | 52 | ASSERT(false); |
| 53 | } | 53 | } |
| @@ -102,12 +102,12 @@ void ThreadManager::TickGPU() { | |||
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { | 104 | void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { |
| 105 | rasterizer->OnCPUWrite(addr, size); | 105 | rasterizer->OnCacheInvalidation(addr, size); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 108 | void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { |
| 109 | // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important | 109 | // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important |
| 110 | rasterizer->OnCPUWrite(addr, size); | 110 | rasterizer->OnCacheInvalidation(addr, size); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { | 113 | u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { |
diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp index cd6a3a9b8..da07a556f 100644 --- a/src/video_core/host1x/codecs/codec.cpp +++ b/src/video_core/host1x/codecs/codec.cpp | |||
| @@ -290,7 +290,7 @@ void Codec::Decode() { | |||
| 290 | return vp9_decoder->GetFrameBytes(); | 290 | return vp9_decoder->GetFrameBytes(); |
| 291 | default: | 291 | default: |
| 292 | ASSERT(false); | 292 | ASSERT(false); |
| 293 | return std::vector<u8>{}; | 293 | return std::span<const u8>{}; |
| 294 | } | 294 | } |
| 295 | }(); | 295 | }(); |
| 296 | AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; | 296 | AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; |
diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index ce827eb6c..862904e39 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp | |||
| @@ -29,15 +29,15 @@ H264::H264(Host1x::Host1x& host1x_) : host1x{host1x_} {} | |||
| 29 | 29 | ||
| 30 | H264::~H264() = default; | 30 | H264::~H264() = default; |
| 31 | 31 | ||
| 32 | const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, | 32 | std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, |
| 33 | bool is_first_frame) { | 33 | bool is_first_frame) { |
| 34 | H264DecoderContext context; | 34 | H264DecoderContext context; |
| 35 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context, | 35 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context, |
| 36 | sizeof(H264DecoderContext)); | 36 | sizeof(H264DecoderContext)); |
| 37 | 37 | ||
| 38 | const s64 frame_number = context.h264_parameter_set.frame_number.Value(); | 38 | const s64 frame_number = context.h264_parameter_set.frame_number.Value(); |
| 39 | if (!is_first_frame && frame_number != 0) { | 39 | if (!is_first_frame && frame_number != 0) { |
| 40 | frame.resize(context.stream_len); | 40 | frame.resize_destructive(context.stream_len); |
| 41 | host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); | 41 | host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); |
| 42 | return frame; | 42 | return frame; |
| 43 | } | 43 | } |
| @@ -135,14 +135,14 @@ const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist | |||
| 135 | for (s32 index = 0; index < 6; index++) { | 135 | for (s32 index = 0; index < 6; index++) { |
| 136 | writer.WriteBit(true); | 136 | writer.WriteBit(true); |
| 137 | std::span<const u8> matrix{context.weight_scale}; | 137 | std::span<const u8> matrix{context.weight_scale}; |
| 138 | writer.WriteScalingList(matrix, index * 16, 16); | 138 | writer.WriteScalingList(scan, matrix, index * 16, 16); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | if (context.h264_parameter_set.transform_8x8_mode_flag) { | 141 | if (context.h264_parameter_set.transform_8x8_mode_flag) { |
| 142 | for (s32 index = 0; index < 2; index++) { | 142 | for (s32 index = 0; index < 2; index++) { |
| 143 | writer.WriteBit(true); | 143 | writer.WriteBit(true); |
| 144 | std::span<const u8> matrix{context.weight_scale_8x8}; | 144 | std::span<const u8> matrix{context.weight_scale_8x8}; |
| 145 | writer.WriteScalingList(matrix, index * 64, 64); | 145 | writer.WriteScalingList(scan, matrix, index * 64, 64); |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | 148 | ||
| @@ -188,8 +188,8 @@ void H264BitWriter::WriteBit(bool state) { | |||
| 188 | WriteBits(state ? 1 : 0, 1); | 188 | WriteBits(state ? 1 : 0, 1); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | void H264BitWriter::WriteScalingList(std::span<const u8> list, s32 start, s32 count) { | 191 | void H264BitWriter::WriteScalingList(Common::ScratchBuffer<u8>& scan, std::span<const u8> list, |
| 192 | static Common::ScratchBuffer<u8> scan{}; | 192 | s32 start, s32 count) { |
| 193 | scan.resize_destructive(count); | 193 | scan.resize_destructive(count); |
| 194 | if (count == 16) { | 194 | if (count == 16) { |
| 195 | std::memcpy(scan.data(), zig_zag_scan.data(), scan.size()); | 195 | std::memcpy(scan.data(), zig_zag_scan.data(), scan.size()); |
diff --git a/src/video_core/host1x/codecs/h264.h b/src/video_core/host1x/codecs/h264.h index 5cc86454e..d6b556322 100644 --- a/src/video_core/host1x/codecs/h264.h +++ b/src/video_core/host1x/codecs/h264.h | |||
| @@ -5,9 +5,11 @@ | |||
| 5 | 5 | ||
| 6 | #include <span> | 6 | #include <span> |
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | |||
| 8 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 9 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/scratch_buffer.h" | ||
| 11 | #include "video_core/host1x/nvdec_common.h" | 13 | #include "video_core/host1x/nvdec_common.h" |
| 12 | 14 | ||
| 13 | namespace Tegra { | 15 | namespace Tegra { |
| @@ -37,7 +39,8 @@ public: | |||
| 37 | 39 | ||
| 38 | /// Based on section 7.3.2.1.1.1 and Table 7-4 in the H.264 specification | 40 | /// Based on section 7.3.2.1.1.1 and Table 7-4 in the H.264 specification |
| 39 | /// Writes the scaling matrices of the sream | 41 | /// Writes the scaling matrices of the sream |
| 40 | void WriteScalingList(std::span<const u8> list, s32 start, s32 count); | 42 | void WriteScalingList(Common::ScratchBuffer<u8>& scan, std::span<const u8> list, s32 start, |
| 43 | s32 count); | ||
| 41 | 44 | ||
| 42 | /// Return the bitstream as a vector. | 45 | /// Return the bitstream as a vector. |
| 43 | [[nodiscard]] std::vector<u8>& GetByteArray(); | 46 | [[nodiscard]] std::vector<u8>& GetByteArray(); |
| @@ -63,11 +66,12 @@ public: | |||
| 63 | ~H264(); | 66 | ~H264(); |
| 64 | 67 | ||
| 65 | /// Compose the H264 frame for FFmpeg decoding | 68 | /// Compose the H264 frame for FFmpeg decoding |
| 66 | [[nodiscard]] const std::vector<u8>& ComposeFrame( | 69 | [[nodiscard]] std::span<const u8> ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, |
| 67 | const Host1x::NvdecCommon::NvdecRegisters& state, bool is_first_frame = false); | 70 | bool is_first_frame = false); |
| 68 | 71 | ||
| 69 | private: | 72 | private: |
| 70 | std::vector<u8> frame; | 73 | Common::ScratchBuffer<u8> frame; |
| 74 | Common::ScratchBuffer<u8> scan; | ||
| 71 | Host1x::Host1x& host1x; | 75 | Host1x::Host1x& host1x; |
| 72 | 76 | ||
| 73 | struct H264ParameterSet { | 77 | struct H264ParameterSet { |
diff --git a/src/video_core/host1x/codecs/vp8.cpp b/src/video_core/host1x/codecs/vp8.cpp index 28fb12cb8..ee6392ff9 100644 --- a/src/video_core/host1x/codecs/vp8.cpp +++ b/src/video_core/host1x/codecs/vp8.cpp | |||
| @@ -12,7 +12,7 @@ VP8::VP8(Host1x::Host1x& host1x_) : host1x{host1x_} {} | |||
| 12 | 12 | ||
| 13 | VP8::~VP8() = default; | 13 | VP8::~VP8() = default; |
| 14 | 14 | ||
| 15 | const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { | 15 | std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { |
| 16 | VP8PictureInfo info; | 16 | VP8PictureInfo info; |
| 17 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); | 17 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); |
| 18 | 18 | ||
diff --git a/src/video_core/host1x/codecs/vp8.h b/src/video_core/host1x/codecs/vp8.h index 5bf07ecab..7926b73f3 100644 --- a/src/video_core/host1x/codecs/vp8.h +++ b/src/video_core/host1x/codecs/vp8.h | |||
| @@ -4,10 +4,11 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <vector> | 7 | #include <span> |
| 8 | 8 | ||
| 9 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/scratch_buffer.h" | ||
| 11 | #include "video_core/host1x/nvdec_common.h" | 12 | #include "video_core/host1x/nvdec_common.h" |
| 12 | 13 | ||
| 13 | namespace Tegra { | 14 | namespace Tegra { |
| @@ -24,11 +25,11 @@ public: | |||
| 24 | ~VP8(); | 25 | ~VP8(); |
| 25 | 26 | ||
| 26 | /// Compose the VP8 frame for FFmpeg decoding | 27 | /// Compose the VP8 frame for FFmpeg decoding |
| 27 | [[nodiscard]] const std::vector<u8>& ComposeFrame( | 28 | [[nodiscard]] std::span<const u8> ComposeFrame( |
| 28 | const Host1x::NvdecCommon::NvdecRegisters& state); | 29 | const Host1x::NvdecCommon::NvdecRegisters& state); |
| 29 | 30 | ||
| 30 | private: | 31 | private: |
| 31 | std::vector<u8> frame; | 32 | Common::ScratchBuffer<u8> frame; |
| 32 | Host1x::Host1x& host1x; | 33 | Host1x::Host1x& host1x; |
| 33 | 34 | ||
| 34 | struct VP8PictureInfo { | 35 | struct VP8PictureInfo { |
diff --git a/src/video_core/host1x/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp index cf40c9012..306c3d0e8 100644 --- a/src/video_core/host1x/codecs/vp9.cpp +++ b/src/video_core/host1x/codecs/vp9.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <algorithm> // for std::copy | 4 | #include <algorithm> // for std::copy |
| 5 | #include <numeric> | 5 | #include <numeric> |
| 6 | |||
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "video_core/host1x/codecs/vp9.h" | 8 | #include "video_core/host1x/codecs/vp9.h" |
| 8 | #include "video_core/host1x/host1x.h" | 9 | #include "video_core/host1x/host1x.h" |
diff --git a/src/video_core/host1x/codecs/vp9.h b/src/video_core/host1x/codecs/vp9.h index d4083e8d3..f1ed19508 100644 --- a/src/video_core/host1x/codecs/vp9.h +++ b/src/video_core/host1x/codecs/vp9.h | |||
| @@ -4,9 +4,11 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <span> | ||
| 7 | #include <vector> | 8 | #include <vector> |
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/scratch_buffer.h" | ||
| 10 | #include "common/stream.h" | 12 | #include "common/stream.h" |
| 11 | #include "video_core/host1x/codecs/vp9_types.h" | 13 | #include "video_core/host1x/codecs/vp9_types.h" |
| 12 | #include "video_core/host1x/nvdec_common.h" | 14 | #include "video_core/host1x/nvdec_common.h" |
| @@ -128,8 +130,8 @@ public: | |||
| 128 | return !current_frame_info.show_frame; | 130 | return !current_frame_info.show_frame; |
| 129 | } | 131 | } |
| 130 | 132 | ||
| 131 | /// Returns a const reference to the composed frame data. | 133 | /// Returns a const span to the composed frame data. |
| 132 | [[nodiscard]] const std::vector<u8>& GetFrameBytes() const { | 134 | [[nodiscard]] std::span<const u8> GetFrameBytes() const { |
| 133 | return frame; | 135 | return frame; |
| 134 | } | 136 | } |
| 135 | 137 | ||
| @@ -181,7 +183,7 @@ private: | |||
| 181 | [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader(); | 183 | [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader(); |
| 182 | 184 | ||
| 183 | Host1x::Host1x& host1x; | 185 | Host1x::Host1x& host1x; |
| 184 | std::vector<u8> frame; | 186 | Common::ScratchBuffer<u8> frame; |
| 185 | 187 | ||
| 186 | std::array<s8, 4> loop_filter_ref_deltas{}; | 188 | std::array<s8, 4> loop_filter_ref_deltas{}; |
| 187 | std::array<s8, 2> loop_filter_mode_deltas{}; | 189 | std::array<s8, 2> loop_filter_mode_deltas{}; |
diff --git a/src/video_core/host1x/codecs/vp9_types.h b/src/video_core/host1x/codecs/vp9_types.h index adad8ed7e..cc9b25690 100644 --- a/src/video_core/host1x/codecs/vp9_types.h +++ b/src/video_core/host1x/codecs/vp9_types.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | |||
| 8 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | 11 | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 7566a8c4e..cb8029a4f 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -109,7 +109,9 @@ public: | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /// Notify rasterizer that any caches of the specified region are desync with guest | 111 | /// Notify rasterizer that any caches of the specified region are desync with guest |
| 112 | virtual void OnCPUWrite(VAddr addr, u64 size) = 0; | 112 | virtual void OnCacheInvalidation(VAddr addr, u64 size) = 0; |
| 113 | |||
| 114 | virtual bool OnCPUWrite(VAddr addr, u64 size) = 0; | ||
| 113 | 115 | ||
| 114 | /// Sync memory between guest and host. | 116 | /// Sync memory between guest and host. |
| 115 | virtual void InvalidateGPUCache() = 0; | 117 | virtual void InvalidateGPUCache() = 0; |
diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp index bf2ce4c49..92ecf6682 100644 --- a/src/video_core/renderer_null/null_rasterizer.cpp +++ b/src/video_core/renderer_null/null_rasterizer.cpp | |||
| @@ -47,7 +47,10 @@ bool RasterizerNull::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheTyp | |||
| 47 | return false; | 47 | return false; |
| 48 | } | 48 | } |
| 49 | void RasterizerNull::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} | 49 | void RasterizerNull::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} |
| 50 | void RasterizerNull::OnCPUWrite(VAddr addr, u64 size) {} | 50 | bool RasterizerNull::OnCPUWrite(VAddr addr, u64 size) { |
| 51 | return false; | ||
| 52 | } | ||
| 53 | void RasterizerNull::OnCacheInvalidation(VAddr addr, u64 size) {} | ||
| 51 | VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(VAddr addr, u64 size) { | 54 | VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(VAddr addr, u64 size) { |
| 52 | VideoCore::RasterizerDownloadArea new_area{ | 55 | VideoCore::RasterizerDownloadArea new_area{ |
| 53 | .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), | 56 | .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), |
diff --git a/src/video_core/renderer_null/null_rasterizer.h b/src/video_core/renderer_null/null_rasterizer.h index a8d35d2c1..93b9a6971 100644 --- a/src/video_core/renderer_null/null_rasterizer.h +++ b/src/video_core/renderer_null/null_rasterizer.h | |||
| @@ -53,7 +53,8 @@ public: | |||
| 53 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 53 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 54 | void InvalidateRegion(VAddr addr, u64 size, | 54 | void InvalidateRegion(VAddr addr, u64 size, |
| 55 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 55 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 56 | void OnCPUWrite(VAddr addr, u64 size) override; | 56 | void OnCacheInvalidation(VAddr addr, u64 size) override; |
| 57 | bool OnCPUWrite(VAddr addr, u64 size) override; | ||
| 57 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; | 58 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; |
| 58 | void InvalidateGPUCache() override; | 59 | void InvalidateGPUCache() override; |
| 59 | void UnmapMemory(VAddr addr, u64 size) override; | 60 | void UnmapMemory(VAddr addr, u64 size) override; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index edf527f2d..aadd6967c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -485,12 +485,33 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::Cache | |||
| 485 | } | 485 | } |
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { | 488 | bool RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { |
| 489 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | ||
| 490 | if (addr == 0 || size == 0) { | ||
| 491 | return false; | ||
| 492 | } | ||
| 493 | |||
| 494 | { | ||
| 495 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 496 | if (buffer_cache.OnCPUWrite(addr, size)) { | ||
| 497 | return true; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | { | ||
| 502 | std::scoped_lock lock{texture_cache.mutex}; | ||
| 503 | texture_cache.WriteMemory(addr, size); | ||
| 504 | } | ||
| 505 | |||
| 506 | shader_cache.InvalidateRegion(addr, size); | ||
| 507 | return false; | ||
| 508 | } | ||
| 509 | |||
| 510 | void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) { | ||
| 489 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 511 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 490 | if (addr == 0 || size == 0) { | 512 | if (addr == 0 || size == 0) { |
| 491 | return; | 513 | return; |
| 492 | } | 514 | } |
| 493 | shader_cache.OnCPUWrite(addr, size); | ||
| 494 | { | 515 | { |
| 495 | std::scoped_lock lock{texture_cache.mutex}; | 516 | std::scoped_lock lock{texture_cache.mutex}; |
| 496 | texture_cache.WriteMemory(addr, size); | 517 | texture_cache.WriteMemory(addr, size); |
| @@ -499,15 +520,11 @@ void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { | |||
| 499 | std::scoped_lock lock{buffer_cache.mutex}; | 520 | std::scoped_lock lock{buffer_cache.mutex}; |
| 500 | buffer_cache.CachedWriteMemory(addr, size); | 521 | buffer_cache.CachedWriteMemory(addr, size); |
| 501 | } | 522 | } |
| 523 | shader_cache.InvalidateRegion(addr, size); | ||
| 502 | } | 524 | } |
| 503 | 525 | ||
| 504 | void RasterizerOpenGL::InvalidateGPUCache() { | 526 | void RasterizerOpenGL::InvalidateGPUCache() { |
| 505 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 527 | gpu.InvalidateGPUCache(); |
| 506 | shader_cache.SyncGuestHost(); | ||
| 507 | { | ||
| 508 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 509 | buffer_cache.FlushCachedWrites(); | ||
| 510 | } | ||
| 511 | } | 528 | } |
| 512 | 529 | ||
| 513 | void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) { | 530 | void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) { |
| @@ -519,7 +536,7 @@ void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) { | |||
| 519 | std::scoped_lock lock{buffer_cache.mutex}; | 536 | std::scoped_lock lock{buffer_cache.mutex}; |
| 520 | buffer_cache.WriteMemory(addr, size); | 537 | buffer_cache.WriteMemory(addr, size); |
| 521 | } | 538 | } |
| 522 | shader_cache.OnCPUWrite(addr, size); | 539 | shader_cache.OnCacheInvalidation(addr, size); |
| 523 | } | 540 | } |
| 524 | 541 | ||
| 525 | void RasterizerOpenGL::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) { | 542 | void RasterizerOpenGL::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index a73ad15c1..8eda2ddba 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -98,7 +98,8 @@ public: | |||
| 98 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; | 98 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; |
| 99 | void InvalidateRegion(VAddr addr, u64 size, | 99 | void InvalidateRegion(VAddr addr, u64 size, |
| 100 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 100 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 101 | void OnCPUWrite(VAddr addr, u64 size) override; | 101 | void OnCacheInvalidation(VAddr addr, u64 size) override; |
| 102 | bool OnCPUWrite(VAddr addr, u64 size) override; | ||
| 102 | void InvalidateGPUCache() override; | 103 | void InvalidateGPUCache() override; |
| 103 | void UnmapMemory(VAddr addr, u64 size) override; | 104 | void UnmapMemory(VAddr addr, u64 size) override; |
| 104 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | 105 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index b72f95235..51df18ec3 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -591,7 +591,7 @@ void BufferCacheRuntime::ReserveNullBuffer() { | |||
| 591 | .flags = 0, | 591 | .flags = 0, |
| 592 | .size = 4, | 592 | .size = 4, |
| 593 | .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | | 593 | .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | |
| 594 | VK_BUFFER_USAGE_TRANSFER_DST_BIT, | 594 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| 595 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 595 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 596 | .queueFamilyIndexCount = 0, | 596 | .queueFamilyIndexCount = 0, |
| 597 | .pQueueFamilyIndices = nullptr, | 597 | .pQueueFamilyIndices = nullptr, |
| @@ -599,7 +599,6 @@ void BufferCacheRuntime::ReserveNullBuffer() { | |||
| 599 | if (device.IsExtTransformFeedbackSupported()) { | 599 | if (device.IsExtTransformFeedbackSupported()) { |
| 600 | create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; | 600 | create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; |
| 601 | } | 601 | } |
| 602 | create_info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; | ||
| 603 | null_buffer = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal); | 602 | null_buffer = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal); |
| 604 | if (device.HasDebuggingToolAttached()) { | 603 | if (device.HasDebuggingToolAttached()) { |
| 605 | null_buffer.SetObjectNameEXT("Null buffer"); | 604 | null_buffer.SetObjectNameEXT("Null buffer"); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f7c0d939a..456bb040e 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -566,11 +566,32 @@ void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<VAddr, std::s | |||
| 566 | } | 566 | } |
| 567 | } | 567 | } |
| 568 | 568 | ||
| 569 | void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { | 569 | bool RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { |
| 570 | if (addr == 0 || size == 0) { | ||
| 571 | return false; | ||
| 572 | } | ||
| 573 | |||
| 574 | { | ||
| 575 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 576 | if (buffer_cache.OnCPUWrite(addr, size)) { | ||
| 577 | return true; | ||
| 578 | } | ||
| 579 | } | ||
| 580 | |||
| 581 | { | ||
| 582 | std::scoped_lock lock{texture_cache.mutex}; | ||
| 583 | texture_cache.WriteMemory(addr, size); | ||
| 584 | } | ||
| 585 | |||
| 586 | pipeline_cache.InvalidateRegion(addr, size); | ||
| 587 | return false; | ||
| 588 | } | ||
| 589 | |||
| 590 | void RasterizerVulkan::OnCacheInvalidation(VAddr addr, u64 size) { | ||
| 570 | if (addr == 0 || size == 0) { | 591 | if (addr == 0 || size == 0) { |
| 571 | return; | 592 | return; |
| 572 | } | 593 | } |
| 573 | pipeline_cache.OnCPUWrite(addr, size); | 594 | |
| 574 | { | 595 | { |
| 575 | std::scoped_lock lock{texture_cache.mutex}; | 596 | std::scoped_lock lock{texture_cache.mutex}; |
| 576 | texture_cache.WriteMemory(addr, size); | 597 | texture_cache.WriteMemory(addr, size); |
| @@ -579,14 +600,11 @@ void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { | |||
| 579 | std::scoped_lock lock{buffer_cache.mutex}; | 600 | std::scoped_lock lock{buffer_cache.mutex}; |
| 580 | buffer_cache.CachedWriteMemory(addr, size); | 601 | buffer_cache.CachedWriteMemory(addr, size); |
| 581 | } | 602 | } |
| 603 | pipeline_cache.InvalidateRegion(addr, size); | ||
| 582 | } | 604 | } |
| 583 | 605 | ||
| 584 | void RasterizerVulkan::InvalidateGPUCache() { | 606 | void RasterizerVulkan::InvalidateGPUCache() { |
| 585 | pipeline_cache.SyncGuestHost(); | 607 | gpu.InvalidateGPUCache(); |
| 586 | { | ||
| 587 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 588 | buffer_cache.FlushCachedWrites(); | ||
| 589 | } | ||
| 590 | } | 608 | } |
| 591 | 609 | ||
| 592 | void RasterizerVulkan::UnmapMemory(VAddr addr, u64 size) { | 610 | void RasterizerVulkan::UnmapMemory(VAddr addr, u64 size) { |
| @@ -598,7 +616,7 @@ void RasterizerVulkan::UnmapMemory(VAddr addr, u64 size) { | |||
| 598 | std::scoped_lock lock{buffer_cache.mutex}; | 616 | std::scoped_lock lock{buffer_cache.mutex}; |
| 599 | buffer_cache.WriteMemory(addr, size); | 617 | buffer_cache.WriteMemory(addr, size); |
| 600 | } | 618 | } |
| 601 | pipeline_cache.OnCPUWrite(addr, size); | 619 | pipeline_cache.OnCacheInvalidation(addr, size); |
| 602 | } | 620 | } |
| 603 | 621 | ||
| 604 | void RasterizerVulkan::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) { | 622 | void RasterizerVulkan::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) { |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index b39710b3c..73257d964 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -96,7 +96,8 @@ public: | |||
| 96 | void InvalidateRegion(VAddr addr, u64 size, | 96 | void InvalidateRegion(VAddr addr, u64 size, |
| 97 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 97 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 98 | void InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) override; | 98 | void InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) override; |
| 99 | void OnCPUWrite(VAddr addr, u64 size) override; | 99 | void OnCacheInvalidation(VAddr addr, u64 size) override; |
| 100 | bool OnCPUWrite(VAddr addr, u64 size) override; | ||
| 100 | void InvalidateGPUCache() override; | 101 | void InvalidateGPUCache() override; |
| 101 | void UnmapMemory(VAddr addr, u64 size) override; | 102 | void UnmapMemory(VAddr addr, u64 size) override; |
| 102 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | 103 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; |
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index 4db948b6d..01701201d 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp | |||
| @@ -24,7 +24,7 @@ void ShaderCache::InvalidateRegion(VAddr addr, size_t size) { | |||
| 24 | RemovePendingShaders(); | 24 | RemovePendingShaders(); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | void ShaderCache::OnCPUWrite(VAddr addr, size_t size) { | 27 | void ShaderCache::OnCacheInvalidation(VAddr addr, size_t size) { |
| 28 | std::scoped_lock lock{invalidation_mutex}; | 28 | std::scoped_lock lock{invalidation_mutex}; |
| 29 | InvalidatePagesInRegion(addr, size); | 29 | InvalidatePagesInRegion(addr, size); |
| 30 | } | 30 | } |
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index f3cc4c70b..de8e08002 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h | |||
| @@ -62,7 +62,7 @@ public: | |||
| 62 | /// @brief Unmarks a memory region as cached and marks it for removal | 62 | /// @brief Unmarks a memory region as cached and marks it for removal |
| 63 | /// @param addr Start address of the CPU write operation | 63 | /// @param addr Start address of the CPU write operation |
| 64 | /// @param size Number of bytes of the CPU write operation | 64 | /// @param size Number of bytes of the CPU write operation |
| 65 | void OnCPUWrite(VAddr addr, size_t size); | 65 | void OnCacheInvalidation(VAddr addr, size_t size); |
| 66 | 66 | ||
| 67 | /// @brief Flushes delayed removal operations | 67 | /// @brief Flushes delayed removal operations |
| 68 | void SyncGuestHost(); | 68 | void SyncGuestHost(); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index d3f03a995..79f158db4 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -598,14 +598,6 @@ void TextureCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t siz | |||
| 598 | [&](ImageId id, Image&) { deleted_images.push_back(id); }); | 598 | [&](ImageId id, Image&) { deleted_images.push_back(id); }); |
| 599 | for (const ImageId id : deleted_images) { | 599 | for (const ImageId id : deleted_images) { |
| 600 | Image& image = slot_images[id]; | 600 | Image& image = slot_images[id]; |
| 601 | if (True(image.flags & ImageFlagBits::CpuModified)) { | ||
| 602 | return; | ||
| 603 | } | ||
| 604 | image.flags |= ImageFlagBits::CpuModified; | ||
| 605 | if (True(image.flags & ImageFlagBits::Tracked)) { | ||
| 606 | UntrackImage(image, id); | ||
| 607 | } | ||
| 608 | /* | ||
| 609 | if (True(image.flags & ImageFlagBits::Remapped)) { | 601 | if (True(image.flags & ImageFlagBits::Remapped)) { |
| 610 | continue; | 602 | continue; |
| 611 | } | 603 | } |
| @@ -613,7 +605,6 @@ void TextureCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t siz | |||
| 613 | if (True(image.flags & ImageFlagBits::Tracked)) { | 605 | if (True(image.flags & ImageFlagBits::Tracked)) { |
| 614 | UntrackImage(image, id); | 606 | UntrackImage(image, id); |
| 615 | } | 607 | } |
| 616 | */ | ||
| 617 | } | 608 | } |
| 618 | } | 609 | } |
| 619 | 610 | ||
| @@ -874,11 +865,19 @@ void TextureCache<P>::PopAsyncFlushes() { | |||
| 874 | template <class P> | 865 | template <class P> |
| 875 | ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand, bool is_upload) { | 866 | ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand, bool is_upload) { |
| 876 | const ImageInfo dst_info(operand); | 867 | const ImageInfo dst_info(operand); |
| 877 | const ImageId image_id = FindDMAImage(dst_info, operand.address); | 868 | const ImageId dst_id = FindDMAImage(dst_info, operand.address); |
| 878 | if (!image_id) { | 869 | if (!dst_id) { |
| 870 | return NULL_IMAGE_ID; | ||
| 871 | } | ||
| 872 | auto& image = slot_images[dst_id]; | ||
| 873 | if (False(image.flags & ImageFlagBits::GpuModified)) { | ||
| 874 | // No need to waste time on an image that's synced with guest | ||
| 875 | return NULL_IMAGE_ID; | ||
| 876 | } | ||
| 877 | if (image.info.type == ImageType::e3D) { | ||
| 878 | // Don't accelerate 3D images. | ||
| 879 | return NULL_IMAGE_ID; | 879 | return NULL_IMAGE_ID; |
| 880 | } | 880 | } |
| 881 | auto& image = slot_images[image_id]; | ||
| 882 | if (!is_upload && !image.info.dma_downloaded) { | 881 | if (!is_upload && !image.info.dma_downloaded) { |
| 883 | // Force a full sync. | 882 | // Force a full sync. |
| 884 | image.info.dma_downloaded = true; | 883 | image.info.dma_downloaded = true; |
| @@ -888,7 +887,7 @@ ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand, boo | |||
| 888 | if (!base) { | 887 | if (!base) { |
| 889 | return NULL_IMAGE_ID; | 888 | return NULL_IMAGE_ID; |
| 890 | } | 889 | } |
| 891 | return image_id; | 890 | return dst_id; |
| 892 | } | 891 | } |
| 893 | 892 | ||
| 894 | template <class P> | 893 | template <class P> |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 70436cf1c..421e71e5a 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -528,6 +528,14 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | sets_per_pool = 64; | 530 | sets_per_pool = 64; |
| 531 | if (extensions.extended_dynamic_state3 && is_amd_driver && | ||
| 532 | properties.properties.driverVersion >= VK_MAKE_API_VERSION(0, 2, 0, 270)) { | ||
| 533 | LOG_WARNING(Render_Vulkan, | ||
| 534 | "AMD drivers after 23.5.2 have broken extendedDynamicState3ColorBlendEquation"); | ||
| 535 | features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false; | ||
| 536 | features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false; | ||
| 537 | dynamic_state3_blending = false; | ||
| 538 | } | ||
| 531 | if (is_amd_driver) { | 539 | if (is_amd_driver) { |
| 532 | // AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2. | 540 | // AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2. |
| 533 | sets_per_pool = 96; | 541 | sets_per_pool = 96; |
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp index 7624a9b32..6a294c1da 100644 --- a/src/video_core/vulkan_common/vulkan_instance.cpp +++ b/src/video_core/vulkan_common/vulkan_instance.cpp | |||
| @@ -19,11 +19,9 @@ | |||
| 19 | #include <windows.h> | 19 | #include <windows.h> |
| 20 | // ensure include order | 20 | // ensure include order |
| 21 | #include <vulkan/vulkan_win32.h> | 21 | #include <vulkan/vulkan_win32.h> |
| 22 | #elif defined(__APPLE__) | ||
| 23 | #include <vulkan/vulkan_macos.h> | ||
| 24 | #elif defined(__ANDROID__) | 22 | #elif defined(__ANDROID__) |
| 25 | #include <vulkan/vulkan_android.h> | 23 | #include <vulkan/vulkan_android.h> |
| 26 | #else | 24 | #elif !defined(__APPLE__) |
| 27 | #include <X11/Xlib.h> | 25 | #include <X11/Xlib.h> |
| 28 | #include <vulkan/vulkan_wayland.h> | 26 | #include <vulkan/vulkan_wayland.h> |
| 29 | #include <vulkan/vulkan_xlib.h> | 27 | #include <vulkan/vulkan_xlib.h> |
| @@ -68,7 +66,7 @@ namespace { | |||
| 68 | break; | 66 | break; |
| 69 | #elif defined(__APPLE__) | 67 | #elif defined(__APPLE__) |
| 70 | case Core::Frontend::WindowSystemType::Cocoa: | 68 | case Core::Frontend::WindowSystemType::Cocoa: |
| 71 | extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); | 69 | extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); |
| 72 | break; | 70 | break; |
| 73 | #elif defined(__ANDROID__) | 71 | #elif defined(__ANDROID__) |
| 74 | case Core::Frontend::WindowSystemType::Android: | 72 | case Core::Frontend::WindowSystemType::Android: |
diff --git a/src/video_core/vulkan_common/vulkan_surface.cpp b/src/video_core/vulkan_common/vulkan_surface.cpp index c34599365..cfea4cd7b 100644 --- a/src/video_core/vulkan_common/vulkan_surface.cpp +++ b/src/video_core/vulkan_common/vulkan_surface.cpp | |||
| @@ -11,11 +11,9 @@ | |||
| 11 | #include <windows.h> | 11 | #include <windows.h> |
| 12 | // ensure include order | 12 | // ensure include order |
| 13 | #include <vulkan/vulkan_win32.h> | 13 | #include <vulkan/vulkan_win32.h> |
| 14 | #elif defined(__APPLE__) | ||
| 15 | #include <vulkan/vulkan_macos.h> | ||
| 16 | #elif defined(__ANDROID__) | 14 | #elif defined(__ANDROID__) |
| 17 | #include <vulkan/vulkan_android.h> | 15 | #include <vulkan/vulkan_android.h> |
| 18 | #else | 16 | #elif !defined(__APPLE__) |
| 19 | #include <X11/Xlib.h> | 17 | #include <X11/Xlib.h> |
| 20 | #include <vulkan/vulkan_wayland.h> | 18 | #include <vulkan/vulkan_wayland.h> |
| 21 | #include <vulkan/vulkan_xlib.h> | 19 | #include <vulkan/vulkan_xlib.h> |
| @@ -44,12 +42,13 @@ vk::SurfaceKHR CreateSurface( | |||
| 44 | } | 42 | } |
| 45 | #elif defined(__APPLE__) | 43 | #elif defined(__APPLE__) |
| 46 | if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) { | 44 | if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) { |
| 47 | const VkMacOSSurfaceCreateInfoMVK mvk_ci{VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, | 45 | const VkMetalSurfaceCreateInfoEXT macos_ci = { |
| 48 | nullptr, 0, window_info.render_surface}; | 46 | .pLayer = static_cast<const CAMetalLayer*>(window_info.render_surface), |
| 49 | const auto vkCreateMacOSSurfaceMVK = reinterpret_cast<PFN_vkCreateMacOSSurfaceMVK>( | 47 | }; |
| 50 | dld.vkGetInstanceProcAddr(*instance, "vkCreateMacOSSurfaceMVK")); | 48 | const auto vkCreateMetalSurfaceEXT = reinterpret_cast<PFN_vkCreateMetalSurfaceEXT>( |
| 51 | if (!vkCreateMacOSSurfaceMVK || | 49 | dld.vkGetInstanceProcAddr(*instance, "vkCreateMetalSurfaceEXT")); |
| 52 | vkCreateMacOSSurfaceMVK(*instance, &mvk_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { | 50 | if (!vkCreateMetalSurfaceEXT || |
| 51 | vkCreateMetalSurfaceEXT(*instance, &macos_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { | ||
| 53 | LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface"); | 52 | LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface"); |
| 54 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | 53 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 55 | } | 54 | } |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index b5e70fcd4..32bd75ad8 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #define VK_NO_PROTOTYPES | 15 | #define VK_NO_PROTOTYPES |
| 16 | #ifdef _WIN32 | 16 | #ifdef _WIN32 |
| 17 | #define VK_USE_PLATFORM_WIN32_KHR | 17 | #define VK_USE_PLATFORM_WIN32_KHR |
| 18 | #elif defined(__APPLE__) | ||
| 19 | #define VK_USE_PLATFORM_METAL_EXT | ||
| 18 | #endif | 20 | #endif |
| 19 | #include <vulkan/vulkan.h> | 21 | #include <vulkan/vulkan.h> |
| 20 | 22 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 29467d380..195d3556c 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -503,8 +503,7 @@ void Config::ReadMousePanningValues() { | |||
| 503 | ReadBasicSetting(Settings::values.mouse_panning); | 503 | ReadBasicSetting(Settings::values.mouse_panning); |
| 504 | ReadBasicSetting(Settings::values.mouse_panning_x_sensitivity); | 504 | ReadBasicSetting(Settings::values.mouse_panning_x_sensitivity); |
| 505 | ReadBasicSetting(Settings::values.mouse_panning_y_sensitivity); | 505 | ReadBasicSetting(Settings::values.mouse_panning_y_sensitivity); |
| 506 | ReadBasicSetting(Settings::values.mouse_panning_deadzone_x_counterweight); | 506 | ReadBasicSetting(Settings::values.mouse_panning_deadzone_counterweight); |
| 507 | ReadBasicSetting(Settings::values.mouse_panning_deadzone_y_counterweight); | ||
| 508 | ReadBasicSetting(Settings::values.mouse_panning_decay_strength); | 507 | ReadBasicSetting(Settings::values.mouse_panning_decay_strength); |
| 509 | ReadBasicSetting(Settings::values.mouse_panning_min_decay); | 508 | ReadBasicSetting(Settings::values.mouse_panning_min_decay); |
| 510 | } | 509 | } |
| @@ -1122,8 +1121,7 @@ void Config::SaveMousePanningValues() { | |||
| 1122 | // Don't overwrite values.mouse_panning | 1121 | // Don't overwrite values.mouse_panning |
| 1123 | WriteBasicSetting(Settings::values.mouse_panning_x_sensitivity); | 1122 | WriteBasicSetting(Settings::values.mouse_panning_x_sensitivity); |
| 1124 | WriteBasicSetting(Settings::values.mouse_panning_y_sensitivity); | 1123 | WriteBasicSetting(Settings::values.mouse_panning_y_sensitivity); |
| 1125 | WriteBasicSetting(Settings::values.mouse_panning_deadzone_x_counterweight); | 1124 | WriteBasicSetting(Settings::values.mouse_panning_deadzone_counterweight); |
| 1126 | WriteBasicSetting(Settings::values.mouse_panning_deadzone_y_counterweight); | ||
| 1127 | WriteBasicSetting(Settings::values.mouse_panning_decay_strength); | 1125 | WriteBasicSetting(Settings::values.mouse_panning_decay_strength); |
| 1128 | WriteBasicSetting(Settings::values.mouse_panning_min_decay); | 1126 | WriteBasicSetting(Settings::values.mouse_panning_min_decay); |
| 1129 | } | 1127 | } |
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index 43f6c7b50..611a79477 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui | |||
| @@ -3105,21 +3105,6 @@ | |||
| 3105 | </property> | 3105 | </property> |
| 3106 | <item> | 3106 | <item> |
| 3107 | <widget class="QPushButton" name="mousePanningButton"> | 3107 | <widget class="QPushButton" name="mousePanningButton"> |
| 3108 | <property name="minimumSize"> | ||
| 3109 | <size> | ||
| 3110 | <width>68</width> | ||
| 3111 | <height>0</height> | ||
| 3112 | </size> | ||
| 3113 | </property> | ||
| 3114 | <property name="maximumSize"> | ||
| 3115 | <size> | ||
| 3116 | <width>68</width> | ||
| 3117 | <height>16777215</height> | ||
| 3118 | </size> | ||
| 3119 | </property> | ||
| 3120 | <property name="styleSheet"> | ||
| 3121 | <string notr="true">min-width: 68px;</string> | ||
| 3122 | </property> | ||
| 3123 | <property name="text"> | 3108 | <property name="text"> |
| 3124 | <string>Configure</string> | 3109 | <string>Configure</string> |
| 3125 | </property> | 3110 | </property> |
diff --git a/src/yuzu/configuration/configure_mouse_panning.cpp b/src/yuzu/configuration/configure_mouse_panning.cpp index f183d2740..e37c546b0 100644 --- a/src/yuzu/configuration/configure_mouse_panning.cpp +++ b/src/yuzu/configuration/configure_mouse_panning.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <QCloseEvent> | 4 | #include <QCloseEvent> |
| 5 | #include <QMessageBox> | ||
| 5 | 6 | ||
| 6 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 7 | #include "ui_configure_mouse_panning.h" | 8 | #include "ui_configure_mouse_panning.h" |
| @@ -27,31 +28,34 @@ void ConfigureMousePanning::SetConfiguration(float right_stick_deadzone, float r | |||
| 27 | ui->enable->setChecked(Settings::values.mouse_panning.GetValue()); | 28 | ui->enable->setChecked(Settings::values.mouse_panning.GetValue()); |
| 28 | ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetValue()); | 29 | ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetValue()); |
| 29 | ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetValue()); | 30 | ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetValue()); |
| 30 | ui->deadzone_x_counterweight->setValue( | 31 | ui->deadzone_counterweight->setValue( |
| 31 | Settings::values.mouse_panning_deadzone_x_counterweight.GetValue()); | 32 | Settings::values.mouse_panning_deadzone_counterweight.GetValue()); |
| 32 | ui->deadzone_y_counterweight->setValue( | ||
| 33 | Settings::values.mouse_panning_deadzone_y_counterweight.GetValue()); | ||
| 34 | ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetValue()); | 33 | ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetValue()); |
| 35 | ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetValue()); | 34 | ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetValue()); |
| 36 | 35 | ||
| 37 | if (right_stick_deadzone > 0.0f || right_stick_range != 1.0f) { | 36 | if (right_stick_deadzone > 0.0f || right_stick_range != 1.0f) { |
| 38 | ui->warning_label->setText(QString::fromStdString( | 37 | const QString right_stick_deadzone_str = |
| 39 | "Mouse panning works better with a deadzone of 0% and a range of 100%.\n" | 38 | QString::fromStdString(std::to_string(static_cast<int>(right_stick_deadzone * 100.0f))); |
| 40 | "Current values are " + | 39 | const QString right_stick_range_str = |
| 41 | std::to_string(static_cast<int>(right_stick_deadzone * 100.0f)) + "% and " + | 40 | QString::fromStdString(std::to_string(static_cast<int>(right_stick_range * 100.0f))); |
| 42 | std::to_string(static_cast<int>(right_stick_range * 100.0f)) + "% respectively.")); | 41 | |
| 43 | } else { | 42 | ui->warning_label->setText( |
| 44 | ui->warning_label->hide(); | 43 | tr("Mouse panning works better with a deadzone of 0% and a range of 100%.\nCurrent " |
| 44 | "values are %1% and %2% respectively.") | ||
| 45 | .arg(right_stick_deadzone_str, right_stick_range_str)); | ||
| 46 | } | ||
| 47 | |||
| 48 | if (Settings::values.mouse_enabled) { | ||
| 49 | ui->warning_label->setText( | ||
| 50 | tr("Emulated mouse is enabled. This is incompatible with mouse panning.")); | ||
| 45 | } | 51 | } |
| 46 | } | 52 | } |
| 47 | 53 | ||
| 48 | void ConfigureMousePanning::SetDefaultConfiguration() { | 54 | void ConfigureMousePanning::SetDefaultConfiguration() { |
| 49 | ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetDefault()); | 55 | ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetDefault()); |
| 50 | ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetDefault()); | 56 | ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetDefault()); |
| 51 | ui->deadzone_x_counterweight->setValue( | 57 | ui->deadzone_counterweight->setValue( |
| 52 | Settings::values.mouse_panning_deadzone_x_counterweight.GetDefault()); | 58 | Settings::values.mouse_panning_deadzone_counterweight.GetDefault()); |
| 53 | ui->deadzone_y_counterweight->setValue( | ||
| 54 | Settings::values.mouse_panning_deadzone_y_counterweight.GetDefault()); | ||
| 55 | ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetDefault()); | 59 | ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetDefault()); |
| 56 | ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetDefault()); | 60 | ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetDefault()); |
| 57 | } | 61 | } |
| @@ -68,12 +72,19 @@ void ConfigureMousePanning::ApplyConfiguration() { | |||
| 68 | Settings::values.mouse_panning = ui->enable->isChecked(); | 72 | Settings::values.mouse_panning = ui->enable->isChecked(); |
| 69 | Settings::values.mouse_panning_x_sensitivity = static_cast<float>(ui->x_sensitivity->value()); | 73 | Settings::values.mouse_panning_x_sensitivity = static_cast<float>(ui->x_sensitivity->value()); |
| 70 | Settings::values.mouse_panning_y_sensitivity = static_cast<float>(ui->y_sensitivity->value()); | 74 | Settings::values.mouse_panning_y_sensitivity = static_cast<float>(ui->y_sensitivity->value()); |
| 71 | Settings::values.mouse_panning_deadzone_x_counterweight = | 75 | Settings::values.mouse_panning_deadzone_counterweight = |
| 72 | static_cast<float>(ui->deadzone_x_counterweight->value()); | 76 | static_cast<float>(ui->deadzone_counterweight->value()); |
| 73 | Settings::values.mouse_panning_deadzone_y_counterweight = | ||
| 74 | static_cast<float>(ui->deadzone_y_counterweight->value()); | ||
| 75 | Settings::values.mouse_panning_decay_strength = static_cast<float>(ui->decay_strength->value()); | 77 | Settings::values.mouse_panning_decay_strength = static_cast<float>(ui->decay_strength->value()); |
| 76 | Settings::values.mouse_panning_min_decay = static_cast<float>(ui->min_decay->value()); | 78 | Settings::values.mouse_panning_min_decay = static_cast<float>(ui->min_decay->value()); |
| 77 | 79 | ||
| 80 | if (Settings::values.mouse_enabled && Settings::values.mouse_panning) { | ||
| 81 | Settings::values.mouse_panning = false; | ||
| 82 | QMessageBox::critical( | ||
| 83 | this, tr("Emulated mouse is enabled"), | ||
| 84 | tr("Real mouse input and mouse panning are incompatible. Please disable the " | ||
| 85 | "emulated mouse in input advanced settings to allow mouse panning.")); | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | |||
| 78 | accept(); | 89 | accept(); |
| 79 | } | 90 | } |
diff --git a/src/yuzu/configuration/configure_mouse_panning.ui b/src/yuzu/configuration/configure_mouse_panning.ui index 75795b727..84fb7ee80 100644 --- a/src/yuzu/configuration/configure_mouse_panning.ui +++ b/src/yuzu/configuration/configure_mouse_panning.ui | |||
| @@ -9,10 +9,10 @@ | |||
| 9 | <item> | 9 | <item> |
| 10 | <widget class="QCheckBox" name="enable"> | 10 | <widget class="QCheckBox" name="enable"> |
| 11 | <property name="text"> | 11 | <property name="text"> |
| 12 | <string>Enable</string> | 12 | <string>Enable mouse panning</string> |
| 13 | </property> | 13 | </property> |
| 14 | <property name="toolTip"> | 14 | <property name="toolTip"> |
| 15 | <string>Can be toggled via a hotkey</string> | 15 | <string>Can be toggled via a hotkey. Default hotkey is Ctrl + F9</string> |
| 16 | </property> | 16 | </property> |
| 17 | </widget> | 17 | </widget> |
| 18 | </item> | 18 | </item> |
| @@ -89,40 +89,14 @@ | |||
| 89 | </property> | 89 | </property> |
| 90 | <layout class="QGridLayout"> | 90 | <layout class="QGridLayout"> |
| 91 | <item row="0" column="0"> | 91 | <item row="0" column="0"> |
| 92 | <widget class="QLabel" name="deadzone_x_counterweight_label"> | 92 | <widget class="QLabel" name="deadzone_counterweight_label"> |
| 93 | <property name="text"> | 93 | <property name="text"> |
| 94 | <string>Horizontal</string> | 94 | <string>Deadzone</string> |
| 95 | </property> | 95 | </property> |
| 96 | </widget> | 96 | </widget> |
| 97 | </item> | 97 | </item> |
| 98 | <item row="0" column="1"> | 98 | <item row="0" column="1"> |
| 99 | <widget class="QSpinBox" name="deadzone_x_counterweight"> | 99 | <widget class="QSpinBox" name="deadzone_counterweight"> |
| 100 | <property name="alignment"> | ||
| 101 | <set>Qt::AlignCenter</set> | ||
| 102 | </property> | ||
| 103 | <property name="suffix"> | ||
| 104 | <string>%</string> | ||
| 105 | </property> | ||
| 106 | <property name="minimum"> | ||
| 107 | <number>0</number> | ||
| 108 | </property> | ||
| 109 | <property name="maximum"> | ||
| 110 | <number>100</number> | ||
| 111 | </property> | ||
| 112 | <property name="value"> | ||
| 113 | <number>0</number> | ||
| 114 | </property> | ||
| 115 | </widget> | ||
| 116 | </item> | ||
| 117 | <item row="1" column="0"> | ||
| 118 | <widget class="QLabel" name="deadzone_y_counterweight_label"> | ||
| 119 | <property name="text"> | ||
| 120 | <string>Vertical</string> | ||
| 121 | </property> | ||
| 122 | </widget> | ||
| 123 | </item> | ||
| 124 | <item row="1" column="1"> | ||
| 125 | <widget class="QSpinBox" name="deadzone_y_counterweight"> | ||
| 126 | <property name="alignment"> | 100 | <property name="alignment"> |
| 127 | <set>Qt::AlignCenter</set> | 101 | <set>Qt::AlignCenter</set> |
| 128 | </property> | 102 | </property> |
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index 71afbc423..f83705544 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.cpp | |||
| @@ -305,6 +305,9 @@ void ConfigureRingController::EnableRingController() { | |||
| 305 | QMessageBox::warning(this, dialog_title, | 305 | QMessageBox::warning(this, dialog_title, |
| 306 | tr("The current mapped device doesn't have a ring attached")); | 306 | tr("The current mapped device doesn't have a ring attached")); |
| 307 | break; | 307 | break; |
| 308 | case Common::Input::DriverResult::InvalidHandle: | ||
| 309 | QMessageBox::warning(this, dialog_title, tr("The current mapped device is not connected")); | ||
| 310 | break; | ||
| 308 | default: | 311 | default: |
| 309 | QMessageBox::warning(this, dialog_title, | 312 | QMessageBox::warning(this, dialog_title, |
| 310 | tr("Unexpected driver result %1").arg(static_cast<int>(result))); | 313 | tr("Unexpected driver result %1").arg(static_cast<int>(result))); |
diff --git a/src/yuzu/qt_common.cpp b/src/yuzu/qt_common.cpp index 5d0fd7674..413402165 100644 --- a/src/yuzu/qt_common.cpp +++ b/src/yuzu/qt_common.cpp | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | #if !defined(WIN32) && !defined(__APPLE__) | 11 | #if !defined(WIN32) && !defined(__APPLE__) |
| 12 | #include <qpa/qplatformnativeinterface.h> | 12 | #include <qpa/qplatformnativeinterface.h> |
| 13 | #elif defined(__APPLE__) | ||
| 14 | #include <objc/message.h> | ||
| 13 | #endif | 15 | #endif |
| 14 | 16 | ||
| 15 | namespace QtCommon { | 17 | namespace QtCommon { |
| @@ -37,9 +39,12 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) | |||
| 37 | Core::Frontend::EmuWindow::WindowSystemInfo wsi; | 39 | Core::Frontend::EmuWindow::WindowSystemInfo wsi; |
| 38 | wsi.type = GetWindowSystemType(); | 40 | wsi.type = GetWindowSystemType(); |
| 39 | 41 | ||
| 42 | #if defined(WIN32) | ||
| 40 | // Our Win32 Qt external doesn't have the private API. | 43 | // Our Win32 Qt external doesn't have the private API. |
| 41 | #if defined(WIN32) || defined(__APPLE__) | 44 | wsi.render_surface = reinterpret_cast<void*>(window->winId()); |
| 42 | wsi.render_surface = window ? reinterpret_cast<void*>(window->winId()) : nullptr; | 45 | #elif defined(__APPLE__) |
| 46 | wsi.render_surface = reinterpret_cast<void* (*)(id, SEL)>(objc_msgSend)( | ||
| 47 | reinterpret_cast<id>(window->winId()), sel_registerName("layer")); | ||
| 43 | #else | 48 | #else |
| 44 | QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); | 49 | QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); |
| 45 | wsi.display_connection = pni->nativeResourceForWindow("display", window); | 50 | wsi.display_connection = pni->nativeResourceForWindow("display", window); |
diff --git a/src/yuzu/vk_device_info.cpp b/src/yuzu/vk_device_info.cpp index 7c26a3dc7..e1a0e6a2a 100644 --- a/src/yuzu/vk_device_info.cpp +++ b/src/yuzu/vk_device_info.cpp | |||
| @@ -26,7 +26,10 @@ Record::~Record() = default; | |||
| 26 | void PopulateRecords(std::vector<Record>& records, QWindow* window) try { | 26 | void PopulateRecords(std::vector<Record>& records, QWindow* window) try { |
| 27 | using namespace Vulkan; | 27 | using namespace Vulkan; |
| 28 | 28 | ||
| 29 | auto wsi = QtCommon::GetWindowSystemInfo(window); | 29 | // Create a test window with a Vulkan surface type for checking present modes. |
| 30 | QWindow test_window(window); | ||
| 31 | test_window.setSurfaceType(QWindow::VulkanSurface); | ||
| 32 | auto wsi = QtCommon::GetWindowSystemInfo(&test_window); | ||
| 30 | 33 | ||
| 31 | vk::InstanceDispatch dld; | 34 | vk::InstanceDispatch dld; |
| 32 | const auto library = OpenLibrary(); | 35 | const auto library = OpenLibrary(); |