summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/CMakeLists.txt27
-rw-r--r--src/yuzu/about_dialog.cpp6
-rw-r--r--src/yuzu/aboutdialog.ui16
-rw-r--r--src/yuzu/applets/qt_controller.cpp2
-rw-r--r--src/yuzu/applets/qt_software_keyboard.cpp29
-rw-r--r--src/yuzu/bootmanager.cpp81
-rw-r--r--src/yuzu/bootmanager.h30
-rw-r--r--src/yuzu/check_vulkan.cpp53
-rw-r--r--src/yuzu/check_vulkan.h6
-rw-r--r--src/yuzu/configuration/config.cpp57
-rw-r--r--src/yuzu/configuration/configure_debug.cpp12
-rw-r--r--src/yuzu/configuration/configure_debug.ui67
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp7
-rw-r--r--src/yuzu/configuration/configure_dialog.h2
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp36
-rw-r--r--src/yuzu/configuration/configure_graphics.h2
-rw-r--r--src/yuzu/configuration/configure_graphics.ui91
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp22
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp78
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp2
-rw-r--r--src/yuzu/configuration/configure_motion_touch.ui19
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp10
-rw-r--r--src/yuzu/configuration/configure_per_game.h4
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp4
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.h2
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp8
-rw-r--r--src/yuzu/configuration/configure_system.cpp6
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp4
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.h2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp16
-rw-r--r--src/yuzu/debugger/wait_tree.h8
-rw-r--r--src/yuzu/game_list.cpp30
-rw-r--r--src/yuzu/game_list.h7
-rw-r--r--src/yuzu/game_list_p.h8
-rw-r--r--src/yuzu/game_list_worker.cpp12
-rw-r--r--src/yuzu/game_list_worker.h8
-rw-r--r--src/yuzu/loading_screen.cpp2
-rw-r--r--src/yuzu/loading_screen.h3
-rw-r--r--src/yuzu/main.cpp143
-rw-r--r--src/yuzu/main.h3
-rw-r--r--src/yuzu/uisettings.h2
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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/icons/yuzu.png&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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"};