diff options
Diffstat (limited to 'src/yuzu')
41 files changed, 604 insertions, 323 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 2ee21f751..242867a4f 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -30,6 +30,8 @@ add_executable(yuzu applets/qt_web_browser_scripts.h bootmanager.cpp bootmanager.h + check_vulkan.cpp + check_vulkan.h compatdb.ui compatibility_list.cpp compatibility_list.h @@ -187,7 +189,7 @@ if (ENABLE_QT_TRANSLATION) # Update source TS file if enabled if (GENERATE_QT_TRANSLATION) get_target_property(SRCS yuzu SOURCES) - qt5_create_translation(QM_FILES + qt_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts @@ -203,7 +205,7 @@ if (ENABLE_QT_TRANSLATION) list(REMOVE_ITEM LANGUAGES_TS ${YUZU_QT_LANGUAGES}/en.ts) # Compile TS files to QM files - qt5_add_translation(LANGUAGES_QM ${LANGUAGES_TS}) + qt_add_translation(LANGUAGES_QM ${LANGUAGES_TS}) # Build a QRC file from the QM file list set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc) @@ -215,7 +217,7 @@ if (ENABLE_QT_TRANSLATION) file(APPEND ${LANGUAGES_QRC} "</qresource></RCC>") # Add the QRC file to package in all QM files - qt5_add_resources(LANGUAGES ${LANGUAGES_QRC}) + qt_add_resources(LANGUAGES ${LANGUAGES_QRC}) else() set(LANGUAGES) endif() @@ -236,18 +238,23 @@ if (APPLE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) elseif(WIN32) # compile as a win32 gui application instead of a console application - target_link_libraries(yuzu PRIVATE Qt5::WinMain) + if (QT_VERSION VERSION_GREATER 6) + target_link_libraries(yuzu PRIVATE Qt6::EntryPointPrivate) + else() + target_link_libraries(yuzu PRIVATE Qt5::WinMain) + endif() if(MSVC) + target_link_libraries(yuzu PRIVATE version.lib) set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") elseif(MINGW) - set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "-mwindows") + set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "-Wl,--subsystem,windows") endif() endif() create_target_directory_groups(yuzu) target_link_libraries(yuzu PRIVATE common core input_common video_core) -target_link_libraries(yuzu PRIVATE Boost::boost glad Qt5::Widgets) +target_link_libraries(yuzu PRIVATE Boost::boost glad Qt::Widgets) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) @@ -255,7 +262,7 @@ if (NOT WIN32) target_include_directories(yuzu PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - target_link_libraries(yuzu PRIVATE Qt5::DBus) + target_link_libraries(yuzu PRIVATE Qt::DBus) endif() target_compile_definitions(yuzu PRIVATE @@ -291,7 +298,7 @@ if (USE_DISCORD_PRESENCE) endif() if (YUZU_USE_QT_WEB_ENGINE) - target_link_libraries(yuzu PRIVATE Qt5::WebEngineCore Qt5::WebEngineWidgets) + target_link_libraries(yuzu PRIVATE Qt::WebEngineCore Qt::WebEngineWidgets) target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE) endif () @@ -319,3 +326,7 @@ endif() if (NOT APPLE) target_compile_definitions(yuzu PRIVATE HAS_OPENGL) endif() + +if (ARCHITECTURE_x86_64) + target_link_libraries(yuzu PRIVATE dynarmic) +endif() diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index cbcef7b45..eeff54359 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp @@ -19,7 +19,11 @@ AboutDialog::AboutDialog(QWidget* parent) const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; ui->setupUi(this); - ui->labelLogo->setPixmap(QIcon::fromTheme(QStringLiteral("yuzu")).pixmap(200)); + // Try and request the icon from Qt theme (Linux?) + const QIcon yuzu_logo = QIcon::fromTheme(QStringLiteral("org.yuzu_emu.yuzu")); + if (!yuzu_logo.isNull()) { + ui->labelLogo->setPixmap(yuzu_logo.pixmap(200)); + } ui->labelBuildInfo->setText( ui->labelBuildInfo->text().arg(QString::fromStdString(yuzu_build_version), QString::fromUtf8(Common::g_build_date).left(10))); diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index 2f7ddc7f3..1dd7b74bf 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui @@ -26,8 +26,20 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="maximumSize"> + <size> + <width>200</width> + <height>200</height> + </size> + </property> <property name="text"> - <string><html><head/><body><p><img src=":/icons/yuzu.png"/></p></body></html></string> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../../dist/qt_themes/default/default.qrc">:/icons/default/256x256/yuzu.png</pixmap> + </property> + <property name="scaledContents"> + <bool>true</bool> </property> </widget> </item> @@ -152,7 +164,7 @@ p, li { white-space: pre-wrap; } </layout> </widget> <resources> - <include location="../../dist/icons/icons.qrc"/> + <include location="../../dist/qt_themes_default/default/default.qrc"/> </resources> <connections> <connection> diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index c924cb0cb..8be311fcb 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -631,7 +631,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { switch (max_supported_players) { case 0: default: - UNREACHABLE(); + ASSERT(false); return; case 1: ui->widgetSpacer->hide(); diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index d3cf0b43b..e8b217d90 100644 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp @@ -411,11 +411,11 @@ void QtSoftwareKeyboardDialog::ShowTextCheckDialog( break; } - auto text = ui->topOSK->currentIndex() == 1 - ? ui->text_edit_osk->toPlainText().toStdU16String() - : ui->line_edit_osk->text().toStdU16String(); + const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText() + : ui->line_edit_osk->text(); + auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size()); - emit SubmitNormalText(SwkbdResult::Ok, std::move(text), true); + emit SubmitNormalText(SwkbdResult::Ok, std::move(text_str), true); break; } } @@ -562,7 +562,7 @@ void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { return; } - InlineTextInsertString(entered_text.toStdU16String()); + InlineTextInsertString(Common::U16StringFromBuffer(entered_text.utf16(), entered_text.size())); } void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { @@ -1119,11 +1119,11 @@ void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) } if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { - auto text = ui->topOSK->currentIndex() == 1 - ? ui->text_edit_osk->toPlainText().toStdU16String() - : ui->line_edit_osk->text().toStdU16String(); + const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText() + : ui->line_edit_osk->text(); + auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size()); - emit SubmitNormalText(SwkbdResult::Ok, std::move(text)); + emit SubmitNormalText(SwkbdResult::Ok, std::move(text_str)); return; } @@ -1189,7 +1189,8 @@ void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) return; } - InlineTextInsertString(button->text().toStdU16String()); + const auto button_text = button->text(); + InlineTextInsertString(Common::U16StringFromBuffer(button_text.utf16(), button_text.size())); // Revert the keyboard to lowercase if the shift key is active. if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { @@ -1282,11 +1283,11 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(Core::HID::NpadButton button if (is_inline) { emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); } else { - auto text = ui->topOSK->currentIndex() == 1 - ? ui->text_edit_osk->toPlainText().toStdU16String() - : ui->line_edit_osk->text().toStdU16String(); + const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText() + : ui->line_edit_osk->text(); + auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size()); - emit SubmitNormalText(SwkbdResult::Cancel, std::move(text)); + emit SubmitNormalText(SwkbdResult::Cancel, std::move(text_str)); } break; case Core::HID::NpadButton::Y: diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index a1b819ae0..cbe4e2daa 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -50,6 +50,7 @@ void EmuThread::run() { auto& gpu = system.GPU(); auto stop_token = stop_source.get_token(); + bool debugger_should_start = system.DebuggerEnabled(); system.RegisterHostThread(); @@ -89,6 +90,12 @@ void EmuThread::run() { this->SetRunning(false); emit ErrorThrown(result, system.GetStatusDetails()); } + + if (debugger_should_start) { + system.InitializeDebugger(); + debugger_should_start = false; + } + running_wait.Wait(); result = system.Pause(); if (result != Core::SystemResultStatus::Success) { @@ -102,11 +109,9 @@ void EmuThread::run() { was_active = true; emit DebugModeEntered(); } - } else if (exec_step) { - UNIMPLEMENTED(); } else { std::unique_lock lock{running_mutex}; - running_cv.wait(lock, stop_token, [this] { return IsRunning() || exec_step; }); + running_cv.wait(lock, stop_token, [this] { return IsRunning(); }); } } @@ -122,7 +127,7 @@ void EmuThread::run() { class OpenGLSharedContext : public Core::Frontend::GraphicsContext { public: /// Create the original context that should be shared from - explicit OpenGLSharedContext(QSurface* surface) : surface(surface) { + explicit OpenGLSharedContext(QSurface* surface_) : surface{surface_} { QSurfaceFormat format; format.setVersion(4, 6); format.setProfile(QSurfaceFormat::CompatibilityProfile); @@ -359,9 +364,9 @@ void GRenderWindow::RestoreGeometry() { QWidget::restoreGeometry(geometry); } -void GRenderWindow::restoreGeometry(const QByteArray& geometry) { +void GRenderWindow::restoreGeometry(const QByteArray& geometry_) { // Make sure users of this class don't need to deal with backing up the geometry themselves - QWidget::restoreGeometry(geometry); + QWidget::restoreGeometry(geometry_); BackupGeometry(); } @@ -747,7 +752,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y); if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { - QCursor::setPos(mapToGlobal({center_x, center_y})); + QCursor::setPos(mapToGlobal(QPoint{center_x, center_y})); } emit MouseActivity(); @@ -772,65 +777,25 @@ void GRenderWindow::wheelEvent(QWheelEvent* event) { void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); for (const auto& touch_point : touch_points) { - if (!TouchUpdate(touch_point)) { - TouchStart(touch_point); - } + const auto [x, y] = ScaleTouch(touch_point.pos()); + const auto [touch_x, touch_y] = MapToTouchScreen(x, y); + input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, touch_point.id()); } } void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); + input_subsystem->GetTouchScreen()->ClearActiveFlag(); for (const auto& touch_point : touch_points) { - if (!TouchUpdate(touch_point)) { - TouchStart(touch_point); - } - } - // Release all inactive points - for (std::size_t id = 0; id < touch_ids.size(); ++id) { - if (!TouchExist(touch_ids[id], touch_points)) { - touch_ids[id] = 0; - input_subsystem->GetTouchScreen()->TouchReleased(id); - } + const auto [x, y] = ScaleTouch(touch_point.pos()); + const auto [touch_x, touch_y] = MapToTouchScreen(x, y); + input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, touch_point.id()); } + input_subsystem->GetTouchScreen()->ReleaseInactiveTouch(); } void GRenderWindow::TouchEndEvent() { - for (std::size_t id = 0; id < touch_ids.size(); ++id) { - if (touch_ids[id] != 0) { - touch_ids[id] = 0; - input_subsystem->GetTouchScreen()->TouchReleased(id); - } - } -} - -void GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) { - for (std::size_t id = 0; id < touch_ids.size(); ++id) { - if (touch_ids[id] == 0) { - touch_ids[id] = touch_point.id() + 1; - const auto [x, y] = ScaleTouch(touch_point.pos()); - const auto [touch_x, touch_y] = MapToTouchScreen(x, y); - input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); - } - } -} - -bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) { - for (std::size_t id = 0; id < touch_ids.size(); ++id) { - if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) { - const auto [x, y] = ScaleTouch(touch_point.pos()); - const auto [touch_x, touch_y] = MapToTouchScreen(x, y); - input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); - return true; - } - } - return false; -} - -bool GRenderWindow::TouchExist(std::size_t id, - const QList<QTouchEvent::TouchPoint>& touch_points) const { - return std::any_of(touch_points.begin(), touch_points.end(), [id](const auto& point) { - return id == static_cast<std::size_t>(point.id() + 1); - }); + input_subsystem->GetTouchScreen()->ReleaseAllTouch(); } bool GRenderWindow::event(QEvent* event) { @@ -1049,8 +1014,8 @@ QStringList GRenderWindow::GetUnsupportedGLExtensions() const { return unsupported_ext; } -void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { - this->emu_thread = emu_thread; +void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread_) { + emu_thread = emu_thread_; } void GRenderWindow::OnEmulationStopping() { diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 4b0ce0293..81fe52c0e 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -10,6 +10,7 @@ #include <mutex> #include <QImage> +#include <QStringList> #include <QThread> #include <QTouchEvent> #include <QWidget> @@ -20,7 +21,6 @@ class GRenderWindow; class GMainWindow; class QKeyEvent; -class QStringList; namespace Core { enum class SystemResultStatus : u32; @@ -55,22 +55,13 @@ public: void run() override; /** - * Steps the emulation thread by a single CPU instruction (if the CPU is not already running) - * @note This function is thread-safe - */ - void ExecStep() { - exec_step = true; - running_cv.notify_all(); - } - - /** * Sets whether the emulation thread is running or not - * @param running Boolean value, set the emulation thread to running if true + * @param running_ Boolean value, set the emulation thread to running if true * @note This function is thread-safe */ - void SetRunning(bool running) { + void SetRunning(bool running_) { std::unique_lock lock{running_mutex}; - this->running = running; + running = running_; lock.unlock(); running_cv.notify_all(); if (!running) { @@ -99,7 +90,6 @@ public: } private: - bool exec_step = false; bool running = false; std::stop_source stop_source; std::mutex running_mutex; @@ -148,8 +138,8 @@ public: void BackupGeometry(); void RestoreGeometry(); - void restoreGeometry(const QByteArray& geometry); // overridden - QByteArray saveGeometry(); // overridden + void restoreGeometry(const QByteArray& geometry_); // overridden + QByteArray saveGeometry(); // overridden qreal windowPixelRatio() const; @@ -199,7 +189,7 @@ public: void Exit(); public slots: - void OnEmulationStarting(EmuThread* emu_thread); + void OnEmulationStarting(EmuThread* emu_thread_); void OnEmulationStopping(); void OnFramebufferSizeChanged(); @@ -217,10 +207,6 @@ private: void TouchUpdateEvent(const QTouchEvent* event); void TouchEndEvent(); - void TouchStart(const QTouchEvent::TouchPoint& touch_point); - bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point); - bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const; - void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; bool InitializeOpenGL(); @@ -246,8 +232,6 @@ private: bool first_frame = false; InputCommon::TasInput::TasState last_tas_state; - std::array<std::size_t, 16> touch_ids{}; - Core::System& system; protected: diff --git a/src/yuzu/check_vulkan.cpp b/src/yuzu/check_vulkan.cpp new file mode 100644 index 000000000..e6d66ab34 --- /dev/null +++ b/src/yuzu/check_vulkan.cpp @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "video_core/vulkan_common/vulkan_wrapper.h" + +#include <filesystem> +#include <fstream> +#include "common/fs/fs.h" +#include "common/fs/path_util.h" +#include "common/logging/log.h" +#include "video_core/vulkan_common/vulkan_instance.h" +#include "video_core/vulkan_common/vulkan_library.h" +#include "yuzu/check_vulkan.h" +#include "yuzu/uisettings.h" + +constexpr char TEMP_FILE_NAME[] = "vulkan_check"; + +bool CheckVulkan() { + if (UISettings::values.has_broken_vulkan) { + return true; + } + + LOG_DEBUG(Frontend, "Checking presence of Vulkan"); + + const auto fs_config_loc = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir); + const auto temp_file_loc = fs_config_loc / TEMP_FILE_NAME; + + if (std::filesystem::exists(temp_file_loc)) { + LOG_WARNING(Frontend, "Detected recovery from previous failed Vulkan initialization"); + + UISettings::values.has_broken_vulkan = true; + std::filesystem::remove(temp_file_loc); + return false; + } + + std::ofstream temp_file_handle(temp_file_loc); + temp_file_handle.close(); + + try { + Vulkan::vk::InstanceDispatch dld; + const Common::DynamicLibrary library = Vulkan::OpenLibrary(); + const Vulkan::vk::Instance instance = + Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_0); + + } catch (const Vulkan::vk::Exception& exception) { + LOG_ERROR(Frontend, "Failed to initialize Vulkan: {}", exception.what()); + // Don't set has_broken_vulkan to true here: we care when loading Vulkan crashes the + // application, not when we can handle it. + } + + std::filesystem::remove(temp_file_loc); + return true; +} diff --git a/src/yuzu/check_vulkan.h b/src/yuzu/check_vulkan.h new file mode 100644 index 000000000..e4ea93582 --- /dev/null +++ b/src/yuzu/check_vulkan.h @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +bool CheckVulkan(); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index ac26b885b..9df4752be 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -71,28 +71,28 @@ const std::array<int, 2> Config::default_ringcon_analogs{{ // UISetting::values.shortcuts, which is alphabetically ordered. // clang-format off const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{ - {QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}}, - {QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}}, - {QStringLiteral("Audio Volume Up"), QStringLiteral("Main Window"), {QStringLiteral("+"), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}}, - {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}}, - {QStringLiteral("Change Adapting Filter"), QStringLiteral("Main Window"), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}}, - {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}}, - {QStringLiteral("Change GPU Accuracy"), QStringLiteral("Main Window"), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut}}, - {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut}}, - {QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut}}, - {QStringLiteral("Exit yuzu"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut}}, - {QStringLiteral("Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut}}, - {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut}}, - {QStringLiteral("Load/Remove Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut}}, - {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut}}, - {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), QStringLiteral(""), Qt::WindowShortcut}}, - {QStringLiteral("TAS Record"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut}}, - {QStringLiteral("TAS Reset"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut}}, - {QStringLiteral("TAS Start/Stop"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut}}, - {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut}}, - {QStringLiteral("Toggle Framerate Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut}}, - {QStringLiteral("Toggle Mouse Panning"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut}}, - {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("+"), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral(""), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut}}, }}; // clang-format on @@ -525,6 +525,9 @@ void Config::ReadDebuggingValues() { // Intentionally not using the QT default setting as this is intended to be changed in the ini Settings::values.record_frame_times = qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); + + ReadBasicSetting(Settings::values.use_gdbstub); + ReadBasicSetting(Settings::values.gdbstub_port); ReadBasicSetting(Settings::values.program_args); ReadBasicSetting(Settings::values.dump_exefs); ReadBasicSetting(Settings::values.dump_nso); @@ -679,6 +682,12 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.bg_green); ReadGlobalSetting(Settings::values.bg_blue); + if (!global && UISettings::values.has_broken_vulkan && + Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::Vulkan && + !Settings::values.renderer_backend.UsingGlobal()) { + Settings::values.renderer_backend.SetGlobal(true); + } + if (global) { ReadBasicSetting(Settings::values.renderer_debug); ReadBasicSetting(Settings::values.renderer_shader_feedback); @@ -798,6 +807,7 @@ void Config::ReadUIValues() { ReadBasicSetting(UISettings::values.pause_when_in_background); ReadBasicSetting(UISettings::values.mute_when_in_background); ReadBasicSetting(UISettings::values.hide_mouse); + ReadBasicSetting(UISettings::values.has_broken_vulkan); ReadBasicSetting(UISettings::values.disable_web_applet); qt_config->endGroup(); @@ -1095,6 +1105,8 @@ void Config::SaveDebuggingValues() { // Intentionally not using the QT default setting as this is intended to be changed in the ini qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); + WriteBasicSetting(Settings::values.use_gdbstub); + WriteBasicSetting(Settings::values.gdbstub_port); WriteBasicSetting(Settings::values.program_args); WriteBasicSetting(Settings::values.dump_exefs); WriteBasicSetting(Settings::values.dump_nso); @@ -1343,6 +1355,7 @@ void Config::SaveUIValues() { WriteBasicSetting(UISettings::values.pause_when_in_background); WriteBasicSetting(UISettings::values.mute_when_in_background); WriteBasicSetting(UISettings::values.hide_mouse); + WriteBasicSetting(UISettings::values.has_broken_vulkan); WriteBasicSetting(UISettings::values.disable_web_applet); qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index bd50f7a68..343d2aee1 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -24,13 +24,18 @@ ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent) QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LogDir)); QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }); + + connect(ui->toggle_gdbstub, &QCheckBox::toggled, + [&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); }); } ConfigureDebug::~ConfigureDebug() = default; void ConfigureDebug::SetConfiguration() { const bool runtime_lock = !system.IsPoweredOn(); - + ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); + ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); + ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); ui->toggle_console->setEnabled(runtime_lock); ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); @@ -53,6 +58,8 @@ void ConfigureDebug::SetConfiguration() { ui->enable_nsight_aftermath->setChecked(Settings::values.enable_nsight_aftermath.GetValue()); ui->dump_shaders->setEnabled(runtime_lock); ui->dump_shaders->setChecked(Settings::values.dump_shaders.GetValue()); + ui->dump_macros->setEnabled(runtime_lock); + ui->dump_macros->setChecked(Settings::values.dump_macros.GetValue()); ui->disable_macro_jit->setEnabled(runtime_lock); ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue()); ui->disable_loop_safety_checks->setEnabled(runtime_lock); @@ -69,6 +76,8 @@ void ConfigureDebug::SetConfiguration() { } void ConfigureDebug::ApplyConfiguration() { + Settings::values.use_gdbstub = ui->toggle_gdbstub->isChecked(); + Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); UISettings::values.show_console = ui->toggle_console->isChecked(); Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); @@ -83,6 +92,7 @@ void ConfigureDebug::ApplyConfiguration() { Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked(); Settings::values.dump_shaders = ui->dump_shaders->isChecked(); + Settings::values.dump_macros = ui->dump_macros->isChecked(); Settings::values.disable_shader_loop_safety_checks = ui->disable_loop_safety_checks->isChecked(); Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index c1d90d588..1152fa6c6 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -3,6 +3,60 @@ <class>ConfigureDebug</class> <widget class="QWidget" name="ConfigureDebug"> <layout class="QVBoxLayout" name="verticalLayout_1"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Debugger</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_11"> + <item> + <widget class="QCheckBox" name="toggle_gdbstub"> + <property name="text"> + <string>Enable GDB Stub</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="gdbport_spinbox"> + <property name="minimum"> + <number>1024</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </item> <item> <widget class="QGroupBox" name="groupBox_2"> <property name="title"> @@ -118,6 +172,19 @@ </property> </widget> </item> + <item row="0" column="2"> + <widget class="QCheckBox" name="dump_macros"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="toolTip"> + <string>When checked, it will dump all the macro programs of the GPU</string> + </property> + <property name="text"> + <string>Dump Maxwell Macros</string> + </property> + </widget> + </item> <item row="0" column="1"> <widget class="QCheckBox" name="disable_macro_jit"> <property name="enabled"> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index b415a1cc4..e99657bd6 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -27,12 +27,11 @@ #include "yuzu/hotkeys.h" #include "yuzu/uisettings.h" -ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, +ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, InputCommon::InputSubsystem* input_subsystem, Core::System& system_) - : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, - registry(registry), system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, - this)}, + : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_}, + system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, this)}, cpu_tab{std::make_unique<ConfigureCpu>(system_, this)}, debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)}, filesystem_tab{std::make_unique<ConfigureFilesystem>(this)}, diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 32ddfd4e0..12cf25daf 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -40,7 +40,7 @@ class ConfigureDialog : public QDialog { Q_OBJECT public: - explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, + explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, InputCommon::InputSubsystem* input_subsystem, Core::System& system_); ~ConfigureDialog() override; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 2f1435b10..85f34dc35 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -17,6 +17,7 @@ #include "video_core/vulkan_common/vulkan_library.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_graphics.h" +#include "yuzu/uisettings.h" ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, system{system_} { @@ -57,6 +58,24 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren UpdateBackgroundColorButton(new_bg_color); }); + connect(ui->button_check_vulkan, &QAbstractButton::clicked, this, [this] { + UISettings::values.has_broken_vulkan = false; + + if (RetrieveVulkanDevices()) { + ui->api->setEnabled(true); + ui->button_check_vulkan->hide(); + + for (const auto& device : vulkan_devices) { + ui->device->addItem(device); + } + } else { + UISettings::values.has_broken_vulkan = true; + } + }); + + ui->api->setEnabled(!UISettings::values.has_broken_vulkan.GetValue()); + ui->button_check_vulkan->setVisible(UISettings::values.has_broken_vulkan.GetValue()); + ui->bg_label->setVisible(Settings::IsConfiguringGlobal()); ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal()); } @@ -296,7 +315,7 @@ void ConfigureGraphics::UpdateAPILayout() { vulkan_device = Settings::values.vulkan_device.GetValue(true); shader_backend = Settings::values.shader_backend.GetValue(true); ui->device_widget->setEnabled(false); - ui->backend_widget->setEnabled(false); + ui->backend_widget->setEnabled(UISettings::values.has_broken_vulkan.GetValue()); } else { vulkan_device = Settings::values.vulkan_device.GetValue(); shader_backend = Settings::values.shader_backend.GetValue(); @@ -318,7 +337,11 @@ void ConfigureGraphics::UpdateAPILayout() { } } -void ConfigureGraphics::RetrieveVulkanDevices() try { +bool ConfigureGraphics::RetrieveVulkanDevices() try { + if (UISettings::values.has_broken_vulkan) { + return false; + } + using namespace Vulkan; vk::InstanceDispatch dld; @@ -333,8 +356,10 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { vulkan_devices.push_back(QString::fromStdString(name)); } + return true; } catch (const Vulkan::vk::Exception& exception) { LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); + return false; } Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { @@ -415,4 +440,11 @@ void ConfigureGraphics::SetupPerGameUI() { ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); ConfigurationShared::InsertGlobalItem( ui->nvdec_emulation, static_cast<int>(Settings::values.nvdec_emulation.GetValue(true))); + + if (UISettings::values.has_broken_vulkan) { + ui->backend_widget->setEnabled(true); + ConfigurationShared::SetColoredComboBox( + ui->backend, ui->backend_widget, + static_cast<int>(Settings::values.shader_backend.GetValue(true))); + } } diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 1b101c940..8438f0187 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -41,7 +41,7 @@ private: void UpdateDeviceSelection(int device); void UpdateShaderBackendSelection(int backend); - void RetrieveVulkanDevices(); + bool RetrieveVulkanDevices(); void SetupPerGameUI(); diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 74f0e0b79..2f94c94bc 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>437</width> - <height>482</height> + <width>471</width> + <height>759</height> </rect> </property> <property name="windowTitle"> @@ -171,11 +171,11 @@ </widget> </item> <item> - <widget class="QCheckBox" name="accelerate_astc"> - <property name="text"> - <string>Accelerate ASTC texture decoding</string> - </property> - </widget> + <widget class="QCheckBox" name="accelerate_astc"> + <property name="text"> + <string>Accelerate ASTC texture decoding</string> + </property> + </widget> </item> <item> <widget class="QWidget" name="nvdec_emulation_widget" native="true"> @@ -438,43 +438,43 @@ </widget> </item> <item> - <widget class="QWidget" name="anti_aliasing_layout" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> + <widget class="QWidget" name="anti_aliasing_layout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="anti_aliasing_label"> + <property name="text"> + <string>Anti-Aliasing Method:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="anti_aliasing_combobox"> + <item> + <property name="text"> + <string>None</string> </property> - <property name="bottomMargin"> - <number>0</number> + </item> + <item> + <property name="text"> + <string>FXAA</string> </property> - <item> - <widget class="QLabel" name="anti_aliasing_label"> - <property name="text"> - <string>Anti-Aliasing Method:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="anti_aliasing_combobox"> - <item> - <property name="text"> - <string>None</string> - </property> - </item> - <item> - <property name="text"> - <string>FXAA</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> + </item> + </widget> + </item> + </layout> + </widget> </item> <item> <widget class="QWidget" name="bg_layout" native="true"> @@ -574,6 +574,13 @@ </property> </spacer> </item> + <item> + <widget class="QPushButton" name="button_check_vulkan"> + <property name="text"> + <string>Check for Working Vulkan</string> + </property> + </widget> + </item> </layout> </widget> <resources/> diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index 6679e9c53..edf0893c4 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -61,14 +61,18 @@ ConfigureHotkeys::~ConfigureHotkeys() = default; void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { for (const auto& group : registry.hotkey_groups) { - auto* parent_item = new QStandardItem(group.first); + auto* parent_item = + new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(group.first))); parent_item->setEditable(false); + parent_item->setData(group.first); for (const auto& hotkey : group.second) { - auto* action = new QStandardItem(hotkey.first); + auto* action = + new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(hotkey.first))); auto* keyseq = new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); auto* controller_keyseq = new QStandardItem(hotkey.second.controller_keyseq); action->setEditable(false); + action->setData(hotkey.first); keyseq->setEditable(false); controller_keyseq->setEditable(false); parent_item->appendRow({action, keyseq, controller_keyseq}); @@ -93,6 +97,16 @@ void ConfigureHotkeys::RetranslateUI() { ui->retranslateUi(this); model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Controller Hotkey")}); + for (int key_id = 0; key_id < model->rowCount(); key_id++) { + QStandardItem* parent = model->item(key_id, 0); + parent->setText( + QCoreApplication::translate("Hotkeys", qPrintable(parent->data().toString()))); + for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) { + QStandardItem* action = parent->child(key_column_id, name_column); + action->setText( + QCoreApplication::translate("Hotkeys", qPrintable(action->data().toString()))); + } + } } void ConfigureHotkeys::Configure(QModelIndex index) { @@ -273,10 +287,10 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { const QStandardItem* controller_keyseq = parent->child(key_column_id, controller_column); for (auto& [group, sub_actions] : registry.hotkey_groups) { - if (group != parent->text()) + if (group != parent->data()) continue; for (auto& [action_name, hotkey] : sub_actions) { - if (action_name != action->text()) + if (action_name != action->data()) continue; hotkey.keyseq = QKeySequence(keyseq->text()); hotkey.controller_keyseq = controller_keyseq->text(); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 1c05dd0f3..f3be9a374 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -264,15 +264,16 @@ QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param, return QObject::tr("[unknown]"); } -ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, - QWidget* bottom_row, +ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index_, + QWidget* bottom_row_, InputCommon::InputSubsystem* input_subsystem_, InputProfiles* profiles_, Core::HID::HIDCore& hid_core_, - bool is_powered_on_, bool debug) - : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), - debug(debug), is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, - profiles(profiles_), timeout_timer(std::make_unique<QTimer>()), - poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row), hid_core{hid_core_} { + bool is_powered_on_, bool debug_) + : QWidget(parent), + ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index{player_index_}, debug{debug_}, + is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_), + timeout_timer(std::make_unique<QTimer>()), + poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} { if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); @@ -696,39 +697,38 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); - connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), - [this, player_index](int) { - UpdateControllerAvailableButtons(); - UpdateControllerEnabledButtons(); - UpdateControllerButtonNames(); - UpdateMotionButtons(); - const Core::HID::NpadStyleIndex type = - GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); - - if (player_index == 0) { - auto* emulated_controller_p1 = - hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_handheld = - hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); - bool is_connected = emulated_controller->IsConnected(true); - - emulated_controller_p1->SetNpadStyleIndex(type); - emulated_controller_handheld->SetNpadStyleIndex(type); - if (is_connected) { - if (type == Core::HID::NpadStyleIndex::Handheld) { - emulated_controller_p1->Disconnect(); - emulated_controller_handheld->Connect(true); - emulated_controller = emulated_controller_handheld; - } else { - emulated_controller_handheld->Disconnect(); - emulated_controller_p1->Connect(true); - emulated_controller = emulated_controller_p1; - } - } - ui->controllerFrame->SetController(emulated_controller); + connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) { + UpdateControllerAvailableButtons(); + UpdateControllerEnabledButtons(); + UpdateControllerButtonNames(); + UpdateMotionButtons(); + const Core::HID::NpadStyleIndex type = + GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); + + if (player_index == 0) { + auto* emulated_controller_p1 = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_handheld = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + bool is_connected = emulated_controller->IsConnected(true); + + emulated_controller_p1->SetNpadStyleIndex(type); + emulated_controller_handheld->SetNpadStyleIndex(type); + if (is_connected) { + if (type == Core::HID::NpadStyleIndex::Handheld) { + emulated_controller_p1->Disconnect(); + emulated_controller_handheld->Connect(true); + emulated_controller = emulated_controller_handheld; + } else { + emulated_controller_handheld->Disconnect(); + emulated_controller_p1->Connect(true); + emulated_controller = emulated_controller_p1; } - emulated_controller->SetNpadStyleIndex(type); - }); + } + ui->controllerFrame->SetController(emulated_controller); + } + emulated_controller->SetNpadStyleIndex(type); + }); connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this, &ConfigureInputPlayer::UpdateMappingWithDefaults); diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index 27559c37b..c313b0919 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp @@ -151,6 +151,8 @@ void ConfigureMotionTouch::ConnectEvents() { &ConfigureMotionTouch::OnConfigureTouchCalibration); connect(ui->touch_from_button_config_btn, &QPushButton::clicked, this, &ConfigureMotionTouch::OnConfigureTouchFromButton); + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, + &ConfigureMotionTouch::ApplyConfiguration); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [this] { if (CanCloseDialog()) { reject(); diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui index c75a84ae4..0237fae54 100644 --- a/src/yuzu/configuration/configure_motion_touch.ui +++ b/src/yuzu/configuration/configure_motion_touch.ui @@ -293,22 +293,5 @@ </layout> </widget> <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>ConfigureMotionTouch</receiver> - <slot>ApplyConfiguration()</slot> - <hints> - <hint type="sourcelabel"> - <x>20</x> - <y>20</y> - </hint> - <hint type="destinationlabel"> - <x>20</x> - <y>20</y> - </hint> - </hints> - </connection> - </connections> + <connections/> </ui> diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 54b3fe150..af8343b2e 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -35,10 +35,10 @@ #include "yuzu/uisettings.h" #include "yuzu/util/util.h" -ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id, const std::string& file_name, +ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name, Core::System& system_) - : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), - title_id(title_id), system{system_} { + : QDialog(parent), + ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_} { const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) : fmt::format("{:016X}", title_id); @@ -116,8 +116,8 @@ void ConfigurePerGame::HandleApplyButtonClicked() { ApplyConfiguration(); } -void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { - this->file = std::move(file); +void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file_) { + file = std::move(file_); LoadConfiguration(); } diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index e6dc05546..17a98a0f3 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h @@ -39,14 +39,14 @@ class ConfigurePerGame : public QDialog { public: // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263 - explicit ConfigurePerGame(QWidget* parent, u64 title_id, const std::string& file_name, + explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name, Core::System& system_); ~ConfigurePerGame() override; /// Save all button configurations to settings file void ApplyConfiguration(); - void LoadFromFile(FileSys::VirtualFile file); + void LoadFromFile(FileSys::VirtualFile file_); private: void changeEvent(QEvent* event) override; diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 7893a85bb..4906997ab 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -89,8 +89,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() { Settings::values.disabled_addons[title_id] = disabled_addons; } -void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file) { - this->file = std::move(file); +void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file_) { + file = std::move(file_); LoadConfiguration(); } diff --git a/src/yuzu/configuration/configure_per_game_addons.h b/src/yuzu/configuration/configure_per_game_addons.h index 24b017494..14690fba8 100644 --- a/src/yuzu/configuration/configure_per_game_addons.h +++ b/src/yuzu/configuration/configure_per_game_addons.h @@ -35,7 +35,7 @@ public: /// Save all button configurations to settings file void ApplyConfiguration(); - void LoadFromFile(FileSys::VirtualFile file); + void LoadFromFile(FileSys::VirtualFile file_); void SetTitleId(u64 id); diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index 4fcc22b7a..688c2dd38 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.cpp @@ -165,10 +165,10 @@ ConfigureRingController::ConfigureRingController(QWidget* parent, const std::string invert_str = invert_value ? "+" : "-"; param.Set("invert_x", invert_str); emulated_device->SetRingParam(param); - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; - ++sub_button_id) { - analog_map_buttons[sub_button_id]->setText( - AnalogToText(param, analog_sub_buttons[sub_button_id])); + for (int sub_button_id2 = 0; sub_button_id2 < ANALOG_SUB_BUTTONS_NUM; + ++sub_button_id2) { + analog_map_buttons[sub_button_id2]->setText( + AnalogToText(param, analog_sub_buttons[sub_button_id2])); } }); context_menu.exec( diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 19aa589f9..ecebb0fb7 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -130,8 +130,7 @@ void ConfigureSystem::ApplyConfiguration() { // Guard if during game and set to game-specific value if (Settings::values.rng_seed.UsingGlobal()) { if (ui->rng_seed_checkbox->isChecked()) { - Settings::values.rng_seed.SetValue( - ui->rng_seed_edit->text().toULongLong(nullptr, 16)); + Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toUInt(nullptr, 16)); } else { Settings::values.rng_seed.SetValue(std::nullopt); } @@ -142,8 +141,7 @@ void ConfigureSystem::ApplyConfiguration() { case ConfigurationShared::CheckState::Off: Settings::values.rng_seed.SetGlobal(false); if (ui->rng_seed_checkbox->isChecked()) { - Settings::values.rng_seed.SetValue( - ui->rng_seed_edit->text().toULongLong(nullptr, 16)); + Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toUInt(nullptr, 16)); } else { Settings::values.rng_seed.SetValue(std::nullopt); } diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp index c17da6fd1..06cc452c3 100644 --- a/src/yuzu/configuration/configure_touch_from_button.cpp +++ b/src/yuzu/configuration/configure_touch_from_button.cpp @@ -68,10 +68,10 @@ static QString ButtonToText(const Common::ParamPackage& param) { } ConfigureTouchFromButton::ConfigureTouchFromButton( - QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps, + QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps_, InputCommon::InputSubsystem* input_subsystem_, const int default_index) : QDialog(parent), ui(std::make_unique<Ui::ConfigureTouchFromButton>()), - touch_maps(touch_maps), input_subsystem{input_subsystem_}, selected_index(default_index), + touch_maps{touch_maps_}, input_subsystem{input_subsystem_}, selected_index{default_index}, timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { ui->setupUi(this); binding_list_model = new QStandardItemModel(0, 3, this); diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h index e1400481a..b8c55db66 100644 --- a/src/yuzu/configuration/configure_touch_from_button.h +++ b/src/yuzu/configuration/configure_touch_from_button.h @@ -37,7 +37,7 @@ class ConfigureTouchFromButton : public QDialog { public: explicit ConfigureTouchFromButton(QWidget* parent, - const std::vector<Settings::TouchFromButtonMap>& touch_maps, + const std::vector<Settings::TouchFromButtonMap>& touch_maps_, InputCommon::InputSubsystem* input_subsystem_, int default_index = 0); ~ConfigureTouchFromButton() override; diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 8f486a131..0ea31cd33 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -113,9 +113,9 @@ QString WaitTreeText::GetText() const { return text; } -WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table, +WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address_, const Kernel::KHandleTable& handle_table, Core::System& system_) - : mutex_address(mutex_address), system{system_} { + : mutex_address{mutex_address_}, system{system_} { mutex_value = system.Memory().Read32(mutex_address); owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe(); @@ -140,8 +140,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() cons return list; } -WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread, Core::System& system_) - : thread(thread), system{system_} {} +WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_) + : thread{thread_}, system{system_} {} WaitTreeCallstack::~WaitTreeCallstack() = default; QString WaitTreeCallstack::GetText() const { @@ -171,8 +171,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons } WaitTreeSynchronizationObject::WaitTreeSynchronizationObject( - const Kernel::KSynchronizationObject& o, Core::System& system_) - : object(o), system{system_} {} + const Kernel::KSynchronizationObject& object_, Core::System& system_) + : object{object_}, system{system_} {} WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default; WaitTreeExpandableItem::WaitTreeExpandableItem() = default; @@ -380,8 +380,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { return list; } -WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object, Core::System& system_) - : WaitTreeSynchronizationObject(object, system_) {} +WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_) + : WaitTreeSynchronizationObject(object_, system_) {} WaitTreeEvent::~WaitTreeEvent() = default; WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_) diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 4a36dfc48..f21b9f467 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h @@ -78,7 +78,7 @@ public: class WaitTreeMutexInfo : public WaitTreeExpandableItem { Q_OBJECT public: - explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table, + explicit WaitTreeMutexInfo(VAddr mutex_address_, const Kernel::KHandleTable& handle_table, Core::System& system_); ~WaitTreeMutexInfo() override; @@ -97,7 +97,7 @@ private: class WaitTreeCallstack : public WaitTreeExpandableItem { Q_OBJECT public: - explicit WaitTreeCallstack(const Kernel::KThread& thread, Core::System& system_); + explicit WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_); ~WaitTreeCallstack() override; QString GetText() const override; @@ -112,7 +112,7 @@ private: class WaitTreeSynchronizationObject : public WaitTreeExpandableItem { Q_OBJECT public: - explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object, + explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object_, Core::System& system_); ~WaitTreeSynchronizationObject() override; @@ -162,7 +162,7 @@ private: class WaitTreeEvent : public WaitTreeSynchronizationObject { Q_OBJECT public: - explicit WaitTreeEvent(const Kernel::KReadableEvent& object, Core::System& system_); + explicit WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_); ~WaitTreeEvent() override; }; diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 4a6d74a7e..05d309827 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -28,8 +28,8 @@ #include "yuzu/uisettings.h" #include "yuzu/util/controller_navigation.h" -GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) - : QObject(parent), gamelist{gamelist} {} +GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent) + : QObject(parent), gamelist{gamelist_} {} // EventFilter in order to process systemkeys while editing the searchfield bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) { @@ -80,9 +80,9 @@ bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* eve return QObject::eventFilter(obj, event); } -void GameListSearchField::setFilterResult(int visible, int total) { - this->visible = visible; - this->total = total; +void GameListSearchField::setFilterResult(int visible_, int total_) { + visible = visible_; + total = total_; label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); } @@ -309,9 +309,9 @@ void GameList::OnFilterCloseClicked() { main_window->filterBarSetChecked(false); } -GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvider* provider, +GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvider* provider_, Core::System& system_, GMainWindow* parent) - : QWidget{parent}, vfs(std::move(vfs)), provider(provider), system{system_} { + : QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_}, system{system_} { watcher = new QFileSystemWatcher(this); connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory); @@ -483,7 +483,7 @@ void GameList::DonePopulating(const QStringList& watch_list) { // Also artificially caps the watcher to a certain number of directories constexpr int LIMIT_WATCH_DIRECTORIES = 5000; constexpr int SLICE_SIZE = 25; - int len = std::min(watch_list.length(), LIMIT_WATCH_DIRECTORIES); + int len = std::min(static_cast<int>(watch_list.size()), LIMIT_WATCH_DIRECTORIES); for (int i = 0; i < len; i += SLICE_SIZE) { watcher->addPaths(watch_list.mid(i, i + SLICE_SIZE)); QCoreApplication::processEvents(); @@ -870,7 +870,7 @@ GameListPlaceholder::GameListPlaceholder(GMainWindow* parent) : QWidget{parent} layout->setAlignment(Qt::AlignCenter); image->setPixmap(QIcon::fromTheme(QStringLiteral("plus_folder")).pixmap(200)); - text->setText(tr("Double-click to add a new folder to the game list")); + RetranslateUI(); QFont font = text->font(); font.setPointSize(20); text->setFont(font); @@ -891,3 +891,15 @@ void GameListPlaceholder::onUpdateThemedIcons() { void GameListPlaceholder::mouseDoubleClickEvent(QMouseEvent* event) { emit GameListPlaceholder::AddDirectory(); } + +void GameListPlaceholder::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void GameListPlaceholder::RetranslateUI() { + text->setText(tr("Double-click to add a new folder to the game list")); +} diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index d19dbe4b0..bc36d015a 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -67,8 +67,8 @@ public: COLUMN_COUNT, // Number of columns }; - explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs, - FileSys::ManualContentProvider* provider, Core::System& system_, + explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs_, + FileSys::ManualContentProvider* provider_, Core::System& system_, GMainWindow* parent = nullptr); ~GameList() override; @@ -166,6 +166,9 @@ protected: void mouseDoubleClickEvent(QMouseEvent* event) override; private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + QVBoxLayout* layout = nullptr; QLabel* image = nullptr; QLabel* text = nullptr; diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index f2a986ed8..cd7d63536 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h @@ -225,8 +225,8 @@ public: static constexpr int GameDirRole = Qt::UserRole + 2; explicit GameListDir(UISettings::GameDir& directory, - GameListItemType dir_type = GameListItemType::CustomDir) - : dir_type{dir_type} { + GameListItemType dir_type_ = GameListItemType::CustomDir) + : dir_type{dir_type_} { setData(type(), TypeRole); UISettings::GameDir* game_dir = &directory; @@ -348,7 +348,7 @@ public: explicit GameListSearchField(GameList* parent = nullptr); QString filterText() const; - void setFilterResult(int visible, int total); + void setFilterResult(int visible_, int total_); void clear(); void setFocus(); @@ -356,7 +356,7 @@ public: private: class KeyReleaseEater : public QObject { public: - explicit KeyReleaseEater(GameList* gamelist, QObject* parent = nullptr); + explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr); private: GameList* gamelist = nullptr; diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index ca1899b5c..63326968b 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -223,12 +223,12 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri } } // Anonymous namespace -GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs, - FileSys::ManualContentProvider* provider, - QVector<UISettings::GameDir>& game_dirs, - const CompatibilityList& compatibility_list, Core::System& system_) - : vfs(std::move(vfs)), provider(provider), game_dirs(game_dirs), - compatibility_list(compatibility_list), system{system_} {} +GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_, + FileSys::ManualContentProvider* provider_, + QVector<UISettings::GameDir>& game_dirs_, + const CompatibilityList& compatibility_list_, Core::System& system_) + : vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_}, + compatibility_list{compatibility_list_}, system{system_} {} GameListWorker::~GameListWorker() = default; diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h index 622d241fb..24a4e92c3 100644 --- a/src/yuzu/game_list_worker.h +++ b/src/yuzu/game_list_worker.h @@ -33,10 +33,10 @@ class GameListWorker : public QObject, public QRunnable { Q_OBJECT public: - explicit GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs, - FileSys::ManualContentProvider* provider, - QVector<UISettings::GameDir>& game_dirs, - const CompatibilityList& compatibility_list, Core::System& system_); + explicit GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs_, + FileSys::ManualContentProvider* provider_, + QVector<UISettings::GameDir>& game_dirs_, + const CompatibilityList& compatibility_list_, Core::System& system_); ~GameListWorker() override; /// Starts the processing of directory tree information. diff --git a/src/yuzu/loading_screen.cpp b/src/yuzu/loading_screen.cpp index edfb946a8..e273744fd 100644 --- a/src/yuzu/loading_screen.cpp +++ b/src/yuzu/loading_screen.cpp @@ -183,7 +183,7 @@ void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size void LoadingScreen::paintEvent(QPaintEvent* event) { QStyleOption opt; - opt.init(this); + opt.initFrom(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); diff --git a/src/yuzu/loading_screen.h b/src/yuzu/loading_screen.h index 7c960ee72..17045595d 100644 --- a/src/yuzu/loading_screen.h +++ b/src/yuzu/loading_screen.h @@ -7,6 +7,7 @@ #include <memory> #include <QString> #include <QWidget> +#include <QtGlobal> #if !QT_CONFIG(movie) #define YUZU_QT_MOVIE_MISSING 1 @@ -88,4 +89,6 @@ private: std::size_t slow_shader_first_value = 0; }; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) Q_DECLARE_METATYPE(VideoCore::LoadCallbackStage); +#endif diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f607f464a..b460020b1 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -52,7 +52,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #define QT_NO_OPENGL #include <QClipboard> #include <QDesktopServices> -#include <QDesktopWidget> #include <QFile> #include <QFileDialog> #include <QInputDialog> @@ -60,6 +59,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include <QProgressBar> #include <QProgressDialog> #include <QPushButton> +#include <QScreen> #include <QShortcut> #include <QStatusBar> #include <QString> @@ -115,6 +115,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "video_core/shader_notify.h" #include "yuzu/about_dialog.h" #include "yuzu/bootmanager.h" +#include "yuzu/check_vulkan.h" #include "yuzu/compatdb.h" #include "yuzu/compatibility_list.h" #include "yuzu/configuration/config.h" @@ -198,6 +199,59 @@ static void RemoveCachedContents() { Common::FS::RemoveDirRecursively(offline_system_data); } +static void LogRuntimes() { +#ifdef _MSC_VER + // It is possible that the name of the dll will change. + // vcruntime140.dll is for 2015 and onwards + constexpr char runtime_dll_name[] = "vcruntime140.dll"; + UINT sz = GetFileVersionInfoSizeA(runtime_dll_name, nullptr); + bool runtime_version_inspection_worked = false; + if (sz > 0) { + std::vector<u8> buf(sz); + if (GetFileVersionInfoA(runtime_dll_name, 0, sz, buf.data())) { + VS_FIXEDFILEINFO* pvi; + sz = sizeof(VS_FIXEDFILEINFO); + if (VerQueryValueA(buf.data(), "\\", reinterpret_cast<LPVOID*>(&pvi), &sz)) { + if (pvi->dwSignature == VS_FFI_SIGNATURE) { + runtime_version_inspection_worked = true; + LOG_INFO(Frontend, "MSVC Compiler: {} Runtime: {}.{}.{}.{}", _MSC_VER, + pvi->dwProductVersionMS >> 16, pvi->dwProductVersionMS & 0xFFFF, + pvi->dwProductVersionLS >> 16, pvi->dwProductVersionLS & 0xFFFF); + } + } + } + } + if (!runtime_version_inspection_worked) { + LOG_INFO(Frontend, "Unable to inspect {}", runtime_dll_name); + } +#endif +} + +static QString PrettyProductName() { +#ifdef _WIN32 + // After Windows 10 Version 2004, Microsoft decided to switch to a different notation: 20H2 + // With that notation change they changed the registry key used to denote the current version + QSettings windows_registry( + QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), + QSettings::NativeFormat); + const QString release_id = windows_registry.value(QStringLiteral("ReleaseId")).toString(); + if (release_id == QStringLiteral("2009")) { + const u32 current_build = windows_registry.value(QStringLiteral("CurrentBuild")).toUInt(); + const QString display_version = + windows_registry.value(QStringLiteral("DisplayVersion")).toString(); + const u32 ubr = windows_registry.value(QStringLiteral("UBR")).toUInt(); + u32 version = 10; + if (current_build >= 22000) { + version = 11; + } + return QStringLiteral("Windows %1 Version %2 (Build %3.%4)") + .arg(QString::number(version), display_version, QString::number(current_build), + QString::number(ubr)); + } +#endif + return QSysInfo::prettyProductName(); +} + GMainWindow::GMainWindow() : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, @@ -243,6 +297,7 @@ GMainWindow::GMainWindow() const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; LOG_INFO(Frontend, "yuzu Version: {}", yuzu_build_version); + LogRuntimes(); #ifdef ARCHITECTURE_x86_64 const auto& caps = Common::GetCPUCaps(); std::string cpu_string = caps.cpu_string; @@ -259,7 +314,7 @@ GMainWindow::GMainWindow() } LOG_INFO(Frontend, "Host CPU: {}", cpu_string); #endif - LOG_INFO(Frontend, "Host OS: {}", QSysInfo::prettyProductName().toStdString()); + LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString()); LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); @@ -297,6 +352,23 @@ GMainWindow::GMainWindow() MigrateConfigFiles(); + if (!CheckVulkan()) { + config->Save(); + + QMessageBox::warning( + this, tr("Broken Vulkan Installation Detected"), + tr("Vulkan initialization failed on the previous boot.<br><br>Click <a " + "href='https://yuzu-emu.org/wiki/faq/" + "#yuzu-starts-with-the-error-broken-vulkan-installation-detected'>here for " + "instructions to fix the issue</a>.")); + } + if (UISettings::values.has_broken_vulkan) { + Settings::values.renderer_backend = Settings::RendererBackend::OpenGL; + + renderer_status_button->setDisabled(true); + renderer_status_button->setChecked(false); + } + #if defined(HAVE_SDL2) && !defined(_WIN32) SDL_InitSubSystem(SDL_INIT_VIDEO); // SDL disables the screen saver by default, and setting the hint @@ -827,12 +899,11 @@ void GMainWindow::InitializeWidgets() { // Setup Dock button dock_status_button = new QPushButton(); - dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); + dock_status_button->setObjectName(QStringLiteral("DockingStatusBarButton")); dock_status_button->setFocusPolicy(Qt::NoFocus); connect(dock_status_button, &QPushButton::clicked, this, &GMainWindow::OnToggleDockedMode); - dock_status_button->setText(tr("DOCK")); dock_status_button->setCheckable(true); - dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); + UpdateDockedButton(); statusBar()->insertPermanentWidget(0, dock_status_button); gpu_accuracy_button = new QPushButton(); @@ -863,8 +934,7 @@ void GMainWindow::InitializeWidgets() { Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan); } else { Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); - const auto filter = Settings::values.scaling_filter.GetValue(); - if (filter == Settings::ScalingFilter::Fsr) { + if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor); UpdateFilterText(); } @@ -1002,7 +1072,7 @@ void GMainWindow::InitializeHotkeys() { void GMainWindow::SetDefaultUIGeometry() { // geometry: 53% of the window contents are in the upper screen half, 47% in the lower half - const QRect screenRect = QApplication::desktop()->screenGeometry(this); + const QRect screenRect = QGuiApplication::primaryScreen()->geometry(); const int w = screenRect.width() * 2 / 3; const int h = screenRect.height() * 2 / 3; @@ -1015,6 +1085,10 @@ void GMainWindow::SetDefaultUIGeometry() { void GMainWindow::RestoreUIState() { setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint); restoreGeometry(UISettings::values.geometry); + // Work-around because the games list isn't supposed to be full screen + if (isFullScreen()) { + showNormal(); + } restoreState(UISettings::values.state); render_window->setWindowFlags(render_window->windowFlags() & ~Qt::FramelessWindowHint); render_window->restoreGeometry(UISettings::values.renderwindow_geometry); @@ -1367,7 +1441,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p } return false; } - game_path = filename; + current_game_path = filename; system->TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt"); return true; @@ -1401,7 +1475,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && type == StartGameType::Normal) { // Load per game settings - const auto file_path = std::filesystem::path{filename.toStdU16String()}; + const auto file_path = + std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())}; const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) : fmt::format("{:016X}", title_id); @@ -1432,7 +1507,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t // Register an ExecuteProgram callback such that Core can execute a sub-program system->RegisterExecuteProgramCallback( - [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); + [this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); }); // Register an Exit callback such that Core can exit the currently running application. system->RegisterExitCallback([this]() { render_window->Exit(); }); @@ -1482,7 +1557,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t } if (res != Loader::ResultStatus::Success || title_name.empty()) { title_name = Common::FS::PathToUTF8String( - std::filesystem::path{filename.toStdU16String()}.filename()); + std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())} + .filename()); } const bool is_64bit = system->Kernel().CurrentProcess()->Is64BitProcess(); const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)"); @@ -1514,6 +1590,7 @@ void GMainWindow::ShutdownGame() { AllowOSSleep(); + system->DetachDebugger(); discord_rpc->Pause(); emu_thread->RequestStop(); @@ -1561,9 +1638,9 @@ void GMainWindow::ShutdownGame() { emu_speed_label->setVisible(false); game_fps_label->setVisible(false); emu_frametime_label->setVisible(false); - renderer_status_button->setEnabled(true); + renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); - game_path.clear(); + current_game_path.clear(); // When closing the game, destroy the GLWindow to clear the context after the game is closed render_window->ReleaseRenderTarget(); @@ -1581,7 +1658,7 @@ void GMainWindow::StoreRecentFile(const QString& filename) { void GMainWindow::UpdateRecentFiles() { const int num_recent_files = - std::min(UISettings::values.recent_files.size(), max_recent_files_item); + std::min(static_cast<int>(UISettings::values.recent_files.size()), max_recent_files_item); for (int i = 0; i < num_recent_files; i++) { const QString text = QStringLiteral("&%1. %2").arg(i + 1).arg( @@ -2482,7 +2559,7 @@ void GMainWindow::OnRestartGame() { return; } // Make a copy since BootGame edits game_path - BootGame(QString(game_path)); + BootGame(QString(current_game_path)); } void GMainWindow::OnPauseGame() { @@ -2579,6 +2656,18 @@ void GMainWindow::ToggleFullscreen() { } } +// We're going to return the screen that the given window has the most pixels on +static QScreen* GuessCurrentScreen(QWidget* window) { + const QList<QScreen*> screens = QGuiApplication::screens(); + return *std::max_element( + screens.cbegin(), screens.cend(), [window](const QScreen* left, const QScreen* right) { + const QSize left_size = left->geometry().intersected(window->geometry()).size(); + const QSize right_size = right->geometry().intersected(window->geometry()).size(); + return (left_size.height() * left_size.width()) < + (right_size.height() * right_size.width()); + }); +} + void GMainWindow::ShowFullscreen() { const auto show_fullscreen = [](QWidget* window) { if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { @@ -2587,7 +2676,7 @@ void GMainWindow::ShowFullscreen() { } window->hide(); window->setWindowFlags(window->windowFlags() | Qt::FramelessWindowHint); - const auto screen_geometry = QApplication::desktop()->screenGeometry(window); + const auto screen_geometry = GuessCurrentScreen(window)->geometry(); window->setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(), screen_geometry.height() + 1); window->raise(); @@ -2771,6 +2860,10 @@ void GMainWindow::OnConfigure() { mouse_hide_timer.start(); } + if (!UISettings::values.has_broken_vulkan) { + renderer_status_button->setEnabled(!emulation_running); + } + UpdateStatusButtons(); controller_dialog->refreshConfiguration(); } @@ -2856,7 +2949,7 @@ void GMainWindow::OnToggleDockedMode() { } Settings::values.use_docked_mode.SetValue(!is_docked); - dock_status_button->setChecked(!is_docked); + UpdateDockedButton(); OnDockedModeChanged(is_docked, !is_docked, *system); } @@ -2895,7 +2988,7 @@ void GMainWindow::OnToggleAdaptingFilter() { void GMainWindow::OnConfigurePerGame() { const u64 title_id = system->GetCurrentProcessProgramID(); - OpenPerGameConfiguration(title_id, game_path.toStdString()); + OpenPerGameConfiguration(title_id, current_game_path.toStdString()); } void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { @@ -3150,7 +3243,7 @@ void GMainWindow::OnTasStateChanged() { } void GMainWindow::UpdateStatusBar() { - if (emu_thread == nullptr) { + if (emu_thread == nullptr || !system->IsPoweredOn()) { status_bar_update_timer.stop(); return; } @@ -3222,6 +3315,12 @@ void GMainWindow::UpdateGPUAccuracyButton() { } } +void GMainWindow::UpdateDockedButton() { + const bool is_docked = Settings::values.use_docked_mode.GetValue(); + dock_status_button->setChecked(is_docked); + dock_status_button->setText(is_docked ? tr("DOCKED") : tr("HANDHELD")); +} + void GMainWindow::UpdateFilterText() { const auto filter = Settings::values.scaling_filter.GetValue(); switch (filter) { @@ -3265,10 +3364,10 @@ void GMainWindow::UpdateAAText() { } void GMainWindow::UpdateStatusButtons() { - dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::Vulkan); UpdateGPUAccuracyButton(); + UpdateDockedButton(); UpdateFilterText(); UpdateAAText(); } @@ -3319,7 +3418,7 @@ void GMainWindow::CenterMouseCursor() { const int center_x = render_window->width() / 2; const int center_y = render_window->height() / 2; - QCursor::setPos(mapToGlobal({center_x, center_y})); + QCursor::setPos(mapToGlobal(QPoint{center_x, center_y})); } void GMainWindow::OnMouseActivity() { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index b399e9b01..8cf224c9c 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -320,6 +320,7 @@ private: void MigrateConfigFiles(); void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, std::string_view gpu_vendor = {}); + void UpdateDockedButton(); void UpdateFilterText(); void UpdateAAText(); void UpdateStatusBar(); @@ -368,7 +369,7 @@ private: bool emulation_running = false; std::unique_ptr<EmuThread> emu_thread; // The path to the game currently running - QString game_path; + QString current_game_path; bool auto_paused = false; bool auto_muted = false; diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 15ba9ea17..c64d87ace 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -77,6 +77,8 @@ struct Values { Settings::BasicSetting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; Settings::BasicSetting<bool> mute_when_in_background{false, "muteWhenInBackground"}; Settings::BasicSetting<bool> hide_mouse{true, "hideInactiveMouse"}; + // Set when Vulkan is known to crash the application + Settings::BasicSetting<bool> has_broken_vulkan{false, "has_broken_vulkan"}; Settings::BasicSetting<bool> select_user_on_boot{false, "select_user_on_boot"}; |