summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/fiber.cpp2
-rw-r--r--src/core/file_sys/system_archive/ng_word.cpp4
-rw-r--r--src/core/file_sys/system_archive/system_version.cpp10
-rw-r--r--src/core/hle/service/sockets/bsd.cpp8
-rw-r--r--src/core/hle/service/time/time.cpp14
-rw-r--r--src/input_common/keyboard.cpp31
-rw-r--r--src/input_common/mouse/mouse_input.cpp36
-rw-r--r--src/input_common/mouse/mouse_input.h5
-rw-r--r--src/input_common/mouse/mouse_poller.cpp20
-rw-r--r--src/video_core/rasterizer_accelerated.cpp62
-rw-r--r--src/video_core/rasterizer_accelerated.h25
-rw-r--r--src/yuzu/bootmanager.cpp8
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp21
-rw-r--r--src/yuzu/main.cpp9
14 files changed, 183 insertions, 72 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 39532ff58..62010d762 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -11,7 +11,7 @@
11 11
12namespace Common { 12namespace Common {
13 13
14constexpr std::size_t default_stack_size = 256 * 1024; 14constexpr std::size_t default_stack_size = 512 * 1024;
15 15
16struct Fiber::FiberImpl { 16struct Fiber::FiberImpl {
17 FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {} 17 FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {}
diff --git a/src/core/file_sys/system_archive/ng_word.cpp b/src/core/file_sys/system_archive/ng_word.cpp
index 100d3c5db..8d86d563a 100644
--- a/src/core/file_sys/system_archive/ng_word.cpp
+++ b/src/core/file_sys/system_archive/ng_word.cpp
@@ -14,7 +14,7 @@ namespace NgWord1Data {
14constexpr std::size_t NUMBER_WORD_TXT_FILES = 0x10; 14constexpr std::size_t NUMBER_WORD_TXT_FILES = 0x10;
15 15
16// Should this archive replacement mysteriously not work on a future game, consider updating. 16// Should this archive replacement mysteriously not work on a future game, consider updating.
17constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x19}; // 5.1.0 System Version 17constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x20}; // 11.0.1 System Version
18 18
19constexpr std::array<u8, 30> WORD_TXT{ 19constexpr std::array<u8, 30> WORD_TXT{
20 0xFE, 0xFF, 0x00, 0x5E, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x62, 0x00, 20 0xFE, 0xFF, 0x00, 0x5E, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x62, 0x00,
@@ -43,7 +43,7 @@ namespace NgWord2Data {
43constexpr std::size_t NUMBER_AC_NX_FILES = 0x10; 43constexpr std::size_t NUMBER_AC_NX_FILES = 0x10;
44 44
45// Should this archive replacement mysteriously not work on a future game, consider updating. 45// Should this archive replacement mysteriously not work on a future game, consider updating.
46constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x15}; // 5.1.0 System Version 46constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x1A}; // 11.0.1 System Version
47 47
48constexpr std::array<u8, 0x2C> AC_NX_DATA{ 48constexpr std::array<u8, 0x2C> AC_NX_DATA{
49 0x1F, 0x8B, 0x08, 0x08, 0xD5, 0x2C, 0x09, 0x5C, 0x04, 0x00, 0x61, 0x63, 0x72, 0x61, 0x77, 49 0x1F, 0x8B, 0x08, 0x08, 0xD5, 0x2C, 0x09, 0x5C, 0x04, 0x00, 0x61, 0x63, 0x72, 0x61, 0x77,
diff --git a/src/core/file_sys/system_archive/system_version.cpp b/src/core/file_sys/system_archive/system_version.cpp
index 7bfbc9a67..54704105b 100644
--- a/src/core/file_sys/system_archive/system_version.cpp
+++ b/src/core/file_sys/system_archive/system_version.cpp
@@ -14,15 +14,15 @@ namespace SystemVersionData {
14 14
15constexpr u8 VERSION_MAJOR = 11; 15constexpr u8 VERSION_MAJOR = 11;
16constexpr u8 VERSION_MINOR = 0; 16constexpr u8 VERSION_MINOR = 0;
17constexpr u8 VERSION_MICRO = 0; 17constexpr u8 VERSION_MICRO = 1;
18 18
19constexpr u8 REVISION_MAJOR = 5; 19constexpr u8 REVISION_MAJOR = 1;
20constexpr u8 REVISION_MINOR = 0; 20constexpr u8 REVISION_MINOR = 0;
21 21
22constexpr char PLATFORM_STRING[] = "NX"; 22constexpr char PLATFORM_STRING[] = "NX";
23constexpr char VERSION_HASH[] = "34197eba8810e2edd5e9dfcfbde7b340882e856d"; 23constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
24constexpr char DISPLAY_VERSION[] = "11.0.0"; 24constexpr char DISPLAY_VERSION[] = "11.0.1";
25constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.0-5.0"; 25constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
26 26
27} // namespace SystemVersionData 27} // namespace SystemVersionData
28 28
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 78e9cd708..5fcd91f68 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -42,7 +42,9 @@ void BSD::PollWork::Execute(BSD* bsd) {
42} 42}
43 43
44void BSD::PollWork::Response(Kernel::HLERequestContext& ctx) { 44void BSD::PollWork::Response(Kernel::HLERequestContext& ctx) {
45 ctx.WriteBuffer(write_buffer); 45 if (write_buffer.size() > 0) {
46 ctx.WriteBuffer(write_buffer);
47 }
46 48
47 IPC::ResponseBuilder rb{ctx, 4}; 49 IPC::ResponseBuilder rb{ctx, 4};
48 rb.Push(RESULT_SUCCESS); 50 rb.Push(RESULT_SUCCESS);
@@ -55,7 +57,9 @@ void BSD::AcceptWork::Execute(BSD* bsd) {
55} 57}
56 58
57void BSD::AcceptWork::Response(Kernel::HLERequestContext& ctx) { 59void BSD::AcceptWork::Response(Kernel::HLERequestContext& ctx) {
58 ctx.WriteBuffer(write_buffer); 60 if (write_buffer.size() > 0) {
61 ctx.WriteBuffer(write_buffer);
62 }
59 63
60 IPC::ResponseBuilder rb{ctx, 5}; 64 IPC::ResponseBuilder rb{ctx, 5};
61 rb.Push(RESULT_SUCCESS); 65 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 18629dd7e..78543688f 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -140,6 +140,8 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
140 140
141 const auto current_time_point{ 141 const auto current_time_point{
142 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)}; 142 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
143 clock_snapshot.steady_clock_time_point = current_time_point;
144
143 if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime( 145 if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime(
144 clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)}; 146 clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)};
145 result != RESULT_SUCCESS) { 147 result != RESULT_SUCCESS) {
@@ -341,12 +343,18 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
341void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) { 343void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) {
342 LOG_DEBUG(Service_Time, "called"); 344 LOG_DEBUG(Service_Time, "called");
343 345
344 IPC::RequestParser rp{ctx}; 346 Clock::ClockSnapshot snapshot_a;
345 const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>(); 347 Clock::ClockSnapshot snapshot_b;
346 const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>(); 348
349 const auto snapshot_a_data = ctx.ReadBuffer(0);
350 const auto snapshot_b_data = ctx.ReadBuffer(1);
351
352 std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(Clock::ClockSnapshot));
353 std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(Clock::ClockSnapshot));
347 354
348 Clock::TimeSpanType time_span_type{}; 355 Clock::TimeSpanType time_span_type{};
349 s64 span{}; 356 s64 span{};
357
350 if (const ResultCode result{snapshot_a.steady_clock_time_point.GetSpanBetween( 358 if (const ResultCode result{snapshot_a.steady_clock_time_point.GetSpanBetween(
351 snapshot_b.steady_clock_time_point, span)}; 359 snapshot_b.steady_clock_time_point, span)};
352 result != RESULT_SUCCESS) { 360 result != RESULT_SUCCESS) {
diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp
index 24a6f7a33..c467ff4c5 100644
--- a/src/input_common/keyboard.cpp
+++ b/src/input_common/keyboard.cpp
@@ -12,20 +12,39 @@ namespace InputCommon {
12 12
13class KeyButton final : public Input::ButtonDevice { 13class KeyButton final : public Input::ButtonDevice {
14public: 14public:
15 explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_) 15 explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_, bool toggle_)
16 : key_button_list(std::move(key_button_list_)) {} 16 : key_button_list(std::move(key_button_list_)), toggle(toggle_) {}
17 17
18 ~KeyButton() override; 18 ~KeyButton() override;
19 19
20 bool GetStatus() const override { 20 bool GetStatus() const override {
21 if (toggle) {
22 return toggled_status.load(std::memory_order_relaxed);
23 }
21 return status.load(); 24 return status.load();
22 } 25 }
23 26
27 void ToggleButton() {
28 if (lock) {
29 return;
30 }
31 lock = true;
32 const bool old_toggle_status = toggled_status.load();
33 toggled_status.store(!old_toggle_status);
34 }
35
36 void UnlockButton() {
37 lock = false;
38 }
39
24 friend class KeyButtonList; 40 friend class KeyButtonList;
25 41
26private: 42private:
27 std::shared_ptr<KeyButtonList> key_button_list; 43 std::shared_ptr<KeyButtonList> key_button_list;
28 std::atomic<bool> status{false}; 44 std::atomic<bool> status{false};
45 std::atomic<bool> toggled_status{false};
46 bool lock{false};
47 const bool toggle;
29}; 48};
30 49
31struct KeyButtonPair { 50struct KeyButtonPair {
@@ -51,6 +70,11 @@ public:
51 for (const KeyButtonPair& pair : list) { 70 for (const KeyButtonPair& pair : list) {
52 if (pair.key_code == key_code) { 71 if (pair.key_code == key_code) {
53 pair.key_button->status.store(pressed); 72 pair.key_button->status.store(pressed);
73 if (pressed) {
74 pair.key_button->ToggleButton();
75 } else {
76 pair.key_button->UnlockButton();
77 }
54 } 78 }
55 } 79 }
56 } 80 }
@@ -75,7 +99,8 @@ KeyButton::~KeyButton() {
75 99
76std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) { 100std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
77 const int key_code = params.Get("code", 0); 101 const int key_code = params.Get("code", 0);
78 std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list); 102 const bool toggle = params.Get("toggle", false);
103 std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list, toggle);
79 key_button_list->AddKeyButton(key_code, button.get()); 104 key_button_list->AddKeyButton(key_code, button.get());
80 return button; 105 return button;
81} 106}
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index d81e790ee..329e416c7 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -162,6 +162,42 @@ void Mouse::EndConfiguration() {
162 configuring = false; 162 configuring = false;
163} 163}
164 164
165bool Mouse::ToggleButton(std::size_t button_) {
166 if (button_ >= mouse_info.size()) {
167 return false;
168 }
169 const auto button = 1U << button_;
170 const bool button_state = (toggle_buttons & button) != 0;
171 const bool button_lock = (lock_buttons & button) != 0;
172
173 if (button_lock) {
174 return button_state;
175 }
176
177 lock_buttons |= static_cast<u16>(button);
178
179 if (button_state) {
180 toggle_buttons &= static_cast<u16>(0xFF - button);
181 } else {
182 toggle_buttons |= static_cast<u16>(button);
183 }
184
185 return !button_state;
186}
187
188bool Mouse::UnlockButton(std::size_t button_) {
189 if (button_ >= mouse_info.size()) {
190 return false;
191 }
192
193 const auto button = 1U << button_;
194 const bool button_state = (toggle_buttons & button) != 0;
195
196 lock_buttons &= static_cast<u16>(0xFF - button);
197
198 return button_state;
199}
200
165Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() { 201Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() {
166 return mouse_queue; 202 return mouse_queue;
167} 203}
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h
index 3622fe080..750d9b011 100644
--- a/src/input_common/mouse/mouse_input.h
+++ b/src/input_common/mouse/mouse_input.h
@@ -69,6 +69,9 @@ public:
69 */ 69 */
70 void ReleaseButton(MouseButton button_); 70 void ReleaseButton(MouseButton button_);
71 71
72 [[nodiscard]] bool ToggleButton(std::size_t button_);
73 [[nodiscard]] bool UnlockButton(std::size_t button_);
74
72 [[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue(); 75 [[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue();
73 [[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const; 76 [[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const;
74 77
@@ -94,6 +97,8 @@ private:
94 }; 97 };
95 98
96 u16 buttons{}; 99 u16 buttons{};
100 u16 toggle_buttons{};
101 u16 lock_buttons{};
97 std::thread update_thread; 102 std::thread update_thread;
98 MouseButton last_button{MouseButton::Undefined}; 103 MouseButton last_button{MouseButton::Undefined};
99 std::array<MouseInfo, 7> mouse_info; 104 std::array<MouseInfo, 7> mouse_info;
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index bb56787ee..0e1db54fb 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -14,16 +14,25 @@ namespace InputCommon {
14 14
15class MouseButton final : public Input::ButtonDevice { 15class MouseButton final : public Input::ButtonDevice {
16public: 16public:
17 explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_) 17 explicit MouseButton(u32 button_, bool toggle_, MouseInput::Mouse* mouse_input_)
18 : button(button_), mouse_input(mouse_input_) {} 18 : button(button_), toggle(toggle_), mouse_input(mouse_input_) {}
19 19
20 bool GetStatus() const override { 20 bool GetStatus() const override {
21 return mouse_input->GetMouseState(button).pressed; 21 const bool button_state = mouse_input->GetMouseState(button).pressed;
22 if (!toggle) {
23 return button_state;
24 }
25
26 if (button_state) {
27 return mouse_input->ToggleButton(button);
28 }
29 return mouse_input->UnlockButton(button);
22 } 30 }
23 31
24private: 32private:
25 const u32 button; 33 const u32 button;
26 const MouseInput::Mouse* mouse_input; 34 const bool toggle;
35 MouseInput::Mouse* mouse_input;
27}; 36};
28 37
29MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_) 38MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
@@ -32,8 +41,9 @@ MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_
32std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create( 41std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
33 const Common::ParamPackage& params) { 42 const Common::ParamPackage& params) {
34 const auto button_id = params.Get("button", 0); 43 const auto button_id = params.Get("button", 0);
44 const auto toggle = params.Get("toggle", false);
35 45
36 return std::make_unique<MouseButton>(button_id, mouse_input.get()); 46 return std::make_unique<MouseButton>(button_id, toggle, mouse_input.get());
37} 47}
38 48
39Common::ParamPackage MouseButtonFactory::GetNextInput() const { 49Common::ParamPackage MouseButtonFactory::GetNextInput() const {
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index 53622ca05..62d84c0f8 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -2,63 +2,43 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <mutex>
6
7#include <boost/icl/interval_map.hpp>
8#include <boost/range/iterator_range.hpp>
9
10#include "common/assert.h" 5#include "common/assert.h"
11#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/div_ceil.h"
12#include "core/memory.h" 8#include "core/memory.h"
13#include "video_core/rasterizer_accelerated.h" 9#include "video_core/rasterizer_accelerated.h"
14 10
15namespace VideoCore { 11namespace VideoCore {
16 12
17namespace {
18
19template <typename Map, typename Interval>
20constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
21 return boost::make_iterator_range(map.equal_range(interval));
22}
23
24} // Anonymous namespace
25
26RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_) 13RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_)
27 : cpu_memory{cpu_memory_} {} 14 : cpu_memory{cpu_memory_} {}
28 15
29RasterizerAccelerated::~RasterizerAccelerated() = default; 16RasterizerAccelerated::~RasterizerAccelerated() = default;
30 17
31void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 18void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
32 std::lock_guard lock{pages_mutex}; 19 const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE);
33 const u64 page_start{addr >> Core::Memory::PAGE_BITS}; 20 for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) {
34 const u64 page_end{(addr + size + Core::Memory::PAGE_SIZE - 1) >> Core::Memory::PAGE_BITS}; 21 auto& count = cached_pages.at(page >> 3).Count(page);
35 22
36 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to 23 if (delta > 0) {
37 // subtract after iterating 24 ASSERT_MSG(count < UINT8_MAX, "Count may overflow!");
38 const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end); 25 } else if (delta < 0) {
39 if (delta > 0) { 26 ASSERT_MSG(count > 0, "Count may underflow!");
40 cached_pages.add({pages_interval, delta});
41 }
42
43 for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
44 const auto interval = pair.first & pages_interval;
45 const int count = pair.second;
46
47 const VAddr interval_start_addr = boost::icl::first(interval) << Core::Memory::PAGE_BITS;
48 const VAddr interval_end_addr = boost::icl::last_next(interval) << Core::Memory::PAGE_BITS;
49 const u64 interval_size = interval_end_addr - interval_start_addr;
50
51 if (delta > 0 && count == delta) {
52 cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
53 } else if (delta < 0 && count == -delta) {
54 cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
55 } else { 27 } else {
56 ASSERT(count >= 0); 28 ASSERT_MSG(true, "Delta must be non-zero!");
57 } 29 }
58 }
59 30
60 if (delta < 0) { 31 // Adds or subtracts 1, as count is a unsigned 8-bit value
61 cached_pages.add({pages_interval, delta}); 32 count += static_cast<u8>(delta);
33
34 // Assume delta is either -1 or 1
35 if (count == 0) {
36 cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS,
37 Core::Memory::PAGE_SIZE, false);
38 } else if (count == 1 && delta > 0) {
39 cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS,
40 Core::Memory::PAGE_SIZE, true);
41 }
62 } 42 }
63} 43}
64 44
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index 91866d7dd..9227a4adc 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -4,9 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <mutex> 7#include <array>
8 8#include <atomic>
9#include <boost/icl/interval_map.hpp>
10 9
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "video_core/rasterizer_interface.h" 11#include "video_core/rasterizer_interface.h"
@@ -26,10 +25,24 @@ public:
26 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; 25 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
27 26
28private: 27private:
29 using CachedPageMap = boost::icl::interval_map<u64, int>; 28 class CacheEntry final {
30 CachedPageMap cached_pages; 29 public:
31 std::mutex pages_mutex; 30 CacheEntry() = default;
31
32 std::atomic_uint8_t& Count(std::size_t page) {
33 return values[page & 7];
34 }
35
36 const std::atomic_uint8_t& Count(std::size_t page) const {
37 return values[page & 7];
38 }
39
40 private:
41 std::array<std::atomic_uint8_t, 8> values{};
42 };
43 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
32 44
45 std::array<CacheEntry, 0x800000> cached_pages;
33 Core::Memory::Memory& cpu_memory; 46 Core::Memory::Memory& cpu_memory;
34}; 47};
35 48
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index ae49cbb45..15c09e0ad 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -376,11 +376,15 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
376} 376}
377 377
378void GRenderWindow::keyPressEvent(QKeyEvent* event) { 378void GRenderWindow::keyPressEvent(QKeyEvent* event) {
379 input_subsystem->GetKeyboard()->PressKey(event->key()); 379 if (!event->isAutoRepeat()) {
380 input_subsystem->GetKeyboard()->PressKey(event->key());
381 }
380} 382}
381 383
382void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { 384void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
383 input_subsystem->GetKeyboard()->ReleaseKey(event->key()); 385 if (!event->isAutoRepeat()) {
386 input_subsystem->GetKeyboard()->ReleaseKey(event->key());
387 }
384} 388}
385 389
386MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) { 390MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index bc572d319..c9318c562 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -105,7 +105,9 @@ QString ButtonToText(const Common::ParamPackage& param) {
105 } 105 }
106 106
107 if (param.Get("engine", "") == "keyboard") { 107 if (param.Get("engine", "") == "keyboard") {
108 return GetKeyName(param.Get("code", 0)); 108 const QString button_str = GetKeyName(param.Get("code", 0));
109 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
110 return QObject::tr("%1%2").arg(toggle, button_str);
109 } 111 }
110 112
111 if (param.Get("engine", "") == "gcpad") { 113 if (param.Get("engine", "") == "gcpad") {
@@ -157,7 +159,8 @@ QString ButtonToText(const Common::ParamPackage& param) {
157 if (param.Get("engine", "") == "mouse") { 159 if (param.Get("engine", "") == "mouse") {
158 if (param.Has("button")) { 160 if (param.Has("button")) {
159 const QString button_str = QString::number(int(param.Get("button", 0))); 161 const QString button_str = QString::number(int(param.Get("button", 0)));
160 return QObject::tr("Click %1").arg(button_str); 162 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
163 return QObject::tr("%1Click %2").arg(toggle, button_str);
161 } 164 }
162 return GetKeyName(param.Get("code", 0)); 165 return GetKeyName(param.Get("code", 0));
163 } 166 }
@@ -301,6 +304,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
301 buttons_param[button_id].Clear(); 304 buttons_param[button_id].Clear();
302 button_map[button_id]->setText(tr("[not set]")); 305 button_map[button_id]->setText(tr("[not set]"));
303 }); 306 });
307 context_menu.addAction(tr("Toggle button"), [&] {
308 const bool toggle_value = !buttons_param[button_id].Get("toggle", false);
309 buttons_param[button_id].Set("toggle", toggle_value);
310 button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
311 });
304 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); 312 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
305 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); 313 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
306 }); 314 });
@@ -413,6 +421,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
413 analogs_param[analog_id].Set("modifier", ""); 421 analogs_param[analog_id].Set("modifier", "");
414 analog_map_modifier_button[analog_id]->setText(tr("[not set]")); 422 analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
415 }); 423 });
424 context_menu.addAction(tr("Toggle button"), [&] {
425 Common::ParamPackage modifier_param =
426 Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")};
427 const bool toggle_value = !modifier_param.Get("toggle", false);
428 modifier_param.Set("toggle", toggle_value);
429 analogs_param[analog_id].Set("modifier", modifier_param.Serialize());
430 analog_map_modifier_button[analog_id]->setText(
431 ButtonToText(modifier_param));
432 });
416 context_menu.exec( 433 context_menu.exec(
417 analog_map_modifier_button[analog_id]->mapToGlobal(menu_location)); 434 analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
418 }); 435 });
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 56d892a31..24bfa4d34 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -60,6 +60,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
60#include <QPushButton> 60#include <QPushButton>
61#include <QShortcut> 61#include <QShortcut>
62#include <QStatusBar> 62#include <QStatusBar>
63#include <QString>
63#include <QSysInfo> 64#include <QSysInfo>
64#include <QUrl> 65#include <QUrl>
65#include <QtConcurrent/QtConcurrent> 66#include <QtConcurrent/QtConcurrent>
@@ -3061,6 +3062,14 @@ int main(int argc, char* argv[]) {
3061 chdir(bin_path.c_str()); 3062 chdir(bin_path.c_str());
3062#endif 3063#endif
3063 3064
3065#ifdef __linux__
3066 // Set the DISPLAY variable in order to open web browsers
3067 // TODO (lat9nq): Find a better solution for AppImages to start external applications
3068 if (QString::fromLocal8Bit(qgetenv("DISPLAY")).isEmpty()) {
3069 qputenv("DISPLAY", ":0");
3070 }
3071#endif
3072
3064 // Enables the core to make the qt created contexts current on std::threads 3073 // Enables the core to make the qt created contexts current on std::threads
3065 QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); 3074 QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
3066 QApplication app(argc, argv); 3075 QApplication app(argc, argv);