diff options
-rw-r--r-- | src/common/fiber.cpp | 2 | ||||
-rw-r--r-- | src/core/file_sys/system_archive/ng_word.cpp | 4 | ||||
-rw-r--r-- | src/core/file_sys/system_archive/system_version.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/service/sockets/bsd.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/service/time/time.cpp | 14 | ||||
-rw-r--r-- | src/input_common/keyboard.cpp | 31 | ||||
-rw-r--r-- | src/input_common/mouse/mouse_input.cpp | 36 | ||||
-rw-r--r-- | src/input_common/mouse/mouse_input.h | 5 | ||||
-rw-r--r-- | src/input_common/mouse/mouse_poller.cpp | 20 | ||||
-rw-r--r-- | src/video_core/rasterizer_accelerated.cpp | 62 | ||||
-rw-r--r-- | src/video_core/rasterizer_accelerated.h | 25 | ||||
-rw-r--r-- | src/yuzu/bootmanager.cpp | 8 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 21 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 9 |
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 @@ namespace Common { -constexpr std::size_t default_stack_size = 256 * 1024; +constexpr std::size_t default_stack_size = 512 * 1024; struct Fiber::FiberImpl { 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 { constexpr std::size_t NUMBER_WORD_TXT_FILES = 0x10; // Should this archive replacement mysteriously not work on a future game, consider updating. -constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x19}; // 5.1.0 System Version +constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x20}; // 11.0.1 System Version constexpr std::array<u8, 30> WORD_TXT{ 0xFE, 0xFF, 0x00, 0x5E, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x62, 0x00, @@ -43,7 +43,7 @@ namespace NgWord2Data { constexpr std::size_t NUMBER_AC_NX_FILES = 0x10; // Should this archive replacement mysteriously not work on a future game, consider updating. -constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x15}; // 5.1.0 System Version +constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x1A}; // 11.0.1 System Version constexpr std::array<u8, 0x2C> AC_NX_DATA{ 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 { constexpr u8 VERSION_MAJOR = 11; constexpr u8 VERSION_MINOR = 0; -constexpr u8 VERSION_MICRO = 0; +constexpr u8 VERSION_MICRO = 1; -constexpr u8 REVISION_MAJOR = 5; +constexpr u8 REVISION_MAJOR = 1; constexpr u8 REVISION_MINOR = 0; constexpr char PLATFORM_STRING[] = "NX"; -constexpr char VERSION_HASH[] = "34197eba8810e2edd5e9dfcfbde7b340882e856d"; -constexpr char DISPLAY_VERSION[] = "11.0.0"; -constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.0-5.0"; +constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf"; +constexpr char DISPLAY_VERSION[] = "11.0.1"; +constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0"; } // namespace SystemVersionData 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) { } void BSD::PollWork::Response(Kernel::HLERequestContext& ctx) { - ctx.WriteBuffer(write_buffer); + if (write_buffer.size() > 0) { + ctx.WriteBuffer(write_buffer); + } IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); @@ -55,7 +57,9 @@ void BSD::AcceptWork::Execute(BSD* bsd) { } void BSD::AcceptWork::Response(Kernel::HLERequestContext& ctx) { - ctx.WriteBuffer(write_buffer); + if (write_buffer.size() > 0) { + ctx.WriteBuffer(write_buffer); + } IPC::ResponseBuilder rb{ctx, 5}; 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( const auto current_time_point{ time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)}; + clock_snapshot.steady_clock_time_point = current_time_point; + if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime( clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)}; result != RESULT_SUCCESS) { @@ -341,12 +343,18 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); - IPC::RequestParser rp{ctx}; - const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>(); - const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>(); + Clock::ClockSnapshot snapshot_a; + Clock::ClockSnapshot snapshot_b; + + const auto snapshot_a_data = ctx.ReadBuffer(0); + const auto snapshot_b_data = ctx.ReadBuffer(1); + + std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(Clock::ClockSnapshot)); + std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(Clock::ClockSnapshot)); Clock::TimeSpanType time_span_type{}; s64 span{}; + if (const ResultCode result{snapshot_a.steady_clock_time_point.GetSpanBetween( snapshot_b.steady_clock_time_point, span)}; 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 { class KeyButton final : public Input::ButtonDevice { public: - explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_) - : key_button_list(std::move(key_button_list_)) {} + explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_, bool toggle_) + : key_button_list(std::move(key_button_list_)), toggle(toggle_) {} ~KeyButton() override; bool GetStatus() const override { + if (toggle) { + return toggled_status.load(std::memory_order_relaxed); + } return status.load(); } + void ToggleButton() { + if (lock) { + return; + } + lock = true; + const bool old_toggle_status = toggled_status.load(); + toggled_status.store(!old_toggle_status); + } + + void UnlockButton() { + lock = false; + } + friend class KeyButtonList; private: std::shared_ptr<KeyButtonList> key_button_list; std::atomic<bool> status{false}; + std::atomic<bool> toggled_status{false}; + bool lock{false}; + const bool toggle; }; struct KeyButtonPair { @@ -51,6 +70,11 @@ public: for (const KeyButtonPair& pair : list) { if (pair.key_code == key_code) { pair.key_button->status.store(pressed); + if (pressed) { + pair.key_button->ToggleButton(); + } else { + pair.key_button->UnlockButton(); + } } } } @@ -75,7 +99,8 @@ KeyButton::~KeyButton() { std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) { const int key_code = params.Get("code", 0); - std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list); + const bool toggle = params.Get("toggle", false); + std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list, toggle); key_button_list->AddKeyButton(key_code, button.get()); return button; } 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() { configuring = false; } +bool Mouse::ToggleButton(std::size_t button_) { + if (button_ >= mouse_info.size()) { + return false; + } + const auto button = 1U << button_; + const bool button_state = (toggle_buttons & button) != 0; + const bool button_lock = (lock_buttons & button) != 0; + + if (button_lock) { + return button_state; + } + + lock_buttons |= static_cast<u16>(button); + + if (button_state) { + toggle_buttons &= static_cast<u16>(0xFF - button); + } else { + toggle_buttons |= static_cast<u16>(button); + } + + return !button_state; +} + +bool Mouse::UnlockButton(std::size_t button_) { + if (button_ >= mouse_info.size()) { + return false; + } + + const auto button = 1U << button_; + const bool button_state = (toggle_buttons & button) != 0; + + lock_buttons &= static_cast<u16>(0xFF - button); + + return button_state; +} + Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() { return mouse_queue; } 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: */ void ReleaseButton(MouseButton button_); + [[nodiscard]] bool ToggleButton(std::size_t button_); + [[nodiscard]] bool UnlockButton(std::size_t button_); + [[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue(); [[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const; @@ -94,6 +97,8 @@ private: }; u16 buttons{}; + u16 toggle_buttons{}; + u16 lock_buttons{}; std::thread update_thread; MouseButton last_button{MouseButton::Undefined}; 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 { class MouseButton final : public Input::ButtonDevice { public: - explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_) - : button(button_), mouse_input(mouse_input_) {} + explicit MouseButton(u32 button_, bool toggle_, MouseInput::Mouse* mouse_input_) + : button(button_), toggle(toggle_), mouse_input(mouse_input_) {} bool GetStatus() const override { - return mouse_input->GetMouseState(button).pressed; + const bool button_state = mouse_input->GetMouseState(button).pressed; + if (!toggle) { + return button_state; + } + + if (button_state) { + return mouse_input->ToggleButton(button); + } + return mouse_input->UnlockButton(button); } private: const u32 button; - const MouseInput::Mouse* mouse_input; + const bool toggle; + MouseInput::Mouse* mouse_input; }; MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_) @@ -32,8 +41,9 @@ MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_ std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create( const Common::ParamPackage& params) { const auto button_id = params.Get("button", 0); + const auto toggle = params.Get("toggle", false); - return std::make_unique<MouseButton>(button_id, mouse_input.get()); + return std::make_unique<MouseButton>(button_id, toggle, mouse_input.get()); } Common::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 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <mutex> - -#include <boost/icl/interval_map.hpp> -#include <boost/range/iterator_range.hpp> - #include "common/assert.h" #include "common/common_types.h" +#include "common/div_ceil.h" #include "core/memory.h" #include "video_core/rasterizer_accelerated.h" namespace VideoCore { -namespace { - -template <typename Map, typename Interval> -constexpr auto RangeFromInterval(Map& map, const Interval& interval) { - return boost::make_iterator_range(map.equal_range(interval)); -} - -} // Anonymous namespace - RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_) : cpu_memory{cpu_memory_} {} RasterizerAccelerated::~RasterizerAccelerated() = default; void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { - std::lock_guard lock{pages_mutex}; - const u64 page_start{addr >> Core::Memory::PAGE_BITS}; - const u64 page_end{(addr + size + Core::Memory::PAGE_SIZE - 1) >> Core::Memory::PAGE_BITS}; - - // Interval maps will erase segments if count reaches 0, so if delta is negative we have to - // subtract after iterating - const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end); - if (delta > 0) { - cached_pages.add({pages_interval, delta}); - } - - for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) { - const auto interval = pair.first & pages_interval; - const int count = pair.second; - - const VAddr interval_start_addr = boost::icl::first(interval) << Core::Memory::PAGE_BITS; - const VAddr interval_end_addr = boost::icl::last_next(interval) << Core::Memory::PAGE_BITS; - const u64 interval_size = interval_end_addr - interval_start_addr; - - if (delta > 0 && count == delta) { - cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, true); - } else if (delta < 0 && count == -delta) { - cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false); + const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE); + for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) { + auto& count = cached_pages.at(page >> 3).Count(page); + + if (delta > 0) { + ASSERT_MSG(count < UINT8_MAX, "Count may overflow!"); + } else if (delta < 0) { + ASSERT_MSG(count > 0, "Count may underflow!"); } else { - ASSERT(count >= 0); + ASSERT_MSG(true, "Delta must be non-zero!"); } - } - if (delta < 0) { - cached_pages.add({pages_interval, delta}); + // Adds or subtracts 1, as count is a unsigned 8-bit value + count += static_cast<u8>(delta); + + // Assume delta is either -1 or 1 + if (count == 0) { + cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS, + Core::Memory::PAGE_SIZE, false); + } else if (count == 1 && delta > 0) { + cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS, + Core::Memory::PAGE_SIZE, true); + } } } 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 @@ #pragma once -#include <mutex> - -#include <boost/icl/interval_map.hpp> +#include <array> +#include <atomic> #include "common/common_types.h" #include "video_core/rasterizer_interface.h" @@ -26,10 +25,24 @@ public: void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; private: - using CachedPageMap = boost::icl::interval_map<u64, int>; - CachedPageMap cached_pages; - std::mutex pages_mutex; + class CacheEntry final { + public: + CacheEntry() = default; + + std::atomic_uint8_t& Count(std::size_t page) { + return values[page & 7]; + } + + const std::atomic_uint8_t& Count(std::size_t page) const { + return values[page & 7]; + } + + private: + std::array<std::atomic_uint8_t, 8> values{}; + }; + static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); + std::array<CacheEntry, 0x800000> cached_pages; Core::Memory::Memory& cpu_memory; }; 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) { } void GRenderWindow::keyPressEvent(QKeyEvent* event) { - input_subsystem->GetKeyboard()->PressKey(event->key()); + if (!event->isAutoRepeat()) { + input_subsystem->GetKeyboard()->PressKey(event->key()); + } } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { - input_subsystem->GetKeyboard()->ReleaseKey(event->key()); + if (!event->isAutoRepeat()) { + input_subsystem->GetKeyboard()->ReleaseKey(event->key()); + } } MouseInput::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) { } if (param.Get("engine", "") == "keyboard") { - return GetKeyName(param.Get("code", 0)); + const QString button_str = GetKeyName(param.Get("code", 0)); + const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); + return QObject::tr("%1%2").arg(toggle, button_str); } if (param.Get("engine", "") == "gcpad") { @@ -157,7 +159,8 @@ QString ButtonToText(const Common::ParamPackage& param) { if (param.Get("engine", "") == "mouse") { if (param.Has("button")) { const QString button_str = QString::number(int(param.Get("button", 0))); - return QObject::tr("Click %1").arg(button_str); + const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); + return QObject::tr("%1Click %2").arg(toggle, button_str); } return GetKeyName(param.Get("code", 0)); } @@ -301,6 +304,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i buttons_param[button_id].Clear(); button_map[button_id]->setText(tr("[not set]")); }); + context_menu.addAction(tr("Toggle button"), [&] { + const bool toggle_value = !buttons_param[button_id].Get("toggle", false); + buttons_param[button_id].Set("toggle", toggle_value); + button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + }); context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); }); @@ -413,6 +421,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i analogs_param[analog_id].Set("modifier", ""); analog_map_modifier_button[analog_id]->setText(tr("[not set]")); }); + context_menu.addAction(tr("Toggle button"), [&] { + Common::ParamPackage modifier_param = + Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")}; + const bool toggle_value = !modifier_param.Get("toggle", false); + modifier_param.Set("toggle", toggle_value); + analogs_param[analog_id].Set("modifier", modifier_param.Serialize()); + analog_map_modifier_button[analog_id]->setText( + ButtonToText(modifier_param)); + }); context_menu.exec( analog_map_modifier_button[analog_id]->mapToGlobal(menu_location)); }); 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 #include <QPushButton> #include <QShortcut> #include <QStatusBar> +#include <QString> #include <QSysInfo> #include <QUrl> #include <QtConcurrent/QtConcurrent> @@ -3061,6 +3062,14 @@ int main(int argc, char* argv[]) { chdir(bin_path.c_str()); #endif +#ifdef __linux__ + // Set the DISPLAY variable in order to open web browsers + // TODO (lat9nq): Find a better solution for AppImages to start external applications + if (QString::fromLocal8Bit(qgetenv("DISPLAY")).isEmpty()) { + qputenv("DISPLAY", ":0"); + } +#endif + // Enables the core to make the qt created contexts current on std::threads QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); QApplication app(argc, argv); |