From 290e127a4f8cc0afab6a4fb4dd7f6410132bdf06 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 15 Feb 2025 03:07:22 -0300 Subject: [PATCH 01/29] More fixes to make the translation work (#2439) * more fixes to make the translation work * If size is disabled, it will not appear on the patches screen * Update game_install_dialog.h --- src/qt_gui/cheats_patches.cpp | 8 +++++--- src/qt_gui/game_install_dialog.h | 1 + src/qt_gui/settings_dialog.cpp | 10 +++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index 866ab3ca0..e9db88381 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -91,9 +91,11 @@ void CheatsPatches::setupUI() { gameVersionLabel->setAlignment(Qt::AlignLeft); gameInfoLayout->addWidget(gameVersionLabel); - QLabel* gameSizeLabel = new QLabel(tr("Size: ") + m_gameSize); - gameSizeLabel->setAlignment(Qt::AlignLeft); - gameInfoLayout->addWidget(gameSizeLabel); + if (m_gameSize.left(4) != "0.00") { + QLabel* gameSizeLabel = new QLabel(tr("Size: ") + m_gameSize); + gameSizeLabel->setAlignment(Qt::AlignLeft); + gameInfoLayout->addWidget(gameSizeLabel); + } // Add a text area for instructions and 'Patch' descriptions instructionsTextEdit = new QTextEdit(); diff --git a/src/qt_gui/game_install_dialog.h b/src/qt_gui/game_install_dialog.h index 0a4e29357..938f0e1f3 100644 --- a/src/qt_gui/game_install_dialog.h +++ b/src/qt_gui/game_install_dialog.h @@ -11,6 +11,7 @@ class QLineEdit; class GameInstallDialog final : public QDialog { + Q_OBJECT public: GameInstallDialog(); ~GameInstallDialog(); diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 1598b0640..bebb16c9a 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -536,7 +536,7 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { } else if (elementName == "fullscreenCheckBox") { text = tr("Enable Full Screen:\\nAutomatically puts the game window into full-screen mode.\\nThis can be toggled by pressing the F11 key."); } else if (elementName == "separateUpdatesCheckBox") { - text = tr("Enable Separate Update Folder:\\nEnables installing game updates into a separate folder for easy management.\\nThis can be manually created by adding the extracted update to the game folder with the name 'CUSA00000-UPDATE' where the CUSA ID matches the game's ID."); + text = tr("Enable Separate Update Folder:\\nEnables installing game updates into a separate folder for easy management.\\nThis can be manually created by adding the extracted update to the game folder with the name \"CUSA00000-UPDATE\" where the CUSA ID matches the game's ID."); } else if (elementName == "showSplashCheckBox") { text = tr("Show Splash Screen:\\nShows the game's splash screen (a special image) while the game is starting."); } else if (elementName == "discordRPCCheckbox") { @@ -548,8 +548,8 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { } else if (elementName == "logTypeGroupBox") { text = tr("Log Type:\\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation."); } else if (elementName == "logFilter") { - text = tr("Log Filter:\nFilters the log to only print specific information.\nExamples: 'Core:Trace' 'Lib.Pad:Debug Common.Filesystem:Error' '*:Critical'\\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it."); -#ifdef ENABLE_UPDATER + text = tr("Log Filter:\\nFilters the log to only print specific information.\\nExamples: \"Core:Trace\" \"Lib.Pad:Debug Common.Filesystem:Error\" \"*:Critical\"\\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it."); + #ifdef ENABLE_UPDATER } else if (elementName == "updaterGroupBox") { text = tr("Update:\\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable."); #endif @@ -562,7 +562,7 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { } else if (elementName == "disableTrophycheckBox") { text = tr("Disable Trophy Pop-ups:\\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window)."); } else if (elementName == "enableCompatibilityCheckBox") { - text = tr("Display Compatibility Data:\\nDisplays game compatibility information in table view. Enable 'Update Compatibility On Startup' to get up-to-date information."); + text = tr("Display Compatibility Data:\\nDisplays game compatibility information in table view. Enable \"Update Compatibility On Startup\" to get up-to-date information."); } else if (elementName == "checkCompatibilityOnStartupCheckBox") { text = tr("Update Compatibility On Startup:\\nAutomatically update the compatibility database when shadPS4 starts."); } else if (elementName == "updateCompatibilityButton") { @@ -580,7 +580,7 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { // Graphics if (elementName == "graphicsAdapterGroupBox") { - text = tr("Graphics Device:\\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\\nor select 'Auto Select' to automatically determine it."); + text = tr("Graphics Device:\\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\\nor select \"Auto Select\" to automatically determine it."); } else if (elementName == "widthGroupBox" || elementName == "heightGroupBox") { text = tr("Width/Height:\\nSets the size of the emulator window at launch, which can be resized during gameplay.\\nThis is different from the in-game resolution."); } else if (elementName == "heightDivider") { From 82cacec8eb18825a163165e4b6790edf0d63ff17 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:06:56 +0200 Subject: [PATCH 02/29] shader_recompiler: Remove special case buffers and add support for aliasing (#2428) * shader_recompiler: Move shared mem lowering into emitter * IR can be quite verbose during first stages of translation, before ssa and constant prop passes have run that drastically simplify it. This lowering can also be done during emission so why not do it then to save some compilation time * runtime_info: Pack PsColorBuffer into 8 bytes * Drops the size of the total structure by half from 396 to 204 bytes. Also should make comparison of the array a bit faster, since its a hot path done every draw * emit_spirv_context: Add infrastructure for buffer aliases * Splits out the buffer creation function so it can be reused when defining multiple type aliases * shader_recompiler: Merge srt_flatbuf into buffers list * Its no longer a special case, yay * shader_recompiler: Complete buffer aliasing support * Add a bunch more types into buffers, such as F32 for float reads/writes and 8/16 bit integer types for formatted buffers * shader_recompiler: Remove existing shared memory emulation * The current impl relies on backend side implementaton and hooking into every shared memory access. It also doesnt handle atomics. Will be replaced by an IR pass that solves these issues * shader_recompiler: Reintroduce shared memory on ssbo emulation * Now it is performed with an IR pass, and combined with the previous commit cleanup, is fully transparent from the backend, other than requiring workgroup_index be provided as an attribute (computing this on every shared memory access is gonna be too verbose * clang format * buffer_cache: Reduce buffer sizes * vk_rasterizer: Cleanup resource binding code * Reduce noise in the functions, also remove some arguments which are class members * Fix gcc --- CMakeLists.txt | 2 +- .../backend/spirv/emit_spirv.cpp | 7 +- .../backend/spirv/emit_spirv_atomic.cpp | 21 +- .../spirv/emit_spirv_context_get_set.cpp | 148 +++++++----- .../spirv/emit_spirv_shared_memory.cpp | 54 +---- .../backend/spirv/emit_spirv_special.cpp | 3 + .../backend/spirv/spirv_emit_context.cpp | 221 +++++++++--------- .../backend/spirv/spirv_emit_context.h | 42 +++- .../frontend/translate/data_share.cpp | 26 ++- .../frontend/translate/export.cpp | 4 +- .../frontend/translate/translate.cpp | 22 +- .../frontend/translate/translate.h | 4 +- src/shader_recompiler/info.h | 42 ++-- src/shader_recompiler/ir/attribute.h | 21 +- src/shader_recompiler/ir/passes/ir_passes.h | 6 +- .../passes/lower_shared_mem_to_registers.cpp | 81 ------- .../ir/passes/resource_tracking_pass.cpp | 48 ++-- .../ir/passes/shader_info_collection_pass.cpp | 12 +- .../ir/passes/shared_memory_barrier_pass.cpp | 72 ++++-- .../passes/shared_memory_to_storage_pass.cpp | 117 ++++++++++ src/shader_recompiler/recompiler.cpp | 7 +- src/shader_recompiler/runtime_info.h | 31 ++- src/shader_recompiler/specialization.h | 18 -- src/video_core/amdgpu/liverpool.h | 4 + src/video_core/amdgpu/resource.h | 6 + src/video_core/amdgpu/types.h | 10 +- src/video_core/buffer_cache/buffer.h | 2 +- src/video_core/buffer_cache/buffer_cache.cpp | 17 +- src/video_core/buffer_cache/buffer_cache.h | 9 +- .../renderer_vulkan/vk_compute_pipeline.cpp | 19 -- .../renderer_vulkan/vk_graphics_pipeline.cpp | 13 -- .../renderer_vulkan/vk_graphics_pipeline.h | 3 +- .../renderer_vulkan/vk_instance.cpp | 24 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 4 +- .../renderer_vulkan/vk_rasterizer.cpp | 172 ++++++-------- .../renderer_vulkan/vk_rasterizer.h | 8 +- 36 files changed, 675 insertions(+), 625 deletions(-) delete mode 100644 src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp create mode 100644 src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 22a811d30..95766bc67 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -766,11 +766,11 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/ir/passes/identity_removal_pass.cpp src/shader_recompiler/ir/passes/ir_passes.h src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp - src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp src/shader_recompiler/ir/passes/resource_tracking_pass.cpp src/shader_recompiler/ir/passes/ring_access_elimination.cpp src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp + src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp src/shader_recompiler/ir/abstract_syntax_list.h src/shader_recompiler/ir/attribute.cpp diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 3712380f5..2a5b9335e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -242,14 +242,17 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct ctx.AddCapability(spv::Capability::Image1D); ctx.AddCapability(spv::Capability::Sampled1D); ctx.AddCapability(spv::Capability::ImageQuery); + ctx.AddCapability(spv::Capability::Int8); + ctx.AddCapability(spv::Capability::Int16); + ctx.AddCapability(spv::Capability::Int64); + ctx.AddCapability(spv::Capability::UniformAndStorageBuffer8BitAccess); + ctx.AddCapability(spv::Capability::UniformAndStorageBuffer16BitAccess); if (info.uses_fp16) { ctx.AddCapability(spv::Capability::Float16); - ctx.AddCapability(spv::Capability::Int16); } if (info.uses_fp64) { ctx.AddCapability(spv::Capability::Float64); } - ctx.AddCapability(spv::Capability::Int64); if (info.has_storage_images) { ctx.AddCapability(spv::Capability::StorageImageExtendedFormats); ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index ce65a5ccb..92cfcbb0f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -23,10 +23,13 @@ Id SharedAtomicU32(EmitContext& ctx, Id offset, Id value, Id BufferAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value, Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) { - auto& buffer = ctx.buffers[handle]; - address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); + const auto& buffer = ctx.buffers[handle]; + if (Sirit::ValidId(buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); + } const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index); + const auto [id, pointer_type] = buffer[EmitContext::BufferAlias::U32]; + const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index); const auto [scope, semantics]{AtomicArgs(ctx)}; return (ctx.*atomic_func)(ctx.U32[1], ptr, scope, semantics, value); } @@ -165,17 +168,17 @@ Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id co } Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding) { - auto& buffer = ctx.buffers[binding]; - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, - ctx.ConstU32(gds_addr)); + const auto& buffer = ctx.buffers[binding]; + const auto [id, pointer_type] = buffer[EmitContext::BufferAlias::U32]; + const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, ctx.ConstU32(gds_addr)); const auto [scope, semantics]{AtomicArgs(ctx)}; return ctx.OpAtomicIIncrement(ctx.U32[1], ptr, scope, semantics); } Id EmitDataConsume(EmitContext& ctx, u32 gds_addr, u32 binding) { - auto& buffer = ctx.buffers[binding]; - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, - ctx.ConstU32(gds_addr)); + const auto& buffer = ctx.buffers[binding]; + const auto [id, pointer_type] = buffer[EmitContext::BufferAlias::U32]; + const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, ctx.ConstU32(gds_addr)); const auto [scope, semantics]{AtomicArgs(ctx)}; return ctx.OpAtomicIDecrement(ctx.U32[1], ptr, scope, semantics); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index ae77ed413..cc7b7e097 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -160,21 +160,25 @@ void EmitGetGotoVariable(EmitContext&) { UNREACHABLE_MSG("Unreachable instruction"); } +using BufferAlias = EmitContext::BufferAlias; + Id EmitReadConst(EmitContext& ctx, IR::Inst* inst) { - u32 flatbuf_off_dw = inst->Flags(); - ASSERT(ctx.srt_flatbuf.binding >= 0); - ASSERT(flatbuf_off_dw > 0); - Id index = ctx.ConstU32(flatbuf_off_dw); - auto& buffer = ctx.srt_flatbuf; - const Id ptr{ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index)}; + const u32 flatbuf_off_dw = inst->Flags(); + const auto& srt_flatbuf = ctx.buffers.back(); + ASSERT(srt_flatbuf.binding >= 0 && flatbuf_off_dw > 0 && + srt_flatbuf.buffer_type == BufferType::ReadConstUbo); + const auto [id, pointer_type] = srt_flatbuf[BufferAlias::U32]; + const Id ptr{ + ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, ctx.ConstU32(flatbuf_off_dw))}; return ctx.OpLoad(ctx.U32[1], ptr); } Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index) { - auto& buffer = ctx.buffers[handle]; + const auto& buffer = ctx.buffers[handle]; index = ctx.OpIAdd(ctx.U32[1], index, buffer.offset_dwords); - const Id ptr{ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index)}; - return ctx.OpLoad(buffer.data_types->Get(1), ptr); + const auto [id, pointer_type] = buffer[BufferAlias::U32]; + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; + return ctx.OpLoad(ctx.U32[1], ptr); } Id EmitReadStepRate(EmitContext& ctx, int rate_idx) { @@ -184,7 +188,7 @@ Id EmitReadStepRate(EmitContext& ctx, int rate_idx) { rate_idx == 0 ? ctx.u32_zero_value : ctx.u32_one_value)); } -Id EmitGetAttributeForGeometry(EmitContext& ctx, IR::Attribute attr, u32 comp, Id index) { +static Id EmitGetAttributeForGeometry(EmitContext& ctx, IR::Attribute attr, u32 comp, Id index) { if (IR::IsPosition(attr)) { ASSERT(attr == IR::Attribute::Position0); const auto position_arr_ptr = ctx.TypePointer(spv::StorageClass::Input, ctx.F32[4]); @@ -285,6 +289,8 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp) { return EmitReadStepRate(ctx, 0); case IR::Attribute::InstanceId1: return EmitReadStepRate(ctx, 1); + case IR::Attribute::WorkgroupIndex: + return ctx.workgroup_index_id; case IR::Attribute::WorkgroupId: return ctx.OpCompositeExtract(ctx.U32[1], ctx.OpLoad(ctx.U32[3], ctx.workgroup_id), comp); case IR::Attribute::LocalInvocationId: @@ -396,140 +402,158 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) { ctx.OpStore(pointer, value); } -template -static Id EmitLoadBufferU32xN(EmitContext& ctx, u32 handle, Id address) { - auto& buffer = ctx.buffers[handle]; - address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); +template +static Id EmitLoadBufferB32xN(EmitContext& ctx, u32 handle, Id address) { + const auto& spv_buffer = ctx.buffers[handle]; + if (Sirit::ValidId(spv_buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); + } const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); + const auto& data_types = alias == BufferAlias::U32 ? ctx.U32 : ctx.F32; + const auto [id, pointer_type] = spv_buffer[alias]; if constexpr (N == 1) { - const Id ptr{ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index)}; - return ctx.OpLoad(buffer.data_types->Get(1), ptr); + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; + return ctx.OpLoad(data_types[1], ptr); } else { boost::container::static_vector ids; for (u32 i = 0; i < N; i++) { const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); - const Id ptr{ - ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index_i)}; - ids.push_back(ctx.OpLoad(buffer.data_types->Get(1), ptr)); + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i)}; + ids.push_back(ctx.OpLoad(data_types[1], ptr)); } - return ctx.OpCompositeConstruct(buffer.data_types->Get(N), ids); + return ctx.OpCompositeConstruct(data_types[N], ids); } } Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(3u))}; - const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))}; - const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)}; - return ctx.OpBitFieldUExtract(ctx.U32[1], dword, bit_offset, ctx.ConstU32(8u)); + const auto& spv_buffer = ctx.buffers[handle]; + if (Sirit::ValidId(spv_buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); + } + const auto [id, pointer_type] = spv_buffer[BufferAlias::U8]; + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)}; + return ctx.OpUConvert(ctx.U32[1], ctx.OpLoad(ctx.U8, ptr)); } Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(2u))}; - const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))}; - const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)}; - return ctx.OpBitFieldUExtract(ctx.U32[1], dword, bit_offset, ctx.ConstU32(16u)); + const auto& spv_buffer = ctx.buffers[handle]; + if (Sirit::ValidId(spv_buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); + } + const auto [id, pointer_type] = spv_buffer[BufferAlias::U16]; + const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(1u)); + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; + return ctx.OpUConvert(ctx.U32[1], ctx.OpLoad(ctx.U16, ptr)); } Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferU32xN<1>(ctx, handle, address); + return EmitLoadBufferB32xN<1, BufferAlias::U32>(ctx, handle, address); } Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferU32xN<2>(ctx, handle, address); + return EmitLoadBufferB32xN<2, BufferAlias::U32>(ctx, handle, address); } Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferU32xN<3>(ctx, handle, address); + return EmitLoadBufferB32xN<3, BufferAlias::U32>(ctx, handle, address); } Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferU32xN<4>(ctx, handle, address); + return EmitLoadBufferB32xN<4, BufferAlias::U32>(ctx, handle, address); } Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return ctx.OpBitcast(ctx.F32[1], EmitLoadBufferU32(ctx, inst, handle, address)); + return EmitLoadBufferB32xN<1, BufferAlias::F32>(ctx, handle, address); } Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return ctx.OpBitcast(ctx.F32[2], EmitLoadBufferU32x2(ctx, inst, handle, address)); + return EmitLoadBufferB32xN<2, BufferAlias::F32>(ctx, handle, address); } Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return ctx.OpBitcast(ctx.F32[3], EmitLoadBufferU32x3(ctx, inst, handle, address)); + return EmitLoadBufferB32xN<3, BufferAlias::F32>(ctx, handle, address); } Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return ctx.OpBitcast(ctx.F32[4], EmitLoadBufferU32x4(ctx, inst, handle, address)); + return EmitLoadBufferB32xN<4, BufferAlias::F32>(ctx, handle, address); } Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { UNREACHABLE_MSG("SPIR-V instruction"); } -template -static void EmitStoreBufferU32xN(EmitContext& ctx, u32 handle, Id address, Id value) { - auto& buffer = ctx.buffers[handle]; - address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); +template +static void EmitStoreBufferB32xN(EmitContext& ctx, u32 handle, Id address, Id value) { + const auto& spv_buffer = ctx.buffers[handle]; + if (Sirit::ValidId(spv_buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); + } const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); + const auto& data_types = alias == BufferAlias::U32 ? ctx.U32 : ctx.F32; + const auto [id, pointer_type] = spv_buffer[alias]; if constexpr (N == 1) { - const Id ptr{ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index)}; + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; ctx.OpStore(ptr, value); } else { for (u32 i = 0; i < N; i++) { const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); - const Id ptr = - ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index_i); - ctx.OpStore(ptr, ctx.OpCompositeExtract(buffer.data_types->Get(1), value, i)); + const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i); + ctx.OpStore(ptr, ctx.OpCompositeExtract(data_types[1], value, i)); } } } void EmitStoreBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(3u))}; - const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))}; - const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)}; - const Id new_val{ctx.OpBitFieldInsert(ctx.U32[1], dword, value, bit_offset, ctx.ConstU32(8u))}; - EmitStoreBufferU32xN<1>(ctx, handle, address, new_val); + const auto& spv_buffer = ctx.buffers[handle]; + if (Sirit::ValidId(spv_buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); + } + const auto [id, pointer_type] = spv_buffer[BufferAlias::U8]; + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)}; + ctx.OpStore(ptr, ctx.OpUConvert(ctx.U8, value)); } void EmitStoreBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - const Id byte_index{ctx.OpBitwiseAnd(ctx.U32[1], address, ctx.ConstU32(2u))}; - const Id bit_offset{ctx.OpShiftLeftLogical(ctx.U32[1], byte_index, ctx.ConstU32(3u))}; - const Id dword{EmitLoadBufferU32xN<1>(ctx, handle, address)}; - const Id new_val{ctx.OpBitFieldInsert(ctx.U32[1], dword, value, bit_offset, ctx.ConstU32(16u))}; - EmitStoreBufferU32xN<1>(ctx, handle, address, new_val); + const auto& spv_buffer = ctx.buffers[handle]; + if (Sirit::ValidId(spv_buffer.offset)) { + address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); + } + const auto [id, pointer_type] = spv_buffer[BufferAlias::U16]; + const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(1u)); + const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; + ctx.OpStore(ptr, ctx.OpUConvert(ctx.U16, value)); } void EmitStoreBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferU32xN<1>(ctx, handle, address, value); + EmitStoreBufferB32xN<1, BufferAlias::U32>(ctx, handle, address, value); } void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferU32xN<2>(ctx, handle, address, value); + EmitStoreBufferB32xN<2, BufferAlias::U32>(ctx, handle, address, value); } void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferU32xN<3>(ctx, handle, address, value); + EmitStoreBufferB32xN<3, BufferAlias::U32>(ctx, handle, address, value); } void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferU32xN<4>(ctx, handle, address, value); + EmitStoreBufferB32xN<4, BufferAlias::U32>(ctx, handle, address, value); } void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferU32(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[1], value)); + EmitStoreBufferB32xN<1, BufferAlias::F32>(ctx, handle, address, value); } void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferU32x2(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[2], value)); + EmitStoreBufferB32xN<2, BufferAlias::F32>(ctx, handle, address, value); } void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferU32x3(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[3], value)); + EmitStoreBufferB32xN<3, BufferAlias::F32>(ctx, handle, address, value); } void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferU32x4(ctx, inst, handle, address, ctx.OpBitcast(ctx.U32[4], value)); + EmitStoreBufferB32xN<4, BufferAlias::F32>(ctx, handle, address, value); } void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp index 550b95f3d..8b1610d61 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp @@ -9,65 +9,35 @@ namespace Shader::Backend::SPIRV { Id EmitLoadSharedU32(EmitContext& ctx, Id offset) { const Id shift_id{ctx.ConstU32(2U)}; const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; - if (ctx.info.has_emulated_shared_memory) { - const Id pointer = - ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, ctx.u32_zero_value, index); - return ctx.OpLoad(ctx.U32[1], pointer); - } else { - const Id pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index); - return ctx.OpLoad(ctx.U32[1], pointer); - } + const Id pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index); + return ctx.OpLoad(ctx.U32[1], pointer); } Id EmitLoadSharedU64(EmitContext& ctx, Id offset) { const Id shift_id{ctx.ConstU32(2U)}; const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; const Id next_index{ctx.OpIAdd(ctx.U32[1], base_index, ctx.ConstU32(1U))}; - if (ctx.info.has_emulated_shared_memory) { - const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, - ctx.u32_zero_value, base_index)}; - const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, - ctx.u32_zero_value, next_index)}; - return ctx.OpCompositeConstruct(ctx.U32[2], ctx.OpLoad(ctx.U32[1], lhs_pointer), - ctx.OpLoad(ctx.U32[1], rhs_pointer)); - } else { - const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, base_index)}; - const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_index)}; - return ctx.OpCompositeConstruct(ctx.U32[2], ctx.OpLoad(ctx.U32[1], lhs_pointer), - ctx.OpLoad(ctx.U32[1], rhs_pointer)); - } + const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, base_index)}; + const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_index)}; + return ctx.OpCompositeConstruct(ctx.U32[2], ctx.OpLoad(ctx.U32[1], lhs_pointer), + ctx.OpLoad(ctx.U32[1], rhs_pointer)); } void EmitWriteSharedU32(EmitContext& ctx, Id offset, Id value) { const Id shift{ctx.ConstU32(2U)}; const Id word_offset{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; - if (ctx.info.has_emulated_shared_memory) { - const Id pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, - ctx.u32_zero_value, word_offset); - ctx.OpStore(pointer, value); - } else { - const Id pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset); - ctx.OpStore(pointer, value); - } + const Id pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset); + ctx.OpStore(pointer, value); } void EmitWriteSharedU64(EmitContext& ctx, Id offset, Id value) { const Id shift{ctx.ConstU32(2U)}; const Id word_offset{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; const Id next_offset{ctx.OpIAdd(ctx.U32[1], word_offset, ctx.ConstU32(1U))}; - if (ctx.info.has_emulated_shared_memory) { - const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, - ctx.u32_zero_value, word_offset)}; - const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, - ctx.u32_zero_value, next_offset)}; - ctx.OpStore(lhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 0U)); - ctx.OpStore(rhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 1U)); - } else { - const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset)}; - const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_offset)}; - ctx.OpStore(lhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 0U)); - ctx.OpStore(rhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 1U)); - } + const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset)}; + const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_offset)}; + ctx.OpStore(lhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 0U)); + ctx.OpStore(rhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 1U)); } } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index a0a3ed8ff..724550cd6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -11,6 +11,9 @@ void EmitPrologue(EmitContext& ctx) { if (ctx.stage == Stage::Fragment) { ctx.DefineInterpolatedAttribs(); } + if (ctx.info.loads.Get(IR::Attribute::WorkgroupIndex)) { + ctx.DefineWorkgroupIndex(); + } ctx.DefineBufferOffsets(); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index d676d205d..da20dc691 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -5,7 +5,6 @@ #include "common/div_ceil.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" #include "shader_recompiler/frontend/fetch_shader.h" -#include "shader_recompiler/ir/passes/srt.h" #include "shader_recompiler/runtime_info.h" #include "video_core/amdgpu/types.h" @@ -107,6 +106,8 @@ Id EmitContext::Def(const IR::Value& value) { void EmitContext::DefineArithmeticTypes() { void_id = Name(TypeVoid(), "void_id"); U1[1] = Name(TypeBool(), "bool_id"); + U8 = Name(TypeUInt(8), "u8_id"); + U16 = Name(TypeUInt(16), "u16_id"); if (info.uses_fp16) { F16[1] = Name(TypeFloat(16), "f16_id"); U16 = Name(TypeUInt(16), "u16_id"); @@ -193,6 +194,9 @@ EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat f void EmitContext::DefineBufferOffsets() { for (BufferDefinition& buffer : buffers) { + if (buffer.buffer_type != BufferType::Guest) { + continue; + } const u32 binding = buffer.binding; const u32 half = PushData::BufOffsetIndex + (binding >> 4); const u32 comp = (binding & 0xf) >> 2; @@ -211,8 +215,7 @@ void EmitContext::DefineInterpolatedAttribs() { if (!profile.needs_manual_interpolation) { return; } - // Iterate all input attributes, load them and manually interpolate with barycentric - // coordinates. + // Iterate all input attributes, load them and manually interpolate. for (s32 i = 0; i < runtime_info.fs_info.num_inputs; i++) { const auto& input = runtime_info.fs_info.inputs[i]; const u32 semantic = input.param_index; @@ -237,6 +240,20 @@ void EmitContext::DefineInterpolatedAttribs() { } } +void EmitContext::DefineWorkgroupIndex() { + const Id workgroup_id_val{OpLoad(U32[3], workgroup_id)}; + const Id workgroup_x{OpCompositeExtract(U32[1], workgroup_id_val, 0)}; + const Id workgroup_y{OpCompositeExtract(U32[1], workgroup_id_val, 1)}; + const Id workgroup_z{OpCompositeExtract(U32[1], workgroup_id_val, 2)}; + const Id num_workgroups{OpLoad(U32[3], num_workgroups_id)}; + const Id num_workgroups_x{OpCompositeExtract(U32[1], num_workgroups, 0)}; + const Id num_workgroups_y{OpCompositeExtract(U32[1], num_workgroups, 1)}; + workgroup_index_id = + OpIAdd(U32[1], OpIAdd(U32[1], workgroup_x, OpIMul(U32[1], workgroup_y, num_workgroups_x)), + OpIMul(U32[1], workgroup_z, OpIMul(U32[1], num_workgroups_x, num_workgroups_y))); + Name(workgroup_index_id, "workgroup_index"); +} + Id MakeDefaultValue(EmitContext& ctx, u32 default_value) { switch (default_value) { case 0: @@ -305,9 +322,16 @@ void EmitContext::DefineInputs() { break; } case LogicalStage::Fragment: - frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input); - frag_depth = DefineVariable(F32[1], spv::BuiltIn::FragDepth, spv::StorageClass::Output); - front_facing = DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input); + if (info.loads.GetAny(IR::Attribute::FragCoord)) { + frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input); + } + if (info.stores.Get(IR::Attribute::Depth)) { + frag_depth = DefineVariable(F32[1], spv::BuiltIn::FragDepth, spv::StorageClass::Output); + } + if (info.loads.Get(IR::Attribute::IsFrontFace)) { + front_facing = + DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input); + } if (profile.needs_manual_interpolation) { gl_bary_coord_id = DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); @@ -342,9 +366,19 @@ void EmitContext::DefineInputs() { } break; case LogicalStage::Compute: - workgroup_id = DefineVariable(U32[3], spv::BuiltIn::WorkgroupId, spv::StorageClass::Input); - local_invocation_id = - DefineVariable(U32[3], spv::BuiltIn::LocalInvocationId, spv::StorageClass::Input); + if (info.loads.GetAny(IR::Attribute::WorkgroupIndex) || + info.loads.GetAny(IR::Attribute::WorkgroupId)) { + workgroup_id = + DefineVariable(U32[3], spv::BuiltIn::WorkgroupId, spv::StorageClass::Input); + } + if (info.loads.GetAny(IR::Attribute::WorkgroupIndex)) { + num_workgroups_id = + DefineVariable(U32[3], spv::BuiltIn::NumWorkgroups, spv::StorageClass::Input); + } + if (info.loads.GetAny(IR::Attribute::LocalInvocationId)) { + local_invocation_id = + DefineVariable(U32[3], spv::BuiltIn::LocalInvocationId, spv::StorageClass::Input); + } break; case LogicalStage::Geometry: { primitive_id = DefineVariable(U32[1], spv::BuiltIn::PrimitiveId, spv::StorageClass::Input); @@ -588,78 +622,74 @@ void EmitContext::DefinePushDataBlock() { interfaces.push_back(push_data_block); } -void EmitContext::DefineBuffers() { - boost::container::small_vector type_ids; - const auto define_struct = [&](Id record_array_type, bool is_instance_data, - std::optional explicit_name = {}) { - const Id struct_type{TypeStruct(record_array_type)}; - if (std::ranges::find(type_ids, record_array_type.value, &Id::value) != type_ids.end()) { - return struct_type; - } - Decorate(record_array_type, spv::Decoration::ArrayStride, 4); - auto name = is_instance_data ? fmt::format("{}_instance_data_f32", stage) - : fmt::format("{}_cbuf_block_f32", stage); - name = explicit_name.value_or(name); - Name(struct_type, name); +EmitContext::BufferSpv EmitContext::DefineBuffer(bool is_storage, bool is_written, u32 elem_shift, + BufferType buffer_type, Id data_type) { + // Define array type. + const Id max_num_items = ConstU32(u32(profile.max_ubo_size) >> elem_shift); + const Id record_array_type{is_storage ? TypeRuntimeArray(data_type) + : TypeArray(data_type, max_num_items)}; + // Define block struct type. Don't perform decorations twice on the same Id. + const Id struct_type{TypeStruct(record_array_type)}; + if (std::ranges::find(buf_type_ids, record_array_type.value, &Id::value) == + buf_type_ids.end()) { + Decorate(record_array_type, spv::Decoration::ArrayStride, 1 << elem_shift); Decorate(struct_type, spv::Decoration::Block); MemberName(struct_type, 0, "data"); MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); - type_ids.push_back(record_array_type); - return struct_type; - }; - - if (info.has_readconst) { - const Id data_type = U32[1]; - const auto storage_class = spv::StorageClass::Uniform; - const Id pointer_type = TypePointer(storage_class, data_type); - const Id record_array_type{ - TypeArray(U32[1], ConstU32(static_cast(info.flattened_ud_buf.size())))}; - - const Id struct_type{define_struct(record_array_type, false, "srt_flatbuf_ty")}; - - const Id struct_pointer_type{TypePointer(storage_class, struct_type)}; - const Id id{AddGlobalVariable(struct_pointer_type, storage_class)}; - Decorate(id, spv::Decoration::Binding, binding.unified++); - Decorate(id, spv::Decoration::DescriptorSet, 0U); - Name(id, "srt_flatbuf_ubo"); - - srt_flatbuf = { - .id = id, - .binding = binding.buffer++, - .pointer_type = pointer_type, - }; - interfaces.push_back(id); + buf_type_ids.push_back(record_array_type); } + // Define buffer binding interface. + const auto storage_class = + is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform; + const Id struct_pointer_type{TypePointer(storage_class, struct_type)}; + const Id pointer_type = TypePointer(storage_class, data_type); + const Id id{AddGlobalVariable(struct_pointer_type, storage_class)}; + Decorate(id, spv::Decoration::Binding, binding.unified); + Decorate(id, spv::Decoration::DescriptorSet, 0U); + if (is_storage && !is_written) { + Decorate(id, spv::Decoration::NonWritable); + } + switch (buffer_type) { + case Shader::BufferType::GdsBuffer: + Name(id, "gds_buffer"); + break; + case Shader::BufferType::ReadConstUbo: + Name(id, "srt_flatbuf_ubo"); + break; + case Shader::BufferType::SharedMemory: + Name(id, "ssbo_shmem"); + break; + default: + Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "ubo", binding.buffer)); + } + interfaces.push_back(id); + return {id, pointer_type}; +}; +void EmitContext::DefineBuffers() { for (const auto& desc : info.buffers) { - const auto sharp = desc.GetSharp(info); - const bool is_storage = desc.IsStorage(sharp, profile); - const u32 array_size = profile.max_ubo_size >> 2; - const auto* data_types = True(desc.used_types & IR::Type::F32) ? &F32 : &U32; - const Id data_type = (*data_types)[1]; - const Id record_array_type{is_storage ? TypeRuntimeArray(data_type) - : TypeArray(data_type, ConstU32(array_size))}; - const Id struct_type{define_struct(record_array_type, desc.is_instance_data)}; + const auto buf_sharp = desc.GetSharp(info); + const bool is_storage = desc.IsStorage(buf_sharp, profile); - const auto storage_class = - is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform; - const Id struct_pointer_type{TypePointer(storage_class, struct_type)}; - const Id pointer_type = TypePointer(storage_class, data_type); - const Id id{AddGlobalVariable(struct_pointer_type, storage_class)}; - Decorate(id, spv::Decoration::Binding, binding.unified++); - Decorate(id, spv::Decoration::DescriptorSet, 0U); - if (is_storage && !desc.is_written) { - Decorate(id, spv::Decoration::NonWritable); + // Define aliases depending on the shader usage. + auto& spv_buffer = buffers.emplace_back(binding.buffer++, desc.buffer_type); + if (True(desc.used_types & IR::Type::U32)) { + spv_buffer[BufferAlias::U32] = + DefineBuffer(is_storage, desc.is_written, 2, desc.buffer_type, U32[1]); } - Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "cbuf", desc.sharp_idx)); - - buffers.push_back({ - .id = id, - .binding = binding.buffer++, - .data_types = data_types, - .pointer_type = pointer_type, - }); - interfaces.push_back(id); + if (True(desc.used_types & IR::Type::F32)) { + spv_buffer[BufferAlias::F32] = + DefineBuffer(is_storage, desc.is_written, 2, desc.buffer_type, F32[1]); + } + if (True(desc.used_types & IR::Type::U16)) { + spv_buffer[BufferAlias::U16] = + DefineBuffer(is_storage, desc.is_written, 1, desc.buffer_type, U16); + } + if (True(desc.used_types & IR::Type::U8)) { + spv_buffer[BufferAlias::U8] = + DefineBuffer(is_storage, desc.is_written, 0, desc.buffer_type, U8); + } + ++binding.unified; } } @@ -809,51 +839,18 @@ void EmitContext::DefineImagesAndSamplers() { } void EmitContext::DefineSharedMemory() { - static constexpr size_t DefaultSharedMemSize = 2_KB; if (!info.uses_shared) { return; } ASSERT(info.stage == Stage::Compute); - - const u32 max_shared_memory_size = profile.max_shared_memory_size; - u32 shared_memory_size = runtime_info.cs_info.shared_memory_size; - if (shared_memory_size == 0) { - shared_memory_size = DefaultSharedMemSize; - } - + const u32 shared_memory_size = runtime_info.cs_info.shared_memory_size; const u32 num_elements{Common::DivCeil(shared_memory_size, 4U)}; const Id type{TypeArray(U32[1], ConstU32(num_elements))}; - - if (shared_memory_size <= max_shared_memory_size) { - shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); - shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); - shared_memory_u32 = AddGlobalVariable(shared_memory_u32_type, spv::StorageClass::Workgroup); - Name(shared_memory_u32, "shared_mem"); - interfaces.push_back(shared_memory_u32); - } else { - shared_memory_u32_type = TypePointer(spv::StorageClass::StorageBuffer, type); - shared_u32 = TypePointer(spv::StorageClass::StorageBuffer, U32[1]); - - Decorate(type, spv::Decoration::ArrayStride, 4); - - const Id struct_type{TypeStruct(type)}; - Name(struct_type, "shared_memory_buf"); - Decorate(struct_type, spv::Decoration::Block); - MemberName(struct_type, 0, "data"); - MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); - - const Id struct_pointer_type{TypePointer(spv::StorageClass::StorageBuffer, struct_type)}; - const Id ssbo_id{AddGlobalVariable(struct_pointer_type, spv::StorageClass::StorageBuffer)}; - Decorate(ssbo_id, spv::Decoration::Binding, binding.unified++); - Decorate(ssbo_id, spv::Decoration::DescriptorSet, 0U); - Name(ssbo_id, "shared_mem_ssbo"); - - shared_memory_u32 = ssbo_id; - - info.has_emulated_shared_memory = true; - info.shared_memory_size = shared_memory_size; - interfaces.push_back(ssbo_id); - } + shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); + shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); + shared_memory_u32 = AddGlobalVariable(shared_memory_u32_type, spv::StorageClass::Workgroup); + Name(shared_memory_u32, "shared_mem"); + interfaces.push_back(shared_memory_u32); } Id EmitContext::DefineFloat32ToUfloatM5(u32 mantissa_bits, const std::string_view name) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 23fca4212..0fe6e336c 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -8,7 +8,7 @@ #include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/info.h" -#include "shader_recompiler/ir/program.h" +#include "shader_recompiler/ir/value.h" #include "shader_recompiler/profile.h" namespace Shader::Backend::SPIRV { @@ -45,6 +45,7 @@ public: void DefineBufferOffsets(); void DefineInterpolatedAttribs(); + void DefineWorkgroupIndex(); [[nodiscard]] Id DefineInput(Id type, std::optional location = std::nullopt, std::optional builtin = std::nullopt) { @@ -200,8 +201,10 @@ public: std::array patches{}; Id workgroup_id{}; + Id num_workgroups_id{}; + Id workgroup_index_id{}; Id local_invocation_id{}; - Id invocation_id{}; // for instanced geoshaders or output vertices within TCS patch + Id invocation_id{}; Id subgroup_local_invocation_id{}; Id image_u32{}; @@ -227,18 +230,38 @@ public: bool is_storage = false; }; - struct BufferDefinition { + enum class BufferAlias : u32 { + U8, + U16, + U32, + F32, + NumAlias, + }; + + struct BufferSpv { Id id; - Id offset; - Id offset_dwords; - u32 binding; - const VectorIds* data_types; Id pointer_type; }; + struct BufferDefinition { + u32 binding; + BufferType buffer_type; + Id offset; + Id offset_dwords; + std::array aliases; + + const BufferSpv& operator[](BufferAlias alias) const { + return aliases[u32(alias)]; + } + + BufferSpv& operator[](BufferAlias alias) { + return aliases[u32(alias)]; + } + }; + Bindings& binding; + boost::container::small_vector buf_type_ids; boost::container::small_vector buffers; - BufferDefinition srt_flatbuf; boost::container::small_vector images; boost::container::small_vector samplers; @@ -279,6 +302,9 @@ private: SpirvAttribute GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id, u32 num_components, bool output); + BufferSpv DefineBuffer(bool is_storage, bool is_written, u32 elem_shift, BufferType buffer_type, + Id data_type); + Id DefineFloat32ToUfloatM5(u32 mantissa_bits, std::string_view name); Id DefineUfloatM5ToFloat32(u32 mantissa_bits, std::string_view name); }; diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index 62c0423dd..460f8913c 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -176,6 +176,13 @@ void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool strid const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; const IR::VectorReg data0{inst.src[1].code}; const IR::VectorReg data1{inst.src[2].code}; + const u32 offset = (inst.control.ds.offset1 << 8u) + inst.control.ds.offset0; + if (info.stage == Stage::Fragment) { + ASSERT_MSG(!is_pair && bit_size == 32 && offset % 256 == 0, + "Unexpected shared memory offset alignment: {}", offset); + ir.SetVectorReg(GetScratchVgpr(offset), ir.GetVectorReg(data0)); + return; + } if (is_pair) { const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1); const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); @@ -195,14 +202,12 @@ void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool strid addr1); } } else if (bit_size == 64) { - const IR::U32 addr0 = ir.IAdd( - addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0))); + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(offset)); const IR::Value data = ir.CompositeConstruct(ir.GetVectorReg(data0), ir.GetVectorReg(data0 + 1)); ir.WriteShared(bit_size, data, addr0); } else { - const IR::U32 addr0 = ir.IAdd( - addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0))); + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(offset)); ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0); } } @@ -223,6 +228,13 @@ void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride const GcnInst& inst) { const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; IR::VectorReg dst_reg{inst.dst[0].code}; + const u32 offset = (inst.control.ds.offset1 << 8u) + inst.control.ds.offset0; + if (info.stage == Stage::Fragment) { + ASSERT_MSG(!is_pair && bit_size == 32 && offset % 256 == 0, + "Unexpected shared memory offset alignment: {}", offset); + ir.SetVectorReg(dst_reg, ir.GetVectorReg(GetScratchVgpr(offset))); + return; + } if (is_pair) { // Pair loads are either 32 or 64-bit const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1); @@ -243,14 +255,12 @@ void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(data1, 1)}); } } else if (bit_size == 64) { - const IR::U32 addr0 = ir.IAdd( - addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0))); + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(offset)); const IR::Value data = ir.LoadShared(bit_size, is_signed, addr0); ir.SetVectorReg(dst_reg, IR::U32{ir.CompositeExtract(data, 0)}); ir.SetVectorReg(dst_reg + 1, IR::U32{ir.CompositeExtract(data, 1)}); } else { - const IR::U32 addr0 = ir.IAdd( - addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0))); + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(offset)); const IR::U32 data = IR::U32{ir.LoadShared(bit_size, is_signed, addr0)}; ir.SetVectorReg(dst_reg, data); } diff --git a/src/shader_recompiler/frontend/translate/export.cpp b/src/shader_recompiler/frontend/translate/export.cpp index ece35093a..0abef2e81 100644 --- a/src/shader_recompiler/frontend/translate/export.cpp +++ b/src/shader_recompiler/frontend/translate/export.cpp @@ -7,7 +7,7 @@ namespace Shader::Gcn { -u32 SwizzleMrtComponent(const FragmentRuntimeInfo::PsColorBuffer& color_buffer, u32 comp) { +u32 SwizzleMrtComponent(const PsColorBuffer& color_buffer, u32 comp) { const auto [r, g, b, a] = color_buffer.swizzle; const std::array swizzle_array = {r, g, b, a}; const auto swizzled_comp_type = static_cast(swizzle_array[comp]); @@ -16,7 +16,7 @@ u32 SwizzleMrtComponent(const FragmentRuntimeInfo::PsColorBuffer& color_buffer, } void Translator::ExportMrtValue(IR::Attribute attribute, u32 comp, const IR::F32& value, - const FragmentRuntimeInfo::PsColorBuffer& color_buffer) { + const PsColorBuffer& color_buffer) { auto converted = ApplyWriteNumberConversion(ir, value, color_buffer.num_conversion); if (color_buffer.needs_unorm_fixup) { // FIXME: Fix-up for GPUs where float-to-unorm rounding is off from expected. diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 7f5504663..7f1bcb33e 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -4,7 +4,6 @@ #include "common/config.h" #include "common/io_file.h" #include "common/path_util.h" -#include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/fetch_shader.h" #include "shader_recompiler/frontend/translate/translate.h" #include "shader_recompiler/info.h" @@ -21,9 +20,14 @@ namespace Shader::Gcn { +static u32 next_vgpr_num; +static std::unordered_map vgpr_map; + Translator::Translator(IR::Block* block_, Info& info_, const RuntimeInfo& runtime_info_, const Profile& profile_) - : ir{*block_, block_->begin()}, info{info_}, runtime_info{runtime_info_}, profile{profile_} {} + : ir{*block_, block_->begin()}, info{info_}, runtime_info{runtime_info_}, profile{profile_} { + next_vgpr_num = vgpr_map.empty() ? runtime_info.num_allocated_vgprs : next_vgpr_num; +} void Translator::EmitPrologue() { ir.Prologue(); @@ -179,8 +183,21 @@ void Translator::EmitPrologue() { default: UNREACHABLE_MSG("Unknown shader stage"); } + + // Clear any scratch vgpr mappings for next shader. + vgpr_map.clear(); } +IR::VectorReg Translator::GetScratchVgpr(u32 offset) { + const auto [it, is_new] = vgpr_map.try_emplace(offset); + if (is_new) { + ASSERT_MSG(next_vgpr_num < 256, "Out of VGPRs"); + const auto new_vgpr = static_cast(next_vgpr_num++); + it->second = new_vgpr; + } + return it->second; +}; + template T Translator::GetSrc(const InstOperand& operand) { constexpr bool is_float = std::is_same_v; @@ -490,7 +507,6 @@ void Translator::EmitFetch(const GcnInst& inst) { info.buffers.push_back({ .sharp_idx = info.srt_info.ReserveSharp(attrib.sgpr_base, attrib.dword_offset, 4), .used_types = IR::Type::F32, - .is_instance_data = true, .instance_attrib = attrib.semantic, }); } diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 287885854..563881a8e 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -309,7 +309,7 @@ private: const IR::F32& x_res, const IR::F32& y_res, const IR::F32& z_res); void ExportMrtValue(IR::Attribute attribute, u32 comp, const IR::F32& value, - const FragmentRuntimeInfo::PsColorBuffer& color_buffer); + const PsColorBuffer& color_buffer); void ExportMrtCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value); void ExportMrtUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value); void ExportCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value); @@ -317,6 +317,8 @@ private: void LogMissingOpcode(const GcnInst& inst); + IR::VectorReg GetScratchVgpr(u32 offset); + private: IR::IREmitter ir; Info& info; diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h index 57d428a49..13f310cf8 100644 --- a/src/shader_recompiler/info.h +++ b/src/shader_recompiler/info.h @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include #include #include #include @@ -19,7 +18,6 @@ #include "shader_recompiler/params.h" #include "shader_recompiler/profile.h" #include "shader_recompiler/runtime_info.h" -#include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/resource.h" namespace Shader { @@ -37,21 +35,30 @@ enum class TextureType : u32 { }; constexpr u32 NUM_TEXTURE_TYPES = 7; +enum class BufferType : u32 { + Guest, + ReadConstUbo, + GdsBuffer, + SharedMemory, +}; + struct Info; struct BufferResource { u32 sharp_idx; IR::Type used_types; AmdGpu::Buffer inline_cbuf; - bool is_gds_buffer{}; - bool is_instance_data{}; + BufferType buffer_type; u8 instance_attrib{}; bool is_written{}; bool is_formatted{}; - [[nodiscard]] bool IsStorage(const AmdGpu::Buffer& buffer, - const Profile& profile) const noexcept { - return buffer.GetSize() > profile.max_ubo_size || is_written || is_gds_buffer; + bool IsSpecial() const noexcept { + return buffer_type != BufferType::Guest; + } + + bool IsStorage(const AmdGpu::Buffer& buffer, const Profile& profile) const noexcept { + return buffer.GetSize() > profile.max_ubo_size || is_written; } [[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; @@ -193,10 +200,8 @@ struct Info { bool uses_unpack_10_11_11{}; bool stores_tess_level_outer{}; bool stores_tess_level_inner{}; - bool translation_failed{}; // indicates that shader has unsupported instructions - bool has_emulated_shared_memory{}; + bool translation_failed{}; bool has_readconst{}; - u32 shared_memory_size{}; u8 mrt_mask{0u}; bool has_fetch_shader{false}; u32 fetch_shader_sgpr_base{0u}; @@ -233,10 +238,8 @@ struct Info { } void AddBindings(Backend::Bindings& bnd) const { - const auto total_buffers = - buffers.size() + (has_readconst ? 1 : 0) + (has_emulated_shared_memory ? 1 : 0); - bnd.buffer += total_buffers; - bnd.unified += total_buffers + images.size() + samplers.size(); + bnd.buffer += buffers.size(); + bnd.unified += buffers.size() + images.size() + samplers.size(); bnd.user_data += ud_mask.NumRegs(); } @@ -283,14 +286,3 @@ constexpr AmdGpu::Image FMaskResource::GetSharp(const Info& info) const noexcept } } // namespace Shader - -template <> -struct fmt::formatter { - constexpr auto parse(format_parse_context& ctx) { - return ctx.begin(); - } - auto format(const Shader::Stage stage, format_context& ctx) const { - constexpr static std::array names = {"fs", "vs", "gs", "es", "hs", "ls", "cs"}; - return fmt::format_to(ctx.out(), "{}", names[static_cast(stage)]); - } -}; diff --git a/src/shader_recompiler/ir/attribute.h b/src/shader_recompiler/ir/attribute.h index bcb2b44a9..5117f5650 100644 --- a/src/shader_recompiler/ir/attribute.h +++ b/src/shader_recompiler/ir/attribute.h @@ -69,16 +69,17 @@ enum class Attribute : u64 { SampleIndex = 72, GlobalInvocationId = 73, WorkgroupId = 74, - LocalInvocationId = 75, - LocalInvocationIndex = 76, - FragCoord = 77, - InstanceId0 = 78, // step rate 0 - InstanceId1 = 79, // step rate 1 - InvocationId = 80, // TCS id in output patch and instanced geometry shader id - PatchVertices = 81, - TessellationEvaluationPointU = 82, - TessellationEvaluationPointV = 83, - PackedHullInvocationInfo = 84, // contains patch id within the VGT and invocation ID + WorkgroupIndex = 75, + LocalInvocationId = 76, + LocalInvocationIndex = 77, + FragCoord = 78, + InstanceId0 = 79, // step rate 0 + InstanceId1 = 80, // step rate 1 + InvocationId = 81, // TCS id in output patch and instanced geometry shader id + PatchVertices = 82, + TessellationEvaluationPointU = 83, + TessellationEvaluationPointV = 84, + PackedHullInvocationInfo = 85, // contains patch id within the VGT and invocation ID Max, }; diff --git a/src/shader_recompiler/ir/passes/ir_passes.h b/src/shader_recompiler/ir/passes/ir_passes.h index 3c98579a0..69628dbfd 100644 --- a/src/shader_recompiler/ir/passes/ir_passes.h +++ b/src/shader_recompiler/ir/passes/ir_passes.h @@ -20,12 +20,14 @@ void FlattenExtendedUserdataPass(IR::Program& program); void ResourceTrackingPass(IR::Program& program); void CollectShaderInfoPass(IR::Program& program); void LowerBufferFormatToRaw(IR::Program& program); -void LowerSharedMemToRegisters(IR::Program& program, const RuntimeInfo& runtime_info); void RingAccessElimination(const IR::Program& program, const RuntimeInfo& runtime_info, Stage stage); void TessellationPreprocess(IR::Program& program, RuntimeInfo& runtime_info); void HullShaderTransform(IR::Program& program, RuntimeInfo& runtime_info); void DomainShaderTransform(IR::Program& program, RuntimeInfo& runtime_info); -void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile); +void SharedMemoryBarrierPass(IR::Program& program, const RuntimeInfo& runtime_info, + const Profile& profile); +void SharedMemoryToStoragePass(IR::Program& program, const RuntimeInfo& runtime_info, + const Profile& profile); } // namespace Shader::Optimization diff --git a/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp b/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp deleted file mode 100644 index 23963a991..000000000 --- a/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "shader_recompiler/ir/ir_emitter.h" -#include "shader_recompiler/ir/program.h" - -namespace Shader::Optimization { - -static bool IsSharedMemoryInst(const IR::Inst& inst) { - const auto opcode = inst.GetOpcode(); - return opcode == IR::Opcode::LoadSharedU32 || opcode == IR::Opcode::LoadSharedU64 || - opcode == IR::Opcode::WriteSharedU32 || opcode == IR::Opcode::WriteSharedU64; -} - -static u32 GetSharedMemImmOffset(const IR::Inst& inst) { - const auto* address = inst.Arg(0).InstRecursive(); - ASSERT(address->GetOpcode() == IR::Opcode::IAdd32); - const auto ir_offset = address->Arg(1); - ASSERT_MSG(ir_offset.IsImmediate()); - const auto offset = ir_offset.U32(); - // Typical usage is the compiler spilling registers into shared memory, with 256 bytes between - // each register to account for 4 bytes per register times 64 threads per group. Ensure that - // this assumption holds, as if it does not this approach may need to be revised. - ASSERT_MSG(offset % 256 == 0, "Unexpected shared memory offset alignment: {}", offset); - return offset; -} - -static void ConvertSharedMemToVgpr(IR::IREmitter& ir, IR::Inst& inst, const IR::VectorReg vgpr) { - switch (inst.GetOpcode()) { - case IR::Opcode::LoadSharedU32: - inst.ReplaceUsesWithAndRemove(ir.GetVectorReg(vgpr)); - break; - case IR::Opcode::LoadSharedU64: - inst.ReplaceUsesWithAndRemove( - ir.CompositeConstruct(ir.GetVectorReg(vgpr), ir.GetVectorReg(vgpr + 1))); - break; - case IR::Opcode::WriteSharedU32: - ir.SetVectorReg(vgpr, IR::U32{inst.Arg(1)}); - inst.Invalidate(); - break; - case IR::Opcode::WriteSharedU64: { - const auto value = inst.Arg(1); - ir.SetVectorReg(vgpr, IR::U32{ir.CompositeExtract(value, 0)}); - ir.SetVectorReg(vgpr, IR::U32{ir.CompositeExtract(value, 1)}); - inst.Invalidate(); - break; - } - default: - UNREACHABLE_MSG("Unknown shared memory opcode: {}", inst.GetOpcode()); - } -} - -void LowerSharedMemToRegisters(IR::Program& program, const RuntimeInfo& runtime_info) { - u32 next_vgpr_num = runtime_info.num_allocated_vgprs; - std::unordered_map vgpr_map; - const auto get_vgpr = [&next_vgpr_num, &vgpr_map](const u32 offset) { - const auto [it, is_new] = vgpr_map.try_emplace(offset); - if (is_new) { - ASSERT_MSG(next_vgpr_num < 256, "Out of VGPRs"); - const auto new_vgpr = static_cast(next_vgpr_num++); - it->second = new_vgpr; - } - return it->second; - }; - - for (IR::Block* const block : program.blocks) { - for (IR::Inst& inst : block->Instructions()) { - if (!IsSharedMemoryInst(inst)) { - continue; - } - const auto offset = GetSharedMemImmOffset(inst); - const auto vgpr = get_vgpr(offset); - IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; - ConvertSharedMemToVgpr(ir, inst, vgpr); - } - } -} - -} // namespace Shader::Optimization diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 029558d9e..c5bfe5796 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -78,7 +78,20 @@ bool IsDataRingInstruction(const IR::Inst& inst) { } IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) { - return IR::Type::U32; + switch (inst.GetOpcode()) { + case IR::Opcode::LoadBufferU8: + case IR::Opcode::StoreBufferU8: + return IR::Type::U8; + case IR::Opcode::LoadBufferU16: + case IR::Opcode::StoreBufferU16: + return IR::Type::U16; + case IR::Opcode::LoadBufferFormatF32: + case IR::Opcode::StoreBufferFormatF32: + // Formatted buffer loads can use a variety of types. + return IR::Type::U32 | IR::Type::F32 | IR::Type::U16 | IR::Type::U8; + default: + return IR::Type::U32; + } } bool IsImageAtomicInstruction(const IR::Inst& inst) { @@ -121,11 +134,9 @@ public: u32 Add(const BufferResource& desc) { const u32 index{Add(buffer_resources, desc, [&desc](const auto& existing) { - // Only one GDS binding can exist. - if (desc.is_gds_buffer && existing.is_gds_buffer) { - return true; - } - return desc.sharp_idx == existing.sharp_idx && desc.inline_cbuf == existing.inline_cbuf; + return desc.sharp_idx == existing.sharp_idx && + desc.inline_cbuf == existing.inline_cbuf && + desc.buffer_type == existing.buffer_type; })}; auto& buffer = buffer_resources[index]; buffer.used_types |= desc.used_types; @@ -272,6 +283,7 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, .sharp_idx = std::numeric_limits::max(), .used_types = BufferDataType(inst, cbuf.GetNumberFmt()), .inline_cbuf = cbuf, + .buffer_type = BufferType::Guest, }); } @@ -286,6 +298,7 @@ void PatchBufferSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& binding = descriptors.Add(BufferResource{ .sharp_idx = sharp, .used_types = BufferDataType(inst, buffer.GetNumberFmt()), + .buffer_type = BufferType::Guest, .is_written = IsBufferStore(inst), .is_formatted = inst.GetOpcode() == IR::Opcode::LoadBufferFormatF32 || inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32, @@ -402,13 +415,10 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& } void PatchDataRingAccess(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { - // Insert gds binding in the shader if it doesn't exist already. - // The buffer is used for append/consume counters. - constexpr static AmdGpu::Buffer GdsSharp{.base_address = 1}; const u32 binding = descriptors.Add(BufferResource{ .used_types = IR::Type::U32, - .inline_cbuf = GdsSharp, - .is_gds_buffer = true, + .inline_cbuf = AmdGpu::Buffer::Null(), + .buffer_type = BufferType::GdsBuffer, .is_written = true, }); @@ -420,12 +430,12 @@ void PatchDataRingAccess(IR::Block& block, IR::Inst& inst, Info& info, Descripto }; // Attempt to deduce the GDS address of counter at compile time. - const u32 gds_addr = [&] { - const IR::Value& gds_offset = inst.Arg(0); - if (gds_offset.IsImmediate()) { - // Nothing to do, offset is known. - return gds_offset.U32() & 0xFFFF; - } + u32 gds_addr = 0; + const IR::Value& gds_offset = inst.Arg(0); + if (gds_offset.IsImmediate()) { + // Nothing to do, offset is known. + gds_addr = gds_offset.U32() & 0xFFFF; + } else { const auto result = IR::BreadthFirstSearch(&inst, pred); ASSERT_MSG(result, "Unable to track M0 source"); @@ -436,8 +446,8 @@ void PatchDataRingAccess(IR::Block& block, IR::Inst& inst, Info& info, Descripto if (prod->GetOpcode() == IR::Opcode::IAdd32) { m0_val += prod->Arg(1).U32(); } - return m0_val & 0xFFFF; - }(); + gds_addr = m0_val & 0xFFFF; + } // Patch instruction. IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; diff --git a/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp b/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp index f3a1fc9a8..219378a6c 100644 --- a/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp +++ b/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp @@ -74,7 +74,14 @@ void Visit(Info& info, const IR::Inst& inst) { info.uses_lane_id = true; break; case IR::Opcode::ReadConst: - info.has_readconst = true; + if (!info.has_readconst) { + info.buffers.push_back({ + .used_types = IR::Type::U32, + .inline_cbuf = AmdGpu::Buffer::Null(), + .buffer_type = BufferType::ReadConstUbo, + }); + info.has_readconst = true; + } break; case IR::Opcode::PackUfloat10_11_11: info.uses_pack_10_11_11 = true; @@ -88,10 +95,9 @@ void Visit(Info& info, const IR::Inst& inst) { } void CollectShaderInfoPass(IR::Program& program) { - Info& info{program.info}; for (IR::Block* const block : program.post_order_blocks) { for (IR::Inst& inst : block->Instructions()) { - Visit(info, inst); + Visit(program.info, inst); } } } diff --git a/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp b/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp index ec7d7e986..0ee52cf19 100644 --- a/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp +++ b/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp @@ -8,37 +8,46 @@ namespace Shader::Optimization { +static bool IsLoadShared(const IR::Inst& inst) { + return inst.GetOpcode() == IR::Opcode::LoadSharedU32 || + inst.GetOpcode() == IR::Opcode::LoadSharedU64; +} + +static bool IsWriteShared(const IR::Inst& inst) { + return inst.GetOpcode() == IR::Opcode::WriteSharedU32 || + inst.GetOpcode() == IR::Opcode::WriteSharedU64; +} + +// Inserts barriers when a shared memory write and read occur in the same basic block. static void EmitBarrierInBlock(IR::Block* block) { - // This is inteded to insert a barrier when shared memory write and read - // occur in the same basic block. Also checks if branch depth is zero as - // we don't want to insert barrier in potentially divergent code. - bool emit_barrier_on_write = false; - bool emit_barrier_on_read = false; - const auto emit_barrier = [block](bool& emit_cond, IR::Inst& inst) { - if (emit_cond) { - IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; - ir.Barrier(); - emit_cond = false; - } + enum class BarrierAction : u32 { + None, + BarrierOnWrite, + BarrierOnRead, }; + BarrierAction action{}; for (IR::Inst& inst : block->Instructions()) { - if (inst.GetOpcode() == IR::Opcode::LoadSharedU32 || - inst.GetOpcode() == IR::Opcode::LoadSharedU64) { - emit_barrier(emit_barrier_on_read, inst); - emit_barrier_on_write = true; + if (IsLoadShared(inst)) { + if (action == BarrierAction::BarrierOnRead) { + IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; + ir.Barrier(); + } + action = BarrierAction::BarrierOnWrite; + continue; } - if (inst.GetOpcode() == IR::Opcode::WriteSharedU32 || - inst.GetOpcode() == IR::Opcode::WriteSharedU64) { - emit_barrier(emit_barrier_on_write, inst); - emit_barrier_on_read = true; + if (IsWriteShared(inst)) { + if (action == BarrierAction::BarrierOnWrite) { + IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; + ir.Barrier(); + } + action = BarrierAction::BarrierOnRead; } } } +// Inserts a barrier after divergent conditional blocks to avoid undefined +// behavior when some threads write and others read from shared memory. static void EmitBarrierInMergeBlock(const IR::AbstractSyntaxNode::Data& data) { - // Insert a barrier after divergent conditional blocks. - // This avoids potential softlocks and crashes when some threads - // initialize shared memory and others read from it. const IR::U1 cond = data.if_node.cond; const auto insert_barrier = IR::BreadthFirstSearch(cond, [](IR::Inst* inst) -> std::optional { @@ -56,8 +65,21 @@ static void EmitBarrierInMergeBlock(const IR::AbstractSyntaxNode::Data& data) { } } -void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) { - if (!program.info.uses_shared || !profile.needs_lds_barriers) { +static constexpr u32 GcnSubgroupSize = 64; + +void SharedMemoryBarrierPass(IR::Program& program, const RuntimeInfo& runtime_info, + const Profile& profile) { + if (program.info.stage != Stage::Compute) { + return; + } + const auto& cs_info = runtime_info.cs_info; + const u32 shared_memory_size = cs_info.shared_memory_size; + const u32 threadgroup_size = + cs_info.workgroup_size[0] * cs_info.workgroup_size[1] * cs_info.workgroup_size[2]; + // The compiler can only omit barriers when the local workgroup size is the same as the HW + // subgroup. + if (shared_memory_size == 0 || threadgroup_size != GcnSubgroupSize || + !profile.needs_lds_barriers) { return; } using Type = IR::AbstractSyntaxNode::Type; @@ -67,6 +89,8 @@ void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) { --branch_depth; continue; } + // Check if branch depth is zero, we don't want to insert barrier in potentially divergent + // code. if (node.type == Type::If && branch_depth++ == 0) { EmitBarrierInMergeBlock(node.data); continue; diff --git a/src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp b/src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp new file mode 100644 index 000000000..25aaf257c --- /dev/null +++ b/src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "shader_recompiler/ir/ir_emitter.h" +#include "shader_recompiler/ir/program.h" +#include "shader_recompiler/profile.h" + +namespace Shader::Optimization { + +static bool IsSharedAccess(const IR::Inst& inst) { + const auto opcode = inst.GetOpcode(); + switch (opcode) { + case IR::Opcode::LoadSharedU32: + case IR::Opcode::LoadSharedU64: + case IR::Opcode::WriteSharedU32: + case IR::Opcode::WriteSharedU64: + case IR::Opcode::SharedAtomicAnd32: + case IR::Opcode::SharedAtomicIAdd32: + case IR::Opcode::SharedAtomicOr32: + case IR::Opcode::SharedAtomicSMax32: + case IR::Opcode::SharedAtomicUMax32: + case IR::Opcode::SharedAtomicSMin32: + case IR::Opcode::SharedAtomicUMin32: + case IR::Opcode::SharedAtomicXor32: + return true; + default: + return false; + } +} + +void SharedMemoryToStoragePass(IR::Program& program, const RuntimeInfo& runtime_info, + const Profile& profile) { + if (program.info.stage != Stage::Compute) { + return; + } + // Only perform the transform if the host shared memory is insufficient. + const u32 shared_memory_size = runtime_info.cs_info.shared_memory_size; + if (shared_memory_size <= profile.max_shared_memory_size) { + return; + } + // Add buffer binding for shared memory storage buffer. + const u32 binding = static_cast(program.info.buffers.size()); + program.info.buffers.push_back({ + .used_types = IR::Type::U32, + .inline_cbuf = AmdGpu::Buffer::Null(), + .buffer_type = BufferType::SharedMemory, + .is_written = true, + }); + for (IR::Block* const block : program.blocks) { + for (IR::Inst& inst : block->Instructions()) { + if (!IsSharedAccess(inst)) { + continue; + } + IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; + const IR::U32 handle = ir.Imm32(binding); + // Replace shared atomics first + switch (inst.GetOpcode()) { + case IR::Opcode::SharedAtomicAnd32: + inst.ReplaceUsesWithAndRemove( + ir.BufferAtomicAnd(handle, inst.Arg(0), inst.Arg(1), {})); + continue; + case IR::Opcode::SharedAtomicIAdd32: + inst.ReplaceUsesWithAndRemove( + ir.BufferAtomicIAdd(handle, inst.Arg(0), inst.Arg(1), {})); + continue; + case IR::Opcode::SharedAtomicOr32: + inst.ReplaceUsesWithAndRemove( + ir.BufferAtomicOr(handle, inst.Arg(0), inst.Arg(1), {})); + continue; + case IR::Opcode::SharedAtomicSMax32: + case IR::Opcode::SharedAtomicUMax32: { + const bool is_signed = inst.GetOpcode() == IR::Opcode::SharedAtomicSMax32; + inst.ReplaceUsesWithAndRemove( + ir.BufferAtomicIMax(handle, inst.Arg(0), inst.Arg(1), is_signed, {})); + continue; + } + case IR::Opcode::SharedAtomicSMin32: + case IR::Opcode::SharedAtomicUMin32: { + const bool is_signed = inst.GetOpcode() == IR::Opcode::SharedAtomicSMin32; + inst.ReplaceUsesWithAndRemove( + ir.BufferAtomicIMin(handle, inst.Arg(0), inst.Arg(1), is_signed, {})); + continue; + } + case IR::Opcode::SharedAtomicXor32: + inst.ReplaceUsesWithAndRemove( + ir.BufferAtomicXor(handle, inst.Arg(0), inst.Arg(1), {})); + continue; + default: + break; + } + // Replace shared operations. + const IR::U32 offset = ir.IMul(ir.GetAttributeU32(IR::Attribute::WorkgroupIndex), + ir.Imm32(shared_memory_size)); + const IR::U32 address = ir.IAdd(IR::U32{inst.Arg(0)}, offset); + switch (inst.GetOpcode()) { + case IR::Opcode::LoadSharedU32: + inst.ReplaceUsesWithAndRemove(ir.LoadBufferU32(1, handle, address, {})); + break; + case IR::Opcode::LoadSharedU64: + inst.ReplaceUsesWithAndRemove(ir.LoadBufferU32(2, handle, address, {})); + break; + case IR::Opcode::WriteSharedU32: + ir.StoreBufferU32(1, handle, address, inst.Arg(1), {}); + inst.Invalidate(); + break; + case IR::Opcode::WriteSharedU64: + ir.StoreBufferU32(2, handle, address, inst.Arg(1), {}); + inst.Invalidate(); + break; + default: + break; + } + } + } +} + +} // namespace Shader::Optimization diff --git a/src/shader_recompiler/recompiler.cpp b/src/shader_recompiler/recompiler.cpp index 5a6d1d775..1c132ebbb 100644 --- a/src/shader_recompiler/recompiler.cpp +++ b/src/shader_recompiler/recompiler.cpp @@ -65,10 +65,6 @@ IR::Program TranslateProgram(std::span code, Pools& pools, Info& info // Run optimization passes const auto stage = program.info.stage; - if (stage == Stage::Fragment) { - // Before SSA pass, as it will rewrite to VGPR load/store. - Shader::Optimization::LowerSharedMemToRegisters(program, runtime_info); - } Shader::Optimization::SsaRewritePass(program.post_order_blocks); Shader::Optimization::IdentityRemovalPass(program.blocks); if (info.l_stage == LogicalStage::TessellationControl) { @@ -90,11 +86,12 @@ IR::Program TranslateProgram(std::span code, Pools& pools, Info& info Shader::Optimization::FlattenExtendedUserdataPass(program); Shader::Optimization::ResourceTrackingPass(program); Shader::Optimization::LowerBufferFormatToRaw(program); + Shader::Optimization::SharedMemoryToStoragePass(program, runtime_info, profile); + Shader::Optimization::SharedMemoryBarrierPass(program, runtime_info, profile); Shader::Optimization::IdentityRemovalPass(program.blocks); Shader::Optimization::DeadCodeEliminationPass(program); Shader::Optimization::ConstantPropagationPass(program.post_order_blocks); Shader::Optimization::CollectShaderInfoPass(program); - Shader::Optimization::SharedMemoryBarrierPass(program, profile); return program; } diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 78973c2d4..517392b98 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -167,6 +167,17 @@ enum class MrtSwizzle : u8 { }; static constexpr u32 MaxColorBuffers = 8; +struct PsColorBuffer { + AmdGpu::NumberFormat num_format : 4; + AmdGpu::NumberConversion num_conversion : 2; + AmdGpu::Liverpool::ShaderExportFormat export_format : 4; + u32 needs_unorm_fixup : 1; + u32 pad : 21; + AmdGpu::CompMapping swizzle; + + auto operator<=>(const PsColorBuffer&) const noexcept = default; +}; + struct FragmentRuntimeInfo { struct PsInput { u8 param_index; @@ -184,15 +195,6 @@ struct FragmentRuntimeInfo { AmdGpu::Liverpool::PsInput addr_flags; u32 num_inputs; std::array inputs; - struct PsColorBuffer { - AmdGpu::NumberFormat num_format; - AmdGpu::NumberConversion num_conversion; - AmdGpu::CompMapping swizzle; - AmdGpu::Liverpool::ShaderExportFormat export_format; - bool needs_unorm_fixup; - - auto operator<=>(const PsColorBuffer&) const noexcept = default; - }; std::array color_buffers; bool operator==(const FragmentRuntimeInfo& other) const noexcept { @@ -264,3 +266,14 @@ struct RuntimeInfo { }; } // namespace Shader + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + auto format(const Shader::Stage stage, format_context& ctx) const { + constexpr static std::array names = {"fs", "vs", "gs", "es", "hs", "ls", "cs"}; + return fmt::format_to(ctx.out(), "{}", names[static_cast(stage)]); + } +}; diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h index 9bf9e71e4..1c3bfc60a 100644 --- a/src/shader_recompiler/specialization.h +++ b/src/shader_recompiler/specialization.h @@ -98,12 +98,6 @@ struct StageSpecialization { }); } u32 binding{}; - if (info->has_emulated_shared_memory) { - binding++; - } - if (info->has_readconst) { - binding++; - } ForEachSharp(binding, buffers, info->buffers, [profile_](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { spec.stride = sharp.GetStride(); @@ -195,18 +189,6 @@ struct StageSpecialization { } } u32 binding{}; - if (info->has_emulated_shared_memory != other.info->has_emulated_shared_memory) { - return false; - } - if (info->has_readconst != other.info->has_readconst) { - return false; - } - if (info->has_emulated_shared_memory) { - binding++; - } - if (info->has_readconst) { - binding++; - } for (u32 i = 0; i < buffers.size(); i++) { if (other.bitset[binding++] && buffers[i] != other.buffers[i]) { return false; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 525a0c9f1..5b9b647eb 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -197,6 +197,10 @@ struct Liverpool { return settings.lds_dwords.Value() * 128 * 4; } + u32 NumWorkgroups() const noexcept { + return dim_x * dim_y * dim_z; + } + bool IsTgidEnabled(u32 i) const noexcept { return (settings.tgid_enable.Value() >> i) & 1; } diff --git a/src/video_core/amdgpu/resource.h b/src/video_core/amdgpu/resource.h index fa8edb3e2..64a85c812 100644 --- a/src/video_core/amdgpu/resource.h +++ b/src/video_core/amdgpu/resource.h @@ -31,6 +31,12 @@ struct Buffer { u32 _padding1 : 6; u32 type : 2; // overlaps with T# type, so should be 0 for buffer + static constexpr Buffer Null() { + Buffer buffer{}; + buffer.base_address = 1; + return buffer; + } + bool Valid() const { return type == 0u; } diff --git a/src/video_core/amdgpu/types.h b/src/video_core/amdgpu/types.h index ee2dda494..d991e0abd 100644 --- a/src/video_core/amdgpu/types.h +++ b/src/video_core/amdgpu/types.h @@ -183,7 +183,7 @@ enum class NumberFormat : u32 { Ubscaled = 13, }; -enum class CompSwizzle : u32 { +enum class CompSwizzle : u8 { Zero = 0, One = 1, Red = 4, @@ -193,10 +193,10 @@ enum class CompSwizzle : u32 { }; enum class NumberConversion : u32 { - None, - UintToUscaled, - SintToSscaled, - UnormToUbnorm, + None = 0, + UintToUscaled = 1, + SintToSscaled = 2, + UnormToUbnorm = 3, }; struct CompMapping { diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index ec92a0ebf..188b4b2ca 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -168,7 +168,7 @@ public: void Commit(); /// Maps and commits a memory region with user provided data - u64 Copy(VAddr src, size_t size, size_t alignment = 0) { + u64 Copy(auto src, size_t size, size_t alignment = 0) { const auto [data, offset] = Map(size, alignment); std::memcpy(data, reinterpret_cast(src), size); Commit(); diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 37af62f30..ccb45c095 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -5,11 +5,8 @@ #include "common/alignment.h" #include "common/scope_exit.h" #include "common/types.h" -#include "shader_recompiler/frontend/fetch_shader.h" -#include "shader_recompiler/info.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/buffer_cache/buffer_cache.h" -#include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" @@ -18,8 +15,8 @@ namespace VideoCore { static constexpr size_t DataShareBufferSize = 64_KB; -static constexpr size_t StagingBufferSize = 1_GB; -static constexpr size_t UboStreamBufferSize = 64_MB; +static constexpr size_t StagingBufferSize = 512_MB; +static constexpr size_t UboStreamBufferSize = 128_MB; BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, AmdGpu::Liverpool* liverpool_, TextureCache& texture_cache_, @@ -29,10 +26,8 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s staging_buffer{instance, scheduler, MemoryUsage::Upload, StagingBufferSize}, stream_buffer{instance, scheduler, MemoryUsage::Stream, UboStreamBufferSize}, gds_buffer{instance, scheduler, MemoryUsage::Stream, 0, AllFlags, DataShareBufferSize}, - lds_buffer{instance, scheduler, MemoryUsage::DeviceLocal, 0, AllFlags, DataShareBufferSize}, memory_tracker{&tracker} { Vulkan::SetObjectName(instance.GetDevice(), gds_buffer.Handle(), "GDS Buffer"); - Vulkan::SetObjectName(instance.GetDevice(), lds_buffer.Handle(), "LDS Buffer"); // Ensure the first slot is used for the null buffer const auto null_id = @@ -251,14 +246,6 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo }); } -std::pair BufferCache::ObtainHostUBO(std::span data) { - static constexpr u64 StreamThreshold = CACHING_PAGESIZE; - ASSERT(data.size_bytes() <= StreamThreshold); - const u64 offset = stream_buffer.Copy(reinterpret_cast(data.data()), data.size_bytes(), - instance.UniformMinAlignment()); - return {&stream_buffer, offset}; -} - std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, bool is_written, bool is_texel_buffer, BufferId buffer_id) { // For small uniform buffers that have not been modified by gpu diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 088c22c12..71a6bed2a 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -68,9 +68,9 @@ public: return &gds_buffer; } - /// Returns a pointer to LDS device local buffer. - [[nodiscard]] const Buffer* GetLdsBuffer() const noexcept { - return &lds_buffer; + /// Retrieves the host visible device local stream buffer. + [[nodiscard]] StreamBuffer& GetStreamBuffer() noexcept { + return stream_buffer; } /// Retrieves the buffer with the specified id. @@ -90,8 +90,6 @@ public: /// Writes a value to GPU buffer. void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds); - [[nodiscard]] std::pair ObtainHostUBO(std::span data); - /// Obtains a buffer for the specified region. [[nodiscard]] std::pair ObtainBuffer(VAddr gpu_addr, u32 size, bool is_written, bool is_texel_buffer = false, @@ -159,7 +157,6 @@ private: StreamBuffer staging_buffer; StreamBuffer stream_buffer; Buffer gds_buffer; - Buffer lds_buffer; std::shared_mutex mutex; Common::SlotVector slot_buffers; RangeSet gpu_modified_ranges; diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index f0346559d..f6216f54f 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -3,11 +3,9 @@ #include -#include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" -#include "video_core/texture_cache/texture_cache.h" namespace Vulkan { @@ -29,23 +27,6 @@ ComputePipeline::ComputePipeline(const Instance& instance, Scheduler& scheduler, u32 binding{}; boost::container::small_vector bindings; - - if (info->has_emulated_shared_memory) { - bindings.push_back({ - .binding = binding++, - .descriptorType = vk::DescriptorType::eStorageBuffer, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eCompute, - }); - } - if (info->has_readconst) { - bindings.push_back({ - .binding = binding++, - .descriptorType = vk::DescriptorType::eUniformBuffer, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eCompute, - }); - } for (const auto& buffer : info->buffers) { const auto sharp = buffer.GetSharp(*info); bindings.push_back({ diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 4eecd1edf..2c432e9bf 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -7,18 +7,13 @@ #include #include "common/assert.h" -#include "common/io_file.h" #include "shader_recompiler/backend/spirv/emit_spirv_quad_rect.h" #include "shader_recompiler/frontend/fetch_shader.h" -#include "shader_recompiler/runtime_info.h" #include "video_core/amdgpu/resource.h" -#include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" #include "video_core/renderer_vulkan/vk_instance.h" -#include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" -#include "video_core/texture_cache/texture_cache.h" namespace Vulkan { @@ -357,14 +352,6 @@ void GraphicsPipeline::BuildDescSetLayout() { if (!stage) { continue; } - if (stage->has_readconst) { - bindings.push_back({ - .binding = binding++, - .descriptorType = vk::DescriptorType::eUniformBuffer, - .descriptorCount = 1, - .stageFlags = gp_stage_flags, - }); - } for (const auto& buffer : stage->buffers) { const auto sharp = buffer.GetSharp(*stage); bindings.push_back({ diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 64cc761f4..e6596db2f 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -35,8 +35,7 @@ struct GraphicsPipelineKey { std::array stage_hashes; u32 num_color_attachments; std::array color_formats; - std::array - color_buffers; + std::array color_buffers; vk::Format depth_format; vk::Format stencil_format; diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 780779c0b..a17f8c9c2 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -1,14 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include #include #include #include #include "common/assert.h" -#include "common/config.h" #include "common/debug.h" #include "sdl_window.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" @@ -206,13 +203,12 @@ std::string Instance::GetDriverVersionName() { } bool Instance::CreateDevice() { - const vk::StructureChain feature_chain = - physical_device - .getFeatures2(); + const vk::StructureChain feature_chain = physical_device.getFeatures2< + vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features, + vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceRobustness2FeaturesEXT, + vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT, + vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, + vk::PhysicalDevicePortabilitySubsetFeaturesKHR>(); features = feature_chain.get().features; #ifdef __APPLE__ portability_features = feature_chain.get(); @@ -319,6 +315,7 @@ bool Instance::CreateDevice() { const auto topology_list_restart_features = feature_chain.get(); + const auto vk11_features = feature_chain.get(); const auto vk12_features = feature_chain.get(); vk::StructureChain device_chain = { vk::DeviceCreateInfo{ @@ -351,12 +348,17 @@ bool Instance::CreateDevice() { }, }, vk::PhysicalDeviceVulkan11Features{ - .shaderDrawParameters = true, + .storageBuffer16BitAccess = vk11_features.storageBuffer16BitAccess, + .uniformAndStorageBuffer16BitAccess = vk11_features.uniformAndStorageBuffer16BitAccess, + .shaderDrawParameters = vk11_features.shaderDrawParameters, }, vk::PhysicalDeviceVulkan12Features{ .samplerMirrorClampToEdge = vk12_features.samplerMirrorClampToEdge, .drawIndirectCount = vk12_features.drawIndirectCount, + .storageBuffer8BitAccess = vk12_features.storageBuffer8BitAccess, + .uniformAndStorageBuffer8BitAccess = vk12_features.uniformAndStorageBuffer8BitAccess, .shaderFloat16 = vk12_features.shaderFloat16, + .shaderInt8 = vk12_features.shaderInt8, .scalarBlockLayout = vk12_features.scalarBlockLayout, .uniformBufferStandardLayout = vk12_features.uniformBufferStandardLayout, .separateDepthStencilLayouts = vk12_features.separateDepthStencilLayouts, diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index f7afd2e75..6ac7f7e43 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -345,12 +345,12 @@ bool PipelineCache::RefreshGraphicsKey() { key.color_formats[remapped_cb] = LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt()); - key.color_buffers[remapped_cb] = { + key.color_buffers[remapped_cb] = Shader::PsColorBuffer{ .num_format = col_buf.GetNumberFmt(), .num_conversion = col_buf.GetNumberConversion(), - .swizzle = col_buf.Swizzle(), .export_format = regs.color_export_format.GetFormat(cb), .needs_unorm_fixup = needs_unorm_fixup, + .swizzle = col_buf.Swizzle(), }; } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index ac6aac7b3..816f149b0 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -19,6 +19,20 @@ namespace Vulkan { +static Shader::PushData MakeUserData(const AmdGpu::Liverpool::Regs& regs) { + Shader::PushData push_data{}; + push_data.step0 = regs.vgt_instance_step_rate_0; + push_data.step1 = regs.vgt_instance_step_rate_1; + + // TODO(roamic): Add support for multiple viewports and geometry shaders when ViewportIndex + // is encountered and implemented in the recompiler. + push_data.xoffset = regs.viewport_control.xoffset_enable ? regs.viewports[0].xoffset : 0.f; + push_data.xscale = regs.viewport_control.xscale_enable ? regs.viewports[0].xscale : 1.f; + push_data.yoffset = regs.viewport_control.yoffset_enable ? regs.viewports[0].yoffset : 0.f; + push_data.yscale = regs.viewport_control.yscale_enable ? regs.viewports[0].yscale : 1.f; + return push_data; +} + Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_, AmdGpu::Liverpool* liverpool_) : instance{instance_}, scheduler{scheduler_}, page_manager{this}, @@ -426,95 +440,69 @@ void Rasterizer::Finish() { } bool Rasterizer::BindResources(const Pipeline* pipeline) { - buffer_infos.clear(); - buffer_views.clear(); - image_infos.clear(); - - const auto& regs = liverpool->regs; - - if (pipeline->IsCompute()) { - const auto& info = pipeline->GetStage(Shader::LogicalStage::Compute); - - // Assume if a shader reads and writes metas at the same time, it is a copy shader. - bool meta_read = false; - for (const auto& desc : info.buffers) { - if (desc.is_gds_buffer) { - continue; - } - if (!desc.is_written) { - const VAddr address = desc.GetSharp(info).base_address; - meta_read = texture_cache.IsMeta(address); - } - } - - // Most of the time when a metadata is updated with a shader it gets cleared. It means - // we can skip the whole dispatch and update the tracked state instead. Also, it is not - // intended to be consumed and in such rare cases (e.g. HTile introspection, CRAA) we - // will need its full emulation anyways. For cases of metadata read a warning will be - // logged. - if (!meta_read) { - for (const auto& desc : info.buffers) { - const auto sharp = desc.GetSharp(info); - const VAddr address = sharp.base_address; - if (desc.is_written) { - // Assume all slices were updates - if (texture_cache.ClearMeta(address)) { - LOG_TRACE(Render_Vulkan, "Metadata update skipped"); - return false; - } - } else { - if (texture_cache.IsMeta(address)) { - LOG_WARNING(Render_Vulkan, - "Unexpected metadata read by a CS shader (buffer)"); - } - } - } - } + if (IsComputeMetaClear(pipeline)) { + return false; } set_writes.clear(); buffer_barriers.clear(); + buffer_infos.clear(); + buffer_views.clear(); + image_infos.clear(); // Bind resource buffers and textures. - Shader::PushData push_data{}; Shader::Backend::Bindings binding{}; - + Shader::PushData push_data = MakeUserData(liverpool->regs); for (const auto* stage : pipeline->GetStages()) { if (!stage) { continue; } - push_data.step0 = regs.vgt_instance_step_rate_0; - push_data.step1 = regs.vgt_instance_step_rate_1; - - // TODO(roamic): add support for multiple viewports and geometry shaders when ViewportIndex - // is encountered and implemented in the recompiler. - if (stage->stage == Shader::Stage::Vertex) { - push_data.xoffset = - regs.viewport_control.xoffset_enable ? regs.viewports[0].xoffset : 0.f; - push_data.xscale = regs.viewport_control.xscale_enable ? regs.viewports[0].xscale : 1.f; - push_data.yoffset = - regs.viewport_control.yoffset_enable ? regs.viewports[0].yoffset : 0.f; - push_data.yscale = regs.viewport_control.yscale_enable ? regs.viewports[0].yscale : 1.f; - } stage->PushUd(binding, push_data); - - BindBuffers(*stage, binding, push_data, set_writes, buffer_barriers); - BindTextures(*stage, binding, set_writes); + BindBuffers(*stage, binding, push_data); + BindTextures(*stage, binding); } pipeline->BindResources(set_writes, buffer_barriers, push_data); - return true; } +bool Rasterizer::IsComputeMetaClear(const Pipeline* pipeline) { + if (!pipeline->IsCompute()) { + return false; + } + + const auto& info = pipeline->GetStage(Shader::LogicalStage::Compute); + + // Assume if a shader reads and writes metas at the same time, it is a copy shader. + for (const auto& desc : info.buffers) { + const VAddr address = desc.GetSharp(info).base_address; + if (!desc.IsSpecial() && !desc.is_written && texture_cache.IsMeta(address)) { + return false; + } + } + + // Most of the time when a metadata is updated with a shader it gets cleared. It means + // we can skip the whole dispatch and update the tracked state instead. Also, it is not + // intended to be consumed and in such rare cases (e.g. HTile introspection, CRAA) we + // will need its full emulation anyways. + for (const auto& desc : info.buffers) { + const VAddr address = desc.GetSharp(info).base_address; + if (!desc.IsSpecial() && desc.is_written && texture_cache.ClearMeta(address)) { + // Assume all slices were updates + LOG_TRACE(Render_Vulkan, "Metadata update skipped"); + return true; + } + } + return false; +} + void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Bindings& binding, - Shader::PushData& push_data, Pipeline::DescriptorWrites& set_writes, - Pipeline::BufferBarriers& buffer_barriers) { + Shader::PushData& push_data) { buffer_bindings.clear(); for (const auto& desc : stage.buffers) { const auto vsharp = desc.GetSharp(stage); - if (!desc.is_gds_buffer && vsharp.base_address != 0 && vsharp.GetSize() > 0) { + if (!desc.IsSpecial() && vsharp.base_address != 0 && vsharp.GetSize() > 0) { const auto buffer_id = buffer_cache.FindBuffer(vsharp.base_address, vsharp.GetSize()); buffer_bindings.emplace_back(buffer_id, vsharp); } else { @@ -522,47 +510,30 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding } } - // Bind a SSBO to act as shared memory in case of not being able to use a workgroup buffer - // (e.g. when the compute shared memory is bigger than the GPU's shared memory) - if (stage.has_emulated_shared_memory) { - const auto* lds_buf = buffer_cache.GetLdsBuffer(); - buffer_infos.emplace_back(lds_buf->Handle(), 0, lds_buf->SizeBytes()); - set_writes.push_back({ - .dstSet = VK_NULL_HANDLE, - .dstBinding = binding.unified++, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eStorageBuffer, - .pBufferInfo = &buffer_infos.back(), - }); - ++binding.buffer; - } - - // Bind the flattened user data buffer as a UBO so it's accessible to the shader - if (stage.has_readconst) { - const auto [vk_buffer, offset] = buffer_cache.ObtainHostUBO(stage.flattened_ud_buf); - buffer_infos.emplace_back(vk_buffer->Handle(), offset, - stage.flattened_ud_buf.size() * sizeof(u32)); - set_writes.push_back({ - .dstSet = VK_NULL_HANDLE, - .dstBinding = binding.unified++, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eUniformBuffer, - .pBufferInfo = &buffer_infos.back(), - }); - ++binding.buffer; - } - // Second pass to re-bind buffers that were updated after binding for (u32 i = 0; i < buffer_bindings.size(); i++) { const auto& [buffer_id, vsharp] = buffer_bindings[i]; const auto& desc = stage.buffers[i]; const bool is_storage = desc.IsStorage(vsharp, pipeline_cache.GetProfile()); + // Buffer is not from the cache, either a special buffer or unbound. if (!buffer_id) { - if (desc.is_gds_buffer) { + if (desc.buffer_type == Shader::BufferType::GdsBuffer) { const auto* gds_buf = buffer_cache.GetGdsBuffer(); buffer_infos.emplace_back(gds_buf->Handle(), 0, gds_buf->SizeBytes()); + } else if (desc.buffer_type == Shader::BufferType::ReadConstUbo) { + auto& vk_buffer = buffer_cache.GetStreamBuffer(); + const u32 ubo_size = stage.flattened_ud_buf.size() * sizeof(u32); + const u64 offset = vk_buffer.Copy(stage.flattened_ud_buf.data(), ubo_size, + instance.UniformMinAlignment()); + buffer_infos.emplace_back(vk_buffer.Handle(), offset, ubo_size); + } else if (desc.buffer_type == Shader::BufferType::SharedMemory) { + auto& lds_buffer = buffer_cache.GetStreamBuffer(); + const auto& cs_program = liverpool->GetCsRegs(); + const auto lds_size = cs_program.SharedMemSize() * cs_program.NumWorkgroups(); + const auto [data, offset] = + lds_buffer.Map(lds_size, instance.StorageMinAlignment()); + std::memset(data, 0, lds_size); + buffer_infos.emplace_back(lds_buffer.Handle(), offset, lds_size); } else if (instance.IsNullDescriptorSupported()) { buffer_infos.emplace_back(VK_NULL_HANDLE, 0, VK_WHOLE_SIZE); } else { @@ -605,8 +576,7 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding } } -void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindings& binding, - Pipeline::DescriptorWrites& set_writes) { +void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindings& binding) { image_bindings.clear(); for (const auto& image_desc : stage.images) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index db458662c..292944a10 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -81,11 +81,9 @@ private: bool FilterDraw(); void BindBuffers(const Shader::Info& stage, Shader::Backend::Bindings& binding, - Shader::PushData& push_data, Pipeline::DescriptorWrites& set_writes, - Pipeline::BufferBarriers& buffer_barriers); + Shader::PushData& push_data); - void BindTextures(const Shader::Info& stage, Shader::Backend::Bindings& binding, - Pipeline::DescriptorWrites& set_writes); + void BindTextures(const Shader::Info& stage, Shader::Backend::Bindings& binding); bool BindResources(const Pipeline* pipeline); void ResetBindings() { @@ -95,6 +93,8 @@ private: bound_images.clear(); } + bool IsComputeMetaClear(const Pipeline* pipeline); + private: const Instance& instance; Scheduler& scheduler; From bdf4a5249d1f0814b4c7f026cf18f15ff1435722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:53:25 +0100 Subject: [PATCH 03/29] imgui: Displays FPS color based on FPS (#2437) --- src/common/config.cpp | 7 +++++++ src/common/config.h | 1 + src/core/devtools/layer.cpp | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/common/config.cpp b/src/common/config.cpp index aae903da6..a42709b7a 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -68,6 +68,7 @@ static bool vkCrashDiagnostic = false; static bool vkHostMarkers = false; static bool vkGuestMarkers = false; static bool rdocEnable = false; +static bool isFpsColor = true; static s16 cursorState = HideCursorState::Idle; static int cursorHideTimeout = 5; // 5 seconds (default) static bool useUnifiedInputConfig = true; @@ -282,6 +283,10 @@ bool isRdocEnabled() { return rdocEnable; } +bool fpsColor() { + return isFpsColor; +} + u32 vblankDiv() { return vblankDivider; } @@ -757,6 +762,7 @@ void load(const std::filesystem::path& path) { isDebugDump = toml::find_or(debug, "DebugDump", false); isShaderDebug = toml::find_or(debug, "CollectShader", false); + isFpsColor = toml::find_or(debug, "FPSColor", true); } if (data.contains("GUI")) { @@ -881,6 +887,7 @@ void save(const std::filesystem::path& path) { data["Vulkan"]["rdocEnable"] = rdocEnable; data["Debug"]["DebugDump"] = isDebugDump; data["Debug"]["CollectShader"] = isShaderDebug; + data["Debug"]["FPSColor"] = isFpsColor; data["Keys"]["TrophyKey"] = trophyKey; diff --git a/src/common/config.h b/src/common/config.h index dfb1d9fad..7b9bc789b 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -67,6 +67,7 @@ bool copyGPUCmdBuffers(); bool dumpShaders(); bool patchShaders(); bool isRdocEnabled(); +bool fpsColor(); u32 vblankDiv(); void setDebugDump(bool enable); diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp index a6d99b49b..603d76df5 100644 --- a/src/core/devtools/layer.cpp +++ b/src/core/devtools/layer.cpp @@ -259,7 +259,19 @@ void L::DrawAdvanced() { void L::DrawSimple() { const float frameRate = DebugState.Framerate; + if (Config::fpsColor()) { + if (frameRate < 10) { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); // Red + } else if (frameRate >= 10 && frameRate < 20) { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f)); // Orange + } else { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); // White + } + } else { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); // White + } Text("%d FPS (%.1f ms)", static_cast(std::round(frameRate)), 1000.0f / frameRate); + PopStyleColor(); } static void LoadSettings(const char* line) { From 2b9a8e5605eae426d34336aa95ddbb475889c9be Mon Sep 17 00:00:00 2001 From: rainmakerv2 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 16 Feb 2025 00:19:04 +0800 Subject: [PATCH 04/29] add lightbar color override to Controller GUI (#2443) * WIP Lightbar GUI, needs saving and loading * Implement saving and loading lightbar values * replace license header deleted by QT --- src/qt_gui/control_settings.cpp | 93 +- src/qt_gui/control_settings.h | 1 + src/qt_gui/control_settings.ui | 2450 ++++++++++++++++--------------- 3 files changed, 1375 insertions(+), 1169 deletions(-) diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index 644576feb..73622e6b0 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -3,9 +3,9 @@ #include #include +#include #include "common/path_util.h" #include "control_settings.h" -#include "kbm_config_dialog.h" #include "ui_control_settings.h" ControlSettings::ControlSettings(std::shared_ptr game_info_get, QWidget* parent) @@ -16,7 +16,7 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, Q AddBoxItems(); SetUIValuestoMappings(); - ui->KBMButton->setFocus(); + UpdateLightbarColor(); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, [this](QAbstractButton* button) { if (button == ui->buttonBox->button(QDialogButtonBox::Save)) { @@ -29,11 +29,7 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, Q }); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close); - connect(ui->KBMButton, &QPushButton::clicked, this, [this] { - auto KBMWindow = new EditorDialog(this); - KBMWindow->exec(); - SetUIValuestoMappings(); - }); + connect(ui->ProfileComboBox, &QComboBox::currentTextChanged, this, [this] { GetGameTitle(); SetUIValuestoMappings(); @@ -61,6 +57,27 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, Q [this](int value) { ui->RStickLeftBox->setCurrentIndex(value); }); connect(ui->RStickLeftBox, &QComboBox::currentIndexChanged, this, [this](int value) { ui->RStickRightBox->setCurrentIndex(value); }); + + connect(ui->RSlider, &QSlider::valueChanged, this, [this](int value) { + QString RedValue = QString("%1").arg(value, 3, 10, QChar('0')); + QString RValue = "R: " + RedValue; + ui->RLabel->setText(RValue); + UpdateLightbarColor(); + }); + + connect(ui->GSlider, &QSlider::valueChanged, this, [this](int value) { + QString GreenValue = QString("%1").arg(value, 3, 10, QChar('0')); + QString GValue = "G: " + GreenValue; + ui->GLabel->setText(GValue); + UpdateLightbarColor(); + }); + + connect(ui->BSlider, &QSlider::valueChanged, this, [this](int value) { + QString BlueValue = QString("%1").arg(value, 3, 10, QChar('0')); + QString BValue = "B: " + BlueValue; + ui->BLabel->setText(BValue); + UpdateLightbarColor(); + }); } void ControlSettings::SaveControllerConfig(bool CloseOnSave) { @@ -121,7 +138,7 @@ void ControlSettings::SaveControllerConfig(bool CloseOnSave) { if (std::find(ControllerInputs.begin(), ControllerInputs.end(), input_string) != ControllerInputs.end() || - output_string == "analog_deadzone") { + output_string == "analog_deadzone" || output_string == "override_controller_color") { line.erase(); continue; } @@ -227,6 +244,14 @@ void ControlSettings::SaveControllerConfig(bool CloseOnSave) { deadzonevalue = std::to_string(ui->RightDeadzoneSlider->value()); lines.push_back("analog_deadzone = rightjoystick, " + deadzonevalue + ", 127"); + lines.push_back(""); + std::string OverrideLB = ui->LightbarCheckBox->isChecked() ? "true" : "false"; + std::string LightBarR = std::to_string(ui->RSlider->value()); + std::string LightBarG = std::to_string(ui->GSlider->value()); + std::string LightBarB = std::to_string(ui->BSlider->value()); + lines.push_back("override_controller_color = " + OverrideLB + ", " + LightBarR + ", " + + LightBarG + ", " + LightBarB); + std::vector save; bool CurrentLineEmpty = false, LastLineEmpty = false; for (auto const& line : lines) { @@ -243,6 +268,9 @@ void ControlSettings::SaveControllerConfig(bool CloseOnSave) { output_file.close(); Config::SetUseUnifiedInputConfig(!ui->PerGameCheckBox->isChecked()); + Config::SetOverrideControllerColor(ui->LightbarCheckBox->isChecked()); + Config::SetControllerCustomColor(ui->RSlider->value(), ui->GSlider->value(), + ui->BSlider->value()); Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); if (CloseOnSave) @@ -351,7 +379,7 @@ void ControlSettings::SetUIValuestoMappings() { if (std::find(ControllerInputs.begin(), ControllerInputs.end(), input_string) != ControllerInputs.end() || - output_string == "analog_deadzone") { + output_string == "analog_deadzone" || output_string == "override_controller_color") { if (input_string == "cross") { ui->ABox->setCurrentText(QString::fromStdString(output_string)); CrossExists = true; @@ -436,9 +464,45 @@ void ControlSettings::SetUIValuestoMappings() { ui->RightDeadzoneSlider->setValue(2); ui->RightDeadzoneValue->setText("2"); } + } else if (output_string == "override_controller_color") { + std::size_t comma_pos = line.find(','); + if (comma_pos != std::string::npos) { + std::string overridestring = line.substr(equal_pos + 1, comma_pos); + bool override = overridestring.contains("true") ? true : false; + ui->LightbarCheckBox->setChecked(override); + + std::string lightbarstring = line.substr(comma_pos + 1); + std::size_t comma_pos2 = lightbarstring.find(','); + if (comma_pos2 != std::string::npos) { + std::string Rstring = lightbarstring.substr(0, comma_pos2); + ui->RSlider->setValue(std::stoi(Rstring)); + QString RedValue = QString("%1").arg(std::stoi(Rstring), 3, 10, QChar('0')); + QString RValue = "R: " + RedValue; + ui->RLabel->setText(RValue); + } + + std::string GBstring = lightbarstring.substr(comma_pos2 + 1); + std::size_t comma_pos3 = GBstring.find(','); + if (comma_pos3 != std::string::npos) { + std::string Gstring = GBstring.substr(0, comma_pos3); + ui->GSlider->setValue(std::stoi(Gstring)); + QString GreenValue = + QString("%1").arg(std::stoi(Gstring), 3, 10, QChar('0')); + QString GValue = "G: " + GreenValue; + ui->GLabel->setText(GValue); + + std::string Bstring = GBstring.substr(comma_pos3 + 1); + ui->BSlider->setValue(std::stoi(Bstring)); + QString BlueValue = + QString("%1").arg(std::stoi(Bstring), 3, 10, QChar('0')); + QString BValue = "B: " + BlueValue; + ui->BLabel->setText(BValue); + } + } } } } + file.close(); // If an entry does not exist in the config file, we assume the user wants it unmapped if (!CrossExists) @@ -490,8 +554,6 @@ void ControlSettings::SetUIValuestoMappings() { ui->RStickUpBox->setCurrentText("unmapped"); ui->RStickDownBox->setCurrentText("unmapped"); } - - file.close(); } void ControlSettings::GetGameTitle() { @@ -507,4 +569,13 @@ void ControlSettings::GetGameTitle() { } } +void ControlSettings::UpdateLightbarColor() { + ui->LightbarColorFrame->setStyleSheet(""); + QString RValue = QString::number(ui->RSlider->value()); + QString GValue = QString::number(ui->GSlider->value()); + QString BValue = QString::number(ui->BSlider->value()); + QString colorstring = "background-color: rgb(" + RValue + "," + GValue + "," + BValue + ")"; + ui->LightbarColorFrame->setStyleSheet(colorstring); +} + ControlSettings::~ControlSettings() {} diff --git a/src/qt_gui/control_settings.h b/src/qt_gui/control_settings.h index 04227f3a8..e686f044d 100644 --- a/src/qt_gui/control_settings.h +++ b/src/qt_gui/control_settings.h @@ -18,6 +18,7 @@ public: private Q_SLOTS: void SaveControllerConfig(bool CloseOnSave); void SetDefault(); + void UpdateLightbarColor(); private: std::unique_ptr ui; diff --git a/src/qt_gui/control_settings.ui b/src/qt_gui/control_settings.ui index b6acb5ca9..e88e239e9 100644 --- a/src/qt_gui/control_settings.ui +++ b/src/qt_gui/control_settings.ui @@ -11,8 +11,8 @@ 0 0 - 1012 - 721 + 1043 + 792 @@ -25,760 +25,681 @@ - - QFrame::Shape::NoFrame - - - 0 - true - + 0 0 - 994 - 673 + 1019 + 732 - - - Control Settings - - - - 5 - - - 5 - - - 5 - - - 5 - + + + + 0 + 0 + 1021 + 731 + + + - + + + 5 + - - - 5 + + + true - - - - true - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - D-Pad - - - - 6 - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - 0 + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + D-Pad + + + + 6 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 124 + 0 + + + + 0 + 16777215 + + + + Up + + + + + + false + + + QComboBox::SizeAdjustPolicy::AdjustToContents + + + + + + + + + + + + + + + Left + + - 0 + 5 - 0 + 5 - 0 + 5 - 0 + 5 - - - - 124 - 0 - - - - - 0 - 16777215 - - - - Up - - - - - - false - - - QComboBox::SizeAdjustPolicy::AdjustToContents - - - - - + - - - - - Left - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - - - - Right - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - false - - - - - - - - - - - + + + Right + + - 0 + 5 - 0 + 5 - 0 + 5 - 0 + 5 - - - - 124 - 16777215 - + + + false - - Down - - - - - - true - - - - 0 - 0 - - - - - 0 - 0 - - - - - - - - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::Maximum - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - Left Stick Deadzone (def:2 max:127) - - - - - - - 0 - 0 - - - - Left Deadzone - - - Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter - - - - - - - - 0 - 0 - - - - 1 - - - 127 - - - Qt::Orientation::Horizontal - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Left Stick - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - 16777215 - 2121 - - - - - 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 124 + 16777215 + - - 0 + + Down - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 124 - 16777215 - - - - Up - - - - - - true - - - - - - - - - - - - - - - Left - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - true - - - - - - - - - - - 179 - 16777215 - - - - Right - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - true - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 124 - 0 - - - - - 124 - 21212 - - - - Down - - - - - - true - - - false - - - false - - - - - - - - - - - - - + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + + + + + - - - 0 + + + Qt::Orientation::Vertical - - - - - 0 - 0 - - - - - 12 - true - - - - Config Selection - - - Qt::AlignmentFlag::AlignCenter - - + + QSizePolicy::Policy::Maximum + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Left Stick Deadzone (def:2 max:127) + + + + + + + 0 + 0 + + + + Left Deadzone + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + 0 + 0 + + + + 1 + + + 127 + + + Qt::Orientation::Horizontal + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Left Stick + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 16777215 + 2121 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 124 + 16777215 + + + + Up + + + + + + true + + + + + + + + + + + - - - - - - 9 - false - - - - - - - -1 - - - Common Config - - - - - - - - 10 - true - - - - Common Config - - - Qt::AlignmentFlag::AlignCenter - - - true - - - - + + + Left + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + true + + + + + - - - - 0 - 0 - + + + + 179 + 16777215 + + + Right + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + true + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 124 + 0 + + + + + 124 + 21212 + + + + Down + + + + + + true + + + false + + + false + + + + + + + + + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + + 12 + true + + + + Config Selection + + + Qt::AlignmentFlag::AlignCenter + + + + + + 9 false + + + + + -1 + + + Common Config + + + + + + + + 10 + true + + - Use per-game configs + Common Config + + + Qt::AlignmentFlag::AlignCenter + + + true - + + + + + + 0 + 0 + + + + + 9 + false + + + + Use per-game configs + + + + + + + + + + 0 + + + + + + + L1 / LB + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + + L2 / LT + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + - - - 0 - + - - - - - L1 / LB - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - - - - L2 / LT - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - + + + Qt::Orientation::Vertical + + + QSizePolicy::Policy::Preferred + + + + 20 + 40 + + + - + + + 10 + - - - 10 - - - - - - true - - - - KBM Controls - - - - - - - true - - - - KBM Editor - - - - - - - - - - Back - - - - - - - - - - - - - - - - + - R1 / RB + Back - - - 5 - - - 5 - - - 5 - - - 5 - + - - - - - - - - - R2 / RT - - - - 5 - - - 5 - - - 5 - - - 5 - - - + @@ -788,62 +709,13 @@ - - - - 0 - 200 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 415 - 256 - - - - :/images/ps4_controller.png - - - true - - - Qt::AlignmentFlag::AlignBottom|Qt::AlignmentFlag::AlignHCenter - - - - - - - - - - 10 - - - QLayout::SizeConstraint::SetDefaultConstraint - + - + - L3 + R1 / RB - + 5 @@ -857,17 +729,17 @@ 5 - + - + - Options / Start + R2 / RT - + 5 @@ -881,31 +753,7 @@ 5 - - - - - - - - - R3 - - - - 5 - - - 5 - - - 5 - - - 5 - - - + @@ -915,22 +763,62 @@ - + + + + 0 + 200 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 415 + 256 + + + + :/images/ps4_controller.png + + + true + + + Qt::AlignmentFlag::AlignBottom|Qt::AlignmentFlag::AlignHCenter + + + + + + + + - 5 + 10 + + + QLayout::SizeConstraint::SetDefaultConstraint - - - - 0 - 0 - - + - Face Buttons + L3 - + 5 @@ -944,244 +832,17 @@ 5 - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 124 - 0 - - - - - 0 - 16777215 - - - - Triangle / Y - - - - - - true - - - - 0 - 0 - - - - - - - - - - - - - - - - Square / X - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - - - - Circle / B - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 124 - 0 - - - - - 124 - 16777215 - - - - Cross / A - - - - - - - - - - + - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::Maximum - - - - 20 - 40 - - - - - - - - - 0 - 0 - - + - Right Stick Deadzone (def:2, max:127) + Options / Start - - - - - - 0 - 0 - - - - Right Deadzone - - - Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter - - - - - - - - 0 - 0 - - - - 1 - - - 127 - - - Qt::Orientation::Horizontal - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Right Stick - - + 5 @@ -1195,164 +856,637 @@ 5 - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 124 - 1231321 - - - - Up - - - - - - true - - - - - - - - + + + + + + + + R3 + + + + 5 + + + 5 + + + 5 + + + 5 + - - - - - Left - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - true - - - - - - - - - - Right - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 124 - 0 - - - - - 124 - 2121 - - - - Down - - - - - - true - - - - - - - - + + + + + + + + + + false + + + + Color Adjustment + + + + + + + + + false + + + + R: 000 + + + + + + + + 0 + 0 + + + + 255 + + + Qt::Orientation::Horizontal + + + + + + + + + + + + false + + + + G: 000 + + + + + + + + 0 + 0 + + + + 255 + + + Qt::Orientation::Horizontal + + + + + + + + + + + + false + + + + B: 255 + + + + + + + + 0 + 0 + + + + 255 + + + 255 + + + Qt::Orientation::Horizontal + + + + + + + + + + + + + + + + + false + + + + Override Lightbar Color + + + + + + + false + + + + Override Color + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + + + + + + + + + + + + 5 + + + + + + 0 + 0 + + + + Face Buttons + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 124 + 0 + + + + + 0 + 16777215 + + + + Triangle / Y + + + + + + true + + + + 0 + 0 + + + + + + + + + + + + + + + + Square / X + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + + Circle / B + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 124 + 0 + + + + + 124 + 16777215 + + + + Cross / A + + + + + + + + + + + + + + + + + + Qt::Orientation::Vertical + + + QSizePolicy::Policy::Maximum + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Right Stick Deadzone (def:2, max:127) + + + + + + + 0 + 0 + + + + Right Deadzone + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + 0 + 0 + + + + 1 + + + 127 + + + Qt::Orientation::Horizontal + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Right Stick + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 124 + 1231321 + + + + Up + + + + + + true + + + + + + + + + + + + + + + Left + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + true + + + + + + + + + + Right + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 124 + 0 + + + + + 124 + 2121 + + + + Down + + + + + + true + + + + + + + + + + + + From e042710eaad0c89beb3610cc4ce65cfc15e3b0b5 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 15 Feb 2025 13:19:33 -0300 Subject: [PATCH 05/29] Background image sized correctly (#2451) --- src/qt_gui/game_grid_frame.cpp | 18 ++++++++++++++++-- src/qt_gui/game_grid_frame.h | 2 ++ src/qt_gui/game_list_frame.cpp | 18 ++++++++++++++++-- src/qt_gui/game_list_frame.h | 1 + 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/qt_gui/game_grid_frame.cpp b/src/qt_gui/game_grid_frame.cpp index 6a42fb1d6..e06fea090 100644 --- a/src/qt_gui/game_grid_frame.cpp +++ b/src/qt_gui/game_grid_frame.cpp @@ -196,14 +196,28 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) { void GameGridFrame::RefreshGridBackgroundImage() { QPalette palette; if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) { - palette.setBrush(QPalette::Base, - QBrush(backgroundImage.scaled(size(), Qt::IgnoreAspectRatio))); + QSize widgetSize = size(); + QPixmap scaledPixmap = + QPixmap::fromImage(backgroundImage) + .scaled(widgetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + int x = (widgetSize.width() - scaledPixmap.width()) / 2; + int y = (widgetSize.height() - scaledPixmap.height()) / 2; + QPixmap finalPixmap(widgetSize); + finalPixmap.fill(Qt::transparent); + QPainter painter(&finalPixmap); + painter.drawPixmap(x, y, scaledPixmap); + palette.setBrush(QPalette::Base, QBrush(finalPixmap)); } QColor transparentColor = QColor(135, 206, 235, 40); palette.setColor(QPalette::Highlight, transparentColor); this->setPalette(palette); } +void GameGridFrame::resizeEvent(QResizeEvent* event) { + QTableWidget::resizeEvent(event); + RefreshGridBackgroundImage(); +} + bool GameGridFrame::IsValidCellSelected() { return validCellSelected; } diff --git a/src/qt_gui/game_grid_frame.h b/src/qt_gui/game_grid_frame.h index 370b71dcb..14596f8e1 100644 --- a/src/qt_gui/game_grid_frame.h +++ b/src/qt_gui/game_grid_frame.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include "background_music_player.h" @@ -21,6 +22,7 @@ Q_SIGNALS: public Q_SLOTS: void SetGridBackgroundImage(int row, int column); void RefreshGridBackgroundImage(); + void resizeEvent(QResizeEvent* event); void PlayBackgroundMusic(QString path); void onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index 2caae35b0..4c0607571 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -200,14 +200,28 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) { void GameListFrame::RefreshListBackgroundImage() { QPalette palette; if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) { - palette.setBrush(QPalette::Base, - QBrush(backgroundImage.scaled(size(), Qt::IgnoreAspectRatio))); + QSize widgetSize = size(); + QPixmap scaledPixmap = + QPixmap::fromImage(backgroundImage) + .scaled(widgetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + int x = (widgetSize.width() - scaledPixmap.width()) / 2; + int y = (widgetSize.height() - scaledPixmap.height()) / 2; + QPixmap finalPixmap(widgetSize); + finalPixmap.fill(Qt::transparent); + QPainter painter(&finalPixmap); + painter.drawPixmap(x, y, scaledPixmap); + palette.setBrush(QPalette::Base, QBrush(finalPixmap)); } QColor transparentColor = QColor(135, 206, 235, 40); palette.setColor(QPalette::Highlight, transparentColor); this->setPalette(palette); } +void GameListFrame::resizeEvent(QResizeEvent* event) { + QTableWidget::resizeEvent(event); + RefreshListBackgroundImage(); +} + void GameListFrame::SortNameAscending(int columnIndex) { std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(), [columnIndex](const GameInfo& a, const GameInfo& b) { diff --git a/src/qt_gui/game_list_frame.h b/src/qt_gui/game_list_frame.h index b2e5f1e2f..782db6bae 100644 --- a/src/qt_gui/game_list_frame.h +++ b/src/qt_gui/game_list_frame.h @@ -30,6 +30,7 @@ Q_SIGNALS: public Q_SLOTS: void SetListBackgroundImage(QTableWidgetItem* item); void RefreshListBackgroundImage(); + void resizeEvent(QResizeEvent* event); void SortNameAscending(int columnIndex); void SortNameDescending(int columnIndex); void PlayBackgroundMusic(QTableWidgetItem* item); From b0169de7c4ba2e47d4a0044fd940308f70ae8450 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 15 Feb 2025 16:40:24 -0300 Subject: [PATCH 06/29] added language pt_PT (#2452) --- src/common/config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index a42709b7a..4383b64b5 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -813,8 +813,8 @@ void load(const std::filesystem::path& path) { // Check if the loaded language is in the allowed list const std::vector allowed_languages = { "ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", "fr_FR", "hu_HU", - "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nl_NL", "no_NO", "pl_PL", "pt_BR", "ro_RO", - "ru_RU", "sq_AL", "sv_SE", "tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW"}; + "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nl_NL", "no_NO", "pl_PL", "pt_BR", "pt_PT", + "ro_RO", "ru_RU", "sq_AL", "sv_SE", "tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW"}; if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) == allowed_languages.end()) { From 7af9de353b1e2147442e2834165d258383fb134b Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 16 Feb 2025 09:40:28 +0200 Subject: [PATCH 07/29] New Crowdin updates (#2440) * New translations en_us.ts (Russian) * New translations en_us.ts (Chinese Simplified) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Japanese) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Turkish) * New translations en_us.ts (Turkish) * New translations en_us.ts (Turkish) * New translations en_us.ts (Chinese Simplified) * New translations en_us.ts (Turkish) * New translations en_us.ts (Norwegian Bokmal) --- src/qt_gui/translations/ja_JP.ts | 108 +- src/qt_gui/translations/nb_NO.ts | 1790 ++++++++++++++++++++++++++++++ src/qt_gui/translations/pt_BR.ts | 14 +- src/qt_gui/translations/pt_PT.ts | 1790 ++++++++++++++++++++++++++++++ src/qt_gui/translations/ru_RU.ts | 8 +- src/qt_gui/translations/tr_TR.ts | 52 +- src/qt_gui/translations/zh_CN.ts | 6 +- 7 files changed, 3674 insertions(+), 94 deletions(-) create mode 100644 src/qt_gui/translations/nb_NO.ts create mode 100644 src/qt_gui/translations/pt_PT.ts diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index fd1de8f78..502070bb5 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -11,7 +11,7 @@ shadPS4 - shadPS4 + shadPS4 shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -411,35 +411,35 @@ ControlSettings Configure Controls - Configure Controls + コントロール設定 Control Settings - Control Settings + 操作設定 D-Pad - D-Pad + 十字キー Up - Up + Left - Left + Right - Right + Down - Down + Left Stick Deadzone (def:2 max:127) - Left Stick Deadzone (def:2 max:127) + 左スティックデッドゾーン(既定:2 最大:127) Left Deadzone @@ -447,7 +447,7 @@ Left Stick - Left Stick + 左スティック Config Selection @@ -463,11 +463,11 @@ L1 / LB - L1 / LB + L1 / LB L2 / LT - L2 / LT + L2 / LT KBM Controls @@ -483,23 +483,23 @@ R1 / RB - R1 / RB + R1 / RB R2 / RT - R2 / RT + R2 / RT L3 - L3 + L3 Options / Start - Options / Start + Options / Start R3 - R3 + R3 Face Buttons @@ -507,23 +507,23 @@ Triangle / Y - Triangle / Y + 三角 / Y Square / X - Square / X + 四角 / X Circle / B - Circle / B + 丸 / B Cross / A - Cross / A + バツ / A Right Stick Deadzone (def:2, max:127) - Right Stick Deadzone (def:2, max:127) + 右スティックデッドゾーン(既定:2, 最大:127) Right Deadzone @@ -531,7 +531,7 @@ Right Stick - Right Stick + 右スティック @@ -576,7 +576,7 @@ Directory to install DLC - Directory to install DLC + DLCをインストールするディレクトリ @@ -595,7 +595,7 @@ Compatibility - Compatibility + 互換性 Region @@ -674,23 +674,23 @@ GameListUtils B - B + B KB - KB + KB MB - MB + MB GB - GB + GB TB - TB + TB @@ -741,11 +741,11 @@ Copy Version - Copy Version + バージョンをコピー Copy Size - Copy Size + サイズをコピー Copy All @@ -821,7 +821,7 @@ DLC - DLC + DLC Delete %1 @@ -833,23 +833,23 @@ Open Update Folder - Open Update Folder + アップデートフォルダを開く Delete Save Data - Delete Save Data + セーブデータを削除 This game has no update folder to open! - This game has no update folder to open! + このゲームにはアップデートフォルダがありません! Failed to convert icon. - Failed to convert icon. + アイコンの変換に失敗しました。 This game has no save data to delete! - This game has no save data to delete! + このゲームには削除するセーブデータがありません! Save Data @@ -872,7 +872,7 @@ Delete PKG File on Install - Delete PKG File on Install + インストール時にPKGファイルを削除 @@ -1151,15 +1151,15 @@ Run Game - Run Game + ゲームを実行 Eboot.bin file not found - Eboot.bin file not found + Eboot.bin ファイルが見つかりません PKG File (*.PKG *.pkg) - PKG File (*.PKG *.pkg) + PKGファイル (*.PKG *.pkg) PKG is a patch or DLC, please install the game first! @@ -1167,11 +1167,11 @@ Game is already running! - Game is already running! + ゲームは既に実行されています! shadPS4 - shadPS4 + shadPS4 @@ -1238,7 +1238,7 @@ Package - Package + パッケージ @@ -1393,7 +1393,7 @@ Enable HDR - Enable HDR + HDRを有効化 Paths @@ -1493,7 +1493,7 @@ Opacity - Opacity + 透明度 Play title music @@ -1729,7 +1729,7 @@ Borderless - Borderless + ボーダーレス True @@ -1737,19 +1737,19 @@ Release - Release + Release Nightly - Nightly + Nightly Set the volume of the background music. - Set the volume of the background music. + バックグラウンドミュージックの音量を設定します。 Enable Motion Controls - Enable Motion Controls + モーションコントロールを有効にする Save Data Path @@ -1761,11 +1761,11 @@ async - async + 非同期 sync - sync + 同期 Auto Select diff --git a/src/qt_gui/translations/nb_NO.ts b/src/qt_gui/translations/nb_NO.ts new file mode 100644 index 000000000..934612683 --- /dev/null +++ b/src/qt_gui/translations/nb_NO.ts @@ -0,0 +1,1790 @@ + + + + + + AboutDialog + + About shadPS4 + Om shadPS4 + + + shadPS4 + shadPS4 + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 er en eksperimentell åpen kildekode-emulator for PlayStation 4. + + + This software should not be used to play games you have not legally obtained. + Denne programvaren skal ikke brukes til å spille spill du ikke har fått lovlig. + + + + CheatsPatches + + Cheats / Patches for + Juks / Programrettelser for + + + Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n + Juks/programrettelse er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned juks individuelt ved å velge pakkebrønn og klikke på nedlastingsknappen.\nPå fanen programrettelse kan du laste ned alle programrettelser samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Juks/Programrettelse,\nvær vennlig å rapportere problemer til juks/programrettelse utvikleren.\n\nHar du laget en ny juks? Besøk:\n + + + No Image Available + Ingen bilde tilgjengelig + + + Serial: + Serienummer: + + + Version: + Versjon: + + + Size: + Størrelse: + + + Select Cheat File: + Velg juksefil: + + + Repository: + Pakkebrønn: + + + Download Cheats + Last ned juks + + + Delete File + Slett fil + + + No files selected. + Ingen filer valgt. + + + You can delete the cheats you don't want after downloading them. + Du kan slette juks du ikke ønsker etter å ha lastet dem ned. + + + Do you want to delete the selected file?\n%1 + Ønsker du å slette den valgte filen?\n%1 + + + Select Patch File: + Velg programrettelse-filen: + + + Download Patches + Last ned programrettelser + + + Save + Lagre + + + Cheats + Juks + + + Patches + Programrettelse + + + Error + Feil + + + No patch selected. + Ingen programrettelse valgt. + + + Unable to open files.json for reading. + Kan ikke åpne files.json for lesing. + + + No patch file found for the current serial. + Ingen programrettelse-fil funnet for det aktuelle serienummeret. + + + Unable to open the file for reading. + Kan ikke åpne filen for lesing. + + + Unable to open the file for writing. + Kan ikke åpne filen for skriving. + + + Failed to parse XML: + Feil ved tolkning av XML: + + + Success + Vellykket + + + Options saved successfully. + Alternativer ble lagret. + + + Invalid Source + Ugyldig kilde + + + The selected source is invalid. + Den valgte kilden er ugyldig. + + + File Exists + Filen eksisterer + + + File already exists. Do you want to replace it? + Filen eksisterer allerede. Ønsker du å erstatte den? + + + Failed to save file: + Kunne ikke lagre filen: + + + Failed to download file: + Kunne ikke laste ned filen: + + + Cheats Not Found + Fant ikke juks + + + No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. + Ingen juks funnet for dette spillet i denne versjonen av den valgte pakkebrønnen,prøv en annen pakkebrønn eller en annen versjon av spillet. + + + Cheats Downloaded Successfully + Juks ble lastet ned + + + You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. + Du har lastet ned juks for denne versjonen av spillet fra den valgte pakkebrønnen. Du kan prøve å laste ned fra en annen pakkebrønn, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. + + + Failed to save: + Kunne ikke lagre: + + + Failed to download: + Kunne ikke laste ned: + + + Download Complete + Nedlasting fullført + + + Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. + Programrettelser ble lastet ned! Alle programrettelsene tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med juks. Hvis programrettelsen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. + + + Failed to parse JSON data from HTML. + Kunne ikke analysere JSON-data fra HTML. + + + Failed to retrieve HTML page. + Kunne ikke hente HTML-side. + + + The game is in version: %1 + Spillet er i versjon: %1 + + + The downloaded patch only works on version: %1 + Den nedlastede programrettelsen fungerer bare på versjon: %1 + + + You may need to update your game. + Du må kanskje oppdatere spillet ditt. + + + Incompatibility Notice + Inkompatibilitets-varsel + + + Failed to open file: + Kunne ikke åpne filen: + + + XML ERROR: + XML FEIL: + + + Failed to open files.json for writing + Kunne ikke åpne files.json for skriving + + + Author: + Forfatter: + + + Directory does not exist: + Mappen eksisterer ikke: + + + Failed to open files.json for reading. + Kunne ikke åpne files.json for lesing. + + + Name: + Navn: + + + Can't apply cheats before the game is started + Kan ikke bruke juks før spillet er startet. + + + Close + Lukk + + + + CheckUpdate + + Auto Updater + Automatisk oppdatering + + + Error + Feil + + + Network error: + Nettverksfeil: + + + The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. + Den automatiske oppdateringen tillater opptil 60 oppdateringssjekker per time.\nDu har nådd denne grensen. Prøv igjen senere. + + + Failed to parse update information. + Kunne ikke analysere oppdaterings-informasjonen. + + + No pre-releases found. + Fant ingen forhåndsutgivelser. + + + Invalid release data. + Ugyldige utgivelsesdata. + + + No download URL found for the specified asset. + Ingen nedlastings-URL funnet for den spesifiserte ressursen. + + + Your version is already up to date! + Din versjon er allerede oppdatert! + + + Update Available + Oppdatering tilgjengelig + + + Update Channel + Oppdateringskanal + + + Current Version + Gjeldende versjon + + + Latest Version + Nyeste versjon + + + Do you want to update? + Vil du oppdatere? + + + Show Changelog + Vis endringslogg + + + Check for Updates at Startup + Se etter oppdateringer ved oppstart + + + Update + Oppdater + + + No + Nei + + + Hide Changelog + Skjul endringslogg + + + Changes + Endringer + + + Network error occurred while trying to access the URL + Nettverksfeil oppstod mens vi prøvde å få tilgang til URL + + + Download Complete + Nedlasting fullført + + + The update has been downloaded, press OK to install. + Oppdateringen har blitt lastet ned, trykk OK for å installere. + + + Failed to save the update file at + Kunne ikke lagre oppdateringsfilen på + + + Starting Update... + Starter oppdatering... + + + Failed to create the update script file + Kunne ikke opprette oppdateringsskriptfilen + + + + CompatibilityInfoClass + + Fetching compatibility data, please wait + Henter kompatibilitetsdata, vennligst vent + + + Cancel + Avbryt + + + Loading... + Laster... + + + Error + Feil + + + Unable to update compatibility data! Try again later. + Kan ikke oppdatere kompatibilitetsdata! Prøv igjen senere. + + + Unable to open compatibility_data.json for writing. + Kan ikke åpne compatibility_data.json for skriving. + + + Unknown + Ukjent + + + Nothing + Ingenting + + + Boots + Starter opp + + + Menus + Menyene + + + Ingame + I spill + + + Playable + Spillbar + + + + ControlSettings + + Configure Controls + Configure Controls + + + Control Settings + Control Settings + + + D-Pad + D-Pad + + + Up + Up + + + Left + Left + + + Right + Right + + + Down + Down + + + Left Stick Deadzone (def:2 max:127) + Left Stick Deadzone (def:2 max:127) + + + Left Deadzone + Left Deadzone + + + Left Stick + Left Stick + + + Config Selection + Config Selection + + + Common Config + Common Config + + + Use per-game configs + Use per-game configs + + + L1 / LB + L1 / LB + + + L2 / LT + L2 / LT + + + KBM Controls + KBM Controls + + + KBM Editor + KBM Editor + + + Back + Back + + + R1 / RB + R1 / RB + + + R2 / RT + R2 / RT + + + L3 + L3 + + + Options / Start + Options / Start + + + R3 + R3 + + + Face Buttons + Face Buttons + + + Triangle / Y + Triangle / Y + + + Square / X + Square / X + + + Circle / B + Circle / B + + + Cross / A + Cross / A + + + Right Stick Deadzone (def:2, max:127) + Right Stick Deadzone (def:2, max:127) + + + Right Deadzone + Right Deadzone + + + Right Stick + Right Stick + + + + ElfViewer + + Open Folder + Åpne mappe + + + + GameInfoClass + + Loading game list, please wait :3 + Laster spill-liste, vennligst vent :3 + + + Cancel + Avbryt + + + Loading... + Laster... + + + + GameInstallDialog + + shadPS4 - Choose directory + shadPS4 - Velg mappe + + + Directory to install games + Mappe for å installere spill + + + Browse + Bla gjennom + + + Error + Feil + + + Directory to install DLC + Directory to install DLC + + + + GameListFrame + + Icon + Ikon + + + Name + Navn + + + Serial + Serienummer + + + Compatibility + Kompatibilitet + + + Region + Region + + + Firmware + Fastvare + + + Size + Størrelse + + + Version + Versjon + + + Path + Adresse + + + Play Time + Spilletid + + + Never Played + Aldri spilt + + + h + h + + + m + m + + + s + s + + + Compatibility is untested + kompatibilitet er utestet + + + Game does not initialize properly / crashes the emulator + Spillet initialiseres ikke riktig / krasjer emulatoren + + + Game boots, but only displays a blank screen + Spillet starter, men viser bare en tom skjerm + + + Game displays an image but does not go past the menu + Spillet viser et bilde, men går ikke forbi menyen + + + Game has game-breaking glitches or unplayable performance + Spillet har spillbrytende feil eller uspillbar ytelse + + + Game can be completed with playable performance and no major glitches + Spillet kan fullføres med spillbar ytelse og uten store feil + + + Click to see details on github + Klikk for å se detaljer på GitHub + + + Last updated + Sist oppdatert + + + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + + + GuiContextMenus + + Create Shortcut + Lag snarvei + + + Cheats / Patches + Juks / Programrettelse + + + SFO Viewer + SFO viser + + + Trophy Viewer + Trofé viser + + + Open Folder... + Åpne mappe... + + + Open Game Folder + Åpne spillmappen + + + Open Save Data Folder + Åpne lagrede datamappen + + + Open Log Folder + Åpne loggmappen + + + Copy info... + Kopier info... + + + Copy Name + Kopier navn + + + Copy Serial + Kopier serienummer + + + Copy Version + Kopier versjon + + + Copy Size + Kopier størrelse + + + Copy All + Kopier alt + + + Delete... + Slett... + + + Delete Game + Slett spill + + + Delete Update + Slett oppdatering + + + Delete DLC + Slett DLC + + + Compatibility... + Kompatibilitet... + + + Update database + Oppdater database + + + View report + Vis rapport + + + Submit a report + Send inn en rapport + + + Shortcut creation + Snarvei opprettelse + + + Shortcut created successfully! + Snarvei opprettet! + + + Error + Feil + + + Error creating shortcut! + Feil ved opprettelse av snarvei! + + + Install PKG + Installer PKG + + + Game + Spill + + + This game has no update to delete! + Dette spillet har ingen oppdatering å slette! + + + Update + Oppdater + + + This game has no DLC to delete! + Dette spillet har ingen DLC å slette! + + + DLC + DLC + + + Delete %1 + Slett %1 + + + Are you sure you want to delete %1's %2 directory? + Er du sikker på at du vil slette %1's %2 directory? + + + Open Update Folder + Open Update Folder + + + Delete Save Data + Delete Save Data + + + This game has no update folder to open! + This game has no update folder to open! + + + Failed to convert icon. + Failed to convert icon. + + + This game has no save data to delete! + This game has no save data to delete! + + + Save Data + Save Data + + + + InstallDirSelect + + shadPS4 - Choose directory + shadPS4 - Velg mappe + + + Select which directory you want to install to. + Velg hvilken mappe du vil installere til. + + + Install All Queued to Selected Folder + Install All Queued to Selected Folder + + + Delete PKG File on Install + Delete PKG File on Install + + + + MainWindow + + Open/Add Elf Folder + Åpne/Legg til Elf-mappe + + + Install Packages (PKG) + Installer pakker (PKG) + + + Boot Game + Start spill + + + Check for Updates + Se etter oppdateringer + + + About shadPS4 + Om shadPS4 + + + Configure... + Konfigurer... + + + Install application from a .pkg file + Installer fra en .pkg fil + + + Recent Games + Nylige spill + + + Open shadPS4 Folder + Open shadPS4 Folder + + + Exit + Avslutt + + + Exit shadPS4 + Avslutt shadPS4 + + + Exit the application. + Avslutt programmet. + + + Show Game List + Vis spill-listen + + + Game List Refresh + Oppdater spill-listen + + + Tiny + Bitteliten + + + Small + Liten + + + Medium + Medium + + + Large + Stor + + + List View + Liste-visning + + + Grid View + Rute-visning + + + Elf Viewer + Elf-visning + + + Game Install Directory + Spillinstallasjons-mappe + + + Download Cheats/Patches + Last ned juks/programrettelse + + + Dump Game List + Dump spill-liste + + + PKG Viewer + PKG viser + + + Search... + Søk... + + + File + Fil + + + View + Oversikt + + + Game List Icons + Spill-liste ikoner + + + Game List Mode + Spill-liste modus + + + Settings + Innstillinger + + + Utils + Verktøy + + + Themes + Tema + + + Help + Hjelp + + + Dark + Mørk + + + Light + Lys + + + Green + Grønn + + + Blue + Blå + + + Violet + Lilla + + + toolBar + Verktøylinje + + + Game List + Spill-liste + + + * Unsupported Vulkan Version + * Ustøttet Vulkan-versjon + + + Download Cheats For All Installed Games + Last ned juks for alle installerte spill + + + Download Patches For All Games + Last ned programrettelser for alle spill + + + Download Complete + Nedlasting fullført + + + You have downloaded cheats for all the games you have installed. + Du har lastet ned juks for alle spillene du har installert. + + + Patches Downloaded Successfully! + Programrettelser ble lastet ned! + + + All Patches available for all games have been downloaded. + Programrettelser tilgjengelige for alle spill har blitt lastet ned. + + + Games: + Spill: + + + ELF files (*.bin *.elf *.oelf) + ELF-filer (*.bin *.elf *.oelf) + + + Game Boot + Spilloppstart + + + Only one file can be selected! + Kun én fil kan velges! + + + PKG Extraction + PKG-utpakking + + + Patch detected! + Programrettelse oppdaget! + + + PKG and Game versions match: + PKG og spillversjoner stemmer overens: + + + Would you like to overwrite? + Ønsker du å overskrive? + + + PKG Version %1 is older than installed version: + PKG-versjon %1 er eldre enn installert versjon: + + + Game is installed: + Spillet er installert: + + + Would you like to install Patch: + Ønsker du å installere programrettelsen: + + + DLC Installation + DLC installasjon + + + Would you like to install DLC: %1? + Ønsker du å installere DLC: %1? + + + DLC already installed: + DLC allerede installert: + + + Game already installed + Spillet er allerede installert + + + PKG ERROR + PKG FEIL + + + Extracting PKG %1/%2 + Pakker ut PKG %1/%2 + + + Extraction Finished + Utpakking fullført + + + Game successfully installed at %1 + Spillet ble installert i %1 + + + File doesn't appear to be a valid PKG file + Filen ser ikke ut til å være en gyldig PKG-fil + + + Run Game + Run Game + + + Eboot.bin file not found + Eboot.bin file not found + + + PKG File (*.PKG *.pkg) + PKG File (*.PKG *.pkg) + + + PKG is a patch or DLC, please install the game first! + PKG is a patch or DLC, please install the game first! + + + Game is already running! + Game is already running! + + + shadPS4 + shadPS4 + + + + PKGViewer + + Open Folder + Åpne mappe + + + PKG ERROR + PKG FEIL + + + Name + Navn + + + Serial + Serienummer + + + Installed + Installed + + + Size + Størrelse + + + Category + Category + + + Type + Type + + + App Ver + App Ver + + + FW + FW + + + Region + Region + + + Flags + Flags + + + Path + Adresse + + + File + Fil + + + Unknown + Ukjent + + + Package + Package + + + + SettingsDialog + + Settings + Innstillinger + + + General + Generell + + + System + System + + + Console Language + Konsollspråk + + + Emulator Language + Emulatorspråk + + + Emulator + Emulator + + + Enable Fullscreen + Aktiver fullskjerm + + + Fullscreen Mode + Fullskjermmodus + + + Enable Separate Update Folder + Aktiver seperat oppdateringsmappe + + + Default tab when opening settings + Standardfanen når innstillingene åpnes + + + Show Game Size In List + Vis spillstørrelse i listen + + + Show Splash + Vis velkomstbilde + + + Enable Discord Rich Presence + Aktiver Discord Rich Presence + + + Username + Brukernavn + + + Trophy Key + Trofénøkkel + + + Trophy + Trofé + + + Logger + Logger + + + Log Type + Logg type + + + Log Filter + Logg filter + + + Open Log Location + Åpne loggplassering + + + Input + Inndata + + + Cursor + Musepeker + + + Hide Cursor + Skjul musepeker + + + Hide Cursor Idle Timeout + Skjul musepeker ved inaktivitet + + + s + s + + + Controller + Kontroller + + + Back Button Behavior + Tilbakeknapp atferd + + + Graphics + Grafikk + + + GUI + Grensesnitt + + + User + Bruker + + + Graphics Device + Grafikkenhet + + + Width + Bredde + + + Height + Høyde + + + Vblank Divider + Vblank skillelinje + + + Advanced + Avansert + + + Enable Shaders Dumping + Aktiver skyggeleggerdumping + + + Enable NULL GPU + Aktiver NULL GPU + + + Enable HDR + Enable HDR + + + Paths + Mapper + + + Game Folders + Spillmapper + + + Add... + Legg til... + + + Remove + Fjern + + + Debug + Feilretting + + + Enable Debug Dumping + Aktiver feilrettingsdumping + + + Enable Vulkan Validation Layers + Aktiver Vulkan Validation Layers + + + Enable Vulkan Synchronization Validation + Aktiver Vulkan synkroniseringslag + + + Enable RenderDoc Debugging + Aktiver RenderDoc feilretting + + + Enable Crash Diagnostics + Aktiver krasjdiagnostikk + + + Collect Shaders + Lagre skyggeleggere + + + Copy GPU Buffers + Kopier GPU-buffere + + + Host Debug Markers + Vertsfeilsøkingsmarkører + + + Guest Debug Markers + Gjestefeilsøkingsmarkører + + + Update + Oppdatering + + + Check for Updates at Startup + Se etter oppdateringer ved oppstart + + + Always Show Changelog + Always Show Changelog + + + Update Channel + Oppdateringskanal + + + Check for Updates + Se etter oppdateringer + + + GUI Settings + Grensesnitt-innstillinger + + + Title Music + Tittelmusikk + + + Disable Trophy Pop-ups + Deaktiver trofé hurtigmeny + + + Background Image + Bakgrunnsbilde + + + Show Background Image + Vis bakgrunnsbilde + + + Opacity + Synlighet + + + Play title music + Spill tittelmusikk + + + Update Compatibility Database On Startup + Oppdater database ved oppstart + + + Game Compatibility + Spill kompatibilitet + + + Display Compatibility Data + Vis kompatibilitets-data + + + Update Compatibility Database + Oppdater kompatibilitets-database + + + Volume + Volum + + + Save + Lagre + + + Apply + Bruk + + + Restore Defaults + Gjenopprett standardinnstillinger + + + Close + Lukk + + + Point your mouse at an option to display its description. + Pek musen over et alternativ for å vise beskrivelsen. + + + Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. + Konsollspråk:\nAngir språket som PS4-spillet bruker.\nDet anbefales å sette dette til et språk som spillet støtter, noe som kan variere avhengig av region. + + + Emulator Language:\nSets the language of the emulator's user interface. + Emulatorspråket:\nAngir språket for emulatorens brukergrensesnitt. + + + Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. + Aktiver fullskjerm:\nSetter spillvinduet automatisk i fullskjermmodus.\nDette kan slås av ved å trykke på F11-tasten. + + + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. + Aktiver separat oppdateringsmappe:\nAktiverer installering av spill i en egen mappe for enkel administrasjon. + + + Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. + Vis velkomstbilde:\nViser spillets velkomstbilde (et spesialbilde) når spillet starter. + + + Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. + Aktiver Discord Rich Presence:\nViser emulatorikonet og relevant informasjon på Discord-profilen din. + + + Username:\nSets the PS4's account username, which may be displayed by some games. + Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill. + + + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + Trofénøkkel:\nNøkkel brukes til å dekryptere trofeer. Må hentes fra din konsoll (jailbroken).\nMå bare inneholde sekskantede tegn. + + + Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. + Logg type:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter for emulatoren. + + + Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. + Logg filter:\nFiltrerer loggen for å kun skrive ut spesifikk informasjon.\nEksempler: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivåer: Trace, Debug, Info, Warning, Error, Critical - i denne rekkefølgen, et spesifikt nivå demper alle tidligere nivåer i listen og logger alle nivåer etter det. + + + Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. + Oppdatering:\nRelease: Offisielle versjoner utgitt hver måned som kan være veldig utdaterte, men er mer pålitelige og testet.\nNightly: Utviklingsversjoner som har alle de nyeste funksjonene og feilrettingene, men som kan inneholde feil og er mindre stabile. + + + Background Image:\nControl the opacity of the game background image. + Bakgrunnsbilde:\nEndrer synligheten til spillets bakgrunnsbilde. + + + Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. + Spille tittelmusikk:\nHvis et spill støtter det, så aktiveres det spesiell musikk når du velger spillet i menyen. + + + Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Deaktiver trofé hurtigmeny:\nDeaktiver trofévarsler i spillet. Trofé-fremgang kan fortsatt ved help av troféviseren (høyreklikk på spillet i hovedvinduet). + + + Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. + Skjul musepeker:\nVelg når musepekeren skal forsvinne:\nAldri: Du vil alltid se musepekeren.\nInaktiv: Sett en tid for at den skal forsvinne etter å ha vært inaktiv.\nAlltid: du vil aldri se musepekeren. + + + Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. + Sett en tid for når musepekeren forsvinner etter å ha vært inaktiv. + + + Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. + Atferd for tilbaketasten:\nSetter tilbaketasten på kontrolleren til å imitere et trykk på den angitte posisjonen på PS4s berøringsplate. + + + Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Vis kompatibilitets-data:\nViser informasjon om spillkompatibilitet i tabellvisning. Aktiver "Oppdater kompatibilitets-data ved oppstart" for oppdatert informasjon. + + + Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Oppdater database ved oppstart:\nOppdaterer kompatibilitets-databasen automatisk når shadPS4 starter. + + + Update Compatibility Database:\nImmediately update the compatibility database. + Oppdater kompatibilitets-database:\nOppdater kompatibilitets-databasen nå. + + + Never + Aldri + + + Idle + Inaktiv + + + Always + Alltid + + + Touchpad Left + Berøringsplate Venstre + + + Touchpad Right + Berøringsplate Høyre + + + Touchpad Center + Berøringsplate Midt + + + None + Ingen + + + Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. + Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en emulatoren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å velge automatisk. + + + Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. + Bredde/Høyde:\nAngir størrelsen på emulatorvinduet ved oppstart, som kan endres under spillingen.\nDette er forskjellig fra oppløsningen i spillet. + + + Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! + Vblank skillelinje:\nBildehastigheten som emulatoren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten av spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! + + + Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. + Aktiver skyggeleggerdumping:\nFor teknisk feilsøking lagrer skyggeleggerne fra spillet i en mappe mens de gjengis. + + + Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. + Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillets-gjengivelse som om det ikke var noe grafikkort. + + + Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. + Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. + + + Game Folders:\nThe list of folders to check for installed games. + Spillmapper:\nListe over mapper som brukes for å se etter installerte spill. + + + Add:\nAdd a folder to the list. + Legg til:\nLegg til en mappe til listen. + + + Remove:\nRemove a folder from the list. + Fjern:\nFjern en mappe fra listen. + + + Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. + Aktiver feilrettingsdumping:\nLagrer import- og eksport-symbolene og filoverskriftsinformasjonen til det nåværende kjørende PS4-programmet i en katalog. + + + Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. + Aktiver Vulkan Validation Layers:\nAktiverer et system som validerer tilstanden til Vulkan-gjengiveren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. + + + Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. + Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer frekvens tiden av Vulkan-gjengivelsensoppgaver. Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. + + + Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + Aktiver RenderDoc feilsøking:\nHvis aktivert, vil emulatoren gi kompatibilitet med RenderDoc for å tillate opptak og analyse av det nåværende gjengitte bildet. + + + Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). + Lagre skyggeleggere:\nDu trenger dette aktivert for å redigere skyggeleggerne med feilsøkingsmenyen (Ctrl + F10). + + + Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. + Krasjdiagnostikk:\nOppretter en .yaml-fil med informasjon om Vulkan-tilstanden ved krasj.\nNyttig for feilsøking 'Device lost' feil. Hvis du har dette aktivert, burde du aktivere vert OG gjestefeilsøkingsmarkører.\nFunker ikke med Intel GPU-er.\nDu trenger Vulkan Validation Layers og Vulkan SDK for at dette skal fungere. + + + Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. + Kopier GPU-buffere:\nKommer rundt løpsforhold som involverer GPU-innsendinger.\nKan muligens hjelpe med PM4 type 0 krasj. + + + Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Vertsfeilsøkingsmarkører:\nSetter inn emulator-side informasjon som markører for spesifikke AMDGPU-kommandoer rundt Vulkan-kommandoer, i tillegg til å gi ressurser feilrettingsnavn.\nHvis du har dette aktivert, burde du aktivere krasjdiagnostikk.\nNyttig for programmer som RenderDoc. + + + Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Gjestefeilsøkingsmarkører:\nSetter inn eventuelle feilsøkingsmarkører spillet selv har lagt til kommandobufferen.\nHvis du har dette aktivert, burde du aktivere krasjdiagnostikk.\nNyttig for programmer som RenderDoc. + + + Save Data Path:\nThe folder where game save data will be saved. + Lagrede datamappe:\nListe over data shadPS4 lagrer. + + + Browse:\nBrowse for a folder to set as the save data path. + Endre mappe:\nEndrer hvilken mappe shadPS4 skal lagre data til. + + + Borderless + Borderless + + + True + True + + + Release + Release + + + Nightly + Nightly + + + Set the volume of the background music. + Set the volume of the background music. + + + Enable Motion Controls + Enable Motion Controls + + + Save Data Path + Lagrede datamappe + + + Browse + Endre mappe + + + async + async + + + sync + sync + + + Auto Select + Auto Select + + + Directory to install games + Mappe for å installere spill + + + Directory to save data + Directory to save data + + + + TrophyViewer + + Trophy Viewer + Trofé viser + + + diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 33f76764f..be9c4d11b 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -1309,7 +1309,7 @@ Logger - Registro-Log + Registros de Log Log Type @@ -1497,7 +1497,7 @@ Play title music - Reproduzir música de abertura + Reproduzir Música do Título Update Compatibility Database On Startup @@ -1573,7 +1573,7 @@ Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. - Tipo do Registro:\nDetermina se a saída da janela de log deve ser sincronizada por motivos de desempenho. Pode impactar negativamente a emulação. + Tipo de Registro:\nDetermina se a saída da janela de log deve ser sincronizada por motivos de desempenho. Pode impactar negativamente a emulação. Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. @@ -1585,7 +1585,7 @@ Background Image:\nControl the opacity of the game background image. - Imagem de fundo:\nControle a opacidade da imagem de fundo do jogo. + Imagem de Fundo:\nControla a opacidade da imagem de fundo do jogo. Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. @@ -1705,7 +1705,7 @@ Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. - Diagnósticos de Falha:\nCria um arquivo .yaml com informações sobre o estado do Vulkan no momento da falha.\nÚtil para depuração de erros de 'Device lost'. Se você tiver isto habilitado, você deve habilitar os Marcadores de Depuração de Host E DE Convidado.\nNão funciona em GPUs Intel.\nVocê precisa ter as Camadas de Validação Vulkan habilitadas e o Vulkan SDK para que isso funcione. + Diagnóstico de Falhas:\nCria um arquivo .yaml com informações sobre o estado do Vulkan no momento da falha.\nÚtil para depuração de erros de 'Device lost'. Se isto estiver ativado, você deve habilitar os Marcadores de Depuração de Host E DE Convidado.\nNão funciona em GPUs Intel.\nVocê precisa ter as Camadas de Validação Vulkan habilitadas e o Vulkan SDK para que isso funcione. Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. @@ -1721,11 +1721,11 @@ Save Data Path:\nThe folder where game save data will be saved. - Diretório dos Dados Salvos:\nA pasta que onde os dados de salvamento de jogo serão salvos. + Caminho dos Dados Salvos:\nA pasta que onde os dados de salvamento de jogo serão salvos. Browse:\nBrowse for a folder to set as the save data path. - Navegar:\nProcure uma pasta para definir como o caminho para salvar dados. + Procurar:\nProcure uma pasta para definir como o caminho para salvar dados. Borderless diff --git a/src/qt_gui/translations/pt_PT.ts b/src/qt_gui/translations/pt_PT.ts new file mode 100644 index 000000000..1a63c88fd --- /dev/null +++ b/src/qt_gui/translations/pt_PT.ts @@ -0,0 +1,1790 @@ + + + + + + AboutDialog + + About shadPS4 + Sobre o shadPS4 + + + shadPS4 + shadPS4 + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 é um emulador de código aberto experimental para o PlayStation 4. + + + This software should not be used to play games you have not legally obtained. + Este programa não deve ser usado para jogar títulos não obtidos legalmente. + + + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n + Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n + + + No Image Available + No Image Available + + + Serial: + Serial: + + + Version: + Version: + + + Size: + Size: + + + Select Cheat File: + Select Cheat File: + + + Repository: + Repository: + + + Download Cheats + Download Cheats + + + Delete File + Delete File + + + No files selected. + No files selected. + + + You can delete the cheats you don't want after downloading them. + You can delete the cheats you don't want after downloading them. + + + Do you want to delete the selected file?\n%1 + Do you want to delete the selected file?\n%1 + + + Select Patch File: + Select Patch File: + + + Download Patches + Download Patches + + + Save + Save + + + Cheats + Cheats + + + Patches + Patches + + + Error + Error + + + No patch selected. + No patch selected. + + + Unable to open files.json for reading. + Unable to open files.json for reading. + + + No patch file found for the current serial. + No patch file found for the current serial. + + + Unable to open the file for reading. + Unable to open the file for reading. + + + Unable to open the file for writing. + Unable to open the file for writing. + + + Failed to parse XML: + Failed to parse XML: + + + Success + Success + + + Options saved successfully. + Options saved successfully. + + + Invalid Source + Invalid Source + + + The selected source is invalid. + The selected source is invalid. + + + File Exists + File Exists + + + File already exists. Do you want to replace it? + File already exists. Do you want to replace it? + + + Failed to save file: + Failed to save file: + + + Failed to download file: + Failed to download file: + + + Cheats Not Found + Cheats Not Found + + + No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. + No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. + + + Cheats Downloaded Successfully + Cheats Downloaded Successfully + + + You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. + You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. + + + Failed to save: + Failed to save: + + + Failed to download: + Failed to download: + + + Download Complete + Download Complete + + + Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. + Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. + + + Failed to parse JSON data from HTML. + Failed to parse JSON data from HTML. + + + Failed to retrieve HTML page. + Failed to retrieve HTML page. + + + The game is in version: %1 + The game is in version: %1 + + + The downloaded patch only works on version: %1 + The downloaded patch only works on version: %1 + + + You may need to update your game. + You may need to update your game. + + + Incompatibility Notice + Incompatibility Notice + + + Failed to open file: + Failed to open file: + + + XML ERROR: + XML ERROR: + + + Failed to open files.json for writing + Failed to open files.json for writing + + + Author: + Author: + + + Directory does not exist: + Directory does not exist: + + + Failed to open files.json for reading. + Failed to open files.json for reading. + + + Name: + Name: + + + Can't apply cheats before the game is started + Can't apply cheats before the game is started + + + Close + Close + + + + CheckUpdate + + Auto Updater + Auto Updater + + + Error + Error + + + Network error: + Network error: + + + The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. + The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. + + + Failed to parse update information. + Failed to parse update information. + + + No pre-releases found. + No pre-releases found. + + + Invalid release data. + Invalid release data. + + + No download URL found for the specified asset. + No download URL found for the specified asset. + + + Your version is already up to date! + Your version is already up to date! + + + Update Available + Update Available + + + Update Channel + Update Channel + + + Current Version + Current Version + + + Latest Version + Latest Version + + + Do you want to update? + Do you want to update? + + + Show Changelog + Show Changelog + + + Check for Updates at Startup + Check for Updates at Startup + + + Update + Update + + + No + No + + + Hide Changelog + Hide Changelog + + + Changes + Changes + + + Network error occurred while trying to access the URL + Network error occurred while trying to access the URL + + + Download Complete + Download Complete + + + The update has been downloaded, press OK to install. + The update has been downloaded, press OK to install. + + + Failed to save the update file at + Failed to save the update file at + + + Starting Update... + Starting Update... + + + Failed to create the update script file + Failed to create the update script file + + + + CompatibilityInfoClass + + Fetching compatibility data, please wait + Fetching compatibility data, please wait + + + Cancel + Cancel + + + Loading... + Loading... + + + Error + Error + + + Unable to update compatibility data! Try again later. + Unable to update compatibility data! Try again later. + + + Unable to open compatibility_data.json for writing. + Unable to open compatibility_data.json for writing. + + + Unknown + Unknown + + + Nothing + Nothing + + + Boots + Boots + + + Menus + Menus + + + Ingame + Ingame + + + Playable + Playable + + + + ControlSettings + + Configure Controls + Configure Controls + + + Control Settings + Control Settings + + + D-Pad + D-Pad + + + Up + Up + + + Left + Left + + + Right + Right + + + Down + Down + + + Left Stick Deadzone (def:2 max:127) + Left Stick Deadzone (def:2 max:127) + + + Left Deadzone + Left Deadzone + + + Left Stick + Left Stick + + + Config Selection + Config Selection + + + Common Config + Common Config + + + Use per-game configs + Use per-game configs + + + L1 / LB + L1 / LB + + + L2 / LT + L2 / LT + + + KBM Controls + KBM Controls + + + KBM Editor + KBM Editor + + + Back + Back + + + R1 / RB + R1 / RB + + + R2 / RT + R2 / RT + + + L3 + L3 + + + Options / Start + Options / Start + + + R3 + R3 + + + Face Buttons + Face Buttons + + + Triangle / Y + Triangle / Y + + + Square / X + Square / X + + + Circle / B + Circle / B + + + Cross / A + Cross / A + + + Right Stick Deadzone (def:2, max:127) + Right Stick Deadzone (def:2, max:127) + + + Right Deadzone + Right Deadzone + + + Right Stick + Right Stick + + + + ElfViewer + + Open Folder + Open Folder + + + + GameInfoClass + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + Cancel + Cancel + + + Loading... + Loading... + + + + GameInstallDialog + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + Directory to install games + Directory to install games + + + Browse + Browse + + + Error + Error + + + Directory to install DLC + Directory to install DLC + + + + GameListFrame + + Icon + Icon + + + Name + Name + + + Serial + Serial + + + Compatibility + Compatibility + + + Region + Region + + + Firmware + Firmware + + + Size + Size + + + Version + Version + + + Path + Path + + + Play Time + Play Time + + + Never Played + Never Played + + + h + h + + + m + m + + + s + s + + + Compatibility is untested + Compatibility is untested + + + Game does not initialize properly / crashes the emulator + Game does not initialize properly / crashes the emulator + + + Game boots, but only displays a blank screen + Game boots, but only displays a blank screen + + + Game displays an image but does not go past the menu + Game displays an image but does not go past the menu + + + Game has game-breaking glitches or unplayable performance + Game has game-breaking glitches or unplayable performance + + + Game can be completed with playable performance and no major glitches + Game can be completed with playable performance and no major glitches + + + Click to see details on github + Click to see details on github + + + Last updated + Last updated + + + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + + + GuiContextMenus + + Create Shortcut + Create Shortcut + + + Cheats / Patches + Cheats / Patches + + + SFO Viewer + SFO Viewer + + + Trophy Viewer + Trophy Viewer + + + Open Folder... + Open Folder... + + + Open Game Folder + Open Game Folder + + + Open Save Data Folder + Open Save Data Folder + + + Open Log Folder + Open Log Folder + + + Copy info... + Copy info... + + + Copy Name + Copy Name + + + Copy Serial + Copy Serial + + + Copy Version + Copy Version + + + Copy Size + Copy Size + + + Copy All + Copy All + + + Delete... + Delete... + + + Delete Game + Delete Game + + + Delete Update + Delete Update + + + Delete DLC + Delete DLC + + + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + + Shortcut creation + Shortcut creation + + + Shortcut created successfully! + Shortcut created successfully! + + + Error + Error + + + Error creating shortcut! + Error creating shortcut! + + + Install PKG + Install PKG + + + Game + Game + + + This game has no update to delete! + This game has no update to delete! + + + Update + Update + + + This game has no DLC to delete! + This game has no DLC to delete! + + + DLC + DLC + + + Delete %1 + Delete %1 + + + Are you sure you want to delete %1's %2 directory? + Are you sure you want to delete %1's %2 directory? + + + Open Update Folder + Open Update Folder + + + Delete Save Data + Delete Save Data + + + This game has no update folder to open! + This game has no update folder to open! + + + Failed to convert icon. + Failed to convert icon. + + + This game has no save data to delete! + This game has no save data to delete! + + + Save Data + Save Data + + + + InstallDirSelect + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + Select which directory you want to install to. + Select which directory you want to install to. + + + Install All Queued to Selected Folder + Install All Queued to Selected Folder + + + Delete PKG File on Install + Delete PKG File on Install + + + + MainWindow + + Open/Add Elf Folder + Open/Add Elf Folder + + + Install Packages (PKG) + Install Packages (PKG) + + + Boot Game + Boot Game + + + Check for Updates + Check for Updates + + + About shadPS4 + About shadPS4 + + + Configure... + Configure... + + + Install application from a .pkg file + Install application from a .pkg file + + + Recent Games + Recent Games + + + Open shadPS4 Folder + Open shadPS4 Folder + + + Exit + Exit + + + Exit shadPS4 + Exit shadPS4 + + + Exit the application. + Exit the application. + + + Show Game List + Show Game List + + + Game List Refresh + Game List Refresh + + + Tiny + Tiny + + + Small + Small + + + Medium + Medium + + + Large + Large + + + List View + List View + + + Grid View + Grid View + + + Elf Viewer + Elf Viewer + + + Game Install Directory + Game Install Directory + + + Download Cheats/Patches + Download Cheats/Patches + + + Dump Game List + Dump Game List + + + PKG Viewer + PKG Viewer + + + Search... + Search... + + + File + File + + + View + View + + + Game List Icons + Game List Icons + + + Game List Mode + Game List Mode + + + Settings + Settings + + + Utils + Utils + + + Themes + Themes + + + Help + Help + + + Dark + Dark + + + Light + Light + + + Green + Green + + + Blue + Blue + + + Violet + Violet + + + toolBar + toolBar + + + Game List + Game List + + + * Unsupported Vulkan Version + * Unsupported Vulkan Version + + + Download Cheats For All Installed Games + Download Cheats For All Installed Games + + + Download Patches For All Games + Download Patches For All Games + + + Download Complete + Download Complete + + + You have downloaded cheats for all the games you have installed. + You have downloaded cheats for all the games you have installed. + + + Patches Downloaded Successfully! + Patches Downloaded Successfully! + + + All Patches available for all games have been downloaded. + All Patches available for all games have been downloaded. + + + Games: + Games: + + + ELF files (*.bin *.elf *.oelf) + ELF files (*.bin *.elf *.oelf) + + + Game Boot + Game Boot + + + Only one file can be selected! + Only one file can be selected! + + + PKG Extraction + PKG Extraction + + + Patch detected! + Patch detected! + + + PKG and Game versions match: + PKG and Game versions match: + + + Would you like to overwrite? + Would you like to overwrite? + + + PKG Version %1 is older than installed version: + PKG Version %1 is older than installed version: + + + Game is installed: + Game is installed: + + + Would you like to install Patch: + Would you like to install Patch: + + + DLC Installation + DLC Installation + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + + + DLC already installed: + DLC already installed: + + + Game already installed + Game already installed + + + PKG ERROR + PKG ERROR + + + Extracting PKG %1/%2 + Extracting PKG %1/%2 + + + Extraction Finished + Extraction Finished + + + Game successfully installed at %1 + Game successfully installed at %1 + + + File doesn't appear to be a valid PKG file + File doesn't appear to be a valid PKG file + + + Run Game + Run Game + + + Eboot.bin file not found + Eboot.bin file not found + + + PKG File (*.PKG *.pkg) + PKG File (*.PKG *.pkg) + + + PKG is a patch or DLC, please install the game first! + PKG is a patch or DLC, please install the game first! + + + Game is already running! + Game is already running! + + + shadPS4 + shadPS4 + + + + PKGViewer + + Open Folder + Open Folder + + + PKG ERROR + PKG ERROR + + + Name + Name + + + Serial + Serial + + + Installed + Installed + + + Size + Size + + + Category + Category + + + Type + Type + + + App Ver + App Ver + + + FW + FW + + + Region + Region + + + Flags + Flags + + + Path + Path + + + File + File + + + Unknown + Unknown + + + Package + Package + + + + SettingsDialog + + Settings + Settings + + + General + General + + + System + System + + + Console Language + Console Language + + + Emulator Language + Emulator Language + + + Emulator + Emulator + + + Enable Fullscreen + Enable Fullscreen + + + Fullscreen Mode + Fullscreen Mode + + + Enable Separate Update Folder + Enable Separate Update Folder + + + Default tab when opening settings + Default tab when opening settings + + + Show Game Size In List + Show Game Size In List + + + Show Splash + Show Splash + + + Enable Discord Rich Presence + Enable Discord Rich Presence + + + Username + Username + + + Trophy Key + Trophy Key + + + Trophy + Trophy + + + Logger + Logger + + + Log Type + Log Type + + + Log Filter + Log Filter + + + Open Log Location + Open Log Location + + + Input + Input + + + Cursor + Cursor + + + Hide Cursor + Hide Cursor + + + Hide Cursor Idle Timeout + Hide Cursor Idle Timeout + + + s + s + + + Controller + Controller + + + Back Button Behavior + Back Button Behavior + + + Graphics + Graphics + + + GUI + GUI + + + User + User + + + Graphics Device + Graphics Device + + + Width + Width + + + Height + Height + + + Vblank Divider + Vblank Divider + + + Advanced + Advanced + + + Enable Shaders Dumping + Enable Shaders Dumping + + + Enable NULL GPU + Enable NULL GPU + + + Enable HDR + Enable HDR + + + Paths + Paths + + + Game Folders + Game Folders + + + Add... + Add... + + + Remove + Remove + + + Debug + Debug + + + Enable Debug Dumping + Enable Debug Dumping + + + Enable Vulkan Validation Layers + Enable Vulkan Validation Layers + + + Enable Vulkan Synchronization Validation + Enable Vulkan Synchronization Validation + + + Enable RenderDoc Debugging + Enable RenderDoc Debugging + + + Enable Crash Diagnostics + Enable Crash Diagnostics + + + Collect Shaders + Collect Shaders + + + Copy GPU Buffers + Copy GPU Buffers + + + Host Debug Markers + Host Debug Markers + + + Guest Debug Markers + Guest Debug Markers + + + Update + Update + + + Check for Updates at Startup + Check for Updates at Startup + + + Always Show Changelog + Always Show Changelog + + + Update Channel + Update Channel + + + Check for Updates + Check for Updates + + + GUI Settings + GUI Settings + + + Title Music + Title Music + + + Disable Trophy Pop-ups + Disable Trophy Pop-ups + + + Background Image + Background Image + + + Show Background Image + Show Background Image + + + Opacity + Opacity + + + Play title music + Play title music + + + Update Compatibility Database On Startup + Update Compatibility Database On Startup + + + Game Compatibility + Game Compatibility + + + Display Compatibility Data + Display Compatibility Data + + + Update Compatibility Database + Update Compatibility Database + + + Volume + Volume + + + Save + Save + + + Apply + Apply + + + Restore Defaults + Restore Defaults + + + Close + Close + + + Point your mouse at an option to display its description. + Point your mouse at an option to display its description. + + + Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. + Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. + + + Emulator Language:\nSets the language of the emulator's user interface. + Emulator Language:\nSets the language of the emulator's user interface. + + + Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. + Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. + + + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. + + + Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. + Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. + + + Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. + Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. + + + Username:\nSets the PS4's account username, which may be displayed by some games. + Username:\nSets the PS4's account username, which may be displayed by some games. + + + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + + Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. + Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. + + + Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. + Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. + + + Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. + Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. + + + Background Image:\nControl the opacity of the game background image. + Background Image:\nControl the opacity of the game background image. + + + Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. + Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. + + + Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + + + Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. + Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. + + + Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. + Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. + + + Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. + Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. + + + Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + + + Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + + + Update Compatibility Database:\nImmediately update the compatibility database. + Update Compatibility Database:\nImmediately update the compatibility database. + + + Never + Never + + + Idle + Idle + + + Always + Always + + + Touchpad Left + Touchpad Left + + + Touchpad Right + Touchpad Right + + + Touchpad Center + Touchpad Center + + + None + None + + + Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. + Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. + + + Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. + Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. + + + Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! + Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! + + + Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. + Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. + + + Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. + Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. + + + Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. + Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. + + + Game Folders:\nThe list of folders to check for installed games. + Game Folders:\nThe list of folders to check for installed games. + + + Add:\nAdd a folder to the list. + Add:\nAdd a folder to the list. + + + Remove:\nRemove a folder from the list. + Remove:\nRemove a folder from the list. + + + Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. + Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. + + + Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. + Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. + + + Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. + Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. + + + Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + + + Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). + Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). + + + Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. + Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. + + + Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. + Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. + + + Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + + + Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + + + Save Data Path:\nThe folder where game save data will be saved. + Save Data Path:\nThe folder where game save data will be saved. + + + Browse:\nBrowse for a folder to set as the save data path. + Browse:\nBrowse for a folder to set as the save data path. + + + Borderless + Borderless + + + True + True + + + Release + Release + + + Nightly + Nightly + + + Set the volume of the background music. + Set the volume of the background music. + + + Enable Motion Controls + Enable Motion Controls + + + Save Data Path + Save Data Path + + + Browse + Browse + + + async + async + + + sync + sync + + + Auto Select + Auto Select + + + Directory to install games + Directory to install games + + + Directory to save data + Directory to save data + + + + TrophyViewer + + Trophy Viewer + Trophy Viewer + + + diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 157fbd4cb..538b774fc 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -471,15 +471,15 @@ KBM Controls - KBM Controls + Управление KBM KBM Editor - KBM Editor + Редактор KBM Back - Back + Назад R1 / RB @@ -1238,7 +1238,7 @@ Package - Package + Пакет diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index b1aeaa9c3..34baf29bd 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -443,7 +443,7 @@ Left Deadzone - Left Deadzone + Sol Ölü Bölge Left Stick @@ -451,7 +451,7 @@ Config Selection - Config Selection + Yapılandırma Seçimi Common Config @@ -459,7 +459,7 @@ Use per-game configs - Use per-game configs + Oyuna özel yapılandırmaları kullan L1 / LB @@ -495,7 +495,7 @@ Options / Start - Options / Start + Seçenekler / Başlat R3 @@ -503,7 +503,7 @@ Face Buttons - Face Buttons + Eylem Düğmeleri Triangle / Y @@ -527,7 +527,7 @@ Right Deadzone - Right Deadzone + Sağ Ölü Bölge Right Stick @@ -655,7 +655,7 @@ Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + Oyunu bozan hatalar ya da oynanamayan performans Game can be completed with playable performance and no major glitches @@ -725,7 +725,7 @@ Open Log Folder - Log Klasörünü Aç + Günlük Klasörünü Aç Copy info... @@ -809,7 +809,7 @@ This game has no update to delete! - This game has no update to delete! + Bu oyunun silinecek güncellemesi yok! Update @@ -817,7 +817,7 @@ This game has no DLC to delete! - This game has no DLC to delete! + Bu oyunun silinecek indirilebilir içeriği yok! DLC @@ -841,7 +841,7 @@ This game has no update folder to open! - This game has no update folder to open! + Bu oyunun açılacak güncelleme klasörü yok! Failed to convert icon. @@ -849,7 +849,7 @@ This game has no save data to delete! - This game has no save data to delete! + Bu oyunun silinecek kayıt verisi yok! Save Data @@ -1206,15 +1206,15 @@ Type - Type + Tür App Ver - App Ver + Uygulama Sürümü FW - FW + Sistem Yazılımı Region @@ -1349,7 +1349,7 @@ Back Button Behavior - Geri Dön Butonu Davranışı + Geri Dönme Butonu Davranışı Graphics @@ -1437,19 +1437,19 @@ Collect Shaders - Collect Shaders + Gölgelendiricileri Topla Copy GPU Buffers - Copy GPU Buffers + GPU Arabelleklerini Kopyala Host Debug Markers - Host Debug Markers + Ana Bilgisayar Hata Ayıklama İşaretleyicileri Guest Debug Markers - Guest Debug Markers + Konuk Hata Ayıklama İşaretleyicileri Update @@ -1569,7 +1569,7 @@ Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + Kupa Anahtarı:\nKupaların şifresini çözmek için kullanılan anahtardır. Jailbreak yapılmış konsolunuzdan alınmalıdır.\nYalnızca onaltılık karakterler içermelidir. Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. @@ -1585,11 +1585,11 @@ Background Image:\nControl the opacity of the game background image. - Background Image:\nControl the opacity of the game background image. + Arka Plan Resmi:\nOyunun arka plan resmi görünürlüğünü ayarlayın. Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - Başlık Müziklerini Çal:\nEğer bir oyun bunu destekliyorsa, GUI'de oyunu seçtiğinizde özel müziklerin çalmasını etkinleştirir. + Oyun Müziklerini Çal:\nEğer oyun destekliyorsa, arayüzde oyunu seçtiğinizde özel müzik çalmasını etkinleştirir. Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). @@ -1613,11 +1613,11 @@ Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Başlangıçta Uyumluluk Veritabanını Güncelle:\nshadPS4 başlatıldığında uyumluluk veritabanını otomatik olarak güncelleyin. Update Compatibility Database:\nImmediately update the compatibility database. - Update Compatibility Database:\nImmediately update the compatibility database. + Uyumluluk Veritabanını Güncelle:\nUyumluluk veri tabanını hemen güncelleyin. Never @@ -1721,7 +1721,7 @@ Save Data Path:\nThe folder where game save data will be saved. - Save Data Path:\nThe folder where game save data will be saved. + Kayıt Verileri Yolu:\nOyun kayıt verilerinin kaydedileceği klasördür. Browse:\nBrowse for a folder to set as the save data path. diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 8eae7ae69..21daafb5e 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -495,7 +495,7 @@ Options / Start - 选项 / 开始 + Options / Start R3 @@ -1238,7 +1238,7 @@ Package - Package + Package @@ -1377,7 +1377,7 @@ Vblank Divider - Vblank Divider + Vblank Divider Advanced From 26bb3d40d9172790249a922a7e24990fe554ce34 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sun, 16 Feb 2025 04:41:37 -0300 Subject: [PATCH 08/29] Correct translation no_NO to nb_NO (#2455) --- src/common/config.cpp | 2 +- src/qt_gui/translations/no_NO.ts | 1790 ------------------------------ 2 files changed, 1 insertion(+), 1791 deletions(-) delete mode 100644 src/qt_gui/translations/no_NO.ts diff --git a/src/common/config.cpp b/src/common/config.cpp index 4383b64b5..32c5e670b 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -813,7 +813,7 @@ void load(const std::filesystem::path& path) { // Check if the loaded language is in the allowed list const std::vector allowed_languages = { "ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", "fr_FR", "hu_HU", - "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nl_NL", "no_NO", "pl_PL", "pt_BR", "pt_PT", + "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO", "nl_NL", "pl_PL", "pt_BR", "pt_PT", "ro_RO", "ru_RU", "sq_AL", "sv_SE", "tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW"}; if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) == diff --git a/src/qt_gui/translations/no_NO.ts b/src/qt_gui/translations/no_NO.ts deleted file mode 100644 index 2613f63b0..000000000 --- a/src/qt_gui/translations/no_NO.ts +++ /dev/null @@ -1,1790 +0,0 @@ - - - - - - AboutDialog - - About shadPS4 - Om shadPS4 - - - shadPS4 - shadPS4 - - - shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 er en eksperimentell åpen kildekode-emulator for PlayStation 4. - - - This software should not be used to play games you have not legally obtained. - Denne programvaren skal ikke brukes til å spille spill du ikke har fått lovlig. - - - - CheatsPatches - - Cheats / Patches for - Juks / Programrettelser for - - - Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n - Juks/programrettelse er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned juks individuelt ved å velge pakkebrønn og klikke på nedlastingsknappen.\nPå fanen programrettelse kan du laste ned alle programrettelser samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Juks/Programrettelse,\nvær vennlig å rapportere problemer til juks/programrettelse utvikleren.\n\nHar du laget en ny juks? Besøk:\n - - - No Image Available - Ingen bilde tilgjengelig - - - Serial: - Serienummer: - - - Version: - Versjon: - - - Size: - Størrelse: - - - Select Cheat File: - Velg juksefil: - - - Repository: - Pakkebrønn: - - - Download Cheats - Last ned juks - - - Delete File - Slett fil - - - No files selected. - Ingen filer valgt. - - - You can delete the cheats you don't want after downloading them. - Du kan slette juks du ikke ønsker etter å ha lastet dem ned. - - - Do you want to delete the selected file?\n%1 - Ønsker du å slette den valgte filen?\n%1 - - - Select Patch File: - Velg programrettelse-filen: - - - Download Patches - Last ned programrettelser - - - Save - Lagre - - - Cheats - Juks - - - Patches - Programrettelse - - - Error - Feil - - - No patch selected. - Ingen programrettelse valgt. - - - Unable to open files.json for reading. - Kan ikke åpne files.json for lesing. - - - No patch file found for the current serial. - Ingen programrettelse-fil funnet for det aktuelle serienummeret. - - - Unable to open the file for reading. - Kan ikke åpne filen for lesing. - - - Unable to open the file for writing. - Kan ikke åpne filen for skriving. - - - Failed to parse XML: - Feil ved tolkning av XML: - - - Success - Vellykket - - - Options saved successfully. - Alternativer ble lagret. - - - Invalid Source - Ugyldig kilde - - - The selected source is invalid. - Den valgte kilden er ugyldig. - - - File Exists - Filen eksisterer - - - File already exists. Do you want to replace it? - Filen eksisterer allerede. Ønsker du å erstatte den? - - - Failed to save file: - Kunne ikke lagre filen: - - - Failed to download file: - Kunne ikke laste ned filen: - - - Cheats Not Found - Fant ikke juks - - - No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. - Ingen juks funnet for dette spillet i denne versjonen av den valgte pakkebrønnen,prøv en annen pakkebrønn eller en annen versjon av spillet. - - - Cheats Downloaded Successfully - Juks ble lastet ned - - - You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. - Du har lastet ned juks for denne versjonen av spillet fra den valgte pakkebrønnen. Du kan prøve å laste ned fra en annen pakkebrønn, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. - - - Failed to save: - Kunne ikke lagre: - - - Failed to download: - Kunne ikke laste ned: - - - Download Complete - Nedlasting fullført - - - Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. - Programrettelser ble lastet ned! Alle programrettelsene tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med juks. Hvis programrettelsen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. - - - Failed to parse JSON data from HTML. - Kunne ikke analysere JSON-data fra HTML. - - - Failed to retrieve HTML page. - Kunne ikke hente HTML-side. - - - The game is in version: %1 - Spillet er i versjon: %1 - - - The downloaded patch only works on version: %1 - Den nedlastede programrettelsen fungerer bare på versjon: %1 - - - You may need to update your game. - Du må kanskje oppdatere spillet ditt. - - - Incompatibility Notice - Inkompatibilitets-varsel - - - Failed to open file: - Kunne ikke åpne filen: - - - XML ERROR: - XML FEIL: - - - Failed to open files.json for writing - Kunne ikke åpne files.json for skriving - - - Author: - Forfatter: - - - Directory does not exist: - Mappen eksisterer ikke: - - - Failed to open files.json for reading. - Kunne ikke åpne files.json for lesing. - - - Name: - Navn: - - - Can't apply cheats before the game is started - Kan ikke bruke juks før spillet er startet. - - - Close - Lukk - - - - CheckUpdate - - Auto Updater - Automatisk oppdatering - - - Error - Feil - - - Network error: - Nettverksfeil: - - - The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. - Den automatiske oppdateringen tillater opptil 60 oppdateringssjekker per time.\nDu har nådd denne grensen. Prøv igjen senere. - - - Failed to parse update information. - Kunne ikke analysere oppdaterings-informasjonen. - - - No pre-releases found. - Fant ingen forhåndsutgivelser. - - - Invalid release data. - Ugyldige utgivelsesdata. - - - No download URL found for the specified asset. - Ingen nedlastings-URL funnet for den spesifiserte ressursen. - - - Your version is already up to date! - Din versjon er allerede oppdatert! - - - Update Available - Oppdatering tilgjengelig - - - Update Channel - Oppdateringskanal - - - Current Version - Gjeldende versjon - - - Latest Version - Nyeste versjon - - - Do you want to update? - Vil du oppdatere? - - - Show Changelog - Vis endringslogg - - - Check for Updates at Startup - Se etter oppdateringer ved oppstart - - - Update - Oppdater - - - No - Nei - - - Hide Changelog - Skjul endringslogg - - - Changes - Endringer - - - Network error occurred while trying to access the URL - Nettverksfeil oppstod mens vi prøvde å få tilgang til URL - - - Download Complete - Nedlasting fullført - - - The update has been downloaded, press OK to install. - Oppdateringen har blitt lastet ned, trykk OK for å installere. - - - Failed to save the update file at - Kunne ikke lagre oppdateringsfilen på - - - Starting Update... - Starter oppdatering... - - - Failed to create the update script file - Kunne ikke opprette oppdateringsskriptfilen - - - - CompatibilityInfoClass - - Fetching compatibility data, please wait - Henter kompatibilitetsdata, vennligst vent - - - Cancel - Avbryt - - - Loading... - Laster... - - - Error - Feil - - - Unable to update compatibility data! Try again later. - Kan ikke oppdatere kompatibilitetsdata! Prøv igjen senere. - - - Unable to open compatibility_data.json for writing. - Kan ikke åpne compatibility_data.json for skriving. - - - Unknown - Ukjent - - - Nothing - Ingenting - - - Boots - Starter opp - - - Menus - Menyene - - - Ingame - I spill - - - Playable - Spillbar - - - - ControlSettings - - Configure Controls - Configure Controls - - - Control Settings - Control Settings - - - D-Pad - D-Pad - - - Up - Up - - - Left - Left - - - Right - Right - - - Down - Down - - - Left Stick Deadzone (def:2 max:127) - Left Stick Deadzone (def:2 max:127) - - - Left Deadzone - Left Deadzone - - - Left Stick - Left Stick - - - Config Selection - Config Selection - - - Common Config - Common Config - - - Use per-game configs - Use per-game configs - - - L1 / LB - L1 / LB - - - L2 / LT - L2 / LT - - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - - - Back - Back - - - R1 / RB - R1 / RB - - - R2 / RT - R2 / RT - - - L3 - L3 - - - Options / Start - Options / Start - - - R3 - R3 - - - Face Buttons - Face Buttons - - - Triangle / Y - Triangle / Y - - - Square / X - Square / X - - - Circle / B - Circle / B - - - Cross / A - Cross / A - - - Right Stick Deadzone (def:2, max:127) - Right Stick Deadzone (def:2, max:127) - - - Right Deadzone - Right Deadzone - - - Right Stick - Right Stick - - - - ElfViewer - - Open Folder - Åpne mappe - - - - GameInfoClass - - Loading game list, please wait :3 - Laster spill-liste, vennligst vent :3 - - - Cancel - Avbryt - - - Loading... - Laster... - - - - GameInstallDialog - - shadPS4 - Choose directory - shadPS4 - Velg mappe - - - Directory to install games - Mappe for å installere spill - - - Browse - Bla gjennom - - - Error - Feil - - - Directory to install DLC - Directory to install DLC - - - - GameListFrame - - Icon - Ikon - - - Name - Navn - - - Serial - Serienummer - - - Compatibility - Kompatibilitet - - - Region - Region - - - Firmware - Fastvare - - - Size - Størrelse - - - Version - Versjon - - - Path - Adresse - - - Play Time - Spilletid - - - Never Played - Aldri spilt - - - h - h - - - m - m - - - s - s - - - Compatibility is untested - kompatibilitet er utestet - - - Game does not initialize properly / crashes the emulator - Spillet initialiseres ikke riktig / krasjer emulatoren - - - Game boots, but only displays a blank screen - Spillet starter, men viser bare en tom skjerm - - - Game displays an image but does not go past the menu - Spillet viser et bilde, men går ikke forbi menyen - - - Game has game-breaking glitches or unplayable performance - Spillet har spillbrytende feil eller uspillbar ytelse - - - Game can be completed with playable performance and no major glitches - Spillet kan fullføres med spillbar ytelse og uten store feil - - - Click to see details on github - Klikk for å se detaljer på GitHub - - - Last updated - Sist oppdatert - - - - GameListUtils - - B - B - - - KB - KB - - - MB - MB - - - GB - GB - - - TB - TB - - - - GuiContextMenus - - Create Shortcut - Lag snarvei - - - Cheats / Patches - Juks / Programrettelse - - - SFO Viewer - SFO viser - - - Trophy Viewer - Trofé viser - - - Open Folder... - Åpne mappe... - - - Open Game Folder - Åpne spillmappen - - - Open Save Data Folder - Åpne lagrede datamappen - - - Open Log Folder - Åpne loggmappen - - - Copy info... - Kopier info... - - - Copy Name - Kopier navn - - - Copy Serial - Kopier serienummer - - - Copy Version - Kopier versjon - - - Copy Size - Kopier størrelse - - - Copy All - Kopier alt - - - Delete... - Slett... - - - Delete Game - Slett spill - - - Delete Update - Slett oppdatering - - - Delete DLC - Slett DLC - - - Compatibility... - Kompatibilitet... - - - Update database - Oppdater database - - - View report - Vis rapport - - - Submit a report - Send inn en rapport - - - Shortcut creation - Snarvei opprettelse - - - Shortcut created successfully! - Snarvei opprettet! - - - Error - Feil - - - Error creating shortcut! - Feil ved opprettelse av snarvei! - - - Install PKG - Installer PKG - - - Game - Spill - - - This game has no update to delete! - Dette spillet har ingen oppdatering å slette! - - - Update - Oppdater - - - This game has no DLC to delete! - Dette spillet har ingen DLC å slette! - - - DLC - DLC - - - Delete %1 - Slett %1 - - - Are you sure you want to delete %1's %2 directory? - Er du sikker på at du vil slette %1's %2 directory? - - - Open Update Folder - Open Update Folder - - - Delete Save Data - Delete Save Data - - - This game has no update folder to open! - This game has no update folder to open! - - - Failed to convert icon. - Failed to convert icon. - - - This game has no save data to delete! - This game has no save data to delete! - - - Save Data - Save Data - - - - InstallDirSelect - - shadPS4 - Choose directory - shadPS4 - Velg mappe - - - Select which directory you want to install to. - Velg hvilken mappe du vil installere til. - - - Install All Queued to Selected Folder - Install All Queued to Selected Folder - - - Delete PKG File on Install - Delete PKG File on Install - - - - MainWindow - - Open/Add Elf Folder - Åpne/Legg til Elf-mappe - - - Install Packages (PKG) - Installer pakker (PKG) - - - Boot Game - Start spill - - - Check for Updates - Se etter oppdateringer - - - About shadPS4 - Om shadPS4 - - - Configure... - Konfigurer... - - - Install application from a .pkg file - Installer fra en .pkg fil - - - Recent Games - Nylige spill - - - Open shadPS4 Folder - Open shadPS4 Folder - - - Exit - Avslutt - - - Exit shadPS4 - Avslutt shadPS4 - - - Exit the application. - Avslutt programmet. - - - Show Game List - Vis spill-listen - - - Game List Refresh - Oppdater spill-listen - - - Tiny - Bitteliten - - - Small - Liten - - - Medium - Medium - - - Large - Stor - - - List View - Liste-visning - - - Grid View - Rute-visning - - - Elf Viewer - Elf-visning - - - Game Install Directory - Spillinstallasjons-mappe - - - Download Cheats/Patches - Last ned juks/programrettelse - - - Dump Game List - Dump spill-liste - - - PKG Viewer - PKG viser - - - Search... - Søk... - - - File - Fil - - - View - Oversikt - - - Game List Icons - Spill-liste ikoner - - - Game List Mode - Spill-liste modus - - - Settings - Innstillinger - - - Utils - Verktøy - - - Themes - Tema - - - Help - Hjelp - - - Dark - Mørk - - - Light - Lys - - - Green - Grønn - - - Blue - Blå - - - Violet - Lilla - - - toolBar - Verktøylinje - - - Game List - Spill-liste - - - * Unsupported Vulkan Version - * Ustøttet Vulkan-versjon - - - Download Cheats For All Installed Games - Last ned juks for alle installerte spill - - - Download Patches For All Games - Last ned programrettelser for alle spill - - - Download Complete - Nedlasting fullført - - - You have downloaded cheats for all the games you have installed. - Du har lastet ned juks for alle spillene du har installert. - - - Patches Downloaded Successfully! - Programrettelser ble lastet ned! - - - All Patches available for all games have been downloaded. - Programrettelser tilgjengelige for alle spill har blitt lastet ned. - - - Games: - Spill: - - - ELF files (*.bin *.elf *.oelf) - ELF-filer (*.bin *.elf *.oelf) - - - Game Boot - Spilloppstart - - - Only one file can be selected! - Kun én fil kan velges! - - - PKG Extraction - PKG-utpakking - - - Patch detected! - Programrettelse oppdaget! - - - PKG and Game versions match: - PKG og spillversjoner stemmer overens: - - - Would you like to overwrite? - Ønsker du å overskrive? - - - PKG Version %1 is older than installed version: - PKG-versjon %1 er eldre enn installert versjon: - - - Game is installed: - Spillet er installert: - - - Would you like to install Patch: - Ønsker du å installere programrettelsen: - - - DLC Installation - DLC installasjon - - - Would you like to install DLC: %1? - Ønsker du å installere DLC: %1? - - - DLC already installed: - DLC allerede installert: - - - Game already installed - Spillet er allerede installert - - - PKG ERROR - PKG FEIL - - - Extracting PKG %1/%2 - Pakker ut PKG %1/%2 - - - Extraction Finished - Utpakking fullført - - - Game successfully installed at %1 - Spillet ble installert i %1 - - - File doesn't appear to be a valid PKG file - Filen ser ikke ut til å være en gyldig PKG-fil - - - Run Game - Run Game - - - Eboot.bin file not found - Eboot.bin file not found - - - PKG File (*.PKG *.pkg) - PKG File (*.PKG *.pkg) - - - PKG is a patch or DLC, please install the game first! - PKG is a patch or DLC, please install the game first! - - - Game is already running! - Game is already running! - - - shadPS4 - shadPS4 - - - - PKGViewer - - Open Folder - Åpne mappe - - - PKG ERROR - PKG FEIL - - - Name - Navn - - - Serial - Serienummer - - - Installed - Installed - - - Size - Størrelse - - - Category - Category - - - Type - Type - - - App Ver - App Ver - - - FW - FW - - - Region - Region - - - Flags - Flags - - - Path - Adresse - - - File - Fil - - - Unknown - Ukjent - - - Package - Package - - - - SettingsDialog - - Settings - Innstillinger - - - General - Generell - - - System - System - - - Console Language - Konsollspråk - - - Emulator Language - Emulatorspråk - - - Emulator - Emulator - - - Enable Fullscreen - Aktiver fullskjerm - - - Fullscreen Mode - Fullskjermmodus - - - Enable Separate Update Folder - Aktiver seperat oppdateringsmappe - - - Default tab when opening settings - Standardfanen når innstillingene åpnes - - - Show Game Size In List - Vis spillstørrelse i listen - - - Show Splash - Vis velkomstbilde - - - Enable Discord Rich Presence - Aktiver Discord Rich Presence - - - Username - Brukernavn - - - Trophy Key - Trofénøkkel - - - Trophy - Trofé - - - Logger - Logger - - - Log Type - Logg type - - - Log Filter - Logg filter - - - Open Log Location - Åpne loggplassering - - - Input - Inndata - - - Cursor - Musepeker - - - Hide Cursor - Skjul musepeker - - - Hide Cursor Idle Timeout - Skjul musepeker ved inaktivitet - - - s - s - - - Controller - Kontroller - - - Back Button Behavior - Tilbakeknapp atferd - - - Graphics - Grafikk - - - GUI - Grensesnitt - - - User - Bruker - - - Graphics Device - Grafikkenhet - - - Width - Bredde - - - Height - Høyde - - - Vblank Divider - Vblank skillelinje - - - Advanced - Avansert - - - Enable Shaders Dumping - Aktiver skyggeleggerdumping - - - Enable NULL GPU - Aktiver NULL GPU - - - Enable HDR - Enable HDR - - - Paths - Mapper - - - Game Folders - Spillmapper - - - Add... - Legg til... - - - Remove - Fjern - - - Debug - Feilretting - - - Enable Debug Dumping - Aktiver feilrettingsdumping - - - Enable Vulkan Validation Layers - Aktiver Vulkan Validation Layers - - - Enable Vulkan Synchronization Validation - Aktiver Vulkan synkroniseringslag - - - Enable RenderDoc Debugging - Aktiver RenderDoc feilretting - - - Enable Crash Diagnostics - Aktiver krasjdiagnostikk - - - Collect Shaders - Lagre skyggeleggere - - - Copy GPU Buffers - Kopier GPU-buffere - - - Host Debug Markers - Vertsfeilsøkingsmarkører - - - Guest Debug Markers - Gjestefeilsøkingsmarkører - - - Update - Oppdatering - - - Check for Updates at Startup - Se etter oppdateringer ved oppstart - - - Always Show Changelog - Always Show Changelog - - - Update Channel - Oppdateringskanal - - - Check for Updates - Se etter oppdateringer - - - GUI Settings - Grensesnitt-innstillinger - - - Title Music - Tittelmusikk - - - Disable Trophy Pop-ups - Deaktiver trofé hurtigmeny - - - Background Image - Bakgrunnsbilde - - - Show Background Image - Vis bakgrunnsbilde - - - Opacity - Synlighet - - - Play title music - Spill tittelmusikk - - - Update Compatibility Database On Startup - Oppdater database ved oppstart - - - Game Compatibility - Spill kompatibilitet - - - Display Compatibility Data - Vis kompatibilitets-data - - - Update Compatibility Database - Oppdater kompatibilitets-database - - - Volume - Volum - - - Save - Lagre - - - Apply - Bruk - - - Restore Defaults - Gjenopprett standardinnstillinger - - - Close - Lukk - - - Point your mouse at an option to display its description. - Pek musen over et alternativ for å vise beskrivelsen. - - - Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. - Konsollspråk:\nAngir språket som PS4-spillet bruker.\nDet anbefales å sette dette til et språk som spillet støtter, noe som kan variere avhengig av region. - - - Emulator Language:\nSets the language of the emulator's user interface. - Emulatorspråket:\nAngir språket for emulatorens brukergrensesnitt. - - - Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. - Aktiver fullskjerm:\nSetter spillvinduet automatisk i fullskjermmodus.\nDette kan slås av ved å trykke på F11-tasten. - - - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. - Aktiver separat oppdateringsmappe:\nAktiverer installering av spill i en egen mappe for enkel administrasjon. - - - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. - Vis velkomstbilde:\nViser spillets velkomstbilde (et spesialbilde) når spillet starter. - - - Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. - Aktiver Discord Rich Presence:\nViser emulatorikonet og relevant informasjon på Discord-profilen din. - - - Username:\nSets the PS4's account username, which may be displayed by some games. - Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill. - - - Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - Trofénøkkel:\nNøkkel brukes til å dekryptere trofeer. Må hentes fra din konsoll (jailbroken).\nMå bare inneholde sekskantede tegn. - - - Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. - Logg type:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter for emulatoren. - - - Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. - Logg filter:\nFiltrerer loggen for å kun skrive ut spesifikk informasjon.\nEksempler: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivåer: Trace, Debug, Info, Warning, Error, Critical - i denne rekkefølgen, et spesifikt nivå demper alle tidligere nivåer i listen og logger alle nivåer etter det. - - - Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. - Oppdatering:\nRelease: Offisielle versjoner utgitt hver måned som kan være veldig utdaterte, men er mer pålitelige og testet.\nNightly: Utviklingsversjoner som har alle de nyeste funksjonene og feilrettingene, men som kan inneholde feil og er mindre stabile. - - - Background Image:\nControl the opacity of the game background image. - Bakgrunnsbilde:\nEndrer synligheten til spillets bakgrunnsbilde. - - - Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - Spille tittelmusikk:\nHvis et spill støtter det, så aktiveres det spesiell musikk når du velger spillet i menyen. - - - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - Deaktiver trofé hurtigmeny:\nDeaktiver trofévarsler i spillet. Trofé-fremgang kan fortsatt ved help av troféviseren (høyreklikk på spillet i hovedvinduet). - - - Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. - Skjul musepeker:\nVelg når musepekeren skal forsvinne:\nAldri: Du vil alltid se musepekeren.\nInaktiv: Sett en tid for at den skal forsvinne etter å ha vært inaktiv.\nAlltid: du vil aldri se musepekeren. - - - Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. - Sett en tid for når musepekeren forsvinner etter å ha vært inaktiv. - - - Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. - Atferd for tilbaketasten:\nSetter tilbaketasten på kontrolleren til å imitere et trykk på den angitte posisjonen på PS4s berøringsplate. - - - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - Vis kompatibilitets-data:\nViser informasjon om spillkompatibilitet i tabellvisning. Aktiver "Oppdater kompatibilitets-data ved oppstart" for oppdatert informasjon. - - - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - Oppdater database ved oppstart:\nOppdaterer kompatibilitets-databasen automatisk når shadPS4 starter. - - - Update Compatibility Database:\nImmediately update the compatibility database. - Oppdater kompatibilitets-database:\nOppdater kompatibilitets-databasen nå. - - - Never - Aldri - - - Idle - Inaktiv - - - Always - Alltid - - - Touchpad Left - Berøringsplate Venstre - - - Touchpad Right - Berøringsplate Høyre - - - Touchpad Center - Berøringsplate Midt - - - None - Ingen - - - Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en emulatoren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å velge automatisk. - - - Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. - Bredde/Høyde:\nAngir størrelsen på emulatorvinduet ved oppstart, som kan endres under spillingen.\nDette er forskjellig fra oppløsningen i spillet. - - - Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! - Vblank skillelinje:\nBildehastigheten som emulatoren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten av spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! - - - Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. - Aktiver skyggeleggerdumping:\nFor teknisk feilsøking lagrer skyggeleggerne fra spillet i en mappe mens de gjengis. - - - Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillets-gjengivelse som om det ikke var noe grafikkort. - - - Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. - Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. - - - Game Folders:\nThe list of folders to check for installed games. - Spillmapper:\nListe over mapper som brukes for å se etter installerte spill. - - - Add:\nAdd a folder to the list. - Legg til:\nLegg til en mappe til listen. - - - Remove:\nRemove a folder from the list. - Fjern:\nFjern en mappe fra listen. - - - Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. - Aktiver feilrettingsdumping:\nLagrer import- og eksport-symbolene og filoverskriftsinformasjonen til det nåværende kjørende PS4-programmet i en katalog. - - - Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. - Aktiver Vulkan Validation Layers:\nAktiverer et system som validerer tilstanden til Vulkan-gjengiveren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. - - - Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. - Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer frekvens tiden av Vulkan-gjengivelsensoppgaver. Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. - - - Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. - Aktiver RenderDoc feilsøking:\nHvis aktivert, vil emulatoren gi kompatibilitet med RenderDoc for å tillate opptak og analyse av det nåværende gjengitte bildet. - - - Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). - Lagre skyggeleggere:\nDu trenger dette aktivert for å redigere skyggeleggerne med feilsøkingsmenyen (Ctrl + F10). - - - Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. - Krasjdiagnostikk:\nOppretter en .yaml-fil med informasjon om Vulkan-tilstanden ved krasj.\nNyttig for feilsøking 'Device lost' feil. Hvis du har dette aktivert, burde du aktivere vert OG gjestefeilsøkingsmarkører.\nFunker ikke med Intel GPU-er.\nDu trenger Vulkan Validation Layers og Vulkan SDK for at dette skal fungere. - - - Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. - Kopier GPU-buffere:\nKommer rundt løpsforhold som involverer GPU-innsendinger.\nKan muligens hjelpe med PM4 type 0 krasj. - - - Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Vertsfeilsøkingsmarkører:\nSetter inn emulator-side informasjon som markører for spesifikke AMDGPU-kommandoer rundt Vulkan-kommandoer, i tillegg til å gi ressurser feilrettingsnavn.\nHvis du har dette aktivert, burde du aktivere krasjdiagnostikk.\nNyttig for programmer som RenderDoc. - - - Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Gjestefeilsøkingsmarkører:\nSetter inn eventuelle feilsøkingsmarkører spillet selv har lagt til kommandobufferen.\nHvis du har dette aktivert, burde du aktivere krasjdiagnostikk.\nNyttig for programmer som RenderDoc. - - - Save Data Path:\nThe folder where game save data will be saved. - Lagrede datamappe:\nListe over data shadPS4 lagrer. - - - Browse:\nBrowse for a folder to set as the save data path. - Endre mappe:\nEndrer hvilken mappe shadPS4 skal lagre data til. - - - Borderless - Borderless - - - True - True - - - Release - Release - - - Nightly - Nightly - - - Set the volume of the background music. - Set the volume of the background music. - - - Enable Motion Controls - Enable Motion Controls - - - Save Data Path - Lagrede datamappe - - - Browse - Endre mappe - - - async - async - - - sync - sync - - - Auto Select - Auto Select - - - Directory to install games - Mappe for å installere spill - - - Directory to save data - Directory to save data - - - - TrophyViewer - - Trophy Viewer - Trofé viser - - - From e13fb2e366042ab66a57a5298101fdb4bba66674 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 16 Feb 2025 05:08:16 -0800 Subject: [PATCH 09/29] renderer_vulkan: Bind descriptors to specific stages in layout. (#2458) --- .../renderer_vulkan/vk_graphics_pipeline.cpp | 18 ++++++++++++++---- .../renderer_vulkan/vk_pipeline_common.cpp | 2 +- .../renderer_vulkan/vk_pipeline_common.h | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 2c432e9bf..901096259 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -19,6 +19,15 @@ namespace Vulkan { using Shader::Backend::SPIRV::AuxShaderType; +static constexpr std::array LogicalStageToStageBit = { + vk::ShaderStageFlagBits::eFragment, + vk::ShaderStageFlagBits::eTessellationControl, + vk::ShaderStageFlagBits::eTessellationEvaluation, + vk::ShaderStageFlagBits::eVertex, + vk::ShaderStageFlagBits::eGeometry, + vk::ShaderStageFlagBits::eCompute, +}; + GraphicsPipeline::GraphicsPipeline( const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap, const Shader::Profile& profile, const GraphicsPipelineKey& key_, @@ -34,7 +43,7 @@ GraphicsPipeline::GraphicsPipeline( const auto debug_str = GetDebugString(); const vk::PushConstantRange push_constants = { - .stageFlags = gp_stage_flags, + .stageFlags = AllGraphicsStageBits, .offset = 0, .size = sizeof(Shader::PushData), }; @@ -352,6 +361,7 @@ void GraphicsPipeline::BuildDescSetLayout() { if (!stage) { continue; } + const auto stage_bit = LogicalStageToStageBit[u32(stage->l_stage)]; for (const auto& buffer : stage->buffers) { const auto sharp = buffer.GetSharp(*stage); bindings.push_back({ @@ -360,7 +370,7 @@ void GraphicsPipeline::BuildDescSetLayout() { ? vk::DescriptorType::eStorageBuffer : vk::DescriptorType::eUniformBuffer, .descriptorCount = 1, - .stageFlags = gp_stage_flags, + .stageFlags = stage_bit, }); } for (const auto& image : stage->images) { @@ -369,7 +379,7 @@ void GraphicsPipeline::BuildDescSetLayout() { .descriptorType = image.is_written ? vk::DescriptorType::eStorageImage : vk::DescriptorType::eSampledImage, .descriptorCount = 1, - .stageFlags = gp_stage_flags, + .stageFlags = stage_bit, }); } for (const auto& sampler : stage->samplers) { @@ -377,7 +387,7 @@ void GraphicsPipeline::BuildDescSetLayout() { .binding = binding++, .descriptorType = vk::DescriptorType::eSampler, .descriptorCount = 1, - .stageFlags = gp_stage_flags, + .stageFlags = stage_bit, }); } } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_common.cpp b/src/video_core/renderer_vulkan/vk_pipeline_common.cpp index bf43257f8..96e19d6a1 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_common.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_common.cpp @@ -37,7 +37,7 @@ void Pipeline::BindResources(DescriptorWrites& set_writes, const BufferBarriers& cmdbuf.pipelineBarrier2(dependencies); } - const auto stage_flags = IsCompute() ? vk::ShaderStageFlagBits::eCompute : gp_stage_flags; + const auto stage_flags = IsCompute() ? vk::ShaderStageFlagBits::eCompute : AllGraphicsStageBits; cmdbuf.pushConstants(*pipeline_layout, stage_flags, 0u, sizeof(push_data), &push_data); // Bind descriptor set. diff --git a/src/video_core/renderer_vulkan/vk_pipeline_common.h b/src/video_core/renderer_vulkan/vk_pipeline_common.h index e9e6fed01..9633fc4ea 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_common.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_common.h @@ -15,7 +15,7 @@ class BufferCache; namespace Vulkan { -static constexpr auto gp_stage_flags = +static constexpr auto AllGraphicsStageBits = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eTessellationControl | vk::ShaderStageFlagBits::eTessellationEvaluation | vk::ShaderStageFlagBits::eGeometry | vk::ShaderStageFlagBits::eFragment; From 0425bd0fd632bbc39beec883b1d1e5a6381b5c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:36:29 +0100 Subject: [PATCH 10/29] Qt: Fix Small Window (#2449) --- src/qt_gui/main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 5cbce1884..7eca2e10f 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -57,7 +57,7 @@ bool MainWindow::Init() { SetLastIconSizeBullet(); GetPhysicalDevices(); // show ui - setMinimumSize(350, minimumSizeHint().height()); + setMinimumSize(720, 405); std::string window_title = ""; if (Common::isRelease) { window_title = fmt::format("shadPS4 v{}", Common::VERSION); From e9b44af46969dd0f19ef2b89d1e6b597dba32695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:36:41 +0100 Subject: [PATCH 11/29] Qt: Use Qt::SmoothTransformation for Cheats Manager (#2450) --- src/qt_gui/cheats_patches.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index e9db88381..01227d822 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -71,7 +71,8 @@ void CheatsPatches::setupUI() { QLabel* gameImageLabel = new QLabel(); if (!m_gameImage.isNull()) { - gameImageLabel->setPixmap(m_gameImage.scaled(275, 275, Qt::KeepAspectRatio)); + gameImageLabel->setPixmap( + m_gameImage.scaled(275, 275, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } else { gameImageLabel->setText(tr("No Image Available")); } @@ -1431,4 +1432,4 @@ void CheatsPatches::onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered) { } else { instructionsTextEdit->setText(defaultTextEdit_MSG); } -} \ No newline at end of file +} From 679f8f1f36df8f9c545e2221ea63be98686cab65 Mon Sep 17 00:00:00 2001 From: rainmakerv2 <30595646+rainmakerv3@users.noreply.github.com> Date: Mon, 17 Feb 2025 18:36:56 +0800 Subject: [PATCH 12/29] Add default values for Lightbar sliders and checkbox, per-game config (#2454) * Update control_settings.cpp * Add default for per game config checkbox as well --- src/qt_gui/control_settings.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index 73622e6b0..0b96eee26 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -306,6 +306,12 @@ void ControlSettings::SetDefault() { ui->LeftDeadzoneSlider->setValue(2); ui->RightDeadzoneSlider->setValue(2); + + ui->RSlider->setValue(0); + ui->GSlider->setValue(0); + ui->BSlider->setValue(255); + ui->LightbarCheckBox->setChecked(false); + ui->PerGameCheckBox->setChecked(false); } void ControlSettings::AddBoxItems() { From 90c01f8d922d4cccd41f817940b45c3603a5f332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:37:11 +0100 Subject: [PATCH 13/29] Qt: Center Installation Dialog (#2453) --- src/qt_gui/main_window.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 7eca2e10f..949d7062e 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -965,6 +965,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int dialog.setAutoClose(true); dialog.setRange(0, nfiles); + dialog.setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, + dialog.size(), this->geometry())); + QFutureWatcher futureWatcher; connect(&futureWatcher, &QFutureWatcher::finished, this, [=, this]() { if (pkgNum == nPkg) { From 195b94c1f1b977fbe31bf1ead4167314ac045a6d Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 17 Feb 2025 12:38:02 +0200 Subject: [PATCH 14/29] New Crowdin updates (#2460) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Albanian) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (Norwegian Bokmal) --- src/qt_gui/translations/nb_NO.ts | 220 ++++----- src/qt_gui/translations/pt_BR.ts | 6 +- src/qt_gui/translations/pt_PT.ts | 780 +++++++++++++++---------------- src/qt_gui/translations/sq_AL.ts | 14 +- 4 files changed, 510 insertions(+), 510 deletions(-) diff --git a/src/qt_gui/translations/nb_NO.ts b/src/qt_gui/translations/nb_NO.ts index 934612683..efeb955fb 100644 --- a/src/qt_gui/translations/nb_NO.ts +++ b/src/qt_gui/translations/nb_NO.ts @@ -11,7 +11,7 @@ shadPS4 - shadPS4 + shadPS4 shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -230,7 +230,7 @@ Directory does not exist: - Mappen eksisterer ikke: + Mappa eksisterer ikke: Failed to open files.json for reading. @@ -411,87 +411,87 @@ ControlSettings Configure Controls - Configure Controls + Sett opp kontroller Control Settings - Control Settings + Kontrollinnstillinger D-Pad - D-Pad + D-Pad Up - Up + Opp Left - Left + Venstre Right - Right + Høyre Down - Down + Ned Left Stick Deadzone (def:2 max:127) - Left Stick Deadzone (def:2 max:127) + Venstre analog dødsone (def:2, maks:127) Left Deadzone - Left Deadzone + Venstre dødsone Left Stick - Left Stick + Venstre analog Config Selection - Config Selection + Utvalg av oppsett Common Config - Common Config + Felles oppsett Use per-game configs - Use per-game configs + Bruk oppsett per spill L1 / LB - L1 / LB + L1 / LB L2 / LT - L2 / LT + L2 / LT KBM Controls - KBM Controls + Mus/tastatur oppsett KBM Editor - KBM Editor + Rediger mus/tastatur Back - Back + Tilbake R1 / RB - R1 / RB + R1 / RB R2 / RT - R2 / RT + R2 / RT L3 - L3 + L3 Options / Start @@ -499,39 +499,39 @@ R3 - R3 + R3 Face Buttons - Face Buttons + Handlingsknapper Triangle / Y - Triangle / Y + Triangel / Y Square / X - Square / X + Firkant / X Circle / B - Circle / B + Sirkel / B Cross / A - Cross / A + Kryss / A Right Stick Deadzone (def:2, max:127) - Right Stick Deadzone (def:2, max:127) + Høyre analog dødsone (def:2, maks:127) Right Deadzone - Right Deadzone + Høyre dødsone Right Stick - Right Stick + Høyre analog @@ -576,7 +576,7 @@ Directory to install DLC - Directory to install DLC + Mappe for å installere DLC @@ -599,7 +599,7 @@ Region - Region + Region Firmware @@ -627,15 +627,15 @@ h - h + h m - m + m s - s + s Compatibility is untested @@ -674,23 +674,23 @@ GameListUtils B - B + B KB - KB + KB MB - MB + MB GB - GB + GB TB - TB + TB @@ -717,15 +717,15 @@ Open Game Folder - Åpne spillmappen + Åpne spillmappa Open Save Data Folder - Åpne lagrede datamappen + Åpne lagrede datamappa Open Log Folder - Åpne loggmappen + Åpne loggmappa Copy info... @@ -821,7 +821,7 @@ DLC - DLC + DLC Delete %1 @@ -833,27 +833,27 @@ Open Update Folder - Open Update Folder + Åpne oppdateringsmappa Delete Save Data - Delete Save Data + Slett lagret data This game has no update folder to open! - This game has no update folder to open! + Dette spillet har ingen oppdateringsmappe å åpne! Failed to convert icon. - Failed to convert icon. + Klarte ikke konvertere ikon. This game has no save data to delete! - This game has no save data to delete! + Dette spillet har ingen lagret data å slette! Save Data - Save Data + Lagret data @@ -868,11 +868,11 @@ Install All Queued to Selected Folder - Install All Queued to Selected Folder + Installer alle i kø til den valgte mappa Delete PKG File on Install - Delete PKG File on Install + Slett PKG-fila ved installering @@ -899,7 +899,7 @@ Configure... - Konfigurer... + Sett opp... Install application from a .pkg file @@ -911,7 +911,7 @@ Open shadPS4 Folder - Open shadPS4 Folder + Åpne shadPS4 mappa Exit @@ -943,7 +943,7 @@ Medium - Medium + Middels Large @@ -1151,27 +1151,27 @@ Run Game - Run Game + Kjør spill Eboot.bin file not found - Eboot.bin file not found + Klarte ikke finne Eboot.bin-fila PKG File (*.PKG *.pkg) - PKG File (*.PKG *.pkg) + PKG-fil (*.PKG *.pkg) PKG is a patch or DLC, please install the game first! - PKG is a patch or DLC, please install the game first! + PKG er en programrettelse eller DLC. Installer spillet først! Game is already running! - Game is already running! + Spillet kjører allerede! shadPS4 - shadPS4 + shadPS4 @@ -1194,7 +1194,7 @@ Installed - Installed + Installert Size @@ -1202,27 +1202,27 @@ Category - Category + Kategori Type - Type + Type App Ver - App Ver + Programversjon FW - FW + FV Region - Region + Region Flags - Flags + Flagg Path @@ -1238,7 +1238,7 @@ Package - Package + Pakke @@ -1253,7 +1253,7 @@ System - System + System Console Language @@ -1265,11 +1265,11 @@ Emulator - Emulator + Emulator Enable Fullscreen - Aktiver fullskjerm + Bruk fullskjerm Fullscreen Mode @@ -1277,7 +1277,7 @@ Enable Separate Update Folder - Aktiver seperat oppdateringsmappe + Bruk seperat oppdateringsmappe Default tab when opening settings @@ -1293,7 +1293,7 @@ Enable Discord Rich Presence - Aktiver Discord Rich Presence + Bruk Discord Rich Presence Username @@ -1309,7 +1309,7 @@ Logger - Logger + Loggføring Log Type @@ -1341,7 +1341,7 @@ s - s + s Controller @@ -1385,15 +1385,15 @@ Enable Shaders Dumping - Aktiver skyggeleggerdumping + Bruk skyggeleggerdumping Enable NULL GPU - Aktiver NULL GPU + Bruk NULL GPU Enable HDR - Enable HDR + Bruk HDR Paths @@ -1417,23 +1417,23 @@ Enable Debug Dumping - Aktiver feilrettingsdumping + Bruk feilrettingsdumping Enable Vulkan Validation Layers - Aktiver Vulkan Validation Layers + Bruk Vulkan Validation Layers Enable Vulkan Synchronization Validation - Aktiver Vulkan synkroniseringslag + Bruk Vulkan Validation Layers Enable RenderDoc Debugging - Aktiver RenderDoc feilretting + Bruk RenderDoc feilsøking Enable Crash Diagnostics - Aktiver krasjdiagnostikk + Bruk krasjdiagnostikk Collect Shaders @@ -1461,7 +1461,7 @@ Always Show Changelog - Always Show Changelog + Vis alltid endringsloggen Update Channel @@ -1549,11 +1549,11 @@ Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. - Aktiver fullskjerm:\nSetter spillvinduet automatisk i fullskjermmodus.\nDette kan slås av ved å trykke på F11-tasten. + Bruk fullskjerm:\nSetter spillvinduet automatisk i fullskjermmodus.\nDette kan slås av ved å trykke på F11-tasten. Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. - Aktiver separat oppdateringsmappe:\nAktiverer installering av spill i en egen mappe for enkel administrasjon. + Bruk separat oppdateringsmappe:\n Gjør det mulig å installere spilloppdateringer i en egen mappe for enkel administrasjon.\nDette kan gjøres manuelt ved å legge til den utpakkede oppdateringen, til spillmappa med navnet "CUSA00000-UPDATE" der CUSA-ID-en samsvarer med spillets-ID. Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. @@ -1561,7 +1561,7 @@ Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. - Aktiver Discord Rich Presence:\nViser emulatorikonet og relevant informasjon på Discord-profilen din. + Bruk Discord Rich Presence:\nViser emulatorikonet og relevant informasjon på Discord-profilen din. Username:\nSets the PS4's account username, which may be displayed by some games. @@ -1589,7 +1589,7 @@ Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - Spille tittelmusikk:\nHvis et spill støtter det, så aktiveres det spesiell musikk når du velger spillet i menyen. + Spill av tittelmusikk:\nHvis et spill støtter det, så brukes det spesiell musikk når du velger spillet i menyen. Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). @@ -1609,7 +1609,7 @@ Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - Vis kompatibilitets-data:\nViser informasjon om spillkompatibilitet i tabellvisning. Aktiver "Oppdater kompatibilitets-data ved oppstart" for oppdatert informasjon. + Vis kompatibilitets-data:\nViser informasjon om spillkompatibilitet i tabellvisning. Bruk "Oppdater kompatibilitets-data ved oppstart" for oppdatert informasjon. Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. @@ -1649,7 +1649,7 @@ Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en emulatoren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å velge automatisk. + Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en emulatoren skal bruke fra rullegardinlisten,\neller "Velg automatisk". Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. @@ -1661,15 +1661,15 @@ Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. - Aktiver skyggeleggerdumping:\nFor teknisk feilsøking lagrer skyggeleggerne fra spillet i en mappe mens de gjengis. + Bruk skyggeleggerdumping:\nFor teknisk feilsøking lagrer skyggeleggerne fra spillet i en mappe mens de gjengis. Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillets-gjengivelse som om det ikke var noe grafikkort. + Bruk Null GPU:\nFor teknisk feilsøking deaktiverer spillets-gjengivelse som om det ikke var noen grafikkort. Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. - Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. + Bruk HDR:\nTillater bruk av HDR i spill som støtter det.\nSkjermen din må ha støtte for BT2020 PQ fargerom og RGB10A2 swapchain-format. Game Folders:\nThe list of folders to check for installed games. @@ -1685,27 +1685,27 @@ Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. - Aktiver feilrettingsdumping:\nLagrer import- og eksport-symbolene og filoverskriftsinformasjonen til det nåværende kjørende PS4-programmet i en katalog. + Bruk feilrettingsdumping:\nLagrer import- og eksport-symbolene og filoverskrifts-informasjonen til det nåværende kjørende PS4-programmet i en mappe. Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. - Aktiver Vulkan Validation Layers:\nAktiverer et system som validerer tilstanden til Vulkan-gjengiveren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. + Bruk Vulkan Validation Layers:\nAktiverer et system som bekrefter tilstanden til Vulkan-gjengiveren og logger informasjon om dens indre tilstand.\n Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. - Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer frekvens tiden av Vulkan-gjengivelsensoppgaver. Dette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. + Bruk Vulkan synkronisering validering:\nEt system som bekrefter frekvens tiden av Vulkan-gjengivelseoppgaver.\nDette vil redusere ytelsen og sannsynligvis endre emulatorens atferd. Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. - Aktiver RenderDoc feilsøking:\nHvis aktivert, vil emulatoren gi kompatibilitet med RenderDoc for å tillate opptak og analyse av det nåværende gjengitte bildet. + Bruk RenderDoc feilsøking:\nHvis brukt, vil emulatoren gi kompatibilitet med RenderDoc for å tillate opptak og analyse av det nåværende gjengitte bildet. Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). - Lagre skyggeleggere:\nDu trenger dette aktivert for å redigere skyggeleggerne med feilsøkingsmenyen (Ctrl + F10). + Lagre skyggeleggere:\nDu trenger dette for å redigere skyggeleggerne med feilsøkingsmenyen (Ctrl + F10). Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. - Krasjdiagnostikk:\nOppretter en .yaml-fil med informasjon om Vulkan-tilstanden ved krasj.\nNyttig for feilsøking 'Device lost' feil. Hvis du har dette aktivert, burde du aktivere vert OG gjestefeilsøkingsmarkører.\nFunker ikke med Intel GPU-er.\nDu trenger Vulkan Validation Layers og Vulkan SDK for at dette skal fungere. + Krasjdiagnostikk:\nOppretter en .yaml-fil med informasjon om Vulkan-tilstanden ved krasj.\nNyttig for feilsøking 'Device lost' feil. Hvis dette brukes, burde du aktivere vert OG gjestefeilsøkingsmarkører.\nFunker ikke med Intel GPU-er.\nDu trenger Vulkan Validation Layers og Vulkan SDK for at dette skal fungere. Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. @@ -1713,11 +1713,11 @@ Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Vertsfeilsøkingsmarkører:\nSetter inn emulator-side informasjon som markører for spesifikke AMDGPU-kommandoer rundt Vulkan-kommandoer, i tillegg til å gi ressurser feilrettingsnavn.\nHvis du har dette aktivert, burde du aktivere krasjdiagnostikk.\nNyttig for programmer som RenderDoc. + Vertsfeilsøkingsmarkører:\nSetter inn emulator-side informasjon som markører for spesifikke AMDGPU-kommandoer rundt Vulkan-kommandoer, i tillegg til å gi ressurser feilrettingsnavn.\nHvis dette brukes, burde du også bruke krasjdiagnostikk.\nNyttig for programmer som RenderDoc. Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Gjestefeilsøkingsmarkører:\nSetter inn eventuelle feilsøkingsmarkører spillet selv har lagt til kommandobufferen.\nHvis du har dette aktivert, burde du aktivere krasjdiagnostikk.\nNyttig for programmer som RenderDoc. + Gjestefeilsøkingsmarkører:\nSetter inn eventuelle feilsøkingsmarkører spillet selv har lagt til kommandobufferen.\nHvis dette brukes, burde du også bruke krasjdiagnostikk.\nNyttig for programmer som RenderDoc. Save Data Path:\nThe folder where game save data will be saved. @@ -1729,11 +1729,11 @@ Borderless - Borderless + Kantløs True - True + Sant Release @@ -1745,11 +1745,11 @@ Set the volume of the background music. - Set the volume of the background music. + Sett volumet til bakgrunnsmusikken. Enable Motion Controls - Enable Motion Controls + Bruk bevegelseskontroller Save Data Path @@ -1769,7 +1769,7 @@ Auto Select - Auto Select + Velg automatisk Directory to install games @@ -1777,7 +1777,7 @@ Directory to save data - Directory to save data + Mappe for lagring av data diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index be9c4d11b..6234a1d86 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -19,7 +19,7 @@ This software should not be used to play games you have not legally obtained. - Este programa não deve ser usado para jogar jogos piratas. + Este programa não deve ser usado para jogar jogos que tenham sido obtidos ilegalmente. @@ -281,7 +281,7 @@ No download URL found for the specified asset. - Nenhuma URL de download encontrada para o asset especificado. + Nenhuma URL de download encontrada para o recurso especificado. Your version is already up to date! @@ -1585,7 +1585,7 @@ Background Image:\nControl the opacity of the game background image. - Imagem de Fundo:\nControla a opacidade da imagem de fundo do jogo. + Imagem de Fundo:\nControla a transparência da imagem de fundo do jogo. Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. diff --git a/src/qt_gui/translations/pt_PT.ts b/src/qt_gui/translations/pt_PT.ts index 1a63c88fd..33fd53953 100644 --- a/src/qt_gui/translations/pt_PT.ts +++ b/src/qt_gui/translations/pt_PT.ts @@ -26,1088 +26,1088 @@ CheatsPatches Cheats / Patches for - Cheats / Patches for + Cheats / Patches para Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n - Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n + Cheats/Patches são experimentais.\nUse com caução.\n\nTransfira os cheats individualmente selecionando o repositório e clicando no botão de transferência.\nNa aba Patches, poderá transferir todos os Patches de uma vez, escolher o qual deseja usar e guardar as suas definições.\n\nComo nós não desenvolvemos os Cheats/Patches,\npor favor, reporte os problemas relacionados com o cheat ao autor deste.\n\nCriou um novo cheat? Visite:\n No Image Available - No Image Available + Nenhuma Imagem Disponível Serial: - Serial: + Número de série: Version: - Version: + Versão: Size: - Size: + Tamanho: Select Cheat File: - Select Cheat File: + Selecionar Ficheiro de Cheat: Repository: - Repository: + Repositório: Download Cheats - Download Cheats + Transferir Cheats Delete File - Delete File + Eliminar Ficheiro No files selected. - No files selected. + Nenhum ficheiro selecionado. You can delete the cheats you don't want after downloading them. - You can delete the cheats you don't want after downloading them. + Poderá eliminar os cheats que não deseja após os transferir. Do you want to delete the selected file?\n%1 - Do you want to delete the selected file?\n%1 + Pretende eliminar o ficheiro selecionado?\n%1 Select Patch File: - Select Patch File: + Selecionar Ficheiro de Patch: Download Patches - Download Patches + Transferir Patches Save - Save + Guardar Cheats - Cheats + Cheats Patches - Patches + Patches Error - Error + Erro No patch selected. - No patch selected. + Nenhum patch selecionado. Unable to open files.json for reading. - Unable to open files.json for reading. + Não foi possível abrir files.json para leitura. No patch file found for the current serial. - No patch file found for the current serial. + Nenhum ficheiro de patch encontrado para o número de série atual. Unable to open the file for reading. - Unable to open the file for reading. + Não foi possível abrir o ficheiro para leitura. Unable to open the file for writing. - Unable to open the file for writing. + Não foi possível abrir o ficheiro para escrita. Failed to parse XML: - Failed to parse XML: + Erro ao interpretar XML: Success - Success + Sucesso Options saved successfully. - Options saved successfully. + Opções guardadas com sucesso. Invalid Source - Invalid Source + Fonte Inválida The selected source is invalid. - The selected source is invalid. + A fonte selecionada é inválida. File Exists - File Exists + O Ficheiro já Existe File already exists. Do you want to replace it? - File already exists. Do you want to replace it? + O ficheiro já existe. Deseja substituí-lo? Failed to save file: - Failed to save file: + Erro ao guardar o ficheiro: Failed to download file: - Failed to download file: + Erro ao transferir o ficheiro: Cheats Not Found - Cheats Not Found + Cheats Não Encontrados No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. - No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. + Não foi encontrado nenhum Cheat para esta versão do jogo no repositório selecionado, tente outro repositório ou uma versão diferente do jogo. Cheats Downloaded Successfully - Cheats Downloaded Successfully + Cheats Transferidos com Sucesso You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. - You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. + Transferiu os cheats para esta versão do jogo através do repositório selecionado com sucesso. Poderá tentar transferir de outro repositório, e se disponível, será possível utilizá-lo selecionando o ficheiro a partir da lista. Failed to save: - Failed to save: + Erro ao guardar: Failed to download: - Failed to download: + Erro ao transferir: Download Complete - Download Complete + Transferência Concluída Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. - Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. + Patches Transferidos com Sucesso! Foram transferidos todos os patches disponíveis para todos os jogos, não sendo necessário transferir individualmente para cada jogo como acontece com os Cheats. Se o patch não aparecer, pode ser que não esteja disponível para o número de série e versão específicos do jogo. Failed to parse JSON data from HTML. - Failed to parse JSON data from HTML. + Falha ao interpretar dados JSON através do HTML. Failed to retrieve HTML page. - Failed to retrieve HTML page. + Falha ao recuperar a página HTML. The game is in version: %1 - The game is in version: %1 + O jogo está na versão: %1 The downloaded patch only works on version: %1 - The downloaded patch only works on version: %1 + O patch transferido só funciona na versão: %1 You may need to update your game. - You may need to update your game. + Talvez seja necessário atualizar o seu jogo. Incompatibility Notice - Incompatibility Notice + Aviso de Incompatibilidade Failed to open file: - Failed to open file: + Erro ao abrir o ficheiro: XML ERROR: - XML ERROR: + ERRO XML: Failed to open files.json for writing - Failed to open files.json for writing + Não foi possível abrir files.json para escrita Author: - Author: + Autor: Directory does not exist: - Directory does not exist: + A pasta não existe: Failed to open files.json for reading. - Failed to open files.json for reading. + Não foi possível abrir files.json para leitura. Name: - Name: + Nome: Can't apply cheats before the game is started - Can't apply cheats before the game is started + Não é possível aplicar cheats antes de iniciar o jogo Close - Close + Fechar CheckUpdate Auto Updater - Auto Updater + Atualizador Automático Error - Error + Erro Network error: - Network error: + Erro de rede: The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. - The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. + O Atualizador Automático permite até 60 verificações de atualização por hora.\nJá atingiu este limite. Por favor, tente novamente mais tarde. Failed to parse update information. - Failed to parse update information. + Falha ao interpretar as informações de atualização. No pre-releases found. - No pre-releases found. + Nenhuma versão de pré-lançamento encontrada. Invalid release data. - Invalid release data. + Dados de lançamento inválidos. No download URL found for the specified asset. - No download URL found for the specified asset. + Nenhum URL de transferência encontrado para o recurso especificado. Your version is already up to date! - Your version is already up to date! + A sua versão já é a mais recente! Update Available - Update Available + Atualização Disponível Update Channel - Update Channel + Canal de Atualização Current Version - Current Version + Versão Atual Latest Version - Latest Version + Última Versão Do you want to update? - Do you want to update? + Deseja atualizar? Show Changelog - Show Changelog + Mostrar Lista de Alterações Check for Updates at Startup - Check for Updates at Startup + Procurar Atualizações ao Iniciar Update - Update + Atualizar No - No + Não Hide Changelog - Hide Changelog + Ocultar Lista de Alterações Changes - Changes + Alterações Network error occurred while trying to access the URL - Network error occurred while trying to access the URL + Ocorreu um erro de rede ao tentar aceder ao URL Download Complete - Download Complete + Transferência Concluída The update has been downloaded, press OK to install. - The update has been downloaded, press OK to install. + A atualização foi transferida, pressione OK para instalar. Failed to save the update file at - Failed to save the update file at + Erro ao guardar o ficheiro de atualização em Starting Update... - Starting Update... + A Iniciar Atualização... Failed to create the update script file - Failed to create the update script file + Erro ao criar o ficheiro de script de atualização CompatibilityInfoClass Fetching compatibility data, please wait - Fetching compatibility data, please wait + A obter dados de compatibilidade, por favor aguarde Cancel - Cancel + Cancelar Loading... - Loading... + A Carregar... Error - Error + Erro Unable to update compatibility data! Try again later. - Unable to update compatibility data! Try again later. + Não foi possível atualizar os dados de compatibilidade! Tente novamente mais tarde. Unable to open compatibility_data.json for writing. - Unable to open compatibility_data.json for writing. + Não foi possível abrir compatibility_data.json para escrita. Unknown - Unknown + Desconhecido Nothing - Nothing + Nada Boots - Boots + Arranca Menus - Menus + Menus Ingame - Ingame + Em Jogo Playable - Playable + Jogável ControlSettings Configure Controls - Configure Controls + Configurar Comandos Control Settings - Control Settings + Definições do Comando D-Pad - D-Pad + Botões de Direção Up - Up + Cima Left - Left + Esquerda Right - Right + Direita Down - Down + Baixo Left Stick Deadzone (def:2 max:127) - Left Stick Deadzone (def:2 max:127) + Zona Morta do Manípulo Esquerdo (def: 2, max: 127) Left Deadzone - Left Deadzone + Zona Morta Esquerda Left Stick - Left Stick + Manípulo Esquerdo Config Selection - Config Selection + Seleção de Configuração Common Config - Common Config + Configuração Comum Use per-game configs - Use per-game configs + Utilizar configurações por jogo L1 / LB - L1 / LB + L1 / LB L2 / LT - L2 / LT + L2 / LT KBM Controls - KBM Controls + Controlo KBM KBM Editor - KBM Editor + Editor KBM Back - Back + Voltar R1 / RB - R1 / RB + R1 / RB R2 / RT - R2 / RT + R2 / RT L3 - L3 + L3 Options / Start - Options / Start + Opções / Start R3 - R3 + R3 Face Buttons - Face Buttons + Botões Frontais Triangle / Y - Triangle / Y + Triângulo / Y Square / X - Square / X + Quadrado / X Circle / B - Circle / B + Círculo / B Cross / A - Cross / A + Cruz / A Right Stick Deadzone (def:2, max:127) - Right Stick Deadzone (def:2, max:127) + Zona Morta do Manípulo Direito (def: 2, max: 127) Right Deadzone - Right Deadzone + Zona Morta Direita Right Stick - Right Stick + Manípulo Direito ElfViewer Open Folder - Open Folder + Abrir Pasta GameInfoClass Loading game list, please wait :3 - Loading game list, please wait :3 + A carregar a lista de jogos, por favor aguarde :3 Cancel - Cancel + Cancelar Loading... - Loading... + A Carregar... GameInstallDialog shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Escolher diretório Directory to install games - Directory to install games + Diretório onde instalar os jogos Browse - Browse + Procurar Error - Error + Erro Directory to install DLC - Directory to install DLC + Diretório onde instalar os DLC GameListFrame Icon - Icon + Ícone Name - Name + Nome Serial - Serial + Número de Série Compatibility - Compatibility + Compatibilidade Region - Region + Região Firmware - Firmware + Firmware Size - Size + Tamanho Version - Version + Versão Path - Path + Caminho Play Time - Play Time + Tempo de Jogo Never Played - Never Played + Nunca Jogado h - h + h m - m + m s - s + s Compatibility is untested - Compatibility is untested + A compatibilidade não foi testada Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + O jogo não arranca corretamente / bloqueia o emulador Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + O jogo arranca, mas não exibe nada Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + O jogo exibe imagem, mas não passa do menu Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + O jogo tem falhas ou desempenho que o tornam injogável Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + O jogo pode ser concluído com desempenho jogável e sem grandes problemas Click to see details on github - Click to see details on github + Clique para ver os detalhes no github Last updated - Last updated + Última atualização GameListUtils B - B + B KB - KB + KB MB - MB + MB GB - GB + GB TB - TB + TB GuiContextMenus Create Shortcut - Create Shortcut + Criar Atalho Cheats / Patches - Cheats / Patches + Cheats / Patches SFO Viewer - SFO Viewer + Visualizador SFO Trophy Viewer - Trophy Viewer + Visualizador de Troféus Open Folder... - Open Folder... + Abrir Pasta... Open Game Folder - Open Game Folder + Abrir Pasta do Jogo Open Save Data Folder - Open Save Data Folder + Abrir Pasta de Dados Guardados Open Log Folder - Open Log Folder + Abrir Pasta de Registo Copy info... - Copy info... + Copiar informação... Copy Name - Copy Name + Copiar Nome Copy Serial - Copy Serial + Copiar Número de Série Copy Version - Copy Version + Copiar Versão Copy Size - Copy Size + Copiar Tamanho Copy All - Copy All + Copiar Tudo Delete... - Delete... + Eliminar... Delete Game - Delete Game + Eliminar Jogo Delete Update - Delete Update + Eliminar Atualização Delete DLC - Delete DLC + Eliminar DLC Compatibility... - Compatibility... + Compatibilidade... Update database - Update database + Atualizar Base de Dados View report - View report + Ver relatório Submit a report - Submit a report + Submeter um relatório Shortcut creation - Shortcut creation + Criação de atalho Shortcut created successfully! - Shortcut created successfully! + Atalho criado com sucesso! Error - Error + Erro Error creating shortcut! - Error creating shortcut! + Erro ao criar atalho! Install PKG - Install PKG + Instalar PKG Game - Game + Jogo This game has no update to delete! - This game has no update to delete! + Este jogo não tem nenhuma atualização para eliminar! Update - Update + Atualizar This game has no DLC to delete! - This game has no DLC to delete! + Este jogo não tem nenhum DLC para eliminar! DLC - DLC + DLC Delete %1 - Delete %1 + Eliminar %1 Are you sure you want to delete %1's %2 directory? - Are you sure you want to delete %1's %2 directory? + Tem certeza de que deseja eliminar o diretório %2 de %1? Open Update Folder - Open Update Folder + Abrir Pasta da Atualização Delete Save Data - Delete Save Data + Eliminar Dados Guardados This game has no update folder to open! - This game has no update folder to open! + Este jogo não tem nenhuma pasta de atualização para abrir! Failed to convert icon. - Failed to convert icon. + Falha ao converter ícone. This game has no save data to delete! - This game has no save data to delete! + Este jogo não tem dados guardados para eliminar! Save Data - Save Data + Dados Guardados InstallDirSelect shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Escolher diretório Select which directory you want to install to. - Select which directory you want to install to. + Selecione o diretório em que deseja instalar. Install All Queued to Selected Folder - Install All Queued to Selected Folder + Instalar Todos os Pendentes para a Pasta Selecionada Delete PKG File on Install - Delete PKG File on Install + Eliminar Ficheiro PKG após Instalação MainWindow Open/Add Elf Folder - Open/Add Elf Folder + Abrir/Adicionar pasta Elf Install Packages (PKG) - Install Packages (PKG) + Instalar Pacotes (PKG) Boot Game - Boot Game + Iniciar Jogo Check for Updates - Check for Updates + Procurar Atualizações About shadPS4 - About shadPS4 + Sobre o shadPS4 Configure... - Configure... + Configurar... Install application from a .pkg file - Install application from a .pkg file + Instalar aplicação através de um ficheiro .pkg Recent Games - Recent Games + Jogos Recentes Open shadPS4 Folder - Open shadPS4 Folder + Abrir Pasta do shadPS4 Exit - Exit + Sair Exit shadPS4 - Exit shadPS4 + Sair do shadPS4 Exit the application. - Exit the application. + Sair da aplicação. Show Game List - Show Game List + Mostrar Lista de Jogos Game List Refresh - Game List Refresh + Atualizar Lista de Jogos Tiny - Tiny + Muito Pequeno Small - Small + Pequeno Medium - Medium + Médio Large - Large + Grande List View - List View + Visualizar em Lista Grid View - Grid View + Visualizar em Grelha Elf Viewer - Elf Viewer + Visualizador Elf Game Install Directory - Game Install Directory + Diretório de Instalação dos Jogos Download Cheats/Patches - Download Cheats/Patches + Transferir Cheats/Patches Dump Game List - Dump Game List + Exportar Lista de Jogos PKG Viewer - PKG Viewer + Visualizador PKG Search... - Search... + Procurar... File - File + Ficheiro View - View + Ver Game List Icons - Game List Icons + Ícones da Lista de Jogos Game List Mode - Game List Mode + Modo da Lista de Jogos Settings - Settings + Definições Utils - Utils + Utilidades Themes - Themes + Temas Help - Help + Ajuda Dark - Dark + Escuro Light - Light + Claro Green - Green + Verde Blue - Blue + Azul Violet - Violet + Violeta toolBar - toolBar + Barra de Ferramentas Game List - Game List + Lista de Jogos * Unsupported Vulkan Version - * Unsupported Vulkan Version + * Versão do Vulkan não suportada Download Cheats For All Installed Games - Download Cheats For All Installed Games + Transferir Cheats para Todos os Jogos Instalados Download Patches For All Games - Download Patches For All Games + Transferir Patches para Todos os Jogos Download Complete - Download Complete + Transferência Concluída You have downloaded cheats for all the games you have installed. - You have downloaded cheats for all the games you have installed. + Transferiu cheats para todos os jogos instalados. Patches Downloaded Successfully! - Patches Downloaded Successfully! + Patches Transferidos com Sucesso! All Patches available for all games have been downloaded. - All Patches available for all games have been downloaded. + Foram transferidos todos os Patches disponíveis para os jogos. Games: - Games: + Jogos: ELF files (*.bin *.elf *.oelf) - ELF files (*.bin *.elf *.oelf) + Ficheiros ELF (*.bin *.elf *.oelf) Game Boot - Game Boot + Arranque do Jogo Only one file can be selected! - Only one file can be selected! + Apenas um ficheiro pode ser selecionado! PKG Extraction - PKG Extraction + Extração de PKG Patch detected! - Patch detected! + Patch detetado! PKG and Game versions match: - PKG and Game versions match: + As versões do PKG e do Jogo coincidem: Would you like to overwrite? - Would you like to overwrite? + Gostaria de substituir? PKG Version %1 is older than installed version: - PKG Version %1 is older than installed version: + A versão do PKG %1 é mais antiga do que a versão instalada: Game is installed: - Game is installed: + O jogo está instalado: Would you like to install Patch: @@ -1115,98 +1115,98 @@ DLC Installation - DLC Installation + Instalação de DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Deseja instalar o DLC: %1? DLC already installed: - DLC already installed: + DLC já está instalado: Game already installed - Game already installed + O jogo já está instalado PKG ERROR - PKG ERROR + ERRO PKG Extracting PKG %1/%2 - Extracting PKG %1/%2 + A extrair PKG %1/%2 Extraction Finished - Extraction Finished + Extração Finalizada Game successfully installed at %1 - Game successfully installed at %1 + Jogo instalado com sucesso em %1 File doesn't appear to be a valid PKG file - File doesn't appear to be a valid PKG file + O ficheiro não aparenta ser um ficheiro PKG válido Run Game - Run Game + Executar Jogo Eboot.bin file not found - Eboot.bin file not found + Ficheiro eboot.bin não encontrado PKG File (*.PKG *.pkg) - PKG File (*.PKG *.pkg) + Ficheiro PKG (*.PKG *.pkg) PKG is a patch or DLC, please install the game first! - PKG is a patch or DLC, please install the game first! + Este PKG é um patch ou DLC, por favor instale o respetivo jogo primeiro! Game is already running! - Game is already running! + O jogo já está a ser executado! shadPS4 - shadPS4 + shadPS4 PKGViewer Open Folder - Open Folder + Abrir Pasta PKG ERROR - PKG ERROR + ERRO PKG Name - Name + Nome Serial - Serial + Número de Série Installed - Installed + Instalado Size - Size + Tamanho Category - Category + Categoria Type - Type + Tipo App Ver @@ -1214,330 +1214,330 @@ FW - FW + FW Region - Region + Região Flags - Flags + Flags Path - Path + Caminho File - File + Ficheiro Unknown - Unknown + Desconhecido Package - Package + Pacote SettingsDialog Settings - Settings + Definições General - General + Geral System - System + Sistema Console Language - Console Language + Idioma da Consola Emulator Language - Emulator Language + Idioma do Emulador Emulator - Emulator + Emulador Enable Fullscreen - Enable Fullscreen + Ativar Ecrã Inteiro Fullscreen Mode - Fullscreen Mode + Modo de Ecrã Inteiro Enable Separate Update Folder - Enable Separate Update Folder + Ativar Pasta de Atualizações Separada Default tab when opening settings - Default tab when opening settings + Aba padrão ao abrir as definições Show Game Size In List - Show Game Size In List + Mostrar Tamanho do Jogo na Lista Show Splash - Show Splash + Mostrar Splash Enable Discord Rich Presence - Enable Discord Rich Presence + Ativar Discord Rich Presence Username - Username + Nome de Utilizador Trophy Key - Trophy Key + Chave de Troféus Trophy - Trophy + Troféus Logger - Logger + Registos Log Type - Log Type + Tipo de Registo Log Filter - Log Filter + Filtro do Registo Open Log Location - Open Log Location + Abrir Localização do Registo Input - Input + Entrada Cursor - Cursor + Cursor Hide Cursor - Hide Cursor + Ocultar Cursor Hide Cursor Idle Timeout - Hide Cursor Idle Timeout + Tempo de Espera para Ocultar Cursor s - s + s Controller - Controller + Comando Back Button Behavior - Back Button Behavior + Comportamento do Botão Voltar Graphics - Graphics + Gráficos GUI - GUI + GUI User - User + Utilizador Graphics Device - Graphics Device + Placa Gráfica Width - Width + Largura Height - Height + Altura Vblank Divider - Vblank Divider + Divisor Vblank Advanced - Advanced + Avançado Enable Shaders Dumping - Enable Shaders Dumping + Ativar Dumping de Shaders Enable NULL GPU - Enable NULL GPU + Ativar GPU NULL Enable HDR - Enable HDR + Ativar HDR Paths - Paths + Caminhos Game Folders - Game Folders + Pastas de Jogos Add... - Add... + Adicionar... Remove - Remove + Remover Debug - Debug + Depuração Enable Debug Dumping - Enable Debug Dumping + Ativar Dumping da Depuração Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Ativar Camadas de Validação do Vulkan Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Ativar Validação da Sincronização do Vulkan Enable RenderDoc Debugging - Enable RenderDoc Debugging + Ativar Depuração por RenderDoc Enable Crash Diagnostics - Enable Crash Diagnostics + Ativar Diagnóstico de Falhas Collect Shaders - Collect Shaders + Recolher Shaders Copy GPU Buffers - Copy GPU Buffers + Copiar Buffers da GPU Host Debug Markers - Host Debug Markers + Marcadores de Depuração do Host Guest Debug Markers - Guest Debug Markers + Marcadores de Depuração do Cliente Update - Update + Atualização Check for Updates at Startup - Check for Updates at Startup + Procurar Atualizações ao Iniciar Always Show Changelog - Always Show Changelog + Mostrar Sempre o Histórico de Mudanças Update Channel - Update Channel + Canal de Atualização Check for Updates - Check for Updates + Procurar Atualizações GUI Settings - GUI Settings + Definições da Interface Title Music - Title Music + Música de Título Disable Trophy Pop-ups - Disable Trophy Pop-ups + Desativar Pop-ups dos Troféus Background Image - Background Image + Imagem de Fundo Show Background Image - Show Background Image + Mostrar Imagem de Fundo Opacity - Opacity + Opacidade Play title music - Play title music + Reproduzir Música de Título Update Compatibility Database On Startup - Update Compatibility Database On Startup + Atualizar Base de Dados de Compatibilidade no Arranque Game Compatibility - Game Compatibility + Compatibilidade dos Jogos Display Compatibility Data - Display Compatibility Data + Exibir Dados de Compatibilidade Update Compatibility Database - Update Compatibility Database + Atualizar Base de Dados de Compatibilidade Volume - Volume + Volume Save - Save + Guardar Apply - Apply + Aplicar Restore Defaults - Restore Defaults + Restaurar Predefinições Close - Close + Fechar Point your mouse at an option to display its description. - Point your mouse at an option to display its description. + Passe o ponteiro do rato sobre uma opção para exibir a sua descrição. Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. @@ -1621,31 +1621,31 @@ Never - Never + Nunca Idle - Idle + Inativo Always - Always + Sempre Touchpad Left - Touchpad Left + Esquerda do Touchpad Touchpad Right - Touchpad Right + Direita do Touchpad Touchpad Center - Touchpad Center + Centro do Touchpad None - None + Nenhum Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. @@ -1677,11 +1677,11 @@ Add:\nAdd a folder to the list. - Add:\nAdd a folder to the list. + Adicionar:\nAdicionar uma pasta à lista. Remove:\nRemove a folder from the list. - Remove:\nRemove a folder from the list. + Remover:\nRemover uma pasta da lista. Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. @@ -1729,62 +1729,62 @@ Borderless - Borderless + Janela sem Bordas True - True + Verdadeiro Release - Release + Lançamento Nightly - Nightly + Nightly Set the volume of the background music. - Set the volume of the background music. + Definir o volume da música de fundo. Enable Motion Controls - Enable Motion Controls + Ativar Comandos de Movimento Save Data Path - Save Data Path + Caminho dos Dados Guardados Browse - Browse + Procurar async - async + assíncrono sync - sync + síncrono Auto Select - Auto Select + Seleção Automática Directory to install games - Directory to install games + Diretório onde instalar os jogos Directory to save data - Directory to save data + Diretório onde guardar os dados TrophyViewer Trophy Viewer - Trophy Viewer + Visualizador de Troféus diff --git a/src/qt_gui/translations/sq_AL.ts b/src/qt_gui/translations/sq_AL.ts index 9e25a19eb..2ecf36e8a 100644 --- a/src/qt_gui/translations/sq_AL.ts +++ b/src/qt_gui/translations/sq_AL.ts @@ -325,7 +325,7 @@ Hide Changelog - Fshih ndryshimet + Fshih Ndryshimet Changes @@ -757,11 +757,11 @@ Delete Game - Fshi lojën + Fshi Lojën Delete Update - Fshi përditësimin + Fshi Përditësimin Delete DLC @@ -837,7 +837,7 @@ Delete Save Data - Fshi të dhënat e ruajtjes + Fshi të Dhënat e Ruajtjes This game has no update folder to open! @@ -911,7 +911,7 @@ Open shadPS4 Folder - Hap dosjen e shadPS4 + Hap Dosjen e shadPS4 Exit @@ -1261,7 +1261,7 @@ Emulator Language - Gjuha e emulatorit + Gjuha e Emulatorit Emulator @@ -1737,7 +1737,7 @@ Release - Botimi + Release Nightly From b06790dfe58431276bc74e39b500c7478046292a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:38:17 +0100 Subject: [PATCH 15/29] Qt: Better title bar for SFO Viewer menu (#2462) --- src/qt_gui/gui_context_menus.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 262a1d733..deb35de8d 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -161,6 +161,7 @@ public: if (selected == &openSfoViewer) { PSF psf; + QString gameName = QString::fromStdString(m_games[itemID].name); std::filesystem::path game_folder_path = m_games[itemID].path; std::filesystem::path game_update_path = game_folder_path; game_update_path += "-UPDATE"; @@ -234,7 +235,7 @@ public: tableWidget->horizontalHeader()->setVisible(false); tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); - tableWidget->setWindowTitle(tr("SFO Viewer")); + tableWidget->setWindowTitle(tr("SFO Viewer for ") + gameName); tableWidget->show(); } } From fd3d3c4158e517b33afbb2f5890d606f042c0b45 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 17 Feb 2025 06:13:39 -0800 Subject: [PATCH 16/29] shader_recompiler: Implement AMD buffer bounds checking behavior. (#2448) * shader_recompiler: Implement AMD buffer bounds checking behavior. * shader_recompiler: Use SRT flatbuf for bounds check size. * shader_recompiler: Fix buffer atomic bounds check. * buffer_cache: Prevent false image-to-buffer sync. Lowering vertex fetch to formatted buffer surfaced an issue where a CPU modified range may be overwritten with stale GPU modified image data. * Address review comments. --- .../backend/spirv/emit_spirv_atomic.cpp | 26 ++- .../spirv/emit_spirv_context_get_set.cpp | 185 +++++++++++++----- .../backend/spirv/emit_spirv_special.cpp | 2 +- .../backend/spirv/spirv_emit_context.cpp | 101 +++++++--- .../backend/spirv/spirv_emit_context.h | 7 +- .../frontend/fetch_shader.cpp | 9 +- src/shader_recompiler/frontend/fetch_shader.h | 2 + .../frontend/translate/translate.cpp | 90 ++++++--- .../frontend/translate/translate.h | 2 + .../frontend/translate/vector_memory.cpp | 4 + src/shader_recompiler/info.h | 30 +-- src/shader_recompiler/ir/reg.h | 1 + src/shader_recompiler/profile.h | 1 + src/video_core/buffer_cache/buffer_cache.cpp | 6 +- .../renderer_vulkan/vk_instance.cpp | 37 ++-- src/video_core/renderer_vulkan/vk_instance.h | 18 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 1 + .../renderer_vulkan/vk_rasterizer.cpp | 1 - .../renderer_vulkan/vk_rasterizer.h | 11 +- 19 files changed, 376 insertions(+), 158 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 92cfcbb0f..4faa99fe8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -21,6 +21,28 @@ Id SharedAtomicU32(EmitContext& ctx, Id offset, Id value, return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value); } +Id BufferAtomicU32BoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto emit_func) { + if (Sirit::ValidId(buffer_size)) { + // Bounds checking enabled, wrap in a conditional branch to make sure that + // the atomic is not mistakenly executed when the index is out of bounds. + const Id in_bounds = ctx.OpULessThan(ctx.U1[1], index, buffer_size); + const Id ib_label = ctx.OpLabel(); + const Id oob_label = ctx.OpLabel(); + const Id end_label = ctx.OpLabel(); + ctx.OpBranchConditional(in_bounds, ib_label, oob_label); + ctx.AddLabel(ib_label); + const Id ib_result = emit_func(); + ctx.OpBranch(end_label); + ctx.AddLabel(oob_label); + const Id oob_result = ctx.u32_zero_value; + ctx.OpBranch(end_label); + ctx.AddLabel(end_label); + return ctx.OpPhi(ctx.U32[1], ib_result, ib_label, oob_result, oob_label); + } + // Bounds checking not enabled, just perform the atomic operation. + return emit_func(); +} + Id BufferAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value, Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) { const auto& buffer = ctx.buffers[handle]; @@ -31,7 +53,9 @@ Id BufferAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id const auto [id, pointer_type] = buffer[EmitContext::BufferAlias::U32]; const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index); const auto [scope, semantics]{AtomicArgs(ctx)}; - return (ctx.*atomic_func)(ctx.U32[1], ptr, scope, semantics, value); + return BufferAtomicU32BoundsCheck(ctx, index, buffer.size_dwords, [&] { + return (ctx.*atomic_func)(ctx.U32[1], ptr, scope, semantics, value); + }); } Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value, diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index cc7b7e097..e4071bb95 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -178,14 +178,21 @@ Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index) { index = ctx.OpIAdd(ctx.U32[1], index, buffer.offset_dwords); const auto [id, pointer_type] = buffer[BufferAlias::U32]; const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; - return ctx.OpLoad(ctx.U32[1], ptr); + const Id result{ctx.OpLoad(ctx.U32[1], ptr)}; + + if (Sirit::ValidId(buffer.size_dwords)) { + const Id in_bounds = ctx.OpULessThan(ctx.U1[1], index, buffer.size_dwords); + return ctx.OpSelect(ctx.U32[1], in_bounds, result, ctx.u32_zero_value); + } else { + return result; + } } Id EmitReadStepRate(EmitContext& ctx, int rate_idx) { + const auto index{rate_idx == 0 ? PushData::Step0Index : PushData::Step1Index}; return ctx.OpLoad( ctx.U32[1], ctx.OpAccessChain(ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1]), - ctx.push_data_block, - rate_idx == 0 ? ctx.u32_zero_value : ctx.u32_one_value)); + ctx.push_data_block, ctx.ConstU32(index))); } static Id EmitGetAttributeForGeometry(EmitContext& ctx, IR::Attribute attr, u32 comp, Id index) { @@ -402,8 +409,30 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) { ctx.OpStore(pointer, value); } +template +static Id EmitLoadBufferBoundsCheck(EmitContext& ctx, Id index, Id buffer_size, Id result, + bool is_float) { + if (Sirit::ValidId(buffer_size)) { + // Bounds checking enabled, wrap in a select. + const auto result_type = is_float ? ctx.F32[N] : ctx.U32[N]; + auto compare_index = index; + auto zero_value = is_float ? ctx.f32_zero_value : ctx.u32_zero_value; + if (N > 1) { + compare_index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(N - 1)); + std::array zero_ids; + zero_ids.fill(zero_value); + zero_value = ctx.ConstantComposite(result_type, zero_ids); + } + const Id in_bounds = ctx.OpULessThan(ctx.U1[1], compare_index, buffer_size); + return ctx.OpSelect(result_type, in_bounds, result, zero_value); + } + // Bounds checking not enabled, just return the plain value. + return result; +} + template -static Id EmitLoadBufferB32xN(EmitContext& ctx, u32 handle, Id address) { +static Id EmitLoadBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { + const auto flags = inst->Flags(); const auto& spv_buffer = ctx.buffers[handle]; if (Sirit::ValidId(spv_buffer.offset)) { address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); @@ -411,31 +440,42 @@ static Id EmitLoadBufferB32xN(EmitContext& ctx, u32 handle, Id address) { const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); const auto& data_types = alias == BufferAlias::U32 ? ctx.U32 : ctx.F32; const auto [id, pointer_type] = spv_buffer[alias]; - if constexpr (N == 1) { - const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; - return ctx.OpLoad(data_types[1], ptr); - } else { - boost::container::static_vector ids; - for (u32 i = 0; i < N; i++) { - const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); - const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i)}; - ids.push_back(ctx.OpLoad(data_types[1], ptr)); + + boost::container::static_vector ids; + for (u32 i = 0; i < N; i++) { + const Id index_i = i == 0 ? index : ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); + const Id ptr_i = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i); + const Id result_i = ctx.OpLoad(data_types[1], ptr_i); + if (!flags.typed) { + // Untyped loads have bounds checking per-component. + ids.push_back(EmitLoadBufferBoundsCheck<1>(ctx, index_i, spv_buffer.size_dwords, + result_i, alias == BufferAlias::F32)); + } else { + ids.push_back(result_i); } - return ctx.OpCompositeConstruct(data_types[N], ids); } + + const Id result = N == 1 ? ids[0] : ctx.OpCompositeConstruct(data_types[N], ids); + if (flags.typed) { + // Typed loads have single bounds check for the whole load. + return EmitLoadBufferBoundsCheck(ctx, index, spv_buffer.size_dwords, result, + alias == BufferAlias::F32); + } + return result; } -Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { +Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { const auto& spv_buffer = ctx.buffers[handle]; if (Sirit::ValidId(spv_buffer.offset)) { address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); } const auto [id, pointer_type] = spv_buffer[BufferAlias::U8]; const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)}; - return ctx.OpUConvert(ctx.U32[1], ctx.OpLoad(ctx.U8, ptr)); + const Id result{ctx.OpUConvert(ctx.U32[1], ctx.OpLoad(ctx.U8, ptr))}; + return EmitLoadBufferBoundsCheck<1>(ctx, address, spv_buffer.size, result, false); } -Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { +Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { const auto& spv_buffer = ctx.buffers[handle]; if (Sirit::ValidId(spv_buffer.offset)) { address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); @@ -443,47 +483,73 @@ Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { const auto [id, pointer_type] = spv_buffer[BufferAlias::U16]; const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(1u)); const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; - return ctx.OpUConvert(ctx.U32[1], ctx.OpLoad(ctx.U16, ptr)); + const Id result{ctx.OpUConvert(ctx.U32[1], ctx.OpLoad(ctx.U16, ptr))}; + return EmitLoadBufferBoundsCheck<1>(ctx, index, spv_buffer.size_shorts, result, false); } -Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferB32xN<1, BufferAlias::U32>(ctx, handle, address); +Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { + return EmitLoadBufferB32xN<1, BufferAlias::U32>(ctx, inst, handle, address); } -Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferB32xN<2, BufferAlias::U32>(ctx, handle, address); +Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { + return EmitLoadBufferB32xN<2, BufferAlias::U32>(ctx, inst, handle, address); } -Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferB32xN<3, BufferAlias::U32>(ctx, handle, address); +Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { + return EmitLoadBufferB32xN<3, BufferAlias::U32>(ctx, inst, handle, address); } -Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferB32xN<4, BufferAlias::U32>(ctx, handle, address); +Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { + return EmitLoadBufferB32xN<4, BufferAlias::U32>(ctx, inst, handle, address); } Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferB32xN<1, BufferAlias::F32>(ctx, handle, address); + return EmitLoadBufferB32xN<1, BufferAlias::F32>(ctx, inst, handle, address); } Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferB32xN<2, BufferAlias::F32>(ctx, handle, address); + return EmitLoadBufferB32xN<2, BufferAlias::F32>(ctx, inst, handle, address); } Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferB32xN<3, BufferAlias::F32>(ctx, handle, address); + return EmitLoadBufferB32xN<3, BufferAlias::F32>(ctx, inst, handle, address); } Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferB32xN<4, BufferAlias::F32>(ctx, handle, address); + return EmitLoadBufferB32xN<4, BufferAlias::F32>(ctx, inst, handle, address); } Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { UNREACHABLE_MSG("SPIR-V instruction"); } +template +void EmitStoreBufferBoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto emit_func) { + if (Sirit::ValidId(buffer_size)) { + // Bounds checking enabled, wrap in a conditional branch. + auto compare_index = index; + if (N > 1) { + index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(N - 1)); + } + const Id in_bounds = ctx.OpULessThan(ctx.U1[1], compare_index, buffer_size); + const Id in_bounds_label = ctx.OpLabel(); + const Id merge_label = ctx.OpLabel(); + ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); + ctx.OpBranchConditional(in_bounds, in_bounds_label, merge_label); + ctx.AddLabel(in_bounds_label); + emit_func(); + ctx.OpBranch(merge_label); + ctx.AddLabel(merge_label); + return; + } + // Bounds checking not enabled, just perform the store. + emit_func(); +} + template -static void EmitStoreBufferB32xN(EmitContext& ctx, u32 handle, Id address, Id value) { +static void EmitStoreBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, + Id value) { + const auto flags = inst->Flags(); const auto& spv_buffer = ctx.buffers[handle]; if (Sirit::ValidId(spv_buffer.offset)) { address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset); @@ -491,15 +557,27 @@ static void EmitStoreBufferB32xN(EmitContext& ctx, u32 handle, Id address, Id va const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); const auto& data_types = alias == BufferAlias::U32 ? ctx.U32 : ctx.F32; const auto [id, pointer_type] = spv_buffer[alias]; - if constexpr (N == 1) { - const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; - ctx.OpStore(ptr, value); - } else { + + auto store = [&] { for (u32 i = 0; i < N; i++) { - const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); - const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i); - ctx.OpStore(ptr, ctx.OpCompositeExtract(data_types[1], value, i)); + const Id index_i = i == 0 ? index : ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); + const Id ptr_i = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i); + const Id value_i = N == 1 ? value : ctx.OpCompositeExtract(data_types[1], value, i); + auto store_i = [&]() { ctx.OpStore(ptr_i, value_i); }; + if (!flags.typed) { + // Untyped stores have bounds checking per-component. + EmitStoreBufferBoundsCheck<1>(ctx, index_i, spv_buffer.size_dwords, store_i); + } else { + store_i(); + } } + }; + + if (flags.typed) { + // Typed stores have single bounds check for the whole store. + EmitStoreBufferBoundsCheck(ctx, index, spv_buffer.size_dwords, store); + } else { + store(); } } @@ -510,7 +588,8 @@ void EmitStoreBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id v } const auto [id, pointer_type] = spv_buffer[BufferAlias::U8]; const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)}; - ctx.OpStore(ptr, ctx.OpUConvert(ctx.U8, value)); + const Id result{ctx.OpUConvert(ctx.U8, value)}; + EmitStoreBufferBoundsCheck<1>(ctx, address, spv_buffer.size, [&] { ctx.OpStore(ptr, result); }); } void EmitStoreBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { @@ -521,39 +600,41 @@ void EmitStoreBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id const auto [id, pointer_type] = spv_buffer[BufferAlias::U16]; const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(1u)); const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)}; - ctx.OpStore(ptr, ctx.OpUConvert(ctx.U16, value)); + const Id result{ctx.OpUConvert(ctx.U16, value)}; + EmitStoreBufferBoundsCheck<1>(ctx, index, spv_buffer.size_shorts, + [&] { ctx.OpStore(ptr, result); }); } -void EmitStoreBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<1, BufferAlias::U32>(ctx, handle, address, value); +void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferB32xN<1, BufferAlias::U32>(ctx, inst, handle, address, value); } -void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<2, BufferAlias::U32>(ctx, handle, address, value); +void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferB32xN<2, BufferAlias::U32>(ctx, inst, handle, address, value); } -void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<3, BufferAlias::U32>(ctx, handle, address, value); +void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferB32xN<3, BufferAlias::U32>(ctx, inst, handle, address, value); } -void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<4, BufferAlias::U32>(ctx, handle, address, value); +void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferB32xN<4, BufferAlias::U32>(ctx, inst, handle, address, value); } void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<1, BufferAlias::F32>(ctx, handle, address, value); + EmitStoreBufferB32xN<1, BufferAlias::F32>(ctx, inst, handle, address, value); } void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<2, BufferAlias::F32>(ctx, handle, address, value); + EmitStoreBufferB32xN<2, BufferAlias::F32>(ctx, inst, handle, address, value); } void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<3, BufferAlias::F32>(ctx, handle, address, value); + EmitStoreBufferB32xN<3, BufferAlias::F32>(ctx, inst, handle, address, value); } void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferB32xN<4, BufferAlias::F32>(ctx, handle, address, value); + EmitStoreBufferB32xN<4, BufferAlias::F32>(ctx, inst, handle, address, value); } void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index 724550cd6..fe7bd3356 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -14,7 +14,7 @@ void EmitPrologue(EmitContext& ctx) { if (ctx.info.loads.Get(IR::Attribute::WorkgroupIndex)) { ctx.DefineWorkgroupIndex(); } - ctx.DefineBufferOffsets(); + ctx.DefineBufferProperties(); } void ConvertDepthMode(EmitContext& ctx) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index da20dc691..7c25d1477 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -192,8 +192,27 @@ EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat f UNREACHABLE_MSG("Invalid attribute type {}", fmt); } -void EmitContext::DefineBufferOffsets() { - for (BufferDefinition& buffer : buffers) { +Id EmitContext::GetBufferSize(const u32 sharp_idx) { + const auto& srt_flatbuf = buffers.back(); + ASSERT(srt_flatbuf.buffer_type == BufferType::ReadConstUbo); + const auto [id, pointer_type] = srt_flatbuf[BufferAlias::U32]; + + const auto rsrc1{ + OpLoad(U32[1], OpAccessChain(pointer_type, id, u32_zero_value, ConstU32(sharp_idx + 1)))}; + const auto rsrc2{ + OpLoad(U32[1], OpAccessChain(pointer_type, id, u32_zero_value, ConstU32(sharp_idx + 2)))}; + + const auto stride{OpBitFieldUExtract(U32[1], rsrc1, ConstU32(16u), ConstU32(14u))}; + const auto num_records{rsrc2}; + + const auto stride_zero{OpIEqual(U1[1], stride, u32_zero_value)}; + const auto stride_size{OpIMul(U32[1], num_records, stride)}; + return OpSelect(U32[1], stride_zero, num_records, stride_size); +} + +void EmitContext::DefineBufferProperties() { + for (u32 i = 0; i < buffers.size(); i++) { + BufferDefinition& buffer = buffers[i]; if (buffer.buffer_type != BufferType::Guest) { continue; } @@ -208,6 +227,22 @@ void EmitContext::DefineBufferOffsets() { Name(buffer.offset, fmt::format("buf{}_off", binding)); buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U)); Name(buffer.offset_dwords, fmt::format("buf{}_dword_off", binding)); + + // Only need to load size if performing bounds checks and the buffer is both guest and not + // inline. + if (!profile.supports_robust_buffer_access && buffer.buffer_type == BufferType::Guest) { + const BufferResource& desc = info.buffers[i]; + if (desc.sharp_idx == std::numeric_limits::max()) { + buffer.size = ConstU32(desc.inline_cbuf.GetSize()); + } else { + buffer.size = GetBufferSize(desc.sharp_idx); + } + Name(buffer.size, fmt::format("buf{}_size", binding)); + buffer.size_shorts = OpShiftRightLogical(U32[1], buffer.size, ConstU32(1U)); + Name(buffer.size_shorts, fmt::format("buf{}_short_size", binding)); + buffer.size_dwords = OpShiftRightLogical(U32[1], buffer.size, ConstU32(2U)); + Name(buffer.size_dwords, fmt::format("buf{}_dword_size", binding)); + } } } @@ -589,34 +624,34 @@ void EmitContext::DefineOutputs() { void EmitContext::DefinePushDataBlock() { // Create push constants block for instance steps rates - const Id struct_type{Name(TypeStruct(U32[1], U32[1], U32[4], U32[4], U32[4], U32[4], U32[4], - U32[4], F32[1], F32[1], F32[1], F32[1]), + const Id struct_type{Name(TypeStruct(U32[1], U32[1], F32[1], F32[1], F32[1], F32[1], U32[4], + U32[4], U32[4], U32[4], U32[4], U32[4]), "AuxData")}; Decorate(struct_type, spv::Decoration::Block); - MemberName(struct_type, 0, "sr0"); - MemberName(struct_type, 1, "sr1"); - MemberName(struct_type, Shader::PushData::BufOffsetIndex + 0, "buf_offsets0"); - MemberName(struct_type, Shader::PushData::BufOffsetIndex + 1, "buf_offsets1"); - MemberName(struct_type, Shader::PushData::UdRegsIndex + 0, "ud_regs0"); - MemberName(struct_type, Shader::PushData::UdRegsIndex + 1, "ud_regs1"); - MemberName(struct_type, Shader::PushData::UdRegsIndex + 2, "ud_regs2"); - MemberName(struct_type, Shader::PushData::UdRegsIndex + 3, "ud_regs3"); - MemberName(struct_type, Shader::PushData::XOffsetIndex, "xoffset"); - MemberName(struct_type, Shader::PushData::YOffsetIndex, "yoffset"); - MemberName(struct_type, Shader::PushData::XScaleIndex, "xscale"); - MemberName(struct_type, Shader::PushData::YScaleIndex, "yscale"); - MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); - MemberDecorate(struct_type, 1, spv::Decoration::Offset, 4U); - MemberDecorate(struct_type, Shader::PushData::BufOffsetIndex + 0, spv::Decoration::Offset, 8U); - MemberDecorate(struct_type, Shader::PushData::BufOffsetIndex + 1, spv::Decoration::Offset, 24U); - MemberDecorate(struct_type, Shader::PushData::UdRegsIndex + 0, spv::Decoration::Offset, 40U); - MemberDecorate(struct_type, Shader::PushData::UdRegsIndex + 1, spv::Decoration::Offset, 56U); - MemberDecorate(struct_type, Shader::PushData::UdRegsIndex + 2, spv::Decoration::Offset, 72U); - MemberDecorate(struct_type, Shader::PushData::UdRegsIndex + 3, spv::Decoration::Offset, 88U); - MemberDecorate(struct_type, Shader::PushData::XOffsetIndex, spv::Decoration::Offset, 104U); - MemberDecorate(struct_type, Shader::PushData::YOffsetIndex, spv::Decoration::Offset, 108U); - MemberDecorate(struct_type, Shader::PushData::XScaleIndex, spv::Decoration::Offset, 112U); - MemberDecorate(struct_type, Shader::PushData::YScaleIndex, spv::Decoration::Offset, 116U); + MemberName(struct_type, PushData::Step0Index, "sr0"); + MemberName(struct_type, PushData::Step1Index, "sr1"); + MemberName(struct_type, PushData::XOffsetIndex, "xoffset"); + MemberName(struct_type, PushData::YOffsetIndex, "yoffset"); + MemberName(struct_type, PushData::XScaleIndex, "xscale"); + MemberName(struct_type, PushData::YScaleIndex, "yscale"); + MemberName(struct_type, PushData::UdRegsIndex + 0, "ud_regs0"); + MemberName(struct_type, PushData::UdRegsIndex + 1, "ud_regs1"); + MemberName(struct_type, PushData::UdRegsIndex + 2, "ud_regs2"); + MemberName(struct_type, PushData::UdRegsIndex + 3, "ud_regs3"); + MemberName(struct_type, PushData::BufOffsetIndex + 0, "buf_offsets0"); + MemberName(struct_type, PushData::BufOffsetIndex + 1, "buf_offsets1"); + MemberDecorate(struct_type, PushData::Step0Index, spv::Decoration::Offset, 0U); + MemberDecorate(struct_type, PushData::Step1Index, spv::Decoration::Offset, 4U); + MemberDecorate(struct_type, PushData::XOffsetIndex, spv::Decoration::Offset, 8U); + MemberDecorate(struct_type, PushData::YOffsetIndex, spv::Decoration::Offset, 12U); + MemberDecorate(struct_type, PushData::XScaleIndex, spv::Decoration::Offset, 16U); + MemberDecorate(struct_type, PushData::YScaleIndex, spv::Decoration::Offset, 20U); + MemberDecorate(struct_type, PushData::UdRegsIndex + 0, spv::Decoration::Offset, 24U); + MemberDecorate(struct_type, PushData::UdRegsIndex + 1, spv::Decoration::Offset, 40U); + MemberDecorate(struct_type, PushData::UdRegsIndex + 2, spv::Decoration::Offset, 56U); + MemberDecorate(struct_type, PushData::UdRegsIndex + 3, spv::Decoration::Offset, 72U); + MemberDecorate(struct_type, PushData::BufOffsetIndex + 0, spv::Decoration::Offset, 88U); + MemberDecorate(struct_type, PushData::BufOffsetIndex + 1, spv::Decoration::Offset, 104U); push_data_block = DefineVar(struct_type, spv::StorageClass::PushConstant); Name(push_data_block, "push_data"); interfaces.push_back(push_data_block); @@ -661,12 +696,22 @@ EmitContext::BufferSpv EmitContext::DefineBuffer(bool is_storage, bool is_writte break; default: Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "ubo", binding.buffer)); + break; } interfaces.push_back(id); return {id, pointer_type}; }; void EmitContext::DefineBuffers() { + if (!profile.supports_robust_buffer_access && !info.has_readconst) { + // In case ReadConstUbo has not already been bound by IR and is needed + // to query buffer sizes, bind it now. + info.buffers.push_back({ + .used_types = IR::Type::U32, + .inline_cbuf = AmdGpu::Buffer::Null(), + .buffer_type = BufferType::ReadConstUbo, + }); + } for (const auto& desc : info.buffers) { const auto buf_sharp = desc.GetSharp(info); const bool is_storage = desc.IsStorage(buf_sharp, profile); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 0fe6e336c..784748658 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -43,7 +43,7 @@ public: Id Def(const IR::Value& value); - void DefineBufferOffsets(); + void DefineBufferProperties(); void DefineInterpolatedAttribs(); void DefineWorkgroupIndex(); @@ -248,6 +248,9 @@ public: BufferType buffer_type; Id offset; Id offset_dwords; + Id size; + Id size_shorts; + Id size_dwords; std::array aliases; const BufferSpv& operator[](BufferAlias alias) const { @@ -307,6 +310,8 @@ private: Id DefineFloat32ToUfloatM5(u32 mantissa_bits, std::string_view name); Id DefineUfloatM5ToFloat32(u32 mantissa_bits, std::string_view name); + + Id GetBufferSize(u32 sharp_idx); }; } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/frontend/fetch_shader.cpp b/src/shader_recompiler/frontend/fetch_shader.cpp index 8ae664d79..55508b0f2 100644 --- a/src/shader_recompiler/frontend/fetch_shader.cpp +++ b/src/shader_recompiler/frontend/fetch_shader.cpp @@ -9,6 +9,12 @@ namespace Shader::Gcn { +const u32* GetFetchShaderCode(const Info& info, u32 sgpr_base) { + const u32* code; + std::memcpy(&code, &info.user_data[sgpr_base], sizeof(code)); + return code; +} + /** * s_load_dwordx4 s[8:11], s[2:3], 0x00 * s_load_dwordx4 s[12:15], s[2:3], 0x04 @@ -38,9 +44,8 @@ std::optional ParseFetchShader(const Shader::Info& info) { if (!info.has_fetch_shader) { return std::nullopt; } - const u32* code; - std::memcpy(&code, &info.user_data[info.fetch_shader_sgpr_base], sizeof(code)); + const auto* code = GetFetchShaderCode(info, info.fetch_shader_sgpr_base); FetchShaderData data{.code = code}; GcnCodeSlice code_slice(code, code + std::numeric_limits::max()); GcnDecodeContext decoder; diff --git a/src/shader_recompiler/frontend/fetch_shader.h b/src/shader_recompiler/frontend/fetch_shader.h index 080b0eb22..837caafa0 100644 --- a/src/shader_recompiler/frontend/fetch_shader.h +++ b/src/shader_recompiler/frontend/fetch_shader.h @@ -64,6 +64,8 @@ struct FetchShaderData { } }; +const u32* GetFetchShaderCode(const Info& info, u32 sgpr_base); + std::optional ParseFetchShader(const Shader::Info& info); } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 7f1bcb33e..230f3917f 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -4,6 +4,7 @@ #include "common/config.h" #include "common/io_file.h" #include "common/path_util.h" +#include "shader_recompiler/frontend/decode.h" #include "shader_recompiler/frontend/fetch_shader.h" #include "shader_recompiler/frontend/translate/translate.h" #include "shader_recompiler/info.h" @@ -470,8 +471,29 @@ void Translator::SetDst64(const InstOperand& operand, const IR::U64F64& value_ra void Translator::EmitFetch(const GcnInst& inst) { // Read the pointer to the fetch shader assembly. + const auto code_sgpr_base = inst.src[0].code; + if (!profile.supports_robust_buffer_access) { + // The fetch shader must be inlined to access as regular buffers, so that + // bounds checks can be emitted to emulate robust buffer access. + const auto* code = GetFetchShaderCode(info, code_sgpr_base); + GcnCodeSlice slice(code, code + std::numeric_limits::max()); + GcnDecodeContext decoder; + + // Decode and save instructions + u32 sub_pc = 0; + while (!slice.atEnd()) { + const auto sub_inst = decoder.decodeInstruction(slice); + if (sub_inst.opcode == Opcode::S_SETPC_B64) { + // Assume we're swapping back to the main shader. + break; + } + TranslateInstruction(sub_inst, sub_pc++); + } + return; + } + info.has_fetch_shader = true; - info.fetch_shader_sgpr_base = inst.src[0].code; + info.fetch_shader_sgpr_base = code_sgpr_base; const auto fetch_data = ParseFetchShader(info); ASSERT(fetch_data.has_value()); @@ -520,6 +542,40 @@ void Translator::LogMissingOpcode(const GcnInst& inst) { info.translation_failed = true; } +void Translator::TranslateInstruction(const GcnInst& inst, const u32 pc) { + // Emit instructions for each category. + switch (inst.category) { + case InstCategory::DataShare: + EmitDataShare(inst); + break; + case InstCategory::VectorInterpolation: + EmitVectorInterpolation(inst); + break; + case InstCategory::ScalarMemory: + EmitScalarMemory(inst); + break; + case InstCategory::VectorMemory: + EmitVectorMemory(inst); + break; + case InstCategory::Export: + EmitExport(inst); + break; + case InstCategory::FlowControl: + EmitFlowControl(pc, inst); + break; + case InstCategory::ScalarALU: + EmitScalarAlu(inst); + break; + case InstCategory::VectorALU: + EmitVectorAlu(inst); + break; + case InstCategory::DebugProfile: + break; + default: + UNREACHABLE(); + } +} + void Translate(IR::Block* block, u32 pc, std::span inst_list, Info& info, const RuntimeInfo& runtime_info, const Profile& profile) { if (inst_list.empty()) { @@ -537,37 +593,7 @@ void Translate(IR::Block* block, u32 pc, std::span inst_list, Inf continue; } - // Emit instructions for each category. - switch (inst.category) { - case InstCategory::DataShare: - translator.EmitDataShare(inst); - break; - case InstCategory::VectorInterpolation: - translator.EmitVectorInterpolation(inst); - break; - case InstCategory::ScalarMemory: - translator.EmitScalarMemory(inst); - break; - case InstCategory::VectorMemory: - translator.EmitVectorMemory(inst); - break; - case InstCategory::Export: - translator.EmitExport(inst); - break; - case InstCategory::FlowControl: - translator.EmitFlowControl(pc, inst); - break; - case InstCategory::ScalarALU: - translator.EmitScalarAlu(inst); - break; - case InstCategory::VectorALU: - translator.EmitVectorAlu(inst); - break; - case InstCategory::DebugProfile: - break; - default: - UNREACHABLE(); - } + translator.TranslateInstruction(inst, pc); } } diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 563881a8e..b4919213b 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -58,6 +58,8 @@ public: explicit Translator(IR::Block* block_, Info& info, const RuntimeInfo& runtime_info, const Profile& profile); + void TranslateInstruction(const GcnInst& inst, u32 pc); + // Instruction categories void EmitPrologue(); void EmitFetch(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 0b911eb57..bfbe937a1 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -195,6 +195,7 @@ void Translator::BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst) buffer_info.inst_offset.Assign(mubuf.offset); buffer_info.globally_coherent.Assign(mubuf.glc); buffer_info.system_coherent.Assign(mubuf.slc); + buffer_info.typed.Assign(is_typed); if (is_typed) { const auto& mtbuf = inst.control.mtbuf; const auto dmft = static_cast(mtbuf.dfmt); @@ -241,6 +242,7 @@ void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst) { buffer_info.inst_offset.Assign(mubuf.offset); buffer_info.globally_coherent.Assign(mubuf.glc); buffer_info.system_coherent.Assign(mubuf.slc); + buffer_info.typed.Assign(true); const IR::Value handle = ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), @@ -283,6 +285,7 @@ void Translator::BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst buffer_info.inst_offset.Assign(mubuf.offset); buffer_info.globally_coherent.Assign(mubuf.glc); buffer_info.system_coherent.Assign(mubuf.slc); + buffer_info.typed.Assign(is_typed); if (is_typed) { const auto& mtbuf = inst.control.mtbuf; const auto dmft = static_cast(mtbuf.dfmt); @@ -339,6 +342,7 @@ void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst) { buffer_info.inst_offset.Assign(mubuf.offset); buffer_info.globally_coherent.Assign(mubuf.glc); buffer_info.system_coherent.Assign(mubuf.slc); + buffer_info.typed.Assign(true); const IR::VectorReg src_reg{inst.src[1].code}; diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h index 13f310cf8..8dcf9c5c4 100644 --- a/src/shader_recompiler/info.h +++ b/src/shader_recompiler/info.h @@ -23,6 +23,10 @@ namespace Shader { static constexpr size_t NumUserDataRegs = 16; +static constexpr size_t NumImages = 64; +static constexpr size_t NumBuffers = 32; +static constexpr size_t NumSamplers = 16; +static constexpr size_t NumFMasks = 8; enum class TextureType : u32 { Color1D, @@ -63,7 +67,7 @@ struct BufferResource { [[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; }; -using BufferResourceList = boost::container::small_vector; +using BufferResourceList = boost::container::small_vector; struct ImageResource { u32 sharp_idx; @@ -74,7 +78,7 @@ struct ImageResource { [[nodiscard]] constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; }; -using ImageResourceList = boost::container::small_vector; +using ImageResourceList = boost::container::small_vector; struct SamplerResource { u32 sharp_idx; @@ -84,31 +88,33 @@ struct SamplerResource { constexpr AmdGpu::Sampler GetSharp(const Info& info) const noexcept; }; -using SamplerResourceList = boost::container::small_vector; +using SamplerResourceList = boost::container::small_vector; struct FMaskResource { u32 sharp_idx; constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; }; -using FMaskResourceList = boost::container::small_vector; +using FMaskResourceList = boost::container::small_vector; struct PushData { - static constexpr u32 BufOffsetIndex = 2; - static constexpr u32 UdRegsIndex = 4; - static constexpr u32 XOffsetIndex = 8; - static constexpr u32 YOffsetIndex = 9; - static constexpr u32 XScaleIndex = 10; - static constexpr u32 YScaleIndex = 11; + static constexpr u32 Step0Index = 0; + static constexpr u32 Step1Index = 1; + static constexpr u32 XOffsetIndex = 2; + static constexpr u32 YOffsetIndex = 3; + static constexpr u32 XScaleIndex = 4; + static constexpr u32 YScaleIndex = 5; + static constexpr u32 UdRegsIndex = 6; + static constexpr u32 BufOffsetIndex = UdRegsIndex + NumUserDataRegs / 4; u32 step0; u32 step1; - std::array buf_offsets; - std::array ud_regs; float xoffset; float yoffset; float xscale; float yscale; + std::array ud_regs; + std::array buf_offsets; void AddOffset(u32 binding, u32 offset) { ASSERT(offset < 256 && binding < buf_offsets.size()); diff --git a/src/shader_recompiler/ir/reg.h b/src/shader_recompiler/ir/reg.h index 19e0da3dd..3ee7c4355 100644 --- a/src/shader_recompiler/ir/reg.h +++ b/src/shader_recompiler/ir/reg.h @@ -51,6 +51,7 @@ union BufferInstInfo { BitField<2, 12, u32> inst_offset; BitField<14, 1, u32> system_coherent; BitField<15, 1, u32> globally_coherent; + BitField<16, 1, u32> typed; }; enum class ScalarReg : u32 { diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 53d940b79..43d2b87d4 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -25,6 +25,7 @@ struct Profile { bool support_legacy_vertex_attributes{}; bool supports_image_load_store_lod{}; bool supports_native_cube_calc{}; + bool supports_robust_buffer_access{}; bool has_broken_spirv_clamp{}; bool lower_left_origin_mode{}; bool needs_manual_interpolation{}; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index ccb45c095..7eb4ea9e1 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -608,7 +608,11 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, return false; } Image& image = texture_cache.GetImage(image_id); - if (False(image.flags & ImageFlagBits::GpuModified)) { + // Only perform sync if image is: + // - GPU modified; otherwise there are no changes to synchronize. + // - Not CPU modified; otherwise we could overwrite CPU changes with stale GPU changes. + if (False(image.flags & ImageFlagBits::GpuModified) || + True(image.flags & ImageFlagBits::CpuDirty)) { return false; } ASSERT_MSG(device_addr == image.info.guest_address, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index a17f8c9c2..f01401569 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -210,9 +210,6 @@ bool Instance::CreateDevice() { vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, vk::PhysicalDevicePortabilitySubsetFeaturesKHR>(); features = feature_chain.get().features; -#ifdef __APPLE__ - portability_features = feature_chain.get(); -#endif const vk::StructureChain properties_chain = physical_device.getProperties2< vk::PhysicalDeviceProperties2, vk::PhysicalDeviceVulkan11Properties, @@ -258,16 +255,19 @@ bool Instance::CreateDevice() { add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); - dynamic_color_write_mask = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); - if (dynamic_color_write_mask) { - dynamic_color_write_mask = - feature_chain.get() - .extendedDynamicState3ColorWriteMask; + dynamic_state_3 = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); + if (dynamic_state_3) { + dynamic_state_3_features = + feature_chain.get(); + LOG_INFO(Render_Vulkan, "- extendedDynamicState3ColorWriteMask: {}", + dynamic_state_3_features.extendedDynamicState3ColorWriteMask); } - null_descriptor = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); - if (null_descriptor) { - null_descriptor = - feature_chain.get().nullDescriptor; + robustness2 = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); + if (robustness2) { + robustness2_features = feature_chain.get(); + LOG_INFO(Render_Vulkan, "- robustBufferAccess2: {}", + robustness2_features.robustBufferAccess2); + LOG_INFO(Render_Vulkan, "- nullDescriptor: {}", robustness2_features.nullDescriptor); } custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); @@ -284,6 +284,9 @@ bool Instance::CreateDevice() { #ifdef __APPLE__ // Required by Vulkan spec if supported. portability_subset = add_extension(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + if (portability_subset) { + portability_features = feature_chain.get(); + } #endif const auto family_properties = physical_device.getQueueFamilyProperties(); @@ -387,13 +390,15 @@ bool Instance::CreateDevice() { .customBorderColorWithoutFormat = true, }, vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{ - .extendedDynamicState3ColorWriteMask = true, + .extendedDynamicState3ColorWriteMask = + dynamic_state_3_features.extendedDynamicState3ColorWriteMask, }, vk::PhysicalDeviceDepthClipControlFeaturesEXT{ .depthClipControl = true, }, vk::PhysicalDeviceRobustness2FeaturesEXT{ - .nullDescriptor = true, + .robustBufferAccess2 = robustness2_features.robustBufferAccess2, + .nullDescriptor = robustness2_features.nullDescriptor, }, vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{ .vertexInputDynamicState = true, @@ -420,13 +425,13 @@ bool Instance::CreateDevice() { if (!custom_border_color) { device_chain.unlink(); } - if (!dynamic_color_write_mask) { + if (!dynamic_state_3) { device_chain.unlink(); } if (!depth_clip_control) { device_chain.unlink(); } - if (!null_descriptor) { + if (!robustness2) { device_chain.unlink(); } if (!vertex_input_dynamic_state) { diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 682824044..bdd92cba9 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -99,9 +99,10 @@ public: return depth_clip_control; } - /// Returns true when dynamic color write mask state is supported + /// Returns true when the extendedDynamicState3ColorWriteMask feature of + /// VK_EXT_extended_dynamic_state3 is supported. bool IsDynamicColorWriteMaskSupported() const { - return dynamic_color_write_mask; + return dynamic_state_3 && dynamic_state_3_features.extendedDynamicState3ColorWriteMask; } /// Returns true when VK_EXT_vertex_input_dynamic_state is supported. @@ -109,9 +110,14 @@ public: return vertex_input_dynamic_state; } + /// Returns true when the robustBufferAccess2 feature of VK_EXT_robustness2 is supported. + bool IsRobustBufferAccess2Supported() const { + return robustness2 && robustness2_features.robustBufferAccess2; + } + /// Returns true when the nullDescriptor feature of VK_EXT_robustness2 is supported. bool IsNullDescriptorSupported() const { - return null_descriptor; + return robustness2 && robustness2_features.nullDescriptor; } /// Returns true when VK_KHR_fragment_shader_barycentric is supported. @@ -303,6 +309,8 @@ private: vk::PhysicalDevicePushDescriptorPropertiesKHR push_descriptor_props; vk::PhysicalDeviceFeatures features; vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features; + vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT dynamic_state_3_features; + vk::PhysicalDeviceRobustness2FeaturesEXT robustness2_features; vk::DriverIdKHR driver_id; vk::UniqueDebugUtilsMessengerEXT debug_callback{}; std::string vendor_name; @@ -317,9 +325,9 @@ private: bool custom_border_color{}; bool fragment_shader_barycentric{}; bool depth_clip_control{}; - bool dynamic_color_write_mask{}; + bool dynamic_state_3{}; bool vertex_input_dynamic_state{}; - bool null_descriptor{}; + bool robustness2{}; bool list_restart{}; bool legacy_vertex_attributes{}; bool shader_stencil_export{}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 6ac7f7e43..3db22d585 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -200,6 +200,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, .support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(), .supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(), .supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(), + .supports_robust_buffer_access = instance_.IsRobustBufferAccess2Supported(), .needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() && instance.GetDriverID() == vk::DriverId::eNvidiaProprietary, .needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary || diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 816f149b0..4d58c0ea3 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -447,7 +447,6 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) { set_writes.clear(); buffer_barriers.clear(); buffer_infos.clear(); - buffer_views.clear(); image_infos.clear(); // Bind resource buffers and textures. diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 292944a10..3b45fd52e 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -110,18 +110,17 @@ private: std::pair, 8> cb_descs; std::optional> db_desc; - boost::container::static_vector image_infos; - boost::container::static_vector buffer_views; - boost::container::static_vector buffer_infos; - boost::container::static_vector bound_images; + boost::container::static_vector image_infos; + boost::container::static_vector buffer_infos; + boost::container::static_vector bound_images; Pipeline::DescriptorWrites set_writes; Pipeline::BufferBarriers buffer_barriers; using BufferBindingInfo = std::pair; - boost::container::static_vector buffer_bindings; + boost::container::static_vector buffer_bindings; using ImageBindingInfo = std::pair; - boost::container::static_vector image_bindings; + boost::container::static_vector image_bindings; }; } // namespace Vulkan From 154473d3b3841e26612da123a0d9092640d1af59 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Mon, 17 Feb 2025 11:59:10 -0300 Subject: [PATCH 17/29] Fixes translation BOT (#2465) * Update update_translation.yml * Update update_translation.yml * Update update_translation.yml --- .github/workflows/update_translation.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update_translation.yml b/.github/workflows/update_translation.yml index 06564d175..6eb9db87a 100644 --- a/.github/workflows/update_translation.yml +++ b/.github/workflows/update_translation.yml @@ -22,10 +22,9 @@ jobs: - name: Create Pull Request uses: peter-evans/create-pull-request@v7 with: + token: ${{ secrets.SHADPS4_TOKEN_REPO }} title: "Qt GUI: Update Translation" - commit-message: "[ci skip] Qt GUI: Update Translation." - committer: "shadPS4 Bot " - author: "shadPS4 Bot " + commit-message: "[ci skip] Qt GUI: Update Translation." body: "Daily update of translation sources." branch: update-translation - delete-branch: true \ No newline at end of file + delete-branch: true From e40451a3f72e2cfac6d3fadd9f5413ccf2bec25f Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 17 Feb 2025 17:01:22 +0200 Subject: [PATCH 18/29] [ci skip] Qt GUI: Update Translation. (#2466) Co-authored-by: georgemoralis <4313123+georgemoralis@users.noreply.github.com> --- src/qt_gui/translations/en_US.ts | 40 ++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/qt_gui/translations/en_US.ts b/src/qt_gui/translations/en_US.ts index e2b56c983..f1ed5df27 100644 --- a/src/qt_gui/translations/en_US.ts +++ b/src/qt_gui/translations/en_US.ts @@ -413,10 +413,6 @@ Configure Controls - - Control Settings - - D-Pad @@ -469,14 +465,6 @@ L2 / LT - - KBM Controls - - - - KBM Editor - - Back @@ -533,6 +521,30 @@ Right Stick + + Color Adjustment + + + + R: 000 + + + + G: 000 + + + + B: 255 + + + + Override Lightbar Color + + + + Override Color + + ElfViewer @@ -855,6 +867,10 @@ Save Data + + SFO Viewer for + + InstallDirSelect From 41496e035a75e629d5423cc1b5d6634cc7f3bfd4 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Mon, 17 Feb 2025 14:45:21 -0300 Subject: [PATCH 19/29] Adjust translation for RGB light (#2468) --- src/qt_gui/about_dialog.ui | 2 +- src/qt_gui/control_settings.cpp | 12 ++++++------ src/qt_gui/control_settings.ui | 6 +++--- src/qt_gui/translations/en_US.ts | 10 +++------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/qt_gui/about_dialog.ui b/src/qt_gui/about_dialog.ui index 19840e452..3842513a5 100644 --- a/src/qt_gui/about_dialog.ui +++ b/src/qt_gui/about_dialog.ui @@ -57,7 +57,7 @@ - shadPS4 + shadPS4 diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index 0b96eee26..820a490a0 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -60,21 +60,21 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, Q connect(ui->RSlider, &QSlider::valueChanged, this, [this](int value) { QString RedValue = QString("%1").arg(value, 3, 10, QChar('0')); - QString RValue = "R: " + RedValue; + QString RValue = tr("R:") + " " + RedValue; ui->RLabel->setText(RValue); UpdateLightbarColor(); }); connect(ui->GSlider, &QSlider::valueChanged, this, [this](int value) { QString GreenValue = QString("%1").arg(value, 3, 10, QChar('0')); - QString GValue = "G: " + GreenValue; + QString GValue = tr("G:") + " " + GreenValue; ui->GLabel->setText(GValue); UpdateLightbarColor(); }); connect(ui->BSlider, &QSlider::valueChanged, this, [this](int value) { QString BlueValue = QString("%1").arg(value, 3, 10, QChar('0')); - QString BValue = "B: " + BlueValue; + QString BValue = tr("B:") + " " + BlueValue; ui->BLabel->setText(BValue); UpdateLightbarColor(); }); @@ -483,7 +483,7 @@ void ControlSettings::SetUIValuestoMappings() { std::string Rstring = lightbarstring.substr(0, comma_pos2); ui->RSlider->setValue(std::stoi(Rstring)); QString RedValue = QString("%1").arg(std::stoi(Rstring), 3, 10, QChar('0')); - QString RValue = "R: " + RedValue; + QString RValue = tr("R:") + " " + RedValue; ui->RLabel->setText(RValue); } @@ -494,14 +494,14 @@ void ControlSettings::SetUIValuestoMappings() { ui->GSlider->setValue(std::stoi(Gstring)); QString GreenValue = QString("%1").arg(std::stoi(Gstring), 3, 10, QChar('0')); - QString GValue = "G: " + GreenValue; + QString GValue = tr("G:") + " " + GreenValue; ui->GLabel->setText(GValue); std::string Bstring = GBstring.substr(comma_pos3 + 1); ui->BSlider->setValue(std::stoi(Bstring)); QString BlueValue = QString("%1").arg(std::stoi(Bstring), 3, 10, QChar('0')); - QString BValue = "B: " + BlueValue; + QString BValue = tr("B:") + " " + BlueValue; ui->BLabel->setText(BValue); } } diff --git a/src/qt_gui/control_settings.ui b/src/qt_gui/control_settings.ui index e88e239e9..41fb005c6 100644 --- a/src/qt_gui/control_settings.ui +++ b/src/qt_gui/control_settings.ui @@ -912,7 +912,7 @@ - R: 000 + R: 000 @@ -944,7 +944,7 @@ - G: 000 + G: 000 @@ -976,7 +976,7 @@ - B: 255 + B: 255 diff --git a/src/qt_gui/translations/en_US.ts b/src/qt_gui/translations/en_US.ts index f1ed5df27..8d719977a 100644 --- a/src/qt_gui/translations/en_US.ts +++ b/src/qt_gui/translations/en_US.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,15 +522,15 @@ - R: 000 + R: - G: 000 + G: - B: 255 + B: From e67263cc0e6d33a40229d970a941f8b5598a9843 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 17 Feb 2025 19:45:33 +0200 Subject: [PATCH 20/29] New Crowdin updates (#2467) * New translations en_us.ts (Romanian) * New translations en_us.ts (French) * New translations en_us.ts (Spanish) * New translations en_us.ts (Arabic) * New translations en_us.ts (Danish) * New translations en_us.ts (German) * New translations en_us.ts (Greek) * New translations en_us.ts (Finnish) * New translations en_us.ts (Hungarian) * New translations en_us.ts (Italian) * New translations en_us.ts (Japanese) * New translations en_us.ts (Korean) * New translations en_us.ts (Lithuanian) * New translations en_us.ts (Dutch) * New translations en_us.ts (Polish) * New translations en_us.ts (Russian) * New translations en_us.ts (Albanian) * New translations en_us.ts (Swedish) * New translations en_us.ts (Turkish) * New translations en_us.ts (Ukrainian) * New translations en_us.ts (Chinese Simplified) * New translations en_us.ts (Chinese Traditional) * New translations en_us.ts (Vietnamese) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Indonesian) * New translations en_us.ts (Persian) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (French) * New translations en_us.ts (Turkish) --- src/qt_gui/translations/ar_SA.ts | 40 ++++++++++++++------- src/qt_gui/translations/da_DK.ts | 40 ++++++++++++++------- src/qt_gui/translations/de_DE.ts | 40 ++++++++++++++------- src/qt_gui/translations/el_GR.ts | 40 ++++++++++++++------- src/qt_gui/translations/es_ES.ts | 40 ++++++++++++++------- src/qt_gui/translations/fa_IR.ts | 40 ++++++++++++++------- src/qt_gui/translations/fi_FI.ts | 40 ++++++++++++++------- src/qt_gui/translations/fr_FR.ts | 44 +++++++++++++++-------- src/qt_gui/translations/hu_HU.ts | 40 ++++++++++++++------- src/qt_gui/translations/id_ID.ts | 40 ++++++++++++++------- src/qt_gui/translations/it_IT.ts | 40 ++++++++++++++------- src/qt_gui/translations/ja_JP.ts | 40 ++++++++++++++------- src/qt_gui/translations/ko_KR.ts | 40 ++++++++++++++------- src/qt_gui/translations/lt_LT.ts | 40 ++++++++++++++------- src/qt_gui/translations/nb_NO.ts | 40 ++++++++++++++------- src/qt_gui/translations/nl_NL.ts | 40 ++++++++++++++------- src/qt_gui/translations/pl_PL.ts | 40 ++++++++++++++------- src/qt_gui/translations/pt_BR.ts | 40 ++++++++++++++------- src/qt_gui/translations/pt_PT.ts | 40 ++++++++++++++------- src/qt_gui/translations/ro_RO.ts | 40 ++++++++++++++------- src/qt_gui/translations/ru_RU.ts | 40 ++++++++++++++------- src/qt_gui/translations/sq_AL.ts | 40 ++++++++++++++------- src/qt_gui/translations/sv_SE.ts | 40 ++++++++++++++------- src/qt_gui/translations/tr_TR.ts | 60 ++++++++++++++++++++------------ src/qt_gui/translations/uk_UA.ts | 40 ++++++++++++++------- src/qt_gui/translations/vi_VN.ts | 40 ++++++++++++++------- src/qt_gui/translations/zh_CN.ts | 40 ++++++++++++++------- src/qt_gui/translations/zh_TW.ts | 40 ++++++++++++++------- 28 files changed, 796 insertions(+), 348 deletions(-) diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index b489e4446..94fa24552 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index 3a66ee624..2c8a88614 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/de_DE.ts b/src/qt_gui/translations/de_DE.ts index 047a25b76..0dc996792 100644 --- a/src/qt_gui/translations/de_DE.ts +++ b/src/qt_gui/translations/de_DE.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/el_GR.ts b/src/qt_gui/translations/el_GR.ts index bb322ce08..139e06dc3 100644 --- a/src/qt_gui/translations/el_GR.ts +++ b/src/qt_gui/translations/el_GR.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index 4997f5645..3d3636d24 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -413,10 +413,6 @@ Configure Controls Configurar Controles - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - Editor KBM - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts index dcbf7e6dd..e5e11dd62 100644 --- a/src/qt_gui/translations/fa_IR.ts +++ b/src/qt_gui/translations/fa_IR.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/fi_FI.ts b/src/qt_gui/translations/fi_FI.ts index 5e9e33c85..1db90a940 100644 --- a/src/qt_gui/translations/fi_FI.ts +++ b/src/qt_gui/translations/fi_FI.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/fr_FR.ts b/src/qt_gui/translations/fr_FR.ts index d01ac2847..642382e9c 100644 --- a/src/qt_gui/translations/fr_FR.ts +++ b/src/qt_gui/translations/fr_FR.ts @@ -413,10 +413,6 @@ Configure Controls Configurer les Commandes - - Control Settings - Paramètres de Contrôle - D-Pad Croix directionnelle @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Commandes KBM - - - KBM Editor - Éditeur KBM - Back Retour @@ -533,6 +521,30 @@ Right Stick Joystick Droit + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Enregistrer les Données + + SFO Viewer for + Visionneuse SFO pour + InstallDirSelect @@ -1745,11 +1761,11 @@ Set the volume of the background music. - Set the volume of the background music. + Volume de la musique de fond. Enable Motion Controls - Enable Motion Controls + Activer les Mouvements Save Data Path diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index 20a6225ca..aa1a289aa 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/id_ID.ts b/src/qt_gui/translations/id_ID.ts index 6504c7808..1f359fca7 100644 --- a/src/qt_gui/translations/id_ID.ts +++ b/src/qt_gui/translations/id_ID.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/it_IT.ts b/src/qt_gui/translations/it_IT.ts index 1990f8cae..66776c7fe 100644 --- a/src/qt_gui/translations/it_IT.ts +++ b/src/qt_gui/translations/it_IT.ts @@ -413,10 +413,6 @@ Configure Controls Configura Comandi - - Control Settings - Impostazioni dei Comandi - D-Pad Croce direzionale @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Controlli Tastiera/Mouse - - - KBM Editor - Editor Tastiera/Mouse - Back Indietro @@ -533,6 +521,30 @@ Right Stick Levetta Destra + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Dati Salvataggio + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index 502070bb5..b4207e772 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -413,10 +413,6 @@ Configure Controls コントロール設定 - - Control Settings - 操作設定 - D-Pad 十字キー @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick 右スティック + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index b344e0b5d..80e99ba13 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index 711d0c7d2..c21fa5c64 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/nb_NO.ts b/src/qt_gui/translations/nb_NO.ts index efeb955fb..8bcf31ee3 100644 --- a/src/qt_gui/translations/nb_NO.ts +++ b/src/qt_gui/translations/nb_NO.ts @@ -413,10 +413,6 @@ Configure Controls Sett opp kontroller - - Control Settings - Kontrollinnstillinger - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Mus/tastatur oppsett - - - KBM Editor - Rediger mus/tastatur - Back Tilbake @@ -533,6 +521,30 @@ Right Stick Høyre analog + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Lagret data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/nl_NL.ts b/src/qt_gui/translations/nl_NL.ts index 6cd39b209..9cf7d955e 100644 --- a/src/qt_gui/translations/nl_NL.ts +++ b/src/qt_gui/translations/nl_NL.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index e17859784..abcefbb7c 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 6234a1d86..accc00561 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -413,10 +413,6 @@ Configure Controls Configurar Controles - - Control Settings - Configurações do Controle - D-Pad Direcional @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Controles T/M - - - KBM Editor - Editor T/M - Back Voltar @@ -533,6 +521,30 @@ Right Stick Analógico Direito + + Color Adjustment + Ajuste de Cores + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Substituir cor da Lightbar + + + Override Color + Substituir a Cor + ElfViewer @@ -855,6 +867,10 @@ Save Data Dados Salvos + + SFO Viewer for + Visualizador de SFO para + InstallDirSelect diff --git a/src/qt_gui/translations/pt_PT.ts b/src/qt_gui/translations/pt_PT.ts index 33fd53953..95d344ba7 100644 --- a/src/qt_gui/translations/pt_PT.ts +++ b/src/qt_gui/translations/pt_PT.ts @@ -413,10 +413,6 @@ Configure Controls Configurar Comandos - - Control Settings - Definições do Comando - D-Pad Botões de Direção @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Controlo KBM - - - KBM Editor - Editor KBM - Back Voltar @@ -533,6 +521,30 @@ Right Stick Manípulo Direito + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Dados Guardados + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index 8e0e4260d..a5f62cbfd 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 538b774fc..d999bf6fe 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -413,10 +413,6 @@ Configure Controls Настроить управление - - Control Settings - Настройки управления - D-Pad Крестовина @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Управление KBM - - - KBM Editor - Редактор KBM - Back Назад @@ -533,6 +521,30 @@ Right Stick Правый стик + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Сохранения + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/sq_AL.ts b/src/qt_gui/translations/sq_AL.ts index 2ecf36e8a..59fcfcf74 100644 --- a/src/qt_gui/translations/sq_AL.ts +++ b/src/qt_gui/translations/sq_AL.ts @@ -413,10 +413,6 @@ Configure Controls Konfiguro kontrollet - - Control Settings - Cilësimet e kontrollit - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - Kontrollet Tastierë/Mi - - - KBM Editor - Redaktues Tastierë/Mi - Back Mbrapa @@ -533,6 +521,30 @@ Right Stick Leva e djathtë + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Të dhënat e ruajtjes + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/sv_SE.ts b/src/qt_gui/translations/sv_SE.ts index 15267951e..46016207c 100644 --- a/src/qt_gui/translations/sv_SE.ts +++ b/src/qt_gui/translations/sv_SE.ts @@ -413,10 +413,6 @@ Configure Controls Konfigurera kontroller - - Control Settings - Kontrollerinställningar - D-Pad Riktningsknappar @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM-kontroller - - - KBM Editor - KBM-redigerare - Back Bakåt @@ -533,6 +521,30 @@ Right Stick Höger spak + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Sparat data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 34baf29bd..4d8d2b916 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -26,7 +26,7 @@ CheatsPatches Cheats / Patches for - Cheats / Patches for + Hileler / Yamalar: Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n @@ -413,10 +413,6 @@ Configure Controls Kontrolleri Yapılandır - - Control Settings - Kontrol Ayarları - D-Pad Yön Düğmeleri @@ -439,7 +435,7 @@ Left Stick Deadzone (def:2 max:127) - Left Stick Deadzone (def:2 max:127) + Sol Analog Ölü Bölgesi (şu an:2, en çok:127) Left Deadzone @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Geri @@ -523,7 +511,7 @@ Right Stick Deadzone (def:2, max:127) - Right Stick Deadzone (def:2, max:127) + Sağ Analog Ölü Bölgesi (şu an:2, en çok:127) Right Deadzone @@ -533,6 +521,30 @@ Right Stick Sağ Analog + + Color Adjustment + Renk Ayarları + + + R: 000 + K: 000 + + + G: 000 + Y: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Rengi Geçersiz Kıl + ElfViewer @@ -825,7 +837,7 @@ Delete %1 - Delete %1 + Sil: %1 Are you sure you want to delete %1's %2 directory? @@ -845,7 +857,7 @@ Failed to convert icon. - Failed to convert icon. + Simge dönüştürülemedi. This game has no save data to delete! @@ -855,6 +867,10 @@ Save Data Kayıt Verisi + + SFO Viewer for + SFO Görüntüleyici: + InstallDirSelect @@ -864,7 +880,7 @@ Select which directory you want to install to. - Select which directory you want to install to. + Hangi dizine yüklemek istediğinizi seçin. Install All Queued to Selected Folder @@ -1163,7 +1179,7 @@ PKG is a patch or DLC, please install the game first! - PKG is a patch or DLC, please install the game first! + PKG bir yama ya da indirilebilir içerik, lütfen önce oyunu yükleyin! Game is already running! @@ -1741,7 +1757,7 @@ Nightly - Nightly + Günlük Set the volume of the background music. @@ -1749,7 +1765,7 @@ Enable Motion Controls - Enable Motion Controls + Hareket Kontrollerini Etkinleştir Save Data Path @@ -1769,7 +1785,7 @@ Auto Select - Auto Select + Otomatik Seç Directory to install games diff --git a/src/qt_gui/translations/uk_UA.ts b/src/qt_gui/translations/uk_UA.ts index 8506d6e33..4a18079de 100644 --- a/src/qt_gui/translations/uk_UA.ts +++ b/src/qt_gui/translations/uk_UA.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Збереження + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 4334a3be2..50d6372cc 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -413,10 +413,6 @@ Configure Controls Cấu hình điều khiển - - Control Settings - Cài đặt điều khiển - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 21daafb5e..9a979394b 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -413,10 +413,6 @@ Configure Controls 配置按键 - - Control Settings - 按键配置 - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - 键鼠 - - - KBM Editor - 键鼠配置 - Back Back @@ -533,6 +521,30 @@ Right Stick 右摇杆 + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data 存档数据 + + SFO Viewer for + SFO Viewer for + InstallDirSelect diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 2654e8707..22edba21e 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -413,10 +413,6 @@ Configure Controls Configure Controls - - Control Settings - Control Settings - D-Pad D-Pad @@ -469,14 +465,6 @@ L2 / LT L2 / LT - - KBM Controls - KBM Controls - - - KBM Editor - KBM Editor - Back Back @@ -533,6 +521,30 @@ Right Stick Right Stick + + Color Adjustment + Color Adjustment + + + R: 000 + R: 000 + + + G: 000 + G: 000 + + + B: 255 + B: 255 + + + Override Lightbar Color + Override Lightbar Color + + + Override Color + Override Color + ElfViewer @@ -855,6 +867,10 @@ Save Data Save Data + + SFO Viewer for + SFO Viewer for + InstallDirSelect From 8447412c776e25cd0728903dd58681bd0abeeade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Tue, 18 Feb 2025 14:55:13 +0100 Subject: [PATCH 21/29] Bump to Clang 19 (#2434) --- .ci/clang-format.sh | 2 +- .github/workflows/build.yml | 4 ++-- src/common/polyfill_thread.h | 4 +++- src/common/thread.cpp | 2 +- src/core/signals.cpp | 4 ++-- src/qt_gui/kbm_config_dialog.h | 4 ++-- src/shader_recompiler/ir/breadth_first_search.h | 8 ++++---- src/shader_recompiler/ir/opcodes.h | 2 +- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.ci/clang-format.sh b/.ci/clang-format.sh index c0d8c2c2d..15868550f 100755 --- a/.ci/clang-format.sh +++ b/.ci/clang-format.sh @@ -10,7 +10,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis fi # Default clang-format points to default 3.5 version one -CLANG_FORMAT=clang-format-18 +CLANG_FORMAT=clang-format-19 $CLANG_FORMAT --version if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63074a0a8..658308b39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,9 +30,9 @@ jobs: - name: Install run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main' + sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main' sudo apt update - sudo apt install clang-format-18 + sudo apt install clang-format-19 - name: Build env: COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index 12e59a893..ca0481055 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -339,7 +339,9 @@ void CondvarWait(Condvar& cv, std::unique_lock& lk, std::stop_token token, } std::stop_callback callback(token, [&] { - { std::scoped_lock lk2{*lk.mutex()}; } + { + std::scoped_lock lk2{*lk.mutex()}; + } cv.notify_all(); }); diff --git a/src/common/thread.cpp b/src/common/thread.cpp index c87aea6ef..9ef1e86d8 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -41,7 +41,7 @@ void SetCurrentThreadRealtime(const std::chrono::nanoseconds period_ns) { const std::chrono::nanoseconds computation_ns = period_ns / 2; // Determine the timebase for converting time to ticks. - struct mach_timebase_info timebase {}; + struct mach_timebase_info timebase{}; mach_timebase_info(&timebase); const auto ticks_per_ns = static_cast(timebase.denom) / static_cast(timebase.numer); diff --git a/src/core/signals.cpp b/src/core/signals.cpp index 89844ae25..e47a78cd2 100644 --- a/src/core/signals.cpp +++ b/src/core/signals.cpp @@ -111,7 +111,7 @@ SignalDispatch::SignalDispatch() { ASSERT_MSG(handle = AddVectoredExceptionHandler(0, SignalHandler), "Failed to register exception handler."); #else - struct sigaction action {}; + struct sigaction action{}; action.sa_sigaction = SignalHandler; action.sa_flags = SA_SIGINFO | SA_ONSTACK; sigemptyset(&action.sa_mask); @@ -130,7 +130,7 @@ SignalDispatch::~SignalDispatch() { #if defined(_WIN32) ASSERT_MSG(RemoveVectoredExceptionHandler(handle), "Failed to remove exception handler."); #else - struct sigaction action {}; + struct sigaction action{}; action.sa_handler = SIG_DFL; action.sa_flags = 0; sigemptyset(&action.sa_mask); diff --git a/src/qt_gui/kbm_config_dialog.h b/src/qt_gui/kbm_config_dialog.h index f436b4a71..cc334b082 100644 --- a/src/qt_gui/kbm_config_dialog.h +++ b/src/qt_gui/kbm_config_dialog.h @@ -9,8 +9,8 @@ #include "string" class EditorDialog : public QDialog { - Q_OBJECT // Necessary for using Qt's meta-object system (signals/slots) - public : explicit EditorDialog(QWidget* parent = nullptr); // Constructor +Q_OBJECT // Necessary for using Qt's meta-object system (signals/slots) + public : explicit EditorDialog(QWidget* parent = nullptr); // Constructor protected: void closeEvent(QCloseEvent* event) override; // Override close event diff --git a/src/shader_recompiler/ir/breadth_first_search.h b/src/shader_recompiler/ir/breadth_first_search.h index 390dffb5c..9deeb2363 100644 --- a/src/shader_recompiler/ir/breadth_first_search.h +++ b/src/shader_recompiler/ir/breadth_first_search.h @@ -14,8 +14,8 @@ namespace Shader::IR { // Use typename Instruction so the function can be used to return either const or mutable // Insts depending on the context. template -auto BreadthFirstSearch(Instruction* inst, - Pred&& pred) -> std::invoke_result_t { +auto BreadthFirstSearch(Instruction* inst, Pred&& pred) + -> std::invoke_result_t { // Most often case the instruction is the desired already. if (std::optional result = pred(inst)) { return result; @@ -53,8 +53,8 @@ auto BreadthFirstSearch(Instruction* inst, } template -auto BreadthFirstSearch(const Value& value, - Pred&& pred) -> std::invoke_result_t { +auto BreadthFirstSearch(const Value& value, Pred&& pred) + -> std::invoke_result_t { if (value.IsImmediate()) { // Nothing to do with immediates return std::nullopt; diff --git a/src/shader_recompiler/ir/opcodes.h b/src/shader_recompiler/ir/opcodes.h index cd73ace7e..f3d16da4a 100644 --- a/src/shader_recompiler/ir/opcodes.h +++ b/src/shader_recompiler/ir/opcodes.h @@ -53,7 +53,7 @@ constexpr Type F64x3{Type::F64x3}; constexpr Type F64x4{Type::F64x4}; constexpr Type StringLiteral{Type::StringLiteral}; -constexpr OpcodeMeta META_TABLE[] { +constexpr OpcodeMeta META_TABLE[]{ #define OPCODE(name_token, type_token, ...) \ { \ .name{#name_token}, \ From 7d756e79ae2b437743cc6c4f4e407840c7bf0995 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 18 Feb 2025 15:55:41 +0200 Subject: [PATCH 22/29] New Crowdin updates (#2470) * New translations en_us.ts (Romanian) * New translations en_us.ts (French) * New translations en_us.ts (Spanish) * New translations en_us.ts (Arabic) * New translations en_us.ts (Danish) * New translations en_us.ts (German) * New translations en_us.ts (Greek) * New translations en_us.ts (Finnish) * New translations en_us.ts (Hungarian) * New translations en_us.ts (Italian) * New translations en_us.ts (Japanese) * New translations en_us.ts (Korean) * New translations en_us.ts (Lithuanian) * New translations en_us.ts (Dutch) * New translations en_us.ts (Polish) * New translations en_us.ts (Russian) * New translations en_us.ts (Albanian) * New translations en_us.ts (Swedish) * New translations en_us.ts (Turkish) * New translations en_us.ts (Ukrainian) * New translations en_us.ts (Chinese Simplified) * New translations en_us.ts (Chinese Traditional) * New translations en_us.ts (Vietnamese) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Indonesian) * New translations en_us.ts (Persian) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (Italian) * New translations en_us.ts (Russian) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Turkish) * New translations en_us.ts (Turkish) * New translations en_us.ts (Turkish) * New translations en_us.ts (Chinese Simplified) * New translations en_us.ts (Swedish) * New translations en_us.ts (Spanish) * New translations en_us.ts (Albanian) --- src/qt_gui/translations/ar_SA.ts | 16 +++++-------- src/qt_gui/translations/da_DK.ts | 16 +++++-------- src/qt_gui/translations/de_DE.ts | 16 +++++-------- src/qt_gui/translations/el_GR.ts | 16 +++++-------- src/qt_gui/translations/es_ES.ts | 24 ++++++++----------- src/qt_gui/translations/fa_IR.ts | 16 +++++-------- src/qt_gui/translations/fi_FI.ts | 16 +++++-------- src/qt_gui/translations/fr_FR.ts | 16 +++++-------- src/qt_gui/translations/hu_HU.ts | 16 +++++-------- src/qt_gui/translations/id_ID.ts | 16 +++++-------- src/qt_gui/translations/it_IT.ts | 24 ++++++++----------- src/qt_gui/translations/ja_JP.ts | 16 +++++-------- src/qt_gui/translations/ko_KR.ts | 16 +++++-------- src/qt_gui/translations/lt_LT.ts | 16 +++++-------- src/qt_gui/translations/nb_NO.ts | 16 +++++-------- src/qt_gui/translations/nl_NL.ts | 16 +++++-------- src/qt_gui/translations/pl_PL.ts | 16 +++++-------- src/qt_gui/translations/pt_BR.ts | 16 +++++-------- src/qt_gui/translations/pt_PT.ts | 16 +++++-------- src/qt_gui/translations/ro_RO.ts | 16 +++++-------- src/qt_gui/translations/ru_RU.ts | 24 ++++++++----------- src/qt_gui/translations/sq_AL.ts | 24 ++++++++----------- src/qt_gui/translations/sv_SE.ts | 24 ++++++++----------- src/qt_gui/translations/tr_TR.ts | 40 ++++++++++++++------------------ src/qt_gui/translations/uk_UA.ts | 16 +++++-------- src/qt_gui/translations/vi_VN.ts | 16 +++++-------- src/qt_gui/translations/zh_CN.ts | 24 ++++++++----------- src/qt_gui/translations/zh_TW.ts | 16 +++++-------- 28 files changed, 204 insertions(+), 316 deletions(-) diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index 94fa24552..2c4535cf6 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -9,10 +9,6 @@ About shadPS4 حول shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 هو محاكي تجريبي مفتوح المصدر لجهاز PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index 2c8a88614..b82b451bb 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/de_DE.ts b/src/qt_gui/translations/de_DE.ts index 0dc996792..b1251452c 100644 --- a/src/qt_gui/translations/de_DE.ts +++ b/src/qt_gui/translations/de_DE.ts @@ -9,10 +9,6 @@ About shadPS4 Über shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 ist ein experimenteller Open-Source-Emulator für die Playstation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/el_GR.ts b/src/qt_gui/translations/el_GR.ts index 139e06dc3..8ecc06e6c 100644 --- a/src/qt_gui/translations/el_GR.ts +++ b/src/qt_gui/translations/el_GR.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index 3d3636d24..e342bf51f 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -9,10 +9,6 @@ About shadPS4 Acerca de shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 es un emulador experimental de código abierto para la PlayStation 4. @@ -98,7 +94,7 @@ Error - Error + Error No patch selected. @@ -257,7 +253,7 @@ Error - Error + Error Network error: @@ -321,7 +317,7 @@ No - No + No Hide Changelog @@ -372,7 +368,7 @@ Error - Error + Error Unable to update compatibility data! Try again later. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts index e5e11dd62..1cdddcf46 100644 --- a/src/qt_gui/translations/fa_IR.ts +++ b/src/qt_gui/translations/fa_IR.ts @@ -9,10 +9,6 @@ About shadPS4 درباره ShadPS4 - - shadPS4 - ShadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. یک شبیه ساز متن باز برای پلی استیشن 4 است. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/fi_FI.ts b/src/qt_gui/translations/fi_FI.ts index 1db90a940..1b8ef4166 100644 --- a/src/qt_gui/translations/fi_FI.ts +++ b/src/qt_gui/translations/fi_FI.ts @@ -9,10 +9,6 @@ About shadPS4 Tietoa shadPS4:sta - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 on kokeellinen avoimen lähdekoodin PlayStation 4 emulaattori. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/fr_FR.ts b/src/qt_gui/translations/fr_FR.ts index 642382e9c..656ce750d 100644 --- a/src/qt_gui/translations/fr_FR.ts +++ b/src/qt_gui/translations/fr_FR.ts @@ -9,10 +9,6 @@ About shadPS4 À propos de shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 est un émulateur open-source expérimental de la PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index aa1a289aa..5be4a6658 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -9,10 +9,6 @@ About shadPS4 A shadPS4-ről - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. A shadPS4 egy kezdetleges, open-source PlayStation 4 emulátor. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/id_ID.ts b/src/qt_gui/translations/id_ID.ts index 1f359fca7..81ae6b0ff 100644 --- a/src/qt_gui/translations/id_ID.ts +++ b/src/qt_gui/translations/id_ID.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/it_IT.ts b/src/qt_gui/translations/it_IT.ts index 66776c7fe..32bb44d3f 100644 --- a/src/qt_gui/translations/it_IT.ts +++ b/src/qt_gui/translations/it_IT.ts @@ -9,10 +9,6 @@ About shadPS4 Riguardo shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 è un emulatore sperimentale open-source per PlayStation 4. @@ -523,27 +519,27 @@ Color Adjustment - Color Adjustment + Regolazione Colore - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + V: - B: 255 - B: 255 + B: + B: Override Lightbar Color - Override Lightbar Color + Sostituisci Colore Lightbar Override Color - Override Color + Sostituisci Colore @@ -869,7 +865,7 @@ SFO Viewer for - SFO Viewer for + Visualizzatore SFO per diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index b4207e772..8614fb79d 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -9,10 +9,6 @@ About shadPS4 shadPS4について - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4は、PlayStation 4の実験的なオープンソースエミュレーターです。 @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index 80e99ba13..98393050f 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index c21fa5c64..b9be1abbd 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/nb_NO.ts b/src/qt_gui/translations/nb_NO.ts index 8bcf31ee3..aea48dec4 100644 --- a/src/qt_gui/translations/nb_NO.ts +++ b/src/qt_gui/translations/nb_NO.ts @@ -9,10 +9,6 @@ About shadPS4 Om shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 er en eksperimentell åpen kildekode-emulator for PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/nl_NL.ts b/src/qt_gui/translations/nl_NL.ts index 9cf7d955e..e6497768e 100644 --- a/src/qt_gui/translations/nl_NL.ts +++ b/src/qt_gui/translations/nl_NL.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index abcefbb7c..379abe346 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -9,10 +9,6 @@ About shadPS4 O programie - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 to eksperymentalny otwartoźródłowy emulator konsoli PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index accc00561..6b92e74af 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -9,10 +9,6 @@ About shadPS4 Sobre o shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 é um emulador experimental de código-fonte aberto para o PlayStation 4. @@ -526,16 +522,16 @@ Ajuste de Cores - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/pt_PT.ts b/src/qt_gui/translations/pt_PT.ts index 95d344ba7..eb25114bf 100644 --- a/src/qt_gui/translations/pt_PT.ts +++ b/src/qt_gui/translations/pt_PT.ts @@ -9,10 +9,6 @@ About shadPS4 Sobre o shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 é um emulador de código aberto experimental para o PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index a5f62cbfd..4f74cb21d 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index d999bf6fe..71fd06b6f 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -9,10 +9,6 @@ About shadPS4 О shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 это экспериментальный эмулятор с открытым исходным кодом для PlayStation 4. @@ -523,27 +519,27 @@ Color Adjustment - Color Adjustment + Настройка цвета - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color - Override Lightbar Color + Заменить цвет световой панели Override Color - Override Color + Заменить цвет @@ -869,7 +865,7 @@ SFO Viewer for - SFO Viewer for + Просмотр SFO для diff --git a/src/qt_gui/translations/sq_AL.ts b/src/qt_gui/translations/sq_AL.ts index 59fcfcf74..623b15604 100644 --- a/src/qt_gui/translations/sq_AL.ts +++ b/src/qt_gui/translations/sq_AL.ts @@ -9,10 +9,6 @@ About shadPS4 Rreth shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 është një emulator eksperimental me burim të hapur për PlayStation 4. @@ -523,27 +519,27 @@ Color Adjustment - Color Adjustment + Rregullimi i Ngjyrave - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color - Override Lightbar Color + Zëvendëso Ngjyrën e Shiritit të ndriçimit Override Color - Override Color + Zëvendëso Ngjyrën @@ -869,7 +865,7 @@ SFO Viewer for - SFO Viewer for + Shikuesi SFO për diff --git a/src/qt_gui/translations/sv_SE.ts b/src/qt_gui/translations/sv_SE.ts index 46016207c..c7d83055a 100644 --- a/src/qt_gui/translations/sv_SE.ts +++ b/src/qt_gui/translations/sv_SE.ts @@ -9,10 +9,6 @@ About shadPS4 Om shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 är en experimentell emulator för PlayStation 4 baserad på öppen källkod. @@ -523,27 +519,27 @@ Color Adjustment - Color Adjustment + Färgjustering - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color - Override Lightbar Color + Åsidosätt ljusrampens färg Override Color - Override Color + Åsidosätt färg @@ -869,7 +865,7 @@ SFO Viewer for - SFO Viewer for + SFO-visare för diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 4d8d2b916..0ecddb128 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -9,10 +9,6 @@ About shadPS4 shadPS4 Hakkında - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4, PlayStation 4 için deneysel bir açık kaynak kodlu emülatördür. @@ -526,20 +522,20 @@ Renk Ayarları - R: 000 - K: 000 + R: + K: - G: 000 - Y: 000 + G: + Y: - B: 255 - B: 255 + B: + M: Override Lightbar Color - Override Lightbar Color + Işıklı Çubuk Rengini Geçersiz Kıl Override Color @@ -841,7 +837,7 @@ Are you sure you want to delete %1's %2 directory? - Are you sure you want to delete %1's %2 directory? + %1%2 adlı oyunun dizinini silmek istediğinize emin misiniz? Open Update Folder @@ -888,7 +884,7 @@ Delete PKG File on Install - Delete PKG File on Install + Yüklemede PKG Dosyasını Sil @@ -1210,7 +1206,7 @@ Installed - Installed + Yüklü Size @@ -1449,7 +1445,7 @@ Enable Crash Diagnostics - Enable Crash Diagnostics + Çökme Tanılamalarını Etkinleştir Collect Shaders @@ -1609,7 +1605,7 @@ Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Kupa Açılır Pencerelerini Devre Dışı Bırak:\nOyun için kupa bildirimlerini devre dışı bırakın. Kupa ilerlemesi hala Kupa Görüntüleyicisi kullanılarak takip edilebilir (ana menüde oyuna sağ tıklayın). Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. @@ -1625,7 +1621,7 @@ Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Uyumluluk Verilerini Göster:\nOyun uyumluluk bilgilerini tablo görünümünde görüntüler. Güncel bilgileri almak için "Başlangıçta Uyumluluk Veritabanını Güncelle"yi etkinleştirin. Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. @@ -1717,7 +1713,7 @@ Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). - Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). + Gölgelendiricileri Topla:\nHata ayıklama menüsüyle (Ctrl + F10) gölgelendiricileri düzenlemek için bunun etkinleştirilmesi gerekir. Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. @@ -1725,7 +1721,7 @@ Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. - Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. + GPU Arabelleklerini Kopyala:\nGPU gönderimlerini içeren yarış koşullarının etrafından dolaşır.\nPM4 tip 0 çökmelerine yardımcı olabilir veya olmayabilir. Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. @@ -1733,7 +1729,7 @@ Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Konuk Hata Ayıklama İşaretleyicileri\nOyunun kendisinin komut arabelleğine eklediği tüm hata ayıklama işaretlerini ekler.\nBunu etkinleştirdiyseniz, Çökme Tanılamalarını etkinleştirmeniz gerekir.\nRenderDoc gibi programlar için kullanışlıdır. Save Data Path:\nThe folder where game save data will be saved. @@ -1741,7 +1737,7 @@ Browse:\nBrowse for a folder to set as the save data path. - Browse:\nBrowse for a folder to set as the save data path. + Gözat:\nVerileri kaydetme yolu olarak ayarlamak için bir klasöre göz atın. Borderless @@ -1749,7 +1745,7 @@ True - True + Gerçek Ekran Release diff --git a/src/qt_gui/translations/uk_UA.ts b/src/qt_gui/translations/uk_UA.ts index 4a18079de..aa430d401 100644 --- a/src/qt_gui/translations/uk_UA.ts +++ b/src/qt_gui/translations/uk_UA.ts @@ -9,10 +9,6 @@ About shadPS4 Про shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 - це експериментальний емулятор з відкритим вихідним кодом для PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 50d6372cc..cccec7ae0 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -9,10 +9,6 @@ About shadPS4 Về shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 là một trình giả lập thử nghiệm mã nguồn mở cho PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 9a979394b..2c5d5005e 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -9,10 +9,6 @@ About shadPS4 关于 shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 是一款实验性质的开源 PlayStation 4 模拟器软件。 @@ -523,27 +519,27 @@ Color Adjustment - Color Adjustment + 颜色调整 - R: 000 - R: 000 + R: + 红: - G: 000 - G: 000 + G: + 绿: - B: 255 - B: 255 + B: + 蓝: Override Lightbar Color - Override Lightbar Color + 覆盖灯条颜色 Override Color - Override Color + 覆盖颜色 @@ -869,7 +865,7 @@ SFO Viewer for - SFO Viewer for + SFO 查看器 - diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 22edba21e..82202a6d6 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -9,10 +9,6 @@ About shadPS4 About shadPS4 - - shadPS4 - shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 is an experimental open-source emulator for the PlayStation 4. @@ -526,16 +522,16 @@ Color Adjustment - R: 000 - R: 000 + R: + R: - G: 000 - G: 000 + G: + G: - B: 255 - B: 255 + B: + B: Override Lightbar Color From 48c621532cedef89db225cacb40074a4577bdf16 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Wed, 19 Feb 2025 08:29:04 -0300 Subject: [PATCH 23/29] Cheats/Patches - add mask_jump32 (#2477) * mask_jump32 * fix qt/sdl * fix dangling pointer? fixes the warning: "clang-diagnostic-dangling-gls: object backing the pointer will be destroyed at the end of the full-expression" --- src/common/memory_patcher.cpp | 164 ++++++++++++++++++++++++++-------- src/common/memory_patcher.h | 5 +- src/qt_gui/cheats_patches.cpp | 22 ++--- 3 files changed, 137 insertions(+), 54 deletions(-) diff --git a/src/common/memory_patcher.cpp b/src/common/memory_patcher.cpp index 899bb6bf3..0a74a45a5 100644 --- a/src/common/memory_patcher.cpp +++ b/src/common/memory_patcher.cpp @@ -144,37 +144,39 @@ void OnGameLoaded() { std::string type = patchLineIt->attribute("Type").value(); std::string address = patchLineIt->attribute("Address").value(); std::string patchValue = patchLineIt->attribute("Value").value(); - std::string maskOffsetStr = patchLineIt->attribute("type").value(); - - patchValue = convertValueToHex(type, patchValue); + std::string maskOffsetStr = patchLineIt->attribute("Offset").value(); + std::string targetStr = ""; + std::string sizeStr = ""; + if (type == "mask_jump32") { + std::string patchValue = patchLineIt->attribute("Value").value(); + targetStr = patchLineIt->attribute("Target").value(); + sizeStr = patchLineIt->attribute("Size").value(); + } else { + patchValue = convertValueToHex(type, patchValue); + } bool littleEndian = false; - if (type == "bytes16") { - littleEndian = true; - } else if (type == "bytes32") { - littleEndian = true; - } else if (type == "bytes64") { + if (type == "bytes16" || type == "bytes32" || type == "bytes64") { littleEndian = true; } MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None; int maskOffsetValue = 0; - if (type == "mask") { + if (type == "mask") patchMask = MemoryPatcher::PatchMask::Mask; - // im not sure if this works, there is no games to test the mask - // offset on yet - if (!maskOffsetStr.empty()) - maskOffsetValue = std::stoi(maskOffsetStr, 0, 10); - } - if (type == "mask_jump32") patchMask = MemoryPatcher::PatchMask::Mask_Jump32; - MemoryPatcher::PatchMemory(currentPatchName, address, patchValue, false, - littleEndian, patchMask, maskOffsetValue); + if (type == "mask" || type == "mask_jump32" && !maskOffsetStr.empty()) { + maskOffsetValue = std::stoi(maskOffsetStr, 0, 10); + } + + MemoryPatcher::PatchMemory(currentPatchName, address, patchValue, + targetStr, sizeStr, false, littleEndian, + patchMask, maskOffsetValue); } } } @@ -279,6 +281,10 @@ void OnGameLoaded() { lineObject["Address"] = attributes.value("Address").toString(); lineObject["Value"] = attributes.value("Value").toString(); lineObject["Offset"] = attributes.value("Offset").toString(); + if (lineObject["Type"].toString() == "mask_jump32") { + lineObject["Target"] = attributes.value("Target").toString(); + lineObject["Size"] = attributes.value("Size").toString(); + } linesArray.append(lineObject); } } @@ -292,37 +298,40 @@ void OnGameLoaded() { QString patchValue = lineObject["Value"].toString(); QString maskOffsetStr = lineObject["Offset"].toString(); - patchValue = QString::fromStdString( - convertValueToHex(type.toStdString(), patchValue.toStdString())); + QString targetStr; + QString sizeStr; + if (type == "mask_jump32") { + QString valueAttributeStr = lineObject["Value"].toString(); + targetStr = lineObject["Value"].toString(); + sizeStr = lineObject["Size"].toString(); + } else { + patchValue = QString::fromStdString(convertValueToHex( + type.toStdString(), patchValue.toStdString())); + } bool littleEndian = false; - if (type == "bytes16") { + if (type == "bytes16" || type == "bytes32" || type == "bytes64") littleEndian = true; - } else if (type == "bytes32") { - littleEndian = true; - } else if (type == "bytes64") { - littleEndian = true; - } MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None; int maskOffsetValue = 0; - if (type == "mask") { + if (type == "mask") patchMask = MemoryPatcher::PatchMask::Mask; - // im not sure if this works, there is no games to test the mask - // offset on yet - if (!maskOffsetStr.toStdString().empty()) - maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); - } - if (type == "mask_jump32") patchMask = MemoryPatcher::PatchMask::Mask_Jump32; - MemoryPatcher::PatchMemory(currentPatchName, address.toStdString(), - patchValue.toStdString(), false, - littleEndian, patchMask, maskOffsetValue); + if (type == "mask" || + type == "mask_jump32" && !maskOffsetStr.toStdString().empty()) { + maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); + } + + MemoryPatcher::PatchMemory( + currentPatchName, address.toStdString(), patchValue.toStdString(), + targetStr.toStdString(), sizeStr.toStdString(), false, littleEndian, + patchMask, maskOffsetValue); } } } @@ -351,7 +360,7 @@ void ApplyPendingPatches() { if (currentPatch.gameSerial != g_game_serial) continue; - PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, + PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, "", "", currentPatch.isOffset, currentPatch.littleEndian, currentPatch.patchMask, currentPatch.maskOffset); } @@ -359,8 +368,9 @@ void ApplyPendingPatches() { pending_patches.clear(); } -void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset, - bool littleEndian, PatchMask patchMask, int maskOffset) { +void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, + std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian, + PatchMask patchMask, int maskOffset) { // Send a request to modify the process memory. void* cheatAddress = nullptr; @@ -377,7 +387,83 @@ void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valu cheatAddress = reinterpret_cast(PatternScan(offsetStr) + maskOffset); } - // TODO: implement mask_jump32 + if (patchMask == PatchMask::Mask_Jump32) { + int jumpSize = std::stoi(sizeStr); + + constexpr int MAX_PATTERN_LENGTH = 256; + if (jumpSize < 5) { + LOG_ERROR(Loader, "Jump size must be at least 5 bytes"); + return; + } + if (jumpSize > MAX_PATTERN_LENGTH) { + LOG_ERROR(Loader, "Jump size must be no more than {} bytes.", MAX_PATTERN_LENGTH); + return; + } + + // Find the base address using "Address" + uintptr_t baseAddress = PatternScan(offsetStr); + if (baseAddress == 0) { + LOG_ERROR(Loader, "PatternScan failed for mask_jump32 with pattern: {}", offsetStr); + return; + } + uintptr_t patchAddress = baseAddress + maskOffset; + + // Fills the original region (jumpSize bytes) with NOPs + std::vector nopBytes(jumpSize, 0x90); + std::memcpy(reinterpret_cast(patchAddress), nopBytes.data(), nopBytes.size()); + + // Use "Target" to locate the start of the code cave + uintptr_t jump_target = PatternScan(targetStr); + if (jump_target == 0) { + LOG_ERROR(Loader, "PatternScan failed to Target with pattern: {}", targetStr); + return; + } + + // Converts the Value attribute to a byte array (payload) + std::vector payload; + for (size_t i = 0; i < valueStr.length(); i += 2) { + + std::string tempStr = valueStr.substr(i, 2); + const char* byteStr = tempStr.c_str(); + char* endPtr; + unsigned int byteVal = std::strtoul(byteStr, &endPtr, 16); + + if (endPtr != byteStr + 2) { + LOG_ERROR(Loader, "Invalid byte in Value: {}", valueStr.substr(i, 2)); + return; + } + payload.push_back(static_cast(byteVal)); + } + + // Calculates the end of the code cave (where the return jump will be inserted) + uintptr_t code_cave_end = jump_target + payload.size(); + + // Write the payload to the code cave, from jump_target + std::memcpy(reinterpret_cast(jump_target), payload.data(), payload.size()); + + // Inserts the initial jump in the original region to divert to the code cave + u8 jumpInstruction[5]; + jumpInstruction[0] = 0xE9; + s32 relJump = static_cast(jump_target - patchAddress - 5); + std::memcpy(&jumpInstruction[1], &relJump, sizeof(relJump)); + std::memcpy(reinterpret_cast(patchAddress), jumpInstruction, + sizeof(jumpInstruction)); + + // Inserts jump back at the end of the code cave to resume execution after patching + u8 jumpBack[5]; + jumpBack[0] = 0xE9; + // Calculates the relative offset to return to the instruction immediately following the + // overwritten region + s32 target_return = static_cast((patchAddress + jumpSize) - (code_cave_end + 5)); + std::memcpy(&jumpBack[1], &target_return, sizeof(target_return)); + std::memcpy(reinterpret_cast(code_cave_end), jumpBack, sizeof(jumpBack)); + + LOG_INFO(Loader, + "Applied Patch mask_jump32: {}, PatchAddress: {:#x}, JumpTarget: {:#x}, " + "CodeCaveEnd: {:#x}, JumpSize: {}", + modNameStr, patchAddress, jump_target, code_cave_end, jumpSize); + return; + } if (cheatAddress == nullptr) { LOG_ERROR(Loader, "Failed to get address for patch {}", modNameStr); diff --git a/src/common/memory_patcher.h b/src/common/memory_patcher.h index 899ffccb1..29045a6a2 100644 --- a/src/common/memory_patcher.h +++ b/src/common/memory_patcher.h @@ -38,8 +38,9 @@ void OnGameLoaded(); void AddPatchToQueue(patchInfo patchToAdd); void ApplyPendingPatches(); -void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset, - bool littleEndian, PatchMask patchMask = PatchMask::None, int maskOffset = 0); +void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, + std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian, + PatchMask patchMask = PatchMask::None, int maskOffset = 0); static std::vector PatternToByte(const std::string& pattern); uintptr_t PatternScan(const std::string& signature); diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index 01227d822..597729a45 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -1346,7 +1346,7 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) { // Determine if the hint field is present bool isHintPresent = m_cheats[modName].hasHint; - MemoryPatcher::PatchMemory(modNameStr, offsetStr, valueStr, !isHintPresent, false); + MemoryPatcher::PatchMemory(modNameStr, offsetStr, valueStr, "", "", !isHintPresent, false); } } @@ -1368,28 +1368,23 @@ void CheatsPatches::applyPatch(const QString& patchName, bool enabled) { bool littleEndian = false; - if (type == "bytes16") { - littleEndian = true; - } else if (type == "bytes32") { - littleEndian = true; - } else if (type == "bytes64") { + if (type == "bytes16" || type == "bytes32" || type == "bytes64") { littleEndian = true; } MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None; int maskOffsetValue = 0; - if (type == "mask") { + if (type == "mask") patchMask = MemoryPatcher::PatchMask::Mask; - // im not sure if this works, there is no games to test the mask offset on yet - if (!maskOffsetStr.toStdString().empty()) - maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); - } - if (type == "mask_jump32") patchMask = MemoryPatcher::PatchMask::Mask_Jump32; + if (type == "mask" || type == "mask_jump32" && !maskOffsetStr.toStdString().empty()) { + maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); + } + if (MemoryPatcher::g_eboot_address == 0) { MemoryPatcher::patchInfo addingPatch; addingPatch.gameSerial = patchInfo.serial.toStdString(); @@ -1405,7 +1400,8 @@ void CheatsPatches::applyPatch(const QString& patchName, bool enabled) { continue; } MemoryPatcher::PatchMemory(patchName.toStdString(), address.toStdString(), - patchValue.toStdString(), false, littleEndian, patchMask); + patchValue.toStdString(), "", "", false, littleEndian, + patchMask); } } } From f686b1df98c2eaa87417c46ed9bb4b7f5cf44f9b Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 19 Feb 2025 13:29:16 +0200 Subject: [PATCH 24/29] New Crowdin updates (#2478) * New translations en_us.ts (French) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Italian) --- src/qt_gui/translations/fr_FR.ts | 2 +- src/qt_gui/translations/it_IT.ts | 4 +- src/qt_gui/translations/pt_PT.ts | 94 ++++++++++++++++---------------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/qt_gui/translations/fr_FR.ts b/src/qt_gui/translations/fr_FR.ts index 656ce750d..d328e9bcc 100644 --- a/src/qt_gui/translations/fr_FR.ts +++ b/src/qt_gui/translations/fr_FR.ts @@ -1733,7 +1733,7 @@ Save Data Path:\nThe folder where game save data will be saved. - Save Data Path:\nThe folder where game save data will be saved. + Chemin de sauvegarde :\nLe dossier où les sauvegardes du jeu sont enregistré. Browse:\nBrowse for a folder to set as the save data path. diff --git a/src/qt_gui/translations/it_IT.ts b/src/qt_gui/translations/it_IT.ts index 32bb44d3f..be61e0df2 100644 --- a/src/qt_gui/translations/it_IT.ts +++ b/src/qt_gui/translations/it_IT.ts @@ -1593,7 +1593,7 @@ Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. - Aggiornamento:\nRelease: Versioni ufficiali rilasciate ogni mese che potrebbero essere molto datate, ma sono più affidabili e testate.\nNightly: Versioni di sviluppo che hanno tutte le ultime funzionalità e correzioni, ma potrebbero contenere bug e sono meno stabili. + Aggiornamento:\nRilascio: Versioni ufficiali rilasciate ogni mese che possono essere molto obsolete, ma sono più affidabili e testati.\nNotturno: Le versioni di sviluppo che hanno tutte le ultime funzionalità e correzioni, ma possono contenere bug e sono meno stabili. Background Image:\nControl the opacity of the game background image. @@ -1661,7 +1661,7 @@ Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - Dispositivo Grafico:\nIn sistemi con più GPU, seleziona la GPU che l'emulatore utilizzerà dall'elenco a discesa,\no seleziona "Auto Select" per determinarlo automaticamente. + Dispositivo Grafico:\nIn sistemi con più GPU, seleziona la GPU che l'emulatore utilizzerà dall'elenco a discesa,\no seleziona "Selezione Automatica" per determinarlo automaticamente. Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. diff --git a/src/qt_gui/translations/pt_PT.ts b/src/qt_gui/translations/pt_PT.ts index eb25114bf..0b5cd5632 100644 --- a/src/qt_gui/translations/pt_PT.ts +++ b/src/qt_gui/translations/pt_PT.ts @@ -519,27 +519,27 @@ Color Adjustment - Color Adjustment + Ajuste de Cores R: - R: + R: G: - G: + G: B: - B: + B: Override Lightbar Color - Override Lightbar Color + Substituir cor da Lightbar Override Color - Override Color + Substituir Cor @@ -865,7 +865,7 @@ SFO Viewer for - SFO Viewer for + Visualizador SFO para @@ -1123,7 +1123,7 @@ Would you like to install Patch: - Would you like to install Patch: + Gostaria de instalar o Patch: DLC Installation @@ -1222,7 +1222,7 @@ App Ver - App Ver + App Ver FW @@ -1553,83 +1553,83 @@ Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. - Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. + Idioma da consola:\nDefine o idioma usado pelo jogo PS4.\nRecomenda-se configurar isto para um idioma que o jogo suporte, o que pode variar conforme a região. Emulator Language:\nSets the language of the emulator's user interface. - Emulator Language:\nSets the language of the emulator's user interface. + Idioma do Emulador:\nDefine o idioma da interface gráfica do emulador. Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. - Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. + Ativar Ecrã Cheio:\nPõe automaticamente a janela do jogo no modo de ecrã cheio.\nIsto pode ser alterado pressionando a tecla F11. Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. + Ativar Pasta de Atualização Separada:\nPermite instalar as atualizações dos jogos numa pasta separada para uma fácil gestão.\nIsto pode ser manualmente criado adicionando a atualização extraída à pasta do jogo com o nome "CUSA00000-UPDATE" onde o ID do CUSA corresponde ao ID do jogo. Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. + Mostrar Splash Inicial:\nExibe o ecrã inicial do jogo (uma imagem especial) enquanto o jogo inicia. Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. - Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. + Ativar Discord Rich Presence:\nExibe o ícone do emulador e informações relevantes no seu perfil do Discord. Username:\nSets the PS4's account username, which may be displayed by some games. - Username:\nSets the PS4's account username, which may be displayed by some games. + Nome de utilizador:\nDefine o nome de utilizador da conta PS4, que poderá ser exibido por alguns jogos. Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + Chave de Troféu:\nChave usada para decifrar os troféus. Deverá ser obtida a partir da sua consola desbloqueada.\nDeve conter apenas caracteres hexadecimais. Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. - Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. + Tipo de Registo:\nDetermina se a saída da janela de registo deve ser sincronizada por motivos de desempenho. Pode impactar negativamente a emulação. Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. - Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. + Filtro de Registo:\nFiltra o registo de modo a exibir apenas informações específicas.\nExemplos: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nNíveis: Trace, Debug, Info, Warning, Error, Critical - nesta ordem, um nível específico silencia todos os níveis anteriores na lista e regista todos os níveis após ele. Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. - Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. + Atualização:\nLançamento: Versões oficiais lançadas todos os meses que podem estar desatualizadas, mas são mais estáveis e testadas.\nNightly: Versões de desenvolvimento que têm todos os últimos recursos e correções, mas podem conter bugs e são menos estáveis. Background Image:\nControl the opacity of the game background image. - Background Image:\nControl the opacity of the game background image. + Imagem de Fundo:\nControla a transparência da imagem de fundo do jogo. Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. + Reproduzir Música de Título:\nSe o jogo suportar, ativa a reprodução de uma música especial ao selecionar o jogo na interface de utilizador. Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Desativar Pop-ups dos Troféus:\nDesativa notificações de troféus em jogo. O progresso do troféu ainda poderá ser rastreado ao usar o Visualizador de Troféus (clique com o botão direito do rato no jogo na janela principal). Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. - Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. + Ocultar Cursor:\nEscolha quando o cursor desaparecerá:\nNunca: Verá sempre o rato.\nParado: Defina um tempo para desaparecer após ficar inativo.\nSempre: Nunca verá o rato. Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. - Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. + Tempo de Espera para Ocultar o Cursor:\nDefine o tempo em segundos para o rato desaparecer após ficar inativo. Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. - Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. + Comportamento do Botão Voltar:\nConfigura o botão Voltar do comando para emular um toque na posição especificada no touchpad do PS4. Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Exibir Dados de Compatibilidade:\nExibe informações de compatibilidade dos jogos em visualização de tabela.\nAtivar "Atualizar Base de Dados de Compatibilidade no Arranque" para obter informações atualizadas. Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Atualizar Base de Dados de Compatibilidade no Arranque:\nAtualiza automaticamente a base de dados de compatibilidade quando o shadPS4 é iniciado. Update Compatibility Database:\nImmediately update the compatibility database. - Update Compatibility Database:\nImmediately update the compatibility database. + Atualizar Base de Dados de Compatibilidade:\nAtualiza imediatamente a base de dados de compatibilidade. Never @@ -1661,31 +1661,31 @@ Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. + Placa Gráfica:\nEm sistemas com múltiplas GPUs, escolha qual GPU da lista o emulador utilizará,\nou escolha "Seleção Automática" para escolher automaticamente a mesma. Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. - Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. + Largura/Altura:\nDefine o tamanho da janela do emulador no arranque, que poderá ser redimensionada enquanto joga.\nIsto difere da resolução do jogo. Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! - Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! + Divisor Vblank:\nA taxa de quadros em que o emulador atualiza é multiplicada por este número. Mudar isto poderá ter efeitos negativos, como aumentar a velocidade ou causar problemas na funcionalidade vital de jogo que não esteja à espera que isto mude! Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. - Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. + Ativar Dumping de Shaders:\nArmazena as shaders do jogo numa pasta durante a renderização para fins de depuração técnica. Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. + Ativar GPU NULL:\nDesativa a renderização do jogo para fins de depuração técnica, como se não existisse uma placa gráfica. Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. - Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. + Ativar HDR:\nAtiva o HDR em jogos que o suportem.\nO seu monitor deverá ter suporte para o espaço de cores BT2020 PQ e para o formato de swapchain RGB10A2. Game Folders:\nThe list of folders to check for installed games. - Game Folders:\nThe list of folders to check for installed games. + Pastas de Jogos:\nLista de pastas onde procurar jogos instalados. Add:\nAdd a folder to the list. @@ -1697,47 +1697,47 @@ Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. - Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. + Ativar Dumping da Depuração:\nArmazena os símbolos de importação, exportação e informações do cabeçalho de ficheiros do atual programa PS4 num diretório. Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. - Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. + Ativar Camadas de Validação do Vulkan:\nAtiva um sistema que valida o estado do renderizador Vulkan e regista informações sobre o seu estado interno.\nIsto irá diminuir o desempenho e provavelmente mudará o comportamento da emulação. Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. - Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. + Ativar Validação da Sincronização do Vulkan:\nAtiva um sistema que valida o agendamento de tarefas de renderização Vulkan.\nIsto irá diminuir o desempenho e provavelmente mudará o comportamento da emulação. Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. - Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + Ativar Depuração por RenderDoc:\nSe ativado, o emulador fornecerá compatibilidade com o RenderDoc para permitir a captura e análise do quadro atualmente renderizado. Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). - Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). + Recolher Shaders:\nIrá precisar desta opção ativada para editar shaders com o menu de depuração (Ctrl + F10). Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. - Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work. + Diagnóstico de Falhas:\nCria um ficheiro .yaml com informações sobre o estado do Vulkan no momento da falha.\nÚtil para depuração de erros de 'Device lost'. Se isto estiver ativado, deverá ativar os Marcadores de Depuração de Host E DE Convidado.\nNão funciona em GPUs Intel.\nPrecisa também de ter as Camadas de Validação Vulkan ativadas e o Vulkan SDK instalado para funcionar. Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. - Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. + Copiar Buffers da GPU:\nContorna condições de corrida envolvendo envios de GPU.\nPode ou não ajudar com bloqueios do PM4 tipo 0. Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Host Debug Markers:\nInserts emulator-side information like markers for specific AMDGPU commands around Vulkan commands, as well as giving resources debug names.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Marcadores de Depuração do Host:\nInsere informações vindas do lado do emulador como marcadores para comandos AMDGPU específicos em torno de comandos Vulkan, além de fornecer nomes de depuração aos recursos.\nSe isto estiver ativado, ative os Diagnósticos de Falha.\nÚtil para programas como o RenderDoc. Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. - Guest Debug Markers:\nInserts any debug markers the game itself has added to the command buffer.\nIf you have this enabled, you should enable Crash Diagnostics.\nUseful for programs like RenderDoc. + Marcadores de Depuração do Cliente:\nInsere quaisquer marcadores de depuração que o próprio jogo adicionou ao buffer de comando.\nSe isto estiver ativado, ative os Diagnósticos de Falha.\nÚtil para programas como o RenderDoc. Save Data Path:\nThe folder where game save data will be saved. - Save Data Path:\nThe folder where game save data will be saved. + Caminho dos Dados Guardados:\nA pasta onde os dados de utilizador dos jogos serão guardados. Browse:\nBrowse for a folder to set as the save data path. - Browse:\nBrowse for a folder to set as the save data path. + Procurar:\nProcure uma pasta para definir como o caminho para guardar os dados. Borderless From 50aa0f5564992f291ae038af4cfd2d659c571b0d Mon Sep 17 00:00:00 2001 From: jarred wilson <20207921+jardon@users.noreply.github.com> Date: Wed, 19 Feb 2025 05:29:31 -0600 Subject: [PATCH 25/29] Update linux build docs (#2474) * fix: update linux build dependencies for libpng - add libpng to linux build docs - add libpng to nix build file * linux docs: reformat code blocks - add code block bash syntax highlighting - format long code blocks to multiline --- documents/building-linux.md | 46 +++++++++++++++++++++++++------------ shell.nix | 1 + 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/documents/building-linux.md b/documents/building-linux.md index 71e26e792..4ca953af6 100644 --- a/documents/building-linux.md +++ b/documents/building-linux.md @@ -13,33 +13,49 @@ First and foremost, Clang 18 is the **recommended compiler** as it is used for o #### Debian & Ubuntu -``` -sudo apt install build-essential clang git cmake libasound2-dev libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev vulkan-validationlayers +```bash +sudo apt install build-essential clang git cmake libasound2-dev \ + libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev \ + libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev \ + qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev \ + vulkan-validationlayers libpng-dev ``` #### Fedora -``` -sudo dnf install clang git cmake libatomic alsa-lib-devel pipewire-jack-audio-connection-kit-devel openal-devel openssl-devel libevdev-devel libudev-devel libXext-devel qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel vulkan-devel vulkan-validation-layers +```bash +sudo dnf install clang git cmake libatomic alsa-lib-devel \ + pipewire-jack-audio-connection-kit-devel openal-devel \ + openssl-devel libevdev-devel libudev-devel libXext-devel \ + qt6-qtbase-devel qt6-qtbase-private-devel \ + qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel \ + vulkan-devel vulkan-validation-layers libpng-devel ``` #### Arch Linux -``` -sudo pacman -S base-devel clang git cmake sndio jack2 openal qt6-base qt6-declarative qt6-multimedia sdl2 vulkan-validation-layers +```bash +sudo pacman -S base-devel clang git cmake sndio jack2 openal \ + qt6-base qt6-declarative qt6-multimedia sdl2 \ + vulkan-validation-layers libpng ``` **Note**: The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion. #### OpenSUSE -``` -sudo zypper install clang git cmake libasound2 libpulse-devel libsndio7 libjack-devel openal-soft-devel libopenssl-devel zlib-devel libedit-devel systemd-devel libevdev-devel qt6-base-devel qt6-multimedia-devel qt6-svg-devel qt6-linguist-devel qt6-gui-private-devel vulkan-devel vulkan-validationlayers +```bash +sudo zypper install clang git cmake libasound2 libpulse-devel \ + libsndio7 libjack-devel openal-soft-devel libopenssl-devel \ + zlib-devel libedit-devel systemd-devel libevdev-devel \ + qt6-base-devel qt6-multimedia-devel qt6-svg-devel \ + qt6-linguist-devel qt6-gui-private-devel vulkan-devel \ + vulkan-validationlayers libpng-devel ``` #### NixOS -``` +```bash nix-shell shell.nix ``` @@ -50,7 +66,7 @@ You can try one of two methods: - Search the packages by name and install them with your package manager, or - Install [distrobox](https://distrobox.it/), create a container using any of the distributions cited above as a base, for Arch Linux you'd do: -``` +```bash distrobox create --name archlinux --init --image archlinux:latest ``` @@ -59,7 +75,7 @@ This option is **highly recommended** for distributions with immutable/atomic fi ### Cloning -``` +```bash git clone --recursive https://github.com/shadps4-emu/shadPS4.git cd shadPS4 ``` @@ -72,7 +88,7 @@ There are 3 options you can choose from. Option 1 is **highly recommended**. 1. Generate the build directory in the shadPS4 directory. -``` +```bash cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ``` @@ -80,7 +96,7 @@ To disable the Qt GUI, remove the `-DENABLE_QT_GUI=ON` flag. To change the build 2. Use CMake to build the project: -``` +```bash cmake --build ./build --parallel$(nproc) ``` @@ -88,13 +104,13 @@ If your computer freezes during this step, this could be caused by excessive sys Now run the emulator. If Qt was enabled at configure time: -``` +```bash ./build/shadps4 ``` Otherwise, specify the path to your PKG's boot file: -``` +```bash ./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin ``` diff --git a/shell.nix b/shell.nix index cc9cc1f82..4eee9fdea 100644 --- a/shell.nix +++ b/shell.nix @@ -46,6 +46,7 @@ pkgs.mkShell { pkgs.stb pkgs.qt6.qtwayland pkgs.wayland-protocols + pkgs.libpng ]; shellHook = '' From da0ab005c78f18afb4168b332107042b1f1d0375 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:31:35 +0200 Subject: [PATCH 26/29] video_core: Fix some cases of "Attempted to track non-GPU memory" (#2447) * memory: Consider flexible mappings as gpu accessible Multiple guest apps do this with perfectly valid sharps in simple shaders. This needs some hw testing to see how it is handled but for now doesnt hurt to handle it * memory: Clamp large buffers to mapped area Sometimes huge buffers can be bound that start on some valid mapping but arent fully contained by it. It is not reasonable to expect the game needing all of the memory, so clamp the size to avoid the gpu tracking assert * clang-format fix --------- Co-authored-by: georgemoralis --- src/core/memory.cpp | 23 +++++++++++++++---- src/core/memory.h | 2 ++ .../renderer_vulkan/vk_rasterizer.cpp | 19 ++++++++------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 4717b3a74..23fb6192f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -56,6 +56,23 @@ void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1 total_flexible_size, total_direct_size); } +u64 MemoryManager::ClampRangeSize(VAddr virtual_addr, u64 size) { + static constexpr u64 MinSizeToClamp = 1_GB; + // Dont bother with clamping if the size is small so we dont pay a map lookup on every buffer. + if (size < MinSizeToClamp) { + return size; + } + const auto vma = FindVMA(virtual_addr); + ASSERT_MSG(vma != vma_map.end(), "Attempted to access invalid GPU address {:#x}", virtual_addr); + const u64 clamped_size = + std::min(size, vma->second.base + vma->second.size - virtual_addr); + if (size != clamped_size) { + LOG_WARNING(Kernel_Vmm, "Clamped requested buffer range addr={:#x}, size={:#x} to {:#x}", + virtual_addr, size, clamped_size); + } + return clamped_size; +} + bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 num_bytes) { const VAddr virtual_addr = std::bit_cast(address); const auto& vma = FindVMA(virtual_addr)->second; @@ -314,11 +331,11 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M if (type == VMAType::Direct) { new_vma.phys_base = phys_addr; - rasterizer->MapMemory(mapped_addr, size); } if (type == VMAType::Flexible) { flexible_usage += size; } + rasterizer->MapMemory(mapped_addr, size); return ORBIS_OK; } @@ -406,12 +423,10 @@ u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma if (type == VMAType::Free) { return adjusted_size; } - if (type == VMAType::Direct || type == VMAType::Pooled) { - rasterizer->UnmapMemory(virtual_addr, adjusted_size); - } if (type == VMAType::Flexible) { flexible_usage -= adjusted_size; } + rasterizer->UnmapMemory(virtual_addr, adjusted_size); // Mark region as free and attempt to coalesce it with neighbours. const auto new_it = CarveVMA(virtual_addr, adjusted_size); diff --git a/src/core/memory.h b/src/core/memory.h index 59e48b248..ff7b82c10 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -164,6 +164,8 @@ public: return virtual_addr >= vma_map.begin()->first && virtual_addr < end_addr; } + u64 ClampRangeSize(VAddr virtual_addr, u64 size); + bool TryWriteBacking(void* address, const void* data, u32 num_bytes); void SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, bool use_extended_mem2); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 4d58c0ea3..87d07a967 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -502,16 +502,17 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding for (const auto& desc : stage.buffers) { const auto vsharp = desc.GetSharp(stage); if (!desc.IsSpecial() && vsharp.base_address != 0 && vsharp.GetSize() > 0) { - const auto buffer_id = buffer_cache.FindBuffer(vsharp.base_address, vsharp.GetSize()); - buffer_bindings.emplace_back(buffer_id, vsharp); + const u64 size = memory->ClampRangeSize(vsharp.base_address, vsharp.GetSize()); + const auto buffer_id = buffer_cache.FindBuffer(vsharp.base_address, size); + buffer_bindings.emplace_back(buffer_id, vsharp, size); } else { - buffer_bindings.emplace_back(VideoCore::BufferId{}, vsharp); + buffer_bindings.emplace_back(VideoCore::BufferId{}, vsharp, 0); } } // Second pass to re-bind buffers that were updated after binding for (u32 i = 0; i < buffer_bindings.size(); i++) { - const auto& [buffer_id, vsharp] = buffer_bindings[i]; + const auto& [buffer_id, vsharp, size] = buffer_bindings[i]; const auto& desc = stage.buffers[i]; const bool is_storage = desc.IsStorage(vsharp, pipeline_cache.GetProfile()); // Buffer is not from the cache, either a special buffer or unbound. @@ -540,17 +541,15 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding buffer_infos.emplace_back(null_buffer.Handle(), 0, VK_WHOLE_SIZE); } } else { - const auto [vk_buffer, offset] = - buffer_cache.ObtainBuffer(vsharp.base_address, vsharp.GetSize(), desc.is_written, - desc.is_formatted, buffer_id); + const auto [vk_buffer, offset] = buffer_cache.ObtainBuffer( + vsharp.base_address, size, desc.is_written, desc.is_formatted, buffer_id); const u32 alignment = is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); const u32 offset_aligned = Common::AlignDown(offset, alignment); const u32 adjust = offset - offset_aligned; ASSERT(adjust % 4 == 0); push_data.AddOffset(binding.buffer, adjust); - buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, - vsharp.GetSize() + adjust); + buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust); if (auto barrier = vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite : vk::AccessFlagBits2::eShaderRead, @@ -558,7 +557,7 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding buffer_barriers.emplace_back(*barrier); } if (desc.is_written && desc.is_formatted) { - texture_cache.InvalidateMemoryFromGPU(vsharp.base_address, vsharp.GetSize()); + texture_cache.InvalidateMemoryFromGPU(vsharp.base_address, size); } } From cc583b6189dd10aa25faa4a7522cd1891e193213 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 19 Feb 2025 13:55:18 +0200 Subject: [PATCH 27/29] hot-fix: rasterizer --- src/video_core/renderer_vulkan/vk_rasterizer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 3b45fd52e..2fac8c8da 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -117,7 +117,7 @@ private: Pipeline::DescriptorWrites set_writes; Pipeline::BufferBarriers buffer_barriers; - using BufferBindingInfo = std::pair; + using BufferBindingInfo = std::tuple; boost::container::static_vector buffer_bindings; using ImageBindingInfo = std::pair; boost::container::static_vector image_bindings; From 2af20b0d8375f9681c16cb165f100df7f833496e Mon Sep 17 00:00:00 2001 From: Dmugetsu <168934208+diegolix29@users.noreply.github.com> Date: Thu, 20 Feb 2025 02:15:54 -0600 Subject: [PATCH 28/29] Now lightbar overwrite works on dualsense while using it on bluetooth (#2481) --- src/sdl_window.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index ccc369c53..db6f37e2a 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -97,6 +97,7 @@ void SDLInputEngine::Init() { SDL_CloseGamepad(m_gamepad); m_gamepad = nullptr; } + int gamepad_count; SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); if (!gamepads) { @@ -108,12 +109,26 @@ void SDLInputEngine::Init() { SDL_free(gamepads); return; } + LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count); - if (!(m_gamepad = SDL_OpenGamepad(gamepads[0]))) { + m_gamepad = SDL_OpenGamepad(gamepads[0]); + if (!m_gamepad) { LOG_ERROR(Input, "Failed to open gamepad 0: {}", SDL_GetError()); SDL_free(gamepads); return; } + + SDL_Joystick* joystick = SDL_GetGamepadJoystick(m_gamepad); + Uint16 vendor = SDL_GetJoystickVendor(joystick); + Uint16 product = SDL_GetJoystickProduct(joystick); + + bool isDualSense = (vendor == 0x054C && product == 0x0CE6); + + LOG_INFO(Input, "Gamepad Vendor: {:04X}, Product: {:04X}", vendor, product); + if (isDualSense) { + LOG_INFO(Input, "Detected DualSense Controller"); + } + if (Config::getIsMotionControlsEnabled()) { if (SDL_SetGamepadSensorEnabled(m_gamepad, SDL_SENSOR_GYRO, true)) { m_gyro_poll_rate = SDL_GetGamepadSensorDataRate(m_gamepad, SDL_SENSOR_GYRO); @@ -126,11 +141,22 @@ void SDLInputEngine::Init() { LOG_INFO(Input, "Accel initialized, poll rate: {}", m_accel_poll_rate); } else { LOG_ERROR(Input, "Failed to initialize accel controls for gamepad"); - }; + } } + SDL_free(gamepads); + int* rgb = Config::GetControllerCustomColor(); - SetLightBarRGB(rgb[0], rgb[1], rgb[2]); + + if (isDualSense) { + if (SDL_SetJoystickLED(joystick, rgb[0], rgb[1], rgb[2]) == 0) { + LOG_INFO(Input, "Set DualSense LED to R:{} G:{} B:{}", rgb[0], rgb[1], rgb[2]); + } else { + LOG_ERROR(Input, "Failed to set DualSense LED: {}", SDL_GetError()); + } + } else { + SetLightBarRGB(rgb[0], rgb[1], rgb[2]); + } } void SDLInputEngine::SetLightBarRGB(u8 r, u8 g, u8 b) { From b6baf7881292958bc5373bd75da50a89de215982 Mon Sep 17 00:00:00 2001 From: Missake212 Date: Thu, 20 Feb 2025 09:16:13 +0100 Subject: [PATCH 29/29] adding info about MSYS2 build (#2482) adding information about MSYS2 builds being broken right now and redirecting people to VS 2022 --- documents/building-windows.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documents/building-windows.md b/documents/building-windows.md index a810124d6..d5db6790a 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -69,6 +69,9 @@ To automatically populate the necessary files to run shadPS4.exe, run in a comma ## Option 2: MSYS2/MinGW +> [!IMPORTANT] +> Building with MSYS2 is broken as of right now, the only way to build on Windows is to use [Option 1: Visual Studio 2022](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md#option-1-visual-studio-2022). + ### (Prerequisite) Download [**MSYS2**](https://www.msys2.org/) Go through the MSYS2 installation as normal