summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/ipc_helpers.h2
-rw-r--r--src/core/hle/kernel/client_session.cpp1
-rw-r--r--src/core/hle/kernel/client_session.h4
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp5
-rw-r--r--src/core/hle/kernel/hle_ipc.h9
-rw-r--r--src/core/hle/kernel/kernel.cpp1
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/server_session.cpp1
-rw-r--r--src/core/hle/kernel/server_session.h1
-rw-r--r--src/core/hle/kernel/wait_object.cpp2
-rw-r--r--src/core/hle/kernel/wait_object.h1
-rw-r--r--src/core/hle/kernel/writable_event.h2
-rw-r--r--src/core/hle/service/am/applets/applets.cpp2
-rw-r--r--src/core/hle/service/am/applets/applets.h2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp2
-rw-r--r--src/core/hle/service/vi/vi.cpp149
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp49
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h32
-rw-r--r--src/yuzu/configuration/config.cpp5
-rw-r--r--src/yuzu/configuration/configure.ui138
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp43
-rw-r--r--src/yuzu/configuration/configure_dialog.h2
-rw-r--r--src/yuzu/configuration/configure_general.cpp2
-rw-r--r--src/yuzu/configuration/configure_general.ui7
-rw-r--r--src/yuzu/configuration/configure_per_general.cpp4
-rw-r--r--src/yuzu/main.cpp54
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu/ui_settings.h2
29 files changed, 355 insertions, 178 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 0a7142ada..0d6c85aed 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -18,7 +18,7 @@
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/object.h"
-#include "core/hle/kernel/server_port.h"
+#include "core/hle/kernel/server_session.h"
namespace IPC {
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp
index c114eaf99..704e82824 100644
--- a/src/core/hle/kernel/client_session.cpp
+++ b/src/core/hle/kernel/client_session.cpp
@@ -8,6 +8,7 @@
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/session.h"
#include "core/hle/kernel/thread.h"
+#include "core/hle/result.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index 439fbdb35..4c18de69c 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -6,9 +6,9 @@
#include <memory>
#include <string>
-#include "common/common_types.h"
#include "core/hle/kernel/object.h"
-#include "core/hle/result.h"
+
+union ResultCode;
namespace Kernel {
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 61ce7d7e4..5dd855db8 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -22,11 +22,16 @@
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
+#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
namespace Kernel {
+SessionRequestHandler::SessionRequestHandler() = default;
+
+SessionRequestHandler::~SessionRequestHandler() = default;
+
void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) {
server_session->SetHleHandler(shared_from_this());
connected_sessions.push_back(std::move(server_session));
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index e5c0610cd..cb1c5aff3 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -14,8 +14,6 @@
#include "common/swap.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/object.h"
-#include "core/hle/kernel/server_session.h"
-#include "core/hle/kernel/thread.h"
namespace Service {
class ServiceFrameworkBase;
@@ -27,9 +25,13 @@ class Domain;
class HandleTable;
class HLERequestContext;
class Process;
+class ServerSession;
+class Thread;
class ReadableEvent;
class WritableEvent;
+enum class ThreadWakeupReason;
+
/**
* Interface implemented by HLE Session handlers.
* This can be provided to a ServerSession in order to hook into several relevant events
@@ -37,7 +39,8 @@ class WritableEvent;
*/
class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
public:
- virtual ~SessionRequestHandler() = default;
+ SessionRequestHandler();
+ virtual ~SessionRequestHandler();
/**
* Handles a sync request from the emulated application.
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1c2290651..67674cd47 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <array>
#include <atomic>
#include <memory>
#include <mutex>
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index b710104ab..dcc57ae9f 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -14,7 +14,6 @@
#include "common/common_types.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/process_capability.h"
-#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/vm_manager.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
@@ -27,6 +26,7 @@ namespace Kernel {
class KernelCore;
class ResourceLimit;
+class Thread;
struct AddressMapping {
// Address and size must be page-aligned
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 80897f3a4..027434f92 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -6,6 +6,7 @@
#include <utility>
#include "common/assert.h"
+#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index e068db2bf..e0e9d64c8 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -8,7 +8,6 @@
#include <string>
#include <vector>
-#include "common/common_types.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 530ee6af7..90580ed93 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -4,11 +4,11 @@
#include <algorithm>
#include "common/assert.h"
+#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
-#include "core/hle/kernel/timer.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index f4367ee28..d70b67893 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -6,7 +6,6 @@
#include <vector>
#include <boost/smart_ptr/intrusive_ptr.hpp>
-#include "common/common_types.h"
#include "core/hle/kernel/object.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h
index 8fa8d68ee..c9068dd3d 100644
--- a/src/core/hle/kernel/writable_event.h
+++ b/src/core/hle/kernel/writable_event.h
@@ -4,9 +4,7 @@
#pragma once
-#include "common/common_types.h"
#include "core/hle/kernel/object.h"
-#include "core/hle/kernel/wait_object.h"
namespace Kernel {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 7698ca819..a6064c63f 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -6,7 +6,7 @@
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/server_port.h"
+#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index b0a8913c3..37424c379 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -7,7 +7,7 @@
#include <memory>
#include <queue>
#include "common/swap.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/writable_event.h"
union ResultCode;
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index a7bed0040..2254fb46b 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -9,9 +9,9 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/lock.h"
-#include "core/hle/service/hid/hid.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index e7bbcfbac..a3b8cec72 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -19,6 +19,7 @@
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
@@ -502,10 +503,12 @@ private:
void TransactParcel(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- u32 id = rp.Pop<u32>();
- auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
- u32 flags = rp.Pop<u32>();
- LOG_DEBUG(Service_VI, "called, transaction={:X}", static_cast<u32>(transaction));
+ const u32 id = rp.Pop<u32>();
+ const auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
+ const u32 flags = rp.Pop<u32>();
+
+ LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
+ static_cast<u32>(transaction), flags);
auto buffer_queue = nv_flinger->GetBufferQueue(id);
@@ -593,9 +596,10 @@ private:
void AdjustRefcount(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- u32 id = rp.Pop<u32>();
- s32 addval = rp.PopRaw<s32>();
- u32 type = rp.Pop<u32>();
+ const u32 id = rp.Pop<u32>();
+ const s32 addval = rp.PopRaw<s32>();
+ const u32 type = rp.Pop<u32>();
+
LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
type);
@@ -605,11 +609,12 @@ private:
void GetNativeHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- u32 id = rp.Pop<u32>();
- u32 unknown = rp.Pop<u32>();
+ const u32 id = rp.Pop<u32>();
+ const u32 unknown = rp.Pop<u32>();
+
LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
- auto buffer_queue = nv_flinger->GetBufferQueue(id);
+ const auto buffer_queue = nv_flinger->GetBufferQueue(id);
// TODO(Subv): Find out what this actually is.
IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -674,11 +679,12 @@ public:
private:
void SetLayerZ(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u64 layer_id = rp.Pop<u64>();
- u64 z_value = rp.Pop<u64>();
+ const u64 layer_id = rp.Pop<u64>();
+ const u64 z_value = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id,
+ z_value);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -686,8 +692,9 @@ private:
void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- u64 layer_id = rp.Pop<u64>();
- bool visibility = rp.Pop<bool>();
+ const u64 layer_id = rp.Pop<u64>();
+ const bool visibility = rp.Pop<bool>();
+
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:08X}, visibility={}", layer_id,
visibility);
@@ -796,25 +803,27 @@ public:
private:
void CloseDisplay(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u64 display = rp.Pop<u64>();
+ const u64 display = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. display=0x{:016X}", display);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u32 unknown = rp.Pop<u32>();
+ const u32 unknown = rp.Pop<u32>();
rp.Skip(1, false);
- u64 display = rp.Pop<u64>();
- u64 aruid = rp.Pop<u64>();
+ const u64 display = rp.Pop<u64>();
+ const u64 aruid = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI,
+ "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
+ unknown, display, aruid);
- u64 layer_id = nv_flinger->CreateLayer(display);
+ const u64 layer_id = nv_flinger->CreateLayer(display);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -822,11 +831,12 @@ private:
}
void AddToLayerStack(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u32 stack = rp.Pop<u32>();
- u64 layer_id = rp.Pop<u64>();
+ const u32 stack = rp.Pop<u32>();
+ const u64 layer_id = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack,
+ layer_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -834,8 +844,9 @@ private:
void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- u64 layer_id = rp.Pop<u64>();
- bool visibility = rp.Pop<bool>();
+ const u64 layer_id = rp.Pop<u64>();
+ const bool visibility = rp.Pop<bool>();
+
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
visibility);
@@ -914,20 +925,29 @@ private:
}
void CloseDisplay(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u64 display_id = rp.Pop<u64>();
+ const u64 display_id = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
- void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
+ // This literally does nothing internally in the actual service itself,
+ // and just returns a successful result code regardless of the input.
+ void SetDisplayEnabled(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_VI, "called.");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+ void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- u64 display_id = rp.Pop<u64>();
+ const u64 display_id = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
@@ -946,11 +966,12 @@ private:
}
void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u32 scaling_mode = rp.Pop<u32>();
- u64 unknown = rp.Pop<u64>();
+ const u32 scaling_mode = rp.Pop<u32>();
+ const u64 unknown = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. scaling_mode=0x{:08X}, unknown=0x{:016X}",
+ scaling_mode, unknown);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -970,19 +991,19 @@ private:
}
void OpenLayer(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
IPC::RequestParser rp{ctx};
- auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
- auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
+ const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
+ const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
+
+ const std::string display_name(name_buf.begin(), end);
- std::string display_name(name_buf.begin(), end);
+ const u64 layer_id = rp.Pop<u64>();
+ const u64 aruid = rp.Pop<u64>();
- u64 layer_id = rp.Pop<u64>();
- u64 aruid = rp.Pop<u64>();
+ LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
- u64 display_id = nv_flinger->OpenDisplay(display_name);
- u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
+ const u64 display_id = nv_flinger->OpenDisplay(display_name);
+ const u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb{ctx, 4};
@@ -991,17 +1012,17 @@ private:
}
void CreateStrayLayer(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
IPC::RequestParser rp{ctx};
- u32 flags = rp.Pop<u32>();
+ const u32 flags = rp.Pop<u32>();
rp.Pop<u32>(); // padding
- u64 display_id = rp.Pop<u64>();
+ const u64 display_id = rp.Pop<u64>();
+
+ LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id);
// TODO(Subv): What's the difference between a Stray and a Managed layer?
- u64 layer_id = nv_flinger->CreateLayer(display_id);
- u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
+ const u64 layer_id = nv_flinger->CreateLayer(display_id);
+ const u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb{ctx, 6};
@@ -1011,22 +1032,22 @@ private:
}
void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u64 layer_id = rp.Pop<u64>();
+ const u64 layer_id = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
IPC::RequestParser rp{ctx};
- u64 display_id = rp.Pop<u64>();
+ const u64 display_id = rp.Pop<u64>();
+
+ LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
- auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
+ const auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
@@ -1097,7 +1118,7 @@ IApplicationDisplayService::IApplicationDisplayService(
{1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
{1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
{1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
- {1101, nullptr, "SetDisplayEnabled"},
+ {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
{1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
{2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
{2021, nullptr, "CloseLayer"},
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 2b29fc45f..089daf96f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -1014,8 +1014,11 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
Surface surface = res_cache.GetTextureSurface(texture, entry);
if (surface != nullptr) {
- state.texture_units[current_bindpoint].texture = surface->Texture().handle;
- state.texture_units[current_bindpoint].target = surface->Target();
+ const GLuint handle =
+ entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
+ const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target();
+ state.texture_units[current_bindpoint].texture = handle;
+ state.texture_units[current_bindpoint].target = target;
state.texture_units[current_bindpoint].swizzle.r =
MaxwellToGL::SwizzleSource(texture.tic.x_source);
state.texture_units[current_bindpoint].swizzle.g =
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 75b4fe88d..d3dcb9a46 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -44,6 +44,17 @@ struct FormatTuple {
bool compressed;
};
+static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1);
+ if (max_mip_level == 1) {
+ glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0);
+ }
+}
+
void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)};
@@ -530,6 +541,9 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
glActiveTexture(GL_TEXTURE0);
const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
+ gl_internal_format = format_tuple.internal_format;
+ gl_is_compressed = format_tuple.compressed;
+
if (!format_tuple.compressed) {
// Only pre-create the texture for non-compressed textures.
switch (params.target) {
@@ -558,15 +572,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
}
}
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL,
- params.max_mip_level - 1);
- if (params.max_mip_level == 1) {
- glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0);
- }
+ ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level);
LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
SurfaceParams::SurfaceTargetName(params.target));
@@ -864,6 +870,31 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
+void CachedSurface::EnsureTextureView() {
+ if (texture_view.handle != 0)
+ return;
+ // Compressed texture are not being created with immutable storage
+ UNIMPLEMENTED_IF(gl_is_compressed);
+
+ const GLenum target{TargetLayer()};
+
+ texture_view.Create();
+ glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0,
+ params.max_mip_level, 0, 1);
+
+ OpenGLState cur_state = OpenGLState::GetCurState();
+ const auto& old_tex = cur_state.texture_units[0];
+ SCOPE_EXIT({
+ cur_state.texture_units[0] = old_tex;
+ cur_state.Apply();
+ });
+ cur_state.texture_units[0].texture = texture_view.handle;
+ cur_state.texture_units[0].target = target;
+ cur_state.Apply();
+
+ ApplyTextureDefaults(target, params.max_mip_level);
+}
+
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
if (params.type == SurfaceType::Fill)
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index c710aa245..7223700c4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -293,10 +293,31 @@ public:
return texture;
}
+ const OGLTexture& TextureLayer() {
+ if (params.is_layered) {
+ return Texture();
+ }
+ EnsureTextureView();
+ return texture_view;
+ }
+
GLenum Target() const {
return gl_target;
}
+ GLenum TargetLayer() const {
+ using VideoCore::Surface::SurfaceTarget;
+ switch (params.target) {
+ case SurfaceTarget::Texture1D:
+ return GL_TEXTURE_1D_ARRAY;
+ case SurfaceTarget::Texture2D:
+ return GL_TEXTURE_2D_ARRAY;
+ case SurfaceTarget::TextureCubemap:
+ return GL_TEXTURE_CUBE_MAP_ARRAY;
+ }
+ return Target();
+ }
+
const SurfaceParams& GetSurfaceParams() const {
return params;
}
@@ -311,11 +332,16 @@ public:
private:
void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
+ void EnsureTextureView();
+
OGLTexture texture;
+ OGLTexture texture_view;
std::vector<std::vector<u8>> gl_buffer;
- SurfaceParams params;
- GLenum gl_target;
- std::size_t cached_size_in_bytes;
+ SurfaceParams params{};
+ GLenum gl_target{};
+ GLenum gl_internal_format{};
+ bool gl_is_compressed{};
+ std::size_t cached_size_in_bytes{};
};
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index c4349ccc8..165d70e9c 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -470,6 +470,8 @@ void Config::ReadValues() {
qt_config->value("enable_discord_presence", true).toBool();
UISettings::values.screenshot_resolution_factor =
static_cast<u16>(qt_config->value("screenshot_resolution_factor", 0).toUInt());
+ UISettings::values.select_user_on_boot =
+ qt_config->value("select_user_on_boot", false).toBool();
qt_config->beginGroup("UIGameList");
UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
@@ -680,7 +682,7 @@ void Config::SaveValues() {
qt_config->setValue("title_id", QVariant::fromValue<u64>(elem.first));
qt_config->beginWriteArray("disabled");
for (std::size_t j = 0; j < elem.second.size(); ++j) {
- qt_config->setArrayIndex(j);
+ qt_config->setArrayIndex(static_cast<int>(j));
qt_config->setValue("d", QString::fromStdString(elem.second[j]));
}
qt_config->endArray();
@@ -693,6 +695,7 @@ void Config::SaveValues() {
qt_config->setValue("enable_discord_presence", UISettings::values.enable_discord_presence);
qt_config->setValue("screenshot_resolution_factor",
UISettings::values.screenshot_resolution_factor);
+ qt_config->setValue("select_user_on_boot", UISettings::values.select_user_on_boot);
qt_config->beginGroup("UIGameList");
qt_config->setValue("show_unknown", UISettings::values.show_unknown);
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui
index 8706b80d2..ce833b6c8 100644
--- a/src/yuzu/configuration/configure.ui
+++ b/src/yuzu/configuration/configure.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>461</width>
- <height>659</height>
+ <width>382</width>
+ <height>241</height>
</rect>
</property>
<property name="windowTitle">
@@ -15,51 +15,71 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="ConfigureGeneral" name="generalTab">
- <attribute name="title">
- <string>General</string>
- </attribute>
- </widget>
- <widget class="ConfigureGameList" name="gameListTab">
- <attribute name="title">
- <string>Game List</string>
- </attribute>
- </widget>
- <widget class="ConfigureSystem" name="systemTab">
- <attribute name="title">
- <string>System</string>
- </attribute>
- </widget>
- <widget class="ConfigureInputSimple" name="inputTab">
- <attribute name="title">
- <string>Input</string>
- </attribute>
- </widget>
- <widget class="ConfigureGraphics" name="graphicsTab">
- <attribute name="title">
- <string>Graphics</string>
- </attribute>
- </widget>
- <widget class="ConfigureAudio" name="audioTab">
- <attribute name="title">
- <string>Audio</string>
- </attribute>
- </widget>
- <widget class="ConfigureDebug" name="debugTab">
- <attribute name="title">
- <string>Debug</string>
- </attribute>
- </widget>
- <widget class="ConfigureWeb" name="webTab">
- <attribute name="title">
- <string>Web</string>
- </attribute>
- </widget>
- </widget>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QListWidget" name="selectorList">
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="ConfigureGeneral" name="generalTab">
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureGameList" name="gameListTab">
+ <attribute name="title">
+ <string>Game List</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureSystem" name="systemTab">
+ <attribute name="title">
+ <string>System</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureInputSimple" name="inputTab">
+ <attribute name="title">
+ <string>Input</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureGraphics" name="graphicsTab">
+ <attribute name="title">
+ <string>Graphics</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureAudio" name="audioTab">
+ <attribute name="title">
+ <string>Audio</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureDebug" name="debugTab">
+ <attribute name="title">
+ <string>Debug</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureWeb" name="webTab">
+ <attribute name="title">
+ <string>Web</string>
+ </attribute>
+ </widget>
+ </widget>
+ </item>
+ </layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
@@ -78,12 +98,6 @@
<container>1</container>
</customwidget>
<customwidget>
- <class>ConfigureGameList</class>
- <extends>QWidget</extends>
- <header>configuration/configure_gamelist.h</header>
- <container>1</container>
- </customwidget>
- <customwidget>
<class>ConfigureSystem</class>
<extends>QWidget</extends>
<header>configuration/configure_system.h</header>
@@ -102,12 +116,6 @@
<container>1</container>
</customwidget>
<customwidget>
- <class>ConfigureInputSimple</class>
- <extends>QWidget</extends>
- <header>configuration/configure_input_simple.h</header>
- <container>1</container>
- </customwidget>
- <customwidget>
<class>ConfigureGraphics</class>
<extends>QWidget</extends>
<header>configuration/configure_graphics.h</header>
@@ -119,6 +127,18 @@
<header>configuration/configure_web.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ConfigureGameList</class>
+ <extends>QWidget</extends>
+ <header>configuration/configure_gamelist.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>ConfigureInputSimple</class>
+ <extends>QWidget</extends>
+ <header>configuration/configure_input_simple.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 3905423e9..90d7c6372 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <QHash>
+#include <QListWidgetItem>
#include "core/settings.h"
#include "ui_configure.h"
#include "yuzu/configuration/config.h"
@@ -13,6 +15,13 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry
ui->setupUi(this);
ui->generalTab->PopulateHotkeyList(registry);
this->setConfiguration();
+ this->PopulateSelectionList();
+ connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
+ &ConfigureDialog::UpdateVisibleTabs);
+
+ adjustSize();
+
+ ui->selectorList->setCurrentRow(0);
}
ConfigureDialog::~ConfigureDialog() = default;
@@ -30,3 +39,37 @@ void ConfigureDialog::applyConfiguration() {
ui->webTab->applyConfiguration();
Settings::Apply();
}
+
+void ConfigureDialog::PopulateSelectionList() {
+ const std::array<std::pair<QString, QStringList>, 4> items{
+ {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}},
+ {tr("System"), {tr("System"), tr("Audio")}},
+ {tr("Graphics"), {tr("Graphics")}},
+ {tr("Controls"), {tr("Input")}}}};
+
+ for (const auto& entry : items) {
+ auto* const item = new QListWidgetItem(entry.first);
+ item->setData(Qt::UserRole, entry.second);
+
+ ui->selectorList->addItem(item);
+ }
+}
+
+void ConfigureDialog::UpdateVisibleTabs() {
+ const auto items = ui->selectorList->selectedItems();
+ if (items.isEmpty())
+ return;
+
+ const std::map<QString, QWidget*> widgets = {
+ {tr("General"), ui->generalTab}, {tr("System"), ui->systemTab},
+ {tr("Input"), ui->inputTab}, {tr("Graphics"), ui->graphicsTab},
+ {tr("Audio"), ui->audioTab}, {tr("Debug"), ui->debugTab},
+ {tr("Web"), ui->webTab}, {tr("Game List"), ui->gameListTab}};
+
+ ui->tabWidget->clear();
+
+ const QStringList tabs = items[0]->data(Qt::UserRole).toStringList();
+
+ for (const auto& tab : tabs)
+ ui->tabWidget->addTab(widgets.find(tab)->second, tab);
+}
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index f6df7b827..243d9fa09 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -24,6 +24,8 @@ public:
private:
void setConfiguration();
+ void UpdateVisibleTabs();
+ void PopulateSelectionList();
std::unique_ptr<Ui::ConfigureDialog> ui;
};
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 92a441308..4116b6cd7 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -30,6 +30,7 @@ ConfigureGeneral::~ConfigureGeneral() = default;
void ConfigureGeneral::setConfiguration() {
ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
+ ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);
ui->enable_nfc->setChecked(Settings::values.enable_nfc);
@@ -42,6 +43,7 @@ void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) {
void ConfigureGeneral::applyConfiguration() {
UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
+ UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.theme =
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index bf37446c6..dff0ad5d0 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -38,6 +38,13 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="toggle_user_on_boot">
+ <property name="text">
+ <string>Prompt for user on game boot</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
</layout>
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp
index dffaba5ed..e13d2eac8 100644
--- a/src/yuzu/configuration/configure_per_general.cpp
+++ b/src/yuzu/configuration/configure_per_general.cpp
@@ -120,7 +120,7 @@ void ConfigurePerGameGeneral::loadConfiguration() {
QPixmap map;
const auto bytes = control.second->ReadAllBytes();
- map.loadFromData(bytes.data(), bytes.size());
+ map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
@@ -130,7 +130,7 @@ void ConfigurePerGameGeneral::loadConfiguration() {
scene->clear();
QPixmap map;
- map.loadFromData(bytes.data(), bytes.size());
+ map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 01a0f94ab..1d5a2b51a 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -687,10 +687,26 @@ bool GMainWindow::LoadROM(const QString& filename) {
return true;
}
+void GMainWindow::SelectAndSetCurrentUser() {
+ QtProfileSelectionDialog dialog(this);
+ dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
+ Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
+ dialog.setWindowModality(Qt::WindowModal);
+ dialog.exec();
+
+ if (dialog.GetStatus()) {
+ Settings::values.current_user = static_cast<s32>(dialog.GetIndex());
+ }
+}
+
void GMainWindow::BootGame(const QString& filename) {
LOG_INFO(Frontend, "yuzu starting...");
StoreRecentFile(filename); // Put the filename on top of the list
+ if (UISettings::values.select_user_on_boot) {
+ SelectAndSetCurrentUser();
+ }
+
if (!LoadROM(filename))
return;
@@ -827,31 +843,25 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
ASSERT(program_id != 0);
- Service::Account::ProfileManager manager{};
- const auto user_ids = manager.GetAllUsers();
- QStringList list;
- for (const auto& user_id : user_ids) {
- if (user_id == Service::Account::UUID{})
- continue;
- Service::Account::ProfileBase base;
- if (!manager.GetProfileBase(user_id, base))
- continue;
-
- list.push_back(QString::fromStdString(Common::StringFromFixedZeroTerminatedBuffer(
- reinterpret_cast<const char*>(base.username.data()), base.username.size())));
- }
+ const auto select_profile = [this]() -> s32 {
+ QtProfileSelectionDialog dialog(this);
+ dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
+ Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
+ dialog.setWindowModality(Qt::WindowModal);
+ dialog.exec();
- bool ok = false;
- const auto index_string =
- QInputDialog::getItem(this, tr("Select User"),
- tr("Please select the user's save data you would like to open."),
- list, Settings::values.current_user, false, &ok);
- if (!ok)
- return;
+ if (!dialog.GetStatus()) {
+ return -1;
+ }
+
+ return dialog.GetIndex();
+ };
- const auto index = list.indexOf(index_string);
- ASSERT(index != -1 && index < 8);
+ const auto index = select_profile();
+ if (index == -1)
+ return;
+ Service::Account::ProfileManager manager;
const auto user_id = manager.GetUser(index);
ASSERT(user_id);
path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser,
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 4e37f6a2d..d560bf75b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -128,6 +128,8 @@ private:
void ShowTelemetryCallout();
void SetDiscordEnabled(bool state);
+ void SelectAndSetCurrentUser();
+
/**
* Stores the filename in the recently loaded files list.
* The new filename is stored at the beginning of the recently loaded files list.
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index 58ba240fd..82aaeedb0 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -40,6 +40,8 @@ struct Values {
bool confirm_before_closing;
bool first_start;
+ bool select_user_on_boot;
+
// Discord RPC
bool enable_discord_presence;