summaryrefslogtreecommitdiffstats
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/hle_ipc.cpp2
-rw-r--r--src/core/hle/kernel/object.h4
-rw-r--r--src/core/hle/kernel/readable_event.cpp3
-rw-r--r--src/core/hle/kernel/svc.cpp89
-rw-r--r--src/core/hle/kernel/thread.h21
-rw-r--r--src/core/hle/service/am/am.cpp8
-rw-r--r--src/core/hle/service/am/applets/applets.cpp6
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp2
-rw-r--r--src/core/hle/service/audio/audout_u.cpp2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp352
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp4
-rw-r--r--src/core/hle/service/btm/btm.cpp8
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp6
-rw-r--r--src/core/hle/service/nifm/nifm.cpp4
-rw-r--r--src/core/hle/service/nim/nim.cpp2
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp2
-rw-r--r--src/core/hle/service/set/set.cpp56
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp2
-rw-r--r--src/video_core/dma_pusher.cpp7
-rw-r--r--src/video_core/engines/engine_upload.cpp6
-rw-r--r--src/video_core/engines/engine_upload.h8
-rw-r--r--src/video_core/engines/maxwell_3d.cpp38
-rw-r--r--src/video_core/engines/maxwell_3d.h3
-rw-r--r--src/video_core/engines/shader_bytecode.h22
-rw-r--r--src/video_core/gpu_thread.cpp2
-rw-r--r--src/video_core/gpu_thread.h8
-rw-r--r--src/video_core/macro_interpreter.cpp6
-rw-r--r--src/video_core/rasterizer_cache.h3
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_device.h14
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp663
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp54
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.h28
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp14
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp7
-rw-r--r--src/video_core/shader/decode/arithmetic.cpp3
-rw-r--r--src/video_core/shader/decode/arithmetic_half.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic_half_immediate.cpp3
-rw-r--r--src/video_core/shader/decode/arithmetic_immediate.cpp2
-rw-r--r--src/video_core/shader/decode/arithmetic_integer_immediate.cpp2
-rw-r--r--src/video_core/shader/decode/bfe.cpp2
-rw-r--r--src/video_core/shader/decode/bfi.cpp2
-rw-r--r--src/video_core/shader/decode/ffma.cpp2
-rw-r--r--src/video_core/shader/decode/float_set.cpp2
-rw-r--r--src/video_core/shader/decode/float_set_predicate.cpp2
-rw-r--r--src/video_core/shader/decode/half_set.cpp3
-rw-r--r--src/video_core/shader/decode/half_set_predicate.cpp2
-rw-r--r--src/video_core/shader/decode/integer_set.cpp3
-rw-r--r--src/video_core/shader/decode/integer_set_predicate.cpp2
-rw-r--r--src/video_core/shader/decode/memory.cpp28
-rw-r--r--src/video_core/shader/decode/other.cpp14
-rw-r--r--src/video_core/shader/decode/predicate_set_predicate.cpp2
-rw-r--r--src/video_core/shader/decode/predicate_set_register.cpp2
-rw-r--r--src/video_core/shader/decode/register_set_predicate.cpp2
-rw-r--r--src/video_core/shader/decode/shift.cpp2
-rw-r--r--src/video_core/shader/decode/video.cpp2
-rw-r--r--src/video_core/shader/shader_ir.cpp24
-rw-r--r--src/video_core/shader/shader_ir.h88
-rw-r--r--src/video_core/shader/track.cpp12
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/applets/error.cpp2
-rw-r--r--src/yuzu/applets/profile_select.cpp4
-rw-r--r--src/yuzu/bootmanager.cpp7
-rw-r--r--src/yuzu/configuration/config.cpp854
-rw-r--r--src/yuzu/configuration/config.h34
-rw-r--r--src/yuzu/configuration/configure_audio.cpp14
-rw-r--r--src/yuzu/configuration/configure_gamelist.cpp8
-rw-r--r--src/yuzu/configuration/configure_general.cpp3
-rw-r--r--src/yuzu/configuration/configure_input.cpp13
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp153
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.cpp75
-rw-r--r--src/yuzu/configuration/configure_per_general.cpp14
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp2
-rw-r--r--src/yuzu/configuration/configure_system.cpp5
-rw-r--r--src/yuzu/configuration/configure_web.cpp24
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoints.cpp2
-rw-r--r--src/yuzu/debugger/profiler.cpp4
-rw-r--r--src/yuzu/debugger/wait_tree.cpp39
-rw-r--r--src/yuzu/game_list.cpp103
-rw-r--r--src/yuzu/game_list.h2
-rw-r--r--src/yuzu/game_list_p.h25
-rw-r--r--src/yuzu/game_list_worker.cpp4
-rw-r--r--src/yuzu/loading_screen.cpp18
-rw-r--r--src/yuzu/util/spinbox.cpp278
-rw-r--r--src/yuzu/util/spinbox.h86
-rw-r--r--src/yuzu/util/util.cpp18
92 files changed, 1953 insertions, 1530 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index ac0e1d796..5bb139483 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -438,7 +438,7 @@ inline float RequestParser::Pop() {
template <>
inline double RequestParser::Pop() {
const u64 value = Pop<u64>();
- float real;
+ double real;
std::memcpy(&real, &value, sizeof(real));
return real;
}
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index dd4eb0978..f3da525d6 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -58,7 +58,7 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread(
auto& kernel = Core::System::GetInstance().Kernel();
if (!writable_event) {
// Create event if not provided
- const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic,
"HLE Pause Event: " + reason);
writable_event = pair.writable;
}
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 332876c27..2821176a7 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -33,8 +33,8 @@ enum class HandleType : u32 {
};
enum class ResetType {
- OneShot, ///< Reset automatically on object acquisition
- Sticky, ///< Never reset automatically
+ Automatic, ///< Reset automatically on object acquisition
+ Manual, ///< Never reset automatically
};
class Object : NonCopyable {
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
index c2b798a4e..06463cd26 100644
--- a/src/core/hle/kernel/readable_event.cpp
+++ b/src/core/hle/kernel/readable_event.cpp
@@ -21,8 +21,9 @@ bool ReadableEvent::ShouldWait(const Thread* thread) const {
void ReadableEvent::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
- if (reset_type == ResetType::OneShot)
+ if (reset_type == ResetType::Automatic) {
signaled = false;
+ }
}
void ReadableEvent::Signal() {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 2dcf174c5..5a5851f66 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1255,8 +1255,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
return vm_manager.MapCodeMemory(dst_address, src_address, size);
}
-ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
- u64 src_address, u64 size) {
+static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle,
+ u64 dst_address, u64 src_address, u64 size) {
LOG_DEBUG(Kernel_SVC,
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
"size=0x{:016X}",
@@ -1342,7 +1342,7 @@ static void ExitProcess(Core::System& system) {
/// Creates a new thread
static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
VAddr stack_top, u32 priority, s32 processor_id) {
- LOG_TRACE(Kernel_SVC,
+ LOG_DEBUG(Kernel_SVC,
"called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, "
"threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}",
entry_point, arg, stack_top, priority, processor_id, *out_handle);
@@ -1402,7 +1402,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
/// Starts the thread for the provided handle
static ResultCode StartThread(Core::System& system, Handle thread_handle) {
- LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
+ LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
@@ -1425,7 +1425,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
/// Called when a thread exits
static void ExitThread(Core::System& system) {
- LOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
+ LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
current_thread->Stop();
@@ -1435,7 +1435,7 @@ static void ExitThread(Core::System& system) {
/// Sleep the current thread
static void SleepThread(Core::System& system, s64 nanoseconds) {
- LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
+ LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds);
enum class SleepType : s64 {
YieldWithoutLoadBalancing = 0,
@@ -1880,52 +1880,59 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
}
static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core,
- u64 mask) {
- LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:016X}, core=0x{:X}", thread_handle,
- mask, core);
+ u64 affinity_mask) {
+ LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}",
+ thread_handle, core, affinity_mask);
- const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
- const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
- if (!thread) {
- LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
- thread_handle);
- return ERR_INVALID_HANDLE;
- }
+ const auto* const current_process = system.Kernel().CurrentProcess();
if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
- const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore();
+ const u8 ideal_cpu_core = current_process->GetIdealCore();
ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL));
// Set the target CPU to the ideal core specified by the process.
core = ideal_cpu_core;
- mask = 1ULL << core;
- }
-
- if (mask == 0) {
- LOG_ERROR(Kernel_SVC, "Mask is 0");
- return ERR_INVALID_COMBINATION;
- }
+ affinity_mask = 1ULL << core;
+ } else {
+ const u64 core_mask = current_process->GetCoreMask();
+
+ if ((core_mask | affinity_mask) != core_mask) {
+ LOG_ERROR(
+ Kernel_SVC,
+ "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})",
+ core_mask, affinity_mask);
+ return ERR_INVALID_PROCESSOR_ID;
+ }
- /// This value is used to only change the affinity mask without changing the current ideal core.
- static constexpr u32 OnlyChangeMask = static_cast<u32>(-3);
+ if (affinity_mask == 0) {
+ LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero.");
+ return ERR_INVALID_COMBINATION;
+ }
- if (core == OnlyChangeMask) {
- core = thread->GetIdealCore();
- } else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(-1)) {
- LOG_ERROR(Kernel_SVC, "Invalid core specified, got {}", core);
- return ERR_INVALID_PROCESSOR_ID;
+ if (core < Core::NUM_CPU_CORES) {
+ if ((affinity_mask & (1ULL << core)) == 0) {
+ LOG_ERROR(Kernel_SVC,
+ "Core is not enabled for the current mask, core={}, mask={:016X}", core,
+ affinity_mask);
+ return ERR_INVALID_COMBINATION;
+ }
+ } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) &&
+ core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) {
+ LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core);
+ return ERR_INVALID_PROCESSOR_ID;
+ }
}
- // Error out if the input core isn't enabled in the input mask.
- if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) {
- LOG_ERROR(Kernel_SVC, "Core is not enabled for the current mask, core={}, mask={:016X}",
- core, mask);
- return ERR_INVALID_COMBINATION;
+ const auto& handle_table = current_process->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
+ thread_handle);
+ return ERR_INVALID_HANDLE;
}
- thread->ChangeCore(core, mask);
-
+ thread->ChangeCore(core, affinity_mask);
return RESULT_SUCCESS;
}
@@ -1980,7 +1987,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle
auto& kernel = system.Kernel();
const auto [readable_event, writable_event] =
- WritableEvent::CreateEventPair(kernel, ResetType::Sticky, "CreateEvent");
+ WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent");
HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
@@ -2183,8 +2190,8 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
return RESULT_SUCCESS;
}
-ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
- u32 out_thread_ids_size, Handle debug_handle) {
+static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
+ u32 out_thread_ids_size, Handle debug_handle) {
// TODO: Handle this case when debug events are supported.
UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index f07332f02..b4b9cda7c 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -30,12 +30,21 @@ enum ThreadPriority : u32 {
};
enum ThreadProcessorId : s32 {
- THREADPROCESSORID_IDEAL = -2, ///< Run thread on the ideal core specified by the process.
- THREADPROCESSORID_0 = 0, ///< Run thread on core 0
- THREADPROCESSORID_1 = 1, ///< Run thread on core 1
- THREADPROCESSORID_2 = 2, ///< Run thread on core 2
- THREADPROCESSORID_3 = 3, ///< Run thread on core 3
- THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
+ /// Indicates that no particular processor core is preferred.
+ THREADPROCESSORID_DONT_CARE = -1,
+
+ /// Run thread on the ideal core specified by the process.
+ THREADPROCESSORID_IDEAL = -2,
+
+ /// Indicates that the preferred processor ID shouldn't be updated in
+ /// a core mask setting operation.
+ THREADPROCESSORID_DONT_UPDATE = -3,
+
+ THREADPROCESSORID_0 = 0, ///< Run thread on core 0
+ THREADPROCESSORID_1 = 1, ///< Run thread on core 1
+ THREADPROCESSORID_2 = 2, ///< Run thread on core 2
+ THREADPROCESSORID_3 = 3, ///< Run thread on core 3
+ THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
/// Allowed CPU mask
THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 26a665bfd..1a32a109f 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -276,7 +276,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+ launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"ISelfController:LaunchableEvent");
}
@@ -442,10 +442,10 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c
AppletMessageQueue::AppletMessageQueue() {
auto& kernel = Core::System::GetInstance().Kernel();
- on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+ on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"AMMessageQueue:OnMessageRecieved");
on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged");
+ kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged");
}
AppletMessageQueue::~AppletMessageQueue() = default;
@@ -835,6 +835,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
+ return;
}
std::memcpy(backing.buffer.data() + offset, data.data(), data.size());
@@ -857,6 +858,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
+ return;
}
ctx.WriteBuffer(backing.buffer.data() + offset, size);
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 7f70b10df..e812c66e9 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -26,11 +26,11 @@ namespace Service::AM::Applets {
AppletDataBroker::AppletDataBroker() {
auto& kernel = Core::System::GetInstance().Kernel();
state_changed_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:StateChangedEvent");
+ kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:StateChangedEvent");
pop_out_data_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:PopDataOutEvent");
+ kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopDataOutEvent");
pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
+ kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
}
AppletDataBroker::~AppletDataBroker() = default;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 51d8c26b4..bd4e38461 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -68,7 +68,7 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+ aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"GetAddOnContentListChanged:Event");
}
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 12875fb42..6ba41b20a 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -67,7 +67,7 @@ public:
// This is the event handle used to check if the audio buffer was released
auto& system = Core::System::GetInstance();
buffer_event = Kernel::WritableEvent::CreateEventPair(
- system.Kernel(), Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
+ system.Kernel(), Kernel::ResetType::Manual, "IAudioOutBufferReleased");
stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
audio_params.channel_count, std::move(unique_name),
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 1dde6edb7..75db0c2dc 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -8,6 +8,7 @@
#include "audio_core/audio_renderer.h"
#include "common/alignment.h"
+#include "common/bit_util.h"
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "common/string_util.h"
@@ -46,7 +47,7 @@ public:
auto& system = Core::System::GetInstance();
system_event = Kernel::WritableEvent::CreateEventPair(
- system.Kernel(), Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
+ system.Kernel(), Kernel::ResetType::Manual, "IAudioRenderer:SystemEvent");
renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), audren_params,
system_event.writable);
}
@@ -178,7 +179,7 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IAudioOutBufferReleasedEvent");
}
@@ -262,64 +263,304 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
OpenAudioRendererImpl(ctx);
}
+static u64 CalculateNumPerformanceEntries(const AudioCore::AudioRendererParameter& params) {
+ // +1 represents the final mix.
+ return u64{params.effect_count} + params.submix_count + params.sink_count + params.voice_count +
+ 1;
+}
+
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
LOG_DEBUG(Service_Audio, "called");
- u64 buffer_sz = Common::AlignUp(4 * params.mix_buffer_count, 0x40);
- buffer_sz += params.submix_count * 1024;
- buffer_sz += 0x940 * (params.submix_count + 1);
- buffer_sz += 0x3F0 * params.voice_count;
- buffer_sz += Common::AlignUp(8 * (params.submix_count + 1), 0x10);
- buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
- buffer_sz += Common::AlignUp(
- (0x3C0 * (params.sink_count + params.submix_count) + 4 * params.sample_count) *
- (params.mix_buffer_count + 6),
- 0x40);
-
- if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
- const u32 count = params.submix_count + 1;
- u64 node_count = Common::AlignUp(count, 0x40);
- const u64 node_state_buffer_sz =
- 4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8);
- u64 edge_matrix_buffer_sz = 0;
- node_count = Common::AlignUp(count * count, 0x40);
- if (node_count >> 31 != 0) {
- edge_matrix_buffer_sz = (node_count | 7) / 8;
- } else {
- edge_matrix_buffer_sz = node_count / 8;
+ // Several calculations below align the sizes being calculated
+ // onto a 64 byte boundary.
+ static constexpr u64 buffer_alignment_size = 64;
+
+ // Some calculations that calculate portions of the buffer
+ // that will contain information, on the other hand, align
+ // the result of some of their calcularions on a 16 byte boundary.
+ static constexpr u64 info_field_alignment_size = 16;
+
+ // Maximum detail entries that may exist at one time for performance
+ // frame statistics.
+ static constexpr u64 max_perf_detail_entries = 100;
+
+ // Size of the data structure representing the bulk of the voice-related state.
+ static constexpr u64 voice_state_size = 0x100;
+
+ // Size of the upsampler manager data structure
+ constexpr u64 upsampler_manager_size = 0x48;
+
+ // Calculates the part of the size that relates to mix buffers.
+ const auto calculate_mix_buffer_sizes = [](const AudioCore::AudioRendererParameter& params) {
+ // As of 8.0.0 this is the maximum on voice channels.
+ constexpr u64 max_voice_channels = 6;
+
+ // The service expects the sample_count member of the parameters to either be
+ // a value of 160 or 240, so the maximum sample count is assumed in order
+ // to adequately handle all values at runtime.
+ constexpr u64 default_max_sample_count = 240;
+
+ const u64 total_mix_buffers = params.mix_buffer_count + max_voice_channels;
+
+ u64 size = 0;
+ size += total_mix_buffers * (sizeof(s32) * params.sample_count);
+ size += total_mix_buffers * (sizeof(s32) * default_max_sample_count);
+ size += u64{params.submix_count} + params.sink_count;
+ size = Common::AlignUp(size, buffer_alignment_size);
+ size += Common::AlignUp(params.unknown_30, buffer_alignment_size);
+ size += Common::AlignUp(sizeof(s32) * params.mix_buffer_count, buffer_alignment_size);
+ return size;
+ };
+
+ // Calculates the portion of the size related to the mix data (and the sorting thereof).
+ const auto calculate_mix_info_size = [this](const AudioCore::AudioRendererParameter& params) {
+ // The size of the mixing info data structure.
+ constexpr u64 mix_info_size = 0x940;
+
+ // Consists of total submixes with the final mix included.
+ const u64 total_mix_count = u64{params.submix_count} + 1;
+
+ // The total number of effects that may be available to the audio renderer at any time.
+ constexpr u64 max_effects = 256;
+
+ // Calculates the part of the size related to the audio node state.
+ // This will only be used if the audio revision supports the splitter.
+ const auto calculate_node_state_size = [](std::size_t num_nodes) {
+ // Internally within a nodestate, it appears to use a data structure
+ // similar to a std::bitset<64> twice.
+ constexpr u64 bit_size = Common::BitSize<u64>();
+ constexpr u64 num_bitsets = 2;
+
+ // Node state instances have three states internally for performing
+ // depth-first searches of nodes. Initialized, Found, and Done Sorting.
+ constexpr u64 num_states = 3;
+
+ u64 size = 0;
+ size += (num_nodes * num_nodes) * sizeof(s32);
+ size += num_states * (num_nodes * sizeof(s32));
+ size += num_bitsets * (Common::AlignUp(num_nodes, bit_size) / Common::BitSize<u8>());
+ return size;
+ };
+
+ // Calculates the part of the size related to the adjacency (aka edge) matrix.
+ const auto calculate_edge_matrix_size = [](std::size_t num_nodes) {
+ return (num_nodes * num_nodes) * sizeof(s32);
+ };
+
+ u64 size = 0;
+ size += Common::AlignUp(sizeof(void*) * total_mix_count, info_field_alignment_size);
+ size += Common::AlignUp(mix_info_size * total_mix_count, info_field_alignment_size);
+ size += Common::AlignUp(sizeof(s32) * max_effects * params.submix_count,
+ info_field_alignment_size);
+
+ if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
+ size += Common::AlignUp(calculate_node_state_size(total_mix_count) +
+ calculate_edge_matrix_size(total_mix_count),
+ info_field_alignment_size);
}
- buffer_sz += Common::AlignUp(node_state_buffer_sz + edge_matrix_buffer_sz, 0x10);
- }
- buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50;
- if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
- buffer_sz += 0xE0 * params.num_splitter_send_channels;
- buffer_sz += 0x20 * params.splitter_count;
- buffer_sz += Common::AlignUp(4 * params.num_splitter_send_channels, 0x10);
- }
- buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count;
- u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count +
- ((params.voice_count * 256) | 0x40);
-
- if (params.performance_frame_count >= 1) {
- output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count +
- 16 * params.voice_count + 16) +
- 0x658) *
- (params.performance_frame_count + 1) +
- 0xc0,
- 0x40) +
- output_sz;
- }
- output_sz = Common::AlignUp(output_sz + 0x1807e, 0x1000);
+ return size;
+ };
- IPC::ResponseBuilder rb{ctx, 4};
+ // Calculates the part of the size related to voice channel info.
+ const auto calculate_voice_info_size = [](const AudioCore::AudioRendererParameter& params) {
+ constexpr u64 voice_info_size = 0x220;
+ constexpr u64 voice_resource_size = 0xD0;
+
+ u64 size = 0;
+ size += Common::AlignUp(sizeof(void*) * params.voice_count, info_field_alignment_size);
+ size += Common::AlignUp(voice_info_size * params.voice_count, info_field_alignment_size);
+ size +=
+ Common::AlignUp(voice_resource_size * params.voice_count, info_field_alignment_size);
+ size += Common::AlignUp(voice_state_size * params.voice_count, info_field_alignment_size);
+ return size;
+ };
+
+ // Calculates the part of the size related to memory pools.
+ const auto calculate_memory_pools_size = [](const AudioCore::AudioRendererParameter& params) {
+ const u64 num_memory_pools = sizeof(s32) * (u64{params.effect_count} + params.voice_count);
+ const u64 memory_pool_info_size = 0x20;
+ return Common::AlignUp(num_memory_pools * memory_pool_info_size, info_field_alignment_size);
+ };
+
+ // Calculates the part of the size related to the splitter context.
+ const auto calculate_splitter_context_size =
+ [this](const AudioCore::AudioRendererParameter& params) -> u64 {
+ if (!IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
+ return 0;
+ }
+
+ constexpr u64 splitter_info_size = 0x20;
+ constexpr u64 splitter_destination_data_size = 0xE0;
+
+ u64 size = 0;
+ size += params.num_splitter_send_channels;
+ size +=
+ Common::AlignUp(splitter_info_size * params.splitter_count, info_field_alignment_size);
+ size += Common::AlignUp(splitter_destination_data_size * params.num_splitter_send_channels,
+ info_field_alignment_size);
+
+ return size;
+ };
+
+ // Calculates the part of the size related to the upsampler info.
+ const auto calculate_upsampler_info_size = [](const AudioCore::AudioRendererParameter& params) {
+ constexpr u64 upsampler_info_size = 0x280;
+ // Yes, using the buffer size over info alignment size is intentional here.
+ return Common::AlignUp(upsampler_info_size * (u64{params.submix_count} + params.sink_count),
+ buffer_alignment_size);
+ };
+
+ // Calculates the part of the size related to effect info.
+ const auto calculate_effect_info_size = [](const AudioCore::AudioRendererParameter& params) {
+ constexpr u64 effect_info_size = 0x2B0;
+ return Common::AlignUp(effect_info_size * params.effect_count, info_field_alignment_size);
+ };
+
+ // Calculates the part of the size related to audio sink info.
+ const auto calculate_sink_info_size = [](const AudioCore::AudioRendererParameter& params) {
+ const u64 sink_info_size = 0x170;
+ return Common::AlignUp(sink_info_size * params.sink_count, info_field_alignment_size);
+ };
+
+ // Calculates the part of the size related to voice state info.
+ const auto calculate_voice_state_size = [](const AudioCore::AudioRendererParameter& params) {
+ const u64 voice_state_size = 0x100;
+ const u64 additional_size = buffer_alignment_size - 1;
+ return Common::AlignUp(voice_state_size * params.voice_count + additional_size,
+ info_field_alignment_size);
+ };
+
+ // Calculates the part of the size related to performance statistics.
+ const auto calculate_perf_size = [this](const AudioCore::AudioRendererParameter& params) {
+ // Extra size value appended to the end of the calculation.
+ constexpr u64 appended = 128;
+
+ // Whether or not we assume the newer version of performance metrics data structures.
+ const bool is_v2 =
+ IsFeatureSupported(AudioFeatures::PerformanceMetricsVersion2, params.revision);
+
+ // Data structure sizes
+ constexpr u64 perf_statistics_size = 0x0C;
+ const u64 header_size = is_v2 ? 0x30 : 0x18;
+ const u64 entry_size = is_v2 ? 0x18 : 0x10;
+ const u64 detail_size = is_v2 ? 0x18 : 0x10;
+
+ const u64 entry_count = CalculateNumPerformanceEntries(params);
+ const u64 size_per_frame =
+ header_size + (entry_size * entry_count) + (detail_size * max_perf_detail_entries);
+
+ u64 size = 0;
+ size += Common::AlignUp(size_per_frame * params.performance_frame_count + 1,
+ buffer_alignment_size);
+ size += Common::AlignUp(perf_statistics_size, buffer_alignment_size);
+ size += appended;
+ return size;
+ };
+
+ // Calculates the part of the size that relates to the audio command buffer.
+ const auto calculate_command_buffer_size =
+ [this](const AudioCore::AudioRendererParameter& params) {
+ constexpr u64 alignment = (buffer_alignment_size - 1) * 2;
+
+ if (!IsFeatureSupported(AudioFeatures::VariadicCommandBuffer, params.revision)) {
+ constexpr u64 command_buffer_size = 0x18000;
+
+ return command_buffer_size + alignment;
+ }
+
+ // When the variadic command buffer is supported, this means
+ // the command generator for the audio renderer can issue commands
+ // that are (as one would expect), variable in size. So what we need to do
+ // is determine the maximum possible size for a few command data structures
+ // then multiply them by the amount of present commands indicated by the given
+ // respective audio parameters.
+
+ constexpr u64 max_biquad_filters = 2;
+ constexpr u64 max_mix_buffers = 24;
+
+ constexpr u64 biquad_filter_command_size = 0x2C;
+
+ constexpr u64 depop_mix_command_size = 0x24;
+ constexpr u64 depop_setup_command_size = 0x50;
+
+ constexpr u64 effect_command_max_size = 0x540;
+
+ constexpr u64 mix_command_size = 0x1C;
+ constexpr u64 mix_ramp_command_size = 0x24;
+ constexpr u64 mix_ramp_grouped_command_size = 0x13C;
+
+ constexpr u64 perf_command_size = 0x28;
+
+ constexpr u64 sink_command_size = 0x130;
+
+ constexpr u64 submix_command_max_size =
+ depop_mix_command_size + (mix_command_size * max_mix_buffers) * max_mix_buffers;
+
+ constexpr u64 volume_command_size = 0x1C;
+ constexpr u64 volume_ramp_command_size = 0x20;
+
+ constexpr u64 voice_biquad_filter_command_size =
+ biquad_filter_command_size * max_biquad_filters;
+ constexpr u64 voice_data_command_size = 0x9C;
+ const u64 voice_command_max_size =
+ (params.splitter_count * depop_setup_command_size) +
+ (voice_data_command_size + voice_biquad_filter_command_size +
+ volume_ramp_command_size + mix_ramp_grouped_command_size);
+
+ // Now calculate the individual elements that comprise the size and add them together.
+ const u64 effect_commands_size = params.effect_count * effect_command_max_size;
+
+ const u64 final_mix_commands_size =
+ depop_mix_command_size + volume_command_size * max_mix_buffers;
+ const u64 perf_commands_size =
+ perf_command_size *
+ (CalculateNumPerformanceEntries(params) + max_perf_detail_entries);
+
+ const u64 sink_commands_size = params.sink_count * sink_command_size;
+
+ const u64 splitter_commands_size =
+ params.num_splitter_send_channels * max_mix_buffers * mix_ramp_command_size;
+
+ const u64 submix_commands_size = params.submix_count * submix_command_max_size;
+
+ const u64 voice_commands_size = params.voice_count * voice_command_max_size;
+
+ return effect_commands_size + final_mix_commands_size + perf_commands_size +
+ sink_commands_size + splitter_commands_size + submix_commands_size +
+ voice_commands_size + alignment;
+ };
+
+ IPC::RequestParser rp{ctx};
+ const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
+
+ u64 size = 0;
+ size += calculate_mix_buffer_sizes(params);
+ size += calculate_mix_info_size(params);
+ size += calculate_voice_info_size(params);
+ size += upsampler_manager_size;
+ size += calculate_memory_pools_size(params);
+ size += calculate_splitter_context_size(params);
+
+ size = Common::AlignUp(size, buffer_alignment_size);
+
+ size += calculate_upsampler_info_size(params);
+ size += calculate_effect_info_size(params);
+ size += calculate_sink_info_size(params);
+ size += calculate_voice_state_size(params);
+ size += calculate_perf_size(params);
+ size += calculate_command_buffer_size(params);
+
+ // finally, 4KB page align the size, and we're done.
+ size = Common::AlignUp(size, 4096);
+
+ IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
- rb.Push<u64>(output_sz);
+ rb.Push<u64>(size);
- LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", output_sz);
+ LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", size);
}
void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) {
@@ -357,10 +598,15 @@ void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) {
}
bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
- u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
+ // Byte swap
+ const u32_be version_num = revision - Common::MakeMagic('R', 'E', 'V', '0');
+
switch (feature) {
case AudioFeatures::Splitter:
- return version_num >= 2u;
+ return version_num >= 2U;
+ case AudioFeatures::PerformanceMetricsVersion2:
+ case AudioFeatures::VariadicCommandBuffer:
+ return version_num >= 5U;
default:
return false;
}
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index e55d25973..1d3c8df61 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -28,6 +28,8 @@ private:
enum class AudioFeatures : u32 {
Splitter,
+ PerformanceMetricsVersion2,
+ VariadicCommandBuffer,
};
bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const;
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 974ff8e1a..3c7ca2c44 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -34,8 +34,8 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- register_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
- "BT:RegisterEvent");
+ register_event = Kernel::WritableEvent::CreateEventPair(
+ kernel, Kernel::ResetType::Automatic, "BT:RegisterEvent");
}
private:
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 4f15c3f19..b439ee7ec 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -57,13 +57,13 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IBtmUserCore:ScanEvent");
connection_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConnectionEvent");
+ kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ConnectionEvent");
service_discovery = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery");
- config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ kernel, Kernel::ResetType::Automatic, "IBtmUserCore:Discovery");
+ config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IBtmUserCore:ConfigEvent");
}
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index e7fc7a619..fdd6d79a2 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -170,7 +170,7 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
void Controller_NPad::OnInit() {
auto& kernel = Core::System::GetInstance().Kernel();
styleset_changed_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
+ kernel, Kernel::ResetType::Automatic, "npad:NpadStyleSetChanged");
if (!IsControllerActivated()) {
return;
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index c6babdd4d..a5cb06f8a 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -26,7 +26,7 @@ constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152);
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {
auto& kernel = Core::System::GetInstance().Kernel();
- nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IUser:NFCTagDetected");
}
@@ -67,9 +67,9 @@ public:
auto& kernel = Core::System::GetInstance().Kernel();
deactivate_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
+ kernel, Kernel::ResetType::Automatic, "IUser:DeactivateEvent");
availability_change_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent");
+ kernel, Kernel::ResetType::Automatic, "IUser:AvailabilityChangeEvent");
}
private:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index f92571008..76b12b482 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -62,9 +62,9 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IRequest:Event1");
- event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"IRequest:Event2");
}
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 0dabcd23b..f319a3ca1 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -141,7 +141,7 @@ public:
auto& kernel = Core::System::GetInstance().Kernel();
finished_event = Kernel::WritableEvent::CreateEventPair(
- kernel, Kernel::ResetType::OneShot,
+ kernel, Kernel::ResetType::Automatic,
"IEnsureNetworkClockAvailabilityService:FinishEvent");
}
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 3b9ab4b14..b60fc748b 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -129,7 +129,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
- query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+ query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
"NVDRV::query_event");
}
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 4d150fc71..5731e815f 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -16,7 +16,7 @@ namespace Service::NVFlinger {
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
auto& kernel = Core::System::GetInstance().Kernel();
- buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+ buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
"BufferQueue NativeHandle");
}
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index 4ecb6bcef..298d85011 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -2,16 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <chrono>
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/client_port.h"
-#include "core/hle/kernel/client_session.h"
#include "core/hle/service/set/set.h"
#include "core/settings.h"
namespace Service::Set {
-
+namespace {
constexpr std::array<LanguageCode, 17> available_language_codes = {{
LanguageCode::JA,
LanguageCode::EN_US,
@@ -32,41 +31,35 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{
LanguageCode::ZH_HANT,
}};
-constexpr std::size_t pre4_0_0_max_entries = 0xF;
-constexpr std::size_t post4_0_0_max_entries = 0x40;
+constexpr std::size_t pre4_0_0_max_entries = 15;
+constexpr std::size_t post4_0_0_max_entries = 17;
constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625};
-LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
- return available_language_codes.at(index);
+void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_language_codes) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(static_cast<u32>(num_language_codes));
}
-template <std::size_t size>
-static std::array<LanguageCode, size> MakeLanguageCodeSubset() {
- std::array<LanguageCode, size> arr;
- std::copy_n(available_language_codes.begin(), size, arr.begin());
- return arr;
+void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t max_size) {
+ const std::size_t requested_amount = ctx.GetWriteBufferSize() / sizeof(LanguageCode);
+ const std::size_t copy_amount = std::min(requested_amount, max_size);
+ const std::size_t copy_size = copy_amount * sizeof(LanguageCode);
+
+ ctx.WriteBuffer(available_language_codes.data(), copy_size);
+ PushResponseLanguageCode(ctx, copy_amount);
}
+} // Anonymous namespace
-static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t max_size) {
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- if (available_language_codes.size() > max_size) {
- rb.Push(static_cast<u32>(max_size));
- } else {
- rb.Push(static_cast<u32>(available_language_codes.size()));
- }
+LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
+ return available_language_codes.at(index);
}
void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
- if (available_language_codes.size() > pre4_0_0_max_entries) {
- ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>());
- } else {
- ctx.WriteBuffer(available_language_codes);
- }
- PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
+ GetAvailableLanguageCodesImpl(ctx, pre4_0_0_max_entries);
}
void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) {
@@ -87,12 +80,7 @@ void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) {
void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
- if (available_language_codes.size() > post4_0_0_max_entries) {
- ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>());
- } else {
- ctx.WriteBuffer(available_language_codes);
- }
- PushResponseLanguageCode(ctx, post4_0_0_max_entries);
+ GetAvailableLanguageCodesImpl(ctx, post4_0_0_max_entries);
}
void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
@@ -102,9 +90,9 @@ void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
}
void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) {
- PushResponseLanguageCode(ctx, post4_0_0_max_entries);
-
LOG_DEBUG(Service_SET, "called");
+
+ PushResponseLanguageCode(ctx, post4_0_0_max_entries);
}
void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 01d80311b..a8d088305 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -17,7 +17,7 @@ namespace Service::VI {
Display::Display(u64 id, std::string name) : id{id}, name{std::move(name)} {
auto& kernel = Core::System::GetInstance().Kernel();
- vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+ vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
fmt::format("Display VSync Event {}", id));
}
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 036e66f05..3175579cc 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -40,6 +40,13 @@ bool DmaPusher::Step() {
}
const CommandList& command_list{dma_pushbuffer.front()};
+ ASSERT_OR_EXECUTE(!command_list.empty(), {
+ // Somehow the command_list is empty, in order to avoid a crash
+ // We ignore it and assume its size is 0.
+ dma_pushbuffer.pop();
+ dma_pushbuffer_subindex = 0;
+ return true;
+ });
const CommandListHeader command_list_header{command_list[dma_pushbuffer_subindex++]};
GPUVAddr dma_get = command_list_header.addr;
GPUVAddr dma_put = dma_get + command_list_header.size * sizeof(u32);
diff --git a/src/video_core/engines/engine_upload.cpp b/src/video_core/engines/engine_upload.cpp
index f8aa4ff55..082a40cd9 100644
--- a/src/video_core/engines/engine_upload.cpp
+++ b/src/video_core/engines/engine_upload.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+
#include "common/assert.h"
#include "video_core/engines/engine_upload.h"
#include "video_core/memory_manager.h"
@@ -10,7 +12,9 @@
namespace Tegra::Engines::Upload {
State::State(MemoryManager& memory_manager, Registers& regs)
- : memory_manager(memory_manager), regs(regs) {}
+ : regs{regs}, memory_manager{memory_manager} {}
+
+State::~State() = default;
void State::ProcessExec(const bool is_linear) {
write_offset = 0;
diff --git a/src/video_core/engines/engine_upload.h b/src/video_core/engines/engine_upload.h
index 9c6e0d21c..ef4f5839a 100644
--- a/src/video_core/engines/engine_upload.h
+++ b/src/video_core/engines/engine_upload.h
@@ -4,10 +4,8 @@
#pragma once
-#include <cstddef>
#include <vector>
#include "common/bit_field.h"
-#include "common/common_funcs.h"
#include "common/common_types.h"
namespace Tegra {
@@ -57,10 +55,10 @@ struct Registers {
class State {
public:
State(MemoryManager& memory_manager, Registers& regs);
- ~State() = default;
+ ~State();
- void ProcessExec(const bool is_linear);
- void ProcessData(const u32 data, const bool is_last_call);
+ void ProcessExec(bool is_linear);
+ void ProcessData(u32 data, bool is_last_call);
private:
u32 write_offset = 0;
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index d7b586db9..39968d403 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -34,9 +34,9 @@ void Maxwell3D::InitializeRegisterDefaults() {
// Depth range near/far is not always set, but is expected to be the default 0.0f, 1.0f. This is
// needed for ARMS.
- for (std::size_t viewport{}; viewport < Regs::NumViewports; ++viewport) {
- regs.viewports[viewport].depth_range_near = 0.0f;
- regs.viewports[viewport].depth_range_far = 1.0f;
+ for (auto& viewport : regs.viewports) {
+ viewport.depth_range_near = 0.0f;
+ viewport.depth_range_far = 1.0f;
}
// Doom and Bomberman seems to use the uninitialized registers and just enable blend
@@ -47,13 +47,13 @@ void Maxwell3D::InitializeRegisterDefaults() {
regs.blend.equation_a = Regs::Blend::Equation::Add;
regs.blend.factor_source_a = Regs::Blend::Factor::One;
regs.blend.factor_dest_a = Regs::Blend::Factor::Zero;
- for (std::size_t blend_index = 0; blend_index < Regs::NumRenderTargets; blend_index++) {
- regs.independent_blend[blend_index].equation_rgb = Regs::Blend::Equation::Add;
- regs.independent_blend[blend_index].factor_source_rgb = Regs::Blend::Factor::One;
- regs.independent_blend[blend_index].factor_dest_rgb = Regs::Blend::Factor::Zero;
- regs.independent_blend[blend_index].equation_a = Regs::Blend::Equation::Add;
- regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One;
- regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero;
+ for (auto& blend : regs.independent_blend) {
+ blend.equation_rgb = Regs::Blend::Equation::Add;
+ blend.factor_source_rgb = Regs::Blend::Factor::One;
+ blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
+ blend.equation_a = Regs::Blend::Equation::Add;
+ blend.factor_source_a = Regs::Blend::Factor::One;
+ blend.factor_dest_a = Regs::Blend::Factor::Zero;
}
regs.stencil_front_op_fail = Regs::StencilOp::Keep;
regs.stencil_front_op_zfail = Regs::StencilOp::Keep;
@@ -75,11 +75,11 @@ void Maxwell3D::InitializeRegisterDefaults() {
// TODO(bunnei): Some games do not initialize the color masks (e.g. Sonic Mania). Assuming a
// default of enabled fixes rendering here.
- for (std::size_t color_mask = 0; color_mask < Regs::NumRenderTargets; color_mask++) {
- regs.color_mask[color_mask].R.Assign(1);
- regs.color_mask[color_mask].G.Assign(1);
- regs.color_mask[color_mask].B.Assign(1);
- regs.color_mask[color_mask].A.Assign(1);
+ for (auto& color_mask : regs.color_mask) {
+ color_mask.R.Assign(1);
+ color_mask.G.Assign(1);
+ color_mask.B.Assign(1);
+ color_mask.A.Assign(1);
}
// Commercial games seem to assume this value is enabled and nouveau sets this value manually.
@@ -178,13 +178,13 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
// Vertex buffer
if (method >= MAXWELL3D_REG_INDEX(vertex_array) &&
- method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) {
+ method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * Regs::NumVertexArrays) {
dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2);
} else if (method >= MAXWELL3D_REG_INDEX(vertex_array_limit) &&
- method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) {
+ method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * Regs::NumVertexArrays) {
dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1);
} else if (method >= MAXWELL3D_REG_INDEX(instanced_arrays) &&
- method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) {
+ method < MAXWELL3D_REG_INDEX(instanced_arrays) + Regs::NumVertexArrays) {
dirty_flags.vertex_array.set(method - MAXWELL3D_REG_INDEX(instanced_arrays));
}
}
@@ -442,7 +442,7 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
const auto a_type = tic_entry.a_type.Value();
// TODO(Subv): Different data types for separate components are not supported
- ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
+ DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
return tic_entry;
}
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 4883b582a..f342c78e6 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -6,6 +6,7 @@
#include <array>
#include <bitset>
+#include <type_traits>
#include <unordered_map>
#include <vector>
@@ -58,6 +59,7 @@ public:
static constexpr std::size_t NumCBData = 16;
static constexpr std::size_t NumVertexArrays = 32;
static constexpr std::size_t NumVertexAttributes = 32;
+ static constexpr std::size_t NumVaryings = 31;
static constexpr std::size_t NumTextureSamplers = 32;
static constexpr std::size_t NumClipDistances = 8;
static constexpr std::size_t MaxShaderProgram = 6;
@@ -1107,6 +1109,7 @@ public:
} regs{};
static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
+ static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
struct State {
struct ConstBufferInfo {
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index e5b4eadea..7bbc556da 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -98,6 +98,10 @@ union Attribute {
BitField<22, 2, u64> element;
BitField<24, 6, Index> index;
BitField<47, 3, AttributeSize> size;
+
+ bool IsPhysical() const {
+ return element == 0 && static_cast<u64>(index.Value()) == 0;
+ }
} fmt20;
union {
@@ -499,6 +503,11 @@ enum class SystemVariable : u64 {
CircularQueueEntryAddressHigh = 0x63,
};
+enum class PhysicalAttributeDirection : u64 {
+ Input = 0,
+ Output = 1,
+};
+
union Instruction {
Instruction& operator=(const Instruction& instr) {
value = instr.value;
@@ -587,6 +596,7 @@ union Instruction {
} alu;
union {
+ BitField<38, 1, u64> idx;
BitField<51, 1, u64> saturate;
BitField<52, 2, IpaSampleMode> sample_mode;
BitField<54, 2, IpaInterpMode> interp_mode;
@@ -812,6 +822,12 @@ union Instruction {
} stg;
union {
+ BitField<32, 1, PhysicalAttributeDirection> direction;
+ BitField<47, 3, AttributeSize> size;
+ BitField<20, 11, u64> address;
+ } al2p;
+
+ union {
BitField<0, 3, u64> pred0;
BitField<3, 3, u64> pred3;
BitField<7, 1, u64> abs_a;
@@ -1374,8 +1390,9 @@ public:
ST_A,
ST_L,
ST_S,
- LDG, // Load from global memory
- STG, // Store in global memory
+ LDG, // Load from global memory
+ STG, // Store in global memory
+ AL2P, // Transforms attribute memory into physical memory
TEX,
TEX_B, // Texture Load Bindless
TXQ, // Texture Query
@@ -1646,6 +1663,7 @@ private:
INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"),
INST("1110111011010---", Id::LDG, Type::Memory, "LDG"),
INST("1110111011011---", Id::STG, Type::Memory, "STG"),
+ INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"),
INST("110000----111---", Id::TEX, Type::Texture, "TEX"),
INST("1101111010111---", Id::TEX_B, Type::Texture, "TEX_B"),
INST("1101111101001---", Id::TXQ, Type::Texture, "TXQ"),
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 03856013f..1e2ff46b0 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -118,7 +118,7 @@ void SynchState::WaitForSynchronization(u64 fence) {
// Wait for the GPU to be idle (all commands to be executed)
{
MICROPROFILE_SCOPE(GPU_wait);
- std::unique_lock<std::mutex> lock{synchronization_mutex};
+ std::unique_lock lock{synchronization_mutex};
synchronization_condition.wait(lock, [this, fence] { return signaled_fence >= fence; });
}
}
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index cc14527c7..05a168a72 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -81,12 +81,6 @@ struct CommandDataContainer {
CommandDataContainer(CommandData&& data, u64 next_fence)
: data{std::move(data)}, fence{next_fence} {}
- CommandDataContainer& operator=(const CommandDataContainer& t) {
- data = std::move(t.data);
- fence = t.fence;
- return *this;
- }
-
CommandData data;
u64 fence{};
};
@@ -109,7 +103,7 @@ struct SynchState final {
void TrySynchronize() {
if (IsSynchronized()) {
- std::lock_guard<std::mutex> lock{synchronization_mutex};
+ std::lock_guard lock{synchronization_mutex};
synchronization_condition.notify_one();
}
}
diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp
index 524d9ea5a..c766ed692 100644
--- a/src/video_core/macro_interpreter.cpp
+++ b/src/video_core/macro_interpreter.cpp
@@ -118,10 +118,12 @@ bool MacroInterpreter::Step(u32 offset, bool is_delay_slot) {
static_cast<u32>(opcode.operation.Value()));
}
+ // An instruction with the Exit flag will not actually
+ // cause an exit if it's executed inside a delay slot.
+ // TODO(Blinkhawk): Reversed to always exit. The behavior explained above requires further
+ // testing on the MME code.
if (opcode.is_exit) {
// Exit has a delay slot, execute the next instruction
- // Note: Executing an exit during a branch delay slot will cause the instruction at the
- // branch target to be executed before exiting.
Step(offset, true);
return false;
}
diff --git a/src/video_core/rasterizer_cache.h b/src/video_core/rasterizer_cache.h
index f820f3ed9..0c4ea1494 100644
--- a/src/video_core/rasterizer_cache.h
+++ b/src/video_core/rasterizer_cache.h
@@ -144,8 +144,9 @@ protected:
object->SetIsRegistered(false);
rasterizer.UpdatePagesCachedCount(object->GetCpuAddr(), object->GetSizeInBytes(), -1);
+ const CacheAddr addr = object->GetCacheAddr();
interval_cache.subtract({GetInterval(object), ObjectSet{object}});
- map_cache.erase(object->GetCacheAddr());
+ map_cache.erase(addr);
}
/// Returns a ticks counter used for tracking when cached objects were last modified
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index b6d9e0ddb..38497678a 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -21,9 +21,18 @@ T GetInteger(GLenum pname) {
Device::Device() {
uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
+ max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
has_variable_aoffi = TestVariableAoffi();
}
+Device::Device(std::nullptr_t) {
+ uniform_buffer_alignment = 0;
+ max_vertex_attributes = 16;
+ max_varyings = 15;
+ has_variable_aoffi = true;
+}
+
bool Device::TestVariableAoffi() {
const GLchar* AOFFI_TEST = R"(#version 430 core
uniform sampler2D tex;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 78ff5ee58..de8490682 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -5,17 +5,27 @@
#pragma once
#include <cstddef>
+#include "common/common_types.h"
namespace OpenGL {
class Device {
public:
- Device();
+ explicit Device();
+ explicit Device(std::nullptr_t);
std::size_t GetUniformBufferAlignment() const {
return uniform_buffer_alignment;
}
+ u32 GetMaxVertexAttributes() const {
+ return max_vertex_attributes;
+ }
+
+ u32 GetMaxVaryings() const {
+ return max_varyings;
+ }
+
bool HasVariableAoffi() const {
return has_variable_aoffi;
}
@@ -24,6 +34,8 @@ private:
static bool TestVariableAoffi();
std::size_t uniform_buffer_alignment{};
+ u32 max_vertex_attributes{};
+ u32 max_varyings{};
bool has_variable_aoffi{};
};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 3cc945235..dbd8049f5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -261,8 +261,8 @@ DrawParameters RasterizerOpenGL::SetupDraw() {
// MakeQuadArray always generates u32 indexes
params.index_format = GL_UNSIGNED_INT;
params.count = (regs.vertex_buffer.count / 4) * 6;
- params.index_buffer_offset =
- primitive_assembler.MakeQuadArray(regs.vertex_buffer.first, params.count);
+ params.index_buffer_offset = primitive_assembler.MakeQuadArray(
+ regs.vertex_buffer.first, regs.vertex_buffer.count);
}
return params;
}
@@ -1135,7 +1135,9 @@ void RasterizerOpenGL::SyncTransformFeedback() {
void RasterizerOpenGL::SyncPointState() {
const auto& regs = system.GPU().Maxwell3D().regs;
- state.point.size = regs.point_size;
+ // Limit the point size to 1 since nouveau sometimes sets a point size of 0 (and that's invalid
+ // in OpenGL).
+ state.point.size = std::max(1.0f, regs.point_size);
}
void RasterizerOpenGL::SyncPolygonOffset() {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 1a62795e1..6d4658c8b 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -57,15 +57,14 @@ public:
shader_source += text;
}
- void AddLine(std::string_view text) {
- AddExpression(text);
- AddNewLine();
- }
-
- void AddLine(char character) {
- DEBUG_ASSERT(scope >= 0);
- AppendIndentation();
- shader_source += character;
+ // Forwards all arguments directly to libfmt.
+ // Note that all formatting requirements for fmt must be
+ // obeyed when using this function. (e.g. {{ must be used
+ // printing the character '{' is desirable. Ditto for }} and '}',
+ // etc).
+ template <typename... Args>
+ void AddLine(std::string_view text, Args&&... args) {
+ AddExpression(fmt::format(text, std::forward<Args>(args)...));
AddNewLine();
}
@@ -75,9 +74,7 @@ public:
}
std::string GenerateTemporary() {
- std::string temporary = "tmp";
- temporary += std::to_string(temporary_index++);
- return temporary;
+ return fmt::format("tmp{}", temporary_index++);
}
std::string GetResult() {
@@ -134,6 +131,19 @@ bool IsPrecise(Node node) {
return false;
}
+constexpr bool IsGenericAttribute(Attribute::Index index) {
+ return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31;
+}
+
+constexpr Attribute::Index ToGenericAttribute(u32 value) {
+ return static_cast<Attribute::Index>(value + static_cast<u32>(Attribute::Index::Attribute_0));
+}
+
+u32 GetGenericAttributeIndex(Attribute::Index index) {
+ ASSERT(IsGenericAttribute(index));
+ return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
+}
+
class GLSLDecompiler final {
public:
explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ShaderStage stage,
@@ -152,42 +162,43 @@ public:
DeclareConstantBuffers();
DeclareGlobalMemory();
DeclareSamplers();
+ DeclarePhysicalAttributeReader();
- code.AddLine("void execute_" + suffix + "() {");
+ code.AddLine("void execute_{}() {{", suffix);
++code.scope;
// VM's program counter
const auto first_address = ir.GetBasicBlocks().begin()->first;
- code.AddLine("uint jmp_to = " + std::to_string(first_address) + "u;");
+ code.AddLine("uint jmp_to = {}u;", first_address);
// TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
// unlikely that shaders will use 20 nested SSYs and PBKs.
constexpr u32 FLOW_STACK_SIZE = 20;
- code.AddLine(fmt::format("uint flow_stack[{}];", FLOW_STACK_SIZE));
+ code.AddLine("uint flow_stack[{}];", FLOW_STACK_SIZE);
code.AddLine("uint flow_stack_top = 0u;");
- code.AddLine("while (true) {");
+ code.AddLine("while (true) {{");
++code.scope;
- code.AddLine("switch (jmp_to) {");
+ code.AddLine("switch (jmp_to) {{");
for (const auto& pair : ir.GetBasicBlocks()) {
const auto [address, bb] = pair;
- code.AddLine(fmt::format("case 0x{:x}u: {{", address));
+ code.AddLine("case 0x{:x}u: {{", address);
++code.scope;
VisitBlock(bb);
--code.scope;
- code.AddLine('}');
+ code.AddLine("}}");
}
code.AddLine("default: return;");
- code.AddLine('}');
+ code.AddLine("}}");
for (std::size_t i = 0; i < 2; ++i) {
--code.scope;
- code.AddLine('}');
+ code.AddLine("}}");
}
}
@@ -227,12 +238,13 @@ private:
}
void DeclareGeometry() {
- if (stage != ShaderStage::Geometry)
+ if (stage != ShaderStage::Geometry) {
return;
+ }
const auto topology = GetTopologyName(header.common3.output_topology);
- const auto max_vertices = std::to_string(header.common4.max_output_vertices);
- code.AddLine("layout (" + topology + ", max_vertices = " + max_vertices + ") out;");
+ const auto max_vertices = header.common4.max_output_vertices.Value();
+ code.AddLine("layout ({}, max_vertices = {}) out;", topology, max_vertices);
code.AddNewLine();
DeclareVertexRedeclarations();
@@ -241,7 +253,7 @@ private:
void DeclareVertexRedeclarations() {
bool clip_distances_declared = false;
- code.AddLine("out gl_PerVertex {");
+ code.AddLine("out gl_PerVertex {{");
++code.scope;
code.AddLine("vec4 gl_Position;");
@@ -257,122 +269,143 @@ private:
}
--code.scope;
- code.AddLine("};");
+ code.AddLine("}};");
code.AddNewLine();
}
void DeclareRegisters() {
const auto& registers = ir.GetRegisters();
for (const u32 gpr : registers) {
- code.AddLine("float " + GetRegister(gpr) + " = 0;");
+ code.AddLine("float {} = 0;", GetRegister(gpr));
}
- if (!registers.empty())
+ if (!registers.empty()) {
code.AddNewLine();
+ }
}
void DeclarePredicates() {
const auto& predicates = ir.GetPredicates();
for (const auto pred : predicates) {
- code.AddLine("bool " + GetPredicate(pred) + " = false;");
+ code.AddLine("bool {} = false;", GetPredicate(pred));
}
- if (!predicates.empty())
+ if (!predicates.empty()) {
code.AddNewLine();
+ }
}
void DeclareLocalMemory() {
if (const u64 local_memory_size = header.GetLocalMemorySize(); local_memory_size > 0) {
const auto element_count = Common::AlignUp(local_memory_size, 4) / 4;
- code.AddLine("float " + GetLocalMemory() + '[' + std::to_string(element_count) + "];");
+ code.AddLine("float {}[{}];", GetLocalMemory(), element_count);
code.AddNewLine();
}
}
void DeclareInternalFlags() {
for (u32 flag = 0; flag < static_cast<u32>(InternalFlag::Amount); flag++) {
- const InternalFlag flag_code = static_cast<InternalFlag>(flag);
- code.AddLine("bool " + GetInternalFlag(flag_code) + " = false;");
+ const auto flag_code = static_cast<InternalFlag>(flag);
+ code.AddLine("bool {} = false;", GetInternalFlag(flag_code));
}
code.AddNewLine();
}
std::string GetInputFlags(AttributeUse attribute) {
- std::string out;
-
switch (attribute) {
- case AttributeUse::Constant:
- out += "flat ";
- break;
- case AttributeUse::ScreenLinear:
- out += "noperspective ";
- break;
case AttributeUse::Perspective:
// Default, Smooth
- break;
+ return {};
+ case AttributeUse::Constant:
+ return "flat ";
+ case AttributeUse::ScreenLinear:
+ return "noperspective ";
default:
- LOG_CRITICAL(HW_GPU, "Unused attribute being fetched");
- UNREACHABLE();
+ case AttributeUse::Unused:
+ UNREACHABLE_MSG("Unused attribute being fetched");
+ return {};
+ UNIMPLEMENTED_MSG("Unknown attribute usage index={}", static_cast<u32>(attribute));
+ return {};
}
- return out;
}
void DeclareInputAttributes() {
- const auto& attributes = ir.GetInputAttributes();
- for (const auto element : attributes) {
- const Attribute::Index index = element.first;
- if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
- // Skip when it's not a generic attribute
- continue;
+ if (ir.HasPhysicalAttributes()) {
+ const u32 num_inputs{GetNumPhysicalInputAttributes()};
+ for (u32 i = 0; i < num_inputs; ++i) {
+ DeclareInputAttribute(ToGenericAttribute(i), true);
}
+ code.AddNewLine();
+ return;
+ }
- // TODO(bunnei): Use proper number of elements for these
- u32 idx = static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
- if (stage != ShaderStage::Vertex) {
- // If inputs are varyings, add an offset
- idx += GENERIC_VARYING_START_LOCATION;
+ const auto& attributes = ir.GetInputAttributes();
+ for (const auto index : attributes) {
+ if (IsGenericAttribute(index)) {
+ DeclareInputAttribute(index, false);
}
+ }
+ if (!attributes.empty()) {
+ code.AddNewLine();
+ }
+ }
- std::string attr = GetInputAttribute(index);
- if (stage == ShaderStage::Geometry) {
- attr = "gs_" + attr + "[]";
- }
- std::string suffix;
- if (stage == ShaderStage::Fragment) {
- const auto input_mode =
- header.ps.GetAttributeUse(idx - GENERIC_VARYING_START_LOCATION);
- suffix = GetInputFlags(input_mode);
+ void DeclareInputAttribute(Attribute::Index index, bool skip_unused) {
+ const u32 generic_index{GetGenericAttributeIndex(index)};
+
+ std::string name{GetInputAttribute(index)};
+ if (stage == ShaderStage::Geometry) {
+ name = "gs_" + name + "[]";
+ }
+
+ std::string suffix;
+ if (stage == ShaderStage::Fragment) {
+ const auto input_mode{header.ps.GetAttributeUse(generic_index)};
+ if (skip_unused && input_mode == AttributeUse::Unused) {
+ return;
}
- code.AddLine("layout (location = " + std::to_string(idx) + ") " + suffix + "in vec4 " +
- attr + ';');
+ suffix = GetInputFlags(input_mode);
}
- if (!attributes.empty())
- code.AddNewLine();
+
+ u32 location = generic_index;
+ if (stage != ShaderStage::Vertex) {
+ // If inputs are varyings, add an offset
+ location += GENERIC_VARYING_START_LOCATION;
+ }
+
+ code.AddLine("layout (location = {}) {} in vec4 {};", location, suffix, name);
}
void DeclareOutputAttributes() {
+ if (ir.HasPhysicalAttributes() && stage != ShaderStage::Fragment) {
+ for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) {
+ DeclareOutputAttribute(ToGenericAttribute(i));
+ }
+ code.AddNewLine();
+ return;
+ }
+
const auto& attributes = ir.GetOutputAttributes();
for (const auto index : attributes) {
- if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
- // Skip when it's not a generic attribute
- continue;
+ if (IsGenericAttribute(index)) {
+ DeclareOutputAttribute(index);
}
- // TODO(bunnei): Use proper number of elements for these
- const auto idx = static_cast<u32>(index) -
- static_cast<u32>(Attribute::Index::Attribute_0) +
- GENERIC_VARYING_START_LOCATION;
- code.AddLine("layout (location = " + std::to_string(idx) + ") out vec4 " +
- GetOutputAttribute(index) + ';');
- }
- if (!attributes.empty())
+ }
+ if (!attributes.empty()) {
code.AddNewLine();
+ }
+ }
+
+ void DeclareOutputAttribute(Attribute::Index index) {
+ const u32 location{GetGenericAttributeIndex(index) + GENERIC_VARYING_START_LOCATION};
+ code.AddLine("layout (location = {}) out vec4 {};", location, GetOutputAttribute(index));
}
void DeclareConstantBuffers() {
for (const auto& entry : ir.GetConstantBuffers()) {
const auto [index, size] = entry;
- code.AddLine("layout (std140, binding = CBUF_BINDING_" + std::to_string(index) +
- ") uniform " + GetConstBufferBlock(index) + " {");
- code.AddLine(" vec4 " + GetConstBuffer(index) + "[MAX_CONSTBUFFER_ELEMENTS];");
- code.AddLine("};");
+ code.AddLine("layout (std140, binding = CBUF_BINDING_{}) uniform {} {{", index,
+ GetConstBufferBlock(index));
+ code.AddLine(" vec4 {}[MAX_CONSTBUFFER_ELEMENTS];", GetConstBuffer(index));
+ code.AddLine("}};");
code.AddNewLine();
}
}
@@ -384,17 +417,16 @@ private:
// Since we don't know how the shader will use the shader, hint the driver to disable as
// much optimizations as possible
std::string qualifier = "coherent volatile";
- if (usage.is_read && !usage.is_written)
+ if (usage.is_read && !usage.is_written) {
qualifier += " readonly";
- else if (usage.is_written && !usage.is_read)
+ } else if (usage.is_written && !usage.is_read) {
qualifier += " writeonly";
+ }
- const std::string binding =
- fmt::format("GMEM_BINDING_{}_{}", base.cbuf_index, base.cbuf_offset);
- code.AddLine("layout (std430, binding = " + binding + ") " + qualifier + " buffer " +
- GetGlobalMemoryBlock(base) + " {");
- code.AddLine(" float " + GetGlobalMemory(base) + "[];");
- code.AddLine("};");
+ code.AddLine("layout (std430, binding = GMEM_BINDING_{}_{}) {} buffer {} {{",
+ base.cbuf_index, base.cbuf_offset, qualifier, GetGlobalMemoryBlock(base));
+ code.AddLine(" float {}[];", GetGlobalMemory(base));
+ code.AddLine("}};");
code.AddNewLine();
}
}
@@ -402,7 +434,7 @@ private:
void DeclareSamplers() {
const auto& samplers = ir.GetSamplers();
for (const auto& sampler : samplers) {
- std::string sampler_type = [&]() {
+ std::string sampler_type = [&sampler] {
switch (sampler.GetType()) {
case Tegra::Shader::TextureType::Texture1D:
return "sampler1D";
@@ -417,16 +449,52 @@ private:
return "sampler2D";
}
}();
- if (sampler.IsArray())
+ if (sampler.IsArray()) {
sampler_type += "Array";
- if (sampler.IsShadow())
+ }
+ if (sampler.IsShadow()) {
sampler_type += "Shadow";
+ }
- code.AddLine("layout (binding = SAMPLER_BINDING_" + std::to_string(sampler.GetIndex()) +
- ") uniform " + sampler_type + ' ' + GetSampler(sampler) + ';');
+ code.AddLine("layout (binding = SAMPLER_BINDING_{}) uniform {} {};", sampler.GetIndex(),
+ sampler_type, GetSampler(sampler));
}
- if (!samplers.empty())
+ if (!samplers.empty()) {
code.AddNewLine();
+ }
+ }
+
+ void DeclarePhysicalAttributeReader() {
+ if (!ir.HasPhysicalAttributes()) {
+ return;
+ }
+ code.AddLine("float readPhysicalAttribute(uint physical_address) {{");
+ ++code.scope;
+ code.AddLine("switch (physical_address) {{");
+
+ // Just declare generic attributes for now.
+ const auto num_attributes{static_cast<u32>(GetNumPhysicalInputAttributes())};
+ for (u32 index = 0; index < num_attributes; ++index) {
+ const auto attribute{ToGenericAttribute(index)};
+ for (u32 element = 0; element < 4; ++element) {
+ constexpr u32 generic_base{0x80};
+ constexpr u32 generic_stride{16};
+ constexpr u32 element_stride{4};
+ const u32 address{generic_base + index * generic_stride + element * element_stride};
+
+ const bool declared{stage != ShaderStage::Fragment ||
+ header.ps.GetAttributeUse(index) != AttributeUse::Unused};
+ const std::string value{declared ? ReadAttribute(attribute, element) : "0"};
+ code.AddLine("case 0x{:x}: return {};", address, value);
+ }
+ }
+
+ code.AddLine("default: return 0;");
+
+ code.AddLine("}}");
+ --code.scope;
+ code.AddLine("}}");
+ code.AddNewLine();
}
void VisitBlock(const NodeBlock& bb) {
@@ -450,23 +518,26 @@ private:
return {};
}
return (this->*decompiler)(*operation);
+ }
- } else if (const auto gpr = std::get_if<GprNode>(node)) {
+ if (const auto gpr = std::get_if<GprNode>(node)) {
const u32 index = gpr->GetIndex();
if (index == Register::ZeroIndex) {
return "0";
}
return GetRegister(index);
+ }
- } else if (const auto immediate = std::get_if<ImmediateNode>(node)) {
+ if (const auto immediate = std::get_if<ImmediateNode>(node)) {
const u32 value = immediate->GetValue();
if (value < 10) {
// For eyecandy avoid using hex numbers on single digits
return fmt::format("utof({}u)", immediate->GetValue());
}
return fmt::format("utof(0x{:x}u)", immediate->GetValue());
+ }
- } else if (const auto predicate = std::get_if<PredicateNode>(node)) {
+ if (const auto predicate = std::get_if<PredicateNode>(node)) {
const auto value = [&]() -> std::string {
switch (const auto index = predicate->GetIndex(); index) {
case Tegra::Shader::Pred::UnusedIndex:
@@ -478,77 +549,22 @@ private:
}
}();
if (predicate->IsNegated()) {
- return "!(" + value + ')';
+ return fmt::format("!({})", value);
}
return value;
+ }
- } else if (const auto abuf = std::get_if<AbufNode>(node)) {
- const auto attribute = abuf->GetIndex();
- const auto element = abuf->GetElement();
-
- const auto GeometryPass = [&](const std::string& name) {
- if (stage == ShaderStage::Geometry && abuf->GetBuffer()) {
- // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
- // set an 0x80000000 index for those and the shader fails to build. Find out why
- // this happens and what's its intent.
- return "gs_" + name + "[ftou(" + Visit(abuf->GetBuffer()) +
- ") % MAX_VERTEX_INPUT]";
- }
- return name;
- };
-
- switch (attribute) {
- case Attribute::Index::Position:
- if (stage != ShaderStage::Fragment) {
- return GeometryPass("position") + GetSwizzle(element);
- } else {
- return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element);
- }
- case Attribute::Index::PointCoord:
- switch (element) {
- case 0:
- return "gl_PointCoord.x";
- case 1:
- return "gl_PointCoord.y";
- case 2:
- case 3:
- return "0";
- }
- UNREACHABLE();
- return "0";
- case Attribute::Index::TessCoordInstanceIDVertexID:
- // TODO(Subv): Find out what the values are for the first two elements when inside a
- // vertex shader, and what's the value of the fourth element when inside a Tess Eval
- // shader.
- ASSERT(stage == ShaderStage::Vertex);
- switch (element) {
- case 2:
- // Config pack's first value is instance_id.
- return "uintBitsToFloat(config_pack[0])";
- case 3:
- return "uintBitsToFloat(gl_VertexID)";
- }
- UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element);
- return "0";
- case Attribute::Index::FrontFacing:
- // TODO(Subv): Find out what the values are for the other elements.
- ASSERT(stage == ShaderStage::Fragment);
- switch (element) {
- case 3:
- return "itof(gl_FrontFacing ? -1 : 0)";
- }
- UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element);
- return "0";
- default:
- if (attribute >= Attribute::Index::Attribute_0 &&
- attribute <= Attribute::Index::Attribute_31) {
- return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element);
- }
- break;
+ if (const auto abuf = std::get_if<AbufNode>(node)) {
+ UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry,
+ "Physical attributes in geometry shaders are not implemented");
+ if (abuf->IsPhysicalBuffer()) {
+ return fmt::format("readPhysicalAttribute(ftou({}))",
+ Visit(abuf->GetPhysicalAddress()));
}
- UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
+ return ReadAttribute(abuf->GetIndex(), abuf->GetElement(), abuf->GetBuffer());
+ }
- } else if (const auto cbuf = std::get_if<CbufNode>(node)) {
+ if (const auto cbuf = std::get_if<CbufNode>(node)) {
const Node offset = cbuf->GetOffset();
if (const auto immediate = std::get_if<ImmediateNode>(offset)) {
// Direct access
@@ -556,48 +572,117 @@ private:
ASSERT_MSG(offset_imm % 4 == 0, "Unaligned cbuf direct access");
return fmt::format("{}[{}][{}]", GetConstBuffer(cbuf->GetIndex()),
offset_imm / (4 * 4), (offset_imm / 4) % 4);
+ }
- } else if (std::holds_alternative<OperationNode>(*offset)) {
+ if (std::holds_alternative<OperationNode>(*offset)) {
// Indirect access
const std::string final_offset = code.GenerateTemporary();
- code.AddLine("uint " + final_offset + " = (ftou(" + Visit(offset) + ") / 4);");
+ code.AddLine("uint {} = (ftou({}) / 4);", final_offset, Visit(offset));
return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()),
final_offset, final_offset);
-
- } else {
- UNREACHABLE_MSG("Unmanaged offset node type");
}
- } else if (const auto gmem = std::get_if<GmemNode>(node)) {
+ UNREACHABLE_MSG("Unmanaged offset node type");
+ }
+
+ if (const auto gmem = std::get_if<GmemNode>(node)) {
const std::string real = Visit(gmem->GetRealAddress());
const std::string base = Visit(gmem->GetBaseAddress());
- const std::string final_offset = "(ftou(" + real + ") - ftou(" + base + ")) / 4";
+ const std::string final_offset = fmt::format("(ftou({}) - ftou({})) / 4", real, base);
return fmt::format("{}[{}]", GetGlobalMemory(gmem->GetDescriptor()), final_offset);
+ }
- } else if (const auto lmem = std::get_if<LmemNode>(node)) {
+ if (const auto lmem = std::get_if<LmemNode>(node)) {
return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
+ }
- } else if (const auto internal_flag = std::get_if<InternalFlagNode>(node)) {
+ if (const auto internal_flag = std::get_if<InternalFlagNode>(node)) {
return GetInternalFlag(internal_flag->GetFlag());
+ }
- } else if (const auto conditional = std::get_if<ConditionalNode>(node)) {
+ if (const auto conditional = std::get_if<ConditionalNode>(node)) {
// It's invalid to call conditional on nested nodes, use an operation instead
- code.AddLine("if (" + Visit(conditional->GetCondition()) + ") {");
+ code.AddLine("if ({}) {{", Visit(conditional->GetCondition()));
++code.scope;
VisitBlock(conditional->GetCode());
--code.scope;
- code.AddLine('}');
+ code.AddLine("}}");
return {};
+ }
- } else if (const auto comment = std::get_if<CommentNode>(node)) {
+ if (const auto comment = std::get_if<CommentNode>(node)) {
return "// " + comment->GetText();
}
+
UNREACHABLE();
return {};
}
+ std::string ReadAttribute(Attribute::Index attribute, u32 element, Node buffer = {}) {
+ const auto GeometryPass = [&](std::string_view name) {
+ if (stage == ShaderStage::Geometry && buffer) {
+ // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
+ // set an 0x80000000 index for those and the shader fails to build. Find out why
+ // this happens and what's its intent.
+ return fmt::format("gs_{}[ftou({}) % MAX_VERTEX_INPUT]", name, Visit(buffer));
+ }
+ return std::string(name);
+ };
+
+ switch (attribute) {
+ case Attribute::Index::Position:
+ if (stage != ShaderStage::Fragment) {
+ return GeometryPass("position") + GetSwizzle(element);
+ } else {
+ return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element);
+ }
+ case Attribute::Index::PointCoord:
+ switch (element) {
+ case 0:
+ return "gl_PointCoord.x";
+ case 1:
+ return "gl_PointCoord.y";
+ case 2:
+ case 3:
+ return "0";
+ }
+ UNREACHABLE();
+ return "0";
+ case Attribute::Index::TessCoordInstanceIDVertexID:
+ // TODO(Subv): Find out what the values are for the first two elements when inside a
+ // vertex shader, and what's the value of the fourth element when inside a Tess Eval
+ // shader.
+ ASSERT(stage == ShaderStage::Vertex);
+ switch (element) {
+ case 2:
+ // Config pack's first value is instance_id.
+ return "uintBitsToFloat(config_pack[0])";
+ case 3:
+ return "uintBitsToFloat(gl_VertexID)";
+ }
+ UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element);
+ return "0";
+ case Attribute::Index::FrontFacing:
+ // TODO(Subv): Find out what the values are for the other elements.
+ ASSERT(stage == ShaderStage::Fragment);
+ switch (element) {
+ case 3:
+ return "itof(gl_FrontFacing ? -1 : 0)";
+ }
+ UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element);
+ return "0";
+ default:
+ if (IsGenericAttribute(attribute)) {
+ return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element);
+ }
+ break;
+ }
+ UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
+ return "0";
+ }
+
std::string ApplyPrecise(Operation operation, const std::string& value) {
if (!IsPrecise(operation)) {
return value;
@@ -606,7 +691,7 @@ private:
const std::string precise = stage != ShaderStage::Fragment ? "precise " : "";
const std::string temporary = code.GenerateTemporary();
- code.AddLine(precise + "float " + temporary + " = " + value + ';');
+ code.AddLine("{}float {} = {};", precise, temporary, value);
return temporary;
}
@@ -620,7 +705,7 @@ private:
}
const std::string temporary = code.GenerateTemporary();
- code.AddLine("float " + temporary + " = " + Visit(operand) + ';');
+ code.AddLine("float {} = {};", temporary, Visit(operand));
return temporary;
}
@@ -635,31 +720,32 @@ private:
case Type::Float:
return value;
case Type::Int:
- return "ftoi(" + value + ')';
+ return fmt::format("ftoi({})", value);
case Type::Uint:
- return "ftou(" + value + ')';
+ return fmt::format("ftou({})", value);
case Type::HalfFloat:
- return "toHalf2(" + value + ')';
+ return fmt::format("toHalf2({})", value);
}
UNREACHABLE();
return value;
}
- std::string BitwiseCastResult(std::string value, Type type, bool needs_parenthesis = false) {
+ std::string BitwiseCastResult(const std::string& value, Type type,
+ bool needs_parenthesis = false) {
switch (type) {
case Type::Bool:
case Type::Bool2:
case Type::Float:
if (needs_parenthesis) {
- return '(' + value + ')';
+ return fmt::format("({})", value);
}
return value;
case Type::Int:
- return "itof(" + value + ')';
+ return fmt::format("itof({})", value);
case Type::Uint:
- return "utof(" + value + ')';
+ return fmt::format("utof({})", value);
case Type::HalfFloat:
- return "fromHalf2(" + value + ')';
+ return fmt::format("fromHalf2({})", value);
}
UNREACHABLE();
return value;
@@ -667,27 +753,27 @@ private:
std::string GenerateUnary(Operation operation, const std::string& func, Type result_type,
Type type_a, bool needs_parenthesis = true) {
- return ApplyPrecise(operation,
- BitwiseCastResult(func + '(' + VisitOperand(operation, 0, type_a) + ')',
- result_type, needs_parenthesis));
+ const std::string op_str = fmt::format("{}({})", func, VisitOperand(operation, 0, type_a));
+
+ return ApplyPrecise(operation, BitwiseCastResult(op_str, result_type, needs_parenthesis));
}
std::string GenerateBinaryInfix(Operation operation, const std::string& func, Type result_type,
Type type_a, Type type_b) {
const std::string op_a = VisitOperand(operation, 0, type_a);
const std::string op_b = VisitOperand(operation, 1, type_b);
+ const std::string op_str = fmt::format("({} {} {})", op_a, func, op_b);
- return ApplyPrecise(
- operation, BitwiseCastResult('(' + op_a + ' ' + func + ' ' + op_b + ')', result_type));
+ return ApplyPrecise(operation, BitwiseCastResult(op_str, result_type));
}
std::string GenerateBinaryCall(Operation operation, const std::string& func, Type result_type,
Type type_a, Type type_b) {
const std::string op_a = VisitOperand(operation, 0, type_a);
const std::string op_b = VisitOperand(operation, 1, type_b);
+ const std::string op_str = fmt::format("{}({}, {})", func, op_a, op_b);
- return ApplyPrecise(operation,
- BitwiseCastResult(func + '(' + op_a + ", " + op_b + ')', result_type));
+ return ApplyPrecise(operation, BitwiseCastResult(op_str, result_type));
}
std::string GenerateTernary(Operation operation, const std::string& func, Type result_type,
@@ -695,10 +781,9 @@ private:
const std::string op_a = VisitOperand(operation, 0, type_a);
const std::string op_b = VisitOperand(operation, 1, type_b);
const std::string op_c = VisitOperand(operation, 2, type_c);
+ const std::string op_str = fmt::format("{}({}, {}, {})", func, op_a, op_b, op_c);
- return ApplyPrecise(
- operation,
- BitwiseCastResult(func + '(' + op_a + ", " + op_b + ", " + op_c + ')', result_type));
+ return ApplyPrecise(operation, BitwiseCastResult(op_str, result_type));
}
std::string GenerateQuaternary(Operation operation, const std::string& func, Type result_type,
@@ -707,10 +792,9 @@ private:
const std::string op_b = VisitOperand(operation, 1, type_b);
const std::string op_c = VisitOperand(operation, 2, type_c);
const std::string op_d = VisitOperand(operation, 3, type_d);
+ const std::string op_str = fmt::format("{}({}, {}, {}, {})", func, op_a, op_b, op_c, op_d);
- return ApplyPrecise(operation, BitwiseCastResult(func + '(' + op_a + ", " + op_b + ", " +
- op_c + ", " + op_d + ')',
- result_type));
+ return ApplyPrecise(operation, BitwiseCastResult(op_str, result_type));
}
std::string GenerateTexture(Operation operation, const std::string& function_suffix,
@@ -773,7 +857,7 @@ private:
// required to be constant)
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
} else {
- expr += "ftoi(" + Visit(operand) + ')';
+ expr += fmt::format("ftoi({})", Visit(operand));
}
break;
case Type::Float:
@@ -806,7 +890,7 @@ private:
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
} else if (device.HasVariableAoffi()) {
// Avoid using variable AOFFI on unsupported devices.
- expr += "ftoi(" + Visit(operand) + ')';
+ expr += fmt::format("ftoi({})", Visit(operand));
} else {
// Insert 0 on devices not supporting variable AOFFI.
expr += '0';
@@ -831,8 +915,9 @@ private:
return {};
}
target = GetRegister(gpr->GetIndex());
-
} else if (const auto abuf = std::get_if<AbufNode>(dest)) {
+ UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer());
+
target = [&]() -> std::string {
switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) {
case Attribute::Index::Position:
@@ -840,12 +925,11 @@ private:
case Attribute::Index::PointSize:
return "gl_PointSize";
case Attribute::Index::ClipDistances0123:
- return "gl_ClipDistance[" + std::to_string(abuf->GetElement()) + ']';
+ return fmt::format("gl_ClipDistance[{}]", abuf->GetElement());
case Attribute::Index::ClipDistances4567:
- return "gl_ClipDistance[" + std::to_string(abuf->GetElement() + 4) + ']';
+ return fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4);
default:
- if (attribute >= Attribute::Index::Attribute_0 &&
- attribute <= Attribute::Index::Attribute_31) {
+ if (IsGenericAttribute(attribute)) {
return GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement());
}
UNIMPLEMENTED_MSG("Unhandled output attribute: {}",
@@ -853,21 +937,18 @@ private:
return "0";
}
}();
-
} else if (const auto lmem = std::get_if<LmemNode>(dest)) {
- target = GetLocalMemory() + "[ftou(" + Visit(lmem->GetAddress()) + ") / 4]";
-
+ target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
} else if (const auto gmem = std::get_if<GmemNode>(dest)) {
const std::string real = Visit(gmem->GetRealAddress());
const std::string base = Visit(gmem->GetBaseAddress());
- const std::string final_offset = "(ftou(" + real + ") - ftou(" + base + ")) / 4";
+ const std::string final_offset = fmt::format("(ftou({}) - ftou({})) / 4", real, base);
target = fmt::format("{}[{}]", GetGlobalMemory(gmem->GetDescriptor()), final_offset);
-
} else {
UNREACHABLE_MSG("Assign called without a proper target");
}
- code.AddLine(target + " = " + Visit(src) + ';');
+ code.AddLine("{} = {};", target, Visit(src));
return {};
}
@@ -920,8 +1001,9 @@ private:
const std::string condition = Visit(operation[0]);
const std::string true_case = Visit(operation[1]);
const std::string false_case = Visit(operation[2]);
- return ApplyPrecise(operation,
- '(' + condition + " ? " + true_case + " : " + false_case + ')');
+ const std::string op_str = fmt::format("({} ? {} : {})", condition, true_case, false_case);
+
+ return ApplyPrecise(operation, op_str);
}
std::string FCos(Operation operation) {
@@ -985,9 +1067,9 @@ private:
std::string ILogicalShiftRight(Operation operation) {
const std::string op_a = VisitOperand(operation, 0, Type::Uint);
const std::string op_b = VisitOperand(operation, 1, Type::Uint);
+ const std::string op_str = fmt::format("int({} >> {})", op_a, op_b);
- return ApplyPrecise(operation,
- BitwiseCastResult("int(" + op_a + " >> " + op_b + ')', Type::Int));
+ return ApplyPrecise(operation, BitwiseCastResult(op_str, Type::Int));
}
std::string IArithmeticShiftRight(Operation operation) {
@@ -1043,11 +1125,12 @@ private:
}
std::string HNegate(Operation operation) {
- const auto GetNegate = [&](std::size_t index) -> std::string {
+ const auto GetNegate = [&](std::size_t index) {
return VisitOperand(operation, index, Type::Bool) + " ? -1 : 1";
};
- const std::string value = '(' + VisitOperand(operation, 0, Type::HalfFloat) + " * vec2(" +
- GetNegate(1) + ", " + GetNegate(2) + "))";
+ const std::string value =
+ fmt::format("({} * vec2({}, {}))", VisitOperand(operation, 0, Type::HalfFloat),
+ GetNegate(1), GetNegate(2));
return BitwiseCastResult(value, Type::HalfFloat);
}
@@ -1055,7 +1138,8 @@ private:
const std::string value = VisitOperand(operation, 0, Type::HalfFloat);
const std::string min = VisitOperand(operation, 1, Type::Float);
const std::string max = VisitOperand(operation, 2, Type::Float);
- const std::string clamped = "clamp(" + value + ", vec2(" + min + "), vec2(" + max + "))";
+ const std::string clamped = fmt::format("clamp({}, vec2({}), vec2({}))", value, min, max);
+
return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat));
}
@@ -1066,34 +1150,35 @@ private:
case Tegra::Shader::HalfType::H0_H1:
return operand;
case Tegra::Shader::HalfType::F32:
- return "vec2(fromHalf2(" + operand + "))";
+ return fmt::format("vec2(fromHalf2({}))", operand);
case Tegra::Shader::HalfType::H0_H0:
- return "vec2(" + operand + "[0])";
+ return fmt::format("vec2({}[0])", operand);
case Tegra::Shader::HalfType::H1_H1:
- return "vec2(" + operand + "[1])";
+ return fmt::format("vec2({}[1])", operand);
}
UNREACHABLE();
return "0";
}();
- return "fromHalf2(" + value + ')';
+ return fmt::format("fromHalf2({})", value);
}
std::string HMergeF32(Operation operation) {
- return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
+ return fmt::format("float(toHalf2({})[0])", Visit(operation[0]));
}
std::string HMergeH0(Operation operation) {
- return "fromHalf2(vec2(toHalf2(" + Visit(operation[1]) + ")[0], toHalf2(" +
- Visit(operation[0]) + ")[1]))";
+ return fmt::format("fromHalf2(vec2(toHalf2({})[0], toHalf2({})[1]))", Visit(operation[1]),
+ Visit(operation[0]));
}
std::string HMergeH1(Operation operation) {
- return "fromHalf2(vec2(toHalf2(" + Visit(operation[0]) + ")[0], toHalf2(" +
- Visit(operation[1]) + ")[1]))";
+ return fmt::format("fromHalf2(vec2(toHalf2({})[0], toHalf2({})[1]))", Visit(operation[0]),
+ Visit(operation[1]));
}
std::string HPack2(Operation operation) {
- return "utof(packHalf2x16(vec2(" + Visit(operation[0]) + ", " + Visit(operation[1]) + ")))";
+ return fmt::format("utof(packHalf2x16(vec2({}, {})))", Visit(operation[0]),
+ Visit(operation[1]));
}
template <Type type>
@@ -1151,7 +1236,7 @@ private:
target = GetInternalFlag(flag->GetFlag());
}
- code.AddLine(target + " = " + Visit(src) + ';');
+ code.AddLine("{} = {};", target, Visit(src));
return {};
}
@@ -1173,7 +1258,7 @@ private:
std::string LogicalPick2(Operation operation) {
const std::string pair = VisitOperand(operation, 0, Type::Bool2);
- return pair + '[' + VisitOperand(operation, 1, Type::Uint) + ']';
+ return fmt::format("{}[{}]", pair, VisitOperand(operation, 1, Type::Uint));
}
std::string LogicalAll2(Operation operation) {
@@ -1185,15 +1270,15 @@ private:
}
template <bool with_nan>
- std::string GenerateHalfComparison(Operation operation, std::string compare_op) {
- std::string comparison{GenerateBinaryCall(operation, compare_op, Type::Bool2,
- Type::HalfFloat, Type::HalfFloat)};
+ std::string GenerateHalfComparison(Operation operation, const std::string& compare_op) {
+ const std::string comparison{GenerateBinaryCall(operation, compare_op, Type::Bool2,
+ Type::HalfFloat, Type::HalfFloat)};
if constexpr (!with_nan) {
return comparison;
}
- return "halfFloatNanComparison(" + comparison + ", " +
- VisitOperand(operation, 0, Type::HalfFloat) + ", " +
- VisitOperand(operation, 1, Type::HalfFloat) + ')';
+ return fmt::format("halfFloatNanComparison({}, {}, {})", comparison,
+ VisitOperand(operation, 0, Type::HalfFloat),
+ VisitOperand(operation, 1, Type::HalfFloat));
}
template <bool with_nan>
@@ -1270,12 +1355,12 @@ private:
switch (meta->element) {
case 0:
case 1:
- return "itof(int(textureSize(" + sampler + ", " + lod + ')' +
- GetSwizzle(meta->element) + "))";
+ return fmt::format("itof(int(textureSize({}, {}){}))", sampler, lod,
+ GetSwizzle(meta->element));
case 2:
return "0";
case 3:
- return "itof(textureQueryLevels(" + sampler + "))";
+ return fmt::format("itof(textureQueryLevels({}))", sampler);
}
UNREACHABLE();
return "0";
@@ -1286,8 +1371,9 @@ private:
ASSERT(meta);
if (meta->element < 2) {
- return "itof(int((" + GenerateTexture(operation, "QueryLod", {}) + " * vec2(256))" +
- GetSwizzle(meta->element) + "))";
+ return fmt::format("itof(int(({} * vec2(256)){}))",
+ GenerateTexture(operation, "QueryLod", {}),
+ GetSwizzle(meta->element));
}
return "0";
}
@@ -1326,7 +1412,7 @@ private:
const auto target = std::get_if<ImmediateNode>(operation[0]);
UNIMPLEMENTED_IF(!target);
- code.AddLine(fmt::format("jmp_to = 0x{:x}u;", target->GetValue()));
+ code.AddLine("jmp_to = 0x{:x}u;", target->GetValue());
code.AddLine("break;");
return {};
}
@@ -1335,7 +1421,7 @@ private:
const auto target = std::get_if<ImmediateNode>(operation[0]);
UNIMPLEMENTED_IF(!target);
- code.AddLine(fmt::format("flow_stack[flow_stack_top++] = 0x{:x}u;", target->GetValue()));
+ code.AddLine("flow_stack[flow_stack_top++] = 0x{:x}u;", target->GetValue());
return {};
}
@@ -1361,7 +1447,7 @@ private:
UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented");
- code.AddLine("if (alpha_test[0] != 0) {");
+ code.AddLine("if (alpha_test[0] != 0) {{");
++code.scope;
// We start on the register containing the alpha value in the first RT.
u32 current_reg = 3;
@@ -1372,13 +1458,12 @@ private:
header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
- code.AddLine(
- fmt::format("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg)));
+ code.AddLine("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg));
current_reg += 4;
}
}
--code.scope;
- code.AddLine('}');
+ code.AddLine("}}");
// Write the color outputs using the data in the shader registers, disabled
// rendertargets/components are skipped in the register assignment.
@@ -1387,8 +1472,8 @@ private:
// TODO(Subv): Figure out how dual-source blending is configured in the Switch.
for (u32 component = 0; component < 4; ++component) {
if (header.ps.IsColorComponentOutputEnabled(render_target, component)) {
- code.AddLine(fmt::format("FragColor{}[{}] = {};", render_target, component,
- SafeGetRegister(current_reg)));
+ code.AddLine("FragColor{}[{}] = {};", render_target, component,
+ SafeGetRegister(current_reg));
++current_reg;
}
}
@@ -1397,7 +1482,7 @@ private:
if (header.ps.omap.depth) {
// The depth output is always 2 registers after the last color output, and current_reg
// already contains one past the last color register.
- code.AddLine("gl_FragDepth = " + SafeGetRegister(current_reg + 1) + ';');
+ code.AddLine("gl_FragDepth = {};", SafeGetRegister(current_reg + 1));
}
code.AddLine("return;");
@@ -1407,11 +1492,11 @@ private:
std::string Discard(Operation operation) {
// Enclose "discard" in a conditional, so that GLSL compilation does not complain
// about unexecuted instructions that may follow this.
- code.AddLine("if (true) {");
+ code.AddLine("if (true) {{");
++code.scope;
code.AddLine("discard;");
--code.scope;
- code.AddLine("}");
+ code.AddLine("}}");
return {};
}
@@ -1591,15 +1676,11 @@ private:
}
std::string GetInputAttribute(Attribute::Index attribute) const {
- const auto index{static_cast<u32>(attribute) -
- static_cast<u32>(Attribute::Index::Attribute_0)};
- return GetDeclarationWithSuffix(index, "input_attr");
+ return GetDeclarationWithSuffix(GetGenericAttributeIndex(attribute), "input_attr");
}
std::string GetOutputAttribute(Attribute::Index attribute) const {
- const auto index{static_cast<u32>(attribute) -
- static_cast<u32>(Attribute::Index::Attribute_0)};
- return GetDeclarationWithSuffix(index, "output_attr");
+ return GetDeclarationWithSuffix(GetGenericAttributeIndex(attribute), "output_attr");
}
std::string GetConstBuffer(u32 index) const {
@@ -1629,7 +1710,7 @@ private:
const auto index = static_cast<u32>(flag);
ASSERT(index < static_cast<u32>(InternalFlag::Amount));
- return std::string(InternalFlagNames[index]) + '_' + suffix;
+ return fmt::format("{}_{}", InternalFlagNames[index], suffix);
}
std::string GetSampler(const Sampler& sampler) const {
@@ -1637,7 +1718,20 @@ private:
}
std::string GetDeclarationWithSuffix(u32 index, const std::string& name) const {
- return name + '_' + std::to_string(index) + '_' + suffix;
+ return fmt::format("{}_{}_{}", name, index, suffix);
+ }
+
+ u32 GetNumPhysicalInputAttributes() const {
+ return stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings();
+ }
+
+ u32 GetNumPhysicalAttributes() const {
+ return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes);
+ }
+
+ u32 GetNumPhysicalVaryings() const {
+ return std::min<u32>(device.GetMaxVaryings() - GENERIC_VARYING_START_LOCATION,
+ Maxwell::NumVaryings);
}
const Device& device;
@@ -1652,24 +1746,25 @@ private:
} // Anonymous namespace
std::string GetCommonDeclarations() {
- const auto cbuf = std::to_string(MAX_CONSTBUFFER_ELEMENTS);
- return "#define MAX_CONSTBUFFER_ELEMENTS " + cbuf + "\n" +
- "#define ftoi floatBitsToInt\n"
- "#define ftou floatBitsToUint\n"
- "#define itof intBitsToFloat\n"
- "#define utof uintBitsToFloat\n\n"
- "float fromHalf2(vec2 pair) {\n"
- " return utof(packHalf2x16(pair));\n"
- "}\n\n"
- "vec2 toHalf2(float value) {\n"
- " return unpackHalf2x16(ftou(value));\n"
- "}\n\n"
- "bvec2 halfFloatNanComparison(bvec2 comparison, vec2 pair1, vec2 pair2) {\n"
- " bvec2 is_nan1 = isnan(pair1);\n"
- " bvec2 is_nan2 = isnan(pair2);\n"
- " return bvec2(comparison.x || is_nan1.x || is_nan2.x, comparison.y || is_nan1.y || "
- "is_nan2.y);\n"
- "}\n";
+ return fmt::format(
+ "#define MAX_CONSTBUFFER_ELEMENTS {}\n"
+ "#define ftoi floatBitsToInt\n"
+ "#define ftou floatBitsToUint\n"
+ "#define itof intBitsToFloat\n"
+ "#define utof uintBitsToFloat\n\n"
+ "float fromHalf2(vec2 pair) {{\n"
+ " return utof(packHalf2x16(pair));\n"
+ "}}\n\n"
+ "vec2 toHalf2(float value) {{\n"
+ " return unpackHalf2x16(ftou(value));\n"
+ "}}\n\n"
+ "bvec2 halfFloatNanComparison(bvec2 comparison, vec2 pair1, vec2 pair2) {{\n"
+ " bvec2 is_nan1 = isnan(pair1);\n"
+ " bvec2 is_nan2 = isnan(pair2);\n"
+ " return bvec2(comparison.x || is_nan1.x || is_nan2.x, comparison.y || is_nan1.y || "
+ "is_nan2.y);\n"
+ "}}\n",
+ MAX_CONSTBUFFER_ELEMENTS);
}
ProgramResult Decompile(const Device& device, const ShaderIR& ir, Maxwell::ShaderStage stage,
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 254c0d499..fba9c594a 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -104,8 +104,9 @@ bool ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const {
return true;
}
-ShaderDiskCacheOpenGL::ShaderDiskCacheOpenGL(Core::System& system)
- : system{system}, precompiled_cache_virtual_file_offset{0} {}
+ShaderDiskCacheOpenGL::ShaderDiskCacheOpenGL(Core::System& system) : system{system} {}
+
+ShaderDiskCacheOpenGL::~ShaderDiskCacheOpenGL() = default;
std::optional<std::pair<std::vector<ShaderDiskCacheRaw>, std::vector<ShaderDiskCacheUsage>>>
ShaderDiskCacheOpenGL::LoadTransferable() {
@@ -243,7 +244,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) {
return {};
}
- const auto entry = LoadDecompiledEntry();
+ auto entry = LoadDecompiledEntry();
if (!entry) {
return {};
}
@@ -287,13 +288,13 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
return {};
}
- std::vector<u8> code(code_size);
+ std::string code(code_size, '\0');
if (!LoadArrayFromPrecompiled(code.data(), code.size())) {
return {};
}
ShaderDiskCacheDecompiled entry;
- entry.code = std::string(reinterpret_cast<const char*>(code.data()), code_size);
+ entry.code = std::move(code);
u32 const_buffers_count{};
if (!LoadObjectFromPrecompiled(const_buffers_count)) {
@@ -303,12 +304,12 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
for (u32 i = 0; i < const_buffers_count; ++i) {
u32 max_offset{};
u32 index{};
- u8 is_indirect{};
+ bool is_indirect{};
if (!LoadObjectFromPrecompiled(max_offset) || !LoadObjectFromPrecompiled(index) ||
!LoadObjectFromPrecompiled(is_indirect)) {
return {};
}
- entry.entries.const_buffers.emplace_back(max_offset, is_indirect != 0, index);
+ entry.entries.const_buffers.emplace_back(max_offset, is_indirect, index);
}
u32 samplers_count{};
@@ -320,18 +321,17 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
u64 offset{};
u64 index{};
u32 type{};
- u8 is_array{};
- u8 is_shadow{};
- u8 is_bindless{};
+ bool is_array{};
+ bool is_shadow{};
+ bool is_bindless{};
if (!LoadObjectFromPrecompiled(offset) || !LoadObjectFromPrecompiled(index) ||
!LoadObjectFromPrecompiled(type) || !LoadObjectFromPrecompiled(is_array) ||
!LoadObjectFromPrecompiled(is_shadow) || !LoadObjectFromPrecompiled(is_bindless)) {
return {};
}
- entry.entries.samplers.emplace_back(static_cast<std::size_t>(offset),
- static_cast<std::size_t>(index),
- static_cast<Tegra::Shader::TextureType>(type),
- is_array != 0, is_shadow != 0, is_bindless != 0);
+ entry.entries.samplers.emplace_back(
+ static_cast<std::size_t>(offset), static_cast<std::size_t>(index),
+ static_cast<Tegra::Shader::TextureType>(type), is_array, is_shadow, is_bindless);
}
u32 global_memory_count{};
@@ -342,21 +342,20 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
for (u32 i = 0; i < global_memory_count; ++i) {
u32 cbuf_index{};
u32 cbuf_offset{};
- u8 is_read{};
- u8 is_written{};
+ bool is_read{};
+ bool is_written{};
if (!LoadObjectFromPrecompiled(cbuf_index) || !LoadObjectFromPrecompiled(cbuf_offset) ||
!LoadObjectFromPrecompiled(is_read) || !LoadObjectFromPrecompiled(is_written)) {
return {};
}
- entry.entries.global_memory_entries.emplace_back(cbuf_index, cbuf_offset, is_read != 0,
- is_written != 0);
+ entry.entries.global_memory_entries.emplace_back(cbuf_index, cbuf_offset, is_read,
+ is_written);
}
for (auto& clip_distance : entry.entries.clip_distances) {
- u8 clip_distance_raw{};
- if (!LoadObjectFromPrecompiled(clip_distance_raw))
+ if (!LoadObjectFromPrecompiled(clip_distance)) {
return {};
- clip_distance = clip_distance_raw != 0;
+ }
}
u64 shader_length{};
@@ -384,7 +383,7 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std:
for (const auto& cbuf : entries.const_buffers) {
if (!SaveObjectToPrecompiled(static_cast<u32>(cbuf.GetMaxOffset())) ||
!SaveObjectToPrecompiled(static_cast<u32>(cbuf.GetIndex())) ||
- !SaveObjectToPrecompiled(static_cast<u8>(cbuf.IsIndirect() ? 1 : 0))) {
+ !SaveObjectToPrecompiled(cbuf.IsIndirect())) {
return false;
}
}
@@ -396,9 +395,9 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std:
if (!SaveObjectToPrecompiled(static_cast<u64>(sampler.GetOffset())) ||
!SaveObjectToPrecompiled(static_cast<u64>(sampler.GetIndex())) ||
!SaveObjectToPrecompiled(static_cast<u32>(sampler.GetType())) ||
- !SaveObjectToPrecompiled(static_cast<u8>(sampler.IsArray() ? 1 : 0)) ||
- !SaveObjectToPrecompiled(static_cast<u8>(sampler.IsShadow() ? 1 : 0)) ||
- !SaveObjectToPrecompiled(static_cast<u8>(sampler.IsBindless() ? 1 : 0))) {
+ !SaveObjectToPrecompiled(sampler.IsArray()) ||
+ !SaveObjectToPrecompiled(sampler.IsShadow()) ||
+ !SaveObjectToPrecompiled(sampler.IsBindless())) {
return false;
}
}
@@ -409,14 +408,13 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std:
for (const auto& gmem : entries.global_memory_entries) {
if (!SaveObjectToPrecompiled(static_cast<u32>(gmem.GetCbufIndex())) ||
!SaveObjectToPrecompiled(static_cast<u32>(gmem.GetCbufOffset())) ||
- !SaveObjectToPrecompiled(static_cast<u8>(gmem.IsRead() ? 1 : 0)) ||
- !SaveObjectToPrecompiled(static_cast<u8>(gmem.IsWritten() ? 1 : 0))) {
+ !SaveObjectToPrecompiled(gmem.IsRead()) || !SaveObjectToPrecompiled(gmem.IsWritten())) {
return false;
}
}
for (const bool clip_distance : entries.clip_distances) {
- if (!SaveObjectToPrecompiled(static_cast<u8>(clip_distance ? 1 : 0))) {
+ if (!SaveObjectToPrecompiled(clip_distance)) {
return false;
}
}
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.h b/src/video_core/renderer_opengl/gl_shader_disk_cache.h
index 0142b2e3b..2da0a4a23 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h
@@ -70,14 +70,14 @@ namespace std {
template <>
struct hash<OpenGL::BaseBindings> {
- std::size_t operator()(const OpenGL::BaseBindings& bindings) const {
+ std::size_t operator()(const OpenGL::BaseBindings& bindings) const noexcept {
return bindings.cbuf | bindings.gmem << 8 | bindings.sampler << 16;
}
};
template <>
struct hash<OpenGL::ShaderDiskCacheUsage> {
- std::size_t operator()(const OpenGL::ShaderDiskCacheUsage& usage) const {
+ std::size_t operator()(const OpenGL::ShaderDiskCacheUsage& usage) const noexcept {
return static_cast<std::size_t>(usage.unique_identifier) ^
std::hash<OpenGL::BaseBindings>()(usage.bindings) ^ usage.primitive << 16;
}
@@ -162,6 +162,7 @@ struct ShaderDiskCacheDump {
class ShaderDiskCacheOpenGL {
public:
explicit ShaderDiskCacheOpenGL(Core::System& system);
+ ~ShaderDiskCacheOpenGL();
/// Loads transferable cache. If file has a old version or on failure, it deletes the file.
std::optional<std::pair<std::vector<ShaderDiskCacheRaw>, std::vector<ShaderDiskCacheUsage>>>
@@ -259,20 +260,35 @@ private:
return SaveArrayToPrecompiled(&object, 1);
}
+ bool SaveObjectToPrecompiled(bool object) {
+ const auto value = static_cast<u8>(object);
+ return SaveArrayToPrecompiled(&value, 1);
+ }
+
template <typename T>
bool LoadObjectFromPrecompiled(T& object) {
return LoadArrayFromPrecompiled(&object, 1);
}
- // Copre system
+ bool LoadObjectFromPrecompiled(bool& object) {
+ u8 value;
+ const bool read_ok = LoadArrayFromPrecompiled(&value, 1);
+ if (!read_ok) {
+ return false;
+ }
+
+ object = value != 0;
+ return true;
+ }
+
+ // Core system
Core::System& system;
// Stored transferable shaders
std::map<u64, std::unordered_set<ShaderDiskCacheUsage>> transferable;
- // Stores whole precompiled cache which will be read from or saved to the precompiled chache
- // file
+ // Stores whole precompiled cache which will be read from/saved to the precompiled cache file
FileSys::VectorVfsFile precompiled_cache_virtual_file;
// Stores the current offset of the precompiled cache file for IO purposes
- std::size_t precompiled_cache_virtual_file_offset;
+ std::size_t precompiled_cache_virtual_file_offset = 0;
// The cache has been loaded at boot
bool tried_to_load{};
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 6abf948f8..7ab0b4553 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -33,14 +33,14 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
};
)";
- ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
+ const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
ProgramResult program =
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
out += program.first;
if (setup.IsDualProgram()) {
- ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
+ const ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
ProgramResult program_b =
Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
@@ -76,7 +76,7 @@ void main() {
}
})";
- return {out, program.second};
+ return {std::move(out), std::move(program.second)};
}
ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) {
@@ -97,7 +97,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
};
)";
- ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
+ const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
ProgramResult program =
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
out += program.first;
@@ -107,7 +107,7 @@ void main() {
execute_geometry();
};)";
- return {out, program.second};
+ return {std::move(out), std::move(program.second)};
}
ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) {
@@ -160,7 +160,7 @@ bool AlphaFunc(in float value) {
}
)";
- ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
+ const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
ProgramResult program =
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");
@@ -172,7 +172,7 @@ void main() {
}
)";
- return {out, program.second};
+ return {std::move(out), std::move(program.second)};
}
} // namespace OpenGL::GLShader
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 95b773135..ed7b5cff0 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -126,6 +126,8 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
return GL_TRIANGLES;
case Maxwell::PrimitiveTopology::TriangleStrip:
return GL_TRIANGLE_STRIP;
+ case Maxwell::PrimitiveTopology::TriangleFan:
+ return GL_TRIANGLE_FAN;
default:
LOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology));
UNREACHABLE();
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index a11000f6b..b61a6d170 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -194,8 +194,8 @@ public:
for (const auto& sampler : ir.GetSamplers()) {
entries.samplers.emplace_back(sampler);
}
- for (const auto& attr : ir.GetInputAttributes()) {
- entries.attributes.insert(GetGenericAttributeLocation(attr.first));
+ for (const auto& attribute : ir.GetInputAttributes()) {
+ entries.attributes.insert(GetGenericAttributeLocation(attribute));
}
entries.clip_distances = ir.GetClipDistances();
entries.shader_length = ir.GetLength();
@@ -321,8 +321,7 @@ private:
}
void DeclareInputAttributes() {
- for (const auto element : ir.GetInputAttributes()) {
- const Attribute::Index index = element.first;
+ for (const auto index : ir.GetInputAttributes()) {
if (!IsGenericAttribute(index)) {
continue;
}
diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp
index 3190e2d7c..b4859bc1e 100644
--- a/src/video_core/shader/decode/arithmetic.cpp
+++ b/src/video_core/shader/decode/arithmetic.cpp
@@ -4,6 +4,7 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/shader_ir.h"
@@ -152,4 +153,4 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/arithmetic_half.cpp b/src/video_core/shader/decode/arithmetic_half.cpp
index 2098c1170..3a29c4a46 100644
--- a/src/video_core/shader/decode/arithmetic_half.cpp
+++ b/src/video_core/shader/decode/arithmetic_half.cpp
@@ -4,6 +4,7 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/shader_ir.h"
diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
index fbcd35b18..5341e460f 100644
--- a/src/video_core/shader/decode/arithmetic_half_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
@@ -4,6 +4,7 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/shader_ir.h"
@@ -47,4 +48,4 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/arithmetic_immediate.cpp b/src/video_core/shader/decode/arithmetic_immediate.cpp
index 0d139c0d2..3095f2fd4 100644
--- a/src/video_core/shader/decode/arithmetic_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_immediate.cpp
@@ -49,4 +49,4 @@ u32 ShaderIR::DecodeArithmeticImmediate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp
index 3ed5ccc5a..679ac0d4e 100644
--- a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp
@@ -93,4 +93,4 @@ void ShaderIR::WriteLogicOperation(NodeBlock& bb, Register dest, LogicOperation
}
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/bfe.cpp b/src/video_core/shader/decode/bfe.cpp
index 6a95dc928..1ae192c6a 100644
--- a/src/video_core/shader/decode/bfe.cpp
+++ b/src/video_core/shader/decode/bfe.cpp
@@ -46,4 +46,4 @@ u32 ShaderIR::DecodeBfe(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/bfi.cpp b/src/video_core/shader/decode/bfi.cpp
index 601d66f1f..0b12a0d08 100644
--- a/src/video_core/shader/decode/bfi.cpp
+++ b/src/video_core/shader/decode/bfi.cpp
@@ -38,4 +38,4 @@ u32 ShaderIR::DecodeBfi(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/ffma.cpp b/src/video_core/shader/decode/ffma.cpp
index 0559cc8de..a1d04c6e5 100644
--- a/src/video_core/shader/decode/ffma.cpp
+++ b/src/video_core/shader/decode/ffma.cpp
@@ -56,4 +56,4 @@ u32 ShaderIR::DecodeFfma(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/float_set.cpp b/src/video_core/shader/decode/float_set.cpp
index 1bd6755dd..cc522f1de 100644
--- a/src/video_core/shader/decode/float_set.cpp
+++ b/src/video_core/shader/decode/float_set.cpp
@@ -55,4 +55,4 @@ u32 ShaderIR::DecodeFloatSet(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/float_set_predicate.cpp b/src/video_core/shader/decode/float_set_predicate.cpp
index 9285b8d05..9d2322a1d 100644
--- a/src/video_core/shader/decode/float_set_predicate.cpp
+++ b/src/video_core/shader/decode/float_set_predicate.cpp
@@ -53,4 +53,4 @@ u32 ShaderIR::DecodeFloatSetPredicate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp
index 1dd94bf9d..755f2ec44 100644
--- a/src/video_core/shader/decode/half_set.cpp
+++ b/src/video_core/shader/decode/half_set.cpp
@@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/shader_ir.h"
@@ -64,4 +65,4 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp
index 6e59eb650..fba44d714 100644
--- a/src/video_core/shader/decode/half_set_predicate.cpp
+++ b/src/video_core/shader/decode/half_set_predicate.cpp
@@ -59,4 +59,4 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/integer_set.cpp b/src/video_core/shader/decode/integer_set.cpp
index a3bf17eba..a4cdaf74d 100644
--- a/src/video_core/shader/decode/integer_set.cpp
+++ b/src/video_core/shader/decode/integer_set.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "common/assert.h"
#include "common/common_types.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/shader_ir.h"
@@ -47,4 +46,4 @@ u32 ShaderIR::DecodeIntegerSet(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/integer_set_predicate.cpp b/src/video_core/shader/decode/integer_set_predicate.cpp
index aad836d24..a6a1fb632 100644
--- a/src/video_core/shader/decode/integer_set_predicate.cpp
+++ b/src/video_core/shader/decode/integer_set_predicate.cpp
@@ -50,4 +50,4 @@ u32 ShaderIR::DecodeIntegerSetPredicate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index ea1092db1..165c2b41b 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -47,17 +47,20 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
"Indirect attribute loads are not supported");
UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0,
"Unaligned attribute loads are not supported");
+ UNIMPLEMENTED_IF_MSG(instr.attribute.fmt20.IsPhysical() &&
+ instr.attribute.fmt20.size != Tegra::Shader::AttributeSize::Word,
+ "Non-32 bits PHYS reads are not implemented");
- Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Pass,
- Tegra::Shader::IpaSampleMode::Default};
+ const Node buffer{GetRegister(instr.gpr39)};
u64 next_element = instr.attribute.fmt20.element;
auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
const auto LoadNextElement = [&](u32 reg_offset) {
- const Node buffer = GetRegister(instr.gpr39);
- const Node attribute = GetInputAttribute(static_cast<Attribute::Index>(next_index),
- next_element, input_mode, buffer);
+ const Node attribute{instr.attribute.fmt20.IsPhysical()
+ ? GetPhysicalInputAttribute(instr.gpr8, buffer)
+ : GetInputAttribute(static_cast<Attribute::Index>(next_index),
+ next_element, buffer)};
SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute);
@@ -239,6 +242,21 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
}
break;
}
+ case OpCode::Id::AL2P: {
+ // Ignore al2p.direction since we don't care about it.
+
+ // Calculate emulation fake physical address.
+ const Node fixed_address{Immediate(static_cast<u32>(instr.al2p.address))};
+ const Node reg{GetRegister(instr.gpr8)};
+ const Node fake_address{Operation(OperationCode::IAdd, NO_PRECISE, reg, fixed_address)};
+
+ // Set the fake address to target register.
+ SetRegister(bb, instr.gpr0, fake_address);
+
+ // Signal the shader IR to declare all possible attributes and varyings
+ uses_physical_attributes = true;
+ break;
+ }
default:
UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName());
}
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index d750a2936..ca7af72e1 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -4,6 +4,7 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/shader_ir.h"
@@ -130,15 +131,18 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
break;
}
case OpCode::Id::IPA: {
- const auto& attribute = instr.attribute.fmt28;
+ const bool is_physical = instr.ipa.idx && instr.gpr8.Value() != 0xff;
+
+ const auto attribute = instr.attribute.fmt28;
const Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(),
instr.ipa.sample_mode.Value()};
- const Node attr = GetInputAttribute(attribute.index, attribute.element, input_mode);
- Node value = attr;
+ Node value = is_physical ? GetPhysicalInputAttribute(instr.gpr8)
+ : GetInputAttribute(attribute.index, attribute.element);
const Tegra::Shader::Attribute::Index index = attribute.index.Value();
- if (index >= Tegra::Shader::Attribute::Index::Attribute_0 &&
- index <= Tegra::Shader::Attribute::Index::Attribute_31) {
+ const bool is_generic = index >= Tegra::Shader::Attribute::Index::Attribute_0 &&
+ index <= Tegra::Shader::Attribute::Index::Attribute_31;
+ if (is_generic || is_physical) {
// TODO(Blinkhawk): There are cases where a perspective attribute use PASS.
// In theory by setting them as perspective, OpenGL does the perspective correction.
// A way must figured to reverse the last step of it.
diff --git a/src/video_core/shader/decode/predicate_set_predicate.cpp b/src/video_core/shader/decode/predicate_set_predicate.cpp
index 83c61680e..71844c42b 100644
--- a/src/video_core/shader/decode/predicate_set_predicate.cpp
+++ b/src/video_core/shader/decode/predicate_set_predicate.cpp
@@ -64,4 +64,4 @@ u32 ShaderIR::DecodePredicateSetPredicate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/predicate_set_register.cpp b/src/video_core/shader/decode/predicate_set_register.cpp
index d0495995d..387491bd3 100644
--- a/src/video_core/shader/decode/predicate_set_register.cpp
+++ b/src/video_core/shader/decode/predicate_set_register.cpp
@@ -43,4 +43,4 @@ u32 ShaderIR::DecodePredicateSetRegister(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/register_set_predicate.cpp b/src/video_core/shader/decode/register_set_predicate.cpp
index f070e8912..f8659e48e 100644
--- a/src/video_core/shader/decode/register_set_predicate.cpp
+++ b/src/video_core/shader/decode/register_set_predicate.cpp
@@ -48,4 +48,4 @@ u32 ShaderIR::DecodeRegisterSetPredicate(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/shift.cpp b/src/video_core/shader/decode/shift.cpp
index 951e85f44..44ae87ece 100644
--- a/src/video_core/shader/decode/shift.cpp
+++ b/src/video_core/shader/decode/shift.cpp
@@ -52,4 +52,4 @@ u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) {
return pc;
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/video.cpp b/src/video_core/shader/decode/video.cpp
index 956c01d9b..cb9ab72b1 100644
--- a/src/video_core/shader/decode/video.cpp
+++ b/src/video_core/shader/decode/video.cpp
@@ -108,4 +108,4 @@ Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed,
}
}
-} // namespace VideoCommon::Shader \ No newline at end of file
+} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index e4eb0dfd9..8a6ee5cf5 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -21,6 +21,13 @@ using Tegra::Shader::PredCondition;
using Tegra::Shader::PredOperation;
using Tegra::Shader::Register;
+ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset)
+ : program_code{program_code}, main_offset{main_offset} {
+ Decode();
+}
+
+ShaderIR::~ShaderIR() = default;
+
Node ShaderIR::StoreNode(NodeData&& node_data) {
auto store = std::make_unique<NodeData>(node_data);
const Node node = store.get();
@@ -32,8 +39,8 @@ Node ShaderIR::Conditional(Node condition, std::vector<Node>&& code) {
return StoreNode(ConditionalNode(condition, std::move(code)));
}
-Node ShaderIR::Comment(const std::string& text) {
- return StoreNode(CommentNode(text));
+Node ShaderIR::Comment(std::string text) {
+ return StoreNode(CommentNode(std::move(text)));
}
Node ShaderIR::Immediate(u32 value) {
@@ -89,13 +96,14 @@ Node ShaderIR::GetPredicate(bool immediate) {
return GetPredicate(static_cast<u64>(immediate ? Pred::UnusedIndex : Pred::NeverExecute));
}
-Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element,
- const Tegra::Shader::IpaMode& input_mode, Node buffer) {
- const auto [entry, is_new] =
- used_input_attributes.emplace(std::make_pair(index, std::set<Tegra::Shader::IpaMode>{}));
- entry->second.insert(input_mode);
+Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) {
+ used_input_attributes.emplace(index);
+ return StoreNode(AbufNode(index, static_cast<u32>(element), buffer));
+}
- return StoreNode(AbufNode(index, static_cast<u32>(element), input_mode, buffer));
+Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) {
+ uses_physical_attributes = true;
+ return StoreNode(AbufNode(GetRegister(physical_address), buffer));
}
Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) {
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 65f1e1de9..34d183ec7 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -328,40 +328,31 @@ struct MetaTexture {
u32 element{};
};
-inline constexpr MetaArithmetic PRECISE = {true};
-inline constexpr MetaArithmetic NO_PRECISE = {false};
+constexpr MetaArithmetic PRECISE = {true};
+constexpr MetaArithmetic NO_PRECISE = {false};
using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
/// Holds any kind of operation that can be done in the IR
class OperationNode final {
public:
- template <typename... T>
- explicit constexpr OperationNode(OperationCode code) : code{code}, meta{} {}
+ explicit OperationNode(OperationCode code) : code{code} {}
- template <typename... T>
- explicit constexpr OperationNode(OperationCode code, Meta&& meta)
- : code{code}, meta{std::move(meta)} {}
+ explicit OperationNode(OperationCode code, Meta&& meta) : code{code}, meta{std::move(meta)} {}
template <typename... T>
- explicit constexpr OperationNode(OperationCode code, const T*... operands)
+ explicit OperationNode(OperationCode code, const T*... operands)
: OperationNode(code, {}, operands...) {}
template <typename... T>
- explicit constexpr OperationNode(OperationCode code, Meta&& meta, const T*... operands_)
- : code{code}, meta{std::move(meta)} {
-
- auto operands_list = {operands_...};
- for (auto& operand : operands_list) {
- operands.push_back(operand);
- }
- }
+ explicit OperationNode(OperationCode code, Meta&& meta, const T*... operands_)
+ : code{code}, meta{std::move(meta)}, operands{operands_...} {}
explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands)
: code{code}, meta{meta}, operands{std::move(operands)} {}
explicit OperationNode(OperationCode code, std::vector<Node>&& operands)
- : code{code}, meta{}, operands{std::move(operands)} {}
+ : code{code}, operands{std::move(operands)} {}
OperationCode GetCode() const {
return code;
@@ -465,17 +456,14 @@ private:
/// Attribute buffer memory (known as attributes or varyings in GLSL terms)
class AbufNode final {
public:
- explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element,
- const Tegra::Shader::IpaMode& input_mode, Node buffer = {})
- : input_mode{input_mode}, buffer{buffer}, index{index}, element{element} {}
-
+ // Initialize for standard attributes (index is explicit).
explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element,
Node buffer = {})
- : input_mode{}, buffer{buffer}, index{index}, element{element} {}
+ : buffer{buffer}, index{index}, element{element} {}
- Tegra::Shader::IpaMode GetInputMode() const {
- return input_mode;
- }
+ // Initialize for physical attributes (index is a variable value).
+ explicit constexpr AbufNode(Node physical_address, Node buffer = {})
+ : physical_address{physical_address}, buffer{buffer} {}
Tegra::Shader::Attribute::Index GetIndex() const {
return index;
@@ -489,11 +477,19 @@ public:
return buffer;
}
+ bool IsPhysicalBuffer() const {
+ return physical_address != nullptr;
+ }
+
+ Node GetPhysicalAddress() const {
+ return physical_address;
+ }
+
private:
- const Tegra::Shader::IpaMode input_mode;
- const Node buffer;
- const Tegra::Shader::Attribute::Index index;
- const u32 element;
+ Node physical_address{};
+ Node buffer{};
+ Tegra::Shader::Attribute::Index index{};
+ u32 element{};
};
/// Constant buffer node, usually mapped to uniform buffers in GLSL
@@ -567,11 +563,8 @@ private:
class ShaderIR final {
public:
- explicit ShaderIR(const ProgramCode& program_code, u32 main_offset)
- : program_code{program_code}, main_offset{main_offset} {
-
- Decode();
- }
+ explicit ShaderIR(const ProgramCode& program_code, u32 main_offset);
+ ~ShaderIR();
const std::map<u32, NodeBlock>& GetBasicBlocks() const {
return basic_blocks;
@@ -585,8 +578,7 @@ public:
return used_predicates;
}
- const std::map<Tegra::Shader::Attribute::Index, std::set<Tegra::Shader::IpaMode>>&
- GetInputAttributes() const {
+ const std::set<Tegra::Shader::Attribute::Index>& GetInputAttributes() const {
return used_input_attributes;
}
@@ -615,6 +607,10 @@ public:
return static_cast<std::size_t>(coverage_end * sizeof(u64));
}
+ bool HasPhysicalAttributes() const {
+ return uses_physical_attributes;
+ }
+
const Tegra::Shader::Header& GetHeader() const {
return header;
}
@@ -667,7 +663,7 @@ private:
/// Creates a conditional node
Node Conditional(Node condition, std::vector<Node>&& code);
/// Creates a commentary
- Node Comment(const std::string& text);
+ Node Comment(std::string text);
/// Creates an u32 immediate
Node Immediate(u32 value);
/// Creates a s32 immediate
@@ -696,8 +692,9 @@ private:
/// Generates a predicate node for an immediate true or false value
Node GetPredicate(bool immediate);
/// Generates a node representing an input attribute. Keeps track of used attributes.
- Node GetInputAttribute(Tegra::Shader::Attribute::Index index, u64 element,
- const Tegra::Shader::IpaMode& input_mode, Node buffer = {});
+ Node GetInputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer = {});
+ /// Generates a node representing a physical input attribute.
+ Node GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer = {});
/// Generates a node representing an output attribute. Keeps track of used attributes.
Node GetOutputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer);
/// Generates a node representing an internal flag
@@ -814,11 +811,12 @@ private:
void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
Node op_c, Node imm_lut, bool sets_cc);
- Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor);
+ Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const;
- std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor);
+ std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const;
- std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, s64 cursor);
+ std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code,
+ s64 cursor) const;
std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(NodeBlock& bb,
Node addr_register,
@@ -835,12 +833,10 @@ private:
return StoreNode(OperationNode(code, std::move(meta), operands...));
}
- template <typename... T>
Node Operation(OperationCode code, std::vector<Node>&& operands) {
return StoreNode(OperationNode(code, std::move(operands)));
}
- template <typename... T>
Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) {
return StoreNode(OperationNode(code, std::move(meta), std::move(operands)));
}
@@ -872,13 +868,13 @@ private:
std::set<u32> used_registers;
std::set<Tegra::Shader::Pred> used_predicates;
- std::map<Tegra::Shader::Attribute::Index, std::set<Tegra::Shader::IpaMode>>
- used_input_attributes;
+ std::set<Tegra::Shader::Attribute::Index> used_input_attributes;
std::set<Tegra::Shader::Attribute::Index> used_output_attributes;
std::map<u32, ConstBuffer> used_cbufs;
std::set<Sampler> used_samplers;
std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory;
+ bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
Tegra::Shader::Header header;
};
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
index 4505667ff..19ede1eb9 100644
--- a/src/video_core/shader/track.cpp
+++ b/src/video_core/shader/track.cpp
@@ -17,22 +17,24 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
for (; cursor >= 0; --cursor) {
const Node node = code.at(cursor);
if (const auto operation = std::get_if<OperationNode>(node)) {
- if (operation->GetCode() == operation_code)
+ if (operation->GetCode() == operation_code) {
return {node, cursor};
+ }
}
if (const auto conditional = std::get_if<ConditionalNode>(node)) {
const auto& conditional_code = conditional->GetCode();
const auto [found, internal_cursor] = FindOperation(
conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code);
- if (found)
+ if (found) {
return {found, cursor};
+ }
}
}
return {};
}
} // namespace
-Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) {
+Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const {
if (const auto cbuf = std::get_if<CbufNode>(tracked)) {
// Cbuf found, but it has to be immediate
return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
@@ -65,7 +67,7 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) {
return nullptr;
}
-std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) {
+std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const {
// Reduce the cursor in one to avoid infinite loops when the instruction sets the same register
// that it uses as operand
const auto [found, found_cursor] =
@@ -80,7 +82,7 @@ std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code,
}
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeBlock& code,
- s64 cursor) {
+ s64 cursor) const {
for (; cursor >= 0; --cursor) {
const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign);
if (!found_node) {
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 5138bd9a3..7e883991a 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -82,8 +82,6 @@ add_executable(yuzu
util/limitable_input_dialog.h
util/sequence_dialog/sequence_dialog.cpp
util/sequence_dialog/sequence_dialog.h
- util/spinbox.cpp
- util/spinbox.h
util/util.cpp
util/util.h
compatdb.cpp
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp
index 1fb2fe277..106dde9e2 100644
--- a/src/yuzu/applets/error.cpp
+++ b/src/yuzu/applets/error.cpp
@@ -54,6 +54,6 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
void QtErrorDisplay::MainWindowFinishedError() {
// Acquire the HLE mutex
- std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
+ std::lock_guard lock{HLE::g_hle_lock};
callback();
}
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
index 743b24d76..7fbc9deeb 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/profile_select.cpp
@@ -84,10 +84,10 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
tree_view->setContextMenuPolicy(Qt::NoContextMenu);
item_model->insertColumns(0, 1);
- item_model->setHeaderData(0, Qt::Horizontal, "Users");
+ item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
// We must register all custom types with the Qt Automoc system so that we are able to use it
- // with signals/slots. In this case, QList falls under the umbrells of custom types.
+ // with signals/slots. In this case, QList falls under the umbrella of custom types.
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
layout->setContentsMargins(0, 0, 0, 0);
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 5c98636c5..c2783d684 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -188,7 +188,9 @@ private:
GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)
: QWidget(parent), emu_thread(emu_thread) {
setWindowTitle(QStringLiteral("yuzu %1 | %2-%3")
- .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
+ .arg(QString::fromUtf8(Common::g_build_name),
+ QString::fromUtf8(Common::g_scm_branch),
+ QString::fromUtf8(Common::g_scm_desc)));
setAttribute(Qt::WA_AcceptTouchEvents);
InputCommon::Init();
@@ -217,7 +219,7 @@ void GRenderWindow::SwapBuffers() {
// However:
// - The Qt debug runtime prints a bogus warning on the console if `makeCurrent` wasn't called
// since the last time `swapBuffers` was executed;
- // - On macOS, if `makeCurrent` isn't called explicitely, resizing the buffer breaks.
+ // - On macOS, if `makeCurrent` isn't called explicitly, resizing the buffer breaks.
context->makeCurrent(child);
context->swapBuffers(child);
@@ -379,6 +381,7 @@ void GRenderWindow::InitRenderTarget() {
fmt.setVersion(4, 3);
if (Settings::values.use_compatibility_profile) {
fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
+ fmt.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
} else {
fmt.setProfile(QSurfaceFormat::CoreProfile);
}
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 6c6f047d8..d28826c67 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -230,55 +230,64 @@ void Config::ReadPlayerValues() {
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
auto& player = Settings::values.players[p];
- player.connected = ReadSetting(QString("player_%1_connected").arg(p), false).toBool();
+ player.connected =
+ ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool();
player.type = static_cast<Settings::ControllerType>(
qt_config
- ->value(QString("player_%1_type").arg(p),
+ ->value(QStringLiteral("player_%1_type").arg(p),
static_cast<u8>(Settings::ControllerType::DualJoycon))
.toUInt());
player.body_color_left = qt_config
- ->value(QString("player_%1_body_color_left").arg(p),
+ ->value(QStringLiteral("player_%1_body_color_left").arg(p),
Settings::JOYCON_BODY_NEON_BLUE)
.toUInt();
player.body_color_right = qt_config
- ->value(QString("player_%1_body_color_right").arg(p),
+ ->value(QStringLiteral("player_%1_body_color_right").arg(p),
Settings::JOYCON_BODY_NEON_RED)
.toUInt();
player.button_color_left = qt_config
- ->value(QString("player_%1_button_color_left").arg(p),
+ ->value(QStringLiteral("player_%1_button_color_left").arg(p),
Settings::JOYCON_BUTTONS_NEON_BLUE)
.toUInt();
- player.button_color_right = qt_config
- ->value(QString("player_%1_button_color_right").arg(p),
- Settings::JOYCON_BUTTONS_NEON_RED)
- .toUInt();
+ player.button_color_right =
+ qt_config
+ ->value(QStringLiteral("player_%1_button_color_right").arg(p),
+ Settings::JOYCON_BUTTONS_NEON_RED)
+ .toUInt();
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- player.buttons[i] =
- qt_config
- ->value(QString("player_%1_").arg(p) + Settings::NativeButton::mapping[i],
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (player.buttons[i].empty())
- player.buttons[i] = default_param;
+ const std::string default_param =
+ InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ auto& player_buttons = player.buttons[i];
+
+ player_buttons = qt_config
+ ->value(QStringLiteral("player_%1_").arg(p) +
+ QString::fromUtf8(Settings::NativeButton::mapping[i]),
+ QString::fromStdString(default_param))
+ .toString()
+ .toStdString();
+ if (player_buttons.empty()) {
+ player_buttons = default_param;
+ }
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
- player.analogs[i] =
- qt_config
- ->value(QString("player_%1_").arg(p) + Settings::NativeAnalog::mapping[i],
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (player.analogs[i].empty())
- player.analogs[i] = default_param;
+ auto& player_analogs = player.analogs[i];
+
+ player_analogs = qt_config
+ ->value(QStringLiteral("player_%1_").arg(p) +
+ QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
+ QString::fromStdString(default_param))
+ .toString()
+ .toStdString();
+ if (player_analogs.empty()) {
+ player_analogs = default_param;
+ }
}
}
@@ -290,36 +299,45 @@ void Config::ReadPlayerValues() {
}
void Config::ReadDebugValues() {
- Settings::values.debug_pad_enabled = ReadSetting("debug_pad_enabled", false).toBool();
+ Settings::values.debug_pad_enabled =
+ ReadSetting(QStringLiteral("debug_pad_enabled"), false).toBool();
+
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- Settings::values.debug_pad_buttons[i] =
- qt_config
- ->value(QString("debug_pad_") + Settings::NativeButton::mapping[i],
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (Settings::values.debug_pad_buttons[i].empty())
- Settings::values.debug_pad_buttons[i] = default_param;
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
+
+ debug_pad_buttons = qt_config
+ ->value(QStringLiteral("debug_pad_") +
+ QString::fromUtf8(Settings::NativeButton::mapping[i]),
+ QString::fromStdString(default_param))
+ .toString()
+ .toStdString();
+ if (debug_pad_buttons.empty()) {
+ debug_pad_buttons = default_param;
+ }
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
- Settings::values.debug_pad_analogs[i] =
- qt_config
- ->value(QString("debug_pad_") + Settings::NativeAnalog::mapping[i],
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (Settings::values.debug_pad_analogs[i].empty())
- Settings::values.debug_pad_analogs[i] = default_param;
+ auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
+
+ debug_pad_analogs = qt_config
+ ->value(QStringLiteral("debug_pad_") +
+ QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
+ QString::fromStdString(default_param))
+ .toString()
+ .toStdString();
+ if (debug_pad_analogs.empty()) {
+ debug_pad_analogs = default_param;
+ }
}
}
void Config::ReadKeyboardValues() {
- Settings::values.keyboard_enabled = ReadSetting("keyboard_enabled", false).toBool();
+ Settings::values.keyboard_enabled =
+ ReadSetting(QStringLiteral("keyboard_enabled"), false).toBool();
std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(),
Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam);
@@ -332,18 +350,22 @@ void Config::ReadKeyboardValues() {
}
void Config::ReadMouseValues() {
- Settings::values.mouse_enabled = ReadSetting("mouse_enabled", false).toBool();
+ Settings::values.mouse_enabled = ReadSetting(QStringLiteral("mouse_enabled"), false).toBool();
for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
- Settings::values.mouse_buttons[i] =
- qt_config
- ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i],
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (Settings::values.mouse_buttons[i].empty())
- Settings::values.mouse_buttons[i] = default_param;
+ const std::string default_param =
+ InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
+ auto& mouse_buttons = Settings::values.mouse_buttons[i];
+
+ mouse_buttons = qt_config
+ ->value(QStringLiteral("mouse_") +
+ QString::fromUtf8(Settings::NativeMouseButton::mapping[i]),
+ QString::fromStdString(default_param))
+ .toString()
+ .toStdString();
+ if (mouse_buttons.empty()) {
+ mouse_buttons = default_param;
+ }
}
}
@@ -356,7 +378,6 @@ void Config::ReadTouchscreenValues() {
Settings::values.touchscreen.rotation_angle = ReadSetting("touchscreen_angle", 0).toUInt();
Settings::values.touchscreen.diameter_x = ReadSetting("touchscreen_diameter_x", 15).toUInt();
Settings::values.touchscreen.diameter_y = ReadSetting("touchscreen_diameter_y", 15).toUInt();
- qt_config->endGroup();
}
void Config::ApplyDefaultProfileIfInputInvalid() {
@@ -366,8 +387,25 @@ void Config::ApplyDefaultProfileIfInputInvalid() {
}
}
-void Config::ReadValues() {
- qt_config->beginGroup("Controls");
+void Config::ReadAudioValues() {
+ qt_config->beginGroup(QStringLiteral("Audio"));
+
+ Settings::values.sink_id = ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto"))
+ .toString()
+ .toStdString();
+ Settings::values.enable_audio_stretching =
+ ReadSetting(QStringLiteral("enable_audio_stretching"), true).toBool();
+ Settings::values.audio_device_id =
+ ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto"))
+ .toString()
+ .toStdString();
+ Settings::values.volume = ReadSetting(QStringLiteral("volume"), 1).toFloat();
+
+ qt_config->endGroup();
+}
+
+void Config::ReadControlValues() {
+ qt_config->beginGroup(QStringLiteral("Controls"));
ReadPlayerValues();
ReadDebugValues();
@@ -376,162 +414,133 @@ void Config::ReadValues() {
ReadTouchscreenValues();
Settings::values.motion_device =
- ReadSetting("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01")
+ ReadSetting(QStringLiteral("motion_device"),
+ QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"))
.toString()
.toStdString();
- qt_config->beginGroup("Core");
- Settings::values.use_cpu_jit = ReadSetting("use_cpu_jit", true).toBool();
- Settings::values.use_multi_core = ReadSetting("use_multi_core", false).toBool();
qt_config->endGroup();
+}
- qt_config->beginGroup("Renderer");
- Settings::values.resolution_factor = ReadSetting("resolution_factor", 1.0).toFloat();
- Settings::values.use_frame_limit = ReadSetting("use_frame_limit", true).toBool();
- Settings::values.frame_limit = ReadSetting("frame_limit", 100).toInt();
- Settings::values.use_compatibility_profile =
- ReadSetting("use_compatibility_profile", true).toBool();
- Settings::values.use_disk_shader_cache = ReadSetting("use_disk_shader_cache", true).toBool();
- Settings::values.use_accurate_gpu_emulation =
- ReadSetting("use_accurate_gpu_emulation", false).toBool();
- Settings::values.use_asynchronous_gpu_emulation =
- ReadSetting("use_asynchronous_gpu_emulation", false).toBool();
- Settings::values.force_30fps_mode = ReadSetting("force_30fps_mode", false).toBool();
+void Config::ReadCoreValues() {
+ qt_config->beginGroup(QStringLiteral("Core"));
- Settings::values.bg_red = ReadSetting("bg_red", 0.0).toFloat();
- Settings::values.bg_green = ReadSetting("bg_green", 0.0).toFloat();
- Settings::values.bg_blue = ReadSetting("bg_blue", 0.0).toFloat();
- qt_config->endGroup();
+ Settings::values.use_cpu_jit = ReadSetting(QStringLiteral("use_cpu_jit"), true).toBool();
+ Settings::values.use_multi_core = ReadSetting(QStringLiteral("use_multi_core"), false).toBool();
- qt_config->beginGroup("Audio");
- Settings::values.sink_id = ReadSetting("output_engine", "auto").toString().toStdString();
- Settings::values.enable_audio_stretching =
- ReadSetting("enable_audio_stretching", true).toBool();
- Settings::values.audio_device_id =
- ReadSetting("output_device", "auto").toString().toStdString();
- Settings::values.volume = ReadSetting("volume", 1).toFloat();
qt_config->endGroup();
+}
+
+void Config::ReadDataStorageValues() {
+ qt_config->beginGroup(QStringLiteral("Data Storage"));
- qt_config->beginGroup("Data Storage");
- Settings::values.use_virtual_sd = ReadSetting("use_virtual_sd", true).toBool();
+ Settings::values.use_virtual_sd = ReadSetting(QStringLiteral("use_virtual_sd"), true).toBool();
FileUtil::GetUserPath(
FileUtil::UserPath::NANDDir,
qt_config
- ->value("nand_directory",
+ ->value(QStringLiteral("nand_directory"),
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)))
.toString()
.toStdString());
FileUtil::GetUserPath(
FileUtil::UserPath::SDMCDir,
qt_config
- ->value("sdmc_directory",
+ ->value(QStringLiteral("sdmc_directory"),
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)))
.toString()
.toStdString());
- qt_config->endGroup();
- qt_config->beginGroup("Core");
- Settings::values.use_cpu_jit = ReadSetting("use_cpu_jit", true).toBool();
- Settings::values.use_multi_core = ReadSetting("use_multi_core", false).toBool();
qt_config->endGroup();
+}
- qt_config->beginGroup("System");
- Settings::values.use_docked_mode = ReadSetting("use_docked_mode", false).toBool();
-
- Settings::values.current_user =
- std::clamp<int>(ReadSetting("current_user", 0).toInt(), 0, Service::Account::MAX_USERS - 1);
-
- Settings::values.language_index = ReadSetting("language_index", 1).toInt();
-
- const auto rng_seed_enabled = ReadSetting("rng_seed_enabled", false).toBool();
- if (rng_seed_enabled) {
- Settings::values.rng_seed = ReadSetting("rng_seed", 0).toULongLong();
- } else {
- Settings::values.rng_seed = std::nullopt;
- }
-
- const auto custom_rtc_enabled = ReadSetting("custom_rtc_enabled", false).toBool();
- if (custom_rtc_enabled) {
- Settings::values.custom_rtc =
- std::chrono::seconds(ReadSetting("custom_rtc", 0).toULongLong());
- } else {
- Settings::values.custom_rtc = std::nullopt;
- }
-
- qt_config->endGroup();
+void Config::ReadDebuggingValues() {
+ qt_config->beginGroup(QStringLiteral("Debugging"));
- qt_config->beginGroup("Miscellaneous");
- Settings::values.log_filter = ReadSetting("log_filter", "*:Info").toString().toStdString();
- Settings::values.use_dev_keys = ReadSetting("use_dev_keys", false).toBool();
- qt_config->endGroup();
+ Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool();
+ Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt();
+ Settings::values.program_args =
+ ReadSetting(QStringLiteral("program_args"), QStringLiteral("")).toString().toStdString();
+ Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool();
+ Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool();
- qt_config->beginGroup("Debugging");
- Settings::values.use_gdbstub = ReadSetting("use_gdbstub", false).toBool();
- Settings::values.gdbstub_port = ReadSetting("gdbstub_port", 24689).toInt();
- Settings::values.program_args = ReadSetting("program_args", "").toString().toStdString();
- Settings::values.dump_exefs = ReadSetting("dump_exefs", false).toBool();
- Settings::values.dump_nso = ReadSetting("dump_nso", false).toBool();
qt_config->endGroup();
+}
- qt_config->beginGroup("WebService");
- Settings::values.enable_telemetry = ReadSetting("enable_telemetry", true).toBool();
- Settings::values.web_api_url =
- ReadSetting("web_api_url", "https://api.yuzu-emu.org").toString().toStdString();
- Settings::values.yuzu_username = ReadSetting("yuzu_username").toString().toStdString();
- Settings::values.yuzu_token = ReadSetting("yuzu_token").toString().toStdString();
- qt_config->endGroup();
+void Config::ReadDisabledAddOnValues() {
+ const auto size = qt_config->beginReadArray(QStringLiteral("DisabledAddOns"));
- const auto size = qt_config->beginReadArray("DisabledAddOns");
for (int i = 0; i < size; ++i) {
qt_config->setArrayIndex(i);
- const auto title_id = ReadSetting("title_id", 0).toULongLong();
+ const auto title_id = ReadSetting(QStringLiteral("title_id"), 0).toULongLong();
std::vector<std::string> out;
- const auto d_size = qt_config->beginReadArray("disabled");
+ const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled"));
for (int j = 0; j < d_size; ++j) {
qt_config->setArrayIndex(j);
- out.push_back(ReadSetting("d", "").toString().toStdString());
+ out.push_back(
+ ReadSetting(QStringLiteral("d"), QStringLiteral("")).toString().toStdString());
}
qt_config->endArray();
Settings::values.disabled_addons.insert_or_assign(title_id, out);
}
+
qt_config->endArray();
+}
- qt_config->beginGroup("UI");
- UISettings::values.theme = ReadSetting("theme", UISettings::themes[0].second).toString();
- UISettings::values.enable_discord_presence =
- ReadSetting("enable_discord_presence", true).toBool();
- UISettings::values.screenshot_resolution_factor =
- static_cast<u16>(ReadSetting("screenshot_resolution_factor", 0).toUInt());
- UISettings::values.select_user_on_boot = ReadSetting("select_user_on_boot", false).toBool();
+void Config::ReadMiscellaneousValues() {
+ qt_config->beginGroup(QStringLiteral("Miscellaneous"));
+
+ Settings::values.log_filter =
+ ReadSetting(QStringLiteral("log_filter"), QStringLiteral("*:Info"))
+ .toString()
+ .toStdString();
+ Settings::values.use_dev_keys = ReadSetting(QStringLiteral("use_dev_keys"), false).toBool();
- qt_config->beginGroup("UIGameList");
- UISettings::values.show_unknown = ReadSetting("show_unknown", true).toBool();
- UISettings::values.show_add_ons = ReadSetting("show_add_ons", true).toBool();
- UISettings::values.icon_size = ReadSetting("icon_size", 64).toUInt();
- UISettings::values.row_1_text_id = ReadSetting("row_1_text_id", 3).toUInt();
- UISettings::values.row_2_text_id = ReadSetting("row_2_text_id", 2).toUInt();
qt_config->endGroup();
+}
+
+void Config::ReadPathValues() {
+ qt_config->beginGroup(QStringLiteral("Paths"));
+
+ UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString();
+ UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString();
+ UISettings::values.game_directory_path =
+ ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString();
+ UISettings::values.game_directory_deepscan =
+ ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool();
+ UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList();
- qt_config->beginGroup("UILayout");
- UISettings::values.geometry = ReadSetting("geometry").toByteArray();
- UISettings::values.state = ReadSetting("state").toByteArray();
- UISettings::values.renderwindow_geometry = ReadSetting("geometryRenderWindow").toByteArray();
- UISettings::values.gamelist_header_state = ReadSetting("gameListHeaderState").toByteArray();
- UISettings::values.microprofile_geometry =
- ReadSetting("microProfileDialogGeometry").toByteArray();
- UISettings::values.microprofile_visible =
- ReadSetting("microProfileDialogVisible", false).toBool();
qt_config->endGroup();
+}
+
+void Config::ReadRendererValues() {
+ qt_config->beginGroup(QStringLiteral("Renderer"));
+
+ Settings::values.resolution_factor =
+ ReadSetting(QStringLiteral("resolution_factor"), 1.0).toFloat();
+ Settings::values.use_frame_limit =
+ ReadSetting(QStringLiteral("use_frame_limit"), true).toBool();
+ Settings::values.frame_limit = ReadSetting(QStringLiteral("frame_limit"), 100).toInt();
+ Settings::values.use_compatibility_profile =
+ ReadSetting(QStringLiteral("use_compatibility_profile"), true).toBool();
+ Settings::values.use_disk_shader_cache =
+ ReadSetting(QStringLiteral("use_disk_shader_cache"), true).toBool();
+ Settings::values.use_accurate_gpu_emulation =
+ ReadSetting(QStringLiteral("use_accurate_gpu_emulation"), false).toBool();
+ Settings::values.use_asynchronous_gpu_emulation =
+ ReadSetting(QStringLiteral("use_asynchronous_gpu_emulation"), false).toBool();
+ Settings::values.force_30fps_mode =
+ ReadSetting(QStringLiteral("force_30fps_mode"), false).toBool();
+
+ Settings::values.bg_red = ReadSetting(QStringLiteral("bg_red"), 0.0).toFloat();
+ Settings::values.bg_green = ReadSetting(QStringLiteral("bg_green"), 0.0).toFloat();
+ Settings::values.bg_blue = ReadSetting(QStringLiteral("bg_blue"), 0.0).toFloat();
- qt_config->beginGroup("Paths");
- UISettings::values.roms_path = ReadSetting("romsPath").toString();
- UISettings::values.symbols_path = ReadSetting("symbolsPath").toString();
- UISettings::values.game_directory_path = ReadSetting("gameListRootDir", ".").toString();
- UISettings::values.game_directory_deepscan = ReadSetting("gameListDeepScan", false).toBool();
- UISettings::values.recent_files = ReadSetting("recentFiles").toStringList();
qt_config->endGroup();
+}
+
+void Config::ReadShortcutValues() {
+ qt_config->beginGroup(QStringLiteral("Shortcuts"));
- qt_config->beginGroup("Shortcuts");
for (auto [name, group, shortcut] : default_hotkeys) {
auto [keyseq, context] = shortcut;
qt_config->beginGroup(group);
@@ -539,57 +548,173 @@ void Config::ReadValues() {
UISettings::values.shortcuts.push_back(
{name,
group,
- {ReadSetting("KeySeq", keyseq).toString(), ReadSetting("Context", context).toInt()}});
+ {ReadSetting(QStringLiteral("KeySeq"), keyseq).toString(),
+ ReadSetting(QStringLiteral("Context"), context).toInt()}});
qt_config->endGroup();
qt_config->endGroup();
}
+
+ qt_config->endGroup();
+}
+
+void Config::ReadSystemValues() {
+ qt_config->beginGroup(QStringLiteral("System"));
+
+ Settings::values.use_docked_mode =
+ ReadSetting(QStringLiteral("use_docked_mode"), false).toBool();
+
+ Settings::values.current_user = std::clamp<int>(
+ ReadSetting(QStringLiteral("current_user"), 0).toInt(), 0, Service::Account::MAX_USERS - 1);
+
+ Settings::values.language_index = ReadSetting(QStringLiteral("language_index"), 1).toInt();
+
+ const auto rng_seed_enabled = ReadSetting(QStringLiteral("rng_seed_enabled"), false).toBool();
+ if (rng_seed_enabled) {
+ Settings::values.rng_seed = ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong();
+ } else {
+ Settings::values.rng_seed = std::nullopt;
+ }
+
+ const auto custom_rtc_enabled =
+ ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool();
+ if (custom_rtc_enabled) {
+ Settings::values.custom_rtc =
+ std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong());
+ } else {
+ Settings::values.custom_rtc = std::nullopt;
+ }
+
qt_config->endGroup();
+}
- UISettings::values.single_window_mode = ReadSetting("singleWindowMode", true).toBool();
- UISettings::values.fullscreen = ReadSetting("fullscreen", false).toBool();
- UISettings::values.display_titlebar = ReadSetting("displayTitleBars", true).toBool();
- UISettings::values.show_filter_bar = ReadSetting("showFilterBar", true).toBool();
- UISettings::values.show_status_bar = ReadSetting("showStatusBar", true).toBool();
- UISettings::values.confirm_before_closing = ReadSetting("confirmClose", true).toBool();
- UISettings::values.first_start = ReadSetting("firstStart", true).toBool();
- UISettings::values.callout_flags = ReadSetting("calloutFlags", 0).toUInt();
- UISettings::values.show_console = ReadSetting("showConsole", false).toBool();
- UISettings::values.profile_index = ReadSetting("profileIndex", 0).toUInt();
+void Config::ReadUIValues() {
+ qt_config->beginGroup(QStringLiteral("UI"));
+
+ UISettings::values.theme =
+ ReadSetting(QStringLiteral("theme"), UISettings::themes[0].second).toString();
+ UISettings::values.enable_discord_presence =
+ ReadSetting(QStringLiteral("enable_discord_presence"), true).toBool();
+ UISettings::values.screenshot_resolution_factor =
+ static_cast<u16>(ReadSetting(QStringLiteral("screenshot_resolution_factor"), 0).toUInt());
+ UISettings::values.select_user_on_boot =
+ ReadSetting(QStringLiteral("select_user_on_boot"), false).toBool();
+
+ ReadUIGamelistValues();
+ ReadUILayoutValues();
+ ReadPathValues();
+ ReadShortcutValues();
+
+ UISettings::values.single_window_mode =
+ ReadSetting(QStringLiteral("singleWindowMode"), true).toBool();
+ UISettings::values.fullscreen = ReadSetting(QStringLiteral("fullscreen"), false).toBool();
+ UISettings::values.display_titlebar =
+ ReadSetting(QStringLiteral("displayTitleBars"), true).toBool();
+ UISettings::values.show_filter_bar =
+ ReadSetting(QStringLiteral("showFilterBar"), true).toBool();
+ UISettings::values.show_status_bar =
+ ReadSetting(QStringLiteral("showStatusBar"), true).toBool();
+ UISettings::values.confirm_before_closing =
+ ReadSetting(QStringLiteral("confirmClose"), true).toBool();
+ UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool();
+ UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt();
+ UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool();
+ UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt();
ApplyDefaultProfileIfInputInvalid();
qt_config->endGroup();
}
+void Config::ReadUIGamelistValues() {
+ qt_config->beginGroup("UIGameList");
+
+ UISettings::values.show_unknown = ReadSetting(QStringLiteral("show_unknown"), true).toBool();
+ UISettings::values.show_add_ons = ReadSetting(QStringLiteral("show_add_ons"), true).toBool();
+ UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt();
+ UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt();
+ UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt();
+
+ qt_config->endGroup();
+}
+
+void Config::ReadUILayoutValues() {
+ qt_config->beginGroup(QStringLiteral("UILayout"));
+
+ UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray();
+ UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray();
+ UISettings::values.renderwindow_geometry =
+ ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray();
+ UISettings::values.gamelist_header_state =
+ ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray();
+ UISettings::values.microprofile_geometry =
+ ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray();
+ UISettings::values.microprofile_visible =
+ ReadSetting(QStringLiteral("microProfileDialogVisible"), false).toBool();
+
+ qt_config->endGroup();
+}
+
+void Config::ReadWebServiceValues() {
+ qt_config->beginGroup(QStringLiteral("WebService"));
+
+ Settings::values.enable_telemetry =
+ ReadSetting(QStringLiteral("enable_telemetry"), true).toBool();
+ Settings::values.web_api_url =
+ ReadSetting(QStringLiteral("web_api_url"), QStringLiteral("https://api.yuzu-emu.org"))
+ .toString()
+ .toStdString();
+ Settings::values.yuzu_username =
+ ReadSetting(QStringLiteral("yuzu_username")).toString().toStdString();
+ Settings::values.yuzu_token =
+ ReadSetting(QStringLiteral("yuzu_token")).toString().toStdString();
+
+ qt_config->endGroup();
+}
+
+void Config::ReadValues() {
+ ReadControlValues();
+ ReadCoreValues();
+ ReadRendererValues();
+ ReadAudioValues();
+ ReadDataStorageValues();
+ ReadSystemValues();
+ ReadMiscellaneousValues();
+ ReadDebugValues();
+ ReadWebServiceValues();
+ ReadDisabledAddOnValues();
+ ReadUIValues();
+}
+
void Config::SavePlayerValues() {
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
const auto& player = Settings::values.players[p];
- WriteSetting(QString("player_%1_connected").arg(p), player.connected, false);
- WriteSetting(QString("player_%1_type").arg(p), static_cast<u8>(player.type),
+ WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false);
+ WriteSetting(QStringLiteral("player_%1_type").arg(p), static_cast<u8>(player.type),
static_cast<u8>(Settings::ControllerType::DualJoycon));
- WriteSetting(QString("player_%1_body_color_left").arg(p), player.body_color_left,
+ WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left,
Settings::JOYCON_BODY_NEON_BLUE);
- WriteSetting(QString("player_%1_body_color_right").arg(p), player.body_color_right,
+ WriteSetting(QStringLiteral("player_%1_body_color_right").arg(p), player.body_color_right,
Settings::JOYCON_BODY_NEON_RED);
- WriteSetting(QString("player_%1_button_color_left").arg(p), player.button_color_left,
+ WriteSetting(QStringLiteral("player_%1_button_color_left").arg(p), player.button_color_left,
Settings::JOYCON_BUTTONS_NEON_BLUE);
- WriteSetting(QString("player_%1_button_color_right").arg(p), player.button_color_right,
- Settings::JOYCON_BUTTONS_NEON_RED);
+ WriteSetting(QStringLiteral("player_%1_button_color_right").arg(p),
+ player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED);
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- WriteSetting(QString("player_%1_").arg(p) +
+ const std::string default_param =
+ InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ WriteSetting(QStringLiteral("player_%1_").arg(p) +
QString::fromStdString(Settings::NativeButton::mapping[i]),
QString::fromStdString(player.buttons[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
- WriteSetting(QString("player_%1_").arg(p) +
+ WriteSetting(QStringLiteral("player_%1_").arg(p) +
QString::fromStdString(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(player.analogs[i]),
QString::fromStdString(default_param));
@@ -600,17 +725,17 @@ void Config::SavePlayerValues() {
void Config::SaveDebugValues() {
WriteSetting("debug_pad_enabled", Settings::values.debug_pad_enabled, false);
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- WriteSetting(QString("debug_pad_") +
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ WriteSetting(QStringLiteral("debug_pad_") +
QString::fromStdString(Settings::NativeButton::mapping[i]),
QString::fromStdString(Settings::values.debug_pad_buttons[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
- WriteSetting(QString("debug_pad_") +
+ WriteSetting(QStringLiteral("debug_pad_") +
QString::fromStdString(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(Settings::values.debug_pad_analogs[i]),
QString::fromStdString(default_param));
@@ -618,11 +743,12 @@ void Config::SaveDebugValues() {
}
void Config::SaveMouseValues() {
- WriteSetting("mouse_enabled", Settings::values.mouse_enabled, false);
+ WriteSetting(QStringLiteral("mouse_enabled"), Settings::values.mouse_enabled, false);
for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
- WriteSetting(QString("mouse_") +
+ const std::string default_param =
+ InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
+ WriteSetting(QStringLiteral("mouse_") +
QString::fromStdString(Settings::NativeMouseButton::mapping[i]),
QString::fromStdString(Settings::values.mouse_buttons[i]),
QString::fromStdString(default_param));
@@ -630,178 +756,276 @@ void Config::SaveMouseValues() {
}
void Config::SaveTouchscreenValues() {
- WriteSetting("touchscreen_enabled", Settings::values.touchscreen.enabled, true);
- WriteSetting("touchscreen_device", QString::fromStdString(Settings::values.touchscreen.device),
- "engine:emu_window");
+ const auto& touchscreen = Settings::values.touchscreen;
+
+ WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true);
+ WriteSetting(QStringLiteral("touchscreen_device"), QString::fromStdString(touchscreen.device),
+ QStringLiteral("engine:emu_window"));
- WriteSetting("touchscreen_finger", Settings::values.touchscreen.finger, 0);
- WriteSetting("touchscreen_angle", Settings::values.touchscreen.rotation_angle, 0);
- WriteSetting("touchscreen_diameter_x", Settings::values.touchscreen.diameter_x, 15);
- WriteSetting("touchscreen_diameter_y", Settings::values.touchscreen.diameter_y, 15);
+ WriteSetting(QStringLiteral("touchscreen_finger"), touchscreen.finger, 0);
+ WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0);
+ WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15);
+ WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15);
}
void Config::SaveValues() {
- qt_config->beginGroup("Controls");
+ SaveControlValues();
+ SaveCoreValues();
+ SaveRendererValues();
+ SaveAudioValues();
+ SaveDataStorageValues();
+ SaveSystemValues();
+ SaveMiscellaneousValues();
+ SaveDebuggingValues();
+ SaveWebServiceValues();
+ SaveDisabledAddOnValues();
+ SaveUIValues();
+}
+
+void Config::SaveAudioValues() {
+ qt_config->beginGroup(QStringLiteral("Audio"));
+
+ WriteSetting(QStringLiteral("output_engine"), QString::fromStdString(Settings::values.sink_id),
+ QStringLiteral("auto"));
+ WriteSetting(QStringLiteral("enable_audio_stretching"),
+ Settings::values.enable_audio_stretching, true);
+ WriteSetting(QStringLiteral("output_device"),
+ QString::fromStdString(Settings::values.audio_device_id), QStringLiteral("auto"));
+ WriteSetting(QStringLiteral("volume"), Settings::values.volume, 1.0f);
+
+ qt_config->endGroup();
+}
+
+void Config::SaveControlValues() {
+ qt_config->beginGroup(QStringLiteral("Controls"));
SavePlayerValues();
SaveDebugValues();
SaveMouseValues();
SaveTouchscreenValues();
- WriteSetting("motion_device", QString::fromStdString(Settings::values.motion_device),
- "engine:motion_emu,update_period:100,sensitivity:0.01");
- WriteSetting("keyboard_enabled", Settings::values.keyboard_enabled, false);
+ WriteSetting(QStringLiteral("motion_device"),
+ QString::fromStdString(Settings::values.motion_device),
+ QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"));
+ WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false);
qt_config->endGroup();
+}
- qt_config->beginGroup("Core");
- WriteSetting("use_cpu_jit", Settings::values.use_cpu_jit, true);
- WriteSetting("use_multi_core", Settings::values.use_multi_core, false);
- qt_config->endGroup();
+void Config::SaveCoreValues() {
+ qt_config->beginGroup(QStringLiteral("Core"));
- qt_config->beginGroup("Renderer");
- WriteSetting("resolution_factor", (double)Settings::values.resolution_factor, 1.0);
- WriteSetting("use_frame_limit", Settings::values.use_frame_limit, true);
- WriteSetting("frame_limit", Settings::values.frame_limit, 100);
- WriteSetting("use_compatibility_profile", Settings::values.use_compatibility_profile, true);
- WriteSetting("use_disk_shader_cache", Settings::values.use_disk_shader_cache, true);
- WriteSetting("use_accurate_gpu_emulation", Settings::values.use_accurate_gpu_emulation, false);
- WriteSetting("use_asynchronous_gpu_emulation", Settings::values.use_asynchronous_gpu_emulation,
- false);
- WriteSetting("force_30fps_mode", Settings::values.force_30fps_mode, false);
+ WriteSetting(QStringLiteral("use_cpu_jit"), Settings::values.use_cpu_jit, true);
+ WriteSetting(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false);
- // Cast to double because Qt's written float values are not human-readable
- WriteSetting("bg_red", (double)Settings::values.bg_red, 0.0);
- WriteSetting("bg_green", (double)Settings::values.bg_green, 0.0);
- WriteSetting("bg_blue", (double)Settings::values.bg_blue, 0.0);
qt_config->endGroup();
+}
- qt_config->beginGroup("Audio");
- WriteSetting("output_engine", QString::fromStdString(Settings::values.sink_id), "auto");
- WriteSetting("enable_audio_stretching", Settings::values.enable_audio_stretching, true);
- WriteSetting("output_device", QString::fromStdString(Settings::values.audio_device_id), "auto");
- WriteSetting("volume", Settings::values.volume, 1.0f);
- qt_config->endGroup();
+void Config::SaveDataStorageValues() {
+ qt_config->beginGroup(QStringLiteral("Data Storage"));
- qt_config->beginGroup("Data Storage");
- WriteSetting("use_virtual_sd", Settings::values.use_virtual_sd, true);
- WriteSetting("nand_directory",
+ WriteSetting(QStringLiteral("use_virtual_sd"), Settings::values.use_virtual_sd, true);
+ WriteSetting(QStringLiteral("nand_directory"),
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)),
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)));
- WriteSetting("sdmc_directory",
+ WriteSetting(QStringLiteral("sdmc_directory"),
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)),
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)));
- qt_config->endGroup();
-
- qt_config->beginGroup("System");
- WriteSetting("use_docked_mode", Settings::values.use_docked_mode, false);
- WriteSetting("current_user", Settings::values.current_user, 0);
- WriteSetting("language_index", Settings::values.language_index, 1);
-
- WriteSetting("rng_seed_enabled", Settings::values.rng_seed.has_value(), false);
- WriteSetting("rng_seed", Settings::values.rng_seed.value_or(0), 0);
-
- WriteSetting("custom_rtc_enabled", Settings::values.custom_rtc.has_value(), false);
- WriteSetting("custom_rtc",
- QVariant::fromValue<long long>(
- Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()),
- 0);
qt_config->endGroup();
+}
- qt_config->beginGroup("Miscellaneous");
- WriteSetting("log_filter", QString::fromStdString(Settings::values.log_filter), "*:Info");
- WriteSetting("use_dev_keys", Settings::values.use_dev_keys, false);
- qt_config->endGroup();
+void Config::SaveDebuggingValues() {
+ qt_config->beginGroup(QStringLiteral("Debugging"));
- qt_config->beginGroup("Debugging");
- WriteSetting("use_gdbstub", Settings::values.use_gdbstub, false);
- WriteSetting("gdbstub_port", Settings::values.gdbstub_port, 24689);
- WriteSetting("program_args", QString::fromStdString(Settings::values.program_args), "");
- WriteSetting("dump_exefs", Settings::values.dump_exefs, false);
- WriteSetting("dump_nso", Settings::values.dump_nso, false);
- qt_config->endGroup();
+ WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false);
+ WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689);
+ WriteSetting(QStringLiteral("program_args"),
+ QString::fromStdString(Settings::values.program_args), QStringLiteral(""));
+ WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false);
+ WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false);
- qt_config->beginGroup("WebService");
- WriteSetting("enable_telemetry", Settings::values.enable_telemetry, true);
- WriteSetting("web_api_url", QString::fromStdString(Settings::values.web_api_url),
- "https://api.yuzu-emu.org");
- WriteSetting("yuzu_username", QString::fromStdString(Settings::values.yuzu_username));
- WriteSetting("yuzu_token", QString::fromStdString(Settings::values.yuzu_token));
qt_config->endGroup();
+}
+
+void Config::SaveDisabledAddOnValues() {
+ qt_config->beginWriteArray(QStringLiteral("DisabledAddOns"));
- qt_config->beginWriteArray("DisabledAddOns");
int i = 0;
for (const auto& elem : Settings::values.disabled_addons) {
qt_config->setArrayIndex(i);
- WriteSetting("title_id", QVariant::fromValue<u64>(elem.first), 0);
- qt_config->beginWriteArray("disabled");
+ WriteSetting(QStringLiteral("title_id"), QVariant::fromValue<u64>(elem.first), 0);
+ qt_config->beginWriteArray(QStringLiteral("disabled"));
for (std::size_t j = 0; j < elem.second.size(); ++j) {
qt_config->setArrayIndex(static_cast<int>(j));
- WriteSetting("d", QString::fromStdString(elem.second[j]), "");
+ WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]),
+ QStringLiteral(""));
}
qt_config->endArray();
++i;
}
+
qt_config->endArray();
+}
- qt_config->beginGroup("UI");
- WriteSetting("theme", UISettings::values.theme, UISettings::themes[0].second);
- WriteSetting("enable_discord_presence", UISettings::values.enable_discord_presence, true);
- WriteSetting("screenshot_resolution_factor", UISettings::values.screenshot_resolution_factor,
- 0);
- WriteSetting("select_user_on_boot", UISettings::values.select_user_on_boot, false);
+void Config::SaveMiscellaneousValues() {
+ qt_config->beginGroup(QStringLiteral("Miscellaneous"));
+
+ WriteSetting(QStringLiteral("log_filter"), QString::fromStdString(Settings::values.log_filter),
+ QStringLiteral("*:Info"));
+ WriteSetting(QStringLiteral("use_dev_keys"), Settings::values.use_dev_keys, false);
- qt_config->beginGroup("UIGameList");
- WriteSetting("show_unknown", UISettings::values.show_unknown, true);
- WriteSetting("show_add_ons", UISettings::values.show_add_ons, true);
- WriteSetting("icon_size", UISettings::values.icon_size, 64);
- WriteSetting("row_1_text_id", UISettings::values.row_1_text_id, 3);
- WriteSetting("row_2_text_id", UISettings::values.row_2_text_id, 2);
qt_config->endGroup();
+}
+
+void Config::SavePathValues() {
+ qt_config->beginGroup(QStringLiteral("Paths"));
+
+ WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path);
+ WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path);
+ WriteSetting(QStringLiteral("screenshotPath"), UISettings::values.screenshot_path);
+ WriteSetting(QStringLiteral("gameListRootDir"), UISettings::values.game_directory_path,
+ QStringLiteral("."));
+ WriteSetting(QStringLiteral("gameListDeepScan"), UISettings::values.game_directory_deepscan,
+ false);
+ WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
- qt_config->beginGroup("UILayout");
- WriteSetting("geometry", UISettings::values.geometry);
- WriteSetting("state", UISettings::values.state);
- WriteSetting("geometryRenderWindow", UISettings::values.renderwindow_geometry);
- WriteSetting("gameListHeaderState", UISettings::values.gamelist_header_state);
- WriteSetting("microProfileDialogGeometry", UISettings::values.microprofile_geometry);
- WriteSetting("microProfileDialogVisible", UISettings::values.microprofile_visible, false);
qt_config->endGroup();
+}
+
+void Config::SaveRendererValues() {
+ qt_config->beginGroup(QStringLiteral("Renderer"));
+
+ WriteSetting(QStringLiteral("resolution_factor"),
+ static_cast<double>(Settings::values.resolution_factor), 1.0);
+ WriteSetting(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true);
+ WriteSetting(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100);
+ WriteSetting(QStringLiteral("use_compatibility_profile"),
+ Settings::values.use_compatibility_profile, true);
+ WriteSetting(QStringLiteral("use_disk_shader_cache"), Settings::values.use_disk_shader_cache,
+ true);
+ WriteSetting(QStringLiteral("use_accurate_gpu_emulation"),
+ Settings::values.use_accurate_gpu_emulation, false);
+ WriteSetting(QStringLiteral("use_asynchronous_gpu_emulation"),
+ Settings::values.use_asynchronous_gpu_emulation, false);
+ WriteSetting(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, false);
+
+ // Cast to double because Qt's written float values are not human-readable
+ WriteSetting(QStringLiteral("bg_red"), static_cast<double>(Settings::values.bg_red), 0.0);
+ WriteSetting(QStringLiteral("bg_green"), static_cast<double>(Settings::values.bg_green), 0.0);
+ WriteSetting(QStringLiteral("bg_blue"), static_cast<double>(Settings::values.bg_blue), 0.0);
- qt_config->beginGroup("Paths");
- WriteSetting("romsPath", UISettings::values.roms_path);
- WriteSetting("symbolsPath", UISettings::values.symbols_path);
- WriteSetting("screenshotPath", UISettings::values.screenshot_path);
- WriteSetting("gameListRootDir", UISettings::values.game_directory_path, ".");
- WriteSetting("gameListDeepScan", UISettings::values.game_directory_deepscan, false);
- WriteSetting("recentFiles", UISettings::values.recent_files);
qt_config->endGroup();
+}
+
+void Config::SaveShortcutValues() {
+ qt_config->beginGroup(QStringLiteral("Shortcuts"));
- qt_config->beginGroup("Shortcuts");
// Lengths of UISettings::values.shortcuts & default_hotkeys are same.
// However, their ordering must also be the same.
for (std::size_t i = 0; i < default_hotkeys.size(); i++) {
- auto [name, group, shortcut] = UISettings::values.shortcuts[i];
+ const auto [name, group, shortcut] = UISettings::values.shortcuts[i];
+ const auto& default_hotkey = default_hotkeys[i].shortcut;
+
qt_config->beginGroup(group);
qt_config->beginGroup(name);
- WriteSetting("KeySeq", shortcut.first, default_hotkeys[i].shortcut.first);
- WriteSetting("Context", shortcut.second, default_hotkeys[i].shortcut.second);
+ WriteSetting(QStringLiteral("KeySeq"), shortcut.first, default_hotkey.first);
+ WriteSetting(QStringLiteral("Context"), shortcut.second, default_hotkey.second);
qt_config->endGroup();
qt_config->endGroup();
}
+
+ qt_config->endGroup();
+}
+
+void Config::SaveSystemValues() {
+ qt_config->beginGroup(QStringLiteral("System"));
+
+ WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
+ WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0);
+ WriteSetting(QStringLiteral("language_index"), Settings::values.language_index, 1);
+
+ WriteSetting(QStringLiteral("rng_seed_enabled"), Settings::values.rng_seed.has_value(), false);
+ WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.value_or(0), 0);
+
+ WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(),
+ false);
+ WriteSetting(QStringLiteral("custom_rtc"),
+ QVariant::fromValue<long long>(
+ Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()),
+ 0);
+
+ qt_config->endGroup();
+}
+
+void Config::SaveUIValues() {
+ qt_config->beginGroup(QStringLiteral("UI"));
+
+ WriteSetting(QStringLiteral("theme"), UISettings::values.theme, UISettings::themes[0].second);
+ WriteSetting(QStringLiteral("enable_discord_presence"),
+ UISettings::values.enable_discord_presence, true);
+ WriteSetting(QStringLiteral("screenshot_resolution_factor"),
+ UISettings::values.screenshot_resolution_factor, 0);
+ WriteSetting(QStringLiteral("select_user_on_boot"), UISettings::values.select_user_on_boot,
+ false);
+
+ SaveUIGamelistValues();
+ SaveUILayoutValues();
+ SavePathValues();
+ SaveShortcutValues();
+
+ WriteSetting(QStringLiteral("singleWindowMode"), UISettings::values.single_window_mode, true);
+ WriteSetting(QStringLiteral("fullscreen"), UISettings::values.fullscreen, false);
+ WriteSetting(QStringLiteral("displayTitleBars"), UISettings::values.display_titlebar, true);
+ WriteSetting(QStringLiteral("showFilterBar"), UISettings::values.show_filter_bar, true);
+ WriteSetting(QStringLiteral("showStatusBar"), UISettings::values.show_status_bar, true);
+ WriteSetting(QStringLiteral("confirmClose"), UISettings::values.confirm_before_closing, true);
+ WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true);
+ WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0);
+ WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false);
+ WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0);
+
+ qt_config->endGroup();
+}
+
+void Config::SaveUIGamelistValues() {
+ qt_config->beginGroup(QStringLiteral("UIGameList"));
+
+ WriteSetting(QStringLiteral("show_unknown"), UISettings::values.show_unknown, true);
+ WriteSetting(QStringLiteral("show_add_ons"), UISettings::values.show_add_ons, true);
+ WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64);
+ WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3);
+ WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2);
+
+ qt_config->endGroup();
+}
+
+void Config::SaveUILayoutValues() {
+ qt_config->beginGroup(QStringLiteral("UILayout"));
+
+ WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry);
+ WriteSetting(QStringLiteral("state"), UISettings::values.state);
+ WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry);
+ WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state);
+ WriteSetting(QStringLiteral("microProfileDialogGeometry"),
+ UISettings::values.microprofile_geometry);
+ WriteSetting(QStringLiteral("microProfileDialogVisible"),
+ UISettings::values.microprofile_visible, false);
+
qt_config->endGroup();
+}
+
+void Config::SaveWebServiceValues() {
+ qt_config->beginGroup(QStringLiteral("WebService"));
+
+ WriteSetting(QStringLiteral("enable_telemetry"), Settings::values.enable_telemetry, true);
+ WriteSetting(QStringLiteral("web_api_url"),
+ QString::fromStdString(Settings::values.web_api_url),
+ QStringLiteral("https://api.yuzu-emu.org"));
+ WriteSetting(QStringLiteral("yuzu_username"),
+ QString::fromStdString(Settings::values.yuzu_username));
+ WriteSetting(QStringLiteral("yuzu_token"), QString::fromStdString(Settings::values.yuzu_token));
- WriteSetting("singleWindowMode", UISettings::values.single_window_mode, true);
- WriteSetting("fullscreen", UISettings::values.fullscreen, false);
- WriteSetting("displayTitleBars", UISettings::values.display_titlebar, true);
- WriteSetting("showFilterBar", UISettings::values.show_filter_bar, true);
- WriteSetting("showStatusBar", UISettings::values.show_status_bar, true);
- WriteSetting("confirmClose", UISettings::values.confirm_before_closing, true);
- WriteSetting("firstStart", UISettings::values.first_start, true);
- WriteSetting("calloutFlags", UISettings::values.callout_flags, 0);
- WriteSetting("showConsole", UISettings::values.show_console, false);
- WriteSetting("profileIndex", UISettings::values.profile_index, 0);
qt_config->endGroup();
}
@@ -811,7 +1035,7 @@ QVariant Config::ReadSetting(const QString& name) const {
QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) const {
QVariant result;
- if (qt_config->value(name + "/default", false).toBool()) {
+ if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) {
result = default_value;
} else {
result = qt_config->value(name, default_value);
@@ -825,7 +1049,7 @@ void Config::WriteSetting(const QString& name, const QVariant& value) {
void Config::WriteSetting(const QString& name, const QVariant& value,
const QVariant& default_value) {
- qt_config->setValue(name + "/default", value == default_value);
+ qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
qt_config->setValue(name, value);
}
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 221d2364c..b62a480ee 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -37,12 +37,46 @@ private:
void ReadTouchscreenValues();
void ApplyDefaultProfileIfInputInvalid();
+ // Read functions bases off the respective config section names.
+ void ReadAudioValues();
+ void ReadControlValues();
+ void ReadCoreValues();
+ void ReadDataStorageValues();
+ void ReadDebuggingValues();
+ void ReadDisabledAddOnValues();
+ void ReadMiscellaneousValues();
+ void ReadPathValues();
+ void ReadRendererValues();
+ void ReadShortcutValues();
+ void ReadSystemValues();
+ void ReadUIValues();
+ void ReadUIGamelistValues();
+ void ReadUILayoutValues();
+ void ReadWebServiceValues();
+
void SaveValues();
void SavePlayerValues();
void SaveDebugValues();
void SaveMouseValues();
void SaveTouchscreenValues();
+ // Save functions based off the respective config section names.
+ void SaveAudioValues();
+ void SaveControlValues();
+ void SaveCoreValues();
+ void SaveDataStorageValues();
+ void SaveDebuggingValues();
+ void SaveDisabledAddOnValues();
+ void SaveMiscellaneousValues();
+ void SavePathValues();
+ void SaveRendererValues();
+ void SaveShortcutValues();
+ void SaveSystemValues();
+ void SaveUIValues();
+ void SaveUIGamelistValues();
+ void SaveUILayoutValues();
+ void SaveWebServiceValues();
+
QVariant ReadSetting(const QString& name) const;
QVariant ReadSetting(const QString& name, const QVariant& default_value) const;
void WriteSetting(const QString& name, const QVariant& value);
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 5d9ccc6e8..b0f9b814d 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -16,21 +16,21 @@ ConfigureAudio::ConfigureAudio(QWidget* parent)
ui->setupUi(this);
ui->output_sink_combo_box->clear();
- ui->output_sink_combo_box->addItem("auto");
+ ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
for (const char* id : AudioCore::GetSinkIDs()) {
- ui->output_sink_combo_box->addItem(id);
+ ui->output_sink_combo_box->addItem(QString::fromUtf8(id));
}
connect(ui->volume_slider, &QSlider::valueChanged, this,
&ConfigureAudio::setVolumeIndicatorText);
this->setConfiguration();
- connect(ui->output_sink_combo_box,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+ connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureAudio::updateAudioDevices);
- ui->output_sink_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn());
- ui->audio_device_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn());
+ const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
+ ui->output_sink_combo_box->setEnabled(!is_powered_on);
+ ui->audio_device_combo_box->setEnabled(!is_powered_on);
}
ConfigureAudio::~ConfigureAudio() = default;
@@ -94,7 +94,7 @@ void ConfigureAudio::applyConfiguration() {
void ConfigureAudio::updateAudioDevices(int sink_index) {
ui->audio_device_combo_box->clear();
- ui->audio_device_combo_box->addItem(AudioCore::auto_device_name);
+ ui->audio_device_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
const std::string sink_id = ui->output_sink_combo_box->itemText(sink_index).toStdString();
for (const auto& device : AudioCore::GetDeviceListForSink(sink_id)) {
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
index ae8cac243..6f0d75605 100644
--- a/src/yuzu/configuration/configure_gamelist.cpp
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -100,13 +100,15 @@ void ConfigureGameList::RetranslateUI() {
void ConfigureGameList::InitializeIconSizeComboBox() {
for (const auto& size : default_icon_sizes) {
- ui->icon_size_combobox->addItem(size.second, size.first);
+ ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first);
}
}
void ConfigureGameList::InitializeRowComboBoxes() {
for (std::size_t i = 0; i < row_text_names.size(); ++i) {
- ui->row_1_text_combobox->addItem(row_text_names[i], QVariant::fromValue(i));
- ui->row_2_text_combobox->addItem(row_text_names[i], QVariant::fromValue(i));
+ const QString row_text_name = QString::fromUtf8(row_text_names[i]);
+
+ ui->row_1_text_combobox->addItem(row_text_name, QVariant::fromValue(i));
+ ui->row_2_text_combobox->addItem(row_text_name, QVariant::fromValue(i));
}
}
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index e48f4f5a3..dd25dc6e1 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -14,7 +14,8 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
ui->setupUi(this);
for (const auto& theme : UISettings::themes) {
- ui->theme_combobox->addItem(theme.first, theme.second);
+ ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
+ QString::fromUtf8(theme.second));
}
this->setConfiguration();
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index f39d57998..87e459714 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -75,8 +75,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
};
for (auto* controller_box : players_controller) {
- controller_box->addItems({"None", "Pro Controller", "Dual Joycons", "Single Right Joycon",
- "Single Left Joycon"});
+ controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"),
+ tr("Single Right Joycon"), tr("Single Left Joycon")});
}
this->loadConfiguration();
@@ -85,9 +85,10 @@ ConfigureInput::ConfigureInput(QWidget* parent)
connect(ui->restore_defaults_button, &QPushButton::pressed, this,
&ConfigureInput::restoreDefaults);
- for (auto* enabled : players_controller)
+ for (auto* enabled : players_controller) {
connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ConfigureInput::updateUIEnabled);
+ }
connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled);
connect(ui->handheld_connected, &QCheckBox::stateChanged, this,
&ConfigureInput::updateUIEnabled);
@@ -147,10 +148,12 @@ void ConfigureInput::updateUIEnabled() {
bool hit_disabled = false;
for (auto* player : players_controller) {
player->setDisabled(hit_disabled);
- if (hit_disabled)
+ if (hit_disabled) {
player->setCurrentIndex(0);
- if (!hit_disabled && player->currentIndex() == 0)
+ }
+ if (!hit_disabled && player->currentIndex() == 0) {
hit_disabled = true;
+ }
}
for (std::size_t i = 0; i < players_controller.size(); ++i) {
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index c5a245ebe..95b0a656a 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -45,7 +45,7 @@ static QString GetKeyName(int key_code) {
case Qt::Key_Alt:
return QObject::tr("Alt");
case Qt::Key_Meta:
- return "";
+ return {};
default:
return QKeySequence(key_code).toString();
}
@@ -65,46 +65,70 @@ static void SetAnalogButton(const Common::ParamPackage& input_param,
static QString ButtonToText(const Common::ParamPackage& param) {
if (!param.Has("engine")) {
return QObject::tr("[not set]");
- } else if (param.Get("engine", "") == "keyboard") {
+ }
+
+ if (param.Get("engine", "") == "keyboard") {
return GetKeyName(param.Get("code", 0));
- } else if (param.Get("engine", "") == "sdl") {
+ }
+
+ if (param.Get("engine", "") == "sdl") {
if (param.Has("hat")) {
- return QString(QObject::tr("Hat %1 %2"))
- .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str());
+ const QString hat_str = QString::fromStdString(param.Get("hat", ""));
+ const QString direction_str = QString::fromStdString(param.Get("direction", ""));
+
+ return QObject::tr("Hat %1 %2").arg(hat_str, direction_str);
}
+
if (param.Has("axis")) {
- return QString(QObject::tr("Axis %1%2"))
- .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str());
+ const QString axis_str = QString::fromStdString(param.Get("axis", ""));
+ const QString direction_str = QString::fromStdString(param.Get("direction", ""));
+
+ return QObject::tr("Axis %1%2").arg(axis_str, direction_str);
}
+
if (param.Has("button")) {
- return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str());
+ const QString button_str = QString::fromStdString(param.Get("button", ""));
+
+ return QObject::tr("Button %1").arg(button_str);
}
- return QString();
- } else {
- return QObject::tr("[unknown]");
+
+ return {};
}
-};
+
+ return QObject::tr("[unknown]");
+}
static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) {
if (!param.Has("engine")) {
return QObject::tr("[not set]");
- } else if (param.Get("engine", "") == "analog_from_button") {
+ }
+
+ if (param.Get("engine", "") == "analog_from_button") {
return ButtonToText(Common::ParamPackage{param.Get(dir, "")});
- } else if (param.Get("engine", "") == "sdl") {
+ }
+
+ if (param.Get("engine", "") == "sdl") {
if (dir == "modifier") {
- return QString(QObject::tr("[unused]"));
+ return QObject::tr("[unused]");
}
if (dir == "left" || dir == "right") {
- return QString(QObject::tr("Axis %1")).arg(param.Get("axis_x", "").c_str());
- } else if (dir == "up" || dir == "down") {
- return QString(QObject::tr("Axis %1")).arg(param.Get("axis_y", "").c_str());
+ const QString axis_x_str = QString::fromStdString(param.Get("axis_x", ""));
+
+ return QObject::tr("Axis %1").arg(axis_x_str);
}
- return QString();
- } else {
- return QObject::tr("[unknown]");
+
+ if (dir == "up" || dir == "down") {
+ const QString axis_y_str = QString::fromStdString(param.Get("axis_y", ""));
+
+ return QObject::tr("Axis %1").arg(axis_y_str);
+ }
+
+ return {};
}
-};
+
+ return QObject::tr("[unknown]");
+}
ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, bool debug)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index),
@@ -214,38 +238,42 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog};
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) {
- if (!button_map[button_id])
+ auto* const button = button_map[button_id];
+ if (button == nullptr) {
continue;
- button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(button_map[button_id], &QPushButton::released, [=]() {
+ }
+
+ button->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(button, &QPushButton::released, [=] {
handleClick(
button_map[button_id],
[=](const Common::ParamPackage& params) { buttons_param[button_id] = params; },
InputCommon::Polling::DeviceType::Button);
});
- connect(button_map[button_id], &QPushButton::customContextMenuRequested,
- [=](const QPoint& menu_location) {
- QMenu context_menu;
- context_menu.addAction(tr("Clear"), [&] {
- buttons_param[button_id].Clear();
- button_map[button_id]->setText(tr("[not set]"));
- });
- context_menu.addAction(tr("Restore Default"), [&] {
- buttons_param[button_id] = Common::ParamPackage{
- InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
- button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
- });
- context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
- });
+ connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
+ QMenu context_menu;
+ context_menu.addAction(tr("Clear"), [&] {
+ buttons_param[button_id].Clear();
+ button_map[button_id]->setText(tr("[not set]"));
+ });
+ context_menu.addAction(tr("Restore Default"), [&] {
+ buttons_param[button_id] = Common::ParamPackage{
+ InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
+ button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
+ });
+ context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
+ });
}
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
- if (!analog_map_buttons[analog_id][sub_button_id])
+ auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
+ if (analog_button == nullptr) {
continue;
- analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy(
- Qt::CustomContextMenu);
- connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() {
+ }
+
+ analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(analog_button, &QPushButton::released, [=]() {
handleClick(analog_map_buttons[analog_id][sub_button_id],
[=](const Common::ParamPackage& params) {
SetAnalogButton(params, analogs_param[analog_id],
@@ -253,8 +281,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
},
InputCommon::Polling::DeviceType::Button);
});
- connect(analog_map_buttons[analog_id][sub_button_id],
- &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
+ connect(analog_button, &QPushButton::customContextMenuRequested,
+ [=](const QPoint& menu_location) {
QMenu context_menu;
context_menu.addAction(tr("Clear"), [&] {
analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
@@ -272,7 +300,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
menu_location));
});
}
- connect(analog_map_stick[analog_id], &QPushButton::released, [=]() {
+ connect(analog_map_stick[analog_id], &QPushButton::released, [=] {
QMessageBox::information(this, tr("Information"),
tr("After pressing OK, first move your joystick horizontally, "
"and then vertically."));
@@ -351,7 +379,7 @@ void ConfigureInputPlayer::OnControllerButtonClick(int i) {
return;
controller_colors[i] = new_bg_color;
controller_color_buttons[i]->setStyleSheet(
- QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name()));
+ QStringLiteral("QPushButton { background-color: %1 }").arg(controller_colors[i].name()));
}
void ConfigureInputPlayer::loadConfiguration() {
@@ -388,7 +416,8 @@ void ConfigureInputPlayer::loadConfiguration() {
for (std::size_t i = 0; i < colors.size(); ++i) {
controller_color_buttons[i]->setStyleSheet(
- QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name()));
+ QStringLiteral("QPushButton { background-color: %1 }")
+ .arg(controller_colors[i].name()));
}
}
@@ -410,14 +439,22 @@ void ConfigureInputPlayer::restoreDefaults() {
void ConfigureInputPlayer::ClearAll() {
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) {
- if (button_map[button_id] && button_map[button_id]->isEnabled())
- buttons_param[button_id].Clear();
+ const auto* const button = button_map[button_id];
+ if (button == nullptr || !button->isEnabled()) {
+ continue;
+ }
+
+ buttons_param[button_id].Clear();
}
+
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
- if (analog_map_buttons[analog_id][sub_button_id] &&
- analog_map_buttons[analog_id][sub_button_id]->isEnabled())
- analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
+ const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
+ if (analog_button == nullptr || !analog_button->isEnabled()) {
+ continue;
+ }
+
+ analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
}
}
@@ -431,10 +468,14 @@ void ConfigureInputPlayer::updateButtonLabels() {
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
- if (analog_map_buttons[analog_id][sub_button_id]) {
- analog_map_buttons[analog_id][sub_button_id]->setText(
- AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
+ auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
+
+ if (analog_button == nullptr) {
+ continue;
}
+
+ analog_button->setText(
+ AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
}
analog_map_stick[analog_id]->setText(tr("Set Analog Stick"));
}
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index ef857035e..a14bb1475 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -25,7 +25,7 @@ static QString GetKeyName(int key_code) {
case Qt::Key_Alt:
return QObject::tr("Alt");
case Qt::Key_Meta:
- return "";
+ return {};
default:
return QKeySequence(key_code).toString();
}
@@ -34,24 +34,36 @@ static QString GetKeyName(int key_code) {
static QString ButtonToText(const Common::ParamPackage& param) {
if (!param.Has("engine")) {
return QObject::tr("[not set]");
- } else if (param.Get("engine", "") == "keyboard") {
+ }
+
+ if (param.Get("engine", "") == "keyboard") {
return GetKeyName(param.Get("code", 0));
- } else if (param.Get("engine", "") == "sdl") {
+ }
+
+ if (param.Get("engine", "") == "sdl") {
if (param.Has("hat")) {
- return QString(QObject::tr("Hat %1 %2"))
- .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str());
+ const QString hat_str = QString::fromStdString(param.Get("hat", ""));
+ const QString direction_str = QString::fromStdString(param.Get("direction", ""));
+
+ return QObject::tr("Hat %1 %2").arg(hat_str, direction_str);
}
+
if (param.Has("axis")) {
- return QString(QObject::tr("Axis %1%2"))
- .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str());
+ const QString axis_str = QString::fromStdString(param.Get("axis", ""));
+ const QString direction_str = QString::fromStdString(param.Get("direction", ""));
+
+ return QObject::tr("Axis %1%2").arg(axis_str, direction_str);
}
+
if (param.Has("button")) {
- return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str());
+ const QString button_str = QString::fromStdString(param.Get("button", ""));
+
+ return QObject::tr("Button %1").arg(button_str);
}
- return QString();
- } else {
- return QObject::tr("[unknown]");
+ return {};
}
+
+ return QObject::tr("[unknown]");
}
ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent)
@@ -65,30 +77,31 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent)
};
for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
- if (!button_map[button_id])
+ auto* const button = button_map[button_id];
+ if (button == nullptr) {
continue;
- button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(button_map[button_id], &QPushButton::released, [=]() {
+ }
+
+ button->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(button, &QPushButton::released, [=] {
handleClick(
button_map[button_id],
[=](const Common::ParamPackage& params) { buttons_param[button_id] = params; },
InputCommon::Polling::DeviceType::Button);
});
- connect(button_map[button_id], &QPushButton::customContextMenuRequested,
- [=](const QPoint& menu_location) {
- QMenu context_menu;
- context_menu.addAction(tr("Clear"), [&] {
- buttons_param[button_id].Clear();
- button_map[button_id]->setText(tr("[not set]"));
- });
- context_menu.addAction(tr("Restore Default"), [&] {
- buttons_param[button_id] =
- Common::ParamPackage{InputCommon::GenerateKeyboardParam(
- Config::default_mouse_buttons[button_id])};
- button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
- });
- context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
- });
+ connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
+ QMenu context_menu;
+ context_menu.addAction(tr("Clear"), [&] {
+ buttons_param[button_id].Clear();
+ button_map[button_id]->setText(tr("[not set]"));
+ });
+ context_menu.addAction(tr("Restore Default"), [&] {
+ buttons_param[button_id] = Common::ParamPackage{
+ InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])};
+ button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
+ });
+ context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
+ });
}
connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); });
@@ -138,8 +151,10 @@ void ConfigureMouseAdvanced::restoreDefaults() {
void ConfigureMouseAdvanced::ClearAll() {
for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
- if (button_map[i] && button_map[i]->isEnabled())
+ const auto* const button = button_map[i];
+ if (button != nullptr && button->isEnabled()) {
buttons_param[i].Clear();
+ }
}
updateButtonLabels();
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp
index 022b94609..2bdfc8e5a 100644
--- a/src/yuzu/configuration/configure_per_general.cpp
+++ b/src/yuzu/configuration/configure_per_general.cpp
@@ -88,15 +88,15 @@ void ConfigurePerGameGeneral::loadFromFile(FileSys::VirtualFile file) {
}
void ConfigurePerGameGeneral::loadConfiguration() {
- if (file == nullptr)
+ if (file == nullptr) {
return;
+ }
- const auto loader = Loader::GetLoader(file);
-
- ui->display_title_id->setText(fmt::format("{:016X}", title_id).c_str());
+ ui->display_title_id->setText(QString::fromStdString(fmt::format("{:016X}", title_id)));
FileSys::PatchManager pm{title_id};
const auto control = pm.GetControlMetadata();
+ const auto loader = Loader::GetLoader(file);
if (control.first != nullptr) {
ui->display_version->setText(QString::fromStdString(control.first->GetVersionString()));
@@ -142,8 +142,10 @@ void ConfigurePerGameGeneral::loadConfiguration() {
const auto& disabled = Settings::values.disabled_addons[title_id];
for (const auto& patch : pm.GetPatchVersionNames(update_raw)) {
- QStandardItem* first_item = new QStandardItem;
- const auto name = QString::fromStdString(patch.first).replace("[D] ", "");
+ const auto name =
+ QString::fromStdString(patch.first).replace(QStringLiteral("[D] "), QString{});
+
+ auto* const first_item = new QStandardItem;
first_item->setText(name);
first_item->setCheckable(true);
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 41663e39a..002a51780 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -98,7 +98,7 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
tree_view->setContextMenuPolicy(Qt::NoContextMenu);
item_model->insertColumns(0, 1);
- item_model->setHeaderData(0, Qt::Horizontal, "Users");
+ item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
// We must register all custom types with the Qt Automoc system so that we are able to use it
// with signals/slots. In this case, QList falls under the umbrells of custom types.
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 10645a2b3..ff18ace40 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -66,8 +66,9 @@ void ConfigureSystem::setConfiguration() {
ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value());
ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value());
- const auto rng_seed =
- QString("%1").arg(Settings::values.rng_seed.value_or(0), 8, 16, QLatin1Char{'0'}).toUpper();
+ const auto rng_seed = QStringLiteral("%1")
+ .arg(Settings::values.rng_seed.value_or(0), 8, 16, QLatin1Char{'0'})
+ .toUpper();
ui->rng_seed_edit->setText(rng_seed);
ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value());
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp
index 18566d028..9dc34412d 100644
--- a/src/yuzu/configuration/configure_web.cpp
+++ b/src/yuzu/configuration/configure_web.cpp
@@ -78,12 +78,16 @@ void ConfigureWeb::RefreshTelemetryID() {
void ConfigureWeb::OnLoginChanged() {
if (ui->edit_username->text().isEmpty() && ui->edit_token->text().isEmpty()) {
user_verified = true;
- ui->label_username_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16));
- ui->label_token_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16));
+
+ const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
+ ui->label_username_verified->setPixmap(pixmap);
+ ui->label_token_verified->setPixmap(pixmap);
} else {
user_verified = false;
- ui->label_username_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16));
- ui->label_token_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16));
+
+ const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
+ ui->label_username_verified->setPixmap(pixmap);
+ ui->label_token_verified->setPixmap(pixmap);
}
}
@@ -101,11 +105,15 @@ void ConfigureWeb::OnLoginVerified() {
ui->button_verify_login->setText(tr("Verify"));
if (verify_watcher.result()) {
user_verified = true;
- ui->label_username_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16));
- ui->label_token_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16));
+
+ const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
+ ui->label_username_verified->setPixmap(pixmap);
+ ui->label_token_verified->setPixmap(pixmap);
} else {
- ui->label_username_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16));
- ui->label_token_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16));
+ const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
+ ui->label_username_verified->setPixmap(pixmap);
+ ui->label_token_verified->setPixmap(pixmap);
+
QMessageBox::critical(
this, tr("Verification failed"),
tr("Verification failed. Check that you have entered your username and token "
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
index 67ed0ba6d..1c80082a4 100644
--- a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
+++ b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
@@ -135,7 +135,7 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(
std::shared_ptr<Tegra::DebugContext> debug_context, QWidget* parent)
: QDockWidget(tr("Maxwell Breakpoints"), parent), Tegra::DebugContext::BreakPointObserver(
debug_context) {
- setObjectName("TegraBreakPointsWidget");
+ setObjectName(QStringLiteral("TegraBreakPointsWidget"));
status_text = new QLabel(tr("Emulation running"));
resume_button = new QPushButton(tr("Resume"));
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp
index 86e03e46d..f594ef076 100644
--- a/src/yuzu/debugger/profiler.cpp
+++ b/src/yuzu/debugger/profiler.cpp
@@ -47,7 +47,7 @@ private:
#endif
MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
- setObjectName("MicroProfile");
+ setObjectName(QStringLiteral("MicroProfile"));
setWindowTitle(tr("MicroProfile"));
resize(1000, 600);
// Remove the "?" button from the titlebar and enable the maximize button
@@ -191,7 +191,7 @@ void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 tex
for (u32 i = 0; i < text_length; ++i) {
// Position the text baseline 1 pixel above the bottom of the text cell, this gives nice
// vertical alignment of text for a wide range of tested fonts.
- mp_painter->drawText(x, y + MICROPROFILE_TEXT_HEIGHT - 2, QChar(text[i]));
+ mp_painter->drawText(x, y + MICROPROFILE_TEXT_HEIGHT - 2, QString{QLatin1Char{text[i]}});
x += MICROPROFILE_TEXT_WIDTH + 1;
}
}
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 85b095688..cd8180f8b 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -91,19 +91,19 @@ WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTa
WaitTreeMutexInfo::~WaitTreeMutexInfo() = default;
QString WaitTreeMutexInfo::GetText() const {
- return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char('0'));
+ return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char{'0'});
}
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() const {
- std::vector<std::unique_ptr<WaitTreeItem>> list;
-
- bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0;
+ const bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0;
+ std::vector<std::unique_ptr<WaitTreeItem>> list;
list.push_back(std::make_unique<WaitTreeText>(tr("has waiters: %1").arg(has_waiters)));
list.push_back(std::make_unique<WaitTreeText>(
- tr("owner handle: 0x%1").arg(owner_handle, 8, 16, QLatin1Char('0'))));
- if (owner != nullptr)
+ tr("owner handle: 0x%1").arg(owner_handle, 8, 16, QLatin1Char{'0'})));
+ if (owner != nullptr) {
list.push_back(std::make_unique<WaitTreeThread>(*owner));
+ }
return list;
}
@@ -121,11 +121,14 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
u64 base_pointer = thread.GetContext().cpu_registers[BaseRegister];
while (base_pointer != 0) {
- u64 lr = Memory::Read64(base_pointer + sizeof(u64));
- if (lr == 0)
+ const u64 lr = Memory::Read64(base_pointer + sizeof(u64));
+ if (lr == 0) {
break;
- list.push_back(
- std::make_unique<WaitTreeText>(tr("0x%1").arg(lr - sizeof(u32), 16, 16, QChar('0'))));
+ }
+
+ list.push_back(std::make_unique<WaitTreeText>(
+ tr("0x%1").arg(lr - sizeof(u32), 16, 16, QLatin1Char{'0'})));
+
base_pointer = Memory::Read64(base_pointer);
}
@@ -174,10 +177,10 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeWaitObject::GetChildren() con
QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) {
switch (reset_type) {
- case Kernel::ResetType::OneShot:
- return tr("one shot");
- case Kernel::ResetType::Sticky:
- return tr("sticky");
+ case Kernel::ResetType::Automatic:
+ return tr("automatic reset");
+ case Kernel::ResetType::Manual:
+ return tr("manual reset");
}
UNREACHABLE();
return {};
@@ -249,9 +252,9 @@ QString WaitTreeThread::GetText() const {
const auto& context = thread.GetContext();
const QString pc_info = tr(" PC = 0x%1 LR = 0x%2")
- .arg(context.pc, 8, 16, QLatin1Char('0'))
- .arg(context.cpu_registers[30], 8, 16, QLatin1Char('0'));
- return WaitTreeWaitObject::GetText() + pc_info + " (" + status + ") ";
+ .arg(context.pc, 8, 16, QLatin1Char{'0'})
+ .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'});
+ return QStringLiteral("%1%2 (%3) ").arg(WaitTreeWaitObject::GetText(), pc_info, status);
}
QColor WaitTreeThread::GetColor() const {
@@ -424,7 +427,7 @@ void WaitTreeModel::InitItems() {
}
WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) {
- setObjectName("WaitTreeWidget");
+ setObjectName(QStringLiteral("WaitTreeWidget"));
view = new QTreeView(this);
view->setHeaderHidden(true);
setWidget(view);
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index b0ca766ec..83d675773 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -14,7 +14,6 @@
#include <QMenu>
#include <QThreadPool>
#include <fmt/format.h>
-#include "common/common_paths.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/file_sys/patch_manager.h"
@@ -48,7 +47,7 @@ bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* eve
return QObject::eventFilter(obj, event);
} else {
gamelist->search_field->edit_filter->clear();
- edit_filter_text = "";
+ edit_filter_text.clear();
}
break;
}
@@ -71,9 +70,9 @@ bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* eve
}
if (resultCount == 1) {
// To avoid loading error dialog loops while confirming them using enter
- // Also users usually want to run a diffrent game after closing one
- gamelist->search_field->edit_filter->setText("");
- edit_filter_text = "";
+ // Also users usually want to run a different game after closing one
+ gamelist->search_field->edit_filter->clear();
+ edit_filter_text.clear();
emit gamelist->GameChosen(file_path);
} else {
return QObject::eventFilter(obj, event);
@@ -93,7 +92,7 @@ void GameListSearchField::setFilterResult(int visible, int total) {
}
void GameListSearchField::clear() {
- edit_filter->setText("");
+ edit_filter->clear();
}
void GameListSearchField::setFocus() {
@@ -103,25 +102,26 @@ void GameListSearchField::setFocus() {
}
GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} {
- KeyReleaseEater* keyReleaseEater = new KeyReleaseEater(parent);
+ auto* const key_release_eater = new KeyReleaseEater(parent);
layout_filter = new QHBoxLayout;
layout_filter->setMargin(8);
label_filter = new QLabel;
label_filter->setText(tr("Filter:"));
edit_filter = new QLineEdit;
- edit_filter->setText("");
+ edit_filter->clear();
edit_filter->setPlaceholderText(tr("Enter pattern to filter"));
- edit_filter->installEventFilter(keyReleaseEater);
+ edit_filter->installEventFilter(key_release_eater);
edit_filter->setClearButtonEnabled(true);
connect(edit_filter, &QLineEdit::textChanged, parent, &GameList::onTextChanged);
label_filter_result = new QLabel;
button_filter_close = new QToolButton(this);
- button_filter_close->setText("X");
+ button_filter_close->setText(QStringLiteral("X"));
button_filter_close->setCursor(Qt::ArrowCursor);
- button_filter_close->setStyleSheet("QToolButton{ border: none; padding: 0px; color: "
- "#000000; font-weight: bold; background: #F0F0F0; }"
- "QToolButton:hover{ border: none; padding: 0px; color: "
- "#EEEEEE; font-weight: bold; background: #E81123}");
+ button_filter_close->setStyleSheet(
+ QStringLiteral("QToolButton{ border: none; padding: 0px; color: "
+ "#000000; font-weight: bold; background: #F0F0F0; }"
+ "QToolButton:hover{ border: none; padding: 0px; color: "
+ "#EEEEEE; font-weight: bold; background: #E81123}"));
connect(button_filter_close, &QToolButton::clicked, parent, &GameList::onFilterCloseClicked);
layout_filter->setSpacing(10);
layout_filter->addWidget(label_filter);
@@ -141,36 +141,34 @@ GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} {
*/
static bool ContainsAllWords(const QString& haystack, const QString& userinput) {
const QStringList userinput_split =
- userinput.split(' ', QString::SplitBehavior::SkipEmptyParts);
+ userinput.split(QLatin1Char{' '}, QString::SplitBehavior::SkipEmptyParts);
return std::all_of(userinput_split.begin(), userinput_split.end(),
[&haystack](const QString& s) { return haystack.contains(s); });
}
// Event in order to filter the gamelist after editing the searchfield
-void GameList::onTextChanged(const QString& newText) {
- int rowCount = tree_view->model()->rowCount();
- QString edit_filter_text = newText.toLower();
-
- QModelIndex root_index = item_model->invisibleRootItem()->index();
+void GameList::onTextChanged(const QString& new_text) {
+ const int row_count = tree_view->model()->rowCount();
+ const QString edit_filter_text = new_text.toLower();
+ const QModelIndex root_index = item_model->invisibleRootItem()->index();
// If the searchfield is empty every item is visible
// Otherwise the filter gets applied
if (edit_filter_text.isEmpty()) {
- for (int i = 0; i < rowCount; ++i) {
+ for (int i = 0; i < row_count; ++i) {
tree_view->setRowHidden(i, root_index, false);
}
- search_field->setFilterResult(rowCount, rowCount);
+ search_field->setFilterResult(row_count, row_count);
} else {
int result_count = 0;
- for (int i = 0; i < rowCount; ++i) {
+ for (int i = 0; i < row_count; ++i) {
const QStandardItem* child_file = item_model->item(i, 0);
const QString file_path =
child_file->data(GameListItemPath::FullPathRole).toString().toLower();
- QString file_name = file_path.mid(file_path.lastIndexOf('/') + 1);
const QString file_title =
child_file->data(GameListItemPath::TitleRole).toString().toLower();
- const QString file_programmid =
+ const QString file_program_id =
child_file->data(GameListItemPath::ProgramIdRole).toString().toLower();
// Only items which filename in combination with its title contains all words
@@ -178,14 +176,16 @@ void GameList::onTextChanged(const QString& newText) {
// The search is case insensitive because of toLower()
// I decided not to use Qt::CaseInsensitive in containsAllWords to prevent
// multiple conversions of edit_filter_text for each game in the gamelist
- if (ContainsAllWords(file_name.append(' ').append(file_title), edit_filter_text) ||
- (file_programmid.count() == 16 && edit_filter_text.contains(file_programmid))) {
+ const QString file_name = file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) +
+ QLatin1Char{' '} + file_title;
+ if (ContainsAllWords(file_name, edit_filter_text) ||
+ (file_program_id.count() == 16 && edit_filter_text.contains(file_program_id))) {
tree_view->setRowHidden(i, root_index, false);
++result_count;
} else {
tree_view->setRowHidden(i, root_index, true);
}
- search_field->setFilterResult(result_count, rowCount);
+ search_field->setFilterResult(result_count, row_count);
}
}
}
@@ -216,7 +216,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvide
tree_view->setEditTriggers(QHeaderView::NoEditTriggers);
tree_view->setUniformRowHeights(true);
tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
- tree_view->setStyleSheet("QTreeView{ border: none; }");
+ tree_view->setStyleSheet(QStringLiteral("QTreeView{ border: none; }"));
item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
@@ -282,9 +282,9 @@ void GameList::ValidateEntry(const QModelIndex& item) {
const QFileInfo file_info{file_path};
if (file_info.isDir()) {
const QDir dir{file_path};
- const QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files);
+ const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files);
if (matching_main.size() == 1) {
- emit GameChosen(dir.path() + DIR_SEP + matching_main[0]);
+ emit GameChosen(dir.path() + QDir::separator() + matching_main[0]);
}
return;
}
@@ -360,7 +360,7 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
}
void GameList::LoadCompatibilityList() {
- QFile compat_list{":compatibility_list/compatibility_list.json"};
+ QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
if (!compat_list.open(QFile::ReadOnly | QFile::Text)) {
LOG_ERROR(Frontend, "Unable to open game compatibility list");
@@ -378,25 +378,27 @@ void GameList::LoadCompatibilityList() {
return;
}
- const QString string_content = content;
- QJsonDocument json = QJsonDocument::fromJson(string_content.toUtf8());
- QJsonArray arr = json.array();
+ const QJsonDocument json = QJsonDocument::fromJson(content);
+ const QJsonArray arr = json.array();
- for (const QJsonValueRef value : arr) {
- QJsonObject game = value.toObject();
+ for (const QJsonValue value : arr) {
+ const QJsonObject game = value.toObject();
+ const QString compatibility_key = QStringLiteral("compatibility");
- if (game.contains("compatibility") && game["compatibility"].isDouble()) {
- int compatibility = game["compatibility"].toInt();
- QString directory = game["directory"].toString();
- QJsonArray ids = game["releases"].toArray();
+ if (!game.contains(compatibility_key) || !game[compatibility_key].isDouble()) {
+ continue;
+ }
- for (const QJsonValueRef id_ref : ids) {
- QJsonObject id_object = id_ref.toObject();
- QString id = id_object["id"].toString();
- compatibility_list.emplace(
- id.toUpper().toStdString(),
- std::make_pair(QString::number(compatibility), directory));
- }
+ const int compatibility = game[compatibility_key].toInt();
+ const QString directory = game[QStringLiteral("directory")].toString();
+ const QJsonArray ids = game[QStringLiteral("releases")].toArray();
+
+ for (const QJsonValue id_ref : ids) {
+ const QJsonObject id_object = id_ref.toObject();
+ const QString id = id_object[QStringLiteral("id")].toString();
+
+ compatibility_list.emplace(id.toUpper().toStdString(),
+ std::make_pair(QString::number(compatibility), directory));
}
}
}
@@ -464,7 +466,10 @@ void GameList::LoadInterfaceLayout() {
item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder());
}
-const QStringList GameList::supported_file_extensions = {"nso", "nro", "nca", "xci", "nsp"};
+const QStringList GameList::supported_file_extensions = {
+ QStringLiteral("nso"), QStringLiteral("nro"), QStringLiteral("nca"),
+ QStringLiteral("xci"), QStringLiteral("nsp"),
+};
void GameList::RefreshGameDirectory() {
if (!UISettings::values.game_directory_path.isEmpty() && current_worker != nullptr) {
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 56007eef8..f8f8bd6c5 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -76,7 +76,7 @@ signals:
void OpenPerGameGeneralRequested(const std::string& file);
private slots:
- void onTextChanged(const QString& newText);
+ void onTextChanged(const QString& new_text);
void onFilterCloseClicked();
private:
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index 2cf5c58a0..0b458ef48 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -4,11 +4,9 @@
#pragma once
-#include <algorithm>
#include <array>
#include <map>
#include <string>
-#include <unordered_map>
#include <utility>
#include <QCoreApplication>
@@ -25,8 +23,8 @@
#include "yuzu/util/util.h"
/**
- * Gets the default icon (for games without valid SMDH)
- * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
+ * Gets the default icon (for games without valid title metadata)
+ * @param size The desired width and height of the default icon.
* @return QPixmap default icon
*/
static QPixmap GetDefaultIcon(u32 size) {
@@ -46,7 +44,7 @@ public:
* A specialization of GameListItem for path values.
* This class ensures that for every full path value it holds, a correct string representation
* of just the filename (with no extension) will be displayed to the user.
- * If this class receives valid SMDH data, it will also display game icons and titles.
+ * If this class receives valid title metadata, it will also display game icons and titles.
*/
class GameListItemPath : public GameListItem {
public:
@@ -95,7 +93,7 @@ public:
if (row2.isEmpty())
return row1;
- return QString(row1 + "\n " + row2);
+ return QString(row1 + QStringLiteral("\n ") + row2);
}
return GameListItem::data(role);
@@ -115,13 +113,14 @@ public:
};
// clang-format off
static const std::map<QString, CompatStatus> status_data = {
- {"0", {"#5c93ed", QT_TR_NOOP("Perfect"), QT_TR_NOOP("Game functions flawless with no audio or graphical glitches, all tested functionality works as intended without\nany workarounds needed.")}},
- {"1", {"#47d35c", QT_TR_NOOP("Great"), QT_TR_NOOP("Game functions with minor graphical or audio glitches and is playable from start to finish. May require some\nworkarounds.")}},
- {"2", {"#94b242", QT_TR_NOOP("Okay"), QT_TR_NOOP("Game functions with major graphical or audio glitches, but game is playable from start to finish with\nworkarounds.")}},
- {"3", {"#f2d624", QT_TR_NOOP("Bad"), QT_TR_NOOP("Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches\neven with workarounds.")}},
- {"4", {"#FF0000", QT_TR_NOOP("Intro/Menu"), QT_TR_NOOP("Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start\nScreen.")}},
- {"5", {"#828282", QT_TR_NOOP("Won't Boot"), QT_TR_NOOP("The game crashes when attempting to startup.")}},
- {"99", {"#000000", QT_TR_NOOP("Not Tested"), QT_TR_NOOP("The game has not yet been tested.")}}};
+ {QStringLiteral("0"), {QStringLiteral("#5c93ed"), QT_TR_NOOP("Perfect"), QT_TR_NOOP("Game functions flawless with no audio or graphical glitches, all tested functionality works as intended without\nany workarounds needed.")}},
+ {QStringLiteral("1"), {QStringLiteral("#47d35c"), QT_TR_NOOP("Great"), QT_TR_NOOP("Game functions with minor graphical or audio glitches and is playable from start to finish. May require some\nworkarounds.")}},
+ {QStringLiteral("2"), {QStringLiteral("#94b242"), QT_TR_NOOP("Okay"), QT_TR_NOOP("Game functions with major graphical or audio glitches, but game is playable from start to finish with\nworkarounds.")}},
+ {QStringLiteral("3"), {QStringLiteral("#f2d624"), QT_TR_NOOP("Bad"), QT_TR_NOOP("Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches\neven with workarounds.")}},
+ {QStringLiteral("4"), {QStringLiteral("#FF0000"), QT_TR_NOOP("Intro/Menu"), QT_TR_NOOP("Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start\nScreen.")}},
+ {QStringLiteral("5"), {QStringLiteral("#828282"), QT_TR_NOOP("Won't Boot"), QT_TR_NOOP("The game crashes when attempting to startup.")}},
+ {QStringLiteral("99"), {QStringLiteral("#000000"), QT_TR_NOOP("Not Tested"), QT_TR_NOOP("The game has not yet been tested.")}},
+ };
// clang-format on
auto iterator = status_data.find(compatibility);
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 8687e7c5a..82d2826ba 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -45,7 +45,7 @@ bool HasSupportedFileExtension(const std::string& file_name) {
}
bool IsExtractedNCAMain(const std::string& file_name) {
- return QFileInfo(QString::fromStdString(file_name)).fileName() == "main";
+ return QFileInfo(QString::fromStdString(file_name)).fileName() == QStringLiteral("main");
}
QString FormatGameName(const std::string& physical_name) {
@@ -97,7 +97,7 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
// The game list uses this as compatibility number for untested games
- QString compatibility{"99"};
+ QString compatibility{QStringLiteral("99")};
if (it != compatibility_list.end()) {
compatibility = it->second.first;
}
diff --git a/src/yuzu/loading_screen.cpp b/src/yuzu/loading_screen.cpp
index 4e2d988cd..4f2bfab48 100644
--- a/src/yuzu/loading_screen.cpp
+++ b/src/yuzu/loading_screen.cpp
@@ -30,11 +30,11 @@
#include <QMovie>
#endif
-constexpr const char PROGRESSBAR_STYLE_PREPARE[] = R"(
+constexpr char PROGRESSBAR_STYLE_PREPARE[] = R"(
QProgressBar {}
QProgressBar::chunk {})";
-constexpr const char PROGRESSBAR_STYLE_DECOMPILE[] = R"(
+constexpr char PROGRESSBAR_STYLE_DECOMPILE[] = R"(
QProgressBar {
background-color: black;
border: 2px solid white;
@@ -46,7 +46,7 @@ QProgressBar::chunk {
width: 1px;
})";
-constexpr const char PROGRESSBAR_STYLE_BUILD[] = R"(
+constexpr char PROGRESSBAR_STYLE_BUILD[] = R"(
QProgressBar {
background-color: black;
border: 2px solid white;
@@ -58,7 +58,7 @@ QProgressBar::chunk {
width: 1px;
})";
-constexpr const char PROGRESSBAR_STYLE_COMPLETE[] = R"(
+constexpr char PROGRESSBAR_STYLE_COMPLETE[] = R"(
QProgressBar {
background-color: #0ab9e6;
border: 2px solid white;
@@ -149,10 +149,10 @@ void LoadingScreen::OnLoadComplete() {
void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value,
std::size_t total) {
using namespace std::chrono;
- auto now = high_resolution_clock::now();
+ const auto now = high_resolution_clock::now();
// reset the timer if the stage changes
if (stage != previous_stage) {
- ui->progress_bar->setStyleSheet(progressbar_style[stage]);
+ ui->progress_bar->setStyleSheet(QString::fromUtf8(progressbar_style[stage]));
// Hide the progress bar during the prepare stage
if (stage == VideoCore::LoadCallbackStage::Prepare) {
ui->progress_bar->hide();
@@ -178,16 +178,16 @@ void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size
slow_shader_first_value = value;
}
// only calculate an estimate time after a second has passed since stage change
- auto diff = duration_cast<milliseconds>(now - slow_shader_start);
+ const auto diff = duration_cast<milliseconds>(now - slow_shader_start);
if (diff > seconds{1}) {
- auto eta_mseconds =
+ const auto eta_mseconds =
static_cast<long>(static_cast<double>(total - slow_shader_first_value) /
(value - slow_shader_first_value) * diff.count());
estimate =
tr("Estimated Time %1")
.arg(QTime(0, 0, 0, 0)
.addMSecs(std::max<long>(eta_mseconds - diff.count() + 1000, 1000))
- .toString("mm:ss"));
+ .toString(QStringLiteral("mm:ss")));
}
}
diff --git a/src/yuzu/util/spinbox.cpp b/src/yuzu/util/spinbox.cpp
deleted file mode 100644
index 14ef1e884..000000000
--- a/src/yuzu/util/spinbox.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// Copyright 2014 Tony Wasserka
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the owner nor the names of its contributors may
-// be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <cstdlib>
-#include <QLineEdit>
-#include <QRegExpValidator>
-#include "common/assert.h"
-#include "yuzu/util/spinbox.h"
-
-CSpinBox::CSpinBox(QWidget* parent)
- : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) {
- // TODO: Might be nice to not immediately call the slot.
- // Think of an address that is being replaced by a different one, in which case a lot
- // invalid intermediate addresses would be read from during editing.
- connect(lineEdit(), &QLineEdit::textEdited, this, &CSpinBox::OnEditingFinished);
-
- UpdateText();
-}
-
-void CSpinBox::SetValue(qint64 val) {
- auto old_value = value;
- value = std::max(std::min(val, max_value), min_value);
-
- if (old_value != value) {
- UpdateText();
- emit ValueChanged(value);
- }
-}
-
-void CSpinBox::SetRange(qint64 min, qint64 max) {
- min_value = min;
- max_value = max;
-
- SetValue(value);
- UpdateText();
-}
-
-void CSpinBox::stepBy(int steps) {
- auto new_value = value;
- // Scale number of steps by the currently selected digit
- // TODO: Move this code elsewhere and enable it.
- // TODO: Support for num_digits==0, too
- // TODO: Support base!=16, too
- // TODO: Make the cursor not jump back to the end of the line...
- /*if (base == 16 && num_digits > 0) {
- int digit = num_digits - (lineEdit()->cursorPosition() - prefix.length()) - 1;
- digit = std::max(0, std::min(digit, num_digits - 1));
- steps <<= digit * 4;
- }*/
-
- // Increment "new_value" by "steps", and perform annoying overflow checks, too.
- if (steps < 0 && new_value + steps > new_value) {
- new_value = std::numeric_limits<qint64>::min();
- } else if (steps > 0 && new_value + steps < new_value) {
- new_value = std::numeric_limits<qint64>::max();
- } else {
- new_value += steps;
- }
-
- SetValue(new_value);
- UpdateText();
-}
-
-QAbstractSpinBox::StepEnabled CSpinBox::stepEnabled() const {
- StepEnabled ret = StepNone;
-
- if (value > min_value)
- ret |= StepDownEnabled;
-
- if (value < max_value)
- ret |= StepUpEnabled;
-
- return ret;
-}
-
-void CSpinBox::SetBase(int base) {
- this->base = base;
-
- UpdateText();
-}
-
-void CSpinBox::SetNumDigits(int num_digits) {
- this->num_digits = num_digits;
-
- UpdateText();
-}
-
-void CSpinBox::SetPrefix(const QString& prefix) {
- this->prefix = prefix;
-
- UpdateText();
-}
-
-void CSpinBox::SetSuffix(const QString& suffix) {
- this->suffix = suffix;
-
- UpdateText();
-}
-
-static QString StringToInputMask(const QString& input) {
- QString mask = input;
-
- // ... replace any special characters by their escaped counterparts ...
- mask.replace("\\", "\\\\");
- mask.replace("A", "\\A");
- mask.replace("a", "\\a");
- mask.replace("N", "\\N");
- mask.replace("n", "\\n");
- mask.replace("X", "\\X");
- mask.replace("x", "\\x");
- mask.replace("9", "\\9");
- mask.replace("0", "\\0");
- mask.replace("D", "\\D");
- mask.replace("d", "\\d");
- mask.replace("#", "\\#");
- mask.replace("H", "\\H");
- mask.replace("h", "\\h");
- mask.replace("B", "\\B");
- mask.replace("b", "\\b");
- mask.replace(">", "\\>");
- mask.replace("<", "\\<");
- mask.replace("!", "\\!");
-
- return mask;
-}
-
-void CSpinBox::UpdateText() {
- // If a fixed number of digits is used, we put the line edit in insertion mode by setting an
- // input mask.
- QString mask;
- if (num_digits != 0) {
- mask += StringToInputMask(prefix);
-
- // For base 10 and negative range, demand a single sign character
- if (HasSign())
- mask += "X"; // identified as "-" or "+" in the validator
-
- // Uppercase digits greater than 9.
- mask += ">";
-
- // Match num_digits digits
- // Digits irrelevant to the chosen number base are filtered in the validator
- mask += QString("H").repeated(std::max(num_digits, 1));
-
- // Switch off case conversion
- mask += "!";
-
- mask += StringToInputMask(suffix);
- }
- lineEdit()->setInputMask(mask);
-
- // Set new text without changing the cursor position. This will cause the cursor to briefly
- // appear at the end of the line and then to jump back to its original position. That's
- // a bit ugly, but better than having setText() move the cursor permanently all the time.
- int cursor_position = lineEdit()->cursorPosition();
- lineEdit()->setText(TextFromValue());
- lineEdit()->setCursorPosition(cursor_position);
-}
-
-QString CSpinBox::TextFromValue() {
- return prefix + QString(HasSign() ? ((value < 0) ? "-" : "+") : "") +
- QString("%1").arg(std::abs(value), num_digits, base, QLatin1Char('0')).toUpper() +
- suffix;
-}
-
-qint64 CSpinBox::ValueFromText() {
- unsigned strpos = prefix.length();
-
- QString num_string = text().mid(strpos, text().length() - strpos - suffix.length());
- return num_string.toLongLong(nullptr, base);
-}
-
-bool CSpinBox::HasSign() const {
- return base == 10 && min_value < 0;
-}
-
-void CSpinBox::OnEditingFinished() {
- // Only update for valid input
- QString input = lineEdit()->text();
- int pos = 0;
- if (QValidator::Acceptable == validate(input, pos))
- SetValue(ValueFromText());
-}
-
-QValidator::State CSpinBox::validate(QString& input, int& pos) const {
- if (!prefix.isEmpty() && input.left(prefix.length()) != prefix)
- return QValidator::Invalid;
-
- int strpos = prefix.length();
-
- // Empty "numbers" allowed as intermediate values
- if (strpos >= input.length() - HasSign() - suffix.length())
- return QValidator::Intermediate;
-
- DEBUG_ASSERT(base <= 10 || base == 16);
- QString regexp;
-
- // Demand sign character for negative ranges
- if (HasSign())
- regexp += "[+\\-]";
-
- // Match digits corresponding to the chosen number base.
- regexp += QString("[0-%1").arg(std::min(base, 9));
- if (base == 16) {
- regexp += "a-fA-F";
- }
- regexp += "]";
-
- // Specify number of digits
- if (num_digits > 0) {
- regexp += QString("{%1}").arg(num_digits);
- } else {
- regexp += "+";
- }
-
- // Match string
- QRegExp num_regexp(regexp);
- int num_pos = strpos;
- QString sub_input = input.mid(strpos, input.length() - strpos - suffix.length());
-
- if (!num_regexp.exactMatch(sub_input) && num_regexp.matchedLength() == 0)
- return QValidator::Invalid;
-
- sub_input = sub_input.left(num_regexp.matchedLength());
- bool ok;
- qint64 val = sub_input.toLongLong(&ok, base);
-
- if (!ok)
- return QValidator::Invalid;
-
- // Outside boundaries => don't accept
- if (val < min_value || val > max_value)
- return QValidator::Invalid;
-
- // Make sure we are actually at the end of this string...
- strpos += num_regexp.matchedLength();
-
- if (!suffix.isEmpty() && input.mid(strpos) != suffix) {
- return QValidator::Invalid;
- } else {
- strpos += suffix.length();
- }
-
- if (strpos != input.length())
- return QValidator::Invalid;
-
- // At this point we can say for sure that the input is fine. Let's fix it up a bit though
- input.replace(num_pos, sub_input.length(), sub_input.toUpper());
-
- return QValidator::Acceptable;
-}
diff --git a/src/yuzu/util/spinbox.h b/src/yuzu/util/spinbox.h
deleted file mode 100644
index 2fa1db3a4..000000000
--- a/src/yuzu/util/spinbox.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// Copyright 2014 Tony Wasserka
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the owner nor the names of its contributors may
-// be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#pragma once
-
-#include <QAbstractSpinBox>
-#include <QtGlobal>
-
-class QVariant;
-
-/**
- * A custom spin box widget with enhanced functionality over Qt's QSpinBox
- */
-class CSpinBox : public QAbstractSpinBox {
- Q_OBJECT
-
-public:
- explicit CSpinBox(QWidget* parent = nullptr);
-
- void stepBy(int steps) override;
- StepEnabled stepEnabled() const override;
-
- void SetValue(qint64 val);
-
- void SetRange(qint64 min, qint64 max);
-
- void SetBase(int base);
-
- void SetPrefix(const QString& prefix);
- void SetSuffix(const QString& suffix);
-
- void SetNumDigits(int num_digits);
-
- QValidator::State validate(QString& input, int& pos) const override;
-
-signals:
- void ValueChanged(qint64 val);
-
-private slots:
- void OnEditingFinished();
-
-private:
- void UpdateText();
-
- bool HasSign() const;
-
- QString TextFromValue();
- qint64 ValueFromText();
-
- qint64 min_value, max_value;
-
- qint64 value;
-
- QString prefix, suffix;
-
- int base;
-
- int num_digits;
-};
diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp
index 62c080aff..ef31bc2d2 100644
--- a/src/yuzu/util/util.cpp
+++ b/src/yuzu/util/util.cpp
@@ -8,7 +8,7 @@
#include "yuzu/util/util.h"
QFont GetMonospaceFont() {
- QFont font("monospace");
+ QFont font(QStringLiteral("monospace"));
// Automatic fallback to a monospace font on on platforms without a font called "monospace"
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
@@ -16,14 +16,16 @@ QFont GetMonospaceFont() {
}
QString ReadableByteSize(qulonglong size) {
- static const std::array<const char*, 6> units = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
- if (size == 0)
- return "0";
- int digit_groups = std::min<int>(static_cast<int>(std::log10(size) / std::log10(1024)),
- static_cast<int>(units.size()));
- return QString("%L1 %2")
+ static constexpr std::array units{"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
+ if (size == 0) {
+ return QStringLiteral("0");
+ }
+
+ const int digit_groups = std::min(static_cast<int>(std::log10(size) / std::log10(1024)),
+ static_cast<int>(units.size()));
+ return QStringLiteral("%L1 %2")
.arg(size / std::pow(1024, digit_groups), 0, 'f', 1)
- .arg(units[digit_groups]);
+ .arg(QString::fromUtf8(units[digit_groups]));
}
QPixmap CreateCirclePixmapFromColor(const QColor& color) {