diff options
Diffstat (limited to 'src')
48 files changed, 467 insertions, 322 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 42d9dd844..f3da525d6 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -43,7 +43,7 @@ void SessionRequestHandler::ClientDisconnected(const SharedPtr<ServerSession>& s } SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( - SharedPtr<Thread> thread, const std::string& reason, u64 timeout, WakeupCallback&& callback, + const std::string& reason, u64 timeout, WakeupCallback&& callback, SharedPtr<WritableEvent> writable_event) { // Put the client thread to sleep until the wait event is signaled or the timeout expires. thread->SetWakeupCallback([context = *this, callback]( @@ -76,8 +76,9 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( return writable_event; } -HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session) - : server_session(std::move(server_session)) { +HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session, + SharedPtr<Thread> thread) + : server_session(std::move(server_session)), thread(std::move(thread)) { cmd_buf[0] = 0; } diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 2bdd9f02c..ccf5e56aa 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -97,7 +97,7 @@ protected: */ class HLERequestContext { public: - explicit HLERequestContext(SharedPtr<ServerSession> session); + explicit HLERequestContext(SharedPtr<ServerSession> session, SharedPtr<Thread> thread); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. @@ -119,7 +119,6 @@ public: /** * Puts the specified guest thread to sleep until the returned event is signaled or until the * specified timeout expires. - * @param thread Thread to be put to sleep. * @param reason Reason for pausing the thread, to be used for debugging purposes. * @param timeout Timeout in nanoseconds after which the thread will be awoken and the callback * invoked with a Timeout reason. @@ -130,8 +129,8 @@ public: * created. * @returns Event that when signaled will resume the thread and call the callback function. */ - SharedPtr<WritableEvent> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason, - u64 timeout, WakeupCallback&& callback, + SharedPtr<WritableEvent> SleepClientThread(const std::string& reason, u64 timeout, + WakeupCallback&& callback, SharedPtr<WritableEvent> writable_event = nullptr); /// Populates this context with data from the requesting process/thread. @@ -268,6 +267,7 @@ private: std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; SharedPtr<Kernel::ServerSession> server_session; + SharedPtr<Thread> thread; // TODO(yuriks): Check common usage of this and optimize size accordingly boost::container::small_vector<SharedPtr<Object>, 8> move_objects; boost::container::small_vector<SharedPtr<Object>, 8> copy_objects; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 696a82cd9..30b2bfb5a 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -130,7 +130,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { // The ServerSession received a sync request, this means that there's new data available // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or // similar. - Kernel::HLERequestContext context(this); + Kernel::HLERequestContext context(this, thread); u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress()); context.PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 4e17249a9..f1fa6ccd1 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -556,7 +556,7 @@ private: } else { // Wait the current thread until a buffer becomes available ctx.SleepClientThread( - Kernel::GetCurrentThread(), "IHOSBinderDriver::DequeueBuffer", -1, + "IHOSBinderDriver::DequeueBuffer", -1, [=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { // Repeat TransactParcel DequeueBuffer when a buffer is available diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 7bbc556da..e83f25fa1 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -530,6 +530,11 @@ union Instruction { BitField<48, 16, u64> opcode; union { + BitField<8, 8, Register> gpr; + BitField<20, 24, s64> offset; + } gmem; + + union { BitField<20, 16, u64> imm20_16; BitField<20, 19, u64> imm20_19; BitField<20, 32, s64> imm20_32; @@ -812,13 +817,11 @@ union Instruction { union { BitField<48, 3, UniformType> type; BitField<46, 2, u64> cache_mode; - BitField<20, 24, s64> immediate_offset; } ldg; union { BitField<48, 3, UniformType> type; BitField<46, 2, u64> cache_mode; - BitField<20, 24, s64> immediate_offset; } stg; union { @@ -828,6 +831,11 @@ union Instruction { } al2p; union { + BitField<53, 3, UniformType> type; + BitField<52, 1, u64> extended; + } generic; + + union { BitField<0, 3, u64> pred0; BitField<3, 3, u64> pred3; BitField<7, 1, u64> abs_a; @@ -1387,10 +1395,12 @@ public: LD_L, LD_S, LD_C, + LD, // Load from generic memory + LDG, // Load from global memory ST_A, ST_L, ST_S, - LDG, // Load from global memory + ST, // Store in generic memory STG, // Store in global memory AL2P, // Transforms attribute memory into physical memory TEX, @@ -1658,10 +1668,12 @@ private: INST("1110111101001---", Id::LD_S, Type::Memory, "LD_S"), INST("1110111101000---", Id::LD_L, Type::Memory, "LD_L"), INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), + INST("100-------------", Id::LD, Type::Memory, "LD"), + INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), INST("1110111101011---", Id::ST_S, Type::Memory, "ST_S"), INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"), - INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), + INST("101-------------", Id::ST, Type::Memory, "ST"), INST("1110111011011---", Id::STG, Type::Memory, "STG"), INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"), INST("110000----111---", Id::TEX, Type::Texture, "TEX"), diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index dbd8049f5..f9b6dfeea 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -98,9 +98,11 @@ struct FramebufferCacheKey { } }; -RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) - : res_cache{*this}, shader_cache{*this, system, device}, global_cache{*this}, system{system}, - screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) { +RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, + ScreenInfo& info) + : res_cache{*this}, shader_cache{*this, system, emu_window, device}, + global_cache{*this}, system{system}, screen_info{info}, + buffer_cache(*this, STREAM_BUFFER_SIZE) { OpenGLState::ApplyDefaultState(); shader_program_manager = std::make_unique<GLShader::ProgramManager>(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 71b9c5ead..d78094138 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -48,7 +48,8 @@ struct FramebufferCacheKey; class RasterizerOpenGL : public VideoCore::RasterizerInterface { public: - explicit RasterizerOpenGL(Core::System& system, ScreenInfo& info); + explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, + ScreenInfo& info); ~RasterizerOpenGL() override; void DrawArrays() override; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index f700dc89a..7ee1c99c0 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -2,10 +2,14 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <mutex> +#include <thread> #include <boost/functional/hash.hpp> #include "common/assert.h" #include "common/hash.h" +#include "common/scope_exit.h" #include "core/core.h" +#include "core/frontend/emu_window.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/memory_manager.h" #include "video_core/renderer_opengl/gl_rasterizer.h" @@ -344,8 +348,8 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode, } ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system, - const Device& device) - : RasterizerCache{rasterizer}, device{device}, disk_cache{system} {} + Core::Frontend::EmuWindow& emu_window, const Device& device) + : RasterizerCache{rasterizer}, emu_window{emu_window}, device{device}, disk_cache{system} {} void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) { @@ -353,62 +357,107 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, if (!transferable) { return; } - const auto [raws, usages] = *transferable; + const auto [raws, shader_usages] = *transferable; auto [decompiled, dumps] = disk_cache.LoadPrecompiled(); const auto supported_formats{GetSupportedFormats()}; - const auto unspecialized{ + const auto unspecialized_shaders{ GenerateUnspecializedShaders(stop_loading, callback, raws, decompiled)}; - if (stop_loading) + if (stop_loading) { return; + } // Track if precompiled cache was altered during loading to know if we have to serialize the // virtual precompiled cache file back to the hard drive bool precompiled_cache_altered = false; - // Build shaders - if (callback) - callback(VideoCore::LoadCallbackStage::Build, 0, usages.size()); - for (std::size_t i = 0; i < usages.size(); ++i) { - if (stop_loading) - return; + // Inform the frontend about shader build initialization + if (callback) { + callback(VideoCore::LoadCallbackStage::Build, 0, shader_usages.size()); + } - const auto& usage{usages[i]}; - LOG_INFO(Render_OpenGL, "Building shader {:016x} ({} of {})", usage.unique_identifier, - i + 1, usages.size()); + std::mutex mutex; + std::size_t built_shaders = 0; // It doesn't have be atomic since it's used behind a mutex + std::atomic_bool compilation_failed = false; - const auto& unspec{unspecialized.at(usage.unique_identifier)}; - const auto dump_it = dumps.find(usage); + const auto Worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin, + std::size_t end, const std::vector<ShaderDiskCacheUsage>& shader_usages, + const ShaderDumpsMap& dumps) { + context->MakeCurrent(); + SCOPE_EXIT({ return context->DoneCurrent(); }); - CachedProgram shader; - if (dump_it != dumps.end()) { - // If the shader is dumped, attempt to load it with - shader = GeneratePrecompiledProgram(dump_it->second, supported_formats); + for (std::size_t i = begin; i < end; ++i) { + if (stop_loading || compilation_failed) { + return; + } + const auto& usage{shader_usages[i]}; + LOG_INFO(Render_OpenGL, "Building shader {:016x} (index {} of {})", + usage.unique_identifier, i, shader_usages.size()); + + const auto& unspecialized{unspecialized_shaders.at(usage.unique_identifier)}; + const auto dump{dumps.find(usage)}; + + CachedProgram shader; + if (dump != dumps.end()) { + // If the shader is dumped, attempt to load it with + shader = GeneratePrecompiledProgram(dump->second, supported_formats); + if (!shader) { + compilation_failed = true; + return; + } + } if (!shader) { - // Invalidate the precompiled cache if a shader dumped shader was rejected - disk_cache.InvalidatePrecompiled(); - precompiled_cache_altered = true; - dumps.clear(); + shader = SpecializeShader(unspecialized.code, unspecialized.entries, + unspecialized.program_type, usage.bindings, + usage.primitive, true); } + + std::scoped_lock lock(mutex); + if (callback) { + callback(VideoCore::LoadCallbackStage::Build, ++built_shaders, + shader_usages.size()); + } + + precompiled_programs.emplace(usage, std::move(shader)); } - if (!shader) { - shader = SpecializeShader(unspec.code, unspec.entries, unspec.program_type, - usage.bindings, usage.primitive, true); - } - precompiled_programs.insert({usage, std::move(shader)}); + }; + + const auto num_workers{static_cast<std::size_t>(std::thread::hardware_concurrency() + 1)}; + const std::size_t bucket_size{shader_usages.size() / num_workers}; + std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers); + std::vector<std::thread> threads(num_workers); + for (std::size_t i = 0; i < num_workers; ++i) { + const bool is_last_worker = i + 1 == num_workers; + const std::size_t start{bucket_size * i}; + const std::size_t end{is_last_worker ? shader_usages.size() : start + bucket_size}; + + // On some platforms the shared context has to be created from the GUI thread + contexts[i] = emu_window.CreateSharedContext(); + threads[i] = std::thread(Worker, contexts[i].get(), start, end, shader_usages, dumps); + } + for (auto& thread : threads) { + thread.join(); + } - if (callback) - callback(VideoCore::LoadCallbackStage::Build, i + 1, usages.size()); + if (compilation_failed) { + // Invalidate the precompiled cache if a shader dumped shader was rejected + disk_cache.InvalidatePrecompiled(); + dumps.clear(); + precompiled_cache_altered = true; + return; + } + if (stop_loading) { + return; } // TODO(Rodrigo): Do state tracking for transferable shaders and do a dummy draw before // precompiling them - for (std::size_t i = 0; i < usages.size(); ++i) { - const auto& usage{usages[i]}; + for (std::size_t i = 0; i < shader_usages.size(); ++i) { + const auto& usage{shader_usages[i]}; if (dumps.find(usage) == dumps.end()) { - const auto& program = precompiled_programs.at(usage); + const auto& program{precompiled_programs.at(usage)}; disk_cache.SaveDump(usage, program->handle); precompiled_cache_altered = true; } diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 31b979987..64e5a5594 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -22,7 +22,11 @@ namespace Core { class System; -} // namespace Core +} + +namespace Core::Frontend { +class EmuWindow; +} namespace OpenGL { @@ -111,7 +115,7 @@ private: class ShaderCacheOpenGL final : public RasterizerCache<Shader> { public: explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system, - const Device& device); + Core::Frontend::EmuWindow& emu_window, const Device& device); /// Loads disk cache for the current game void LoadDiskCache(const std::atomic_bool& stop_loading, @@ -133,13 +137,13 @@ private: CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump, const std::set<GLenum>& supported_formats); + Core::Frontend::EmuWindow& emu_window; const Device& device; - - std::array<Shader, Maxwell::MaxShaderProgram> last_shaders; - ShaderDiskCacheOpenGL disk_cache; + PrecompiledShaders precompiled_shaders; PrecompiledPrograms precompiled_programs; + std::array<Shader, Maxwell::MaxShaderProgram> last_shaders; }; } // namespace OpenGL 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 fba9c594a..ee4a45ca2 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -183,8 +183,7 @@ ShaderDiskCacheOpenGL::LoadTransferable() { return {{raws, usages}}; } -std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, - std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>> +std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, ShaderDumpsMap> ShaderDiskCacheOpenGL::LoadPrecompiled() { if (!IsUsable()) return {}; @@ -208,8 +207,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiled() { return *result; } -std::optional<std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, - std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>>> +std::optional<std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, ShaderDumpsMap>> ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) { // Read compressed file from disk and decompress to virtual precompiled cache file std::vector<u8> compressed(file.GetSize()); @@ -230,7 +228,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) { } std::unordered_map<u64, ShaderDiskCacheDecompiled> decompiled; - std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump> dumps; + ShaderDumpsMap dumps; while (precompiled_cache_virtual_file_offset < precompiled_cache_virtual_file.GetSize()) { PrecompiledEntryKind kind{}; if (!LoadObjectFromPrecompiled(kind)) { 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 2da0a4a23..ecd72ba58 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h @@ -33,6 +33,11 @@ namespace OpenGL { using ProgramCode = std::vector<u64>; using Maxwell = Tegra::Engines::Maxwell3D::Regs; +struct ShaderDiskCacheUsage; +struct ShaderDiskCacheDump; + +using ShaderDumpsMap = std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>; + /// Allocated bindings used by an OpenGL shader program struct BaseBindings { u32 cbuf{}; @@ -294,4 +299,4 @@ private: bool tried_to_load{}; }; -} // namespace OpenGL
\ No newline at end of file +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index d69cba9c3..3451d321d 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -97,8 +97,8 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons return matrix; } -RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window, Core::System& system) - : VideoCore::RendererBase{window}, system{system} {} +RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) + : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system} {} RendererOpenGL::~RendererOpenGL() = default; @@ -265,7 +265,7 @@ void RendererOpenGL::CreateRasterizer() { } // Initialize sRGB Usage OpenGLState::ClearsRGBUsed(); - rasterizer = std::make_unique<RasterizerOpenGL>(system, screen_info); + rasterizer = std::make_unique<RasterizerOpenGL>(system, emu_window, screen_info); } void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 6cbf9d2cb..4aebf2321 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -45,7 +45,7 @@ struct ScreenInfo { class RendererOpenGL : public VideoCore::RendererBase { public: - explicit RendererOpenGL(Core::Frontend::EmuWindow& window, Core::System& system); + explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system); ~RendererOpenGL() override; /// Swap buffers (render frame) @@ -77,6 +77,7 @@ private: void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture); + Core::Frontend::EmuWindow& emu_window; Core::System& system; OpenGLState state; 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 165c2b41b..e6a010a7d 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -146,12 +146,25 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } + case OpCode::Id::LD: case OpCode::Id::LDG: { + const auto type = [instr, &opcode]() -> Tegra::Shader::UniformType { + switch (opcode->get().GetId()) { + case OpCode::Id::LD: + UNIMPLEMENTED_IF_MSG(!instr.generic.extended, "Unextended LD is not implemented"); + return instr.generic.type; + case OpCode::Id::LDG: + return instr.ldg.type; + default: + UNREACHABLE(); + return {}; + } + }(); + const auto [real_address_base, base_address, descriptor] = - TrackAndGetGlobalMemory(bb, GetRegister(instr.gpr8), - static_cast<u32>(instr.ldg.immediate_offset.Value()), false); + TrackAndGetGlobalMemory(bb, instr, false); - const u32 count = GetUniformTypeElementsCount(instr.ldg.type); + const u32 count = GetUniformTypeElementsCount(type); for (u32 i = 0; i < count; ++i) { const Node it_offset = Immediate(i * 4); const Node real_address = @@ -165,28 +178,6 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } - case OpCode::Id::STG: { - const auto [real_address_base, base_address, descriptor] = - TrackAndGetGlobalMemory(bb, GetRegister(instr.gpr8), - static_cast<u32>(instr.stg.immediate_offset.Value()), true); - - // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} - SetTemporal(bb, 0, real_address_base); - - const u32 count = GetUniformTypeElementsCount(instr.stg.type); - for (u32 i = 0; i < count; ++i) { - SetTemporal(bb, i + 1, GetRegister(instr.gpr0.Value() + i)); - } - for (u32 i = 0; i < count; ++i) { - const Node it_offset = Immediate(i * 4); - const Node real_address = - Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); - const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor)); - - bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1))); - } - break; - } case OpCode::Id::ST_A: { UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, "Indirect attribute loads are not supported"); @@ -242,6 +233,41 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } + case OpCode::Id::ST: + case OpCode::Id::STG: { + const auto type = [instr, &opcode]() -> Tegra::Shader::UniformType { + switch (opcode->get().GetId()) { + case OpCode::Id::ST: + UNIMPLEMENTED_IF_MSG(!instr.generic.extended, "Unextended ST is not implemented"); + return instr.generic.type; + case OpCode::Id::STG: + return instr.stg.type; + default: + UNREACHABLE(); + return {}; + } + }(); + + const auto [real_address_base, base_address, descriptor] = + TrackAndGetGlobalMemory(bb, instr, true); + + // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} + SetTemporal(bb, 0, real_address_base); + + const u32 count = GetUniformTypeElementsCount(type); + for (u32 i = 0; i < count; ++i) { + SetTemporal(bb, i + 1, GetRegister(instr.gpr0.Value() + i)); + } + for (u32 i = 0; i < count; ++i) { + const Node it_offset = Immediate(i * 4); + const Node real_address = + Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); + const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor)); + + bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1))); + } + break; + } case OpCode::Id::AL2P: { // Ignore al2p.direction since we don't care about it. @@ -265,9 +291,11 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, - Node addr_register, - u32 immediate_offset, + Instruction instr, bool is_write) { + const auto addr_register{GetRegister(instr.gmem.gpr)}; + const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; + const Node base_address{ TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))}; const auto cbuf = std::get_if<CbufNode>(base_address); diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index fa17c45b5..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" 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 153ad1fd0..8a6ee5cf5 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -39,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) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 0bf124252..35f72bddb 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -663,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 @@ -818,10 +818,8 @@ private: 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, - u32 immediate_offset, - bool is_write); + std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory( + NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write); template <typename... T> Node Operation(OperationCode code, const T*... operands) { diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 7e883991a..3ea7b55d0 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -155,6 +155,10 @@ target_compile_definitions(yuzu PRIVATE # Use QStringBuilder for string concatenation to reduce # the overall number of temporary strings created. -DQT_USE_QSTRINGBUILDER + + # Disable implicit conversions from/to C strings + -DQT_NO_CAST_FROM_ASCII + -DQT_NO_CAST_TO_ASCII ) if (YUZU_ENABLE_COMPATIBILITY_REPORTING) diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp index 106dde9e2..08ed57355 100644 --- a/src/yuzu/applets/error.cpp +++ b/src/yuzu/applets/error.cpp @@ -29,11 +29,13 @@ void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, std::function<void()> finished) const { this->callback = std::move(finished); + + const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); emit MainWindowDisplayError( tr("An error occured on %1 at %2.\nPlease try again or contact the " "developer of the software.\n\nError Code: %3-%4 (0x%5)") - .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("dddd, MMMM d, yyyy")) - .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("h:mm:ss A")) + .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) + .arg(date_time.toString(QStringLiteral("h:mm:ss A"))) .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) .arg(error.description, 4, 10, QChar::fromLatin1('0')) .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index f3eb29b25..5223ec977 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -18,23 +18,30 @@ QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( : parameters(std::move(parameters)) {} QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { - if (input.size() > parameters.max_length) + if (input.size() > static_cast<s64>(parameters.max_length)) { return Invalid; - if (parameters.disable_space && input.contains(' ')) + } + if (parameters.disable_space && input.contains(QLatin1Char{' '})) { return Invalid; - if (parameters.disable_address && input.contains('@')) + } + if (parameters.disable_address && input.contains(QLatin1Char{'@'})) { return Invalid; - if (parameters.disable_percent && input.contains('%')) + } + if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) { return Invalid; - if (parameters.disable_slash && (input.contains('/') || input.contains('\\'))) + } + if (parameters.disable_slash && + (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) { return Invalid; + } if (parameters.disable_number && std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { return Invalid; } - if (parameters.disable_download_code && - std::any_of(input.begin(), input.end(), [](QChar c) { return c == 'O' || c == 'I'; })) { + if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) { + return c == QLatin1Char{'O'} || c == QLatin1Char{'I'}; + })) { return Invalid; } @@ -142,7 +149,7 @@ void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message, void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) { // Acquire the HLE mutex std::lock_guard lock{HLE::g_hle_lock}; - text_output(text); + text_output(std::move(text)); } void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index c63720ba4..78c5a042b 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -6,7 +6,6 @@ #include <QDialog> #include <QValidator> -#include "common/assert.h" #include "core/frontend/applets/software_keyboard.h" class GMainWindow; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index c2783d684..eeee603d1 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -91,25 +91,25 @@ void EmuThread::run() { class GGLContext : public Core::Frontend::GraphicsContext { public: - explicit GGLContext(QOpenGLContext* shared_context) - : context{std::make_unique<QOpenGLContext>(shared_context)} { - surface.setFormat(shared_context->format()); - surface.create(); + explicit GGLContext(QOpenGLContext* shared_context) : shared_context{shared_context} { + context.setFormat(shared_context->format()); + context.setShareContext(shared_context); + context.create(); } void MakeCurrent() override { - context->makeCurrent(&surface); + context.makeCurrent(shared_context->surface()); } void DoneCurrent() override { - context->doneCurrent(); + context.doneCurrent(); } void SwapBuffers() override {} private: - std::unique_ptr<QOpenGLContext> context; - QOffscreenSurface surface; + QOpenGLContext* shared_context; + QOpenGLContext context; }; // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL @@ -358,7 +358,7 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { } std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { - return std::make_unique<GGLContext>(shared_context.get()); + return std::make_unique<GGLContext>(context.get()); } void GRenderWindow::InitRenderTarget() { diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index d28826c67..db27da23e 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -11,6 +11,7 @@ #include "core/hle/service/hid/controllers/npad.h" #include "input_common/main.h" #include "yuzu/configuration/config.h" +#include "yuzu/ui_settings.h" Config::Config() { // TODO: Don't hardcode the path; let the frontend decide where to put the config files. @@ -206,25 +207,28 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default }; // This shouldn't have anything except static initializers (no functions). So -// QKeySequnce(...).toString() is NOT ALLOWED HERE. +// QKeySequence(...).toString() is NOT ALLOWED HERE. // This must be in alphabetical order according to action name as it must have the same order as // UISetting::values.shortcuts, which is alphabetically ordered. -const std::array<UISettings::Shortcut, 15> Config::default_hotkeys{ - {{"Capture Screenshot", "Main Window", {"Ctrl+P", Qt::ApplicationShortcut}}, - {"Continue/Pause Emulation", "Main Window", {"F4", Qt::WindowShortcut}}, - {"Decrease Speed Limit", "Main Window", {"-", Qt::ApplicationShortcut}}, - {"Exit yuzu", "Main Window", {"Ctrl+Q", Qt::WindowShortcut}}, - {"Exit Fullscreen", "Main Window", {"Esc", Qt::WindowShortcut}}, - {"Fullscreen", "Main Window", {"F11", Qt::WindowShortcut}}, - {"Increase Speed Limit", "Main Window", {"+", Qt::ApplicationShortcut}}, - {"Load Amiibo", "Main Window", {"F2", Qt::ApplicationShortcut}}, - {"Load File", "Main Window", {"Ctrl+O", Qt::WindowShortcut}}, - {"Restart Emulation", "Main Window", {"F6", Qt::WindowShortcut}}, - {"Stop Emulation", "Main Window", {"F5", Qt::WindowShortcut}}, - {"Toggle Filter Bar", "Main Window", {"Ctrl+F", Qt::WindowShortcut}}, - {"Toggle Speed Limit", "Main Window", {"Ctrl+Z", Qt::ApplicationShortcut}}, - {"Toggle Status Bar", "Main Window", {"Ctrl+S", Qt::WindowShortcut}}, - {"Change Docked Mode", "Main Window", {"F10", Qt::ApplicationShortcut}}}}; +// clang-format off +const std::array<UISettings::Shortcut, 15> default_hotkeys{{ + {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::ApplicationShortcut}}, + {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, + {QStringLiteral("Decrease Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("-"), Qt::ApplicationShortcut}}, + {QStringLiteral("Exit yuzu"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), Qt::WindowShortcut}}, + {QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), Qt::WindowShortcut}}, + {QStringLiteral("Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("F11"), Qt::WindowShortcut}}, + {QStringLiteral("Increase Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("+"), Qt::ApplicationShortcut}}, + {QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::ApplicationShortcut}}, + {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WindowShortcut}}, + {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, + {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, + {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, + {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}}, + {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}}, + {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, +}}; +// clang-format on void Config::ReadPlayerValues() { for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { @@ -370,14 +374,21 @@ void Config::ReadMouseValues() { } void Config::ReadTouchscreenValues() { - Settings::values.touchscreen.enabled = ReadSetting("touchscreen_enabled", true).toBool(); + Settings::values.touchscreen.enabled = + ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); Settings::values.touchscreen.device = - ReadSetting("touchscreen_device", "engine:emu_window").toString().toStdString(); + ReadSetting(QStringLiteral("touchscreen_device"), QStringLiteral("engine:emu_window")) + .toString() + .toStdString(); - Settings::values.touchscreen.finger = ReadSetting("touchscreen_finger", 0).toUInt(); - 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(); + Settings::values.touchscreen.finger = + ReadSetting(QStringLiteral("touchscreen_finger"), 0).toUInt(); + Settings::values.touchscreen.rotation_angle = + ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt(); + Settings::values.touchscreen.diameter_x = + ReadSetting(QStringLiteral("touchscreen_diameter_x"), 15).toUInt(); + Settings::values.touchscreen.diameter_y = + ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); } void Config::ApplyDefaultProfileIfInputInvalid() { @@ -541,8 +552,8 @@ void Config::ReadRendererValues() { void Config::ReadShortcutValues() { qt_config->beginGroup(QStringLiteral("Shortcuts")); - for (auto [name, group, shortcut] : default_hotkeys) { - auto [keyseq, context] = shortcut; + for (const auto& [name, group, shortcut] : default_hotkeys) { + const auto& [keyseq, context] = shortcut; qt_config->beginGroup(group); qt_config->beginGroup(name); UISettings::values.shortcuts.push_back( @@ -591,7 +602,8 @@ void Config::ReadUIValues() { qt_config->beginGroup(QStringLiteral("UI")); UISettings::values.theme = - ReadSetting(QStringLiteral("theme"), UISettings::themes[0].second).toString(); + ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second)) + .toString(); UISettings::values.enable_discord_presence = ReadSetting(QStringLiteral("enable_discord_presence"), true).toBool(); UISettings::values.screenshot_resolution_factor = @@ -626,7 +638,7 @@ void Config::ReadUIValues() { } void Config::ReadUIGamelistValues() { - qt_config->beginGroup("UIGameList"); + qt_config->beginGroup(QStringLiteral("UIGameList")); UISettings::values.show_unknown = ReadSetting(QStringLiteral("show_unknown"), true).toBool(); UISettings::values.show_add_ons = ReadSetting(QStringLiteral("show_add_ons"), true).toBool(); @@ -723,7 +735,7 @@ void Config::SavePlayerValues() { } void Config::SaveDebugValues() { - WriteSetting("debug_pad_enabled", Settings::values.debug_pad_enabled, false); + WriteSetting(QStringLiteral("debug_pad_enabled"), Settings::values.debug_pad_enabled, false); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); WriteSetting(QStringLiteral("debug_pad_") + @@ -924,7 +936,7 @@ void Config::SaveShortcutValues() { // 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++) { - const 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); @@ -961,7 +973,8 @@ void Config::SaveSystemValues() { void Config::SaveUIValues() { qt_config->beginGroup(QStringLiteral("UI")); - WriteSetting(QStringLiteral("theme"), UISettings::values.theme, UISettings::themes[0].second); + WriteSetting(QStringLiteral("theme"), UISettings::values.theme, + QString::fromUtf8(UISettings::themes[0].second)); WriteSetting(QStringLiteral("enable_discord_presence"), UISettings::values.enable_discord_presence, true); WriteSetting(QStringLiteral("screenshot_resolution_factor"), diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index b62a480ee..6b523ecdd 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -9,7 +9,6 @@ #include <string> #include <QVariant> #include "core/settings.h" -#include "yuzu/ui_settings.h" class QSettings; @@ -82,8 +81,6 @@ private: void WriteSetting(const QString& name, const QVariant& value); void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); - static const std::array<UISettings::Shortcut, 15> default_hotkeys; - std::unique_ptr<QSettings> qt_config; std::string qt_config_loc; }; diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 32c05b797..8086f9d6b 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -25,9 +25,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) adjustSize(); ui->selectorList->setCurrentRow(0); - - // Synchronise lists upon initialisation - ui->hotkeysTab->EmitHotkeysChanged(); } ConfigureDialog::~ConfigureDialog() = default; diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index a7a8752e5..9fb970c21 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -31,22 +31,6 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) ConfigureHotkeys::~ConfigureHotkeys() = default; -void ConfigureHotkeys::EmitHotkeysChanged() { - emit HotkeysChanged(GetUsedKeyList()); -} - -QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() const { - QList<QKeySequence> list; - for (int r = 0; r < model->rowCount(); r++) { - const QStandardItem* parent = model->item(r, 0); - for (int r2 = 0; r2 < parent->rowCount(); r2++) { - const QStandardItem* keyseq = parent->child(r2, 1); - list << QKeySequence::fromString(keyseq->text(), QKeySequence::NativeText); - } - } - return list; -} - void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { for (const auto& group : registry.hotkey_groups) { auto* parent_item = new QStandardItem(group.first); @@ -83,16 +67,29 @@ void ConfigureHotkeys::Configure(QModelIndex index) { } if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { - QMessageBox::critical(this, tr("Error in inputted key"), - tr("You're using a key that's already bound.")); + QMessageBox::warning(this, tr("Conflicting Key Sequence"), + tr("The entered key sequence is already assigned to another hotkey.")); } else { model->setData(index, key_sequence.toString(QKeySequence::NativeText)); - EmitHotkeysChanged(); } } bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { - return GetUsedKeyList().contains(key_sequence); + for (int r = 0; r < model->rowCount(); r++) { + const QStandardItem* const parent = model->item(r, 0); + + for (int r2 = 0; r2 < parent->rowCount(); r2++) { + const QStandardItem* const key_seq_item = parent->child(r2, 1); + const auto key_seq_str = key_seq_item->text(); + const auto key_seq = QKeySequence::fromString(key_seq_str, QKeySequence::NativeText); + + if (key_sequence == key_seq) { + return true; + } + } + } + + return false; } void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { @@ -114,7 +111,6 @@ void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { } registry.SaveHotkeys(); - Settings::Apply(); } void ConfigureHotkeys::retranslateUi() { diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h index 73fb8a175..e77d73c35 100644 --- a/src/yuzu/configuration/configure_hotkeys.h +++ b/src/yuzu/configuration/configure_hotkeys.h @@ -24,8 +24,6 @@ public: void applyConfiguration(HotkeyRegistry& registry); void retranslateUi(); - void EmitHotkeysChanged(); - /** * Populates the hotkey list widget using data from the provided registry. * Called everytime the Configure dialog is opened. @@ -33,13 +31,9 @@ public: */ void Populate(const HotkeyRegistry& registry); -signals: - void HotkeysChanged(QList<QKeySequence> new_key_list); - private: void Configure(QModelIndex index); bool IsUsedKey(QKeySequence key_sequence) const; - QList<QKeySequence> GetUsedKeyList() const; std::unique_ptr<Ui::ConfigureHotkeys> ui; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a59abf6e8..cef2cc1ae 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -281,7 +281,7 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) { NXInputWebEngineView web_browser_view(this); - // Scope to contain the QProgressDialog for initalization + // Scope to contain the QProgressDialog for initialization { QProgressDialog progress(this); progress.setMinimumDuration(200); @@ -301,7 +301,7 @@ void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view QWebEngineScript nx_shim; nx_shim.setSourceCode(GetNXShimInjectionScript()); nx_shim.setWorldId(QWebEngineScript::MainWorld); - nx_shim.setName("nx_inject.js"); + nx_shim.setName(QStringLiteral("nx_inject.js")); nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation); nx_shim.setRunsOnSubFrames(true); web_browser_view.page()->profile()->scripts()->insert(nx_shim); @@ -347,7 +347,7 @@ void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view const auto fire_js_keypress = [&web_browser_view](u32 key_code) { web_browser_view.page()->runJavaScript( QStringLiteral("document.dispatchEvent(new KeyboardEvent('keydown', {'key': %1}));") - .arg(QString::fromStdString(std::to_string(key_code)))); + .arg(key_code)); }; QMessageBox::information( @@ -468,7 +468,7 @@ void GMainWindow::InitializeWidgets() { statusBar()->addPermanentWidget(label, 0); } statusBar()->setVisible(true); - setStyleSheet("QStatusBar::item{border: none;}"); + setStyleSheet(QStringLiteral("QStatusBar::item{border: none;}")); } void GMainWindow::InitializeDebugWidgets() { @@ -518,58 +518,67 @@ void GMainWindow::InitializeRecentFileMenuActions() { void GMainWindow::InitializeHotkeys() { hotkey_registry.LoadHotkeys(); - ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Load File")); + const QString main_window = QStringLiteral("Main Window"); + const QString load_file = QStringLiteral("Load File"); + const QString exit_yuzu = QStringLiteral("Exit yuzu"); + const QString stop_emulation = QStringLiteral("Stop Emulation"); + const QString toggle_filter_bar = QStringLiteral("Toggle Filter Bar"); + const QString toggle_status_bar = QStringLiteral("Toggle Status Bar"); + const QString fullscreen = QStringLiteral("Fullscreen"); + + ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file)); ui.action_Load_File->setShortcutContext( - hotkey_registry.GetShortcutContext("Main Window", "Load File")); + hotkey_registry.GetShortcutContext(main_window, load_file)); - ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Exit yuzu")); - ui.action_Exit->setShortcutContext( - hotkey_registry.GetShortcutContext("Main Window", "Exit yuzu")); + ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence(main_window, exit_yuzu)); + ui.action_Exit->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, exit_yuzu)); - ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Stop Emulation")); + ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence(main_window, stop_emulation)); ui.action_Stop->setShortcutContext( - hotkey_registry.GetShortcutContext("Main Window", "Stop Emulation")); + hotkey_registry.GetShortcutContext(main_window, stop_emulation)); ui.action_Show_Filter_Bar->setShortcut( - hotkey_registry.GetKeySequence("Main Window", "Toggle Filter Bar")); + hotkey_registry.GetKeySequence(main_window, toggle_filter_bar)); ui.action_Show_Filter_Bar->setShortcutContext( - hotkey_registry.GetShortcutContext("Main Window", "Toggle Filter Bar")); + hotkey_registry.GetShortcutContext(main_window, toggle_filter_bar)); ui.action_Show_Status_Bar->setShortcut( - hotkey_registry.GetKeySequence("Main Window", "Toggle Status Bar")); + hotkey_registry.GetKeySequence(main_window, toggle_status_bar)); ui.action_Show_Status_Bar->setShortcutContext( - hotkey_registry.GetShortcutContext("Main Window", "Toggle Status Bar")); - - connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated, - this, &GMainWindow::OnMenuLoadFile); - connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause Emulation", this), - &QShortcut::activated, this, [&] { - if (emulation_running) { - if (emu_thread->IsRunning()) { - OnPauseGame(); - } else { - OnStartGame(); - } + hotkey_registry.GetShortcutContext(main_window, toggle_status_bar)); + + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this), + &QShortcut::activated, this, &GMainWindow::OnMenuLoadFile); + connect( + hotkey_registry.GetHotkey(main_window, QStringLiteral("Continue/Pause Emulation"), this), + &QShortcut::activated, this, [&] { + if (emulation_running) { + if (emu_thread->IsRunning()) { + OnPauseGame(); + } else { + OnStartGame(); } - }); - connect(hotkey_registry.GetHotkey("Main Window", "Restart Emulation", this), + } + }); + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Restart Emulation"), this), &QShortcut::activated, this, [this] { - if (!Core::System::GetInstance().IsPoweredOn()) + if (!Core::System::GetInstance().IsPoweredOn()) { return; - BootGame(QString(game_path)); + } + BootGame(game_path); }); - connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), + connect(hotkey_registry.GetHotkey(main_window, fullscreen, render_window), &QShortcut::activated, ui.action_Fullscreen, &QAction::trigger); - connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), + connect(hotkey_registry.GetHotkey(main_window, fullscreen, render_window), &QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger); - connect(hotkey_registry.GetHotkey("Main Window", "Exit Fullscreen", this), + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Exit Fullscreen"), this), &QShortcut::activated, this, [&] { if (emulation_running) { ui.action_Fullscreen->setChecked(false); ToggleFullscreen(); } }); - connect(hotkey_registry.GetHotkey("Main Window", "Toggle Speed Limit", this), + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this), &QShortcut::activated, this, [&] { Settings::values.use_frame_limit = !Settings::values.use_frame_limit; UpdateStatusBar(); @@ -578,33 +587,33 @@ void GMainWindow::InitializeHotkeys() { // MSVC occurs and we make it a requirement (see: // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html) static constexpr u16 SPEED_LIMIT_STEP = 5; - connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), &QShortcut::activated, this, [&] { if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { Settings::values.frame_limit += SPEED_LIMIT_STEP; UpdateStatusBar(); } }); - connect(hotkey_registry.GetHotkey("Main Window", "Decrease Speed Limit", this), + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), &QShortcut::activated, this, [&] { if (Settings::values.frame_limit > SPEED_LIMIT_STEP) { Settings::values.frame_limit -= SPEED_LIMIT_STEP; UpdateStatusBar(); } }); - connect(hotkey_registry.GetHotkey("Main Window", "Load Amiibo", this), &QShortcut::activated, - this, [&] { + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load Amiibo"), this), + &QShortcut::activated, this, [&] { if (ui.action_Load_Amiibo->isEnabled()) { OnLoadAmiibo(); } }); - connect(hotkey_registry.GetHotkey("Main Window", "Capture Screenshot", this), + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Capture Screenshot"), this), &QShortcut::activated, this, [&] { if (emu_thread->IsRunning()) { OnCaptureScreenshot(); } }); - connect(hotkey_registry.GetHotkey("Main Window", "Change Docked Mode", this), + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this), &QShortcut::activated, this, [&] { Settings::values.use_docked_mode = !Settings::values.use_docked_mode; OnDockedModeChanged(!Settings::values.use_docked_mode, @@ -705,7 +714,9 @@ void GMainWindow::ConnectMenuEvents() { // Fullscreen ui.action_Fullscreen->setShortcut( - hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key()); + hotkey_registry + .GetHotkey(QStringLiteral("Main Window"), QStringLiteral("Fullscreen"), this) + ->key()); connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); // Movie @@ -742,25 +753,33 @@ void GMainWindow::OnDisplayTitleBars(bool show) { QStringList GMainWindow::GetUnsupportedGLExtensions() { QStringList unsupported_ext; - if (!GLAD_GL_ARB_direct_state_access) - unsupported_ext.append("ARB_direct_state_access"); - if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) - unsupported_ext.append("ARB_vertex_type_10f_11f_11f_rev"); - if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) - unsupported_ext.append("ARB_texture_mirror_clamp_to_edge"); - if (!GLAD_GL_ARB_multi_bind) - unsupported_ext.append("ARB_multi_bind"); + if (!GLAD_GL_ARB_direct_state_access) { + unsupported_ext.append(QStringLiteral("ARB_direct_state_access")); + } + if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) { + unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev")); + } + if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) { + unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge")); + } + if (!GLAD_GL_ARB_multi_bind) { + unsupported_ext.append(QStringLiteral("ARB_multi_bind")); + } // Extensions required to support some texture formats. - if (!GLAD_GL_EXT_texture_compression_s3tc) - unsupported_ext.append("EXT_texture_compression_s3tc"); - if (!GLAD_GL_ARB_texture_compression_rgtc) - unsupported_ext.append("ARB_texture_compression_rgtc"); - if (!GLAD_GL_ARB_depth_buffer_float) - unsupported_ext.append("ARB_depth_buffer_float"); - - for (const QString& ext : unsupported_ext) + if (!GLAD_GL_EXT_texture_compression_s3tc) { + unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc")); + } + if (!GLAD_GL_ARB_texture_compression_rgtc) { + unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc")); + } + if (!GLAD_GL_ARB_depth_buffer_float) { + unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float")); + } + + for (const QString& ext : unsupported_ext) { LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString()); + } return unsupported_ext; } @@ -782,13 +801,13 @@ bool GMainWindow::LoadROM(const QString& filename) { } } - QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions(); + const QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions(); if (!unsupported_gl_extensions.empty()) { QMessageBox::critical(this, tr("Error while initializing OpenGL Core!"), tr("Your GPU may not support one or more required OpenGL" "extensions. Please ensure you have the latest graphics " "driver.<br><br>Unsupported extensions:<br>") + - unsupported_gl_extensions.join("<br>")); + unsupported_gl_extensions.join(QStringLiteral("<br>"))); return false; } @@ -1007,7 +1026,7 @@ void GMainWindow::UpdateRecentFiles() { std::min(UISettings::values.recent_files.size(), max_recent_files_item); for (int i = 0; i < num_recent_files; i++) { - const QString text = QString("&%1. %2").arg(i + 1).arg( + const QString text = QStringLiteral("&%1. %2").arg(i + 1).arg( QFileInfo(UISettings::values.recent_files[i]).fileName()); actions_recent_files[i]->setText(text); actions_recent_files[i]->setData(UISettings::values.recent_files[i]); @@ -1029,10 +1048,10 @@ void GMainWindow::OnGameListLoadFile(QString game_path) { void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target) { std::string path; - std::string open_target; + QString open_target; switch (target) { case GameListOpenTarget::SaveData: { - open_target = "Save Data"; + open_target = tr("Save Data"); const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); ASSERT(program_id != 0); @@ -1069,7 +1088,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target break; } case GameListOpenTarget::ModData: { - open_target = "Mod Data"; + open_target = tr("Mod Data"); const auto load_dir = FileUtil::GetUserPath(FileUtil::UserPath::LoadDir); path = fmt::format("{}{:016X}", load_dir, program_id); break; @@ -1079,27 +1098,26 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target } const QString qpath = QString::fromStdString(path); - const QDir dir(qpath); if (!dir.exists()) { - QMessageBox::warning(this, - tr("Error Opening %1 Folder").arg(QString::fromStdString(open_target)), + QMessageBox::warning(this, tr("Error Opening %1 Folder").arg(open_target), tr("Folder does not exist!")); return; } - LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target, program_id); + LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target.toStdString(), + program_id); QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); } void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { ASSERT(program_id != 0); + const QString shader_dir = + QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)); const QString tranferable_shader_cache_folder_path = - QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) + "opengl" + - DIR_SEP + "transferable"; - + shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); const QString transferable_shader_cache_file_path = - tranferable_shader_cache_folder_path + DIR_SEP + + tranferable_shader_cache_folder_path + QDir::separator() + QString::fromStdString(fmt::format("{:016X}.bin", program_id)); if (!QFile::exists(transferable_shader_cache_file_path)) { @@ -1216,20 +1234,21 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa return; } - bool ok; + bool ok = false; + const QStringList selections{tr("Full"), tr("Skeleton")}; const auto res = QInputDialog::getItem( this, tr("Select RomFS Dump Mode"), tr("Please select the how you would like the RomFS dumped.<br>Full will copy all of the " "files into the new directory while <br>skeleton will only create the directory " "structure."), - {"Full", "Skeleton"}, 0, false, &ok); + selections, 0, false, &ok); if (!ok) { failed(); vfs->DeleteDirectory(path); return; } - const auto full = res == "Full"; + const auto full = res == selections.constFirst(); const auto entry_size = CalculateRomFSEntrySize(extracted, full); QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, @@ -1259,10 +1278,11 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); QString directory; - if (it != compatibility_list.end()) + if (it != compatibility_list.end()) { directory = it->second.second; + } - QDesktopServices::openUrl(QUrl("https://yuzu-emu.org/game/" + directory)); + QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory)); } void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { @@ -1293,7 +1313,9 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { void GMainWindow::OnMenuLoadFile() { const QString extensions = - QString("*.").append(GameList::supported_file_extensions.join(" *.")).append(" main"); + QStringLiteral("*.") + .append(GameList::supported_file_extensions.join(QStringLiteral(" *."))) + .append(QStringLiteral(" main")); const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)", "%1 is an identifier for the Switch executable file extensions.") .arg(extensions); @@ -1317,9 +1339,9 @@ void GMainWindow::OnMenuLoadFolder() { } const QDir dir{dir_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) { - BootGame(dir.path() + DIR_SEP + matching_main[0]); + BootGame(dir.path() + QDir::separator() + matching_main[0]); } else { QMessageBox::warning(this, tr("Invalid Directory Selected"), tr("The directory you have selected does not contain a 'main' file.")); @@ -1391,11 +1413,10 @@ void GMainWindow::OnMenuInstallToNAND() { QMessageBox::Yes; }; - if (filename.endsWith("xci", Qt::CaseInsensitive) || - filename.endsWith("nsp", Qt::CaseInsensitive)) { - + if (filename.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) || + filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { std::shared_ptr<FileSys::NSP> nsp; - if (filename.endsWith("nsp", Qt::CaseInsensitive)) { + if (filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { nsp = std::make_shared<FileSys::NSP>( vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); if (nsp->IsExtractedType()) @@ -1690,9 +1711,9 @@ void GMainWindow::OnConfigure() { } void GMainWindow::OnLoadAmiibo() { - const QString extensions{"*.bin"}; + const QString extensions{QStringLiteral("*.bin")}; const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions); - const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), "", file_filter); + const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), {}, file_filter); if (filename.isEmpty()) { return; @@ -1754,7 +1775,7 @@ void GMainWindow::OnCaptureScreenshot() { QFileDialog png_dialog(this, tr("Capture Screenshot"), UISettings::values.screenshot_path, tr("PNG Image (*.png)")); png_dialog.setAcceptMode(QFileDialog::AcceptSave); - png_dialog.setDefaultSuffix("png"); + png_dialog.setDefaultSuffix(QStringLiteral("png")); if (png_dialog.exec()) { const QString path = png_dialog.selectedFiles().first(); if (!path.isEmpty()) { @@ -1817,17 +1838,17 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det "data, or other bugs."); switch (result) { case Core::System::ResultStatus::ErrorSystemFiles: { - QString message = "yuzu was unable to locate a Switch system archive"; + QString message = tr("yuzu was unable to locate a Switch system archive"); if (!details.empty()) { - message.append(tr(": %1. ").arg(details.c_str())); + message.append(tr(": %1. ").arg(QString::fromStdString(details))); } else { - message.append(". "); + message.append(tr(". ")); } message.append(common_message); answer = QMessageBox::question(this, tr("System Archive Not Found"), message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - status_message = "System Archive Missing"; + status_message = tr("System Archive Missing"); break; } @@ -1836,7 +1857,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det message.append(common_message); answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - status_message = "Shared Font Missing"; + status_message = tr("Shared Font Missing"); break; } @@ -1852,7 +1873,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det "Continuing emulation may result in crashes, corrupted save data, or other " "bugs."), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - status_message = "Fatal Error encountered"; + status_message = tr("Fatal Error encountered"); break; } @@ -1903,18 +1924,19 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { }; QString errors; - - if (!pdm.HasFuses()) + if (!pdm.HasFuses()) { errors += tr("- Missing fuses - Cannot derive SBK\n"); - if (!pdm.HasBoot0()) + } + if (!pdm.HasBoot0()) { errors += tr("- Missing BOOT0 - Cannot derive master keys\n"); - if (!pdm.HasPackage2()) + } + if (!pdm.HasPackage2()) { errors += tr("- Missing BCPKG2-1-Normal-Main - Cannot derive general keys\n"); - if (!pdm.HasProdInfo()) + } + if (!pdm.HasProdInfo()) { errors += tr("- Missing PRODINFO - Cannot derive title keys\n"); - + } if (!errors.isEmpty()) { - QMessageBox::warning( this, tr("Warning Missing Derivation Components"), tr("The following are missing from your configuration that may hinder key " @@ -1964,13 +1986,15 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv std::vector<u64> romfs_tids; romfs_tids.push_back(program_id); - for (const auto& entry : dlc_match) + for (const auto& entry : dlc_match) { romfs_tids.push_back(entry.title_id); + } if (romfs_tids.size() > 1) { - QStringList list{"Base"}; - for (std::size_t i = 1; i < romfs_tids.size(); ++i) + QStringList list{QStringLiteral("Base")}; + for (std::size_t i = 1; i < romfs_tids.size(); ++i) { list.push_back(QStringLiteral("DLC %1").arg(romfs_tids[i] & 0x7FF)); + } bool ok; const auto res = QInputDialog::getItem( @@ -2082,26 +2106,32 @@ void GMainWindow::filterBarSetChecked(bool state) { } void GMainWindow::UpdateUITheme() { + const QString default_icons = QStringLiteral(":/icons/default"); + const QString& current_theme = UISettings::values.theme; + const bool is_default_theme = current_theme == QString::fromUtf8(UISettings::themes[0].second); QStringList theme_paths(default_theme_paths); - if (UISettings::values.theme != UISettings::themes[0].second && - !UISettings::values.theme.isEmpty()) { - const QString theme_uri(":" + UISettings::values.theme + "/style.qss"); + + if (is_default_theme || current_theme.isEmpty()) { + qApp->setStyleSheet({}); + setStyleSheet({}); + theme_paths.append(default_icons); + QIcon::setThemeName(default_icons); + } else { + const QString theme_uri(QLatin1Char{':'} + current_theme + QStringLiteral("/style.qss")); QFile f(theme_uri); if (f.open(QFile::ReadOnly | QFile::Text)) { QTextStream ts(&f); qApp->setStyleSheet(ts.readAll()); - GMainWindow::setStyleSheet(ts.readAll()); + setStyleSheet(ts.readAll()); } else { LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found"); } - theme_paths.append(QStringList{":/icons/default", ":/icons/" + UISettings::values.theme}); - QIcon::setThemeName(":/icons/" + UISettings::values.theme); - } else { - qApp->setStyleSheet(""); - GMainWindow::setStyleSheet(""); - theme_paths.append(QStringList{":/icons/default"}); - QIcon::setThemeName(":/icons/default"); + + const QString theme_name = QStringLiteral(":/icons/") + current_theme; + theme_paths.append({default_icons, theme_name}); + QIcon::setThemeName(theme_name); } + QIcon::setThemeSearchPaths(theme_paths); emit UpdateThemedIcons(); } @@ -2129,8 +2159,8 @@ int main(int argc, char* argv[]) { SCOPE_EXIT({ MicroProfileShutdown(); }); // Init settings params - QCoreApplication::setOrganizationName("yuzu team"); - QCoreApplication::setApplicationName("yuzu"); + QCoreApplication::setOrganizationName(QStringLiteral("yuzu team")); + QCoreApplication::setApplicationName(QStringLiteral("yuzu")); // Enables the core to make the qt created contexts current on std::threads QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); diff --git a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp index d3edf6ec3..bb5f74ec4 100644 --- a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp +++ b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp @@ -9,16 +9,19 @@ SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) { setWindowTitle(tr("Enter a hotkey")); - auto* layout = new QVBoxLayout(this); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + key_sequence = new QKeySequenceEdit; - layout->addWidget(key_sequence); - auto* buttons = - new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); + + auto* const buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttons->setCenterButtons(true); + + auto* const layout = new QVBoxLayout(this); + layout->addWidget(key_sequence); layout->addWidget(buttons); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); } SequenceDialog::~SequenceDialog() = default; |